summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boards/highbank/init.c6
-rw-r--r--arch/arm/cpu/psci.c6
-rw-r--r--arch/sandbox/board/hostfile.c6
-rw-r--r--common/memory.c2
-rw-r--r--common/oftree.c2
-rw-r--r--common/partitions.c2
-rw-r--r--common/state/state.c5
-rw-r--r--drivers/base/driver.c2
-rw-r--r--drivers/eeprom/at24.c1
-rw-r--r--drivers/eeprom/at25.c2
-rw-r--r--drivers/mci/mci-core.c4
-rw-r--r--drivers/mtd/core.c65
-rw-r--r--drivers/mtd/partition.c2
-rw-r--r--drivers/of/base.c24
-rw-r--r--drivers/of/of_path.c107
-rw-r--r--drivers/of/partition.c176
-rw-r--r--drivers/video/simplefb.c12
-rw-r--r--fs/devfs-core.c82
-rw-r--r--include/driver.h4
-rw-r--r--include/linux/mtd/mtd.h1
-rw-r--r--include/of.h15
21 files changed, 360 insertions, 166 deletions
diff --git a/arch/arm/boards/highbank/init.c b/arch/arm/boards/highbank/init.c
index 577ccc0b74..32e217321a 100644
--- a/arch/arm/boards/highbank/init.c
+++ b/arch/arm/boards/highbank/init.c
@@ -37,14 +37,12 @@ static int hb_fixup(struct device_node *root, void *unused)
if (!(reg & HB_PWRDOM_STAT_SATA)) {
for_each_compatible_node_from(node, root, NULL, "calxeda,hb-ahci")
- of_set_property(node, "status", "disabled",
- sizeof("disabled"), 1);
+ of_property_write_string(node, "status", "disabled");
}
if (!(reg & HB_PWRDOM_STAT_EMMC)) {
for_each_compatible_node_from(node, root, NULL, "calxeda,hb-sdhci")
- of_set_property(node, "status", "disabled",
- sizeof("disabled"), 1);
+ of_property_write_string(node, "status", "disabled");
}
if ((opp_table[0] >> 16) != HB_OPP_VERSION)
diff --git a/arch/arm/cpu/psci.c b/arch/arm/cpu/psci.c
index d650c23ea2..eafb361a0a 100644
--- a/arch/arm/cpu/psci.c
+++ b/arch/arm/cpu/psci.c
@@ -204,13 +204,11 @@ static int of_psci_fixup(struct device_node *root, void *unused)
if (!psci)
return -EINVAL;
- ret = of_set_property(psci, "compatible", "arm,psci-1.0",
- strlen("arm,psci-1.0") + 1, 1);
+ ret = of_property_write_string(psci, "compatible", "arm,psci-1.0");
if (ret)
return ret;
- ret = of_set_property(psci, "method", "smc",
- strlen("smc") + 1, 1);
+ ret = of_property_write_string(psci, "method", "smc");
if (ret)
return ret;
diff --git a/arch/sandbox/board/hostfile.c b/arch/sandbox/board/hostfile.c
index c1a2643bc7..e7d92ea031 100644
--- a/arch/sandbox/board/hostfile.c
+++ b/arch/sandbox/board/hostfile.c
@@ -133,8 +133,7 @@ static int of_hostfile_fixup(struct device_node *root, void *ctx)
node = of_new_node(root, hf->devname);
- ret = of_set_property(node, "compatible", hostfile_dt_ids->compatible,
- strlen(hostfile_dt_ids->compatible) + 1, 1);
+ ret = of_property_write_string(node, "compatible", hostfile_dt_ids->compatible);
if (ret)
return ret;
@@ -146,8 +145,7 @@ static int of_hostfile_fixup(struct device_node *root, void *ctx)
if (ret)
return ret;
- ret = of_set_property(node, "barebox,filename", hf->filename,
- strlen(hf->filename) + 1, 1);
+ ret = of_property_write_string(node, "barebox,filename", hf->filename);
return ret;
}
diff --git a/common/memory.c b/common/memory.c
index ad38b00ecb..ff5bdc14e2 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -185,7 +185,7 @@ static int of_memory_fixup(struct device_node *node, void *unused)
if (!memnode)
return -ENOMEM;
- err = of_set_property(memnode, "device_type", "memory", sizeof("memory"), 1);
+ err = of_property_write_string(memnode, "device_type", "memory");
if (err)
return err;
diff --git a/common/oftree.c b/common/oftree.c
index e98b908738..09a4455a9e 100644
--- a/common/oftree.c
+++ b/common/oftree.c
@@ -128,7 +128,7 @@ static int of_fixup_bootargs(struct device_node *root, void *unused)
return -ENOMEM;
- err = of_set_property(node, "bootargs", str, strlen(str) + 1, 1);
+ err = of_property_write_string(node, "bootargs", str);
return err;
}
diff --git a/common/partitions.c b/common/partitions.c
index 69a2b1fefb..574b31fbbe 100644
--- a/common/partitions.c
+++ b/common/partitions.c
@@ -63,6 +63,8 @@ static int register_one_partition(struct block_device *blk,
goto out;
}
+ cdev->flags |= DEVFS_PARTITION_FROM_TABLE;
+
cdev->dos_partition_type = part->dos_partition_type;
strcpy(cdev->partuuid, part->partuuid);
diff --git a/common/state/state.c b/common/state/state.c
index 4020d5e1ea..02bb1bb24a 100644
--- a/common/state/state.c
+++ b/common/state/state.c
@@ -167,9 +167,8 @@ static int state_convert_node_variable(struct state *state,
if ((conv == STATE_CONVERT_TO_NODE)
|| (conv == STATE_CONVERT_FIXUP)) {
- ret = of_set_property(new_node, "type",
- vtype->type_name,
- strlen(vtype->type_name) + 1, 1);
+ ret = of_property_write_string(new_node, "type",
+ vtype->type_name);
if (ret)
goto out;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 5867fe45d0..83260990af 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -221,7 +221,7 @@ int unregister_device(struct device_d *old_dev)
}
list_for_each_entry_safe(cdev, ct, &old_dev->cdevs, devices_list) {
- if (cdev->flags & DEVFS_IS_PARTITION) {
+ if (cdev->master) {
dev_dbg(old_dev, "unregister part %s\n", cdev->name);
devfs_del_partition(cdev->name);
}
diff --git a/drivers/eeprom/at24.c b/drivers/eeprom/at24.c
index 4ae3776554..1227286fbe 100644
--- a/drivers/eeprom/at24.c
+++ b/drivers/eeprom/at24.c
@@ -500,6 +500,7 @@ static int at24_probe(struct device_d *dev)
goto err_devfs_create;
of_parse_partitions(&at24->cdev, dev->device_node);
+ of_partitions_register_fixup(&at24->cdev);
return 0;
diff --git a/drivers/eeprom/at25.c b/drivers/eeprom/at25.c
index f7f8368c4b..1caaebd371 100644
--- a/drivers/eeprom/at25.c
+++ b/drivers/eeprom/at25.c
@@ -360,6 +360,8 @@ static int at25_probe(struct device_d *dev)
dev_dbg(dev, "%s probed\n", at25->cdev.name);
of_parse_partitions(&at25->cdev, dev->device_node);
+ of_partitions_register_fixup(&at25->cdev);
+
return 0;
fail:
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 928277a924..b173a173b1 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -1621,8 +1621,10 @@ static int mci_register_partition(struct mci_part *part)
rc = 0; /* it's not a failure */
}
- if (np)
+ if (np) {
of_parse_partitions(&part->blk.cdev, np);
+ of_partitions_register_fixup(&part->blk.cdev);
+ }
return 0;
}
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
index 4e7bfdb3da..1eb8dd36d8 100644
--- a/drivers/mtd/core.c
+++ b/drivers/mtd/core.c
@@ -556,67 +556,6 @@ static int mtd_part_compare(struct list_head *a, struct list_head *b)
return 0;
}
-static int of_mtd_fixup(struct device_node *root, void *ctx)
-{
- struct mtd_info *mtd = ctx, *partmtd;
- struct device_node *np, *part, *tmp;
- int ret;
-
- 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",
- mtd->of_path);
- return -EINVAL;
- }
-
- for_each_child_of_node_safe(np, tmp, part) {
- if (of_get_property(part, "compatible", NULL))
- continue;
- of_delete_node(part);
- }
-
- list_for_each_entry(partmtd, &mtd->partitions, partitions_entry) {
- int na, ns, len = 0;
- char *name = basprintf("partition@%0llx",
- partmtd->master_offset);
- void *p;
- u8 tmp[16 * 16]; /* Up to 64-bit address + 64-bit size */
-
- if (!name)
- return -ENOMEM;
-
- part = of_new_node(np, name);
- free(name);
- if (!part)
- return -ENOMEM;
-
- p = of_new_property(part, "label", partmtd->cdev.partname,
- strlen(partmtd->cdev.partname) + 1);
- if (!p)
- return -ENOMEM;
-
- na = of_n_addr_cells(part);
- ns = of_n_size_cells(part);
-
- of_write_number(tmp + len, partmtd->master_offset, na);
- len += na * 4;
- of_write_number(tmp + len, partmtd->size, ns);
- len += ns * 4;
-
- ret = of_set_property(part, "reg", tmp, len, 1);
- if (ret)
- return ret;
-
- if (partmtd->cdev.flags & DEVFS_PARTITION_READONLY) {
- ret = of_set_property(part, "read-only", NULL, 0, 1);
- if (ret)
- return ret;
- }
- }
-
- return 0;
-}
-
static int mtd_detect(struct device_d *dev)
{
struct mtd_info *mtd = container_of(dev, struct mtd_info, class_dev);
@@ -732,7 +671,9 @@ int add_mtd_device(struct mtd_info *mtd, const char *devname, int device_id)
of_parse_partitions(&mtd->cdev, mtd->parent->device_node);
if (IS_ENABLED(CONFIG_OFDEVICE) && mtd->parent->device_node) {
mtd->of_path = xstrdup(mtd->parent->device_node->full_name);
- of_register_fixup(of_mtd_fixup, mtd);
+ ret = of_partitions_register_fixup(&mtd->cdev);
+ if (ret)
+ goto err1;
}
}
diff --git a/drivers/mtd/partition.c b/drivers/mtd/partition.c
index 777cb758ce..013697732d 100644
--- a/drivers/mtd/partition.c
+++ b/drivers/mtd/partition.c
@@ -225,6 +225,8 @@ struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset,
if (ret)
goto err;
+ part->cdev.master = &part->master->cdev;
+
return part;
err:
free(part->cdev.partname);
diff --git a/drivers/of/base.c b/drivers/of/base.c
index bef8f1de1a..6632f4d9dd 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1217,6 +1217,28 @@ int of_property_write_u64_array(struct device_node *np,
}
/**
+ * of_property_write_string - Write a string to a property. If
+ * the property does not exist, it will be created and appended to the given
+ * device node.
+ *
+ * @np: device node to which the property value is to be written.
+ * @propname: name of the property to be written.
+ * value: pointer to the string to write
+ *
+ * Search for a property in a device node and write a string to
+ * it. If the property does not exist, it will be created and appended to
+ * the device node. Returns 0 on success, -ENOMEM if the property or array
+ * of elements cannot be created.
+ */
+int of_property_write_string(struct device_node *np,
+ const char *propname, const char *value)
+{
+ size_t len = strlen(value);
+
+ return of_set_property(np, propname, value, len + 1, 1);
+}
+
+/**
* of_parse_phandle_from - Resolve a phandle property to a device_node pointer from
* a given root node
* @np: Pointer to device node holding phandle property
@@ -2093,7 +2115,7 @@ int of_device_enable_path(const char *path)
*/
int of_device_disable(struct device_node *node)
{
- return of_set_property(node, "status", "disabled", sizeof("disabled"), 1);
+ return of_property_write_string(node, "status", "disabled");
}
/**
diff --git a/drivers/of/of_path.c b/drivers/of/of_path.c
index e0b2dc1247..a5886dffac 100644
--- a/drivers/of/of_path.c
+++ b/drivers/of/of_path.c
@@ -104,6 +104,113 @@ int of_find_path_by_node(struct device_node *node, char **outpath, unsigned flag
}
/**
+ * of_find_node_by_devpath - translate a device path to a device tree node
+ *
+ * @root: The device tree root. Can be NULL, in this case the internal tree is used
+ * @path: The path to look the node up for. Can be "/dev/cdevname" or "cdevname" directly.
+ *
+ * This is the counterpart of of_find_path_by_node(). Given a path this function tries
+ * to find the corresponding node in the given device tree.
+ *
+ * We first have to find the hardware device in the tree we are passed and then find
+ * a partition matching offset/size in this tree. This is necessary because the
+ * passed tree may use another partition binding (legacy vs. fixed-partitions). Also
+ * the node names may differ (some device trees have partition@<num> instead of
+ * partition@<offset>.
+ */
+struct device_node *of_find_node_by_devpath(struct device_node *root, const char *path)
+{
+ struct cdev *cdev;
+ bool is_partition = false;
+ struct device_node *np, *partnode, *rnp;
+ loff_t part_offset = 0, part_size = 0;
+
+ pr_debug("%s: looking for path %s\n", __func__, path);
+
+ if (!strncmp(path, "/dev/", 5))
+ path += 5;
+
+ cdev = cdev_by_name(path);
+ if (!cdev) {
+ pr_debug("%s: cdev %s not found\n", __func__, path);
+ return NULL;
+ }
+
+ /*
+ * Look for the device node of the master device (the one of_parse_partitions() has
+ * been called with
+ */
+ if (cdev->master) {
+ is_partition = true;
+ part_offset = cdev->offset;
+ part_size = cdev->size;
+ pr_debug("%s path %s: is a partition with offset 0x%08llx, size 0x%08llx\n",
+ __func__, path, part_offset, part_size);
+ np = cdev->master->device_node;
+ } else {
+ np = cdev->device_node;
+ }
+
+ /*
+ * Now find the device node of the master device in the device tree we have
+ * been passed.
+ */
+ rnp = of_find_node_by_path_from(root, np->full_name);
+ if (!rnp) {
+ pr_debug("%s path %s: %s not found in passed tree\n", __func__, path,
+ np->full_name);
+ return NULL;
+ }
+
+ if (!is_partition) {
+ pr_debug("%s path %s: returning full device node %s\n", __func__, path,
+ rnp->full_name);
+ return rnp;
+ }
+
+ /*
+ * Look for a partition with matching offset/size in the device node of
+ * the tree we have been passed.
+ */
+ partnode = of_get_child_by_name(rnp, "partitions");
+ if (!partnode) {
+ pr_debug("%s path %s: using legacy partition binding\n", __func__, path);
+ partnode = rnp;
+ }
+
+ for_each_child_of_node(partnode, np) {
+ const __be32 *reg;
+ int na, ns, len;
+ loff_t offset, size;
+
+ reg = of_get_property(np, "reg", &len);
+ if (!reg)
+ return NULL;
+
+ na = of_n_addr_cells(np);
+ ns = of_n_size_cells(np);
+
+ if (len < (na + ns) * sizeof(__be32)) {
+ pr_err("reg property too small in %s\n", np->full_name);
+ continue;
+ }
+
+ offset = of_read_number(reg, na);
+ size = of_read_number(reg + na, ns);
+
+ if (part_offset == offset && part_size == size) {
+ pr_debug("%s path %s: found matching partition in %s\n", __func__, path,
+ np->full_name);
+ return np;
+ }
+ }
+
+ pr_debug("%s path %s: no matching node found\n", __func__, path);
+
+ return NULL;
+}
+
+/**
* of_find_path - translate a path description in the devicetree to a barebox
* path
*
diff --git a/drivers/of/partition.c b/drivers/of/partition.c
index 8c2aef2326..25b41cb012 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)
{
@@ -30,10 +40,11 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node)
char *filename;
struct cdev *new;
const __be32 *reg;
- unsigned long offset, size;
+ u64 offset, size;
const char *name;
int len;
unsigned long flags = 0;
+ int na, ns;
if (!node)
return NULL;
@@ -42,8 +53,16 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node)
if (!reg)
return NULL;
- offset = be32_to_cpu(reg[0]);
- size = be32_to_cpu(reg[1]);
+ na = of_n_addr_cells(node);
+ ns = of_n_size_cells(node);
+
+ if (len < (na + ns) * sizeof(__be32)) {
+ pr_err("reg property too small in %s\n", node->full_name);
+ return NULL;
+ }
+
+ offset = of_read_number(reg, na);
+ size = of_read_number(reg + na, ns);
partname = of_get_property(node, "label", &len);
if (!partname)
@@ -53,7 +72,7 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node)
name = (char *)partname;
- debug("add partition: %s.%s 0x%08lx 0x%08lx\n", cdev->name, partname, offset, size);
+ debug("add partition: %s.%s 0x%08llx 0x%08llx\n", cdev->name, partname, offset, size);
if (of_get_property(node, "read-only", &len))
flags = DEVFS_PARTITION_READONLY;
@@ -79,6 +98,8 @@ int of_parse_partitions(struct cdev *cdev, struct device_node *node)
if (!node)
return -EINVAL;
+ cdev->device_node = node;
+
subnode = of_get_child_by_name(node, "partitions");
if (subnode) {
if (!of_device_is_compatible(subnode, "fixed-partitions"))
@@ -92,3 +113,150 @@ 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_partition_fixup(struct device_node *root, void *ctx)
+{
+ struct cdev *cdev = ctx, *partcdev;
+ struct device_node *np, *part, *partnode;
+ int ret;
+ int n_cells, n_parts = 0;
+
+ if (of_partition_binding == MTD_OF_BINDING_DONTTOUCH)
+ return 0;
+
+ if (!cdev->device_node)
+ return -EINVAL;
+
+ list_for_each_entry(partcdev, &cdev->partitions, partition_entry) {
+ if (partcdev->flags & DEVFS_PARTITION_FROM_TABLE)
+ continue;
+ n_parts++;
+ }
+
+ if (!n_parts)
+ return 0;
+
+ if (cdev->size >= 0x100000000)
+ n_cells = 2;
+ else
+ n_cells = 1;
+
+ np = of_find_node_by_path_from(root, cdev->device_node->full_name);
+ if (!np) {
+ dev_err(cdev->dev, "Cannot find nodepath %s, cannot fixup\n",
+ cdev->device_node->full_name);
+ return -EINVAL;
+ }
+
+ 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(partcdev, &cdev->partitions, partition_entry) {
+ int na, ns, len = 0;
+ char *name;
+ void *p;
+ u8 tmp[16 * 16]; /* Up to 64-bit address + 64-bit size */
+ loff_t partoffset;
+
+ if (partcdev->flags & DEVFS_PARTITION_FROM_TABLE)
+ continue;
+
+ if (partcdev->mtd)
+ partoffset = partcdev->mtd->master_offset;
+ else
+ partoffset = partcdev->offset;
+
+ name = basprintf("partition@%0llx", partoffset);
+ if (!name)
+ return -ENOMEM;
+
+ part = of_new_node(partnode, name);
+ free(name);
+ if (!part)
+ return -ENOMEM;
+
+ p = of_new_property(part, "label", partcdev->partname,
+ strlen(partcdev->partname) + 1);
+ if (!p)
+ return -ENOMEM;
+
+ na = of_n_addr_cells(part);
+ ns = of_n_size_cells(part);
+
+ of_write_number(tmp + len, partoffset, na);
+ len += na * 4;
+ of_write_number(tmp + len, partcdev->size, ns);
+ len += ns * 4;
+
+ ret = of_set_property(part, "reg", tmp, len, 1);
+ if (ret)
+ return ret;
+
+ if (partcdev->flags & DEVFS_PARTITION_READONLY) {
+ ret = of_set_property(part, "read-only", NULL, 0, 1);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int of_partitions_register_fixup(struct cdev *cdev)
+{
+ return of_register_fixup(of_partition_fixup, cdev);
+}
+
+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);
diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c
index 357262988e..a2c59de364 100644
--- a/drivers/video/simplefb.c
+++ b/drivers/video/simplefb.c
@@ -89,9 +89,6 @@ static const struct simplefb_mode *simplefb_find_mode(const struct fb_info *fbi)
static int simplefb_create_node(struct device_node *root,
const struct fb_info *fbi, const char *format)
{
- const char *compat = "simple-framebuffer";
- const char *disabled = "disabled";
- const char *okay = "okay";
struct device_node *node;
u32 cells[2];
int ret;
@@ -100,12 +97,11 @@ static int simplefb_create_node(struct device_node *root,
if (!node)
return -ENOMEM;
- ret = of_set_property(node, "status", disabled,
- strlen(disabled) + 1, 1);
+ ret = of_property_write_string(node, "status", "disabled");
if (ret < 0)
return ret;
- ret = of_set_property(node, "compatible", compat, strlen(compat) + 1, 1);
+ ret = of_property_write_string(node, "compatible", "simple-framebuffer");
if (ret)
return ret;
@@ -130,14 +126,14 @@ static int simplefb_create_node(struct device_node *root,
if (ret < 0)
return ret;
- ret = of_set_property(node, "format", format, strlen(format) + 1, 1);
+ ret = of_property_write_string(node, "format", format);
if (ret < 0)
return ret;
of_add_reserve_entry((u32)fbi->screen_base,
(u32)fbi->screen_base + fbi->screen_size);
- return of_set_property(node, "status", okay, strlen(okay) + 1, 1);
+ return of_property_write_string(node, "status", "okay");
}
static int simplefb_of_fixup(struct device_node *root, void *ctx)
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 75ed3b0e66..382606f1cf 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -37,7 +37,7 @@ int devfs_partition_complete(struct string_list *sl, char *instr)
len = strlen(instr);
list_for_each_entry(cdev, &cdev_list, list) {
- if (cdev->flags & DEVFS_IS_PARTITION &&
+ if (cdev->master &&
!strncmp(instr, cdev->name, len)) {
string_list_add_asprintf(sl, "%s ", cdev->name);
}
@@ -184,76 +184,8 @@ int cdev_flush(struct cdev *cdev)
return cdev->ops->flush(cdev);
}
-static int partition_ioctl(struct cdev *cdev, int request, void *buf)
-{
- int ret = 0;
- loff_t offset, *_buf = buf;
- struct mtd_info_user *user = buf;
-
- switch (request) {
- case MEMSETBADBLOCK:
- case MEMSETGOODBLOCK:
- case MEMGETBADBLOCK:
- offset = *_buf;
- offset += cdev->offset;
- ret = cdev->ops->ioctl(cdev, request, &offset);
- break;
- case MEMGETINFO:
- if (cdev->mtd) {
- user->type = cdev->mtd->type;
- user->flags = cdev->mtd->flags;
- user->size = cdev->mtd->size;
- user->erasesize = cdev->mtd->erasesize;
- user->writesize = cdev->mtd->writesize;
- user->oobsize = cdev->mtd->oobsize;
- user->subpagesize = cdev->mtd->writesize >> cdev->mtd->subpage_sft;
- user->mtd = cdev->mtd;
- /* The below fields are obsolete */
- user->ecctype = -1;
- user->eccsize = 0;
- break;
- }
- if (!cdev->ops->ioctl) {
- ret = -EINVAL;
- break;
- }
- ret = cdev->ops->ioctl(cdev, request, buf);
- break;
-#if (defined(CONFIG_NAND_ECC_HW) || defined(CONFIG_NAND_ECC_SOFT))
- case ECCGETSTATS:
-#endif
- case MEMERASE:
- if (!cdev->ops->ioctl) {
- ret = -EINVAL;
- break;
- }
- ret = cdev->ops->ioctl(cdev, request, buf);
- break;
-#ifdef CONFIG_PARTITION
- case MEMGETREGIONINFO:
- if (cdev->mtd) {
- struct region_info_user *reg = buf;
- int erasesize_shift = ffs(cdev->mtd->erasesize) - 1;
-
- reg->offset = cdev->offset;
- reg->erasesize = cdev->mtd->erasesize;
- reg->numblocks = cdev->size >> erasesize_shift;
- reg->regionindex = cdev->mtd->index;
- }
- break;
-#endif
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
int cdev_ioctl(struct cdev *cdev, int request, void *buf)
{
- if (cdev->flags & DEVFS_IS_PARTITION)
- return partition_ioctl(cdev, request, buf);
-
if (!cdev->ops->ioctl)
return -EINVAL;
@@ -277,6 +209,7 @@ int devfs_create(struct cdev *new)
return -EEXIST;
INIT_LIST_HEAD(&new->links);
+ INIT_LIST_HEAD(&new->partitions);
list_add_tail(&new->list, &cdev_list);
if (new->dev) {
@@ -326,6 +259,9 @@ int devfs_remove(struct cdev *cdev)
list_for_each_entry_safe(c, tmp, &cdev->links, link_entry)
devfs_remove(c);
+ if (cdev->master)
+ list_del(&cdev->partition_entry);
+
if (cdev->link)
free(cdev);
@@ -374,6 +310,8 @@ static struct cdev *__devfs_add_partition(struct cdev *cdev,
partinfo->flags, partinfo->name);
if (IS_ERR(mtd))
return (void *)mtd;
+
+ list_add_tail(&mtd->cdev.partition_entry, &cdev->partitions);
return &mtd->cdev;
}
@@ -388,7 +326,9 @@ static struct cdev *__devfs_add_partition(struct cdev *cdev,
new->offset = cdev->offset + offset;
new->dev = cdev->dev;
- new->flags = partinfo->flags | DEVFS_IS_PARTITION;
+ new->master = cdev;
+
+ list_add_tail(&new->partition_entry, &cdev->partitions);
devfs_create(new);
@@ -428,7 +368,7 @@ int devfs_del_partition(const char *name)
return ret;
}
- if (!(cdev->flags & DEVFS_IS_PARTITION))
+ if (!cdev->master)
return -EINVAL;
if (cdev->flags & DEVFS_PARTITION_FIXED)
return -EPERM;
diff --git a/include/driver.h b/include/driver.h
index 6abaaad8b4..52e06f7d62 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -459,6 +459,8 @@ struct cdev {
u8 dos_partition_type;
struct cdev *link;
struct list_head link_entry, links;
+ struct list_head partition_entry, partitions;
+ struct cdev *master;
};
int devfs_create(struct cdev *);
@@ -481,8 +483,8 @@ int cdev_erase(struct cdev *cdev, loff_t count, loff_t offset);
#define DEVFS_PARTITION_FIXED (1U << 0)
#define DEVFS_PARTITION_READONLY (1U << 1)
-#define DEVFS_IS_PARTITION (1 << 2)
#define DEVFS_IS_CHARACTER_DEV (1 << 3)
+#define DEVFS_PARTITION_FROM_TABLE (1 << 4)
struct cdev *devfs_add_partition(const char *devname, loff_t offset,
loff_t size, unsigned int flags, const char *name);
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index f93fac00f2..fa35c7ef39 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -228,6 +228,7 @@ struct mtd_info {
struct list_head partitions_entry;
char *of_path;
+ unsigned int of_binding;
};
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
diff --git a/include/of.h b/include/of.h
index e3bb452b86..0ba73f197f 100644
--- a/include/of.h
+++ b/include/of.h
@@ -205,6 +205,8 @@ extern int of_property_write_u32_array(struct device_node *np,
extern int of_property_write_u64_array(struct device_node *np,
const char *propname, const u64 *values,
size_t sz);
+extern int of_property_write_string(struct device_node *np, const char *propname,
+ const char *value);
extern struct device_node *of_parse_phandle(const struct device_node *np,
const char *phandle_name,
@@ -238,6 +240,7 @@ extern struct device_d *of_device_enable_and_register_by_name(const char *name);
struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node);
int of_parse_partitions(struct cdev *cdev, struct device_node *node);
+int of_partitions_register_fixup(struct cdev *cdev);
int of_device_is_stdout_path(struct device_d *dev);
const char *of_get_model(void);
void *of_flatten_dtb(struct device_node *node);
@@ -248,6 +251,7 @@ struct device_d *of_find_device_by_node_path(const char *path);
#define OF_FIND_PATH_FLAGS_BB 1 /* return .bb device if available */
int of_find_path(struct device_node *node, const char *propname, char **outpath, unsigned flags);
int of_find_path_by_node(struct device_node *node, char **outpath, unsigned flags);
+struct device_node *of_find_node_by_devpath(struct device_node *root, const char *path);
int of_register_fixup(int (*fixup)(struct device_node *, void *), void *context);
int of_unregister_fixup(int (*fixup)(struct device_node *, void *), void *context);
int of_register_set_status_fixup(const char *node, bool status);
@@ -262,6 +266,11 @@ static inline int of_parse_partitions(struct cdev *cdev,
return -EINVAL;
}
+static inline int of_partitions_register_fixup(struct cdev *cdev)
+{
+ return -ENOSYS;
+}
+
static inline int of_device_is_stdout_path(struct device_d *dev)
{
return 0;
@@ -466,6 +475,12 @@ static inline int of_property_write_u64_array(struct device_node *np,
return -ENOSYS;
}
+static inline int of_property_write_string(struct device_node *np, const char *propname,
+ const char *value)
+{
+ return -ENOSYS;
+}
+
static inline struct device_node *of_parse_phandle(const struct device_node *np,
const char *phandle_name, int index)
{