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