xref: /rk3399_ARM-atf/plat/st/common/stm32mp_dt.c (revision ccc199eddaa6f5545e5c375be258b6ba686205ff)
1c9d75b3cSYann Gautier /*
2cd4941deSYann Gautier  * Copyright (c) 2017-2020, 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>
1552a616b4SAndre Przywara #include <common/fdt_wrappers.h>
16c9d75b3cSYann Gautier #include <drivers/st/stm32_gpio.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 
243f9c9784SYann 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 
96cd4941deSYann Gautier #if ENABLE_ASSERTIONS
97c9d75b3cSYann Gautier /*******************************************************************************
98dd85e572SLionel Debieve  * This function returns the address cells from the node parent.
99dd85e572SLionel Debieve  * Returns:
100dd85e572SLionel Debieve  * - #address-cells value if success.
101dd85e572SLionel Debieve  * - invalid value if error.
102dd85e572SLionel Debieve  * - a default value if undefined #address-cells property as per libfdt
103dd85e572SLionel Debieve  *   implementation.
104dd85e572SLionel Debieve  ******************************************************************************/
105cd4941deSYann Gautier static int fdt_get_node_parent_address_cells(int node)
106dd85e572SLionel Debieve {
107dd85e572SLionel Debieve 	int parent;
108dd85e572SLionel Debieve 
109dd85e572SLionel Debieve 	parent = fdt_parent_offset(fdt, node);
110dd85e572SLionel Debieve 	if (parent < 0) {
111dd85e572SLionel Debieve 		return -FDT_ERR_NOTFOUND;
112dd85e572SLionel Debieve 	}
113dd85e572SLionel Debieve 
114dd85e572SLionel Debieve 	return fdt_address_cells(fdt, parent);
115dd85e572SLionel Debieve }
116dd85e572SLionel Debieve 
117dd85e572SLionel Debieve /*******************************************************************************
118dd85e572SLionel Debieve  * This function returns the size cells from the node parent.
119dd85e572SLionel Debieve  * Returns:
120dd85e572SLionel Debieve  * - #size-cells value if success.
121dd85e572SLionel Debieve  * - invalid value if error.
122dd85e572SLionel Debieve  * - a default value if undefined #size-cells property as per libfdt
123dd85e572SLionel Debieve  *   implementation.
124dd85e572SLionel Debieve  ******************************************************************************/
125cd4941deSYann Gautier static int fdt_get_node_parent_size_cells(int node)
126dd85e572SLionel Debieve {
127dd85e572SLionel Debieve 	int parent;
128dd85e572SLionel Debieve 
129dd85e572SLionel Debieve 	parent = fdt_parent_offset(fdt, node);
130dd85e572SLionel Debieve 	if (parent < 0) {
131dd85e572SLionel Debieve 		return -FDT_ERR_NOTFOUND;
132dd85e572SLionel Debieve 	}
133dd85e572SLionel Debieve 
134dd85e572SLionel Debieve 	return fdt_size_cells(fdt, parent);
135dd85e572SLionel Debieve }
136cd4941deSYann Gautier #endif
137dd85e572SLionel Debieve 
138dd85e572SLionel Debieve /*******************************************************************************
139c9d75b3cSYann Gautier  * This function gets the stdout pin configuration information from the DT.
140c9d75b3cSYann Gautier  * And then calls the sub-function to treat it and set GPIO registers.
141c9d75b3cSYann Gautier  * Returns 0 on success and a negative FDT error code on failure.
142c9d75b3cSYann Gautier  ******************************************************************************/
143c9d75b3cSYann Gautier int dt_set_stdout_pinctrl(void)
144c9d75b3cSYann Gautier {
145c9d75b3cSYann Gautier 	int node;
146c9d75b3cSYann Gautier 
1477a61114dSAndre Przywara 	node = fdt_get_stdout_node_offset(fdt);
148c9d75b3cSYann Gautier 	if (node < 0) {
149c9d75b3cSYann Gautier 		return -FDT_ERR_NOTFOUND;
150c9d75b3cSYann Gautier 	}
151c9d75b3cSYann Gautier 
152c9d75b3cSYann Gautier 	return dt_set_pinctrl_config(node);
153c9d75b3cSYann Gautier }
154c9d75b3cSYann Gautier 
155c9d75b3cSYann Gautier /*******************************************************************************
156c9d75b3cSYann Gautier  * This function fills the generic information from a given node.
157c9d75b3cSYann Gautier  ******************************************************************************/
158c9d75b3cSYann Gautier void dt_fill_device_info(struct dt_node_info *info, int node)
159c9d75b3cSYann Gautier {
160c9d75b3cSYann Gautier 	const fdt32_t *cuint;
161c9d75b3cSYann Gautier 
162dd85e572SLionel Debieve 	assert(fdt_get_node_parent_address_cells(node) == 1);
163dd85e572SLionel Debieve 
164c9d75b3cSYann Gautier 	cuint = fdt_getprop(fdt, node, "reg", NULL);
165c9d75b3cSYann Gautier 	if (cuint != NULL) {
166c9d75b3cSYann Gautier 		info->base = fdt32_to_cpu(*cuint);
167c9d75b3cSYann Gautier 	} else {
168c9d75b3cSYann Gautier 		info->base = 0;
169c9d75b3cSYann Gautier 	}
170c9d75b3cSYann Gautier 
171c9d75b3cSYann Gautier 	cuint = fdt_getprop(fdt, node, "clocks", NULL);
172c9d75b3cSYann Gautier 	if (cuint != NULL) {
173c9d75b3cSYann Gautier 		cuint++;
174c9d75b3cSYann Gautier 		info->clock = (int)fdt32_to_cpu(*cuint);
175c9d75b3cSYann Gautier 	} else {
176c9d75b3cSYann Gautier 		info->clock = -1;
177c9d75b3cSYann Gautier 	}
178c9d75b3cSYann Gautier 
179c9d75b3cSYann Gautier 	cuint = fdt_getprop(fdt, node, "resets", NULL);
180c9d75b3cSYann Gautier 	if (cuint != NULL) {
181c9d75b3cSYann Gautier 		cuint++;
182c9d75b3cSYann Gautier 		info->reset = (int)fdt32_to_cpu(*cuint);
183c9d75b3cSYann Gautier 	} else {
184c9d75b3cSYann Gautier 		info->reset = -1;
185c9d75b3cSYann Gautier 	}
186c9d75b3cSYann Gautier 
187c9d75b3cSYann Gautier 	info->status = fdt_get_status(node);
188c9d75b3cSYann Gautier }
189c9d75b3cSYann Gautier 
190c9d75b3cSYann Gautier /*******************************************************************************
191c9d75b3cSYann Gautier  * This function retrieve the generic information from DT.
192c9d75b3cSYann Gautier  * Returns node on success and a negative FDT error code on failure.
193c9d75b3cSYann Gautier  ******************************************************************************/
194c9d75b3cSYann Gautier int dt_get_node(struct dt_node_info *info, int offset, const char *compat)
195c9d75b3cSYann Gautier {
196c9d75b3cSYann Gautier 	int node;
197c9d75b3cSYann Gautier 
198c9d75b3cSYann Gautier 	node = fdt_node_offset_by_compatible(fdt, offset, compat);
199c9d75b3cSYann Gautier 	if (node < 0) {
200c9d75b3cSYann Gautier 		return -FDT_ERR_NOTFOUND;
201c9d75b3cSYann Gautier 	}
202c9d75b3cSYann Gautier 
203c9d75b3cSYann Gautier 	dt_fill_device_info(info, node);
204c9d75b3cSYann Gautier 
205c9d75b3cSYann Gautier 	return node;
206c9d75b3cSYann Gautier }
207c9d75b3cSYann Gautier 
208c9d75b3cSYann Gautier /*******************************************************************************
209c9d75b3cSYann Gautier  * This function gets the UART instance info of stdout from the DT.
210c9d75b3cSYann Gautier  * Returns node on success and a negative FDT error code on failure.
211c9d75b3cSYann Gautier  ******************************************************************************/
212c9d75b3cSYann Gautier int dt_get_stdout_uart_info(struct dt_node_info *info)
213c9d75b3cSYann Gautier {
214c9d75b3cSYann Gautier 	int node;
215c9d75b3cSYann Gautier 
2167a61114dSAndre Przywara 	node = fdt_get_stdout_node_offset(fdt);
217c9d75b3cSYann Gautier 	if (node < 0) {
218c9d75b3cSYann Gautier 		return -FDT_ERR_NOTFOUND;
219c9d75b3cSYann Gautier 	}
220c9d75b3cSYann Gautier 
221c9d75b3cSYann Gautier 	dt_fill_device_info(info, node);
222c9d75b3cSYann Gautier 
223c9d75b3cSYann Gautier 	return node;
224c9d75b3cSYann Gautier }
225c9d75b3cSYann Gautier 
226c9d75b3cSYann Gautier /*******************************************************************************
227c9d75b3cSYann Gautier  * This function gets DDR size information from the DT.
228c9d75b3cSYann Gautier  * Returns value in bytes on success, and 0 on failure.
229c9d75b3cSYann Gautier  ******************************************************************************/
230c9d75b3cSYann Gautier uint32_t dt_get_ddr_size(void)
231c9d75b3cSYann Gautier {
232c9d75b3cSYann Gautier 	int node;
233c9d75b3cSYann Gautier 
234c9d75b3cSYann Gautier 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
235c9d75b3cSYann Gautier 	if (node < 0) {
236c9d75b3cSYann Gautier 		INFO("%s: Cannot read DDR node in DT\n", __func__);
237c9d75b3cSYann Gautier 		return 0;
238c9d75b3cSYann Gautier 	}
239c9d75b3cSYann Gautier 
240be858cffSAndre Przywara 	return fdt_read_uint32_default(fdt, node, "st,mem-size", 0);
241c9d75b3cSYann Gautier }
242c9d75b3cSYann Gautier 
243c9d75b3cSYann Gautier /*******************************************************************************
2447ae58c6bSYann Gautier  * This function gets DDRCTRL base address information from the DT.
2457ae58c6bSYann Gautier  * Returns value on success, and 0 on failure.
2467ae58c6bSYann Gautier  ******************************************************************************/
2477ae58c6bSYann Gautier uintptr_t dt_get_ddrctrl_base(void)
2487ae58c6bSYann Gautier {
2497ae58c6bSYann Gautier 	int node;
2507ae58c6bSYann Gautier 	uint32_t array[4];
2517ae58c6bSYann Gautier 
2527ae58c6bSYann Gautier 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
2537ae58c6bSYann Gautier 	if (node < 0) {
2547ae58c6bSYann Gautier 		INFO("%s: Cannot read DDR node in DT\n", __func__);
2557ae58c6bSYann Gautier 		return 0;
2567ae58c6bSYann Gautier 	}
2577ae58c6bSYann Gautier 
258dd85e572SLionel Debieve 	assert((fdt_get_node_parent_address_cells(node) == 1) &&
259dd85e572SLionel Debieve 	       (fdt_get_node_parent_size_cells(node) == 1));
260dd85e572SLionel Debieve 
26152a616b4SAndre Przywara 	if (fdt_read_uint32_array(fdt, node, "reg", 4, array) < 0) {
2627ae58c6bSYann Gautier 		return 0;
2637ae58c6bSYann Gautier 	}
2647ae58c6bSYann Gautier 
2657ae58c6bSYann Gautier 	return array[0];
2667ae58c6bSYann Gautier }
2677ae58c6bSYann Gautier 
2687ae58c6bSYann Gautier /*******************************************************************************
2697ae58c6bSYann Gautier  * This function gets DDRPHYC base address information from the DT.
2707ae58c6bSYann Gautier  * Returns value on success, and 0 on failure.
2717ae58c6bSYann Gautier  ******************************************************************************/
2727ae58c6bSYann Gautier uintptr_t dt_get_ddrphyc_base(void)
2737ae58c6bSYann Gautier {
2747ae58c6bSYann Gautier 	int node;
2757ae58c6bSYann Gautier 	uint32_t array[4];
2767ae58c6bSYann Gautier 
2777ae58c6bSYann Gautier 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
2787ae58c6bSYann Gautier 	if (node < 0) {
2797ae58c6bSYann Gautier 		INFO("%s: Cannot read DDR node in DT\n", __func__);
2807ae58c6bSYann Gautier 		return 0;
2817ae58c6bSYann Gautier 	}
2827ae58c6bSYann Gautier 
283dd85e572SLionel Debieve 	assert((fdt_get_node_parent_address_cells(node) == 1) &&
284dd85e572SLionel Debieve 	       (fdt_get_node_parent_size_cells(node) == 1));
285dd85e572SLionel Debieve 
28652a616b4SAndre Przywara 	if (fdt_read_uint32_array(fdt, node, "reg", 4, array) < 0) {
2877ae58c6bSYann Gautier 		return 0;
2887ae58c6bSYann Gautier 	}
2897ae58c6bSYann Gautier 
2907ae58c6bSYann Gautier 	return array[2];
2917ae58c6bSYann Gautier }
2927ae58c6bSYann Gautier 
2937ae58c6bSYann Gautier /*******************************************************************************
2947ae58c6bSYann Gautier  * This function gets PWR base address information from the DT.
2957ae58c6bSYann Gautier  * Returns value on success, and 0 on failure.
2967ae58c6bSYann Gautier  ******************************************************************************/
2977ae58c6bSYann Gautier uintptr_t dt_get_pwr_base(void)
2987ae58c6bSYann Gautier {
2997ae58c6bSYann Gautier 	int node;
3007ae58c6bSYann Gautier 	const fdt32_t *cuint;
3017ae58c6bSYann Gautier 
3027ae58c6bSYann Gautier 	node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
3037ae58c6bSYann Gautier 	if (node < 0) {
3047ae58c6bSYann Gautier 		INFO("%s: Cannot read PWR node in DT\n", __func__);
3057ae58c6bSYann Gautier 		return 0;
3067ae58c6bSYann Gautier 	}
3077ae58c6bSYann Gautier 
308dd85e572SLionel Debieve 	assert(fdt_get_node_parent_address_cells(node) == 1);
309dd85e572SLionel Debieve 
3107ae58c6bSYann Gautier 	cuint = fdt_getprop(fdt, node, "reg", NULL);
3117ae58c6bSYann Gautier 	if (cuint == NULL) {
3127ae58c6bSYann Gautier 		return 0;
3137ae58c6bSYann Gautier 	}
3147ae58c6bSYann Gautier 
3157ae58c6bSYann Gautier 	return fdt32_to_cpu(*cuint);
3167ae58c6bSYann Gautier }
3177ae58c6bSYann Gautier 
3187ae58c6bSYann Gautier /*******************************************************************************
319f33b2433SYann Gautier  * This function gets PWR VDD regulator voltage information from the DT.
320f33b2433SYann Gautier  * Returns value in microvolts on success, and 0 on failure.
321f33b2433SYann Gautier  ******************************************************************************/
322f33b2433SYann Gautier uint32_t dt_get_pwr_vdd_voltage(void)
323f33b2433SYann Gautier {
324f33b2433SYann Gautier 	int node, pwr_regulators_node;
325f33b2433SYann Gautier 	const fdt32_t *cuint;
326f33b2433SYann Gautier 
327f33b2433SYann Gautier 	node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT);
328f33b2433SYann Gautier 	if (node < 0) {
329f33b2433SYann Gautier 		INFO("%s: Cannot read PWR node in DT\n", __func__);
330f33b2433SYann Gautier 		return 0;
331f33b2433SYann Gautier 	}
332f33b2433SYann Gautier 
333f33b2433SYann Gautier 	pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators");
334e9d1e5afSYann Gautier 	if (pwr_regulators_node < 0) {
335f33b2433SYann Gautier 		INFO("%s: Cannot read pwr-regulators node in DT\n", __func__);
336f33b2433SYann Gautier 		return 0;
337f33b2433SYann Gautier 	}
338f33b2433SYann Gautier 
339f33b2433SYann Gautier 	cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL);
340f33b2433SYann Gautier 	if (cuint == NULL) {
341f33b2433SYann Gautier 		return 0;
342f33b2433SYann Gautier 	}
343f33b2433SYann Gautier 
344f33b2433SYann Gautier 	node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
345f33b2433SYann Gautier 	if (node < 0) {
346f33b2433SYann Gautier 		return 0;
347f33b2433SYann Gautier 	}
348f33b2433SYann Gautier 
349f33b2433SYann Gautier 	cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL);
350f33b2433SYann Gautier 	if (cuint == NULL) {
351f33b2433SYann Gautier 		return 0;
352f33b2433SYann Gautier 	}
353f33b2433SYann Gautier 
354f33b2433SYann Gautier 	return fdt32_to_cpu(*cuint);
355f33b2433SYann Gautier }
356f33b2433SYann Gautier 
357f33b2433SYann Gautier /*******************************************************************************
358f33b2433SYann Gautier  * This function gets SYSCFG base address information from the DT.
359f33b2433SYann Gautier  * Returns value on success, and 0 on failure.
360f33b2433SYann Gautier  ******************************************************************************/
361f33b2433SYann Gautier uintptr_t dt_get_syscfg_base(void)
362f33b2433SYann Gautier {
363f33b2433SYann Gautier 	int node;
364f33b2433SYann Gautier 	const fdt32_t *cuint;
365f33b2433SYann Gautier 
366f33b2433SYann Gautier 	node = fdt_node_offset_by_compatible(fdt, -1, DT_SYSCFG_COMPAT);
367f33b2433SYann Gautier 	if (node < 0) {
368f33b2433SYann Gautier 		INFO("%s: Cannot read SYSCFG node in DT\n", __func__);
369f33b2433SYann Gautier 		return 0;
370f33b2433SYann Gautier 	}
371f33b2433SYann Gautier 
372dd85e572SLionel Debieve 	assert(fdt_get_node_parent_address_cells(node) == 1);
373dd85e572SLionel Debieve 
374f33b2433SYann Gautier 	cuint = fdt_getprop(fdt, node, "reg", NULL);
375f33b2433SYann Gautier 	if (cuint == NULL) {
376f33b2433SYann Gautier 		return 0;
377f33b2433SYann Gautier 	}
378f33b2433SYann Gautier 
379f33b2433SYann Gautier 	return fdt32_to_cpu(*cuint);
380f33b2433SYann Gautier }
381f33b2433SYann Gautier 
382f33b2433SYann Gautier /*******************************************************************************
383c9d75b3cSYann Gautier  * This function retrieves board model from DT
384c9d75b3cSYann Gautier  * Returns string taken from model node, NULL otherwise
385c9d75b3cSYann Gautier  ******************************************************************************/
386c9d75b3cSYann Gautier const char *dt_get_board_model(void)
387c9d75b3cSYann Gautier {
388c9d75b3cSYann Gautier 	int node = fdt_path_offset(fdt, "/");
389c9d75b3cSYann Gautier 
390c9d75b3cSYann Gautier 	if (node < 0) {
391c9d75b3cSYann Gautier 		return NULL;
392c9d75b3cSYann Gautier 	}
393c9d75b3cSYann Gautier 
394c9d75b3cSYann Gautier 	return (const char *)fdt_getprop(fdt, node, "model", NULL);
395c9d75b3cSYann Gautier }
396*ccc199edSEtienne Carriere 
397*ccc199edSEtienne Carriere /*******************************************************************************
398*ccc199edSEtienne Carriere  * This function gets the pin count for a GPIO bank based from the FDT.
399*ccc199edSEtienne Carriere  * It also checks node consistency.
400*ccc199edSEtienne Carriere  ******************************************************************************/
401*ccc199edSEtienne Carriere int fdt_get_gpio_bank_pin_count(unsigned int bank)
402*ccc199edSEtienne Carriere {
403*ccc199edSEtienne Carriere 	int pinctrl_node;
404*ccc199edSEtienne Carriere 	int node;
405*ccc199edSEtienne Carriere 	uint32_t bank_offset;
406*ccc199edSEtienne Carriere 
407*ccc199edSEtienne Carriere 	pinctrl_node = stm32_get_gpio_bank_pinctrl_node(fdt, bank);
408*ccc199edSEtienne Carriere 	if (pinctrl_node < 0) {
409*ccc199edSEtienne Carriere 		return -FDT_ERR_NOTFOUND;
410*ccc199edSEtienne Carriere 	}
411*ccc199edSEtienne Carriere 
412*ccc199edSEtienne Carriere 	bank_offset = stm32_get_gpio_bank_offset(bank);
413*ccc199edSEtienne Carriere 
414*ccc199edSEtienne Carriere 	fdt_for_each_subnode(node, fdt, pinctrl_node) {
415*ccc199edSEtienne Carriere 		const fdt32_t *cuint;
416*ccc199edSEtienne Carriere 
417*ccc199edSEtienne Carriere 		if (fdt_getprop(fdt, node, "gpio-controller", NULL) == NULL) {
418*ccc199edSEtienne Carriere 			continue;
419*ccc199edSEtienne Carriere 		}
420*ccc199edSEtienne Carriere 
421*ccc199edSEtienne Carriere 		cuint = fdt_getprop(fdt, node, "reg", NULL);
422*ccc199edSEtienne Carriere 		if (cuint == NULL) {
423*ccc199edSEtienne Carriere 			continue;
424*ccc199edSEtienne Carriere 		}
425*ccc199edSEtienne Carriere 
426*ccc199edSEtienne Carriere 		if (fdt32_to_cpu(*cuint) != bank_offset) {
427*ccc199edSEtienne Carriere 			continue;
428*ccc199edSEtienne Carriere 		}
429*ccc199edSEtienne Carriere 
430*ccc199edSEtienne Carriere 		if (fdt_get_status(node) == DT_DISABLED) {
431*ccc199edSEtienne Carriere 			return 0;
432*ccc199edSEtienne Carriere 		}
433*ccc199edSEtienne Carriere 
434*ccc199edSEtienne Carriere 		cuint = fdt_getprop(fdt, node, "ngpios", NULL);
435*ccc199edSEtienne Carriere 		if (cuint == NULL) {
436*ccc199edSEtienne Carriere 			return -FDT_ERR_NOTFOUND;
437*ccc199edSEtienne Carriere 		}
438*ccc199edSEtienne Carriere 
439*ccc199edSEtienne Carriere 		return (int)fdt32_to_cpu(*cuint);
440*ccc199edSEtienne Carriere 	}
441*ccc199edSEtienne Carriere 
442*ccc199edSEtienne Carriere 	return 0;
443*ccc199edSEtienne Carriere }
444