Hi Grant,

I came down to this. Could you review? Is that
implementation closer to the suggestion made by you.

---
 drivers/of/address.c       |   49 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/of/platform.c      |   20 ++++++++++++++---
 include/linux/of_address.h |   19 +++++++++++++++++
 3 files changed, 84 insertions(+), 4 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index e371825..86c2166 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -601,6 +601,32 @@ const __be32 *of_get_address(struct device_node *dev, int 
index, u64 *size,
 }
 EXPORT_SYMBOL(of_get_address);
 
+const __be32 *of_get_localbus_address(struct device_node *np, int index,
+                                     u64 *size)
+{
+       struct device_node *root, *parent;
+       const __be32 *ranges, *prop = NULL;
+
+       parent = of_get_parent(np);
+       if (!parent)
+               return NULL;
+
+       root = of_find_node_by_path("/");
+
+       if (parent == root) {
+               of_node_put(parent);
+               return NULL;
+       }
+
+       ranges = of_get_property(parent, "ranges", NULL);
+       of_node_put(parent);
+
+       if (!ranges)
+               prop = of_get_address(np, index, size, NULL);
+
+       return prop;
+}
+
 unsigned long __weak pci_address_to_pio(phys_addr_t address)
 {
        if (address > IO_SPACE_LIMIT)
@@ -665,6 +691,29 @@ int of_address_to_resource(struct device_node *dev, int 
index,
 }
 EXPORT_SYMBOL_GPL(of_address_to_resource);
 
+int of_localbus_address_to_resource(struct device_node *dev, int index,
+                                   struct resource *r)
+{
+       const char *name = NULL;
+       const __be32 *addrp;
+       u64 size;
+
+       addrp = of_get_localbus_address(dev, index, &size);
+       if (!addrp)
+               return -EINVAL;
+
+       of_property_read_string_index(dev, "reg-names", index, &name);
+
+       memset(r, 0, sizeof(*r));
+       r->start = be32_to_cpup(addrp);
+       r->end = r->start + size - 1;
+       r->flags = IORESOURCE_REG;
+       r->name = name ? name : dev->full_name;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_localbus_address_to_resource);
+
 struct device_node *of_find_matching_node_by_address(struct device_node *from,
                                        const struct of_device_id *matches,
                                        u64 base_address)
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 0197725..36dcbd7 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -106,8 +106,9 @@ struct platform_device *of_device_alloc(struct device_node 
*np,
                                  struct device *parent)
 {
        struct platform_device *dev;
-       int rc, i, num_reg = 0, num_irq;
+       int rc, i, num_reg = 0, num_localbus_reg = 0, num_irq;
        struct resource *res, temp_res;
+       int num_resources;
 
        dev = platform_device_alloc("", -1);
        if (!dev)
@@ -116,22 +117,33 @@ struct platform_device *of_device_alloc(struct 
device_node *np,
        /* count the io and irq resources */
        while (of_address_to_resource(np, num_reg, &temp_res) == 0)
                num_reg++;
+
+       while (of_localbus_address_to_resource(np,
+                                       num_localbus_reg, &temp_res) == 0)
+               num_localbus_reg++;
+
        num_irq = of_irq_count(np);
 
+       num_resources = num_reg + num_localbus_reg + num_irq;
+
        /* Populate the resource table */
-       if (num_irq || num_reg) {
-               res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
+       if (num_resources) {
+               res = kzalloc(sizeof(*res) * num_resources, GFP_KERNEL);
                if (!res) {
                        platform_device_put(dev);
                        return NULL;
                }
 
-               dev->num_resources = num_reg + num_irq;
+               dev->num_resources = num_resources;
                dev->resource = res;
                for (i = 0; i < num_reg; i++, res++) {
                        rc = of_address_to_resource(np, i, res);
                        WARN_ON(rc);
                }
+               for (i = 0; i < num_localbus_reg; i++, res++) {
+                       rc = of_localbus_address_to_resource(np, i, res);
+                       WARN_ON(rc);
+               }
                if (of_irq_to_resource_table(np, res, num_irq) != num_irq)
                        pr_debug("not all legacy IRQ resources mapped for %s\n",
                                 np->name);
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index fb7b722..10112ea 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -42,6 +42,8 @@ extern u64 of_translate_dma_address(struct device_node *dev,
 extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
 extern int of_address_to_resource(struct device_node *dev, int index,
                                  struct resource *r);
+extern int of_localbus_address_to_resource(struct device_node *dev, int index,
+                                 struct resource *r);
 extern struct device_node *of_find_matching_node_by_address(
                                        struct device_node *from,
                                        const struct of_device_id *matches,
@@ -55,6 +57,9 @@ extern void __iomem *of_iomap(struct device_node *device, int 
index);
 extern const __be32 *of_get_address(struct device_node *dev, int index,
                           u64 *size, unsigned int *flags);
 
+extern const __be32 *of_get_localbus_address(struct device_node *np, int index,
+                          u64 *size);
+
 extern unsigned long pci_address_to_pio(phys_addr_t addr);
 
 extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
@@ -80,6 +85,12 @@ static inline const __be32 *of_get_address(struct 
device_node *dev, int index,
        return NULL;
 }
 
+static inline const __be32 *of_get_localbus_address(struct device_node *dev,
+                                                   int index, u64 *size)
+{
+       return NULL;
+}
+
 static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser,
                        struct device_node *node)
 {
@@ -108,6 +119,8 @@ static inline bool of_dma_is_coherent(struct device_node 
*np)
 #ifdef CONFIG_OF
 extern int of_address_to_resource(struct device_node *dev, int index,
                                  struct resource *r);
+extern int of_localbus_address_to_resource(struct device_node *dev, int index,
+                                 struct resource *r);
 void __iomem *of_iomap(struct device_node *node, int index);
 void __iomem *of_io_request_and_map(struct device_node *device,
                                        int index, char *name);
@@ -121,6 +134,12 @@ static inline int of_address_to_resource(struct 
device_node *dev, int index,
        return -EINVAL;
 }
 
+static inline int of_localbus_address_to_resource(struct device_node *dev,
+                                                 int index, struct resource *r)
+{
+       return -EINVAL;
+}
+
 static inline void __iomem *of_iomap(struct device_node *device, int index)
 {
        return NULL;
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to