[PATCH 1/3] mtd: nand-imx: fix byte reading in x16 mode

Uwe Kleine-König u.kleine-koenig at pengutronix.de
Thu Feb 5 13:21:30 PST 2015


There are a few NAND commands that make the chip only respond on I/O
lines 0 to 7 even for x16 devices. READID (90h) is one such command
which was already handled fine in the driver (at least for NFC v1 and
v2). Other commands (like PARAM (ECh) to read out ONFI parameters)
however were not handled properly. Instead of adding another callback
make the read_byte callback handle the holes added by the NFC and depend
on the nand-base support to call read_byte when necessary instead of
read_buf.

This fixes reading the ONFI parameter page on an i.MX25 with an x16 NAND
and probably[1] also the result of READID on i.MX51/i.MX53 with x16
NAND.

[1] untested because no matching machine available

Signed-off-by: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c | 33 +++++++++++++++------------------
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index e2aaa153eb18..685750991389 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -377,8 +377,6 @@ static void send_read_param_v3(struct imx_nand_host *host)
 
 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_V1_V2_BUF_ADDR);
 
@@ -387,20 +385,11 @@ static void send_read_id_v1_v2(struct imx_nand_host *host)
 	/* Wait for operation to complete */
 	wait_op_done(host);
 
-	if (this->options & NAND_BUSWIDTH_16) {
-		volatile u16 *mainbuf = host->main_area0;
-
-		/*
-		 * Pack the every-other-byte result for 16-bit ID reads
-		 * into every-byte as the generic code expects and various
-		 * chips implement.
-		 */
-
-		mainbuf[0] = (mainbuf[0] & 0xff) | ((mainbuf[1] & 0xff) << 8);
-		mainbuf[1] = (mainbuf[2] & 0xff) | ((mainbuf[3] & 0xff) << 8);
-		mainbuf[2] = (mainbuf[4] & 0xff) | ((mainbuf[5] & 0xff) << 8);
-	}
-	memcpy32(host->data_buf, host->main_area0, 16);
+	/*
+	 * NFC_ID results in reading 6 bytes or words (depending on data width),
+	 * so copying 3 32-bit values is just fine.
+	 */
+	memcpy32(host->data_buf, host->main_area0, 12);
 }
 
 static void send_read_param_v1_v2(struct imx_nand_host *host)
@@ -572,8 +561,16 @@ static u_char imx_nand_read_byte(struct mtd_info *mtd)
 	if (host->status_request)
 		return host->get_dev_status(host) & 0xFF;
 
-	ret = *(uint8_t *)(host->data_buf + host->buf_start);
-	host->buf_start++;
+	if (nand_chip->options & NAND_BUSWIDTH_16) {
+		/* only take the lower byte of each word */
+		BUG_ON(host->buf_start & 1);
+		ret = *(uint16_t *)(host->data_buf + host->buf_start);
+
+		host->buf_start += 2;
+	} else {
+		ret = *(uint8_t *)(host->data_buf + host->buf_start);
+		host->buf_start++;
+	}
 
 	return ret;
 }
-- 
2.1.4




More information about the barebox mailing list