diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2017-03-30 11:13:03 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2017-03-30 23:47:31 +0200 |
commit | a2fa18f9f483a7fd1703996782778ee142a47141 (patch) | |
tree | e60cfc49916ab3bdca888a2b61c5b72e78211faf /drivers/of | |
parent | bd28ade42a334d7102cd3999331d9320f169bcbf (diff) | |
download | barebox-a2fa18f9f483a7fd1703996782778ee142a47141.tar.gz barebox-a2fa18f9f483a7fd1703996782778ee142a47141.tar.xz |
mtd: of: Make used partition binding configurable
So far we used the legacy partition binding when fixing up the
mtd partition nodes. Change this to default to the new binding
with a "partitions" submode. Make this behaviour configurable
though: This creates a new of_binding device variable for
mtd devices. This can be set to:
- "new": Use the new partition binding (default)
- "legacy": Use the old partition binding
- "donttouch": Do not touch the partition node
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/partition.c | 84 |
1 files changed, 77 insertions, 7 deletions
diff --git a/drivers/of/partition.c b/drivers/of/partition.c index 68f3812ed6..f4d6c3322c 100644 --- a/drivers/of/partition.c +++ b/drivers/of/partition.c @@ -23,6 +23,16 @@ #include <linux/mtd/mtd.h> #include <linux/err.h> #include <nand.h> +#include <init.h> +#include <globalvar.h> + +static unsigned int of_partition_binding; + +enum of_binding_name { + MTD_OF_BINDING_NEW, + MTD_OF_BINDING_LEGACY, + MTD_OF_BINDING_DONTTOUCH, +}; struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node) { @@ -93,15 +103,36 @@ int of_parse_partitions(struct cdev *cdev, struct device_node *node) return 0; } +static void delete_subnodes(struct device_node *np) +{ + struct device_node *part, *tmp; + + for_each_child_of_node_safe(np, tmp, part) { + if (of_get_property(part, "compatible", NULL)) + continue; + + of_delete_node(part); + } +} + static int of_mtd_fixup(struct device_node *root, void *ctx) { struct cdev *cdev = ctx; struct mtd_info *mtd, *partmtd; - struct device_node *np, *part, *tmp; + struct device_node *np, *part, *partnode; int ret; + int n_cells; mtd = container_of(cdev, struct mtd_info, cdev); + if (of_partition_binding == MTD_OF_BINDING_DONTTOUCH) + return 0; + + if (mtd->size >= 0x100000000) + n_cells = 2; + else + n_cells = 1; + np = of_find_node_by_path_from(root, mtd->of_path); if (!np) { dev_err(&mtd->class_dev, "Cannot find nodepath %s, cannot fixup\n", @@ -109,12 +140,37 @@ static int of_mtd_fixup(struct device_node *root, void *ctx) return -EINVAL; } - for_each_child_of_node_safe(np, tmp, part) { - if (of_get_property(part, "compatible", NULL)) - continue; - of_delete_node(part); + partnode = of_get_child_by_name(np, "partitions"); + if (partnode) { + if (of_partition_binding == MTD_OF_BINDING_LEGACY) { + of_delete_node(partnode); + partnode = np; + } + delete_subnodes(partnode); + } else { + delete_subnodes(np); + + if (of_partition_binding == MTD_OF_BINDING_LEGACY) + partnode = np; + else + partnode = of_new_node(np, "partitions"); + } + + if (of_partition_binding == MTD_OF_BINDING_NEW) { + ret = of_property_write_string(partnode, "compatible", + "fixed-partitions"); + if (ret) + return ret; } + of_property_write_u32(partnode, "#size-cells", n_cells); + if (ret) + return ret; + + of_property_write_u32(partnode, "#addres-cells", n_cells); + if (ret) + return ret; + list_for_each_entry(partmtd, &mtd->partitions, partitions_entry) { int na, ns, len = 0; char *name = basprintf("partition@%0llx", @@ -125,7 +181,7 @@ static int of_mtd_fixup(struct device_node *root, void *ctx) if (!name) return -ENOMEM; - part = of_new_node(np, name); + part = of_new_node(partnode, name); free(name); if (!part) return -ENOMEM; @@ -160,4 +216,18 @@ static int of_mtd_fixup(struct device_node *root, void *ctx) int of_partitions_register_fixup(struct cdev *cdev) { return of_register_fixup(of_mtd_fixup, cdev); -}
\ No newline at end of file +} + +static const char *of_binding_names[] = { + "new", "legacy", "donttouch" +}; + +static int of_partition_init(void) +{ + dev_add_param_enum(&global_device, "of_partition_binding", NULL, NULL, + &of_partition_binding, of_binding_names, + ARRAY_SIZE(of_binding_names), NULL); + + return 0; +} +device_initcall(of_partition_init);
\ No newline at end of file |