Skip to contentSkip to conversation

Basic N800 support

PATCH In review Kyungmin Park 6 participants 14 messages Jan 22, 2007 – Mar 29, 2007

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

Hi Tony,

Thank you for releasing N800 source code. It's very helpful for OMAP2 board, such as Apollon.

I checked and downloaded the source code in maemo. I'll check the OMAP2 core stuff and OneNAND in apollon board.

Thank you,
Kyungmin Park

P.S., Is it possible to change 'omap2.c' in drivers/mtd/onenand to 'n800.c' or another? It's not generic for OMAP2. :)

------- Original Message -------
Sender : Tony Lindgren<[email protected]>
Date : Jan 20, 2007 05:57
Title : [PATCH] Basic N800 support

Hi,

Here's a quick patch of N800 support against the current git tree for people to play with until we get N800 support merged in. It just contains the board support and basic NAND changes to get root mounted, so most driver changes are not included.

Regards,

Tony

maintainer
#1 lore raw
Quoted 4 lines · Kyungmin Park

Hi Tony,

Thank you for releasing N800 source code. It's very helpful for OMAP2 board, such as Apollon.

Well I just took what Nokia published at maemo.org..

Quoted 7 lines

I checked and downloaded the source code in maemo. I'll check the OMAP2 core stuff and OneNAND in apollon board.

Thank you,
Kyungmin Park

P.S., Is it possible to change 'omap2.c' in drivers/mtd/onenand to 'n800.c' or another? It's not generic for OMAP2. :)

Sure, maybe there's some code that should be shared though?

Regards,

Tony

maintainer
#2 lore raw
Quoted 11 lines · Tony Lindgren
Quoted 4 lines · Kyungmin Park

Hi Tony,

Thank you for releasing N800 source code. It's very helpful for OMAP2 board, such as Apollon.

Well I just took what Nokia published at maemo.org..

Quoted 3 lines

I checked and downloaded the source code in maemo. I'll check the OMAP2 core stuff and OneNAND in apollon board.

Quoted 6 lines
Quoted 4 lines

Thank you,
Kyungmin Park

P.S., Is it possible to change 'omap2.c' in drivers/mtd/onenand to 'n800.c' or another? It's not generic for OMAP2. :)

Sure, maybe there's some code that should be shared though?

Kyungmin, can you list what else makes the N800 onenand support non-generic other than the GPMC timings that should come from board-*.c files?

I'd like to get this to linux-omap tree in some format to be able to mount root :)

Regards,

Tony

#3 lore raw

Hi Tony,

Quoted 9 lines
Quoted 1 line
Quoted 1 line

P.S., Is it possible to change 'omap2.c' in

drivers/mtd/onenand to

Quoted 3 lines
Quoted 1 line

'n800.c' or another? It's not generic for OMAP2. :)

Sure, maybe there's some code that should be shared though?

Kyungmin, can you list what else makes the N800 onenand support non-generic other than the GPMC timings that should come from board-*.c files?

Only things are GPMC and OneNAND configuration.

GPMC timings should be set in platform file such as board-n800-onenand.c or bootloader
and don't need to configure the OneNAND system configuration in omap2.c

In apollon, we configure GPMC timings and OneNAND configuration at bootloader
and don't modify in the kernel code.

In the previous time, OneNAND MTD don't probe chip when sync. mode enabled. Now it can find the chip whether sync. mode or not
In omap2.c it set OneNAND as async mode, probe it and then set sync. mode. I think it is reasons based on this history.

Finally it don't need to configure IOBE in omap2_onenand_wait

#if 0
                /* Turn interrupts on */
                syscfg = omap2_onenand_readw(info->onenand.base +
ONENAND_REG_SYS_CFG1);
                syscfg |= ONENAND_SYS_CFG1_IOBE;
                omap2_onenand_writew(syscfg, info->onenand.base +
ONENAND_REG_SYS_CFG1);
#endif
#if 0
                /* Turn interrupts off */
                syscfg = omap2_onenand_readw(info->onenand.base +
ONENAND_REG_SYS_CFG1);
                syscfg &= ~ONENAND_SYS_CFG1_IOBE;
                omap2_onenand_writew(syscfg, info->onenand.base +

ONENAND_REG_SYS_CFG1);
#endif

Thank you,
Kyungmin Park

#4 lore raw

Hi,

Quoted 16 lines · Kyungmin Park

Finally it don't need to configure IOBE in omap2_onenand_wait

#if 0
                /* Turn interrupts on */
                syscfg = omap2_onenand_readw(info->onenand.base +
ONENAND_REG_SYS_CFG1);
                syscfg |= ONENAND_SYS_CFG1_IOBE;
                omap2_onenand_writew(syscfg, info->onenand.base +
ONENAND_REG_SYS_CFG1);
#endif
#if 0
                /* Turn interrupts off */
                syscfg = omap2_onenand_readw(info->onenand.base +
ONENAND_REG_SYS_CFG1);
                syscfg &= ~ONENAND_SYS_CFG1_IOBE;
                omap2_onenand_writew(syscfg, info->onenand.base +
Quoted 2 lines

ONENAND_REG_SYS_CFG1);
#endif

Yes, this is not strictly necessery. But we noticed that using polling instead of interrupts for some operations give slightly better performance.

Cheers,
Timo

#5 lore raw
In reply to Kyungmin Park
Quoted 3 lines · Kyungmin Park

GPMC timings should be set in platform file such as board-n800-onenand.c or bootloader and don't need to configure the OneNAND system configuration in omap2.c

Attaches is a candidate patch which moves N800 OneNand sync mode timing setup into platform specific file.

Regards
Jarkko Lavinen

Quoted 1 line

From 312f30aceb98fabaec048bd35b640d444d6a52eb Mon Sep 17 00:00:00 2001

From: Jarkko Lavinen <[email protected]>
Date: Thu, 1 Mar 2007 14:05:20 +0200
Subject: [PATCH] Move N800 specific OneNand setup to N800 platform file.

---
 arch/arm/mach-omap2/board-n800-flash.c |  102 ++++++++++++++++++++++++++-
 drivers/mtd/onenand/omap2.c            |  124 ++------------------------------
 include/asm-arm/arch-omap/onenand.h    |    1 +
 3 files changed, 109 insertions(+), 118 deletions(-)
arch/arm/mach-omap2/board-n800-flash.c +101 -1
index 3a4c52a..c1c0d36 100644
@@ -12,16 +12,23 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <asm/mach/flash.h>
+#include <linux/mtd/onenand_regs.h>
+
+#include <asm/io.h>
 #include <asm/arch/onenand.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpmc.h>
 
 static struct mtd_partition n800_partitions[8];
 
+static int n800_onenand_setup(void __iomem *);
+
 static struct omap_onenand_platform_data n800_onenand_data = {
 	.cs = 0,
 	.gpio_irq = 26,
 	.parts = n800_partitions,
-	.nr_parts = 0 /* filled later */
+	.nr_parts = 0, /* filled later */
+	.onenand_setup = n800_onenand_setup
 };
 
 static struct platform_device n800_onenand_device = {
@@ -32,6 +39,99 @@ static struct platform_device n800_onenand_device = {
 	},
 };
 
+static unsigned short omap2_onenand_readw(void __iomem *addr)
+{
+	return readw(addr);
+}
+
+static void omap2_onenand_writew(unsigned short value, void __iomem *addr)
+{
+	writew(value, addr);
+}
+
+static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base)
+{
+	const int min_gpmc_clk_period = 18;
+	struct gpmc_timings t;
+	int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
+	u32 reg;
+
+	tick_ns = gpmc_round_ns_to_ticks(1);
+	div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
+	gpmc_clk_ns = div * tick_ns;
+	if (gpmc_clk_ns >= 24)
+		latency = 3;
+	else
+		latency = 4;
+
+	/* Configure OneNAND for sync read */
+	reg = omap2_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1);
+	reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
+	reg |=	(latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
+		ONENAND_SYS_CFG1_SYNC_READ |
+		ONENAND_SYS_CFG1_BL_16;
+	omap2_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+
+	/* FIXME: Get timings from platform data */
+	/* Set syncronous read timings */
+	memset(&t, 0, sizeof(t));
+	t.sync_clk = min_gpmc_clk_period;
+	t.cs_on = 0;
+	t.adv_on = gpmc_round_ns_to_ticks(7);
+	fclk_offset_ns = t.adv_on + gpmc_round_ns_to_ticks(7);
+	fclk_offset = fclk_offset_ns / gpmc_round_ns_to_ticks(1);
+	t.page_burst_access = gpmc_clk_ns;
+
+	/* Read */
+	t.adv_rd_off = fclk_offset_ns + gpmc_round_ns_to_ticks(7);
+	t.oe_on = t.adv_rd_off;
+	t.access = fclk_offset_ns + (latency + 1) * gpmc_clk_ns;
+	t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
+	t.cs_rd_off = t.oe_off;
+	t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(17);
+
+	/* Write */
+	t.adv_wr_off = t.adv_on + gpmc_round_ns_to_ticks(12);
+	t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(1);
+	t.we_off = t.we_on + gpmc_round_ns_to_ticks(40);
+	t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(1);
+	t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(1);
+
+	/* Configure GPMC for synchronous read */
+	fclk_offset %= div;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
+			  GPMC_CONFIG1_WRAPBURST_SUPP |
+			  GPMC_CONFIG1_READMULTIPLE_SUPP |
+			  GPMC_CONFIG1_READTYPE_SYNC |
+			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
+			  GPMC_CONFIG1_PAGE_LEN(2) |
+			  GPMC_CONFIG1_WAIT_READ_MON |
+			  GPMC_CONFIG1_WAIT_PIN_SEL(0) |
+			  GPMC_CONFIG1_DEVICESIZE_16 |
+			  GPMC_CONFIG1_DEVICETYPE_NOR |
+			  GPMC_CONFIG1_MUXADDDATA);
+
+	return gpmc_cs_set_timings(cs, &t);
+}
+
+static int n800_onenand_setup(void __iomem *onenand_base)
+{
+	struct omap_onenand_platform_data *datap = &n800_onenand_data;
+	struct device *dev = &n800_onenand_device.dev;
+
+	/* Force OneNAND to async mode */
+	omap2_onenand_writew(ONENAND_SYS_CFG1_BRL_4 | ONENAND_SYS_CFG1_RDY |
+			     ONENAND_SYS_CFG1_INT,
+			     onenand_base + ONENAND_REG_SYS_CFG1);
+
+	/* Set sync timings in GPMC */
+	if (omap2_onenand_set_sync_mode(datap->cs, onenand_base) < 0) {
+		dev_err(dev, "Unable to set synchronous mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 void __init n800_flash_init(void)
 {
drivers/mtd/onenand/omap2.c +7 -117

142 lines not on this page · raw message

include/asm-arm/arch-omap/onenand.h +1 -0
index b8a19be..3e8ab2f 100644
@@ -16,4 +16,5 @@ struct omap_onenand_platform_data {
 	int			gpio_irq;
 	struct mtd_partition	*parts;
 	int			nr_parts;
+	int                     (*onenand_setup)(void __iomem *);
 };
Signature · 1 line
1.4.4.4
#6 lore raw

Hi Jarkko Lavinen,

Looks good.

Tony, please add drivers/mtd/onenand/omap2.c first

+
+static int n800_onenand_setup(void __iomem *onenand_base) +{
+ struct omap_onenand_platform_data *datap = &n800_onenand_data;
+ struct device *dev = &n800_onenand_device.dev;
+
+ /* Force OneNAND to async mode */
+ omap2_onenand_writew(ONENAND_SYS_CFG1_BRL_4 | ONENAND_SYS_CFG1_RDY |
+ ONENAND_SYS_CFG1_INT,
+ onenand_base + ONENAND_REG_SYS_CFG1);

If you don't need async mode settings, it also don't need it.

+
+ /* Set sync timings in GPMC */
+ if (omap2_onenand_set_sync_mode(datap->cs, onenand_base) < 0) {
+ dev_err(dev, "Unable to set synchronous mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}

Thank you,
Kyungmin Park

Quoted 20 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Jarkko Lavinen
Sent: Thursday, March 01, 2007 10:46 PM
To: [email protected]
Cc: Kyungmin Park
Subject: Re: Basic N800 support

Quoted 3 lines · Kyungmin Park

GPMC timings should be set in platform file such as board-n800-onenand.c or bootloader and don't need to configure the OneNAND system configuration in omap2.c

Attaches is a candidate patch which moves N800 OneNand sync mode timing setup into platform specific file.

Regards
Jarkko Lavinen

#7 lore raw

Hi Kyungmin

Quoted 1 line

If you don't need async mode settings, it also don't need it.

Yes. It is obvious. Removed async part. New patch attached.

Best Regards
Jarkko Lavinen

Quoted 1 line

From 5b99cf491a1105cde1f766bb760e1f39d964dc1a Mon Sep 17 00:00:00 2001

From: Jarkko Lavinen <[email protected]>
Date: Fri, 2 Mar 2007 17:02:09 +0200
Subject: [PATCH] Move N800 specific OneNand setup to N800 platform file.

---
 arch/arm/mach-omap2/board-n800-flash.c |   97 ++++++++++++++++++++++++-
 drivers/mtd/onenand/omap2.c            |  124 ++------------------------------
 include/asm-arm/arch-omap/onenand.h    |    1 +
 3 files changed, 104 insertions(+), 118 deletions(-)
arch/arm/mach-omap2/board-n800-flash.c +96 -1
index 3a4c52a..84ba984 100644
@@ -12,16 +12,23 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <asm/mach/flash.h>
+#include <linux/mtd/onenand_regs.h>
+
+#include <asm/io.h>
 #include <asm/arch/onenand.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpmc.h>
 
 static struct mtd_partition n800_partitions[8];
 
+static int n800_onenand_setup(void __iomem *);
+
 static struct omap_onenand_platform_data n800_onenand_data = {
 	.cs = 0,
 	.gpio_irq = 26,
 	.parts = n800_partitions,
-	.nr_parts = 0 /* filled later */
+	.nr_parts = 0, /* filled later */
+	.onenand_setup = n800_onenand_setup
 };
 
 static struct platform_device n800_onenand_device = {
@@ -32,6 +39,94 @@ static struct platform_device n800_onenand_device = {
 	},
 };
 
+static unsigned short omap2_onenand_readw(void __iomem *addr)
+{
+	return readw(addr);
+}
+
+static void omap2_onenand_writew(unsigned short value, void __iomem *addr)
+{
+	writew(value, addr);
+}
+
+static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base)
+{
+	const int min_gpmc_clk_period = 18;
+	struct gpmc_timings t;
+	int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
+	u32 reg;
+
+	tick_ns = gpmc_round_ns_to_ticks(1);
+	div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
+	gpmc_clk_ns = div * tick_ns;
+	if (gpmc_clk_ns >= 24)
+		latency = 3;
+	else
+		latency = 4;
+
+	/* Configure OneNAND for sync read */
+	reg = omap2_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1);
+	reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
+	reg |=	(latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
+		ONENAND_SYS_CFG1_SYNC_READ |
+		ONENAND_SYS_CFG1_BL_16;
+	omap2_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+
+	/* FIXME: Get timings from platform data */
+	/* Set syncronous read timings */
+	memset(&t, 0, sizeof(t));
+	t.sync_clk = min_gpmc_clk_period;
+	t.cs_on = 0;
+	t.adv_on = gpmc_round_ns_to_ticks(7);
+	fclk_offset_ns = t.adv_on + gpmc_round_ns_to_ticks(7);
+	fclk_offset = fclk_offset_ns / gpmc_round_ns_to_ticks(1);
+	t.page_burst_access = gpmc_clk_ns;
+
+	/* Read */
+	t.adv_rd_off = fclk_offset_ns + gpmc_round_ns_to_ticks(7);
+	t.oe_on = t.adv_rd_off;
+	t.access = fclk_offset_ns + (latency + 1) * gpmc_clk_ns;
+	t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
+	t.cs_rd_off = t.oe_off;
+	t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(17);
+
+	/* Write */
+	t.adv_wr_off = t.adv_on + gpmc_round_ns_to_ticks(12);
+	t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(1);
+	t.we_off = t.we_on + gpmc_round_ns_to_ticks(40);
+	t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(1);
+	t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(1);
+
+	/* Configure GPMC for synchronous read */
+	fclk_offset %= div;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
+			  GPMC_CONFIG1_WRAPBURST_SUPP |
+			  GPMC_CONFIG1_READMULTIPLE_SUPP |
+			  GPMC_CONFIG1_READTYPE_SYNC |
+			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
+			  GPMC_CONFIG1_PAGE_LEN(2) |
+			  GPMC_CONFIG1_WAIT_READ_MON |
+			  GPMC_CONFIG1_WAIT_PIN_SEL(0) |
+			  GPMC_CONFIG1_DEVICESIZE_16 |
+			  GPMC_CONFIG1_DEVICETYPE_NOR |
+			  GPMC_CONFIG1_MUXADDDATA);
+
+	return gpmc_cs_set_timings(cs, &t);
+}
+
+static int n800_onenand_setup(void __iomem *onenand_base)
+{
+	struct omap_onenand_platform_data *datap = &n800_onenand_data;
+	struct device *dev = &n800_onenand_device.dev;
+
+	/* Set sync timings in GPMC */
+	if (omap2_onenand_set_sync_mode(datap->cs, onenand_base) < 0) {
+		dev_err(dev, "Unable to set synchronous mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 void __init n800_flash_init(void)
 {
drivers/mtd/onenand/omap2.c +7 -117

142 lines not on this page · raw message

include/asm-arm/arch-omap/onenand.h +1 -0
index b8a19be..3e8ab2f 100644
@@ -16,4 +16,5 @@ struct omap_onenand_platform_data {
 	int			gpio_irq;
 	struct mtd_partition	*parts;
 	int			nr_parts;
+	int                     (*onenand_setup)(void __iomem *);
 };
Signature · 1 line
1.4.4.4
#8 lore raw

PATCH 1/1 Move N800 specific OneNand setup to N800 platform file, was: Basic N800 support

Quoted 3 lines · Jarkko Lavinen
Quoted 1 line

If you don't need async mode settings, it also don't need it.

Yes. It is obvious. Removed async part. New patch attached.

Are there any dependencies to apply this patch I missed? I tried to apply it on top of 01-onenand.patch posted by Tony
[1] but got rejects.

If not, sligthly modified patch that cleanly applies on top of [1] in attachment. I additionally removed duplication of omap2_onenand_readw and writew. Can you please test if it is still okay? ;)

Dirk

[1]
http://linux.omap.com/pipermail/linux-omap-open-source/2007-January/008958.html

Quoted 1 line

From 5b99cf491a1105cde1f766bb760e1f39d964dc1a Mon Sep 17 00:00:00 2001

From: Jarkko Lavinen <[email protected]>
Date: Fri, 2 Mar 2007 17:02:09 +0200
Subject: [PATCH] Move N800 specific OneNand setup to N800 platform file.

---
 arch/arm/mach-omap2/board-n800-flash.c |   97 ++++++++++++++++++++++++-
 drivers/mtd/onenand/omap2.c            |  124 ++------------------------------
 include/asm-arm/arch-omap/onenand.h    |    1 +
 3 files changed, 104 insertions(+), 118 deletions(-)
arch/arm/mach-omap2/board-n800-flash.c +98 -1
Index: linux-osk/arch/arm/mach-omap2/board-n800-flash.c
===================================================================
@@ -12,16 +12,100 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <asm/mach/flash.h>
+#include <linux/mtd/onenand_regs.h>
+
+#include <asm/io.h>
 #include <asm/arch/onenand.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpmc.h>
 
 static struct mtd_partition n800_partitions[8];
 
+static unsigned short n800_onenand_readw(void __iomem *addr)
+{
+	return readw(addr);
+}
+
+static void n800_onenand_writew(unsigned short value, void __iomem *addr)
+{
+	writew(value, addr);
+}
+
+static int n800_onenand_set_sync_mode(int cs, void __iomem *onenand_base)
+{
+	const int min_gpmc_clk_period = 18;
+	struct gpmc_timings t;
+	int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
+	u32 reg;
+
+	tick_ns = gpmc_round_ns_to_ticks(1);
+	div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
+	gpmc_clk_ns = div * tick_ns;
+	if (gpmc_clk_ns >= 24)
+		latency = 3;
+	else
+		latency = 4;
+
+	/* Configure OneNAND for sync read */
+	reg = n800_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1);
+	reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
+	reg |=	(latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
+		ONENAND_SYS_CFG1_SYNC_READ |
+		ONENAND_SYS_CFG1_BL_16;
+	n800_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+
+	/* FIXME: Get timings from platform data */
+	/* Set syncronous read timings */
+	memset(&t, 0, sizeof(t));
+	t.sync_clk = min_gpmc_clk_period;
+	t.cs_on = 0;
+	t.adv_on = gpmc_round_ns_to_ticks(7);
+	fclk_offset_ns = t.adv_on + gpmc_round_ns_to_ticks(7);
+	fclk_offset = fclk_offset_ns / gpmc_round_ns_to_ticks(1);
+	t.page_burst_access = gpmc_clk_ns;
+
+	/* Read */
+	t.adv_rd_off = fclk_offset_ns + gpmc_round_ns_to_ticks(7);
+	t.oe_on = t.adv_rd_off;
+	t.access = fclk_offset_ns + (latency + 1) * gpmc_clk_ns;
+	t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
+	t.cs_rd_off = t.oe_off;
+	t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(17);
+
+	/* Write */
+	t.adv_wr_off = t.adv_on + gpmc_round_ns_to_ticks(12);
+	t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(1);
+	t.we_off = t.we_on + gpmc_round_ns_to_ticks(40);
+	t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(1);
+	t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(1);
+
+	/* Configure GPMC for synchronous read */
+	fclk_offset %= div;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
+			  GPMC_CONFIG1_WRAPBURST_SUPP |
+			  GPMC_CONFIG1_READMULTIPLE_SUPP |
+			  GPMC_CONFIG1_READTYPE_SYNC |
+			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
+			  GPMC_CONFIG1_PAGE_LEN(2) |
+			  GPMC_CONFIG1_WAIT_READ_MON |
+			  GPMC_CONFIG1_WAIT_PIN_SEL(0) |
+			  GPMC_CONFIG1_DEVICESIZE_16 |
+			  GPMC_CONFIG1_DEVICETYPE_NOR |
+			  GPMC_CONFIG1_MUXADDDATA);
+
+	return gpmc_cs_set_timings(cs, &t);
+}
+
+static int n800_onenand_setup(void __iomem *);
+
 static struct omap_onenand_platform_data n800_onenand_data = {
 	.cs = 0,
 	.gpio_irq = 26,
 	.parts = n800_partitions,
-	.nr_parts = 0 /* filled later */
+	.nr_parts = 0, /* filled later */
+	.onenand_setup = n800_onenand_setup,
+	.onenand_readw = n800_onenand_readw,
+	.onenand_writew = n800_onenand_writew
 };
 
 static struct platform_device n800_onenand_device = {
@@ -32,6 +116,19 @@ static struct platform_device n800_onena
 	},
 };
 
+static int n800_onenand_setup(void __iomem *onenand_base)
+{
+	struct omap_onenand_platform_data *datap = &n800_onenand_data;
+	struct device *dev = &n800_onenand_device.dev;
+
+	/* Set sync timings in GPMC */
+	if (n800_onenand_set_sync_mode(datap->cs, onenand_base) < 0) {
+		dev_err(dev, "Unable to set synchronous mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 void __init n800_flash_init(void)
 {
drivers/mtd/onenand/omap2.c +13 -132

192 lines not on this page · raw message

include/asm-arm/arch-omap/onenand.h +3 -0
Index: linux-osk/include/asm-arm/arch-omap/onenand.h
===================================================================
@@ -16,4 +16,7 @@ struct omap_onenand_platform_data {
 	int			gpio_irq;
 	struct mtd_partition	*parts;
 	int			nr_parts;
+	int                     (*onenand_setup)(void __iomem *);
+	unsigned short 		(*onenand_readw)(void __iomem *);
+	void 			(*onenand_writew)(unsigned short, void __iomem *);
 };
maintainer
#9 lore raw

Re: [PATCH] Move N800 specific OneNand setup to N800 platform file, was: Basic N800 support

Quoted 5 lines · Dirk Behme
Quoted 3 lines · Jarkko Lavinen
Quoted 1 line

If you don't need async mode settings, it also don't need it.

Yes. It is obvious. Removed async part. New patch attached.

Quoted 8 lines

Are there any dependencies to apply this patch I missed? I tried to apply it on top of 01-onenand.patch posted by Tony
[1] but got rejects.

If not, sligthly modified patch that cleanly applies on top of [1] in attachment. I additionally removed duplication of omap2_onenand_readw and writew. Can you please test if it is still okay? ;)

I've pushed Jarkko's onenand patches as two parts:

omap-drivers: onenand support for omap2 that can be sent to mtd list
omap-upstream: onenand board specific support for n800

Can you all please verify that they're OK?

Kyungmin & Dirk, do you have some additional patches on top of Jarkko's patches?

Regards,

Tony

Quoted 2 lines

[1]
http://linux.omap.com/pipermail/linux-omap-open-source/2007-January/008958.html

#10 lore raw

RE: [PATCH] Move N800 specific OneNand setup to N800 platform file, was: Basic N800 support

Hi

Quoted 12 lines · Dirk Behme
Quoted 10 lines
Quoted 3 lines · Jarkko Lavinen
Quoted 1 line

If you don't need async mode settings, it also don't need it.

Yes. It is obvious. Removed async part. New patch attached.

Are there any dependencies to apply this patch I missed? I tried to apply it on top of 01-onenand.patch posted by Tony [1] but got rejects.

If not, sligthly modified patch that cleanly applies on top

Quoted 8 lines

of [1] in

Quoted 1 line

attachment. I additionally removed duplication of

omap2_onenand_readw

Quoted 1 line

and writew. Can you please test if it is still okay? ;)

I've pushed Jarkko's onenand patches as two parts:

omap-drivers: onenand support for omap2 that can be sent to mtd list

I will push it mtd list

Quoted 3 lines

omap-upstream: onenand board specific support for n800

Can you all please verify that they're OK?

There's one compiler bug related with interrupt handler.

Quoted 4 lines

Kyungmin & Dirk, do you have some additional patches on top of Jarkko's patches?

Please don't patch [1]. If this patch is applied, we have to add all platform files to add onenand_readw, onenand_writew.

Now apollon board can use it without modification of omap2.c

Thank you,
Kyungmin Park

1. http://linux.omap.com/pipermail/linux-omap-open-source/2007-March/009210.
html

Quoted 1 line

From d4978e6cfbb4824391d568051bd0027622cac729 Mon Sep 17 00:00:00 2001

From: Kyungmin Park <[email protected]>
Date: Thu, 8 Mar 2007 10:05:01 +0900
Subject: [PATCH] ARM: OMAP: Fix old interrupt handler function in omap2-onenand

Fix old interrupt handler function in omap2-onenand

---
 drivers/mtd/onenand/omap2.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)
drivers/mtd/onenand/omap2.c +1 -2
index bbc9beb..96fcb5f 100644
@@ -80,8 +80,7 @@ static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 	complete(&info->dma_done);
 }
 
-static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id,
-					   struct pt_regs *regs)
+static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id)
 {
 	struct omap2_onenand *info = dev_id;
 
Signature · 1 line
1.4.4.2
#11 lore raw

RE: [PATCH] Move N800 specific OneNand setup to N800 platform file, was: Basic N800 support

Quoted 16 lines
Quoted 9 lines · Dirk Behme
Quoted 6 lines
Quoted 3 lines · Jarkko Lavinen
Quoted 1 line

If you don't need async mode settings, it also don't need it.

Yes. It is obvious. Removed async part. New patch attached.

Are there any dependencies to apply this patch I missed?

I tried to

Quoted 6 lines
Quoted 4 lines

apply it on top of 01-onenand.patch posted by Tony [1] but got rejects.

If not, sligthly modified patch that cleanly applies on top

of [1] in

Quoted 1 line

attachment. I additionally removed duplication of

Quoted 8 lines
Quoted 6 lines

omap2_onenand_readw

Quoted 1 line

and writew. Can you please test if it is still okay? ;)

I've pushed Jarkko's onenand patches as two parts:

omap-drivers: onenand support for omap2 that can be sent to mtd list

I will push it mtd list

Umm, there's omap tree dependency.
omap2_block_sleep() & omap2_allow_sleep().

It just increase and decrease sleep_block variable atomically

Just remove it or define dummy macro?

Please give your opinions.

Thank you,
Kyungmin Park

#12 lore raw

Re: [PATCH] Move N800 specific OneNand setup to N800 platform file, was: Basic N800 support

In reply to Kyungmin Park

Hi Kyungmin

Thank you for your comments and irq handler fix.

Quoted 2 lines

If this patch is applied, we have to add all platform files to add onenand_readw, onenand_writew.

We could pass the needed methods to the setup. This would also allow to add more fields if new omap2 devices with more complex setups are needed.

Quoted 3 lines

Umm, there's omap tree dependency. omap2_block_sleep() & omap2_allow_sleep().
...
Just remove it or define dummy macro?

The log message in our internal tree says the sleep prevention was added to maximise speed when reading from bufferram.

I vote for dummy macro, which can then presumably be overdriven by a custom definion from some device specific header.

Regards
Jarkko Lavinen

Quoted 1 line

From a6200a8f8f029193cce157a3efe90809104c353f Mon Sep 17 00:00:00 2001

From: Jarkko Lavinen <[email protected]>
Date: Fri, 9 Mar 2007 20:56:39 +0200
Subject: [PATCH] Fix request_irq compile error and pass readw, and writew methods to platform setup.

---
 arch/arm/mach-omap2/board-n800-flash.c |   27 +++++++++++----------------
 drivers/mtd/onenand/omap2.c            |    6 +++++-
 include/asm-arm/arch-omap/onenand.h    |    8 +++++++-
 3 files changed, 23 insertions(+), 18 deletions(-)
arch/arm/mach-omap2/board-n800-flash.c +11 -16
index 4005cfb..08678dc 100644
@@ -21,7 +21,7 @@
 
 static struct mtd_partition n800_partitions[8];
 
-static int n800_onenand_setup(void __iomem *);
+static int n800_onenand_setup(struct omap_onenand_setup_data *sdata);
 
 static struct omap_onenand_platform_data n800_onenand_data = {
 	.cs = 0,
@@ -39,17 +39,7 @@ static struct platform_device n800_onenand_device = {
 	},
 };
 
-static unsigned short omap2_onenand_readw(void __iomem *addr)
-{
-	return readw(addr);
-}
-
-static void omap2_onenand_writew(unsigned short value, void __iomem *addr)
-{
-	writew(value, addr);
-}
-
-static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base)
+static int omap2_onenand_set_sync_mode(int cs, struct omap_onenand_setup_data *sdata)
 {
 	const int min_gpmc_clk_period = 18;
 	struct gpmc_timings t;
@@ -65,12 +55,12 @@ static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base)
 		latency = 4;
 
 	/* Configure OneNAND for sync read */
-	reg = omap2_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1);
+	reg = (sdata->readw)(sdata->iobase + ONENAND_REG_SYS_CFG1);
 	reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
 	reg |=	(latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
 		ONENAND_SYS_CFG1_SYNC_READ |
 		ONENAND_SYS_CFG1_BL_16;
-	omap2_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+	(sdata->writew)(reg, sdata->iobase + ONENAND_REG_SYS_CFG1);
 
 	/* FIXME: Get timings from platform data */
 	/* Set syncronous read timings */
@@ -114,13 +104,18 @@ static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base)
 	return gpmc_cs_set_timings(cs, &t);
 }
 
-static int n800_onenand_setup(void __iomem *onenand_base)
+static int n800_onenand_setup(struct omap_onenand_setup_data *sdata)
 {
 	struct omap_onenand_platform_data *datap = &n800_onenand_data;
 	struct device *dev = &n800_onenand_device.dev;
 
+	if (sdata == NULL) {
+		dev_err(dev, "setup data is a NULL pointer\n");
+		return -EINVAL;
+	}
+
 	/* Set sync timings in GPMC */
-	if (omap2_onenand_set_sync_mode(datap->cs, onenand_base) < 0) {
+	if (omap2_onenand_set_sync_mode(datap->cs, sdata) < 0) {
 		dev_err(dev, "Unable to set synchronous mode\n");
 		return -EINVAL;
 	}
drivers/mtd/onenand/omap2.c +5 -1
index 96fcb5f..fb1c15c 100644
@@ -337,7 +337,11 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	}
 
 	if (pdata->onenand_setup != NULL) {
-		r = pdata->onenand_setup(info->onenand.base);
+		struct omap_onenand_setup_data data;
+		data.iobase = info->onenand.base;
+		data.readw  = omap2_onenand_readw;
+		data.writew = omap2_onenand_writew;
+		r = pdata->onenand_setup(&data);
 		if (r < 0) {
 			dev_err(&pdev->dev, "Onenand platform setup failed: %d\n", r);
 			goto err_iounmap;                       
include/asm-arm/arch-omap/onenand.h +7 -1
index 3e8ab2f..a7670af 100644
@@ -11,10 +11,16 @@
 
 #include <linux/mtd/partitions.h>
 
+struct omap_onenand_setup_data {
+	void __iomem            *iobase;
+	unsigned short          (*readw)(void __iomem *);
+	void                    (*writew)(unsigned short, void __iomem *);
+};
+
 struct omap_onenand_platform_data {
 	int			cs;
 	int			gpio_irq;
 	struct mtd_partition	*parts;
 	int			nr_parts;
-	int                     (*onenand_setup)(void __iomem *);
+	int                     (*onenand_setup)(struct omap_onenand_setup_data *);
 };
Signature · 1 line
1.4.4.4
maintainer
#13 lore raw

Re: [PATCH] Move N800 specific OneNand setup to N800 platform file, was: Basic N800 support

In reply to Kyungmin Park
Quoted 14 lines · Kyungmin Park

ARM: OMAP: Fix old interrupt handler function in omap2-onenand

Fix old interrupt handler function in omap2-onenand

---
 drivers/mtd/onenand/omap2.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)
drivers/mtd/onenand/omap2.c +0 -0
index bbc9beb..96fcb5f 100644

drivers/mtd/onenand/omap2.c static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data) · line 86

Quoted 9 lines
drivers/mtd/onenand/omap2.c +1 -2
@@ -80,8 +80,7 @@ static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 	complete(&info->dma_done);
 }
 
-static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id,
-					   struct pt_regs *regs)
+static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id)
 {
 	struct omap2_onenand *info = dev_id;
 

Pushing this today.

Tony