mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* add i.MX51 Nand support
@ 2010-11-10 14:53 Sascha Hauer
  2010-11-10 14:53 ` [PATCH 01/13] NAND: reset chips before usage like the kernel does Sascha Hauer
                   ` (13 more replies)
  0 siblings, 14 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

Hi all,

The following series is a respin of the series adding i.MX51 Nand support
to the kernel for barebox.

The series reveals to problems in barebox. First the i.MX51 Nand controller
needs two memory resources. Since I know that Jean-Christophe recently
worked on adding resources to barebox I decided for a hack in the driver
for now: I just hardcoded the second base address. Second the current
implementation of dma_alloc_coherent stinks. The implementation simply
maps the whole SDRAM a second time uncached. This way we can use the
normal malloc function to allocate dma coherent memory and just add
a known offset to the returned pointer. On i.MX51 boards with 512MB SDRAM
we do not have enough space in the memory map to map the SDRAM twice, in
my case the mapping shadowed the Nand register space. Be aware of this
when you try to add Nand support to your i.MX51 board and use the babbage
code as a template.

Sascha

The following changes since commit 6a84a019abf0663c27c2c41e69cf0aea1dce19e9:

  i.MX device macros: Fix typo (2010-11-10 10:46:03 +0100)

are available in the git repository at:
  git://git.pengutronix.de/git/barebox.git imx51-nand

Sascha Hauer (13):
      NAND: reset chips before usage like the kernel does
      imx_nand: remove 0xe00 offset from registers
      imx_nand: rework get_dev_status
      imx nand: remove unnecessary register write
      imx_nand: make some internally used functions overwriteable
      imx nand: do not read-modify-write SPAS register
      imx nand: add V1_V2 namespace to registers
      mxc_nand: fix correct_data function
      imx nand: move initialization to preset function
      imx nand: introduce overwritable check_int function
      imx nand: Add v3 (i.MX51) support
      fb: set id for framebuffer device correctly
      ARM i.MX51: Add nand device

 arch/arm/mach-imx/include/mach/devices-imx51.h |    5 +
 arch/arm/mach-imx/include/mach/imx51-regs.h    |    2 +
 arch/arm/mach-imx/nand.c                       |    9 +
 drivers/mtd/nand/Kconfig                       |    4 +-
 drivers/mtd/nand/nand_base.c                   |    6 +
 drivers/mtd/nand/nand_imx.c                    |  718 ++++++++++++++++--------
 drivers/video/fb.c                             |    1 +
 7 files changed, 494 insertions(+), 251 deletions(-)


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 01/13] NAND: reset chips before usage like the kernel does
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 02/13] imx_nand: remove 0xe00 offset from registers Sascha Hauer
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_base.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index b75a450..56fafb0 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2215,6 +2215,12 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	/* Select the device */
 	chip->select_chip(mtd, 0);
 
+	/*
+	 * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
+	 * after power-up
+	 */
+	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
 	/* Send the command for reading device ID */
 	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
 
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 02/13] imx_nand: remove 0xe00 offset from registers
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
  2010-11-10 14:53 ` [PATCH 01/13] NAND: reset chips before usage like the kernel does Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 03/13] imx_nand: rework get_dev_status Sascha Hauer
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

Add the offset to the register base instead. This is done
in preparation for v3 controller support.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c |   42 +++++++++++++++++++++---------------------
 1 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 63ba188..d5503a1 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -38,23 +38,23 @@
 /*
  * Addresses for NFC registers
  */
-#define NFC_BUF_SIZE		0xE00
-#define NFC_BUF_ADDR		0xE04
-#define NFC_FLASH_ADDR		0xE06
-#define NFC_FLASH_CMD		0xE08
-#define NFC_CONFIG		0xE0A
-#define NFC_ECC_STATUS_RESULT	0xE0C
-#define NFC_RSLTMAIN_AREA	0xE0E
-#define NFC_RSLTSPARE_AREA	0xE10
-#define NFC_SPAS		0xe10
-#define NFC_WRPROT		0xE12
-#define NFC_V1_UNLOCKSTART_BLKADDR	0xe14
-#define NFC_V1_UNLOCKEND_BLKADDR	0xe16
-#define NFC_V21_UNLOCKSTART_BLKADDR	0xe20
-#define NFC_V21_UNLOCKEND_BLKADDR	0xe22
-#define NFC_NF_WRPRST		0xE18
-#define NFC_CONFIG1		0xE1A
-#define NFC_CONFIG2		0xE1C
+#define NFC_BUF_SIZE			0x00
+#define NFC_BUF_ADDR			0x04
+#define NFC_FLASH_ADDR			0x06
+#define NFC_FLASH_CMD			0x08
+#define NFC_CONFIG			0x0a
+#define NFC_ECC_STATUS_RESULT		0x0c
+#define NFC_RSLTMAIN_AREA		0x0e
+#define NFC_RSLTSPARE_AREA		0x10
+#define NFC_SPAS			0x10
+#define NFC_WRPROT			0x12
+#define NFC_V1_UNLOCKSTART_BLKADDR	0x14
+#define NFC_V1_UNLOCKEND_BLKADDR	0x16
+#define NFC_V21_UNLOCKSTART_BLKADDR	0x20
+#define NFC_V21_UNLOCKEND_BLKADDR	0x22
+#define NFC_NF_WRPRST			0x18
+#define NFC_CONFIG1			0x1a
+#define NFC_CONFIG2			0x1c
 
 /*
  * Addresses for NFC RAM BUFFER Main area 0
@@ -861,13 +861,13 @@ static int __init imxnd_probe(struct device_d *dev)
 	host->main_area1 = host->base + 0x200;
 
 	if (nfc_is_v21()) {
-		host->regs = host->base + 0x1000;
+		host->regs = host->base + 0x1e00;
 		host->spare0 = host->base + 0x1000;
 		host->spare_len = 64;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
 	} else if (nfc_is_v1()) {
-		host->regs = host->base;
+		host->regs = host->base + 0xe00;
 		host->spare0 = host->base + 0x800;
 		host->spare_len = 16;
 		oob_smallpage = &nandv1_hw_eccoob_smallpage;
@@ -1159,10 +1159,10 @@ void __nand_boot_init imx_nand_load_image(void *dest, int size)
 
 	base = (void __iomem *)IMX_NFC_BASE;
 	if (nfc_is_v21()) {
-		regs = base + 0x1000;
+		regs = base + 0x1e00;
 		spare0 = base + 0x1000;
 	} else if (nfc_is_v1()) {
-		regs = base;
+		regs = base + 0xe00;
 		spare0 = base + 0x800;
 	}
 
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 03/13] imx_nand: rework get_dev_status
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
  2010-11-10 14:53 ` [PATCH 01/13] NAND: reset chips before usage like the kernel does Sascha Hauer
  2010-11-10 14:53 ` [PATCH 02/13] imx_nand: remove 0xe00 offset from registers Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 04/13] imx nand: remove unnecessary register write Sascha Hauer
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

We save/restore the value in the buffer anyway, so it makes
no difference whether we use main_area0 or main_area1. So,
we can use main_area0 and remove main_area1 from the driver
which is otherwise unused. Also, clean up the comments in
get_dev_status.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c |   21 ++++++++++-----------
 1 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index d5503a1..b49b7db 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -142,7 +142,6 @@ struct imx_nand_host {
 
 	void			*spare0;
 	void			*main_area0;
-	void			*main_area1;
 
 	void __iomem		*base;
 	void __iomem		*regs;
@@ -361,18 +360,18 @@ static void send_read_id(struct imx_nand_host *host)
  */
 static u16 get_dev_status(struct imx_nand_host *host)
 {
-	volatile u16 *mainbuf = host->main_area1;
+	void *main_buf = host->main_area0;
 	u32 store;
 	u16 ret, tmp;
-	/* Issue status request to NAND device */
 
-	/* store the main area1 first word, later do recovery */
-	store = *((u32 *) mainbuf);
+	writew(0x0, host->regs + NFC_BUF_ADDR);
+
 	/*
-	 * NANDFC buffer 1 is used for device status to prevent
-	 * corruption of read/write buffer on status requests.
+	 * The device status is stored in main_area0. To
+	 * prevent corruption of the buffer save the value
+	 * and restore it afterwards.
 	 */
-	writew(1, host->regs + NFC_BUF_ADDR);
+	store = readl(main_buf);
 
 	/* Read status into main buffer */
 	tmp = readw(host->regs + NFC_CONFIG1);
@@ -386,8 +385,9 @@ static u16 get_dev_status(struct imx_nand_host *host)
 
 	/* Status is placed in first word of main buffer */
 	/* get status, then recovery area 1 data */
-	ret = mainbuf[0];
-	*((u32 *) mainbuf) = store;
+	ret = readw(main_buf);
+
+	writel(store, main_buf);
 
 	return ret;
 }
@@ -858,7 +858,6 @@ static int __init imxnd_probe(struct device_d *dev)
 	host->base = (void __iomem *)dev->map_base;
 
 	host->main_area0 = host->base;
-	host->main_area1 = host->base + 0x200;
 
 	if (nfc_is_v21()) {
 		host->regs = host->base + 0x1e00;
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 04/13] imx nand: remove unnecessary register write
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (2 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 03/13] imx_nand: rework get_dev_status Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 05/13] imx_nand: make some internally used functions overwriteable Sascha Hauer
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

NFC_SP_EN is cleared in probe and never set again, so we do not
need to clear it in other functions again.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c |   13 +------------
 1 files changed, 1 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index b49b7db..4b74974 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -321,16 +321,10 @@ static void send_page(struct imx_nand_host *host,
 static void send_read_id(struct imx_nand_host *host)
 {
 	struct nand_chip *this = &host->nand;
-	u16 tmp;
 
 	/* NANDFC buffer 0 is used for device ID output */
 	writew(0x0, host->regs + NFC_BUF_ADDR);
 
-	/* Read ID into main buffer */
-	tmp = readw(host->regs + NFC_CONFIG1);
-	tmp &= ~NFC_SP_EN;
-	writew(tmp, host->regs + NFC_CONFIG1);
-
 	writew(NFC_ID, host->regs + NFC_CONFIG2);
 
 	/* Wait for operation to complete */
@@ -362,7 +356,7 @@ static u16 get_dev_status(struct imx_nand_host *host)
 {
 	void *main_buf = host->main_area0;
 	u32 store;
-	u16 ret, tmp;
+	u16 ret;
 
 	writew(0x0, host->regs + NFC_BUF_ADDR);
 
@@ -373,11 +367,6 @@ static u16 get_dev_status(struct imx_nand_host *host)
 	 */
 	store = readl(main_buf);
 
-	/* Read status into main buffer */
-	tmp = readw(host->regs + NFC_CONFIG1);
-	tmp &= ~NFC_SP_EN;
-	writew(tmp, host->regs + NFC_CONFIG1);
-
 	writew(NFC_STATUS, host->regs + NFC_CONFIG2);
 
 	/* Wait for operation to complete */
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 05/13] imx_nand: make some internally used functions overwriteable
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (3 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 04/13] imx nand: remove unnecessary register write Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 06/13] imx nand: do not read-modify-write SPAS register Sascha Hauer
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

This patch prepares the driver to add v3 controller support
later. The v3 controller is basically the same controller as v1
and v2, but with a completely different register layout.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c |   66 ++++++++++++++++++++++++++-----------------
 1 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 4b74974..22251e4 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -153,6 +153,12 @@ struct imx_nand_host {
 	unsigned int		buf_start;
 	int			spare_len;
 
+	void			(*preset)(struct mtd_info *);
+	void			(*send_cmd)(struct imx_nand_host *, uint16_t);
+	void			(*send_addr)(struct imx_nand_host *, uint16_t);
+	void			(*send_page)(struct imx_nand_host *, unsigned int);
+	void			(*send_read_id)(struct imx_nand_host *);
+	uint16_t		(*get_dev_status)(struct imx_nand_host *);
 };
 
 /*
@@ -246,7 +252,7 @@ static void wait_op_done(struct imx_nand_host *host)
  *
  * @param       cmd     command for NAND Flash
  */
-static void send_cmd(struct imx_nand_host *host, u16 cmd)
+static void send_cmd_v1_v2(struct imx_nand_host *host, u16 cmd)
 {
 	MTD_DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
 
@@ -275,7 +281,7 @@ static void send_cmd(struct imx_nand_host *host, u16 cmd)
  * @param       addr    address to be written to NFC.
  * @param       islast  True if this is the last address cycle for command
  */
-static void send_addr(struct imx_nand_host *host, u16 addr)
+static void send_addr_v1_v2(struct imx_nand_host *host, u16 addr)
 {
 	MTD_DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
 
@@ -293,7 +299,7 @@ static void send_addr(struct imx_nand_host *host, u16 addr)
  * @param	buf_id	      Specify Internal RAM Buffer number (0-3)
  * @param       spare_only    set true if only the spare area is transferred
  */
-static void send_page(struct imx_nand_host *host,
+static void send_page_v1_v2(struct imx_nand_host *host,
 		unsigned int ops)
 {
 	int bufs, i;
@@ -318,7 +324,7 @@ static void send_page(struct imx_nand_host *host,
  * This function requests the NANDFC to perform a read of the
  * NAND device ID.
  */
-static void send_read_id(struct imx_nand_host *host)
+static void send_read_id_v1_v2(struct imx_nand_host *host)
 {
 	struct nand_chip *this = &host->nand;
 
@@ -352,7 +358,7 @@ static void send_read_id(struct imx_nand_host *host)
  *
  * @return  device status
  */
-static u16 get_dev_status(struct imx_nand_host *host)
+static u16 get_dev_status_v1_v2(struct imx_nand_host *host)
 {
 	void *main_buf = host->main_area0;
 	u32 store;
@@ -448,7 +454,7 @@ static u_char imx_nand_read_byte(struct mtd_info *mtd)
 
 	/* Check for status request */
 	if (host->status_request)
-		return get_dev_status(host) & 0xFF;
+		return host->get_dev_status(host) & 0xFF;
 
 	ret = *(uint8_t *)(host->data_buf + host->buf_start);
 	host->buf_start++;
@@ -616,32 +622,32 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 		 * we will used the saved column adress to index into
 		 * the full page.
 		 */
-		send_addr(host, 0);
+		host->send_addr(host, 0);
 		if (host->pagesize_2k)
 			/* another col addr cycle for 2k page */
-			send_addr(host, 0);
+			host->send_addr(host, 0);
 	}
 
 	/*
 	 * Write out page address, if necessary
 	 */
 	if (page_addr != -1) {
-		send_addr(host, (page_addr & 0xff));	/* paddr_0 - p_addr_7 */
+		host->send_addr(host, (page_addr & 0xff));	/* paddr_0 - p_addr_7 */
 
 		if (host->pagesize_2k) {
-			send_addr(host, (page_addr >> 8) & 0xFF);
+			host->send_addr(host, (page_addr >> 8) & 0xFF);
 			if (mtd->size >= 0x10000000) {
-				send_addr(host, (page_addr >> 16) & 0xff);
+				host->send_addr(host, (page_addr >> 16) & 0xff);
 			}
 		} else {
 			/* One more address cycle for higher density devices */
 			if (mtd->size >= 0x4000000) {
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff);
-				send_addr(host, (page_addr >> 16) & 0xff);
+				host->send_addr(host, (page_addr >> 8) & 0xff);
+				host->send_addr(host, (page_addr >> 16) & 0xff);
 			} else
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff);
+				host->send_addr(host, (page_addr >> 8) & 0xff);
 		}
 	}
 }
@@ -678,7 +684,7 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command,
 	case NAND_CMD_STATUS:
 		host->buf_start = 0;
 		host->status_request = 1;
-		send_cmd(host, command);
+		host->send_cmd(host, command);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 
@@ -691,14 +697,14 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command,
 
 		command = NAND_CMD_READ0;
 
-		send_cmd(host, command);
+		host->send_cmd(host, command);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 
 		if (host->pagesize_2k)
 			/* send read confirm command */
-			send_cmd(host, NAND_CMD_READSTART);
+			host->send_cmd(host, NAND_CMD_READSTART);
 
-		send_page(host, NFC_OUTPUT);
+		host->send_page(host, NFC_OUTPUT);
 
 		memcpy32(host->data_buf, host->main_area0, mtd->writesize);
 		copy_spare(mtd, 1);
@@ -722,15 +728,15 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command,
 
 			/* Set program pointer to spare region */
 			if (!host->pagesize_2k)
-				send_cmd(host, NAND_CMD_READOOB);
+				host->send_cmd(host, NAND_CMD_READOOB);
 		} else {
 			host->buf_start = column;
 
 			/* Set program pointer to page start */
 			if (!host->pagesize_2k)
-				send_cmd(host, NAND_CMD_READ0);
+				host->send_cmd(host, NAND_CMD_READ0);
 		}
-		send_cmd(host, command);
+		host->send_cmd(host, command);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 
 		break;
@@ -738,22 +744,22 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command,
 	case NAND_CMD_PAGEPROG:
 		memcpy32(host->main_area0, host->data_buf, mtd->writesize);
 		copy_spare(mtd, 0);
-		send_page(host, NFC_INPUT);
-		send_cmd(host, command);
+		host->send_page(host, NFC_INPUT);
+		host->send_cmd(host, command);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 
 	case NAND_CMD_READID:
-		send_cmd(host, command);
+		host->send_cmd(host, command);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		host->buf_start = 0;
-		send_read_id(host);
+		host->send_read_id(host);
 		break;
 
 	case NAND_CMD_ERASE1:
 	case NAND_CMD_ERASE2:
 	case NAND_CMD_RESET:
-		send_cmd(host, command);
+		host->send_cmd(host, command);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 	}
@@ -848,6 +854,14 @@ static int __init imxnd_probe(struct device_d *dev)
 
 	host->main_area0 = host->base;
 
+	if (nfc_is_v1() || nfc_is_v21()) {
+		host->send_cmd = send_cmd_v1_v2;
+		host->send_addr = send_addr_v1_v2;
+		host->send_page = send_page_v1_v2;
+		host->send_read_id = send_read_id_v1_v2;
+		host->get_dev_status = get_dev_status_v1_v2;
+	}
+
 	if (nfc_is_v21()) {
 		host->regs = host->base + 0x1e00;
 		host->spare0 = host->base + 0x1000;
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 06/13] imx nand: do not read-modify-write SPAS register
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (4 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 05/13] imx_nand: make some internally used functions overwriteable Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 07/13] imx nand: add V1_V2 namespace to registers Sascha Hauer
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c |   31 ++++++++-----------------------
 1 files changed, 8 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 22251e4..62a23d5 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -975,19 +975,11 @@ static int __init imxnd_probe(struct device_d *dev)
 	if (mtd->writesize == 2048) {
 		this->ecc.layout = oob_largepage;
 		host->pagesize_2k = 1;
-		if (nfc_is_v21()) {
-			tmp = readw(host->regs + NFC_SPAS);
-			tmp &= 0xff00;
-			tmp |= NFC_SPAS_64;
-			writew(tmp, host->regs + NFC_SPAS);
-		}
+		if (nfc_is_v21())
+			writew(NFC_SPAS_64, host->regs + NFC_SPAS);
 	} else {
-		if (nfc_is_v21()) {
-			tmp = readw(host->regs + NFC_SPAS);
-			tmp &= 0xff00;
-			tmp |= NFC_SPAS_16;
-			writew(tmp, host->regs + NFC_SPAS);
-		}
+		if (nfc_is_v21())
+			writew(NFC_SPAS_16, host->regs + NFC_SPAS);
 	}
 
 	/* second phase scan */
@@ -1186,17 +1178,10 @@ void __nand_boot_init imx_nand_load_image(void *dest, int size)
 	writew(tmp, regs + NFC_CONFIG1);
 
 	if (nfc_is_v21()) {
-		if (pagesize_2k) {
-			tmp = readw(regs + NFC_SPAS);
-			tmp &= 0xff00;
-			tmp |= NFC_SPAS_64;
-			writew(tmp, regs + NFC_SPAS);
-		} else {
-			tmp = readw(regs + NFC_SPAS);
-			tmp &= 0xff00;
-			tmp |= NFC_SPAS_16;
-			writew(tmp, regs + NFC_SPAS);
-		}
+		if (pagesize_2k)
+			writew(NFC_SPAS_64, regs + NFC_SPAS);
+		else
+			writew(NFC_SPAS_16, regs + NFC_SPAS);
 	}
 
 	block = page = 0;
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 07/13] imx nand: add V1_V2 namespace to registers
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (5 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 06/13] imx nand: do not read-modify-write SPAS register Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 08/13] mxc_nand: fix correct_data function Sascha Hauer
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

This prepares the driver for v3 support. The v3 controller
has a completely different register layout, so add a V1_V2_
namespace to the register defines to avoid confusion with
the v3 regs.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c |  220 +++++++++++++++++--------------------------
 1 files changed, 86 insertions(+), 134 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 62a23d5..99f6714 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -30,103 +30,55 @@
 #include <asm/io.h>
 #include <errno.h>
 
-#define DVR_VER "2.0"
-
 #define nfc_is_v21()		(cpu_is_mx25() || cpu_is_mx35())
 #define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
 
-/*
- * Addresses for NFC registers
- */
-#define NFC_BUF_SIZE			0x00
-#define NFC_BUF_ADDR			0x04
-#define NFC_FLASH_ADDR			0x06
-#define NFC_FLASH_CMD			0x08
-#define NFC_CONFIG			0x0a
-#define NFC_ECC_STATUS_RESULT		0x0c
-#define NFC_RSLTMAIN_AREA		0x0e
-#define NFC_RSLTSPARE_AREA		0x10
-#define NFC_SPAS			0x10
-#define NFC_WRPROT			0x12
+#define NFC_V1_ECC_STATUS_RESULT	0x0c
+#define NFC_V1_RSLTMAIN_AREA		0x0e
+#define NFC_V1_RSLTSPARE_AREA		0x10
+
+#define NFC_V2_ECC_STATUS_RESULT1	0x0c
+#define NFC_V2_ECC_STATUS_RESULT2	0x0e
+#define NFC_V2_SPAS			0x10
+
+#define NFC_V1_V2_BUF_SIZE		0x00
+#define NFC_V1_V2_BUF_ADDR		0x04
+#define NFC_V1_V2_FLASH_ADDR		0x06
+#define NFC_V1_V2_FLASH_CMD		0x08
+#define NFC_V1_V2_CONFIG		0x0a
+
+#define NFC_V1_V2_WRPROT		0x12
 #define NFC_V1_UNLOCKSTART_BLKADDR	0x14
 #define NFC_V1_UNLOCKEND_BLKADDR	0x16
 #define NFC_V21_UNLOCKSTART_BLKADDR	0x20
 #define NFC_V21_UNLOCKEND_BLKADDR	0x22
-#define NFC_NF_WRPRST			0x18
-#define NFC_CONFIG1			0x1a
-#define NFC_CONFIG2			0x1c
+#define NFC_V1_V2_NF_WRPRST		0x18
+#define NFC_V1_V2_CONFIG1		0x1a
+#define NFC_V1_V2_CONFIG2		0x1c
 
-/*
- * Addresses for NFC RAM BUFFER Main area 0
- */
-#define MAIN_AREA0		0x000
-#define MAIN_AREA1		0x200
-#define MAIN_AREA2		0x400
-#define MAIN_AREA3		0x600
+#define NFC_V2_CONFIG1_ECC_MODE_4       (1 << 0)
+#define NFC_V1_V2_CONFIG1_SP_EN		(1 << 2)
+#define NFC_V1_V2_CONFIG1_ECC_EN	(1 << 3)
+#define NFC_V1_V2_CONFIG1_INT_MSK	(1 << 4)
+#define NFC_V1_V2_CONFIG1_BIG		(1 << 5)
+#define NFC_V1_V2_CONFIG1_RST		(1 << 6)
+#define NFC_V1_V2_CONFIG1_CE		(1 << 7)
+#define NFC_V1_V2_CONFIG1_ONE_CYCLE	(1 << 8)
 
-/*
- * Addresses for NFC SPARE BUFFER Spare area 0
- */
-#define SPARE_AREA0		0x800
-#define SPARE_AREA1		0x810
-#define SPARE_AREA2		0x820
-#define SPARE_AREA3		0x830
-
-/*
- * Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register for Command
- * operation
- */
-#define NFC_CMD            0x1
+#define NFC_V1_V2_CONFIG2_INT		(1 << 15)
 
-/*
- * Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register for Address
- * operation
- */
-#define NFC_ADDR           0x2
+#define NFC_V2_SPAS_SPARESIZE(spas)	((spas) >> 1)
 
 /*
- * Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register for Input
- * operation
+ * Operation modes for the NFC. Valid for v1, v2 and v3
+ * type controllers.
  */
-#define NFC_INPUT          0x4
-
-/*
- * Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register for Data Output
- * operation
- */
-#define NFC_OUTPUT         0x8
-
-/*
- * Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register for Read ID
- * operation
- */
-#define NFC_ID             0x10
-
-/*
- * Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register for Read Status
- * operation
- */
-#define NFC_STATUS         0x20
-
-/*
- * Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read Status
- * operation
- */
-#define NFC_INT            0x8000
-
-#define NFC_ECC_MODE        (1 << 0)
-#define NFC_SP_EN           (1 << 2)
-#define NFC_ECC_EN          (1 << 3)
-#define NFC_INT_MSK         (1 << 4)
-#define NFC_BIG             (1 << 5)
-#define NFC_RST             (1 << 6)
-#define NFC_CE              (1 << 7)
-#define NFC_ONE_CYCLE       (1 << 8)
-
-#define NFC_SPAS_16			 8
-#define NFC_SPAS_64			 32
-#define NFC_SPAS_128			 64
-#define NFC_SPAS_218			 109
+#define NFC_CMD				(1 << 0)
+#define NFC_ADDR			(1 << 1)
+#define NFC_INPUT			(1 << 2)
+#define NFC_OUTPUT			(1 << 3)
+#define NFC_ID				(1 << 4)
+#define NFC_STATUS			(1 << 5)
 
 #ifdef CONFIG_NAND_IMX_BOOT
 #define __nand_boot_init __bare_init
@@ -237,10 +189,10 @@ static void wait_op_done(struct imx_nand_host *host)
 	 * here as we might be here from nand booting.
 	 */
 	for (i = 0; i < 100000; i++) {
-		if (readw(host->regs + NFC_CONFIG2) & NFC_INT) {
-			tmp = readw(host->regs + NFC_CONFIG2);
-			tmp  &= ~NFC_INT;
-			writew(tmp, host->regs + NFC_CONFIG2);
+		if (readw(host->regs + NFC_V1_V2_CONFIG2) & NFC_V1_V2_CONFIG2_INT) {
+			tmp = readw(host->regs + NFC_V1_V2_CONFIG2);
+			tmp  &= ~NFC_V1_V2_CONFIG2_INT;
+			writew(tmp, host->regs + NFC_V1_V2_CONFIG2);
 			return;
 		}
 	}
@@ -256,15 +208,15 @@ static void send_cmd_v1_v2(struct imx_nand_host *host, u16 cmd)
 {
 	MTD_DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
 
-	writew(cmd, host->regs + NFC_FLASH_CMD);
-	writew(NFC_CMD, host->regs + NFC_CONFIG2);
+	writew(cmd, host->regs + NFC_V1_V2_FLASH_CMD);
+	writew(NFC_CMD, host->regs + NFC_V1_V2_CONFIG2);
 
 	if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
 		/* Reset completion is indicated by NFC_CONFIG2 */
 		/* being set to 0 */
 		int i;
 		for (i = 0; i < 100000; i++) {
-			if (readw(host->regs + NFC_CONFIG2) == 0) {
+			if (readw(host->regs + NFC_V1_V2_CONFIG2) == 0) {
 				break;
 			}
 		}
@@ -285,8 +237,8 @@ static void send_addr_v1_v2(struct imx_nand_host *host, u16 addr)
 {
 	MTD_DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
 
-	writew(addr, host->regs + NFC_FLASH_ADDR);
-	writew(NFC_ADDR, host->regs + NFC_CONFIG2);
+	writew(addr, host->regs + NFC_V1_V2_FLASH_ADDR);
+	writew(NFC_ADDR, host->regs + NFC_V1_V2_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host);
@@ -311,9 +263,9 @@ static void send_page_v1_v2(struct imx_nand_host *host,
 
 	for (i = 0; i < bufs; i++) {
 		/* NANDFC buffer 0 is used for page read/write */
-		writew(i, host->regs + NFC_BUF_ADDR);
+		writew(i, host->regs + NFC_V1_V2_BUF_ADDR);
 
-		writew(ops, host->regs + NFC_CONFIG2);
+		writew(ops, host->regs + NFC_V1_V2_CONFIG2);
 
 		/* Wait for operation to complete */
 		wait_op_done(host);
@@ -329,9 +281,9 @@ static void send_read_id_v1_v2(struct imx_nand_host *host)
 	struct nand_chip *this = &host->nand;
 
 	/* NANDFC buffer 0 is used for device ID output */
-	writew(0x0, host->regs + NFC_BUF_ADDR);
+	writew(0x0, host->regs + NFC_V1_V2_BUF_ADDR);
 
-	writew(NFC_ID, host->regs + NFC_CONFIG2);
+	writew(NFC_ID, host->regs + NFC_V1_V2_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host);
@@ -364,7 +316,7 @@ static u16 get_dev_status_v1_v2(struct imx_nand_host *host)
 	u32 store;
 	u16 ret;
 
-	writew(0x0, host->regs + NFC_BUF_ADDR);
+	writew(0x0, host->regs + NFC_V1_V2_BUF_ADDR);
 
 	/*
 	 * The device status is stored in main_area0. To
@@ -373,7 +325,7 @@ static u16 get_dev_status_v1_v2(struct imx_nand_host *host)
 	 */
 	store = readl(main_buf);
 
-	writew(NFC_STATUS, host->regs + NFC_CONFIG2);
+	writew(NFC_STATUS, host->regs + NFC_V1_V2_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host);
@@ -422,7 +374,7 @@ static int imx_nand_correct_data(struct mtd_info *mtd, u_char * dat,
 	 * additional correction.  2-Bit errors cannot be corrected by
 	 * HW ECC, so we need to return failure
 	 */
-	u16 ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT);
+	u16 ecc_status = readw(host->regs + NFC_V1_ECC_STATUS_RESULT);
 
 	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
 		MTD_DEBUG(MTD_DEBUG_LEVEL0,
@@ -902,13 +854,13 @@ static int __init imxnd_probe(struct device_d *dev)
 	clk_enable(host->clk);
 #endif
 
-	tmp = readw(host->regs + NFC_CONFIG1);
-	tmp |= NFC_INT_MSK;
-	tmp &= ~NFC_SP_EN;
+	tmp = readw(host->regs + NFC_V1_V2_CONFIG1);
+	tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
+	tmp &= ~NFC_V1_V2_CONFIG1_SP_EN;
 	if (nfc_is_v21())
 		/* currently no support for 218 byte OOB with stronger ECC */
-		tmp |= NFC_ECC_MODE;
-	writew(tmp, host->regs + NFC_CONFIG1);
+		tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
+	writew(tmp, host->regs + NFC_V1_V2_CONFIG1);
 
 	if (pdata->hw_ecc) {
 		this->ecc.calculate = imx_nand_calculate_ecc;
@@ -916,15 +868,15 @@ static int __init imxnd_probe(struct device_d *dev)
 		this->ecc.correct = imx_nand_correct_data;
 		this->ecc.mode = NAND_ECC_HW;
 		this->ecc.size = 512;
-		tmp = readw(host->regs + NFC_CONFIG1);
-		tmp |= NFC_ECC_EN;
-		writew(tmp, host->regs + NFC_CONFIG1);
+		tmp = readw(host->regs + NFC_V1_V2_CONFIG1);
+		tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
+		writew(tmp, host->regs + NFC_V1_V2_CONFIG1);
 	} else {
 		this->ecc.size = 512;
 		this->ecc.mode = NAND_ECC_SOFT;
-		tmp = readw(host->regs + NFC_CONFIG1);
-		tmp &= ~NFC_ECC_EN;
-		writew(tmp, host->regs + NFC_CONFIG1);
+		tmp = readw(host->regs + NFC_V1_V2_CONFIG1);
+		tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN;
+		writew(tmp, host->regs + NFC_V1_V2_CONFIG1);
 	}
 
 	/* Reset NAND */
@@ -932,7 +884,7 @@ static int __init imxnd_probe(struct device_d *dev)
 
 	/* preset operation */
 	/* Unlock the internal RAM Buffer */
-	writew(0x2, host->regs + NFC_CONFIG);
+	writew(0x2, host->regs + NFC_V1_V2_CONFIG);
 
 	/* Blocks to be unlocked */
 	if (nfc_is_v21()) {
@@ -946,7 +898,7 @@ static int __init imxnd_probe(struct device_d *dev)
 	}
 
 	/* Unlock Block Command for given address range */
-	writew(0x4, host->regs + NFC_WRPROT);
+	writew(0x4, host->regs + NFC_V1_V2_WRPROT);
 
 	this->ecc.layout = oob_smallpage;
 
@@ -976,10 +928,10 @@ static int __init imxnd_probe(struct device_d *dev)
 		this->ecc.layout = oob_largepage;
 		host->pagesize_2k = 1;
 		if (nfc_is_v21())
-			writew(NFC_SPAS_64, host->regs + NFC_SPAS);
+			writew(NFC_V2_SPAS_SPARESIZE(64), host->regs + NFC_V2_SPAS);
 	} else {
 		if (nfc_is_v21())
-			writew(NFC_SPAS_16, host->regs + NFC_SPAS);
+			writew(NFC_V2_SPAS_SPARESIZE(16), host->regs + NFC_V2_SPAS);
 	}
 
 	/* second phase scan */
@@ -1012,14 +964,14 @@ static void __nand_boot_init noinline imx_nandboot_wait_op_done(void *regs)
 	u32 r;
 
 	while (1) {
-		r = readw(regs + NFC_CONFIG2);
-		if (r & NFC_INT)
+		r = readw(regs + NFC_V1_V2_CONFIG2);
+		if (r & NFC_V1_V2_CONFIG2_INT)
 			break;
 	};
 
-	r &= ~NFC_INT;
+	r &= ~NFC_V1_V2_CONFIG2_INT;
 
-	writew(r, regs + NFC_CONFIG2);
+	writew(r, regs + NFC_V1_V2_CONFIG2);
 }
 
 /*
@@ -1030,8 +982,8 @@ static void __nand_boot_init noinline imx_nandboot_wait_op_done(void *regs)
  */
 static void __nand_boot_init imx_nandboot_send_cmd(void *regs, u16 cmd)
 {
-	writew(cmd, regs + NFC_FLASH_CMD);
-	writew(NFC_CMD, regs + NFC_CONFIG2);
+	writew(cmd, regs + NFC_V1_V2_FLASH_CMD);
+	writew(NFC_CMD, regs + NFC_V1_V2_CONFIG2);
 
 	imx_nandboot_wait_op_done(regs);
 }
@@ -1046,8 +998,8 @@ static void __nand_boot_init imx_nandboot_send_cmd(void *regs, u16 cmd)
  */
 static void __nand_boot_init noinline imx_nandboot_send_addr(void *regs, u16 addr)
 {
-	writew(addr, regs + NFC_FLASH_ADDR);
-	writew(NFC_ADDR, regs + NFC_CONFIG2);
+	writew(addr, regs + NFC_V1_V2_FLASH_ADDR);
+	writew(NFC_ADDR, regs + NFC_V1_V2_CONFIG2);
 
 	/* Wait for operation to complete */
 	imx_nandboot_wait_op_done(regs);
@@ -1082,9 +1034,9 @@ static void __nand_boot_init imx_nandboot_send_page(void *regs,
 
 	for (i = 0; i < bufs; i++) {
 		/* NANDFC buffer 0 is used for page read/write */
-		writew(i, regs + NFC_BUF_ADDR);
+		writew(i, regs + NFC_V1_V2_BUF_ADDR);
 
-		writew(ops, regs + NFC_CONFIG2);
+		writew(ops, regs + NFC_V1_V2_CONFIG2);
 
 		/* Wait for operation to complete */
 		imx_nandboot_wait_op_done(regs);
@@ -1164,24 +1116,24 @@ void __nand_boot_init imx_nand_load_image(void *dest, int size)
 
 	/* preset operation */
 	/* Unlock the internal RAM Buffer */
-	writew(0x2, regs + NFC_CONFIG);
+	writew(0x2, regs + NFC_V1_V2_CONFIG);
 
 	/* Unlock Block Command for given address range */
-	writew(0x4, regs + NFC_WRPROT);
+	writew(0x4, regs + NFC_V1_V2_WRPROT);
 
-	tmp = readw(regs + NFC_CONFIG1);
-	tmp |= NFC_ECC_EN;
+	tmp = readw(regs + NFC_V1_V2_CONFIG1);
+	tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
 	if (nfc_is_v21())
 		/* currently no support for 218 byte OOB with stronger ECC */
-		tmp |= NFC_ECC_MODE;
-	tmp &= ~(NFC_SP_EN | NFC_INT_MSK);
-	writew(tmp, regs + NFC_CONFIG1);
+		tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
+	tmp &= ~(NFC_V1_V2_CONFIG1_SP_EN | NFC_V1_V2_CONFIG1_INT_MSK);
+	writew(tmp, regs + NFC_V1_V2_CONFIG1);
 
 	if (nfc_is_v21()) {
 		if (pagesize_2k)
-			writew(NFC_SPAS_64, regs + NFC_SPAS);
+			writew(NFC_V2_SPAS_SPARESIZE(64), regs + NFC_V2_SPAS);
 		else
-			writew(NFC_SPAS_16, regs + NFC_SPAS);
+			writew(NFC_V2_SPAS_SPARESIZE(16), regs + NFC_V2_SPAS);
 	}
 
 	block = page = 0;
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 08/13] mxc_nand: fix correct_data function
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (6 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 07/13] imx nand: add V1_V2 namespace to registers Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-11  5:25   ` Baruch Siach
  2010-11-10 14:53 ` [PATCH 09/13] imx nand: move initialization to preset function Sascha Hauer
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

The v2 controller has a totally different mechanism to check
whether the data we read had ecc errors or not. Implement this.
The mechanism in the v2 controller happens to be identical to
the v3 controller.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c |   44 +++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 99f6714..214f391 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -104,6 +104,7 @@ struct imx_nand_host {
 	uint8_t			*data_buf;
 	unsigned int		buf_start;
 	int			spare_len;
+	int			eccsize;
 
 	void			(*preset)(struct mtd_info *);
 	void			(*send_cmd)(struct imx_nand_host *, uint16_t);
@@ -363,7 +364,7 @@ static void imx_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 	 */
 }
 
-static int imx_nand_correct_data(struct mtd_info *mtd, u_char * dat,
+static int imx_nand_correct_data_v1(struct mtd_info *mtd, u_char * dat,
 				 u_char * read_ecc, u_char * calc_ecc)
 {
 	struct nand_chip *nand_chip = mtd->priv;
@@ -385,6 +386,40 @@ static int imx_nand_correct_data(struct mtd_info *mtd, u_char * dat,
 	return 0;
 }
 
+static int imx_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
+				u_char *read_ecc, u_char *calc_ecc)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct imx_nand_host *host = nand_chip->priv;
+	u32 ecc_stat, err;
+	int no_subpages = 1;
+	int ret = 0;
+	u8 ecc_bit_mask, err_limit;
+
+	ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
+	err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
+
+	no_subpages = mtd->writesize >> 9;
+
+	ecc_stat = readl(host->regs + NFC_V2_ECC_STATUS_RESULT1);
+
+	do {
+		err = ecc_stat & ecc_bit_mask;
+		if (err > err_limit) {
+			printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
+			return -1;
+		} else {
+			ret += err;
+		}
+		ecc_stat >>= 4;
+	} while (--no_subpages);
+
+	mtd->ecc_stats.corrected += ret;
+	pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
+
+	return ret;
+}
+
 static int imx_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
 				  u_char * ecc_code)
 {
@@ -818,12 +853,14 @@ static int __init imxnd_probe(struct device_d *dev)
 		host->regs = host->base + 0x1e00;
 		host->spare0 = host->base + 0x1000;
 		host->spare_len = 64;
+		host->eccsize = 1;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
 	} else if (nfc_is_v1()) {
 		host->regs = host->base + 0xe00;
 		host->spare0 = host->base + 0x800;
 		host->spare_len = 16;
+		host->eccsize = 4;
 		oob_smallpage = &nandv1_hw_eccoob_smallpage;
 		oob_largepage = &nandv1_hw_eccoob_largepage;
 	}
@@ -865,7 +902,10 @@ static int __init imxnd_probe(struct device_d *dev)
 	if (pdata->hw_ecc) {
 		this->ecc.calculate = imx_nand_calculate_ecc;
 		this->ecc.hwctl = imx_nand_enable_hwecc;
-		this->ecc.correct = imx_nand_correct_data;
+		if (nfc_is_v1())
+			this->ecc.correct = imx_nand_correct_data_v1;
+		else
+			this->ecc.correct = imx_nand_correct_data_v2_v3;
 		this->ecc.mode = NAND_ECC_HW;
 		this->ecc.size = 512;
 		tmp = readw(host->regs + NFC_V1_V2_CONFIG1);
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 09/13] imx nand: move initialization to preset function
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (7 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 08/13] mxc_nand: fix correct_data function Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 10/13] imx nand: introduce overwritable check_int function Sascha Hauer
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

This has two purposes. First we need to factor out initialization
to be able to do something different on v3 type controllers,
second with this patch we are independent of preinitialized register
values.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c |  110 +++++++++++++++++++++++++++---------------
 1 files changed, 71 insertions(+), 39 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 214f391..b3191a7 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -64,6 +64,8 @@
 #define NFC_V1_V2_CONFIG1_RST		(1 << 6)
 #define NFC_V1_V2_CONFIG1_CE		(1 << 7)
 #define NFC_V1_V2_CONFIG1_ONE_CYCLE	(1 << 8)
+#define NFC_V2_CONFIG1_PPB(x)		(((x) & 0x3) << 9)
+#define NFC_V2_CONFIG1_FP_INT		(1 << 11)
 
 #define NFC_V1_V2_CONFIG2_INT		(1 << 15)
 
@@ -640,6 +642,67 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 }
 
 /*
+ * v2 and v3 type controllers can do 4bit or 8bit ecc depending
+ * on how much oob the nand chip has. For 8bit ecc we need at least
+ * 26 bytes of oob data per 512 byte block.
+ */
+static int get_eccsize(struct mtd_info *mtd)
+{
+	int oobbytes_per_512 = 0;
+
+	oobbytes_per_512 = mtd->oobsize * 512 / mtd->writesize;
+
+	if (oobbytes_per_512 < 26)
+		return 4;
+	else
+		return 8;
+}
+
+static void preset_v1_v2(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct imx_nand_host *host = nand_chip->priv;
+	uint16_t config1 = 0;
+
+	if (nand_chip->ecc.mode == NAND_ECC_HW)
+		config1 |= NFC_V1_V2_CONFIG1_ECC_EN;
+
+	if (nfc_is_v21())
+		config1 |= NFC_V2_CONFIG1_FP_INT;
+
+	if (nfc_is_v21() && mtd->writesize) {
+		uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
+
+		host->eccsize = get_eccsize(mtd);
+		if (host->eccsize == 4)
+			config1 |= NFC_V2_CONFIG1_ECC_MODE_4;
+
+		config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6);
+	} else {
+		host->eccsize = 1;
+	}
+
+	writew(config1, host->regs + NFC_V1_V2_CONFIG1);
+	/* preset operation */
+
+	/* Unlock the internal RAM Buffer */
+	writew(0x2, host->regs + NFC_V1_V2_CONFIG);
+
+	/* Blocks to be unlocked */
+	if (nfc_is_v21()) {
+		writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
+		writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
+	} else if (nfc_is_v1()) {
+		writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
+		writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
+	} else
+		BUG();
+
+	/* Unlock Block Command for given address range */
+	writew(0x4, host->regs + NFC_V1_V2_WRPROT);
+}
+
+/*
  * This function is used by the upper layer to write command to NAND Flash for
  * different operations to be carried out on NAND Flash
  *
@@ -667,6 +730,10 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command,
 	 * Command pre-processing step
 	 */
 	switch (command) {
+	case NAND_CMD_RESET:
+		host->preset(mtd);
+		host->send_cmd(host, command);
+		break;
 
 	case NAND_CMD_STATUS:
 		host->buf_start = 0;
@@ -745,7 +812,6 @@ static void imx_nand_command(struct mtd_info *mtd, unsigned command,
 
 	case NAND_CMD_ERASE1:
 	case NAND_CMD_ERASE2:
-	case NAND_CMD_RESET:
 		host->send_cmd(host, command);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
@@ -821,7 +887,6 @@ static int __init imxnd_probe(struct device_d *dev)
 	struct imx_nand_platform_data *pdata = dev->platform_data;
 	struct imx_nand_host *host;
 	struct nand_ecclayout *oob_smallpage, *oob_largepage;
-	u16 tmp;
 	int err = 0;
 
 #ifdef CONFIG_ARCH_IMX27
@@ -842,6 +907,7 @@ static int __init imxnd_probe(struct device_d *dev)
 	host->main_area0 = host->base;
 
 	if (nfc_is_v1() || nfc_is_v21()) {
+		host->preset = preset_v1_v2;
 		host->send_cmd = send_cmd_v1_v2;
 		host->send_addr = send_addr_v1_v2;
 		host->send_page = send_page_v1_v2;
@@ -853,14 +919,12 @@ static int __init imxnd_probe(struct device_d *dev)
 		host->regs = host->base + 0x1e00;
 		host->spare0 = host->base + 0x1000;
 		host->spare_len = 64;
-		host->eccsize = 1;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
 	} else if (nfc_is_v1()) {
 		host->regs = host->base + 0xe00;
 		host->spare0 = host->base + 0x800;
 		host->spare_len = 16;
-		host->eccsize = 4;
 		oob_smallpage = &nandv1_hw_eccoob_smallpage;
 		oob_largepage = &nandv1_hw_eccoob_largepage;
 	}
@@ -891,14 +955,6 @@ static int __init imxnd_probe(struct device_d *dev)
 	clk_enable(host->clk);
 #endif
 
-	tmp = readw(host->regs + NFC_V1_V2_CONFIG1);
-	tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
-	tmp &= ~NFC_V1_V2_CONFIG1_SP_EN;
-	if (nfc_is_v21())
-		/* currently no support for 218 byte OOB with stronger ECC */
-		tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
-	writew(tmp, host->regs + NFC_V1_V2_CONFIG1);
-
 	if (pdata->hw_ecc) {
 		this->ecc.calculate = imx_nand_calculate_ecc;
 		this->ecc.hwctl = imx_nand_enable_hwecc;
@@ -908,38 +964,11 @@ static int __init imxnd_probe(struct device_d *dev)
 			this->ecc.correct = imx_nand_correct_data_v2_v3;
 		this->ecc.mode = NAND_ECC_HW;
 		this->ecc.size = 512;
-		tmp = readw(host->regs + NFC_V1_V2_CONFIG1);
-		tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
-		writew(tmp, host->regs + NFC_V1_V2_CONFIG1);
 	} else {
 		this->ecc.size = 512;
 		this->ecc.mode = NAND_ECC_SOFT;
-		tmp = readw(host->regs + NFC_V1_V2_CONFIG1);
-		tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN;
-		writew(tmp, host->regs + NFC_V1_V2_CONFIG1);
 	}
 
-	/* Reset NAND */
-	this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
-
-	/* preset operation */
-	/* Unlock the internal RAM Buffer */
-	writew(0x2, host->regs + NFC_V1_V2_CONFIG);
-
-	/* Blocks to be unlocked */
-	if (nfc_is_v21()) {
-		writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
-		writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
-		this->ecc.bytes = 9;
-	} else if (nfc_is_v1()) {
-		writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
-		writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
-		this->ecc.bytes = 3;
-	}
-
-	/* Unlock Block Command for given address range */
-	writew(0x4, host->regs + NFC_V1_V2_WRPROT);
-
 	this->ecc.layout = oob_smallpage;
 
 	/* NAND bus width determines access funtions used by upper layer */
@@ -962,6 +991,9 @@ static int __init imxnd_probe(struct device_d *dev)
 		goto escan;
 	}
 
+	/* Call preset again, with correct writesize this time */
+	host->preset(mtd);
+
 	imx_nand_set_layout(mtd->writesize, pdata->width == 2 ? 16 : 8);
 
 	if (mtd->writesize == 2048) {
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 10/13] imx nand: introduce overwritable check_int function
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (8 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 09/13] imx nand: move initialization to preset function Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 11/13] imx nand: Add v3 (i.MX51) support Sascha Hauer
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

needed for v3 support later.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c |   29 ++++++++++++++++-------------
 1 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index b3191a7..9e2ba32 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -114,6 +114,7 @@ struct imx_nand_host {
 	void			(*send_page)(struct imx_nand_host *, unsigned int);
 	void			(*send_read_id)(struct imx_nand_host *);
 	uint16_t		(*get_dev_status)(struct imx_nand_host *);
+	int			(*check_int)(struct imx_nand_host *);
 };
 
 /*
@@ -175,16 +176,21 @@ static void memcpy32(void *trg, const void *src, int size)
 		*t++ = *s++;
 }
 
-/*
- * This function polls the NANDFC to wait for the basic operation to complete by
- * checking the INT bit of config2 register.
- *
- * @param       max_retries     number of retry attempts (separated by 1 us)
- * @param       param           parameter for debug
- */
+static int check_int_v1_v2(struct imx_nand_host *host)
+{
+	uint32_t tmp;
+
+	tmp = readw(host->regs + NFC_V1_V2_CONFIG2);
+	if (!(tmp & NFC_V1_V2_CONFIG2_INT))
+		return 0;
+
+	writew(tmp & ~NFC_V1_V2_CONFIG2_INT, host->regs + NFC_V1_V2_CONFIG2);
+
+	return 1;
+}
+
 static void wait_op_done(struct imx_nand_host *host)
 {
-	u32 tmp;
 	int i;
 
 	/* This is a timeout of roughly 15ms on my system. We
@@ -192,12 +198,8 @@ static void wait_op_done(struct imx_nand_host *host)
 	 * here as we might be here from nand booting.
 	 */
 	for (i = 0; i < 100000; i++) {
-		if (readw(host->regs + NFC_V1_V2_CONFIG2) & NFC_V1_V2_CONFIG2_INT) {
-			tmp = readw(host->regs + NFC_V1_V2_CONFIG2);
-			tmp  &= ~NFC_V1_V2_CONFIG2_INT;
-			writew(tmp, host->regs + NFC_V1_V2_CONFIG2);
+		if (host->check_int(host))
 			return;
-		}
 	}
 }
 
@@ -913,6 +915,7 @@ static int __init imxnd_probe(struct device_d *dev)
 		host->send_page = send_page_v1_v2;
 		host->send_read_id = send_read_id_v1_v2;
 		host->get_dev_status = get_dev_status_v1_v2;
+		host->check_int = check_int_v1_v2;
 	}
 
 	if (nfc_is_v21()) {
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 11/13] imx nand: Add v3 (i.MX51) support
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (9 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 10/13] imx nand: introduce overwritable check_int function Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 12/13] fb: set id for framebuffer device correctly Sascha Hauer
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/include/mach/imx51-regs.h |    2 +
 arch/arm/mach-imx/nand.c                    |    9 ++
 drivers/mtd/nand/Kconfig                    |    4 +-
 drivers/mtd/nand/nand_imx.c                 |  208 ++++++++++++++++++++++++++-
 4 files changed, 220 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-imx/include/mach/imx51-regs.h b/arch/arm/mach-imx/include/mach/imx51-regs.h
index 1d241c8..2e6cacb 100644
--- a/arch/arm/mach-imx/include/mach/imx51-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx51-regs.h
@@ -104,6 +104,8 @@
 #define MX51_HSI2C_DMA_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x00038000)
 #define MX51_SPBA_CTRL_BASE_ADDR	(MX51_SPBA0_BASE_ADDR + 0x0003C000)
 
+#define MX51_NFC_AXI_BASE_ADDR	0xcfff0000
+
 /*
  * Memory regions and CS
  */
diff --git a/arch/arm/mach-imx/nand.c b/arch/arm/mach-imx/nand.c
index c228f96..c52b8b0 100644
--- a/arch/arm/mach-imx/nand.c
+++ b/arch/arm/mach-imx/nand.c
@@ -95,6 +95,15 @@ void imx_nand_set_layout(int writesize, int datawidth)
 	FMCR = fmcr;
 }
 
+#elif defined CONFIG_ARCH_IMX51
+
+void imx_nand_set_layout(int writesize, int datawidth)
+{
+	/* Just silence the compiler warning below. On i.MX51 we don't
+	 * have external boot.
+	 */
+}
+
 #else
 #warning using empty imx_nand_set_layout(). NAND flash will not work properly if not booting from it
 
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index bc95195..034bb6f 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -11,12 +11,12 @@ if NAND
 config NAND_IMX
 	bool
 	prompt "i.MX NAND driver"
-	depends on ARCH_IMX21 || ARCH_IMX27 || ARCH_IMX31 || ARCH_IMX35 || ARCH_IMX25
+	depends on ARCH_IMX21 || ARCH_IMX27 || ARCH_IMX31 || ARCH_IMX35 || ARCH_IMX25 || ARCH_IMX51
 
 config NAND_IMX_BOOT
 	bool
 	prompt "Support Starting barebox from NAND"
-	depends on NAND_IMX || NAND_IMX_V2
+	depends on NAND_IMX && !ARCH_IMX51
 
 choice
 	depends on NAND_IMX_BOOT
diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 9e2ba32..9a15ab2 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -32,6 +32,8 @@
 
 #define nfc_is_v21()		(cpu_is_mx25() || cpu_is_mx35())
 #define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
+#define nfc_is_v3_2()		cpu_is_mx51()
+#define nfc_is_v3()		nfc_is_v3_2()
 
 #define NFC_V1_ECC_STATUS_RESULT	0x0c
 #define NFC_V1_RSLTMAIN_AREA		0x0e
@@ -82,6 +84,54 @@
 #define NFC_ID				(1 << 4)
 #define NFC_STATUS			(1 << 5)
 
+#define NFC_V3_FLASH_CMD		(host->regs_axi + 0x00)
+#define NFC_V3_FLASH_ADDR0		(host->regs_axi + 0x04)
+
+#define NFC_V3_CONFIG1			(host->regs_axi + 0x34)
+#define NFC_V3_CONFIG1_SP_EN		(1 << 0)
+#define NFC_V3_CONFIG1_RBA(x)		(((x) & 0x7 ) << 4)
+
+#define NFC_V3_ECC_STATUS_RESULT	(host->regs_axi + 0x38)
+
+#define NFC_V3_LAUNCH			(host->regs_axi + 0x40)
+
+#define NFC_V3_WRPROT			(host->regs_ip + 0x0)
+#define NFC_V3_WRPROT_LOCK_TIGHT	(1 << 0)
+#define NFC_V3_WRPROT_LOCK		(1 << 1)
+#define NFC_V3_WRPROT_UNLOCK		(1 << 2)
+#define NFC_V3_WRPROT_BLS_UNLOCK	(2 << 6)
+
+#define NFC_V3_WRPROT_UNLOCK_BLK_ADD0   (host->regs_ip + 0x04)
+
+#define NFC_V3_CONFIG2			(host->regs_ip + 0x24)
+#define NFC_V3_CONFIG2_PS_512			(0 << 0)
+#define NFC_V3_CONFIG2_PS_2048			(1 << 0)
+#define NFC_V3_CONFIG2_PS_4096			(2 << 0)
+#define NFC_V3_CONFIG2_ONE_CYCLE		(1 << 2)
+#define NFC_V3_CONFIG2_ECC_EN			(1 << 3)
+#define NFC_V3_CONFIG2_2CMD_PHASES		(1 << 4)
+#define NFC_V3_CONFIG2_NUM_ADDR_PHASE0		(1 << 5)
+#define NFC_V3_CONFIG2_ECC_MODE_8		(1 << 6)
+#define NFC_V3_CONFIG2_PPB(x)			(((x) & 0x3) << 7)
+#define NFC_V3_CONFIG2_NUM_ADDR_PHASE1(x)	(((x) & 0x3) << 12)
+#define NFC_V3_CONFIG2_INT_MSK			(1 << 15)
+#define NFC_V3_CONFIG2_ST_CMD(x)		(((x) & 0xff) << 24)
+#define NFC_V3_CONFIG2_SPAS(x)			(((x) & 0xff) << 16)
+
+#define NFC_V3_CONFIG3				(host->regs_ip + 0x28)
+#define NFC_V3_CONFIG3_ADD_OP(x)		(((x) & 0x3) << 0)
+#define NFC_V3_CONFIG3_FW8			(1 << 3)
+#define NFC_V3_CONFIG3_SBB(x)			(((x) & 0x7) << 8)
+#define NFC_V3_CONFIG3_NUM_OF_DEVICES(x)	(((x) & 0x7) << 12)
+#define NFC_V3_CONFIG3_RBB_MODE			(1 << 15)
+#define NFC_V3_CONFIG3_NO_SDMA			(1 << 20)
+
+#define NFC_V3_IPC			(host->regs_ip + 0x2C)
+#define NFC_V3_IPC_CREQ			(1 << 0)
+#define NFC_V3_IPC_INT			(1 << 31)
+
+#define NFC_V3_DELAY_LINE		(host->regs_ip + 0x34)
+
 #ifdef CONFIG_NAND_IMX_BOOT
 #define __nand_boot_init __bare_init
 #else
@@ -99,6 +149,8 @@ struct imx_nand_host {
 
 	void __iomem		*base;
 	void __iomem		*regs;
+	void __iomem		*regs_axi;
+	void __iomem		*regs_ip;
 	int			status_request;
 	struct clk		*clk;
 
@@ -176,6 +228,20 @@ static void memcpy32(void *trg, const void *src, int size)
 		*t++ = *s++;
 }
 
+static int check_int_v3(struct imx_nand_host *host)
+{
+	uint32_t tmp;
+
+	tmp = readl(NFC_V3_IPC);
+	if (!(tmp & NFC_V3_IPC_INT))
+		return 0;
+
+	tmp &= ~NFC_V3_IPC_INT;
+	writel(tmp, NFC_V3_IPC);
+
+	return 1;
+}
+
 static int check_int_v1_v2(struct imx_nand_host *host)
 {
 	uint32_t tmp;
@@ -209,6 +275,18 @@ static void wait_op_done(struct imx_nand_host *host)
  *
  * @param       cmd     command for NAND Flash
  */
+static void send_cmd_v3(struct imx_nand_host *host, uint16_t cmd)
+{
+	/* fill command */
+	writel(cmd, NFC_V3_FLASH_CMD);
+
+	/* send out command */
+	writel(NFC_CMD, NFC_V3_LAUNCH);
+
+	/* Wait for operation to complete */
+	wait_op_done(host);
+}
+
 static void send_cmd_v1_v2(struct imx_nand_host *host, u16 cmd)
 {
 	MTD_DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x)\n", cmd);
@@ -238,6 +316,17 @@ static void send_cmd_v1_v2(struct imx_nand_host *host, u16 cmd)
  * @param       addr    address to be written to NFC.
  * @param       islast  True if this is the last address cycle for command
  */
+static void send_addr_v3(struct imx_nand_host *host, uint16_t addr)
+{
+	/* fill address */
+	writel(addr, NFC_V3_FLASH_ADDR0);
+
+	/* send out address */
+	writel(NFC_ADDR, NFC_V3_LAUNCH);
+
+	wait_op_done(host);
+}
+
 static void send_addr_v1_v2(struct imx_nand_host *host, u16 addr)
 {
 	MTD_DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
@@ -256,6 +345,20 @@ static void send_addr_v1_v2(struct imx_nand_host *host, u16 addr)
  * @param	buf_id	      Specify Internal RAM Buffer number (0-3)
  * @param       spare_only    set true if only the spare area is transferred
  */
+static void send_page_v3(struct imx_nand_host *host, unsigned int ops)
+{
+	uint32_t tmp;
+
+	tmp = readl(NFC_V3_CONFIG1);
+	tmp &= ~(7 << 4);
+	writel(tmp, NFC_V3_CONFIG1);
+
+	/* transfer data from NFC ram to nand */
+	writel(ops, NFC_V3_LAUNCH);
+
+	wait_op_done(host);
+}
+
 static void send_page_v1_v2(struct imx_nand_host *host,
 		unsigned int ops)
 {
@@ -281,6 +384,16 @@ static void send_page_v1_v2(struct imx_nand_host *host,
  * This function requests the NANDFC to perform a read of the
  * NAND device ID.
  */
+static void send_read_id_v3(struct imx_nand_host *host)
+{
+	/* Read ID into main buffer */
+	writel(NFC_ID, NFC_V3_LAUNCH);
+
+	wait_op_done(host);
+
+	memcpy(host->data_buf, host->main_area0, 16);
+}
+
 static void send_read_id_v1_v2(struct imx_nand_host *host)
 {
 	struct nand_chip *this = &host->nand;
@@ -315,6 +428,14 @@ static void send_read_id_v1_v2(struct imx_nand_host *host)
  *
  * @return  device status
  */
+static uint16_t get_dev_status_v3(struct imx_nand_host *host)
+{
+	writew(NFC_STATUS, NFC_V3_LAUNCH);
+	wait_op_done(host);
+
+	return readl(NFC_V3_CONFIG1) >> 16;
+}
+
 static u16 get_dev_status_v1_v2(struct imx_nand_host *host)
 {
 	void *main_buf = host->main_area0;
@@ -405,7 +526,10 @@ static int imx_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
 
 	no_subpages = mtd->writesize >> 9;
 
-	ecc_stat = readl(host->regs + NFC_V2_ECC_STATUS_RESULT1);
+	if (nfc_is_v21())
+		ecc_stat = readl(host->regs + NFC_V2_ECC_STATUS_RESULT1);
+	else
+		ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT);
 
 	do {
 		err = ecc_stat & ecc_bit_mask;
@@ -704,6 +828,72 @@ static void preset_v1_v2(struct mtd_info *mtd)
 	writew(0x4, host->regs + NFC_V1_V2_WRPROT);
 }
 
+static void preset_v3(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct imx_nand_host *host = chip->priv;
+	uint32_t config2, config3;
+	int i, addr_phases;
+
+	writel(NFC_V3_CONFIG1_RBA(0), NFC_V3_CONFIG1);
+	writel(NFC_V3_IPC_CREQ, NFC_V3_IPC);
+
+	/* Unlock the internal RAM Buffer */
+	writel(NFC_V3_WRPROT_BLS_UNLOCK | NFC_V3_WRPROT_UNLOCK,
+			NFC_V3_WRPROT);
+
+	/* Blocks to be unlocked */
+	for (i = 0; i < NAND_MAX_CHIPS; i++)
+		writel(0x0 | (0xffff << 16),
+				NFC_V3_WRPROT_UNLOCK_BLK_ADD0 + (i << 2));
+
+	writel(0, NFC_V3_IPC);
+
+	config2 = NFC_V3_CONFIG2_ONE_CYCLE |
+		NFC_V3_CONFIG2_2CMD_PHASES |
+		NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
+		NFC_V3_CONFIG2_ST_CMD(0x70) |
+		NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
+
+	if (chip->ecc.mode == NAND_ECC_HW)
+		config2 |= NFC_V3_CONFIG2_ECC_EN;
+
+	addr_phases = fls(chip->pagemask) >> 3;
+
+	if (mtd->writesize == 2048) {
+		config2 |= NFC_V3_CONFIG2_PS_2048;
+		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
+	} else if (mtd->writesize == 4096) {
+		config2 |= NFC_V3_CONFIG2_PS_4096;
+		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases);
+	} else {
+		config2 |= NFC_V3_CONFIG2_PS_512;
+		config2 |= NFC_V3_CONFIG2_NUM_ADDR_PHASE1(addr_phases - 1);
+	}
+
+	if (mtd->writesize) {
+		config2 |= NFC_V3_CONFIG2_PPB(ffs(mtd->erasesize / mtd->writesize) - 6);
+		host->eccsize = get_eccsize(mtd);
+		if (host->eccsize == 8)
+			config2 |= NFC_V3_CONFIG2_ECC_MODE_8;
+	}
+
+	writel(config2, NFC_V3_CONFIG2);
+
+	config3 = NFC_V3_CONFIG3_NUM_OF_DEVICES(0) |
+			NFC_V3_CONFIG3_NO_SDMA |
+			NFC_V3_CONFIG3_RBB_MODE |
+			NFC_V3_CONFIG3_SBB(6) | /* Reset default */
+			NFC_V3_CONFIG3_ADD_OP(0);
+
+	if (!(chip->options & NAND_BUSWIDTH_16))
+		config3 |= NFC_V3_CONFIG3_FW8;
+
+	writel(config3, NFC_V3_CONFIG3);
+
+	writel(0, NFC_V3_DELAY_LINE);
+}
+
 /*
  * This function is used by the upper layer to write command to NAND Flash for
  * different operations to be carried out on NAND Flash
@@ -930,6 +1120,22 @@ static int __init imxnd_probe(struct device_d *dev)
 		host->spare_len = 16;
 		oob_smallpage = &nandv1_hw_eccoob_smallpage;
 		oob_largepage = &nandv1_hw_eccoob_largepage;
+	} else if (nfc_is_v3_2()) {
+#ifdef CONFIG_ARCH_IMX51
+		host->regs_ip = (void *)MX51_NFC_BASE_ADDR;
+#endif
+		host->regs_axi = host->base + 0x1e00;
+		host->spare0 = host->base + 0x1000;
+		host->spare_len = 64;
+		host->preset = preset_v3;
+		host->send_cmd = send_cmd_v3;
+		host->send_addr = send_addr_v3;
+		host->send_page = send_page_v3;
+		host->send_read_id = send_read_id_v3;
+		host->get_dev_status = get_dev_status_v3;
+		host->check_int = check_int_v3;
+		oob_smallpage = &nandv2_hw_eccoob_smallpage;
+		oob_largepage = &nandv2_hw_eccoob_largepage;
 	}
 
 	host->dev = dev;
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 12/13] fb: set id for framebuffer device correctly
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (10 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 11/13] imx nand: Add v3 (i.MX51) support Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-10 14:55   ` Sascha Hauer
  2010-11-10 14:53 ` [PATCH 13/13] ARM i.MX51: Add nand device Sascha Hauer
  2010-11-11  5:26 ` add i.MX51 Nand support Jean-Christophe PLAGNIOL-VILLARD
  13 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/video/fb.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index f9a425e..ab2c5eb 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -80,6 +80,7 @@ int register_framebuffer(struct fb_info *info)
 
 	dev = &info->dev;
 	dev->priv = info;
+	dev->id = id;
 
 	sprintf(dev->name, "fb");
 
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 13/13] ARM i.MX51: Add nand device
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (11 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 12/13] fb: set id for framebuffer device correctly Sascha Hauer
@ 2010-11-10 14:53 ` Sascha Hauer
  2010-11-11  5:26 ` add i.MX51 Nand support Jean-Christophe PLAGNIOL-VILLARD
  13 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:53 UTC (permalink / raw)
  To: barebox

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/include/mach/devices-imx51.h |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-imx/include/mach/devices-imx51.h b/arch/arm/mach-imx/include/mach/devices-imx51.h
index ff63fca..ae85318 100644
--- a/arch/arm/mach-imx/include/mach/devices-imx51.h
+++ b/arch/arm/mach-imx/include/mach/devices-imx51.h
@@ -51,3 +51,8 @@ static inline struct device_d *imx51_add_mmc1(void *pdata)
 	return imx_add_mmc((void *)MX51_MMC_SDHC2_BASE_ADDR, 0, pdata);
 }
 
+static inline struct device_d *imx51_add_nand(struct imx_nand_platform_data *pdata)
+{
+	return imx_add_nand((void *)MX51_NFC_AXI_BASE_ADDR, pdata);
+}
+
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 12/13] fb: set id for framebuffer device correctly
  2010-11-10 14:53 ` [PATCH 12/13] fb: set id for framebuffer device correctly Sascha Hauer
@ 2010-11-10 14:55   ` Sascha Hauer
  0 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2010-11-10 14:55 UTC (permalink / raw)
  To: barebox

On Wed, Nov 10, 2010 at 03:53:58PM +0100, Sascha Hauer wrote:
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  drivers/video/fb.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/video/fb.c b/drivers/video/fb.c
> index f9a425e..ab2c5eb 100644
> --- a/drivers/video/fb.c
> +++ b/drivers/video/fb.c
> @@ -80,6 +80,7 @@ int register_framebuffer(struct fb_info *info)
>  
>  	dev = &info->dev;
>  	dev->priv = info;
> +	dev->id = id;
>  
>  	sprintf(dev->name, "fb");
>

This patch is unrelated to this series and got in here accidently.
Anyway, it is correct and should go to master.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 08/13] mxc_nand: fix correct_data function
  2010-11-10 14:53 ` [PATCH 08/13] mxc_nand: fix correct_data function Sascha Hauer
@ 2010-11-11  5:25   ` Baruch Siach
  2010-11-11 10:32     ` Sascha Hauer
  0 siblings, 1 reply; 19+ messages in thread
From: Baruch Siach @ 2010-11-11  5:25 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Hi Sascha,

On Wed, Nov 10, 2010 at 03:53:54PM +0100, Sascha Hauer wrote:
> The v2 controller has a totally different mechanism to check
> whether the data we read had ecc errors or not. Implement this.
> The mechanism in the v2 controller happens to be identical to
> the v3 controller.

Does this mean that the current .correct method in not compatible with v2 
controllers? If so, does this bug makes any read error look like an 
uncorrectable error? Something else (silent corruption)?

baruch

-- 
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch@tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: add i.MX51 Nand support
  2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
                   ` (12 preceding siblings ...)
  2010-11-10 14:53 ` [PATCH 13/13] ARM i.MX51: Add nand device Sascha Hauer
@ 2010-11-11  5:26 ` Jean-Christophe PLAGNIOL-VILLARD
  13 siblings, 0 replies; 19+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2010-11-11  5:26 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On 15:53 Wed 10 Nov     , Sascha Hauer wrote:
> Hi all,
> 
> The following series is a respin of the series adding i.MX51 Nand support
> to the kernel for barebox.
> 
> The series reveals to problems in barebox. First the i.MX51 Nand controller
> needs two memory resources. Since I know that Jean-Christophe recently
> worked on adding resources to barebox I decided for a hack in the driver
> for now: I just hardcoded the second base address. Second the current
> implementation of dma_alloc_coherent stinks. The implementation simply
> maps the whole SDRAM a second time uncached. This way we can use the
> normal malloc function to allocate dma coherent memory and just add
> a known offset to the returned pointer. On i.MX51 boards with 512MB SDRAM
> we do not have enough space in the memory map to map the SDRAM twice, in
> my case the mapping shadowed the Nand register space. Be aware of this
> when you try to add Nand support to your i.MX51 board and use the babbage
> code as a template.
I'll try to push the code today for the ressource
because as for the i.MX51 I need multiple ressource for sh4 for USB as example

Best Regards,
J.

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* Re: [PATCH 08/13] mxc_nand: fix correct_data function
  2010-11-11  5:25   ` Baruch Siach
@ 2010-11-11 10:32     ` Sascha Hauer
  2010-11-15 12:08       ` [PATCH] " Baruch Siach
  0 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2010-11-11 10:32 UTC (permalink / raw)
  To: Baruch Siach; +Cc: barebox

Hi Baruch,

On Thu, Nov 11, 2010 at 07:25:49AM +0200, Baruch Siach wrote:
> Hi Sascha,
> 
> On Wed, Nov 10, 2010 at 03:53:54PM +0100, Sascha Hauer wrote:
> > The v2 controller has a totally different mechanism to check
> > whether the data we read had ecc errors or not. Implement this.
> > The mechanism in the v2 controller happens to be identical to
> > the v3 controller.
> 
> Does this mean that the current .correct method in not compatible with v2 
> controllers? If so, does this bug makes any read error look like an 
> uncorrectable error? Something else (silent corruption)?

I'm afraid it's silent corruption. As I see it good crc sums can be
detected as bad crc sums and bad crc sums can be detected as good crc
sums if the v1 implementation is used instead of v2.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH] mxc_nand: fix correct_data function
  2010-11-11 10:32     ` Sascha Hauer
@ 2010-11-15 12:08       ` Baruch Siach
  0 siblings, 0 replies; 19+ messages in thread
From: Baruch Siach @ 2010-11-15 12:08 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

From: Sascha Hauer <s.hauer@pengutronix.de>

Commit da1ad19 upstream.

The v2 controller has a totally different mechanism to check
whether the data we read had ecc errors or not. Implement this.
The mechanism in the v2 controller happens to be identical to
the v3 controller.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
---
Hi Sascha,

This should apply cleanly on v2010.09.0, v2010.10.0, and v2010.11.0. I tested 
this on v2010.09.0 with i.MX25 (not the actual correction algorithm, just 
verified that it doesn't break anything).  Please consider using this for a 
stable release.

 drivers/mtd/nand/nand_imx.c |   73 ++++++++++++++++++++++++++++++++++---------
 1 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 5454e32..8bfa2ba 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -43,10 +43,15 @@
 #define NFC_FLASH_ADDR		0xE06
 #define NFC_FLASH_CMD		0xE08
 #define NFC_CONFIG		0xE0A
-#define NFC_ECC_STATUS_RESULT	0xE0C
-#define NFC_RSLTMAIN_AREA	0xE0E
-#define NFC_RSLTSPARE_AREA	0xE10
-#define NFC_SPAS		0xe10
+
+#define NFC_V1_ECC_STATUS_RESULT	0xE0C
+#define NFC_V1_RSLTMAIN_AREA		0xE0E
+#define NFC_V1_RSLTSPARE_AREA		0xE10
+
+#define NFC_V2_ECC_STATUS_RESULT1       0xE0C
+#define NFC_V2_ECC_STATUS_RESULT2       0xE0E
+#define NFC_V2_SPAS                     0xE10
+
 #define NFC_WRPROT		0xE12
 #define NFC_V1_UNLOCKSTART_BLKADDR	0xe14
 #define NFC_V1_UNLOCKEND_BLKADDR	0xe16
@@ -153,6 +158,7 @@ struct imx_nand_host {
 	uint8_t			*data_buf;
 	unsigned int		buf_start;
 	int			spare_len;
+	int			eccsize;
 
 };
 
@@ -416,7 +422,7 @@ static void imx_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 	 */
 }
 
-static int imx_nand_correct_data(struct mtd_info *mtd, u_char * dat,
+static int imx_nand_correct_data_v1(struct mtd_info *mtd, u_char * dat,
 				 u_char * read_ecc, u_char * calc_ecc)
 {
 	struct nand_chip *nand_chip = mtd->priv;
@@ -427,7 +433,7 @@ static int imx_nand_correct_data(struct mtd_info *mtd, u_char * dat,
 	 * additional correction.  2-Bit errors cannot be corrected by
 	 * HW ECC, so we need to return failure
 	 */
-	u16 ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT);
+	u16 ecc_status = readw(host->regs + NFC_V1_ECC_STATUS_RESULT);
 
 	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
 		MTD_DEBUG(MTD_DEBUG_LEVEL0,
@@ -438,6 +444,38 @@ static int imx_nand_correct_data(struct mtd_info *mtd, u_char * dat,
 	return 0;
 }
 
+static int imx_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
+				u_char *read_ecc, u_char *calc_ecc)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct imx_nand_host *host = nand_chip->priv;
+	u32 ecc_stat, err;
+	int no_subpages = mtd->writesize >> 9;
+	int ret = 0;
+	u8 ecc_bit_mask, err_limit;
+
+	ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf;
+	err_limit = (host->eccsize == 4) ? 0x4 : 0x8;
+
+	ecc_stat = readl(host->regs + NFC_V2_ECC_STATUS_RESULT1);
+
+	do {
+		err = ecc_stat & ecc_bit_mask;
+		if (err > err_limit) {
+			printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
+			return -1;
+		} else {
+			ret += err;
+		}
+		ecc_stat >>= 4;
+	} while (--no_subpages);
+
+	mtd->ecc_stats.corrected += ret;
+	pr_debug("%d Symbol Correctable RS-ECC Error\n", ret);
+
+	return ret;
+}
+
 static int imx_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
 				  u_char * ecc_code)
 {
@@ -864,12 +902,14 @@ static int __init imxnd_probe(struct device_d *dev)
 		host->regs = host->base + 0x1000;
 		host->spare0 = host->base + 0x1000;
 		host->spare_len = 64;
+		host->eccsize = 1;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
 	} else if (nfc_is_v1()) {
 		host->regs = host->base;
 		host->spare0 = host->base + 0x800;
 		host->spare_len = 16;
+		host->eccsize = 4;
 		oob_smallpage = &nandv1_hw_eccoob_smallpage;
 		oob_largepage = &nandv1_hw_eccoob_largepage;
 	}
@@ -911,7 +951,10 @@ static int __init imxnd_probe(struct device_d *dev)
 	if (pdata->hw_ecc) {
 		this->ecc.calculate = imx_nand_calculate_ecc;
 		this->ecc.hwctl = imx_nand_enable_hwecc;
-		this->ecc.correct = imx_nand_correct_data;
+		if (nfc_is_v1())
+			this->ecc.correct = imx_nand_correct_data_v1;
+		else
+			this->ecc.correct = imx_nand_correct_data_v2_v3;
 		this->ecc.mode = NAND_ECC_HW;
 		this->ecc.size = 512;
 		tmp = readw(host->regs + NFC_CONFIG1);
@@ -974,17 +1017,17 @@ static int __init imxnd_probe(struct device_d *dev)
 		this->ecc.layout = oob_largepage;
 		host->pagesize_2k = 1;
 		if (nfc_is_v21()) {
-			tmp = readw(host->regs + NFC_SPAS);
+			tmp = readw(host->regs + NFC_V2_SPAS);
 			tmp &= 0xff00;
 			tmp |= NFC_SPAS_64;
-			writew(tmp, host->regs + NFC_SPAS);
+			writew(tmp, host->regs + NFC_V2_SPAS);
 		}
 	} else {
 		if (nfc_is_v21()) {
-			tmp = readw(host->regs + NFC_SPAS);
+			tmp = readw(host->regs + NFC_V2_SPAS);
 			tmp &= 0xff00;
 			tmp |= NFC_SPAS_16;
-			writew(tmp, host->regs + NFC_SPAS);
+			writew(tmp, host->regs + NFC_V2_SPAS);
 		}
 	}
 
@@ -1109,15 +1152,15 @@ void __nand_boot_init imx_nand_load_image(void *dest, int size)
 
 	if (nfc_is_v21()) {
 		if (host.pagesize_2k) {
-			tmp = readw(host.regs + NFC_SPAS);
+			tmp = readw(host.regs + NFC_V2_SPAS);
 			tmp &= 0xff00;
 			tmp |= NFC_SPAS_64;
-			writew(tmp, host.regs + NFC_SPAS);
+			writew(tmp, host.regs + NFC_V2_SPAS);
 		} else {
-			tmp = readw(host.regs + NFC_SPAS);
+			tmp = readw(host.regs + NFC_V2_SPAS);
 			tmp &= 0xff00;
 			tmp |= NFC_SPAS_16;
-			writew(tmp, host.regs + NFC_SPAS);
+			writew(tmp, host.regs + NFC_V2_SPAS);
 		}
 	}
 
-- 
1.7.2.3


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2010-11-15 12:09 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-10 14:53 add i.MX51 Nand support Sascha Hauer
2010-11-10 14:53 ` [PATCH 01/13] NAND: reset chips before usage like the kernel does Sascha Hauer
2010-11-10 14:53 ` [PATCH 02/13] imx_nand: remove 0xe00 offset from registers Sascha Hauer
2010-11-10 14:53 ` [PATCH 03/13] imx_nand: rework get_dev_status Sascha Hauer
2010-11-10 14:53 ` [PATCH 04/13] imx nand: remove unnecessary register write Sascha Hauer
2010-11-10 14:53 ` [PATCH 05/13] imx_nand: make some internally used functions overwriteable Sascha Hauer
2010-11-10 14:53 ` [PATCH 06/13] imx nand: do not read-modify-write SPAS register Sascha Hauer
2010-11-10 14:53 ` [PATCH 07/13] imx nand: add V1_V2 namespace to registers Sascha Hauer
2010-11-10 14:53 ` [PATCH 08/13] mxc_nand: fix correct_data function Sascha Hauer
2010-11-11  5:25   ` Baruch Siach
2010-11-11 10:32     ` Sascha Hauer
2010-11-15 12:08       ` [PATCH] " Baruch Siach
2010-11-10 14:53 ` [PATCH 09/13] imx nand: move initialization to preset function Sascha Hauer
2010-11-10 14:53 ` [PATCH 10/13] imx nand: introduce overwritable check_int function Sascha Hauer
2010-11-10 14:53 ` [PATCH 11/13] imx nand: Add v3 (i.MX51) support Sascha Hauer
2010-11-10 14:53 ` [PATCH 12/13] fb: set id for framebuffer device correctly Sascha Hauer
2010-11-10 14:55   ` Sascha Hauer
2010-11-10 14:53 ` [PATCH 13/13] ARM i.MX51: Add nand device Sascha Hauer
2010-11-11  5:26 ` add i.MX51 Nand support Jean-Christophe PLAGNIOL-VILLARD

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