@@ -360,6 +360,7 @@ enum brcmnand_reg {
360
360
BRCMNAND_CORR_THRESHOLD_EXT ,
361
361
BRCMNAND_UNCORR_COUNT ,
362
362
BRCMNAND_CORR_COUNT ,
363
+ BRCMNAND_READ_ERROR_COUNT ,
363
364
BRCMNAND_CORR_EXT_ADDR ,
364
365
BRCMNAND_CORR_ADDR ,
365
366
BRCMNAND_UNCORR_EXT_ADDR ,
@@ -390,6 +391,7 @@ static const u16 brcmnand_regs_v21[] = {
390
391
[BRCMNAND_CORR_THRESHOLD_EXT ] = 0 ,
391
392
[BRCMNAND_UNCORR_COUNT ] = 0 ,
392
393
[BRCMNAND_CORR_COUNT ] = 0 ,
394
+ [BRCMNAND_READ_ERROR_COUNT ] = 0 ,
393
395
[BRCMNAND_CORR_EXT_ADDR ] = 0x60 ,
394
396
[BRCMNAND_CORR_ADDR ] = 0x64 ,
395
397
[BRCMNAND_UNCORR_EXT_ADDR ] = 0x68 ,
@@ -420,6 +422,7 @@ static const u16 brcmnand_regs_v33[] = {
420
422
[BRCMNAND_CORR_THRESHOLD_EXT ] = 0 ,
421
423
[BRCMNAND_UNCORR_COUNT ] = 0 ,
422
424
[BRCMNAND_CORR_COUNT ] = 0 ,
425
+ [BRCMNAND_READ_ERROR_COUNT ] = 0x80 ,
423
426
[BRCMNAND_CORR_EXT_ADDR ] = 0x70 ,
424
427
[BRCMNAND_CORR_ADDR ] = 0x74 ,
425
428
[BRCMNAND_UNCORR_EXT_ADDR ] = 0x78 ,
@@ -450,6 +453,7 @@ static const u16 brcmnand_regs_v50[] = {
450
453
[BRCMNAND_CORR_THRESHOLD_EXT ] = 0 ,
451
454
[BRCMNAND_UNCORR_COUNT ] = 0 ,
452
455
[BRCMNAND_CORR_COUNT ] = 0 ,
456
+ [BRCMNAND_READ_ERROR_COUNT ] = 0x80 ,
453
457
[BRCMNAND_CORR_EXT_ADDR ] = 0x70 ,
454
458
[BRCMNAND_CORR_ADDR ] = 0x74 ,
455
459
[BRCMNAND_UNCORR_EXT_ADDR ] = 0x78 ,
@@ -480,6 +484,7 @@ static const u16 brcmnand_regs_v60[] = {
480
484
[BRCMNAND_CORR_THRESHOLD_EXT ] = 0xc4 ,
481
485
[BRCMNAND_UNCORR_COUNT ] = 0xfc ,
482
486
[BRCMNAND_CORR_COUNT ] = 0x100 ,
487
+ [BRCMNAND_READ_ERROR_COUNT ] = 0x104 ,
483
488
[BRCMNAND_CORR_EXT_ADDR ] = 0x10c ,
484
489
[BRCMNAND_CORR_ADDR ] = 0x110 ,
485
490
[BRCMNAND_UNCORR_EXT_ADDR ] = 0x114 ,
@@ -510,6 +515,7 @@ static const u16 brcmnand_regs_v71[] = {
510
515
[BRCMNAND_CORR_THRESHOLD_EXT ] = 0xe0 ,
511
516
[BRCMNAND_UNCORR_COUNT ] = 0xfc ,
512
517
[BRCMNAND_CORR_COUNT ] = 0x100 ,
518
+ [BRCMNAND_READ_ERROR_COUNT ] = 0x104 ,
513
519
[BRCMNAND_CORR_EXT_ADDR ] = 0x10c ,
514
520
[BRCMNAND_CORR_ADDR ] = 0x110 ,
515
521
[BRCMNAND_UNCORR_EXT_ADDR ] = 0x114 ,
@@ -540,6 +546,7 @@ static const u16 brcmnand_regs_v72[] = {
540
546
[BRCMNAND_CORR_THRESHOLD_EXT ] = 0xe0 ,
541
547
[BRCMNAND_UNCORR_COUNT ] = 0xfc ,
542
548
[BRCMNAND_CORR_COUNT ] = 0x100 ,
549
+ [BRCMNAND_READ_ERROR_COUNT ] = 0x104 ,
543
550
[BRCMNAND_CORR_EXT_ADDR ] = 0x10c ,
544
551
[BRCMNAND_CORR_ADDR ] = 0x110 ,
545
552
[BRCMNAND_UNCORR_EXT_ADDR ] = 0x114 ,
@@ -960,11 +967,11 @@ static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs,
960
967
return offs_cs0 + cs * ctrl -> reg_spacing + cs_offs ;
961
968
}
962
969
963
- static inline u32 brcmnand_count_corrected (struct brcmnand_controller * ctrl )
970
+ static inline u32 brcmnand_corr_total (struct brcmnand_controller * ctrl )
964
971
{
965
- if (ctrl -> nand_version < 0x0600 )
966
- return 1 ;
967
- return brcmnand_read_reg (ctrl , BRCMNAND_CORR_COUNT );
972
+ if (ctrl -> nand_version < 0x400 )
973
+ return 0 ;
974
+ return brcmnand_read_reg (ctrl , BRCMNAND_READ_ERROR_COUNT );
968
975
}
969
976
970
977
static void brcmnand_wr_corr_thresh (struct brcmnand_host * host , u8 val )
@@ -2067,15 +2074,20 @@ static int brcmnand_dma_trans(struct brcmnand_host *host, u64 addr, u32 *buf,
2067
2074
*/
2068
2075
static int brcmnand_read_by_pio (struct mtd_info * mtd , struct nand_chip * chip ,
2069
2076
u64 addr , unsigned int trans , u32 * buf ,
2070
- u8 * oob , u64 * err_addr )
2077
+ u8 * oob , u64 * err_addr , unsigned int * corr )
2071
2078
{
2072
2079
struct brcmnand_host * host = nand_get_controller_data (chip );
2073
2080
struct brcmnand_controller * ctrl = host -> ctrl ;
2074
2081
int i , ret = 0 ;
2082
+ unsigned int prev_corr ;
2083
+
2084
+ if (corr )
2085
+ * corr = 0 ;
2075
2086
2076
2087
brcmnand_clear_ecc_addr (ctrl );
2077
2088
2078
2089
for (i = 0 ; i < trans ; i ++ , addr += FC_BYTES ) {
2090
+ prev_corr = brcmnand_corr_total (ctrl );
2079
2091
brcmnand_set_cmd_addr (mtd , addr );
2080
2092
/* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */
2081
2093
brcmnand_send_cmd (host , CMD_PAGE_READ );
@@ -2100,13 +2112,16 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip,
2100
2112
2101
2113
if (* err_addr )
2102
2114
ret = - EBADMSG ;
2103
- }
2115
+ else {
2116
+ * err_addr = brcmnand_get_correcc_addr (ctrl );
2104
2117
2105
- if (! ret ) {
2106
- * err_addr = brcmnand_get_correcc_addr ( ctrl ) ;
2118
+ if (* err_addr ) {
2119
+ ret = - EUCLEAN ;
2107
2120
2108
- if (* err_addr )
2109
- ret = - EUCLEAN ;
2121
+ if (corr && (brcmnand_corr_total (ctrl ) - prev_corr ) > * corr )
2122
+ * corr = brcmnand_corr_total (ctrl ) - prev_corr ;
2123
+ }
2124
+ }
2110
2125
}
2111
2126
}
2112
2127
@@ -2174,6 +2189,8 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
2174
2189
int err ;
2175
2190
bool retry = true;
2176
2191
bool edu_err = false;
2192
+ unsigned int corrected = 0 ; /* max corrected bits per subpage */
2193
+ unsigned int prev_tot = brcmnand_corr_total (ctrl );
2177
2194
2178
2195
dev_dbg (ctrl -> dev , "read %llx -> %p\n" , (unsigned long long )addr , buf );
2179
2196
@@ -2201,9 +2218,11 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
2201
2218
memset (oob , 0x99 , mtd -> oobsize );
2202
2219
2203
2220
err = brcmnand_read_by_pio (mtd , chip , addr , trans , buf ,
2204
- oob , & err_addr );
2221
+ oob , & err_addr , & corrected );
2205
2222
}
2206
2223
2224
+ mtd -> ecc_stats .corrected += brcmnand_corr_total (ctrl ) - prev_tot ;
2225
+
2207
2226
if (mtd_is_eccerr (err )) {
2208
2227
/*
2209
2228
* On controller version and 7.0, 7.1 , DMA read after a
@@ -2241,16 +2260,20 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip,
2241
2260
}
2242
2261
2243
2262
if (mtd_is_bitflip (err )) {
2244
- unsigned int corrected = brcmnand_count_corrected (ctrl );
2245
-
2246
2263
/* in case of EDU correctable error we read again using PIO */
2247
2264
if (edu_err )
2248
2265
err = brcmnand_read_by_pio (mtd , chip , addr , trans , buf ,
2249
- oob , & err_addr );
2266
+ oob , & err_addr , & corrected );
2250
2267
2251
2268
dev_dbg (ctrl -> dev , "corrected error at 0x%llx\n" ,
2252
2269
(unsigned long long )err_addr );
2253
- mtd -> ecc_stats .corrected += corrected ;
2270
+ /*
2271
+ * if flipped bits accumulator is not supported but we detected
2272
+ * a correction, increase stat by 1 to match previous behavior.
2273
+ */
2274
+ if (brcmnand_corr_total (ctrl ) == prev_tot )
2275
+ mtd -> ecc_stats .corrected ++ ;
2276
+
2254
2277
/* Always exceed the software-imposed threshold */
2255
2278
return max (mtd -> bitflip_threshold , corrected );
2256
2279
}
0 commit comments