1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * This file provides ECC correction for more than 1 bit per block of data,
4 * using binary BCH codes. It relies on the generic BCH library lib/bch.c.
6 * Copyright © 2011 Ivan Djelic <ivan.djelic@parrot.com>
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/bitops.h>
14 #include <linux/mtd/nand.h>
15 #include <linux/mtd/nand-ecc-sw-bch.h>
18 * nand_ecc_sw_bch_calculate - Calculate the ECC corresponding to a data block
20 * @buf: Input buffer with raw data
21 * @code: Output buffer with ECC
23 int nand_ecc_sw_bch_calculate(struct nand_device
*nand
,
24 const unsigned char *buf
, unsigned char *code
)
26 struct nand_ecc_sw_bch_conf
*engine_conf
= nand
->ecc
.ctx
.priv
;
29 memset(code
, 0, engine_conf
->code_size
);
30 bch_encode(engine_conf
->bch
, buf
, nand
->ecc
.ctx
.conf
.step_size
, code
);
32 /* apply mask so that an erased page is a valid codeword */
33 for (i
= 0; i
< engine_conf
->code_size
; i
++)
34 code
[i
] ^= engine_conf
->eccmask
[i
];
38 EXPORT_SYMBOL(nand_ecc_sw_bch_calculate
);
41 * nand_ecc_sw_bch_correct - Detect, correct and report bit error(s)
43 * @buf: Raw data read from the chip
44 * @read_ecc: ECC bytes from the chip
45 * @calc_ecc: ECC calculated from the raw data
47 * Detect and correct bit errors for a data block.
49 int nand_ecc_sw_bch_correct(struct nand_device
*nand
, unsigned char *buf
,
50 unsigned char *read_ecc
, unsigned char *calc_ecc
)
52 struct nand_ecc_sw_bch_conf
*engine_conf
= nand
->ecc
.ctx
.priv
;
53 unsigned int step_size
= nand
->ecc
.ctx
.conf
.step_size
;
54 unsigned int *errloc
= engine_conf
->errloc
;
57 count
= bch_decode(engine_conf
->bch
, NULL
, step_size
, read_ecc
,
58 calc_ecc
, NULL
, errloc
);
60 for (i
= 0; i
< count
; i
++) {
61 if (errloc
[i
] < (step_size
* 8))
62 /* The error is in the data area: correct it */
63 buf
[errloc
[i
] >> 3] ^= (1 << (errloc
[i
] & 7));
65 /* Otherwise the error is in the ECC area: nothing to do */
66 pr_debug("%s: corrected bitflip %u\n", __func__
,
69 } else if (count
< 0) {
70 pr_err("ECC unrecoverable error\n");
76 EXPORT_SYMBOL(nand_ecc_sw_bch_correct
);
79 * nand_ecc_sw_bch_cleanup - Cleanup software BCH ECC resources
82 static void nand_ecc_sw_bch_cleanup(struct nand_device
*nand
)
84 struct nand_ecc_sw_bch_conf
*engine_conf
= nand
->ecc
.ctx
.priv
;
86 bch_free(engine_conf
->bch
);
87 kfree(engine_conf
->errloc
);
88 kfree(engine_conf
->eccmask
);
92 * nand_ecc_sw_bch_init - Initialize software BCH ECC engine
95 * Returns: a pointer to a new NAND BCH control structure, or NULL upon failure
97 * Initialize NAND BCH error correction. @nand.ecc parameters 'step_size' and
98 * 'bytes' are used to compute the following BCH parameters:
99 * m, the Galois field order
100 * t, the error correction capability
101 * 'bytes' should be equal to the number of bytes required to store m * t
102 * bits, where m is such that 2^m - 1 > step_size * 8.
104 * Example: to configure 4 bit correction per 512 bytes, you should pass
105 * step_size = 512 (thus, m = 13 is the smallest integer such that 2^m - 1 > 512 * 8)
106 * bytes = 7 (7 bytes are required to store m * t = 13 * 4 = 52 bits)
108 static int nand_ecc_sw_bch_init(struct nand_device
*nand
)
110 struct nand_ecc_sw_bch_conf
*engine_conf
= nand
->ecc
.ctx
.priv
;
111 unsigned int eccsize
= nand
->ecc
.ctx
.conf
.step_size
;
112 unsigned int eccbytes
= engine_conf
->code_size
;
113 unsigned int m
, t
, i
;
114 unsigned char *erased_page
;
117 m
= fls(1 + (8 * eccsize
));
118 t
= (eccbytes
* 8) / m
;
120 engine_conf
->bch
= bch_init(m
, t
, 0, false);
121 if (!engine_conf
->bch
)
124 engine_conf
->eccmask
= kzalloc(eccbytes
, GFP_KERNEL
);
125 engine_conf
->errloc
= kmalloc_array(t
, sizeof(*engine_conf
->errloc
),
127 if (!engine_conf
->eccmask
|| !engine_conf
->errloc
) {
132 /* Compute and store the inverted ECC of an erased step */
133 erased_page
= kmalloc(eccsize
, GFP_KERNEL
);
139 memset(erased_page
, 0xff, eccsize
);
140 bch_encode(engine_conf
->bch
, erased_page
, eccsize
,
141 engine_conf
->eccmask
);
144 for (i
= 0; i
< eccbytes
; i
++)
145 engine_conf
->eccmask
[i
] ^= 0xff;
147 /* Verify that the number of code bytes has the expected value */
148 if (engine_conf
->bch
->ecc_bytes
!= eccbytes
) {
149 pr_err("Invalid number of ECC bytes: %u, expected: %u\n",
150 eccbytes
, engine_conf
->bch
->ecc_bytes
);
156 if (8 * (eccsize
+ eccbytes
) >= (1 << m
)) {
157 pr_err("ECC step size is too large (%u)\n", eccsize
);
165 nand_ecc_sw_bch_cleanup(nand
);
170 int nand_ecc_sw_bch_init_ctx(struct nand_device
*nand
)
172 struct nand_ecc_props
*conf
= &nand
->ecc
.ctx
.conf
;
173 struct mtd_info
*mtd
= nanddev_to_mtd(nand
);
174 struct nand_ecc_sw_bch_conf
*engine_conf
;
175 unsigned int code_size
= 0, nsteps
;
178 /* Only large page NAND chips may use BCH */
179 if (mtd
->oobsize
< 64) {
180 pr_err("BCH cannot be used with small page NAND chips\n");
185 mtd_set_ooblayout(mtd
, nand_get_large_page_ooblayout());
187 conf
->engine_type
= NAND_ECC_ENGINE_TYPE_SOFT
;
188 conf
->algo
= NAND_ECC_ALGO_BCH
;
189 conf
->step_size
= nand
->ecc
.user_conf
.step_size
;
190 conf
->strength
= nand
->ecc
.user_conf
.strength
;
193 * Board driver should supply ECC size and ECC strength
194 * values to select how many bits are correctable.
195 * Otherwise, default to 512 bytes for large page devices and 256 for
196 * small page devices.
198 if (!conf
->step_size
) {
199 if (mtd
->oobsize
>= 64)
200 conf
->step_size
= 512;
202 conf
->step_size
= 256;
207 nsteps
= mtd
->writesize
/ conf
->step_size
;
210 if (nand
->ecc
.user_conf
.flags
& NAND_ECC_MAXIMIZE_STRENGTH
) {
211 conf
->step_size
= 1024;
212 nsteps
= mtd
->writesize
/ conf
->step_size
;
213 /* Reserve 2 bytes for the BBM */
214 code_size
= (mtd
->oobsize
- 2) / nsteps
;
215 conf
->strength
= code_size
* 8 / fls(8 * conf
->step_size
);
219 code_size
= DIV_ROUND_UP(conf
->strength
*
220 fls(8 * conf
->step_size
), 8);
223 conf
->strength
= (code_size
* 8) / fls(8 * conf
->step_size
);
225 if (!code_size
&& !conf
->strength
) {
226 pr_err("Missing ECC parameters\n");
230 engine_conf
= kzalloc(sizeof(*engine_conf
), GFP_KERNEL
);
234 ret
= nand_ecc_init_req_tweaking(&engine_conf
->req_ctx
, nand
);
236 goto free_engine_conf
;
238 engine_conf
->code_size
= code_size
;
239 engine_conf
->nsteps
= nsteps
;
240 engine_conf
->calc_buf
= kzalloc(mtd
->oobsize
, GFP_KERNEL
);
241 engine_conf
->code_buf
= kzalloc(mtd
->oobsize
, GFP_KERNEL
);
242 if (!engine_conf
->calc_buf
|| !engine_conf
->code_buf
) {
247 nand
->ecc
.ctx
.priv
= engine_conf
;
248 nand
->ecc
.ctx
.total
= nsteps
* code_size
;
250 ret
= nand_ecc_sw_bch_init(nand
);
254 /* Verify the layout validity */
255 if (mtd_ooblayout_count_eccbytes(mtd
) !=
256 engine_conf
->nsteps
* engine_conf
->code_size
) {
257 pr_err("Invalid ECC layout\n");
259 goto cleanup_bch_ctx
;
265 nand_ecc_sw_bch_cleanup(nand
);
267 nand_ecc_cleanup_req_tweaking(&engine_conf
->req_ctx
);
268 kfree(engine_conf
->calc_buf
);
269 kfree(engine_conf
->code_buf
);
275 EXPORT_SYMBOL(nand_ecc_sw_bch_init_ctx
);
277 void nand_ecc_sw_bch_cleanup_ctx(struct nand_device
*nand
)
279 struct nand_ecc_sw_bch_conf
*engine_conf
= nand
->ecc
.ctx
.priv
;
282 nand_ecc_sw_bch_cleanup(nand
);
283 nand_ecc_cleanup_req_tweaking(&engine_conf
->req_ctx
);
284 kfree(engine_conf
->calc_buf
);
285 kfree(engine_conf
->code_buf
);
289 EXPORT_SYMBOL(nand_ecc_sw_bch_cleanup_ctx
);
291 static int nand_ecc_sw_bch_prepare_io_req(struct nand_device
*nand
,
292 struct nand_page_io_req
*req
)
294 struct nand_ecc_sw_bch_conf
*engine_conf
= nand
->ecc
.ctx
.priv
;
295 struct mtd_info
*mtd
= nanddev_to_mtd(nand
);
296 int eccsize
= nand
->ecc
.ctx
.conf
.step_size
;
297 int eccbytes
= engine_conf
->code_size
;
298 int eccsteps
= engine_conf
->nsteps
;
299 int total
= nand
->ecc
.ctx
.total
;
300 u8
*ecccalc
= engine_conf
->calc_buf
;
304 /* Nothing to do for a raw operation */
305 if (req
->mode
== MTD_OPS_RAW
)
308 /* This engine does not provide BBM/free OOB bytes protection */
312 nand_ecc_tweak_req(&engine_conf
->req_ctx
, req
);
314 /* No more preparation for page read */
315 if (req
->type
== NAND_PAGE_READ
)
318 /* Preparation for page write: derive the ECC bytes and place them */
319 for (i
= 0, data
= req
->databuf
.out
;
321 eccsteps
--, i
+= eccbytes
, data
+= eccsize
)
322 nand_ecc_sw_bch_calculate(nand
, data
, &ecccalc
[i
]);
324 return mtd_ooblayout_set_eccbytes(mtd
, ecccalc
, (void *)req
->oobbuf
.out
,
328 static int nand_ecc_sw_bch_finish_io_req(struct nand_device
*nand
,
329 struct nand_page_io_req
*req
)
331 struct nand_ecc_sw_bch_conf
*engine_conf
= nand
->ecc
.ctx
.priv
;
332 struct mtd_info
*mtd
= nanddev_to_mtd(nand
);
333 int eccsize
= nand
->ecc
.ctx
.conf
.step_size
;
334 int total
= nand
->ecc
.ctx
.total
;
335 int eccbytes
= engine_conf
->code_size
;
336 int eccsteps
= engine_conf
->nsteps
;
337 u8
*ecccalc
= engine_conf
->calc_buf
;
338 u8
*ecccode
= engine_conf
->code_buf
;
339 unsigned int max_bitflips
= 0;
340 u8
*data
= req
->databuf
.in
;
343 /* Nothing to do for a raw operation */
344 if (req
->mode
== MTD_OPS_RAW
)
347 /* This engine does not provide BBM/free OOB bytes protection */
351 /* No more preparation for page write */
352 if (req
->type
== NAND_PAGE_WRITE
) {
353 nand_ecc_restore_req(&engine_conf
->req_ctx
, req
);
357 /* Finish a page read: retrieve the (raw) ECC bytes*/
358 ret
= mtd_ooblayout_get_eccbytes(mtd
, ecccode
, req
->oobbuf
.in
, 0,
363 /* Calculate the ECC bytes */
364 for (i
= 0; eccsteps
; eccsteps
--, i
+= eccbytes
, data
+= eccsize
)
365 nand_ecc_sw_bch_calculate(nand
, data
, &ecccalc
[i
]);
367 /* Finish a page read: compare and correct */
368 for (eccsteps
= engine_conf
->nsteps
, i
= 0, data
= req
->databuf
.in
;
370 eccsteps
--, i
+= eccbytes
, data
+= eccsize
) {
371 int stat
= nand_ecc_sw_bch_correct(nand
, data
,
375 mtd
->ecc_stats
.failed
++;
377 mtd
->ecc_stats
.corrected
+= stat
;
378 max_bitflips
= max_t(unsigned int, max_bitflips
, stat
);
382 nand_ecc_restore_req(&engine_conf
->req_ctx
, req
);
387 static struct nand_ecc_engine_ops nand_ecc_sw_bch_engine_ops
= {
388 .init_ctx
= nand_ecc_sw_bch_init_ctx
,
389 .cleanup_ctx
= nand_ecc_sw_bch_cleanup_ctx
,
390 .prepare_io_req
= nand_ecc_sw_bch_prepare_io_req
,
391 .finish_io_req
= nand_ecc_sw_bch_finish_io_req
,
394 static struct nand_ecc_engine nand_ecc_sw_bch_engine
= {
395 .ops
= &nand_ecc_sw_bch_engine_ops
,
398 struct nand_ecc_engine
*nand_ecc_sw_bch_get_engine(void)
400 return &nand_ecc_sw_bch_engine
;
402 EXPORT_SYMBOL(nand_ecc_sw_bch_get_engine
);
404 MODULE_LICENSE("GPL");
405 MODULE_AUTHOR("Ivan Djelic <ivan.djelic@parrot.com>");
406 MODULE_DESCRIPTION("NAND software BCH ECC support");