X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fcore%2Fofnode.c;h=b7b7ad3a625da9cbff62bed3644067eabc72ac1f;hb=3d5ced9e22d32112a20f9dc0f5fb1f22ef088079;hp=3cf3205a2f1d192c0354c6996e2190465c2b6bf5;hpb=5ccc2c21307e186722ca9966bad0e03189c237c5;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 3cf3205..b7b7ad3 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -55,6 +55,38 @@ int ofnode_read_s32_default(ofnode node, const char *propname, s32 def) return def; } +int ofnode_read_u64(ofnode node, const char *propname, u64 *outp) +{ + const fdt64_t *cell; + int len; + + assert(ofnode_valid(node)); + debug("%s: %s: ", __func__, propname); + + if (ofnode_is_np(node)) + return of_read_u64(ofnode_to_np(node), propname, outp); + + cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, + &len); + if (!cell || len < sizeof(*cell)) { + debug("(not found)\n"); + return -EINVAL; + } + *outp = fdt64_to_cpu(cell[0]); + debug("%#llx (%lld)\n", (unsigned long long)*outp, + (unsigned long long)*outp); + + return 0; +} + +int ofnode_read_u64_default(ofnode node, const char *propname, u64 def) +{ + assert(ofnode_valid(node)); + ofnode_read_u64(node, propname, &def); + + return def; +} + bool ofnode_read_bool(ofnode node, const char *propname) { const void *prop; @@ -509,9 +541,13 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, if (!prop) return FDT_ADDR_T_NONE; na = of_n_addr_cells(np); - ns = of_n_addr_cells(np); + ns = of_n_size_cells(np); *sizep = of_read_number(prop + na, ns); - return of_read_number(prop, na); + + if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) + return of_translate_address(np, prop); + else + return of_read_number(prop, na); } else { return fdtdec_get_addr_size(gd->fdt_blob, ofnode_to_offset(node), property, @@ -591,6 +627,42 @@ fail: return ret; } +int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device) +{ + const char *list, *end; + int len; + + list = ofnode_get_property(node, "compatible", &len); + if (!list) + return -ENOENT; + + end = list + len; + while (list < end) { + len = strlen(list); + if (len >= strlen("pciVVVV,DDDD")) { + char *s = strstr(list, "pci"); + + /* + * check if the string is something like pciVVVV,DDDD.RR + * or just pciVVVV,DDDD + */ + if (s && s[7] == ',' && + (s[12] == '.' || s[12] == 0)) { + s += 3; + *vendor = simple_strtol(s, NULL, 16); + + s += 5; + *device = simple_strtol(s, NULL, 16); + + return 0; + } + } + list += (len + 1); + } + + return -ENOENT; +} + int ofnode_read_addr_cells(ofnode node) { if (ofnode_is_np(node)) @@ -627,6 +699,8 @@ bool ofnode_pre_reloc(ofnode node) { if (ofnode_read_bool(node, "u-boot,dm-pre-reloc")) return true; + if (ofnode_read_bool(node, "u-boot,dm-pre-proper")) + return true; #ifdef CONFIG_TPL_BUILD if (ofnode_read_bool(node, "u-boot,dm-tpl")) @@ -697,3 +771,99 @@ int ofnode_device_is_compatible(ofnode node, const char *compat) ofnode_to_offset(node), compat); } + +ofnode ofnode_by_compatible(ofnode from, const char *compat) +{ + if (of_live_active()) { + return np_to_ofnode(of_find_compatible_node( + (struct device_node *)ofnode_to_np(from), NULL, + compat)); + } else { + return offset_to_ofnode(fdt_node_offset_by_compatible( + gd->fdt_blob, ofnode_to_offset(from), compat)); + } +} + +ofnode ofnode_by_prop_value(ofnode from, const char *propname, + const void *propval, int proplen) +{ + if (of_live_active()) { + return np_to_ofnode(of_find_node_by_prop_value( + (struct device_node *)ofnode_to_np(from), propname, + propval, proplen)); + } else { + return offset_to_ofnode(fdt_node_offset_by_prop_value( + gd->fdt_blob, ofnode_to_offset(from), + propname, propval, proplen)); + } +} + +int ofnode_write_prop(ofnode node, const char *propname, int len, + const void *value) +{ + const struct device_node *np = ofnode_to_np(node); + struct property *pp; + struct property *pp_last = NULL; + struct property *new; + + if (!of_live_active()) + return -ENOSYS; + + if (!np) + return -EINVAL; + + for (pp = np->properties; pp; pp = pp->next) { + if (strcmp(pp->name, propname) == 0) { + /* Property exists -> change value */ + pp->value = (void *)value; + pp->length = len; + return 0; + } + pp_last = pp; + } + + if (!pp_last) + return -ENOENT; + + /* Property does not exist -> append new property */ + new = malloc(sizeof(struct property)); + if (!new) + return -ENOMEM; + + new->name = strdup(propname); + if (!new->name) + return -ENOMEM; + + new->value = (void *)value; + new->length = len; + new->next = NULL; + + pp_last->next = new; + + return 0; +} + +int ofnode_write_string(ofnode node, const char *propname, const char *value) +{ + if (!of_live_active()) + return -ENOSYS; + + assert(ofnode_valid(node)); + + debug("%s: %s = %s", __func__, propname, value); + + return ofnode_write_prop(node, propname, strlen(value) + 1, value); +} + +int ofnode_set_enabled(ofnode node, bool value) +{ + if (!of_live_active()) + return -ENOSYS; + + assert(ofnode_valid(node)); + + if (value) + return ofnode_write_string(node, "status", "okay"); + else + return ofnode_write_string(node, "status", "disable"); +}