Message ID | 1301048581-21321-4-git-send-email-b32955@freescale.com |
---|---|
State | New, archived |
Headers | show |
Hello Huang, On Friday 25 March 2011 11:22:57 Huang Shijie wrote: > This is a new database for the NANDs which is searched by the id_bytes. > > Signed-off-by: Huang Shijie <b32955@freescale.com> > --- > drivers/mtd/nand/nand_device_info.c | 154 > +++++++++++++++++++++++++++++++++++ drivers/mtd/nand/nand_device_info.h | > 83 +++++++++++++++++++ > 2 files changed, 237 insertions(+), 0 deletions(-) > create mode 100644 drivers/mtd/nand/nand_device_info.c > create mode 100644 drivers/mtd/nand/nand_device_info.h > > diff --git a/drivers/mtd/nand/nand_device_info.c > b/drivers/mtd/nand/nand_device_info.c new file mode 100644 > index 0000000..3ceec9c > --- /dev/null > +++ b/drivers/mtd/nand/nand_device_info.c > @@ -0,0 +1,154 @@ > +/* > + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. > + */ > + > +/* > + * The code contained herein is licensed under the GNU General Public > + * License. You may obtain a copy of the GNU General Public License > + * Version 2 or later at the following locations: > + * > + * http://www.opensource.org/licenses/gpl-license.html > + * http://www.gnu.org/copyleft/gpl.html > + */ > +#include <asm/sizes.h> > +#include <linux/mtd/nand.h> > + > +#include "nand_device_info.h" > + > +static const struct nand_device_info samsung_nand[] = { > + { > + .id = { 0xec, 0xd3, 0x14, 0x25, 0x64, 0xec, 0xd3, 0x14 }, > + .id_len = 8, > + .desc = "K9G8G08U0M, K9HAG08U1M", > + .attr = ATTR(MLC, 1LL * SZ_1G, 128, 2 * SZ_1K + 64, 8, 512), > + }, { > + .id = { 0xec, 0xd7, 0xd5, 0x29, 0x38, 0x41, 0xec, 0xd7 }, > + .id_len = 8, > + .desc = "K9LBG08U0D", > + .attr = ATTR(MLC, 4LL * SZ_1G, 128, 4 * SZ_1K + 218, 16, 512), > + }, { > + .id = { 0xec, 0xd5, 0x14, 0xb6, 0x74, 0xec, 0xd5, 0x14 }, > + .id_len = 8, > + .desc = "K9GAG08U0M", > + .attr = ATTR(MLC, 2LL * SZ_1G, 128, 4 * SZ_1K + 218, 16, 512), > + }, { > + /* end of the table. */ > + .id = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, > + }, > +}; Sorry, but I do not see why this is still needed. drivers/mtd/nand_ids.c should already recognize all of these chips correctly. If this is not the case for you, you should fix nand_get_flash_type() instead. > + > +/* macro to get the id bytes */ > +#define ID_GET_MFR_CODE(id) ((id)[0]) > + > +void nand_device_print_info(struct nand_device_info *info) > +{ > + unsigned i; > + const char *mfr_name; > + const char *cell_technology_name; > + uint64_t chip_size; > + const char *chip_size_units; > + unsigned page_size; > + unsigned oob_size; > + struct nand_attr *attr = &info->attr; > + > + /* Prepare the manufacturer name. */ > + mfr_name = "Unknown"; > + for (i = 0; nand_manuf_ids[i].id; i++) { > + if (nand_manuf_ids[i].id == ID_GET_MFR_CODE(info->id)) { > + mfr_name = nand_manuf_ids[i].name; > + break; > + } > + } > + > + /* Prepare the name of the cell technology. */ > + switch (attr->cell_technology) { > + case SLC: > + cell_technology_name = "SLC"; > + break; > + case MLC: > + cell_technology_name = "MLC"; > + break; > + default: > + cell_technology_name = "Unknown"; > + break; > + } > + > + /* Prepare the chip size. */ > + if ((attr->chip_size_in_bytes >= SZ_1G) && > + !(attr->chip_size_in_bytes % SZ_1G)) { > + chip_size = attr->chip_size_in_bytes / ((uint64_t) SZ_1G); > + chip_size_units = "GiB"; > + } else if ((attr->chip_size_in_bytes >= SZ_1M) && > + !(attr->chip_size_in_bytes % SZ_1M)) { > + chip_size = attr->chip_size_in_bytes / ((uint64_t) SZ_1M); > + chip_size_units = "MiB"; > + } else { > + chip_size = attr->chip_size_in_bytes; > + chip_size_units = "B"; > + } > + > + /* Prepare the page geometry. */ > + page_size = (1 << (fls(attr->page_total_size_in_bytes) - 1)); > + oob_size = attr->page_total_size_in_bytes - page_size; > + > + /* Print the infomation. */ > + pr_info("--------------------------------------\n"); > + pr_info(" NAND device infomation (RAW)\n"); > + pr_info("--------------------------------------\n"); > + pr_info("Manufacturer : %s (0x%02x)\n", mfr_name, info->id[0]); > + pr_info("Device Code : 0x%02x\n", info->id[1]); > + pr_info("Cell Technology : %s\n", cell_technology_name); > + pr_info("Chip Size : %llu %s\n", chip_size, chip_size_units); > + pr_info("Pages per Block : %u\n", attr->block_size_in_pages); > + pr_info("Page Geometry : %u+%u\n", page_size, oob_size); > + pr_info("ECC Strength : %u bits\n", attr->ecc_strength_in_bits); > + pr_info("ECC Size : %u B\n", attr->ecc_size_in_bytes); > + pr_info("Description : %s\n", info->desc); > +} > + > +static struct nand_device_info * __init > +search_table(const struct nand_device_info *table, const uint8_t id[]) > +{ > + struct nand_device_info *info = (struct nand_device_info *)table; > + > + while (ID_GET_MFR_CODE(info->id)) { > + int i; > + > + /* match all the valid id bytes. Is it too strict? */ > + for (i = 0; i < info->id_len; i++) > + if (info->id[i] != id[i]) > + break; > + > + /* found it */ > + if (i == info->id_len) > + return info; > + info++; > + } > + return NULL; > +} > + > +struct nand_device_mfr_info { > + uint8_t id; > + const struct nand_device_info *table; > +}; > + > +static const struct nand_device_mfr_info nand_device_mfr_directory[] = { > + { NAND_MFR_SAMSUNG, samsung_nand }, > + { 0, NULL }, > +}; > + > +struct nand_device_info *nand_device_get_info(const uint8_t id[]) > +{ > + uint8_t mfr_id = ID_GET_MFR_CODE(id); > + unsigned i; > + > + for (i = 0; nand_device_mfr_directory[i].id; i++) { > + if (nand_device_mfr_directory[i].id == mfr_id) { > + const struct nand_device_info *table; > + > + table = nand_device_mfr_directory[i].table; > + return search_table(table, id); > + } > + } > + return NULL; > +} > diff --git a/drivers/mtd/nand/nand_device_info.h > b/drivers/mtd/nand/nand_device_info.h new file mode 100644 > index 0000000..fe22233 > --- /dev/null > +++ b/drivers/mtd/nand/nand_device_info.h > @@ -0,0 +1,83 @@ > +/* > + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. > + */ > + > +/* > + * The code contained herein is licensed under the GNU General Public > + * License. You may obtain a copy of the GNU General Public License > + * Version 2 or later at the following locations: > + * > + * http://www.opensource.org/licenses/gpl-license.html > + * http://www.gnu.org/copyleft/gpl.html > + */ > +#ifndef __DRIVERS_NAND_DEVICE_INFO_H > +#define __DRIVERS_NAND_DEVICE_INFO_H > + > +enum nand_device_cell_technology { > + SLC = 0, > + MLC = 1, > +}; > + > +/** > + * @cell_technology: The storage cell technology. > + * @chip_size_in_bytes: The total size of the storage behind a > single + * chip select, in bytes. Notice that > this is *not* + * necessarily the total size > of the storage in a + * *package*, which may > contain several chips. + * @block_size_in_pages: The number of pages > in a block. > + * @page_total_size_in_bytes: The total size of a page, in bytes, > including + * both the data and the OOB. > + * @ecc_strength_in_bits: The strength of the ECC called for by the > + * manufacturer, in number of correctable > bits. + * @ecc_size_in_bytes: The size of the data block over > which the + * manufacturer calls for the given > ECC algorithm + * and strength. > + */ > +struct nand_attr { > + /* Technology */ > + enum nand_device_cell_technology cell_technology; > + > + /* Geometry */ > + uint64_t chip_size_in_bytes; > + uint32_t block_size_in_pages; > + uint32_t page_total_size_in_bytes; > + > + /* ECC */ > + uint16_t ecc_strength_in_bits; > + uint16_t ecc_size_in_bytes; > +}; > + > +#define ID_BYTES (8) > +/* > + * struct nand_device_info - Information about a single NAND Flash device. > + * > + * This structure contains all the *essential* information about a NAND > Flash + * device, derived from the device's data sheet. > + */ > +struct nand_device_info { > + /* id */ > + uint8_t id[ID_BYTES]; > + unsigned int id_len; > + > + /* Description */ > + const char *desc; > + > + /* attribute*/ > + struct nand_attr attr; > +}; > + > +/* macro for the NAND attribute */ > +#define ATTR(_a, _b, _c, _d, _e, _f) \ > + { \ > + .cell_technology = (_a), \ > + .chip_size_in_bytes = (_b), \ > + .block_size_in_pages = (_c), \ > + .page_total_size_in_bytes = (_d), \ > + .ecc_strength_in_bits = (_e), \ > + .ecc_size_in_bytes = (_f), \ > + } > + > +struct nand_device_info *nand_device_get_info(const uint8_t id_bytes[]); > +void nand_device_print_info(struct nand_device_info *info); > + > +#endif
Hi Florian: > Hello Huang, > > On Friday 25 March 2011 11:22:57 Huang Shijie wrote: >> This is a new database for the NANDs which is searched by the id_bytes. >> >> Signed-off-by: Huang Shijie<b32955@freescale.com> >> --- >> drivers/mtd/nand/nand_device_info.c | 154 >> +++++++++++++++++++++++++++++++++++ drivers/mtd/nand/nand_device_info.h | >> 83 +++++++++++++++++++ >> 2 files changed, 237 insertions(+), 0 deletions(-) >> create mode 100644 drivers/mtd/nand/nand_device_info.c >> create mode 100644 drivers/mtd/nand/nand_device_info.h >> >> diff --git a/drivers/mtd/nand/nand_device_info.c >> b/drivers/mtd/nand/nand_device_info.c new file mode 100644 >> index 0000000..3ceec9c >> --- /dev/null >> +++ b/drivers/mtd/nand/nand_device_info.c >> @@ -0,0 +1,154 @@ >> +/* >> + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. >> + */ >> + >> +/* >> + * The code contained herein is licensed under the GNU General Public >> + * License. You may obtain a copy of the GNU General Public License >> + * Version 2 or later at the following locations: >> + * >> + * http://www.opensource.org/licenses/gpl-license.html >> + * http://www.gnu.org/copyleft/gpl.html >> + */ >> +#include<asm/sizes.h> >> +#include<linux/mtd/nand.h> >> + >> +#include "nand_device_info.h" >> + >> +static const struct nand_device_info samsung_nand[] = { >> + { >> + .id = { 0xec, 0xd3, 0x14, 0x25, 0x64, 0xec, 0xd3, 0x14 }, >> + .id_len = 8, >> + .desc = "K9G8G08U0M, K9HAG08U1M", >> + .attr = ATTR(MLC, 1LL * SZ_1G, 128, 2 * SZ_1K + 64, 8, 512), >> + }, { >> + .id = { 0xec, 0xd7, 0xd5, 0x29, 0x38, 0x41, 0xec, 0xd7 }, >> + .id_len = 8, >> + .desc = "K9LBG08U0D", >> + .attr = ATTR(MLC, 4LL * SZ_1G, 128, 4 * SZ_1K + 218, 16, 512), >> + }, { >> + .id = { 0xec, 0xd5, 0x14, 0xb6, 0x74, 0xec, 0xd5, 0x14 }, >> + .id_len = 8, >> + .desc = "K9GAG08U0M", >> + .attr = ATTR(MLC, 2LL * SZ_1G, 128, 4 * SZ_1K + 218, 16, 512), >> + }, { >> + /* end of the table. */ >> + .id = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, >> + }, >> +}; > Sorry, but I do not see why this is still needed. drivers/mtd/nand_ids.c > should already recognize all of these chips correctly. If this is not the case > for you, you should fix nand_get_flash_type() instead. > These nands are only a example. I have other nands to add in future. I will fix nand_get_flash_type() in future, not now. thanks Btw : I forget to add the `busw` field in my nand_device_info{}. >> + >> +/* macro to get the id bytes */ >> +#define ID_GET_MFR_CODE(id) ((id)[0]) >> + >> +void nand_device_print_info(struct nand_device_info *info) >> +{ >> + unsigned i; >> + const char *mfr_name; >> + const char *cell_technology_name; >> + uint64_t chip_size; >> + const char *chip_size_units; >> + unsigned page_size; >> + unsigned oob_size; >> + struct nand_attr *attr =&info->attr; >> + >> + /* Prepare the manufacturer name. */ >> + mfr_name = "Unknown"; >> + for (i = 0; nand_manuf_ids[i].id; i++) { >> + if (nand_manuf_ids[i].id == ID_GET_MFR_CODE(info->id)) { >> + mfr_name = nand_manuf_ids[i].name; >> + break; >> + } >> + } >> + >> + /* Prepare the name of the cell technology. */ >> + switch (attr->cell_technology) { >> + case SLC: >> + cell_technology_name = "SLC"; >> + break; >> + case MLC: >> + cell_technology_name = "MLC"; >> + break; >> + default: >> + cell_technology_name = "Unknown"; >> + break; >> + } >> + >> + /* Prepare the chip size. */ >> + if ((attr->chip_size_in_bytes>= SZ_1G)&& >> + !(attr->chip_size_in_bytes % SZ_1G)) { >> + chip_size = attr->chip_size_in_bytes / ((uint64_t) SZ_1G); >> + chip_size_units = "GiB"; >> + } else if ((attr->chip_size_in_bytes>= SZ_1M)&& >> + !(attr->chip_size_in_bytes % SZ_1M)) { >> + chip_size = attr->chip_size_in_bytes / ((uint64_t) SZ_1M); >> + chip_size_units = "MiB"; >> + } else { >> + chip_size = attr->chip_size_in_bytes; >> + chip_size_units = "B"; >> + } >> + >> + /* Prepare the page geometry. */ >> + page_size = (1<< (fls(attr->page_total_size_in_bytes) - 1)); >> + oob_size = attr->page_total_size_in_bytes - page_size; >> + >> + /* Print the infomation. */ >> + pr_info("--------------------------------------\n"); >> + pr_info(" NAND device infomation (RAW)\n"); >> + pr_info("--------------------------------------\n"); >> + pr_info("Manufacturer : %s (0x%02x)\n", mfr_name, info->id[0]); >> + pr_info("Device Code : 0x%02x\n", info->id[1]); >> + pr_info("Cell Technology : %s\n", cell_technology_name); >> + pr_info("Chip Size : %llu %s\n", chip_size, chip_size_units); >> + pr_info("Pages per Block : %u\n", attr->block_size_in_pages); >> + pr_info("Page Geometry : %u+%u\n", page_size, oob_size); >> + pr_info("ECC Strength : %u bits\n", attr->ecc_strength_in_bits); >> + pr_info("ECC Size : %u B\n", attr->ecc_size_in_bytes); >> + pr_info("Description : %s\n", info->desc); >> +} >> + >> +static struct nand_device_info * __init >> +search_table(const struct nand_device_info *table, const uint8_t id[]) >> +{ >> + struct nand_device_info *info = (struct nand_device_info *)table; >> + >> + while (ID_GET_MFR_CODE(info->id)) { >> + int i; >> + >> + /* match all the valid id bytes. Is it too strict? */ >> + for (i = 0; i< info->id_len; i++) >> + if (info->id[i] != id[i]) >> + break; >> + >> + /* found it */ >> + if (i == info->id_len) >> + return info; >> + info++; >> + } >> + return NULL; >> +} >> + >> +struct nand_device_mfr_info { >> + uint8_t id; >> + const struct nand_device_info *table; >> +}; >> + >> +static const struct nand_device_mfr_info nand_device_mfr_directory[] = { >> + { NAND_MFR_SAMSUNG, samsung_nand }, >> + { 0, NULL }, >> +}; >> + >> +struct nand_device_info *nand_device_get_info(const uint8_t id[]) >> +{ >> + uint8_t mfr_id = ID_GET_MFR_CODE(id); >> + unsigned i; >> + >> + for (i = 0; nand_device_mfr_directory[i].id; i++) { >> + if (nand_device_mfr_directory[i].id == mfr_id) { >> + const struct nand_device_info *table; >> + >> + table = nand_device_mfr_directory[i].table; >> + return search_table(table, id); >> + } >> + } >> + return NULL; >> +} >> diff --git a/drivers/mtd/nand/nand_device_info.h >> b/drivers/mtd/nand/nand_device_info.h new file mode 100644 >> index 0000000..fe22233 >> --- /dev/null >> +++ b/drivers/mtd/nand/nand_device_info.h >> @@ -0,0 +1,83 @@ >> +/* >> + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. >> + */ >> + >> +/* >> + * The code contained herein is licensed under the GNU General Public >> + * License. You may obtain a copy of the GNU General Public License >> + * Version 2 or later at the following locations: >> + * >> + * http://www.opensource.org/licenses/gpl-license.html >> + * http://www.gnu.org/copyleft/gpl.html >> + */ >> +#ifndef __DRIVERS_NAND_DEVICE_INFO_H >> +#define __DRIVERS_NAND_DEVICE_INFO_H >> + >> +enum nand_device_cell_technology { >> + SLC = 0, >> + MLC = 1, >> +}; >> + >> +/** >> + * @cell_technology: The storage cell technology. >> + * @chip_size_in_bytes: The total size of the storage behind a >> single + * chip select, in bytes. Notice that >> this is *not* + * necessarily the total size >> of the storage in a + * *package*, which may >> contain several chips. + * @block_size_in_pages: The number of pages >> in a block. >> + * @page_total_size_in_bytes: The total size of a page, in bytes, >> including + * both the data and the OOB. >> + * @ecc_strength_in_bits: The strength of the ECC called for by the >> + * manufacturer, in number of correctable >> bits. + * @ecc_size_in_bytes: The size of the data block over >> which the + * manufacturer calls for the given >> ECC algorithm + * and strength. >> + */ >> +struct nand_attr { >> + /* Technology */ >> + enum nand_device_cell_technology cell_technology; >> + >> + /* Geometry */ >> + uint64_t chip_size_in_bytes; >> + uint32_t block_size_in_pages; >> + uint32_t page_total_size_in_bytes; >> + >> + /* ECC */ >> + uint16_t ecc_strength_in_bits; >> + uint16_t ecc_size_in_bytes; >> +}; >> + >> +#define ID_BYTES (8) >> +/* >> + * struct nand_device_info - Information about a single NAND Flash device. >> + * >> + * This structure contains all the *essential* information about a NAND >> Flash + * device, derived from the device's data sheet. >> + */ >> +struct nand_device_info { >> + /* id */ >> + uint8_t id[ID_BYTES]; >> + unsigned int id_len; >> + >> + /* Description */ >> + const char *desc; >> + >> + /* attribute*/ >> + struct nand_attr attr; >> +}; >> + >> +/* macro for the NAND attribute */ >> +#define ATTR(_a, _b, _c, _d, _e, _f) \ >> + { \ >> + .cell_technology = (_a), \ >> + .chip_size_in_bytes = (_b), \ >> + .block_size_in_pages = (_c), \ >> + .page_total_size_in_bytes = (_d), \ >> + .ecc_strength_in_bits = (_e), \ >> + .ecc_size_in_bytes = (_f), \ >> + } >> + >> +struct nand_device_info *nand_device_get_info(const uint8_t id_bytes[]); >> +void nand_device_print_info(struct nand_device_info *info); >> + >> +#endif Best Regards Huang Shijie
On Mon, 2011-03-28 at 10:00 +0800, Huang Shijie wrote: > These nands are only a example. I have other nands to add in future. > I will fix nand_get_flash_type() in future, not now. thanks > > Btw : I forget to add the `busw` field in my nand_device_info{}. I think you should consider this as a merge criteria - I do not think we can allow people to have their own NAND data-bases, even "for now".
Hi: > On Mon, 2011-03-28 at 10:00 +0800, Huang Shijie wrote: >> These nands are only a example. I have other nands to add in future. >> I will fix nand_get_flash_type() in future, not now. thanks >> >> Btw : I forget to add the `busw` field in my nand_device_info{}. > I think you should consider this as a merge criteria - I do not think we > can allow people to have their own NAND data-bases, even "for now". > In the version 3, I want to replace the old database. Thanks Huang Shijie
diff --git a/drivers/mtd/nand/nand_device_info.c b/drivers/mtd/nand/nand_device_info.c new file mode 100644 index 0000000..3ceec9c --- /dev/null +++ b/drivers/mtd/nand/nand_device_info.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#include <asm/sizes.h> +#include <linux/mtd/nand.h> + +#include "nand_device_info.h" + +static const struct nand_device_info samsung_nand[] = { + { + .id = { 0xec, 0xd3, 0x14, 0x25, 0x64, 0xec, 0xd3, 0x14 }, + .id_len = 8, + .desc = "K9G8G08U0M, K9HAG08U1M", + .attr = ATTR(MLC, 1LL * SZ_1G, 128, 2 * SZ_1K + 64, 8, 512), + }, { + .id = { 0xec, 0xd7, 0xd5, 0x29, 0x38, 0x41, 0xec, 0xd7 }, + .id_len = 8, + .desc = "K9LBG08U0D", + .attr = ATTR(MLC, 4LL * SZ_1G, 128, 4 * SZ_1K + 218, 16, 512), + }, { + .id = { 0xec, 0xd5, 0x14, 0xb6, 0x74, 0xec, 0xd5, 0x14 }, + .id_len = 8, + .desc = "K9GAG08U0M", + .attr = ATTR(MLC, 2LL * SZ_1G, 128, 4 * SZ_1K + 218, 16, 512), + }, { + /* end of the table. */ + .id = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + }, +}; + +/* macro to get the id bytes */ +#define ID_GET_MFR_CODE(id) ((id)[0]) + +void nand_device_print_info(struct nand_device_info *info) +{ + unsigned i; + const char *mfr_name; + const char *cell_technology_name; + uint64_t chip_size; + const char *chip_size_units; + unsigned page_size; + unsigned oob_size; + struct nand_attr *attr = &info->attr; + + /* Prepare the manufacturer name. */ + mfr_name = "Unknown"; + for (i = 0; nand_manuf_ids[i].id; i++) { + if (nand_manuf_ids[i].id == ID_GET_MFR_CODE(info->id)) { + mfr_name = nand_manuf_ids[i].name; + break; + } + } + + /* Prepare the name of the cell technology. */ + switch (attr->cell_technology) { + case SLC: + cell_technology_name = "SLC"; + break; + case MLC: + cell_technology_name = "MLC"; + break; + default: + cell_technology_name = "Unknown"; + break; + } + + /* Prepare the chip size. */ + if ((attr->chip_size_in_bytes >= SZ_1G) && + !(attr->chip_size_in_bytes % SZ_1G)) { + chip_size = attr->chip_size_in_bytes / ((uint64_t) SZ_1G); + chip_size_units = "GiB"; + } else if ((attr->chip_size_in_bytes >= SZ_1M) && + !(attr->chip_size_in_bytes % SZ_1M)) { + chip_size = attr->chip_size_in_bytes / ((uint64_t) SZ_1M); + chip_size_units = "MiB"; + } else { + chip_size = attr->chip_size_in_bytes; + chip_size_units = "B"; + } + + /* Prepare the page geometry. */ + page_size = (1 << (fls(attr->page_total_size_in_bytes) - 1)); + oob_size = attr->page_total_size_in_bytes - page_size; + + /* Print the infomation. */ + pr_info("--------------------------------------\n"); + pr_info(" NAND device infomation (RAW)\n"); + pr_info("--------------------------------------\n"); + pr_info("Manufacturer : %s (0x%02x)\n", mfr_name, info->id[0]); + pr_info("Device Code : 0x%02x\n", info->id[1]); + pr_info("Cell Technology : %s\n", cell_technology_name); + pr_info("Chip Size : %llu %s\n", chip_size, chip_size_units); + pr_info("Pages per Block : %u\n", attr->block_size_in_pages); + pr_info("Page Geometry : %u+%u\n", page_size, oob_size); + pr_info("ECC Strength : %u bits\n", attr->ecc_strength_in_bits); + pr_info("ECC Size : %u B\n", attr->ecc_size_in_bytes); + pr_info("Description : %s\n", info->desc); +} + +static struct nand_device_info * __init +search_table(const struct nand_device_info *table, const uint8_t id[]) +{ + struct nand_device_info *info = (struct nand_device_info *)table; + + while (ID_GET_MFR_CODE(info->id)) { + int i; + + /* match all the valid id bytes. Is it too strict? */ + for (i = 0; i < info->id_len; i++) + if (info->id[i] != id[i]) + break; + + /* found it */ + if (i == info->id_len) + return info; + info++; + } + return NULL; +} + +struct nand_device_mfr_info { + uint8_t id; + const struct nand_device_info *table; +}; + +static const struct nand_device_mfr_info nand_device_mfr_directory[] = { + { NAND_MFR_SAMSUNG, samsung_nand }, + { 0, NULL }, +}; + +struct nand_device_info *nand_device_get_info(const uint8_t id[]) +{ + uint8_t mfr_id = ID_GET_MFR_CODE(id); + unsigned i; + + for (i = 0; nand_device_mfr_directory[i].id; i++) { + if (nand_device_mfr_directory[i].id == mfr_id) { + const struct nand_device_info *table; + + table = nand_device_mfr_directory[i].table; + return search_table(table, id); + } + } + return NULL; +} diff --git a/drivers/mtd/nand/nand_device_info.h b/drivers/mtd/nand/nand_device_info.h new file mode 100644 index 0000000..fe22233 --- /dev/null +++ b/drivers/mtd/nand/nand_device_info.h @@ -0,0 +1,83 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __DRIVERS_NAND_DEVICE_INFO_H +#define __DRIVERS_NAND_DEVICE_INFO_H + +enum nand_device_cell_technology { + SLC = 0, + MLC = 1, +}; + +/** + * @cell_technology: The storage cell technology. + * @chip_size_in_bytes: The total size of the storage behind a single + * chip select, in bytes. Notice that this is *not* + * necessarily the total size of the storage in a + * *package*, which may contain several chips. + * @block_size_in_pages: The number of pages in a block. + * @page_total_size_in_bytes: The total size of a page, in bytes, including + * both the data and the OOB. + * @ecc_strength_in_bits: The strength of the ECC called for by the + * manufacturer, in number of correctable bits. + * @ecc_size_in_bytes: The size of the data block over which the + * manufacturer calls for the given ECC algorithm + * and strength. + */ +struct nand_attr { + /* Technology */ + enum nand_device_cell_technology cell_technology; + + /* Geometry */ + uint64_t chip_size_in_bytes; + uint32_t block_size_in_pages; + uint32_t page_total_size_in_bytes; + + /* ECC */ + uint16_t ecc_strength_in_bits; + uint16_t ecc_size_in_bytes; +}; + +#define ID_BYTES (8) +/* + * struct nand_device_info - Information about a single NAND Flash device. + * + * This structure contains all the *essential* information about a NAND Flash + * device, derived from the device's data sheet. + */ +struct nand_device_info { + /* id */ + uint8_t id[ID_BYTES]; + unsigned int id_len; + + /* Description */ + const char *desc; + + /* attribute*/ + struct nand_attr attr; +}; + +/* macro for the NAND attribute */ +#define ATTR(_a, _b, _c, _d, _e, _f) \ + { \ + .cell_technology = (_a), \ + .chip_size_in_bytes = (_b), \ + .block_size_in_pages = (_c), \ + .page_total_size_in_bytes = (_d), \ + .ecc_strength_in_bits = (_e), \ + .ecc_size_in_bytes = (_f), \ + } + +struct nand_device_info *nand_device_get_info(const uint8_t id_bytes[]); +void nand_device_print_info(struct nand_device_info *info); + +#endif
This is a new database for the NANDs which is searched by the id_bytes. Signed-off-by: Huang Shijie <b32955@freescale.com> --- drivers/mtd/nand/nand_device_info.c | 154 +++++++++++++++++++++++++++++++++++ drivers/mtd/nand/nand_device_info.h | 83 +++++++++++++++++++ 2 files changed, 237 insertions(+), 0 deletions(-) create mode 100644 drivers/mtd/nand/nand_device_info.c create mode 100644 drivers/mtd/nand/nand_device_info.h