diff options
| -rw-r--r-- | drivers/mmc/core/sd.c | 6 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 168 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.h | 3 | ||||
| -rw-r--r-- | include/linux/mmc/host.h | 1 | ||||
| -rw-r--r-- | include/linux/mmc/mmc.h | 1 | ||||
| -rw-r--r-- | include/linux/mmc/sdhci.h | 4 |
6 files changed, 182 insertions, 1 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 732c3171ceca..fc65475a26ee 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
| @@ -618,6 +618,12 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) | |||
| 618 | 618 | ||
| 619 | /* Set current limit for the card */ | 619 | /* Set current limit for the card */ |
| 620 | err = sd_set_current_limit(card, status); | 620 | err = sd_set_current_limit(card, status); |
| 621 | if (err) | ||
| 622 | goto out; | ||
| 623 | |||
| 624 | /* SPI mode doesn't define CMD19 */ | ||
| 625 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) | ||
| 626 | err = card->host->ops->execute_tuning(card->host); | ||
| 621 | 627 | ||
| 622 | out: | 628 | out: |
| 623 | kfree(status); | 629 | kfree(status); |
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, | ||
