1c9d75b3cSYann Gautier /* 2f714ca80SYann Gautier * Copyright (c) 2017-2021, 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 22c20b0606SYann Gautier static void *fdt; 23c9d75b3cSYann Gautier 24c9d75b3cSYann Gautier /******************************************************************************* 25c9d75b3cSYann Gautier * This function checks device tree file with its header. 26c9d75b3cSYann Gautier * Returns 0 on success and a negative FDT error code on failure. 27c9d75b3cSYann Gautier ******************************************************************************/ 28c20b0606SYann Gautier int dt_open_and_check(uintptr_t dt_addr) 29c9d75b3cSYann Gautier { 30c20b0606SYann Gautier int ret; 31c9d75b3cSYann Gautier 32c20b0606SYann Gautier ret = fdt_check_header((void *)dt_addr); 33c9d75b3cSYann Gautier if (ret == 0) { 34c20b0606SYann Gautier fdt = (void *)dt_addr; 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 { 47c20b0606SYann Gautier if (fdt == NULL) { 48c20b0606SYann Gautier return 0; 49c9d75b3cSYann Gautier } 50c9d75b3cSYann Gautier 51c20b0606SYann Gautier *fdt_addr = fdt; 52c20b0606SYann Gautier 53c20b0606SYann Gautier return 1; 54c9d75b3cSYann Gautier } 55c9d75b3cSYann Gautier 56c9d75b3cSYann Gautier /******************************************************************************* 57c9d75b3cSYann Gautier * This function check the presence of a node (generic use of fdt library). 58c9d75b3cSYann Gautier * Returns true if present, else return false. 59c9d75b3cSYann Gautier ******************************************************************************/ 60c9d75b3cSYann Gautier bool fdt_check_node(int node) 61c9d75b3cSYann Gautier { 62c9d75b3cSYann Gautier int len; 63c9d75b3cSYann Gautier const char *cchar; 64c9d75b3cSYann Gautier 65c9d75b3cSYann Gautier cchar = fdt_get_name(fdt, node, &len); 66c9d75b3cSYann Gautier 67c9d75b3cSYann Gautier return (cchar != NULL) && (len >= 0); 68c9d75b3cSYann Gautier } 69c9d75b3cSYann Gautier 70c9d75b3cSYann Gautier /******************************************************************************* 71c9d75b3cSYann Gautier * This function return global node status (generic use of fdt library). 72c9d75b3cSYann Gautier ******************************************************************************/ 73c9d75b3cSYann Gautier uint8_t fdt_get_status(int node) 74c9d75b3cSYann Gautier { 75c9d75b3cSYann Gautier uint8_t status = DT_DISABLED; 76c9d75b3cSYann Gautier const char *cchar; 77c9d75b3cSYann Gautier 78f714ca80SYann Gautier cchar = fdt_getprop(fdt, node, "status", NULL); 79c9d75b3cSYann Gautier if ((cchar == NULL) || 80f714ca80SYann Gautier (strncmp(cchar, "okay", strlen("okay")) == 0)) { 81c9d75b3cSYann Gautier status |= DT_NON_SECURE; 82c9d75b3cSYann Gautier } 83c9d75b3cSYann Gautier 84f714ca80SYann Gautier cchar = fdt_getprop(fdt, node, "secure-status", NULL); 85c9d75b3cSYann Gautier if (cchar == NULL) { 86c9d75b3cSYann Gautier if (status == DT_NON_SECURE) { 87c9d75b3cSYann Gautier status |= DT_SECURE; 88c9d75b3cSYann Gautier } 89f714ca80SYann Gautier } else if (strncmp(cchar, "okay", strlen("okay")) == 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 } 116cd4941deSYann Gautier #endif 117dd85e572SLionel Debieve 118dd85e572SLionel Debieve /******************************************************************************* 119c9d75b3cSYann Gautier * This function gets the stdout pin configuration information from the DT. 120c9d75b3cSYann Gautier * And then calls the sub-function to treat it and set GPIO registers. 121c9d75b3cSYann Gautier * Returns 0 on success and a negative FDT error code on failure. 122c9d75b3cSYann Gautier ******************************************************************************/ 123c9d75b3cSYann Gautier int dt_set_stdout_pinctrl(void) 124c9d75b3cSYann Gautier { 125c9d75b3cSYann Gautier int node; 126c9d75b3cSYann Gautier 1277a61114dSAndre Przywara node = fdt_get_stdout_node_offset(fdt); 128c9d75b3cSYann Gautier if (node < 0) { 129c9d75b3cSYann Gautier return -FDT_ERR_NOTFOUND; 130c9d75b3cSYann Gautier } 131c9d75b3cSYann Gautier 132c9d75b3cSYann Gautier return dt_set_pinctrl_config(node); 133c9d75b3cSYann Gautier } 134c9d75b3cSYann Gautier 135c9d75b3cSYann Gautier /******************************************************************************* 136c9d75b3cSYann Gautier * This function fills the generic information from a given node. 137c9d75b3cSYann Gautier ******************************************************************************/ 138c9d75b3cSYann Gautier void dt_fill_device_info(struct dt_node_info *info, int node) 139c9d75b3cSYann Gautier { 140c9d75b3cSYann Gautier const fdt32_t *cuint; 141c9d75b3cSYann Gautier 142dd85e572SLionel Debieve assert(fdt_get_node_parent_address_cells(node) == 1); 143dd85e572SLionel Debieve 144c9d75b3cSYann Gautier cuint = fdt_getprop(fdt, node, "reg", NULL); 145c9d75b3cSYann Gautier if (cuint != NULL) { 146c9d75b3cSYann Gautier info->base = fdt32_to_cpu(*cuint); 147c9d75b3cSYann Gautier } else { 148c9d75b3cSYann Gautier info->base = 0; 149c9d75b3cSYann Gautier } 150c9d75b3cSYann Gautier 151c9d75b3cSYann Gautier cuint = fdt_getprop(fdt, node, "clocks", NULL); 152c9d75b3cSYann Gautier if (cuint != NULL) { 153c9d75b3cSYann Gautier cuint++; 154c9d75b3cSYann Gautier info->clock = (int)fdt32_to_cpu(*cuint); 155c9d75b3cSYann Gautier } else { 156c9d75b3cSYann Gautier info->clock = -1; 157c9d75b3cSYann Gautier } 158c9d75b3cSYann Gautier 159c9d75b3cSYann Gautier cuint = fdt_getprop(fdt, node, "resets", NULL); 160c9d75b3cSYann Gautier if (cuint != NULL) { 161c9d75b3cSYann Gautier cuint++; 162c9d75b3cSYann Gautier info->reset = (int)fdt32_to_cpu(*cuint); 163c9d75b3cSYann Gautier } else { 164c9d75b3cSYann Gautier info->reset = -1; 165c9d75b3cSYann Gautier } 166c9d75b3cSYann Gautier 167c9d75b3cSYann Gautier info->status = fdt_get_status(node); 168c9d75b3cSYann Gautier } 169c9d75b3cSYann Gautier 170c9d75b3cSYann Gautier /******************************************************************************* 171c9d75b3cSYann Gautier * This function retrieve the generic information from DT. 172c9d75b3cSYann Gautier * Returns node on success and a negative FDT error code on failure. 173c9d75b3cSYann Gautier ******************************************************************************/ 174c9d75b3cSYann Gautier int dt_get_node(struct dt_node_info *info, int offset, const char *compat) 175c9d75b3cSYann Gautier { 176c9d75b3cSYann Gautier int node; 177c9d75b3cSYann Gautier 178c9d75b3cSYann Gautier node = fdt_node_offset_by_compatible(fdt, offset, compat); 179c9d75b3cSYann Gautier if (node < 0) { 180c9d75b3cSYann Gautier return -FDT_ERR_NOTFOUND; 181c9d75b3cSYann Gautier } 182c9d75b3cSYann Gautier 183c9d75b3cSYann Gautier dt_fill_device_info(info, node); 184c9d75b3cSYann Gautier 185c9d75b3cSYann Gautier return node; 186c9d75b3cSYann Gautier } 187c9d75b3cSYann Gautier 188c9d75b3cSYann Gautier /******************************************************************************* 189c9d75b3cSYann Gautier * This function gets the UART instance info of stdout from the DT. 190c9d75b3cSYann Gautier * Returns node on success and a negative FDT error code on failure. 191c9d75b3cSYann Gautier ******************************************************************************/ 192c9d75b3cSYann Gautier int dt_get_stdout_uart_info(struct dt_node_info *info) 193c9d75b3cSYann Gautier { 194c9d75b3cSYann Gautier int node; 195c9d75b3cSYann Gautier 1967a61114dSAndre Przywara node = fdt_get_stdout_node_offset(fdt); 197c9d75b3cSYann Gautier if (node < 0) { 198c9d75b3cSYann Gautier return -FDT_ERR_NOTFOUND; 199c9d75b3cSYann Gautier } 200c9d75b3cSYann Gautier 201c9d75b3cSYann Gautier dt_fill_device_info(info, node); 202c9d75b3cSYann Gautier 203c9d75b3cSYann Gautier return node; 204c9d75b3cSYann Gautier } 205c9d75b3cSYann Gautier 206c9d75b3cSYann Gautier /******************************************************************************* 207*ea97bbf6SYann Gautier * This function returns the node offset matching compatible string in the DT, 208*ea97bbf6SYann Gautier * and also matching the reg property with the given address. 209*ea97bbf6SYann Gautier * Returns value on success, and error value on failure. 210*ea97bbf6SYann Gautier ******************************************************************************/ 211*ea97bbf6SYann Gautier int dt_match_instance_by_compatible(const char *compatible, uintptr_t address) 212*ea97bbf6SYann Gautier { 213*ea97bbf6SYann Gautier int node; 214*ea97bbf6SYann Gautier 215*ea97bbf6SYann Gautier fdt_for_each_compatible_node(fdt, node, compatible) { 216*ea97bbf6SYann Gautier const fdt32_t *cuint; 217*ea97bbf6SYann Gautier 218*ea97bbf6SYann Gautier assert(fdt_get_node_parent_address_cells(node) == 1); 219*ea97bbf6SYann Gautier 220*ea97bbf6SYann Gautier cuint = fdt_getprop(fdt, node, "reg", NULL); 221*ea97bbf6SYann Gautier if (cuint == NULL) { 222*ea97bbf6SYann Gautier continue; 223*ea97bbf6SYann Gautier } 224*ea97bbf6SYann Gautier 225*ea97bbf6SYann Gautier if ((uintptr_t)fdt32_to_cpu(*cuint) == address) { 226*ea97bbf6SYann Gautier return node; 227*ea97bbf6SYann Gautier } 228*ea97bbf6SYann Gautier } 229*ea97bbf6SYann Gautier 230*ea97bbf6SYann Gautier return -FDT_ERR_NOTFOUND; 231*ea97bbf6SYann Gautier } 232*ea97bbf6SYann Gautier 233*ea97bbf6SYann Gautier /******************************************************************************* 234c9d75b3cSYann Gautier * This function gets DDR size information from the DT. 235c9d75b3cSYann Gautier * Returns value in bytes on success, and 0 on failure. 236c9d75b3cSYann Gautier ******************************************************************************/ 237c9d75b3cSYann Gautier uint32_t dt_get_ddr_size(void) 238c9d75b3cSYann Gautier { 23991ffc1deSLionel Debieve static uint32_t size; 240c9d75b3cSYann Gautier int node; 241c9d75b3cSYann Gautier 24291ffc1deSLionel Debieve if (size != 0U) { 24391ffc1deSLionel Debieve return size; 24491ffc1deSLionel Debieve } 24591ffc1deSLionel Debieve 246c9d75b3cSYann Gautier node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); 247c9d75b3cSYann Gautier if (node < 0) { 248c9d75b3cSYann Gautier INFO("%s: Cannot read DDR node in DT\n", __func__); 249c9d75b3cSYann Gautier return 0; 250c9d75b3cSYann Gautier } 251c9d75b3cSYann Gautier 25291ffc1deSLionel Debieve size = fdt_read_uint32_default(fdt, node, "st,mem-size", 0U); 25391ffc1deSLionel Debieve 25491ffc1deSLionel Debieve flush_dcache_range((uintptr_t)&size, sizeof(uint32_t)); 25591ffc1deSLionel Debieve 25691ffc1deSLionel Debieve return size; 257c9d75b3cSYann Gautier } 258c9d75b3cSYann Gautier 259c9d75b3cSYann Gautier /******************************************************************************* 260f33b2433SYann Gautier * This function gets PWR VDD regulator voltage information from the DT. 261f33b2433SYann Gautier * Returns value in microvolts on success, and 0 on failure. 262f33b2433SYann Gautier ******************************************************************************/ 263f33b2433SYann Gautier uint32_t dt_get_pwr_vdd_voltage(void) 264f33b2433SYann Gautier { 265f33b2433SYann Gautier int node, pwr_regulators_node; 266f33b2433SYann Gautier const fdt32_t *cuint; 267f33b2433SYann Gautier 268f33b2433SYann Gautier node = fdt_node_offset_by_compatible(fdt, -1, DT_PWR_COMPAT); 269f33b2433SYann Gautier if (node < 0) { 270f33b2433SYann Gautier INFO("%s: Cannot read PWR node in DT\n", __func__); 271f33b2433SYann Gautier return 0; 272f33b2433SYann Gautier } 273f33b2433SYann Gautier 274f33b2433SYann Gautier pwr_regulators_node = fdt_subnode_offset(fdt, node, "pwr-regulators"); 275e9d1e5afSYann Gautier if (pwr_regulators_node < 0) { 276f33b2433SYann Gautier INFO("%s: Cannot read pwr-regulators node in DT\n", __func__); 277f33b2433SYann Gautier return 0; 278f33b2433SYann Gautier } 279f33b2433SYann Gautier 280f33b2433SYann Gautier cuint = fdt_getprop(fdt, pwr_regulators_node, "vdd-supply", NULL); 281f33b2433SYann Gautier if (cuint == NULL) { 282f33b2433SYann Gautier return 0; 283f33b2433SYann Gautier } 284f33b2433SYann Gautier 285f33b2433SYann Gautier node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); 286f33b2433SYann Gautier if (node < 0) { 287f33b2433SYann Gautier return 0; 288f33b2433SYann Gautier } 289f33b2433SYann Gautier 290f33b2433SYann Gautier cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); 291f33b2433SYann Gautier if (cuint == NULL) { 292f33b2433SYann Gautier return 0; 293f33b2433SYann Gautier } 294f33b2433SYann Gautier 295f33b2433SYann Gautier return fdt32_to_cpu(*cuint); 296f33b2433SYann Gautier } 297f33b2433SYann Gautier 298f33b2433SYann Gautier /******************************************************************************* 299c9d75b3cSYann Gautier * This function retrieves board model from DT 300c9d75b3cSYann Gautier * Returns string taken from model node, NULL otherwise 301c9d75b3cSYann Gautier ******************************************************************************/ 302c9d75b3cSYann Gautier const char *dt_get_board_model(void) 303c9d75b3cSYann Gautier { 304c9d75b3cSYann Gautier int node = fdt_path_offset(fdt, "/"); 305c9d75b3cSYann Gautier 306c9d75b3cSYann Gautier if (node < 0) { 307c9d75b3cSYann Gautier return NULL; 308c9d75b3cSYann Gautier } 309c9d75b3cSYann Gautier 310c9d75b3cSYann Gautier return (const char *)fdt_getprop(fdt, node, "model", NULL); 311c9d75b3cSYann Gautier } 312ccc199edSEtienne Carriere 313ccc199edSEtienne Carriere /******************************************************************************* 314ccc199edSEtienne Carriere * This function gets the pin count for a GPIO bank based from the FDT. 315ccc199edSEtienne Carriere * It also checks node consistency. 316ccc199edSEtienne Carriere ******************************************************************************/ 317ccc199edSEtienne Carriere int fdt_get_gpio_bank_pin_count(unsigned int bank) 318ccc199edSEtienne Carriere { 319ccc199edSEtienne Carriere int pinctrl_node; 320ccc199edSEtienne Carriere int node; 321ccc199edSEtienne Carriere uint32_t bank_offset; 322ccc199edSEtienne Carriere 323ccc199edSEtienne Carriere pinctrl_node = stm32_get_gpio_bank_pinctrl_node(fdt, bank); 324ccc199edSEtienne Carriere if (pinctrl_node < 0) { 325ccc199edSEtienne Carriere return -FDT_ERR_NOTFOUND; 326ccc199edSEtienne Carriere } 327ccc199edSEtienne Carriere 328ccc199edSEtienne Carriere bank_offset = stm32_get_gpio_bank_offset(bank); 329ccc199edSEtienne Carriere 330ccc199edSEtienne Carriere fdt_for_each_subnode(node, fdt, pinctrl_node) { 331ccc199edSEtienne Carriere const fdt32_t *cuint; 332ccc199edSEtienne Carriere 333ccc199edSEtienne Carriere if (fdt_getprop(fdt, node, "gpio-controller", NULL) == NULL) { 334ccc199edSEtienne Carriere continue; 335ccc199edSEtienne Carriere } 336ccc199edSEtienne Carriere 337ccc199edSEtienne Carriere cuint = fdt_getprop(fdt, node, "reg", NULL); 338ccc199edSEtienne Carriere if (cuint == NULL) { 339ccc199edSEtienne Carriere continue; 340ccc199edSEtienne Carriere } 341ccc199edSEtienne Carriere 342ccc199edSEtienne Carriere if (fdt32_to_cpu(*cuint) != bank_offset) { 343ccc199edSEtienne Carriere continue; 344ccc199edSEtienne Carriere } 345ccc199edSEtienne Carriere 346ccc199edSEtienne Carriere if (fdt_get_status(node) == DT_DISABLED) { 347ccc199edSEtienne Carriere return 0; 348ccc199edSEtienne Carriere } 349ccc199edSEtienne Carriere 350ccc199edSEtienne Carriere cuint = fdt_getprop(fdt, node, "ngpios", NULL); 351ccc199edSEtienne Carriere if (cuint == NULL) { 352ccc199edSEtienne Carriere return -FDT_ERR_NOTFOUND; 353ccc199edSEtienne Carriere } 354ccc199edSEtienne Carriere 355ccc199edSEtienne Carriere return (int)fdt32_to_cpu(*cuint); 356ccc199edSEtienne Carriere } 357ccc199edSEtienne Carriere 358ccc199edSEtienne Carriere return 0; 359ccc199edSEtienne Carriere } 360