xref: /rk3399_ARM-atf/drivers/nxp/ddr/s32cc/ddr_init.c (revision 7ad4b5ed31e33dca21dd4d2f4a9f64f9b7d4db85)
1 /*
2  * Copyright 2020-2023, 2025-2026 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <assert.h>
7 
8 #include <ddr_init.h>
9 
10 static uint32_t load_phy_image(uint32_t start_addr, size_t size,
11 			       const uint16_t image[]);
12 
13 /* Load DDR configuration from given address and populate ddrss struct */
14 static struct ddrss_config load_ddr_config(uintptr_t load_from)
15 {
16 	struct ddrss_config config;
17 	struct ddr_fw_layout ddr_layout;
18 	uintptr_t current_addr = load_from;
19 
20 	ddr_layout = *(struct ddr_fw_layout *)load_from;
21 	current_addr += sizeof(struct ddr_fw_layout);
22 
23 	config.memory_type = ddr_layout.memory_type;
24 	config.frequency = ddr_layout.frequency;
25 	config.ddrc_size = ddr_layout.ddrc_size;
26 	config.dq_swap_size = ddr_layout.dq_swap_size;
27 	config.phy_size = ddr_layout.phy_size;
28 	config.pie_size = ddr_layout.pie_size;
29 	config.imem_1d_size = ddr_layout.imem_1d_size;
30 	config.dmem_1d_size = ddr_layout.dmem_1d_size;
31 	config.imem_2d_size = ddr_layout.imem_2d_size;
32 	config.dmem_2d_size = ddr_layout.dmem_2d_size;
33 	config.phy_csr_size = ddr_layout.phy_csr_size;
34 	config.ddrc_csr_size = ddr_layout.ddrc_csr_size;
35 
36 	config.ddrc = (struct regconf *)(current_addr + ddr_layout.ddrc_offset);
37 	config.dq_swap = (struct dqconf *)(current_addr + ddr_layout.dq_swap_offset);
38 	config.phy = (struct regconf_16 *)(current_addr + ddr_layout.phy_offset);
39 	config.pie = (struct regconf_16 *)(current_addr + ddr_layout.pie_offset);
40 	config.imem_1d = (uint16_t *)(current_addr + ddr_layout.imem_1d_offset);
41 	config.dmem_1d = (uint16_t *)(current_addr + ddr_layout.dmem_1d_offset);
42 	config.imem_2d = (uint16_t *)(current_addr + ddr_layout.imem_2d_offset);
43 	config.dmem_2d = (uint16_t *)(current_addr + ddr_layout.dmem_2d_offset);
44 	config.phy_csr = (uint32_t *)(current_addr + ddr_layout.phy_csr_offset);
45 	config.ddrc_csr = (uint32_t *)(current_addr + ddr_layout.ddrc_csr_offset);
46 
47 	return config;
48 }
49 
50 /* Initialize ddr controller with given settings. */
51 static uint32_t ddrc_init_cfg(const struct ddrss_config *config)
52 {
53 	return load_register_cfg(config->ddrc_size, config->ddrc);
54 }
55 
56 /* Main method needed to initialize ddr subsystem. */
57 uint32_t ddr_init(uintptr_t load_from)
58 {
59 	struct ddrss_config ddr_config;
60 	int err;
61 
62 	assert(load_from != 0UL);
63 
64 	err = plat_ddr_mmap_setup();
65 	if (err != 0) {
66 		return MAPPING_FAILED;
67 	}
68 
69 	ddr_config = load_ddr_config(load_from + sizeof(struct ddr_fw_header));
70 	return ddr_init_cfg(&ddr_config);
71 }
72 
73 /* Execute 2D training stage if images are available */
74 static uint32_t execute_2d_training(const struct ddrss_config *config)
75 {
76 	uint32_t ret = NO_ERR;
77 
78 	/* Load 2d imem image */
79 	mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS);
80 	ret = load_phy_image(IMEM_START_ADDR, config->imem_2d_size,
81 			     config->imem_2d);
82 	if (ret != NO_ERR) {
83 		return ret;
84 	}
85 	mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS);
86 
87 	/* Load 2d dmem image */
88 	mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS);
89 	ret = load_phy_image(DMEM_START_ADDR, config->dmem_2d_size,
90 			     config->dmem_2d);
91 	if (ret != NO_ERR) {
92 		return ret;
93 	}
94 
95 	mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS);
96 	mmio_write_32(APBONLY_MICRORESET, APBONLY_RESET_STALL_MASK);
97 	mmio_write_32(APBONLY_MICRORESET, APBONLY_STALL_TO_MICRO_MASK);
98 	mmio_write_32(APBONLY_MICRORESET, APBONLY_MICRORESET_CLR_MASK);
99 
100 	ret = wait_firmware_execution();
101 	if (ret != NO_ERR) {
102 		return ret;
103 	}
104 
105 	/* Read 2D training results */
106 	if (config->memory_type == (uint8_t)LPDDR4) {
107 		mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS);
108 		read_vref_dq();
109 		compute_tphy_wrdata_delay();
110 		mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS);
111 	}
112 
113 	return ret;
114 }
115 
116 /* Execute phy training with given settings. 2D training stage is optional. */
117 static uint32_t execute_training(const struct ddrss_config *config)
118 {
119 	uint32_t ret = NO_ERR;
120 
121 	/* Apply DQ swapping settings */
122 	ret = load_dq_cfg(config->dq_swap_size, config->dq_swap);
123 	if (ret != NO_ERR) {
124 		return ret;
125 	}
126 
127 	/* Initialize phy module */
128 	ret = load_register_cfg_16(config->phy_size, config->phy);
129 	if (ret != NO_ERR) {
130 		return ret;
131 	}
132 
133 	/* Configure PLL optimal settings */
134 	set_optimal_pll(config->frequency);
135 
136 	/* Load 1D imem image */
137 	mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS);
138 	ret = load_phy_image(IMEM_START_ADDR, config->imem_1d_size,
139 			     config->imem_1d);
140 	if (ret != NO_ERR) {
141 		return ret;
142 	}
143 	mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS);
144 
145 	/* Load 1D dmem image */
146 	mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS);
147 	ret = load_phy_image(DMEM_START_ADDR, config->dmem_1d_size,
148 			     config->dmem_1d);
149 	if (ret != NO_ERR) {
150 		return ret;
151 	}
152 
153 	mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS);
154 	mmio_write_32(APBONLY_MICRORESET, APBONLY_RESET_STALL_MASK);
155 	mmio_write_32(APBONLY_MICRORESET, APBONLY_STALL_TO_MICRO_MASK);
156 	mmio_write_32(APBONLY_MICRORESET, APBONLY_MICRORESET_CLR_MASK);
157 
158 	ret = wait_firmware_execution();
159 	mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS);
160 	if (ret != NO_ERR) {
161 		return ret;
162 	}
163 
164 	/* Read critical delay differences and training results */
165 	mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS);
166 	read_cdds();
167 	if (config->memory_type == (uint8_t)LPDDR4) {
168 		read_vref_ca();
169 	}
170 	if (config->memory_type == (uint8_t)DDR3L) {
171 		compute_tphy_wrdata_delay();
172 	}
173 	mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS);
174 
175 	/*
176 	 * Check if 2d training images have been initialized before executing
177 	 * the second training stage.
178 	 */
179 	if ((config->imem_2d_size > 0U) && (config->dmem_2d_size > 0U)) {
180 		ret = execute_2d_training(config);
181 		if (ret != NO_ERR) {
182 			return ret;
183 		}
184 	}
185 
186 	mmio_write_32(MICROCONT_MUX_SEL, UNLOCK_CSR_ACCESS);
187 	/*  Load pie image after training has executed */
188 	ret = load_register_cfg_16(config->pie_size, config->pie);
189 	mmio_write_32(MICROCONT_MUX_SEL, LOCK_CSR_ACCESS);
190 	return ret;
191 }
192 
193 /* Initialize ddr based on input configuration */
194 uint32_t ddr_init_cfg(const struct ddrss_config *config)
195 {
196 	uint32_t ret = NO_ERR;
197 
198 	/* Init DDR controller based on selected parameter values */
199 	ret = ddrc_init_cfg(config);
200 	if (ret != NO_ERR) {
201 		return ret;
202 	}
203 
204 	/* Setup AXI ports parity */
205 	ret = set_axi_parity();
206 	if (ret != NO_ERR) {
207 		return ret;
208 	}
209 
210 	/* Init PHY module */
211 	ret = execute_training(config);
212 	if (ret != NO_ERR) {
213 		return ret;
214 	}
215 
216 	/* Execute post training setup */
217 	ret = post_train_setup((uint8_t)(ADJUST_DDRC_MASK));
218 
219 	return ret;
220 }
221 
222 /* Load register array into memory. */
223 uint32_t load_register_cfg_16(size_t size, const struct regconf_16 cfg[])
224 {
225 	size_t i;
226 
227 	for (i = 0; i < size; i++) {
228 		mmio_write_16((uintptr_t)cfg[i].addr, cfg[i].data);
229 	}
230 
231 	return NO_ERR;
232 }
233 
234 /* Load register array into memory. */
235 uint32_t load_register_cfg(size_t size, const struct regconf cfg[])
236 {
237 	size_t i;
238 
239 	for (i = 0; i < size; i++) {
240 		mmio_write_32((uintptr_t)cfg[i].addr, cfg[i].data);
241 	}
242 
243 	return NO_ERR;
244 }
245 
246 /* Load dq config array into memory. */
247 uint32_t load_dq_cfg(size_t size, const struct dqconf cfg[])
248 {
249 	size_t i;
250 
251 	for (i = 0; i < size; i++) {
252 		mmio_write_32((uintptr_t)cfg[i].addr, cfg[i].data);
253 	}
254 
255 	return NO_ERR;
256 }
257 
258 /* Load image into memory at consecutive addresses */
259 static uint32_t load_phy_image(uint32_t start_addr, size_t size,
260 			       const uint16_t image[])
261 {
262 	uint32_t current_addr = start_addr;
263 	size_t i;
264 
265 	for (i = 0; i < size; i++) {
266 		mmio_write_32((uintptr_t)current_addr, image[i]);
267 		current_addr += (uint32_t)sizeof(uint32_t);
268 	}
269 	return NO_ERR;
270 }
271 
272 /* Ensure optimal phy pll settings for selected frequency. */
273 void set_optimal_pll(uint16_t frequency)
274 {
275 	/* Configure phy pll registers */
276 	mmio_write_32(MASTER_PLLCTRL1, PLLCTRL1_VALUE);
277 	mmio_write_32(MASTER_PLLTESTMODE, PLLTESTMODE_VALUE);
278 	mmio_write_32(MASTER_PLLCTRL4, PLLCTRL4_VALUE);
279 	mmio_write_32(MASTER_PLLCTRL2, pllctrl2_value(frequency));
280 
281 	mmio_setbits_32(MASTER_CALMISC2, (CALMISC2 << CALMISC2_OFFSET));
282 
283 	mmio_clrsetbits_32(MASTER_CALOFFSET,
284 			   CALDRV_MASK, ((CALDRV << CALDRV_OFFSET) | (CALDRV << CALDRV2_OFFSET)));
285 }
286