aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2011-06-24 08:57:18 -0400
committerChris Ball <cjb@laptop.org>2011-07-20 17:20:59 -0400
commitb86d825323b4c5d0c406e5b1a85af614acf0cf5a (patch)
tree15d9f279e07948eb0649bafa0c14d9a785afda0a
parent892b1e312b179139026e366a9d70065a7f897dbc (diff)
mmc: dw_mmc: don't hard code fifo depth, fix usage
The FIFO_DEPTH hardware configuration parameter can be found from the power-on value of RX_WMark in the FIFOTH register. This is used to initialise the watermarks, but when calculating the number of free fifo spaces a preprocessor definition is used which is hard coded to 32. Fix reading the value out of FIFOTH (the default value in the RX_WMark field is FIFO_DEPTH-1 not FIFO_DEPTH). Allow the fifo depth to be overriden by platform data (since a bootloader may have changed FIFOTH making auto-detection unreliable). Store the fifo_depth for later use. Also fix the calculation to find the number of free bytes in the fifo to include the fifo depth in the left shift by the data shift, since the fifo depth is measured in fifo items not bytes. Signed-off-by: James Hogan <james.hogan@imgtec.com> Acked-by: Will Newton <will.newton@imgtec.com> Signed-off-by: Chris Ball <cjb@laptop.org>
-rw-r--r--drivers/mmc/host/dw_mmc.c23
-rw-r--r--drivers/mmc/host/dw_mmc.h1
-rw-r--r--include/linux/mmc/dw_mmc.h8
3 files changed, 26 insertions, 6 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 3f610d55f38e..3832312ce7cb 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1116,8 +1116,8 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
1116 unsigned int nbytes = 0, len; 1116 unsigned int nbytes = 0, len;
1117 1117
1118 do { 1118 do {
1119 len = SDMMC_FIFO_SZ - 1119 len = (host->fifo_depth -
1120 (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift); 1120 SDMMC_GET_FCNT(mci_readl(host, STATUS))) << shift;
1121 if (offset + len <= sg->length) { 1121 if (offset + len <= sg->length) {
1122 host->push_data(host, (void *)(buf + offset), len); 1122 host->push_data(host, (void *)(buf + offset), len);
1123 1123
@@ -1659,8 +1659,19 @@ static int dw_mci_probe(struct platform_device *pdev)
1659 * FIFO threshold settings RxMark = fifo_size / 2 - 1, 1659 * FIFO threshold settings RxMark = fifo_size / 2 - 1,
1660 * Tx Mark = fifo_size / 2 DMA Size = 8 1660 * Tx Mark = fifo_size / 2 DMA Size = 8
1661 */ 1661 */
1662 fifo_size = mci_readl(host, FIFOTH); 1662 if (!host->pdata->fifo_depth) {
1663 fifo_size = (fifo_size >> 16) & 0x7ff; 1663 /*
1664 * Power-on value of RX_WMark is FIFO_DEPTH-1, but this may
1665 * have been overwritten by the bootloader, just like we're
1666 * about to do, so if you know the value for your hardware, you
1667 * should put it in the platform data.
1668 */
1669 fifo_size = mci_readl(host, FIFOTH);
1670 fifo_size = 1 + ((fifo_size >> 16) & 0x7ff);
1671 } else {
1672 fifo_size = host->pdata->fifo_depth;
1673 }
1674 host->fifo_depth = fifo_size;
1664 host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) | 1675 host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
1665 ((fifo_size/2) << 0)); 1676 ((fifo_size/2) << 0));
1666 mci_writel(host, FIFOTH, host->fifoth_val); 1677 mci_writel(host, FIFOTH, host->fifoth_val);
@@ -1707,7 +1718,9 @@ static int dw_mci_probe(struct platform_device *pdev)
1707 mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ 1718 mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
1708 1719
1709 dev_info(&pdev->dev, "DW MMC controller at irq %d, " 1720 dev_info(&pdev->dev, "DW MMC controller at irq %d, "
1710 "%d bit host data width\n", irq, width); 1721 "%d bit host data width, "
1722 "%u deep fifo\n",
1723 irq, width, fifo_size);
1711 if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) 1724 if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
1712 dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n"); 1725 dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n");
1713 1726
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index bb9e5de76ae9..027d37735394 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -118,7 +118,6 @@
118#define SDMMC_CMD_INDX(n) ((n) & 0x1F) 118#define SDMMC_CMD_INDX(n) ((n) & 0x1F)
119/* Status register defines */ 119/* Status register defines */
120#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FF) 120#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FF)
121#define SDMMC_FIFO_SZ 32
122/* Internal DMAC interrupt defines */ 121/* Internal DMAC interrupt defines */
123#define SDMMC_IDMAC_INT_AI BIT(9) 122#define SDMMC_IDMAC_INT_AI BIT(9)
124#define SDMMC_IDMAC_INT_NI BIT(8) 123#define SDMMC_IDMAC_INT_NI BIT(8)
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index dea48475c436..01db1a0b3dd1 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -74,6 +74,7 @@ struct mmc_data;
74 * @pdev: Platform device associated with the MMC controller. 74 * @pdev: Platform device associated with the MMC controller.
75 * @pdata: Platform data associated with the MMC controller. 75 * @pdata: Platform data associated with the MMC controller.
76 * @slot: Slots sharing this MMC controller. 76 * @slot: Slots sharing this MMC controller.
77 * @fifo_depth: depth of FIFO.
77 * @data_shift: log2 of FIFO item size. 78 * @data_shift: log2 of FIFO item size.
78 * @push_data: Pointer to FIFO push function. 79 * @push_data: Pointer to FIFO push function.
79 * @pull_data: Pointer to FIFO pull function. 80 * @pull_data: Pointer to FIFO pull function.
@@ -146,6 +147,7 @@ struct dw_mci {
146 struct dw_mci_slot *slot[MAX_MCI_SLOTS]; 147 struct dw_mci_slot *slot[MAX_MCI_SLOTS];
147 148
148 /* FIFO push and pull */ 149 /* FIFO push and pull */
150 int fifo_depth;
149 int data_shift; 151 int data_shift;
150 void (*push_data)(struct dw_mci *host, void *buf, int cnt); 152 void (*push_data)(struct dw_mci *host, void *buf, int cnt);
151 void (*pull_data)(struct dw_mci *host, void *buf, int cnt); 153 void (*pull_data)(struct dw_mci *host, void *buf, int cnt);
@@ -196,6 +198,12 @@ struct dw_mci_board {
196 unsigned int bus_hz; /* Bus speed */ 198 unsigned int bus_hz; /* Bus speed */
197 199
198 unsigned int caps; /* Capabilities */ 200 unsigned int caps; /* Capabilities */
201 /*
202 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
203 * but note that this may not be reliable after a bootloader has used
204 * it.
205 */
206 unsigned int fifo_depth;
199 207
200 /* delay in mS before detecting cards after interrupt */ 208 /* delay in mS before detecting cards after interrupt */
201 u32 detect_delay_ms; 209 u32 detect_delay_ms;