diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r-- | drivers/mmc/host/sdhci.c | 168 |
1 files changed, 167 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2a15aad2eba5..8a56eacea34d 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #define SDHCI_USE_LEDS_CLASS | 38 | #define SDHCI_USE_LEDS_CLASS |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | #define MAX_TUNING_LOOP 40 | ||
42 | |||
41 | static unsigned int debug_quirks = 0; | 43 | static unsigned int debug_quirks = 0; |
42 | 44 | ||
43 | static void sdhci_finish_data(struct sdhci_host *); | 45 | static void sdhci_finish_data(struct sdhci_host *); |
@@ -968,7 +970,9 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
968 | flags |= SDHCI_CMD_CRC; | 970 | flags |= SDHCI_CMD_CRC; |
969 | if (cmd->flags & MMC_RSP_OPCODE) | 971 | if (cmd->flags & MMC_RSP_OPCODE) |
970 | flags |= SDHCI_CMD_INDEX; | 972 | flags |= SDHCI_CMD_INDEX; |
971 | if (cmd->data) | 973 | |
974 | /* CMD19 is special in that the Data Present Select should be set */ | ||
975 | if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK)) | ||
972 | flags |= SDHCI_CMD_DATA; | 976 | flags |= SDHCI_CMD_DATA; |
973 | 977 | ||
974 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); | 978 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); |
@@ -1501,12 +1505,157 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, | |||
1501 | return 0; | 1505 | return 0; |
1502 | } | 1506 | } |
1503 | 1507 | ||
1508 | static int sdhci_execute_tuning(struct mmc_host *mmc) | ||
1509 | { | ||
1510 | struct sdhci_host *host; | ||
1511 | u16 ctrl; | ||
1512 | u32 ier; | ||
1513 | int tuning_loop_counter = MAX_TUNING_LOOP; | ||
1514 | unsigned long timeout; | ||
1515 | int err = 0; | ||
1516 | |||
1517 | host = mmc_priv(mmc); | ||
1518 | |||
1519 | disable_irq(host->irq); | ||
1520 | spin_lock(&host->lock); | ||
1521 | |||
1522 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1523 | |||
1524 | /* | ||
1525 | * Host Controller needs tuning only in case of SDR104 mode | ||
1526 | * and for SDR50 mode when Use Tuning for SDR50 is set in | ||
1527 | * Capabilities register. | ||
1528 | */ | ||
1529 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || | ||
1530 | (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && | ||
1531 | (host->flags & SDHCI_SDR50_NEEDS_TUNING))) | ||
1532 | ctrl |= SDHCI_CTRL_EXEC_TUNING; | ||
1533 | else { | ||
1534 | spin_unlock(&host->lock); | ||
1535 | enable_irq(host->irq); | ||
1536 | return 0; | ||
1537 | } | ||
1538 | |||
1539 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1540 | |||
1541 | /* | ||
1542 | * As per the Host Controller spec v3.00, tuning command | ||
1543 | * generates Buffer Read Ready interrupt, so enable that. | ||
1544 | * | ||
1545 | * Note: The spec clearly says that when tuning sequence | ||
1546 | * is being performed, the controller does not generate | ||
1547 | * interrupts other than Buffer Read Ready interrupt. But | ||
1548 | * to make sure we don't hit a controller bug, we _only_ | ||
1549 | * enable Buffer Read Ready interrupt here. | ||
1550 | */ | ||
1551 | ier = sdhci_readl(host, SDHCI_INT_ENABLE); | ||
1552 | sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL); | ||
1553 | |||
1554 | /* | ||
1555 | * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number | ||
1556 | * of loops reaches 40 times or a timeout of 150ms occurs. | ||
1557 | */ | ||
1558 | timeout = 150; | ||
1559 | do { | ||
1560 | struct mmc_command cmd = {0}; | ||
1561 | struct mmc_request mrq = {0}; | ||
1562 | |||
1563 | if (!tuning_loop_counter && !timeout) | ||
1564 | break; | ||
1565 | |||
1566 | cmd.opcode = MMC_SEND_TUNING_BLOCK; | ||
1567 | cmd.arg = 0; | ||
1568 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | ||
1569 | cmd.retries = 0; | ||
1570 | cmd.data = NULL; | ||
1571 | cmd.error = 0; | ||
1572 | |||
1573 | mrq.cmd = &cmd; | ||
1574 | host->mrq = &mrq; | ||
1575 | |||
1576 | /* | ||
1577 | * In response to CMD19, the card sends 64 bytes of tuning | ||
1578 | * block to the Host Controller. So we set the block size | ||
1579 | * to 64 here. | ||
1580 | */ | ||
1581 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE); | ||
1582 | |||
1583 | /* | ||
1584 | * The tuning block is sent by the card to the host controller. | ||
1585 | * So we set the TRNS_READ bit in the Transfer Mode register. | ||
1586 | * This also takes care of setting DMA Enable and Multi Block | ||
1587 | * Select in the same register to 0. | ||
1588 | */ | ||
1589 | sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); | ||
1590 | |||
1591 | sdhci_send_command(host, &cmd); | ||
1592 | |||
1593 | host->cmd = NULL; | ||
1594 | host->mrq = NULL; | ||
1595 | |||
1596 | spin_unlock(&host->lock); | ||
1597 | enable_irq(host->irq); | ||
1598 | |||
1599 | /* Wait for Buffer Read Ready interrupt */ | ||
1600 | wait_event_interruptible_timeout(host->buf_ready_int, | ||
1601 | (host->tuning_done == 1), | ||
1602 | msecs_to_jiffies(50)); | ||
1603 | disable_irq(host->irq); | ||
1604 | spin_lock(&host->lock); | ||
1605 | |||
1606 | if (!host->tuning_done) { | ||
1607 | printk(KERN_INFO DRIVER_NAME ": Timeout waiting for " | ||
1608 | "Buffer Read Ready interrupt during tuning " | ||
1609 | "procedure, falling back to fixed sampling " | ||
1610 | "clock\n"); | ||
1611 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1612 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; | ||
1613 | ctrl &= ~SDHCI_CTRL_EXEC_TUNING; | ||
1614 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1615 | |||
1616 | err = -EIO; | ||
1617 | goto out; | ||
1618 | } | ||
1619 | |||
1620 | host->tuning_done = 0; | ||
1621 | |||
1622 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1623 | tuning_loop_counter--; | ||
1624 | timeout--; | ||
1625 | mdelay(1); | ||
1626 | } while (ctrl & SDHCI_CTRL_EXEC_TUNING); | ||
1627 | |||
1628 | /* | ||
1629 | * The Host Driver has exhausted the maximum number of loops allowed, | ||
1630 | * so use fixed sampling frequency. | ||
1631 | */ | ||
1632 | if (!tuning_loop_counter || !timeout) { | ||
1633 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; | ||
1634 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1635 | } else { | ||
1636 | if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { | ||
1637 | printk(KERN_INFO DRIVER_NAME ": Tuning procedure" | ||
1638 | " failed, falling back to fixed sampling" | ||
1639 | " clock\n"); | ||
1640 | err = -EIO; | ||
1641 | } | ||
1642 | } | ||
1643 | |||
1644 | out: | ||
1645 | sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); | ||
1646 | spin_unlock(&host->lock); | ||
1647 | enable_irq(host->irq); | ||
1648 | |||
1649 | return err; | ||
1650 | } | ||
1651 | |||
1504 | static const struct mmc_host_ops sdhci_ops = { | 1652 | static const struct mmc_host_ops sdhci_ops = { |
1505 | .request = sdhci_request, | 1653 | .request = sdhci_request, |
1506 | .set_ios = sdhci_set_ios, | 1654 | .set_ios = sdhci_set_ios, |
1507 | .get_ro = sdhci_get_ro, | 1655 | .get_ro = sdhci_get_ro, |
1508 | .enable_sdio_irq = sdhci_enable_sdio_irq, | 1656 | .enable_sdio_irq = sdhci_enable_sdio_irq, |
1509 | .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, | 1657 | .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, |
1658 | .execute_tuning = sdhci_execute_tuning, | ||
1510 | }; | 1659 | }; |
1511 | 1660 | ||
1512 | /*****************************************************************************\ | 1661 | /*****************************************************************************\ |
@@ -1724,6 +1873,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
1724 | { | 1873 | { |
1725 | BUG_ON(intmask == 0); | 1874 | BUG_ON(intmask == 0); |
1726 | 1875 | ||
1876 | /* CMD19 generates _only_ Buffer Read Ready interrupt */ | ||
1877 | if (intmask & SDHCI_INT_DATA_AVAIL) { | ||
1878 | if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) == | ||
1879 | MMC_SEND_TUNING_BLOCK) { | ||
1880 | host->tuning_done = 1; | ||
1881 | wake_up(&host->buf_ready_int); | ||
1882 | return; | ||
1883 | } | ||
1884 | } | ||
1885 | |||
1727 | if (!host->data) { | 1886 | if (!host->data) { |
1728 | /* | 1887 | /* |
1729 | * The "data complete" interrupt is also used to | 1888 | * The "data complete" interrupt is also used to |
@@ -2160,6 +2319,10 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2160 | if (caps[1] & SDHCI_SUPPORT_DDR50) | 2319 | if (caps[1] & SDHCI_SUPPORT_DDR50) |
2161 | mmc->caps |= MMC_CAP_UHS_DDR50; | 2320 | mmc->caps |= MMC_CAP_UHS_DDR50; |
2162 | 2321 | ||
2322 | /* Does the host needs tuning for SDR50? */ | ||
2323 | if (caps[1] & SDHCI_USE_SDR50_TUNING) | ||
2324 | host->flags |= SDHCI_SDR50_NEEDS_TUNING; | ||
2325 | |||
2163 | /* Driver Type(s) (A, C, D) supported by the host */ | 2326 | /* Driver Type(s) (A, C, D) supported by the host */ |
2164 | if (caps[1] & SDHCI_DRIVER_TYPE_A) | 2327 | if (caps[1] & SDHCI_DRIVER_TYPE_A) |
2165 | mmc->caps |= MMC_CAP_DRIVER_TYPE_A; | 2328 | mmc->caps |= MMC_CAP_DRIVER_TYPE_A; |
@@ -2313,6 +2476,9 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2313 | 2476 | ||
2314 | setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); | 2477 | setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); |
2315 | 2478 | ||
2479 | if (host->version >= SDHCI_SPEC_300) | ||
2480 | init_waitqueue_head(&host->buf_ready_int); | ||
2481 | |||
2316 | ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, | 2482 | ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, |
2317 | mmc_hostname(mmc), host); | 2483 | mmc_hostname(mmc), host); |
2318 | if (ret) | 2484 | if (ret) |