aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/nand_base.c132
1 files changed, 71 insertions, 61 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 5b26fffc353..5b96f621f7c 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2819,6 +2819,72 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
2819} 2819}
2820 2820
2821/* 2821/*
2822 * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
2823 */
2824static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
2825 int busw)
2826{
2827 struct nand_onfi_params *p = &chip->onfi_params;
2828 int i;
2829 int val;
2830
2831 /* try ONFI for unknow chip or LP */
2832 chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
2833 if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
2834 chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
2835 return 0;
2836
2837 printk(KERN_INFO "ONFI flash detected\n");
2838 chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
2839 for (i = 0; i < 3; i++) {
2840 chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
2841 if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
2842 le16_to_cpu(p->crc)) {
2843 printk(KERN_INFO "ONFI param page %d valid\n", i);
2844 break;
2845 }
2846 }
2847
2848 if (i == 3)
2849 return 0;
2850
2851 /* check version */
2852 val = le16_to_cpu(p->revision);
2853 if (val == 1 || val > (1 << 4)) {
2854 printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
2855 __func__, val);
2856 return 0;
2857 }
2858
2859 if (val & (1 << 4))
2860 chip->onfi_version = 22;
2861 else if (val & (1 << 3))
2862 chip->onfi_version = 21;
2863 else if (val & (1 << 2))
2864 chip->onfi_version = 20;
2865 else
2866 chip->onfi_version = 10;
2867
2868 sanitize_string(p->manufacturer, sizeof(p->manufacturer));
2869 sanitize_string(p->model, sizeof(p->model));
2870 if (!mtd->name)
2871 mtd->name = p->model;
2872 mtd->writesize = le32_to_cpu(p->byte_per_page);
2873 mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
2874 mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
2875 chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
2876 busw = 0;
2877 if (le16_to_cpu(p->features) & 1)
2878 busw = NAND_BUSWIDTH_16;
2879
2880 chip->options &= ~NAND_CHIPOPTIONS_MSK;
2881 chip->options |= (NAND_NO_READRDY |
2882 NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK;
2883
2884 return 1;
2885}
2886
2887/*
2822 * Get the flash and manufacturer id and lookup if the type is supported 2888 * Get the flash and manufacturer id and lookup if the type is supported
2823 */ 2889 */
2824static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, 2890static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
@@ -2828,6 +2894,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2828{ 2894{
2829 int i, maf_idx; 2895 int i, maf_idx;
2830 u8 id_data[8]; 2896 u8 id_data[8];
2897 int ret;
2831 2898
2832 /* Select the device */ 2899 /* Select the device */
2833 chip->select_chip(mtd, 0); 2900 chip->select_chip(mtd, 0);
@@ -2872,67 +2939,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
2872 2939
2873 chip->onfi_version = 0; 2940 chip->onfi_version = 0;
2874 if (!type->name || !type->pagesize) { 2941 if (!type->name || !type->pagesize) {
2875 /* try ONFI for unknow chip or LP */ 2942 /* Check is chip is ONFI compliant */
2876 chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); 2943 ret = nand_flash_detect_onfi(mtd, chip, busw);
2877 if (chip->read_byte(mtd) == 'O' && 2944 if (ret)
2878 chip->read_byte(mtd) == 'N' && 2945 goto ident_done;
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 } 2946 }
2937 2947
2938 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); 2948 chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);