linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
@ 2009-06-02  4:07 Mike Frysinger
  2009-06-02 22:58 ` Ben Dooks
  2009-06-03 12:51 ` [PATCH v2] " Mike Frysinger
  0 siblings, 2 replies; 15+ messages in thread
From: Mike Frysinger @ 2009-06-02  4:07 UTC (permalink / raw)
  To: linux-mtd; +Cc: uclinux-dist-devel, Bryan Wu

This driver lets people use GPIO's for additional address lines in case
their processor does not have enough address lines already.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
---
 drivers/mtd/maps/Kconfig           |   10 ++
 drivers/mtd/maps/Makefile          |    1 +
 drivers/mtd/maps/gpio-addr-flash.c |  220 ++++++++++++++++++++++++++++++++++++
 3 files changed, 231 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/maps/gpio-addr-flash.c

diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 82923bd..05f6c08 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -500,6 +500,16 @@ config MTD_BFIN_ASYNC
 
 	  If compiled as a module, it will be called bfin-async-flash.
 
+config MTD_GPIO_ADDR
+	tristate "GPIO-assisted Flash Chip Support"
+	depends on MTD_COMPLEX_MAPPINGS
+	select MTD_PARTITIONS
+	help
+	  Map driver which allows flashes to be partially physically addressed
+	  and assisted by GPIOs.
+
+	  If compiled as a module, it will be called gpio-addr-flash.
+
 config MTD_UCLINUX
 	tristate "Generic uClinux RAM/ROM filesystem support"
 	depends on MTD_PARTITIONS && MTD_RAM && !MMU
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 2dbc1be..d9cbd8a 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_MTD_INTEL_VR_NOR)	+= intel_vr_nor.o
 obj-$(CONFIG_MTD_BFIN_ASYNC)	+= bfin-async-flash.o
 obj-$(CONFIG_MTD_RBTX4939)	+= rbtx4939-flash.o
 obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
+obj-$(CONFIG_MTD_GPIO_ADDR)	+= gpio-addr-flash.o
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
new file mode 100644
index 0000000..524131d
--- /dev/null
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -0,0 +1,220 @@
+/*
+ * drivers/mtd/maps/gpio-addr-flash.c
+ *
+ * Handle the case where a flash device is mostly addressed using physical
+ * line and supplemented by GPIOs.  This way you can hook up say a 8meg flash
+ * to a 2meg memory range and use the GPIOs to select a particular range.
+ *
+ * Copyright 2000 Nicolas Pitre <nico@cam.org>
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
+
+#define DRIVER_NAME "gpio-addr-flash"
+
+struct async_state {
+	struct mtd_info *mtd;
+	struct map_info map;
+	size_t gpio_count;
+	unsigned *gpio_addrs;
+	int *gpio_values;
+	unsigned long win_size;
+};
+
+static void gf_set_gpios(struct async_state *state, unsigned long ofs)
+{
+	size_t i;
+	int value;
+	for (i = 0; i < state->gpio_count; ++i) {
+		value = !!((ofs / state->win_size) & (1 << i));
+		if (state->gpio_values[i] != value) {
+			gpio_set_value(state->gpio_addrs[i], value);
+			state->gpio_values[i] = value;
+		}
+	}
+}
+
+static map_word gf_read(struct map_info *map, unsigned long ofs)
+{
+	struct async_state *state = (struct async_state *)map->map_priv_1;
+	u16 word;
+	map_word test;
+
+	gf_set_gpios(state, ofs);
+
+	word = readw(map->virt + (ofs % state->win_size));
+	test.x[0] = word;
+	return test;
+}
+
+static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
+{
+	struct async_state *state = (struct async_state *)map->map_priv_1;
+
+	gf_set_gpios(state, from);
+
+	/* BUG if operation crosss the win_size */
+	BUG_ON(!((from + len) % state->win_size <= (from + len)));
+
+	/* operation does not cross the win_size, so one shot it */
+	memcpy_fromio(to, map->virt + (from % state->win_size), len);
+}
+
+static void gf_write(struct map_info *map, map_word d1, unsigned long ofs)
+{
+	struct async_state *state = (struct async_state *)map->map_priv_1;
+	u16 d;
+
+	gf_set_gpios(state, ofs);
+
+	d = d1.x[0];
+	writew(d, map->virt + (ofs % state->win_size));
+}
+
+static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
+{
+	struct async_state *state = (struct async_state *)map->map_priv_1;
+
+	gf_set_gpios(state, to);
+
+	/* BUG if operation crosss the win_size */
+	BUG_ON(!((to + len) % state->win_size <= (to + len)));
+
+	/* operation does not cross the win_size, so one shot it */
+	memcpy_toio(map->virt + (to % state->win_size), from, len);
+}
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+#endif
+
+static int __devinit gpio_flash_probe(struct platform_device *pdev)
+{
+	int ret;
+	size_t i;
+	struct physmap_flash_data *pdata = pdev->dev.platform_data;
+	struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	struct resource *gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	struct async_state *state;
+
+	state = kzalloc(sizeof(*state) + (sizeof(int) * gpios->end * 2), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	state->gpio_count     = gpios->end;
+	state->gpio_addrs     = (void *)(state + 1);
+	state->gpio_values    = state->gpio_addrs + state->gpio_count;
+	state->win_size       = memory->end - memory->start + 1;
+	memcpy(state->gpio_addrs, (void *)gpios->start, sizeof(unsigned) * state->gpio_count);
+	for (i = 0; i < state->gpio_count; ++i)
+		state->gpio_values[i] = -1;
+
+	state->map.name       = DRIVER_NAME;
+	state->map.read       = gf_read;
+	state->map.copy_from  = gf_copy_from;
+	state->map.write      = gf_write;
+	state->map.copy_to    = gf_copy_to;
+	state->map.bankwidth  = pdata->width;
+	state->map.size       = state->win_size * (1 << state->gpio_count);
+	state->map.virt       = (void __iomem *)memory->start;
+	state->map.phys       = NO_XIP;
+	state->map.map_priv_1 = (unsigned long)state;
+
+	platform_set_drvdata(pdev, state);
+
+	for (i = 0; i < state->gpio_count; ++i) {
+		if (gpio_request(state->gpio_addrs[i], DRIVER_NAME)) {
+			pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->gpio_addrs[i]);
+			while (i--)
+				gpio_free(state->gpio_addrs[i]);
+			kfree(state);
+			return -EBUSY;
+		}
+		gpio_direction_output(state->gpio_addrs[i], 0);
+	}
+
+	pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
+	state->mtd = do_map_probe(memory->name, &state->map);
+	if (!state->mtd) {
+		for (i = 0; i < state->gpio_count; ++i)
+			gpio_free(state->gpio_addrs[i]);
+		kfree(state);
+		return -ENXIO;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
+	if (ret > 0) {
+		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
+		add_mtd_partitions(state->mtd, pdata->parts, ret);
+		kfree(pdata->parts);
+
+	} else if (pdata->nr_parts) {
+		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
+		add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts);
+
+	} else
+#endif
+	{
+		pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
+		add_mtd_device(state->mtd);
+	}
+
+	return 0;
+}
+
+static int __devexit gpio_flash_remove(struct platform_device *pdev)
+{
+	struct async_state *state = platform_get_drvdata(pdev);
+	size_t i;
+	for (i = 0; i < state->gpio_count; ++i)
+		gpio_free(state->gpio_addrs[i]);
+#ifdef CONFIG_MTD_PARTITIONS
+	del_mtd_partitions(state->mtd);
+#endif
+	map_destroy(state->mtd);
+	kfree(state);
+	return 0;
+}
+
+static struct platform_driver gpio_flash_driver = {
+	.probe		= gpio_flash_probe,
+	.remove		= __devexit_p(gpio_flash_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init gpio_flash_init(void)
+{
+	return platform_driver_register(&gpio_flash_driver);
+}
+module_init(gpio_flash_init);
+
+static void __exit gpio_flash_exit(void)
+{
+	platform_driver_unregister(&gpio_flash_driver);
+}
+module_exit(gpio_flash_exit);
+
+MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
+MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios");
+MODULE_LICENSE("GPL");
-- 
1.6.3.1

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

* Re: [PATCH] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-06-02  4:07 [PATCH] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing Mike Frysinger
@ 2009-06-02 22:58 ` Ben Dooks
  2009-06-02 23:37   ` [Uclinux-dist-devel] " Mike Frysinger
  2009-06-03 12:51 ` [PATCH v2] " Mike Frysinger
  1 sibling, 1 reply; 15+ messages in thread
From: Ben Dooks @ 2009-06-02 22:58 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: uclinux-dist-devel, Bryan Wu, linux-mtd

On Tue, Jun 02, 2009 at 12:07:30AM -0400, Mike Frysinger wrote:
> This driver lets people use GPIO's for additional address lines in case
> their processor does not have enough address lines already.
> 
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
> Signed-off-by: Bryan Wu <cooloney@kernel.org>
> ---
>  drivers/mtd/maps/Kconfig           |   10 ++
>  drivers/mtd/maps/Makefile          |    1 +
>  drivers/mtd/maps/gpio-addr-flash.c |  220 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 231 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mtd/maps/gpio-addr-flash.c
> 
> diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
> index 82923bd..05f6c08 100644
> --- a/drivers/mtd/maps/Kconfig
> +++ b/drivers/mtd/maps/Kconfig
> @@ -500,6 +500,16 @@ config MTD_BFIN_ASYNC
>  
>  	  If compiled as a module, it will be called bfin-async-flash.
>  
> +config MTD_GPIO_ADDR
> +	tristate "GPIO-assisted Flash Chip Support"
> +	depends on MTD_COMPLEX_MAPPINGS
> +	select MTD_PARTITIONS
> +	help
> +	  Map driver which allows flashes to be partially physically addressed
> +	  and assisted by GPIOs.
> +
> +	  If compiled as a module, it will be called gpio-addr-flash.
> +
>  config MTD_UCLINUX
>  	tristate "Generic uClinux RAM/ROM filesystem support"
>  	depends on MTD_PARTITIONS && MTD_RAM && !MMU
> diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
> index 2dbc1be..d9cbd8a 100644
> --- a/drivers/mtd/maps/Makefile
> +++ b/drivers/mtd/maps/Makefile
> @@ -62,3 +62,4 @@ obj-$(CONFIG_MTD_INTEL_VR_NOR)	+= intel_vr_nor.o
>  obj-$(CONFIG_MTD_BFIN_ASYNC)	+= bfin-async-flash.o
>  obj-$(CONFIG_MTD_RBTX4939)	+= rbtx4939-flash.o
>  obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
> +obj-$(CONFIG_MTD_GPIO_ADDR)	+= gpio-addr-flash.o
> diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
> new file mode 100644
> index 0000000..524131d
> --- /dev/null
> +++ b/drivers/mtd/maps/gpio-addr-flash.c
> @@ -0,0 +1,220 @@
> +/*
> + * drivers/mtd/maps/gpio-addr-flash.c
> + *
> + * Handle the case where a flash device is mostly addressed using physical
> + * line and supplemented by GPIOs.  This way you can hook up say a 8meg flash
> + * to a 2meg memory range and use the GPIOs to select a particular range.
> + *
> + * Copyright 2000 Nicolas Pitre <nico@cam.org>
> + * Copyright 2005-2008 Analog Devices Inc.
> + *
> + * Enter bugs at http://blackfin.uclinux.org/
> + *
> + * Licensed under the GPL-2 or later.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mtd/mtd.h>
> +#include <linux/mtd/map.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/mtd/physmap.h>
> +#include <linux/platform_device.h>
> +#include <linux/types.h>
> +
> +#include <asm/gpio.h>
> +#include <asm/io.h>
> +
> +#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })

?? why

> +#define DRIVER_NAME "gpio-addr-flash"
> +
> +struct async_state {
> +	struct mtd_info *mtd;
> +	struct map_info map;
> +	size_t gpio_count;
> +	unsigned *gpio_addrs;
> +	int *gpio_values;
> +	unsigned long win_size;
> +};

no kerneldoc for this?

> +
> +static void gf_set_gpios(struct async_state *state, unsigned long ofs)
> +{
> +	size_t i;
> +	int value;
> +	for (i = 0; i < state->gpio_count; ++i) {
> +		value = !!((ofs / state->win_size) & (1 << i));
> +		if (state->gpio_values[i] != value) {
> +			gpio_set_value(state->gpio_addrs[i], value);
> +			state->gpio_values[i] = value;
> +		}
> +	}
> +}
> +
> +static map_word gf_read(struct map_info *map, unsigned long ofs)
> +{
> +	struct async_state *state = (struct async_state *)map->map_priv_1;
> +	u16 word;
> +	map_word test;
> +
> +	gf_set_gpios(state, ofs);
> +
> +	word = readw(map->virt + (ofs % state->win_size));
> +	test.x[0] = word;
> +	return test;
> +}
> +
> +static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
> +{
> +	struct async_state *state = (struct async_state *)map->map_priv_1;
> +
> +	gf_set_gpios(state, from);
> +
> +	/* BUG if operation crosss the win_size */
> +	BUG_ON(!((from + len) % state->win_size <= (from + len)));
> +
> +	/* operation does not cross the win_size, so one shot it */
> +	memcpy_fromio(to, map->virt + (from % state->win_size), len);
> +}
> +
> +static void gf_write(struct map_info *map, map_word d1, unsigned long ofs)
> +{
> +	struct async_state *state = (struct async_state *)map->map_priv_1;
> +	u16 d;
> +
> +	gf_set_gpios(state, ofs);
> +
> +	d = d1.x[0];
> +	writew(d, map->virt + (ofs % state->win_size));
> +}
> +
> +static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
> +{
> +	struct async_state *state = (struct async_state *)map->map_priv_1;
> +
> +	gf_set_gpios(state, to);
> +
> +	/* BUG if operation crosss the win_size */
> +	BUG_ON(!((to + len) % state->win_size <= (to + len)));
> +
> +	/* operation does not cross the win_size, so one shot it */
> +	memcpy_toio(map->virt + (to % state->win_size), from, len);
> +}
> +
> +#ifdef CONFIG_MTD_PARTITIONS
> +static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
> +#endif
> +
> +static int __devinit gpio_flash_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	size_t i;
> +	struct physmap_flash_data *pdata = pdev->dev.platform_data;
> +	struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	struct resource *gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	struct async_state *state;

both memory and gpios wrap, please put the platform_get_resource()
onto their own lines.

	gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0);

nope, not irqs. maybe someone should propose IORESOURCE_GPIO.

> +	state = kzalloc(sizeof(*state) + (sizeof(int) * gpios->end * 2), GFP_KERNEL);

hmm, why not keep the pointer to the resource you just got instead?

> +	if (!state)
> +		return -ENOMEM;
> +
> +	state->gpio_count     = gpios->end;
> +	state->gpio_addrs     = (void *)(state + 1);
> +	state->gpio_values    = state->gpio_addrs + state->gpio_count;
> +	state->win_size       = memory->end - memory->start + 1;
> +	memcpy(state->gpio_addrs, (void *)gpios->start, sizeof(unsigned) * state->gpio_count);
> +	for (i = 0; i < state->gpio_count; ++i)
> +		state->gpio_values[i] = -1;
> +
> +	state->map.name       = DRIVER_NAME;
> +	state->map.read       = gf_read;
> +	state->map.copy_from  = gf_copy_from;
> +	state->map.write      = gf_write;
> +	state->map.copy_to    = gf_copy_to;
> +	state->map.bankwidth  = pdata->width;
> +	state->map.size       = state->win_size * (1 << state->gpio_count);
> +	state->map.virt       = (void __iomem *)memory->start;
> +	state->map.phys       = NO_XIP;
> +	state->map.map_priv_1 = (unsigned long)state;
> +
> +	platform_set_drvdata(pdev, state);
> +
> +	for (i = 0; i < state->gpio_count; ++i) {
> +		if (gpio_request(state->gpio_addrs[i], DRIVER_NAME)) {
> +			pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->gpio_addrs[i]);
> +			while (i--)
> +				gpio_free(state->gpio_addrs[i]);
> +			kfree(state);
> +			return -EBUSY;
> +		}
> +		gpio_direction_output(state->gpio_addrs[i], 0);
> +	}
> +
> +	pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
> +	state->mtd = do_map_probe(memory->name, &state->map);
> +	if (!state->mtd) {
> +		for (i = 0; i < state->gpio_count; ++i)
> +			gpio_free(state->gpio_addrs[i]);
> +		kfree(state);
> +		return -ENXIO;
> +	}
> +
> +#ifdef CONFIG_MTD_PARTITIONS
> +	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
> +	if (ret > 0) {
> +		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
> +		add_mtd_partitions(state->mtd, pdata->parts, ret);
> +		kfree(pdata->parts);
> +
> +	} else if (pdata->nr_parts) {
> +		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
> +		add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts);
> +
> +	} else
> +#endif
> +	{
> +		pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
> +		add_mtd_device(state->mtd);
> +	}
> +
> +	return 0;
> +}
> +
> +static int __devexit gpio_flash_remove(struct platform_device *pdev)
> +{
> +	struct async_state *state = platform_get_drvdata(pdev);
> +	size_t i;
> +	for (i = 0; i < state->gpio_count; ++i)
> +		gpio_free(state->gpio_addrs[i]);
> +#ifdef CONFIG_MTD_PARTITIONS
> +	del_mtd_partitions(state->mtd);
> +#endif
> +	map_destroy(state->mtd);
> +	kfree(state);
> +	return 0;
> +}
> +
> +static struct platform_driver gpio_flash_driver = {
> +	.probe		= gpio_flash_probe,
> +	.remove		= __devexit_p(gpio_flash_remove),
> +	.driver		= {
> +		.name	= DRIVER_NAME,
> +	},
> +};
> +
> +static int __init gpio_flash_init(void)
> +{
> +	return platform_driver_register(&gpio_flash_driver);
> +}
> +module_init(gpio_flash_init);
> +
> +static void __exit gpio_flash_exit(void)
> +{
> +	platform_driver_unregister(&gpio_flash_driver);
> +}
> +module_exit(gpio_flash_exit);
> +
> +MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
> +MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios");
> +MODULE_LICENSE("GPL");
> -- 
> 1.6.3.1
> 
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/

-- 
Ben (ben@fluff.org, http://www.fluff.org/)

  'a smiley only costs 4 bytes'

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

* Re: [Uclinux-dist-devel] [PATCH] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-06-02 22:58 ` Ben Dooks
@ 2009-06-02 23:37   ` Mike Frysinger
  0 siblings, 0 replies; 15+ messages in thread
From: Mike Frysinger @ 2009-06-02 23:37 UTC (permalink / raw)
  To: Ben Dooks; +Cc: uclinux-dist-devel, Mike Frysinger, linux-mtd

On Tue, Jun 2, 2009 at 18:58, Ben Dooks wrote:
> On Tue, Jun 02, 2009 at 12:07:30AM -0400, Mike Frysinger wrote:
>> +struct async_state {
>> +     struct mtd_info *mtd;
>> +     struct map_info map;
>> +     size_t gpio_count;
>> +     unsigned *gpio_addrs;
>> +     int *gpio_values;
>> +     unsigned long win_size;
>> +};
>
> no kerneldoc for this?

guess i could figure that out and add it

>> +static void gf_set_gpios(struct async_state *state, unsigned long ofs)
>> +{
>> +     size_t i;
>> +     int value;
>> +     for (i = 0; i < state->gpio_count; ++i) {
>> +             value = !!((ofs / state->win_size) & (1 << i));
>> +             if (state->gpio_values[i] != value) {
>> +                     gpio_set_value(state->gpio_addrs[i], value);
>> +                     state->gpio_values[i] = value;
>> +             }
>> +     }
>> +}
>> +
>> +static map_word gf_read(struct map_info *map, unsigned long ofs)
>> +{
>> +     struct async_state *state = (struct async_state *)map->map_priv_1;
>> +     u16 word;
>> +     map_word test;
>> +
>> +     gf_set_gpios(state, ofs);
>> +
>> +     word = readw(map->virt + (ofs % state->win_size));
>> +     test.x[0] = word;
>> +     return test;
>> +}
>> +
>> +static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
>> +{
>> +     struct async_state *state = (struct async_state *)map->map_priv_1;
>> +
>> +     gf_set_gpios(state, from);
>> +
>> +     /* BUG if operation crosss the win_size */
>> +     BUG_ON(!((from + len) % state->win_size <= (from + len)));
>> +
>> +     /* operation does not cross the win_size, so one shot it */
>> +     memcpy_fromio(to, map->virt + (from % state->win_size), len);
>> +}
>> +
>> +static void gf_write(struct map_info *map, map_word d1, unsigned long ofs)
>> +{
>> +     struct async_state *state = (struct async_state *)map->map_priv_1;
>> +     u16 d;
>> +
>> +     gf_set_gpios(state, ofs);
>> +
>> +     d = d1.x[0];
>> +     writew(d, map->virt + (ofs % state->win_size));
>> +}
>> +
>> +static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
>> +{
>> +     struct async_state *state = (struct async_state *)map->map_priv_1;
>> +
>> +     gf_set_gpios(state, to);
>> +
>> +     /* BUG if operation crosss the win_size */
>> +     BUG_ON(!((to + len) % state->win_size <= (to + len)));
>> +
>> +     /* operation does not cross the win_size, so one shot it */
>> +     memcpy_toio(map->virt + (to % state->win_size), from, len);
>> +}
>> +
>> +#ifdef CONFIG_MTD_PARTITIONS
>> +static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
>> +#endif
>> +
>> +static int __devinit gpio_flash_probe(struct platform_device *pdev)
>> +{
>> +     int ret;
>> +     size_t i;
>> +     struct physmap_flash_data *pdata = pdev->dev.platform_data;
>> +     struct resource *memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +     struct resource *gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>> +     struct async_state *state;
>
> both memory and gpios wrap, please put the platform_get_resource()
> onto their own lines.

looks fine to me

>        gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
>
> nope, not irqs. maybe someone should propose IORESOURCE_GPIO.

IORESOURCE_IRQ is the closest thing as it represents a pin.  the
existing masks allows for only 4 types and they're already allocated.
if someone felt like tackling that crap, i'd have no problem
converting the driver.

>> +     state = kzalloc(sizeof(*state) + (sizeof(int) * gpios->end * 2), GFP_KERNEL);
>
> hmm, why not keep the pointer to the resource you just got instead?

the GPIO array is duplicated and i could keep a reference to that, but
the rest would add overhead.  i would need two pointers anyways, so
simply caching the calculated values (gpio_count and win_size) instead
makes more sense.
-mike

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

* [PATCH v2] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-06-02  4:07 [PATCH] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing Mike Frysinger
  2009-06-02 22:58 ` Ben Dooks
@ 2009-06-03 12:51 ` Mike Frysinger
  2009-09-20 22:04   ` David Woodhouse
  2009-09-23  4:48   ` [PATCH v3] " Mike Frysinger
  1 sibling, 2 replies; 15+ messages in thread
From: Mike Frysinger @ 2009-06-03 12:51 UTC (permalink / raw)
  To: linux-mtd; +Cc: uclinux-dist-devel, Bryan Wu

This driver lets people use GPIO's for additional address lines in case
their processor does not have enough address lines already.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
---
v2
	- add kernel doc suggested by Ben
	- touchup style pointed out by Ben
	- avoid duplication of gpio array pointed out by Ben
	- optimize code a bit

 drivers/mtd/maps/Kconfig           |   10 ++
 drivers/mtd/maps/Makefile          |    1 +
 drivers/mtd/maps/gpio-addr-flash.c |  311 ++++++++++++++++++++++++++++++++++++
 3 files changed, 322 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/maps/gpio-addr-flash.c

diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 82923bd..05f6c08 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -500,6 +500,16 @@ config MTD_BFIN_ASYNC
 
 	  If compiled as a module, it will be called bfin-async-flash.
 
+config MTD_GPIO_ADDR
+	tristate "GPIO-assisted Flash Chip Support"
+	depends on MTD_COMPLEX_MAPPINGS
+	select MTD_PARTITIONS
+	help
+	  Map driver which allows flashes to be partially physically addressed
+	  and assisted by GPIOs.
+
+	  If compiled as a module, it will be called gpio-addr-flash.
+
 config MTD_UCLINUX
 	tristate "Generic uClinux RAM/ROM filesystem support"
 	depends on MTD_PARTITIONS && MTD_RAM && !MMU
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 2dbc1be..d9cbd8a 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_MTD_INTEL_VR_NOR)	+= intel_vr_nor.o
 obj-$(CONFIG_MTD_BFIN_ASYNC)	+= bfin-async-flash.o
 obj-$(CONFIG_MTD_RBTX4939)	+= rbtx4939-flash.o
 obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
+obj-$(CONFIG_MTD_GPIO_ADDR)	+= gpio-addr-flash.o
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
new file mode 100644
index 0000000..6724255
--- /dev/null
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -0,0 +1,311 @@
+/*
+ * drivers/mtd/maps/gpio-addr-flash.c
+ *
+ * Handle the case where a flash device is mostly addressed using physical
+ * line and supplemented by GPIOs.  This way you can hook up say a 8meg flash
+ * to a 2meg memory range and use the GPIOs to select a particular range.
+ *
+ * Copyright 2000 Nicolas Pitre <nico@cam.org>
+ * Copyright 2005-2009 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
+
+#define DRIVER_NAME "gpio-addr-flash"
+#define PFX DRIVER_NAME ": "
+
+/**
+ * struct async_state - keep GPIO flash state
+ *	@mtd:         MTD state for this mapping
+ *	@map:         MTD map state for this flash
+ *	@gpio_count:  number of GPIOs used to address
+ *	@gpio_addrs:  array of GPIOs to twiddle
+ *	@gpio_values: cached GPIO values
+ *	@win_size:    dedicated memory size (if no GPIOs)
+ */
+struct async_state {
+	struct mtd_info *mtd;
+	struct map_info map;
+	size_t gpio_count;
+	unsigned *gpio_addrs;
+	int *gpio_values;
+	unsigned long win_size;
+};
+#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1)
+
+/**
+ * gf_set_gpios() - set GPIO address lines to access specified flash offset
+ *	@state: GPIO flash state
+ *	@ofs:   desired offset to access
+ *
+ * Rather than call the GPIO framework every time, cache the last-programmed
+ * value.  This speeds up sequential accesses (which are by far the most common
+ * type).  We rely on the GPIO framework to treat non-zero value as high so
+ * that we don't have to normalize the bits.
+ */
+static void gf_set_gpios(struct async_state *state, unsigned long ofs)
+{
+	size_t i = 0;
+	int value;
+	ofs /= state->win_size;
+	do {
+		value = ofs & (1 << i);
+		if (state->gpio_values[i] != value) {
+			gpio_set_value(state->gpio_addrs[i], value);
+			state->gpio_values[i] = value;
+		}
+	} while (++i < state->gpio_count);
+}
+
+/**
+ * gf_read() - read a word at the specified offset
+ *	@map: MTD map state
+ *	@ofs: desired offset to read
+ */
+static map_word gf_read(struct map_info *map, unsigned long ofs)
+{
+	struct async_state *state = gf_map_info_to_state(map);
+	u16 word;
+	map_word test;
+
+	gf_set_gpios(state, ofs);
+
+	word = readw(map->virt + (ofs % state->win_size));
+	test.x[0] = word;
+	return test;
+}
+
+/**
+ * gf_copy_from() - copy a chunk of data from the flash
+ *	@map:  MTD map state
+ *	@to:   memory to copy to
+ *	@from: flash offset to copy from
+ *	@len:  how much to copy
+ *
+ * We rely on the MTD layer to chunk up copies such that a single request here
+ * will not cross a window size.  This allows us to only wiggle the GPIOs once
+ * before falling back to a normal memcpy.  Reading the higher layer code shows
+ * that this is indeed the case, but add a BUG_ON() to future proof.
+ */
+static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
+{
+	struct async_state *state = gf_map_info_to_state(map);
+
+	gf_set_gpios(state, from);
+
+	/* BUG if operation crosses the win_size */
+	BUG_ON(!((from + len) % state->win_size <= (from + len)));
+
+	/* operation does not cross the win_size, so one shot it */
+	memcpy_fromio(to, map->virt + (from % state->win_size), len);
+}
+
+/**
+ * gf_write() - write a word at the specified offset
+ *	@map: MTD map state
+ *	@ofs: desired offset to write
+ */
+static void gf_write(struct map_info *map, map_word d1, unsigned long ofs)
+{
+	struct async_state *state = gf_map_info_to_state(map);
+	u16 d;
+
+	gf_set_gpios(state, ofs);
+
+	d = d1.x[0];
+	writew(d, map->virt + (ofs % state->win_size));
+}
+
+/**
+ * gf_copy_to() - copy a chunk of data to the flash
+ *	@map:  MTD map state
+ *	@to:   flash offset to copy to
+ *	@from: memory to copy from
+ *	@len:  how much to copy
+ *
+ * See gf_copy_from() caveat.
+ */
+static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
+{
+	struct async_state *state = gf_map_info_to_state(map);
+
+	gf_set_gpios(state, to);
+
+	/* BUG if operation crosses the win_size */
+	BUG_ON(!((to + len) % state->win_size <= (to + len)));
+
+	/* operation does not cross the win_size, so one shot it */
+	memcpy_toio(map->virt + (to % state->win_size), from, len);
+}
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+#endif
+
+/**
+ * gpio_flash_probe() - setup a mapping for a GPIO assisted flash
+ *	@pdev: platform device
+ *
+ * The platform resource layout expected looks something like:
+ * struct mtd_partition partitions[] = { ... };
+ * struct physmap_flash_data flash_data = { ... };
+ * unsigned flash_gpios[] = { GPIO_XX, GPIO_XX, ... };
+ * struct resource flash_resource[] = {
+ *	{
+ *		.name  = "cfi_probe",
+ *		.start = 0x20000000,
+ *		.end   = 0x201fffff,
+ *		.flags = IORESOURCE_MEM,
+ *	}, {
+ *		.start = (unsigned long)flash_gpios,
+ *		.end   = ARRAY_SIZE(flash_gpios),
+ *		.flags = IORESOURCE_IRQ,
+ *	}
+ * };
+ * struct platform_device flash_device = {
+ *	.name          = "gpio-addr-flash",
+ *	.dev           = { .platform_data = &flash_data, },
+ *	.num_resources = ARRAY_SIZE(flash_resource),
+ *	.resource      = flash_resource,
+ *	...
+ * };
+ */
+static int __devinit gpio_flash_probe(struct platform_device *pdev)
+{
+	int ret;
+	size_t i, arr_size;
+	struct physmap_flash_data *pdata;
+	struct resource *memory;
+	struct resource *gpios;
+	struct async_state *state;
+
+	pdata = pdev->dev.platform_data;
+	memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+	if (!memory || !gpios || !gpios->end)
+		return -EINVAL;
+
+	arr_size = sizeof(int) * gpios->end;
+	state = kzalloc(sizeof(*state) + arr_size, GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	state->gpio_count     = gpios->end;
+	state->gpio_addrs     = (void *)gpios->start;
+	state->gpio_values    = (void *)(state + 1);
+	state->win_size       = memory->end - memory->start + 1;
+	memset(state->gpio_values, 0xff, arr_size);
+
+	state->map.name       = DRIVER_NAME;
+	state->map.read       = gf_read;
+	state->map.copy_from  = gf_copy_from;
+	state->map.write      = gf_write;
+	state->map.copy_to    = gf_copy_to;
+	state->map.bankwidth  = pdata->width;
+	state->map.size       = state->win_size * (1 << state->gpio_count);
+	state->map.virt       = (void __iomem *)memory->start;
+	state->map.phys       = NO_XIP;
+	state->map.map_priv_1 = (unsigned long)state;
+
+	platform_set_drvdata(pdev, state);
+
+	i = 0;
+	do {
+		if (gpio_request(state->gpio_addrs[i], DRIVER_NAME)) {
+			pr_devinit(KERN_ERR PFX "failed to request gpio %d\n",
+				state->gpio_addrs[i]);
+			while (i--)
+				gpio_free(state->gpio_addrs[i]);
+			kfree(state);
+			return -EBUSY;
+		}
+		gpio_direction_output(state->gpio_addrs[i], 0);
+	} while (++i < state->gpio_count);
+
+	pr_devinit(KERN_NOTICE PFX "probing %d-bit flash bus\n",
+		state->map.bankwidth * 8);
+	state->mtd = do_map_probe(memory->name, &state->map);
+	if (!state->mtd) {
+		for (i = 0; i < state->gpio_count; ++i)
+			gpio_free(state->gpio_addrs[i]);
+		kfree(state);
+		return -ENXIO;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
+	if (ret > 0) {
+		pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n");
+		add_mtd_partitions(state->mtd, pdata->parts, ret);
+		kfree(pdata->parts);
+
+	} else if (pdata->nr_parts) {
+		pr_devinit(KERN_NOTICE PFX "Using board partition definition\n");
+		add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts);
+
+	} else
+#endif
+	{
+		pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n");
+		add_mtd_device(state->mtd);
+	}
+
+	return 0;
+}
+
+static int __devexit gpio_flash_remove(struct platform_device *pdev)
+{
+	struct async_state *state = platform_get_drvdata(pdev);
+	size_t i = 0;
+	do {
+		gpio_free(state->gpio_addrs[i]);
+	} while (++i < state->gpio_count);
+#ifdef CONFIG_MTD_PARTITIONS
+	del_mtd_partitions(state->mtd);
+#endif
+	map_destroy(state->mtd);
+	kfree(state);
+	return 0;
+}
+
+static struct platform_driver gpio_flash_driver = {
+	.probe		= gpio_flash_probe,
+	.remove		= __devexit_p(gpio_flash_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init gpio_flash_init(void)
+{
+	return platform_driver_register(&gpio_flash_driver);
+}
+module_init(gpio_flash_init);
+
+static void __exit gpio_flash_exit(void)
+{
+	platform_driver_unregister(&gpio_flash_driver);
+}
+module_exit(gpio_flash_exit);
+
+MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
+MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios");
+MODULE_LICENSE("GPL");
-- 
1.6.3.1

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

* Re: [PATCH v2] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-06-03 12:51 ` [PATCH v2] " Mike Frysinger
@ 2009-09-20 22:04   ` David Woodhouse
  2009-09-20 22:49     ` Mike Frysinger
  2009-09-23  4:48   ` [PATCH v3] " Mike Frysinger
  1 sibling, 1 reply; 15+ messages in thread
From: David Woodhouse @ 2009-09-20 22:04 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: uclinux-dist-devel, Bryan Wu, linux-mtd

On Wed, 2009-06-03 at 08:51 -0400, Mike Frysinger wrote:
> This driver lets people use GPIO's for additional address lines in case
> their processor does not have enough address lines already.
> 
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
> Signed-off-by: Bryan Wu <cooloney@kernel.org>

In file included from /home/dwmw2/git/mtd-2.6/arch/x86/include/asm/gpio.h:20,
                 from drivers/mtd/maps/gpio-addr-flash.c:27:
include/asm-generic/gpio.h: In function ‘gpio_get_value_cansleep’:
include/asm-generic/gpio.h:168: error: implicit declaration of function ‘gpio_get_value’
include/asm-generic/gpio.h: In function ‘gpio_set_value_cansleep’:
include/asm-generic/gpio.h:174: error: implicit declaration of function ‘gpio_set_value’
drivers/mtd/maps/gpio-addr-flash.c: In function ‘gpio_flash_probe’:
drivers/mtd/maps/gpio-addr-flash.c:232: error: implicit declaration of function ‘gpio_request’
drivers/mtd/maps/gpio-addr-flash.c:236: error: implicit declaration of function ‘gpio_free’
drivers/mtd/maps/gpio-addr-flash.c:240: error: implicit declaration of function ‘gpio_direction_output’
make[2]: *** [drivers/mtd/maps/gpio-addr-flash.o] Error 1
make[1]: *** [drivers/mtd/maps] Error 2
make: *** [_module_drivers/mtd] Error 2

Setting CONFIG_GPIOLIB seems to fix it -- but we can't make it depend on
that, can we? Maybe it should be GPIOLIB || !GENERIC_GPIO?

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation

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

* Re: [PATCH v2] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-09-20 22:04   ` David Woodhouse
@ 2009-09-20 22:49     ` Mike Frysinger
  2009-09-21  1:25       ` David Woodhouse
  0 siblings, 1 reply; 15+ messages in thread
From: Mike Frysinger @ 2009-09-20 22:49 UTC (permalink / raw)
  To: David Woodhouse; +Cc: uclinux-dist-devel, Bryan Wu, linux-mtd

On Sun, Sep 20, 2009 at 18:04, David Woodhouse wrote:
> On Wed, 2009-06-03 at 08:51 -0400, Mike Frysinger wrote:
>> This driver lets people use GPIO's for additional address lines in case
>> their processor does not have enough address lines already.
>>
>> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
>> Signed-off-by: Bryan Wu <cooloney@kernel.org>
>
> In file included from /home/dwmw2/git/mtd-2.6/arch/x86/include/asm/gpio.h:20,
>                 from drivers/mtd/maps/gpio-addr-flash.c:27:
> include/asm-generic/gpio.h: In function ‘gpio_get_value_cansleep’:
> include/asm-generic/gpio.h:168: error: implicit declaration of function ‘gpio_get_value’
> include/asm-generic/gpio.h: In function ‘gpio_set_value_cansleep’:
> include/asm-generic/gpio.h:174: error: implicit declaration of function ‘gpio_set_value’
> drivers/mtd/maps/gpio-addr-flash.c: In function ‘gpio_flash_probe’:
> drivers/mtd/maps/gpio-addr-flash.c:232: error: implicit declaration of function ‘gpio_request’
> drivers/mtd/maps/gpio-addr-flash.c:236: error: implicit declaration of function ‘gpio_free’
> drivers/mtd/maps/gpio-addr-flash.c:240: error: implicit declaration of function ‘gpio_direction_output’
> make[2]: *** [drivers/mtd/maps/gpio-addr-flash.o] Error 1
> make[1]: *** [drivers/mtd/maps] Error 2
> make: *** [_module_drivers/mtd] Error 2
>
> Setting CONFIG_GPIOLIB seems to fix it -- but we can't make it depend on
> that, can we? Maybe it should be GPIOLIB || !GENERIC_GPIO?

it works fine on Blackfin systems w/out gpiolib, so yes, forcing a
depend on that would be awful.

i think you mean:
depend GPIOLIB || GENERIC_GPIO
-mike

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

* Re: [PATCH v2] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-09-20 22:49     ` Mike Frysinger
@ 2009-09-21  1:25       ` David Woodhouse
  2009-09-21  1:35         ` Mike Frysinger
  0 siblings, 1 reply; 15+ messages in thread
From: David Woodhouse @ 2009-09-21  1:25 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: uclinux-dist-devel, Bryan Wu, linux-mtd

On Sun, 2009-09-20 at 18:49 -0400, Mike Frysinger wrote:
> 
> i think you mean:
> depend GPIOLIB || GENERIC_GPIO

No, I think the failing configuration was GENERIC_GPIO && !GPIOLIB

With GENERIC_GPIO, we include <asm-generic/gpio.h>, and _without_
GPIOLIB that header doesn't actually do anything useful.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation

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

* Re: [PATCH v2] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-09-21  1:25       ` David Woodhouse
@ 2009-09-21  1:35         ` Mike Frysinger
  2009-09-21  1:56           ` David Woodhouse
  0 siblings, 1 reply; 15+ messages in thread
From: Mike Frysinger @ 2009-09-21  1:35 UTC (permalink / raw)
  To: David Woodhouse; +Cc: uclinux-dist-devel, Bryan Wu, linux-mtd

On Sun, Sep 20, 2009 at 21:25, David Woodhouse wrote:
> On Sun, 2009-09-20 at 18:49 -0400, Mike Frysinger wrote:
>> i think you mean:
>> depend GPIOLIB || GENERIC_GPIO
>
> No, I think the failing configuration was GENERIC_GPIO && !GPIOLIB
>
> With GENERIC_GPIO, we include <asm-generic/gpio.h>, and _without_
> GPIOLIB that header doesn't actually do anything useful.

i dont know what you mean by "we".  GENERIC_GPIO means asm/gpio.h is
useful and so provides the basic gpio functions (which this driver
uses).  the driver, nor common gpio.h headers, pull in
asm-generic/gpio.h.

that is how the Blackfin arch works.  GENERIC_GPIO -> basic gpio
functions work fine as the on-chip gpio functions are supported.
-mike

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

* Re: [PATCH v2] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-09-21  1:35         ` Mike Frysinger
@ 2009-09-21  1:56           ` David Woodhouse
  2009-09-21  2:16             ` Mike Frysinger
  0 siblings, 1 reply; 15+ messages in thread
From: David Woodhouse @ 2009-09-21  1:56 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: uclinux-dist-devel, Bryan Wu, linux-mtd

On Sun, 2009-09-20 at 21:35 -0400, Mike Frysinger wrote:
> On Sun, Sep 20, 2009 at 21:25, David Woodhouse wrote:
> > On Sun, 2009-09-20 at 18:49 -0400, Mike Frysinger wrote:
> >> i think you mean:
> >> depend GPIOLIB || GENERIC_GPIO
> >
> > No, I think the failing configuration was GENERIC_GPIO && !GPIOLIB
> >
> > With GENERIC_GPIO, we include <asm-generic/gpio.h>, and _without_
> > GPIOLIB that header doesn't actually do anything useful.
> 
> i dont know what you mean by "we". GENERIC_GPIO means asm/gpio.h is
> useful and so provides the basic gpio functions (which this driver
> uses).  the driver, nor common gpio.h headers, pull in
> asm-generic/gpio.h.
> 
> that is how the Blackfin arch works.  GENERIC_GPIO -> basic gpio
> functions work fine as the on-chip gpio functions are supported.
> -mike

On i386, <linux/gpio.h> includes <asm/gpio.h>. And that includes
<asm-generic/gpio.h> -- which only does anything useful if
CONFIG_GPIOLIB is set.

The failed compilation I showed you earlier was with CONFIG_GENERIC_GPIO
set, but not CONFIG_GPIOLIB.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation

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

* Re: [PATCH v2] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-09-21  1:56           ` David Woodhouse
@ 2009-09-21  2:16             ` Mike Frysinger
  0 siblings, 0 replies; 15+ messages in thread
From: Mike Frysinger @ 2009-09-21  2:16 UTC (permalink / raw)
  To: David Woodhouse; +Cc: uclinux-dist-devel, Bryan Wu, linux-mtd

On Sun, Sep 20, 2009 at 21:56, David Woodhouse wrote:
> On Sun, 2009-09-20 at 21:35 -0400, Mike Frysinger wrote:
>> On Sun, Sep 20, 2009 at 21:25, David Woodhouse wrote:
>> > On Sun, 2009-09-20 at 18:49 -0400, Mike Frysinger wrote:
>> >> i think you mean:
>> >> depend GPIOLIB || GENERIC_GPIO
>> >
>> > No, I think the failing configuration was GENERIC_GPIO && !GPIOLIB
>> >
>> > With GENERIC_GPIO, we include <asm-generic/gpio.h>, and _without_
>> > GPIOLIB that header doesn't actually do anything useful.
>>
>> i dont know what you mean by "we". GENERIC_GPIO means asm/gpio.h is
>> useful and so provides the basic gpio functions (which this driver
>> uses).  the driver, nor common gpio.h headers, pull in
>> asm-generic/gpio.h.
>>
>> that is how the Blackfin arch works.  GENERIC_GPIO -> basic gpio
>> functions work fine as the on-chip gpio functions are supported.
>
> On i386, <linux/gpio.h> includes <asm/gpio.h>. And that includes
> <asm-generic/gpio.h> -- which only does anything useful if
> CONFIG_GPIOLIB is set.
>
> The failed compilation I showed you earlier was with CONFIG_GENERIC_GPIO
> set, but not CONFIG_GPIOLIB.

that isnt a valid GENERIC_GPIO implementation.  x86 cant support it
w/out GPIOLIB.  so the depend still should be "(GENERIC_GPIO ||
GPIOLIB)".
-mike

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

* [PATCH v3] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-06-03 12:51 ` [PATCH v2] " Mike Frysinger
  2009-09-20 22:04   ` David Woodhouse
@ 2009-09-23  4:48   ` Mike Frysinger
  2009-09-23  7:16     ` David Woodhouse
  1 sibling, 1 reply; 15+ messages in thread
From: Mike Frysinger @ 2009-09-23  4:48 UTC (permalink / raw)
  To: linux-mtd, David Woodhouse; +Cc: uclinux-dist-devel, Bryan Wu

This driver lets people use GPIO's for additional address lines in case
their processor does not have enough address lines already.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
---
v3
	- rebase onto latest mainline
	- add missing GPIO dependency pointed out by David
	- switch to linux/*.h includes rather than asm/*.h includes

 drivers/mtd/maps/Kconfig           |   11 ++
 drivers/mtd/maps/Makefile          |    3 +-
 drivers/mtd/maps/gpio-addr-flash.c |  310 ++++++++++++++++++++++++++++++++++++
 3 files changed, 322 insertions(+), 2 deletions(-)
 create mode 100644 drivers/mtd/maps/gpio-addr-flash.c

diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 0f314eb..0fc67a2 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -484,6 +484,17 @@ config MTD_BFIN_ASYNC
 
 	  If compiled as a module, it will be called bfin-async-flash.
 
+config MTD_GPIO_ADDR
+	tristate "GPIO-assisted Flash Chip Support"
+	depends on GENERIC_GPIO || GPIOLIB
+	depends on MTD_COMPLEX_MAPPINGS
+	select MTD_PARTITIONS
+	help
+	  Map driver which allows flashes to be partially physically addressed
+	  and assisted by GPIOs.
+
+	  If compiled as a module, it will be called gpio-addr-flash.
+
 config MTD_UCLINUX
 	bool "Generic uClinux RAM/ROM filesystem support"
 	depends on MTD_PARTITIONS && MTD_RAM=y && !MMU
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 5beb066..1d5cf86 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -58,5 +58,4 @@ obj-$(CONFIG_MTD_PLATRAM)	+= plat-ram.o
 obj-$(CONFIG_MTD_OMAP_NOR)	+= omap_nor.o
 obj-$(CONFIG_MTD_INTEL_VR_NOR)	+= intel_vr_nor.o
 obj-$(CONFIG_MTD_BFIN_ASYNC)	+= bfin-async-flash.o
-obj-$(CONFIG_MTD_RBTX4939)	+= rbtx4939-flash.o
-obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
+obj-$(CONFIG_MTD_GPIO_ADDR)	+= gpio-addr-flash.o
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
new file mode 100644
index 0000000..844a7a5
--- /dev/null
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -0,0 +1,310 @@
+/*
+ * drivers/mtd/maps/gpio-addr-flash.c
+ *
+ * Handle the case where a flash device is mostly addressed using physical
+ * line and supplemented by GPIOs.  This way you can hook up say a 8meg flash
+ * to a 2meg memory range and use the GPIOs to select a particular range.
+ *
+ * Copyright 2000 Nicolas Pitre <nico@cam.org>
+ * Copyright 2005-2009 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
+
+#define DRIVER_NAME "gpio-addr-flash"
+#define PFX DRIVER_NAME ": "
+
+/**
+ * struct async_state - keep GPIO flash state
+ *	@mtd:         MTD state for this mapping
+ *	@map:         MTD map state for this flash
+ *	@gpio_count:  number of GPIOs used to address
+ *	@gpio_addrs:  array of GPIOs to twiddle
+ *	@gpio_values: cached GPIO values
+ *	@win_size:    dedicated memory size (if no GPIOs)
+ */
+struct async_state {
+	struct mtd_info *mtd;
+	struct map_info map;
+	size_t gpio_count;
+	unsigned *gpio_addrs;
+	int *gpio_values;
+	unsigned long win_size;
+};
+#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1)
+
+/**
+ * gf_set_gpios() - set GPIO address lines to access specified flash offset
+ *	@state: GPIO flash state
+ *	@ofs:   desired offset to access
+ *
+ * Rather than call the GPIO framework every time, cache the last-programmed
+ * value.  This speeds up sequential accesses (which are by far the most common
+ * type).  We rely on the GPIO framework to treat non-zero value as high so
+ * that we don't have to normalize the bits.
+ */
+static void gf_set_gpios(struct async_state *state, unsigned long ofs)
+{
+	size_t i = 0;
+	int value;
+	ofs /= state->win_size;
+	do {
+		value = ofs & (1 << i);
+		if (state->gpio_values[i] != value) {
+			gpio_set_value(state->gpio_addrs[i], value);
+			state->gpio_values[i] = value;
+		}
+	} while (++i < state->gpio_count);
+}
+
+/**
+ * gf_read() - read a word at the specified offset
+ *	@map: MTD map state
+ *	@ofs: desired offset to read
+ */
+static map_word gf_read(struct map_info *map, unsigned long ofs)
+{
+	struct async_state *state = gf_map_info_to_state(map);
+	u16 word;
+	map_word test;
+
+	gf_set_gpios(state, ofs);
+
+	word = readw(map->virt + (ofs % state->win_size));
+	test.x[0] = word;
+	return test;
+}
+
+/**
+ * gf_copy_from() - copy a chunk of data from the flash
+ *	@map:  MTD map state
+ *	@to:   memory to copy to
+ *	@from: flash offset to copy from
+ *	@len:  how much to copy
+ *
+ * We rely on the MTD layer to chunk up copies such that a single request here
+ * will not cross a window size.  This allows us to only wiggle the GPIOs once
+ * before falling back to a normal memcpy.  Reading the higher layer code shows
+ * that this is indeed the case, but add a BUG_ON() to future proof.
+ */
+static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
+{
+	struct async_state *state = gf_map_info_to_state(map);
+
+	gf_set_gpios(state, from);
+
+	/* BUG if operation crosses the win_size */
+	BUG_ON(!((from + len) % state->win_size <= (from + len)));
+
+	/* operation does not cross the win_size, so one shot it */
+	memcpy_fromio(to, map->virt + (from % state->win_size), len);
+}
+
+/**
+ * gf_write() - write a word at the specified offset
+ *	@map: MTD map state
+ *	@ofs: desired offset to write
+ */
+static void gf_write(struct map_info *map, map_word d1, unsigned long ofs)
+{
+	struct async_state *state = gf_map_info_to_state(map);
+	u16 d;
+
+	gf_set_gpios(state, ofs);
+
+	d = d1.x[0];
+	writew(d, map->virt + (ofs % state->win_size));
+}
+
+/**
+ * gf_copy_to() - copy a chunk of data to the flash
+ *	@map:  MTD map state
+ *	@to:   flash offset to copy to
+ *	@from: memory to copy from
+ *	@len:  how much to copy
+ *
+ * See gf_copy_from() caveat.
+ */
+static void gf_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
+{
+	struct async_state *state = gf_map_info_to_state(map);
+
+	gf_set_gpios(state, to);
+
+	/* BUG if operation crosses the win_size */
+	BUG_ON(!((to + len) % state->win_size <= (to + len)));
+
+	/* operation does not cross the win_size, so one shot it */
+	memcpy_toio(map->virt + (to % state->win_size), from, len);
+}
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+#endif
+
+/**
+ * gpio_flash_probe() - setup a mapping for a GPIO assisted flash
+ *	@pdev: platform device
+ *
+ * The platform resource layout expected looks something like:
+ * struct mtd_partition partitions[] = { ... };
+ * struct physmap_flash_data flash_data = { ... };
+ * unsigned flash_gpios[] = { GPIO_XX, GPIO_XX, ... };
+ * struct resource flash_resource[] = {
+ *	{
+ *		.name  = "cfi_probe",
+ *		.start = 0x20000000,
+ *		.end   = 0x201fffff,
+ *		.flags = IORESOURCE_MEM,
+ *	}, {
+ *		.start = (unsigned long)flash_gpios,
+ *		.end   = ARRAY_SIZE(flash_gpios),
+ *		.flags = IORESOURCE_IRQ,
+ *	}
+ * };
+ * struct platform_device flash_device = {
+ *	.name          = "gpio-addr-flash",
+ *	.dev           = { .platform_data = &flash_data, },
+ *	.num_resources = ARRAY_SIZE(flash_resource),
+ *	.resource      = flash_resource,
+ *	...
+ * };
+ */
+static int __devinit gpio_flash_probe(struct platform_device *pdev)
+{
+	int ret;
+	size_t i, arr_size;
+	struct physmap_flash_data *pdata;
+	struct resource *memory;
+	struct resource *gpios;
+	struct async_state *state;
+
+	pdata = pdev->dev.platform_data;
+	memory = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	gpios = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+	if (!memory || !gpios || !gpios->end)
+		return -EINVAL;
+
+	arr_size = sizeof(int) * gpios->end;
+	state = kzalloc(sizeof(*state) + arr_size, GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	state->gpio_count     = gpios->end;
+	state->gpio_addrs     = (void *)gpios->start;
+	state->gpio_values    = (void *)(state + 1);
+	state->win_size       = memory->end - memory->start + 1;
+	memset(state->gpio_values, 0xff, arr_size);
+
+	state->map.name       = DRIVER_NAME;
+	state->map.read       = gf_read;
+	state->map.copy_from  = gf_copy_from;
+	state->map.write      = gf_write;
+	state->map.copy_to    = gf_copy_to;
+	state->map.bankwidth  = pdata->width;
+	state->map.size       = state->win_size * (1 << state->gpio_count);
+	state->map.virt       = (void __iomem *)memory->start;
+	state->map.phys       = NO_XIP;
+	state->map.map_priv_1 = (unsigned long)state;
+
+	platform_set_drvdata(pdev, state);
+
+	i = 0;
+	do {
+		if (gpio_request(state->gpio_addrs[i], DRIVER_NAME)) {
+			pr_devinit(KERN_ERR PFX "failed to request gpio %d\n",
+				state->gpio_addrs[i]);
+			while (i--)
+				gpio_free(state->gpio_addrs[i]);
+			kfree(state);
+			return -EBUSY;
+		}
+		gpio_direction_output(state->gpio_addrs[i], 0);
+	} while (++i < state->gpio_count);
+
+	pr_devinit(KERN_NOTICE PFX "probing %d-bit flash bus\n",
+		state->map.bankwidth * 8);
+	state->mtd = do_map_probe(memory->name, &state->map);
+	if (!state->mtd) {
+		for (i = 0; i < state->gpio_count; ++i)
+			gpio_free(state->gpio_addrs[i]);
+		kfree(state);
+		return -ENXIO;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
+	if (ret > 0) {
+		pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n");
+		add_mtd_partitions(state->mtd, pdata->parts, ret);
+		kfree(pdata->parts);
+
+	} else if (pdata->nr_parts) {
+		pr_devinit(KERN_NOTICE PFX "Using board partition definition\n");
+		add_mtd_partitions(state->mtd, pdata->parts, pdata->nr_parts);
+
+	} else
+#endif
+	{
+		pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n");
+		add_mtd_device(state->mtd);
+	}
+
+	return 0;
+}
+
+static int __devexit gpio_flash_remove(struct platform_device *pdev)
+{
+	struct async_state *state = platform_get_drvdata(pdev);
+	size_t i = 0;
+	do {
+		gpio_free(state->gpio_addrs[i]);
+	} while (++i < state->gpio_count);
+#ifdef CONFIG_MTD_PARTITIONS
+	del_mtd_partitions(state->mtd);
+#endif
+	map_destroy(state->mtd);
+	kfree(state);
+	return 0;
+}
+
+static struct platform_driver gpio_flash_driver = {
+	.probe		= gpio_flash_probe,
+	.remove		= __devexit_p(gpio_flash_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init gpio_flash_init(void)
+{
+	return platform_driver_register(&gpio_flash_driver);
+}
+module_init(gpio_flash_init);
+
+static void __exit gpio_flash_exit(void)
+{
+	platform_driver_unregister(&gpio_flash_driver);
+}
+module_exit(gpio_flash_exit);
+
+MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
+MODULE_DESCRIPTION("MTD map driver for flashes addressed physically and with gpios");
+MODULE_LICENSE("GPL");
-- 
1.6.5.rc1

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

* Re: [PATCH v3] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-09-23  4:48   ` [PATCH v3] " Mike Frysinger
@ 2009-09-23  7:16     ` David Woodhouse
  2009-09-23 14:54       ` [Uclinux-dist-devel] " Mike Frysinger
                         ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: David Woodhouse @ 2009-09-23  7:16 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: uclinux-dist-devel, Bryan Wu, linux-mtd

On Wed, 2009-09-23 at 00:48 -0400, Mike Frysinger wrote:
> 
> +       depends on GENERIC_GPIO || GPIOLIB

That still isn't right -- the failing case for me was when GENERIC_GPIO
was set but _not_ GPIOLIB.

I'll accept an answer of "that's because x86 gpio support is broken",
but you do have to handle the whining from the 'make randconfig' folks
for me :)

And please can you make it an incremental patch against what's in the
mtd-2.6.git tree (which I've already asked Linus to pull).

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation

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

* Re: [Uclinux-dist-devel] [PATCH v3] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing
  2009-09-23  7:16     ` David Woodhouse
@ 2009-09-23 14:54       ` Mike Frysinger
  2009-09-24 19:11       ` [PATCH 1/2] mtd/maps: gpio-addr-flash: pull in linux/ headers rather than asm/ Mike Frysinger
  2009-09-24 19:11       ` [PATCH 2/2] mtd/maps: gpio-addr-flash: depend on GPIO arch support Mike Frysinger
  2 siblings, 0 replies; 15+ messages in thread
From: Mike Frysinger @ 2009-09-23 14:54 UTC (permalink / raw)
  To: David Woodhouse; +Cc: uclinux-dist-devel, linux-mtd

On Wed, Sep 23, 2009 at 03:16, David Woodhouse wrote:
> On Wed, 2009-09-23 at 00:48 -0400, Mike Frysinger wrote:
>>
>> +       depends on GENERIC_GPIO || GPIOLIB
>
> That still isn't right -- the failing case for me was when GENERIC_GPIO
> was set but _not_ GPIOLIB.
>
> I'll accept an answer of "that's because x86 gpio support is broken",
> but you do have to handle the whining from the 'make randconfig' folks
> for me :)

right, but this code doesnt depend on GPIOLIB.  it needs functioning
GPIO support and GENERIC_GPIO means the arch has a functioning GPIO
core for just the CPU pins.  i'm pretty sure x86 lies in this respect,
so hopefully this randconfig will poke the x86 guys to fix their tree
(or tell me where i'm wrong).  i looked at the x86 Kconfig and it
seems like it should be using "def_bool n" for this symbol, but i'm
not sure that'll fix things.

> And please can you make it an incremental patch against what's in the
> mtd-2.6.git tree (which I've already asked Linus to pull).

sorry, i didnt realize you merged it
-mike

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

* [PATCH 1/2] mtd/maps: gpio-addr-flash: pull in linux/ headers rather than asm/
  2009-09-23  7:16     ` David Woodhouse
  2009-09-23 14:54       ` [Uclinux-dist-devel] " Mike Frysinger
@ 2009-09-24 19:11       ` Mike Frysinger
  2009-09-24 19:11       ` [PATCH 2/2] mtd/maps: gpio-addr-flash: depend on GPIO arch support Mike Frysinger
  2 siblings, 0 replies; 15+ messages in thread
From: Mike Frysinger @ 2009-09-24 19:11 UTC (permalink / raw)
  To: linux-mtd, David Woodhouse; +Cc: uclinux-dist-devel

Now that there are linux/ versions of gpio.h and io.h, include those
rather than hitting the asm/ versions.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
 drivers/mtd/maps/gpio-addr-flash.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 44ef9a4..1ad5caf 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -13,7 +13,9 @@
  * Licensed under the GPL-2 or later.
  */
 
+#include <linux/gpio.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
@@ -23,9 +25,6 @@
 #include <linux/platform_device.h>
 #include <linux/types.h>
 
-#include <asm/gpio.h>
-#include <asm/io.h>
-
 #define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); })
 
 #define DRIVER_NAME "gpio-addr-flash"
-- 
1.6.5.rc1

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

* [PATCH 2/2] mtd/maps: gpio-addr-flash: depend on GPIO arch support
  2009-09-23  7:16     ` David Woodhouse
  2009-09-23 14:54       ` [Uclinux-dist-devel] " Mike Frysinger
  2009-09-24 19:11       ` [PATCH 1/2] mtd/maps: gpio-addr-flash: pull in linux/ headers rather than asm/ Mike Frysinger
@ 2009-09-24 19:11       ` Mike Frysinger
  2 siblings, 0 replies; 15+ messages in thread
From: Mike Frysinger @ 2009-09-24 19:11 UTC (permalink / raw)
  To: linux-mtd, David Woodhouse; +Cc: uclinux-dist-devel

The driver requires gpio functionality, so make sure we depend on that in
the Kconfig menu.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
 drivers/mtd/maps/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 3a9a960..0fc67a2 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -486,6 +486,7 @@ config MTD_BFIN_ASYNC
 
 config MTD_GPIO_ADDR
 	tristate "GPIO-assisted Flash Chip Support"
+	depends on GENERIC_GPIO || GPIOLIB
 	depends on MTD_COMPLEX_MAPPINGS
 	select MTD_PARTITIONS
 	help
-- 
1.6.5.rc1

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

end of thread, other threads:[~2009-09-24 19:11 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-02  4:07 [PATCH] mtd/maps: gpio-addr-flash: new driver for GPIO assisted flash addressing Mike Frysinger
2009-06-02 22:58 ` Ben Dooks
2009-06-02 23:37   ` [Uclinux-dist-devel] " Mike Frysinger
2009-06-03 12:51 ` [PATCH v2] " Mike Frysinger
2009-09-20 22:04   ` David Woodhouse
2009-09-20 22:49     ` Mike Frysinger
2009-09-21  1:25       ` David Woodhouse
2009-09-21  1:35         ` Mike Frysinger
2009-09-21  1:56           ` David Woodhouse
2009-09-21  2:16             ` Mike Frysinger
2009-09-23  4:48   ` [PATCH v3] " Mike Frysinger
2009-09-23  7:16     ` David Woodhouse
2009-09-23 14:54       ` [Uclinux-dist-devel] " Mike Frysinger
2009-09-24 19:11       ` [PATCH 1/2] mtd/maps: gpio-addr-flash: pull in linux/ headers rather than asm/ Mike Frysinger
2009-09-24 19:11       ` [PATCH 2/2] mtd/maps: gpio-addr-flash: depend on GPIO arch support Mike Frysinger

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).