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 5e1346e5242ad78916b655239d8cddc771190064..5dfcbf3b017bec52a80f97eab0121302c27de46b 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 cb52e648731ce9687b7c9cb472463fd54d8da38d..69f737f3bffc5eb8873c6d511b4e60dcf455c99a 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/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 2cd7bae078b896c0dec41d750b7f34153b23ad56..2309f59999314f0bbc7de61f674fffc2c6bfc88e 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 diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig index 45eadcb44312c585bacb1c45fbf0b836ee193ef3..c53ade0c97154707b78e1f8e7bb22750616367f6 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 diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 56c352e72a0210ea417a8348581af971c9ba529b..6de927b8c6cb98ee71c60b8b6e22ec8ae3a7ffa7 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 588574fab6a9a02ff2dae4b49d1a8f1729e209f6..4edb4be46c819295e99917e75c143cae489c7258 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; + setbits_le32(&priv->reg->ntsr, SUNXI_MMC_NTSR_MODE_SEL_NEW); +#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); @@ -498,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