xref: /rk3399_ARM-atf/plat/st/common/stm32mp_dt.c (revision f1b6b014d79b7522b0494c1595f7cd5900964681)
1 /*
2  * Copyright (c) 2017-2021, 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 <common/fdt_wrappers.h>
16 #include <drivers/st/stm32_gpio.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)STM32MP_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 	const char *cchar;
76 
77 	cchar = fdt_getprop(fdt, node, "status", NULL);
78 	if ((cchar == NULL) ||
79 	    (strncmp(cchar, "okay", strlen("okay")) == 0)) {
80 		status |= DT_NON_SECURE;
81 	}
82 
83 	cchar = fdt_getprop(fdt, node, "secure-status", NULL);
84 	if (cchar == NULL) {
85 		if (status == DT_NON_SECURE) {
86 			status |= DT_SECURE;
87 		}
88 	} else if (strncmp(cchar, "okay", strlen("okay")) == 0) {
89 		status |= DT_SECURE;
90 	}
91 
92 	return status;
93 }
94 
95 #if ENABLE_ASSERTIONS
96 /*******************************************************************************
97  * This function returns the address cells from the node parent.
98  * Returns:
99  * - #address-cells value if success.
100  * - invalid value if error.
101  * - a default value if undefined #address-cells property as per libfdt
102  *   implementation.
103  ******************************************************************************/
104 static int fdt_get_node_parent_address_cells(int node)
105 {
106 	int parent;
107 
108 	parent = fdt_parent_offset(fdt, node);
109 	if (parent < 0) {
110 		return -FDT_ERR_NOTFOUND;
111 	}
112 
113 	return fdt_address_cells(fdt, parent);
114 }
115 #endif
116 
117 /*******************************************************************************
118  * This function gets the stdout pin configuration information from the DT.
119  * And then calls the sub-function to treat it and set GPIO registers.
120  * Returns 0 on success and a negative FDT error code on failure.
121  ******************************************************************************/
122 int dt_set_stdout_pinctrl(void)
123 {
124 	int node;
125 
126 	node = fdt_get_stdout_node_offset(fdt);
127 	if (node < 0) {
128 		return -FDT_ERR_NOTFOUND;
129 	}
130 
131 	return dt_set_pinctrl_config(node);
132 }
133 
134 /*******************************************************************************
135  * This function fills the generic information from a given node.
136  ******************************************************************************/
137 void dt_fill_device_info(struct dt_node_info *info, int node)
138 {
139 	const fdt32_t *cuint;
140 
141 	assert(fdt_get_node_parent_address_cells(node) == 1);
142 
143 	cuint = fdt_getprop(fdt, node, "reg", NULL);
144 	if (cuint != NULL) {
145 		info->base = fdt32_to_cpu(*cuint);
146 	} else {
147 		info->base = 0;
148 	}
149 
150 	cuint = fdt_getprop(fdt, node, "clocks", NULL);
151 	if (cuint != NULL) {
152 		cuint++;
153 		info->clock = (int)fdt32_to_cpu(*cuint);
154 	} else {
155 		info->clock = -1;
156 	}
157 
158 	cuint = fdt_getprop(fdt, node, "resets", NULL);
159 	if (cuint != NULL) {
160 		cuint++;
161 		info->reset = (int)fdt32_to_cpu(*cuint);
162 	} else {
163 		info->reset = -1;
164 	}
165 
166 	info->status = fdt_get_status(node);
167 }
168 
169 /*******************************************************************************
170  * This function retrieve the generic information from DT.
171  * Returns node on success and a negative FDT error code on failure.
172  ******************************************************************************/
173 int dt_get_node(struct dt_node_info *info, int offset, const char *compat)
174 {
175 	int node;
176 
177 	node = fdt_node_offset_by_compatible(fdt, offset, compat);
178 	if (node < 0) {
179 		return -FDT_ERR_NOTFOUND;
180 	}
181 
182 	dt_fill_device_info(info, node);
183 
184 	return node;
185 }
186 
187 /*******************************************************************************
188  * This function gets the UART instance info of stdout from the DT.
189  * Returns node on success and a negative FDT error code on failure.
190  ******************************************************************************/
191 int dt_get_stdout_uart_info(struct dt_node_info *info)
192 {
193 	int node;
194 
195 	node = fdt_get_stdout_node_offset(fdt);
196 	if (node < 0) {
197 		return -FDT_ERR_NOTFOUND;
198 	}
199 
200 	dt_fill_device_info(info, node);
201 
202 	return node;
203 }
204 
205 /*******************************************************************************
206  * This function gets DDR size information from the DT.
207  * Returns value in bytes on success, and 0 on failure.
208  ******************************************************************************/
209 uint32_t dt_get_ddr_size(void)
210 {
211 	int node;
212 
213 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
214 	if (node < 0) {
215 		INFO("%s: Cannot read DDR node in DT\n", __func__);
216 		return 0;
217 	}
218 
219 	return fdt_read_uint32_default(fdt, node, "st,mem-size", 0);
220 }
221 
222 /*******************************************************************************
223  * This function gets PWR VDD regulator voltage information from the DT.
224  * Returns value in microvolts on success, and 0 on failure.
225  ******************************************************************************/
226 uint32_t dt_get_pwr_vdd_voltage(void)
227 {
228 	int node, pwr_regulators_node;
229 	const fdt32_t *cuint;
230 
231 	node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
232 	if (node < 0) {
233 		INFO("%s: Cannot read PWR node in DT\n", __func__);
234 		return 0;
235 	}
236 
237 	pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators");
238 	if (pwr_regulators_node < 0) {
239 		INFO("%s: Cannot read pwr-regulators node in DT\n", __func__);
240 		return 0;
241 	}
242 
243 	cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL);
244 	if (cuint == NULL) {
245 		return 0;
246 	}
247 
248 	node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
249 	if (node < 0) {
250 		return 0;
251 	}
252 
253 	cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
254 	if (cuint == NULL) {
255 		return 0;
256 	}
257 
258 	return fdt32_to_cpu(*cuint);
259 }
260 
261 /*******************************************************************************
262  * This function retrieves board model from DT
263  * Returns string taken from model node, NULL otherwise
264  ******************************************************************************/
265 const char *dt_get_board_model(void)
266 {
267 	int node = fdt_path_offset(fdt, "/");
268 
269 	if (node < 0) {
270 		return NULL;
271 	}
272 
273 	return (const char *)fdt_getprop(fdt, node, "model", NULL);
274 }
275 
276 /*******************************************************************************
277  * This function gets the pin count for a GPIO bank based from the FDT.
278  * It also checks node consistency.
279  ******************************************************************************/
280 int fdt_get_gpio_bank_pin_count(unsigned int bank)
281 {
282 	int pinctrl_node;
283 	int node;
284 	uint32_t bank_offset;
285 
286 	pinctrl_node = stm32_get_gpio_bank_pinctrl_node(fdt, bank);
287 	if (pinctrl_node < 0) {
288 		return -FDT_ERR_NOTFOUND;
289 	}
290 
291 	bank_offset = stm32_get_gpio_bank_offset(bank);
292 
293 	fdt_for_each_subnode(node, fdt, pinctrl_node) {
294 		const fdt32_t *cuint;
295 
296 		if (fdt_getprop(fdt, node, "gpio-controller", NULL) == NULL) {
297 			continue;
298 		}
299 
300 		cuint = fdt_getprop(fdt, node, "reg", NULL);
301 		if (cuint == NULL) {
302 			continue;
303 		}
304 
305 		if (fdt32_to_cpu(*cuint) != bank_offset) {
306 			continue;
307 		}
308 
309 		if (fdt_get_status(node) == DT_DISABLED) {
310 			return 0;
311 		}
312 
313 		cuint = fdt_getprop(fdt, node, "ngpios", NULL);
314 		if (cuint == NULL) {
315 			return -FDT_ERR_NOTFOUND;
316 		}
317 
318 		return (int)fdt32_to_cpu(*cuint);
319 	}
320 
321 	return 0;
322 }
323