Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mtd: rawnand: sunxi: introduce maximize variable user data length

In Allwinner SoCs, user data can be added in OOB before each ECC data.
For older SoCs like A10, the user data size was the size of a register
(4 bytes) and was mandatory before each ECC step.
So, the A10 OOB Layout is:
[4Bytes USER_DATA_STEP0] [ECC_STEP0 bytes]
[4bytes USER_DATA_STEP1] [ECC_STEP1 bytes]
...
NB: the BBM is stored at the beginning of the USER_DATA_STEP0.

Now, for H6/H616 NAND flash controller, this user data can have a
different size for each step.
So, we are maximizing the user data length to use as many OOB bytes as
possible.

Fixes: 88fd4e4deae8 ("mtd: rawnand: sunxi: Add support for H616 nand controller")
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

authored by

Richard Genoud and committed by
Miquel Raynal
54dcd6aa a22f40d9

+257 -64
+257 -64
drivers/mtd/nand/raw/sunxi_nand.c
··· 209 209 210 210 /* 211 211 * On A10/A23, this is the size of the NDFC User Data Register, containing the 212 - * mandatory user data bytes following the ECC for each ECC step. 212 + * mandatory user data bytes preceding the ECC for each ECC step. 213 213 * Thus, for each ECC step, we need the ECC bytes + USER_DATA_SZ. 214 - * Those bits are currently unsused, and kept as default value 0xffffffff. 215 214 * 216 215 * On H6/H616, this size became configurable, from 0 bytes to 32, via the 217 216 * USER_DATA_LEN registers. ··· 248 249 * @timing_ctl: TIMING_CTL register value for this NAND chip 249 250 * @nsels: number of CS lines required by the NAND chip 250 251 * @sels: array of CS lines descriptions 252 + * @user_data_bytes: array of user data lengths for all ECC steps 251 253 */ 252 254 struct sunxi_nand_chip { 253 255 struct list_head node; ··· 257 257 unsigned long clk_rate; 258 258 u32 timing_cfg; 259 259 u32 timing_ctl; 260 + u8 *user_data_bytes; 260 261 int nsels; 261 262 struct sunxi_nand_chip_sel sels[] __counted_by(nsels); 262 263 }; ··· 824 823 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 825 824 } 826 825 827 - static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, 828 - int step, bool bbm, int page) 826 + static u8 sunxi_nfc_user_data_sz(struct sunxi_nand_chip *sunxi_nand, int step) 829 827 { 830 - struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 828 + if (!sunxi_nand->user_data_bytes) 829 + return USER_DATA_SZ; 831 830 832 - sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)), oob); 831 + return sunxi_nand->user_data_bytes[step]; 832 + } 833 + 834 + static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob, 835 + int step, bool bbm, int page, 836 + unsigned int user_data_sz) 837 + { 838 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 839 + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 840 + u32 user_data; 841 + 842 + if (!nfc->caps->reg_user_data_len) { 843 + /* 844 + * For A10, the user data for step n is in the nth 845 + * REG_USER_DATA 846 + */ 847 + user_data = readl(nfc->regs + NFC_REG_USER_DATA(nfc, step)); 848 + sunxi_nfc_user_data_to_buf(user_data, oob); 849 + } else { 850 + /* 851 + * For H6 NAND controller, the user data for all steps is 852 + * contained in 32 user data registers, but not at a specific 853 + * offset for each step, they are just concatenated. 854 + */ 855 + unsigned int user_data_off = 0; 856 + unsigned int reg_off; 857 + u8 *ptr = oob; 858 + unsigned int i; 859 + 860 + for (i = 0; i < step; i++) 861 + user_data_off += sunxi_nfc_user_data_sz(sunxi_nand, i); 862 + 863 + user_data_off /= 4; 864 + for (i = 0; i < user_data_sz / 4; i++, ptr += 4) { 865 + reg_off = NFC_REG_USER_DATA(nfc, user_data_off + i); 866 + user_data = readl(nfc->regs + reg_off); 867 + sunxi_nfc_user_data_to_buf(user_data, ptr); 868 + } 869 + } 833 870 834 871 /* De-randomize the Bad Block Marker. */ 835 872 if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) ··· 926 887 bool bbm, int page) 927 888 { 928 889 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 929 - u8 user_data[USER_DATA_SZ]; 890 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 891 + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); 892 + u8 *user_data = NULL; 930 893 931 894 /* Randomize the Bad Block Marker. */ 932 895 if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) { 933 - memcpy(user_data, oob, sizeof(user_data)); 896 + user_data = kmalloc(user_data_sz, GFP_KERNEL); 897 + memcpy(user_data, oob, user_data_sz); 934 898 sunxi_nfc_randomize_bbm(nand, page, user_data); 935 899 oob = user_data; 936 900 } 937 901 938 - writel(sunxi_nfc_buf_to_user_data(oob), 939 - nfc->regs + NFC_REG_USER_DATA(nfc, step)); 902 + if (!nfc->caps->reg_user_data_len) { 903 + /* 904 + * For A10, the user data for step n is in the nth 905 + * REG_USER_DATA 906 + */ 907 + writel(sunxi_nfc_buf_to_user_data(oob), 908 + nfc->regs + NFC_REG_USER_DATA(nfc, step)); 909 + } else { 910 + /* 911 + * For H6 NAND controller, the user data for all steps is 912 + * contained in 32 user data registers, but not at a specific 913 + * offset for each step, they are just concatenated. 914 + */ 915 + unsigned int user_data_off = 0; 916 + const u8 *ptr = oob; 917 + unsigned int i; 918 + 919 + for (i = 0; i < step; i++) 920 + user_data_off += sunxi_nfc_user_data_sz(sunxi_nand, i); 921 + 922 + user_data_off /= 4; 923 + for (i = 0; i < user_data_sz / 4; i++, ptr += 4) { 924 + writel(sunxi_nfc_buf_to_user_data(ptr), 925 + nfc->regs + NFC_REG_USER_DATA(nfc, user_data_off + i)); 926 + } 927 + } 928 + 929 + kfree(user_data); 940 930 } 941 931 942 932 static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand, ··· 986 918 bool *erased) 987 919 { 988 920 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 921 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 922 + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); 989 923 struct nand_ecc_ctrl *ecc = &nand->ecc; 990 924 u32 tmp; 991 925 ··· 1010 940 memset(data, pattern, ecc->size); 1011 941 1012 942 if (oob) 1013 - memset(oob, pattern, ecc->bytes + USER_DATA_SZ); 943 + memset(oob, pattern, ecc->bytes + user_data_sz); 1014 944 1015 945 return 0; 1016 946 } ··· 1025 955 u8 *oob, int oob_off, 1026 956 int *cur_off, 1027 957 unsigned int *max_bitflips, 1028 - bool bbm, bool oob_required, int page) 958 + int step, bool oob_required, int page) 1029 959 { 1030 960 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 961 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 962 + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); 1031 963 struct nand_ecc_ctrl *ecc = &nand->ecc; 1032 964 int raw_mode = 0; 1033 965 u32 pattern_found; 966 + bool bbm = !step; 1034 967 bool erased; 1035 968 int ret; 1036 969 /* From the controller point of view, we are at step 0 */ ··· 1051 978 if (ret) 1052 979 return ret; 1053 980 1054 - sunxi_nfc_reset_user_data_len(nfc); 1055 - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, nfc_step); 981 + sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); 1056 982 sunxi_nfc_randomizer_config(nand, page, false); 1057 983 sunxi_nfc_randomizer_enable(nand); 1058 984 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP, ··· 1062 990 if (ret) 1063 991 return ret; 1064 992 1065 - *cur_off = oob_off + ecc->bytes + USER_DATA_SZ; 993 + *cur_off = oob_off + ecc->bytes + user_data_sz; 1066 994 1067 995 pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found); 1068 996 pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found); ··· 1086 1014 ecc->size); 1087 1015 1088 1016 nand_change_read_column_op(nand, oob_off, oob, 1089 - ecc->bytes + USER_DATA_SZ, false); 1017 + ecc->bytes + user_data_sz, false); 1090 1018 1091 1019 ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, 1092 - ecc->bytes + USER_DATA_SZ, 1020 + ecc->bytes + user_data_sz, 1093 1021 NULL, 0, ecc->strength); 1094 1022 if (ret >= 0) 1095 1023 raw_mode = 1; ··· 1099 1027 if (oob_required) { 1100 1028 nand_change_read_column_op(nand, oob_off, NULL, 0, 1101 1029 false); 1102 - sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + USER_DATA_SZ, 1030 + sunxi_nfc_randomizer_read_buf(nand, oob, ecc->bytes + user_data_sz, 1103 1031 true, page); 1104 1032 1105 1033 sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, nfc_step, 1106 - bbm, page); 1034 + bbm, page, user_data_sz); 1107 1035 } 1108 1036 } 1109 1037 ··· 1112 1040 return raw_mode; 1113 1041 } 1114 1042 1043 + /* 1044 + * Returns the offset of the OOB for each step. 1045 + * (it includes the user data before the ECC data.) 1046 + */ 1047 + static int sunxi_get_oob_offset(struct sunxi_nand_chip *sunxi_nand, 1048 + struct nand_ecc_ctrl *ecc, int step) 1049 + { 1050 + int ecc_off = step * ecc->bytes; 1051 + int i; 1052 + 1053 + for (i = 0; i < step; i++) 1054 + ecc_off += sunxi_nfc_user_data_sz(sunxi_nand, i); 1055 + 1056 + return ecc_off; 1057 + } 1058 + 1059 + /* 1060 + * Returns the offset of the ECC for each step. 1061 + * So, it's the same as sunxi_get_oob_offset(), 1062 + * but it skips the next user data. 1063 + */ 1064 + static int sunxi_get_ecc_offset(struct sunxi_nand_chip *sunxi_nand, 1065 + struct nand_ecc_ctrl *ecc, int step) 1066 + { 1067 + return sunxi_get_oob_offset(sunxi_nand, ecc, step) + 1068 + sunxi_nfc_user_data_sz(sunxi_nand, step); 1069 + } 1070 + 1115 1071 static void sunxi_nfc_hw_ecc_read_extra_oob(struct nand_chip *nand, 1116 1072 u8 *oob, int *cur_off, 1117 1073 bool randomize, int page) 1118 1074 { 1075 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1119 1076 struct mtd_info *mtd = nand_to_mtd(nand); 1120 1077 struct nand_ecc_ctrl *ecc = &nand->ecc; 1121 - int offset = ((ecc->bytes + USER_DATA_SZ) * ecc->steps); 1078 + int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); 1122 1079 int len = mtd->oobsize - offset; 1123 1080 1124 1081 if (len <= 0) ··· 1172 1071 int nchunks) 1173 1072 { 1174 1073 bool randomized = nand->options & NAND_NEED_SCRAMBLING; 1074 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1175 1075 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 1176 1076 struct mtd_info *mtd = nand_to_mtd(nand); 1177 1077 struct nand_ecc_ctrl *ecc = &nand->ecc; ··· 1192 1090 1193 1091 sunxi_nfc_hw_ecc_enable(nand); 1194 1092 sunxi_nfc_reset_user_data_len(nfc); 1195 - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, 0); 1093 + for (i = 0; i < nchunks; i++) 1094 + sunxi_nfc_set_user_data_len(nfc, sunxi_nfc_user_data_sz(sunxi_nand, i), i); 1196 1095 sunxi_nfc_randomizer_config(nand, page, false); 1197 1096 sunxi_nfc_randomizer_enable(nand); 1198 1097 ··· 1228 1125 1229 1126 for (i = 0; i < nchunks; i++) { 1230 1127 int data_off = i * ecc->size; 1231 - int oob_off = i * (ecc->bytes + USER_DATA_SZ); 1128 + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); 1129 + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); 1232 1130 u8 *data = buf + data_off; 1233 1131 u8 *oob = nand->oob_poi + oob_off; 1234 1132 bool erased; ··· 1247 1143 /* TODO: use DMA to retrieve OOB */ 1248 1144 nand_change_read_column_op(nand, 1249 1145 mtd->writesize + oob_off, 1250 - oob, ecc->bytes + USER_DATA_SZ, false); 1146 + oob, ecc->bytes + user_data_sz, false); 1251 1147 1252 - sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, 1253 - !i, page); 1148 + sunxi_nfc_hw_ecc_get_prot_oob_bytes(nand, oob, i, !i, 1149 + page, user_data_sz); 1254 1150 } 1255 1151 1256 1152 if (erased) ··· 1262 1158 if (status & NFC_ECC_ERR_MSK(nfc)) { 1263 1159 for (i = 0; i < nchunks; i++) { 1264 1160 int data_off = i * ecc->size; 1265 - int oob_off = i * (ecc->bytes + USER_DATA_SZ); 1161 + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); 1162 + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); 1266 1163 u8 *data = buf + data_off; 1267 1164 u8 *oob = nand->oob_poi + oob_off; 1268 1165 ··· 1283 1178 /* TODO: use DMA to retrieve OOB */ 1284 1179 nand_change_read_column_op(nand, 1285 1180 mtd->writesize + oob_off, 1286 - oob, ecc->bytes + USER_DATA_SZ, false); 1181 + oob, ecc->bytes + user_data_sz, false); 1287 1182 1288 1183 ret = nand_check_erased_ecc_chunk(data, ecc->size, oob, 1289 - ecc->bytes + USER_DATA_SZ, 1184 + ecc->bytes + user_data_sz, 1290 1185 NULL, 0, 1291 1186 ecc->strength); 1292 1187 if (ret >= 0) ··· 1307 1202 static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand, 1308 1203 const u8 *data, int data_off, 1309 1204 const u8 *oob, int oob_off, 1310 - int *cur_off, bool bbm, 1205 + int *cur_off, int step, 1311 1206 int page) 1312 1207 { 1313 1208 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 1209 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1210 + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, step); 1314 1211 struct nand_ecc_ctrl *ecc = &nand->ecc; 1212 + bool bbm = !step; 1315 1213 int ret; 1316 1214 /* From the controller point of view, we are at step 0 */ 1317 1215 const int nfc_step = 0; ··· 1333 1225 1334 1226 sunxi_nfc_randomizer_config(nand, page, false); 1335 1227 sunxi_nfc_randomizer_enable(nand); 1336 - sunxi_nfc_reset_user_data_len(nfc); 1337 - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, nfc_step); 1228 + sunxi_nfc_set_user_data_len(nfc, user_data_sz, nfc_step); 1338 1229 sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, nfc_step, bbm, page); 1339 1230 1340 1231 writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | ··· 1345 1238 if (ret) 1346 1239 return ret; 1347 1240 1348 - *cur_off = oob_off + ecc->bytes + USER_DATA_SZ; 1241 + *cur_off = oob_off + ecc->bytes + user_data_sz; 1349 1242 1350 1243 return 0; 1351 1244 } ··· 1355 1248 int page) 1356 1249 { 1357 1250 struct mtd_info *mtd = nand_to_mtd(nand); 1251 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1358 1252 struct nand_ecc_ctrl *ecc = &nand->ecc; 1359 - int offset = ((ecc->bytes + USER_DATA_SZ) * ecc->steps); 1253 + int offset = sunxi_get_oob_offset(sunxi_nand, ecc, ecc->steps); 1360 1254 int len = mtd->oobsize - offset; 1361 1255 1362 1256 if (len <= 0) ··· 1376 1268 static int sunxi_nfc_hw_ecc_read_page(struct nand_chip *nand, uint8_t *buf, 1377 1269 int oob_required, int page) 1378 1270 { 1271 + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 1272 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1379 1273 struct mtd_info *mtd = nand_to_mtd(nand); 1380 1274 struct nand_ecc_ctrl *ecc = &nand->ecc; 1381 1275 unsigned int max_bitflips = 0; ··· 1390 1280 1391 1281 sunxi_nfc_hw_ecc_enable(nand); 1392 1282 1283 + sunxi_nfc_reset_user_data_len(nfc); 1393 1284 for (i = 0; i < ecc->steps; i++) { 1394 1285 int data_off = i * ecc->size; 1395 - int oob_off = i * (ecc->bytes + USER_DATA_SZ); 1286 + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); 1396 1287 u8 *data = buf + data_off; 1397 1288 u8 *oob = nand->oob_poi + oob_off; 1398 1289 1399 1290 ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, oob, 1400 1291 oob_off + mtd->writesize, 1401 1292 &cur_off, &max_bitflips, 1402 - !i, oob_required, page); 1293 + i, oob_required, page); 1403 1294 if (ret < 0) 1404 1295 return ret; 1405 1296 else if (ret) ··· 1438 1327 u32 data_offs, u32 readlen, 1439 1328 u8 *bufpoi, int page) 1440 1329 { 1330 + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 1331 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1441 1332 struct mtd_info *mtd = nand_to_mtd(nand); 1442 1333 struct nand_ecc_ctrl *ecc = &nand->ecc; 1443 1334 int ret, i, cur_off = 0; ··· 1451 1338 1452 1339 sunxi_nfc_hw_ecc_enable(nand); 1453 1340 1341 + sunxi_nfc_reset_user_data_len(nfc); 1454 1342 for (i = data_offs / ecc->size; 1455 1343 i < DIV_ROUND_UP(data_offs + readlen, ecc->size); i++) { 1456 1344 int data_off = i * ecc->size; 1457 - int oob_off = i * (ecc->bytes + USER_DATA_SZ); 1345 + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); 1458 1346 u8 *data = bufpoi + data_off; 1459 1347 u8 *oob = nand->oob_poi + oob_off; 1460 1348 1461 1349 ret = sunxi_nfc_hw_ecc_read_chunk(nand, data, data_off, 1462 1350 oob, 1463 1351 oob_off + mtd->writesize, 1464 - &cur_off, &max_bitflips, !i, 1352 + &cur_off, &max_bitflips, i, 1465 1353 false, page); 1466 1354 if (ret < 0) 1467 1355 return ret; ··· 1497 1383 const uint8_t *buf, int oob_required, 1498 1384 int page) 1499 1385 { 1386 + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 1387 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1500 1388 struct mtd_info *mtd = nand_to_mtd(nand); 1501 1389 struct nand_ecc_ctrl *ecc = &nand->ecc; 1502 1390 int ret, i, cur_off = 0; ··· 1509 1393 1510 1394 sunxi_nfc_hw_ecc_enable(nand); 1511 1395 1396 + sunxi_nfc_reset_user_data_len(nfc); 1512 1397 for (i = 0; i < ecc->steps; i++) { 1513 1398 int data_off = i * ecc->size; 1514 - int oob_off = i * (ecc->bytes + USER_DATA_SZ); 1399 + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); 1515 1400 const u8 *data = buf + data_off; 1516 1401 const u8 *oob = nand->oob_poi + oob_off; 1517 1402 1518 1403 ret = sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob, 1519 1404 oob_off + mtd->writesize, 1520 - &cur_off, !i, page); 1405 + &cur_off, i, page); 1521 1406 if (ret) 1522 1407 return ret; 1523 1408 } ··· 1537 1420 const u8 *buf, int oob_required, 1538 1421 int page) 1539 1422 { 1423 + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 1424 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1540 1425 struct mtd_info *mtd = nand_to_mtd(nand); 1541 1426 struct nand_ecc_ctrl *ecc = &nand->ecc; 1542 1427 int ret, i, cur_off = 0; ··· 1549 1430 1550 1431 sunxi_nfc_hw_ecc_enable(nand); 1551 1432 1433 + sunxi_nfc_reset_user_data_len(nfc); 1552 1434 for (i = data_offs / ecc->size; 1553 1435 i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) { 1554 1436 int data_off = i * ecc->size; 1555 - int oob_off = i * (ecc->bytes + USER_DATA_SZ); 1437 + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); 1556 1438 const u8 *data = buf + data_off; 1557 1439 const u8 *oob = nand->oob_poi + oob_off; 1558 1440 1559 1441 ret = sunxi_nfc_hw_ecc_write_chunk(nand, data, data_off, oob, 1560 1442 oob_off + mtd->writesize, 1561 - &cur_off, !i, page); 1443 + &cur_off, i, page); 1562 1444 if (ret) 1563 1445 return ret; 1564 1446 } ··· 1575 1455 int page) 1576 1456 { 1577 1457 struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 1458 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1578 1459 struct nand_ecc_ctrl *ecc = &nand->ecc; 1579 1460 struct scatterlist sg; 1580 1461 u32 wait; ··· 1594 1473 1595 1474 sunxi_nfc_reset_user_data_len(nfc); 1596 1475 for (i = 0; i < ecc->steps; i++) { 1597 - const u8 *oob = nand->oob_poi + (i * (ecc->bytes + USER_DATA_SZ)); 1476 + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, i); 1477 + int oob_off = sunxi_get_oob_offset(sunxi_nand, ecc, i); 1478 + const u8 *oob = nand->oob_poi + oob_off; 1598 1479 1599 1480 sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page); 1600 - sunxi_nfc_set_user_data_len(nfc, USER_DATA_SZ, i); 1481 + sunxi_nfc_set_user_data_len(nfc, user_data_sz, i); 1601 1482 } 1602 1483 1603 1484 nand_prog_page_begin_op(nand, page, 0, NULL, 0); ··· 1863 1740 { 1864 1741 struct nand_chip *nand = mtd_to_nand(mtd); 1865 1742 struct nand_ecc_ctrl *ecc = &nand->ecc; 1743 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1866 1744 1867 1745 if (section >= ecc->steps) 1868 1746 return -ERANGE; 1869 1747 1870 - oobregion->offset = section * (ecc->bytes + USER_DATA_SZ) + USER_DATA_SZ; 1748 + oobregion->offset = sunxi_get_ecc_offset(sunxi_nand, ecc, section); 1871 1749 oobregion->length = ecc->bytes; 1872 1750 1873 1751 return 0; ··· 1879 1755 { 1880 1756 struct nand_chip *nand = mtd_to_nand(mtd); 1881 1757 struct nand_ecc_ctrl *ecc = &nand->ecc; 1758 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1759 + unsigned int user_data_sz = sunxi_nfc_user_data_sz(sunxi_nand, section); 1882 1760 1883 1761 /* 1884 1762 * The controller does not provide access to OOB bytes ··· 1891 1765 1892 1766 /* 1893 1767 * The first 2 bytes are used for BB markers, hence we 1894 - * only have USER_DATA_SZ - 2 bytes available in the first user data 1768 + * only have user_data_sz - 2 bytes available in the first user data 1895 1769 * section. 1896 1770 */ 1897 1771 if (section == 0) { 1898 1772 oobregion->offset = 2; 1899 - oobregion->length = USER_DATA_SZ - 2; 1773 + oobregion->length = user_data_sz - 2; 1900 1774 1901 1775 return 0; 1902 1776 } 1903 1777 1904 - oobregion->offset = section * (ecc->bytes + USER_DATA_SZ); 1905 - oobregion->length = USER_DATA_SZ; 1778 + oobregion->offset = sunxi_get_ecc_offset(sunxi_nand, ecc, section); 1779 + oobregion->length = user_data_sz; 1906 1780 1907 1781 return 0; 1908 1782 } ··· 1911 1785 .ecc = sunxi_nand_ooblayout_ecc, 1912 1786 .free = sunxi_nand_ooblayout_free, 1913 1787 }; 1788 + 1789 + static void sunxi_nand_detach_chip(struct nand_chip *nand) 1790 + { 1791 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1792 + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 1793 + 1794 + devm_kfree(nfc->dev, sunxi_nand->user_data_bytes); 1795 + sunxi_nand->user_data_bytes = NULL; 1796 + } 1797 + 1798 + static int sunxi_nfc_maximize_user_data(struct nand_chip *nand, uint32_t oobsize, 1799 + int ecc_bytes, int nsectors) 1800 + { 1801 + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand); 1802 + struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller); 1803 + const struct sunxi_nfc_caps *c = nfc->caps; 1804 + int remaining_bytes = oobsize - (ecc_bytes * nsectors); 1805 + int i, step; 1806 + 1807 + sunxi_nand->user_data_bytes = devm_kzalloc(nfc->dev, nsectors, 1808 + GFP_KERNEL); 1809 + if (!sunxi_nand->user_data_bytes) 1810 + return -ENOMEM; 1811 + 1812 + for (step = 0; (step < nsectors) && (remaining_bytes > 0); step++) { 1813 + for (i = 0; i < c->nuser_data_tab; i++) { 1814 + if (c->user_data_len_tab[i] > remaining_bytes) 1815 + break; 1816 + sunxi_nand->user_data_bytes[step] = c->user_data_len_tab[i]; 1817 + } 1818 + remaining_bytes -= sunxi_nand->user_data_bytes[step]; 1819 + if (sunxi_nand->user_data_bytes[step] == 0) 1820 + break; 1821 + } 1822 + 1823 + return 0; 1824 + } 1914 1825 1915 1826 static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand, 1916 1827 struct nand_ecc_ctrl *ecc, ··· 1958 1795 const u8 *strengths = nfc->caps->ecc_strengths; 1959 1796 struct mtd_info *mtd = nand_to_mtd(nand); 1960 1797 struct nand_device *nanddev = mtd_to_nanddev(mtd); 1798 + int total_user_data_sz = 0; 1961 1799 int nsectors; 1962 1800 int ecc_mode; 1963 1801 int i; 1964 1802 1965 1803 if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE_STRENGTH) { 1966 - int bytes; 1804 + int bytes = mtd->oobsize; 1967 1805 1968 1806 ecc->size = 1024; 1969 1807 nsectors = mtd->writesize / ecc->size; 1970 1808 1971 - /* 1972 - * The 2 BBM bytes should not be removed from the grand total, 1973 - * because they are part of the USER_DATA_SZ. 1974 - * But we can't modify that for older platform since it may 1975 - * result in a stronger ECC at the end, and break the 1976 - * compatibility. 1977 - */ 1978 - if (nfc->caps->legacy_max_strength) 1979 - bytes = (mtd->oobsize - 2) / nsectors; 1980 - else 1981 - bytes = mtd->oobsize / nsectors; 1809 + if (!nfc->caps->reg_user_data_len) { 1810 + /* 1811 + * If there's a fixed user data length, subtract it before 1812 + * computing the max ECC strength 1813 + */ 1814 + 1815 + for (i = 0; i < nsectors; i++) 1816 + total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); 1817 + 1818 + /* 1819 + * The 2 BBM bytes should not be removed from the grand total, 1820 + * because they are part of the USER_DATA_SZ. 1821 + * But we can't modify that for older platform since it may 1822 + * result in a stronger ECC at the end, and break the 1823 + * compatibility. 1824 + */ 1825 + if (nfc->caps->legacy_max_strength) 1826 + bytes -= 2; 1827 + 1828 + bytes -= total_user_data_sz; 1829 + } else { 1830 + /* 1831 + * remove at least the BBM size before computing the 1832 + * max ECC 1833 + */ 1834 + bytes -= 2; 1835 + } 1982 1836 1983 1837 /* 1984 - * USER_DATA_SZ non-ECC bytes are added before each ECC bytes 1985 - * section, they contain the 2 BBM bytes 1838 + * Once all user data has been subtracted, the rest can be used 1839 + * for ECC bytes 1986 1840 */ 1987 - bytes -= USER_DATA_SZ; 1841 + bytes /= nsectors; 1988 1842 1989 1843 /* and bytes has to be even. */ 1990 1844 if (bytes % 2) ··· 2054 1874 2055 1875 nsectors = mtd->writesize / ecc->size; 2056 1876 2057 - if (mtd->oobsize < ((ecc->bytes + USER_DATA_SZ) * nsectors)) 1877 + /* 1878 + * The rationale for variable data length is to prioritize maximum ECC 1879 + * strength, and then use the remaining space for user data. 1880 + */ 1881 + if (nfc->caps->reg_user_data_len) 1882 + sunxi_nfc_maximize_user_data(nand, mtd->oobsize, ecc->bytes, 1883 + nsectors); 1884 + 1885 + if (total_user_data_sz == 0) 1886 + for (i = 0; i < nsectors; i++) 1887 + total_user_data_sz += sunxi_nfc_user_data_sz(sunxi_nand, i); 1888 + 1889 + if (mtd->oobsize < (ecc->bytes * nsectors + total_user_data_sz)) 2058 1890 return -EINVAL; 2059 1891 2060 1892 ecc->read_oob = sunxi_nfc_hw_ecc_read_oob; ··· 2296 2104 2297 2105 static const struct nand_controller_ops sunxi_nand_controller_ops = { 2298 2106 .attach_chip = sunxi_nand_attach_chip, 2107 + .detach_chip = sunxi_nand_detach_chip, 2299 2108 .setup_interface = sunxi_nfc_setup_interface, 2300 2109 .exec_op = sunxi_nfc_exec_op, 2301 2110 };