static void __init build_device_resources(struct of_device *op, struct device *parent) { struct of_device *p_op; struct of_bus *bus; int na, ns; int index, num_reg; const void *preg; if (!parent) return; p_op = to_of_device(parent); bus = of_match_bus(p_op->node); bus->count_cells(op->node, &na, &ns); preg = of_get_property(op->node, bus->addr_prop_name, &num_reg); if (!preg || num_reg == 0) return; /* Convert to num-cells. */ num_reg /= 4; /* Conver to num-entries. */ num_reg /= na + ns; for (index = 0; index < num_reg; index++) { struct resource *r = &op->resource[index]; u32 addr[OF_MAX_ADDR_CELLS]; const u32 *reg = (preg + (index * ((na + ns) * 4))); struct device_node *dp = op->node; struct device_node *pp = p_op->node; struct of_bus *pbus, *dbus; u64 size, result = OF_BAD_ADDR; unsigned long flags; int dna, dns; int pna, pns; size = of_read_addr(reg + na, ns); flags = bus->get_flags(reg); memcpy(addr, reg, na * 4); /* If the immediate parent has no ranges property to apply, * just use a 1<->1 mapping. */ if (of_find_property(pp, "ranges", NULL) == NULL) { result = of_read_addr(addr, na); goto build_res; } dna = na; dns = ns; dbus = bus; while (1) { dp = pp; pp = dp->parent; if (!pp) { result = of_read_addr(addr, dna); break; } pbus = of_match_bus(pp); pbus->count_cells(dp, &pna, &pns); if (build_one_resource(dp, dbus, pbus, addr, dna, dns, pna)) break; dna = pna; dns = pns; dbus = pbus; } build_res: memset(r, 0, sizeof(*r)); if (of_resource_verbose) printk("%s reg[%d] -> %llx\n", op->node->full_name, index, result); if (result != OF_BAD_ADDR) { r->start = result & 0xffffffff; r->end = result + size - 1; r->flags = flags | ((result >> 32ULL) & 0xffUL); } r->name = op->node->name; }
static void __init build_device_resources(struct platform_device *op, struct device *parent) { struct platform_device *p_op; struct of_bus *bus; int na, ns; int index, num_reg; const void *preg; if (!parent) return; p_op = to_platform_device(parent); bus = of_match_bus(p_op->dev.of_node); bus->count_cells(op->dev.of_node, &na, &ns); preg = of_get_property(op->dev.of_node, bus->addr_prop_name, &num_reg); if (!preg || num_reg == 0) return; num_reg /= 4; num_reg /= na + ns; op->resource = op->archdata.resource; op->num_resources = num_reg; for (index = 0; index < num_reg; index++) { struct resource *r = &op->resource[index]; u32 addr[OF_MAX_ADDR_CELLS]; const u32 *reg = (preg + (index * ((na + ns) * 4))); struct device_node *dp = op->dev.of_node; struct device_node *pp = p_op->dev.of_node; struct of_bus *pbus, *dbus; u64 size, result = OF_BAD_ADDR; unsigned long flags; int dna, dns; int pna, pns; size = of_read_addr(reg + na, ns); memcpy(addr, reg, na * 4); flags = bus->get_flags(reg, 0); if (use_1to1_mapping(pp)) { result = of_read_addr(addr, na); goto build_res; } dna = na; dns = ns; dbus = bus; while (1) { dp = pp; pp = dp->parent; if (!pp) { result = of_read_addr(addr, dna); break; } pbus = of_match_bus(pp); pbus->count_cells(dp, &pna, &pns); if (build_one_resource(dp, dbus, pbus, addr, dna, dns, pna)) break; flags = pbus->get_flags(addr, flags); dna = pna; dns = pns; dbus = pbus; } build_res: memset(r, 0, sizeof(*r)); if (of_resource_verbose) printk("%s reg[%d] -> %llx\n", op->dev.of_node->full_name, index, result); if (result != OF_BAD_ADDR) { r->start = result & 0xffffffff; r->end = result + size - 1; r->flags = flags | ((result >> 32ULL) & 0xffUL); } r->name = op->dev.of_node->name; }