public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH V7] MIPS: lantiq: add NOR flash support
@ 2011-04-05 12:33 John Crispin
  2011-04-05 12:36 ` Artem Bityutskiy
  0 siblings, 1 reply; 5+ messages in thread
From: John Crispin @ 2011-04-05 12:33 UTC (permalink / raw)
  To: Ralf Baechle
  Cc: linux-mips, Ralph Hempel, linux-mtd, Daniel Schwierzeck,
	David Woodhouse, John Crispin

This patch adds the driver/map for NOR devices attached to the SoC via the
External Bus Unit (EBU).

Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
Cc: linux-mips@linux-mips.org
Cc: linux-mtd@lists.infradead.org

---

Changes in V2
* handle the endianess bug inside the map code and not in the generic cfi code
* remove the addr swizzle patch

Changes in V3
* whitespace
* change __iomem void to void __iomem

Changes in V4
* fixes a checkpatch.pl bug, the second is a false positive
* whitespace cleanups
* remove unused typecasts
* cleanup ltq_copy_from and ltq_copy_to

Changes in V6
* cleanup/add comments
* fix line breaks
* properly handle return code of add_mtd_partitions()
* use pr_err instead of printk

Changes in V7
* remove bogus KERN_INFO from pr_err() call

This patch should be merged via the MIPS tree

 drivers/mtd/maps/Kconfig  |    9 ++
 drivers/mtd/maps/Makefile |    1 +
 drivers/mtd/maps/lantiq.c |  187 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 197 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/maps/lantiq.c

diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 44b1f46..83376d3 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -260,6 +260,15 @@ config MTD_BCM963XX
 	  Support for parsing CFE image tag and creating MTD partitions on
 	  Broadcom BCM63xx boards.
 
+config MTD_LANTIQ
+	bool "Lantiq SoC NOR support"
+	depends on LANTIQ
+	select MTD_PARTITIONS
+	help
+	  Lantiq SoCs have a EBU (External Bus Unit). This IP allows to attach
+	  a number of different peripherals to the SoC. This driver adds
+	  support for NOR chips to be added.
+
 config MTD_DILNETPC
 	tristate "CFI Flash device mapped on DIL/Net PC"
 	depends on X86 && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 08533bd..0db4ba3 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
 obj-$(CONFIG_MTD_GPIO_ADDR)	+= gpio-addr-flash.o
 obj-$(CONFIG_MTD_BCM963XX)	+= bcm963xx-flash.o
 obj-$(CONFIG_MTD_LATCH_ADDR)	+= latch-addr-flash.o
+obj-$(CONFIG_MTD_LANTIQ)	+= lantiq.o
diff --git a/drivers/mtd/maps/lantiq.c b/drivers/mtd/maps/lantiq.c
new file mode 100644
index 0000000..588e873
--- /dev/null
+++ b/drivers/mtd/maps/lantiq.c
@@ -0,0 +1,187 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  Copyright (C) 2004 Liu Peng Infineon IFAP DC COM CPE
+ *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/cfi.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_platform.h>
+
+/* 
+ * The NOR flash is connected to the same external bus unit (EBU) as PCI.
+ * To make PCI work we need to enable the endianess swapping for the address
+ * written to the EBU. This endianess swapping works for PCI correctly but
+ * fails for attached NOR devices. To workaround this we need to use a complex
+ * map. The workaround involves swapping all addresses whilste probing the chip.
+ * Once probing is complete we stop swapping the addresses but swizzle the
+ * unlock addresses to ensure that access to the NOR device works correctly.
+ */
+
+static int ltq_mtd_probing;
+
+static map_word
+ltq_read16(struct map_info *map, unsigned long adr)
+{
+	unsigned long flags;
+	map_word temp;
+
+	if (ltq_mtd_probing)
+		adr ^= 2;
+	spin_lock_irqsave(&ebu_lock, flags);
+	temp.x[0] = *((__u16 *)(map->virt + adr));
+	spin_unlock_irqrestore(&ebu_lock, flags);
+	return temp;
+}
+
+static void
+ltq_write16(struct map_info *map, map_word d, unsigned long adr)
+{
+	unsigned long flags;
+
+	if (ltq_mtd_probing)
+		adr ^= 2;
+	spin_lock_irqsave(&ebu_lock, flags);
+	*((__u16 *)(map->virt + adr)) = d.x[0];
+	spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+/*
+ * The following 2 functions copy data between iomem and a cached memory
+ * section. As memcpy() makes use of pre-fetching we cannot use it here.
+ * The normal alternative of using memcpy_{to,from}io also makes use of
+ * memcpy() on MIPS so it is not applicable either. We are therefore stuck
+ * with having to use our own loop.
+ */
+static void
+ltq_copy_from(struct map_info *map, void *to,
+	unsigned long from, ssize_t len)
+{
+	unsigned char *f = (unsigned char *) (map->virt + from);
+	unsigned char *t = (unsigned char *) to;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ebu_lock, flags);
+	while (len--)
+		*t++ = *f++;
+	spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static void
+ltq_copy_to(struct map_info *map, unsigned long to,
+	const void *from, ssize_t len)
+{
+	unsigned char *f = (unsigned char *) from;
+	unsigned char *t = (unsigned char *) (map->virt + to);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ebu_lock, flags);
+	while (len--)
+		*t++ = *f++;
+	spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static const char const *part_probe_types[] = { "cmdlinepart", NULL };
+
+static struct map_info ltq_map = {
+	.name = "ltq_nor",
+	.bankwidth = 2,
+	.read = ltq_read16,
+	.write = ltq_write16,
+	.copy_from = ltq_copy_from,
+	.copy_to = ltq_copy_to,
+};
+
+static int __init
+ltq_mtd_probe(struct platform_device *pdev)
+{
+	struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
+	struct mtd_info *ltq_mtd = NULL;
+	struct mtd_partition *parts = NULL;
+	struct resource *res;
+	int nr_parts = 0;
+	struct cfi_private *cfi;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to get memory resource");
+		return -ENOENT;
+	}
+	res = devm_request_mem_region(&pdev->dev, res->start,
+		resource_size(res), dev_name(&pdev->dev));
+	if (!res) {
+		dev_err(&pdev->dev, "failed to request mem resource");
+		return -EBUSY;
+	}
+
+	ltq_map.phys = res->start;
+	ltq_map.size = resource_size(res);
+	ltq_map.virt = devm_ioremap_nocache(&pdev->dev, ltq_map.phys,
+					ltq_map.size);
+	if (!ltq_map.virt) {
+		dev_err(&pdev->dev, "failed to ioremap!\n");
+		return -EIO;
+	}
+
+	ltq_mtd_probing = 1;
+	ltq_mtd = do_map_probe("cfi_probe", &ltq_map);
+	ltq_mtd_probing = 0;
+	if (!ltq_mtd) {
+		iounmap(ltq_map.virt);
+		dev_err(&pdev->dev, "probing failed\n");
+		return -ENXIO;
+	}
+	ltq_mtd->owner = THIS_MODULE;
+
+	cfi = ltq_map.fldrv_priv;
+	cfi->addr_unlock1 ^= 1;
+	cfi->addr_unlock2 ^= 1;
+
+	nr_parts = parse_mtd_partitions(ltq_mtd, part_probe_types, &parts, 0);
+	if (nr_parts > 0) {
+		dev_info(&pdev->dev,
+			"using %d partitions from cmdline", nr_parts);
+	} else {
+		nr_parts = ltq_mtd_data->nr_parts;
+		parts = ltq_mtd_data->parts;
+	}
+
+	return add_mtd_partitions(ltq_mtd, parts, nr_parts);
+}
+
+static struct platform_driver ltq_mtd_driver = {
+	.driver = {
+		.name = "ltq_nor",
+		.owner = THIS_MODULE,
+	},
+};
+
+int __init
+init_ltq_mtd(void)
+{
+	int ret = platform_driver_probe(&ltq_mtd_driver, ltq_mtd_probe);
+
+	if (ret)
+		pr_err("ltq_nor: error registering platfom driver");
+	return ret;
+}
+
+module_init(init_ltq_mtd);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq SoC NOR");
-- 
1.7.2.3

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

* Re: [PATCH V7] MIPS: lantiq: add NOR flash support
  2011-04-05 12:33 [PATCH V7] MIPS: lantiq: add NOR flash support John Crispin
@ 2011-04-05 12:36 ` Artem Bityutskiy
  2011-04-05 12:57   ` John Crispin
  0 siblings, 1 reply; 5+ messages in thread
From: Artem Bityutskiy @ 2011-04-05 12:36 UTC (permalink / raw)
  To: John Crispin
  Cc: linux-mips, Ralf Baechle, Ralph Hempel, linux-mtd,
	Daniel Schwierzeck, David Woodhouse

On Tue, 2011-04-05 at 14:33 +0200, John Crispin wrote:
> +#include <lantiq_soc.h>
> +#include <lantiq_platform.h>
> +
> +/* 
> + * The NOR flash is connected to the same external bus unit (EBU) as PCI.
> + * To make PCI work we need to enable the endianess swapping for the address
> + * written to the EBU. This endianess swapping works for PCI correctly but
> + * fails for attached NOR devices. To workaround this we need to use a complex
> + * map. The workaround involves swapping all addresses whilste probing the chip.
> + * Once probing is complete we stop swapping the addresses but swizzle the
> + * unlock addresses to ensure that access to the NOR device works correctly.
> + */
> +
> +static int ltq_mtd_probing;
Disclamer: I do not really understand the PCI/swapping issue, even
though you wrote a comment about this, but still....

... I'm worried about this global variable. If you have multiple
instances of such NOR flash, then you theoretically may have a situation
when one of them is being probed, while another is being used for real.
And this single global switch will break the one which is used for real.

IOW, the right solution would be to have per-chip flag, not a global
flag.

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [PATCH V7] MIPS: lantiq: add NOR flash support
  2011-04-05 12:36 ` Artem Bityutskiy
@ 2011-04-05 12:57   ` John Crispin
  2011-04-05 12:58     ` Artem Bityutskiy
  0 siblings, 1 reply; 5+ messages in thread
From: John Crispin @ 2011-04-05 12:57 UTC (permalink / raw)
  To: dedekind1
  Cc: linux-mips, Ralf Baechle, Ralph Hempel, linux-mtd,
	Daniel Schwierzeck, David Woodhouse


>> +
>> +static int ltq_mtd_probing;
>>     
> ... I'm worried about this global variable. If you have multiple
> instances of such NOR flash, then you theoretically may have a situation
> when one of them is being probed, while another is being used for real.
> And this single global switch will break the one which is used for real.
>
> IOW, the right solution would be to have per-chip flag, not a global
> flag.
>
>   

Hi,

we could dynamically allocate the instance of struct map_info and then
use map_priv_1 to indicate whether the device is probing or not.

this would avoid using a global variable

John

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

* Re: [PATCH V7] MIPS: lantiq: add NOR flash support
  2011-04-05 12:57   ` John Crispin
@ 2011-04-05 12:58     ` Artem Bityutskiy
  2011-04-05 13:06       ` John Crispin
  0 siblings, 1 reply; 5+ messages in thread
From: Artem Bityutskiy @ 2011-04-05 12:58 UTC (permalink / raw)
  To: John Crispin
  Cc: linux-mips, Ralf Baechle, Ralph Hempel, linux-mtd,
	Daniel Schwierzeck, David Woodhouse

On Tue, 2011-04-05 at 14:57 +0200, John Crispin wrote:
> we could dynamically allocate the instance of struct map_info and then
> use map_priv_1 to indicate whether the device is probing or not.

Yeah, may be you could indeed use map_priv_1 instead of the global
variable already now? 

-- 
Best Regards,
Artem Bityutskiy (Артём Битюцкий)

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

* Re: [PATCH V7] MIPS: lantiq: add NOR flash support
  2011-04-05 12:58     ` Artem Bityutskiy
@ 2011-04-05 13:06       ` John Crispin
  0 siblings, 0 replies; 5+ messages in thread
From: John Crispin @ 2011-04-05 13:06 UTC (permalink / raw)
  To: dedekind1
  Cc: linux-mips, Ralf Baechle, Ralph Hempel, linux-mtd,
	Daniel Schwierzeck, David Woodhouse

On 05/04/11 14:58, Artem Bityutskiy wrote:
> On Tue, 2011-04-05 at 14:57 +0200, John Crispin wrote:
>   
>> we could dynamically allocate the instance of struct map_info and then
>> use map_priv_1 to indicate whether the device is probing or not.
>>     
> Yeah, may be you could indeed use map_priv_1 instead of the global
> variable already now? 
>
>   
Hi,

ok, let me add it to the patch ...

thanks, John

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

end of thread, other threads:[~2011-04-05 13:05 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-05 12:33 [PATCH V7] MIPS: lantiq: add NOR flash support John Crispin
2011-04-05 12:36 ` Artem Bityutskiy
2011-04-05 12:57   ` John Crispin
2011-04-05 12:58     ` Artem Bityutskiy
2011-04-05 13:06       ` John Crispin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox