diff options
Diffstat (limited to 'drivers/ram/stm32mp1')
-rw-r--r-- | drivers/ram/stm32mp1/stm32mp1_ddr.c | 95 | ||||
-rw-r--r-- | drivers/ram/stm32mp1/stm32mp1_ddr.h | 6 | ||||
-rw-r--r-- | drivers/ram/stm32mp1/stm32mp1_ram.c | 5 |
3 files changed, 87 insertions, 19 deletions
diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c index 0e37ea93fbc..b275407d4ac 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr.c +++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c @@ -12,6 +12,7 @@ #include <timer.h> #include <asm/io.h> #include <asm/arch/ddr.h> +#include <dm/device.h> #include <linux/bitops.h> #include <linux/delay.h> #include <linux/iopoll.h> @@ -19,7 +20,8 @@ #include "stm32mp1_ddr.h" #include "stm32mp1_ddr_regs.h" -#define RCC_DDRITFCR 0xD8 +#define RCC_DDRITFCR_STM32MP13xx 0x5c0 +#define RCC_DDRITFCR_STM32MP15xx 0xd8 #define RCC_DDRITFCR_DDRCAPBRST (BIT(14)) #define RCC_DDRITFCR_DDRCAXIRST (BIT(15)) @@ -66,9 +68,19 @@ struct reg_desc { #define DDRCTL_REG_REG_SIZE 25 /* st,ctl-reg */ #define DDRCTL_REG_TIMING_SIZE 12 /* st,ctl-timing */ #define DDRCTL_REG_MAP_SIZE 9 /* st,ctl-map */ -#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */ -#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */ +#define DDRCTL_REG_PERF_SIZE_STM32MP13xx 11 /* st,ctl-perf */ +#define DDRCTL_REG_PERF_SIZE_STM32MP15xx 17 /* st,ctl-perf */ +#define DDRCTL_REG_PERF_SIZE \ + (IS_ENABLED(CONFIG_STM32MP15X) ? DDRCTL_REG_PERF_SIZE_STM32MP15xx : \ + DDRCTL_REG_PERF_SIZE_STM32MP13xx) + +#define DDRPHY_REG_REG_SIZE_STM32MP13xx 9 /* st,phy-reg */ +#define DDRPHY_REG_REG_SIZE_STM32MP15xx 11 /* st,phy-reg */ +#define DDRPHY_REG_REG_SIZE \ + (IS_ENABLED(CONFIG_STM32MP15X) ? DDRPHY_REG_REG_SIZE_STM32MP15xx : \ + DDRPHY_REG_REG_SIZE_STM32MP13xx) + #define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */ #define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg) @@ -142,12 +154,14 @@ static const struct reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = { DDRCTL_REG_PERF(pcfgqos1_0), DDRCTL_REG_PERF(pcfgwqos0_0), DDRCTL_REG_PERF(pcfgwqos1_0), +#if IS_ENABLED(CONFIG_STM32MP15X) DDRCTL_REG_PERF(pcfgr_1), DDRCTL_REG_PERF(pcfgw_1), DDRCTL_REG_PERF(pcfgqos0_1), DDRCTL_REG_PERF(pcfgqos1_1), DDRCTL_REG_PERF(pcfgwqos0_1), DDRCTL_REG_PERF(pcfgwqos1_1), +#endif }; #define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg) @@ -161,8 +175,10 @@ static const struct reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = { DDRPHY_REG_REG(zq0cr1), DDRPHY_REG_REG(dx0gcr), DDRPHY_REG_REG(dx1gcr), +#if IS_ENABLED(CONFIG_STM32MP15X) DDRPHY_REG_REG(dx2gcr), DDRPHY_REG_REG(dx3gcr), +#endif }; #define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing) @@ -211,6 +227,7 @@ static const struct reg_desc ddrphy_dyn[] = { DDRPHY_REG_DYN(dx1dllcr), DDRPHY_REG_DYN(dx1dqtr), DDRPHY_REG_DYN(dx1dqstr), +#if IS_ENABLED(CONFIG_STM32MP15X) DDRPHY_REG_DYN(dx2gsr0), DDRPHY_REG_DYN(dx2gsr1), DDRPHY_REG_DYN(dx2dllcr), @@ -221,6 +238,7 @@ static const struct reg_desc ddrphy_dyn[] = { DDRPHY_REG_DYN(dx3dllcr), DDRPHY_REG_DYN(dx3dqtr), DDRPHY_REG_DYN(dx3dqstr), +#endif }; #define DDRPHY_REG_DYN_SIZE ARRAY_SIZE(ddrphy_dyn) @@ -287,6 +305,24 @@ const char *base_name[] = { [DDRPHY_BASE] = "phy", }; +bool is_stm32mp13_ddrc(const struct ddr_info *priv) +{ + if (IS_ENABLED(CONFIG_STM32MP13X) && !IS_ENABLED(CONFIG_STM32MP15X)) + return true; /* STM32MP13xx only build */ + else if (!IS_ENABLED(CONFIG_STM32MP13X) && IS_ENABLED(CONFIG_STM32MP15X)) + return false; /* STM32MP15xx only build */ + + /* Combined STM32MP13xx and STM32MP15xx build */ + return device_is_compatible(priv->dev, "st,stm32mp13-ddr"); +} + +static u32 get_rcc_ddritfcr(const struct ddr_info *priv) +{ + return priv->rcc + (is_stm32mp13_ddrc(priv) ? + RCC_DDRITFCR_STM32MP13xx : + RCC_DDRITFCR_STM32MP15xx); +} + static u32 get_base_addr(const struct ddr_info *priv, enum base_type base) { if (base == DDRPHY_BASE) @@ -295,6 +331,21 @@ static u32 get_base_addr(const struct ddr_info *priv, enum base_type base) return (u32)priv->ctl; } +static u32 get_type_size(const struct ddr_info *priv, enum reg_type type) +{ + bool is_mp13 = is_stm32mp13_ddrc(priv); + + if (type == REG_PERF) + return is_mp13 ? DDRCTL_REG_PERF_SIZE_STM32MP13xx : + DDRCTL_REG_PERF_SIZE_STM32MP15xx; + else if (type == REGPHY_REG) + return is_mp13 ? DDRPHY_REG_REG_SIZE_STM32MP13xx : + DDRPHY_REG_REG_SIZE_STM32MP15xx; + + /* Everything else is the default size */ + return ddr_registers[type].size; +} + static void set_reg(const struct ddr_info *priv, enum reg_type type, const void *param) @@ -304,9 +355,10 @@ static void set_reg(const struct ddr_info *priv, enum base_type base = ddr_registers[type].base; u32 base_addr = get_base_addr(priv, base); const struct reg_desc *desc = ddr_registers[type].desc; + u32 size = get_type_size(priv, type); log_debug("init %s\n", ddr_registers[type].name); - for (i = 0; i < ddr_registers[type].size; i++) { + for (i = 0; i < size; i++) { ptr = (unsigned int *)(base_addr + desc[i].offset); if (desc[i].par_offset == INVALID_OFFSET) { log_err("invalid parameter offset for %s", desc[i].name); @@ -656,12 +708,13 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, static void stm32mp1_asr_enable(struct ddr_info *priv, const u32 pwrctl) { struct stm32mp1_ddrctl *ctl = priv->ctl; + u32 rcc_ddritfcr = get_rcc_ddritfcr(priv); /* SSR is the best we can do. */ if (!(pwrctl & DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE)) return; - clrsetbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCKMOD_MASK, + clrsetbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, RCC_DDRITFCR_DDRCKMOD_ASR); start_sw_done(ctl); @@ -691,6 +744,7 @@ __maybe_unused void stm32mp1_ddr_init(struct ddr_info *priv, const struct stm32mp1_ddr_config *config) { + u32 rcc_ddritfcr = get_rcc_ddritfcr(priv); u32 pir; int ret = -EINVAL; char bus_width; @@ -732,12 +786,12 @@ start: * 1.1 RESETS: presetn, core_ddrc_rstn, aresetn */ /* Assert All DDR part */ - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAXIRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCORERST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYAPBRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYCTLRST); /* 1.2. start CLOCK */ if (stm32mp1_ddr_clk_enable(priv, config->info.speed)) @@ -746,12 +800,12 @@ start: /* 1.3. deassert reset */ /* de-assert PHY rstn and ctl_rstn via DPHYRST and DPHYCTLRST */ - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYCTLRST); /* De-assert presetn once the clocks are active * and stable via DDRCAPBRST bit */ - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBRST); /* 1.4. wait 128 cycles to permit initialization of end logic */ udelay(2); @@ -781,9 +835,9 @@ start: goto start; /* 2. deassert reset signal core_ddrc_rstn, aresetn and presetn */ - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCORERST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAXIRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYAPBRST); /* 3. start PHY init by accessing relevant PUBL registers * (DXGCR, DCR, PTR*, MR*, DTPR*) @@ -854,9 +908,12 @@ start: /* Enable auto-self-refresh, which saves a bit of power at runtime. */ stm32mp1_asr_enable(priv, config->c_reg.pwrctl); - /* enable uMCTL2 AXI port 0 and 1 */ + /* enable uMCTL2 AXI port 0 */ setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); - setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); + + /* enable uMCTL2 AXI port 1 only on STM32MP15xx with 32bit DRAM bus */ + if (!is_stm32mp13_ddrc(priv)) + setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); if (INTERACTIVE(STEP_DDR_READY)) goto start; diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.h b/drivers/ram/stm32mp1/stm32mp1_ddr.h index 861efff92be..3621e6c9a1b 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr.h +++ b/drivers/ram/stm32mp1/stm32mp1_ddr.h @@ -105,12 +105,14 @@ struct stm32mp1_ddrctrl_perf { u32 pcfgqos1_0; u32 pcfgwqos0_0; u32 pcfgwqos1_0; +#if IS_ENABLED(CONFIG_STM32MP15X) u32 pcfgr_1; u32 pcfgw_1; u32 pcfgqos0_1; u32 pcfgqos1_1; u32 pcfgwqos0_1; u32 pcfgwqos1_1; +#endif }; struct stm32mp1_ddrphy_reg { @@ -123,8 +125,10 @@ struct stm32mp1_ddrphy_reg { u32 zq0cr1; u32 dx0gcr; u32 dx1gcr; +#if IS_ENABLED(CONFIG_STM32MP15X) u32 dx2gcr; u32 dx3gcr; +#endif }; struct stm32mp1_ddrphy_timing { @@ -181,4 +185,6 @@ bool stm32mp1_ddr_interactive( enum stm32mp1_ddr_interact_step step, const struct stm32mp1_ddr_config *config); +bool is_stm32mp13_ddrc(const struct ddr_info *priv); + #endif diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c index e9cd6229ec4..5f9b91d50e4 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ram.c +++ b/drivers/ram/stm32mp1/stm32mp1_ram.c @@ -33,6 +33,7 @@ static const char *const clkname[] = { int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) { + bool is_mp13 = is_stm32mp13_ddrc(priv); unsigned long ddrphy_clk; unsigned long ddr_clk; struct clk clk; @@ -40,6 +41,10 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) unsigned int idx; for (idx = 0; idx < ARRAY_SIZE(clkname); idx++) { + /* DDRC2 clock are available only on STM32MP15xx */ + if (is_mp13 && !strcmp(clkname[idx], "ddrc2")) + continue; + ret = clk_get_by_name(priv->dev, clkname[idx], &clk); if (!ret) |