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