bool of_can_translate_address(struct device_node *dev) { struct device_node *parent; struct of_bus *bus; int na, ns; parent = of_get_parent(dev); if (parent == NULL) return false; bus = of_match_bus(parent); bus->count_cells(dev, &na, &ns); of_node_put(parent); return OF_CHECK_COUNTS(na, ns); }
const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, unsigned int *flags) { const __be32 *prop; unsigned int psize; struct device_node *parent; struct of_bus *bus; int onesize, i, na, ns; /* Get parent & match bus type */ parent = of_get_parent(dev); if (parent == NULL) return NULL; bus = of_match_bus(parent); if (strcmp(bus->name, "pci")) { of_node_put(parent); return NULL; } bus->count_cells(dev, &na, &ns); of_node_put(parent); if (!OF_CHECK_ADDR_COUNT(na)) return NULL; /* Get "reg" or "assigned-addresses" property */ prop = of_get_property(dev, bus->addresses, &psize); if (prop == NULL) return NULL; psize /= 4; onesize = na + ns; for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) { u32 val = be32_to_cpu(prop[0]); if ((val & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { if (size) *size = of_read_number(prop + na, ns); if (flags) *flags = bus->get_flags(prop); return prop; } } return NULL; }
const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags) { const __be32 *prop; unsigned int psize; struct device_node *parent; struct of_bus *bus; int onesize, i, na, ns; /* Get parent & match bus type */ parent = of_get_parent(dev); if (parent == NULL) return NULL; bus = of_match_bus(parent); bus->count_cells(dev, &na, &ns); of_node_put(parent); if (!OF_CHECK_ADDR_COUNT(na)) return NULL; /* Get "reg" or "assigned-addresses" property */ prop = of_get_property(dev, bus->addresses, &psize); if (prop == NULL) return NULL; psize /= 4; onesize = na + ns; for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) if (i == index) { if (size) *size = of_read_number(prop + na, ns); if (flags) *flags = bus->get_flags(prop); return prop; } return NULL; }
/* * Translate an address from the device-tree into a CPU physical address, * this walks up the tree and applies the various bus mappings on the * way. * * Note: We consider that crossing any level with #size-cells == 0 to mean * that translation is impossible (that is we are not dealing with a value * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things */ static u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, const char *rprop) { struct device_node *parent = NULL; struct of_bus *bus, *pbus; __be32 addr[OF_MAX_ADDR_CELLS]; int na, ns, pna, pns; u64 result = OF_BAD_ADDR; pr_debug("** translation for device %pOF **\n", dev); /* Increase refcount at current level */ of_node_get(dev); /* Get parent & match bus type */ parent = of_get_parent(dev); if (parent == NULL) goto bail; bus = of_match_bus(parent); /* Count address cells & copy address locally */ bus->count_cells(dev, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { pr_debug("Bad cell count for %pOF\n", dev); goto bail; } memcpy(addr, in_addr, na * 4); pr_debug("bus is %s (na=%d, ns=%d) on %pOF\n", bus->name, na, ns, parent); of_dump_addr("translating address:", addr, na); /* Translate */ for (;;) { /* Switch to parent bus */ of_node_put(dev); dev = parent; parent = of_get_parent(dev); /* If root, we have finished */ if (parent == NULL) { pr_debug("reached root node\n"); result = of_read_number(addr, na); break; } /* Get new parent bus and counts */ pbus = of_match_bus(parent); pbus->count_cells(dev, &pna, &pns); if (!OF_CHECK_COUNTS(pna, pns)) { pr_err("Bad cell count for %pOF\n", dev); break; } pr_debug("parent bus is %s (na=%d, ns=%d) on %pOF\n", pbus->name, pna, pns, parent); /* Apply bus translation */ if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) break; /* Complete the move up one level */ na = pna; ns = pns; bus = pbus; of_dump_addr("one level translation:", addr, na); } bail: of_node_put(parent); of_node_put(dev); return result; }
/* * Translate an address from the device-tree into a CPU physical address, * this walks up the tree and applies the various bus mappings on the * way. * * Note: We consider that crossing any level with #size-cells == 0 to mean * that translation is impossible (that is we are not dealing with a value * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things */ u64 of_translate_address(struct device_node *dev, const u32 *in_addr) { struct device_node *parent = NULL; struct of_bus *bus, *pbus; u32 addr[OF_MAX_ADDR_CELLS]; int na, ns, pna, pns; u64 result = OF_BAD_ADDR; DBG("OF: ** translation for device %s **\n", dev->full_name); /* Increase refcount at current level */ of_node_get(dev); /* Get parent & match bus type */ parent = of_get_parent(dev); if (parent == NULL) goto bail; bus = of_match_bus(parent); /* Cound address cells & copy address locally */ bus->count_cells(dev, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printk(KERN_ERR "prom_parse: Bad cell count for %s\n", dev->full_name); goto bail; } memcpy(addr, in_addr, na * 4); DBG("OF: bus is %s (na=%d, ns=%d) on %s\n", bus->name, na, ns, parent->full_name); of_dump_addr("OF: translating address:", addr, na); /* Translate */ for (;;) { /* Switch to parent bus */ of_node_put(dev); dev = parent; parent = of_get_parent(dev); /* If root, we have finished */ if (parent == NULL) { DBG("OF: reached root node\n"); result = of_read_number(addr, na); break; } /* Get new parent bus and counts */ pbus = of_match_bus(parent); pbus->count_cells(dev, &pna, &pns); if (!OF_CHECK_COUNTS(pna, pns)) { printk(KERN_ERR "prom_parse: Bad cell count for %s\n", dev->full_name); break; } DBG("OF: parent bus is %s (na=%d, ns=%d) on %s\n", pbus->name, pna, pns, parent->full_name); /* Apply bus translation */ if (of_translate_one(dev, bus, pbus, addr, na, ns, pna)) break; /* Complete the move up one level */ na = pna; ns = pns; bus = pbus; of_dump_addr("OF: one level translation:", addr, na); } bail: of_node_put(parent); of_node_put(dev); return result; }
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; }
/* * Translate an address from the device-tree into a CPU physical address, * this walks up the tree and applies the various bus mappings on the * way. * * Note: We consider that crossing any level with #size-cells == 0 to mean * that translation is impossible (that is we are not dealing with a value * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things * * Whenever the translation fails, the *host pointer will be set to the * device that had registered logical PIO mapping, and the return code is * relative to that node. */ static u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, const char *rprop, struct device_node **host) { struct device_node *parent = NULL; struct of_bus *bus, *pbus; __be32 addr[OF_MAX_ADDR_CELLS]; int na, ns, pna, pns; u64 result = OF_BAD_ADDR; pr_debug("** translation for device %pOF **\n", dev); /* Increase refcount at current level */ of_node_get(dev); *host = NULL; /* Get parent & match bus type */ parent = of_get_parent(dev); if (parent == NULL) goto bail; bus = of_match_bus(parent); /* Count address cells & copy address locally */ bus->count_cells(dev, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { pr_debug("Bad cell count for %pOF\n", dev); goto bail; } memcpy(addr, in_addr, na * 4); pr_debug("bus is %s (na=%d, ns=%d) on %pOF\n", bus->name, na, ns, parent); of_dump_addr("translating address:", addr, na); /* Translate */ for (;;) { struct logic_pio_hwaddr *iorange; /* Switch to parent bus */ of_node_put(dev); dev = parent; parent = of_get_parent(dev); /* If root, we have finished */ if (parent == NULL) { pr_debug("reached root node\n"); result = of_read_number(addr, na); break; } /* * For indirectIO device which has no ranges property, get * the address from reg directly. */ iorange = find_io_range_by_fwnode(&dev->fwnode); if (iorange && (iorange->flags != LOGIC_PIO_CPU_MMIO)) { result = of_read_number(addr + 1, na - 1); pr_debug("indirectIO matched(%pOF) 0x%llx\n", dev, result); *host = of_node_get(dev); break; } /* Get new parent bus and counts */ pbus = of_match_bus(parent); pbus->count_cells(dev, &pna, &pns); if (!OF_CHECK_COUNTS(pna, pns)) { pr_err("Bad cell count for %pOF\n", dev); break; } pr_debug("parent bus is %s (na=%d, ns=%d) on %pOF\n", pbus->name, pna, pns, parent); /* Apply bus translation */ if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) break; /* Complete the move up one level */ na = pna; ns = pns; bus = pbus; of_dump_addr("one level translation:", addr, na); } bail: of_node_put(parent); of_node_put(dev); return result; }
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; }
u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, const char *rprop) { struct device_node *parent = NULL; struct of_bus *bus, *pbus; u32 addr[OF_MAX_ADDR_CELLS]; int na, ns, pna, pns; u64 result = OF_BAD_ADDR; pr_debug("OF: ** translation for device %s **\n", dev->full_name); of_node_get(dev); parent = of_get_parent(dev); if (parent == NULL) goto bail; bus = of_match_bus(parent); bus->count_cells(dev, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printk(KERN_ERR "prom_parse: Bad cell count for %s\n", dev->full_name); goto bail; } memcpy(addr, in_addr, na * 4); pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n", bus->name, na, ns, parent->full_name); of_dump_addr("OF: translating address:", addr, na); for (;;) { of_node_put(dev); dev = parent; parent = of_get_parent(dev); if (parent == NULL) { pr_debug("OF: reached root node\n"); result = of_read_number(addr, na); break; } pbus = of_match_bus(parent); pbus->count_cells(dev, &pna, &pns); if (!OF_CHECK_COUNTS(pna, pns)) { printk(KERN_ERR "prom_parse: Bad cell count for %s\n", dev->full_name); break; } pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n", pbus->name, pna, pns, parent->full_name); if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) break; na = pna; ns = pns; bus = pbus; of_dump_addr("OF: one level translation:", addr, na); } bail: of_node_put(parent); of_node_put(dev); return result; }