aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/mshci.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/mshci.h')
-rw-r--r--drivers/mmc/host/mshci.h463
1 files changed, 463 insertions, 0 deletions
diff --git a/drivers/mmc/host/mshci.h b/drivers/mmc/host/mshci.h
new file mode 100644
index 0000000..40212ae
--- /dev/null
+++ b/drivers/mmc/host/mshci.h
@@ -0,0 +1,463 @@
+/*
+* linux/drivers/mmc/host/mshci.h
+* Mobile Storage Host Controller Interface driver
+*
+* Copyright (c) 2011 Samsung Electronics Co., Ltd.
+* http://www.samsung.com
+*
+* Based on linux/drivers/mmc/host/sdhci.h
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or (at
+* your option) any later version.
+*
+*/
+
+#include <linux/scatterlist.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+/*
+ * Controller registers
+ */
+/*****************************************************/
+/* MSHC Internal Registers */
+/*****************************************************/
+
+#define MSHCI_CTRL 0x00 /* Control */
+#define MSHCI_PWREN 0x04 /* Power-enable */
+#define MSHCI_CLKDIV 0x08 /* Clock divider */
+#define MSHCI_CLKSRC 0x0C /* Clock source */
+#define MSHCI_CLKENA 0x10 /* Clock enable */
+#define MSHCI_TMOUT 0x14 /* Timeout */
+#define MSHCI_CTYPE 0x18 /* Card type */
+#define MSHCI_BLKSIZ 0x1C /* Block Size */
+#define MSHCI_BYTCNT 0x20 /* Byte count */
+#define MSHCI_INTMSK 0x24 /* Interrupt Mask */
+#define MSHCI_CMDARG 0x28 /* Command Argument */
+#define MSHCI_CMD 0x2C /* Command */
+#define MSHCI_RESP0 0x30 /* Response 0 */
+#define MSHCI_RESP1 0x34 /* Response 1 */
+#define MSHCI_RESP2 0x38 /* Response 2 */
+#define MSHCI_RESP3 0x3C /* Response 3 */
+#define MSHCI_MINTSTS 0x40 /* Masked interrupt status */
+#define MSHCI_RINTSTS 0x44 /* Raw interrupt status */
+#define MSHCI_STATUS 0x48 /* Status */
+#define MSHCI_FIFOTH 0x4C /* FIFO threshold */
+#define MSHCI_CDETECT 0x50 /* Card detect */
+#define MSHCI_WRTPRT 0x54 /* Write protect */
+#define MSHCI_GPIO 0x58 /* General Purpose IO */
+#define MSHCI_TCBCNT 0x5C /* Transferred CIU byte count */
+#define MSHCI_TBBCNT 0x60 /* Transferred host/DMA to/from byte count */
+#define MSHCI_DEBNCE 0x64 /* Card detect debounce */
+#define MSHCI_USRID 0x68 /* User ID */
+#define MSHCI_VERID 0x6C /* Version ID */
+#define MSHCI_HCON 0x70 /* Hardware Configuration */
+#define MSHCI_UHS_REG 0x74 /* UHS and DDR setting */
+#define MSHCI_BMOD 0x80 /* Bus mode register */
+#define MSHCI_PLDMND 0x84 /* Poll demand */
+#define MSHCI_DBADDR 0x88 /* Descriptor list base address */
+#define MSHCI_IDSTS 0x8C /* Internal DMAC status */
+#define MSHCI_IDINTEN 0x90 /* Internal DMAC interrupt enable */
+#define MSHCI_DSCADDR 0x94 /* Current host descriptor address */
+#define MSHCI_BUFADDR 0x98 /* Current host buffer address */
+#define MSHCI_CLKSEL 0x9C /* Clock Selection Register */
+#define MSHCI_WAKEUPCON 0xA0 /* Wakeup control register */
+#define MSHCI_CLOCKCON 0xA4 /* Clock (delay) control register */
+#define MSHCI_FIFODAT 0x100 /* FIFO data read write */
+
+/*****************************************************
+ * Control Register Register
+ * MSHCI_CTRL - offset 0x00
+ *****************************************************/
+
+#define CTRL_RESET (0x1<<0) /* Reset DWC_mobile_storage controller */
+#define FIFO_RESET (0x1<<1) /* Reset FIFO */
+#define DMA_RESET (0x1<<2) /* Reset DMA interface */
+#define INT_ENABLE (0x1<<4) /* Global interrupt enable/disable bit */
+#define DMA_ENABLE (0x1<<5) /* DMA transfer mode enable/disable bit */
+#define READ_WAIT (0x1<<6) /* For sending read-wait to SDIO cards */
+#define SEND_IRQ_RESP (0x1<<7) /* Send auto IRQ response */
+#define ABRT_READ_DATA (0x1<<8)
+#define SEND_CCSD (0x1<<9)
+#define SEND_AS_CCSD (0x1<<10)
+#define CEATA_INTSTAT (0x1<<11)
+#define CARD_VOLA (0xF<<16)
+#define CARD_VOLB (0xF<<20)
+#define ENABLE_OD_PULLUP (0x1<<24)
+#define ENABLE_IDMAC (0x1<<25)
+
+#define MSHCI_RESET_ALL (0x1)
+
+/*****************************************************
+ * Power Enable Register
+ * MSHCI_PWREN - offset 0x04
+ *****************************************************/
+#define POWER_ENABLE (0x1<<0)
+
+/*****************************************************
+ * Clock Divider Register
+ * MSHCI_CLKDIV - offset 0x08
+ *****************************************************/
+#define CLK_DIVIDER0 (0xFF<<0)
+#define CLK_DIVIDER1 (0xFF<<8)
+#define CLK_DIVIDER2 (0xFF<<16)
+#define CLK_DIVIDER3 (0xFF<<24)
+
+/*****************************************************
+ * Clock Enable Register
+ * MSHCI_CLKENA - offset 0x10
+ *****************************************************/
+#define CLK_SDMMC_MAX (48000000) /* 96Mhz. it SHOULDBE optimized */
+#define CLK_ENABLE (0x1<<0)
+#define CLK_DISABLE (0x0<<0)
+
+/*****************************************************
+ * Timeout Register
+ * MSHCI_TMOUT - offset 0x14
+ *****************************************************/
+#define RSP_TIMEOUT (0xFF<<0)
+#define DATA_TIMEOUT (0xFFFFFF<<8)
+
+/*****************************************************
+ * Card Type Register
+ * MSHCI_CTYPE - offset 0x18
+ *****************************************************/
+#define CARD_WIDTH4 (0xFFFF<<0)
+#define CARD_WIDTH8 (0xFFFF<<16)
+
+/*****************************************************
+ * Block Size Register
+ * MSHCI_BLKSIZ - offset 0x1C
+ *****************************************************/
+#define BLK_SIZ (0xFFFF<<0)
+
+/*****************************************************
+ * Interrupt Mask Register
+ * MSHCI_INTMSK - offset 0x24
+ *****************************************************/
+#define INT_MASK (0xFFFF<<0)
+#define SDIO_INT_MASK (0xFFFF<<16)
+#define SDIO_INT_ENABLE (0x1<<16)
+
+/* interrupt bits */
+#define INTMSK_ALL 0xFFFFFFFF
+#define INTMSK_CDETECT (0x1<<0)
+#define INTMSK_RE (0x1<<1)
+#define INTMSK_CDONE (0x1<<2)
+#define INTMSK_DTO (0x1<<3)
+#define INTMSK_TXDR (0x1<<4)
+#define INTMSK_RXDR (0x1<<5)
+#define INTMSK_RCRC (0x1<<6)
+#define INTMSK_DCRC (0x1<<7)
+#define INTMSK_RTO (0x1<<8)
+#define INTMSK_DRTO (0x1<<9)
+#define INTMSK_HTO (0x1<<10)
+#define INTMSK_FRUN (0x1<<11)
+#define INTMSK_HLE (0x1<<12)
+#define INTMSK_SBE (0x1<<13)
+#define INTMSK_ACD (0x1<<14)
+#define INTMSK_EBE (0x1<<15)
+#define INTMSK_DMA (INTMSK_ACD|INTMSK_RXDR|INTMSK_TXDR)
+
+#define INT_SRC_IDMAC (0x0)
+#define INT_SRC_MINT (0x1)
+
+
+/*****************************************************
+ * Command Register
+ * MSHCI_CMD - offset 0x2C
+ *****************************************************/
+
+#define CMD_RESP_EXP_BIT (0x1<<6)
+#define CMD_RESP_LENGTH_BIT (0x1<<7)
+#define CMD_CHECK_CRC_BIT (0x1<<8)
+#define CMD_DATA_EXP_BIT (0x1<<9)
+#define CMD_RW_BIT (0x1<<10)
+#define CMD_TRANSMODE_BIT (0x1<<11)
+#define CMD_SENT_AUTO_STOP_BIT (0x1<<12)
+#define CMD_WAIT_PRV_DAT_BIT (0x1<<13)
+#define CMD_ABRT_CMD_BIT (0x1<<14)
+#define CMD_SEND_INIT_BIT (0x1<<15)
+#define CMD_CARD_NUM_BITS (0x1F<<16)
+#define CMD_SEND_CLK_ONLY (0x1<<21)
+#define CMD_READ_CEATA (0x1<<22)
+#define CMD_CCS_EXPECTED (0x1<<23)
+#define CMD_USE_HOLD_REG (0x1<<29)
+#define CMD_STRT_BIT (0x1<<31)
+#define CMD_ONLY_CLK (CMD_STRT_BIT | CMD_SEND_CLK_ONLY | \
+ CMD_WAIT_PRV_DAT_BIT)
+
+/*****************************************************
+ * Masked Interrupt Status Register
+ * MSHCI_MINTSTS - offset 0x40
+ *****************************************************/
+/*****************************************************
+ * Raw Interrupt Register
+ * MSHCI_RINTSTS - offset 0x44
+ *****************************************************/
+#define INT_STATUS (0xFFFF<<0)
+#define SDIO_INTR (0xFFFF<<16)
+#define DATA_ERR (INTMSK_EBE|INTMSK_SBE|INTMSK_HLE|INTMSK_FRUN|\
+ INTMSK_EBE|INTMSK_DCRC)
+#define DATA_TOUT (INTMSK_HTO|INTMSK_DRTO)
+#define DATA_STATUS (DATA_ERR|DATA_TOUT|INTMSK_RXDR|INTMSK_TXDR|INTMSK_DTO)
+#define CMD_STATUS (INTMSK_RTO|INTMSK_RCRC|INTMSK_CDONE|INTMSK_RE)
+#define CMD_ERROR (INTMSK_RCRC|INTMSK_RTO|INTMSK_RE)
+
+/*****************************************************
+ * Status Register
+ * MSHCI_STATUS - offset 0x48
+ *****************************************************/
+#define FIFO_RXWTRMARK (0x1<<0)
+#define FIFO_TXWTRMARK (0x1<<1)
+#define FIFO_EMPTY (0x1<<2)
+#define FIFO_FULL (0x1<<3)
+#define CMD_FSMSTAT (0xF<<4)
+#define DATA_3STATUS (0x1<<8)
+#define DATA_BUSY (0x1<<9)
+#define DATA_MCBUSY (0x1<<10)
+#define RSP_INDEX (0x3F<<11)
+#define FIFO_COUNT (0x1FFF<<17)
+#define DMA_ACK (0x1<<30)
+#define DMA_REQ (0x1<<31)
+#define FIFO_WIDTH (0x4)
+#define FIFO_DEPTH (0x20)
+
+/*Command FSM status */
+#define FSM_IDLE (0<<4)
+#define FSM_SEND_INIT_SEQ (1<<4)
+#define FSM_TX_CMD_STARTBIT (2<<4)
+#define FSM_TX_CMD_TXBIT (3<<4)
+#define FSM_TX_CMD_INDEX_ARG (4<<4)
+#define FSM_TX_CMD_CRC7 (5<<4)
+#define FSM_TX_CMD_ENDBIT (6<<4)
+#define FSM_RX_RESP_STARTBIT (7<<4)
+#define FSM_RX_RESP_IRQRESP (8<<4)
+#define FSM_RX_RESP_TXBIT (9<<4)
+#define FSM_RX_RESP_CMDIDX (10<<4)
+#define FSM_RX_RESP_DATA (11<<4)
+#define FSM_RX_RESP_CRC7 (12<<4)
+#define FSM_RX_RESP_ENDBIT (13<<4)
+#define FSM_CMD_PATHWAITNCC (14<<4)
+#define FSM_WAIT (15<<4)
+
+/*****************************************************
+ * FIFO Threshold Watermark Register
+ * MSHCI_FIFOTH - offset 0x4C
+ *****************************************************/
+#define TX_WMARK (0xFFF<<0)
+#define RX_WMARK (0xFFF<<16)
+#define MSIZE_MASK (0x7<<28)
+
+/* DW DMA Mutiple Transaction Size */
+#define MSIZE_1 (0<<28)
+#define MSIZE_4 (1<<28)
+#define MSIZE_8 (2<<28)
+#define MSIZE_16 (3<<28)
+#define MSIZE_32 (4<<28)
+#define MSIZE_64 (5<<28)
+#define MSIZE_128 (6<<28)
+#define MSIZE_256 (7<<28)
+
+/*****************************************************
+ * FIFO Threshold Watermark Register
+ * MSHCI_FIFOTH - offset 0x4C
+ *****************************************************/
+#define GPI (0xFF<<0)
+#define GPO (0xFFFF<<8)
+
+
+/*****************************************************
+ * Card Detect Register
+ * MSHCI_CDETECT - offset 0x50
+ * It assumes there is only one SD slot
+ *****************************************************/
+#define CARD_PRESENT (0x1<<0)
+
+/*****************************************************
+ * Write Protect Register
+ * MSHCI_WRTPRT - offset 0x54
+ * It assumes there is only one SD slot
+ *****************************************************/
+#define WRTPRT_ON (0x1<<0)
+
+/*****************************************************
+ * Bus Mode Register
+ * MSHCI_BMOD - offset 0x80
+ *****************************************************/
+#define BMOD_IDMAC_RESET (0x1<<0)
+#define BMOD_IDMAC_FB (0x1<<1)
+#define BMOD_IDMAC_ENABLE (0x1<<7)
+
+/*****************************************************
+ * Hardware Configuration Register
+ * MSHCI_HCON - offset 0x70
+ *****************************************************/
+#define CARD_TYPE (0x1<<0)
+#define NUM_CARDS (0x1F<<1)
+#define H_BUS_TYPE (0x1<<6)
+#define H_DATA_WIDTH (0x7<<7)
+#define H_ADDR_WIDTH (0x3F<<10)
+#define DMA_INTERFACE (0x3<<16)
+#define GE_DMA_DATA_WIDTH (0x7<<18)
+#define FIFO_RAM_INSIDE (0x1<<21)
+#define UMPLEMENT_HOLD_REG (0x1<<22)
+#define SET_CLK_FALSE_PATH (0x1<<23)
+#define NUM_CLK_DIVIDER (0x3<<24)
+
+/*****************************************************
+ * Hardware Configuration Register
+ * MSHCI_IDSTS - offset 0x8c
+ *****************************************************/
+#define IDSTS_FSM (0xf<<13)
+#define IDSTS_EB (0x7<<10)
+#define IDSTS_AIS (0x1<<9)
+#define IDSTS_NIS (0x1<<8)
+#define IDSTS_CES (0x1<<5)
+#define IDSTS_DU (0x1<<4)
+#define IDSTS_FBE (0x1<<2)
+#define IDSTS_RI (0x1<<1)
+#define IDSTS_TI (0x1<<0)
+
+struct mshci_ops;
+
+struct mshci_idmac {
+ u32 des0;
+ u32 des1;
+ u32 des2;
+ u32 des3;
+#define MSHCI_IDMAC_OWN (1<<31)
+#define MSHCI_IDMAC_ER (1<<5)
+#define MSHCI_IDMAC_CH (1<<4)
+#define MSHCI_IDMAC_FS (1<<3)
+#define MSHCI_IDMAC_LD (1<<2)
+#define MSHCI_IDMAC_DIC (1<<1)
+#define INTMSK_IDMAC_ALL (0x337)
+#define INTMSK_IDMAC_ERROR (0x214)
+};
+
+struct mshci_host {
+ /* Data set by hardware interface driver */
+ const char *hw_name; /* Hardware bus name */
+
+ unsigned int quirks; /* Deviations from spec. */
+/* Controller has no write-protect pin connected with SD card */
+#define MSHCI_QUIRK_NO_WP_BIT (1<<0)
+#define MSHCI_QUIRK_BROKEN_CARD_DETECTION (1<<1)
+#define MSHCI_QUIRK_BROKEN_PRESENT_BIT (1<<2)
+
+ int irq; /* Device IRQ */
+ void __iomem *ioaddr; /* Mapped address */
+
+ const struct mshci_ops *ops; /* Low level hw interface */
+
+ /* Internal data */
+ struct mmc_host *mmc; /* MMC structure */
+ u64 dma_mask; /* custom DMA mask */
+
+ spinlock_t lock; /* Mutex */
+
+ int flags; /* Host attributes */
+#define MSHCI_USE_IDMA (1<<1) /* Host is ADMA capable */
+#define MSHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */
+#define MSHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */
+
+ unsigned int version; /* SDHCI spec. version */
+
+ unsigned int max_clk; /* Max possible freq (MHz) */
+ unsigned int timeout_clk; /* Timeout freq (KHz) */
+
+ unsigned int clock; /* Current clock (MHz) */
+ unsigned int clock_to_restore; /* Saved clock for dynamic clock gating (MHz) */
+ u8 pwr; /* Current voltage */
+
+ struct mmc_request *mrq; /* Current request */
+ struct mmc_command *cmd; /* Current command */
+ struct mmc_data *data; /* Current data request */
+ unsigned int data_early:1; /* Data finished before cmd */
+
+ struct sg_mapping_iter sg_miter; /* SG state for PIO */
+ unsigned int blocks; /* remaining PIO blocks */
+
+ int sg_count; /* Mapped sg entries */
+
+ u8 *idma_desc; /* ADMA descriptor table */
+ u8 *align_buffer; /* Bounce buffer */
+
+ dma_addr_t idma_addr; /* Mapped ADMA descr. table */
+ dma_addr_t align_addr; /* Mapped bounce buffer */
+
+ struct tasklet_struct card_tasklet; /* Tasklet structures */
+ struct tasklet_struct finish_tasklet;
+
+ struct timer_list timer; /* Timer for timeouts */
+
+ u32 fifo_depth;
+ u32 fifo_threshold;
+ u32 data_transfered;
+
+ /* IP version control */
+ u32 data_addr;
+ u32 hold_bit;
+
+ u32 error_state;
+
+ unsigned long sl_flags;
+ unsigned long private[0] ____cacheline_aligned;
+};
+
+struct mshci_ops {
+ void (*set_clock)(struct mshci_host *host, unsigned int clock);
+
+ int (*enable_dma)(struct mshci_host *host);
+ unsigned int (*get_max_clock)(struct mshci_host *host);
+ unsigned int (*get_min_clock)(struct mshci_host *host);
+ unsigned int (*get_timeout_clock)(struct mshci_host *host);
+ void (*set_ios)(struct mshci_host *host,
+ struct mmc_ios *ios);
+ int (*get_ro) (struct mmc_host *mmc);
+ void (*init_issue_cmd)(struct mshci_host *host);
+ void (*init_card)(struct mshci_host *host);
+
+ int (*dma_map_sg)(struct mshci_host *host,
+ struct device *dev,
+ struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ int flush_type);
+ void (*dma_unmap_sg)(struct mshci_host *host,
+ struct device *dev,
+ struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ int flush_type);
+ int (*get_fifo_depth)(struct mshci_host *host);
+};
+
+static inline void mshci_writel(struct mshci_host *host, u32 val, int reg)
+{
+ __raw_writel(val, host->ioaddr + reg);
+}
+
+static inline u32 mshci_readl(struct mshci_host *host, int reg)
+{
+ return readl(host->ioaddr + reg);
+}
+
+extern struct mshci_host *mshci_alloc_host(struct device *dev,
+ size_t priv_size);
+extern void mshci_free_host(struct mshci_host *host);
+
+static inline void *mshci_priv(struct mshci_host *host)
+{
+ return (void *)host->private;
+}
+
+extern int mshci_add_host(struct mshci_host *host);
+extern void mshci_remove_host(struct mshci_host *host, int dead);
+
+#ifdef CONFIG_PM
+extern int mshci_suspend_host(struct mshci_host *host, pm_message_t state);
+extern int mshci_resume_host(struct mshci_host *host);
+#endif