@@ -343,23 +343,22 @@ int SPINANDBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
343
343
goto exit_point;
344
344
}
345
345
346
- // calculate the software ECC
347
- for (uint8_t i = 0 ; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
348
- _bch_calculate_ecc (p, _ecc_calc + i);
349
- }
350
-
351
346
memcpy (_ecc_code, _page_buf + _page_size + _ecc_layout_pos, _ecc_bytes * _ecc_steps);
352
347
353
348
p = (uint8_t *)_page_buf;
354
349
ecc_steps = _ecc_steps;
355
350
for (uint8_t i = 0 ; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
356
- int res = _bch_correct_data (p, _ecc_code + i, _ecc_calc + i);
351
+ memset (_nbc.bch ->input_data , 0x0 , (1 << _nbc.bch ->m ) / 8 );
352
+ memcpy (_nbc.bch ->input_data + _ecc_bytes, p, _ecc_size);
353
+
354
+ int res = bch_decode (_nbc.bch , _nbc.bch ->input_data , (unsigned int *)(_ecc_code + i));
357
355
if (res < 0 ) {
358
356
tr_error (" Reading data failed" );
359
357
status = SPINAND_BD_ERROR_DEVICE_ERROR;
360
358
read_failed = true ;
361
359
goto exit_point;
362
360
}
361
+ memcpy (p, _nbc.bch ->input_data + _ecc_bytes, _ecc_size);
363
362
}
364
363
memcpy (buffer, _page_buf + offset, read_bytes);
365
364
}
@@ -431,7 +430,9 @@ int SPINANDBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t si
431
430
432
431
// calculate the software ECC
433
432
for (uint8_t i = 0 ; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
434
- _bch_calculate_ecc (p, _ecc_calc + i);
433
+ memset (_nbc.bch ->input_data , 0x0 , (1 << _nbc.bch ->m ) / 8 );
434
+ memcpy (_nbc.bch ->input_data + _ecc_bytes, p, _ecc_size);
435
+ _bch_calculate_ecc (_nbc.bch ->input_data , _ecc_calc + i);
435
436
}
436
437
437
438
// prepare ECC code
@@ -1251,26 +1252,26 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
1251
1252
{
1252
1253
unsigned int m, t, i;
1253
1254
unsigned char *erased_page;
1254
- unsigned int eccsize = 512 ;
1255
+ unsigned int eccsize = 410 ;
1255
1256
unsigned int eccbytes = 0 ;
1256
1257
1257
- _ecc_bytes = eccbytes = DIV_ROUND_UP (ecc_bits * fls (8 * eccsize), 8 );
1258
+ m = fls (1 + 8 * eccsize);
1259
+ t = ecc_bits;
1260
+
1261
+ _ecc_bytes = eccbytes = ((m * t + 31 ) / 32 ) * 4 ;
1258
1262
_ecc_size = eccsize;
1259
1263
_ecc_steps = _page_size / eccsize;
1260
1264
_ecc_layout_pos = 2 ; // skip the bad block mark for Macronix spi nand
1261
1265
1262
- m = fls (1 + 8 * eccsize);
1263
- t = (eccbytes * 8 ) / m;
1264
-
1265
- _nbc.bch = init_bch (m, t, 0 );
1266
+ _nbc.bch = bch_init (m, t);
1266
1267
if (!_nbc.bch ) {
1267
1268
return ;
1268
1269
}
1269
1270
1270
1271
/* verify that eccbytes has the expected value */
1271
- if (_nbc.bch ->ecc_bytes != eccbytes) {
1272
+ if (_nbc.bch ->ecc_words * 4 != eccbytes) {
1272
1273
tr_error (" invalid eccbytes %u, should be %u\n " ,
1273
- eccbytes, _nbc.bch ->ecc_bytes );
1274
+ eccbytes, _nbc.bch ->ecc_words );
1274
1275
return ;
1275
1276
}
1276
1277
@@ -1292,7 +1293,7 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
1292
1293
memset (_page_buf, 0xff , _page_size + _oob_size);
1293
1294
memset (erased_page, 0xff , eccsize);
1294
1295
memset (_nbc.eccmask , 0 , eccbytes);
1295
- encode_bch (_nbc.bch , erased_page, eccsize, _nbc.eccmask );
1296
+ bch_encode (_nbc.bch , erased_page, ( unsigned int *) _nbc.eccmask );
1296
1297
free (erased_page);
1297
1298
1298
1299
for (i = 0 ; i < eccbytes; i++) {
@@ -1302,7 +1303,7 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
1302
1303
1303
1304
void SPINANDBlockDevice::_bch_free ()
1304
1305
{
1305
- free_bch (_nbc.bch );
1306
+ bch_free (_nbc.bch );
1306
1307
free (_nbc.errloc );
1307
1308
free (_nbc.eccmask );
1308
1309
free (_page_buf);
@@ -1312,42 +1313,11 @@ void SPINANDBlockDevice::_bch_free()
1312
1313
1313
1314
int SPINANDBlockDevice::_bch_calculate_ecc (unsigned char *buf, unsigned char *code)
1314
1315
{
1315
- unsigned int i;
1316
1316
1317
1317
memset (code, 0 , _ecc_bytes);
1318
1318
1319
- encode_bch (_nbc.bch , buf, _ecc_size, code);
1320
-
1321
- /* apply mask so that an erased page is a valid codeword */
1322
- for (i = 0 ; i < _ecc_bytes; i++) {
1323
- code[i] ^= _nbc.eccmask [i];
1324
- }
1319
+ bch_encode (_nbc.bch , buf, (unsigned int *)code);
1325
1320
1326
1321
return 0 ;
1327
1322
}
1328
1323
1329
- int SPINANDBlockDevice::_bch_correct_data (unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc)
1330
- {
1331
- unsigned int *errloc = _nbc.errloc ;
1332
- int i, count;
1333
-
1334
- count = decode_bch (_nbc.bch , NULL , _ecc_size, read_ecc, calc_ecc,
1335
- NULL , errloc);
1336
- if (count > 0 ) {
1337
- for (i = 0 ; i < count; i++) {
1338
- if (errloc[i] < (_ecc_size * 8 )) {
1339
- /* error is located in data, correct it */
1340
- buf[(errloc[i] >> 3 ) ^ 3 ] ^= (1 << (errloc[i] & 7 ));
1341
- }
1342
-
1343
- /* else error in ecc, no action needed */
1344
- tr_error (" corrected bitflip %04x:%d\n " , (errloc[i] >> 3 ) ^ 3 , errloc[i] & 7 );
1345
- }
1346
- } else if (count < 0 ) {
1347
- tr_error (" ecc unrecoverable error\n " );
1348
- count = -EBADMSG;
1349
- }
1350
- return count;
1351
- }
1352
-
1353
-
0 commit comments