diff options
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 64 | ||||
-rw-r--r-- | include/linux/mtd/nand.h | 2 |
2 files changed, 45 insertions, 21 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index b9dc65c7253c..85891dcc27ad 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -2774,8 +2774,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2774 | int busw, int *maf_id, | 2774 | int busw, int *maf_id, |
2775 | struct nand_flash_dev *type) | 2775 | struct nand_flash_dev *type) |
2776 | { | 2776 | { |
2777 | int dev_id, maf_idx; | 2777 | int i, dev_id, maf_idx; |
2778 | int tmp_id, tmp_manf; | 2778 | u8 id_data[8]; |
2779 | 2779 | ||
2780 | /* Select the device */ | 2780 | /* Select the device */ |
2781 | chip->select_chip(mtd, 0); | 2781 | chip->select_chip(mtd, 0); |
@@ -2801,15 +2801,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2801 | 2801 | ||
2802 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | 2802 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); |
2803 | 2803 | ||
2804 | /* Read manufacturer and device IDs */ | 2804 | /* Read entire ID string */ |
2805 | 2805 | ||
2806 | tmp_manf = chip->read_byte(mtd); | 2806 | for (i = 0; i < 8; i++) |
2807 | tmp_id = chip->read_byte(mtd); | 2807 | id_data[i] = chip->read_byte(mtd); |
2808 | 2808 | ||
2809 | if (tmp_manf != *maf_id || tmp_id != dev_id) { | 2809 | if (id_data[0] != *maf_id || id_data[1] != dev_id) { |
2810 | printk(KERN_INFO "%s: second ID read did not match " | 2810 | printk(KERN_INFO "%s: second ID read did not match " |
2811 | "%02x,%02x against %02x,%02x\n", __func__, | 2811 | "%02x,%02x against %02x,%02x\n", __func__, |
2812 | *maf_id, dev_id, tmp_manf, tmp_id); | 2812 | *maf_id, dev_id, id_data[0], id_data[1]); |
2813 | return ERR_PTR(-ENODEV); | 2813 | return ERR_PTR(-ENODEV); |
2814 | } | 2814 | } |
2815 | 2815 | ||
@@ -2832,21 +2832,45 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
2832 | if (!type->pagesize) { | 2832 | if (!type->pagesize) { |
2833 | int extid; | 2833 | int extid; |
2834 | /* The 3rd id byte holds MLC / multichip data */ | 2834 | /* The 3rd id byte holds MLC / multichip data */ |
2835 | chip->cellinfo = chip->read_byte(mtd); | 2835 | chip->cellinfo = id_data[2]; |
2836 | /* The 4th id byte is the important one */ | 2836 | /* The 4th id byte is the important one */ |
2837 | extid = chip->read_byte(mtd); | 2837 | extid = id_data[3]; |
2838 | /* Calc pagesize */ | ||
2839 | mtd->writesize = 1024 << (extid & 0x3); | ||
2840 | extid >>= 2; | ||
2841 | /* Calc oobsize */ | ||
2842 | mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); | ||
2843 | extid >>= 2; | ||
2844 | /* Calc blocksize. Blocksize is multiples of 64KiB */ | ||
2845 | mtd->erasesize = (64 * 1024) << (extid & 0x03); | ||
2846 | extid >>= 2; | ||
2847 | /* Get buswidth information */ | ||
2848 | busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; | ||
2849 | 2838 | ||
2839 | /* | ||
2840 | * Field definitions are in the following datasheets: | ||
2841 | * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) | ||
2842 | * New style (6 byte ID): Samsung K9GAG08U0D (p.40) | ||
2843 | * | ||
2844 | * Check for wraparound + Samsung ID + nonzero 6th byte | ||
2845 | * to decide what to do. | ||
2846 | */ | ||
2847 | if (id_data[0] == id_data[6] && id_data[1] == id_data[7] && | ||
2848 | id_data[0] == NAND_MFR_SAMSUNG && | ||
2849 | id_data[5] != 0x00) { | ||
2850 | /* Calc pagesize */ | ||
2851 | mtd->writesize = 2048 << (extid & 0x03); | ||
2852 | extid >>= 2; | ||
2853 | /* Calc oobsize */ | ||
2854 | mtd->oobsize = (extid & 0x03) == 0x01 ? 128 : 218; | ||
2855 | extid >>= 2; | ||
2856 | /* Calc blocksize */ | ||
2857 | mtd->erasesize = (128 * 1024) << | ||
2858 | (((extid >> 1) & 0x04) | (extid & 0x03)); | ||
2859 | busw = 0; | ||
2860 | } else { | ||
2861 | /* Calc pagesize */ | ||
2862 | mtd->writesize = 1024 << (extid & 0x03); | ||
2863 | extid >>= 2; | ||
2864 | /* Calc oobsize */ | ||
2865 | mtd->oobsize = (8 << (extid & 0x01)) * | ||
2866 | (mtd->writesize >> 9); | ||
2867 | extid >>= 2; | ||
2868 | /* Calc blocksize. Blocksize is multiples of 64KiB */ | ||
2869 | mtd->erasesize = (64 * 1024) << (extid & 0x03); | ||
2870 | extid >>= 2; | ||
2871 | /* Get buswidth information */ | ||
2872 | busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; | ||
2873 | } | ||
2850 | } else { | 2874 | } else { |
2851 | /* | 2875 | /* |
2852 | * Old devices have chip data hardcoded in the device id table | 2876 | * Old devices have chip data hardcoded in the device id table |
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 8bdacb885f90..50f3aa00a452 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h | |||
@@ -53,7 +53,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); | |||
53 | * is supported now. If you add a chip with bigger oobsize/page | 53 | * is supported now. If you add a chip with bigger oobsize/page |
54 | * adjust this accordingly. | 54 | * adjust this accordingly. |
55 | */ | 55 | */ |
56 | #define NAND_MAX_OOBSIZE 128 | 56 | #define NAND_MAX_OOBSIZE 256 |
57 | #define NAND_MAX_PAGESIZE 4096 | 57 | #define NAND_MAX_PAGESIZE 4096 |
58 | 58 | ||
59 | /* | 59 | /* |