137
137
#define BADBLOCK_MARKER_LENGTH 2
138
138
139
139
#ifdef CONFIG_MTD_NAND_OMAP_BCH
140
+ static u_char bch16_vector [] = {0xf5 , 0x24 , 0x1c , 0xd0 , 0x61 , 0xb3 , 0xf1 , 0x55 ,
141
+ 0x2e , 0x2c , 0x86 , 0xa3 , 0xed , 0x36 , 0x1b , 0x78 ,
142
+ 0x48 , 0x76 , 0xa9 , 0x3b , 0x97 , 0xd1 , 0x7a , 0x93 ,
143
+ 0x07 , 0x0e };
140
144
static u_char bch8_vector [] = {0xf3 , 0xdb , 0x14 , 0x16 , 0x8b , 0xd2 , 0xbe , 0xcc ,
141
145
0xac , 0x6b , 0xff , 0x99 , 0x7b };
142
146
static u_char bch4_vector [] = {0x00 , 0x6b , 0x31 , 0xdd , 0x41 , 0xbc , 0x10 };
@@ -1114,6 +1118,19 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode)
1114
1118
ecc_size1 = BCH_ECC_SIZE1 ;
1115
1119
}
1116
1120
break ;
1121
+ case OMAP_ECC_BCH16_CODE_HW :
1122
+ bch_type = 0x2 ;
1123
+ nsectors = chip -> ecc .steps ;
1124
+ if (mode == NAND_ECC_READ ) {
1125
+ wr_mode = 0x01 ;
1126
+ ecc_size0 = 52 ; /* ECC bits in nibbles per sector */
1127
+ ecc_size1 = 0 ; /* non-ECC bits in nibbles per sector */
1128
+ } else {
1129
+ wr_mode = 0x01 ;
1130
+ ecc_size0 = 0 ; /* extra bits in nibbles per sector */
1131
+ ecc_size1 = 52 ; /* OOB bits in nibbles per sector */
1132
+ }
1133
+ break ;
1117
1134
default :
1118
1135
return ;
1119
1136
}
@@ -1162,6 +1179,7 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
1162
1179
struct gpmc_nand_regs * gpmc_regs = & info -> reg ;
1163
1180
u8 * ecc_code ;
1164
1181
unsigned long nsectors , bch_val1 , bch_val2 , bch_val3 , bch_val4 ;
1182
+ u32 val ;
1165
1183
int i ;
1166
1184
1167
1185
nsectors = ((readl (info -> reg .gpmc_ecc_config ) >> 4 ) & 0x7 ) + 1 ;
@@ -1201,6 +1219,41 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
1201
1219
* ecc_code ++ = ((bch_val1 >> 4 ) & 0xFF );
1202
1220
* ecc_code ++ = ((bch_val1 & 0xF ) << 4 );
1203
1221
break ;
1222
+ case OMAP_ECC_BCH16_CODE_HW :
1223
+ val = readl (gpmc_regs -> gpmc_bch_result6 [i ]);
1224
+ ecc_code [0 ] = ((val >> 8 ) & 0xFF );
1225
+ ecc_code [1 ] = ((val >> 0 ) & 0xFF );
1226
+ val = readl (gpmc_regs -> gpmc_bch_result5 [i ]);
1227
+ ecc_code [2 ] = ((val >> 24 ) & 0xFF );
1228
+ ecc_code [3 ] = ((val >> 16 ) & 0xFF );
1229
+ ecc_code [4 ] = ((val >> 8 ) & 0xFF );
1230
+ ecc_code [5 ] = ((val >> 0 ) & 0xFF );
1231
+ val = readl (gpmc_regs -> gpmc_bch_result4 [i ]);
1232
+ ecc_code [6 ] = ((val >> 24 ) & 0xFF );
1233
+ ecc_code [7 ] = ((val >> 16 ) & 0xFF );
1234
+ ecc_code [8 ] = ((val >> 8 ) & 0xFF );
1235
+ ecc_code [9 ] = ((val >> 0 ) & 0xFF );
1236
+ val = readl (gpmc_regs -> gpmc_bch_result3 [i ]);
1237
+ ecc_code [10 ] = ((val >> 24 ) & 0xFF );
1238
+ ecc_code [11 ] = ((val >> 16 ) & 0xFF );
1239
+ ecc_code [12 ] = ((val >> 8 ) & 0xFF );
1240
+ ecc_code [13 ] = ((val >> 0 ) & 0xFF );
1241
+ val = readl (gpmc_regs -> gpmc_bch_result2 [i ]);
1242
+ ecc_code [14 ] = ((val >> 24 ) & 0xFF );
1243
+ ecc_code [15 ] = ((val >> 16 ) & 0xFF );
1244
+ ecc_code [16 ] = ((val >> 8 ) & 0xFF );
1245
+ ecc_code [17 ] = ((val >> 0 ) & 0xFF );
1246
+ val = readl (gpmc_regs -> gpmc_bch_result1 [i ]);
1247
+ ecc_code [18 ] = ((val >> 24 ) & 0xFF );
1248
+ ecc_code [19 ] = ((val >> 16 ) & 0xFF );
1249
+ ecc_code [20 ] = ((val >> 8 ) & 0xFF );
1250
+ ecc_code [21 ] = ((val >> 0 ) & 0xFF );
1251
+ val = readl (gpmc_regs -> gpmc_bch_result0 [i ]);
1252
+ ecc_code [22 ] = ((val >> 24 ) & 0xFF );
1253
+ ecc_code [23 ] = ((val >> 16 ) & 0xFF );
1254
+ ecc_code [24 ] = ((val >> 8 ) & 0xFF );
1255
+ ecc_code [25 ] = ((val >> 0 ) & 0xFF );
1256
+ break ;
1204
1257
default :
1205
1258
return - EINVAL ;
1206
1259
}
@@ -1227,6 +1280,8 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
1227
1280
/* Set 14th ECC byte as 0x0 for ROM compatibility */
1228
1281
ecc_calc [eccbytes - 1 ] = 0x0 ;
1229
1282
break ;
1283
+ case OMAP_ECC_BCH16_CODE_HW :
1284
+ break ;
1230
1285
default :
1231
1286
return - EINVAL ;
1232
1287
}
@@ -1318,6 +1373,10 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
1318
1373
actual_eccbytes = ecc -> bytes - 1 ;
1319
1374
erased_ecc_vec = bch8_vector ;
1320
1375
break ;
1376
+ case OMAP_ECC_BCH16_CODE_HW :
1377
+ actual_eccbytes = ecc -> bytes ;
1378
+ erased_ecc_vec = bch16_vector ;
1379
+ break ;
1321
1380
default :
1322
1381
pr_err ("invalid driver configuration\n" );
1323
1382
return - EINVAL ;
@@ -1401,6 +1460,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
1401
1460
BCH4_BIT_PAD ;
1402
1461
break ;
1403
1462
case OMAP_ECC_BCH8_CODE_HW :
1463
+ case OMAP_ECC_BCH16_CODE_HW :
1404
1464
pos = err_vec [i ].error_loc [j ];
1405
1465
break ;
1406
1466
default :
@@ -1912,6 +1972,40 @@ static int omap_nand_probe(struct platform_device *pdev)
1912
1972
goto return_error ;
1913
1973
#endif
1914
1974
1975
+ case OMAP_ECC_BCH16_CODE_HW :
1976
+ #ifdef CONFIG_MTD_NAND_OMAP_BCH
1977
+ pr_info ("using OMAP_ECC_BCH16_CODE_HW ECC scheme\n" );
1978
+ nand_chip -> ecc .mode = NAND_ECC_HW ;
1979
+ nand_chip -> ecc .size = 512 ;
1980
+ nand_chip -> ecc .bytes = 26 ;
1981
+ nand_chip -> ecc .strength = 16 ;
1982
+ nand_chip -> ecc .hwctl = omap_enable_hwecc_bch ;
1983
+ nand_chip -> ecc .correct = omap_elm_correct_data ;
1984
+ nand_chip -> ecc .calculate = omap_calculate_ecc_bch ;
1985
+ nand_chip -> ecc .read_page = omap_read_page_bch ;
1986
+ nand_chip -> ecc .write_page = omap_write_page_bch ;
1987
+ /* This ECC scheme requires ELM H/W block */
1988
+ err = is_elm_present (info , pdata -> elm_of_node , BCH16_ECC );
1989
+ if (err < 0 ) {
1990
+ pr_err ("ELM is required for this ECC scheme\n" );
1991
+ goto return_error ;
1992
+ }
1993
+ /* define ECC layout */
1994
+ ecclayout -> eccbytes = nand_chip -> ecc .bytes *
1995
+ (mtd -> writesize /
1996
+ nand_chip -> ecc .size );
1997
+ oob_index = BADBLOCK_MARKER_LENGTH ;
1998
+ for (i = 0 ; i < ecclayout -> eccbytes ; i ++ , oob_index ++ )
1999
+ ecclayout -> eccpos [i ] = oob_index ;
2000
+ /* reserved marker already included in ecclayout->eccbytes */
2001
+ ecclayout -> oobfree -> offset =
2002
+ ecclayout -> eccpos [ecclayout -> eccbytes - 1 ] + 1 ;
2003
+ break ;
2004
+ #else
2005
+ pr_err ("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n" );
2006
+ err = - EINVAL ;
2007
+ goto return_error ;
2008
+ #endif
1915
2009
default :
1916
2010
pr_err ("nand: error: invalid or unsupported ECC scheme\n" );
1917
2011
err = - EINVAL ;
0 commit comments