static u64 __init fdt_bus_default_map(__be32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; cp = of_read_number(range, na); s = of_read_number(range + na + pna, ns); da = of_read_number(addr, na); pr_debug("FDT: default map, cp=%llx, s=%llx, da=%llx\n", cp, s, da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; return da - cp; }
static void traverse_siblings_chip_id(int cpu, bool add, int chipid) { const struct cpumask *mask; struct device_node *np; int i, plen; const __be32 *prop; mask = add ? cpu_online_mask : cpu_present_mask; for_each_cpu(i, mask) { np = of_get_cpu_node(i, NULL); if (!np) continue; prop = of_get_property(np, "ibm,chip-id", &plen); if (prop && plen == sizeof(int) && of_read_number(prop, 1) == chipid) { if (add) { cpumask_set_cpu(cpu, cpu_core_mask(i)); cpumask_set_cpu(i, cpu_core_mask(cpu)); } else { cpumask_clear_cpu(cpu, cpu_core_mask(i)); cpumask_clear_cpu(i, cpu_core_mask(cpu)); } } of_node_put(np); }
static u64 __init of_get_cpu_mpidr(struct device_node *dn) { const __be32 *cell; u64 hwid; /* * A cpu node with missing "reg" property is * considered invalid to build a cpu_logical_map * entry. */ cell = of_get_property(dn, "reg", NULL); if (!cell) { pr_err("%s: missing reg property\n", dn->full_name); return INVALID_HWID; } hwid = of_read_number(cell, of_n_addr_cells(dn)); /* * Non affinity bits must be set to 0 in the DT */ if (hwid & ~MPIDR_HWID_BITMASK) { pr_err("%s: invalid reg property\n", dn->full_name); return INVALID_HWID; } return hwid; }
static int of_translate_one(struct device_node *parent, struct of_bus *bus, struct of_bus *pbus, __be32 *addr, int na, int ns, int pna, const char *rprop) { const __be32 *ranges; unsigned int rlen; int rone; u64 offset = OF_BAD_ADDR; /* * Normally, an absence of a "ranges" property means we are * crossing a non-translatable boundary, and thus the addresses * below the current cannot be converted to CPU physical ones. * Unfortunately, while this is very clear in the spec, it's not * what Apple understood, and they do have things like /uni-n or * /ht nodes with no "ranges" property and a lot of perfectly * useable mapped devices below them. Thus we treat the absence of * "ranges" as equivalent to an empty "ranges" property which means * a 1:1 translation at that level. It's up to the caller not to try * to translate addresses that aren't supposed to be translated in * the first place. --BenH. * * As far as we know, this damage only exists on Apple machines, so * This code is only enabled on powerpc. --gcl */ ranges = of_get_property(parent, rprop, &rlen); if (ranges == NULL && !of_empty_ranges_quirk(parent)) { pr_debug("no ranges; cannot translate\n"); return 1; } if (ranges == NULL || rlen == 0) { offset = of_read_number(addr, na); memset(addr, 0, pna * 4); pr_debug("empty ranges; 1:1 translation\n"); goto finish; } pr_debug("walking ranges...\n"); /* Now walk through the ranges */ rlen /= 4; rone = na + pna + ns; for (; rlen >= rone; rlen -= rone, ranges += rone) { offset = bus->map(addr, ranges, na, ns, pna); if (offset != OF_BAD_ADDR) break; } if (offset == OF_BAD_ADDR) { pr_debug("not found !\n"); return 1; } memcpy(addr, ranges + na, 4 * pna); finish: of_dump_addr("parent translation for:", addr, pna); pr_debug("with offset: %llx\n", (unsigned long long)offset); /* Translate it into parent bus space */ return pbus->translate(addr, offset, pna); }
/** * fdt_init_reserved_mem - allocate and init all saved reserved memory regions */ void __init fdt_init_reserved_mem(void) { int i; /* check for overlapping reserved regions */ __rmem_check_for_overlap(); for (i = 0; i < reserved_mem_count; i++) { struct reserved_mem *rmem = &reserved_mem[i]; unsigned long node = rmem->fdt_node; int len; const __be32 *prop; int err = 0; prop = of_get_flat_dt_prop(node, "phandle", &len); if (!prop) prop = of_get_flat_dt_prop(node, "linux,phandle", &len); if (prop) rmem->phandle = of_read_number(prop, len/4); if (rmem->size == 0) err = __reserved_mem_alloc_size(node, rmem->name, &rmem->base, &rmem->size); if (err == 0) __reserved_mem_init_node(rmem); } }
/** * of_property_read_variable_u64_array - Find and read an array of 64 bit * integers from a property, with bounds on the minimum and maximum array size. * * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. * @out_values: pointer to return value, modified only if return value is 0. * @sz_min: minimum number of array elements to read * @sz_max: maximum number of array elements to read, if zero there is no * upper limit on the number of elements in the dts entry but only * sz_min will be read. * * Search for a property in a device node and read 64-bit value(s) from * it. Returns number of elements read on success, -EINVAL if the property * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW * if the property data is smaller than sz_min or longer than sz_max. * * The out_values is modified only if a valid u64 value can be decoded. */ int of_property_read_variable_u64_array(const struct device_node *np, const char *propname, u64 *out_values, size_t sz_min, size_t sz_max) { size_t sz, count; const __be32 *val = of_find_property_value_of_size(np, propname, (sz_min * sizeof(*out_values)), (sz_max * sizeof(*out_values)), &sz); if (IS_ERR(val)) return PTR_ERR(val); if (!sz_max) sz = sz_min; else sz /= sizeof(*out_values); count = sz; while (count--) { *out_values++ = of_read_number(val, 2); val += 2; } return sz; }
u64 __init dt_mem_next_cell(int s, const __be32 **cellp) { const __be32 *p = *cellp; *cellp = p + s; return of_read_number(p, s); }
static void __init __walk_drmem_v2_lmbs(const __be32 *prop, const __be32 *usm, void (*func)(struct drmem_lmb *, const __be32 **)) { struct of_drconf_cell_v2 dr_cell; struct drmem_lmb lmb; u32 i, j, lmb_sets; lmb_sets = of_read_number(prop++, 1); if (lmb_sets == 0) return; for (i = 0; i < lmb_sets; i++) { read_drconf_v2_cell(&dr_cell, &prop); for (j = 0; j < dr_cell.seq_lmbs; j++) { lmb.base_addr = dr_cell.base_addr; dr_cell.base_addr += drmem_lmb_size(); lmb.drc_index = dr_cell.drc_index; dr_cell.drc_index++; lmb.aa_index = dr_cell.aa_index; lmb.flags = dr_cell.flags; func(&lmb, &usm); } } }
static u64 of_bus_default_map(u32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; cp = of_read_number(range, na); s = of_read_number(range + na + pna, ns); da = of_read_number(addr, na); pr_debug("OF: default map, cp=%llx, s=%llx, da=%llx\n", (unsigned long long)cp, (unsigned long long)s, (unsigned long long)da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; return da - cp; }
/** * of_device_make_bus_id - Use the device node data to assign a unique name * @dev: pointer to device structure that is linked to a device tree node * * This routine will first try using either the dcr-reg or the reg property * value to derive a unique name. As a last resort it will use the node * name followed by a unique number. */ void of_device_make_bus_id(struct device *dev) { static atomic_t bus_no_reg_magic; struct device_node *node = dev->of_node; const __be32 *reg; u64 addr; const __be32 *addrp; int magic; #ifdef CONFIG_PPC_DCR /* * If it's a DCR based device, use 'd' for native DCRs * and 'D' for MMIO DCRs. */ reg = of_get_property(node, "dcr-reg", NULL); if (reg) { #ifdef CONFIG_PPC_DCR_NATIVE dev_set_name(dev, "d%x.%s", *reg, node->name); #else /* CONFIG_PPC_DCR_NATIVE */ u64 addr = of_translate_dcr_address(node, *reg, NULL); if (addr != OF_BAD_ADDR) { dev_set_name(dev, "D%llx.%s", (unsigned long long)addr, node->name); return; } #endif /* !CONFIG_PPC_DCR_NATIVE */ } #endif /* CONFIG_PPC_DCR */ /* * For MMIO, get the physical address */ reg = of_get_property(node, "reg", NULL); if (reg) { if (of_can_translate_address(node)) { addr = of_translate_address(node, reg); } else { addrp = of_get_address(node, 0, NULL, NULL); if (addrp) addr = of_read_number(addrp, 1); else addr = OF_BAD_ADDR; } if (addr != OF_BAD_ADDR) { dev_set_name(dev, "%llx.%s", (unsigned long long)addr, node->name); return; } } /* * No BusID, use the node name and add a globally incremented * counter (and pray...) */ magic = atomic_add_return(1, &bus_no_reg_magic); dev_set_name(dev, "%s.%d", node->name, magic - 1); }
struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser, struct of_pci_range *range) { const int na = 3, ns = 2; if (!range) return NULL; if (!parser->range || parser->range + parser->np > parser->end) return NULL; range->pci_space = parser->range[0]; range->flags = of_bus_pci_get_flags(parser->range); range->pci_addr = of_read_number(parser->range + 1, ns); range->cpu_addr = of_translate_address(parser->node, parser->range + na); range->size = of_read_number(parser->range + parser->pna + na, ns); parser->range += parser->np; /* Now consume following elements while they are contiguous */ while (parser->range + parser->np <= parser->end) { u32 flags, pci_space; u64 pci_addr, cpu_addr, size; pci_space = be32_to_cpup(parser->range); flags = of_bus_pci_get_flags(parser->range); pci_addr = of_read_number(parser->range + 1, ns); cpu_addr = of_translate_address(parser->node, parser->range + na); size = of_read_number(parser->range + parser->pna + na, ns); if (flags != range->flags) break; if (pci_addr != range->pci_addr + range->size || cpu_addr != range->cpu_addr + range->size) break; range->size += size; parser->range += parser->np; } return range; }
/** * get_int_prop - Decode a u32 from a device tree property */ static u32 get_int_prop(struct device_node *np, const char *name, u32 def) { const __be32 *prop; int len; prop = of_get_property(np, name, &len); if (prop && len >= 4) return of_read_number(prop, 1); return def; }
static unsigned long read_n_cells(int n, const __be32 **buf) { unsigned long result = 0; while (n--) { result = (result << 32) | of_read_number(*buf, 1); (*buf)++; } return result; }
static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna) { u64 cp, s, da; /* Check address type match */ if ((addr[0] ^ range[0]) & 0x00000001) return OF_BAD_ADDR; /* Read address values, skipping high cell */ cp = of_read_number(range + 1, na - 1); s = of_read_number(range + na + pna, ns); da = of_read_number(addr + 1, na - 1); DBG("OF: ISA map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; return da - cp; }
static void hwadp_dts_register_base_addr(void) { struct device_node *node = NULL, *np = NULL; int retval = 0; const char * nmi_node = "hisilicon,mdrv_nmi_interrupt_regs"; unsigned int nmi_regs_val[NMI_INT_CORE_NUM] = {0,}; node = of_find_compatible_node(NULL, NULL, "hisilicon,hardware_adapt"); if (!node) { hwadp_printf("dts node not found!\n"); return; } for_each_available_child_of_node(node, np) { unsigned int ip_type = ~0U, int_type = ~0U, irq_num = ~0U; int na = 0, ns = 0, len = 0; unsigned long base_addr = 0; const __be32 *prop = NULL; if(!np->name || !strlen(np->name)) continue; /* try to obtain ip base address */ na = of_n_addr_cells(np); ns = of_n_size_cells(np); prop = of_get_property(np, "reg", &len); retval = of_property_read_u32(np, "ip_type", &ip_type); if(prop && (len == (na + ns) * (int)sizeof(*prop))) { base_addr = (unsigned long)of_read_number(prop, na); if(base_addr && !(base_addr & ((0x1U << 12) - 1))) (void)of_iomap(np, 0); else hwadp_printf("hwad:reg addr = 0x%X Address of zero or that ones not aligned for page are not map!\n",base_addr); if(retval) ip_type = ~0U; retval = bsp_hwadp_register_base_addr(ip_type, (const char *)np->name, (void *)base_addr); if(retval) hwadp_printf("hwadp:failed to register base addr!ip_type=%d base_addr=%p name=%s\n",(int)ip_type, (void*)base_addr,np->name); continue; } /* try to obtain irq number */ retval = of_property_read_u32_index(np, "interrupts", 1, &irq_num); if(retval) continue; retval = of_property_read_u32(np, "int_type", &int_type); if(retval) int_type = ~0U; if(bsp_hwadp_register_irq_num(int_type, (const char *)np->name, irq_num)) hwadp_printf("hwadp:failed to register irq number!int_type=%d irq_num=%d name=%s\n", (int)int_type, irq_num, np->name); }
static int of_bus_default_translate(__be32 *addr, u64 offset, int na) { u64 a = of_read_number(addr, na); memset(addr, 0, na * 4); a += offset; if (na > 1) addr[na - 2] = cpu_to_be32(a >> 32); addr[na - 1] = cpu_to_be32(a & 0xffffffffu); return 0; }
void __init hvc_vio_init_early(void) { const __be32 *termno; const char *name; const struct hv_ops *ops; /* find the boot console from /chosen/stdout */ if (!of_stdout) return; name = of_get_property(of_stdout, "name", NULL); if (!name) { printk(KERN_WARNING "stdout node missing 'name' property!\n"); return; } /* Check if it's a virtual terminal */ if (strncmp(name, "vty", 3) != 0) return; termno = of_get_property(of_stdout, "reg", NULL); if (termno == NULL) return; hvterm_priv0.termno = of_read_number(termno, 1); spin_lock_init(&hvterm_priv0.buf_lock); hvterm_privs[0] = &hvterm_priv0; /* Check the protocol */ if (of_device_is_compatible(of_stdout, "hvterm1")) { hvterm_priv0.proto = HV_PROTOCOL_RAW; ops = &hvterm_raw_ops; } else if (of_device_is_compatible(of_stdout, "hvterm-protocol")) { hvterm_priv0.proto = HV_PROTOCOL_HVSI; ops = &hvterm_hvsi_ops; hvsilib_init(&hvterm_priv0.hvsi, hvc_get_chars, hvc_put_chars, hvterm_priv0.termno, 1); /* HVSI, perform the handshake now */ hvsilib_establish(&hvterm_priv0.hvsi); } else return; udbg_putc = udbg_hvc_putc; udbg_getc = udbg_hvc_getc; udbg_getc_poll = udbg_hvc_getc_poll; #ifdef HVC_OLD_HVSI /* When using the old HVSI driver don't register the HVC * backend for HVSI, only do udbg */ if (hvterm_priv0.proto == HV_PROTOCOL_HVSI) return; #endif /* Check whether the user has requested a different console. */ if (!strstr(boot_command_line, "console=")) add_preferred_console("hvc", 0, NULL); hvc_instantiate(0, 0, ops); }
static int read_phys_addr(struct device_node *np, char *prop_name, struct cxl_afu *afu) { int i, len, entry_size, naddr, nsize, type; u64 addr, size; const __be32 *prop; naddr = of_n_addr_cells(np); nsize = of_n_size_cells(np); prop = of_get_property(np, prop_name, &len); if (prop) { entry_size = naddr + nsize; for (i = 0; i < (len / 4); i += entry_size, prop += entry_size) { type = be32_to_cpu(prop[0]); addr = of_read_number(prop, naddr); size = of_read_number(&prop[naddr], nsize); switch (type) { case 0: /* unit address */ afu->guest->handle = addr; break; case 1: /* p2 area */ afu->guest->p2n_phys += addr; afu->guest->p2n_size = size; break; case 2: /* problem state area */ afu->psn_phys += addr; afu->adapter->ps_size = size; break; default: pr_err("Invalid address type %d found in %s property of AFU\n", type, prop_name); return -EINVAL; } if (cxl_verbose) pr_info("%s: %#x %#llx (size %#llx)\n", prop_name, type, addr, size); } } return 0; }
int __init early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data) { const void *basep, *entryp, *sizep; int basesz, entrysz, runtimesz; if (depth != 1 || strcmp(uname, "ibm,opal") != 0) return 0; basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz); entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz); sizep = of_get_flat_dt_prop(node, "opal-runtime-size", &runtimesz); if (!basep || !entryp || !sizep) return 1; opal.base = of_read_number(basep, basesz/4); opal.entry = of_read_number(entryp, entrysz/4); opal.size = of_read_number(sizep, runtimesz/4); pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%d)\n", opal.base, basep, basesz); pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%d)\n", opal.entry, entryp, entrysz); pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%d)\n", opal.size, sizep, runtimesz); powerpc_firmware_features |= FW_FEATURE_OPAL; if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) { powerpc_firmware_features |= FW_FEATURE_OPALv2; powerpc_firmware_features |= FW_FEATURE_OPALv3; printk("OPAL V3 detected !\n"); } else if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { powerpc_firmware_features |= FW_FEATURE_OPALv2; printk("OPAL V2 detected !\n"); } else { printk("OPAL V1 detected !\n"); } return 1; }
static int mnemosyne_parse_dt(struct device_node *node) { phys_addr_t phys = 0, size = 0; struct device_node *pnode = NULL; int ret; pr_info("%s: init from device tree.\n", MNEMOSYNE_MODULE_NAME); if (node == NULL) { pr_err("%s: Can't find device_node", MNEMOSYNE_MODULE_NAME); ret = -ENODEV; goto PARSE_DT_ERR_OUT; } pnode = of_parse_phandle(node, "linux,contiguous-region", 0); if (!pnode) { pr_err("%s: mnemosyne memory is not reserved.\n", MNEMOSYNE_MODULE_NAME); } else { const __be32 *prop; int addr_cells, size_cells; prop = of_get_address(pnode, 0, NULL, NULL); if (!prop) { pr_err("%s: Can't find register property", MNEMOSYNE_MODULE_NAME); ret = -ENODEV; of_node_put(pnode); goto PARSE_DT_ERR_OUT; } of_node_put(pnode); addr_cells = of_n_addr_cells(pnode); size_cells = of_n_size_cells(pnode); phys = of_read_number(prop, addr_cells); size = of_read_number(prop + addr_cells, size_cells); } ret = mnemosyne_setup(phys, size); PARSE_DT_ERR_OUT: return ret; }
/** * of_property_read_u64 - Find and read a 64 bit integer from a property * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. * @out_value: pointer to return value, modified only if return value is 0. * * Search for a property in a device node and read a 64-bit value from * it. Returns 0 on success, -EINVAL if the property does not exist, * -ENODATA if property does not have a value, and -EOVERFLOW if the * property data isn't large enough. * * The out_value is modified only if a valid u64 value can be decoded. */ int of_property_read_u64(const struct device_node *np, const char *propname, u64 *out_value) { const __be32 *val = of_find_property_value_of_size(np, propname, sizeof(*out_value)); if (IS_ERR(val)) return PTR_ERR(val); *out_value = of_read_number(val, 2); return 0; }
/* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa * info is found. */ static int associativity_to_nid(const __be32 *associativity) { int nid = -1; if (min_common_depth == -1) goto out; if (of_read_number(associativity, 1) >= min_common_depth) nid = of_read_number(&associativity[min_common_depth], 1); /* POWER4 LPAR uses 0xffff as invalid node */ if (nid == 0xffff || nid >= MAX_NUMNODES) nid = -1; if (nid > 0 && of_read_number(associativity, 1) >= distance_ref_points_depth) initialize_distance_lookup_table(nid, associativity); out: return nid; }
static int of_translate_one(struct device_node *parent, struct of_bus *bus, struct of_bus *pbus, u32 *addr, int na, int ns, int pna) { const u32 *ranges; unsigned int rlen; int rone; u64 offset = OF_BAD_ADDR; /* Normally, an absence of a "ranges" property means we are * crossing a non-translatable boundary, and thus the addresses * below the current not cannot be converted to CPU physical ones. * Unfortunately, while this is very clear in the spec, it's not * what Apple understood, and they do have things like /uni-n or * /ht nodes with no "ranges" property and a lot of perfectly * useable mapped devices below them. Thus we treat the absence of * "ranges" as equivalent to an empty "ranges" property which means * a 1:1 translation at that level. It's up to the caller not to try * to translate addresses that aren't supposed to be translated in * the first place. --BenH. */ ranges = of_get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) { offset = of_read_number(addr, na); memset(addr, 0, pna * 4); DBG("OF: no ranges, 1:1 translation\n"); goto finish; } DBG("OF: walking ranges...\n"); /* Now walk through the ranges */ rlen /= 4; rone = na + pna + ns; for (; rlen >= rone; rlen -= rone, ranges += rone) { offset = bus->map(addr, ranges, na, ns, pna); if (offset != OF_BAD_ADDR) break; } if (offset == OF_BAD_ADDR) { DBG("OF: not found !\n"); return 1; } memcpy(addr, ranges + na, 4 * pna); finish: of_dump_addr("OF: parent translation for:", addr, pna); DBG("OF: with offset: "PRu64"\n", offset); /* Translate it into parent bus space */ return pbus->translate(addr, offset, pna); }
static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; /* Check address type match */ if ((addr[0] ^ range[0]) & cpu_to_be32(1)) return OF_BAD_ADDR; /* Read address values, skipping high cell */ cp = of_read_number(range + 1, na - 1); s = of_read_number(range + na + pna, ns); da = of_read_number(addr + 1, na - 1); pr_debug("ISA map, cp=%llx, s=%llx, da=%llx\n", (unsigned long long)cp, (unsigned long long)s, (unsigned long long)da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; return da - cp; }
/* * Retrieve and validate the list of associativity arrays for drconf * memory from the ibm,associativity-lookup-arrays property of the * device tree.. * * The layout of the ibm,associativity-lookup-arrays property is a number N * indicating the number of associativity arrays, followed by a number M * indicating the size of each associativity array, followed by a list * of N associativity arrays. */ static int of_get_assoc_arrays(struct device_node *memory, struct assoc_arrays *aa) { const __be32 *prop; u32 len; prop = of_get_property(memory, "ibm,associativity-lookup-arrays", &len); if (!prop || len < 2 * sizeof(unsigned int)) return -1; aa->n_arrays = of_read_number(prop++, 1); aa->array_sz = of_read_number(prop++, 1); /* Now that we know the number of arrays and size of each array, * revalidate the size of the property read in. */ if (len < (aa->n_arrays * aa->array_sz + 2) * sizeof(unsigned int)) return -1; aa->arrays = prop; return 0; }
static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; if ((addr[0] ^ range[0]) & cpu_to_be32(1)) return OF_BAD_ADDR; cp = of_read_number(range + 1, na - 1); s = of_read_number(range + na + pna, ns); da = of_read_number(addr + 1, na - 1); pr_debug("OF: ISA map, cp=%llx, s=%llx, da=%llx\n", (unsigned long long)cp, (unsigned long long)s, (unsigned long long)da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; return da - cp; }
/** * early_init_dt_check_for_initrd - Decode initrd location from flat tree * @node: reference to node containing initrd location ('chosen') */ void __init early_init_dt_check_for_initrd(unsigned long node) { u64 start, end; int len; const __be32 *prop; pr_debug("Looking for initrd properties... "); prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len); if (!prop) return; start = of_read_number(prop, len/4); prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len); if (!prop) return; end = of_read_number(prop, len/4); early_init_dt_setup_initrd_arch(start, end); pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", (unsigned long long)start, (unsigned long long)end); }
/** * of_property_read_u64 - Find and read a 64 bit integer from a property * @np: device node from which the property value is to be read. * @propname: name of the property to be sea rched. * @out_value: pointer to return value, modified only if return value is 0. * * Search for a property in a device node and read a 64-bit value from * it. Returns 0 on success, -EINVAL if the property does not exist, * -ENODATA if property does not have a value, and -EOVERFLOW if the * property data isn't large enough. * * The out_value is modified only if a valid u64 value can be decoded. */ int of_property_read_u64(const struct device_node *np, const char *propname, u64 *out_value) { struct property *prop = of_find_property(np, propname, NULL); if (!prop) return -EINVAL; if (!prop->value) return -ENODATA; if (sizeof(*out_value) > prop->length) return -EOVERFLOW; *out_value = of_read_number(prop->value, 2); return 0; }
static int read_handle(struct device_node *np, u64 *handle) { const __be32 *prop; u64 size; /* Get address and size of the node */ prop = of_get_address(np, 0, &size, NULL); if (size) return -EINVAL; /* Helper to read a big number; size is in cells (not bytes) */ *handle = of_read_number(prop, of_n_addr_cells(np)); return 0; }
void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, unsigned long *busno, unsigned long *phys, unsigned long *size) { u32 *dma_window, cells; unsigned char *prop; dma_window = (u32 *)dma_window_prop; /* busno is always one cell */ *busno = *(dma_window++); prop = get_property(dn, "ibm,#dma-address-cells", NULL); if (!prop) prop = get_property(dn, "#address-cells", NULL); cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); *phys = of_read_number(dma_window, cells); dma_window += cells; prop = get_property(dn, "ibm,#dma-size-cells", NULL); cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); *size = of_read_number(dma_window, cells); }