Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: onenand: switch to mtd_ooblayout_ops

Implementing the mtd_ooblayout_ops interface is the new way of exposing
ECC/OOB layout to MTD users. Modify the onenand drivers to switch to this
approach.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>

+97 -67
+97 -65
drivers/mtd/onenand/onenand_base.c
··· 68 68 * flexonenand_oob_128 - oob info for Flex-Onenand with 4KB page 69 69 * For now, we expose only 64 out of 80 ecc bytes 70 70 */ 71 - static struct nand_ecclayout flexonenand_oob_128 = { 72 - .eccbytes = 64, 73 - .eccpos = { 74 - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 75 - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 76 - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 77 - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 78 - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 79 - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 80 - 102, 103, 104, 105 81 - }, 82 - .oobfree = { 83 - {2, 4}, {18, 4}, {34, 4}, {50, 4}, 84 - {66, 4}, {82, 4}, {98, 4}, {114, 4} 85 - } 71 + static int flexonenand_ooblayout_ecc(struct mtd_info *mtd, int section, 72 + struct mtd_oob_region *oobregion) 73 + { 74 + if (section > 7) 75 + return -ERANGE; 76 + 77 + oobregion->offset = (section * 16) + 6; 78 + oobregion->length = 10; 79 + 80 + return 0; 81 + } 82 + 83 + static int flexonenand_ooblayout_free(struct mtd_info *mtd, int section, 84 + struct mtd_oob_region *oobregion) 85 + { 86 + if (section > 7) 87 + return -ERANGE; 88 + 89 + oobregion->offset = (section * 16) + 2; 90 + oobregion->length = 4; 91 + 92 + return 0; 93 + } 94 + 95 + static const struct mtd_ooblayout_ops flexonenand_ooblayout_ops = { 96 + .ecc = flexonenand_ooblayout_ecc, 97 + .free = flexonenand_ooblayout_free, 86 98 }; 87 99 88 100 /* ··· 103 91 * Based on specification: 104 92 * 4Gb M-die OneNAND Flash (KFM4G16Q4M, KFN8G16Q4M). Rev. 1.3, Apr. 2010 105 93 * 106 - * For eccpos we expose only 64 bytes out of 72 (see struct nand_ecclayout) 107 - * 108 - * oobfree uses the spare area fields marked as 109 - * "Managed by internal ECC logic for Logical Sector Number area" 110 94 */ 111 - static struct nand_ecclayout onenand_oob_128 = { 112 - .eccbytes = 64, 113 - .eccpos = { 114 - 7, 8, 9, 10, 11, 12, 13, 14, 15, 115 - 23, 24, 25, 26, 27, 28, 29, 30, 31, 116 - 39, 40, 41, 42, 43, 44, 45, 46, 47, 117 - 55, 56, 57, 58, 59, 60, 61, 62, 63, 118 - 71, 72, 73, 74, 75, 76, 77, 78, 79, 119 - 87, 88, 89, 90, 91, 92, 93, 94, 95, 120 - 103, 104, 105, 106, 107, 108, 109, 110, 111, 121 - 119 122 - }, 123 - .oobfree = { 124 - {2, 3}, {18, 3}, {34, 3}, {50, 3}, 125 - {66, 3}, {82, 3}, {98, 3}, {114, 3} 126 - } 95 + static int onenand_ooblayout_128_ecc(struct mtd_info *mtd, int section, 96 + struct mtd_oob_region *oobregion) 97 + { 98 + if (section > 7) 99 + return -ERANGE; 100 + 101 + oobregion->offset = (section * 16) + 7; 102 + oobregion->length = 9; 103 + 104 + return 0; 105 + } 106 + 107 + static int onenand_ooblayout_128_free(struct mtd_info *mtd, int section, 108 + struct mtd_oob_region *oobregion) 109 + { 110 + if (section >= 8) 111 + return -ERANGE; 112 + 113 + /* 114 + * free bytes are using the spare area fields marked as 115 + * "Managed by internal ECC logic for Logical Sector Number area" 116 + */ 117 + oobregion->offset = (section * 16) + 2; 118 + oobregion->length = 3; 119 + 120 + return 0; 121 + } 122 + 123 + static const struct mtd_ooblayout_ops onenand_oob_128_ooblayout_ops = { 124 + .ecc = onenand_ooblayout_128_ecc, 125 + .free = onenand_ooblayout_128_free, 127 126 }; 128 127 129 128 /** 130 - * onenand_oob_64 - oob info for large (2KB) page 129 + * onenand_oob_32_64 - oob info for large (2KB) page 131 130 */ 132 - static struct nand_ecclayout onenand_oob_64 = { 133 - .eccbytes = 20, 134 - .eccpos = { 135 - 8, 9, 10, 11, 12, 136 - 24, 25, 26, 27, 28, 137 - 40, 41, 42, 43, 44, 138 - 56, 57, 58, 59, 60, 139 - }, 140 - .oobfree = { 141 - {2, 3}, {14, 2}, {18, 3}, {30, 2}, 142 - {34, 3}, {46, 2}, {50, 3}, {62, 2} 143 - } 144 - }; 131 + static int onenand_ooblayout_32_64_ecc(struct mtd_info *mtd, int section, 132 + struct mtd_oob_region *oobregion) 133 + { 134 + if (section > 3) 135 + return -ERANGE; 145 136 146 - /** 147 - * onenand_oob_32 - oob info for middle (1KB) page 148 - */ 149 - static struct nand_ecclayout onenand_oob_32 = { 150 - .eccbytes = 10, 151 - .eccpos = { 152 - 8, 9, 10, 11, 12, 153 - 24, 25, 26, 27, 28, 154 - }, 155 - .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} } 137 + oobregion->offset = (section * 16) + 8; 138 + oobregion->length = 5; 139 + 140 + return 0; 141 + } 142 + 143 + static int onenand_ooblayout_32_64_free(struct mtd_info *mtd, int section, 144 + struct mtd_oob_region *oobregion) 145 + { 146 + int sections = (mtd->oobsize / 32) * 2; 147 + 148 + if (section >= sections) 149 + return -ERANGE; 150 + 151 + if (section & 1) { 152 + oobregion->offset = ((section - 1) * 16) + 14; 153 + oobregion->length = 2; 154 + } else { 155 + oobregion->offset = (section * 16) + 2; 156 + oobregion->length = 3; 157 + } 158 + 159 + return 0; 160 + } 161 + 162 + static const struct mtd_ooblayout_ops onenand_oob_32_64_ooblayout_ops = { 163 + .ecc = onenand_ooblayout_32_64_ecc, 164 + .free = onenand_ooblayout_32_64_free, 156 165 }; 157 166 158 167 static const unsigned char ffchars[] = { ··· 3990 3957 switch (mtd->oobsize) { 3991 3958 case 128: 3992 3959 if (FLEXONENAND(this)) { 3993 - this->ecclayout = &flexonenand_oob_128; 3960 + mtd_set_ooblayout(mtd, &flexonenand_ooblayout_ops); 3994 3961 mtd->subpage_sft = 0; 3995 3962 } else { 3996 - this->ecclayout = &onenand_oob_128; 3963 + mtd_set_ooblayout(mtd, &onenand_oob_128_ooblayout_ops); 3997 3964 mtd->subpage_sft = 2; 3998 3965 } 3999 3966 if (ONENAND_IS_NOP_1(this)) 4000 3967 mtd->subpage_sft = 0; 4001 3968 break; 4002 3969 case 64: 4003 - this->ecclayout = &onenand_oob_64; 3970 + mtd_set_ooblayout(mtd, &onenand_oob_32_64_ooblayout_ops); 4004 3971 mtd->subpage_sft = 2; 4005 3972 break; 4006 3973 4007 3974 case 32: 4008 - this->ecclayout = &onenand_oob_32; 3975 + mtd_set_ooblayout(mtd, &onenand_oob_32_64_ooblayout_ops); 4009 3976 mtd->subpage_sft = 1; 4010 3977 break; 4011 3978 ··· 4014 3981 __func__, mtd->oobsize); 4015 3982 mtd->subpage_sft = 0; 4016 3983 /* To prevent kernel oops */ 4017 - this->ecclayout = &onenand_oob_32; 3984 + mtd_set_ooblayout(mtd, &onenand_oob_32_64_ooblayout_ops); 4018 3985 break; 4019 3986 } 4020 3987 ··· 4030 3997 4031 3998 mtd->oobavail = ret; 4032 3999 4033 - mtd_set_ecclayout(mtd, this->ecclayout); 4034 4000 mtd->ecc_strength = 1; 4035 4001 4036 4002 /* Fill in remaining MTD driver data */
-2
include/linux/mtd/onenand.h
··· 80 80 * @page_buf: [INTERN] page main data buffer 81 81 * @oob_buf: [INTERN] page oob data buffer 82 82 * @subpagesize: [INTERN] holds the subpagesize 83 - * @ecclayout: [REPLACEABLE] the default ecc placement scheme 84 83 * @bbm: [REPLACEABLE] pointer to Bad Block Management 85 84 * @priv: [OPTIONAL] pointer to private chip date 86 85 */ ··· 133 134 #endif 134 135 135 136 int subpagesize; 136 - struct nand_ecclayout *ecclayout; 137 137 138 138 void *bbm; 139 139