diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-04-22 08:58:37 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-04-22 09:23:50 +0200 |
commit | 6d1788ab34c91279c1a277cb1a10f3e95a59b96e (patch) | |
tree | e80a5da51e600577bcffd7f277eb97ab2609fac7 | |
parent | 266dea34a53bf985ff851662309b5c07c250b4d0 (diff) | |
download | barebox-6d1788ab34c91279c1a277cb1a10f3e95a59b96e.tar.gz barebox-6d1788ab34c91279c1a277cb1a10f3e95a59b96e.tar.xz |
of: Allow multiple resources in 'reg' property
Some devices need multiple resources in the reg property. This patch
adds support for it.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | drivers/of/base.c | 55 | ||||
-rw-r--r-- | include/of.h | 1 |
2 files changed, 39 insertions, 17 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index c086f7e231..b8c2e8946b 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -828,7 +828,7 @@ static struct device_d *add_of_platform_device(struct device_node *node) dev->id = DEVICE_ID_SINGLE; dev->resource = node->resource; - dev->num_resources = 1; + dev->num_resources = node->num_resource; dev->device_node = node; node->device = dev; @@ -915,25 +915,44 @@ int of_add_memory(struct device_node *node, bool dump) static int add_of_device_resource(struct device_node *node) { - struct property *reg; - u64 address, size; - struct resource *res; + u64 address = 0, size; + struct resource *res, *resp; struct device_d *dev; - int ret; + const __be32 *endp, *reg; + int na, nc, n_resources; + int ret, len; ret = of_add_memory(node, false); if (ret != -ENXIO) return ret; - reg = of_find_property(node, "reg"); + reg = of_get_property(node, "reg", &len); if (!reg) - return -ENODEV; - - address = of_translate_address(node, reg->value); - if (address == OF_BAD_ADDR) return -EINVAL; - size = be32_to_cpu(((u32 *)reg->value)[1]); + of_bus_count_cells(node, &na, &nc); + + n_resources = (len / sizeof(__be32)) / (na + nc); + + res = resp = xzalloc(sizeof(*res) * n_resources); + + endp = reg + (len / sizeof(__be32)); + + while ((endp - reg) >= (na + nc)) { + address = of_translate_address(node, reg); + if (address == OF_BAD_ADDR) { + ret = -EINVAL; + goto err_free; + } + + reg += na; + size = dt_mem_next_cell(nc, ®); + + resp->start = address; + resp->end = address + size - 1; + resp->flags = IORESOURCE_MEM; + resp++; + } /* * A device may already be registered as platform_device. @@ -948,20 +967,22 @@ static int add_of_device_resource(struct device_node *node) node->device = dev; dev->device_node = node; node->resource = dev->resource; - return 0; + ret = 0; + goto err_free; } } - res = xzalloc(sizeof(*res)); - res->start = address; - res->end = address + size - 1; - res->flags = IORESOURCE_MEM; - node->resource = res; + node->num_resource = n_resources; add_of_device(node); return 0; + +err_free: + free(res); + + return ret; } void of_free(struct device_node *node) diff --git a/include/of.h b/include/of.h index 852231e7a4..9349e6a30a 100644 --- a/include/of.h +++ b/include/of.h @@ -26,6 +26,7 @@ struct device_node { struct list_head parent_list; struct list_head list; struct resource *resource; + int num_resource; struct device_d *device; struct list_head phandles; phandle phandle; |