summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2017-08-23 10:03:41 (GMT)
committerJagan Teki <jagan@amarulasolutions.com>2017-08-28 17:06:44 (GMT)
commitde9b1771c3b663509102aa05b4275949da69f998 (patch)
tree22dfd9766e26175be0442dcf1791ebdd9e2e846f /drivers/mmc
parent8b3cec7da18645eda7f7cd0b65ee9f2dac573409 (diff)
downloadu-boot-de9b1771c3b663509102aa05b4275949da69f998.tar.xz
mmc: sunxi: Support new mode
Almost all of the newer Allwinner SoCs have a new operating mode for the eMMC clocks that needs to be enabled in both the clock and the MMC controller. Details about that mode are sparse, and the name itself (new mode vs old mode) doesn't give much details, but it seems that the it changes the sampling of the MMC clock. One side effect is also that it divides the parent clock rate by 2. Add support for it through a Kconfig option. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Reviewed-by: Jagan Teki <jagan@openedev.com>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/Kconfig4
-rw-r--r--drivers/mmc/sunxi_mmc.c27
2 files changed, 28 insertions, 3 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 56c352e..6de927b 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -369,6 +369,10 @@ config MMC_SUNXI
This selects support for the SD/MMC Host Controller on
Allwinner sunxi SoCs.
+config MMC_SUNXI_HAS_NEW_MODE
+ bool
+ depends on MMC_SUNXI
+
config GENERIC_ATMEL_MCI
bool "Atmel Multimedia Card Interface support"
depends on DM_MMC && BLK && ARCH_AT91
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 588574f..bc638ae 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -96,6 +96,18 @@ static int mmc_resource_init(int sdc_no)
static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
{
unsigned int pll, pll_hz, div, n, oclk_dly, sclk_dly;
+ bool new_mode = false;
+ u32 val = 0;
+
+ if (IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE) && (priv->mmc_no == 2))
+ new_mode = true;
+
+ /*
+ * The MMC clock has an extra /2 post-divider when operating in the new
+ * mode.
+ */
+ if (new_mode)
+ hz = hz * 2;
if (hz <= 24000000) {
pll = CCM_MMC_CTRL_OSCM24;
@@ -152,9 +164,18 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
#endif
}
- writel(CCM_MMC_CTRL_ENABLE | pll | CCM_MMC_CTRL_SCLK_DLY(sclk_dly) |
- CCM_MMC_CTRL_N(n) | CCM_MMC_CTRL_OCLK_DLY(oclk_dly) |
- CCM_MMC_CTRL_M(div), priv->mclkreg);
+ if (new_mode) {
+#ifdef CONFIG_MMC_SUNXI_HAS_NEW_MODE
+ val = CCM_MMC_CTRL_MODE_SEL_NEW;
+ writel(SUNXI_MMC_NTSR_MODE_SEL_NEW, &priv->reg->ntsr);
+#endif
+ } else {
+ val = CCM_MMC_CTRL_OCLK_DLY(oclk_dly) |
+ CCM_MMC_CTRL_SCLK_DLY(sclk_dly);
+ }
+
+ writel(CCM_MMC_CTRL_ENABLE| pll | CCM_MMC_CTRL_N(n) |
+ CCM_MMC_CTRL_M(div) | val, priv->mclkreg);
debug("mmc %u set mod-clk req %u parent %u n %u m %u rate %u\n",
priv->mmc_no, hz, pll_hz, 1u << n, div, pll_hz / (1u << n) / div);