From de9b1771c3b663509102aa05b4275949da69f998 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Aug 2017 12:03:41 +0200 Subject: 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 Reviewed-by: Jagan Teki diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun8i_a83t.h b/arch/arm/include/asm/arch-sunxi/clock_sun8i_a83t.h index 5e1346e..5dfcbf3 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun8i_a83t.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun8i_a83t.h @@ -220,6 +220,7 @@ struct sunxi_ccm_reg { #define CCM_MMC_CTRL_SCLK_DLY(x) ((x) << 20) #define CCM_MMC_CTRL_OSCM24 (0x0 << 24) #define CCM_MMC_CTRL_PLL6 (0x1 << 24) +#define CCM_MMC_CTRL_MODE_SEL_NEW (0x1 << 30) #define CCM_MMC_CTRL_ENABLE (0x1 << 31) #define CCM_USB_CTRL_PHY0_RST (0x1 << 0) diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h index cb52e64..69f737f 100644 --- a/arch/arm/include/asm/arch-sunxi/mmc.h +++ b/arch/arm/include/asm/arch-sunxi/mmc.h @@ -35,16 +35,19 @@ struct sunxi_mmc { u32 cbcr; /* 0x48 CIU byte count */ u32 bbcr; /* 0x4c BIU byte count */ u32 dbgc; /* 0x50 debug enable */ - u32 res0[11]; + u32 res0; /* 0x54 reserved */ + u32 a12a; /* 0x58 Auto command 12 argument */ + u32 ntsr; /* 0x5c New timing set register */ + u32 res1[8]; u32 dmac; /* 0x80 internal DMA control */ u32 dlba; /* 0x84 internal DMA descr list base address */ u32 idst; /* 0x88 internal DMA status */ u32 idie; /* 0x8c internal DMA interrupt enable */ u32 chda; /* 0x90 */ u32 cbda; /* 0x94 */ - u32 res1[26]; + u32 res2[26]; #ifdef CONFIG_SUNXI_GEN_SUN6I - u32 res2[64]; + u32 res3[64]; #endif u32 fifo; /* 0x100 / 0x200 FIFO access address */ }; @@ -116,6 +119,8 @@ struct sunxi_mmc { #define SUNXI_MMC_STATUS_CARD_DATA_BUSY (0x1 << 9) #define SUNXI_MMC_STATUS_DATA_FSM_BUSY (0x1 << 10) +#define SUNXI_MMC_NTSR_MODE_SEL_NEW (0x1 << 31) + #define SUNXI_MMC_IDMAC_RESET (0x1 << 0) #define SUNXI_MMC_IDMAC_FIXBURST (0x1 << 1) #define SUNXI_MMC_IDMAC_ENABLE (0x1 << 7) 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); -- cgit v0.10.2 From 343ff161062880c5112b014c9181694bd01ee886 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Aug 2017 12:03:42 +0200 Subject: sunxi: Enable MMC new mode for A83T The eMMC controller for the A83T uses the new operating mode. Enable it. Signed-off-by: Maxime Ripard Reviewed-by: Jagan Teki diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 2cd7bae..2309f59 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -125,6 +125,7 @@ config MACH_SUN8I_A83T bool "sun8i (Allwinner A83T)" select CPU_V7 select SUNXI_GEN_SUN6I + select MMC_SUNXI_HAS_NEW_MODE select SUPPORT_SPL config MACH_SUN8I_H3 -- cgit v0.10.2 From c9319b3f204583f5c415db8865492a76ab9425b3 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 28 Aug 2017 14:30:31 +0530 Subject: sunxi: bpi-m3: Enable eMMC Add CONFIG_MMC_SUNXI_SLOT_EXTRA=2 to use eMMC on BPI_M3 board. Cc: Chen-Yu Tsai Cc: Maxime Ripard Signed-off-by: Jagan Teki Tested-by: Jagan Teki diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig index 45eadcb..c53ade0 100644 --- a/configs/Sinovoip_BPI_M3_defconfig +++ b/configs/Sinovoip_BPI_M3_defconfig @@ -12,6 +12,7 @@ CONFIG_USB0_ID_DET="PH11" CONFIG_USB1_VBUS_PIN="PD24" CONFIG_AXP_GPIO=y CONFIG_SATAPWR="PD25" +CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-sinovoip-bpi-m3" # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_CONSOLE_MUX=y -- cgit v0.10.2 From ead3697d7ec491c055fe546b3a45bcfba45fa022 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Aug 2017 13:41:33 +0200 Subject: mmc: sunxi: fix legacy MMC initialisation The driver-model rework changed, among other things, the way the private data were moved around. It now uses the private field in the struct mmc. However, the mmc_create argument was changed in the process to always pass the array we used to have to store our private structures. The basically means that all the MMC driver instances will now have the private data of the first instance, which obviously doesn't work very well. Pass the proper pointer to mmc_create. Fixes: 034e226bc77e ("dm: mmc: sunxi: Pass private data around explicitly") Signed-off-by: Maxime Ripard Tested-by: Chen-Yu Tsai Tested-by: Jagan Teki Reviewed-by: Jagan Teki diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index bc638ae..a76e763 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -519,7 +519,7 @@ struct mmc *sunxi_mmc_init(int sdc_no) if (ret) return NULL; - return mmc_create(cfg, mmc_host); + return mmc_create(cfg, priv); } #else -- cgit v0.10.2 From 8a647fc3ca2a93e2b6c965999ac2e0316191a755 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 31 Aug 2017 21:57:48 +0800 Subject: mmc: sunxi: Only update timing mode bit when enabling new timing mode When enabling the new mmc timing mode, we inadvertently clear all the remaining bits in the new timing mode register. The bits cleared include a default phase delay on the output clock. The BSP kernel states that the default values are supposed to be used. Clearing them results in decreased performance or transfer errors on some boards. Fixes: de9b1771c3b6 ("mmc: sunxi: Support new mode") Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Reviewed-by: Jagan Teki diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index a76e763..4edb4be 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -167,7 +167,7 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) 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); + setbits_le32(&priv->reg->ntsr, SUNXI_MMC_NTSR_MODE_SEL_NEW); #endif } else { val = CCM_MMC_CTRL_OCLK_DLY(oclk_dly) | -- cgit v0.10.2