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