xref: /rk3399_ARM-atf/plat/st/common/stm32mp_dt.c (revision fd7b287cbe9147ca9e07dd9f30c49c58bbdd92a8)
1 /*
2  * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 
10 #include <libfdt.h>
11 
12 #include <platform_def.h>
13 
14 #include <common/debug.h>
15 #include <drivers/st/stm32_gpio.h>
16 #include <drivers/st/stm32mp1_ddr.h>
17 #include <drivers/st/stm32mp1_ram.h>
18 
19 #include <stm32mp_dt.h>
20 
21 static int fdt_checked;
22 
23 static void *fdt = (void *)(uintptr_t)STM32MP_DTB_BASE;
24 
25 /*******************************************************************************
26  * This function checks device tree file with its header.
27  * Returns 0 on success and a negative FDT error code on failure.
28  ******************************************************************************/
29 int dt_open_and_check(void)
30 {
31 	int ret = fdt_check_header(fdt);
32 
33 	if (ret == 0) {
34 		fdt_checked = 1;
35 	}
36 
37 	return ret;
38 }
39 
40 /*******************************************************************************
41  * This function gets the address of the DT.
42  * If DT is OK, fdt_addr is filled with DT address.
43  * Returns 1 if success, 0 otherwise.
44  ******************************************************************************/
45 int fdt_get_address(void **fdt_addr)
46 {
47 	if (fdt_checked == 1) {
48 		*fdt_addr = fdt;
49 	}
50 
51 	return fdt_checked;
52 }
53 
54 /*******************************************************************************
55  * This function check the presence of a node (generic use of fdt library).
56  * Returns true if present, else return false.
57  ******************************************************************************/
58 bool fdt_check_node(int node)
59 {
60 	int len;
61 	const char *cchar;
62 
63 	cchar = fdt_get_name(fdt, node, &len);
64 
65 	return (cchar != NULL) && (len >= 0);
66 }
67 
68 /*******************************************************************************
69  * This function return global node status (generic use of fdt library).
70  ******************************************************************************/
71 uint8_t fdt_get_status(int node)
72 {
73 	uint8_t status = DT_DISABLED;
74 	int len;
75 	const char *cchar;
76 
77 	cchar = fdt_getprop(fdt, node, "status", &len);
78 	if ((cchar == NULL) ||
79 	    (strncmp(cchar, "okay", (size_t)len) == 0)) {
80 		status |= DT_NON_SECURE;
81 	}
82 
83 	cchar = fdt_getprop(fdt, node, "secure-status", &len);
84 	if (cchar == NULL) {
85 		if (status == DT_NON_SECURE) {
86 			status |= DT_SECURE;
87 		}
88 	} else if (strncmp(cchar, "okay", (size_t)len) == 0) {
89 		status |= DT_SECURE;
90 	}
91 
92 	return status;
93 }
94 
95 /*******************************************************************************
96  * This function reads a value of a node property (generic use of fdt
97  * library).
98  * Returns value if success, and a default value if property not found.
99  * Default value is passed as parameter.
100  ******************************************************************************/
101 uint32_t fdt_read_uint32_default(int node, const char *prop_name,
102 				 uint32_t dflt_value)
103 {
104 	const fdt32_t *cuint;
105 	int lenp;
106 
107 	cuint = fdt_getprop(fdt, node, prop_name, &lenp);
108 	if (cuint == NULL) {
109 		return dflt_value;
110 	}
111 
112 	return fdt32_to_cpu(*cuint);
113 }
114 
115 /*******************************************************************************
116  * This function reads a series of parameters in a node property
117  * (generic use of fdt library).
118  * It reads the values inside the device tree, from property name and node.
119  * The number of parameters is also indicated as entry parameter.
120  * Returns 0 on success and a negative FDT error code on failure.
121  * If success, values are stored at the third parameter address.
122  ******************************************************************************/
123 int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array,
124 			  uint32_t count)
125 {
126 	const fdt32_t *cuint;
127 	int len;
128 	uint32_t i;
129 
130 	cuint = fdt_getprop(fdt, node, prop_name, &len);
131 	if (cuint == NULL) {
132 		return -FDT_ERR_NOTFOUND;
133 	}
134 
135 	if ((uint32_t)len != (count * sizeof(uint32_t))) {
136 		return -FDT_ERR_BADLAYOUT;
137 	}
138 
139 	for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
140 		*array = fdt32_to_cpu(*cuint);
141 		array++;
142 		cuint++;
143 	}
144 
145 	return 0;
146 }
147 
148 /*******************************************************************************
149  * This function gets the stdout pin configuration information from the DT.
150  * And then calls the sub-function to treat it and set GPIO registers.
151  * Returns 0 on success and a negative FDT error code on failure.
152  ******************************************************************************/
153 int dt_set_stdout_pinctrl(void)
154 {
155 	int node;
156 
157 	node = dt_get_stdout_node_offset();
158 	if (node < 0) {
159 		return -FDT_ERR_NOTFOUND;
160 	}
161 
162 	return dt_set_pinctrl_config(node);
163 }
164 
165 /*******************************************************************************
166  * This function fills the generic information from a given node.
167  ******************************************************************************/
168 void dt_fill_device_info(struct dt_node_info *info, int node)
169 {
170 	const fdt32_t *cuint;
171 
172 	cuint = fdt_getprop(fdt, node, "reg", NULL);
173 	if (cuint != NULL) {
174 		info->base = fdt32_to_cpu(*cuint);
175 	} else {
176 		info->base = 0;
177 	}
178 
179 	cuint = fdt_getprop(fdt, node, "clocks", NULL);
180 	if (cuint != NULL) {
181 		cuint++;
182 		info->clock = (int)fdt32_to_cpu(*cuint);
183 	} else {
184 		info->clock = -1;
185 	}
186 
187 	cuint = fdt_getprop(fdt, node, "resets", NULL);
188 	if (cuint != NULL) {
189 		cuint++;
190 		info->reset = (int)fdt32_to_cpu(*cuint);
191 	} else {
192 		info->reset = -1;
193 	}
194 
195 	info->status = fdt_get_status(node);
196 }
197 
198 /*******************************************************************************
199  * This function retrieve the generic information from DT.
200  * Returns node on success and a negative FDT error code on failure.
201  ******************************************************************************/
202 int dt_get_node(struct dt_node_info *info, int offset, const char *compat)
203 {
204 	int node;
205 
206 	node = fdt_node_offset_by_compatible(fdt, offset, compat);
207 	if (node < 0) {
208 		return -FDT_ERR_NOTFOUND;
209 	}
210 
211 	dt_fill_device_info(info, node);
212 
213 	return node;
214 }
215 
216 /*******************************************************************************
217  * This function gets the UART instance info of stdout from the DT.
218  * Returns node on success and a negative FDT error code on failure.
219  ******************************************************************************/
220 int dt_get_stdout_uart_info(struct dt_node_info *info)
221 {
222 	int node;
223 
224 	node = dt_get_stdout_node_offset();
225 	if (node < 0) {
226 		return -FDT_ERR_NOTFOUND;
227 	}
228 
229 	dt_fill_device_info(info, node);
230 
231 	return node;
232 }
233 
234 /*******************************************************************************
235  * This function gets the stdout path node.
236  * It reads the value indicated inside the device tree.
237  * Returns node if success, and a negative value else.
238  ******************************************************************************/
239 int dt_get_stdout_node_offset(void)
240 {
241 	int node;
242 	const char *cchar;
243 
244 	node = fdt_path_offset(fdt, "/chosen");
245 	if (node < 0) {
246 		return -FDT_ERR_NOTFOUND;
247 	}
248 
249 	cchar = fdt_getprop(fdt, node, "stdout-path", NULL);
250 	if (cchar == NULL) {
251 		return -FDT_ERR_NOTFOUND;
252 	}
253 
254 	node = -FDT_ERR_NOTFOUND;
255 	if (strchr(cchar, (int)':') != NULL) {
256 		const char *name;
257 		char *str = (char *)cchar;
258 		int len = 0;
259 
260 		while (strncmp(":", str, 1)) {
261 			len++;
262 			str++;
263 		}
264 
265 		name = fdt_get_alias_namelen(fdt, cchar, len);
266 
267 		if (name != NULL) {
268 			node = fdt_path_offset(fdt, name);
269 		}
270 	} else {
271 		node = fdt_path_offset(fdt, cchar);
272 	}
273 
274 	return node;
275 }
276 
277 /*******************************************************************************
278  * This function gets DDR size information from the DT.
279  * Returns value in bytes on success, and 0 on failure.
280  ******************************************************************************/
281 uint32_t dt_get_ddr_size(void)
282 {
283 	int node;
284 
285 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
286 	if (node < 0) {
287 		INFO("%s: Cannot read DDR node in DT\n", __func__);
288 		return 0;
289 	}
290 
291 	return fdt_read_uint32_default(node, "st,mem-size", 0);
292 }
293 
294 /*******************************************************************************
295  * This function gets DDRCTRL base address information from the DT.
296  * Returns value on success, and 0 on failure.
297  ******************************************************************************/
298 uintptr_t dt_get_ddrctrl_base(void)
299 {
300 	int node;
301 	uint32_t array[4];
302 
303 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
304 	if (node < 0) {
305 		INFO("%s: Cannot read DDR node in DT\n", __func__);
306 		return 0;
307 	}
308 
309 	if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
310 		return 0;
311 	}
312 
313 	return array[0];
314 }
315 
316 /*******************************************************************************
317  * This function gets DDRPHYC base address information from the DT.
318  * Returns value on success, and 0 on failure.
319  ******************************************************************************/
320 uintptr_t dt_get_ddrphyc_base(void)
321 {
322 	int node;
323 	uint32_t array[4];
324 
325 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
326 	if (node < 0) {
327 		INFO("%s: Cannot read DDR node in DT\n", __func__);
328 		return 0;
329 	}
330 
331 	if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
332 		return 0;
333 	}
334 
335 	return array[2];
336 }
337 
338 /*******************************************************************************
339  * This function gets PWR base address information from the DT.
340  * Returns value on success, and 0 on failure.
341  ******************************************************************************/
342 uintptr_t dt_get_pwr_base(void)
343 {
344 	int node;
345 	const fdt32_t *cuint;
346 
347 	node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
348 	if (node < 0) {
349 		INFO("%s: Cannot read PWR node in DT\n", __func__);
350 		return 0;
351 	}
352 
353 	cuint = fdt_getprop(fdt, node, "reg", NULL);
354 	if (cuint == NULL) {
355 		return 0;
356 	}
357 
358 	return fdt32_to_cpu(*cuint);
359 }
360 
361 /*******************************************************************************
362  * This function retrieves board model from DT
363  * Returns string taken from model node, NULL otherwise
364  ******************************************************************************/
365 const char *dt_get_board_model(void)
366 {
367 	int node = fdt_path_offset(fdt, "/");
368 
369 	if (node < 0) {
370 		return NULL;
371 	}
372 
373 	return (const char *)fdt_getprop(fdt, node, "model", NULL);
374 }
375