Commit 6fb277ba authored by Florian Fainelli's avatar Florian Fainelli Committed by David Woodhouse

mtd: nand: split ONFI detection logic to its own function

In order to reduce the indentation and improve the readability of nand_get_
flash_type, split the ONFI detection logic to its own function. The detection
logic inside nand_flash_detect_onfi is also rewritten to allow for less
indentation.
Signed-off-by: default avatarFlorian Fainelli <ffainelli@freebox.fr>
Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent d1e1f4e4
...@@ -2818,6 +2818,72 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len) ...@@ -2818,6 +2818,72 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
return crc; return crc;
} }
/*
* Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
*/
static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
int busw)
{
struct nand_onfi_params *p = &chip->onfi_params;
int i;
int val;
/* try ONFI for unknow chip or LP */
chip->cmdfunc(mtd, NAND_CMD_READID, 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;
printk(KERN_INFO "ONFI flash detected\n");
chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
for (i = 0; i < 3; i++) {
chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
le16_to_cpu(p->crc)) {
printk(KERN_INFO "ONFI param page %d valid\n", i);
break;
}
}
if (i == 3)
return 0;
/* check version */
val = le16_to_cpu(p->revision);
if (val == 1 || val > (1 << 4)) {
printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
__func__, val);
return 0;
}
if (val & (1 << 4))
chip->onfi_version = 22;
else if (val & (1 << 3))
chip->onfi_version = 21;
else if (val & (1 << 2))
chip->onfi_version = 20;
else
chip->onfi_version = 10;
sanitize_string(p->manufacturer, sizeof(p->manufacturer));
sanitize_string(p->model, sizeof(p->model));
if (!mtd->name)
mtd->name = p->model;
mtd->writesize = le32_to_cpu(p->byte_per_page);
mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
busw = 0;
if (le16_to_cpu(p->features) & 1)
busw = NAND_BUSWIDTH_16;
chip->options &= ~NAND_CHIPOPTIONS_MSK;
chip->options |= (NAND_NO_READRDY |
NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK;
return 1;
}
/* /*
* Get the flash and manufacturer id and lookup if the type is supported * Get the flash and manufacturer id and lookup if the type is supported
*/ */
...@@ -2828,6 +2894,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, ...@@ -2828,6 +2894,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
{ {
int i, maf_idx; int i, maf_idx;
u8 id_data[8]; u8 id_data[8];
int ret;
/* Select the device */ /* Select the device */
chip->select_chip(mtd, 0); chip->select_chip(mtd, 0);
...@@ -2872,67 +2939,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, ...@@ -2872,67 +2939,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->onfi_version = 0; chip->onfi_version = 0;
if (!type->name || !type->pagesize) { if (!type->name || !type->pagesize) {
/* try ONFI for unknow chip or LP */ /* Check is chip is ONFI compliant */
chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); ret = nand_flash_detect_onfi(mtd, chip, busw);
if (chip->read_byte(mtd) == 'O' && if (ret)
chip->read_byte(mtd) == 'N' &&
chip->read_byte(mtd) == 'F' &&
chip->read_byte(mtd) == 'I') {
struct nand_onfi_params *p = &chip->onfi_params;
int i;
printk(KERN_INFO "ONFI flash detected\n");
chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
for (i = 0; i < 3; i++) {
chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
le16_to_cpu(p->crc))
{
printk(KERN_INFO "ONFI param page %d valid\n", i);
break;
}
}
if (i < 3) {
/* check version */
int val = le16_to_cpu(p->revision);
if (val == 1 || val > (1 << 4))
printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
__func__, val);
else {
if (val & (1 << 4))
chip->onfi_version = 22;
else if (val & (1 << 3))
chip->onfi_version = 21;
else if (val & (1 << 2))
chip->onfi_version = 20;
else
chip->onfi_version = 10;
}
}
if (chip->onfi_version) {
sanitize_string(p->manufacturer, sizeof(p->manufacturer));
sanitize_string(p->model, sizeof(p->model));
if (!mtd->name)
mtd->name = p->model;
mtd->writesize = le32_to_cpu(p->byte_per_page);
mtd->erasesize = le32_to_cpu(p->pages_per_block)*mtd->writesize;
mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
busw = 0;
if (le16_to_cpu(p->features) & 1)
busw = NAND_BUSWIDTH_16;
chip->options &= ~NAND_CHIPOPTIONS_MSK;
chip->options |= (NAND_NO_READRDY |
NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK;
goto ident_done; goto ident_done;
}
}
} }
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment