summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/porting.txt2
-rw-r--r--arch/arm/boards/a9m2410/a9m2410.c27
-rw-r--r--arch/arm/boards/freescale-mx35-3ds/3stack.c42
-rw-r--r--arch/arm/boards/phytec-phycore-imx27/pcm038.c47
-rw-r--r--arch/arm/boards/sama5d3xek/init.c41
-rw-r--r--drivers/mtd/nand/nand-bb.c2
-rw-r--r--fs/devfs-core.c100
-rw-r--r--include/driver.h41
-rw-r--r--include/nand.h4
9 files changed, 250 insertions, 56 deletions
diff --git a/Documentation/porting.txt b/Documentation/porting.txt
index a350e5e5fe..bd807a3186 100644
--- a/Documentation/porting.txt
+++ b/Documentation/porting.txt
@@ -50,7 +50,7 @@ extra-y += barebox.lds
is not ported yet.
- Call devfs_add_partition() to add an environment partition for your device:
- devfs_add_partition("nor0", 0x40000, 0x20000, "env0");
+ devfs_add_partition("nor0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env0");
This will add an area starting at 0x40000 of size 0x20000 of the device
nor0 as env0.
diff --git a/arch/arm/boards/a9m2410/a9m2410.c b/arch/arm/boards/a9m2410/a9m2410.c
index b2b6c87117..943b7709bf 100644
--- a/arch/arm/boards/a9m2410/a9m2410.c
+++ b/arch/arm/boards/a9m2410/a9m2410.c
@@ -82,6 +82,24 @@ static int a9m2410_mem_init(void)
}
mem_initcall(a9m2410_mem_init);
+static const struct devfs_partition a9m2410_nand0_partitions[] = {
+ {
+ .offset = 0,
+ .size = 0x40000,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "self_raw",
+ .bbname = "self0",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND,
+ .size = 0x20000,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "env_raw",
+ .bbname = "env0",
+ }, {
+ /* sentinel */
+ }
+};
+
static int a9m2410_devices_init(void)
{
uint32_t reg;
@@ -116,14 +134,9 @@ static int a9m2410_devices_init(void)
add_generic_device("smc91c111", DEVICE_ID_DYNAMIC, NULL, S3C_CS1_BASE + 0x300,
16, IORESOURCE_MEM, NULL);
-#ifdef CONFIG_NAND
- /* ----------- add some vital partitions -------- */
- devfs_add_partition("nand0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self_raw");
- dev_add_bb_dev("self_raw", "self0");
+ if (IS_ENABLED(CONFIG_NAND))
+ devfs_create_partitions("nand0", a9m2410_nand0_partitions);
- devfs_add_partition("nand0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env_raw");
- dev_add_bb_dev("env_raw", "env0");
-#endif
armlinux_set_architecture(MACH_TYPE_A9M2410);
return 0;
diff --git a/arch/arm/boards/freescale-mx35-3ds/3stack.c b/arch/arm/boards/freescale-mx35-3ds/3stack.c
index dbd1c7adcb..2be1554b68 100644
--- a/arch/arm/boards/freescale-mx35-3ds/3stack.c
+++ b/arch/arm/boards/freescale-mx35-3ds/3stack.c
@@ -129,6 +129,40 @@ static void set_board_rev(int rev)
imx35_3ds_system_rev = (imx35_3ds_system_rev & ~(0xF << 8)) | (rev & 0xF) << 8;
}
+static const struct devfs_partition f3s_nand0_partitions[] = {
+ {
+ .offset = 0,
+ .size = 0x40000,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "self_raw",
+ .bbname = "self0",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND, /* 0x40000 */
+ .size = 0x80000,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "env_raw",
+ .bbname = "env0",
+ }, {
+ /* sentinel */
+ }
+};
+
+static const struct devfs_partition f3s_nor0_partitions[] = {
+ {
+ .offset = 0,
+ .size = 0x40000,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "self0",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND, /* 0x40000 */
+ .size = 0x80000,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "env0",
+ }, {
+ /* sentinel */
+ }
+};
+
static int f3s_devices_init(void)
{
uint32_t reg;
@@ -151,15 +185,11 @@ static int f3s_devices_init(void)
switch ((reg >> 25) & 0x3) {
case 0x01: /* NAND is the source */
- devfs_add_partition("nand0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self_raw");
- dev_add_bb_dev("self_raw", "self0");
- devfs_add_partition("nand0", 0x40000, 0x80000, DEVFS_PARTITION_FIXED, "env_raw");
- dev_add_bb_dev("env_raw", "env0");
+ devfs_create_partitions("nand0", f3s_nand0_partitions);
break;
case 0x00: /* NOR is the source */
- devfs_add_partition("nor0", 0x00000, 0x40000, DEVFS_PARTITION_FIXED, "self0");
- devfs_add_partition("nor0", 0x40000, 0x80000, DEVFS_PARTITION_FIXED, "env0");
+ devfs_create_partitions("nor0", f3s_nor0_partitions);
protect_file("/dev/env0", 1);
break;
}
diff --git a/arch/arm/boards/phytec-phycore-imx27/pcm038.c b/arch/arm/boards/phytec-phycore-imx27/pcm038.c
index 1733261f7d..7df0ddc31b 100644
--- a/arch/arm/boards/phytec-phycore-imx27/pcm038.c
+++ b/arch/arm/boards/phytec-phycore-imx27/pcm038.c
@@ -199,6 +199,40 @@ struct imxusb_platformdata pcm038_otg_pdata = {
.flags = MXC_EHCI_MODE_ULPI | MXC_EHCI_INTERFACE_DIFF_UNI,
};
+static const struct devfs_partition pcm038_nand0_partitions[] = {
+ {
+ .offset = 0,
+ .size = SZ_512K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "self_raw",
+ .bbname = "self0",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND, /* 512 KiB */
+ .size = SZ_128K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "env_raw",
+ .bbname = "env0",
+ }, {
+ /* sentinel */
+ }
+};
+
+static const struct devfs_partition pcm038_nor0_partitions[] = {
+ {
+ .offset = 0,
+ .size = SZ_512K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "self0",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND, /* 512 KiB */
+ .size = SZ_128K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "env0",
+ }, {
+ /* sentinel */
+ }
+};
+
static int pcm038_devices_init(void)
{
int i;
@@ -336,19 +370,12 @@ static int pcm038_devices_init(void)
switch (bootsource_get()) {
case BOOTSOURCE_NAND:
- devfs_add_partition("nand0", 0, SZ_512K,
- DEVFS_PARTITION_FIXED, "self_raw");
- dev_add_bb_dev("self_raw", "self0");
- devfs_add_partition("nand0", SZ_512K, SZ_128K,
- DEVFS_PARTITION_FIXED, "env_raw");
- dev_add_bb_dev("env_raw", "env0");
+ devfs_create_partitions("nand0", pcm038_nand0_partitions);
+
envdev = "NAND";
break;
default:
- devfs_add_partition("nor0", 0, SZ_512K,
- DEVFS_PARTITION_FIXED, "self0");
- devfs_add_partition("nor0", SZ_512K, SZ_128K,
- DEVFS_PARTITION_FIXED, "env0");
+ devfs_create_partitions("nor0", pcm038_nor0_partitions);
protect_file("/dev/env0", 1);
envdev = "NOR";
}
diff --git a/arch/arm/boards/sama5d3xek/init.c b/arch/arm/boards/sama5d3xek/init.c
index 4f866aa6f8..e078642242 100644
--- a/arch/arm/boards/sama5d3xek/init.c
+++ b/arch/arm/boards/sama5d3xek/init.c
@@ -400,6 +400,38 @@ static void ek_add_device_hdmi(void)
}
#endif
+static const struct devfs_partition at91sama5d3xek_nand0_partitions[] = {
+ {
+ .offset = 0x00000,
+ .size = SZ_256K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "at91bootstrap_raw",
+ .bbname = "at91bootstrap",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND, /* 256 KiB */
+ .size = SZ_256K + SZ_128K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "self_raw",
+ .bbname = "self0",
+ },
+ /* hole of 128 KiB */
+ {
+ .offset = SZ_512K + SZ_256K,
+ .size = SZ_256K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "env_raw",
+ .bbname = "env0",
+ }, {
+ .offset = DEVFS_PARTITION_APPEND, /* 1 MiB */
+ .size = SZ_256K,
+ .flags = DEVFS_PARTITION_FIXED,
+ .name = "env_raw1",
+ .bbname = "env1",
+ }, {
+ /* sentinel */
+ }
+};
+
static int at91sama5d3xek_devices_init(void)
{
ek_add_device_w1();
@@ -411,14 +443,7 @@ static int at91sama5d3xek_devices_init(void)
ek_add_device_mci();
ek_add_device_lcdc();
- devfs_add_partition("nand0", 0x00000, SZ_256K, DEVFS_PARTITION_FIXED, "at91bootstrap_raw");
- dev_add_bb_dev("at91bootstrap_raw", "at91bootstrap");
- devfs_add_partition("nand0", SZ_256K, SZ_256K + SZ_128K, DEVFS_PARTITION_FIXED, "self_raw");
- dev_add_bb_dev("self_raw", "self0");
- devfs_add_partition("nand0", SZ_512K + SZ_256K, SZ_256K, DEVFS_PARTITION_FIXED, "env_raw");
- dev_add_bb_dev("env_raw", "env0");
- devfs_add_partition("nand0", SZ_1M, SZ_256K, DEVFS_PARTITION_FIXED, "env_raw1");
- dev_add_bb_dev("env_raw1", "env1");
+ devfs_create_partitions("nand0", at91sama5d3xek_nand0_partitions);
return 0;
}
diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c
index 0292f2f426..f387ef687a 100644
--- a/drivers/mtd/nand/nand-bb.c
+++ b/drivers/mtd/nand/nand-bb.c
@@ -261,7 +261,7 @@ static LIST_HEAD(bb_list);
* @param[in] name Partition name (can be obtained with devinfo command)
* @return The device representing the new partition.
*/
-int dev_add_bb_dev(char *path, const char *name)
+int dev_add_bb_dev(const char *path, const char *name)
{
struct nand_bb *bb;
int ret = -ENOMEM;
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index bd6d482867..eafdc878ac 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <malloc.h>
#include <ioctl.h>
+#include <nand.h>
#include <linux/err.h>
#include <linux/mtd/mtd.h>
@@ -260,47 +261,88 @@ int devfs_remove(struct cdev *cdev)
return 0;
}
-struct cdev *devfs_add_partition(const char *devname, loff_t offset, loff_t size,
- int flags, const char *name)
+static struct cdev *__devfs_add_partition(struct cdev *cdev,
+ const struct devfs_partition *partinfo, loff_t *end)
{
- struct cdev *cdev, *new;
+ loff_t offset, size;
+ static struct cdev *new;
- cdev = cdev_by_name(name);
- if (cdev)
+ if (cdev_by_name(partinfo->name))
return ERR_PTR(-EEXIST);
- cdev = cdev_by_name(devname);
- if (!cdev)
- return ERR_PTR(-ENOENT);
-
- if (offset + size > cdev->size)
+ if (partinfo->offset > 0)
+ offset = partinfo->offset;
+ else if (partinfo->offset == 0)
+ /* append to previous partition */
+ offset = *end;
+ else
+ /* relative to end of cdev */
+ offset = cdev->size + partinfo->offset;
+
+ if (partinfo->size > 0)
+ size = partinfo->size;
+ else
+ size = cdev->size + partinfo->size - offset;
+
+ if (offset >= 0 && offset < *end)
+ pr_debug("partition %s not after previous partition\n",
+ partinfo->name);
+
+ *end = offset + size;
+
+ if (offset < 0 || *end > cdev->size) {
+ pr_warn("partition %s not completely inside device %s\n",
+ partinfo->name, cdev->name);
return ERR_PTR(-EINVAL);
+ }
if (IS_ENABLED(CONFIG_PARTITION_NEED_MTD) && cdev->mtd) {
struct mtd_info *mtd;
- mtd = mtd_add_partition(cdev->mtd, offset, size, flags, name);
+ mtd = mtd_add_partition(cdev->mtd, offset, size,
+ partinfo->flags, partinfo->name);
if (IS_ERR(mtd))
return (void *)mtd;
return 0;
}
- new = xzalloc(sizeof (*new));
- new->name = strdup(name);
- if (!strncmp(devname, name, strlen(devname)))
- new->partname = xstrdup(name + strlen(devname) + 1);
+ new = xzalloc(sizeof(*new));
+ new->name = strdup(partinfo->name);
+ if (!strncmp(cdev->name, partinfo->name, strlen(cdev->name)))
+ new->partname = xstrdup(partinfo->name + strlen(cdev->name) + 1);
+
new->ops = cdev->ops;
new->priv = cdev->priv;
new->size = size;
- new->offset = offset + cdev->offset;
+ new->offset = cdev->offset + offset;
+
new->dev = cdev->dev;
- new->flags = flags | DEVFS_IS_PARTITION;
+ new->flags = partinfo->flags | DEVFS_IS_PARTITION;
devfs_create(new);
return new;
}
+struct cdev *devfs_add_partition(const char *devname, loff_t offset,
+ loff_t size, unsigned int flags, const char *name)
+{
+ struct cdev *cdev;
+ loff_t end = 0;
+ const struct devfs_partition partinfo = {
+ .offset = offset,
+ .size = size,
+ .flags = flags,
+ .name = name,
+ };
+
+ cdev = cdev_by_name(devname);
+ if (!cdev)
+ return ERR_PTR(-ENOENT);
+
+ return __devfs_add_partition(cdev, &partinfo, &end);
+}
+
int devfs_del_partition(const char *name)
{
struct cdev *cdev;
@@ -330,3 +372,27 @@ int devfs_del_partition(const char *name)
return 0;
}
+
+int devfs_create_partitions(const char *devname,
+ const struct devfs_partition partinfo[])
+{
+ loff_t offset = 0;
+ struct cdev *cdev;
+
+ cdev = cdev_by_name(devname);
+ if (!cdev)
+ return -ENOENT;
+
+ for (; partinfo->name; ++partinfo) {
+ struct cdev *new;
+
+ new = __devfs_add_partition(cdev, partinfo, &offset);
+ if (IS_ERR(new))
+ return PTR_ERR(new);
+
+ if (partinfo->bbname)
+ dev_add_bb_dev(partinfo->name, partinfo->bbname);
+ }
+
+ return 0;
+}
diff --git a/include/driver.h b/include/driver.h
index cbb040170c..01b181ddbd 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -482,15 +482,48 @@ ssize_t cdev_write(struct cdev *cdev, const void *buf, size_t count, loff_t offs
int cdev_ioctl(struct cdev *cdev, int cmd, void *buf);
int cdev_erase(struct cdev *cdev, size_t count, loff_t offset);
-#define DEVFS_PARTITION_FIXED (1 << 0)
-#define DEVFS_PARTITION_READONLY (1 << 1)
+#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)
-struct cdev *devfs_add_partition(const char *devname, loff_t offset, loff_t size,
- int flags, const char *name);
+struct cdev *devfs_add_partition(const char *devname, loff_t offset,
+ loff_t size, unsigned int flags, const char *name);
int devfs_del_partition(const char *name);
+#define DEVFS_PARTITION_APPEND 0
+
+/**
+ * struct devfs_partition - defines parameters for a single partition
+ * @offset: start of partition
+ * a negative offset requests to start the partition relative to the
+ * device's end. DEVFS_PARTITION_APPEND (i.e. 0) means start directly at
+ * the end of the previous partition.
+ * @size: size of partition
+ * a non-positive value requests to use a size that keeps -size free space
+ * after the current partition. A special case of this is passing 0, which
+ * means "until end of device".
+ * @flags: flags passed to devfs_add_partition
+ * @name: name passed to devfs_add_partition
+ * @bbname: if non-NULL also dev_add_bb_dev() is called for the partition during
+ * devfs_create_partitions().
+ */
+struct devfs_partition {
+ loff_t offset;
+ loff_t size;
+ unsigned int flags;
+ const char *name;
+ const char *bbname;
+};
+/**
+ * devfs_create_partitions - create a set of partitions for a device
+ * @devname: name of the device to partition
+ * @partinfo: array of partition parameters
+ * The array is processed until an entry with .name = NULL is found.
+ */
+int devfs_create_partitions(const char *devname,
+ const struct devfs_partition partinfo[]);
+
#define DRV_OF_COMPAT(compat) \
IS_ENABLED(CONFIG_OFDEVICE) ? (compat) : NULL
diff --git a/include/nand.h b/include/nand.h
index b1762dfa45..a0e77cc8cd 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -5,10 +5,10 @@
struct nand_bb;
#ifdef CONFIG_NAND
-int dev_add_bb_dev(char *filename, const char *name);
+int dev_add_bb_dev(const char *filename, const char *name);
int dev_remove_bb_dev(const char *name);
#else
-static inline int dev_add_bb_dev(char *filename, const char *name) {
+static inline int dev_add_bb_dev(const char *filename, const char *name) {
return 0;
}
static inline int dev_remove_bb_dev(const char *name)