
From: Matthieu CASTET matthieu.castet@parrot.com
This patch is slightly modified from following linux patch http://lists.infradead.org/pipermail/linux-mtd/2012-November/044803.html So retaining the authorship to Matthieu CASTET matthieu.castet@parrot.com *Modifications from original patch* reset chip->read_byte, chip->read_buf, chip->write_buf before setting defaults.
*Original patch message* The driver call nand_scan_ident in 8 bit mode, then readid or onfi detection are done (and detect bus width). The driver should update its bus width before calling nand_scan_tail.
This work because readid and onfi are read work 8 byte mode.
Note that nand_scan_ident send command (NAND_CMD_RESET, NAND_CMD_READID, NAND_CMD_PARAM), address and read data The ONFI specificication is not very clear for x16 device if high byte of address should be driven to 0, but according to [1] it should be ok to not drive it during autodetection.
[1] 3.3.2. Target Initialization
[...] The Read ID and Read Parameter Page commands only use the lower 8-bits of the data bus. The host shall not issue commands that use a word data width on x16 devices until the host determines the device supports a 16-bit data bus width in the parameter page.
Signed-off-by: Pekon Gupta pekon@ti.com --- drivers/mtd/nand/nand_base.c | 20 +++++++++++++++----- include/linux/mtd/nand.h | 7 +++++++ 2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 9e05cef..52e799b 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2977,11 +2977,21 @@ ident_done: break; }
- /* - * Check, if buswidth is correct. Hardware drivers should set - * chip correct! - */ - if (busw != (chip->options & NAND_BUSWIDTH_16)) { + if (chip->options & NAND_BUSWIDTH_AUTO) { + WARN_ON(chip->options & NAND_BUSWIDTH_16); + chip->options |= busw; + if (chip->read_byte == nand_read_byte) + chip->read_byte = NULL; + if (chip->read_buf == nand_read_buf) + chip->read_buf = NULL; + if (chip->write_buf == nand_write_buf) + chip->write_buf = NULL; + nand_set_defaults(chip, busw); + } else if (busw != (chip->options & NAND_BUSWIDTH_16)) { + /* + * Check, if buswidth is correct. Hardware drivers should set + * chip correct! + */ pr_info("NAND device: Manufacturer ID:" " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 2055584..bd6bc25 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -211,6 +211,13 @@ typedef enum { #define NAND_OWN_BUFFERS 0x00020000 /* Chip may not exist, so silence any errors in scan */ #define NAND_SCAN_SILENT_NODEV 0x00040000 +/* + * Autodetect nand buswidth with readid/onfi. + * This suppose the driver will configure the hardware in 8 bits mode + * when calling nand_scan_ident, and update its configuration + * before calling nand_scan_tail. + */ +#define NAND_BUSWIDTH_AUTO 0x00080000
/* Options set by nand scan */ /* bbt has already been read */