aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Fainelli <florian@openwrt.org>2010-08-30 12:32:24 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-10-24 18:46:34 -0400
commitd1e1f4e42b5df063712ca2926e50c07b95c96b96 (patch)
tree6dc4ab018397d5029690957b27d376e25d1c1f85
parent42af8b58fb5ec97214e85780db71bb9d60541fcc (diff)
mtd: nand: add support for reading ONFI parameters from NAND device
This patch adds support for reading NAND device ONFI parameters and use the ONFI informations to define its geometry. In case the device supports ONFI, the onfi_version field in struct nand_chip contains the version (BCD) and the onfi_params structure can be used by drivers to set up timings and such. We currently only support ONFI 1.0 parameters. Signed-off-by: Brian Norris <norris@broadcom.com> Signed-off-by: Matthieu Castet <matthieu.castet@parrot.com> Signed-off-by: Maxime Bizon <mbizon@freebox.fr> Signed-off-by: Florian Fainelli <ffainelli@freebox.fr> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/mtd/nand/nand_base.c164
-rw-r--r--include/linux/mtd/nand.h68
2 files changed, 202 insertions, 30 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 596ac848b46d..5b26fffc3534 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2787,14 +2787,46 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
2787} 2787}
2788 2788
2789/* 2789/*
2790 * sanitize ONFI strings so we can safely print them
2791 */
2792static void sanitize_string(uint8_t *s, size_t len)
2793{
2794 ssize_t i;
2795
2796 /* null terminate */
2797 s[len - 1] = 0;
2798
2799 /* remove non printable chars */
2800 for (i = 0; i < len - 1; i++) {
2801 if (s[i] < ' ' || s[i] > 127)
2802 s[i] = '?';
2803 }
2804
2805 /* remove trailing spaces */
2806 strim(s);
2807}
2808
2809static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
2810{
2811 int i;
2812 while (len--) {
2813 crc ^= *p++ << 8;
2814 for (i = 0; i < 8; i++)
2815 crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
2816 }
2817
2818 return crc;
2819}
2820
2821/*
2790 * Get the flash and manufacturer id and lookup if the type is supported 2822 * Get the flash and manufacturer id and lookup if the type is supported
2791 */ 2823 */
2792static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, 2824static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2793 struct nand_chip *chip, 2825 struct nand_chip *chip,
2794 int busw, int *maf_id, 2826 int busw, int *maf_id, int *dev_id,
2795 struct nand_flash_dev *type) 2827 struct nand_flash_dev *type)
2796{ 2828{
2797 int i, dev_id, maf_idx; 2829 int i, maf_idx;
2798 u8 id_data[8]; 2830 u8 id_data[8];
2799 2831
2800 /* Select the device */ 2832 /* Select the device */
@@ -2811,7 +2843,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2811 2843
2812 /* Read manufacturer and device IDs */ 2844 /* Read manufacturer and device IDs */
2813 *maf_id = chip->read_byte(mtd); 2845 *maf_id = chip->read_byte(mtd);
2814 dev_id = chip->read_byte(mtd); 2846 *dev_id = chip->read_byte(mtd);
2815 2847
2816 /* Try again to make sure, as some systems the bus-hold or other 2848 /* Try again to make sure, as some systems the bus-hold or other
2817 * interface concerns can cause random data which looks like a 2849 * interface concerns can cause random data which looks like a
@@ -2821,15 +2853,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2821 2853
2822 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); 2854 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
2823 2855
2824 /* Read entire ID string */ 2856 for (i = 0; i < 2; i++)
2825
2826 for (i = 0; i < 8; i++)
2827 id_data[i] = chip->read_byte(mtd); 2857 id_data[i] = chip->read_byte(mtd);
2828 2858
2829 if (id_data[0] != *maf_id || id_data[1] != dev_id) { 2859 if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
2830 printk(KERN_INFO "%s: second ID read did not match " 2860 printk(KERN_INFO "%s: second ID read did not match "
2831 "%02x,%02x against %02x,%02x\n", __func__, 2861 "%02x,%02x against %02x,%02x\n", __func__,
2832 *maf_id, dev_id, id_data[0], id_data[1]); 2862 *maf_id, *dev_id, id_data[0], id_data[1]);
2833 return ERR_PTR(-ENODEV); 2863 return ERR_PTR(-ENODEV);
2834 } 2864 }
2835 2865
@@ -2837,9 +2867,81 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2837 type = nand_flash_ids; 2867 type = nand_flash_ids;
2838 2868
2839 for (; type->name != NULL; type++) 2869 for (; type->name != NULL; type++)
2840 if (dev_id == type->id) 2870 if (*dev_id == type->id)
2841 break; 2871 break;
2842 2872
2873 chip->onfi_version = 0;
2874 if (!type->name || !type->pagesize) {
2875 /* try ONFI for unknow chip or LP */
2876 chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
2877 if (chip->read_byte(mtd) == 'O' &&
2878 chip->read_byte(mtd) == 'N' &&
2879 chip->read_byte(mtd) == 'F' &&
2880 chip->read_byte(mtd) == 'I') {
2881
2882 struct nand_onfi_params *p = &chip->onfi_params;
2883 int i;
2884
2885 printk(KERN_INFO "ONFI flash detected\n");
2886 chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
2887 for (i = 0; i < 3; i++) {
2888 chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
2889 if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
2890 le16_to_cpu(p->crc))
2891 {
2892 printk(KERN_INFO "ONFI param page %d valid\n", i);
2893 break;
2894 }
2895 }
2896
2897 if (i < 3) {
2898 /* check version */
2899 int val = le16_to_cpu(p->revision);
2900 if (val == 1 || val > (1 << 4))
2901 printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
2902 __func__, val);
2903 else {
2904 if (val & (1 << 4))
2905 chip->onfi_version = 22;
2906 else if (val & (1 << 3))
2907 chip->onfi_version = 21;
2908 else if (val & (1 << 2))
2909 chip->onfi_version = 20;
2910 else
2911 chip->onfi_version = 10;
2912 }
2913 }
2914
2915 if (chip->onfi_version) {
2916 sanitize_string(p->manufacturer, sizeof(p->manufacturer));
2917 sanitize_string(p->model, sizeof(p->model));
2918 if (!mtd->name)
2919 mtd->name = p->model;
2920 mtd->writesize = le32_to_cpu(p->byte_per_page);
2921 mtd->erasesize = le32_to_cpu(p->pages_per_block)*mtd->writesize;
2922 mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
2923 chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
2924 busw = 0;
2925 if (le16_to_cpu(p->features) & 1)
2926 busw = NAND_BUSWIDTH_16;
2927
2928 chip->options &= ~NAND_CHIPOPTIONS_MSK;
2929 chip->options |= (NAND_NO_READRDY |
2930 NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK;
2931
2932 goto ident_done;
2933
2934 }
2935 }
2936 }
2937
2938 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
2939
2940 /* Read entire ID string */
2941
2942 for (i = 0; i < 8; i++)
2943 id_data[i] = chip->read_byte(mtd);
2944
2843 if (!type->name) 2945 if (!type->name)
2844 return ERR_PTR(-ENODEV); 2946 return ERR_PTR(-ENODEV);
2845 2947
@@ -2927,6 +3029,21 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2927 mtd->erasesize <<= ((id_data[3] & 0x03) << 1); 3029 mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
2928 } 3030 }
2929 } 3031 }
3032 /* Get chip options, preserve non chip based options */
3033 chip->options &= ~NAND_CHIPOPTIONS_MSK;
3034 chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
3035
3036 /* Check if chip is a not a samsung device. Do not clear the
3037 * options for chips which are not having an extended id.
3038 */
3039 if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
3040 chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
3041ident_done:
3042
3043 /*
3044 * Set chip as a default. Board drivers can override it, if necessary
3045 */
3046 chip->options |= NAND_NO_AUTOINCR;
2930 3047
2931 /* Try to identify manufacturer */ 3048 /* Try to identify manufacturer */
2932 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { 3049 for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
@@ -2941,7 +3058,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2941 if (busw != (chip->options & NAND_BUSWIDTH_16)) { 3058 if (busw != (chip->options & NAND_BUSWIDTH_16)) {
2942 printk(KERN_INFO "NAND device: Manufacturer ID:" 3059 printk(KERN_INFO "NAND device: Manufacturer ID:"
2943 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, 3060 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
2944 dev_id, nand_manuf_ids[maf_idx].name, mtd->name); 3061 *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
2945 printk(KERN_WARNING "NAND bus width %d instead %d bit\n", 3062 printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
2946 (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, 3063 (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
2947 busw ? 16 : 8); 3064 busw ? 16 : 8);
@@ -2966,21 +3083,6 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2966 else 3083 else
2967 chip->badblockpos = NAND_SMALL_BADBLOCK_POS; 3084 chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
2968 3085
2969 /* Get chip options, preserve non chip based options */
2970 chip->options &= ~NAND_CHIPOPTIONS_MSK;
2971 chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
2972
2973 /*
2974 * Set chip as a default. Board drivers can override it, if necessary
2975 */
2976 chip->options |= NAND_NO_AUTOINCR;
2977
2978 /* Check if chip is a not a samsung device. Do not clear the
2979 * options for chips which are not having an extended id.
2980 */
2981 if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
2982 chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
2983
2984 /* 3086 /*
2985 * Bad block marker is stored in the last page of each block 3087 * Bad block marker is stored in the last page of each block
2986 * on Samsung and Hynix MLC devices; stored in first two pages 3088 * on Samsung and Hynix MLC devices; stored in first two pages
@@ -3021,9 +3123,11 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
3021 if (mtd->writesize > 512 && chip->cmdfunc == nand_command) 3123 if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
3022 chip->cmdfunc = nand_command_lp; 3124 chip->cmdfunc = nand_command_lp;
3023 3125
3126 /* TODO onfi flash name */
3024 printk(KERN_INFO "NAND device: Manufacturer ID:" 3127 printk(KERN_INFO "NAND device: Manufacturer ID:"
3025 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id, 3128 " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
3026 nand_manuf_ids[maf_idx].name, type->name); 3129 nand_manuf_ids[maf_idx].name,
3130 chip->onfi_version ? type->name:chip->onfi_params.model);
3027 3131
3028 return type; 3132 return type;
3029} 3133}
@@ -3042,7 +3146,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
3042int nand_scan_ident(struct mtd_info *mtd, int maxchips, 3146int nand_scan_ident(struct mtd_info *mtd, int maxchips,
3043 struct nand_flash_dev *table) 3147 struct nand_flash_dev *table)
3044{ 3148{
3045 int i, busw, nand_maf_id; 3149 int i, busw, nand_maf_id, nand_dev_id;
3046 struct nand_chip *chip = mtd->priv; 3150 struct nand_chip *chip = mtd->priv;
3047 struct nand_flash_dev *type; 3151 struct nand_flash_dev *type;
3048 3152
@@ -3052,7 +3156,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
3052 nand_set_defaults(chip, busw); 3156 nand_set_defaults(chip, busw);
3053 3157
3054 /* Read the flash type */ 3158 /* Read the flash type */
3055 type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id, table); 3159 type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id, &nand_dev_id, table);
3056 3160
3057 if (IS_ERR(type)) { 3161 if (IS_ERR(type)) {
3058 if (!(chip->options & NAND_SCAN_SILENT_NODEV)) 3162 if (!(chip->options & NAND_SCAN_SILENT_NODEV))
@@ -3070,7 +3174,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
3070 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); 3174 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
3071 /* Read manufacturer and device IDs */ 3175 /* Read manufacturer and device IDs */
3072 if (nand_maf_id != chip->read_byte(mtd) || 3176 if (nand_maf_id != chip->read_byte(mtd) ||
3073 type->id != chip->read_byte(mtd)) 3177 nand_dev_id != chip->read_byte(mtd))
3074 break; 3178 break;
3075 } 3179 }
3076 if (i > 1) 3180 if (i > 1)
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 29656a3f9331..7666c42235c7 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -228,6 +228,69 @@ typedef enum {
228/* Keep gcc happy */ 228/* Keep gcc happy */
229struct nand_chip; 229struct nand_chip;
230 230
231struct nand_onfi_params {
232 /* rev info and features block */
233 u8 sig[4]; /* 'O' 'N' 'F' 'I' */
234 __le16 revision;
235 __le16 features;
236 __le16 opt_cmd;
237 u8 reserved[22];
238
239 /* manufacturer information block */
240 char manufacturer[12];
241 char model[20];
242 u8 jedec_id;
243 __le16 date_code;
244 u8 reserved2[13];
245
246 /* memory organization block */
247 __le32 byte_per_page;
248 __le16 spare_bytes_per_page;
249 __le32 data_bytes_per_ppage;
250 __le16 spare_bytes_per_ppage;
251 __le32 pages_per_block;
252 __le32 blocks_per_lun;
253 u8 lun_count;
254 u8 addr_cycles;
255 u8 bits_per_cell;
256 __le16 bb_per_lun;
257 __le16 block_endurance;
258 u8 guaranteed_good_blocks;
259 __le16 guaranteed_block_endurance;
260 u8 programs_per_page;
261 u8 ppage_attr;
262 u8 ecc_bits;
263 u8 interleaved_bits;
264 u8 interleaved_ops;
265 u8 reserved3[13];
266
267 /* electrical parameter block */
268 u8 io_pin_capacitance_max;
269 __le16 async_timing_mode;
270 __le16 program_cache_timing_mode;
271 __le16 t_prog;
272 __le16 t_bers;
273 __le16 t_r;
274 __le16 t_ccs;
275 __le16 src_sync_timing_mode;
276 __le16 src_ssync_features;
277 __le16 clk_pin_capacitance_typ;
278 __le16 io_pin_capacitance_typ;
279 __le16 input_pin_capacitance_typ;
280 u8 input_pin_capacitance_max;
281 u8 driver_strenght_support;
282 __le16 t_int_r;
283 __le16 t_ald;
284 u8 reserved4[7];
285
286 /* vendor */
287 u8 reserved5[90];
288
289 __le16 crc;
290} __attribute__((packed));
291
292#define ONFI_CRC_BASE 0x4F4E
293
231/** 294/**
232 * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices 295 * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
233 * @lock: protection lock 296 * @lock: protection lock
@@ -360,6 +423,8 @@ struct nand_buffers {
360 * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 423 * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
361 * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf 424 * @pagebuf: [INTERN] holds the pagenumber which is currently in data_buf
362 * @subpagesize: [INTERN] holds the subpagesize 425 * @subpagesize: [INTERN] holds the subpagesize
426 * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded), non 0 if ONFI supported
427 * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is supported, 0 otherwise
363 * @ecclayout: [REPLACEABLE] the default ecc placement scheme 428 * @ecclayout: [REPLACEABLE] the default ecc placement scheme
364 * @bbt: [INTERN] bad block table pointer 429 * @bbt: [INTERN] bad block table pointer
365 * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup 430 * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup
@@ -412,6 +477,9 @@ struct nand_chip {
412 int badblockpos; 477 int badblockpos;
413 int badblockbits; 478 int badblockbits;
414 479
480 int onfi_version;
481 struct nand_onfi_params onfi_params;
482
415 flstate_t state; 483 flstate_t state;
416 484
417 uint8_t *oob_poi; 485 uint8_t *oob_poi;