summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2017-03-30 11:13:03 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2017-03-30 23:47:31 +0200
commita2fa18f9f483a7fd1703996782778ee142a47141 (patch)
treee60cfc49916ab3bdca888a2b61c5b72e78211faf /drivers
parentbd28ade42a334d7102cd3999331d9320f169bcbf (diff)
downloadbarebox-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')
-rw-r--r--drivers/of/partition.c84
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