xref: /rk3399_ARM-atf/plat/ti/k3low/common/drivers/k3-ddrss/am62l_ddrss.c (revision 6c0c3a74dda68e7ffc8bd6c156918ddbfea7e03a)
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, &regval);
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, &regval);
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