@@ -343,23 +343,22 @@ int SPINANDBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
343343 goto exit_point;
344344 }
345345
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-
351346 memcpy (_ecc_code, _page_buf + _page_size + _ecc_layout_pos, _ecc_bytes * _ecc_steps);
352347
353348 p = (uint8_t *)_page_buf;
354349 ecc_steps = _ecc_steps;
355350 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));
357355 if (res < 0 ) {
358356 tr_error (" Reading data failed" );
359357 status = SPINAND_BD_ERROR_DEVICE_ERROR;
360358 read_failed = true ;
361359 goto exit_point;
362360 }
361+ memcpy (p, _nbc.bch ->input_data + _ecc_bytes, _ecc_size);
363362 }
364363 memcpy (buffer, _page_buf + offset, read_bytes);
365364 }
@@ -431,7 +430,9 @@ int SPINANDBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t si
431430
432431 // calculate the software ECC
433432 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);
435436 }
436437
437438 // prepare ECC code
@@ -1251,26 +1252,26 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
12511252{
12521253 unsigned int m, t, i;
12531254 unsigned char *erased_page;
1254- unsigned int eccsize = 512 ;
1255+ unsigned int eccsize = 410 ;
12551256 unsigned int eccbytes = 0 ;
12561257
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 ;
12581262 _ecc_size = eccsize;
12591263 _ecc_steps = _page_size / eccsize;
12601264 _ecc_layout_pos = 2 ; // skip the bad block mark for Macronix spi nand
12611265
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);
12661267 if (!_nbc.bch ) {
12671268 return ;
12681269 }
12691270
12701271 /* verify that eccbytes has the expected value */
1271- if (_nbc.bch ->ecc_bytes != eccbytes) {
1272+ if (_nbc.bch ->ecc_words * 4 != eccbytes) {
12721273 tr_error (" invalid eccbytes %u, should be %u\n " ,
1273- eccbytes, _nbc.bch ->ecc_bytes );
1274+ eccbytes, _nbc.bch ->ecc_words );
12741275 return ;
12751276 }
12761277
@@ -1292,7 +1293,7 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
12921293 memset (_page_buf, 0xff , _page_size + _oob_size);
12931294 memset (erased_page, 0xff , eccsize);
12941295 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 );
12961297 free (erased_page);
12971298
12981299 for (i = 0 ; i < eccbytes; i++) {
@@ -1302,7 +1303,7 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
13021303
13031304void SPINANDBlockDevice::_bch_free ()
13041305{
1305- free_bch (_nbc.bch );
1306+ bch_free (_nbc.bch );
13061307 free (_nbc.errloc );
13071308 free (_nbc.eccmask );
13081309 free (_page_buf);
@@ -1312,42 +1313,11 @@ void SPINANDBlockDevice::_bch_free()
13121313
13131314int SPINANDBlockDevice::_bch_calculate_ecc (unsigned char *buf, unsigned char *code)
13141315{
1315- unsigned int i;
13161316
13171317 memset (code, 0 , _ecc_bytes);
13181318
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);
13251320
13261321 return 0 ;
13271322}
13281323
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