From 2a8882ecefdeb9eb7ea2ea21427460e773a00e5a Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Fri, 9 Nov 2018 20:41:44 -0800 Subject: [PATCH 1/5] sunxi-mmc: introduce new MMC_SUNXI_HAS_MODE_SWITCH option Allwinner A64 has new mode but doesn't have a mode switch in CCM, and CCM_MMC_CTRL_MODE_SEL_NEW is not defined, so compilation fails if MMC_SUNXI_HAS_NEW_MODE is enabled Introduce new MMC_SUNXI_HAS_MODE_SWITCH option to be able to ifdef usage of CCM_MMC_CTRL_MODE_SEL_NEW Signed-off-by: Vasily Khoruzhick Reviewed-by: Jagan Teki [jagan: update commit message] Signed-off-by: Jagan Teki Tested-by: Jagan Teki # Amarula A64-Relic --- arch/arm/mach-sunxi/Kconfig | 1 + drivers/mmc/Kconfig | 4 ++++ drivers/mmc/sunxi_mmc.c | 2 ++ 3 files changed, 7 insertions(+) diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 560dc9b25d..66fff6c6d3 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -230,6 +230,7 @@ config MACH_SUN8I_A83T select PHY_SUN4I_USB select SUNXI_GEN_SUN6I select MMC_SUNXI_HAS_NEW_MODE + select MMC_SUNXI_HAS_MODE_SWITCH select SUPPORT_SPL config MACH_SUN8I_H3 diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 27246ee465..3f7458d409 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -569,6 +569,10 @@ config MMC_SUNXI_HAS_NEW_MODE bool depends on MMC_SUNXI +config MMC_SUNXI_HAS_MODE_SWITCH + 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 147eb9b4d5..b3526f5e3f 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -176,7 +176,9 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) if (new_mode) { #ifdef CONFIG_MMC_SUNXI_HAS_NEW_MODE +#ifdef CONFIG_MMC_SUNXI_HAS_MODE_SWITCH val = CCM_MMC_CTRL_MODE_SEL_NEW; +#endif setbits_le32(&priv->reg->ntsr, SUNXI_MMC_NTSR_MODE_SEL_NEW); #endif } else if (!calibrate) { From 629d267a9738f0214853493968f114962de54642 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Fri, 9 Nov 2018 20:41:45 -0800 Subject: [PATCH 2/5] sunxi-mmc: don't double clock for new mode unconditionally Comment in Linux driver says that clock needs to be doubled only if we use DDR modes, moreover divider has to be set accordingly. U-boot driver doesn't declare support for any DDR modes and doesn't set internal clock divider in CLKCR, so it doubles clock unconditionally when new mode is used. Some cards can't handle that and as result SPL fails to load u-boot. Fixes: de9b1771c3b ("mmc: sunxi: Support new mode") Signed-off-by: Vasily Khoruzhick Reviewed-by: Jagan Teki Tested-by: Jagan Teki # Amarula A64-Relic --- drivers/mmc/sunxi_mmc.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index b3526f5e3f..e50b2c3343 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -109,13 +109,6 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz) calibrate = true; #endif - /* - * 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; pll_hz = 24000000; From 0e21a2ffb3404152c90cdcd9fc9ba34b404beab8 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Fri, 9 Nov 2018 20:41:46 -0800 Subject: [PATCH 3/5] sunxi-mmc: use new mode on both controllers on A64 Using new mode improves stability of eMMC and SD cards. Without it SPL fails to load u-boot from SD on Pinebook. Signed-off-by: Vasily Khoruzhick Reviewed-by: Chen-Yu Tsai Tested-by: Jagan Teki # Amarula A64-Relic Reviewed-by: Jagan Teki --- arch/arm/mach-sunxi/Kconfig | 1 + drivers/mmc/sunxi_mmc.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 66fff6c6d3..3c54f5106d 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -282,6 +282,7 @@ config MACH_SUN50I select SUN6I_PRCM select SUNXI_DE2 select SUNXI_GEN_SUN6I + select MMC_SUNXI_HAS_NEW_MODE select SUPPORT_SPL select SUNXI_DRAM_DW select SUNXI_DRAM_DW_32BIT diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index e50b2c3343..9bf040cb40 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -98,12 +98,16 @@ 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; + bool new_mode = true; bool calibrate = false; u32 val = 0; - if (IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE) && (priv->mmc_no == 2)) - new_mode = true; + if (!IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE)) + new_mode = false; + + /* A83T support new mode only on eMMC */ + if (IS_ENABLED(CONFIG_MACH_SUN8I_A83T) && priv->mmc_no != 2) + new_mode = false; #if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H6) calibrate = true; From aa09a071c3295011816c0e2f18532f61bc8b74f3 Mon Sep 17 00:00:00 2001 From: Michael Trimarchi Date: Wed, 31 Oct 2018 20:03:16 +0100 Subject: [PATCH 4/5] sunxi: Fix memory 2-rank initialization for a33 cpu When we initialize the memory we need to autodetect rank and size but this can happen only if we send the proper reset to both memory module including cke signal. For this reason we need initialize the physical on both channel because we need to presume that both are connected. This way let the CLKE to be activated at the right time with the memory reset coming from the cpu Signed-off-by: Michael Trimarchi Acked-by: Maxime Ripard --- arch/arm/mach-sunxi/dram_sun8i_a33.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-sunxi/dram_sun8i_a33.c b/arch/arm/mach-sunxi/dram_sun8i_a33.c index d9aa0c6d7e..1da2727f98 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a33.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a33.c @@ -334,7 +334,7 @@ unsigned long sunxi_dram_init(void) struct dram_para para = { .cs1 = 0, .bank = 1, - .rank = 1, + .rank = 2, .rows = 15, .bus_width = 16, .page_size = 2048, From 9b16ede4a4e898564f54e1c09ae658a5975b432b Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Fri, 23 Nov 2018 00:37:48 +0100 Subject: [PATCH 5/5] sun8i_emac: add support for setting EMAC TX/RX delay Some boards have the EMAC TX/RX lanes wired with a different length with the clock lane, which can be workarounded by setting a TX/RX delay in the EMAC. This kind of delays are already defined in the newest device tree binding of dwmac-sun8i, which has already entered linux-next. Add support for setting these delays. Signed-off-by: Icenowy Zheng Reviewed-by: Jagan Teki --- drivers/net/sun8i_emac.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index 3ba3a1ff8b..c9798445c7 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -60,6 +60,10 @@ #define SC_ETCS_MASK GENMASK(1, 0) #define SC_ETCS_EXT_GMII 0x1 #define SC_ETCS_INT_GMII 0x2 +#define SC_ETXDC_MASK GENMASK(12, 10) +#define SC_ETXDC_OFFSET 10 +#define SC_ERXDC_MASK GENMASK(9, 5) +#define SC_ERXDC_OFFSET 5 #define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ) @@ -140,6 +144,8 @@ struct emac_eth_dev { struct sun8i_eth_pdata { struct eth_pdata eth_pdata; u32 reset_delays[3]; + int tx_delay_ps; + int rx_delay_ps; }; @@ -273,7 +279,8 @@ static int sun8i_emac_set_syscon_ephy(struct emac_eth_dev *priv, u32 *reg) return 0; } -static int sun8i_emac_set_syscon(struct emac_eth_dev *priv) +static int sun8i_emac_set_syscon(struct sun8i_eth_pdata *pdata, + struct emac_eth_dev *priv) { int ret; u32 reg; @@ -312,6 +319,14 @@ static int sun8i_emac_set_syscon(struct emac_eth_dev *priv) return -EINVAL; } + if (pdata->tx_delay_ps) + reg |= ((pdata->tx_delay_ps / 100) << SC_ETXDC_OFFSET) + & SC_ETXDC_MASK; + + if (pdata->rx_delay_ps) + reg |= ((pdata->rx_delay_ps / 100) << SC_ERXDC_OFFSET) + & SC_ERXDC_MASK; + writel(reg, priv->sysctl_reg + 0x30); return 0; @@ -784,13 +799,14 @@ static void sun8i_emac_eth_stop(struct udevice *dev) static int sun8i_emac_eth_probe(struct udevice *dev) { - struct eth_pdata *pdata = dev_get_platdata(dev); + struct sun8i_eth_pdata *sun8i_pdata = dev_get_platdata(dev); + struct eth_pdata *pdata = &sun8i_pdata->eth_pdata; struct emac_eth_dev *priv = dev_get_priv(dev); priv->mac_reg = (void *)pdata->iobase; sun8i_emac_board_setup(priv); - sun8i_emac_set_syscon(priv); + sun8i_emac_set_syscon(sun8i_pdata, priv); sun8i_mdio_init(dev->name, dev); priv->bus = miiphy_get_dev_by_name(dev->name); @@ -891,6 +907,18 @@ static int sun8i_emac_eth_ofdata_to_platdata(struct udevice *dev) if (!priv->use_internal_phy) parse_phy_pins(dev); + sun8i_pdata->tx_delay_ps = fdtdec_get_int(gd->fdt_blob, node, + "allwinner,tx-delay-ps", 0); + if (sun8i_pdata->tx_delay_ps < 0 || sun8i_pdata->tx_delay_ps > 700) + printf("%s: Invalid TX delay value %d\n", __func__, + sun8i_pdata->tx_delay_ps); + + sun8i_pdata->rx_delay_ps = fdtdec_get_int(gd->fdt_blob, node, + "allwinner,rx-delay-ps", 0); + if (sun8i_pdata->rx_delay_ps < 0 || sun8i_pdata->rx_delay_ps > 3100) + printf("%s: Invalid RX delay value %d\n", __func__, + sun8i_pdata->rx_delay_ps); + #ifdef CONFIG_DM_GPIO if (fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), "snps,reset-active-low"))