1*9e512045SSimon Glass /* 2*9e512045SSimon Glass * Copyright (c) 2017 Google, Inc 3*9e512045SSimon Glass * Written by Simon Glass <sjg@chromium.org> 4*9e512045SSimon Glass * 5*9e512045SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 6*9e512045SSimon Glass */ 7*9e512045SSimon Glass 8*9e512045SSimon Glass #include <common.h> 9*9e512045SSimon Glass #include <dm.h> 10*9e512045SSimon Glass #include <fdtdec.h> 11*9e512045SSimon Glass #include <fdt_support.h> 12*9e512045SSimon Glass #include <libfdt.h> 13*9e512045SSimon Glass #include <dm/of_access.h> 14*9e512045SSimon Glass #include <dm/ofnode.h> 15*9e512045SSimon Glass #include <linux/err.h> 16*9e512045SSimon Glass 17*9e512045SSimon Glass int ofnode_read_u32(ofnode node, const char *propname, u32 *outp) 18*9e512045SSimon Glass { 19*9e512045SSimon Glass assert(ofnode_valid(node)); 20*9e512045SSimon Glass debug("%s: %s: ", __func__, propname); 21*9e512045SSimon Glass 22*9e512045SSimon Glass if (ofnode_is_np(node)) { 23*9e512045SSimon Glass return of_read_u32(ofnode_to_np(node), propname, outp); 24*9e512045SSimon Glass } else { 25*9e512045SSimon Glass const int *cell; 26*9e512045SSimon Glass int len; 27*9e512045SSimon Glass 28*9e512045SSimon Glass cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 29*9e512045SSimon Glass propname, &len); 30*9e512045SSimon Glass if (!cell || len < sizeof(int)) { 31*9e512045SSimon Glass debug("(not found)\n"); 32*9e512045SSimon Glass return -EINVAL; 33*9e512045SSimon Glass } 34*9e512045SSimon Glass *outp = fdt32_to_cpu(cell[0]); 35*9e512045SSimon Glass } 36*9e512045SSimon Glass debug("%#x (%d)\n", *outp, *outp); 37*9e512045SSimon Glass 38*9e512045SSimon Glass return 0; 39*9e512045SSimon Glass } 40*9e512045SSimon Glass 41*9e512045SSimon Glass int ofnode_read_u32_default(ofnode node, const char *propname, u32 def) 42*9e512045SSimon Glass { 43*9e512045SSimon Glass assert(ofnode_valid(node)); 44*9e512045SSimon Glass ofnode_read_u32(node, propname, &def); 45*9e512045SSimon Glass 46*9e512045SSimon Glass return def; 47*9e512045SSimon Glass } 48*9e512045SSimon Glass 49*9e512045SSimon Glass int ofnode_read_s32_default(ofnode node, const char *propname, s32 def) 50*9e512045SSimon Glass { 51*9e512045SSimon Glass assert(ofnode_valid(node)); 52*9e512045SSimon Glass ofnode_read_u32(node, propname, (u32 *)&def); 53*9e512045SSimon Glass 54*9e512045SSimon Glass return def; 55*9e512045SSimon Glass } 56*9e512045SSimon Glass 57*9e512045SSimon Glass bool ofnode_read_bool(ofnode node, const char *propname) 58*9e512045SSimon Glass { 59*9e512045SSimon Glass bool val; 60*9e512045SSimon Glass 61*9e512045SSimon Glass assert(ofnode_valid(node)); 62*9e512045SSimon Glass debug("%s: %s: ", __func__, propname); 63*9e512045SSimon Glass 64*9e512045SSimon Glass if (ofnode_is_np(node)) { 65*9e512045SSimon Glass val = !!of_find_property(ofnode_to_np(node), propname, NULL); 66*9e512045SSimon Glass } else { 67*9e512045SSimon Glass val = !!fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 68*9e512045SSimon Glass propname, NULL); 69*9e512045SSimon Glass } 70*9e512045SSimon Glass debug("%s\n", val ? "true" : "false"); 71*9e512045SSimon Glass 72*9e512045SSimon Glass return val; 73*9e512045SSimon Glass } 74*9e512045SSimon Glass 75*9e512045SSimon Glass const char *ofnode_read_string(ofnode node, const char *propname) 76*9e512045SSimon Glass { 77*9e512045SSimon Glass const char *str = NULL; 78*9e512045SSimon Glass int len = -1; 79*9e512045SSimon Glass 80*9e512045SSimon Glass assert(ofnode_valid(node)); 81*9e512045SSimon Glass debug("%s: %s: ", __func__, propname); 82*9e512045SSimon Glass 83*9e512045SSimon Glass if (ofnode_is_np(node)) { 84*9e512045SSimon Glass struct property *prop = of_find_property( 85*9e512045SSimon Glass ofnode_to_np(node), propname, NULL); 86*9e512045SSimon Glass 87*9e512045SSimon Glass if (prop) { 88*9e512045SSimon Glass str = prop->value; 89*9e512045SSimon Glass len = prop->length; 90*9e512045SSimon Glass } 91*9e512045SSimon Glass } else { 92*9e512045SSimon Glass str = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 93*9e512045SSimon Glass propname, &len); 94*9e512045SSimon Glass } 95*9e512045SSimon Glass if (!str) { 96*9e512045SSimon Glass debug("<not found>\n"); 97*9e512045SSimon Glass return NULL; 98*9e512045SSimon Glass } 99*9e512045SSimon Glass if (strnlen(str, len) >= len) { 100*9e512045SSimon Glass debug("<invalid>\n"); 101*9e512045SSimon Glass return NULL; 102*9e512045SSimon Glass } 103*9e512045SSimon Glass debug("%s\n", str); 104*9e512045SSimon Glass 105*9e512045SSimon Glass return str; 106*9e512045SSimon Glass } 107*9e512045SSimon Glass 108*9e512045SSimon Glass ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) 109*9e512045SSimon Glass { 110*9e512045SSimon Glass ofnode subnode; 111*9e512045SSimon Glass 112*9e512045SSimon Glass assert(ofnode_valid(node)); 113*9e512045SSimon Glass debug("%s: %s: ", __func__, subnode_name); 114*9e512045SSimon Glass 115*9e512045SSimon Glass if (ofnode_is_np(node)) { 116*9e512045SSimon Glass const struct device_node *np = ofnode_to_np(node); 117*9e512045SSimon Glass 118*9e512045SSimon Glass for (np = np->child; np; np = np->sibling) { 119*9e512045SSimon Glass if (!strcmp(subnode_name, np->name)) 120*9e512045SSimon Glass break; 121*9e512045SSimon Glass } 122*9e512045SSimon Glass subnode = np_to_ofnode(np); 123*9e512045SSimon Glass } else { 124*9e512045SSimon Glass int ooffset = fdt_subnode_offset(gd->fdt_blob, 125*9e512045SSimon Glass ofnode_to_offset(node), subnode_name); 126*9e512045SSimon Glass subnode = offset_to_ofnode(ooffset); 127*9e512045SSimon Glass } 128*9e512045SSimon Glass debug("%s\n", ofnode_valid(subnode) ? 129*9e512045SSimon Glass ofnode_get_name(subnode) : "<none>"); 130*9e512045SSimon Glass 131*9e512045SSimon Glass return subnode; 132*9e512045SSimon Glass } 133*9e512045SSimon Glass 134*9e512045SSimon Glass int ofnode_read_u32_array(ofnode node, const char *propname, 135*9e512045SSimon Glass u32 *out_values, size_t sz) 136*9e512045SSimon Glass { 137*9e512045SSimon Glass assert(ofnode_valid(node)); 138*9e512045SSimon Glass debug("%s: %s: ", __func__, propname); 139*9e512045SSimon Glass 140*9e512045SSimon Glass if (ofnode_is_np(node)) { 141*9e512045SSimon Glass return of_read_u32_array(ofnode_to_np(node), propname, 142*9e512045SSimon Glass out_values, sz); 143*9e512045SSimon Glass } else { 144*9e512045SSimon Glass return fdtdec_get_int_array(gd->fdt_blob, 145*9e512045SSimon Glass ofnode_to_offset(node), propname, 146*9e512045SSimon Glass out_values, sz); 147*9e512045SSimon Glass } 148*9e512045SSimon Glass } 149*9e512045SSimon Glass 150*9e512045SSimon Glass ofnode ofnode_first_subnode(ofnode node) 151*9e512045SSimon Glass { 152*9e512045SSimon Glass assert(ofnode_valid(node)); 153*9e512045SSimon Glass if (ofnode_is_np(node)) 154*9e512045SSimon Glass return np_to_ofnode(node.np->child); 155*9e512045SSimon Glass 156*9e512045SSimon Glass return offset_to_ofnode( 157*9e512045SSimon Glass fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node))); 158*9e512045SSimon Glass } 159*9e512045SSimon Glass 160*9e512045SSimon Glass ofnode ofnode_next_subnode(ofnode node) 161*9e512045SSimon Glass { 162*9e512045SSimon Glass assert(ofnode_valid(node)); 163*9e512045SSimon Glass if (ofnode_is_np(node)) 164*9e512045SSimon Glass return np_to_ofnode(node.np->sibling); 165*9e512045SSimon Glass 166*9e512045SSimon Glass return offset_to_ofnode( 167*9e512045SSimon Glass fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node))); 168*9e512045SSimon Glass } 169*9e512045SSimon Glass 170*9e512045SSimon Glass const char *ofnode_get_name(ofnode node) 171*9e512045SSimon Glass { 172*9e512045SSimon Glass assert(ofnode_valid(node)); 173*9e512045SSimon Glass if (ofnode_is_np(node)) 174*9e512045SSimon Glass return strrchr(node.np->full_name, '/') + 1; 175*9e512045SSimon Glass 176*9e512045SSimon Glass return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL); 177*9e512045SSimon Glass } 178*9e512045SSimon Glass 179*9e512045SSimon Glass int ofnode_read_size(ofnode node, const char *propname) 180*9e512045SSimon Glass { 181*9e512045SSimon Glass int len; 182*9e512045SSimon Glass 183*9e512045SSimon Glass if (ofnode_is_np(node)) { 184*9e512045SSimon Glass struct property *prop = of_find_property( 185*9e512045SSimon Glass ofnode_to_np(node), propname, NULL); 186*9e512045SSimon Glass 187*9e512045SSimon Glass if (prop) 188*9e512045SSimon Glass return prop->length; 189*9e512045SSimon Glass } else { 190*9e512045SSimon Glass if (fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, 191*9e512045SSimon Glass &len)) 192*9e512045SSimon Glass return len; 193*9e512045SSimon Glass } 194*9e512045SSimon Glass 195*9e512045SSimon Glass return -EINVAL; 196*9e512045SSimon Glass } 197*9e512045SSimon Glass 198*9e512045SSimon Glass int ofnode_stringlist_search(ofnode node, const char *property, 199*9e512045SSimon Glass const char *string) 200*9e512045SSimon Glass { 201*9e512045SSimon Glass if (ofnode_is_np(node)) { 202*9e512045SSimon Glass return of_property_match_string(ofnode_to_np(node), 203*9e512045SSimon Glass property, string); 204*9e512045SSimon Glass } else { 205*9e512045SSimon Glass int ret; 206*9e512045SSimon Glass 207*9e512045SSimon Glass ret = fdt_stringlist_search(gd->fdt_blob, 208*9e512045SSimon Glass ofnode_to_offset(node), property, 209*9e512045SSimon Glass string); 210*9e512045SSimon Glass if (ret == -FDT_ERR_NOTFOUND) 211*9e512045SSimon Glass return -ENODATA; 212*9e512045SSimon Glass else if (ret < 0) 213*9e512045SSimon Glass return -EINVAL; 214*9e512045SSimon Glass 215*9e512045SSimon Glass return ret; 216*9e512045SSimon Glass } 217*9e512045SSimon Glass } 218*9e512045SSimon Glass 219*9e512045SSimon Glass int ofnode_read_string_index(ofnode node, const char *property, int index, 220*9e512045SSimon Glass const char **outp) 221*9e512045SSimon Glass { 222*9e512045SSimon Glass if (ofnode_is_np(node)) { 223*9e512045SSimon Glass return of_property_read_string_index(ofnode_to_np(node), 224*9e512045SSimon Glass property, index, outp); 225*9e512045SSimon Glass } else { 226*9e512045SSimon Glass int len; 227*9e512045SSimon Glass 228*9e512045SSimon Glass *outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node), 229*9e512045SSimon Glass property, index, &len); 230*9e512045SSimon Glass if (len < 0) 231*9e512045SSimon Glass return -EINVAL; 232*9e512045SSimon Glass return 0; 233*9e512045SSimon Glass } 234*9e512045SSimon Glass } 235*9e512045SSimon Glass 236*9e512045SSimon Glass static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in, 237*9e512045SSimon Glass struct ofnode_phandle_args *out) 238*9e512045SSimon Glass { 239*9e512045SSimon Glass assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 240*9e512045SSimon Glass out->node = offset_to_ofnode(in->node); 241*9e512045SSimon Glass out->args_count = in->args_count; 242*9e512045SSimon Glass memcpy(out->args, in->args, sizeof(out->args)); 243*9e512045SSimon Glass } 244*9e512045SSimon Glass 245*9e512045SSimon Glass static void ofnode_from_of_phandle_args(struct of_phandle_args *in, 246*9e512045SSimon Glass struct ofnode_phandle_args *out) 247*9e512045SSimon Glass { 248*9e512045SSimon Glass assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 249*9e512045SSimon Glass out->node = np_to_ofnode(in->np); 250*9e512045SSimon Glass out->args_count = in->args_count; 251*9e512045SSimon Glass memcpy(out->args, in->args, sizeof(out->args)); 252*9e512045SSimon Glass } 253*9e512045SSimon Glass 254*9e512045SSimon Glass int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, 255*9e512045SSimon Glass const char *cells_name, int cell_count, 256*9e512045SSimon Glass int index, 257*9e512045SSimon Glass struct ofnode_phandle_args *out_args) 258*9e512045SSimon Glass { 259*9e512045SSimon Glass if (ofnode_is_np(node)) { 260*9e512045SSimon Glass struct of_phandle_args args; 261*9e512045SSimon Glass int ret; 262*9e512045SSimon Glass 263*9e512045SSimon Glass ret = of_parse_phandle_with_args(ofnode_to_np(node), 264*9e512045SSimon Glass list_name, cells_name, index, &args); 265*9e512045SSimon Glass if (ret) 266*9e512045SSimon Glass return ret; 267*9e512045SSimon Glass ofnode_from_of_phandle_args(&args, out_args); 268*9e512045SSimon Glass } else { 269*9e512045SSimon Glass struct fdtdec_phandle_args args; 270*9e512045SSimon Glass int ret; 271*9e512045SSimon Glass 272*9e512045SSimon Glass ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, 273*9e512045SSimon Glass ofnode_to_offset(node), list_name, cells_name, 274*9e512045SSimon Glass cell_count, index, &args); 275*9e512045SSimon Glass if (ret) 276*9e512045SSimon Glass return ret; 277*9e512045SSimon Glass ofnode_from_fdtdec_phandle_args(&args, out_args); 278*9e512045SSimon Glass } 279*9e512045SSimon Glass 280*9e512045SSimon Glass return 0; 281*9e512045SSimon Glass } 282*9e512045SSimon Glass 283*9e512045SSimon Glass ofnode ofnode_path(const char *path) 284*9e512045SSimon Glass { 285*9e512045SSimon Glass if (of_live_active()) 286*9e512045SSimon Glass return np_to_ofnode(of_find_node_by_path(path)); 287*9e512045SSimon Glass else 288*9e512045SSimon Glass return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path)); 289*9e512045SSimon Glass } 290*9e512045SSimon Glass 291*9e512045SSimon Glass const char *ofnode_get_chosen_prop(const char *name) 292*9e512045SSimon Glass { 293*9e512045SSimon Glass ofnode chosen_node; 294*9e512045SSimon Glass 295*9e512045SSimon Glass chosen_node = ofnode_path("/chosen"); 296*9e512045SSimon Glass 297*9e512045SSimon Glass return ofnode_read_string(chosen_node, name); 298*9e512045SSimon Glass } 299*9e512045SSimon Glass 300*9e512045SSimon Glass ofnode ofnode_get_chosen_node(const char *name) 301*9e512045SSimon Glass { 302*9e512045SSimon Glass const char *prop; 303*9e512045SSimon Glass 304*9e512045SSimon Glass prop = ofnode_get_chosen_prop(name); 305*9e512045SSimon Glass if (!prop) 306*9e512045SSimon Glass return ofnode_null(); 307*9e512045SSimon Glass 308*9e512045SSimon Glass return ofnode_path(prop); 309*9e512045SSimon Glass } 310*9e512045SSimon Glass 311*9e512045SSimon Glass static int decode_timing_property(ofnode node, const char *name, 312*9e512045SSimon Glass struct timing_entry *result) 313*9e512045SSimon Glass { 314*9e512045SSimon Glass int length, ret = 0; 315*9e512045SSimon Glass 316*9e512045SSimon Glass length = ofnode_read_size(node, name); 317*9e512045SSimon Glass if (length < 0) { 318*9e512045SSimon Glass debug("%s: could not find property %s\n", 319*9e512045SSimon Glass ofnode_get_name(node), name); 320*9e512045SSimon Glass return length; 321*9e512045SSimon Glass } 322*9e512045SSimon Glass 323*9e512045SSimon Glass if (length == sizeof(u32)) { 324*9e512045SSimon Glass result->typ = ofnode_read_u32_default(node, name, 0); 325*9e512045SSimon Glass result->min = result->typ; 326*9e512045SSimon Glass result->max = result->typ; 327*9e512045SSimon Glass } else { 328*9e512045SSimon Glass ret = ofnode_read_u32_array(node, name, &result->min, 3); 329*9e512045SSimon Glass } 330*9e512045SSimon Glass 331*9e512045SSimon Glass return ret; 332*9e512045SSimon Glass } 333*9e512045SSimon Glass 334*9e512045SSimon Glass int ofnode_decode_display_timing(ofnode parent, int index, 335*9e512045SSimon Glass struct display_timing *dt) 336*9e512045SSimon Glass { 337*9e512045SSimon Glass int i; 338*9e512045SSimon Glass ofnode timings, node; 339*9e512045SSimon Glass u32 val = 0; 340*9e512045SSimon Glass int ret = 0; 341*9e512045SSimon Glass 342*9e512045SSimon Glass timings = ofnode_find_subnode(parent, "display-timings"); 343*9e512045SSimon Glass if (!ofnode_valid(timings)) 344*9e512045SSimon Glass return -EINVAL; 345*9e512045SSimon Glass 346*9e512045SSimon Glass for (i = 0, node = ofnode_first_subnode(timings); 347*9e512045SSimon Glass ofnode_valid(node) && i != index; 348*9e512045SSimon Glass node = ofnode_first_subnode(node)) 349*9e512045SSimon Glass i++; 350*9e512045SSimon Glass 351*9e512045SSimon Glass if (!ofnode_valid(node)) 352*9e512045SSimon Glass return -EINVAL; 353*9e512045SSimon Glass 354*9e512045SSimon Glass memset(dt, 0, sizeof(*dt)); 355*9e512045SSimon Glass 356*9e512045SSimon Glass ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch); 357*9e512045SSimon Glass ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch); 358*9e512045SSimon Glass ret |= decode_timing_property(node, "hactive", &dt->hactive); 359*9e512045SSimon Glass ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len); 360*9e512045SSimon Glass ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch); 361*9e512045SSimon Glass ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch); 362*9e512045SSimon Glass ret |= decode_timing_property(node, "vactive", &dt->vactive); 363*9e512045SSimon Glass ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len); 364*9e512045SSimon Glass ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock); 365*9e512045SSimon Glass 366*9e512045SSimon Glass dt->flags = 0; 367*9e512045SSimon Glass val = ofnode_read_u32_default(node, "vsync-active", -1); 368*9e512045SSimon Glass if (val != -1) { 369*9e512045SSimon Glass dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : 370*9e512045SSimon Glass DISPLAY_FLAGS_VSYNC_LOW; 371*9e512045SSimon Glass } 372*9e512045SSimon Glass val = ofnode_read_u32_default(node, "hsync-active", -1); 373*9e512045SSimon Glass if (val != -1) { 374*9e512045SSimon Glass dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : 375*9e512045SSimon Glass DISPLAY_FLAGS_HSYNC_LOW; 376*9e512045SSimon Glass } 377*9e512045SSimon Glass val = ofnode_read_u32_default(node, "de-active", -1); 378*9e512045SSimon Glass if (val != -1) { 379*9e512045SSimon Glass dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : 380*9e512045SSimon Glass DISPLAY_FLAGS_DE_LOW; 381*9e512045SSimon Glass } 382*9e512045SSimon Glass val = ofnode_read_u32_default(node, "pixelclk-active", -1); 383*9e512045SSimon Glass if (val != -1) { 384*9e512045SSimon Glass dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : 385*9e512045SSimon Glass DISPLAY_FLAGS_PIXDATA_NEGEDGE; 386*9e512045SSimon Glass } 387*9e512045SSimon Glass 388*9e512045SSimon Glass if (ofnode_read_bool(node, "interlaced")) 389*9e512045SSimon Glass dt->flags |= DISPLAY_FLAGS_INTERLACED; 390*9e512045SSimon Glass if (ofnode_read_bool(node, "doublescan")) 391*9e512045SSimon Glass dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; 392*9e512045SSimon Glass if (ofnode_read_bool(node, "doubleclk")) 393*9e512045SSimon Glass dt->flags |= DISPLAY_FLAGS_DOUBLECLK; 394*9e512045SSimon Glass 395*9e512045SSimon Glass return ret; 396*9e512045SSimon Glass } 397*9e512045SSimon Glass 398*9e512045SSimon Glass const u32 *ofnode_read_prop(ofnode node, const char *propname, int *lenp) 399*9e512045SSimon Glass { 400*9e512045SSimon Glass if (ofnode_is_np(node)) { 401*9e512045SSimon Glass struct property *prop; 402*9e512045SSimon Glass 403*9e512045SSimon Glass prop = of_find_property(ofnode_to_np(node), propname, lenp); 404*9e512045SSimon Glass if (!prop) 405*9e512045SSimon Glass return NULL; 406*9e512045SSimon Glass return prop->value; 407*9e512045SSimon Glass } else { 408*9e512045SSimon Glass return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 409*9e512045SSimon Glass propname, lenp); 410*9e512045SSimon Glass } 411*9e512045SSimon Glass } 412*9e512045SSimon Glass 413*9e512045SSimon Glass bool ofnode_is_available(ofnode node) 414*9e512045SSimon Glass { 415*9e512045SSimon Glass if (ofnode_is_np(node)) 416*9e512045SSimon Glass return of_device_is_available(ofnode_to_np(node)); 417*9e512045SSimon Glass else 418*9e512045SSimon Glass return fdtdec_get_is_enabled(gd->fdt_blob, 419*9e512045SSimon Glass ofnode_to_offset(node)); 420*9e512045SSimon Glass } 421*9e512045SSimon Glass 422*9e512045SSimon Glass fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, 423*9e512045SSimon Glass fdt_size_t *sizep) 424*9e512045SSimon Glass { 425*9e512045SSimon Glass if (ofnode_is_np(node)) { 426*9e512045SSimon Glass int na, ns; 427*9e512045SSimon Glass int psize; 428*9e512045SSimon Glass const struct device_node *np = ofnode_to_np(node); 429*9e512045SSimon Glass const __be32 *prop = of_get_property(np, "reg", &psize); 430*9e512045SSimon Glass 431*9e512045SSimon Glass na = of_n_addr_cells(np); 432*9e512045SSimon Glass ns = of_n_addr_cells(np); 433*9e512045SSimon Glass *sizep = of_read_number(prop + na, ns); 434*9e512045SSimon Glass return of_read_number(prop, na); 435*9e512045SSimon Glass } else { 436*9e512045SSimon Glass return fdtdec_get_addr_size(gd->fdt_blob, 437*9e512045SSimon Glass ofnode_to_offset(node), property, 438*9e512045SSimon Glass sizep); 439*9e512045SSimon Glass } 440*9e512045SSimon Glass } 441*9e512045SSimon Glass 442*9e512045SSimon Glass const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, 443*9e512045SSimon Glass size_t sz) 444*9e512045SSimon Glass { 445*9e512045SSimon Glass if (ofnode_is_np(node)) { 446*9e512045SSimon Glass const struct device_node *np = ofnode_to_np(node); 447*9e512045SSimon Glass int psize; 448*9e512045SSimon Glass const __be32 *prop = of_get_property(np, propname, &psize); 449*9e512045SSimon Glass 450*9e512045SSimon Glass if (!prop || sz != psize) 451*9e512045SSimon Glass return NULL; 452*9e512045SSimon Glass return (uint8_t *)prop; 453*9e512045SSimon Glass 454*9e512045SSimon Glass } else { 455*9e512045SSimon Glass return fdtdec_locate_byte_array(gd->fdt_blob, 456*9e512045SSimon Glass ofnode_to_offset(node), propname, sz); 457*9e512045SSimon Glass } 458*9e512045SSimon Glass } 459*9e512045SSimon Glass 460*9e512045SSimon Glass int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, 461*9e512045SSimon Glass const char *propname, struct fdt_pci_addr *addr) 462*9e512045SSimon Glass { 463*9e512045SSimon Glass const u32 *cell; 464*9e512045SSimon Glass int len; 465*9e512045SSimon Glass int ret = -ENOENT; 466*9e512045SSimon Glass 467*9e512045SSimon Glass debug("%s: %s: ", __func__, propname); 468*9e512045SSimon Glass 469*9e512045SSimon Glass /* 470*9e512045SSimon Glass * If we follow the pci bus bindings strictly, we should check 471*9e512045SSimon Glass * the value of the node's parent node's #address-cells and 472*9e512045SSimon Glass * #size-cells. They need to be 3 and 2 accordingly. However, 473*9e512045SSimon Glass * for simplicity we skip the check here. 474*9e512045SSimon Glass */ 475*9e512045SSimon Glass cell = ofnode_read_prop(node, propname, &len); 476*9e512045SSimon Glass if (!cell) 477*9e512045SSimon Glass goto fail; 478*9e512045SSimon Glass 479*9e512045SSimon Glass if ((len % FDT_PCI_REG_SIZE) == 0) { 480*9e512045SSimon Glass int num = len / FDT_PCI_REG_SIZE; 481*9e512045SSimon Glass int i; 482*9e512045SSimon Glass 483*9e512045SSimon Glass for (i = 0; i < num; i++) { 484*9e512045SSimon Glass debug("pci address #%d: %08lx %08lx %08lx\n", i, 485*9e512045SSimon Glass (ulong)fdt32_to_cpu(cell[0]), 486*9e512045SSimon Glass (ulong)fdt32_to_cpu(cell[1]), 487*9e512045SSimon Glass (ulong)fdt32_to_cpu(cell[2])); 488*9e512045SSimon Glass if ((fdt32_to_cpu(*cell) & type) == type) { 489*9e512045SSimon Glass addr->phys_hi = fdt32_to_cpu(cell[0]); 490*9e512045SSimon Glass addr->phys_mid = fdt32_to_cpu(cell[1]); 491*9e512045SSimon Glass addr->phys_lo = fdt32_to_cpu(cell[1]); 492*9e512045SSimon Glass break; 493*9e512045SSimon Glass } else { 494*9e512045SSimon Glass cell += (FDT_PCI_ADDR_CELLS + 495*9e512045SSimon Glass FDT_PCI_SIZE_CELLS); 496*9e512045SSimon Glass } 497*9e512045SSimon Glass } 498*9e512045SSimon Glass 499*9e512045SSimon Glass if (i == num) { 500*9e512045SSimon Glass ret = -ENXIO; 501*9e512045SSimon Glass goto fail; 502*9e512045SSimon Glass } 503*9e512045SSimon Glass 504*9e512045SSimon Glass return 0; 505*9e512045SSimon Glass } else { 506*9e512045SSimon Glass ret = -EINVAL; 507*9e512045SSimon Glass } 508*9e512045SSimon Glass 509*9e512045SSimon Glass fail: 510*9e512045SSimon Glass debug("(not found)\n"); 511*9e512045SSimon Glass return ret; 512*9e512045SSimon Glass } 513*9e512045SSimon Glass 514*9e512045SSimon Glass int ofnode_read_addr_cells(ofnode node) 515*9e512045SSimon Glass { 516*9e512045SSimon Glass if (ofnode_is_np(node)) 517*9e512045SSimon Glass return of_n_addr_cells(ofnode_to_np(node)); 518*9e512045SSimon Glass else 519*9e512045SSimon Glass return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); 520*9e512045SSimon Glass } 521*9e512045SSimon Glass 522*9e512045SSimon Glass int ofnode_read_size_cells(ofnode node) 523*9e512045SSimon Glass { 524*9e512045SSimon Glass if (ofnode_is_np(node)) 525*9e512045SSimon Glass return of_n_size_cells(ofnode_to_np(node)); 526*9e512045SSimon Glass else 527*9e512045SSimon Glass return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); 528*9e512045SSimon Glass } 529*9e512045SSimon Glass 530*9e512045SSimon Glass bool ofnode_pre_reloc(ofnode node) 531*9e512045SSimon Glass { 532*9e512045SSimon Glass if (ofnode_read_prop(node, "u-boot,dm-pre-reloc", NULL)) 533*9e512045SSimon Glass return true; 534*9e512045SSimon Glass 535*9e512045SSimon Glass #ifdef CONFIG_TPL_BUILD 536*9e512045SSimon Glass if (ofnode_read_prop(node, "u-boot,dm-tpl", NULL)) 537*9e512045SSimon Glass return true; 538*9e512045SSimon Glass #elif defined(CONFIG_SPL_BUILD) 539*9e512045SSimon Glass if (ofnode_read_prop(node, "u-boot,dm-spl", NULL)) 540*9e512045SSimon Glass return true; 541*9e512045SSimon Glass #else 542*9e512045SSimon Glass /* 543*9e512045SSimon Glass * In regular builds individual spl and tpl handling both 544*9e512045SSimon Glass * count as handled pre-relocation for later second init. 545*9e512045SSimon Glass */ 546*9e512045SSimon Glass if (ofnode_read_prop(node, "u-boot,dm-spl", NULL) || 547*9e512045SSimon Glass ofnode_read_prop(node, "u-boot,dm-tpl", NULL)) 548*9e512045SSimon Glass return true; 549*9e512045SSimon Glass #endif 550*9e512045SSimon Glass 551*9e512045SSimon Glass return false; 552*9e512045SSimon Glass } 553