aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorBrian Norris <computersforpeace@gmail.com>2012-09-24 23:40:50 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-09-29 10:57:38 -0400
commitfc09bbc04ccd7f069c1928a0156968b888393833 (patch)
tree75d7b13a28849caf125cb7cdf82f291dff716907 /drivers/mtd
parent7e74c2d7141e8929049233e28c74cd089f6ae962 (diff)
mtd: nand: split extended ID decoding into its own function
When detecting NAND parameters, the code gets a little ugly so that the logic is obscured. Try to remedy that by moving code to separate functions that have well-defined purposes. This patch splits out the extended ID decode functionality, which handles decoding the 3rd-8th ID bytes to determine NAND device parameters. Signed-off-by: Brian Norris <computersforpeace@gmail.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/nand_base.c122
1 files changed, 67 insertions, 55 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 16bb17f93997..e017af02da1c 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2906,6 +2906,71 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
2906} 2906}
2907 2907
2908/* 2908/*
2909 * Many new NAND share similar device ID codes, which represent the size of the
2910 * chip. The rest of the parameters must be decoded according to generic or
2911 * manufacturer-specific "extended ID" decoding patterns.
2912 */
2913static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
2914 u8 id_data[8], int *busw)
2915{
2916 int extid;
2917 /* The 3rd id byte holds MLC / multichip data */
2918 chip->cellinfo = id_data[2];
2919 /* The 4th id byte is the important one */
2920 extid = id_data[3];
2921
2922 /*
2923 * Field definitions are in the following datasheets:
2924 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
2925 * New style (6 byte ID): Samsung K9GBG08U0M (p.40)
2926 *
2927 * Check for wraparound + Samsung ID + nonzero 6th byte
2928 * to decide what to do.
2929 */
2930 if (id_data[0] == id_data[6] && id_data[1] == id_data[7] &&
2931 id_data[0] == NAND_MFR_SAMSUNG &&
2932 (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
2933 id_data[5] != 0x00) {
2934 /* Calc pagesize */
2935 mtd->writesize = 2048 << (extid & 0x03);
2936 extid >>= 2;
2937 /* Calc oobsize */
2938 switch (extid & 0x03) {
2939 case 1:
2940 mtd->oobsize = 128;
2941 break;
2942 case 2:
2943 mtd->oobsize = 218;
2944 break;
2945 case 3:
2946 mtd->oobsize = 400;
2947 break;
2948 default:
2949 mtd->oobsize = 436;
2950 break;
2951 }
2952 extid >>= 2;
2953 /* Calc blocksize */
2954 mtd->erasesize = (128 * 1024) <<
2955 (((extid >> 1) & 0x04) | (extid & 0x03));
2956 *busw = 0;
2957 } else {
2958 /* Calc pagesize */
2959 mtd->writesize = 1024 << (extid & 0x03);
2960 extid >>= 2;
2961 /* Calc oobsize */
2962 mtd->oobsize = (8 << (extid & 0x01)) *
2963 (mtd->writesize >> 9);
2964 extid >>= 2;
2965 /* Calc blocksize. Blocksize is multiples of 64KiB */
2966 mtd->erasesize = (64 * 1024) << (extid & 0x03);
2967 extid >>= 2;
2968 /* Get buswidth information */
2969 *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
2970 }
2971}
2972
2973/*
2909 * Set the bad block marker/indicator (BBM/BBI) patterns according to some 2974 * Set the bad block marker/indicator (BBM/BBI) patterns according to some
2910 * heuristic patterns using various detected parameters (e.g., manufacturer, 2975 * heuristic patterns using various detected parameters (e.g., manufacturer,
2911 * page size, cell-type information). 2976 * page size, cell-type information).
@@ -3016,61 +3081,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
3016 /* Set the pagesize, oobsize, erasesize by the driver */ 3081 /* Set the pagesize, oobsize, erasesize by the driver */
3017 busw = chip->init_size(mtd, chip, id_data); 3082 busw = chip->init_size(mtd, chip, id_data);
3018 } else if (!type->pagesize) { 3083 } else if (!type->pagesize) {
3019 int extid; 3084 /* Decode parameters from extended ID */
3020 /* The 3rd id byte holds MLC / multichip data */ 3085 nand_decode_ext_id(mtd, chip, id_data, &busw);
3021 chip->cellinfo = id_data[2];
3022 /* The 4th id byte is the important one */
3023 extid = id_data[3];
3024
3025 /*
3026 * Field definitions are in the following datasheets:
3027 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
3028 * New style (6 byte ID): Samsung K9GBG08U0M (p.40)
3029 *
3030 * Check for wraparound + Samsung ID + nonzero 6th byte
3031 * to decide what to do.
3032 */
3033 if (id_data[0] == id_data[6] && id_data[1] == id_data[7] &&
3034 id_data[0] == NAND_MFR_SAMSUNG &&
3035 (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
3036 id_data[5] != 0x00) {
3037 /* Calc pagesize */
3038 mtd->writesize = 2048 << (extid & 0x03);
3039 extid >>= 2;
3040 /* Calc oobsize */
3041 switch (extid & 0x03) {
3042 case 1:
3043 mtd->oobsize = 128;
3044 break;
3045 case 2:
3046 mtd->oobsize = 218;
3047 break;
3048 case 3:
3049 mtd->oobsize = 400;
3050 break;
3051 default:
3052 mtd->oobsize = 436;
3053 break;
3054 }
3055 extid >>= 2;
3056 /* Calc blocksize */
3057 mtd->erasesize = (128 * 1024) <<
3058 (((extid >> 1) & 0x04) | (extid & 0x03));
3059 busw = 0;
3060 } else {
3061 /* Calc pagesize */
3062 mtd->writesize = 1024 << (extid & 0x03);
3063 extid >>= 2;
3064 /* Calc oobsize */
3065 mtd->oobsize = (8 << (extid & 0x01)) *
3066 (mtd->writesize >> 9);
3067 extid >>= 2;
3068 /* Calc blocksize. Blocksize is multiples of 64KiB */
3069 mtd->erasesize = (64 * 1024) << (extid & 0x03);
3070 extid >>= 2;
3071 /* Get buswidth information */
3072 busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
3073 }
3074 } else { 3086 } else {
3075 /* 3087 /*
3076 * Old devices have chip data hardcoded in the device id table. 3088 * Old devices have chip data hardcoded in the device id table.