diff options
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r-- | drivers/mmc/host/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 3 | ||||
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 144 | ||||
-rw-r--r-- | drivers/mmc/host/of_mmc_spi.c | 4 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-of-esdhc.c | 32 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pltfm.c | 10 | ||||
-rw-r--r-- | drivers/mmc/host/sh_mmcif.c | 16 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc.h | 7 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_dma.c | 12 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_pio.c | 6 |
11 files changed, 154 insertions, 83 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index cf444b0ca2cc..00fcbed1afd2 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -477,7 +477,6 @@ config MMC_SDHI | |||
477 | config MMC_CB710 | 477 | config MMC_CB710 |
478 | tristate "ENE CB710 MMC/SD Interface support" | 478 | tristate "ENE CB710 MMC/SD Interface support" |
479 | depends on PCI | 479 | depends on PCI |
480 | select MISC_DEVICES | ||
481 | select CB710_CORE | 480 | select CB710_CORE |
482 | help | 481 | help |
483 | This option enables support for MMC/SD part of ENE CB710/720 Flash | 482 | This option enables support for MMC/SD part of ENE CB710/720 Flash |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index fcfe1eb5acc8..6985cdb0bb26 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -969,11 +969,14 @@ static void atmci_start_request(struct atmel_mci *host, | |||
969 | host->data_status = 0; | 969 | host->data_status = 0; |
970 | 970 | ||
971 | if (host->need_reset) { | 971 | if (host->need_reset) { |
972 | iflags = atmci_readl(host, ATMCI_IMR); | ||
973 | iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB); | ||
972 | atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); | 974 | atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); |
973 | atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); | 975 | atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); |
974 | atmci_writel(host, ATMCI_MR, host->mode_reg); | 976 | atmci_writel(host, ATMCI_MR, host->mode_reg); |
975 | if (host->caps.has_cfg_reg) | 977 | if (host->caps.has_cfg_reg) |
976 | atmci_writel(host, ATMCI_CFG, host->cfg_reg); | 978 | atmci_writel(host, ATMCI_CFG, host->cfg_reg); |
979 | atmci_writel(host, ATMCI_IER, iflags); | ||
977 | host->need_reset = false; | 980 | host->need_reset = false; |
978 | } | 981 | } |
979 | atmci_writel(host, ATMCI_SDCR, slot->sdc_reg); | 982 | atmci_writel(host, ATMCI_SDCR, slot->sdc_reg); |
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 0e342793ff14..8bec1c36b159 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/scatterlist.h> | ||
26 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | #include <linux/stat.h> | 27 | #include <linux/stat.h> |
@@ -502,8 +501,14 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) | |||
502 | host->dir_status = DW_MCI_SEND_STATUS; | 501 | host->dir_status = DW_MCI_SEND_STATUS; |
503 | 502 | ||
504 | if (dw_mci_submit_data_dma(host, data)) { | 503 | if (dw_mci_submit_data_dma(host, data)) { |
504 | int flags = SG_MITER_ATOMIC; | ||
505 | if (host->data->flags & MMC_DATA_READ) | ||
506 | flags |= SG_MITER_TO_SG; | ||
507 | else | ||
508 | flags |= SG_MITER_FROM_SG; | ||
509 | |||
510 | sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); | ||
505 | host->sg = data->sg; | 511 | host->sg = data->sg; |
506 | host->pio_offset = 0; | ||
507 | host->part_buf_start = 0; | 512 | host->part_buf_start = 0; |
508 | host->part_buf_count = 0; | 513 | host->part_buf_count = 0; |
509 | 514 | ||
@@ -972,6 +977,7 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
972 | * generates a block interrupt, hence setting | 977 | * generates a block interrupt, hence setting |
973 | * the scatter-gather pointer to NULL. | 978 | * the scatter-gather pointer to NULL. |
974 | */ | 979 | */ |
980 | sg_miter_stop(&host->sg_miter); | ||
975 | host->sg = NULL; | 981 | host->sg = NULL; |
976 | ctrl = mci_readl(host, CTRL); | 982 | ctrl = mci_readl(host, CTRL); |
977 | ctrl |= SDMMC_CTRL_FIFO_RESET; | 983 | ctrl |= SDMMC_CTRL_FIFO_RESET; |
@@ -1311,54 +1317,44 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) | |||
1311 | 1317 | ||
1312 | static void dw_mci_read_data_pio(struct dw_mci *host) | 1318 | static void dw_mci_read_data_pio(struct dw_mci *host) |
1313 | { | 1319 | { |
1314 | struct scatterlist *sg = host->sg; | 1320 | struct sg_mapping_iter *sg_miter = &host->sg_miter; |
1315 | void *buf = sg_virt(sg); | 1321 | void *buf; |
1316 | unsigned int offset = host->pio_offset; | 1322 | unsigned int offset; |
1317 | struct mmc_data *data = host->data; | 1323 | struct mmc_data *data = host->data; |
1318 | int shift = host->data_shift; | 1324 | int shift = host->data_shift; |
1319 | u32 status; | 1325 | u32 status; |
1320 | unsigned int nbytes = 0, len; | 1326 | unsigned int nbytes = 0, len; |
1327 | unsigned int remain, fcnt; | ||
1321 | 1328 | ||
1322 | do { | 1329 | do { |
1323 | len = host->part_buf_count + | 1330 | if (!sg_miter_next(sg_miter)) |
1324 | (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift); | 1331 | goto done; |
1325 | if (offset + len <= sg->length) { | 1332 | |
1333 | host->sg = sg_miter->__sg; | ||
1334 | buf = sg_miter->addr; | ||
1335 | remain = sg_miter->length; | ||
1336 | offset = 0; | ||
1337 | |||
1338 | do { | ||
1339 | fcnt = (SDMMC_GET_FCNT(mci_readl(host, STATUS)) | ||
1340 | << shift) + host->part_buf_count; | ||
1341 | len = min(remain, fcnt); | ||
1342 | if (!len) | ||
1343 | break; | ||
1326 | dw_mci_pull_data(host, (void *)(buf + offset), len); | 1344 | dw_mci_pull_data(host, (void *)(buf + offset), len); |
1327 | |||
1328 | offset += len; | 1345 | offset += len; |
1329 | nbytes += len; | 1346 | nbytes += len; |
1330 | 1347 | remain -= len; | |
1331 | if (offset == sg->length) { | 1348 | } while (remain); |
1332 | flush_dcache_page(sg_page(sg)); | 1349 | sg_miter->consumed = offset; |
1333 | host->sg = sg = sg_next(sg); | ||
1334 | if (!sg) | ||
1335 | goto done; | ||
1336 | |||
1337 | offset = 0; | ||
1338 | buf = sg_virt(sg); | ||
1339 | } | ||
1340 | } else { | ||
1341 | unsigned int remaining = sg->length - offset; | ||
1342 | dw_mci_pull_data(host, (void *)(buf + offset), | ||
1343 | remaining); | ||
1344 | nbytes += remaining; | ||
1345 | |||
1346 | flush_dcache_page(sg_page(sg)); | ||
1347 | host->sg = sg = sg_next(sg); | ||
1348 | if (!sg) | ||
1349 | goto done; | ||
1350 | |||
1351 | offset = len - remaining; | ||
1352 | buf = sg_virt(sg); | ||
1353 | dw_mci_pull_data(host, buf, offset); | ||
1354 | nbytes += offset; | ||
1355 | } | ||
1356 | 1350 | ||
1357 | status = mci_readl(host, MINTSTS); | 1351 | status = mci_readl(host, MINTSTS); |
1358 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); | 1352 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); |
1359 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | 1353 | if (status & DW_MCI_DATA_ERROR_FLAGS) { |
1360 | host->data_status = status; | 1354 | host->data_status = status; |
1361 | data->bytes_xfered += nbytes; | 1355 | data->bytes_xfered += nbytes; |
1356 | sg_miter_stop(sg_miter); | ||
1357 | host->sg = NULL; | ||
1362 | smp_wmb(); | 1358 | smp_wmb(); |
1363 | 1359 | ||
1364 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | 1360 | set_bit(EVENT_DATA_ERROR, &host->pending_events); |
@@ -1367,65 +1363,66 @@ static void dw_mci_read_data_pio(struct dw_mci *host) | |||
1367 | return; | 1363 | return; |
1368 | } | 1364 | } |
1369 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ | 1365 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ |
1370 | host->pio_offset = offset; | ||
1371 | data->bytes_xfered += nbytes; | 1366 | data->bytes_xfered += nbytes; |
1367 | |||
1368 | if (!remain) { | ||
1369 | if (!sg_miter_next(sg_miter)) | ||
1370 | goto done; | ||
1371 | sg_miter->consumed = 0; | ||
1372 | } | ||
1373 | sg_miter_stop(sg_miter); | ||
1372 | return; | 1374 | return; |
1373 | 1375 | ||
1374 | done: | 1376 | done: |
1375 | data->bytes_xfered += nbytes; | 1377 | data->bytes_xfered += nbytes; |
1378 | sg_miter_stop(sg_miter); | ||
1379 | host->sg = NULL; | ||
1376 | smp_wmb(); | 1380 | smp_wmb(); |
1377 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | 1381 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); |
1378 | } | 1382 | } |
1379 | 1383 | ||
1380 | static void dw_mci_write_data_pio(struct dw_mci *host) | 1384 | static void dw_mci_write_data_pio(struct dw_mci *host) |
1381 | { | 1385 | { |
1382 | struct scatterlist *sg = host->sg; | 1386 | struct sg_mapping_iter *sg_miter = &host->sg_miter; |
1383 | void *buf = sg_virt(sg); | 1387 | void *buf; |
1384 | unsigned int offset = host->pio_offset; | 1388 | unsigned int offset; |
1385 | struct mmc_data *data = host->data; | 1389 | struct mmc_data *data = host->data; |
1386 | int shift = host->data_shift; | 1390 | int shift = host->data_shift; |
1387 | u32 status; | 1391 | u32 status; |
1388 | unsigned int nbytes = 0, len; | 1392 | unsigned int nbytes = 0, len; |
1393 | unsigned int fifo_depth = host->fifo_depth; | ||
1394 | unsigned int remain, fcnt; | ||
1389 | 1395 | ||
1390 | do { | 1396 | do { |
1391 | len = ((host->fifo_depth - | 1397 | if (!sg_miter_next(sg_miter)) |
1392 | SDMMC_GET_FCNT(mci_readl(host, STATUS))) << shift) | 1398 | goto done; |
1393 | - host->part_buf_count; | 1399 | |
1394 | if (offset + len <= sg->length) { | 1400 | host->sg = sg_miter->__sg; |
1401 | buf = sg_miter->addr; | ||
1402 | remain = sg_miter->length; | ||
1403 | offset = 0; | ||
1404 | |||
1405 | do { | ||
1406 | fcnt = ((fifo_depth - | ||
1407 | SDMMC_GET_FCNT(mci_readl(host, STATUS))) | ||
1408 | << shift) - host->part_buf_count; | ||
1409 | len = min(remain, fcnt); | ||
1410 | if (!len) | ||
1411 | break; | ||
1395 | host->push_data(host, (void *)(buf + offset), len); | 1412 | host->push_data(host, (void *)(buf + offset), len); |
1396 | |||
1397 | offset += len; | 1413 | offset += len; |
1398 | nbytes += len; | 1414 | nbytes += len; |
1399 | if (offset == sg->length) { | 1415 | remain -= len; |
1400 | host->sg = sg = sg_next(sg); | 1416 | } while (remain); |
1401 | if (!sg) | 1417 | sg_miter->consumed = offset; |
1402 | goto done; | ||
1403 | |||
1404 | offset = 0; | ||
1405 | buf = sg_virt(sg); | ||
1406 | } | ||
1407 | } else { | ||
1408 | unsigned int remaining = sg->length - offset; | ||
1409 | |||
1410 | host->push_data(host, (void *)(buf + offset), | ||
1411 | remaining); | ||
1412 | nbytes += remaining; | ||
1413 | |||
1414 | host->sg = sg = sg_next(sg); | ||
1415 | if (!sg) | ||
1416 | goto done; | ||
1417 | |||
1418 | offset = len - remaining; | ||
1419 | buf = sg_virt(sg); | ||
1420 | host->push_data(host, (void *)buf, offset); | ||
1421 | nbytes += offset; | ||
1422 | } | ||
1423 | 1418 | ||
1424 | status = mci_readl(host, MINTSTS); | 1419 | status = mci_readl(host, MINTSTS); |
1425 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); | 1420 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); |
1426 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | 1421 | if (status & DW_MCI_DATA_ERROR_FLAGS) { |
1427 | host->data_status = status; | 1422 | host->data_status = status; |
1428 | data->bytes_xfered += nbytes; | 1423 | data->bytes_xfered += nbytes; |
1424 | sg_miter_stop(sg_miter); | ||
1425 | host->sg = NULL; | ||
1429 | 1426 | ||
1430 | smp_wmb(); | 1427 | smp_wmb(); |
1431 | 1428 | ||
@@ -1435,12 +1432,20 @@ static void dw_mci_write_data_pio(struct dw_mci *host) | |||
1435 | return; | 1432 | return; |
1436 | } | 1433 | } |
1437 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ | 1434 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ |
1438 | host->pio_offset = offset; | ||
1439 | data->bytes_xfered += nbytes; | 1435 | data->bytes_xfered += nbytes; |
1436 | |||
1437 | if (!remain) { | ||
1438 | if (!sg_miter_next(sg_miter)) | ||
1439 | goto done; | ||
1440 | sg_miter->consumed = 0; | ||
1441 | } | ||
1442 | sg_miter_stop(sg_miter); | ||
1440 | return; | 1443 | return; |
1441 | 1444 | ||
1442 | done: | 1445 | done: |
1443 | data->bytes_xfered += nbytes; | 1446 | data->bytes_xfered += nbytes; |
1447 | sg_miter_stop(sg_miter); | ||
1448 | host->sg = NULL; | ||
1444 | smp_wmb(); | 1449 | smp_wmb(); |
1445 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | 1450 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); |
1446 | } | 1451 | } |
@@ -1643,6 +1648,7 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1643 | * block interrupt, hence setting the | 1648 | * block interrupt, hence setting the |
1644 | * scatter-gather pointer to NULL. | 1649 | * scatter-gather pointer to NULL. |
1645 | */ | 1650 | */ |
1651 | sg_miter_stop(&host->sg_miter); | ||
1646 | host->sg = NULL; | 1652 | host->sg = NULL; |
1647 | 1653 | ||
1648 | ctrl = mci_readl(host, CTRL); | 1654 | ctrl = mci_readl(host, CTRL); |
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index ab66f2454dc4..1534b582c419 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c | |||
@@ -113,8 +113,8 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) | |||
113 | const int j = i * 2; | 113 | const int j = i * 2; |
114 | u32 mask; | 114 | u32 mask; |
115 | 115 | ||
116 | mask = mmc_vddrange_to_ocrmask(voltage_ranges[j], | 116 | mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]), |
117 | voltage_ranges[j + 1]); | 117 | be32_to_cpu(voltage_ranges[j + 1])); |
118 | if (!mask) { | 118 | if (!mask) { |
119 | ret = -EINVAL; | 119 | ret = -EINVAL; |
120 | dev_err(dev, "OF: voltage-range #%d is invalid\n", i); | 120 | dev_err(dev, "OF: voltage-range #%d is invalid\n", i); |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index ff4adc018041..5d876ff86f37 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -38,6 +38,23 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg) | |||
38 | int base = reg & ~0x3; | 38 | int base = reg & ~0x3; |
39 | int shift = (reg & 0x3) * 8; | 39 | int shift = (reg & 0x3) * 8; |
40 | u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff; | 40 | u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff; |
41 | |||
42 | /* | ||
43 | * "DMA select" locates at offset 0x28 in SD specification, but on | ||
44 | * P5020 or P3041, it locates at 0x29. | ||
45 | */ | ||
46 | if (reg == SDHCI_HOST_CONTROL) { | ||
47 | u32 dma_bits; | ||
48 | |||
49 | dma_bits = in_be32(host->ioaddr + reg); | ||
50 | /* DMA select is 22,23 bits in Protocol Control Register */ | ||
51 | dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK; | ||
52 | |||
53 | /* fixup the result */ | ||
54 | ret &= ~SDHCI_CTRL_DMA_MASK; | ||
55 | ret |= dma_bits; | ||
56 | } | ||
57 | |||
41 | return ret; | 58 | return ret; |
42 | } | 59 | } |
43 | 60 | ||
@@ -56,6 +73,21 @@ static void esdhc_writew(struct sdhci_host *host, u16 val, int reg) | |||
56 | 73 | ||
57 | static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) | 74 | static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) |
58 | { | 75 | { |
76 | /* | ||
77 | * "DMA select" location is offset 0x28 in SD specification, but on | ||
78 | * P5020 or P3041, it's located at 0x29. | ||
79 | */ | ||
80 | if (reg == SDHCI_HOST_CONTROL) { | ||
81 | u32 dma_bits; | ||
82 | |||
83 | /* DMA select is 22,23 bits in Protocol Control Register */ | ||
84 | dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; | ||
85 | clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, | ||
86 | dma_bits); | ||
87 | val &= ~SDHCI_CTRL_DMA_MASK; | ||
88 | val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK; | ||
89 | } | ||
90 | |||
59 | /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */ | 91 | /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */ |
60 | if (reg == SDHCI_HOST_CONTROL) | 92 | if (reg == SDHCI_HOST_CONTROL) |
61 | val &= ~ESDHC_HOST_CONTROL_RES; | 93 | val &= ~ESDHC_HOST_CONTROL_RES; |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 7165e6a09274..6ebdc4010e7c 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -250,7 +250,7 @@ static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot) | |||
250 | 250 | ||
251 | static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot) | 251 | static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot) |
252 | { | 252 | { |
253 | slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD; | 253 | slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE; |
254 | return 0; | 254 | return 0; |
255 | } | 255 | } |
256 | 256 | ||
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 03970bcb3495..c5c2a48bdd94 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * sdhci-pltfm.c Support for SDHCI platform devices | 2 | * sdhci-pltfm.c Support for SDHCI platform devices |
3 | * Copyright (c) 2009 Intel Corporation | 3 | * Copyright (c) 2009 Intel Corporation |
4 | * | 4 | * |
5 | * Copyright (c) 2007 Freescale Semiconductor, Inc. | 5 | * Copyright (c) 2007, 2011 Freescale Semiconductor, Inc. |
6 | * Copyright (c) 2009 MontaVista Software, Inc. | 6 | * Copyright (c) 2009 MontaVista Software, Inc. |
7 | * | 7 | * |
8 | * Authors: Xiaobo Xie <X.Xie@freescale.com> | 8 | * Authors: Xiaobo Xie <X.Xie@freescale.com> |
@@ -71,6 +71,14 @@ void sdhci_get_of_property(struct platform_device *pdev) | |||
71 | if (sdhci_of_wp_inverted(np)) | 71 | if (sdhci_of_wp_inverted(np)) |
72 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; | 72 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; |
73 | 73 | ||
74 | if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) | ||
75 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; | ||
76 | |||
77 | if (of_device_is_compatible(np, "fsl,p2020-esdhc") || | ||
78 | of_device_is_compatible(np, "fsl,p1010-esdhc") || | ||
79 | of_device_is_compatible(np, "fsl,mpc8536-esdhc")) | ||
80 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; | ||
81 | |||
74 | clk = of_get_property(np, "clock-frequency", &size); | 82 | clk = of_get_property(np, "clock-frequency", &size); |
75 | if (clk && size == sizeof(*clk) && *clk) | 83 | if (clk && size == sizeof(*clk) && *clk) |
76 | pltfm_host->clock = be32_to_cpup(clk); | 84 | pltfm_host->clock = be32_to_cpup(clk); |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index f5d8b53be333..352d4797865b 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -1327,7 +1327,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) | |||
1327 | if (ret < 0) | 1327 | if (ret < 0) |
1328 | goto clean_up2; | 1328 | goto clean_up2; |
1329 | 1329 | ||
1330 | mmc_add_host(mmc); | 1330 | INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); |
1331 | 1331 | ||
1332 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); | 1332 | sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); |
1333 | 1333 | ||
@@ -1338,22 +1338,24 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) | |||
1338 | } | 1338 | } |
1339 | ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); | 1339 | ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); |
1340 | if (ret) { | 1340 | if (ret) { |
1341 | free_irq(irq[0], host); | ||
1342 | dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); | 1341 | dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); |
1343 | goto clean_up3; | 1342 | goto clean_up4; |
1344 | } | 1343 | } |
1345 | 1344 | ||
1346 | INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); | 1345 | ret = mmc_add_host(mmc); |
1347 | 1346 | if (ret < 0) | |
1348 | mmc_detect_change(host->mmc, 0); | 1347 | goto clean_up5; |
1349 | 1348 | ||
1350 | dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); | 1349 | dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); |
1351 | dev_dbg(&pdev->dev, "chip ver H'%04x\n", | 1350 | dev_dbg(&pdev->dev, "chip ver H'%04x\n", |
1352 | sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff); | 1351 | sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff); |
1353 | return ret; | 1352 | return ret; |
1354 | 1353 | ||
1354 | clean_up5: | ||
1355 | free_irq(irq[1], host); | ||
1356 | clean_up4: | ||
1357 | free_irq(irq[0], host); | ||
1355 | clean_up3: | 1358 | clean_up3: |
1356 | mmc_remove_host(mmc); | ||
1357 | pm_runtime_suspend(&pdev->dev); | 1359 | pm_runtime_suspend(&pdev->dev); |
1358 | clean_up2: | 1360 | clean_up2: |
1359 | pm_runtime_disable(&pdev->dev); | 1361 | pm_runtime_disable(&pdev->dev); |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index a95e6d901726..f96c536d130a 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
@@ -20,8 +20,8 @@ | |||
20 | #include <linux/mmc/tmio.h> | 20 | #include <linux/mmc/tmio.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/scatterlist.h> | 23 | #include <linux/scatterlist.h> |
24 | #include <linux/spinlock.h> | ||
25 | 25 | ||
26 | /* Definitions for values the CTRL_SDIO_STATUS register can take. */ | 26 | /* Definitions for values the CTRL_SDIO_STATUS register can take. */ |
27 | #define TMIO_SDIO_STAT_IOIRQ 0x0001 | 27 | #define TMIO_SDIO_STAT_IOIRQ 0x0001 |
@@ -120,6 +120,7 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); | |||
120 | void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable); | 120 | void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable); |
121 | void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); | 121 | void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); |
122 | void tmio_mmc_release_dma(struct tmio_mmc_host *host); | 122 | void tmio_mmc_release_dma(struct tmio_mmc_host *host); |
123 | void tmio_mmc_abort_dma(struct tmio_mmc_host *host); | ||
123 | #else | 124 | #else |
124 | static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, | 125 | static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, |
125 | struct mmc_data *data) | 126 | struct mmc_data *data) |
@@ -140,6 +141,10 @@ static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host, | |||
140 | static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host) | 141 | static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host) |
141 | { | 142 | { |
142 | } | 143 | } |
144 | |||
145 | static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host) | ||
146 | { | ||
147 | } | ||
143 | #endif | 148 | #endif |
144 | 149 | ||
145 | #ifdef CONFIG_PM | 150 | #ifdef CONFIG_PM |
diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 7a6e6cc8f8b8..8253ec12003e 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c | |||
@@ -34,6 +34,18 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) | |||
34 | #endif | 34 | #endif |
35 | } | 35 | } |
36 | 36 | ||
37 | void tmio_mmc_abort_dma(struct tmio_mmc_host *host) | ||
38 | { | ||
39 | tmio_mmc_enable_dma(host, false); | ||
40 | |||
41 | if (host->chan_rx) | ||
42 | dmaengine_terminate_all(host->chan_rx); | ||
43 | if (host->chan_tx) | ||
44 | dmaengine_terminate_all(host->chan_tx); | ||
45 | |||
46 | tmio_mmc_enable_dma(host, true); | ||
47 | } | ||
48 | |||
37 | static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) | 49 | static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) |
38 | { | 50 | { |
39 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; | 51 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; |
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index abad01b37cfb..5f9ad74fbf80 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c | |||
@@ -41,8 +41,8 @@ | |||
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
42 | #include <linux/pm_runtime.h> | 42 | #include <linux/pm_runtime.h> |
43 | #include <linux/scatterlist.h> | 43 | #include <linux/scatterlist.h> |
44 | #include <linux/workqueue.h> | ||
45 | #include <linux/spinlock.h> | 44 | #include <linux/spinlock.h> |
45 | #include <linux/workqueue.h> | ||
46 | 46 | ||
47 | #include "tmio_mmc.h" | 47 | #include "tmio_mmc.h" |
48 | 48 | ||
@@ -246,6 +246,7 @@ static void tmio_mmc_reset_work(struct work_struct *work) | |||
246 | /* Ready for new calls */ | 246 | /* Ready for new calls */ |
247 | host->mrq = NULL; | 247 | host->mrq = NULL; |
248 | 248 | ||
249 | tmio_mmc_abort_dma(host); | ||
249 | mmc_request_done(host->mmc, mrq); | 250 | mmc_request_done(host->mmc, mrq); |
250 | } | 251 | } |
251 | 252 | ||
@@ -272,6 +273,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) | |||
272 | host->mrq = NULL; | 273 | host->mrq = NULL; |
273 | spin_unlock_irqrestore(&host->lock, flags); | 274 | spin_unlock_irqrestore(&host->lock, flags); |
274 | 275 | ||
276 | if (mrq->cmd->error || (mrq->data && mrq->data->error)) | ||
277 | tmio_mmc_abort_dma(host); | ||
278 | |||
275 | mmc_request_done(host->mmc, mrq); | 279 | mmc_request_done(host->mmc, mrq); |
276 | } | 280 | } |
277 | 281 | ||