NAND: add NAND_CMD_PARAM (0xec) definition
Subsystems (2)
PATCH 1/2 NAND: add NAND_CMD_PARAM (0xec) definition
From: Florian Fainelli <[email protected]>
This command is used to read the device ONFI parameters page.
--- include/linux/mtd/nand.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
include/linux/mtd/nand.h +1 -0
@@ -84,6 +84,7 @@ extern void nand_wait_ready(struct mtd_info *mtd);#define NAND_CMD_SEQIN 0x80#define NAND_CMD_RNDIN 0x85#define NAND_CMD_READID 0x90 +#define NAND_CMD_PARAM 0xec#define NAND_CMD_ERASE2 0xd0#define NAND_CMD_RESET 0xff
Signature · 1 line
1.7.2.3
PATCH 2/2 NAND: add support for reading ONFI page table
From: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct nand_chip onfi_version member contains the supported ONFI version, 0 otherwise.
This allows NAND drivers past nand_scan_ident to set the best timings for the NAND chip.
--- drivers/mtd/nand/nand_base.c | 129 ++++++++++++++++++++++++++++++++++------- include/linux/mtd/nand.h | 68 ++++++++++++++++++++++ 2 files changed, 175 insertions(+), 22 deletions(-)
drivers/mtd/nand/nand_base.c +107 -22
@@ -2406,15 +2406,94 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; } +static u16 onfi_crc16 (u16 crc,u8 const *p,size_t len) +{ +int i; + +while (len--) { + crc ^= *p++ <<8 ; +for (i =0 ; i <8 ; i++) + crc = (crc <<1 ) ^ ((crc &0x8000 ) ?0x8005 :0 ); + } + +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 ; + +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 */ static struct nand_flash_dev *nand_get_flash_type (struct mtd_info *mtd,struct nand_chip *chip, -int busw,int *maf_id) +int busw, +int *maf_id,int *dev_id) {struct nand_flash_dev *type =NULL ; -int i, dev_id, maf_idx; +int i, ret, maf_idx;int tmp_id, tmp_manf;/* Select the device */
@@ -2431,7 +2510,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,/* Read manufacturer and device IDs */ *maf_id = chip->read_byte (mtd); - dev_id = chip->read_byte (mtd); + *dev_id = chip->read_byte (mtd);/* Try again to make sure, as some systems the bus-hold or other * interface concerns can cause random data which looks like a
@@ -2446,16 +2525,16 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, tmp_manf = chip->read_byte (mtd); tmp_id = chip->read_byte (mtd); -if (tmp_manf != *maf_id || tmp_id != dev_id) { +if (tmp_manf != *maf_id || tmp_id != *dev_id) {printk (KERN_INFO "%s: second ID read did not match " "%02x,%02x against %02x,%02x\n" , __func__, - *maf_id, dev_id, tmp_manf, tmp_id); + *maf_id, *dev_id, tmp_manf, tmp_id);return ERR_PTR (-ENODEV ); }/* Lookup the flash id */ for (i =0 ; nand_flash_ids[i].name !=NULL ; i++) { -if (dev_id == nand_flash_ids[i].id) { +if (*dev_id == nand_flash_ids[i].id) { type = &nand_flash_ids[i];break ; }
@@ -2464,10 +2543,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,if (!type) {/* supress warning if there is no nand */ if (*maf_id !=0x00 && *maf_id !=0xff && - dev_id !=0x00 && dev_id !=0xff ) + *dev_id !=0x00 && *dev_id !=0xff )printk (KERN_INFO "%s: unknown NAND device: " "Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n" , - __func__, *maf_id, dev_id); + __func__, *maf_id, *dev_id);return ERR_PTR (-ENODEV ); }
@@ -2475,6 +2554,11 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, mtd->name = type->name; chip->chipsize = (uint64_t )type->chipsize <<20 ; + chip->onfi_version =0 ; + + ret =nand_flash_detect_onfi (mtd, chip, busw); +if (ret) + goto ident_done;/* Newer devices have all the information in additional id bytes */ if (!type->pagesize) {
@@ -2505,6 +2589,16 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, busw = type->options &NAND_BUSWIDTH_16 ; } +/* Get chip options, preserve non chip based options */ + chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; + +/* +* Set chip as a default. Board drivers can override it, if necessary +*/ +ident_done: + chip->options |=NAND_NO_AUTOINCR ; +/* Try to identify manufacturer */ for (maf_idx =0 ; nand_manuf_ids[maf_idx].id !=0x0 ; maf_idx++) {if (nand_manuf_ids[maf_idx].id == *maf_id)
@@ -2518,7 +2612,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,if (busw != (chip->options &NAND_BUSWIDTH_16 )) {printk (KERN_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); + *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);printk (KERN_WARNING "NAND bus width %d instead %d bit\n" , (chip->options &NAND_BUSWIDTH_16 ) ?16 :8 , busw ?16 :8 );
@@ -2541,15 +2635,6 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->badblockpos = mtd->writesize >512 ?NAND_LARGE_BADBLOCK_POS :NAND_SMALL_BADBLOCK_POS ; -/* Get chip options, preserve non chip based options */ - chip->options &= ~NAND_CHIPOPTIONS_MSK ; - chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; - -/* -* Set chip as a default. Board drivers can override it, if necessary -*/ - chip->options |=NAND_NO_AUTOINCR ; -/* Check if chip is a not a samsung device. Do not clear the * options for chips which are not having an extended id. */
@@ -2567,7 +2652,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->cmdfunc = nand_command_lp;MTDDEBUG (MTD_DEBUG_LEVEL0 ,"NAND device: Manufacturer ID:" -" 0x%02x, Chip ID: 0x%02x (%s %s)\n" , *maf_id, dev_id, +" 0x%02x, Chip ID: 0x%02x (%s %s)\n" , *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, type->name);return type;
@@ -2585,7 +2670,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,*/ int nand_scan_ident (struct mtd_info *mtd,int maxchips) { -int i, busw, nand_maf_id; +int i, busw, nand_maf_id, nand_dev_id;struct nand_chip *chip = mtd->priv;struct nand_flash_dev *type;
@@ -2595,7 +2680,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)nand_set_defaults (chip, busw);/* Read the flash type */ - type =nand_get_flash_type (mtd, chip, busw, &nand_maf_id); + type =nand_get_flash_type (mtd, chip, busw, &nand_maf_id, &nand_dev_id);if (IS_ERR (type)) {#ifndef CONFIG_SYS_NAND_QUIET_TEST
@@ -2614,7 +2699,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips) chip->cmdfunc (mtd,NAND_CMD_READID ,0x00 ,-1 );/* Read manufacturer and device IDs */ if (nand_maf_id != chip->read_byte (mtd) || - type->id != chip->read_byte (mtd)) + nand_dev_id != chip->read_byte (mtd))break ; }#ifdef DEBUG
include/linux/mtd/nand.h +68 -0
80 lines not on this page · raw message
Signature · 1 line
1.7.2.3
PATCH 2/2 NAND: add support for reading ONFI page table
Quoted 8 lines · Florian Fainelli
From: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct
nand_chiponfi_versionmember contains the supported ONFI version, 0 otherwise.This allows NAND drivers past
nand_scan_identto set the best timings for the NAND chip.
Wrap changelogs around 72 characters, as git log indents them a bit.
Quoted 7 lines
Signed-off-by Florian Fainelli <[email protected]>---
drivers/mtd/nand/nand_base.c| 129 ++++++++++++++++++++++++++++++++++-------include/linux/mtd/nand.h | 68 ++++++++++++++++++++++ 2 files changed, 175 insertions(+), 22 deletions(-)
Tested on what I assume is a non-ONFI chip, no breakage.
Please wrap this in a CONFIG option, so that we don't increase the image size of boards that don't need to support this.
Quoted 17 lines
drivers/mtd/nand/nand_base.c +9
-0@@ -2406,15 +2406,94 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; } +static u16 onfi_crc16 (u16 crc,u8 const *p,size_t len) +{ +int i; + +while (len--) { + crc ^= *p++ <<8 ; +for (i =0 ; i <8 ; i++) + crc = (crc <<1 ) ^ ((crc &0x8000 ) ?0x8005 :0 ); + }
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2427
Quoted 10 lines
drivers/mtd/nand/nand_base.c +10
-0+ +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) +{
Keep lines under 80 columns.
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2429
Quoted 2 lines
drivers/mtd/nand/nand_base.c +2
-0+ +/* try ONFI for unknow chip or LP */
"unknown".
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2436
Quoted 4 lines
drivers/mtd/nand/nand_base.c +4
-0+ 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 ;
I'm not sure how this comment matches the code -- it looks like it's checking for an explicit ONFI ID. I don't see anything about unknown chips or large pages.
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2458
Quoted 7 lines
drivers/mtd/nand/nand_base.c +7
-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 ; + }
Ideally I'd like to see continuation lines lined up nicely with the start of arguments on the previous line, but at least don't tab it all the way over to the right edge of the screen.
drivers/mtd/nand/nand_base.c static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, · line 2561
Quoted 6 lines
drivers/mtd/nand/nand_base.c +5
-0chip->chipsize = (uint64_t )type->chipsize <<20 ; + chip->onfi_version =0 ; + + ret =nand_flash_detect_onfi (mtd, chip, busw); +if (ret) + goto ident_done;
Move the non-ONFI code out into its own function, instead of using goto.
Quoted 8 lines
drivers/mtd/nand/nand_base.c +8
-0+__le32 blocks_per_lun; +u8 lun_count; +u8 addr_cycles; +u8 bits_per_cell; +__le16 bb_per_lun; +__le16 block_endurance; +u8 guaranteed_good_blocks; +__le16 guaranteed_block_endurance;
[snip]
Quoted 1 line
+} __attribute__((packed));
Sigh. Someone on the standards body needs to learn about alignment.
-Scott
PATCH 2/2 NAND: add support for reading ONFI page table
Quoted 18 lines · On Saturday 11 December 2010 01:15:13 Scott Wood wrote:
Quoted 8 lines · Florian Fainelli
From: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct
nand_chiponfi_versionmember contains the supported ONFI version, 0 otherwise.This allows NAND drivers past
nand_scan_identto set the best timings for the NAND chip.Wrap changelogs around 72 characters, as git log indents them a bit.
Quoted 6 lines
Signed-off-by Florian Fainelli <[email protected]>---
drivers/mtd/nand/nand_base.c| 129
++++++++++++++++++++++++++++++++++-------
Quoted 7 lines
Quoted 2 lines
include/linux/mtd/nand.h | 68 ++++++++++++++++++++++ 2 files changed, 175 insertions(+), 22 deletions(-)Tested on what I assume is a non-ONFI chip, no breakage.
Please wrap this in a CONFIG option, so that we don't increase the image size of boards that don't need to support this.
Makes sense, I will do this
Quoted 39 lines
Quoted 27 lines
drivers/mtd/nand/nand_base.c +15
-0@@ -2406,15 +2406,94 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; } +static u16 onfi_crc16 (u16 crc,u8 const *p,size_t len) +{ +int i; + +while (len--) { + crc ^= *p++ <<8 ; +for (i =0 ; i <8 ; i++) + crc = (crc <<1 ) ^ ((crc &0x8000 ) ?0x8005 :0 ); + } + +return crc; +} + +/* +* Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 Quoted 4 lines
otherwise + */
+static int nand_flash_detect_onfi(structmtd_info*mtd, structnand_chip
*chip, + int busw)
+{Keep lines under 80 columns.
drivers/mtd/nand/nand_base.c
Quoted 2 lines
drivers/mtd/nand/nand_base.c +2
-0+ +/* try ONFI for unknow chip or LP */ "unknown".
Quoted 8 lines
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2436
Quoted 4 lines
drivers/mtd/nand/nand_base.c +4
-0+ 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 ;I'm not sure how this comment matches the code -- it looks like it's checking for an explicit ONFI ID. I don't see anything about unknown chips or large pages.
It does not actually, I did not think about checking it when porting this from Linux.
Quoted 45 lines
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2458
Quoted 8 lines
drivers/mtd/nand/nand_base.c +7
-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 ; + }Ideally I'd like to see continuation lines lined up nicely with the start of arguments on the previous line, but at least don't tab it all the way over to the right edge of the screen.
drivers/mtd/nand/nand_base.c static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, · line 2561
Quoted 7 lines
drivers/mtd/nand/nand_base.c +5
-0chip->chipsize = (uint64_t )type->chipsize <<20 ; + chip->onfi_version =0 ; + + ret =nand_flash_detect_onfi (mtd, chip, busw); +if (ret) + goto ident_done;Move the non-ONFI code out into its own function, instead of using goto.
Quoted 8 lines
drivers/mtd/nand/nand_base.c +8
-0+__le32 blocks_per_lun; +u8 lun_count; +u8 addr_cycles; +u8 bits_per_cell; +__le16 bb_per_lun; +__le16 block_endurance; +u8 guaranteed_good_blocks; +__le16 guaranteed_block_endurance;[snip]
Quoted 1 line
+} __attribute__((packed));
Sigh. Someone on the standards body needs to learn about alignment.
-Scott
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
PATCH v2 1/1 NAND: add support for reading ONFI page table
In reply to Florian FainelliFrom: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct nand_chip onfi_version member contains the supported ONFI version, 0 otherwise.
This allows NAND drivers past nand_scan_ident to set the best timings for the NAND chip.
---
Changes since v1:
- ifdef out ONFI detection code around CONFIG_SYS_NAND_ONFI_DETECTION
- removed bogus comment
- fixed busw variable usage
- move non-ONFI detection code to its own function
- fixed stylistic issues spotted by Scott
drivers/mtd/nand/nand_base.c +151 -49
@@ -2409,15 +2409,141 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; } +#ifdef CONFIG_SYS_NAND_ONFI_DETECTION +static u16 onfi_crc16 (u16 crc,u8 const *p,size_t len) +{ +int i; + +while (len--) { + crc ^= *p++ <<8 ; +for (i =0 ; i <8 ; i++) + crc = (crc <<1 ) ^ ((crc &0x8000 ) ?0x8005 :0 ); + } + +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; + + 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 ; + +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 ; +} +#else +static inline int nand_flash_detect_onfi (struct mtd_info *mtd, +struct nand_chip *chip, +int *busw) +{ +return 0 ; +} +#endif + +static void nand_flash_detect_non_onfi (struct mtd_info *mtd, +struct nand_chip *chip, +const struct nand_flash_dev *type, +int *busw) +{ +/* Newer devices have all the information in additional id bytes */ +if (!type->pagesize) { +int extid; +/* The 3rd id byte holds MLC / multichip data */ + chip->cellinfo = chip->read_byte (mtd); +/* The 4th id byte is the important one */ + extid = chip->read_byte (mtd); +/* Calc pagesize */ + mtd->writesize =1024 << (extid &0x3 ); + extid >>=2 ; +/* Calc oobsize */ + mtd->oobsize = (8 << (extid &0x01 )) * (mtd->writesize >>9 ); + extid >>=2 ; +/* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 *1024 ) << (extid &0x03 ); + extid >>=2 ; +/* Get buswidth information */ + *busw = (extid &0x01 ) ?NAND_BUSWIDTH_16 :0 ; + + }else { +/* +* Old devices have chip data hardcoded in the device id table +*/ + mtd->erasesize = type->erasesize; + mtd->writesize = type->pagesize; + mtd->oobsize = mtd->writesize /32 ; + *busw = type->options &NAND_BUSWIDTH_16 ; + } + +/* Get chip options, preserve non chip based options */ + chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; +} +/* * Get the flash and manufacturer id and lookup if the type is supported */ static const struct nand_flash_dev *nand_get_flash_type (struct mtd_info *mtd,struct nand_chip *chip, -int busw,int *maf_id) +int busw, +int *maf_id,int *dev_id) {const struct nand_flash_dev *type =NULL ; -int i, dev_id, maf_idx; +int i, ret, maf_idx;int tmp_id, tmp_manf;/* Select the device */
@@ -2434,7 +2560,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,/* Read manufacturer and device IDs */ *maf_id = chip->read_byte (mtd); - dev_id = chip->read_byte (mtd); + *dev_id = chip->read_byte (mtd);/* Try again to make sure, as some systems the bus-hold or other * interface concerns can cause random data which looks like a
@@ -2449,16 +2575,16 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, tmp_manf = chip->read_byte (mtd); tmp_id = chip->read_byte (mtd); -if (tmp_manf != *maf_id || tmp_id != dev_id) { +if (tmp_manf != *maf_id || tmp_id != *dev_id) {printk (KERN_INFO "%s: second ID read did not match " "%02x,%02x against %02x,%02x\n" , __func__, - *maf_id, dev_id, tmp_manf, tmp_id); + *maf_id, *dev_id, tmp_manf, tmp_id);return ERR_PTR (-ENODEV ); }/* Lookup the flash id */ for (i =0 ; nand_flash_ids[i].name !=NULL ; i++) { -if (dev_id == nand_flash_ids[i].id) { +if (*dev_id == nand_flash_ids[i].id) { type = &nand_flash_ids[i];break ; }
@@ -2467,10 +2593,10 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,if (!type) {/* supress warning if there is no nand */ if (*maf_id !=0x00 && *maf_id !=0xff && - dev_id !=0x00 && dev_id !=0xff ) + *dev_id !=0x00 && *dev_id !=0xff )printk (KERN_INFO "%s: unknown NAND device: " "Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n" , - __func__, *maf_id, dev_id); + __func__, *maf_id, *dev_id);return ERR_PTR (-ENODEV ); }
@@ -2478,35 +2604,20 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, mtd->name = type->name; chip->chipsize = (uint64_t )type->chipsize <<20 ; + chip->onfi_version =0 ; -/* Newer devices have all the information in additional id bytes */ -if (!type->pagesize) { -int extid; -/* The 3rd id byte holds MLC / multichip data */ - chip->cellinfo = chip->read_byte (mtd); -/* The 4th id byte is the important one */ - extid = chip->read_byte (mtd); -/* Calc pagesize */ - mtd->writesize =1024 << (extid &0x3 ); - extid >>=2 ; -/* Calc oobsize */ - mtd->oobsize = (8 << (extid &0x01 )) * (mtd->writesize >>9 ); - extid >>=2 ; -/* Calc blocksize. Blocksize is multiples of 64KiB */ - mtd->erasesize = (64 *1024 ) << (extid &0x03 ); - extid >>=2 ; -/* Get buswidth information */ - busw = (extid &0x01 ) ?NAND_BUSWIDTH_16 :0 ; + ret =nand_flash_detect_onfi (mtd, chip, &busw); +if (!ret) +nand_flash_detect_non_onfi (mtd, chip, type, &busw); - }else { -/* -* Old devices have chip data hardcoded in the device id table -*/ - mtd->erasesize = type->erasesize; - mtd->writesize = type->pagesize; - mtd->oobsize = mtd->writesize /32 ; - busw = type->options &NAND_BUSWIDTH_16 ; - } +/* Get chip options, preserve non chip based options */ + chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; + +/* +* Set chip as a default. Board drivers can override it, if necessary +*/ + chip->options |=NAND_NO_AUTOINCR ;/* Try to identify manufacturer */ for (maf_idx =0 ; nand_manuf_ids[maf_idx].id !=0x0 ; maf_idx++) {
@@ -2521,7 +2632,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,if (busw != (chip->options &NAND_BUSWIDTH_16 )) {printk (KERN_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); + *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);printk (KERN_WARNING "NAND bus width %d instead %d bit\n" , (chip->options &NAND_BUSWIDTH_16 ) ?16 :8 , busw ?16 :8 );
@@ -2544,15 +2655,6 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->badblockpos = mtd->writesize >512 ?NAND_LARGE_BADBLOCK_POS :NAND_SMALL_BADBLOCK_POS ; -/* Get chip options, preserve non chip based options */ - chip->options &= ~NAND_CHIPOPTIONS_MSK ; - chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; - -/* -* Set chip as a default. Board drivers can override it, if necessary -*/ - chip->options |=NAND_NO_AUTOINCR ; -/* Check if chip is a not a samsung device. Do not clear the * options for chips which are not having an extended id. */
@@ -2570,7 +2672,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->cmdfunc = nand_command_lp;MTDDEBUG (MTD_DEBUG_LEVEL0 ,"NAND device: Manufacturer ID:" -" 0x%02x, Chip ID: 0x%02x (%s %s)\n" , *maf_id, dev_id, +" 0x%02x, Chip ID: 0x%02x (%s %s)\n" , *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, type->name);return type;
@@ -2588,7 +2690,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,*/ int nand_scan_ident (struct mtd_info *mtd,int maxchips) { -int i, busw, nand_maf_id; +int i, busw, nand_maf_id, nand_dev_id;struct nand_chip *chip = mtd->priv;const struct nand_flash_dev *type;
@@ -2598,7 +2700,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)nand_set_defaults (chip, busw);/* Read the flash type */ - type =nand_get_flash_type (mtd, chip, busw, &nand_maf_id); + type =nand_get_flash_type (mtd, chip, busw, &nand_maf_id, &nand_dev_id);if (IS_ERR (type)) {#ifndef CONFIG_SYS_NAND_QUIET_TEST
@@ -2617,7 +2719,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips) chip->cmdfunc (mtd,NAND_CMD_READID ,0x00 ,-1 );/* Read manufacturer and device IDs */ if (nand_maf_id != chip->read_byte (mtd) || - type->id != chip->read_byte (mtd)) + nand_dev_id != chip->read_byte (mtd))break ; }#ifdef DEBUG
include/linux/mtd/nand.h +69 -0
81 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v2 1/1 NAND: add support for reading ONFI page table
Hello Scott,
Forgot to mention that this patch is against your 'next' branch. --
Florian
PATCH v2 1/1 NAND: add support for reading ONFI page table
In reply to Florian Fainellidrivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2459
Quoted 4 lines · Florian Fainelli
drivers/mtd/nand/nand_base.c +4
-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);
Line length.
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2485
Quoted 3 lines
drivers/mtd/nand/nand_base.c +3
-0+ chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |= (NAND_NO_READRDY | +NAND_NO_AUTOINCR ) &NAND_CHIPOPTIONS_MSK ;
NAND_NO_AUTOINCR is not included in NAND_CHIPOPTIONS_MSK, so including it here has no effect.
Quoted 10 lines
drivers/mtd/nand/nand_base.c +3
-6+ ret =nand_flash_detect_onfi (mtd, chip, &busw); +if (!ret) +nand_flash_detect_non_onfi (mtd, chip, type, &busw); - }else { -/* -* Old devices have chip data hardcoded in the device id table -*/ - mtd->erasesize = type->erasesize; - mtd->writesize = type->pagesize;
drivers/mtd/nand/nand_base.c static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, · line 2620
Quoted 10 lines
drivers/mtd/nand/nand_base.c +7
-3- mtd->oobsize = mtd->writesize /32 ; - busw = type->options &NAND_BUSWIDTH_16 ; - } +/* Get chip options, preserve non chip based options */ + chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; +/* +* Set chip as a default. Board drivers can override it, if necessary +*/ + chip->options |=NAND_NO_AUTOINCR ;
Won't this duplicate/overwrite what was done in nand_flash_detect_*()?
include/linux/mtd/nand.h typedef enum { · line 277
Quoted 10 lines
include/linux/mtd/nand.h +10
-0+u8 input_pin_capacitance_max; +u8 driver_strenght_support; +__le16 t_int_r; +__le16 t_ald; +u8 reserved4[7 ]; + +/* vendor */ +u8 reserved5[90 ]; + +__le16 crc;
Extra space before __le16.
-Scott
PATCH v3 1/1 NAND: add support for reading ONFI page table
From: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct nand_chip onfi_version member contains the supported ONFI version, 0 otherwise.
This allows NAND drivers past nand_scan_ident to set the best timings for the NAND chip.
---
Patch against your 'next' branch
Changes since v1:
- ifdef out ONFI detection code around CONFIG_SYS_NAND_ONFI_DETECTION
- removed bogus comment
- fixed busw variable usage
- move non-ONFI detection code to its own function
- fixed stylistic issues spotted by Scott
Changes since v2:
- reduce lenght of some lines down to 80 columns
- change chip->options consistently wrt to ONFI detected or not
- removed extra spaces
drivers/mtd/nand/nand_base.c +147 -49
@@ -2409,15 +2409,137 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; } +#ifdef CONFIG_SYS_NAND_ONFI_DETECTION +static u16 onfi_crc16 (u16 crc,u8 const *p,size_t len) +{ +int i; + +while (len--) { + crc ^= *p++ <<8 ; +for (i =0 ; i <8 ; i++) + crc = (crc <<1 ) ^ ((crc &0x8000 ) ?0x8005 :0 ); + } + +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; + + 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 ; + +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_CHIPOPTIONS_MSK ; + +return 1 ; +} +#else +static inline int nand_flash_detect_onfi (struct mtd_info *mtd, +struct nand_chip *chip, +int *busw) +{ +return 0 ; +} +#endif + +static void nand_flash_detect_non_onfi (struct mtd_info *mtd, +struct nand_chip *chip, +const struct nand_flash_dev *type, +int *busw) +{ +/* Newer devices have all the information in additional id bytes */ +if (!type->pagesize) { +int extid; +/* The 3rd id byte holds MLC / multichip data */ + chip->cellinfo = chip->read_byte (mtd); +/* The 4th id byte is the important one */ + extid = chip->read_byte (mtd); +/* Calc pagesize */ + mtd->writesize =1024 << (extid &0x3 ); + extid >>=2 ; +/* Calc oobsize */ + mtd->oobsize = (8 << (extid &0x01 )) * (mtd->writesize >>9 ); + extid >>=2 ; +/* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 *1024 ) << (extid &0x03 ); + extid >>=2 ; +/* Get buswidth information */ + *busw = (extid &0x01 ) ?NAND_BUSWIDTH_16 :0 ; + + }else { +/* +* Old devices have chip data hardcoded in the device id table +*/ + mtd->erasesize = type->erasesize; + mtd->writesize = type->pagesize; + mtd->oobsize = mtd->writesize /32 ; + *busw = type->options &NAND_BUSWIDTH_16 ; + } +} +/* * Get the flash and manufacturer id and lookup if the type is supported */ static const struct nand_flash_dev *nand_get_flash_type (struct mtd_info *mtd,struct nand_chip *chip, -int busw,int *maf_id) +int busw, +int *maf_id,int *dev_id) {const struct nand_flash_dev *type =NULL ; -int i, dev_id, maf_idx; +int i, ret, maf_idx;int tmp_id, tmp_manf;/* Select the device */
@@ -2434,7 +2556,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,/* Read manufacturer and device IDs */ *maf_id = chip->read_byte (mtd); - dev_id = chip->read_byte (mtd); + *dev_id = chip->read_byte (mtd);/* Try again to make sure, as some systems the bus-hold or other * interface concerns can cause random data which looks like a
@@ -2449,16 +2571,16 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, tmp_manf = chip->read_byte (mtd); tmp_id = chip->read_byte (mtd); -if (tmp_manf != *maf_id || tmp_id != dev_id) { +if (tmp_manf != *maf_id || tmp_id != *dev_id) {printk (KERN_INFO "%s: second ID read did not match " "%02x,%02x against %02x,%02x\n" , __func__, - *maf_id, dev_id, tmp_manf, tmp_id); + *maf_id, *dev_id, tmp_manf, tmp_id);return ERR_PTR (-ENODEV ); }/* Lookup the flash id */ for (i =0 ; nand_flash_ids[i].name !=NULL ; i++) { -if (dev_id == nand_flash_ids[i].id) { +if (*dev_id == nand_flash_ids[i].id) { type = &nand_flash_ids[i];break ; }
@@ -2467,10 +2589,10 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,if (!type) {/* supress warning if there is no nand */ if (*maf_id !=0x00 && *maf_id !=0xff && - dev_id !=0x00 && dev_id !=0xff ) + *dev_id !=0x00 && *dev_id !=0xff )printk (KERN_INFO "%s: unknown NAND device: " "Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n" , - __func__, *maf_id, dev_id); + __func__, *maf_id, *dev_id);return ERR_PTR (-ENODEV ); }
@@ -2478,35 +2600,20 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, mtd->name = type->name; chip->chipsize = (uint64_t )type->chipsize <<20 ; + chip->onfi_version =0 ; -/* Newer devices have all the information in additional id bytes */ -if (!type->pagesize) { -int extid; -/* The 3rd id byte holds MLC / multichip data */ - chip->cellinfo = chip->read_byte (mtd); -/* The 4th id byte is the important one */ - extid = chip->read_byte (mtd); -/* Calc pagesize */ - mtd->writesize =1024 << (extid &0x3 ); - extid >>=2 ; -/* Calc oobsize */ - mtd->oobsize = (8 << (extid &0x01 )) * (mtd->writesize >>9 ); - extid >>=2 ; -/* Calc blocksize. Blocksize is multiples of 64KiB */ - mtd->erasesize = (64 *1024 ) << (extid &0x03 ); - extid >>=2 ; -/* Get buswidth information */ - busw = (extid &0x01 ) ?NAND_BUSWIDTH_16 :0 ; + ret =nand_flash_detect_onfi (mtd, chip, &busw); +if (!ret) +nand_flash_detect_non_onfi (mtd, chip, type, &busw); - }else { -/* -* Old devices have chip data hardcoded in the device id table -*/ - mtd->erasesize = type->erasesize; - mtd->writesize = type->pagesize; - mtd->oobsize = mtd->writesize /32 ; - busw = type->options &NAND_BUSWIDTH_16 ; - } +/* Get chip options, preserve non chip based options */ + chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; + +/* +* Set chip as a default. Board drivers can override it, if necessary +*/ + chip->options |=NAND_NO_AUTOINCR ;/* Try to identify manufacturer */ for (maf_idx =0 ; nand_manuf_ids[maf_idx].id !=0x0 ; maf_idx++) {
@@ -2521,7 +2628,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,if (busw != (chip->options &NAND_BUSWIDTH_16 )) {printk (KERN_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); + *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);printk (KERN_WARNING "NAND bus width %d instead %d bit\n" , (chip->options &NAND_BUSWIDTH_16 ) ?16 :8 , busw ?16 :8 );
@@ -2544,15 +2651,6 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->badblockpos = mtd->writesize >512 ?NAND_LARGE_BADBLOCK_POS :NAND_SMALL_BADBLOCK_POS ; -/* Get chip options, preserve non chip based options */ - chip->options &= ~NAND_CHIPOPTIONS_MSK ; - chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; - -/* -* Set chip as a default. Board drivers can override it, if necessary -*/ - chip->options |=NAND_NO_AUTOINCR ; -/* Check if chip is a not a samsung device. Do not clear the * options for chips which are not having an extended id. */
@@ -2570,7 +2668,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->cmdfunc = nand_command_lp;MTDDEBUG (MTD_DEBUG_LEVEL0 ,"NAND device: Manufacturer ID:" -" 0x%02x, Chip ID: 0x%02x (%s %s)\n" , *maf_id, dev_id, +" 0x%02x, Chip ID: 0x%02x (%s %s)\n" , *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, type->name);return type;
@@ -2588,7 +2686,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,*/ int nand_scan_ident (struct mtd_info *mtd,int maxchips) { -int i, busw, nand_maf_id; +int i, busw, nand_maf_id, nand_dev_id;struct nand_chip *chip = mtd->priv;const struct nand_flash_dev *type;
@@ -2598,7 +2696,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)nand_set_defaults (chip, busw);/* Read the flash type */ - type =nand_get_flash_type (mtd, chip, busw, &nand_maf_id); + type =nand_get_flash_type (mtd, chip, busw, &nand_maf_id, &nand_dev_id);if (IS_ERR (type)) {#ifndef CONFIG_SYS_NAND_QUIET_TEST
@@ -2617,7 +2715,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips) chip->cmdfunc (mtd,NAND_CMD_READID ,0x00 ,-1 );/* Read manufacturer and device IDs */ if (nand_maf_id != chip->read_byte (mtd) || - type->id != chip->read_byte (mtd)) + nand_dev_id != chip->read_byte (mtd))break ; }#ifdef DEBUG
include/linux/mtd/nand.h +69 -0
81 lines not on this page · raw message
--
1.7.1
PATCH v3 1/1 NAND: add support for reading ONFI page table
Quoted 6 lines · On Mon, 14 Feb 2011 16:48:01 +0100 Florian Fainelli <[email protected]> wrote:
From: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct
nand_chiponfi_versionmember contains the supported ONFI version, 0 otherwise.
Quoted 6 lines
This allows NAND drivers past
nand_scan_identto set the best timings for the NAND chip.Signed-off-by Florian Fainelli <[email protected]>---
Patch against your 'next' branch
The 'next' branch is old, since I haven't pushed anything to it yet this cycle. Base it on Wolfgang's 'next'.
Quoted 23 lines
Changes since v1:
- ifdef out ONFI detection code aroundCONFIG_SYS_NAND_ONFI_DETECTION
- removed bogus comment
- fixed busw variable usage
- move non-ONFI detection code to its own function
- fixed stylistic issues spotted by ScottChanges since v2:
- reduce lenght of some lines down to 80 columns
- changechip->optionsconsistently wrt to ONFI detected or not
- removed extra spacesdrivers/mtd/nand/nand_base.c +3
-0@@ -2409,15 +2409,137 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; } +#ifdef CONFIG_SYS_NAND_ONFI_DETECTION +static u16 onfi_crc16 (u16 crc,u8 const *p,size_t len) +{
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2424
Quoted 10 lines
drivers/mtd/nand/nand_base.c +10
-0+int i; + +while (len--) { + crc ^= *p++ <<8 ; +for (i =0 ; i <8 ; i++) + crc = (crc <<1 ) ^ ((crc &0x8000 ) ?0x8005 :0 ); + } + +return crc; +}
Is this different from what's in lib/crc16.c (other than appearing to have made a different speed/size tradeoff)?
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2425
Quoted 1 line
drivers/mtd/nand/nand_base.c +1
-0+#define ONFI_CRC_BASE 0x4F4E
Is this ONFI-specific, or standard for crc16?
Quoted 8 lines
drivers/mtd/nand/nand_base.c +8
-0+ +/* +* 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) +{
[snip]
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2485
Quoted 2 lines
drivers/mtd/nand/nand_base.c +2
-0+ chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |=NAND_NO_READRDY &NAND_CHIPOPTIONS_MSK ;
Won't this get overwritten by this later?
drivers/mtd/nand/nand_base.c static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, · line 2611
Quoted 3 lines
drivers/mtd/nand/nand_base.c +3
-0+/* Get chip options, preserve non chip based options */ + chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |= type->options &NAND_CHIPOPTIONS_MSK ;
-Scott
PATCH v3 1/1 NAND: add support for reading ONFI page table
Dear Scott Wood,
Quoted 3 lines · In message <[email protected]> you wrote:
The 'next' branch is old, since I haven't pushed anything to it yet this cycle. Base it on Wolfgang's 'next'.
I don't have a "next" yet. I will create it when -rc2 is out.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Plans break down. You cannot plan the future. Only presumptuous fools plan. The wise man _steers_. - Terry Pratchett, _Making_Money_
PATCH v3 1/1 NAND: add support for reading ONFI page table
In reply to Scott WoodHello Scott,
(sorry for the lag in answering)
Quoted 42 lines · On Tuesday 15 February 2011 00:46:07 Scott Wood wrote:
On Mon, 14 Feb 2011 16:48:01 +0100
Quoted 6 lines · Florian Fainelli
From: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct
nand_chiponfi_versionmember contains the supported ONFI version, 0 otherwise.Quoted 6 lines
This allows NAND drivers past
nand_scan_identto set the best timings for the NAND chip.Signed-off-by Florian Fainelli <[email protected]>---
Patch against your 'next' branchThe 'next' branch is old, since I haven't pushed anything to it yet this cycle. Base it on Wolfgang's 'next'.
Quoted 23 lines
Changes since v1:
- ifdef out ONFI detection code aroundCONFIG_SYS_NAND_ONFI_DETECTION
- removed bogus comment
- fixed busw variable usage
- move non-ONFI detection code to its own function
- fixed stylistic issues spotted by ScottChanges since v2:
- reduce lenght of some lines down to 80 columns
- changechip->optionsconsistently wrt to ONFI detected or not
- removed extra spacesdrivers/mtd/nand/nand_base.c +0
-0@@ -2409,15 +2409,137 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; }
Quoted 16 lines
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2424
Quoted 13 lines
drivers/mtd/nand/nand_base.c +13
-0+#ifdef CONFIG_SYS_NAND_ONFI_DETECTION +static u16 onfi_crc16 (u16 crc,u8 const *p,size_t len) +{ +int i; + +while (len--) { + crc ^= *p++ <<8 ; +for (i =0 ; i <8 ; i++) + crc = (crc <<1 ) ^ ((crc &0x8000 ) ?0x8005 :0 ); + } + +return crc; +}Is this different from what's in
lib/crc16.c(other than appearing to have made a different speed/size tradeoff)?
Yes it is a different version of the CRC16 function.
Quoted 16 lines
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip · line 2428
Quoted 2 lines
drivers/mtd/nand/nand_base.c +1
-0+#define ONFI_CRC_BASE 0x4F4EIs this ONFI-specific, or standard for crc16?
Quoted 8 lines
drivers/mtd/nand/nand_base.c +3
-0+ +/* +* Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise + */
drivers/mtd/nand/nand_base.c +4
-0+static int nand_flash_detect_onfi (struct mtd_info *mtd, +struct nand_chip *chip, +int *busw) +{[snip]
Quoted 4 lines
drivers/mtd/nand/nand_base.c static void nand_set_defaults(struct nand_chip *chip, int busw) · line 2485
Quoted 2 lines
drivers/mtd/nand/nand_base.c +2
-0+ chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |=NAND_NO_READRDY &NAND_CHIPOPTIONS_MSK ;Won't this get overwritten by this later?
It will, thanks for spotting.
--
Florian
PATCH v4 1/1 NAND: add support for reading ONFI page table
In reply to Scott WoodFrom: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct nand_chip onfi_version member contains the supported ONFI version, 0 otherwise.
This allows NAND drivers past nand_scan_ident to set the best timings for the NAND chip.
---
Patch against your 'master' branch
Changes since v1:
- ifdef out ONFI detection code around CONFIG_SYS_NAND_ONFI_DETECTION
- removed bogus comment
- fixed busw variable usage
- move non-ONFI detection code to its own function
- fixed stylistic issues spotted by Scott
Changes since v2:
- reduce lenght of some lines down to 80 columns
- change chip->options consistently wrt to ONFI detected or not
- removed extra spaces
Changes since v3:
- removed chip->options modification in nand_flash_detect_onfi because it is overwritten in nand_flash_detect() later
drivers/mtd/nand/nand_base.c +143 -48
@@ -2409,15 +2409,134 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->controller = &chip->hwcontrol; } +#ifdef CONFIG_SYS_NAND_ONFI_DETECTION +static u16 onfi_crc16 (u16 crc,u8 const *p,size_t len) +{ +int i; + +while (len--) { + crc ^= *p++ <<8 ; +for (i =0 ; i <8 ; i++) + crc = (crc <<1 ) ^ ((crc &0x8000 ) ?0x8005 :0 ); + } + +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; + + 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 ; + +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 ; + +return 1 ; +} +#else +static inline int nand_flash_detect_onfi (struct mtd_info *mtd, +struct nand_chip *chip, +int *busw) +{ +return 0 ; +} +#endif + +static void nand_flash_detect_non_onfi (struct mtd_info *mtd, +struct nand_chip *chip, +const struct nand_flash_dev *type, +int *busw) +{ +/* Newer devices have all the information in additional id bytes */ +if (!type->pagesize) { +int extid; +/* The 3rd id byte holds MLC / multichip data */ + chip->cellinfo = chip->read_byte (mtd); +/* The 4th id byte is the important one */ + extid = chip->read_byte (mtd); +/* Calc pagesize */ + mtd->writesize =1024 << (extid &0x3 ); + extid >>=2 ; +/* Calc oobsize */ + mtd->oobsize = (8 << (extid &0x01 )) * (mtd->writesize >>9 ); + extid >>=2 ; +/* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 *1024 ) << (extid &0x03 ); + extid >>=2 ; +/* Get buswidth information */ + *busw = (extid &0x01 ) ?NAND_BUSWIDTH_16 :0 ; + + }else { +/* +* Old devices have chip data hardcoded in the device id table +*/ + mtd->erasesize = type->erasesize; + mtd->writesize = type->pagesize; + mtd->oobsize = mtd->writesize /32 ; + *busw = type->options &NAND_BUSWIDTH_16 ; + } +} +/* * Get the flash and manufacturer id and lookup if the type is supported */ static const struct nand_flash_dev *nand_get_flash_type (struct mtd_info *mtd,struct nand_chip *chip, -int busw,int *maf_id, +int busw, +int *maf_id,int *dev_id,const struct nand_flash_dev *type) { -int dev_id, maf_idx; +int ret, maf_idx;int tmp_id, tmp_manf;/* Select the device */
@@ -2434,7 +2553,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,/* Read manufacturer and device IDs */ *maf_id = chip->read_byte (mtd); - dev_id = chip->read_byte (mtd); + *dev_id = chip->read_byte (mtd);/* Try again to make sure, as some systems the bus-hold or other * interface concerns can cause random data which looks like a
@@ -2449,10 +2568,10 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, tmp_manf = chip->read_byte (mtd); tmp_id = chip->read_byte (mtd); -if (tmp_manf != *maf_id || tmp_id != dev_id) { +if (tmp_manf != *maf_id || tmp_id != *dev_id) {printk (KERN_INFO "%s: second ID read did not match " "%02x,%02x against %02x,%02x\n" , __func__, - *maf_id, dev_id, tmp_manf, tmp_id); + *maf_id, *dev_id, tmp_manf, tmp_id);return ERR_PTR (-ENODEV ); }
@@ -2466,10 +2585,10 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,if (!type->name) {/* supress warning if there is no nand */ if (*maf_id !=0x00 && *maf_id !=0xff && - dev_id !=0x00 && dev_id !=0xff ) + *dev_id !=0x00 && *dev_id !=0xff )printk (KERN_INFO "%s: unknown NAND device: " "Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n" , - __func__, *maf_id, dev_id); + __func__, *maf_id, *dev_id);return ERR_PTR (-ENODEV ); }
@@ -2477,35 +2596,20 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, mtd->name = type->name; chip->chipsize = (uint64_t )type->chipsize <<20 ; + chip->onfi_version =0 ; -/* Newer devices have all the information in additional id bytes */ -if (!type->pagesize) { -int extid; -/* The 3rd id byte holds MLC / multichip data */ - chip->cellinfo = chip->read_byte (mtd); -/* The 4th id byte is the important one */ - extid = chip->read_byte (mtd); -/* Calc pagesize */ - mtd->writesize =1024 << (extid &0x3 ); - extid >>=2 ; -/* Calc oobsize */ - mtd->oobsize = (8 << (extid &0x01 )) * (mtd->writesize >>9 ); - extid >>=2 ; -/* Calc blocksize. Blocksize is multiples of 64KiB */ - mtd->erasesize = (64 *1024 ) << (extid &0x03 ); - extid >>=2 ; -/* Get buswidth information */ - busw = (extid &0x01 ) ?NAND_BUSWIDTH_16 :0 ; + ret =nand_flash_detect_onfi (mtd, chip, &busw); +if (!ret) +nand_flash_detect_non_onfi (mtd, chip, type, &busw); - }else { -/* -* Old devices have chip data hardcoded in the device id table -*/ - mtd->erasesize = type->erasesize; - mtd->writesize = type->pagesize; - mtd->oobsize = mtd->writesize /32 ; - busw = type->options &NAND_BUSWIDTH_16 ; - } +/* Get chip options, preserve non chip based options */ + chip->options &= ~NAND_CHIPOPTIONS_MSK ; + chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; + +/* +* Set chip as a default. Board drivers can override it, if necessary +*/ + chip->options |=NAND_NO_AUTOINCR ;/* Try to identify manufacturer */ for (maf_idx =0 ; nand_manuf_ids[maf_idx].id !=0x0 ; maf_idx++) {
@@ -2520,7 +2624,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,if (busw != (chip->options &NAND_BUSWIDTH_16 )) {printk (KERN_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); + *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);printk (KERN_WARNING "NAND bus width %d instead %d bit\n" , (chip->options &NAND_BUSWIDTH_16 ) ?16 :8 , busw ?16 :8 );
@@ -2543,15 +2647,6 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->badblockpos = mtd->writesize >512 ?NAND_LARGE_BADBLOCK_POS :NAND_SMALL_BADBLOCK_POS ; -/* Get chip options, preserve non chip based options */ - chip->options &= ~NAND_CHIPOPTIONS_MSK ; - chip->options |= type->options &NAND_CHIPOPTIONS_MSK ; - -/* -* Set chip as a default. Board drivers can override it, if necessary -*/ - chip->options |=NAND_NO_AUTOINCR ; -/* Check if chip is a not a samsung device. Do not clear the * options for chips which are not having an extended id. */
@@ -2569,7 +2664,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->cmdfunc = nand_command_lp;MTDDEBUG (MTD_DEBUG_LEVEL0 ,"NAND device: Manufacturer ID:" -" 0x%02x, Chip ID: 0x%02x (%s %s)\n" , *maf_id, dev_id, +" 0x%02x, Chip ID: 0x%02x (%s %s)\n" , *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, type->name);return type;
@@ -2589,7 +2684,7 @@ static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,int nand_scan_ident (struct mtd_info *mtd,int maxchips,const struct nand_flash_dev *table) { -int i, busw, nand_maf_id; +int i, busw, nand_maf_id, nand_dev_id;struct nand_chip *chip = mtd->priv;const struct nand_flash_dev *type;
@@ -2599,7 +2694,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,nand_set_defaults (chip, busw);/* Read the flash type */ - type =nand_get_flash_type (mtd, chip, busw, &nand_maf_id, table); + type =nand_get_flash_type (mtd, chip, busw, &nand_maf_id, &nand_dev_id, table);if (IS_ERR (type)) {#ifndef CONFIG_SYS_NAND_QUIET_TEST
@@ -2618,7 +2713,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, chip->cmdfunc (mtd,NAND_CMD_READID ,0x00 ,-1 );/* Read manufacturer and device IDs */ if (nand_maf_id != chip->read_byte (mtd) || - type->id != chip->read_byte (mtd)) + nand_dev_id != chip->read_byte (mtd))break ; }#ifdef DEBUG
include/linux/mtd/nand.h +69 -0
81 lines not on this page · raw message
--
1.7.1
PATCH v4 1/1 NAND: add support for reading ONFI page table
Quoted 10 lines · Florian Fainelli
From: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct
nand_chiponfi_versionmember contains the supported ONFI version, 0 otherwise.This allows NAND drivers past
nand_scan_identto set the best timings for the NAND chip.Signed-off-by Florian Fainelli <[email protected]>
Applied to u-boot-nand-flash next with this change:
drivers/mtd/nand/nand_base.c +1 -1
@@ -2585,7 +2585,7 @@ static const struct nand_flash_dev *nand_get_flash_type(st type = nand_flash_ids;for (; type->name !=NULL ; type++) -if (dev_id == type->id) +if (*dev_id == type->id)break ;
-Scott
PATCH v4 1/1 NAND: add support for reading ONFI page table
Le jeudi 17 mars 2011 00:42:55, Scott Wood a ?crit :
Quoted 19 lines · Florian Fainelli
Quoted 10 lines
From: Florian Fainelli <[email protected]>
This patch adds support for reading an ONFI page parameter from a NAND device supporting it. If this is the case, struct
nand_chiponfi_versionmember contains the supported ONFI version, 0 otherwise.This allows NAND drivers past
nand_scan_identto set the best timings for the NAND chip.Signed-off-by Florian Fainelli <[email protected]>Applied to u-boot-nand-flash next with this change:
drivers/mtd/nand/nand_base.c +0
-0
drivers/mtd/nand/nand_base.c static const struct nand_flash_dev · line 2589
Quoted 6 lines
drivers/mtd/nand/nand_base.c +1
-1@@ -2585,7 +2585,7 @@ static const struct nand_flash_dev *nand_get_flash_type(st type = nand_flash_ids;for (; type->name !=NULL ; type++) -if (dev_id == type->id) +if (*dev_id == type->id)break ;
My bad, thanks for fixing this and committing the patch! --
Florian
PATCH 1/2 NAND: add NAND_CMD_PARAM (0xec) definition
In reply to Florian FainelliQuoted 9 lines · Florian Fainelli
From: Florian Fainelli <[email protected]>
This command is used to read the device ONFI parameters page.
Signed-off-by Florian Fainelli <[email protected]>---
include/linux/mtd/nand.h| 1 +1 files changed, 1 insertions(+), 0 deletions(-)
Applied to u-boot-nand-flash next
-Scott