diff options
| -rw-r--r-- | drivers/mmc/card/block.c | 26 | ||||
| -rw-r--r-- | drivers/mmc/host/atmel-mci.c | 6 | ||||
| -rw-r--r-- | drivers/mmc/host/bfin_sdh.c | 7 | ||||
| -rw-r--r-- | drivers/mmc/host/dw_mmc.c | 85 | ||||
| -rw-r--r-- | drivers/mmc/host/mxs-mmc.c | 14 | ||||
| -rw-r--r-- | drivers/mmc/host/omap.c | 14 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-esdhc.h | 6 | ||||
| -rw-r--r-- | include/linux/mmc/card.h | 1 |
8 files changed, 98 insertions, 61 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index f1c84decb192..172a768036d8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
| @@ -1411,7 +1411,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 1411 | /* complete ongoing async transfer before issuing discard */ | 1411 | /* complete ongoing async transfer before issuing discard */ |
| 1412 | if (card->host->areq) | 1412 | if (card->host->areq) |
| 1413 | mmc_blk_issue_rw_rq(mq, NULL); | 1413 | mmc_blk_issue_rw_rq(mq, NULL); |
| 1414 | if (req->cmd_flags & REQ_SECURE) | 1414 | if (req->cmd_flags & REQ_SECURE && |
| 1415 | !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) | ||
| 1415 | ret = mmc_blk_issue_secdiscard_rq(mq, req); | 1416 | ret = mmc_blk_issue_secdiscard_rq(mq, req); |
| 1416 | else | 1417 | else |
| 1417 | ret = mmc_blk_issue_discard_rq(mq, req); | 1418 | ret = mmc_blk_issue_discard_rq(mq, req); |
| @@ -1716,6 +1717,7 @@ force_ro_fail: | |||
| 1716 | #define CID_MANFID_SANDISK 0x2 | 1717 | #define CID_MANFID_SANDISK 0x2 |
| 1717 | #define CID_MANFID_TOSHIBA 0x11 | 1718 | #define CID_MANFID_TOSHIBA 0x11 |
| 1718 | #define CID_MANFID_MICRON 0x13 | 1719 | #define CID_MANFID_MICRON 0x13 |
| 1720 | #define CID_MANFID_SAMSUNG 0x15 | ||
| 1719 | 1721 | ||
| 1720 | static const struct mmc_fixup blk_fixups[] = | 1722 | static const struct mmc_fixup blk_fixups[] = |
| 1721 | { | 1723 | { |
| @@ -1752,6 +1754,28 @@ static const struct mmc_fixup blk_fixups[] = | |||
| 1752 | MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, | 1754 | MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, |
| 1753 | MMC_QUIRK_LONG_READ_TIME), | 1755 | MMC_QUIRK_LONG_READ_TIME), |
| 1754 | 1756 | ||
| 1757 | /* | ||
| 1758 | * On these Samsung MoviNAND parts, performing secure erase or | ||
| 1759 | * secure trim can result in unrecoverable corruption due to a | ||
| 1760 | * firmware bug. | ||
| 1761 | */ | ||
| 1762 | MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | ||
| 1763 | MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | ||
| 1764 | MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | ||
| 1765 | MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | ||
| 1766 | MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | ||
| 1767 | MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | ||
| 1768 | MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | ||
| 1769 | MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | ||
| 1770 | MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | ||
| 1771 | MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | ||
| 1772 | MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | ||
| 1773 | MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | ||
| 1774 | MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | ||
| 1775 | MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | ||
| 1776 | MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | ||
| 1777 | MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | ||
| 1778 | |||
| 1755 | END_FIXUP | 1779 | END_FIXUP |
| 1756 | }; | 1780 | }; |
| 1757 | 1781 | ||
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 322412cec4ee..a53c7c478e05 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
| @@ -81,6 +81,7 @@ struct atmel_mci_caps { | |||
| 81 | bool has_bad_data_ordering; | 81 | bool has_bad_data_ordering; |
| 82 | bool need_reset_after_xfer; | 82 | bool need_reset_after_xfer; |
| 83 | bool need_blksz_mul_4; | 83 | bool need_blksz_mul_4; |
| 84 | bool need_notbusy_for_read_ops; | ||
| 84 | }; | 85 | }; |
| 85 | 86 | ||
| 86 | struct atmel_mci_dma { | 87 | struct atmel_mci_dma { |
| @@ -1625,7 +1626,8 @@ static void atmci_tasklet_func(unsigned long priv) | |||
| 1625 | __func__); | 1626 | __func__); |
| 1626 | atmci_set_completed(host, EVENT_XFER_COMPLETE); | 1627 | atmci_set_completed(host, EVENT_XFER_COMPLETE); |
| 1627 | 1628 | ||
| 1628 | if (host->data->flags & MMC_DATA_WRITE) { | 1629 | if (host->caps.need_notbusy_for_read_ops || |
| 1630 | (host->data->flags & MMC_DATA_WRITE)) { | ||
| 1629 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); | 1631 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); |
| 1630 | state = STATE_WAITING_NOTBUSY; | 1632 | state = STATE_WAITING_NOTBUSY; |
| 1631 | } else if (host->mrq->stop) { | 1633 | } else if (host->mrq->stop) { |
| @@ -2218,6 +2220,7 @@ static void __init atmci_get_cap(struct atmel_mci *host) | |||
| 2218 | host->caps.has_bad_data_ordering = 1; | 2220 | host->caps.has_bad_data_ordering = 1; |
| 2219 | host->caps.need_reset_after_xfer = 1; | 2221 | host->caps.need_reset_after_xfer = 1; |
| 2220 | host->caps.need_blksz_mul_4 = 1; | 2222 | host->caps.need_blksz_mul_4 = 1; |
| 2223 | host->caps.need_notbusy_for_read_ops = 0; | ||
| 2221 | 2224 | ||
| 2222 | /* keep only major version number */ | 2225 | /* keep only major version number */ |
| 2223 | switch (version & 0xf00) { | 2226 | switch (version & 0xf00) { |
| @@ -2238,6 +2241,7 @@ static void __init atmci_get_cap(struct atmel_mci *host) | |||
| 2238 | case 0x200: | 2241 | case 0x200: |
| 2239 | host->caps.has_rwproof = 1; | 2242 | host->caps.has_rwproof = 1; |
| 2240 | host->caps.need_blksz_mul_4 = 0; | 2243 | host->caps.need_blksz_mul_4 = 0; |
| 2244 | host->caps.need_notbusy_for_read_ops = 1; | ||
| 2241 | case 0x100: | 2245 | case 0x100: |
| 2242 | host->caps.has_bad_data_ordering = 0; | 2246 | host->caps.has_bad_data_ordering = 0; |
| 2243 | host->caps.need_reset_after_xfer = 0; | 2247 | host->caps.need_reset_after_xfer = 0; |
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 03666174ca48..a17dd7363ceb 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
| @@ -49,13 +49,6 @@ | |||
| 49 | #define bfin_write_SDH_CFG bfin_write_RSI_CFG | 49 | #define bfin_write_SDH_CFG bfin_write_RSI_CFG |
| 50 | #endif | 50 | #endif |
| 51 | 51 | ||
| 52 | struct dma_desc_array { | ||
| 53 | unsigned long start_addr; | ||
| 54 | unsigned short cfg; | ||
| 55 | unsigned short x_count; | ||
| 56 | short x_modify; | ||
| 57 | } __packed; | ||
| 58 | |||
| 59 | struct sdh_host { | 52 | struct sdh_host { |
| 60 | struct mmc_host *mmc; | 53 | struct mmc_host *mmc; |
| 61 | spinlock_t lock; | 54 | spinlock_t lock; |
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 72dc3cde646d..af40d227bece 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
| @@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) | |||
| 627 | { | 627 | { |
| 628 | struct dw_mci *host = slot->host; | 628 | struct dw_mci *host = slot->host; |
| 629 | u32 div; | 629 | u32 div; |
| 630 | u32 clk_en_a; | ||
| 630 | 631 | ||
| 631 | if (slot->clock != host->current_speed) { | 632 | if (slot->clock != host->current_speed) { |
| 632 | div = host->bus_hz / slot->clock; | 633 | div = host->bus_hz / slot->clock; |
| @@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) | |||
| 659 | mci_send_cmd(slot, | 660 | mci_send_cmd(slot, |
| 660 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | 661 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); |
| 661 | 662 | ||
| 662 | /* enable clock */ | 663 | /* enable clock; only low power if no SDIO */ |
| 663 | mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE | | 664 | clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; |
| 664 | SDMMC_CLKEN_LOW_PWR) << slot->id)); | 665 | if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) |
| 666 | clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; | ||
| 667 | mci_writel(host, CLKENA, clk_en_a); | ||
| 665 | 668 | ||
| 666 | /* inform CIU */ | 669 | /* inform CIU */ |
| 667 | mci_send_cmd(slot, | 670 | mci_send_cmd(slot, |
| @@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc) | |||
| 862 | return present; | 865 | return present; |
| 863 | } | 866 | } |
| 864 | 867 | ||
| 868 | /* | ||
| 869 | * Disable lower power mode. | ||
| 870 | * | ||
| 871 | * Low power mode will stop the card clock when idle. According to the | ||
| 872 | * description of the CLKENA register we should disable low power mode | ||
| 873 | * for SDIO cards if we need SDIO interrupts to work. | ||
| 874 | * | ||
| 875 | * This function is fast if low power mode is already disabled. | ||
| 876 | */ | ||
| 877 | static void dw_mci_disable_low_power(struct dw_mci_slot *slot) | ||
| 878 | { | ||
| 879 | struct dw_mci *host = slot->host; | ||
| 880 | u32 clk_en_a; | ||
| 881 | const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; | ||
| 882 | |||
| 883 | clk_en_a = mci_readl(host, CLKENA); | ||
| 884 | |||
| 885 | if (clk_en_a & clken_low_pwr) { | ||
| 886 | mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); | ||
| 887 | mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | | ||
| 888 | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
| 889 | } | ||
| 890 | } | ||
| 891 | |||
| 865 | static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) | 892 | static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) |
| 866 | { | 893 | { |
| 867 | struct dw_mci_slot *slot = mmc_priv(mmc); | 894 | struct dw_mci_slot *slot = mmc_priv(mmc); |
| @@ -871,6 +898,14 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) | |||
| 871 | /* Enable/disable Slot Specific SDIO interrupt */ | 898 | /* Enable/disable Slot Specific SDIO interrupt */ |
| 872 | int_mask = mci_readl(host, INTMASK); | 899 | int_mask = mci_readl(host, INTMASK); |
| 873 | if (enb) { | 900 | if (enb) { |
| 901 | /* | ||
| 902 | * Turn off low power mode if it was enabled. This is a bit of | ||
| 903 | * a heavy operation and we disable / enable IRQs a lot, so | ||
| 904 | * we'll leave low power mode disabled and it will get | ||
| 905 | * re-enabled again in dw_mci_setup_bus(). | ||
| 906 | */ | ||
| 907 | dw_mci_disable_low_power(slot); | ||
| 908 | |||
| 874 | mci_writel(host, INTMASK, | 909 | mci_writel(host, INTMASK, |
| 875 | (int_mask | SDMMC_INT_SDIO(slot->id))); | 910 | (int_mask | SDMMC_INT_SDIO(slot->id))); |
| 876 | } else { | 911 | } else { |
| @@ -1429,22 +1464,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host) | |||
| 1429 | nbytes += len; | 1464 | nbytes += len; |
| 1430 | remain -= len; | 1465 | remain -= len; |
| 1431 | } while (remain); | 1466 | } while (remain); |
| 1432 | sg_miter->consumed = offset; | ||
| 1433 | 1467 | ||
| 1468 | sg_miter->consumed = offset; | ||
| 1434 | status = mci_readl(host, MINTSTS); | 1469 | status = mci_readl(host, MINTSTS); |
| 1435 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); | 1470 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); |
| 1436 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | ||
| 1437 | host->data_status = status; | ||
| 1438 | data->bytes_xfered += nbytes; | ||
| 1439 | sg_miter_stop(sg_miter); | ||
| 1440 | host->sg = NULL; | ||
| 1441 | smp_wmb(); | ||
| 1442 | |||
| 1443 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | ||
| 1444 | |||
| 1445 | tasklet_schedule(&host->tasklet); | ||
| 1446 | return; | ||
| 1447 | } | ||
| 1448 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ | 1471 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ |
| 1449 | data->bytes_xfered += nbytes; | 1472 | data->bytes_xfered += nbytes; |
| 1450 | 1473 | ||
| @@ -1497,23 +1520,10 @@ static void dw_mci_write_data_pio(struct dw_mci *host) | |||
| 1497 | nbytes += len; | 1520 | nbytes += len; |
| 1498 | remain -= len; | 1521 | remain -= len; |
| 1499 | } while (remain); | 1522 | } while (remain); |
| 1500 | sg_miter->consumed = offset; | ||
| 1501 | 1523 | ||
| 1524 | sg_miter->consumed = offset; | ||
| 1502 | status = mci_readl(host, MINTSTS); | 1525 | status = mci_readl(host, MINTSTS); |
| 1503 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); | 1526 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); |
| 1504 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | ||
| 1505 | host->data_status = status; | ||
| 1506 | data->bytes_xfered += nbytes; | ||
| 1507 | sg_miter_stop(sg_miter); | ||
| 1508 | host->sg = NULL; | ||
| 1509 | |||
| 1510 | smp_wmb(); | ||
| 1511 | |||
| 1512 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | ||
| 1513 | |||
| 1514 | tasklet_schedule(&host->tasklet); | ||
| 1515 | return; | ||
| 1516 | } | ||
| 1517 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ | 1527 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ |
| 1518 | data->bytes_xfered += nbytes; | 1528 | data->bytes_xfered += nbytes; |
| 1519 | 1529 | ||
| @@ -1547,12 +1557,11 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) | |||
| 1547 | static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | 1557 | static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) |
| 1548 | { | 1558 | { |
| 1549 | struct dw_mci *host = dev_id; | 1559 | struct dw_mci *host = dev_id; |
| 1550 | u32 status, pending; | 1560 | u32 pending; |
| 1551 | unsigned int pass_count = 0; | 1561 | unsigned int pass_count = 0; |
| 1552 | int i; | 1562 | int i; |
| 1553 | 1563 | ||
| 1554 | do { | 1564 | do { |
| 1555 | status = mci_readl(host, RINTSTS); | ||
| 1556 | pending = mci_readl(host, MINTSTS); /* read-only mask reg */ | 1565 | pending = mci_readl(host, MINTSTS); /* read-only mask reg */ |
| 1557 | 1566 | ||
| 1558 | /* | 1567 | /* |
| @@ -1570,7 +1579,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
| 1570 | 1579 | ||
| 1571 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { | 1580 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { |
| 1572 | mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); | 1581 | mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); |
| 1573 | host->cmd_status = status; | 1582 | host->cmd_status = pending; |
| 1574 | smp_wmb(); | 1583 | smp_wmb(); |
| 1575 | set_bit(EVENT_CMD_COMPLETE, &host->pending_events); | 1584 | set_bit(EVENT_CMD_COMPLETE, &host->pending_events); |
| 1576 | } | 1585 | } |
| @@ -1578,18 +1587,16 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
| 1578 | if (pending & DW_MCI_DATA_ERROR_FLAGS) { | 1587 | if (pending & DW_MCI_DATA_ERROR_FLAGS) { |
| 1579 | /* if there is an error report DATA_ERROR */ | 1588 | /* if there is an error report DATA_ERROR */ |
| 1580 | mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); | 1589 | mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); |
| 1581 | host->data_status = status; | 1590 | host->data_status = pending; |
| 1582 | smp_wmb(); | 1591 | smp_wmb(); |
| 1583 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | 1592 | set_bit(EVENT_DATA_ERROR, &host->pending_events); |
| 1584 | if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC | | 1593 | tasklet_schedule(&host->tasklet); |
| 1585 | SDMMC_INT_SBE | SDMMC_INT_EBE))) | ||
| 1586 | tasklet_schedule(&host->tasklet); | ||
| 1587 | } | 1594 | } |
| 1588 | 1595 | ||
| 1589 | if (pending & SDMMC_INT_DATA_OVER) { | 1596 | if (pending & SDMMC_INT_DATA_OVER) { |
| 1590 | mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); | 1597 | mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); |
| 1591 | if (!host->data_status) | 1598 | if (!host->data_status) |
| 1592 | host->data_status = status; | 1599 | host->data_status = pending; |
| 1593 | smp_wmb(); | 1600 | smp_wmb(); |
| 1594 | if (host->dir_status == DW_MCI_RECV_STATUS) { | 1601 | if (host->dir_status == DW_MCI_RECV_STATUS) { |
| 1595 | if (host->sg != NULL) | 1602 | if (host->sg != NULL) |
| @@ -1613,7 +1620,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
| 1613 | 1620 | ||
| 1614 | if (pending & SDMMC_INT_CMD_DONE) { | 1621 | if (pending & SDMMC_INT_CMD_DONE) { |
| 1615 | mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); | 1622 | mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); |
| 1616 | dw_mci_cmd_interrupt(host, status); | 1623 | dw_mci_cmd_interrupt(host, pending); |
| 1617 | } | 1624 | } |
| 1618 | 1625 | ||
| 1619 | if (pending & SDMMC_INT_CD) { | 1626 | if (pending & SDMMC_INT_CD) { |
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index a51f9309ffbb..ad3fcea1269e 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
| @@ -285,11 +285,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) | |||
| 285 | writel(stat & MXS_MMC_IRQ_BITS, | 285 | writel(stat & MXS_MMC_IRQ_BITS, |
| 286 | host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); | 286 | host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); |
| 287 | 287 | ||
| 288 | spin_unlock(&host->lock); | ||
| 289 | |||
| 288 | if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) | 290 | if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) |
| 289 | mmc_signal_sdio_irq(host->mmc); | 291 | mmc_signal_sdio_irq(host->mmc); |
| 290 | 292 | ||
| 291 | spin_unlock(&host->lock); | ||
| 292 | |||
| 293 | if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ) | 293 | if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ) |
| 294 | cmd->error = -ETIMEDOUT; | 294 | cmd->error = -ETIMEDOUT; |
| 295 | else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ) | 295 | else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ) |
| @@ -644,11 +644,6 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
| 644 | host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); | 644 | host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); |
| 645 | writel(BM_SSP_CTRL1_SDIO_IRQ_EN, | 645 | writel(BM_SSP_CTRL1_SDIO_IRQ_EN, |
| 646 | host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET); | 646 | host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET); |
| 647 | |||
| 648 | if (readl(host->base + HW_SSP_STATUS(host)) & | ||
| 649 | BM_SSP_STATUS_SDIO_IRQ) | ||
| 650 | mmc_signal_sdio_irq(host->mmc); | ||
| 651 | |||
| 652 | } else { | 647 | } else { |
| 653 | writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, | 648 | writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, |
| 654 | host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); | 649 | host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); |
| @@ -657,6 +652,11 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
| 657 | } | 652 | } |
| 658 | 653 | ||
| 659 | spin_unlock_irqrestore(&host->lock, flags); | 654 | spin_unlock_irqrestore(&host->lock, flags); |
| 655 | |||
| 656 | if (enable && readl(host->base + HW_SSP_STATUS(host)) & | ||
| 657 | BM_SSP_STATUS_SDIO_IRQ) | ||
| 658 | mmc_signal_sdio_irq(host->mmc); | ||
| 659 | |||
| 660 | } | 660 | } |
| 661 | 661 | ||
| 662 | static const struct mmc_host_ops mxs_mmc_ops = { | 662 | static const struct mmc_host_ops mxs_mmc_ops = { |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 50e08f03aa65..a5999a74496a 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
| @@ -668,7 +668,7 @@ mmc_omap_clk_timer(unsigned long data) | |||
| 668 | static void | 668 | static void |
| 669 | mmc_omap_xfer_data(struct mmc_omap_host *host, int write) | 669 | mmc_omap_xfer_data(struct mmc_omap_host *host, int write) |
| 670 | { | 670 | { |
| 671 | int n; | 671 | int n, nwords; |
| 672 | 672 | ||
| 673 | if (host->buffer_bytes_left == 0) { | 673 | if (host->buffer_bytes_left == 0) { |
| 674 | host->sg_idx++; | 674 | host->sg_idx++; |
| @@ -678,15 +678,23 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) | |||
| 678 | n = 64; | 678 | n = 64; |
| 679 | if (n > host->buffer_bytes_left) | 679 | if (n > host->buffer_bytes_left) |
| 680 | n = host->buffer_bytes_left; | 680 | n = host->buffer_bytes_left; |
| 681 | |||
| 682 | nwords = n / 2; | ||
| 683 | nwords += n & 1; /* handle odd number of bytes to transfer */ | ||
| 684 | |||
| 681 | host->buffer_bytes_left -= n; | 685 | host->buffer_bytes_left -= n; |
| 682 | host->total_bytes_left -= n; | 686 | host->total_bytes_left -= n; |
| 683 | host->data->bytes_xfered += n; | 687 | host->data->bytes_xfered += n; |
| 684 | 688 | ||
| 685 | if (write) { | 689 | if (write) { |
| 686 | __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); | 690 | __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), |
| 691 | host->buffer, nwords); | ||
| 687 | } else { | 692 | } else { |
| 688 | __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); | 693 | __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), |
| 694 | host->buffer, nwords); | ||
| 689 | } | 695 | } |
| 696 | |||
| 697 | host->buffer += nwords; | ||
| 690 | } | 698 | } |
| 691 | 699 | ||
| 692 | static inline void mmc_omap_report_irq(u16 status) | 700 | static inline void mmc_omap_report_irq(u16 status) |
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index b97b2f5dafdb..d25f9ab9a54d 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h | |||
| @@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) | |||
| 48 | int div = 1; | 48 | int div = 1; |
| 49 | u32 temp; | 49 | u32 temp; |
| 50 | 50 | ||
| 51 | if (clock == 0) | ||
| 52 | goto out; | ||
| 53 | |||
| 51 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); | 54 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); |
| 52 | temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | 55 | temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN |
| 53 | | ESDHC_CLOCK_MASK); | 56 | | ESDHC_CLOCK_MASK); |
| 54 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); | 57 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); |
| 55 | 58 | ||
| 56 | if (clock == 0) | ||
| 57 | goto out; | ||
| 58 | |||
| 59 | while (host->max_clk / pre_div / 16 > clock && pre_div < 256) | 59 | while (host->max_clk / pre_div / 16 > clock && pre_div < 256) |
| 60 | pre_div *= 2; | 60 | pre_div *= 2; |
| 61 | 61 | ||
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 111aca5e97f3..4b27f9f503e4 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
| @@ -239,6 +239,7 @@ struct mmc_card { | |||
| 239 | #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ | 239 | #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ |
| 240 | #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ | 240 | #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ |
| 241 | #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ | 241 | #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ |
| 242 | #define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ | ||
| 242 | /* byte mode */ | 243 | /* byte mode */ |
| 243 | unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ | 244 | unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ |
| 244 | #define MMC_NO_POWER_NOTIFICATION 0 | 245 | #define MMC_NO_POWER_NOTIFICATION 0 |
