mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
mtd: nand: don't use {read,write}_buf for 8-bit transfers
According to the Open NAND Flash Interface Specification (ONFI) Revision 3.1 "Parameters are always transferred on the lower 8-bits of the data bus." for the Get Features and Set Features commands. So using read_buf and write_buf is wrong for 16-bit wide nand chips as they use I/O[15:0]. The Get Features command is easily fixed using 4 times the read_byte callback. For Set Features implement a new overwritable callback "write_byte". Still I expect the default to work just fine for all controllers and making it overwriteable was just done for symmetry. Signed-off-by: Uwe Kleine-König <[email protected]> [Brian: fixed warning] Tested-by: Brian Norris <[email protected]> Signed-off-by: Brian Norris <[email protected]>
This commit is contained in:
parent
e2e6b7b7d6
commit
05f7835975
2 changed files with 58 additions and 2 deletions
|
|
@ -203,6 +203,51 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nand_write_byte - [DEFAULT] write single byte to chip
|
||||
* @mtd: MTD device structure
|
||||
* @byte: value to write
|
||||
*
|
||||
* Default function to write a byte to I/O[7:0]
|
||||
*/
|
||||
static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
chip->write_buf(mtd, &byte, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16
|
||||
* @mtd: MTD device structure
|
||||
* @byte: value to write
|
||||
*
|
||||
* Default function to write a byte to I/O[7:0] on a 16-bit wide chip.
|
||||
*/
|
||||
static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
uint16_t word = byte;
|
||||
|
||||
/*
|
||||
* It's not entirely clear what should happen to I/O[15:8] when writing
|
||||
* a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads:
|
||||
*
|
||||
* When the host supports a 16-bit bus width, only data is
|
||||
* transferred at the 16-bit width. All address and command line
|
||||
* transfers shall use only the lower 8-bits of the data bus. During
|
||||
* command transfers, the host may place any value on the upper
|
||||
* 8-bits of the data bus. During address transfers, the host shall
|
||||
* set the upper 8-bits of the data bus to 00h.
|
||||
*
|
||||
* One user of the write_byte callback is nand_onfi_set_features. The
|
||||
* four parameters are specified to be written to I/O[7:0], but this is
|
||||
* neither an address nor a command transfer. Let's assume a 0 on the
|
||||
* upper I/O lines is OK.
|
||||
*/
|
||||
chip->write_buf(mtd, (uint8_t *)&word, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* nand_write_buf - [DEFAULT] write buffer to chip
|
||||
* @mtd: MTD device structure
|
||||
|
|
@ -2769,6 +2814,7 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
int addr, uint8_t *subfeature_param)
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
|
||||
if (!chip->onfi_version ||
|
||||
!(le16_to_cpu(chip->onfi_params.opt_cmd)
|
||||
|
|
@ -2776,7 +2822,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
return -EINVAL;
|
||||
|
||||
chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1);
|
||||
chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
|
||||
for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
|
||||
chip->write_byte(mtd, subfeature_param[i]);
|
||||
|
||||
status = chip->waitfunc(mtd, chip);
|
||||
if (status & NAND_STATUS_FAIL)
|
||||
return -EIO;
|
||||
|
|
@ -2793,6 +2841,8 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
int addr, uint8_t *subfeature_param)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!chip->onfi_version ||
|
||||
!(le16_to_cpu(chip->onfi_params.opt_cmd)
|
||||
& ONFI_OPT_CMD_SET_GET_FEATURES))
|
||||
|
|
@ -2802,7 +2852,8 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
|
||||
|
||||
chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
|
||||
chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN);
|
||||
for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
|
||||
*subfeature_param++ = chip->read_byte(mtd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2865,6 +2916,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
|
|||
chip->block_markbad = nand_default_block_markbad;
|
||||
if (!chip->write_buf || chip->write_buf == nand_write_buf)
|
||||
chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
|
||||
if (!chip->write_byte || chip->write_byte == nand_write_byte)
|
||||
chip->write_byte = busw ? nand_write_byte16 : nand_write_byte;
|
||||
if (!chip->read_buf || chip->read_buf == nand_read_buf)
|
||||
chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
|
||||
if (!chip->scan_bbt)
|
||||
|
|
|
|||
Loading…
Reference in a new issue