2 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
11 #include <platform_def.h>
13 #include <common/debug.h>
14 #include <drivers/st/stm32_gpio.h>
15 #include <drivers/st/stm32mp1_clk.h>
16 #include <drivers/st/stm32mp1_clkfunc.h>
17 #include <drivers/st/stm32mp1_ddr.h>
18 #include <drivers/st/stm32mp1_ram.h>
20 #include <stm32mp1_dt.h>
22 #define DT_GPIO_BANK_SHIFT 12
23 #define DT_GPIO_BANK_MASK 0x1F000U
24 #define DT_GPIO_PIN_SHIFT 8
25 #define DT_GPIO_PIN_MASK 0xF00U
26 #define DT_GPIO_MODE_MASK 0xFFU
28 static int fdt_checked
;
30 static void *fdt
= (void *)(uintptr_t)STM32MP1_DTB_BASE
;
32 /*******************************************************************************
33 * This function gets the pin settings from DT information.
34 * When analyze and parsing is done, set the GPIO registers.
35 * Return 0 on success, else return a negative FDT_ERR_xxx error code.
36 ******************************************************************************/
37 static int dt_set_gpio_config(int node
)
39 const fdt32_t
*cuint
, *slewrate
;
40 int len
, pinctrl_node
, pinctrl_subnode
;
42 uint32_t speed
= GPIO_SPEED_LOW
;
43 uint32_t pull
= GPIO_NO_PULL
;
45 cuint
= fdt_getprop(fdt
, node
, "pinmux", &len
);
47 return -FDT_ERR_NOTFOUND
;
50 pinctrl_node
= fdt_parent_offset(fdt
, fdt_parent_offset(fdt
, node
));
51 if (pinctrl_node
< 0) {
52 return -FDT_ERR_NOTFOUND
;
55 slewrate
= fdt_getprop(fdt
, node
, "slew-rate", NULL
);
56 if (slewrate
!= NULL
) {
57 speed
= fdt32_to_cpu(*slewrate
);
60 if (fdt_getprop(fdt
, node
, "bias-pull-up", NULL
) != NULL
) {
62 } else if (fdt_getprop(fdt
, node
, "bias-pull-down", NULL
) != NULL
) {
63 pull
= GPIO_PULL_DOWN
;
65 VERBOSE("No bias configured in node %d\n", node
);
68 for (i
= 0; i
< ((uint32_t)len
/ sizeof(uint32_t)); i
++) {
73 uint32_t alternate
= GPIO_ALTERNATE_0
;
75 pincfg
= fdt32_to_cpu(*cuint
);
78 bank
= (pincfg
& DT_GPIO_BANK_MASK
) >> DT_GPIO_BANK_SHIFT
;
80 pin
= (pincfg
& DT_GPIO_PIN_MASK
) >> DT_GPIO_PIN_SHIFT
;
82 mode
= pincfg
& DT_GPIO_MODE_MASK
;
86 mode
= GPIO_MODE_INPUT
;
89 alternate
= mode
- 1U;
90 mode
= GPIO_MODE_ALTERNATE
;
93 mode
= GPIO_MODE_ANALOG
;
96 mode
= GPIO_MODE_OUTPUT
;
100 if (fdt_getprop(fdt
, node
, "drive-open-drain", NULL
) != NULL
) {
101 mode
|= GPIO_OPEN_DRAIN
;
104 fdt_for_each_subnode(pinctrl_subnode
, fdt
, pinctrl_node
) {
105 uint32_t bank_offset
;
106 const fdt32_t
*cuint2
;
108 if (fdt_getprop(fdt
, pinctrl_subnode
,
109 "gpio-controller", NULL
) == NULL
) {
113 cuint2
= fdt_getprop(fdt
, pinctrl_subnode
, "reg", NULL
);
114 if (cuint2
== NULL
) {
118 if (bank
== GPIO_BANK_Z
) {
121 bank_offset
= bank
* STM32_GPIO_BANK_OFFSET
;
124 if (fdt32_to_cpu(*cuint2
) == bank_offset
) {
125 int clk_id
= fdt_get_clock_id(pinctrl_subnode
);
128 return -FDT_ERR_NOTFOUND
;
131 if (stm32mp1_clk_enable((unsigned long)clk_id
) <
133 return -FDT_ERR_BADVALUE
;
140 set_gpio(bank
, pin
, mode
, speed
, pull
, alternate
);
146 /*******************************************************************************
147 * This function checks device tree file with its header.
148 * Returns 0 if success, and a negative value else.
149 ******************************************************************************/
150 int dt_open_and_check(void)
152 int ret
= fdt_check_header(fdt
);
161 /*******************************************************************************
162 * This function gets the address of the DT.
163 * If DT is OK, fdt_addr is filled with DT address.
164 * Returns 1 if success, 0 otherwise.
165 ******************************************************************************/
166 int fdt_get_address(void **fdt_addr
)
168 if (fdt_checked
== 1) {
175 /*******************************************************************************
176 * This function check the presence of a node (generic use of fdt library).
177 * Returns true if present, false else.
178 ******************************************************************************/
179 bool fdt_check_node(int node
)
184 cchar
= fdt_get_name(fdt
, node
, &len
);
186 return (cchar
!= NULL
) && (len
>= 0);
189 /*******************************************************************************
190 * This function check the status of a node (generic use of fdt library).
191 * Returns true if "okay" or missing, false else.
192 ******************************************************************************/
193 bool fdt_check_status(int node
)
198 cchar
= fdt_getprop(fdt
, node
, "status", &len
);
203 return strncmp(cchar
, "okay", (size_t)len
) == 0;
206 /*******************************************************************************
207 * This function check the secure-status of a node (generic use of fdt library).
208 * Returns true if "okay" or missing, false else.
209 ******************************************************************************/
210 bool fdt_check_secure_status(int node
)
215 cchar
= fdt_getprop(fdt
, node
, "secure-status", &len
);
220 return strncmp(cchar
, "okay", (size_t)len
) == 0;
223 /*******************************************************************************
224 * This function reads a value of a node property (generic use of fdt
226 * Returns value if success, and a default value if property not found.
227 * Default value is passed as parameter.
228 ******************************************************************************/
229 uint32_t fdt_read_uint32_default(int node
, const char *prop_name
,
232 const fdt32_t
*cuint
;
235 cuint
= fdt_getprop(fdt
, node
, prop_name
, &lenp
);
240 return fdt32_to_cpu(*cuint
);
243 /*******************************************************************************
244 * This function reads a series of parameters in a node property
245 * (generic use of fdt library).
246 * It reads the values inside the device tree, from property name and node.
247 * The number of parameters is also indicated as entry parameter.
248 * Returns 0 if success, and a negative value else.
249 * If success, values are stored at the third parameter address.
250 ******************************************************************************/
251 int fdt_read_uint32_array(int node
, const char *prop_name
, uint32_t *array
,
254 const fdt32_t
*cuint
;
258 cuint
= fdt_getprop(fdt
, node
, prop_name
, &len
);
260 return -FDT_ERR_NOTFOUND
;
263 if ((uint32_t)len
!= (count
* sizeof(uint32_t))) {
264 return -FDT_ERR_BADLAYOUT
;
267 for (i
= 0; i
< ((uint32_t)len
/ sizeof(uint32_t)); i
++) {
268 *array
= fdt32_to_cpu(*cuint
);
276 /*******************************************************************************
277 * This function gets the pin settings from DT information.
278 * When analyze and parsing is done, set the GPIO registers.
279 * Returns 0 if success, and a negative value else.
280 ******************************************************************************/
281 int dt_set_pinctrl_config(int node
)
283 const fdt32_t
*cuint
;
287 if (!fdt_check_status(node
)) {
288 return -FDT_ERR_NOTFOUND
;
291 cuint
= fdt_getprop(fdt
, node
, "pinctrl-0", &lenp
);
293 return -FDT_ERR_NOTFOUND
;
296 for (i
= 0; i
< ((uint32_t)lenp
/ 4U); i
++) {
297 int phandle_node
, phandle_subnode
;
300 fdt_node_offset_by_phandle(fdt
, fdt32_to_cpu(*cuint
));
301 if (phandle_node
< 0) {
302 return -FDT_ERR_NOTFOUND
;
305 fdt_for_each_subnode(phandle_subnode
, fdt
, phandle_node
) {
306 int ret
= dt_set_gpio_config(phandle_subnode
);
319 /*******************************************************************************
320 * This function gets the stdout pin configuration information from the DT.
321 * And then calls the sub-function to treat it and set GPIO registers.
322 * Returns 0 if success, and a negative value else.
323 ******************************************************************************/
324 int dt_set_stdout_pinctrl(void)
328 node
= dt_get_stdout_node_offset();
330 return -FDT_ERR_NOTFOUND
;
333 return dt_set_pinctrl_config(node
);
336 /*******************************************************************************
337 * This function fills the generic information from a given node.
338 ******************************************************************************/
339 void dt_fill_device_info(struct dt_node_info
*info
, int node
)
341 const fdt32_t
*cuint
;
343 cuint
= fdt_getprop(fdt
, node
, "reg", NULL
);
345 info
->base
= fdt32_to_cpu(*cuint
);
350 cuint
= fdt_getprop(fdt
, node
, "clocks", NULL
);
353 info
->clock
= (int)fdt32_to_cpu(*cuint
);
358 cuint
= fdt_getprop(fdt
, node
, "resets", NULL
);
361 info
->reset
= (int)fdt32_to_cpu(*cuint
);
366 info
->status
= fdt_check_status(node
);
367 info
->sec_status
= fdt_check_secure_status(node
);
370 /*******************************************************************************
371 * This function retrieve the generic information from DT.
372 * Returns node if success, and a negative value else.
373 ******************************************************************************/
374 int dt_get_node(struct dt_node_info
*info
, int offset
, const char *compat
)
378 node
= fdt_node_offset_by_compatible(fdt
, offset
, compat
);
380 return -FDT_ERR_NOTFOUND
;
383 dt_fill_device_info(info
, node
);
388 /*******************************************************************************
389 * This function gets the UART instance info of stdout from the DT.
390 * Returns node if success, and a negative value else.
391 ******************************************************************************/
392 int dt_get_stdout_uart_info(struct dt_node_info
*info
)
396 node
= dt_get_stdout_node_offset();
398 return -FDT_ERR_NOTFOUND
;
401 dt_fill_device_info(info
, node
);
406 /*******************************************************************************
407 * This function gets the stdout path node.
408 * It reads the value indicated inside the device tree.
409 * Returns node if success, and a negative value else.
410 ******************************************************************************/
411 int dt_get_stdout_node_offset(void)
416 node
= fdt_path_offset(fdt
, "/chosen");
418 return -FDT_ERR_NOTFOUND
;
421 cchar
= fdt_getprop(fdt
, node
, "stdout-path", NULL
);
423 return -FDT_ERR_NOTFOUND
;
426 node
= -FDT_ERR_NOTFOUND
;
427 if (strchr(cchar
, (int)':') != NULL
) {
429 char *str
= (char *)cchar
;
432 while (strncmp(":", str
, 1)) {
437 name
= fdt_get_alias_namelen(fdt
, cchar
, len
);
440 node
= fdt_path_offset(fdt
, name
);
443 node
= fdt_path_offset(fdt
, cchar
);
449 /*******************************************************************************
450 * This function gets DDR size information from the DT.
451 * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else.
452 ******************************************************************************/
453 uint32_t dt_get_ddr_size(void)
457 node
= fdt_node_offset_by_compatible(fdt
, -1, DT_DDR_COMPAT
);
459 INFO("%s: Cannot read DDR node in DT\n", __func__
);
460 return STM32MP1_DDR_SIZE_DFLT
;
463 return fdt_read_uint32_default(node
, "st,mem-size",
464 STM32MP1_DDR_SIZE_DFLT
);
467 /*******************************************************************************
468 * This function retrieves board model from DT
469 * Returns string taken from model node, NULL otherwise
470 ******************************************************************************/
471 const char *dt_get_board_model(void)
473 int node
= fdt_path_offset(fdt
, "/");
479 return (const char *)fdt_getprop(fdt
, node
, "model", NULL
);