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