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