Skip to contentSkip to conversation

NAND hardware ECC controller on at91sam9263 / at91sam9260

PATCH In review Richard Genoud 3 participants 9 messages Feb 19, 2008 – Apr 25, 2008

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

PATCH 1/1 NAND hardware ECC controller on at91sam9263 / at91sam9260

This is a patch to use the hardware ECC controller of the AT91SAM9260 and AT91SAM9263 for the AT91 nand. On AT91 NAND, there's now a choice between ECC soft, ECC hard or no ECC (for debug).

It has been tested on AT91SAM9263 with 8 bits large and small page NAND.

kernel version : 2.6.25-rc2

---
 arch/arm/mach-at91/at91sam9260_devices.c |    9 +-
 arch/arm/mach-at91/at91sam9263_devices.c |    9 +-
 drivers/mtd/nand/Kconfig                 |   41 ++++
 drivers/mtd/nand/at91_nand.c             |  361 +++++++++++++++++++++++++++++-
 include/asm-arm/arch-at91/at91_ecc.h     |   12 +-
 include/asm-arm/arch-at91/at91sam9260.h  |   21 ++
 include/asm-arm/arch-at91/at91sam9263.h  |   27 +++
 7 files changed, 466 insertions(+), 14 deletions(-)
arch/arm/mach-at91/at91sam9260_devices.c +7 -2
index 105f840..f494d92 100644
@@ -288,11 +288,16 @@ static struct at91_nand_data nand_data;
 #define NAND_BASE	AT91_CHIPSELECT_3
 
 static struct resource nand_resources[] = {
-	{
+	[0] = {
 		.start	= NAND_BASE,
 		.end	= NAND_BASE + SZ_256M - 1,
 		.flags	= IORESOURCE_MEM,
-	}
+	},
+	[1] = {
+		.start	= AT91SAM9260_ECC,
+		.end	= AT91SAM9260_ECC + SZ_512 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
 };
 
 static struct platform_device at91sam9260_nand_device = {
arch/arm/mach-at91/at91sam9263_devices.c +7 -2
index 0b12e1a..fc0d50a 100644
@@ -358,11 +358,16 @@ static struct at91_nand_data nand_data;
 #define NAND_BASE	AT91_CHIPSELECT_3
 
 static struct resource nand_resources[] = {
-	{
+	[0] = {
 		.start	= NAND_BASE,
 		.end	= NAND_BASE + SZ_256M - 1,
 		.flags	= IORESOURCE_MEM,
-	}
+	},
+	[1] = {
+		.start	= AT91SAM9263_ECC0,
+		.end	= AT91SAM9263_ECC0 + SZ_512 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
 };
 
 static struct platform_device at91sam9263_nand_device = {
drivers/mtd/nand/Kconfig +41 -0

47 lines not on this page · raw message

drivers/mtd/nand/at91_nand.c +356 -5

433 lines not on this page · raw message

include/asm-arm/arch-at91/at91_ecc.h +7 -5
index ff93df5..0dc4e6b 100644
@@ -13,26 +13,28 @@
 #ifndef AT91_ECC_H
 #define AT91_ECC_H
 
-#define AT91_ECC_CR		(AT91_ECC + 0x00)	/* Control register */
+/* ECC registers offsets */
+#define AT91_ECC_CR		0x00				/* Control register */
 #define		AT91_ECC_RST		(1 << 0)		/* Reset parity */
 
-#define AT91_ECC_MR		(AT91_ECC + 0x04)	/* Mode register */
+#define AT91_ECC_MR		0x04				/* Mode register */
 #define		AT91_ECC_PAGESIZE	(3 << 0)		/* Page Size */
 #define			AT91_ECC_PAGESIZE_528		(0)
 #define			AT91_ECC_PAGESIZE_1056		(1)
 #define			AT91_ECC_PAGESIZE_2112		(2)
 #define			AT91_ECC_PAGESIZE_4224		(3)
 
-#define AT91_ECC_SR		(AT91_ECC + 0x08)	/* Status register */
+#define AT91_ECC_SR		0x08				/* Status register */
 #define		AT91_ECC_RECERR		(1 << 0)		/* Recoverable Error */
 #define		AT91_ECC_ECCERR		(1 << 1)		/* ECC Single Bit Error */
 #define		AT91_ECC_MULERR		(1 << 2)		/* Multiple Errors */
 
-#define AT91_ECC_PR		(AT91_ECC + 0x0c)	/* Parity register */
+#define AT91_ECC_PR		0x0c				/* Parity register */
 #define		AT91_ECC_BITADDR	(0xf << 0)		/* Bit Error Address */
 #define		AT91_ECC_WORDADDR	(0xfff << 4)		/* Word Error Address */
+#define		AT91_ECC_PARITY		(0xffff << 0)		/* Parity */
 
-#define AT91_ECC_NPR		(AT91_ECC + 0x10)	/* NParity register */
+#define AT91_ECC_NPR		0x10				/* NParity register */
 #define		AT91_ECC_NPARITY	(0xffff << 0)		/* NParity */
 
 #endif
include/asm-arm/arch-at91/at91sam9260.h +21 -0
index c8934fe..b2be92b 100644
@@ -79,6 +79,27 @@
 #define AT91_BASE_SYS			0xffffe800
 
 /*
+ * System Peripherals physical base addresses.
+ */
+#define AT91SAM9260_ECC		0xffffe800
+#define AT91SAM9260_SDRAMC	0xffffea00
+#define AT91SAM9260_SMC		0xffffec00
+#define AT91SAM9260_MATRIX	0xffffee00
+#define AT91SAM9260_CCFG	0xffffef10
+#define AT91SAM9260_AIC		0xfffff000
+#define AT91SAM9260_DBGU	0xfffff200
+#define AT91SAM9260_PIOA	0xfffff400
+#define AT91SAM9260_PIOB	0xfffff600
+#define AT91SAM9260_PIOC	0xfffff800
+#define AT91SAM9260_PMC		0xfffffc00
+#define AT91SAM9260_RSTC	0xfffffd00
+#define AT91SAM9260_SHDWC	0xfffffd10
+#define AT91SAM9260_RTT		0xfffffd20
+#define AT91SAM9260_PIT		0xfffffd30
+#define AT91SAM9260_WDT		0xfffffd40
+#define AT91SAM9260_GPBR	0xfffffd50
+
+/*
  * System Peripherals (offset from AT91_BASE_SYS)
  */
 #define AT91_ECC	(0xffffe800 - AT91_BASE_SYS)
include/asm-arm/arch-at91/at91sam9263.h +27 -0
index 018a647..acf6bb1 100644
@@ -75,6 +75,33 @@
 #define AT91_BASE_SYS			0xffffe000
 
 /*
+ * System Peripherals physical base addresses.
+ */
+#define AT91SAM9263_ECC0	0xffffe000
+#define AT91SAM9263_SDRAMC0	0xffffe200
+#define AT91SAM9263_SMC0	0xffffe400
+#define AT91SAM9263_ECC1	0xffffe600
+#define AT91SAM9263_SDRAMC1	0xffffe800
+#define AT91SAM9263_SMC1	0xffffea00
+#define AT91SAM9263_MATRIX	0xffffec00
+#define AT91SAM9263_CCFG	0xffffed10
+#define AT91SAM9263_DBGU	0xffffee00
+#define AT91SAM9263_AIC		0xfffff000
+#define AT91SAM9263_PIOA	0xfffff200
+#define AT91SAM9263_PIOB	0xfffff400
+#define AT91SAM9263_PIOC	0xfffff600
+#define AT91SAM9263_PIOD	0xfffff800
+#define AT91SAM9263_PIOE	0xfffffa00
+#define AT91SAM9263_PMC		0xfffffc00
+#define AT91SAM9263_RSTC	0xfffffd00
+#define AT91SAM9263_SHDWC	0xfffffd10
+#define AT91SAM9263_RTT0	0xfffffd20
+#define AT91SAM9263_PIT		0xfffffd30
+#define AT91SAM9263_WDT		0xfffffd40
+#define AT91SAM9263_RTT1	0xfffffd50
+#define AT91SAM9263_GPBR	0xfffffd60
+
+/*
  * System Peripherals (offset from AT91_BASE_SYS)
  */
 #define AT91_ECC0	(0xffffe000 - AT91_BASE_SYS)
#1 lore raw
Quoted 5 lines · Richard Genoud

This is a patch to use the hardware ECC controller of the AT91SAM9260 and AT91SAM9263 for the AT91 nand. On AT91 NAND, there's now a choice between ECC soft, ECC hard or no ECC (for debug).

Quoted 7 lines

It has been tested on AT91SAM9263 with 8 bits large and small page NAND.

kernel version : 2.6.25-rc2

patching file arch/arm/mach-at91/at91sam9260_devices.c
Hunk #1 FAILED at 288.
1 out of 1 hunk FAILED -- saving rejects to file arch/arm/mach-at91/at91sam9260_devices.c.rej patching file arch/arm/mach-at91/at91sam9263_devices.c
Hunk #1 FAILED at 358.
1 out of 1 hunk FAILED -- saving rejects to file arch/arm/mach-at91/at91sam9263_devices.c.rej patching file drivers/mtd/nand/Kconfig
Hunk #1 succeeded at 278 with fuzz 2.
patching file drivers/mtd/nand/at91_nand.c
Hunk #3 succeeded at 139 with fuzz 2.
Hunk #11 FAILED at 584.
1 out of 11 hunks FAILED -- saving rejects to file drivers/mtd/nand/at91_nand.c.rej patching file include/asm-arm/arch-at91/at91_ecc.h
Hunk #1 FAILED at 13.
1 out of 1 hunk FAILED -- saving rejects to file include/asm-arm/arch-at91/at91_ecc.h.rej patching file include/asm-arm/arch-at91/at91sam9260.h
patching file include/asm-arm/arch-at91/at91sam9263.h

Signature · 1 line
dwmw2
#2 lore raw
Quoted 11 lines

patching file arch/arm/mach-at91/at91sam9260_devices.c
Hunk #1 FAILED at 288.
1 out of 1 hunk FAILED -- saving rejects to file arch/arm/mach-at91/at91sam9260_devices.c.rej patching file arch/arm/mach-at91/at91sam9263_devices.c
Hunk #1 FAILED at 358.
1 out of 1 hunk FAILED -- saving rejects to file arch/arm/mach-at91/at91sam9263_devices.c.rej patching file drivers/mtd/nand/Kconfig
Hunk #1 succeeded at 278 with fuzz 2.
patching file drivers/mtd/nand/at91_nand.c
Hunk #3 succeeded at 139 with fuzz 2.
Hunk #11 FAILED at 584.

Quoted 8 lines

1 out of 11 hunks FAILED -- saving rejects to file drivers/mtd/nand/at91_nand.c.rej patching file include/asm-arm/arch-at91/at91_ecc.h
Hunk #1 FAILED at 13.
1 out of 1 hunk FAILED -- saving rejects to file include/asm-arm/arch-at91/at91_ecc.h.rej patching file include/asm-arm/arch-at91/at91sam9260.h
patching file include/asm-arm/arch-at91/at91sam9263.h
--
dwmw2

I don't know what kernel you use, but I'm getting no error with this patch on kernel 2.6.25-rc2 (and on 2.6.25 it's also ok) that I've downloaded from kernel.org:

~/dev/kernels/linux-2.6.25-rc2$ patch -p1 < ../mail.google.com patching file arch/arm/mach-at91/at91sam9260_devices.c patching file arch/arm/mach-at91/at91sam9263_devices.c patching file drivers/mtd/nand/Kconfig
patching file drivers/mtd/nand/at91_nand.c
patching file include/asm-arm/arch-at91/at91_ecc.h patching file include/asm-arm/arch-at91/at91sam9260.h patching file include/asm-arm/arch-at91/at91sam9263.h

#3 lore raw
Quoted 3 lines · Richard Genoud

I don't know what kernel you use, but I'm getting no error with this patch on kernel 2.6.25-rc2 (and on 2.6.25 it's also ok) that I've downloaded from kernel.org:

Hm, that's true. There seem to have been changes since 2.6.25 which cause the conflicts. Please could you make it apply to the current git tree?

Thanks.

Signature · 1 line
dwmw2
#4 lore raw
Quoted 5 lines

Hm, that's true. There seem to have been changes since 2.6.25 which
cause the conflicts. Please could you make it apply to the current git tree?

Thanks.

I'm firewalled for the moment (I can't use git), I'll try to do this at home.

Richard.

#6 lore raw

This is a patch to use the hardware ECC controller of the AT91SAM9260 and AT91SAM9263 for the AT91 nand. On AT91 NAND, there's now a choice between ECC soft, ECC hard or no ECC (for debug).

It has been tested on AT91SAM9263 with 8 bits large and small page NAND.

kernel version : 2.6.25 linux-mtd master tree

---
 drivers/mtd/nand/Kconfig                 |   41 ++++
 drivers/mtd/nand/at91_nand.c             |  361 +++++++++++++++++++++++++++++-
 2 files changed, 397 insertions(+), 5 deletions(-)
arch/arm/mach-at91/at91sam9260_devices.c +0 -0
drivers/mtd/nand/Kconfig +41 -0

47 lines not on this page · raw message

drivers/mtd/nand/at91_nand.c +356 -5

434 lines not on this page · raw message

#7 lore raw

drivers/mtd/nand/at91_nand.c static void at91_nand_disable(struct at91_nand_host *host) · line 205

Quoted 13 lines · Richard Genoud
drivers/mtd/nand/at91_nand.c +13 -0
+static int at91_nand_calculate(struct mtd_info *mtd,
+               const u_char *dat, unsigned char *ecc_code)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct at91_nand_host *host = nand_chip->priv;
+       uint32_t *eccpos = nand_chip->ecc.layout->eccpos;
+       unsigned int ecc_value;
+
+       /* get the first 2 ECC bytes */
+       ecc_value = ecc_readl(host->ecc, PR) & AT91_ECC_PARITY;
+
+       ecc_code[eccpos[0]] = ecc_value & 0xFF;
+       ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;

My copy of the sam9263 docs doesn't list an "ECC_PARITY" field in the PR register ... just two masked fields, 0xfff0 and 0x000f labeled WORDADDR and BITADDR respectively. (Which evidently are combined into a single opague 0xffff mask on block writes, and are interpretable only on block reads.)

And the system header doesn't have an ECC_PARITY mask ... so I get build errors with current GIT.

drivers/mtd/nand/at91_nand.c static void at91_nand_disable(struct at91_nand_host *host) · line 211

Quoted 6 lines
drivers/mtd/nand/at91_nand.c +6 -0
+
+       /* get the last 2 ECC bytes */
+       ecc_value = ecc_readl(host->ecc, NPR) & AT91_ECC_NPARITY;
+
+       ecc_code[eccpos[2]] = ecc_value & 0xFF;
+       ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;

That one builds OK.

I suggest you just remove the masks from the readl() lines. They're not necessary.

- Dave

Quoted 3 lines
drivers/mtd/nand/at91_nand.c +3 -0
+
+       return 0;
+}
#8 lore raw

2008/4/24, David Brownell <[email protected]>:

Quoted 11 lines

My copy of the sam9263 docs doesn't list an "ECC_PARITY" field
in the PR register ... just two masked fields, 0xfff0 and 0x000f labeled WORDADDR and BITADDR respectively. (Which evidently are combined into a single opague 0xffff mask on block writes, and are interpretable only on block reads.)

And the system header doesn't have an ECC_PARITY mask ... so I get build errors with current GIT.

- Dave

you're right, this is my bad. Thanks for pointing this out.

David W., could you apply the patch bellow to make things right again ?

The AT91_ECC_PARITY mask does not exist (and masking with it was useless). kernel version : mtd-2.6 current git

---

mtd/nand/at91_nand.c renamed from mtd/nand/at91_nand.c.orig +1 -1
@@ -199,7 +199,7 @@ static int at91_nand_calculate(struct mt
 	unsigned int ecc_value;
 
 	/* get the first 2 ECC bytes */
-	ecc_value = ecc_readl(host->ecc, PR) & AT91_ECC_PARITY;
+	ecc_value = ecc_readl(host->ecc, PR);
 
 	ecc_code[eccpos[0]] = ecc_value & 0xFF;
 	ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;