1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3 * Wrapper for Cadence DDR Driver
4 *
5 * Copyright (C) 2025-2026 Texas Instruments Incorporated - https://www.ti.com/
6 */
7
8 #include <errno.h>
9
10 #include <arch.h>
11 #include <arch_helpers.h>
12 #include <common/bl_common.h>
13 #include <common/debug.h>
14 #include <lib/mmio.h>
15 #include <lib/xlat_tables/xlat_tables_v2.h>
16
17 #include <am62l_psc_minimal.h>
18 #include <am62lx_ddr_config.h>
19 #include "cps_drv_lpddr4.h"
20 #include <k3_console.h>
21 #include "lpddr4_ctl_regs.h"
22 #include "lpddr4_if.h"
23 #include "lpddr4_obj_if.h"
24 #include "lpddr4_structs_if.h"
25 #include <platform_def.h>
26
27 #define HERTZ_PER_MEGAHERTZ 1000000UL
28 #define HERTZ_PER_GIGAHERTZ 1000000000UL
29 #define MAIN_PLL0_VCO_FREQ (2UL * HERTZ_PER_GIGAHERTZ)
30 #define MAIN_PLL0_HSDIV2_MAX_FREQ (400UL * HERTZ_PER_MEGAHERTZ)
31
32 #define DDRSS_CTL_CFG 0x0f308000
33 #define DDRSS_CTRL_MMR 0x43040000
34 #define DDRSS_SS_CFG 0x0f300000
35 #define DDR4_FSP_CLKCHNG_REQ 0x80
36 #define DDR4_FSP_CLKCHNG_ACK 0x84
37
38 #define MAIN_PLL0_CFG 0x04060000
39 #define MAIN_PLL0_HSDIV2_CTRL 0x88
40 #define PLL_HSDIV_RESET_MASK GENMASK(31, 31)
41 #define PLL_HSDIV_DIV_MASK GENMASK(6, 0)
42 #define PLL_HSDIV_CLKOUT_MASK GENMASK(15, 15)
43 #define DDR4_CLKCHNG_REQ_MASK GENMASK(7, 7)
44 #define DDR4_CLKCHNG_REQ_ACTIVE 0x01U
45 #define DDR4_CLKCHNG_REQ_INACTIVE 0x00U
46 #define DDR4_CLKCHNG_REQTYPE_MASK GENMASK(1, 0)
47 #define DDR4_CLKCHNG_REQ_FREQ1 0x01U
48 #define DDR4_CLKCHNG_REQ_FREQ2 0x02U
49 #define DDR4_CLKCHNG_REQ_FREQ0 0x00U
50 #define DDR4_CLKCHNG_ACK_DONE 0x01U
51 #define DDR4_CLKCHNG_ACK_NONE 0x00U
52
53 #define DDRSS_PI_REGISTER_BLOCK__OFFS 0x2000
54 #define DDRSS_PI_83__SFR_OFFS 0x14C
55 #define DDRSS_CTL_342__SFR_OFFS 0x558
56 #define DENALI_CTL_0_DRAM_CLASS_LPDDR4 0xBU
57
58 #define DDRSS_V2A_CTL_REG 0x0020
59
60 #define DDRSS_V2A_CTL_REG_SDRAM_IDX_CALC(x) ((ddrss_log2_floor(x) - 16) << 5)
61 #define DDRSS_V2A_CTL_REG_SDRAM_IDX_MASK (~(0x1F << 5))
62
63 #define PD_DDR 2
64 #define LPSC_MAIN_DDR_LOCAL 21
65 #define LPSC_MAIN_DDR_CFG_ISO_N 22
66 #define LPSC_MAIN_DDR_DATA_ISO_N 23
67
68 #define str(s) #s
69 #define xstr(s) str(s)
70 #define TH_OFFSET_FROM_REG(REG, offset) do { \
71 char *i, *pstr = xstr(REG); offset = 0; \
72 for (i = pstr; *i != '\0' && *i != '['; ++i) \
73 ; \
74 if (*i == '[') { \
75 for (++i; *i != '\0' && *i != ']'; ++i) { \
76 offset = offset * 10 + (*i - '0'); } \
77 } \
78 } while (0)
79
80 struct k3_ddrss_desc {
81 void *ddrss_ss_cfg;
82 void *ddrss_ctrl_mmr;
83 void *ddrss_ctl_cfg;
84 uint32_t ddr_freq0;
85 uint32_t ddr_freq1;
86 uint32_t ddr_freq2;
87 uint32_t ddr_fhs_cnt;
88 uint32_t dram_class;
89 uint32_t instance;
90 ti_lpddr4_obj *driverdt;
91 ti_lpddr4_config config;
92 ti_lpddr4_privatedata pd;
93 uint64_t ecc_reserved_space;
94 bool ti_ecc_enabled;
95 };
96
97 static struct k3_ddrss_desc ddrss;
98
ddrss_log2_floor(uint64_t n)99 static inline uint64_t ddrss_log2_floor(uint64_t n)
100 {
101 uint64_t val;
102
103 for (val = 0; n > 1U; val++, n >>= 1)
104 ;
105
106 return val;
107 }
108
109 /************************************************
110 * Function to set PLL divider for DDR SS clocks
111 ************************************************/
set_ddr_pll_div(unsigned int div)112 static int set_ddr_pll_div(unsigned int div)
113 {
114 volatile uint32_t reg_val;
115 uint32_t set_val;
116
117 /* Set reset to high */
118 reg_val = mmio_read_32((uintptr_t)(MAIN_PLL0_CFG + MAIN_PLL0_HSDIV2_CTRL));
119 set_val = (reg_val & ~PLL_HSDIV_RESET_MASK) | FIELD_PREP(PLL_HSDIV_RESET_MASK, 1);
120 mmio_write_32((uintptr_t)(MAIN_PLL0_CFG + MAIN_PLL0_HSDIV2_CTRL), set_val);
121
122 /* Set divider value */
123 reg_val = mmio_read_32((uintptr_t)(MAIN_PLL0_CFG + MAIN_PLL0_HSDIV2_CTRL));
124 set_val = (reg_val & ~PLL_HSDIV_DIV_MASK) | FIELD_PREP(PLL_HSDIV_DIV_MASK, div);
125 mmio_write_32((uintptr_t)(MAIN_PLL0_CFG + MAIN_PLL0_HSDIV2_CTRL), set_val);
126
127 /* Set enable bit */
128 reg_val = mmio_read_32((uintptr_t)(MAIN_PLL0_CFG + MAIN_PLL0_HSDIV2_CTRL));
129 set_val = (reg_val & ~PLL_HSDIV_CLKOUT_MASK) | FIELD_PREP(PLL_HSDIV_CLKOUT_MASK, 1);
130 mmio_write_32((uintptr_t)(MAIN_PLL0_CFG + MAIN_PLL0_HSDIV2_CTRL), set_val);
131
132 /* clear reset */
133 reg_val = mmio_read_32((uintptr_t)(MAIN_PLL0_CFG + MAIN_PLL0_HSDIV2_CTRL));
134 set_val = (reg_val & ~PLL_HSDIV_RESET_MASK) | FIELD_PREP(PLL_HSDIV_RESET_MASK, 0);
135 mmio_write_32((uintptr_t)(MAIN_PLL0_CFG + MAIN_PLL0_HSDIV2_CTRL), set_val);
136
137 return 0;
138 }
139
140 /*******************************
141 * Function to set DDRSS PLL
142 ******************************/
ddrss_set_pll(unsigned long freq)143 static int ddrss_set_pll(unsigned long freq)
144 {
145 int ret = 0;
146 unsigned int div;
147
148 if (freq == 0UL || freq > MAIN_PLL0_HSDIV2_MAX_FREQ) {
149 return -1;
150 }
151
152 /* set HSDIV divider. Set less by 1 as HSDIV adds a one. */
153 div = MAIN_PLL0_VCO_FREQ/freq;
154 div -= 1;
155 ret = set_ddr_pll_div(div);
156
157 return ret;
158 }
159
160 /*************************************************************************
161 * Function to change DDRSS PLL clock. It is called by the lpddr4 driver
162 * during training
163 ************************************************************************/
k3_lpddr4_freq_update(struct k3_ddrss_desc * ddr)164 static void k3_lpddr4_freq_update(struct k3_ddrss_desc *ddr)
165 {
166 volatile uint32_t reg_val;
167 uint32_t req = 0;
168 uint32_t counter = 0;
169 uint32_t req_type;
170
171 for (counter = 0; counter < ddr->ddr_fhs_cnt; counter++) {
172 /* update the PLL divisor for DDR PLL */
173 reg_val = mmio_read_32(DDRSS_CTRL_MMR + DDR4_FSP_CLKCHNG_REQ);
174 req = FIELD_GET(DDR4_CLKCHNG_REQ_MASK, reg_val);
175 while (req == DDR4_CLKCHNG_REQ_INACTIVE) {
176 reg_val = mmio_read_32((uintptr_t)(DDRSS_CTRL_MMR + DDR4_FSP_CLKCHNG_REQ));
177 req = FIELD_GET(DDR4_CLKCHNG_REQ_MASK, reg_val);
178 }
179
180 reg_val = mmio_read_32((uintptr_t)(DDRSS_CTRL_MMR + DDR4_FSP_CLKCHNG_REQ));
181 req_type = FIELD_GET(DDR4_CLKCHNG_REQTYPE_MASK, reg_val);
182 if (req_type == DDR4_CLKCHNG_REQ_FREQ1)
183 ddrss_set_pll(ddr->ddr_freq1);
184 else if (req_type == DDR4_CLKCHNG_REQ_FREQ2)
185 ddrss_set_pll(ddr->ddr_freq2);
186 else if (req_type == DDR4_CLKCHNG_REQ_FREQ0)
187 ddrss_set_pll(ddr->ddr_freq0);
188 else
189 WARN("invalid DDR freq request type\n");
190
191 mmio_write_32((uintptr_t)(DDRSS_CTRL_MMR + DDR4_FSP_CLKCHNG_ACK),
192 DDR4_CLKCHNG_ACK_DONE);
193 reg_val = mmio_read_32((uintptr_t)(DDRSS_CTRL_MMR + DDR4_FSP_CLKCHNG_REQ));
194 req = FIELD_GET(DDR4_CLKCHNG_REQ_MASK, reg_val);
195 while (req == DDR4_CLKCHNG_REQ_ACTIVE) {
196 reg_val = mmio_read_32((uintptr_t)(DDRSS_CTRL_MMR + DDR4_FSP_CLKCHNG_REQ));
197 req = FIELD_GET(DDR4_CLKCHNG_REQ_MASK, reg_val);
198 }
199 mmio_write_32((uintptr_t)(DDRSS_CTRL_MMR + DDR4_FSP_CLKCHNG_ACK),
200 DDR4_CLKCHNG_ACK_NONE);
201 }
202 INFO("DDR Freq change complete\n");
203 }
204
205 /*************************************************************************
206 * Function to change DDRSS PLL clock. It is called by the lpddr4 driver
207 * during training
208 ************************************************************************/
k3_lpddr4_ack_freq_upd_req(const ti_lpddr4_privatedata * pd)209 static void k3_lpddr4_ack_freq_upd_req(const ti_lpddr4_privatedata *pd)
210 {
211 if (ddrss.dram_class == DENALI_CTL_0_DRAM_CLASS_LPDDR4)
212 k3_lpddr4_freq_update(&ddrss);
213 }
214
k3_lpddr4_info_handler(const ti_lpddr4_privatedata * pd,ti_lpddr4_infotype infotype)215 static void k3_lpddr4_info_handler(const ti_lpddr4_privatedata *pd,
216 ti_lpddr4_infotype infotype)
217 {
218 if (infotype == LPDDR4_DRV_SOC_PLL_UPDATE)
219 k3_lpddr4_ack_freq_upd_req(pd);
220 }
221
222 /*************************************************************************
223 * Function to change DDRSS PLL clock. It is called by the lpddr4 driver
224 * during training
225 ************************************************************************/
am62l_lpddr4_init(void)226 int am62l_lpddr4_init(void)
227 {
228 uint16_t configsize = 0U;
229 uint32_t status = 0U;
230 ti_lpddr4_config *config = &ddrss.config;
231 ti_lpddr4_privatedata *pd = &ddrss.pd;
232 ti_lpddr4_obj *driverdt;
233 uint32_t offset = 0;
234 uint32_t regval;
235 uint32_t sdram_idx;
236 uint32_t v2a_ctl_reg;
237 uint64_t ddr_ram_size;
238 int ret;
239
240 ddrss.ddr_fhs_cnt = am62lx_ddr_cfg.ddr_fhs_cnt;
241 ddrss.ddr_freq0 = am62lx_ddr_cfg.ddr_freq0;
242 ddrss.ddr_freq1 = am62lx_ddr_cfg.ddr_freq1;
243 ddrss.ddr_freq2 = am62lx_ddr_cfg.ddr_freq2;
244 ddr_ram_size = AM62L_DDR_RAM_SIZE;
245
246 ddrss.dram_class = CPS_FLD_READ(TI_LPDDR4__DRAM_CLASS__FLD,
247 am62lx_ddr_cfg.ctl_data[0]);
248 NOTICE("BL1: dram_class: %d\n", ddrss.dram_class);
249
250 if (ddrss.dram_class == DENALI_CTL_0_DRAM_CLASS_LPDDR4)
251 ret = ddrss_set_pll(ddrss.ddr_freq0);
252 else
253 ret = ddrss_set_pll(ddrss.ddr_freq1);
254
255 if (ret != 0)
256 return ret;
257
258 /* Disable the DDR LPSCs to start in known state */
259 ret = set_main_psc_state(PD_DDR, LPSC_MAIN_DDR_DATA_ISO_N,
260 PSC_PD_ON, PSC_MD_SWRESETDISABLE);
261 if (ret != 0)
262 return ret;
263
264 ret = set_main_psc_state(PD_DDR, LPSC_MAIN_DDR_CFG_ISO_N,
265 PSC_PD_ON, PSC_MD_SWRESETDISABLE);
266 if (ret != 0)
267 return ret;
268
269 ret = set_main_psc_state(PD_DDR, LPSC_MAIN_DDR_LOCAL,
270 PSC_PD_OFF, PSC_MD_SWRESETDISABLE);
271 if (ret != 0)
272 return ret;
273
274 /* Enable DDR LPSCs to configure the controllers */
275 ret = set_main_psc_state(PD_DDR, LPSC_MAIN_DDR_LOCAL, PSC_PD_ON, PSC_MD_ENABLE);
276 if (ret != 0)
277 return ret;
278
279 ret = set_main_psc_state(PD_DDR, LPSC_MAIN_DDR_CFG_ISO_N, PSC_PD_ON, PSC_MD_ENABLE);
280 if (ret != 0)
281 return ret;
282
283 ret = set_main_psc_state(PD_DDR, LPSC_MAIN_DDR_DATA_ISO_N, PSC_PD_ON, PSC_MD_ENABLE);
284 if (ret != 0)
285 return ret;
286
287 ddrss.ddrss_ctl_cfg = (void *)DDRSS_CTL_CFG;
288 ddrss.ddrss_ctrl_mmr = (void *)DDRSS_CTRL_MMR;
289 ddrss.ddrss_ss_cfg = (void *)DDRSS_SS_CFG;
290
291 ddrss.driverdt = ti_lpddr4_getinstance();
292 driverdt = ddrss.driverdt;
293
294 status = driverdt->probe(config, &configsize);
295 if (status != 0U) {
296 ERROR("lpddr4: probe failed status=0x%x\n", status);
297 return (int)status;
298 }
299 INFO("lpddr4: probe done\n");
300
301 /* set LPDDR4 size */
302 sdram_idx = DDRSS_V2A_CTL_REG_SDRAM_IDX_CALC(ddr_ram_size);
303 v2a_ctl_reg = mmio_read_32((uintptr_t)(DDRSS_SS_CFG + DDRSS_V2A_CTL_REG));
304 v2a_ctl_reg = (v2a_ctl_reg & DDRSS_V2A_CTL_REG_SDRAM_IDX_MASK) | sdram_idx;
305 mmio_write_32((uintptr_t)(DDRSS_SS_CFG + DDRSS_V2A_CTL_REG), v2a_ctl_reg);
306
307 /* Initialize LPDDR4 */
308 config->ctlbase = ddrss.ddrss_ctl_cfg;
309 config->infohandler = k3_lpddr4_info_handler;
310 status = driverdt->init(pd, config);
311 if (status != 0U) {
312 ERROR("lpddr4: init failed status=0x%x\n", status);
313 return (int)status;
314 }
315 INFO("lpddr4/ddr4: init done\n");
316
317 /* Configure DDR with config and control structures */
318 driverdt->writectlconfigex(pd, am62lx_ddr_cfg.ctl_data,
319 TI_LPDDR4_INTR_CTL_REG_COUNT);
320 driverdt->writephyindepconfigex(pd, am62lx_ddr_cfg.pi_data,
321 TI_LPDDR4_INTR_PHY_INDEP_REG_COUNT);
322 driverdt->writephyconfigex(pd, am62lx_ddr_cfg.phy_data,
323 TI_LPDDR4_INTR_PHY_REG_COUNT);
324
325 TH_OFFSET_FROM_REG(TI_LPDDR4__START__REG, offset);
326 driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, ®val);
327 if (CPS_FLD_READ(TI_LPDDR4__START__FLD, regval) != 0) {
328 ERROR("LPDDR4 prestart failed\n");
329 return -ENXIO;
330 }
331
332 INFO("lpddr4: Start DDR controller\n");
333 status = driverdt->start(pd);
334 if (status != 0) {
335 ERROR("lpddr4: start failed status = 0x%x\n", status);
336 return status;
337 }
338
339 /* check poststart status */
340 driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, ®val);
341 INFO("start-status reg: after =0x%x\n", regval);
342 if (CPS_FLD_READ(TI_LPDDR4__START__FLD, regval) != 1) {
343 ERROR("LPDDR4 poststart failed\n");
344 return -ENXIO;
345 }
346
347 return 0;
348 }
349