aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/dw_mmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/dw_mmc.c')
-rw-r--r--drivers/mmc/host/dw_mmc.c85
1 files changed, 46 insertions, 39 deletions
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 */
877static 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
865static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) 892static 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)
1547static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) 1557static 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) {