diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-05-06 09:30:37 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-05-06 09:30:37 +0200 |
commit | 579b794b5d13e4a1ffa21d2426bfab7050eaba9d (patch) | |
tree | fb7aec42846fb17498f1371363f474691fdbf4d4 /drivers/of | |
parent | 646a0d058dd206ee978803aaeb53c886cbc5ad9f (diff) | |
parent | 32dc070fd499a8a0bc4bc434fe74319c7463a97a (diff) | |
download | barebox-579b794b5d13e4a1ffa21d2426bfab7050eaba9d.tar.gz barebox-579b794b5d13e4a1ffa21d2426bfab7050eaba9d.tar.xz |
Merge branch 'for-next/of'
Conflicts:
arch/arm/mach-imx/Makefile
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/base.c | 133 | ||||
-rw-r--r-- | drivers/of/partition.c | 13 |
2 files changed, 117 insertions, 29 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 1dad8e0660..8383549821 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -579,6 +579,52 @@ int of_property_read_string(struct device_node *np, const char *propname, } EXPORT_SYMBOL_GPL(of_property_read_string); +/** + * of_property_read_string_index - Find and read a string from a multiple + * strings property. + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @index: index of the string in the list of strings + * @out_string: pointer to null terminated return string, modified only if + * return value is 0. + * + * Search for a property in a device tree node and retrieve a null + * terminated string value (pointer to data, not a copy) in the list of strings + * contained in that property. + * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if + * property does not have a value, and -EILSEQ if the string is not + * null-terminated within the length of the property data. + * + * The out_string pointer is modified only if a valid string can be decoded. + */ +int of_property_read_string_index(struct device_node *np, const char *propname, + int index, const char **output) +{ + struct property *prop = of_find_property(np, propname); + int i = 0; + size_t l = 0, total = 0; + const char *p; + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + if (strnlen(prop->value, prop->length) >= prop->length) + return -EILSEQ; + + p = prop->value; + + for (i = 0; total < prop->length; total += l, p += l) { + l = strlen(p) + 1; + if (i++ == index) { + *output = p; + return 0; + } + } + return -ENODATA; +} +EXPORT_SYMBOL_GPL(of_property_read_string_index); + struct device_node *of_get_root_node(void) { return root_node; @@ -782,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; @@ -869,32 +915,52 @@ 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; - phandle phandle; - int ret; - - ret = of_property_read_u32(node, "phandle", &phandle); - if (!ret) { - node->phandle = phandle; - list_add_tail(&node->phandles, &phandle_list); - } + const __be32 *endp, *reg; + const char *resname; + int na, nc, n_resources; + int ret, len, index; 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)); + + index = 0; + + 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; + resname = NULL; + of_property_read_string_index(node, "reg-names", index, &resname); + if (resname) + resp->name = xstrdup(resname); + resp->flags = IORESOURCE_MEM; + resp++; + index++; + } /* * A device may already be registered as platform_device. @@ -909,20 +975,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) @@ -975,6 +1043,22 @@ static void __of_probe(struct device_node *node) __of_probe(n); } +static void __of_parse_phandles(struct device_node *node) +{ + struct device_node *n; + phandle phandle; + int ret; + + ret = of_property_read_u32(node, "phandle", &phandle); + if (!ret) { + node->phandle = phandle; + list_add_tail(&node->phandles, &phandle_list); + } + + list_for_each_entry(n, &node->children, parent_list) + __of_parse_phandles(n); +} + struct device_node *of_chosen; const char *of_model; @@ -991,6 +1075,7 @@ int of_probe(void) of_chosen = of_find_node_by_path(root_node, "/chosen"); of_property_read_string(root_node, "model", &of_model); + __of_parse_phandles(root_node); __of_probe(root_node); return 0; diff --git a/drivers/of/partition.c b/drivers/of/partition.c index 6a57a6036e..2d70cf5353 100644 --- a/drivers/of/partition.c +++ b/drivers/of/partition.c @@ -21,9 +21,9 @@ #include <of.h> #include <malloc.h> #include <linux/mtd/mtd.h> +#include <nand.h> -int of_parse_partitions(const char *cdevname, - struct device_node *node) +int of_parse_partitions(struct cdev *cdev, struct device_node *node) { struct device_node *n; const char *partname; @@ -48,14 +48,17 @@ int of_parse_partitions(const char *cdevname, partname = of_get_property(n, "name", &len); name = (char *)partname; - debug("add partition: %s.%s 0x%08lx 0x%08lx\n", cdevname, partname, offset, size); + debug("add partition: %s.%s 0x%08lx 0x%08lx\n", cdev->name, partname, offset, size); if (of_get_property(n, "read-only", &len)) flags = DEVFS_PARTITION_READONLY; - filename = asprintf("%s.%s", cdevname, partname); + filename = asprintf("%s.%s", cdev->name, partname); - devfs_add_partition(cdevname, offset, size, flags, filename); + devfs_add_partition(cdev->name, offset, size, flags, filename); + + if (cdev->mtd && cdev->mtd->type == MTD_NANDFLASH) + dev_add_bb_dev(filename, NULL); free(filename); } |