static int __of_address_to_resource(struct device_node *dev, const __be32 *addrp, u64 size, unsigned int flags, const char *name, struct resource *r) { u64 taddr; if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) return -EINVAL; taddr = of_translate_address(dev, addrp); if (taddr == OF_BAD_ADDR) return -EINVAL; memset(r, 0, sizeof(struct resource)); if (flags & IORESOURCE_IO) { unsigned long port; port = pci_address_to_pio(taddr); if (port == (unsigned long)-1) return -EINVAL; r->start = port; r->end = port + size - 1; } else { r->start = taddr; r->end = taddr + size - 1; } r->flags = flags; r->name = name ? name : dev->full_name; return 0; }
static u64 of_translate_ioport(struct device_node *dev, const __be32 *in_addr, u64 size) { u64 taddr; unsigned long port; struct device_node *host; taddr = __of_translate_address(dev, in_addr, "ranges", &host); if (host) { /* host-specific port access */ port = logic_pio_trans_hwaddr(&host->fwnode, taddr, size); of_node_put(host); } else { /* memory-mapped I/O range */ port = pci_address_to_pio(taddr); } if (port == (unsigned long)-1) return OF_BAD_ADDR; return port; }
/* * of_pci_range_to_resource - Create a resource from an of_pci_range * @range: the PCI range that describes the resource * @np: device node where the range belongs to * @res: pointer to a valid resource that will be updated to * reflect the values contained in the range. * * Returns EINVAL if the range cannot be converted to resource. * * Note that if the range is an IO range, the resource will be converted * using pci_address_to_pio() which can fail if it is called too early or * if the range cannot be matched to any host bridge IO space (our case here). * To guard against that we try to register the IO range first. * If that fails we know that pci_address_to_pio() will do too. */ int of_pci_range_to_resource(struct of_pci_range *range, struct device_node *np, struct resource *res) { int err; res->flags = range->flags; res->parent = res->child = res->sibling = NULL; res->name = np->full_name; if (res->flags & IORESOURCE_IO) { unsigned long port; err = pci_register_io_range(&np->fwnode, range->cpu_addr, range->size); if (err) goto invalid_range; port = pci_address_to_pio(range->cpu_addr); if (port == (unsigned long)-1) { err = -EINVAL; goto invalid_range; } res->start = port; } else { if ((sizeof(resource_size_t) < 8) && upper_32_bits(range->cpu_addr)) { err = -EINVAL; goto invalid_range; } res->start = range->cpu_addr; } res->end = res->start + range->size - 1; return 0; invalid_range: res->start = (resource_size_t)OF_BAD_ADDR; res->end = (resource_size_t)OF_BAD_ADDR; return err; }