linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mtd: physmap_of: Add multiple regions and concatenation support
@ 2009-04-03  9:55 Stefan Roese
  2009-04-03 14:04 ` Grant Likely
  0 siblings, 1 reply; 3+ messages in thread
From: Stefan Roese @ 2009-04-03  9:55 UTC (permalink / raw)
  To: linux-mtd, linuxppc-dev

This patch adds support to handle multiple non-identical chips in one
flash device tree node. It also adds concat support to physmap_of. This
makes it possible to support e.g. the Intel P30 48F4400 chips which
internally consists of 2 non-identical NOR chips on one die. Additionally
partitions now can span over multiple chips.

To describe such a chip's, multiple "reg" tuples are now supported in one
flash device tree node. Here an dts example:

        flash@f0000000,0 {
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "cfi-flash";
                reg = <0 0x00000000 0x02000000
                       0 0x02000000 0x02000000>;
                bank-width = <2>;
                partition@0 {
                        label = "test-part1";
                        reg = <0 0x04000000>;
                };
        };

Signed-off-by: Stefan Roese <sr@denx.de>
CC: Grant Likely <grant.likely@secretlab.ca>
---
 drivers/mtd/maps/physmap_of.c |  174 ++++++++++++++++++++++++++++-------------
 1 files changed, 120 insertions(+), 54 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 5fcfec0..c1c2d08 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -20,13 +20,17 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mtd/concat.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 
+#define MAX_RESOURCES		4
+
 struct of_flash {
-	struct mtd_info		*mtd;
-	struct map_info		map;
-	struct resource		*res;
+	struct mtd_info		*mtd[MAX_RESOURCES];
+	struct mtd_info		*cmtd;
+	struct map_info		map[MAX_RESOURCES];
+	struct resource		*res[MAX_RESOURCES];
 #ifdef CONFIG_MTD_PARTITIONS
 	struct mtd_partition	*parts;
 #endif
@@ -88,28 +92,40 @@ static int parse_obsolete_partitions(struct of_device *dev,
 static int of_flash_remove(struct of_device *dev)
 {
 	struct of_flash *info;
+	int i;
 
 	info = dev_get_drvdata(&dev->dev);
 	if (!info)
 		return 0;
 	dev_set_drvdata(&dev->dev, NULL);
 
-	if (info->mtd) {
+#ifdef CONFIG_MTD_CONCAT
+	if (info->cmtd != info->mtd[0]) {
+		del_mtd_device(info->cmtd);
+		mtd_concat_destroy(info->cmtd);
+	}
+#endif
+
+	if (info->cmtd) {
 		if (OF_FLASH_PARTS(info)) {
-			del_mtd_partitions(info->mtd);
+			del_mtd_partitions(info->cmtd);
 			kfree(OF_FLASH_PARTS(info));
 		} else {
-			del_mtd_device(info->mtd);
+			del_mtd_device(info->cmtd);
 		}
-		map_destroy(info->mtd);
 	}
 
-	if (info->map.virt)
-		iounmap(info->map.virt);
+	for (i = 0; i < MAX_RESOURCES; i++) {
+		if (info->mtd[i])
+			map_destroy(info->mtd[i]);
+
+		if (info->map[i].virt)
+			iounmap(info->map[i].virt);
 
-	if (info->res) {
-		release_resource(info->res);
-		kfree(info->res);
+		if (info->res[i]) {
+			release_resource(info->res[i]);
+			kfree(info->res[i]);
+		}
 	}
 
 	return 0;
@@ -164,15 +180,25 @@ static int __devinit of_flash_probe(struct of_device *dev,
 	const char *probe_type = match->data;
 	const u32 *width;
 	int err;
-
-	err = -ENXIO;
-	if (of_address_to_resource(dp, 0, &res)) {
-		dev_err(&dev->dev, "Can't get IO address from device tree\n");
+	int i;
+	int count;
+	const u32 *p;
+	int devices_found = 0;
+
+	/*
+	 * Get number of "reg" tuples. Scan for MTD devices on area's
+	 * described by each "reg" region. This makes it possible (including
+	 * the concat support) to support the Intel P30 48F4400 chips which
+	 * consists internally of 2 non-identical NOR chips on one die.
+	 */
+	p = of_get_property(dp, "reg", &count);
+	if (count % 12 != 0) {
+		dev_err(&dev->dev, "Malformed reg property on %s\n",
+				dev->node->full_name);
+		err = -EINVAL;
 		goto err_out;
 	}
-
-       	dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
-		(unsigned long long)res.start, (unsigned long long)res.end);
+	count /= 12;
 
 	err = -ENOMEM;
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -181,50 +207,90 @@ static int __devinit of_flash_probe(struct of_device *dev,
 
 	dev_set_drvdata(&dev->dev, info);
 
-	err = -EBUSY;
-	info->res = request_mem_region(res.start, res.end - res.start + 1,
-				       dev_name(&dev->dev));
-	if (!info->res)
-		goto err_out;
+	for (i = 0; i < count; i++) {
+		err = -ENXIO;
+		if (of_address_to_resource(dp, i, &res)) {
+			dev_err(&dev->dev, "Can't get IO address from device"
+				" tree\n");
+			goto err_out;
+		}
 
-	err = -ENXIO;
-	width = of_get_property(dp, "bank-width", NULL);
-	if (!width) {
-		dev_err(&dev->dev, "Can't get bank width from device tree\n");
-		goto err_out;
-	}
+		dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
+			(unsigned long long)res.start,
+			(unsigned long long)res.end);
+
+		err = -EBUSY;
+		info->res[i] = request_mem_region(res.start, res.end -
+						  res.start + 1,
+						  dev_name(&dev->dev));
+		if (!info->res[i])
+			goto err_out;
+
+		err = -ENXIO;
+		width = of_get_property(dp, "bank-width", NULL);
+		if (!width) {
+			dev_err(&dev->dev, "Can't get bank width from device"
+				" tree\n");
+			goto err_out;
+		}
 
-	info->map.name = dev_name(&dev->dev);
-	info->map.phys = res.start;
-	info->map.size = res.end - res.start + 1;
-	info->map.bankwidth = *width;
+		info->map[i].name = dev_name(&dev->dev);
+		info->map[i].phys = res.start;
+		info->map[i].size = res.end - res.start + 1;
+		info->map[i].bankwidth = *width;
+
+		err = -ENOMEM;
+		info->map[i].virt = ioremap(info->map[i].phys,
+					    info->map[i].size);
+		if (!info->map[i].virt) {
+			dev_err(&dev->dev, "Failed to ioremap() flash"
+				" region\n");
+			goto err_out;
+		}
 
-	err = -ENOMEM;
-	info->map.virt = ioremap(info->map.phys, info->map.size);
-	if (!info->map.virt) {
-		dev_err(&dev->dev, "Failed to ioremap() flash region\n");
-		goto err_out;
-	}
+		simple_map_init(&info->map[i]);
 
-	simple_map_init(&info->map);
+		if (probe_type)
+			info->mtd[i] = do_map_probe(probe_type, &info->map[i]);
+		else
+			info->mtd[i] = obsolete_probe(dev, &info->map[i]);
 
-	if (probe_type)
-		info->mtd = do_map_probe(probe_type, &info->map);
-	else
-		info->mtd = obsolete_probe(dev, &info->map);
+		err = -ENXIO;
+		if (!info->mtd[i]) {
+			dev_err(&dev->dev, "do_map_probe() failed\n");
+			goto err_out;
+		} else {
+			devices_found++;
+		}
+		info->mtd[i]->owner = THIS_MODULE;
+	}
 
-	err = -ENXIO;
-	if (!info->mtd) {
-		dev_err(&dev->dev, "do_map_probe() failed\n");
-		goto err_out;
+	err = 0;
+	if (devices_found == 1) {
+		info->cmtd = info->mtd[0];
+	} else if (devices_found > 1) {
+		/*
+		 * We detected multiple devices. Concatenate them together.
+		 */
+#ifdef CONFIG_MTD_CONCAT
+		info->cmtd = mtd_concat_create(info->mtd, devices_found,
+					       dev_name(&dev->dev));
+		if (info->cmtd == NULL)
+			err = -ENXIO;
+#else
+		printk(KERN_ERR "physmap_of: multiple devices "
+		       "found but MTD concat support disabled.\n");
+		err = -ENXIO;
+#endif
 	}
-	info->mtd->owner = THIS_MODULE;
+	if (err)
+		goto err_out;
 
 #ifdef CONFIG_MTD_PARTITIONS
 	/* First look for RedBoot table or partitions on the command
 	 * line, these take precedence over device tree information */
-	err = parse_mtd_partitions(info->mtd, part_probe_types,
-	                           &info->parts, 0);
+	err = parse_mtd_partitions(info->cmtd, part_probe_types,
+				   &info->parts, 0);
 	if (err < 0)
 		return err;
 
@@ -243,10 +309,10 @@ static int __devinit of_flash_probe(struct of_device *dev,
 	}
 
 	if (err > 0)
-		add_mtd_partitions(info->mtd, info->parts, err);
+		add_mtd_partitions(info->cmtd, info->parts, err);
 	else
 #endif
-		add_mtd_device(info->mtd);
+		add_mtd_device(info->cmtd);
 
 	return 0;
 
-- 
1.6.2.2

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] mtd: physmap_of: Add multiple regions and concatenation support
  2009-04-03  9:55 [PATCH] mtd: physmap_of: Add multiple regions and concatenation support Stefan Roese
@ 2009-04-03 14:04 ` Grant Likely
  2009-04-06  7:43   ` Stefan Roese
  0 siblings, 1 reply; 3+ messages in thread
From: Grant Likely @ 2009-04-03 14:04 UTC (permalink / raw)
  To: Stefan Roese; +Cc: linuxppc-dev, devicetree-discuss, linux-mtd

On Fri, Apr 3, 2009 at 3:55 AM, Stefan Roese <sr@denx.de> wrote:
> This patch adds support to handle multiple non-identical chips in one
> flash device tree node. It also adds concat support to physmap_of. This
> makes it possible to support e.g. the Intel P30 48F4400 chips which
> internally consists of 2 non-identical NOR chips on one die. Additionally
> partitions now can span over multiple chips.
>
> To describe such a chip's, multiple "reg" tuples are now supported in one
> flash device tree node. Here an dts example:
>
> =A0 =A0 =A0 =A0flash@f0000000,0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0#address-cells =3D <1>;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0#size-cells =3D <1>;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0compatible =3D "cfi-flash";
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0reg =3D <0 0x00000000 0x02000000
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0 0x02000000 0x02000000>;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bank-width =3D <2>;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0partition@0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0label =3D "test-part1";
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0reg =3D <0 0x04000000>;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0};
> =A0 =A0 =A0 =A0};

Binding looks good to me.  Add a variant of this blurb to
Documentation/powerpc/booting-without-of.txt.  For extra credit,
factor out the MTD stuff and move it to
Documentation/powerpc/dts-bindings/.  Remember to cc: the
devicetree-discuss@ozlabs.org list when you post the binding
documentation.

> Signed-off-by: Stefan Roese <sr@denx.de>
> CC: Grant Likely <grant.likely@secretlab.ca>
> ---
> =A0drivers/mtd/maps/physmap_of.c | =A0174 ++++++++++++++++++++++++++++---=
----------
> =A01 files changed, 120 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.=
c
> index 5fcfec0..c1c2d08 100644
> --- a/drivers/mtd/maps/physmap_of.c
> +++ b/drivers/mtd/maps/physmap_of.c
> @@ -20,13 +20,17 @@
> =A0#include <linux/mtd/mtd.h>
> =A0#include <linux/mtd/map.h>
> =A0#include <linux/mtd/partitions.h>
> +#include <linux/mtd/concat.h>
> =A0#include <linux/of.h>
> =A0#include <linux/of_platform.h>
>
> +#define MAX_RESOURCES =A0 =A0 =A0 =A0 =A04
> +

Why is this static?  Instead you could define:

struct of_flash_list {
        struct mtd_info *mtd;
        struct map_info map;
        struct resource *res;
};

struct of_flash {
        struct mtd_info         *cmtd;
#ifdef CONFIG_MTD_PARTITIONS
        struct mtd_partition    *parts;
#endif
        int list_size; /* number of elements in of_flash_list */
        struct of_flash_list     list[0];
};

Using a zero length array at the end of the structure allows you to do
this after counting the number of reg tuples:

f =3D kzalloc(sizeof(struct of_flash) + sizeof(struct of_flash_list)*num_ch=
ips);

That eliminates a needless hard limit to the number of flash chips.

> =A0struct of_flash {
> - =A0 =A0 =A0 struct mtd_info =A0 =A0 =A0 =A0 *mtd;
> - =A0 =A0 =A0 struct map_info =A0 =A0 =A0 =A0 map;
> - =A0 =A0 =A0 struct resource =A0 =A0 =A0 =A0 *res;
> + =A0 =A0 =A0 struct mtd_info =A0 =A0 =A0 =A0 *mtd[MAX_RESOURCES];
> + =A0 =A0 =A0 struct mtd_info =A0 =A0 =A0 =A0 *cmtd;
> + =A0 =A0 =A0 struct map_info =A0 =A0 =A0 =A0 map[MAX_RESOURCES];
> + =A0 =A0 =A0 struct resource =A0 =A0 =A0 =A0 *res[MAX_RESOURCES];
> =A0#ifdef CONFIG_MTD_PARTITIONS
> =A0 =A0 =A0 =A0struct mtd_partition =A0 =A0*parts;
> =A0#endif
> @@ -88,28 +92,40 @@ static int parse_obsolete_partitions(struct of_device=
 *dev,
> =A0static int of_flash_remove(struct of_device *dev)
> =A0{
> =A0 =A0 =A0 =A0struct of_flash *info;
> + =A0 =A0 =A0 int i;
>
> =A0 =A0 =A0 =A0info =3D dev_get_drvdata(&dev->dev);
> =A0 =A0 =A0 =A0if (!info)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return 0;
> =A0 =A0 =A0 =A0dev_set_drvdata(&dev->dev, NULL);
>
> - =A0 =A0 =A0 if (info->mtd) {
> +#ifdef CONFIG_MTD_CONCAT
> + =A0 =A0 =A0 if (info->cmtd !=3D info->mtd[0]) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_device(info->cmtd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mtd_concat_destroy(info->cmtd);
> + =A0 =A0 =A0 }
> +#endif
> +
> + =A0 =A0 =A0 if (info->cmtd) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (OF_FLASH_PARTS(info)) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_partitions(info->mt=
d);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_partitions(info->cm=
td);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0kfree(OF_FLASH_PARTS(info)=
);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_device(info->mtd);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_device(info->cmtd);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 map_destroy(info->mtd);
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 if (info->map.virt)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 iounmap(info->map.virt);
> + =A0 =A0 =A0 for (i =3D 0; i < MAX_RESOURCES; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (info->mtd[i])
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 map_destroy(info->mtd[i]);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (info->map[i].virt)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 iounmap(info->map[i].virt);
>
> - =A0 =A0 =A0 if (info->res) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 release_resource(info->res);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 kfree(info->res);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (info->res[i]) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 release_resource(info->res[=
i]);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 kfree(info->res[i]);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0return 0;
> @@ -164,15 +180,25 @@ static int __devinit of_flash_probe(struct of_devic=
e *dev,
> =A0 =A0 =A0 =A0const char *probe_type =3D match->data;
> =A0 =A0 =A0 =A0const u32 *width;
> =A0 =A0 =A0 =A0int err;
> -
> - =A0 =A0 =A0 err =3D -ENXIO;
> - =A0 =A0 =A0 if (of_address_to_resource(dp, 0, &res)) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&dev->dev, "Can't get IO address fr=
om device tree\n");
> + =A0 =A0 =A0 int i;
> + =A0 =A0 =A0 int count;
> + =A0 =A0 =A0 const u32 *p;
> + =A0 =A0 =A0 int devices_found =3D 0;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Get number of "reg" tuples. Scan for MTD devices on ar=
ea's
> + =A0 =A0 =A0 =A0* described by each "reg" region. This makes it possible=
 (including
> + =A0 =A0 =A0 =A0* the concat support) to support the Intel P30 48F4400 c=
hips which
> + =A0 =A0 =A0 =A0* consists internally of 2 non-identical NOR chips on on=
e die.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 p =3D of_get_property(dp, "reg", &count);
> + =A0 =A0 =A0 if (count % 12 !=3D 0) {

This doesn't work.  You cannot know the size of each reg tuple until
#address-cells/#size-cells is parsed for the parent node.  It won't
always be 12.  Use of_n_addr_cells() + of_n_size_cells() to determine
size of each tuple.

Other than that, I think it looks good, but I'll look again when you repost=
.

g.

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] mtd: physmap_of: Add multiple regions and concatenation support
  2009-04-03 14:04 ` Grant Likely
@ 2009-04-06  7:43   ` Stefan Roese
  0 siblings, 0 replies; 3+ messages in thread
From: Stefan Roese @ 2009-04-06  7:43 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev, devicetree-discuss, linux-mtd

On Friday 03 April 2009, Grant Likely wrote:
> > =A0 =A0 =A0 =A0flash@f0000000,0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0#address-cells =3D <1>;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0#size-cells =3D <1>;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0compatible =3D "cfi-flash";
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0reg =3D <0 0x00000000 0x02000000
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0 0x02000000 0x02000000>;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bank-width =3D <2>;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0partition@0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0label =3D "test-part1";
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0reg =3D <0 0x04000000>;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0};
> > =A0 =A0 =A0 =A0};
>
> Binding looks good to me.  Add a variant of this blurb to
> Documentation/powerpc/booting-without-of.txt.  For extra credit,
> factor out the MTD stuff and move it to
> Documentation/powerpc/dts-bindings/.  Remember to cc: the
> devicetree-discuss@ozlabs.org list when you post the binding
> documentation.

OK, will do.

> > Signed-off-by: Stefan Roese <sr@denx.de>
> > CC: Grant Likely <grant.likely@secretlab.ca>
> > ---
> > =A0drivers/mtd/maps/physmap_of.c | =A0174
> > ++++++++++++++++++++++++++++------------- 1 files changed, 120
> > insertions(+), 54 deletions(-)
> >
> > diff --git a/drivers/mtd/maps/physmap_of.c
> > b/drivers/mtd/maps/physmap_of.c index 5fcfec0..c1c2d08 100644
> > --- a/drivers/mtd/maps/physmap_of.c
> > +++ b/drivers/mtd/maps/physmap_of.c
> > @@ -20,13 +20,17 @@
> > =A0#include <linux/mtd/mtd.h>
> > =A0#include <linux/mtd/map.h>
> > =A0#include <linux/mtd/partitions.h>
> > +#include <linux/mtd/concat.h>
> > =A0#include <linux/of.h>
> > =A0#include <linux/of_platform.h>
> >
> > +#define MAX_RESOURCES =A0 =A0 =A0 =A0 =A04
> > +
>
> Why is this static?

Because I cloned it from physmap.c.

> Instead you could define:=20
>
> struct of_flash_list {
>         struct mtd_info *mtd;
>         struct map_info map;
>         struct resource *res;
> };
>
> struct of_flash {
>         struct mtd_info         *cmtd;
> #ifdef CONFIG_MTD_PARTITIONS
>         struct mtd_partition    *parts;
> #endif
>         int list_size; /* number of elements in of_flash_list */
>         struct of_flash_list     list[0];
> };
>
> Using a zero length array at the end of the structure allows you to do
> this after counting the number of reg tuples:
>
> f =3D kzalloc(sizeof(struct of_flash) + sizeof(struct
> of_flash_list)*num_chips);
>
> That eliminates a needless hard limit to the number of flash chips.

Good idea. Will update. Thanks.

> > =A0struct of_flash {
> > - =A0 =A0 =A0 struct mtd_info =A0 =A0 =A0 =A0 *mtd;
> > - =A0 =A0 =A0 struct map_info =A0 =A0 =A0 =A0 map;
> > - =A0 =A0 =A0 struct resource =A0 =A0 =A0 =A0 *res;
> > + =A0 =A0 =A0 struct mtd_info =A0 =A0 =A0 =A0 *mtd[MAX_RESOURCES];
> > + =A0 =A0 =A0 struct mtd_info =A0 =A0 =A0 =A0 *cmtd;
> > + =A0 =A0 =A0 struct map_info =A0 =A0 =A0 =A0 map[MAX_RESOURCES];
> > + =A0 =A0 =A0 struct resource =A0 =A0 =A0 =A0 *res[MAX_RESOURCES];
> > =A0#ifdef CONFIG_MTD_PARTITIONS
> > =A0 =A0 =A0 =A0struct mtd_partition =A0 =A0*parts;
> > =A0#endif
> > @@ -88,28 +92,40 @@ static int parse_obsolete_partitions(struct of_devi=
ce
> > *dev, static int of_flash_remove(struct of_device *dev)
> > =A0{
> > =A0 =A0 =A0 =A0struct of_flash *info;
> > + =A0 =A0 =A0 int i;
> >
> > =A0 =A0 =A0 =A0info =3D dev_get_drvdata(&dev->dev);
> > =A0 =A0 =A0 =A0if (!info)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return 0;
> > =A0 =A0 =A0 =A0dev_set_drvdata(&dev->dev, NULL);
> >
> > - =A0 =A0 =A0 if (info->mtd) {
> > +#ifdef CONFIG_MTD_CONCAT
> > + =A0 =A0 =A0 if (info->cmtd !=3D info->mtd[0]) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_device(info->cmtd);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 mtd_concat_destroy(info->cmtd);
> > + =A0 =A0 =A0 }
> > +#endif
> > +
> > + =A0 =A0 =A0 if (info->cmtd) {
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (OF_FLASH_PARTS(info)) {
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_partitions(info->=
mtd);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_partitions(info->=
cmtd);
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0kfree(OF_FLASH_PARTS(inf=
o));
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else {
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_device(info->mtd);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 del_mtd_device(info->cmtd=
);
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 map_destroy(info->mtd);
> > =A0 =A0 =A0 =A0}
> >
> > - =A0 =A0 =A0 if (info->map.virt)
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 iounmap(info->map.virt);
> > + =A0 =A0 =A0 for (i =3D 0; i < MAX_RESOURCES; i++) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (info->mtd[i])
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 map_destroy(info->mtd[i]);
> > +
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (info->map[i].virt)
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 iounmap(info->map[i].virt=
);
> >
> > - =A0 =A0 =A0 if (info->res) {
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 release_resource(info->res);
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 kfree(info->res);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (info->res[i]) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 release_resource(info->re=
s[i]);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 kfree(info->res[i]);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> > =A0 =A0 =A0 =A0}
> >
> > =A0 =A0 =A0 =A0return 0;
> > @@ -164,15 +180,25 @@ static int __devinit of_flash_probe(struct
> > of_device *dev, const char *probe_type =3D match->data;
> > =A0 =A0 =A0 =A0const u32 *width;
> > =A0 =A0 =A0 =A0int err;
> > -
> > - =A0 =A0 =A0 err =3D -ENXIO;
> > - =A0 =A0 =A0 if (of_address_to_resource(dp, 0, &res)) {
> > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&dev->dev, "Can't get IO address =
from device
> > tree\n"); + =A0 =A0 =A0 int i;
> > + =A0 =A0 =A0 int count;
> > + =A0 =A0 =A0 const u32 *p;
> > + =A0 =A0 =A0 int devices_found =3D 0;
> > +
> > + =A0 =A0 =A0 /*
> > + =A0 =A0 =A0 =A0* Get number of "reg" tuples. Scan for MTD devices on =
area's
> > + =A0 =A0 =A0 =A0* described by each "reg" region. This makes it possib=
le
> > (including + =A0 =A0 =A0 =A0* the concat support) to support the Intel =
P30
> > 48F4400 chips which + =A0 =A0 =A0 =A0* consists internally of 2 non-ide=
ntical NOR
> > chips on one die. + =A0 =A0 =A0 =A0*/
> > + =A0 =A0 =A0 p =3D of_get_property(dp, "reg", &count);
> > + =A0 =A0 =A0 if (count % 12 !=3D 0) {
>
> This doesn't work.  You cannot know the size of each reg tuple until
> #address-cells/#size-cells is parsed for the parent node.  It won't
> always be 12.  Use of_n_addr_cells() + of_n_size_cells() to determine
> size of each tuple.

OK, I'll change it in the next patch version.

Thanks.

Best regards,
Stefan

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-04-06  7:43 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-03  9:55 [PATCH] mtd: physmap_of: Add multiple regions and concatenation support Stefan Roese
2009-04-03 14:04 ` Grant Likely
2009-04-06  7:43   ` Stefan Roese

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).