diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 132 |
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 | */ | ||
2824 | static 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 | */ |
2824 | static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | 2890 | static 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); |