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