diff options
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r-- | drivers/mmc/host/bfin_sdh.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/jz4740_mmc.c | 5 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.c | 109 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.h | 5 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-s3c.c | 36 | ||||
-rw-r--r-- | drivers/mmc/host/ushc.c | 1 |
6 files changed, 67 insertions, 91 deletions
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index bac7d62866b7..0371bf502249 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
@@ -462,7 +462,7 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
462 | goto out; | 462 | goto out; |
463 | } | 463 | } |
464 | 464 | ||
465 | mmc = mmc_alloc_host(sizeof(*mmc), &pdev->dev); | 465 | mmc = mmc_alloc_host(sizeof(struct sdh_host), &pdev->dev); |
466 | if (!mmc) { | 466 | if (!mmc) { |
467 | ret = -ENOMEM; | 467 | ret = -ENOMEM; |
468 | goto out; | 468 | goto out; |
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index b3a0ab0e4c2b..74218ad677e4 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/mmc/host.h> | 16 | #include <linux/mmc/host.h> |
17 | #include <linux/err.h> | ||
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
18 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
@@ -827,8 +828,8 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev) | |||
827 | } | 828 | } |
828 | 829 | ||
829 | host->clk = clk_get(&pdev->dev, "mmc"); | 830 | host->clk = clk_get(&pdev->dev, "mmc"); |
830 | if (!host->clk) { | 831 | if (IS_ERR(host->clk)) { |
831 | ret = -ENOENT; | 832 | ret = PTR_ERR(host->clk); |
832 | dev_err(&pdev->dev, "Failed to get mmc clock\n"); | 833 | dev_err(&pdev->dev, "Failed to get mmc clock\n"); |
833 | goto err_free_host; | 834 | goto err_free_host; |
834 | } | 835 | } |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 563022825667..2d6de3e03e2d 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/kernel.h> | ||
17 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
18 | #include <linux/err.h> | 19 | #include <linux/err.h> |
19 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
@@ -46,10 +47,6 @@ static unsigned int fmax = 515633; | |||
46 | * is asserted (likewise for RX) | 47 | * is asserted (likewise for RX) |
47 | * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY | 48 | * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY |
48 | * is asserted (likewise for RX) | 49 | * is asserted (likewise for RX) |
49 | * @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware | ||
50 | * and will not work at all. | ||
51 | * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when | ||
52 | * using DMA. | ||
53 | * @sdio: variant supports SDIO | 50 | * @sdio: variant supports SDIO |
54 | * @st_clkdiv: true if using a ST-specific clock divider algorithm | 51 | * @st_clkdiv: true if using a ST-specific clock divider algorithm |
55 | */ | 52 | */ |
@@ -59,8 +56,6 @@ struct variant_data { | |||
59 | unsigned int datalength_bits; | 56 | unsigned int datalength_bits; |
60 | unsigned int fifosize; | 57 | unsigned int fifosize; |
61 | unsigned int fifohalfsize; | 58 | unsigned int fifohalfsize; |
62 | bool broken_blockend; | ||
63 | bool broken_blockend_dma; | ||
64 | bool sdio; | 59 | bool sdio; |
65 | bool st_clkdiv; | 60 | bool st_clkdiv; |
66 | }; | 61 | }; |
@@ -76,7 +71,6 @@ static struct variant_data variant_u300 = { | |||
76 | .fifohalfsize = 8 * 4, | 71 | .fifohalfsize = 8 * 4, |
77 | .clkreg_enable = 1 << 13, /* HWFCEN */ | 72 | .clkreg_enable = 1 << 13, /* HWFCEN */ |
78 | .datalength_bits = 16, | 73 | .datalength_bits = 16, |
79 | .broken_blockend_dma = true, | ||
80 | .sdio = true, | 74 | .sdio = true, |
81 | }; | 75 | }; |
82 | 76 | ||
@@ -86,7 +80,6 @@ static struct variant_data variant_ux500 = { | |||
86 | .clkreg = MCI_CLK_ENABLE, | 80 | .clkreg = MCI_CLK_ENABLE, |
87 | .clkreg_enable = 1 << 14, /* HWFCEN */ | 81 | .clkreg_enable = 1 << 14, /* HWFCEN */ |
88 | .datalength_bits = 24, | 82 | .datalength_bits = 24, |
89 | .broken_blockend = true, | ||
90 | .sdio = true, | 83 | .sdio = true, |
91 | .st_clkdiv = true, | 84 | .st_clkdiv = true, |
92 | }; | 85 | }; |
@@ -210,8 +203,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) | |||
210 | host->data = data; | 203 | host->data = data; |
211 | host->size = data->blksz * data->blocks; | 204 | host->size = data->blksz * data->blocks; |
212 | host->data_xfered = 0; | 205 | host->data_xfered = 0; |
213 | host->blockend = false; | ||
214 | host->dataend = false; | ||
215 | 206 | ||
216 | mmci_init_sg(host, data); | 207 | mmci_init_sg(host, data); |
217 | 208 | ||
@@ -288,21 +279,26 @@ static void | |||
288 | mmci_data_irq(struct mmci_host *host, struct mmc_data *data, | 279 | mmci_data_irq(struct mmci_host *host, struct mmc_data *data, |
289 | unsigned int status) | 280 | unsigned int status) |
290 | { | 281 | { |
291 | struct variant_data *variant = host->variant; | ||
292 | |||
293 | /* First check for errors */ | 282 | /* First check for errors */ |
294 | if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { | 283 | if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { |
284 | u32 remain, success; | ||
285 | |||
286 | /* Calculate how far we are into the transfer */ | ||
287 | remain = readl(host->base + MMCIDATACNT); | ||
288 | success = data->blksz * data->blocks - remain; | ||
289 | |||
295 | dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); | 290 | dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); |
296 | if (status & MCI_DATACRCFAIL) | 291 | if (status & MCI_DATACRCFAIL) { |
292 | /* Last block was not successful */ | ||
293 | host->data_xfered = round_down(success - 1, data->blksz); | ||
297 | data->error = -EILSEQ; | 294 | data->error = -EILSEQ; |
298 | else if (status & MCI_DATATIMEOUT) | 295 | } else if (status & MCI_DATATIMEOUT) { |
296 | host->data_xfered = round_down(success, data->blksz); | ||
299 | data->error = -ETIMEDOUT; | 297 | data->error = -ETIMEDOUT; |
300 | else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) | 298 | } else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) { |
299 | host->data_xfered = round_down(success, data->blksz); | ||
301 | data->error = -EIO; | 300 | data->error = -EIO; |
302 | 301 | } | |
303 | /* Force-complete the transaction */ | ||
304 | host->blockend = true; | ||
305 | host->dataend = true; | ||
306 | 302 | ||
307 | /* | 303 | /* |
308 | * We hit an error condition. Ensure that any data | 304 | * We hit an error condition. Ensure that any data |
@@ -321,61 +317,14 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, | |||
321 | } | 317 | } |
322 | } | 318 | } |
323 | 319 | ||
324 | /* | 320 | if (status & MCI_DATABLOCKEND) |
325 | * On ARM variants in PIO mode, MCI_DATABLOCKEND | 321 | dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n"); |
326 | * is always sent first, and we increase the | ||
327 | * transfered number of bytes for that IRQ. Then | ||
328 | * MCI_DATAEND follows and we conclude the transaction. | ||
329 | * | ||
330 | * On the Ux500 single-IRQ variant MCI_DATABLOCKEND | ||
331 | * doesn't seem to immediately clear from the status, | ||
332 | * so we can't use it keep count when only one irq is | ||
333 | * used because the irq will hit for other reasons, and | ||
334 | * then the flag is still up. So we use the MCI_DATAEND | ||
335 | * IRQ at the end of the entire transfer because | ||
336 | * MCI_DATABLOCKEND is broken. | ||
337 | * | ||
338 | * In the U300, the IRQs can arrive out-of-order, | ||
339 | * e.g. MCI_DATABLOCKEND sometimes arrives after MCI_DATAEND, | ||
340 | * so for this case we use the flags "blockend" and | ||
341 | * "dataend" to make sure both IRQs have arrived before | ||
342 | * concluding the transaction. (This does not apply | ||
343 | * to the Ux500 which doesn't fire MCI_DATABLOCKEND | ||
344 | * at all.) In DMA mode it suffers from the same problem | ||
345 | * as the Ux500. | ||
346 | */ | ||
347 | if (status & MCI_DATABLOCKEND) { | ||
348 | /* | ||
349 | * Just being a little over-cautious, we do not | ||
350 | * use this progressive update if the hardware blockend | ||
351 | * flag is unreliable: since it can stay high between | ||
352 | * IRQs it will corrupt the transfer counter. | ||
353 | */ | ||
354 | if (!variant->broken_blockend) | ||
355 | host->data_xfered += data->blksz; | ||
356 | host->blockend = true; | ||
357 | } | ||
358 | |||
359 | if (status & MCI_DATAEND) | ||
360 | host->dataend = true; | ||
361 | 322 | ||
362 | /* | 323 | if (status & MCI_DATAEND || data->error) { |
363 | * On variants with broken blockend we shall only wait for dataend, | ||
364 | * on others we must sync with the blockend signal since they can | ||
365 | * appear out-of-order. | ||
366 | */ | ||
367 | if (host->dataend && (host->blockend || variant->broken_blockend)) { | ||
368 | mmci_stop_data(host); | 324 | mmci_stop_data(host); |
369 | 325 | ||
370 | /* Reset these flags */ | 326 | if (!data->error) |
371 | host->blockend = false; | 327 | /* The error clause is handled above, success! */ |
372 | host->dataend = false; | ||
373 | |||
374 | /* | ||
375 | * Variants with broken blockend flags need to handle the | ||
376 | * end of the entire transfer here. | ||
377 | */ | ||
378 | if (variant->broken_blockend && !data->error) | ||
379 | host->data_xfered += data->blksz * data->blocks; | 328 | host->data_xfered += data->blksz * data->blocks; |
380 | 329 | ||
381 | if (!data->stop) { | 330 | if (!data->stop) { |
@@ -394,15 +343,15 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, | |||
394 | 343 | ||
395 | host->cmd = NULL; | 344 | host->cmd = NULL; |
396 | 345 | ||
397 | cmd->resp[0] = readl(base + MMCIRESPONSE0); | ||
398 | cmd->resp[1] = readl(base + MMCIRESPONSE1); | ||
399 | cmd->resp[2] = readl(base + MMCIRESPONSE2); | ||
400 | cmd->resp[3] = readl(base + MMCIRESPONSE3); | ||
401 | |||
402 | if (status & MCI_CMDTIMEOUT) { | 346 | if (status & MCI_CMDTIMEOUT) { |
403 | cmd->error = -ETIMEDOUT; | 347 | cmd->error = -ETIMEDOUT; |
404 | } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) { | 348 | } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) { |
405 | cmd->error = -EILSEQ; | 349 | cmd->error = -EILSEQ; |
350 | } else { | ||
351 | cmd->resp[0] = readl(base + MMCIRESPONSE0); | ||
352 | cmd->resp[1] = readl(base + MMCIRESPONSE1); | ||
353 | cmd->resp[2] = readl(base + MMCIRESPONSE2); | ||
354 | cmd->resp[3] = readl(base + MMCIRESPONSE3); | ||
406 | } | 355 | } |
407 | 356 | ||
408 | if (!cmd->data || cmd->error) { | 357 | if (!cmd->data || cmd->error) { |
@@ -770,7 +719,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
770 | struct variant_data *variant = id->data; | 719 | struct variant_data *variant = id->data; |
771 | struct mmci_host *host; | 720 | struct mmci_host *host; |
772 | struct mmc_host *mmc; | 721 | struct mmc_host *mmc; |
773 | unsigned int mask; | ||
774 | int ret; | 722 | int ret; |
775 | 723 | ||
776 | /* must have platform data */ | 724 | /* must have platform data */ |
@@ -951,12 +899,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
951 | goto irq0_free; | 899 | goto irq0_free; |
952 | } | 900 | } |
953 | 901 | ||
954 | mask = MCI_IRQENABLE; | 902 | writel(MCI_IRQENABLE, host->base + MMCIMASK0); |
955 | /* Don't use the datablockend flag if it's broken */ | ||
956 | if (variant->broken_blockend) | ||
957 | mask &= ~MCI_DATABLOCKEND; | ||
958 | |||
959 | writel(mask, host->base + MMCIMASK0); | ||
960 | 903 | ||
961 | amba_set_drvdata(dev, mmc); | 904 | amba_set_drvdata(dev, mmc); |
962 | 905 | ||
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index df06f01aac89..c1df7b82d36c 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h | |||
@@ -137,7 +137,7 @@ | |||
137 | #define MCI_IRQENABLE \ | 137 | #define MCI_IRQENABLE \ |
138 | (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ | 138 | (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ |
139 | MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ | 139 | MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ |
140 | MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK) | 140 | MCI_CMDRESPENDMASK|MCI_CMDSENTMASK) |
141 | 141 | ||
142 | /* These interrupts are directed to IRQ1 when two IRQ lines are available */ | 142 | /* These interrupts are directed to IRQ1 when two IRQ lines are available */ |
143 | #define MCI_IRQ1MASK \ | 143 | #define MCI_IRQ1MASK \ |
@@ -177,9 +177,6 @@ struct mmci_host { | |||
177 | struct timer_list timer; | 177 | struct timer_list timer; |
178 | unsigned int oldstat; | 178 | unsigned int oldstat; |
179 | 179 | ||
180 | bool blockend; | ||
181 | bool dataend; | ||
182 | |||
183 | /* pio stuff */ | 180 | /* pio stuff */ |
184 | struct sg_mapping_iter sg_miter; | 181 | struct sg_mapping_iter sg_miter; |
185 | unsigned int size; | 182 | unsigned int size; |
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 17203586305c..5309ab95aada 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
@@ -277,10 +277,43 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) | |||
277 | host->clock = clock; | 277 | host->clock = clock; |
278 | } | 278 | } |
279 | 279 | ||
280 | /** | ||
281 | * sdhci_s3c_platform_8bit_width - support 8bit buswidth | ||
282 | * @host: The SDHCI host being queried | ||
283 | * @width: MMC_BUS_WIDTH_ macro for the bus width being requested | ||
284 | * | ||
285 | * We have 8-bit width support but is not a v3 controller. | ||
286 | * So we add platform_8bit_width() and support 8bit width. | ||
287 | */ | ||
288 | static int sdhci_s3c_platform_8bit_width(struct sdhci_host *host, int width) | ||
289 | { | ||
290 | u8 ctrl; | ||
291 | |||
292 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | ||
293 | |||
294 | switch (width) { | ||
295 | case MMC_BUS_WIDTH_8: | ||
296 | ctrl |= SDHCI_CTRL_8BITBUS; | ||
297 | ctrl &= ~SDHCI_CTRL_4BITBUS; | ||
298 | break; | ||
299 | case MMC_BUS_WIDTH_4: | ||
300 | ctrl |= SDHCI_CTRL_4BITBUS; | ||
301 | ctrl &= ~SDHCI_CTRL_8BITBUS; | ||
302 | break; | ||
303 | default: | ||
304 | break; | ||
305 | } | ||
306 | |||
307 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
280 | static struct sdhci_ops sdhci_s3c_ops = { | 312 | static struct sdhci_ops sdhci_s3c_ops = { |
281 | .get_max_clock = sdhci_s3c_get_max_clk, | 313 | .get_max_clock = sdhci_s3c_get_max_clk, |
282 | .set_clock = sdhci_s3c_set_clock, | 314 | .set_clock = sdhci_s3c_set_clock, |
283 | .get_min_clock = sdhci_s3c_get_min_clock, | 315 | .get_min_clock = sdhci_s3c_get_min_clock, |
316 | .platform_8bit_width = sdhci_s3c_platform_8bit_width, | ||
284 | }; | 317 | }; |
285 | 318 | ||
286 | static void sdhci_s3c_notify_change(struct platform_device *dev, int state) | 319 | static void sdhci_s3c_notify_change(struct platform_device *dev, int state) |
@@ -473,6 +506,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
473 | if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) | 506 | if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) |
474 | host->mmc->caps = MMC_CAP_NONREMOVABLE; | 507 | host->mmc->caps = MMC_CAP_NONREMOVABLE; |
475 | 508 | ||
509 | if (pdata->host_caps) | ||
510 | host->mmc->caps |= pdata->host_caps; | ||
511 | |||
476 | host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | | 512 | host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | |
477 | SDHCI_QUIRK_32BIT_DMA_SIZE); | 513 | SDHCI_QUIRK_32BIT_DMA_SIZE); |
478 | 514 | ||
diff --git a/drivers/mmc/host/ushc.c b/drivers/mmc/host/ushc.c index f8f65df9b017..f08f944ac53c 100644 --- a/drivers/mmc/host/ushc.c +++ b/drivers/mmc/host/ushc.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/usb.h> | 20 | #include <linux/usb.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/usb.h> | ||
23 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
24 | #include <linux/dma-mapping.h> | 23 | #include <linux/dma-mapping.h> |
25 | #include <linux/mmc/host.h> | 24 | #include <linux/mmc/host.h> |