xref: /rk3399_ARM-atf/plat/st/common/stm32mp_dt.c (revision 7af195e29a4213eefac0661d84e1c9c20476e166)
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 path node.
150  * It reads the value indicated inside the device tree.
151  * Returns node offset on success and a negative FDT error code on failure.
152  ******************************************************************************/
153 static int dt_get_stdout_node_offset(void)
154 {
155 	int node;
156 	const char *cchar;
157 
158 	node = fdt_path_offset(fdt, "/secure-chosen");
159 	if (node < 0) {
160 		node = fdt_path_offset(fdt, "/chosen");
161 		if (node < 0) {
162 			return -FDT_ERR_NOTFOUND;
163 		}
164 	}
165 
166 	cchar = fdt_getprop(fdt, node, "stdout-path", NULL);
167 	if (cchar == NULL) {
168 		return -FDT_ERR_NOTFOUND;
169 	}
170 
171 	node = -FDT_ERR_NOTFOUND;
172 	if (strchr(cchar, (int)':') != NULL) {
173 		const char *name;
174 		char *str = (char *)cchar;
175 		int len = 0;
176 
177 		while (strncmp(":", str, 1)) {
178 			len++;
179 			str++;
180 		}
181 
182 		name = fdt_get_alias_namelen(fdt, cchar, len);
183 
184 		if (name != NULL) {
185 			node = fdt_path_offset(fdt, name);
186 		}
187 	} else {
188 		node = fdt_path_offset(fdt, cchar);
189 	}
190 
191 	return node;
192 }
193 
194 /*******************************************************************************
195  * This function gets the stdout pin configuration information from the DT.
196  * And then calls the sub-function to treat it and set GPIO registers.
197  * Returns 0 on success and a negative FDT error code on failure.
198  ******************************************************************************/
199 int dt_set_stdout_pinctrl(void)
200 {
201 	int node;
202 
203 	node = dt_get_stdout_node_offset();
204 	if (node < 0) {
205 		return -FDT_ERR_NOTFOUND;
206 	}
207 
208 	return dt_set_pinctrl_config(node);
209 }
210 
211 /*******************************************************************************
212  * This function fills the generic information from a given node.
213  ******************************************************************************/
214 void dt_fill_device_info(struct dt_node_info *info, int node)
215 {
216 	const fdt32_t *cuint;
217 
218 	cuint = fdt_getprop(fdt, node, "reg", NULL);
219 	if (cuint != NULL) {
220 		info->base = fdt32_to_cpu(*cuint);
221 	} else {
222 		info->base = 0;
223 	}
224 
225 	cuint = fdt_getprop(fdt, node, "clocks", NULL);
226 	if (cuint != NULL) {
227 		cuint++;
228 		info->clock = (int)fdt32_to_cpu(*cuint);
229 	} else {
230 		info->clock = -1;
231 	}
232 
233 	cuint = fdt_getprop(fdt, node, "resets", NULL);
234 	if (cuint != NULL) {
235 		cuint++;
236 		info->reset = (int)fdt32_to_cpu(*cuint);
237 	} else {
238 		info->reset = -1;
239 	}
240 
241 	info->status = fdt_get_status(node);
242 }
243 
244 /*******************************************************************************
245  * This function retrieve the generic information from DT.
246  * Returns node on success and a negative FDT error code on failure.
247  ******************************************************************************/
248 int dt_get_node(struct dt_node_info *info, int offset, const char *compat)
249 {
250 	int node;
251 
252 	node = fdt_node_offset_by_compatible(fdt, offset, compat);
253 	if (node < 0) {
254 		return -FDT_ERR_NOTFOUND;
255 	}
256 
257 	dt_fill_device_info(info, node);
258 
259 	return node;
260 }
261 
262 /*******************************************************************************
263  * This function gets the UART instance info of stdout from the DT.
264  * Returns node on success and a negative FDT error code on failure.
265  ******************************************************************************/
266 int dt_get_stdout_uart_info(struct dt_node_info *info)
267 {
268 	int node;
269 
270 	node = dt_get_stdout_node_offset();
271 	if (node < 0) {
272 		return -FDT_ERR_NOTFOUND;
273 	}
274 
275 	dt_fill_device_info(info, node);
276 
277 	return node;
278 }
279 
280 /*******************************************************************************
281  * This function gets DDR size information from the DT.
282  * Returns value in bytes on success, and 0 on failure.
283  ******************************************************************************/
284 uint32_t dt_get_ddr_size(void)
285 {
286 	int node;
287 
288 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
289 	if (node < 0) {
290 		INFO("%s: Cannot read DDR node in DT\n", __func__);
291 		return 0;
292 	}
293 
294 	return fdt_read_uint32_default(node, "st,mem-size", 0);
295 }
296 
297 /*******************************************************************************
298  * This function gets DDRCTRL base address information from the DT.
299  * Returns value on success, and 0 on failure.
300  ******************************************************************************/
301 uintptr_t dt_get_ddrctrl_base(void)
302 {
303 	int node;
304 	uint32_t array[4];
305 
306 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
307 	if (node < 0) {
308 		INFO("%s: Cannot read DDR node in DT\n", __func__);
309 		return 0;
310 	}
311 
312 	if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
313 		return 0;
314 	}
315 
316 	return array[0];
317 }
318 
319 /*******************************************************************************
320  * This function gets DDRPHYC base address information from the DT.
321  * Returns value on success, and 0 on failure.
322  ******************************************************************************/
323 uintptr_t dt_get_ddrphyc_base(void)
324 {
325 	int node;
326 	uint32_t array[4];
327 
328 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
329 	if (node < 0) {
330 		INFO("%s: Cannot read DDR node in DT\n", __func__);
331 		return 0;
332 	}
333 
334 	if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
335 		return 0;
336 	}
337 
338 	return array[2];
339 }
340 
341 /*******************************************************************************
342  * This function gets PWR base address information from the DT.
343  * Returns value on success, and 0 on failure.
344  ******************************************************************************/
345 uintptr_t dt_get_pwr_base(void)
346 {
347 	int node;
348 	const fdt32_t *cuint;
349 
350 	node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
351 	if (node < 0) {
352 		INFO("%s: Cannot read PWR node in DT\n", __func__);
353 		return 0;
354 	}
355 
356 	cuint = fdt_getprop(fdt, node, "reg", NULL);
357 	if (cuint == NULL) {
358 		return 0;
359 	}
360 
361 	return fdt32_to_cpu(*cuint);
362 }
363 
364 /*******************************************************************************
365  * This function gets PWR VDD regulator voltage information from the DT.
366  * Returns value in microvolts on success, and 0 on failure.
367  ******************************************************************************/
368 uint32_t dt_get_pwr_vdd_voltage(void)
369 {
370 	int node, pwr_regulators_node;
371 	const fdt32_t *cuint;
372 
373 	node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
374 	if (node < 0) {
375 		INFO("%s: Cannot read PWR node in DT\n", __func__);
376 		return 0;
377 	}
378 
379 	pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators");
380 	if (node < 0) {
381 		INFO("%s: Cannot read pwr-regulators node in DT\n", __func__);
382 		return 0;
383 	}
384 
385 	cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL);
386 	if (cuint == NULL) {
387 		return 0;
388 	}
389 
390 	node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
391 	if (node < 0) {
392 		return 0;
393 	}
394 
395 	cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
396 	if (cuint == NULL) {
397 		return 0;
398 	}
399 
400 	return fdt32_to_cpu(*cuint);
401 }
402 
403 /*******************************************************************************
404  * This function gets SYSCFG base address information from the DT.
405  * Returns value on success, and 0 on failure.
406  ******************************************************************************/
407 uintptr_t dt_get_syscfg_base(void)
408 {
409 	int node;
410 	const fdt32_t *cuint;
411 
412 	node = fdt_node_offset_by_compatible(fdt, -1, DT_SYSCFG_COMPAT);
413 	if (node < 0) {
414 		INFO("%s: Cannot read SYSCFG node in DT\n", __func__);
415 		return 0;
416 	}
417 
418 	cuint = fdt_getprop(fdt, node, "reg", NULL);
419 	if (cuint == NULL) {
420 		return 0;
421 	}
422 
423 	return fdt32_to_cpu(*cuint);
424 }
425 
426 /*******************************************************************************
427  * This function retrieves board model from DT
428  * Returns string taken from model node, NULL otherwise
429  ******************************************************************************/
430 const char *dt_get_board_model(void)
431 {
432 	int node = fdt_path_offset(fdt, "/");
433 
434 	if (node < 0) {
435 		return NULL;
436 	}
437 
438 	return (const char *)fdt_getprop(fdt, node, "model", NULL);
439 }
440