[PATCH] RFC: add function for localbus address

From: Stanimir Varbanov
Date: Tue Sep 02 2014 - 11:46:12 EST


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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/