@@ -13,6 +13,7 @@
#define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0)
static struct of_bus *of_match_bus(struct device_node *np);
+static struct of_bus *of_find_bus(const char *name);
static int __of_address_to_resource(struct device_node *dev,
const __be32 *addrp, u64 size, unsigned int flags,
const char *name, struct resource *r);
@@ -227,6 +228,57 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
}
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
+
+const __be32 *of_pci_process_ranges(struct device_node *node,
+ struct resource *res, const __be32 *from)
+{
+ const __be32 *start, *end;
+ int na, ns, np, pna;
+ int rlen;
+ struct of_bus *bus;
+
+ WARN_ON(!res);
+
+ bus = of_find_bus("pci");
+ bus->count_cells(node, &na, &ns);
+ if (!OF_CHECK_COUNTS(na, ns)) {
+ pr_err("Bad cell count for %s\n", node->full_name);
+ return NULL;
+ }
+
+ pna = of_n_addr_cells(node);
+ np = pna + na + ns;
+
+ start = of_get_property(node, "ranges", &rlen);
+ if (start == NULL)
+ return NULL;
+
+ end = start + rlen / sizeof(__be32);
+
+ if (!from)
+ from = start;
+
+ while (from + np <= end) {
+ u64 cpu_addr, size;
+
+ cpu_addr = of_translate_address(node, from + na);
+ size = of_read_number(from + na + pna, ns);
+ res->flags = bus->get_flags(from);
+ from += np;
+
+ if (cpu_addr == OF_BAD_ADDR || size == 0)
+ continue;
+
+ res->name = node->full_name;
+ res->start = cpu_addr;
+ res->end = res->start + size - 1;
+ res->parent = res->child = res->sibling = NULL;
+ return from;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(of_pci_process_ranges);
#endif /* CONFIG_PCI */
/*
@@ -337,6 +389,17 @@ static struct of_bus *of_match_bus(struct device_node *np)
return NULL;
}
+static struct of_bus *of_find_bus(const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(of_busses); i++)
+ if (strcmp(name, of_busses[i].name) == 0)
+ return &of_busses[i];
+
+ return NULL;
+}
+
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)
@@ -27,6 +27,8 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
#define pci_address_to_pio pci_address_to_pio
#endif
+const __be32 *of_pci_process_ranges(struct device_node *node,
+ struct resource *res, const __be32 *from);
#else /* CONFIG_OF_ADDRESS */
#ifndef of_address_to_resource
static inline int of_address_to_resource(struct device_node *dev, int index,
@@ -53,6 +55,13 @@ static inline const __be32 *of_get_address(struct device_node *dev, int index,
{
return NULL;
}
+
+static inline const __be32 *of_pci_process_ranges(struct device_node *node,
+ struct resource *res,
+ const __be32 *from)
+{
+ return NULL;
+}
#endif /* CONFIG_OF_ADDRESS */