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