[PATCH] mtd: nand: fix byte addressing on 16-bit wide devices

David Mosberger davidm at egauge.net
Fri Mar 21 13:42:31 EDT 2014


This is a revised version of a patch that I submitted a while ago.
It's relative to linux-mtd.
Please apply.

Thanks!

  --david
-- 
eGauge Systems LLC, http://egauge.net/, 1.877-EGAUGE1, fax 720.545.9768
-------------- next part --------------
mtd: nand: fix byte adressing on 16-bit wide devices

Some commands (READID, GET_FEATURES, and SET_FEATURES) require
byte-addresses even when the databus is 16 bits wide.  Without this
patch, 16-bit wide devices are unable to detect ONFI.

Signed-off-by: David Mosberger <davidm at egauge.net>

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 9715a7b..132866c 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -103,6 +103,20 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
  */
 DEFINE_LED_TRIGGER(nand_led_trigger);
 
+/*
+ * Some commands (READID, GET_FEATURES, and SET_FEATURES) are
+ * byte-oriented even when the data-bus is 16 bits wide.  To preserve
+ * the byte-address, we need to encode it properly depending on
+ * whether or not the device has a 16 bit wide bus.
+ */
+static inline int byte_addr(struct nand_chip *chip, int addr)
+{
+	if (chip->options & NAND_BUSWIDTH_16)
+		return addr << 1;
+	else
+		return addr;
+}
+
 static int check_offs_len(struct mtd_info *mtd,
 					loff_t ofs, uint64_t len)
 {
@@ -2821,7 +2835,7 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 	      & ONFI_OPT_CMD_SET_GET_FEATURES))
 		return -EINVAL;
 
-	chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
+	chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, byte_addr(chip, addr), -1);
 	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
 		chip->write_byte(mtd, subfeature_param[i]);
 
@@ -2851,7 +2865,7 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
 	/* clear the sub feature parameters */
 	memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
 
-	chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
+	chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, byte_addr(chip, addr), -1);
 	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
 		*subfeature_param++ = chip->read_byte(mtd);
 	return 0;
@@ -3067,7 +3081,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 	int val;
 
 	/* Try ONFI for unknown chip or LP */
-	chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
+	chip->cmdfunc(mtd, NAND_CMD_READID, byte_addr(chip, 0x20), -1);
 	if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
 		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
 		return 0;
@@ -3491,7 +3505,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 
 	/* Send the command for reading device ID */
-	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+	chip->cmdfunc(mtd, NAND_CMD_READID, byte_addr(chip, 0x00), -1);
 
 	/* Read manufacturer and device IDs */
 	*maf_id = chip->read_byte(mtd);
@@ -3504,7 +3518,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	 * not match, ignore the device completely.
 	 */
 
-	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+	chip->cmdfunc(mtd, NAND_CMD_READID, byte_addr(chip, 0x00), -1);
 
 	/* Read entire ID string */
 	for (i = 0; i < 8; i++)
@@ -3662,7 +3676,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 		/* See comment in nand_get_flash_type for reset */
 		chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 		/* Send the command for reading device ID */
-		chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+		chip->cmdfunc(mtd, NAND_CMD_READID, byte_addr(chip, 0x00), -1);
 		/* Read manufacturer and device IDs */
 		if (nand_maf_id != chip->read_byte(mtd) ||
 		    nand_dev_id != chip->read_byte(mtd)) {


More information about the linux-mtd mailing list