Skip to contentSkip to conversation

Add i.MX51 support to mxc_nand

PATCH New Sascha Hauer 6 participants 25 messages Aug 6, 2010 – Aug 29, 2010

Subsystems (3)
lore
Share & tools
lore

Sascha Hauer

author maintainer
#0 lore raw

Hi all,

The following series adds v3 (found on i.MX51) support to the i.MX nand controller. auto mode is not supported, but if I understand correctly the auto mode is only of use when more than one nand chip is connected. Without the auto mode the v3 controller behaves very similar to the v2 controller, but unfortunately it has a completely different register layout. For this reason this series has some preparation patches before the v3 support is added as the last patch.

This series conflicts with the series John Ogness recently posted, so it has probably to be reworked a bit.

I'll post the nand platform support for i.MX51 in a seperate series.

Sascha

author maintainer
#1 lore raw

PATCH 1/8 mxc_nand: remove 0xe00 offset from registers

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

---
 drivers/mtd/nand/mxc_nand.c |   36 ++++++++++++++++++------------------
 1 files changed, 18 insertions(+), 18 deletions(-)
drivers/mtd/nand/mxc_nand.c +18 -18
index 0d76b16..abec73a 100644
@@ -41,22 +41,22 @@
 #define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
 
 /* 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_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_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
 
 /* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
  * for Command operation */
@@ -764,14 +764,14 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	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;
 		this->ecc.bytes = 9;
 	} 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;
Signature · 1 line
1.7.1
author maintainer
#2 lore raw

PATCH 2/8 mxc_nand: rework get_dev_status

In reply to Sascha Hauer

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.

---
 drivers/mtd/nand/mxc_nand.c |   21 +++++++++------------
 1 files changed, 9 insertions(+), 12 deletions(-)
drivers/mtd/nand/mxc_nand.c +9 -12
index abec73a..6654446 100644
@@ -102,7 +102,6 @@ struct mxc_nand_host {
 
 	void			*spare0;
 	void			*main_area0;
-	void			*main_area1;
 
 	void __iomem		*base;
 	void __iomem		*regs;
@@ -305,25 +304,24 @@ static void send_read_id(struct mxc_nand_host *host)
  * NAND device status and returns the current status. */
 static uint16_t get_dev_status(struct mxc_nand_host *host)
 {
-	void __iomem *main_buf = host->main_area1;
+	void __iomem *main_buf = host->main_area0;
 	uint32_t store;
 	uint16_t ret;
-	/* Issue status request to NAND device */
 
-	/* store the main area1 first word, later do recovery */
+	writew(0x0, NFC_V1_V2_BUF_ADDR);
+
+	/*
+	 * The device status is stored in main_area0. To
+	 * prevent corruption of the buffer save the value
+	 * and restore it afterwards.
+	 */
 	store = readl(main_buf);
-	/* NANDFC buffer 1 is used for device status to prevent
-	 * corruption of read/write buffer on status requests. */
-	writew(1, host->regs + NFC_BUF_ADDR);
 
 	writew(NFC_STATUS, host->regs + NFC_CONFIG2);
-
-	/* Wait for operation to complete */
 	wait_op_done(host, true);
 
-	/* Status is placed in first word of main buffer */
-	/* get status, then recovery area 1 data */
 	ret = readw(main_buf);
+
 	writel(store, main_buf);
 
 	return ret;
@@ -761,7 +759,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	}
 
 	host->main_area0 = host->base;
-	host->main_area1 = host->base + 0x200;
 
 	if (nfc_is_v21()) {
 		host->regs = host->base + 0x1e00;
Signature · 1 line
1.7.1
author maintainer
#3 lore raw

PATCH 3/8 mxc_nand: make some internally used functions overwriteable

In reply to Sascha Hauer

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.

---
 drivers/mtd/nand/mxc_nand.c |   72 ++++++++++++++++++++++++++----------------
 1 files changed, 44 insertions(+), 28 deletions(-)
drivers/mtd/nand/mxc_nand.c +44 -28
index 6654446..2d2e2e7 100644
@@ -115,6 +115,13 @@ struct mxc_nand_host {
 	uint8_t			*data_buf;
 	unsigned int		buf_start;
 	int			spare_len;
+
+	void			(*preset)(struct mtd_info *);
+	void			(*send_cmd)(struct mxc_nand_host *, uint16_t, int);
+	void			(*send_addr)(struct mxc_nand_host *, uint16_t, int);
+	void			(*send_page)(struct mtd_info *, unsigned int);
+	void			(*send_read_id)(struct mxc_nand_host *);
+	uint16_t		(*get_dev_status)(struct mxc_nand_host *);
 };
 
 /* OOB placement block for use with hardware ecc generation */
@@ -212,7 +219,7 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
 
 /* This function issues the specified command to the NAND device and
  * waits for completion. */
-static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
+static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
 {
 	DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
 
@@ -241,7 +248,7 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
 /* This function sends an address (or partial address) to the
  * NAND device. The address is used to select the source/destination for
  * a NAND command. */
-static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
+static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islast)
 {
 	DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
 
@@ -252,7 +259,7 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
 	wait_op_done(host, islast);
 }
 
-static void send_page(struct mtd_info *mtd, unsigned int ops)
+static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops)
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
@@ -276,7 +283,7 @@ static void send_page(struct mtd_info *mtd, unsigned int ops)
 }
 
 /* Request the NANDFC to perform a read of the NAND device ID. */
-static void send_read_id(struct mxc_nand_host *host)
+static void send_read_id_v1_v2(struct mxc_nand_host *host)
 {
 	struct nand_chip *this = &host->nand;
 
@@ -302,7 +309,7 @@ static void send_read_id(struct mxc_nand_host *host)
 
 /* This function requests the NANDFC to perform a read of the
  * NAND device status and returns the current status. */
-static uint16_t get_dev_status(struct mxc_nand_host *host)
+static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
 {
 	void __iomem *main_buf = host->main_area0;
 	uint32_t store;
@@ -381,7 +388,7 @@ static u_char mxc_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++;
@@ -517,39 +524,39 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 		 * we will used the saved column address to index into
 		 * the full page.
 		 */
-		send_addr(host, 0, page_addr == -1);
+		host->send_addr(host, 0, page_addr == -1);
 		if (mtd->writesize > 512)
 			/* another col addr cycle for 2k page */
-			send_addr(host, 0, false);
+			host->send_addr(host, 0, false);
 	}
 
 	/* Write out page address, if necessary */
 	if (page_addr != -1) {
 		/* paddr_0 - p_addr_7 */
-		send_addr(host, (page_addr & 0xff), false);
+		host->send_addr(host, (page_addr & 0xff), false);
 
 		if (mtd->writesize > 512) {
 			if (mtd->size >= 0x10000000) {
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, false);
-				send_addr(host, (page_addr >> 16) & 0xff, true);
+				host->send_addr(host, (page_addr >> 8) & 0xff, false);
+				host->send_addr(host, (page_addr >> 16) & 0xff, true);
 			} else
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, true);
+				host->send_addr(host, (page_addr >> 8) & 0xff, true);
 		} else {
 			/* One more address cycle for higher density devices */
 			if (mtd->size >= 0x4000000) {
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, false);
-				send_addr(host, (page_addr >> 16) & 0xff, true);
+				host->send_addr(host, (page_addr >> 8) & 0xff, false);
+				host->send_addr(host, (page_addr >> 16) & 0xff, true);
 			} else
 				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, true);
+				host->send_addr(host, (page_addr >> 8) & 0xff, true);
 		}
 	}
 }
 
-static void preset(struct mtd_info *mtd)
+static void preset_v1_v2(struct mtd_info *mtd)
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
@@ -602,15 +609,15 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 	/* Command pre-processing step */
 	switch (command) {
 	case NAND_CMD_RESET:
-		send_cmd(host, command, false);
-		preset(mtd);
+		host->send_cmd(host, command, false);
+		host->preset(mtd);
 		break;
 
 	case NAND_CMD_STATUS:
 		host->buf_start = 0;
 		host->status_request = true;
 
-		send_cmd(host, command, true);
+		host->send_cmd(host, command, true);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 
@@ -623,13 +630,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 
 		command = NAND_CMD_READ0; /* only READ0 is valid */
 
-		send_cmd(host, command, false);
+		host->send_cmd(host, command, false);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 
 		if (mtd->writesize > 512)
-			send_cmd(host, NAND_CMD_READSTART, true);
+			host->send_cmd(host, NAND_CMD_READSTART, true);
 
-		send_page(mtd, NFC_OUTPUT);
+		host->send_page(mtd, NFC_OUTPUT);
 
 		memcpy(host->data_buf, host->main_area0, mtd->writesize);
 		copy_spare(mtd, true);
@@ -642,28 +649,28 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 
 		host->buf_start = column;
 
-		send_cmd(host, command, false);
+		host->send_cmd(host, command, false);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 
 	case NAND_CMD_PAGEPROG:
 		memcpy(host->main_area0, host->data_buf, mtd->writesize);
 		copy_spare(mtd, false);
-		send_page(mtd, NFC_INPUT);
-		send_cmd(host, command, true);
+		host->send_page(mtd, NFC_INPUT);
+		host->send_cmd(host, command, true);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 
 	case NAND_CMD_READID:
-		send_cmd(host, command, true);
+		host->send_cmd(host, command, true);
 		mxc_do_addr_cycle(mtd, column, page_addr);
-		send_read_id(host);
+		host->send_read_id(host);
 		host->buf_start = column;
 		break;
 
 	case NAND_CMD_ERASE1:
 	case NAND_CMD_ERASE2:
-		send_cmd(host, command, false);
+		host->send_cmd(host, command, false);
 		mxc_do_addr_cycle(mtd, column, page_addr);
 
 		break;
@@ -760,6 +767,15 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 
 	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;
+		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;
Signature · 1 line
1.7.1
author maintainer
#4 lore raw

PATCH 4/8 mxc_nand: factor out a check_int function

In reply to Sascha Hauer
---
 drivers/mtd/nand/mxc_nand.c |   32 +++++++++++++++++++-------------
 1 files changed, 19 insertions(+), 13 deletions(-)
drivers/mtd/nand/mxc_nand.c +19 -13
index 2d2e2e7..70f64dc 100644
@@ -122,6 +122,7 @@ struct mxc_nand_host {
 	void			(*send_page)(struct mtd_info *, unsigned int);
 	void			(*send_read_id)(struct mxc_nand_host *);
 	uint16_t		(*get_dev_status)(struct mxc_nand_host *);
+	int			(*check_int)(struct mxc_nand_host *);
 };
 
 /* OOB placement block for use with hardware ecc generation */
@@ -181,34 +182,38 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int check_int_v1_v2(struct mxc_nand_host *host)
+{
+	uint32_t tmp;
+
+	tmp = readw(host->regs + NFC_CONFIG2);
+	if (!(tmp & NFC_INT))
+		return 0;
+
+	writew(tmp & ~NFC_INT, NFC_CONFIG2);
+
+	return 1;
+}
+
 /* This function polls the NANDFC to wait for the basic operation to
  * complete by checking the INT bit of config2 register.
  */
 static void wait_op_done(struct mxc_nand_host *host, int useirq)
 {
-	uint16_t tmp;
 	int max_retries = 8000;
 
 	if (useirq) {
-		if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
+		if (!host->check_int(host)) {
 
 			enable_irq(host->irq);
 
-			wait_event(host->irq_waitq,
-				readw(host->regs + NFC_CONFIG2) & NFC_INT);
-
-			tmp = readw(host->regs + NFC_CONFIG2);
-			tmp  &= ~NFC_INT;
-			writew(tmp, host->regs + NFC_CONFIG2);
+			wait_event(host->irq_waitq, host->check_int(host));
 		}
 	} else {
 		while (max_retries-- > 0) {
-			if (readw(host->regs + NFC_CONFIG2) & NFC_INT) {
-				tmp = readw(host->regs + NFC_CONFIG2);
-				tmp  &= ~NFC_INT;
-				writew(tmp, host->regs + NFC_CONFIG2);
+			if (host->check_int(host))
 				break;
-			}
+
 			udelay(1);
 		}
 		if (max_retries < 0)
@@ -774,6 +779,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 		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()) {
Signature · 1 line
1.7.1
author maintainer
#5 lore raw

PATCH 5/8 mxc_nand: add V1_V2 namespace to registers

In reply to Sascha Hauer

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.

---
 drivers/mtd/nand/mxc_nand.c |  141 +++++++++++++++++++------------------------
 1 files changed, 63 insertions(+), 78 deletions(-)
drivers/mtd/nand/mxc_nand.c +63 -78
index 70f64dc..48b6dca 100644
@@ -41,58 +41,43 @@
 #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_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
-
-/* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
- * for Command operation */
-#define NFC_CMD            0x1
-
-/* Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
- * for Address operation */
-#define NFC_ADDR           0x2
-
-/* Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
- * for Input operation */
-#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_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_V1_V2_BUF_SIZE		(host->regs + 0x00)
+#define NFC_V1_V2_BUF_ADDR		(host->regs + 0x04)
+#define NFC_V1_V2_FLASH_ADDR		(host->regs + 0x06)
+#define NFC_V1_V2_FLASH_CMD		(host->regs + 0x08)
+#define NFC_V1_V2_CONFIG		(host->regs + 0x0a)
+#define NFC_V1_V2_ECC_STATUS_RESULT	(host->regs + 0x0c)
+#define NFC_V1_V2_RSLTMAIN_AREA		(host->regs + 0x0e)
+#define NFC_V1_V2_RSLTSPARE_AREA	(host->regs + 0x10)
+#define NFC_V1_V2_WRPROT		(host->regs + 0x12)
+#define NFC_V1_UNLOCKSTART_BLKADDR	(host->regs + 0x14)
+#define NFC_V1_UNLOCKEND_BLKADDR	(host->regs + 0x16)
+#define NFC_V21_UNLOCKSTART_BLKADDR	(host->regs + 0x20)
+#define NFC_V21_UNLOCKEND_BLKADDR	(host->regs + 0x22)
+#define NFC_V1_V2_NF_WRPRST		(host->regs + 0x18)
+#define NFC_V1_V2_CONFIG1		(host->regs + 0x1a)
+#define NFC_V1_V2_CONFIG2		(host->regs + 0x1c)
+
+#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)
+
+#define NFC_V1_V2_CONFIG2_INT		(1 << 15)
+
+/*
+ * Operation modes for the NFC. Valid for v1, v2 and v3
+ * type controllers.
+ */
+#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)
 
 struct mxc_nand_host {
 	struct mtd_info		mtd;
@@ -186,11 +171,11 @@ static int check_int_v1_v2(struct mxc_nand_host *host)
 {
 	uint32_t tmp;
 
-	tmp = readw(host->regs + NFC_CONFIG2);
-	if (!(tmp & NFC_INT))
+	tmp = readw(NFC_V1_V2_CONFIG2);
+	if (!(tmp & NFC_V1_V2_CONFIG2_INT))
 		return 0;
 
-	writew(tmp & ~NFC_INT, NFC_CONFIG2);
+	writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
 
 	return 1;
 }
@@ -228,15 +213,15 @@ static void send_cmd_v1_v2(struct mxc_nand_host *host, uint16_t cmd, int useirq)
 {
 	DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
 
-	writew(cmd, host->regs + NFC_FLASH_CMD);
-	writew(NFC_CMD, host->regs + NFC_CONFIG2);
+	writew(cmd, NFC_V1_V2_FLASH_CMD);
+	writew(NFC_CMD, NFC_V1_V2_CONFIG2);
 
 	if (cpu_is_mx21() && (cmd == NAND_CMD_RESET)) {
 		int max_retries = 100;
 		/* Reset completion is indicated by NFC_CONFIG2 */
 		/* being set to 0 */
 		while (max_retries-- > 0) {
-			if (readw(host->regs + NFC_CONFIG2) == 0) {
+			if (readw(NFC_V1_V2_CONFIG2) == 0) {
 				break;
 			}
 			udelay(1);
@@ -257,8 +242,8 @@ static void send_addr_v1_v2(struct mxc_nand_host *host, uint16_t addr, int islas
 {
 	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, NFC_V1_V2_FLASH_ADDR);
+	writew(NFC_ADDR, NFC_V1_V2_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host, islast);
@@ -278,9 +263,9 @@ static void send_page_v1_v2(struct mtd_info *mtd, unsigned int ops)
 	for (i = 0; i < bufs; i++) {
 
 		/* NANDFC buffer 0 is used for page read/write */
-		writew(i, host->regs + NFC_BUF_ADDR);
+		writew(i, NFC_V1_V2_BUF_ADDR);
 
-		writew(ops, host->regs + NFC_CONFIG2);
+		writew(ops, NFC_V1_V2_CONFIG2);
 
 		/* Wait for operation to complete */
 		wait_op_done(host, true);
@@ -293,9 +278,9 @@ static void send_read_id_v1_v2(struct mxc_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, NFC_V1_V2_BUF_ADDR);
 
-	writew(NFC_ID, host->regs + NFC_CONFIG2);
+	writew(NFC_ID, NFC_V1_V2_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host, true);
@@ -329,7 +314,7 @@ static uint16_t get_dev_status_v1_v2(struct mxc_nand_host *host)
 	 */
 	store = readl(main_buf);
 
-	writew(NFC_STATUS, host->regs + NFC_CONFIG2);
+	writew(NFC_STATUS, NFC_V1_V2_CONFIG2);
 	wait_op_done(host, true);
 
 	ret = readw(main_buf);
@@ -368,7 +353,7 @@ static int mxc_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
 	 */
-	uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT);
+	uint16_t ecc_status = readw(NFC_V1_V2_ECC_STATUS_RESULT);
 
 	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
 		DEBUG(MTD_DEBUG_LEVEL0,
@@ -568,32 +553,32 @@ static void preset_v1_v2(struct mtd_info *mtd)
 	uint16_t tmp;
 
 	/* enable interrupt, disable spare enable */
-	tmp = readw(host->regs + NFC_CONFIG1);
-	tmp &= ~NFC_INT_MSK;
-	tmp &= ~NFC_SP_EN;
+	tmp = readw(NFC_V1_V2_CONFIG1);
+	tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
+	tmp &= ~NFC_V1_V2_CONFIG1_SP_EN;
 	if (nand_chip->ecc.mode == NAND_ECC_HW) {
-		tmp |= NFC_ECC_EN;
+		tmp |= NFC_V1_V2_CONFIG1_ECC_EN;
 	} else {
-		tmp &= ~NFC_ECC_EN;
+		tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN;
 	}
-	writew(tmp, host->regs + NFC_CONFIG1);
+	writew(tmp, NFC_V1_V2_CONFIG1);
 	/* preset operation */
 
 	/* Unlock the internal RAM Buffer */
-	writew(0x2, host->regs + NFC_CONFIG);
+	writew(0x2, 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);
+		writew(0x0, NFC_V21_UNLOCKSTART_BLKADDR);
+		writew(0xffff, 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);
+		writew(0x0, NFC_V1_UNLOCKSTART_BLKADDR);
+		writew(0x4000, NFC_V1_UNLOCKEND_BLKADDR);
 	} else
 		BUG();
 
 	/* Unlock Block Command for given address range */
-	writew(0x4, host->regs + NFC_WRPROT);
+	writew(0x4, NFC_V1_V2_WRPROT);
 }
 
 /* Used by the upper layer to write command to NAND Flash for
Signature · 1 line
1.7.1
author maintainer
#6 lore raw

PATCH 6/8 mxc_nand: fix correct_data function

In reply to Sascha Hauer

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.

---
 drivers/mtd/nand/mxc_nand.c |   42 ++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 40 insertions(+), 2 deletions(-)
drivers/mtd/nand/mxc_nand.c +40 -2
index 48b6dca..a6dc5a5 100644
@@ -94,6 +94,7 @@ struct mxc_nand_host {
 	struct clk		*clk;
 	int			clk_act;
 	int			irq;
+	int			eccsize;
 
 	wait_queue_head_t	irq_waitq;
 
@@ -342,7 +343,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 	 */
 }
 
-static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+static int mxc_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;
@@ -364,6 +365,40 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 	return 0;
 }
 
+static int mxc_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 mxc_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(NFC_V1_V2_ECC_STATUS_RESULT);
+
+	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 mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 				  u_char *ecc_code)
 {
@@ -790,7 +825,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	if (pdata->hw_ecc) {
 		this->ecc.calculate = mxc_nand_calculate_ecc;
 		this->ecc.hwctl = mxc_nand_enable_hwecc;
-		this->ecc.correct = mxc_nand_correct_data;
+		if (nfc_is_v1())
+			this->ecc.correct = mxc_nand_correct_data_v1;
+		else
+			this->ecc.correct = mxc_nand_correct_data_v2_v3;
 		this->ecc.mode = NAND_ECC_HW;
 	} else {
 		this->ecc.mode = NAND_ECC_SOFT;
Signature · 1 line
1.7.1
#7 lore raw

PATCH 6/8 mxc_nand: fix correct_data function

Hi Sascha,

Quoted 15 lines · Sascha Hauer

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.

---
 drivers/mtd/nand/mxc_nand.c |   42 ++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 40 insertions(+), 2 deletions(-)
drivers/mtd/nand/mxc_nand.c +0 -0
index 48b6dca..a6dc5a5 100644

drivers/mtd/nand/mxc_nand.c struct mxc_nand_host { · line 97

Quoted 4 lines
drivers/mtd/nand/mxc_nand.c +1 -0
@@ -94,6 +94,7 @@ struct mxc_nand_host {
 	struct clk		*clk;
 	int			clk_act;
 	int			irq;
+	int			eccsize;

This new mxc_nand_host field doesn't get initialized in this patch, although it is used in the .correct implementation. The next patch in this series includes the eccsize initialization code. This might break bisect. Won't it be safer to switch the order of these patches?

baruch

Quoted 64 lines
drivers/mtd/nand/mxc_nand.c +39 -2
 	wait_queue_head_t	irq_waitq;
 
@@ -342,7 +343,7 @@ static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 	 */
 }
 
-static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+static int mxc_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;
@@ -364,6 +365,40 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 	return 0;
 }
 
+static int mxc_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 mxc_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(NFC_V1_V2_ECC_STATUS_RESULT);
+
+	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 mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 				  u_char *ecc_code)
 {
@@ -790,7 +825,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	if (pdata->hw_ecc) {
 		this->ecc.calculate = mxc_nand_calculate_ecc;
 		this->ecc.hwctl = mxc_nand_enable_hwecc;
-		this->ecc.correct = mxc_nand_correct_data;
+		if (nfc_is_v1())
+			this->ecc.correct = mxc_nand_correct_data_v1;
+		else
+			this->ecc.correct = mxc_nand_correct_data_v2_v3;
 		this->ecc.mode = NAND_ECC_HW;
 	} else {
 		this->ecc.mode = NAND_ECC_SOFT;
Signature · 3 lines
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
author maintainer
#8 lore raw

PATCH 6/8 mxc_nand: fix correct_data function

Quoted 13 lines · Baruch Siach

Hi Sascha,

Quoted 10 lines · Sascha Hauer

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.

---
 drivers/mtd/nand/mxc_nand.c |   42 ++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 40 insertions(+), 2 deletions(-)
Quoted 14 lines

drivers/mtd/nand/mxc_nand.c struct mxc_nand_host { · line 97

Quoted 9 lines
drivers/mtd/nand/mxc_nand.c +1 -0
index 48b6dca..a6dc5a5 100644
@@ -94,6 +94,7 @@ struct mxc_nand_host {
 	struct clk		*clk;
 	int			clk_act;
 	int			irq;
+	int			eccsize;

This new mxc_nand_host field doesn't get initialized in this patch, although it is used in the .correct implementation. The next patch in this series includes the eccsize initialization code. This might break bisect. Won't it be safer to switch the order of these patches?

Ok, will fix.

Sascha

Signature · 4 lines
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 |
#9 lore raw

PATCH 6/8 mxc_nand: fix correct_data function

In reply to Sascha Hauer

drivers/mtd/nand/mxc_nand.c static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, · line 389

Quoted 4 lines · Sascha Hauer
drivers/mtd/nand/mxc_nand.c +4 -0
+		err = ecc_stat & ecc_bit_mask;
+		if (err > err_limit) {
+			printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
+			return -1;

Someone's being lazy.

#10 lore raw

PATCH 6/8 mxc_nand: fix correct_data function

Hi Russell,

Quoted 7 lines · Russell King - ARM Linux

drivers/mtd/nand/mxc_nand.c static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, · line 389

Quoted 4 lines · Sascha Hauer
drivers/mtd/nand/mxc_nand.c +4 -0
+		err = ecc_stat & ecc_bit_mask;
+		if (err > err_limit) {
+			printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
+			return -1;

Someone's being lazy.

The code at nand_read_subpage() (drivers/mtd/nand/nand_base.c) expects the .correct callback to return -1 on an uncorrectable error:

                stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
                if (stat == -1)
                        mtd->ecc_stats.failed++;
                else
                        mtd->ecc_stats.corrected += stat;

baruch

Signature · 3 lines
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
author maintainer
#11 lore raw

PATCH 6/8 mxc_nand: fix correct_data function

Quoted 11 lines · Baruch Siach

Hi Russell,

Quoted 7 lines · Russell King - ARM Linux

drivers/mtd/nand/mxc_nand.c static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, · line 389

Quoted 4 lines · Sascha Hauer
drivers/mtd/nand/mxc_nand.c +4 -0
+		err = ecc_stat & ecc_bit_mask;
+		if (err > err_limit) {
+			printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
+			return -1;

Someone's being lazy.

Quoted 8 lines

The code at nand_read_subpage() (drivers/mtd/nand/nand_base.c) expects the .correct callback to return -1 on an uncorrectable error:

                stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
                if (stat == -1)
                        mtd->ecc_stats.failed++;
                else
                        mtd->ecc_stats.corrected += stat;

Then this should be changed to check for stat < 0. I found some drivers in the tree returning an errno value in their .correct function instead of -1.

Sascha

Signature · 4 lines
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 |
#12 lore raw

PATCH 6/8 mxc_nand: fix correct_data function

Quoted 21 lines · Sascha Hauer
Quoted 11 lines · Baruch Siach

Hi Russell,

Quoted 7 lines · Russell King - ARM Linux

drivers/mtd/nand/mxc_nand.c static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat, · line 389

Quoted 4 lines · Sascha Hauer
drivers/mtd/nand/mxc_nand.c +4 -0
+		err = ecc_stat & ecc_bit_mask;
+		if (err > err_limit) {
+			printk(KERN_WARNING "UnCorrectable RS-ECC Error\n");
+			return -1;

Someone's being lazy.

Quoted 8 lines

The code at nand_read_subpage() (drivers/mtd/nand/nand_base.c) expects the .correct callback to return -1 on an uncorrectable error:

                stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
                if (stat == -1)
                        mtd->ecc_stats.failed++;
                else
                        mtd->ecc_stats.corrected += stat;
Quoted 3 lines

Then this should be changed to check for stat < 0. I found some drivers in the tree returning an errno value in their .correct function instead of -1.

That's the whole danger of the whole 'return -1' evilness in the kernel. The long established convention in the kernel is that negative numbers returned from functions are negative errno codes.

As soon as you decide that you want a function to return -1 to indicate an error rather than a real errno code, you lose clarity on which functions need '-1' and which are proper negative errno codes, and then you end up with people returning negative errno codes for functions which should be -1, and people returning -1 for functions which should be negative errno codes.

If you want a function to return -1 for error, then it probably makes sense to create a ECC_CORRECT_FAILED definition which happens to be -1. Or some other number. But don't use plain '-1' - it looks far too much like "I was lazy, I couldn't be bothered to look up a proper errno."

We know full well that _lots_ of people submit stuff with 'return -1' statements where they should be proper negative errno codes, so it's something people are having a great deal of trouble with already. Let's not further confuse everyone by having functions expecting called methods to do a plain "return -1;" on error.

#13 lore raw

PATCH 1/1 nand: fix .correct callback return value check

In reply to Sascha Hauer

Drivers may (and do) return negative errno values other than -1 from the .correct callback.

---
 drivers/mtd/nand/nand_base.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/mtd/nand/nand_base.c +1 -1
index 4a7b864..080f551 100644
@@ -1210,7 +1210,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3
 		int stat;
 
 		stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
-		if (stat == -1)
+		if (stat < 0)
 			mtd->ecc_stats.failed++;
 		else
 			mtd->ecc_stats.corrected += stat;
Signature · 1 line
1.7.1
#14 lore raw

PATCH 1/1 nand: fix .correct callback return value check

Hi linux-mtd list,

Ping?

At least the atmel_nand and the bf5xx_nand drivers may return -EIO for uncorrectable errors, so this patch fixes a real bug.

baruch

Quoted 23 lines · Baruch Siach

Drivers may (and do) return negative errno values other than -1 from the .correct callback.

---
 drivers/mtd/nand/nand_base.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/mtd/nand/nand_base.c +1 -1
index 4a7b864..080f551 100644
@@ -1210,7 +1210,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint3
 		int stat;
 
 		stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
-		if (stat == -1)
+		if (stat < 0)
 			mtd->ecc_stats.failed++;
 		else
 			mtd->ecc_stats.corrected += stat;
Signature · 1 line
1.7.1
Signature · 3 lines
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
author maintainer
#16 lore raw

PATCH 7/8 mxc_nand: support 8bit ecc

In reply to Sascha Hauer

Nand devices with at least 26 bytes of oob data per 512 byte block can have 8bit ecc on v2 type controllers. This is currently not tested, but at least this patch puts the ECC_MODE bit into a well defined state.

---
 drivers/mtd/nand/mxc_nand.c |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)
drivers/mtd/nand/mxc_nand.c +30 -0
index a6dc5a5..030da08 100644
@@ -58,6 +58,7 @@
 #define NFC_V1_V2_CONFIG1		(host->regs + 0x1a)
 #define NFC_V1_V2_CONFIG2		(host->regs + 0x1c)
 
+#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)
@@ -581,6 +582,23 @@ 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@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;
@@ -596,6 +614,15 @@ static void preset_v1_v2(struct mtd_info *mtd)
 	} else {
 		tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN;
 	}
+
+	if (nfc_is_v21() && mtd->writesize) {
+		host->eccsize = get_eccsize(mtd);
+		if (host->eccsize == 4)
+			tmp |= NFC_V2_CONFIG1_ECC_MODE_4;
+	} else {
+		host->eccsize = 1;
+	}
+
 	writew(tmp, NFC_V1_V2_CONFIG1);
 	/* preset operation */
 
@@ -859,6 +886,9 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 		goto escan;
 	}
 
+	/* Call preset again, with correct writesize this time */
+	host->preset(mtd);
+
 	if (mtd->writesize == 2048)
 		this->ecc.layout = oob_largepage;
 
Signature · 1 line
1.7.1
author maintainer
#17 lore raw

PATCH 8/8 mxc_nand: Add v3 (i.MX51) Support

In reply to Sascha Hauer
---
 drivers/mtd/nand/Kconfig    |    2 +-
 drivers/mtd/nand/mxc_nand.c |  222 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 222 insertions(+), 2 deletions(-)
drivers/mtd/nand/Kconfig +1 -1
index 362d177..b8a03bd 100644
@@ -482,7 +482,7 @@ config MTD_NAND_MPC5121_NFC
 
 config MTD_NAND_MXC
 	tristate "MXC NAND support"
-	depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3
+	depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX51
 	help
 	  This enables the driver for the NAND flash controller on the
 	  MXC processors.
drivers/mtd/nand/mxc_nand.c +221 -1

306 lines not on this page · raw message

Signature · 1 line
1.7.1
#18 lore raw

cover mxc_nand: fixes for purposed updates

In reply to Sascha Hauer

With these patches applied I've tested mxc-nand-pu on a i.MX25 based system.

Baruch Siach (2):
mxc_nand: fix build error
mxc_nand: remove unused variables

 drivers/mtd/nand/mxc_nand.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)
#19 lore raw

PATCH 1/2 mxc_nand: fix build error

drivers/mtd/nand/mxc_nand.c: In function 'mxc_nand_command':
drivers/mtd/nand/mxc_nand.c:908: error: implicit declaration of function 'send_cmd'

---
 drivers/mtd/nand/mxc_nand.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/mtd/nand/mxc_nand.c +2 -2
index 4032e0b..3092240 100644
@@ -905,13 +905,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 
 			/* Set program pointer to spare region */
 			if (mtd->writesize == 512)
-				send_cmd(host, NAND_CMD_READOOB, false);
+				host->send_cmd(host, NAND_CMD_READOOB, false);
 		} else {
 			host->buf_start = column;
 
 			/* Set program pointer to page start */
 			if (mtd->writesize == 512)
-				send_cmd(host, NAND_CMD_READ0, false);
+				host->send_cmd(host, NAND_CMD_READ0, false);
 		}
 
 		host->send_cmd(host, command, false);
Signature · 1 line
1.7.1
author maintainer
#20 lore raw

PATCH 1/2 mxc_nand: fix build error

Quoted 2 lines · Baruch Siach

drivers/mtd/nand/mxc_nand.c: In function 'mxc_nand_command':
drivers/mtd/nand/mxc_nand.c:908: error: implicit declaration of function 'send_cmd'

This is because you based my series on 2.6.35. With current master this patch is not necessary.

Sascha

Quoted 30 lines
---
 drivers/mtd/nand/mxc_nand.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/mtd/nand/mxc_nand.c +2 -2
index 4032e0b..3092240 100644
@@ -905,13 +905,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 
 			/* Set program pointer to spare region */
 			if (mtd->writesize == 512)
-				send_cmd(host, NAND_CMD_READOOB, false);
+				host->send_cmd(host, NAND_CMD_READOOB, false);
 		} else {
 			host->buf_start = column;
 
 			/* Set program pointer to page start */
 			if (mtd->writesize == 512)
-				send_cmd(host, NAND_CMD_READ0, false);
+				host->send_cmd(host, NAND_CMD_READ0, false);
 		}
 
 		host->send_cmd(host, command, false);
Signature · 1 line
1.7.1
Signature · 4 lines
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 |
#21 lore raw

PATCH 2/2 mxc_nand: remove unused variables

In reply to Baruch Siach
---
 drivers/mtd/nand/mxc_nand.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)
drivers/mtd/nand/mxc_nand.c +1 -4
index 3092240..dfa8311 100644
@@ -1210,15 +1210,12 @@ static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
 static int mxcnd_resume(struct platform_device *pdev)
 {
 	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
-	int ret = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
 
 	mtd->resume(mtd);
 
-	return ret;
+	return 0;
 }
 
 #else
Signature · 1 line
1.7.1
#22 lore raw

PATCH 2/2 mxc_nand: remove unused variables

Hi,

Quoted 11 lines · Baruch Siach
---
 drivers/mtd/nand/mxc_nand.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)
drivers/mtd/nand/mxc_nand.c +0 -0
index 3092240..dfa8311 100644
@@ -1210,15 +1210,12 @@ static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
 static int mxcnd_resume(struct platform_device *pdev)

drivers/mtd/nand/mxc_nand.c static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) · line 1217

Quoted 10 lines
drivers/mtd/nand/mxc_nand.c +0 -3
 {
 	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
-	int ret = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
 
 	mtd->resume(mtd);
 

There was a patch to remove the whole function mxcnd_resume() because the call to mtd->resume() is done elsewhere in the MTD layer:
http://lists.infradead.org/pipermail/linux-arm-kernel/2010-June/018243.html

Lothar Wa?mann

Signature · 9 lines
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________
#23 lore raw

cover mxc_nand: fixes for purposed updates

In reply to Baruch Siach
Quoted 8 lines · Baruch Siach

With these patches applied I've tested mxc-nand-pu on a i.MX25 based system.

Baruch Siach (2):
mxc_nand: fix build error
mxc_nand: remove unused variables

 drivers/mtd/nand/mxc_nand.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

These patches don't apply to the mtd-2.6.git tree.

Signature · 2 lines
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation
#24 lore raw

cover mxc_nand: fixes for purposed updates

Hi David,

Quoted 11 lines · David Woodhouse
Quoted 8 lines · Baruch Siach

With these patches applied I've tested mxc-nand-pu on a i.MX25 based system.

Baruch Siach (2):
mxc_nand: fix build error
mxc_nand: remove unused variables

 drivers/mtd/nand/mxc_nand.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

These patches don't apply to the mtd-2.6.git tree.

These patches apply on top of the mxc-nand-pu branch of Sascha Hauer at
git://git.pengutronix.de/git/imx/linux-2.6.git. Sorry for not mentioning this.

baruch

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