diff options
author | Kevin Liu <kliu5@marvell.com> | 2012-12-17 06:29:26 -0500 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2013-02-24 14:37:09 -0500 |
commit | 20b92a30b5610a5222060417961bc4ccb42ea5a5 (patch) | |
tree | 53672837a479970a0db28626907aaa0ff7250522 /drivers/mmc | |
parent | 0797e5f1453b2bedc08bbcbea0ea4fbe20350823 (diff) |
mmc: sdhci: update signal voltage switch code
The protocol related code is moved to core stack. So update the host
driver accordingly.
Signed-off-by: Kevin Liu <kliu5@marvell.com>
Tested-by: Tim Wang <wangtt@marvell.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-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 | /*****************************************************************************\ |