19e512045SSimon Glass /* 29e512045SSimon Glass * Copyright (c) 2017 Google, Inc 39e512045SSimon Glass * Written by Simon Glass <sjg@chromium.org> 49e512045SSimon Glass * 59e512045SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 69e512045SSimon Glass */ 79e512045SSimon Glass 89e512045SSimon Glass #include <common.h> 99e512045SSimon Glass #include <dm.h> 109e512045SSimon Glass #include <fdtdec.h> 119e512045SSimon Glass #include <fdt_support.h> 120e00a84cSMasahiro Yamada #include <linux/libfdt.h> 139e512045SSimon Glass #include <dm/of_access.h> 14bed77496SSimon Glass #include <dm/of_addr.h> 159e512045SSimon Glass #include <dm/ofnode.h> 169e512045SSimon Glass #include <linux/err.h> 17dcf98852SSimon Glass #include <linux/ioport.h> 189e512045SSimon Glass 199e512045SSimon Glass int ofnode_read_u32(ofnode node, const char *propname, u32 *outp) 209e512045SSimon Glass { 219e512045SSimon Glass assert(ofnode_valid(node)); 229e512045SSimon Glass debug("%s: %s: ", __func__, propname); 239e512045SSimon Glass 249e512045SSimon Glass if (ofnode_is_np(node)) { 259e512045SSimon Glass return of_read_u32(ofnode_to_np(node), propname, outp); 269e512045SSimon Glass } else { 278c9eaadaSMasahiro Yamada const fdt32_t *cell; 289e512045SSimon Glass int len; 299e512045SSimon Glass 309e512045SSimon Glass cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 319e512045SSimon Glass propname, &len); 329e512045SSimon Glass if (!cell || len < sizeof(int)) { 339e512045SSimon Glass debug("(not found)\n"); 349e512045SSimon Glass return -EINVAL; 359e512045SSimon Glass } 369e512045SSimon Glass *outp = fdt32_to_cpu(cell[0]); 379e512045SSimon Glass } 389e512045SSimon Glass debug("%#x (%d)\n", *outp, *outp); 399e512045SSimon Glass 409e512045SSimon Glass return 0; 419e512045SSimon Glass } 429e512045SSimon Glass 439e512045SSimon Glass int ofnode_read_u32_default(ofnode node, const char *propname, u32 def) 449e512045SSimon Glass { 459e512045SSimon Glass assert(ofnode_valid(node)); 469e512045SSimon Glass ofnode_read_u32(node, propname, &def); 479e512045SSimon Glass 489e512045SSimon Glass return def; 499e512045SSimon Glass } 509e512045SSimon Glass 519e512045SSimon Glass int ofnode_read_s32_default(ofnode node, const char *propname, s32 def) 529e512045SSimon Glass { 539e512045SSimon Glass assert(ofnode_valid(node)); 549e512045SSimon Glass ofnode_read_u32(node, propname, (u32 *)&def); 559e512045SSimon Glass 569e512045SSimon Glass return def; 579e512045SSimon Glass } 589e512045SSimon Glass 59d59cf5aeSJoseph Chen int ofnode_read_u64(ofnode node, const char *propname, u64 *outp) 60d59cf5aeSJoseph Chen { 61d59cf5aeSJoseph Chen assert(ofnode_valid(node)); 62d59cf5aeSJoseph Chen debug("%s: %s: ", __func__, propname); 63d59cf5aeSJoseph Chen 64d59cf5aeSJoseph Chen if (ofnode_is_np(node)) { 65d59cf5aeSJoseph Chen return of_property_read_u64(ofnode_to_np(node), propname, outp); 66d59cf5aeSJoseph Chen } else { 67d59cf5aeSJoseph Chen printf("%s: not implement\n", __func__); 68d59cf5aeSJoseph Chen return -EINVAL; 69d59cf5aeSJoseph Chen } 70d59cf5aeSJoseph Chen 71d59cf5aeSJoseph Chen return 0; 72d59cf5aeSJoseph Chen } 73d59cf5aeSJoseph Chen 749e512045SSimon Glass bool ofnode_read_bool(ofnode node, const char *propname) 759e512045SSimon Glass { 76b2ec7ea7SMasahiro Yamada const void *prop; 779e512045SSimon Glass 789e512045SSimon Glass assert(ofnode_valid(node)); 799e512045SSimon Glass debug("%s: %s: ", __func__, propname); 809e512045SSimon Glass 81b2ec7ea7SMasahiro Yamada prop = ofnode_get_property(node, propname, NULL); 829e512045SSimon Glass 83b2ec7ea7SMasahiro Yamada debug("%s\n", prop ? "true" : "false"); 84b2ec7ea7SMasahiro Yamada 85b2ec7ea7SMasahiro Yamada return prop ? true : false; 869e512045SSimon Glass } 879e512045SSimon Glass 889e512045SSimon Glass const char *ofnode_read_string(ofnode node, const char *propname) 899e512045SSimon Glass { 909e512045SSimon Glass const char *str = NULL; 919e512045SSimon Glass int len = -1; 929e512045SSimon Glass 939e512045SSimon Glass assert(ofnode_valid(node)); 949e512045SSimon Glass debug("%s: %s: ", __func__, propname); 959e512045SSimon Glass 969e512045SSimon Glass if (ofnode_is_np(node)) { 979e512045SSimon Glass struct property *prop = of_find_property( 989e512045SSimon Glass ofnode_to_np(node), propname, NULL); 999e512045SSimon Glass 1009e512045SSimon Glass if (prop) { 1019e512045SSimon Glass str = prop->value; 1029e512045SSimon Glass len = prop->length; 1039e512045SSimon Glass } 1049e512045SSimon Glass } else { 1059e512045SSimon Glass str = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 1069e512045SSimon Glass propname, &len); 1079e512045SSimon Glass } 1089e512045SSimon Glass if (!str) { 1099e512045SSimon Glass debug("<not found>\n"); 1109e512045SSimon Glass return NULL; 1119e512045SSimon Glass } 1129e512045SSimon Glass if (strnlen(str, len) >= len) { 1139e512045SSimon Glass debug("<invalid>\n"); 1149e512045SSimon Glass return NULL; 1159e512045SSimon Glass } 1169e512045SSimon Glass debug("%s\n", str); 1179e512045SSimon Glass 1189e512045SSimon Glass return str; 1199e512045SSimon Glass } 1209e512045SSimon Glass 1219e512045SSimon Glass ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) 1229e512045SSimon Glass { 1239e512045SSimon Glass ofnode subnode; 1249e512045SSimon Glass 1259e512045SSimon Glass assert(ofnode_valid(node)); 1269e512045SSimon Glass debug("%s: %s: ", __func__, subnode_name); 1279e512045SSimon Glass 1289e512045SSimon Glass if (ofnode_is_np(node)) { 1299e512045SSimon Glass const struct device_node *np = ofnode_to_np(node); 1309e512045SSimon Glass 1319e512045SSimon Glass for (np = np->child; np; np = np->sibling) { 1329e512045SSimon Glass if (!strcmp(subnode_name, np->name)) 1339e512045SSimon Glass break; 1349e512045SSimon Glass } 1359e512045SSimon Glass subnode = np_to_ofnode(np); 1369e512045SSimon Glass } else { 1379e512045SSimon Glass int ooffset = fdt_subnode_offset(gd->fdt_blob, 1389e512045SSimon Glass ofnode_to_offset(node), subnode_name); 1399e512045SSimon Glass subnode = offset_to_ofnode(ooffset); 1409e512045SSimon Glass } 1419e512045SSimon Glass debug("%s\n", ofnode_valid(subnode) ? 1429e512045SSimon Glass ofnode_get_name(subnode) : "<none>"); 1439e512045SSimon Glass 1449e512045SSimon Glass return subnode; 1459e512045SSimon Glass } 1469e512045SSimon Glass 1479e512045SSimon Glass int ofnode_read_u32_array(ofnode node, const char *propname, 1489e512045SSimon Glass u32 *out_values, size_t sz) 1499e512045SSimon Glass { 1509e512045SSimon Glass assert(ofnode_valid(node)); 1519e512045SSimon Glass debug("%s: %s: ", __func__, propname); 1529e512045SSimon Glass 1539e512045SSimon Glass if (ofnode_is_np(node)) { 1549e512045SSimon Glass return of_read_u32_array(ofnode_to_np(node), propname, 1559e512045SSimon Glass out_values, sz); 1569e512045SSimon Glass } else { 1579e512045SSimon Glass return fdtdec_get_int_array(gd->fdt_blob, 1589e512045SSimon Glass ofnode_to_offset(node), propname, 1599e512045SSimon Glass out_values, sz); 1609e512045SSimon Glass } 1619e512045SSimon Glass } 1629e512045SSimon Glass 16304539b46SJoseph Chen int ofnode_write_u32_array(ofnode node, const char *propname, 16404539b46SJoseph Chen u32 *values, size_t sz) 16504539b46SJoseph Chen { 16604539b46SJoseph Chen assert(ofnode_valid(node)); 16704539b46SJoseph Chen debug("%s: %s: ", __func__, propname); 16804539b46SJoseph Chen 16904539b46SJoseph Chen if (ofnode_is_np(node)) { 17004539b46SJoseph Chen return of_write_u32_array(ofnode_to_np(node), propname, 17104539b46SJoseph Chen values, sz); 17204539b46SJoseph Chen } else { 17304539b46SJoseph Chen return fdt_setprop((void *)gd->fdt_blob, ofnode_to_offset(node), 17404539b46SJoseph Chen propname, values, sz); 17504539b46SJoseph Chen } 17604539b46SJoseph Chen } 17704539b46SJoseph Chen 1789e512045SSimon Glass ofnode ofnode_first_subnode(ofnode node) 1799e512045SSimon Glass { 1809e512045SSimon Glass assert(ofnode_valid(node)); 1819e512045SSimon Glass if (ofnode_is_np(node)) 1829e512045SSimon Glass return np_to_ofnode(node.np->child); 1839e512045SSimon Glass 1849e512045SSimon Glass return offset_to_ofnode( 1859e512045SSimon Glass fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node))); 1869e512045SSimon Glass } 1879e512045SSimon Glass 1889e512045SSimon Glass ofnode ofnode_next_subnode(ofnode node) 1899e512045SSimon Glass { 1909e512045SSimon Glass assert(ofnode_valid(node)); 1919e512045SSimon Glass if (ofnode_is_np(node)) 1929e512045SSimon Glass return np_to_ofnode(node.np->sibling); 1939e512045SSimon Glass 1949e512045SSimon Glass return offset_to_ofnode( 1959e512045SSimon Glass fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node))); 1969e512045SSimon Glass } 1979e512045SSimon Glass 198e7ca7e39SPhilipp Tomsich ofnode ofnode_get_parent(ofnode node) 199e7ca7e39SPhilipp Tomsich { 200e7ca7e39SPhilipp Tomsich ofnode parent; 201e7ca7e39SPhilipp Tomsich 202e7ca7e39SPhilipp Tomsich assert(ofnode_valid(node)); 203e7ca7e39SPhilipp Tomsich if (ofnode_is_np(node)) 204e7ca7e39SPhilipp Tomsich parent = np_to_ofnode(of_get_parent(ofnode_to_np(node))); 205e7ca7e39SPhilipp Tomsich else 206e7ca7e39SPhilipp Tomsich parent.of_offset = fdt_parent_offset(gd->fdt_blob, 207e7ca7e39SPhilipp Tomsich ofnode_to_offset(node)); 208e7ca7e39SPhilipp Tomsich 209e7ca7e39SPhilipp Tomsich return parent; 210e7ca7e39SPhilipp Tomsich } 211e7ca7e39SPhilipp Tomsich 2129e512045SSimon Glass const char *ofnode_get_name(ofnode node) 2139e512045SSimon Glass { 214a49612a6SKever Yang if(!ofnode_valid(node)){ 215a49612a6SKever Yang debug("%s node not valid\n", __func__); 216a49612a6SKever Yang return NULL; 217a49612a6SKever Yang } 2189e512045SSimon Glass if (ofnode_is_np(node)) 2199e512045SSimon Glass return strrchr(node.np->full_name, '/') + 1; 2209e512045SSimon Glass 2219e512045SSimon Glass return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL); 2229e512045SSimon Glass } 2239e512045SSimon Glass 224df5ceb01SKever Yang ofnode ofnode_get_by_phandle(uint phandle) 225df5ceb01SKever Yang { 226df5ceb01SKever Yang ofnode node; 227df5ceb01SKever Yang 228df5ceb01SKever Yang if (of_live_active()) 229df5ceb01SKever Yang node = np_to_ofnode(of_find_node_by_phandle(phandle)); 230df5ceb01SKever Yang else 231df5ceb01SKever Yang node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob, 232df5ceb01SKever Yang phandle); 233df5ceb01SKever Yang 234df5ceb01SKever Yang return node; 235df5ceb01SKever Yang } 236df5ceb01SKever Yang 2379e512045SSimon Glass int ofnode_read_size(ofnode node, const char *propname) 2389e512045SSimon Glass { 2399e512045SSimon Glass int len; 2409e512045SSimon Glass 2419e512045SSimon Glass if (ofnode_is_np(node)) { 2429e512045SSimon Glass struct property *prop = of_find_property( 2439e512045SSimon Glass ofnode_to_np(node), propname, NULL); 2449e512045SSimon Glass 2459e512045SSimon Glass if (prop) 2469e512045SSimon Glass return prop->length; 2479e512045SSimon Glass } else { 2489e512045SSimon Glass if (fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, 2499e512045SSimon Glass &len)) 2509e512045SSimon Glass return len; 2519e512045SSimon Glass } 2529e512045SSimon Glass 2539e512045SSimon Glass return -EINVAL; 2549e512045SSimon Glass } 2559e512045SSimon Glass 256bed77496SSimon Glass fdt_addr_t ofnode_get_addr_index(ofnode node, int index) 257bed77496SSimon Glass { 258bed77496SSimon Glass if (ofnode_is_np(node)) { 259bed77496SSimon Glass const __be32 *prop_val; 260bed77496SSimon Glass uint flags; 261bed77496SSimon Glass u64 size; 2620f6507a7SSimon Glass int na; 263bed77496SSimon Glass 2640f6507a7SSimon Glass prop_val = of_get_address(ofnode_to_np(node), index, &size, 2650f6507a7SSimon Glass &flags); 266bed77496SSimon Glass if (!prop_val) 267bed77496SSimon Glass return FDT_ADDR_T_NONE; 2680f6507a7SSimon Glass na = of_n_addr_cells(ofnode_to_np(node)); 2690f6507a7SSimon Glass return of_read_number(prop_val, na); 270bed77496SSimon Glass } else { 271bed77496SSimon Glass return fdt_get_base_address(gd->fdt_blob, 272bed77496SSimon Glass ofnode_to_offset(node)); 273bed77496SSimon Glass } 274bed77496SSimon Glass 275bed77496SSimon Glass return FDT_ADDR_T_NONE; 276bed77496SSimon Glass } 277bed77496SSimon Glass 278bed77496SSimon Glass fdt_addr_t ofnode_get_addr(ofnode node) 279bed77496SSimon Glass { 280bed77496SSimon Glass return ofnode_get_addr_index(node, 0); 281bed77496SSimon Glass } 282bed77496SSimon Glass 2839e512045SSimon Glass int ofnode_stringlist_search(ofnode node, const char *property, 2849e512045SSimon Glass const char *string) 2859e512045SSimon Glass { 2869e512045SSimon Glass if (ofnode_is_np(node)) { 2879e512045SSimon Glass return of_property_match_string(ofnode_to_np(node), 2889e512045SSimon Glass property, string); 2899e512045SSimon Glass } else { 2909e512045SSimon Glass int ret; 2919e512045SSimon Glass 2929e512045SSimon Glass ret = fdt_stringlist_search(gd->fdt_blob, 2939e512045SSimon Glass ofnode_to_offset(node), property, 2949e512045SSimon Glass string); 2959e512045SSimon Glass if (ret == -FDT_ERR_NOTFOUND) 2969e512045SSimon Glass return -ENODATA; 2979e512045SSimon Glass else if (ret < 0) 2989e512045SSimon Glass return -EINVAL; 2999e512045SSimon Glass 3009e512045SSimon Glass return ret; 3019e512045SSimon Glass } 3029e512045SSimon Glass } 3039e512045SSimon Glass 3049e512045SSimon Glass int ofnode_read_string_index(ofnode node, const char *property, int index, 3059e512045SSimon Glass const char **outp) 3069e512045SSimon Glass { 3079e512045SSimon Glass if (ofnode_is_np(node)) { 3089e512045SSimon Glass return of_property_read_string_index(ofnode_to_np(node), 3099e512045SSimon Glass property, index, outp); 3109e512045SSimon Glass } else { 3119e512045SSimon Glass int len; 3129e512045SSimon Glass 3139e512045SSimon Glass *outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node), 3149e512045SSimon Glass property, index, &len); 3159e512045SSimon Glass if (len < 0) 3169e512045SSimon Glass return -EINVAL; 3179e512045SSimon Glass return 0; 3189e512045SSimon Glass } 3199e512045SSimon Glass } 3209e512045SSimon Glass 3218c293d6aSSimon Glass int ofnode_read_string_count(ofnode node, const char *property) 3228c293d6aSSimon Glass { 3238c293d6aSSimon Glass if (ofnode_is_np(node)) { 3248c293d6aSSimon Glass return of_property_count_strings(ofnode_to_np(node), property); 3258c293d6aSSimon Glass } else { 3268c293d6aSSimon Glass return fdt_stringlist_count(gd->fdt_blob, 3278c293d6aSSimon Glass ofnode_to_offset(node), property); 3288c293d6aSSimon Glass } 3298c293d6aSSimon Glass } 3308c293d6aSSimon Glass 3319e512045SSimon Glass static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in, 3329e512045SSimon Glass struct ofnode_phandle_args *out) 3339e512045SSimon Glass { 3349e512045SSimon Glass assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 3359e512045SSimon Glass out->node = offset_to_ofnode(in->node); 3369e512045SSimon Glass out->args_count = in->args_count; 3379e512045SSimon Glass memcpy(out->args, in->args, sizeof(out->args)); 3389e512045SSimon Glass } 3399e512045SSimon Glass 3409e512045SSimon Glass static void ofnode_from_of_phandle_args(struct of_phandle_args *in, 3419e512045SSimon Glass struct ofnode_phandle_args *out) 3429e512045SSimon Glass { 3439e512045SSimon Glass assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 3449e512045SSimon Glass out->node = np_to_ofnode(in->np); 3459e512045SSimon Glass out->args_count = in->args_count; 3469e512045SSimon Glass memcpy(out->args, in->args, sizeof(out->args)); 3479e512045SSimon Glass } 3489e512045SSimon Glass 3499e512045SSimon Glass int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, 3509e512045SSimon Glass const char *cells_name, int cell_count, 3519e512045SSimon Glass int index, 3529e512045SSimon Glass struct ofnode_phandle_args *out_args) 3539e512045SSimon Glass { 3549e512045SSimon Glass if (ofnode_is_np(node)) { 3559e512045SSimon Glass struct of_phandle_args args; 3569e512045SSimon Glass int ret; 3579e512045SSimon Glass 3589e512045SSimon Glass ret = of_parse_phandle_with_args(ofnode_to_np(node), 3599e512045SSimon Glass list_name, cells_name, index, &args); 3609e512045SSimon Glass if (ret) 3619e512045SSimon Glass return ret; 3629e512045SSimon Glass ofnode_from_of_phandle_args(&args, out_args); 3639e512045SSimon Glass } else { 3649e512045SSimon Glass struct fdtdec_phandle_args args; 3659e512045SSimon Glass int ret; 3669e512045SSimon Glass 3679e512045SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, 3689e512045SSimon Glass ofnode_to_offset(node), list_name, cells_name, 3699e512045SSimon Glass cell_count, index, &args); 3709e512045SSimon Glass if (ret) 3719e512045SSimon Glass return ret; 3729e512045SSimon Glass ofnode_from_fdtdec_phandle_args(&args, out_args); 3739e512045SSimon Glass } 3749e512045SSimon Glass 3759e512045SSimon Glass return 0; 3769e512045SSimon Glass } 3779e512045SSimon Glass 378642346aeSPatrice Chotard int ofnode_count_phandle_with_args(ofnode node, const char *list_name, 379642346aeSPatrice Chotard const char *cells_name) 380642346aeSPatrice Chotard { 381642346aeSPatrice Chotard if (ofnode_is_np(node)) 382642346aeSPatrice Chotard return of_count_phandle_with_args(ofnode_to_np(node), 383642346aeSPatrice Chotard list_name, cells_name); 384642346aeSPatrice Chotard else 385642346aeSPatrice Chotard return fdtdec_parse_phandle_with_args(gd->fdt_blob, 386642346aeSPatrice Chotard ofnode_to_offset(node), list_name, cells_name, 387642346aeSPatrice Chotard 0, -1, NULL); 388642346aeSPatrice Chotard } 389642346aeSPatrice Chotard 3909e512045SSimon Glass ofnode ofnode_path(const char *path) 3919e512045SSimon Glass { 3929e512045SSimon Glass if (of_live_active()) 3939e512045SSimon Glass return np_to_ofnode(of_find_node_by_path(path)); 3949e512045SSimon Glass else 3959e512045SSimon Glass return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path)); 3969e512045SSimon Glass } 3979e512045SSimon Glass 3989e512045SSimon Glass const char *ofnode_get_chosen_prop(const char *name) 3999e512045SSimon Glass { 4009e512045SSimon Glass ofnode chosen_node; 4019e512045SSimon Glass 4029e512045SSimon Glass chosen_node = ofnode_path("/chosen"); 4039e512045SSimon Glass 4049e512045SSimon Glass return ofnode_read_string(chosen_node, name); 4059e512045SSimon Glass } 4069e512045SSimon Glass 4079e512045SSimon Glass ofnode ofnode_get_chosen_node(const char *name) 4089e512045SSimon Glass { 4099e512045SSimon Glass const char *prop; 4109e512045SSimon Glass 4119e512045SSimon Glass prop = ofnode_get_chosen_prop(name); 4129e512045SSimon Glass if (!prop) 4139e512045SSimon Glass return ofnode_null(); 4149e512045SSimon Glass 4159e512045SSimon Glass return ofnode_path(prop); 4169e512045SSimon Glass } 4179e512045SSimon Glass 4189e512045SSimon Glass static int decode_timing_property(ofnode node, const char *name, 4199e512045SSimon Glass struct timing_entry *result) 4209e512045SSimon Glass { 4219e512045SSimon Glass int length, ret = 0; 4229e512045SSimon Glass 4239e512045SSimon Glass length = ofnode_read_size(node, name); 4249e512045SSimon Glass if (length < 0) { 4259e512045SSimon Glass debug("%s: could not find property %s\n", 4269e512045SSimon Glass ofnode_get_name(node), name); 4279e512045SSimon Glass return length; 4289e512045SSimon Glass } 4299e512045SSimon Glass 4309e512045SSimon Glass if (length == sizeof(u32)) { 4319e512045SSimon Glass result->typ = ofnode_read_u32_default(node, name, 0); 4329e512045SSimon Glass result->min = result->typ; 4339e512045SSimon Glass result->max = result->typ; 4349e512045SSimon Glass } else { 4359e512045SSimon Glass ret = ofnode_read_u32_array(node, name, &result->min, 3); 4369e512045SSimon Glass } 4379e512045SSimon Glass 4389e512045SSimon Glass return ret; 4399e512045SSimon Glass } 4409e512045SSimon Glass 4419e512045SSimon Glass int ofnode_decode_display_timing(ofnode parent, int index, 4429e512045SSimon Glass struct display_timing *dt) 4439e512045SSimon Glass { 4449e512045SSimon Glass int i; 4459e512045SSimon Glass ofnode timings, node; 4469e512045SSimon Glass u32 val = 0; 4479e512045SSimon Glass int ret = 0; 4489e512045SSimon Glass 4499e512045SSimon Glass timings = ofnode_find_subnode(parent, "display-timings"); 4509e512045SSimon Glass if (!ofnode_valid(timings)) 4519e512045SSimon Glass return -EINVAL; 4529e512045SSimon Glass 45317c82fdcSSimon Glass i = 0; 45417c82fdcSSimon Glass ofnode_for_each_subnode(node, timings) { 45517c82fdcSSimon Glass if (i++ == index) 45617c82fdcSSimon Glass break; 45717c82fdcSSimon Glass } 4589e512045SSimon Glass 4599e512045SSimon Glass if (!ofnode_valid(node)) 4609e512045SSimon Glass return -EINVAL; 4619e512045SSimon Glass 4629e512045SSimon Glass memset(dt, 0, sizeof(*dt)); 4639e512045SSimon Glass 4649e512045SSimon Glass ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch); 4659e512045SSimon Glass ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch); 4669e512045SSimon Glass ret |= decode_timing_property(node, "hactive", &dt->hactive); 4679e512045SSimon Glass ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len); 4689e512045SSimon Glass ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch); 4699e512045SSimon Glass ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch); 4709e512045SSimon Glass ret |= decode_timing_property(node, "vactive", &dt->vactive); 4719e512045SSimon Glass ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len); 4729e512045SSimon Glass ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock); 4739e512045SSimon Glass 4749e512045SSimon Glass dt->flags = 0; 4759e512045SSimon Glass val = ofnode_read_u32_default(node, "vsync-active", -1); 4769e512045SSimon Glass if (val != -1) { 4779e512045SSimon Glass dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : 4789e512045SSimon Glass DISPLAY_FLAGS_VSYNC_LOW; 4799e512045SSimon Glass } 4809e512045SSimon Glass val = ofnode_read_u32_default(node, "hsync-active", -1); 4819e512045SSimon Glass if (val != -1) { 4829e512045SSimon Glass dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : 4839e512045SSimon Glass DISPLAY_FLAGS_HSYNC_LOW; 4849e512045SSimon Glass } 4859e512045SSimon Glass val = ofnode_read_u32_default(node, "de-active", -1); 4869e512045SSimon Glass if (val != -1) { 4879e512045SSimon Glass dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : 4889e512045SSimon Glass DISPLAY_FLAGS_DE_LOW; 4899e512045SSimon Glass } 4909e512045SSimon Glass val = ofnode_read_u32_default(node, "pixelclk-active", -1); 4919e512045SSimon Glass if (val != -1) { 4929e512045SSimon Glass dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : 4939e512045SSimon Glass DISPLAY_FLAGS_PIXDATA_NEGEDGE; 4949e512045SSimon Glass } 4959e512045SSimon Glass 4969e512045SSimon Glass if (ofnode_read_bool(node, "interlaced")) 4979e512045SSimon Glass dt->flags |= DISPLAY_FLAGS_INTERLACED; 4989e512045SSimon Glass if (ofnode_read_bool(node, "doublescan")) 4999e512045SSimon Glass dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; 5009e512045SSimon Glass if (ofnode_read_bool(node, "doubleclk")) 5019e512045SSimon Glass dt->flags |= DISPLAY_FLAGS_DOUBLECLK; 5029e512045SSimon Glass 5039e512045SSimon Glass return ret; 5049e512045SSimon Glass } 5059e512045SSimon Glass 50661e51babSMasahiro Yamada const void *ofnode_get_property(ofnode node, const char *propname, int *lenp) 5079e512045SSimon Glass { 508cb7dbe1fSMasahiro Yamada if (ofnode_is_np(node)) 509cb7dbe1fSMasahiro Yamada return of_get_property(ofnode_to_np(node), propname, lenp); 510cb7dbe1fSMasahiro Yamada else 5119e512045SSimon Glass return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 5129e512045SSimon Glass propname, lenp); 5139e512045SSimon Glass } 5149e512045SSimon Glass 5159e512045SSimon Glass bool ofnode_is_available(ofnode node) 5169e512045SSimon Glass { 5179e512045SSimon Glass if (ofnode_is_np(node)) 5189e512045SSimon Glass return of_device_is_available(ofnode_to_np(node)); 5199e512045SSimon Glass else 5209e512045SSimon Glass return fdtdec_get_is_enabled(gd->fdt_blob, 5219e512045SSimon Glass ofnode_to_offset(node)); 5229e512045SSimon Glass } 5239e512045SSimon Glass 5249e512045SSimon Glass fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, 5259e512045SSimon Glass fdt_size_t *sizep) 5269e512045SSimon Glass { 5279e512045SSimon Glass if (ofnode_is_np(node)) { 5289e512045SSimon Glass int na, ns; 5299e512045SSimon Glass int psize; 5309e512045SSimon Glass const struct device_node *np = ofnode_to_np(node); 5311b189a92SKlaus Goger const __be32 *prop = of_get_property(np, property, &psize); 5329e512045SSimon Glass 5331b189a92SKlaus Goger if (!prop) 5341b189a92SKlaus Goger return FDT_ADDR_T_NONE; 5359e512045SSimon Glass na = of_n_addr_cells(np); 5369e512045SSimon Glass ns = of_n_addr_cells(np); 537a4b8e372SSimon Glass *sizep = of_read_number(prop + na, ns); 538a4b8e372SSimon Glass return of_read_number(prop, na); 5399e512045SSimon Glass } else { 5409e512045SSimon Glass return fdtdec_get_addr_size(gd->fdt_blob, 5419e512045SSimon Glass ofnode_to_offset(node), property, 5429e512045SSimon Glass sizep); 5439e512045SSimon Glass } 5449e512045SSimon Glass } 5459e512045SSimon Glass 5469e512045SSimon Glass const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, 5479e512045SSimon Glass size_t sz) 5489e512045SSimon Glass { 5499e512045SSimon Glass if (ofnode_is_np(node)) { 5509e512045SSimon Glass const struct device_node *np = ofnode_to_np(node); 5519e512045SSimon Glass int psize; 5529e512045SSimon Glass const __be32 *prop = of_get_property(np, propname, &psize); 5539e512045SSimon Glass 5549e512045SSimon Glass if (!prop || sz != psize) 5559e512045SSimon Glass return NULL; 5569e512045SSimon Glass return (uint8_t *)prop; 5579e512045SSimon Glass 5589e512045SSimon Glass } else { 5599e512045SSimon Glass return fdtdec_locate_byte_array(gd->fdt_blob, 5609e512045SSimon Glass ofnode_to_offset(node), propname, sz); 5619e512045SSimon Glass } 5629e512045SSimon Glass } 5639e512045SSimon Glass 5649e512045SSimon Glass int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, 5659e512045SSimon Glass const char *propname, struct fdt_pci_addr *addr) 5669e512045SSimon Glass { 5678c9eaadaSMasahiro Yamada const fdt32_t *cell; 5689e512045SSimon Glass int len; 5699e512045SSimon Glass int ret = -ENOENT; 5709e512045SSimon Glass 5719e512045SSimon Glass debug("%s: %s: ", __func__, propname); 5729e512045SSimon Glass 5739e512045SSimon Glass /* 5749e512045SSimon Glass * If we follow the pci bus bindings strictly, we should check 5759e512045SSimon Glass * the value of the node's parent node's #address-cells and 5769e512045SSimon Glass * #size-cells. They need to be 3 and 2 accordingly. However, 5779e512045SSimon Glass * for simplicity we skip the check here. 5789e512045SSimon Glass */ 57961e51babSMasahiro Yamada cell = ofnode_get_property(node, propname, &len); 5809e512045SSimon Glass if (!cell) 5819e512045SSimon Glass goto fail; 5829e512045SSimon Glass 5839e512045SSimon Glass if ((len % FDT_PCI_REG_SIZE) == 0) { 5849e512045SSimon Glass int num = len / FDT_PCI_REG_SIZE; 5859e512045SSimon Glass int i; 5869e512045SSimon Glass 5879e512045SSimon Glass for (i = 0; i < num; i++) { 5889e512045SSimon Glass debug("pci address #%d: %08lx %08lx %08lx\n", i, 5899e512045SSimon Glass (ulong)fdt32_to_cpu(cell[0]), 5909e512045SSimon Glass (ulong)fdt32_to_cpu(cell[1]), 5919e512045SSimon Glass (ulong)fdt32_to_cpu(cell[2])); 5929e512045SSimon Glass if ((fdt32_to_cpu(*cell) & type) == type) { 5939e512045SSimon Glass addr->phys_hi = fdt32_to_cpu(cell[0]); 5949e512045SSimon Glass addr->phys_mid = fdt32_to_cpu(cell[1]); 5959e512045SSimon Glass addr->phys_lo = fdt32_to_cpu(cell[1]); 5969e512045SSimon Glass break; 5979e512045SSimon Glass } else { 5989e512045SSimon Glass cell += (FDT_PCI_ADDR_CELLS + 5999e512045SSimon Glass FDT_PCI_SIZE_CELLS); 6009e512045SSimon Glass } 6019e512045SSimon Glass } 6029e512045SSimon Glass 6039e512045SSimon Glass if (i == num) { 6049e512045SSimon Glass ret = -ENXIO; 6059e512045SSimon Glass goto fail; 6069e512045SSimon Glass } 6079e512045SSimon Glass 6089e512045SSimon Glass return 0; 6099e512045SSimon Glass } else { 6109e512045SSimon Glass ret = -EINVAL; 6119e512045SSimon Glass } 6129e512045SSimon Glass 6139e512045SSimon Glass fail: 6149e512045SSimon Glass debug("(not found)\n"); 6159e512045SSimon Glass return ret; 6169e512045SSimon Glass } 6179e512045SSimon Glass 6189e512045SSimon Glass int ofnode_read_addr_cells(ofnode node) 6199e512045SSimon Glass { 6209e512045SSimon Glass if (ofnode_is_np(node)) 6219e512045SSimon Glass return of_n_addr_cells(ofnode_to_np(node)); 622878d68c0SSimon Glass else /* NOTE: this call should walk up the parent stack */ 6239e512045SSimon Glass return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); 6249e512045SSimon Glass } 6259e512045SSimon Glass 6269e512045SSimon Glass int ofnode_read_size_cells(ofnode node) 6279e512045SSimon Glass { 6289e512045SSimon Glass if (ofnode_is_np(node)) 6299e512045SSimon Glass return of_n_size_cells(ofnode_to_np(node)); 630878d68c0SSimon Glass else /* NOTE: this call should walk up the parent stack */ 631878d68c0SSimon Glass return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); 632878d68c0SSimon Glass } 633878d68c0SSimon Glass 634878d68c0SSimon Glass int ofnode_read_simple_addr_cells(ofnode node) 635878d68c0SSimon Glass { 636878d68c0SSimon Glass if (ofnode_is_np(node)) 637878d68c0SSimon Glass return of_simple_addr_cells(ofnode_to_np(node)); 638878d68c0SSimon Glass else 639878d68c0SSimon Glass return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); 640878d68c0SSimon Glass } 641878d68c0SSimon Glass 642878d68c0SSimon Glass int ofnode_read_simple_size_cells(ofnode node) 643878d68c0SSimon Glass { 644878d68c0SSimon Glass if (ofnode_is_np(node)) 645878d68c0SSimon Glass return of_simple_size_cells(ofnode_to_np(node)); 6469e512045SSimon Glass else 6479e512045SSimon Glass return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); 6489e512045SSimon Glass } 6499e512045SSimon Glass 6509e512045SSimon Glass bool ofnode_pre_reloc(ofnode node) 6519e512045SSimon Glass { 652252510acSMasahiro Yamada if (ofnode_read_bool(node, "u-boot,dm-pre-reloc")) 6539e512045SSimon Glass return true; 6549e512045SSimon Glass 6559e512045SSimon Glass #ifdef CONFIG_TPL_BUILD 656252510acSMasahiro Yamada if (ofnode_read_bool(node, "u-boot,dm-tpl")) 6579e512045SSimon Glass return true; 6589e512045SSimon Glass #elif defined(CONFIG_SPL_BUILD) 659252510acSMasahiro Yamada if (ofnode_read_bool(node, "u-boot,dm-spl")) 6609e512045SSimon Glass return true; 6619e512045SSimon Glass #else 6629e512045SSimon Glass /* 6639e512045SSimon Glass * In regular builds individual spl and tpl handling both 6649e512045SSimon Glass * count as handled pre-relocation for later second init. 6659e512045SSimon Glass */ 666252510acSMasahiro Yamada if (ofnode_read_bool(node, "u-boot,dm-spl") || 667252510acSMasahiro Yamada ofnode_read_bool(node, "u-boot,dm-tpl")) 6689e512045SSimon Glass return true; 6699e512045SSimon Glass #endif 6709e512045SSimon Glass 6719e512045SSimon Glass return false; 6729e512045SSimon Glass } 673dcf98852SSimon Glass 674dcf98852SSimon Glass int ofnode_read_resource(ofnode node, uint index, struct resource *res) 675dcf98852SSimon Glass { 676dcf98852SSimon Glass if (ofnode_is_np(node)) { 677dcf98852SSimon Glass return of_address_to_resource(ofnode_to_np(node), index, res); 678dcf98852SSimon Glass } else { 679dcf98852SSimon Glass struct fdt_resource fres; 680dcf98852SSimon Glass int ret; 681dcf98852SSimon Glass 682dcf98852SSimon Glass ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node), 683dcf98852SSimon Glass "reg", index, &fres); 684dcf98852SSimon Glass if (ret < 0) 685dcf98852SSimon Glass return -EINVAL; 686dcf98852SSimon Glass memset(res, '\0', sizeof(*res)); 687dcf98852SSimon Glass res->start = fres.start; 688dcf98852SSimon Glass res->end = fres.end; 689dcf98852SSimon Glass 690dcf98852SSimon Glass return 0; 691dcf98852SSimon Glass } 692dcf98852SSimon Glass } 6937b8b47bdSMasahiro Yamada 6947b8b47bdSMasahiro Yamada int ofnode_read_resource_byname(ofnode node, const char *name, 6957b8b47bdSMasahiro Yamada struct resource *res) 6967b8b47bdSMasahiro Yamada { 6977b8b47bdSMasahiro Yamada int index; 6987b8b47bdSMasahiro Yamada 6997b8b47bdSMasahiro Yamada index = ofnode_stringlist_search(node, "reg-names", name); 7007b8b47bdSMasahiro Yamada if (index < 0) 7017b8b47bdSMasahiro Yamada return index; 7027b8b47bdSMasahiro Yamada 7037b8b47bdSMasahiro Yamada return ofnode_read_resource(node, index, res); 7047b8b47bdSMasahiro Yamada } 705*a9bd1c73SMario Six 706*a9bd1c73SMario Six u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr) 707*a9bd1c73SMario Six { 708*a9bd1c73SMario Six if (ofnode_is_np(node)) 709*a9bd1c73SMario Six return of_translate_address(ofnode_to_np(node), in_addr); 710*a9bd1c73SMario Six else 711*a9bd1c73SMario Six return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr); 712*a9bd1c73SMario Six } 713