aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
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 /drivers/mtd
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>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/nand_base.c164
1 files changed, 134 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)