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/