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