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