From: Icenowy Zheng Date: Sat, 3 Jun 2017 09:10:16 +0000 (+0800) Subject: sunxi: add option for 16-bit DW DRAM controller X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=87098d701da77f264c9cbed67a5d6fb27fbaaf3f;p=u-boot.git sunxi: add option for 16-bit DW DRAM controller Some Allwinner SoCs features a DesignWare-like controller with only 16 bit bus width. Add support for them. Signed-off-by: Icenowy Zheng Reviewed-by: Jagan Teki Tested-by: Jagan Teki --- diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 11da1ab738..8b8fc20a51 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -37,11 +37,26 @@ config SUNXI_DRAM_DW not have official open-source DRAM initialization code, but can use modified H3 DRAM initialization code. +if SUNXI_DRAM_DW +config SUNXI_DRAM_DW_16BIT + bool + ---help--- + Select this for sunxi SoCs with DesignWare DRAM controller and + have only 16-bit memory buswidth. + +config SUNXI_DRAM_DW_32BIT + bool + ---help--- + Select this for sunxi SoCs with DesignWare DRAM controller with + 32-bit memory buswidth. +endif + config MACH_SUNXI_H3_H5 bool select DM_I2C select SUNXI_DE2 select SUNXI_DRAM_DW + select SUNXI_DRAM_DW_32BIT select SUNXI_GEN_SUN6I select SUPPORT_SPL @@ -127,6 +142,7 @@ config MACH_SUN8I_R40 select SUNXI_GEN_SUN6I select SUPPORT_SPL select SUNXI_DRAM_DW + select SUNXI_DRAM_DW_32BIT config MACH_SUN8I_V3S bool "sun8i (Allwinner V3s)" @@ -153,6 +169,7 @@ config MACH_SUN50I select SUNXI_HIGH_SRAM select SUPPORT_SPL select SUNXI_DRAM_DW + select SUNXI_DRAM_DW_32BIT select FIT select SPL_LOAD_FIT diff --git a/arch/arm/mach-sunxi/dram_sunxi_dw.c b/arch/arm/mach-sunxi/dram_sunxi_dw.c index 77fa6c2889..de683a1b63 100644 --- a/arch/arm/mach-sunxi/dram_sunxi_dw.c +++ b/arch/arm/mach-sunxi/dram_sunxi_dw.c @@ -380,6 +380,13 @@ static void mctl_h3_zq_calibration_quirk(struct dram_para *para) { struct sunxi_mctl_ctl_reg * const mctl_ctl = (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; + int zq_count; + +#if defined CONFIG_SUNXI_DRAM_DW_16BIT + zq_count = 4; +#else + zq_count = 6; +#endif if ((readl(SUNXI_SRAMC_BASE + 0x24) & 0xff) == 0 && (readl(SUNXI_SRAMC_BASE + 0xf0) & 0x1) == 0) { @@ -408,7 +415,7 @@ static void mctl_h3_zq_calibration_quirk(struct dram_para *para) writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]); - for (i = 0; i < 6; i++) { + for (i = 0; i < zq_count; i++) { u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf; writel((zq << 20) | (zq << 16) | (zq << 12) | @@ -430,7 +437,9 @@ static void mctl_h3_zq_calibration_quirk(struct dram_para *para) writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]); writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]); - writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]); + if (zq_count > 4) + writel((zq_val[5] << 16) | zq_val[4], + &mctl_ctl->zqdr[2]); } } @@ -580,8 +589,14 @@ static int mctl_channel_init(uint16_t socid, struct dram_para *para) /* set half DQ */ if (!para->bus_full_width) { +#if defined CONFIG_SUNXI_DRAM_DW_32BIT writel(0x0, &mctl_ctl->dx[2].gcr); writel(0x0, &mctl_ctl->dx[3].gcr); +#elif defined CONFIG_SUNXI_DRAM_DW_16BIT + writel(0x0, &mctl_ctl->dx[1].gcr); +#else +#error Unsupported DRAM bus width! +#endif } /* data training configuration */ @@ -612,19 +627,29 @@ static int mctl_channel_init(uint16_t socid, struct dram_para *para) /* detect ranks and bus width */ if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) { /* only one rank */ - if (((readl(&mctl_ctl->dx[0].gsr[0]) >> 24) & 0x2) || - ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x2)) { + if (((readl(&mctl_ctl->dx[0].gsr[0]) >> 24) & 0x2) +#if defined CONFIG_SUNXI_DRAM_DW_32BIT + || ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x2) +#endif + ) { clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24); para->dual_rank = 0; } /* only half DQ width */ +#if defined CONFIG_SUNXI_DRAM_DW_32BIT if (((readl(&mctl_ctl->dx[2].gsr[0]) >> 24) & 0x1) || ((readl(&mctl_ctl->dx[3].gsr[0]) >> 24) & 0x1)) { writel(0x0, &mctl_ctl->dx[2].gcr); writel(0x0, &mctl_ctl->dx[3].gcr); para->bus_full_width = 0; } +#elif defined CONFIG_SUNXI_DRAM_DW_16BIT + if ((readl(&mctl_ctl->dx[1].gsr[0]) >> 24) & 0x1) { + writel(0x0, &mctl_ctl->dx[1].gcr); + para->bus_full_width = 0; + } +#endif mctl_set_cr(socid, para); udelay(20);