aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_base.c
diff options
context:
space:
mode:
authorBrian Norris <computersforpeace@gmail.com>2012-09-24 23:40:49 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-09-29 10:57:33 -0400
commit7e74c2d7141e8929049233e28c74cd089f6ae962 (patch)
treed811df16199367e4ebba1d6a6135cc9783e87c1e /drivers/mtd/nand/nand_base.c
parent4aef9b78de057349ad9d620851b14800af0b962c (diff)
mtd: nand: split BB marker options 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 the bad block marker options detection into its own function, away from the other parameters (e.g., chip size, page size, etc.). 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/nand/nand_base.c')
-rw-r--r--drivers/mtd/nand/nand_base.c66
1 files changed, 39 insertions, 27 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 77b340068c6e..16bb17f93997 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2906,6 +2906,43 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
2906} 2906}
2907 2907
2908/* 2908/*
2909 * Set the bad block marker/indicator (BBM/BBI) patterns according to some
2910 * heuristic patterns using various detected parameters (e.g., manufacturer,
2911 * page size, cell-type information).
2912 */
2913static void nand_decode_bbm_options(struct mtd_info *mtd,
2914 struct nand_chip *chip, u8 id_data[8])
2915{
2916 int maf_id = id_data[0];
2917
2918 /* Set the bad block position */
2919 if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
2920 chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
2921 else
2922 chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
2923
2924 /*
2925 * Bad block marker is stored in the last page of each block on Samsung
2926 * and Hynix MLC devices; stored in first two pages of each block on
2927 * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
2928 * AMD/Spansion, and Macronix. All others scan only the first page.
2929 */
2930 if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
2931 (maf_id == NAND_MFR_SAMSUNG ||
2932 maf_id == NAND_MFR_HYNIX))
2933 chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
2934 else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
2935 (maf_id == NAND_MFR_SAMSUNG ||
2936 maf_id == NAND_MFR_HYNIX ||
2937 maf_id == NAND_MFR_TOSHIBA ||
2938 maf_id == NAND_MFR_AMD ||
2939 maf_id == NAND_MFR_MACRONIX)) ||
2940 (mtd->writesize == 2048 &&
2941 maf_id == NAND_MFR_MICRON))
2942 chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
2943}
2944
2945/*
2909 * Get the flash and manufacturer id and lookup if the type is supported. 2946 * Get the flash and manufacturer id and lookup if the type is supported.
2910 */ 2947 */
2911static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, 2948static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
@@ -3087,6 +3124,8 @@ ident_done:
3087 return ERR_PTR(-EINVAL); 3124 return ERR_PTR(-EINVAL);
3088 } 3125 }
3089 3126
3127 nand_decode_bbm_options(mtd, chip, id_data);
3128
3090 /* Calculate the address shift from the page size */ 3129 /* Calculate the address shift from the page size */
3091 chip->page_shift = ffs(mtd->writesize) - 1; 3130 chip->page_shift = ffs(mtd->writesize) - 1;
3092 /* Convert chipsize to number of pages per chip -1 */ 3131 /* Convert chipsize to number of pages per chip -1 */
@@ -3103,33 +3142,6 @@ ident_done:
3103 3142
3104 chip->badblockbits = 8; 3143 chip->badblockbits = 8;
3105 3144
3106 /* Set the bad block position */
3107 if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16))
3108 chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
3109 else
3110 chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
3111
3112 /*
3113 * Bad block marker is stored in the last page of each block
3114 * on Samsung and Hynix MLC devices; stored in first two pages
3115 * of each block on Micron devices with 2KiB pages and on
3116 * SLC Samsung, Hynix, Toshiba, AMD/Spansion, and Macronix.
3117 * All others scan only the first page.
3118 */
3119 if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
3120 (*maf_id == NAND_MFR_SAMSUNG ||
3121 *maf_id == NAND_MFR_HYNIX))
3122 chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
3123 else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
3124 (*maf_id == NAND_MFR_SAMSUNG ||
3125 *maf_id == NAND_MFR_HYNIX ||
3126 *maf_id == NAND_MFR_TOSHIBA ||
3127 *maf_id == NAND_MFR_AMD ||
3128 *maf_id == NAND_MFR_MACRONIX)) ||
3129 (mtd->writesize == 2048 &&
3130 *maf_id == NAND_MFR_MICRON))
3131 chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
3132
3133 /* Check for AND chips with 4 page planes */ 3145 /* Check for AND chips with 4 page planes */
3134 if (chip->options & NAND_4PAGE_ARRAY) 3146 if (chip->options & NAND_4PAGE_ARRAY)
3135 chip->erase_cmd = multi_erase_cmd; 3147 chip->erase_cmd = multi_erase_cmd;