aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Couzens <lynxis@fe80.eu>2017-05-02 06:19:00 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-25 09:44:48 -0400
commit5956b2815f90e0749d98ea0baedc49b1792f598b (patch)
tree99a25b587bf888b8e9f33d60e5b773b0b7528e4d
parent6639b27f5a4c5425a46b2f1039d390dd1ad7b94f (diff)
mtd: nand: add ooblayout for old hamming layout
commit 6a623e07694437ad09f382a13f76cffc32239a7f upstream. The old 1-bit hamming layout requires ECC data to be placed at a fixed offset, and not necessarily at the end of the OOB area. Add this old layout back in order to fix legacy setups. Fixes: 41b207a70d3a ("mtd: nand: implement the default mtd_ooblayout_ops") Signed-off-by: Alexander Couzens <lynxis@fe80.eu> Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/mtd/nand/nand_base.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 3bde96a3f7bf..f222f8a7ba52 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -138,6 +138,74 @@ const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = {
138}; 138};
139EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops); 139EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops);
140 140
141/*
142 * Support the old "large page" layout used for 1-bit Hamming ECC where ECC
143 * are placed at a fixed offset.
144 */
145static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
146 struct mtd_oob_region *oobregion)
147{
148 struct nand_chip *chip = mtd_to_nand(mtd);
149 struct nand_ecc_ctrl *ecc = &chip->ecc;
150
151 if (section)
152 return -ERANGE;
153
154 switch (mtd->oobsize) {
155 case 64:
156 oobregion->offset = 40;
157 break;
158 case 128:
159 oobregion->offset = 80;
160 break;
161 default:
162 return -EINVAL;
163 }
164
165 oobregion->length = ecc->total;
166 if (oobregion->offset + oobregion->length > mtd->oobsize)
167 return -ERANGE;
168
169 return 0;
170}
171
172static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
173 struct mtd_oob_region *oobregion)
174{
175 struct nand_chip *chip = mtd_to_nand(mtd);
176 struct nand_ecc_ctrl *ecc = &chip->ecc;
177 int ecc_offset = 0;
178
179 if (section < 0 || section > 1)
180 return -ERANGE;
181
182 switch (mtd->oobsize) {
183 case 64:
184 ecc_offset = 40;
185 break;
186 case 128:
187 ecc_offset = 80;
188 break;
189 default:
190 return -EINVAL;
191 }
192
193 if (section == 0) {
194 oobregion->offset = 2;
195 oobregion->length = ecc_offset - 2;
196 } else {
197 oobregion->offset = ecc_offset + ecc->total;
198 oobregion->length = mtd->oobsize - oobregion->offset;
199 }
200
201 return 0;
202}
203
204const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
205 .ecc = nand_ooblayout_ecc_lp_hamming,
206 .free = nand_ooblayout_free_lp_hamming,
207};
208
141static int check_offs_len(struct mtd_info *mtd, 209static int check_offs_len(struct mtd_info *mtd,
142 loff_t ofs, uint64_t len) 210 loff_t ofs, uint64_t len)
143{ 211{
@@ -4565,7 +4633,7 @@ int nand_scan_tail(struct mtd_info *mtd)
4565 break; 4633 break;
4566 case 64: 4634 case 64:
4567 case 128: 4635 case 128:
4568 mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops); 4636 mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops);
4569 break; 4637 break;
4570 default: 4638 default:
4571 WARN(1, "No oob scheme defined for oobsize %d\n", 4639 WARN(1, "No oob scheme defined for oobsize %d\n",