1*79629b1aSNicolas Le Bayon /* 2*79629b1aSNicolas Le Bayon * Copyright (C) 2021-2024, STMicroelectronics - All Rights Reserved 3*79629b1aSNicolas Le Bayon * 4*79629b1aSNicolas Le Bayon * SPDX-License-Identifier: BSD-3-Clause 5*79629b1aSNicolas Le Bayon */ 6*79629b1aSNicolas Le Bayon 7*79629b1aSNicolas Le Bayon #include <errno.h> 8*79629b1aSNicolas Le Bayon 9*79629b1aSNicolas Le Bayon #include <common/debug.h> 10*79629b1aSNicolas Le Bayon 11*79629b1aSNicolas Le Bayon #include <ddrphy_phyinit.h> 12*79629b1aSNicolas Le Bayon 13*79629b1aSNicolas Le Bayon #include <drivers/delay_timer.h> 14*79629b1aSNicolas Le Bayon #include <drivers/st/stm32mp2_ddr_helpers.h> 15*79629b1aSNicolas Le Bayon #include <drivers/st/stm32mp2_ddr_regs.h> 16*79629b1aSNicolas Le Bayon #include <drivers/st/stm32mp_ddr.h> 17*79629b1aSNicolas Le Bayon 18*79629b1aSNicolas Le Bayon #include <lib/mmio.h> 19*79629b1aSNicolas Le Bayon 20*79629b1aSNicolas Le Bayon #include <platform_def.h> 21*79629b1aSNicolas Le Bayon 22*79629b1aSNicolas Le Bayon #define DDRDBG_FRAC_PLL_LOCK U(0x10) 23*79629b1aSNicolas Le Bayon 24*79629b1aSNicolas Le Bayon #define DDRCTL_REG(x, y, z) \ 25*79629b1aSNicolas Le Bayon { \ 26*79629b1aSNicolas Le Bayon .offset = offsetof(struct stm32mp_ddrctl, x), \ 27*79629b1aSNicolas Le Bayon .par_offset = offsetof(struct y, x), \ 28*79629b1aSNicolas Le Bayon .qd = z \ 29*79629b1aSNicolas Le Bayon } 30*79629b1aSNicolas Le Bayon 31*79629b1aSNicolas Le Bayon /* 32*79629b1aSNicolas Le Bayon * PARAMETERS: value get from device tree : 33*79629b1aSNicolas Le Bayon * size / order need to be aligned with binding 34*79629b1aSNicolas Le Bayon * modification NOT ALLOWED !!! 35*79629b1aSNicolas Le Bayon */ 36*79629b1aSNicolas Le Bayon #define DDRCTL_REG_REG_SIZE 48 /* st,ctl-reg */ 37*79629b1aSNicolas Le Bayon #define DDRCTL_REG_TIMING_SIZE 20 /* st,ctl-timing */ 38*79629b1aSNicolas Le Bayon #define DDRCTL_REG_MAP_SIZE 12 /* st,ctl-map */ 39*79629b1aSNicolas Le Bayon #if STM32MP_DDR_DUAL_AXI_PORT 40*79629b1aSNicolas Le Bayon #define DDRCTL_REG_PERF_SIZE 21 /* st,ctl-perf */ 41*79629b1aSNicolas Le Bayon #else /* !STM32MP_DDR_DUAL_AXI_PORT */ 42*79629b1aSNicolas Le Bayon #define DDRCTL_REG_PERF_SIZE 14 /* st,ctl-perf */ 43*79629b1aSNicolas Le Bayon #endif /* STM32MP_DDR_DUAL_AXI_PORT */ 44*79629b1aSNicolas Le Bayon 45*79629b1aSNicolas Le Bayon #define DDRPHY_REG_REG_SIZE 0 /* st,phy-reg */ 46*79629b1aSNicolas Le Bayon #define DDRPHY_REG_TIMING_SIZE 0 /* st,phy-timing */ 47*79629b1aSNicolas Le Bayon 48*79629b1aSNicolas Le Bayon #define DDRCTL_REG_REG(x, z) DDRCTL_REG(x, stm32mp2_ddrctrl_reg, z) 49*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = { 50*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(mstr, true), 51*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(mrctrl0, false), 52*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(mrctrl1, false), 53*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(mrctrl2, false), 54*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(derateen, true), 55*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(derateint, false), 56*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(deratectl, false), 57*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(pwrctl, false), 58*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(pwrtmg, true), 59*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(hwlpctl, true), 60*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(rfshctl0, false), 61*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(rfshctl1, false), 62*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(rfshctl3, true), 63*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(crcparctl0, false), 64*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(crcparctl1, false), 65*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(init0, true), 66*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(init1, false), 67*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(init2, false), 68*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(init3, true), 69*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(init4, true), 70*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(init5, false), 71*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(init6, true), 72*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(init7, true), 73*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dimmctl, false), 74*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(rankctl, true), 75*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(rankctl1, true), 76*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(zqctl0, true), 77*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(zqctl1, false), 78*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(zqctl2, false), 79*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfitmg0, true), 80*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfitmg1, true), 81*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfilpcfg0, false), 82*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfilpcfg1, false), 83*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfiupd0, true), 84*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfiupd1, false), 85*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfiupd2, false), 86*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfimisc, true), 87*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfitmg2, true), 88*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfitmg3, false), 89*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dbictl, true), 90*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dfiphymstr, false), 91*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dbg0, false), 92*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dbg1, false), 93*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(dbgcmd, false), 94*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(swctl, false), /* forced qd value */ 95*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(swctlstatic, false), 96*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(poisoncfg, false), 97*79629b1aSNicolas Le Bayon DDRCTL_REG_REG(pccfg, false), 98*79629b1aSNicolas Le Bayon }; 99*79629b1aSNicolas Le Bayon 100*79629b1aSNicolas Le Bayon #define DDRCTL_REG_TIMING(x, z) DDRCTL_REG(x, stm32mp2_ddrctrl_timing, z) 101*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddr_timing[DDRCTL_REG_TIMING_SIZE] = { 102*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(rfshtmg, false), 103*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(rfshtmg1, false), 104*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg0, true), 105*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg1, true), 106*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg2, true), 107*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg3, true), 108*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg4, true), 109*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg5, true), 110*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg6, true), 111*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg7, true), 112*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg8, true), 113*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg9, true), 114*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg10, true), 115*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg11, true), 116*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg12, true), 117*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg13, true), 118*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg14, true), 119*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(dramtmg15, true), 120*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(odtcfg, true), 121*79629b1aSNicolas Le Bayon DDRCTL_REG_TIMING(odtmap, false), 122*79629b1aSNicolas Le Bayon }; 123*79629b1aSNicolas Le Bayon 124*79629b1aSNicolas Le Bayon #define DDRCTL_REG_MAP(x) DDRCTL_REG(x, stm32mp2_ddrctrl_map, false) 125*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddr_map[DDRCTL_REG_MAP_SIZE] = { 126*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap0), 127*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap1), 128*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap2), 129*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap3), 130*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap4), 131*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap5), 132*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap6), 133*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap7), 134*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap8), 135*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap9), 136*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap10), 137*79629b1aSNicolas Le Bayon DDRCTL_REG_MAP(addrmap11), 138*79629b1aSNicolas Le Bayon }; 139*79629b1aSNicolas Le Bayon 140*79629b1aSNicolas Le Bayon #define DDRCTL_REG_PERF(x, z) DDRCTL_REG(x, stm32mp2_ddrctrl_perf, z) 141*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = { 142*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(sched, true), 143*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(sched1, false), 144*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(perfhpr1, true), 145*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(perflpr1, true), 146*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(perfwr1, true), 147*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(sched3, false), 148*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(sched4, false), 149*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgr_0, false), 150*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgw_0, false), 151*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pctrl_0, false), 152*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgqos0_0, true), 153*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgqos1_0, true), 154*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgwqos0_0, true), 155*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgwqos1_0, true), 156*79629b1aSNicolas Le Bayon #if STM32MP_DDR_DUAL_AXI_PORT 157*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgr_1, false), 158*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgw_1, false), 159*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pctrl_1, false), 160*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgqos0_1, true), 161*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgqos1_1, true), 162*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgwqos0_1, true), 163*79629b1aSNicolas Le Bayon DDRCTL_REG_PERF(pcfgwqos1_1, true), 164*79629b1aSNicolas Le Bayon #endif /* STM32MP_DDR_DUAL_AXI_PORT */ 165*79629b1aSNicolas Le Bayon }; 166*79629b1aSNicolas Le Bayon 167*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = {}; 168*79629b1aSNicolas Le Bayon 169*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = {}; 170*79629b1aSNicolas Le Bayon 171*79629b1aSNicolas Le Bayon /* 172*79629b1aSNicolas Le Bayon * REGISTERS ARRAY: used to parse device tree and interactive mode 173*79629b1aSNicolas Le Bayon */ 174*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_info ddr_registers[REG_TYPE_NB] __unused = { 175*79629b1aSNicolas Le Bayon [REG_REG] = { 176*79629b1aSNicolas Le Bayon .name = "static", 177*79629b1aSNicolas Le Bayon .desc = ddr_reg, 178*79629b1aSNicolas Le Bayon .size = DDRCTL_REG_REG_SIZE, 179*79629b1aSNicolas Le Bayon .base = DDR_BASE 180*79629b1aSNicolas Le Bayon }, 181*79629b1aSNicolas Le Bayon [REG_TIMING] = { 182*79629b1aSNicolas Le Bayon .name = "timing", 183*79629b1aSNicolas Le Bayon .desc = ddr_timing, 184*79629b1aSNicolas Le Bayon .size = DDRCTL_REG_TIMING_SIZE, 185*79629b1aSNicolas Le Bayon .base = DDR_BASE 186*79629b1aSNicolas Le Bayon }, 187*79629b1aSNicolas Le Bayon [REG_PERF] = { 188*79629b1aSNicolas Le Bayon .name = "perf", 189*79629b1aSNicolas Le Bayon .desc = ddr_perf, 190*79629b1aSNicolas Le Bayon .size = DDRCTL_REG_PERF_SIZE, 191*79629b1aSNicolas Le Bayon .base = DDR_BASE 192*79629b1aSNicolas Le Bayon }, 193*79629b1aSNicolas Le Bayon [REG_MAP] = { 194*79629b1aSNicolas Le Bayon .name = "map", 195*79629b1aSNicolas Le Bayon .desc = ddr_map, 196*79629b1aSNicolas Le Bayon .size = DDRCTL_REG_MAP_SIZE, 197*79629b1aSNicolas Le Bayon .base = DDR_BASE 198*79629b1aSNicolas Le Bayon }, 199*79629b1aSNicolas Le Bayon [REGPHY_REG] = { 200*79629b1aSNicolas Le Bayon .name = "static", 201*79629b1aSNicolas Le Bayon .desc = ddrphy_reg, 202*79629b1aSNicolas Le Bayon .size = DDRPHY_REG_REG_SIZE, 203*79629b1aSNicolas Le Bayon .base = DDRPHY_BASE 204*79629b1aSNicolas Le Bayon }, 205*79629b1aSNicolas Le Bayon [REGPHY_TIMING] = { 206*79629b1aSNicolas Le Bayon .name = "timing", 207*79629b1aSNicolas Le Bayon .desc = ddrphy_timing, 208*79629b1aSNicolas Le Bayon .size = DDRPHY_REG_TIMING_SIZE, 209*79629b1aSNicolas Le Bayon .base = DDRPHY_BASE 210*79629b1aSNicolas Le Bayon }, 211*79629b1aSNicolas Le Bayon }; 212*79629b1aSNicolas Le Bayon 213*79629b1aSNicolas Le Bayon static void ddr_reset(struct stm32mp_ddr_priv *priv) 214*79629b1aSNicolas Le Bayon { 215*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 216*79629b1aSNicolas Le Bayon 217*79629b1aSNicolas Le Bayon mmio_setbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST); 218*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRPHYCAPBCFGR, 219*79629b1aSNicolas Le Bayon RCC_DDRPHYCAPBCFGR_DDRPHYCAPBEN | RCC_DDRPHYCAPBCFGR_DDRPHYCAPBLPEN | 220*79629b1aSNicolas Le Bayon RCC_DDRPHYCAPBCFGR_DDRPHYCAPBRST); 221*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRCAPBCFGR, 222*79629b1aSNicolas Le Bayon RCC_DDRCAPBCFGR_DDRCAPBEN | RCC_DDRCAPBCFGR_DDRCAPBLPEN | 223*79629b1aSNicolas Le Bayon RCC_DDRCAPBCFGR_DDRCAPBRST); 224*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRCFGR, 225*79629b1aSNicolas Le Bayon RCC_DDRCFGR_DDRCFGEN | RCC_DDRCFGR_DDRCFGLPEN | RCC_DDRCFGR_DDRCFGRST); 226*79629b1aSNicolas Le Bayon 227*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 228*79629b1aSNicolas Le Bayon 229*79629b1aSNicolas Le Bayon mmio_setbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST); 230*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRPHYCAPBCFGR, 231*79629b1aSNicolas Le Bayon RCC_DDRPHYCAPBCFGR_DDRPHYCAPBEN | RCC_DDRPHYCAPBCFGR_DDRPHYCAPBLPEN); 232*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRCAPBCFGR, 233*79629b1aSNicolas Le Bayon RCC_DDRCAPBCFGR_DDRCAPBEN | RCC_DDRCAPBCFGR_DDRCAPBLPEN); 234*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRCFGR, RCC_DDRCFGR_DDRCFGEN | RCC_DDRCFGR_DDRCFGLPEN); 235*79629b1aSNicolas Le Bayon 236*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 237*79629b1aSNicolas Le Bayon } 238*79629b1aSNicolas Le Bayon 239*79629b1aSNicolas Le Bayon static void ddr_standby_reset(struct stm32mp_ddr_priv *priv) 240*79629b1aSNicolas Le Bayon { 241*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 242*79629b1aSNicolas Le Bayon 243*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRCPCFGR, 244*79629b1aSNicolas Le Bayon RCC_DDRCPCFGR_DDRCPEN | RCC_DDRCPCFGR_DDRCPLPEN | RCC_DDRCPCFGR_DDRCPRST); 245*79629b1aSNicolas Le Bayon mmio_setbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST); 246*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRPHYCAPBCFGR, 247*79629b1aSNicolas Le Bayon RCC_DDRPHYCAPBCFGR_DDRPHYCAPBEN | RCC_DDRPHYCAPBCFGR_DDRPHYCAPBLPEN | 248*79629b1aSNicolas Le Bayon RCC_DDRPHYCAPBCFGR_DDRPHYCAPBRST); 249*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRCAPBCFGR, 250*79629b1aSNicolas Le Bayon RCC_DDRCAPBCFGR_DDRCAPBEN | RCC_DDRCAPBCFGR_DDRCAPBLPEN | 251*79629b1aSNicolas Le Bayon RCC_DDRCAPBCFGR_DDRCAPBRST); 252*79629b1aSNicolas Le Bayon 253*79629b1aSNicolas Le Bayon mmio_clrbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRPHYDLP); 254*79629b1aSNicolas Le Bayon mmio_setbits_32(priv->rcc + RCC_DDRPHYCCFGR, RCC_DDRPHYCCFGR_DDRPHYCEN); 255*79629b1aSNicolas Le Bayon 256*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 257*79629b1aSNicolas Le Bayon } 258*79629b1aSNicolas Le Bayon 259*79629b1aSNicolas Le Bayon static void ddr_standby_reset_release(struct stm32mp_ddr_priv *priv) 260*79629b1aSNicolas Le Bayon { 261*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 262*79629b1aSNicolas Le Bayon 263*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRCPCFGR, RCC_DDRCPCFGR_DDRCPEN | RCC_DDRCPCFGR_DDRCPLPEN); 264*79629b1aSNicolas Le Bayon mmio_clrbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST); 265*79629b1aSNicolas Le Bayon mmio_clrbits_32(priv->rcc + RCC_DDRPHYCAPBCFGR, RCC_DDRPHYCAPBCFGR_DDRPHYCAPBRST); 266*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRCFGR, RCC_DDRCFGR_DDRCFGEN | RCC_DDRCFGR_DDRCFGLPEN); 267*79629b1aSNicolas Le Bayon 268*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 269*79629b1aSNicolas Le Bayon } 270*79629b1aSNicolas Le Bayon 271*79629b1aSNicolas Le Bayon static void ddr_sysconf_configuration(struct stm32mp_ddr_priv *priv, 272*79629b1aSNicolas Le Bayon struct stm32mp_ddr_config *config) 273*79629b1aSNicolas Le Bayon { 274*79629b1aSNicolas Le Bayon mmio_write_32(stm32_ddrdbg_get_base() + DDRDBG_LP_DISABLE, 275*79629b1aSNicolas Le Bayon DDRDBG_LP_DISABLE_LPI_XPI_DISABLE | DDRDBG_LP_DISABLE_LPI_DDRC_DISABLE); 276*79629b1aSNicolas Le Bayon 277*79629b1aSNicolas Le Bayon mmio_write_32(stm32_ddrdbg_get_base() + DDRDBG_BYPASS_PCLKEN, 278*79629b1aSNicolas Le Bayon (uint32_t)config->uib.pllbypass); 279*79629b1aSNicolas Le Bayon 280*79629b1aSNicolas Le Bayon mmio_write_32(priv->rcc + RCC_DDRPHYCCFGR, RCC_DDRPHYCCFGR_DDRPHYCEN); 281*79629b1aSNicolas Le Bayon mmio_setbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST); 282*79629b1aSNicolas Le Bayon 283*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 284*79629b1aSNicolas Le Bayon } 285*79629b1aSNicolas Le Bayon 286*79629b1aSNicolas Le Bayon static void set_dfi_init_complete_en(struct stm32mp_ddrctl *ctl, bool phy_init_done) 287*79629b1aSNicolas Le Bayon { 288*79629b1aSNicolas Le Bayon /* 289*79629b1aSNicolas Le Bayon * Manage quasi-dynamic registers modification 290*79629b1aSNicolas Le Bayon * dfimisc.dfi_init_complete_en : Group 3 291*79629b1aSNicolas Le Bayon */ 292*79629b1aSNicolas Le Bayon stm32mp_ddr_set_qd3_update_conditions(ctl); 293*79629b1aSNicolas Le Bayon 294*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 295*79629b1aSNicolas Le Bayon 296*79629b1aSNicolas Le Bayon if (phy_init_done) { 297*79629b1aSNicolas Le Bayon /* Indicates to controller that PHY has completed initialization */ 298*79629b1aSNicolas Le Bayon mmio_setbits_32((uintptr_t)&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); 299*79629b1aSNicolas Le Bayon } else { 300*79629b1aSNicolas Le Bayon /* PHY not initialized yet, wait for completion */ 301*79629b1aSNicolas Le Bayon mmio_clrbits_32((uintptr_t)&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); 302*79629b1aSNicolas Le Bayon } 303*79629b1aSNicolas Le Bayon 304*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 305*79629b1aSNicolas Le Bayon 306*79629b1aSNicolas Le Bayon stm32mp_ddr_unset_qd3_update_conditions(ctl); 307*79629b1aSNicolas Le Bayon 308*79629b1aSNicolas Le Bayon } 309*79629b1aSNicolas Le Bayon 310*79629b1aSNicolas Le Bayon static void disable_refresh(struct stm32mp_ddrctl *ctl) 311*79629b1aSNicolas Le Bayon { 312*79629b1aSNicolas Le Bayon mmio_setbits_32((uintptr_t)&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); 313*79629b1aSNicolas Le Bayon 314*79629b1aSNicolas Le Bayon stm32mp_ddr_wait_refresh_update_done_ack(ctl); 315*79629b1aSNicolas Le Bayon 316*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 317*79629b1aSNicolas Le Bayon 318*79629b1aSNicolas Le Bayon mmio_clrbits_32((uintptr_t)&ctl->pwrctl, 319*79629b1aSNicolas Le Bayon DDRCTRL_PWRCTL_POWERDOWN_EN | DDRCTRL_PWRCTL_SELFREF_EN); 320*79629b1aSNicolas Le Bayon 321*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 322*79629b1aSNicolas Le Bayon 323*79629b1aSNicolas Le Bayon set_dfi_init_complete_en(ctl, false); 324*79629b1aSNicolas Le Bayon } 325*79629b1aSNicolas Le Bayon 326*79629b1aSNicolas Le Bayon static void restore_refresh(struct stm32mp_ddrctl *ctl, uint32_t rfshctl3, uint32_t pwrctl) 327*79629b1aSNicolas Le Bayon { 328*79629b1aSNicolas Le Bayon if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) { 329*79629b1aSNicolas Le Bayon mmio_clrbits_32((uintptr_t)&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); 330*79629b1aSNicolas Le Bayon 331*79629b1aSNicolas Le Bayon stm32mp_ddr_wait_refresh_update_done_ack(ctl); 332*79629b1aSNicolas Le Bayon 333*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 334*79629b1aSNicolas Le Bayon } 335*79629b1aSNicolas Le Bayon 336*79629b1aSNicolas Le Bayon if ((pwrctl & DDRCTRL_PWRCTL_SELFREF_SW) != 0U) { 337*79629b1aSNicolas Le Bayon mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW); 338*79629b1aSNicolas Le Bayon 339*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 340*79629b1aSNicolas Le Bayon } 341*79629b1aSNicolas Le Bayon 342*79629b1aSNicolas Le Bayon if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) { 343*79629b1aSNicolas Le Bayon mmio_setbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); 344*79629b1aSNicolas Le Bayon 345*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 346*79629b1aSNicolas Le Bayon } 347*79629b1aSNicolas Le Bayon 348*79629b1aSNicolas Le Bayon if ((pwrctl & DDRCTRL_PWRCTL_SELFREF_EN) != 0U) { 349*79629b1aSNicolas Le Bayon mmio_setbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_EN); 350*79629b1aSNicolas Le Bayon 351*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 352*79629b1aSNicolas Le Bayon } 353*79629b1aSNicolas Le Bayon 354*79629b1aSNicolas Le Bayon set_dfi_init_complete_en(ctl, true); 355*79629b1aSNicolas Le Bayon } 356*79629b1aSNicolas Le Bayon 357*79629b1aSNicolas Le Bayon void stm32mp2_ddr_init(struct stm32mp_ddr_priv *priv, 358*79629b1aSNicolas Le Bayon struct stm32mp_ddr_config *config) 359*79629b1aSNicolas Le Bayon { 360*79629b1aSNicolas Le Bayon int ret = -EINVAL; 361*79629b1aSNicolas Le Bayon uint32_t ddr_retdis; 362*79629b1aSNicolas Le Bayon enum ddr_type ddr_type; 363*79629b1aSNicolas Le Bayon 364*79629b1aSNicolas Le Bayon if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { 365*79629b1aSNicolas Le Bayon ddr_type = STM32MP_DDR3; 366*79629b1aSNicolas Le Bayon } else if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR4) != 0U) { 367*79629b1aSNicolas Le Bayon ddr_type = STM32MP_DDR4; 368*79629b1aSNicolas Le Bayon } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR4) != 0U) { 369*79629b1aSNicolas Le Bayon ddr_type = STM32MP_LPDDR4; 370*79629b1aSNicolas Le Bayon } else { 371*79629b1aSNicolas Le Bayon ERROR("DDR type not supported\n"); 372*79629b1aSNicolas Le Bayon panic(); 373*79629b1aSNicolas Le Bayon } 374*79629b1aSNicolas Le Bayon 375*79629b1aSNicolas Le Bayon VERBOSE("name = %s\n", config->info.name); 376*79629b1aSNicolas Le Bayon VERBOSE("speed = %u kHz\n", config->info.speed); 377*79629b1aSNicolas Le Bayon VERBOSE("size = 0x%zx\n", config->info.size); 378*79629b1aSNicolas Le Bayon if (config->self_refresh) { 379*79629b1aSNicolas Le Bayon VERBOSE("sel-refresh exit (zdata = 0x%x)\n", config->zdata); 380*79629b1aSNicolas Le Bayon } 381*79629b1aSNicolas Le Bayon 382*79629b1aSNicolas Le Bayon /* Check DDR PHY pads retention */ 383*79629b1aSNicolas Le Bayon ddr_retdis = mmio_read_32(priv->pwr + PWR_CR11) & PWR_CR11_DDRRETDIS; 384*79629b1aSNicolas Le Bayon if (config->self_refresh) { 385*79629b1aSNicolas Le Bayon if (ddr_retdis == PWR_CR11_DDRRETDIS) { 386*79629b1aSNicolas Le Bayon VERBOSE("self-refresh aborted: no retention\n"); 387*79629b1aSNicolas Le Bayon config->self_refresh = false; 388*79629b1aSNicolas Le Bayon } 389*79629b1aSNicolas Le Bayon } 390*79629b1aSNicolas Le Bayon 391*79629b1aSNicolas Le Bayon if (config->self_refresh) { 392*79629b1aSNicolas Le Bayon ddr_standby_reset(priv); 393*79629b1aSNicolas Le Bayon 394*79629b1aSNicolas Le Bayon VERBOSE("disable DDR PHY retention\n"); 395*79629b1aSNicolas Le Bayon mmio_setbits_32(priv->pwr + PWR_CR11, PWR_CR11_DDRRETDIS); 396*79629b1aSNicolas Le Bayon 397*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 398*79629b1aSNicolas Le Bayon 399*79629b1aSNicolas Le Bayon mmio_clrbits_32(priv->rcc + RCC_DDRCAPBCFGR, RCC_DDRCAPBCFGR_DDRCAPBRST); 400*79629b1aSNicolas Le Bayon 401*79629b1aSNicolas Le Bayon udelay(DDR_DELAY_1US); 402*79629b1aSNicolas Le Bayon 403*79629b1aSNicolas Le Bayon } else { 404*79629b1aSNicolas Le Bayon if (stm32mp_board_ddr_power_init(ddr_type) != 0) { 405*79629b1aSNicolas Le Bayon ERROR("DDR power init failed\n"); 406*79629b1aSNicolas Le Bayon panic(); 407*79629b1aSNicolas Le Bayon } 408*79629b1aSNicolas Le Bayon 409*79629b1aSNicolas Le Bayon VERBOSE("disable DDR PHY retention\n"); 410*79629b1aSNicolas Le Bayon mmio_setbits_32(priv->pwr + PWR_CR11, PWR_CR11_DDRRETDIS); 411*79629b1aSNicolas Le Bayon 412*79629b1aSNicolas Le Bayon ddr_reset(priv); 413*79629b1aSNicolas Le Bayon 414*79629b1aSNicolas Le Bayon ddr_sysconf_configuration(priv, config); 415*79629b1aSNicolas Le Bayon } 416*79629b1aSNicolas Le Bayon 417*79629b1aSNicolas Le Bayon #if STM32MP_LPDDR4_TYPE 418*79629b1aSNicolas Le Bayon /* 419*79629b1aSNicolas Le Bayon * Enable PWRCTL.SELFREF_SW to ensure correct setting of PWRCTL.LPDDR4_SR_ALLOWED. 420*79629b1aSNicolas Le Bayon * Later disabled in restore_refresh(). 421*79629b1aSNicolas Le Bayon */ 422*79629b1aSNicolas Le Bayon config->c_reg.pwrctl |= DDRCTRL_PWRCTL_SELFREF_SW; 423*79629b1aSNicolas Le Bayon #endif /* STM32MP_LPDDR4_TYPE */ 424*79629b1aSNicolas Le Bayon 425*79629b1aSNicolas Le Bayon stm32mp_ddr_set_reg(priv, REG_REG, &config->c_reg, ddr_registers); 426*79629b1aSNicolas Le Bayon stm32mp_ddr_set_reg(priv, REG_TIMING, &config->c_timing, ddr_registers); 427*79629b1aSNicolas Le Bayon stm32mp_ddr_set_reg(priv, REG_MAP, &config->c_map, ddr_registers); 428*79629b1aSNicolas Le Bayon stm32mp_ddr_set_reg(priv, REG_PERF, &config->c_perf, ddr_registers); 429*79629b1aSNicolas Le Bayon 430*79629b1aSNicolas Le Bayon if (!config->self_refresh) { 431*79629b1aSNicolas Le Bayon /* DDR core and PHY reset de-assert */ 432*79629b1aSNicolas Le Bayon mmio_clrbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST); 433*79629b1aSNicolas Le Bayon 434*79629b1aSNicolas Le Bayon disable_refresh(priv->ctl); 435*79629b1aSNicolas Le Bayon } 436*79629b1aSNicolas Le Bayon 437*79629b1aSNicolas Le Bayon if (config->self_refresh) { 438*79629b1aSNicolas Le Bayon ddr_standby_reset_release(priv); 439*79629b1aSNicolas Le Bayon 440*79629b1aSNicolas Le Bayon /* Initialize DDR by skipping training and disabling result saving */ 441*79629b1aSNicolas Le Bayon ret = ddrphy_phyinit_sequence(config, true, false); 442*79629b1aSNicolas Le Bayon 443*79629b1aSNicolas Le Bayon if (ret == 0) { 444*79629b1aSNicolas Le Bayon ret = ddrphy_phyinit_restore_sequence(); 445*79629b1aSNicolas Le Bayon } 446*79629b1aSNicolas Le Bayon 447*79629b1aSNicolas Le Bayon /* Poll on ddrphy_initeng0_phyinlpx.phyinlp3 = 0 */ 448*79629b1aSNicolas Le Bayon ddr_wait_lp3_mode(false); 449*79629b1aSNicolas Le Bayon } else { 450*79629b1aSNicolas Le Bayon /* Initialize DDR including training and result saving */ 451*79629b1aSNicolas Le Bayon ret = ddrphy_phyinit_sequence(config, false, true); 452*79629b1aSNicolas Le Bayon } 453*79629b1aSNicolas Le Bayon 454*79629b1aSNicolas Le Bayon if (ret != 0) { 455*79629b1aSNicolas Le Bayon ERROR("DDR PHY init: Error %d\n", ret); 456*79629b1aSNicolas Le Bayon panic(); 457*79629b1aSNicolas Le Bayon } 458*79629b1aSNicolas Le Bayon 459*79629b1aSNicolas Le Bayon ddr_activate_controller(priv->ctl, false); 460*79629b1aSNicolas Le Bayon 461*79629b1aSNicolas Le Bayon if (config->self_refresh) { 462*79629b1aSNicolas Le Bayon struct stm32mp_ddrctl *ctl = priv->ctl; 463*79629b1aSNicolas Le Bayon 464*79629b1aSNicolas Le Bayon /* SW self refresh exit prequested */ 465*79629b1aSNicolas Le Bayon mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW); 466*79629b1aSNicolas Le Bayon 467*79629b1aSNicolas Le Bayon if (ddr_sr_exit_loop() != 0) { 468*79629b1aSNicolas Le Bayon ERROR("DDR Standby exit error\n"); 469*79629b1aSNicolas Le Bayon panic(); 470*79629b1aSNicolas Le Bayon } 471*79629b1aSNicolas Le Bayon 472*79629b1aSNicolas Le Bayon /* Re-enable DFI low-power interface */ 473*79629b1aSNicolas Le Bayon mmio_clrbits_32((uintptr_t)&ctl->dfilpcfg0, DDRCTRL_DFILPCFG0_DFI_LP_EN_SR); 474*79629b1aSNicolas Le Bayon } else { 475*79629b1aSNicolas Le Bayon restore_refresh(priv->ctl, config->c_reg.rfshctl3, config->c_reg.pwrctl); 476*79629b1aSNicolas Le Bayon } 477*79629b1aSNicolas Le Bayon 478*79629b1aSNicolas Le Bayon stm32mp_ddr_enable_axi_port(priv->ctl); 479*79629b1aSNicolas Le Bayon } 480