diff options
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 192 |
1 files changed, 78 insertions, 114 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3bb9b88772cf..efb112684787 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -1615,145 +1615,95 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
| 1615 | spin_unlock_irqrestore(&host->lock, flags); | 1615 | spin_unlock_irqrestore(&host->lock, flags); |
| 1616 | } | 1616 | } |
| 1617 | 1617 | ||
| 1618 | static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host, | 1618 | static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, |
| 1619 | u16 ctrl) | 1619 | int signal_voltage) |
| 1620 | { | 1620 | { |
| 1621 | u16 ctrl; | ||
| 1621 | int ret; | 1622 | int ret; |
| 1622 | 1623 | ||
| 1623 | /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ | 1624 | /* |
| 1624 | ctrl &= ~SDHCI_CTRL_VDD_180; | 1625 | * Signal Voltage Switching is only applicable for Host Controllers |
| 1625 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 1626 | * v3.00 and above. |
| 1626 | 1627 | */ | |
| 1627 | if (host->vqmmc) { | 1628 | if (host->version < SDHCI_SPEC_300) |
| 1628 | ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000); | 1629 | return 0; |
| 1629 | if (ret) { | ||
| 1630 | pr_warning("%s: Switching to 3.3V signalling voltage " | ||
| 1631 | " failed\n", mmc_hostname(host->mmc)); | ||
| 1632 | return -EIO; | ||
| 1633 | } | ||
| 1634 | } | ||
| 1635 | /* Wait for 5ms */ | ||
| 1636 | usleep_range(5000, 5500); | ||
| 1637 | 1630 | ||
| 1638 | /* 3.3V regulator output should be stable within 5 ms */ | ||
| 1639 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1631 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
| 1640 | if (!(ctrl & SDHCI_CTRL_VDD_180)) | ||
| 1641 | return 0; | ||
| 1642 | 1632 | ||
| 1643 | pr_warning("%s: 3.3V regulator output did not became stable\n", | 1633 | switch (signal_voltage) { |
| 1644 | mmc_hostname(host->mmc)); | 1634 | case MMC_SIGNAL_VOLTAGE_330: |
| 1635 | /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ | ||
| 1636 | ctrl &= ~SDHCI_CTRL_VDD_180; | ||
| 1637 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
| 1645 | 1638 | ||
| 1646 | return -EIO; | 1639 | if (host->vqmmc) { |
| 1647 | } | 1640 | ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000); |
| 1641 | if (ret) { | ||
| 1642 | pr_warning("%s: Switching to 3.3V signalling voltage " | ||
| 1643 | " failed\n", mmc_hostname(host->mmc)); | ||
| 1644 | return -EIO; | ||
| 1645 | } | ||
| 1646 | } | ||
| 1647 | /* Wait for 5ms */ | ||
| 1648 | usleep_range(5000, 5500); | ||
| 1648 | 1649 | ||
| 1649 | static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host, | 1650 | /* 3.3V regulator output should be stable within 5 ms */ |
| 1650 | u16 ctrl) | 1651 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
| 1651 | { | 1652 | if (!(ctrl & SDHCI_CTRL_VDD_180)) |
| 1652 | u8 pwr; | 1653 | return 0; |
| 1653 | u16 clk; | ||
| 1654 | u32 present_state; | ||
| 1655 | int ret; | ||
| 1656 | 1654 | ||
| 1657 | /* Stop SDCLK */ | 1655 | pr_warning("%s: 3.3V regulator output did not became stable\n", |
| 1658 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | 1656 | mmc_hostname(host->mmc)); |
| 1659 | clk &= ~SDHCI_CLOCK_CARD_EN; | 1657 | |
| 1660 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | 1658 | return -EAGAIN; |
| 1659 | case MMC_SIGNAL_VOLTAGE_180: | ||
| 1660 | if (host->vqmmc) { | ||
| 1661 | ret = regulator_set_voltage(host->vqmmc, | ||
| 1662 | 1700000, 1950000); | ||
| 1663 | if (ret) { | ||
| 1664 | pr_warning("%s: Switching to 1.8V signalling voltage " | ||
| 1665 | " failed\n", mmc_hostname(host->mmc)); | ||
| 1666 | return -EIO; | ||
| 1667 | } | ||
| 1668 | } | ||
| 1661 | 1669 | ||
| 1662 | /* Check whether DAT[3:0] is 0000 */ | ||
| 1663 | present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); | ||
| 1664 | if (!((present_state & SDHCI_DATA_LVL_MASK) >> | ||
| 1665 | SDHCI_DATA_LVL_SHIFT)) { | ||
| 1666 | /* | 1670 | /* |
| 1667 | * Enable 1.8V Signal Enable in the Host Control2 | 1671 | * Enable 1.8V Signal Enable in the Host Control2 |
| 1668 | * register | 1672 | * register |
| 1669 | */ | 1673 | */ |
| 1670 | if (host->vqmmc) | 1674 | ctrl |= SDHCI_CTRL_VDD_180; |
| 1671 | ret = regulator_set_voltage(host->vqmmc, | 1675 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
| 1672 | 1700000, 1950000); | ||
| 1673 | else | ||
| 1674 | ret = 0; | ||
| 1675 | 1676 | ||
| 1676 | if (!ret) { | 1677 | /* Wait for 5ms */ |
| 1677 | ctrl |= SDHCI_CTRL_VDD_180; | 1678 | usleep_range(5000, 5500); |
| 1678 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
| 1679 | 1679 | ||
| 1680 | /* Wait for 5ms */ | 1680 | /* 1.8V regulator output should be stable within 5 ms */ |
| 1681 | usleep_range(5000, 5500); | 1681 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
| 1682 | if (ctrl & SDHCI_CTRL_VDD_180) | ||
| 1683 | return 0; | ||
| 1682 | 1684 | ||
| 1683 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1685 | pr_warning("%s: 1.8V regulator output did not became stable\n", |
| 1684 | if (ctrl & SDHCI_CTRL_VDD_180) { | 1686 | mmc_hostname(host->mmc)); |
| 1685 | /* Provide SDCLK again and wait for 1ms */ | ||
| 1686 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | ||
| 1687 | clk |= SDHCI_CLOCK_CARD_EN; | ||
| 1688 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
| 1689 | usleep_range(1000, 1500); | ||
| 1690 | 1687 | ||
| 1691 | /* | 1688 | return -EAGAIN; |
| 1692 | * If DAT[3:0] level is 1111b, then the card | 1689 | case MMC_SIGNAL_VOLTAGE_120: |
| 1693 | * was successfully switched to 1.8V signaling. | 1690 | if (host->vqmmc) { |
| 1694 | */ | 1691 | ret = regulator_set_voltage(host->vqmmc, 1100000, 1300000); |
| 1695 | present_state = sdhci_readl(host, | 1692 | if (ret) { |
| 1696 | SDHCI_PRESENT_STATE); | 1693 | pr_warning("%s: Switching to 1.2V signalling voltage " |
| 1697 | if ((present_state & SDHCI_DATA_LVL_MASK) == | 1694 | " failed\n", mmc_hostname(host->mmc)); |
| 1698 | SDHCI_DATA_LVL_MASK) | 1695 | return -EIO; |
| 1699 | return 0; | ||
| 1700 | } | 1696 | } |
| 1701 | } | 1697 | } |
| 1702 | } | ||
| 1703 | |||
| 1704 | /* | ||
| 1705 | * If we are here, that means the switch to 1.8V signaling | ||
| 1706 | * failed. We power cycle the card, and retry initialization | ||
| 1707 | * sequence by setting S18R to 0. | ||
| 1708 | */ | ||
| 1709 | pwr = sdhci_readb(host, SDHCI_POWER_CONTROL); | ||
| 1710 | pwr &= ~SDHCI_POWER_ON; | ||
| 1711 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | ||
| 1712 | if (host->vmmc) | ||
| 1713 | regulator_disable(host->vmmc); | ||
| 1714 | |||
| 1715 | /* Wait for 1ms as per the spec */ | ||
| 1716 | usleep_range(1000, 1500); | ||
| 1717 | pwr |= SDHCI_POWER_ON; | ||
| 1718 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | ||
| 1719 | if (host->vmmc) | ||
| 1720 | regulator_enable(host->vmmc); | ||
| 1721 | |||
| 1722 | pr_warning("%s: Switching to 1.8V signalling voltage failed, " | ||
| 1723 | "retrying with S18R set to 0\n", mmc_hostname(host->mmc)); | ||
| 1724 | |||
| 1725 | return -EAGAIN; | ||
| 1726 | } | ||
| 1727 | |||
| 1728 | static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | ||
| 1729 | struct mmc_ios *ios) | ||
| 1730 | { | ||
| 1731 | u16 ctrl; | ||
| 1732 | |||
| 1733 | /* | ||
| 1734 | * Signal Voltage Switching is only applicable for Host Controllers | ||
| 1735 | * v3.00 and above. | ||
| 1736 | */ | ||
| 1737 | if (host->version < SDHCI_SPEC_300) | ||
| 1738 | return 0; | 1698 | return 0; |
| 1739 | 1699 | default: | |
| 1740 | /* | ||
| 1741 | * We first check whether the request is to set signalling voltage | ||
| 1742 | * to 3.3V. If so, we change the voltage to 3.3V and return quickly. | ||
| 1743 | */ | ||
| 1744 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
| 1745 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) | ||
| 1746 | return sdhci_do_3_3v_signal_voltage_switch(host, ctrl); | ||
| 1747 | else if (!(ctrl & SDHCI_CTRL_VDD_180) && | ||
| 1748 | (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) | ||
| 1749 | return sdhci_do_1_8v_signal_voltage_switch(host, ctrl); | ||
| 1750 | else | ||
| 1751 | /* No signal voltage switch required */ | 1700 | /* No signal voltage switch required */ |
| 1752 | return 0; | 1701 | return 0; |
| 1702 | } | ||
| 1753 | } | 1703 | } |
| 1754 | 1704 | ||
| 1755 | static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, | 1705 | static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, |
| 1756 | struct mmc_ios *ios) | 1706 | int signal_voltage) |
| 1757 | { | 1707 | { |
| 1758 | struct sdhci_host *host = mmc_priv(mmc); | 1708 | struct sdhci_host *host = mmc_priv(mmc); |
| 1759 | int err; | 1709 | int err; |
| @@ -1761,11 +1711,24 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, | |||
| 1761 | if (host->version < SDHCI_SPEC_300) | 1711 | if (host->version < SDHCI_SPEC_300) |
| 1762 | return 0; | 1712 | return 0; |
| 1763 | sdhci_runtime_pm_get(host); | 1713 | sdhci_runtime_pm_get(host); |
| 1764 | err = sdhci_do_start_signal_voltage_switch(host, ios); | 1714 | err = sdhci_do_start_signal_voltage_switch(host, signal_voltage); |
| 1765 | sdhci_runtime_pm_put(host); | 1715 | sdhci_runtime_pm_put(host); |
| 1766 | return err; | 1716 | return err; |
| 1767 | } | 1717 | } |
| 1768 | 1718 | ||
| 1719 | static int sdhci_card_busy(struct mmc_host *mmc) | ||
| 1720 | { | ||
| 1721 | struct sdhci_host *host = mmc_priv(mmc); | ||
| 1722 | u32 present_state; | ||
| 1723 | |||
| 1724 | sdhci_runtime_pm_get(host); | ||
| 1725 | /* Check whether DAT[3:0] is 0000 */ | ||
| 1726 | present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); | ||
| 1727 | sdhci_runtime_pm_put(host); | ||
| 1728 | |||
| 1729 | return !(present_state & SDHCI_DATA_LVL_MASK); | ||
| 1730 | } | ||
| 1731 | |||
| 1769 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) | 1732 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) |
| 1770 | { | 1733 | { |
| 1771 | struct sdhci_host *host; | 1734 | struct sdhci_host *host; |
| @@ -2036,6 +1999,7 @@ static const struct mmc_host_ops sdhci_ops = { | |||
| 2036 | .execute_tuning = sdhci_execute_tuning, | 1999 | .execute_tuning = sdhci_execute_tuning, |
| 2037 | .enable_preset_value = sdhci_enable_preset_value, | 2000 | .enable_preset_value = sdhci_enable_preset_value, |
| 2038 | .card_event = sdhci_card_event, | 2001 | .card_event = sdhci_card_event, |
| 2002 | .card_busy = sdhci_card_busy, | ||
| 2039 | }; | 2003 | }; |
| 2040 | 2004 | ||
| 2041 | /*****************************************************************************\ | 2005 | /*****************************************************************************\ |
