9
0
Fork 0

mtd nand: implement buswidth detection

This introduces a new NAND_BUSWIDTH_AUTO flag which can be used
to automatically detect the nand buswidth. The id is always read
in 8bit mode. An additional callback is needed to switch the nand
controller into 16bit mode.
This currently depends on a safe read_byte (always) and read_buf
(for onfi-only flashes) callback. It has been tested on OMAP, but
is not something that generally works. For this reason the existence
of the set_buswidth callback is used to determine whether we are
able to do autodetection or not.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Sascha Hauer 2012-08-02 12:01:05 +02:00
parent 5a693051df
commit 85f4fe32cf
2 changed files with 19 additions and 4 deletions

View File

@ -1000,7 +1000,7 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
if (!chip->select_chip)
chip->select_chip = nand_select_chip;
if (!chip->read_byte)
if (!chip->read_byte || chip->read_byte == nand_read_byte)
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
if (!chip->read_word)
chip->read_word = nand_read_word;
@ -1009,12 +1009,12 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
#ifdef CONFIG_MTD_WRITE
if (!chip->block_markbad)
chip->block_markbad = nand_default_block_markbad;
if (!chip->write_buf)
if (!chip->write_buf || chip->write_buf == nand_write_buf)
chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
#endif
if (!chip->read_buf)
if (!chip->read_buf || chip->read_buf == nand_read_buf)
chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
if (!chip->verify_buf)
if (!chip->verify_buf || chip->verify_buf == nand_verify_buf)
chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
#ifdef CONFIG_NAND_BBT
if (!chip->scan_bbt)
@ -1258,6 +1258,13 @@ ident_done:
break;
}
if (chip->options & NAND_BUSWIDTH_AUTO) {
chip->options |= busw;
nand_set_defaults(chip, busw);
if (chip->set_buswidth)
chip->set_buswidth(mtd, chip, busw);
}
/*
* Check, if buswidth is correct. Hardware drivers should set
* chip correct !
@ -1326,6 +1333,11 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
struct nand_chip *chip = mtd->priv;
struct nand_flash_dev *type;
if (chip->options & NAND_BUSWIDTH_AUTO && !chip->set_buswidth) {
printk(KERN_ERR "buswidth detection but no buswidth callback\n");
return -EINVAL;
}
/* Get buswidth to select the correct functions */
busw = chip->options & NAND_BUSWIDTH_16;
/* Set the default functions */

View File

@ -169,6 +169,8 @@ typedef enum {
#define NAND_NO_READRDY 0x00000100
/* Chip does not allow subpage writes */
#define NAND_NO_SUBPAGE_WRITE 0x00000200
/* Buswitdh shal be autodetected */
#define NAND_BUSWIDTH_AUTO 0x00080000
/* Options valid for Samsung large page devices */
@ -451,6 +453,7 @@ struct nand_chip {
int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int page, int cached, int raw);
int (*set_buswidth)(struct mtd_info *mtd, struct nand_chip *this, int buswidth);
int chip_delay;
unsigned int options;