summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2016-02-03 14:11:14 -0500
committerBoris Brezillon <boris.brezillon@free-electrons.com>2016-04-19 16:05:49 -0400
commit78d28e8ec4fbd4d1e0c375d7a28f4f23e9e7b15e (patch)
treee2dee2e1186735d8be0fa8bd3366d0a1ae68d2a6
parent846031d3e1837b71e350bd8098f00995069859a8 (diff)
mtd: nand: atmel: use mtd_ooblayout_xxx() helpers where appropriate
The mtd_ooblayout_xxx() helper functions have been added to avoid direct accesses to the ecclayout field, and thus ease for future reworks. Use these helpers in all places where the oobfree[] and eccpos[] arrays where directly accessed. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Reviewed-by: Nicolas Ferre <nicolas.ferre@atmel.com>
-rw-r--r--drivers/mtd/nand/atmel_nand.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 5e716f2a8739..b132c8fd3701 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -833,13 +833,16 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
833 dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", 833 dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
834 pos, bit_pos, err_byte, *(buf + byte_pos)); 834 pos, bit_pos, err_byte, *(buf + byte_pos));
835 } else { 835 } else {
836 struct mtd_oob_region oobregion;
837
836 /* Bit flip in OOB area */ 838 /* Bit flip in OOB area */
837 tmp = sector_num * nand_chip->ecc.bytes 839 tmp = sector_num * nand_chip->ecc.bytes
838 + (byte_pos - sector_size); 840 + (byte_pos - sector_size);
839 err_byte = ecc[tmp]; 841 err_byte = ecc[tmp];
840 ecc[tmp] ^= (1 << bit_pos); 842 ecc[tmp] ^= (1 << bit_pos);
841 843
842 pos = tmp + nand_chip->ecc.layout->eccpos[0]; 844 mtd_ooblayout_ecc(mtd, 0, &oobregion);
845 pos = tmp + oobregion.offset;
843 dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", 846 dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
844 pos, bit_pos, err_byte, ecc[tmp]); 847 pos, bit_pos, err_byte, ecc[tmp]);
845 } 848 }
@@ -931,7 +934,6 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
931 struct atmel_nand_host *host = nand_get_controller_data(chip); 934 struct atmel_nand_host *host = nand_get_controller_data(chip);
932 int eccsize = chip->ecc.size * chip->ecc.steps; 935 int eccsize = chip->ecc.size * chip->ecc.steps;
933 uint8_t *oob = chip->oob_poi; 936 uint8_t *oob = chip->oob_poi;
934 uint32_t *eccpos = chip->ecc.layout->eccpos;
935 uint32_t stat; 937 uint32_t stat;
936 unsigned long end_time; 938 unsigned long end_time;
937 int bitflips = 0; 939 int bitflips = 0;
@@ -953,7 +955,11 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
953 955
954 stat = pmecc_readl_relaxed(host->ecc, ISR); 956 stat = pmecc_readl_relaxed(host->ecc, ISR);
955 if (stat != 0) { 957 if (stat != 0) {
956 bitflips = pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]); 958 struct mtd_oob_region oobregion;
959
960 mtd_ooblayout_ecc(mtd, 0, &oobregion);
961 bitflips = pmecc_correction(mtd, stat, buf,
962 &oob[oobregion.offset]);
957 if (bitflips < 0) 963 if (bitflips < 0)
958 /* uncorrectable errors */ 964 /* uncorrectable errors */
959 return 0; 965 return 0;
@@ -967,8 +973,8 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
967 int page) 973 int page)
968{ 974{
969 struct atmel_nand_host *host = nand_get_controller_data(chip); 975 struct atmel_nand_host *host = nand_get_controller_data(chip);
970 uint32_t *eccpos = chip->ecc.layout->eccpos; 976 struct mtd_oob_region oobregion = { };
971 int i, j; 977 int i, j, section = 0;
972 unsigned long end_time; 978 unsigned long end_time;
973 979
974 if (!host->nfc || !host->nfc->write_by_sram) { 980 if (!host->nfc || !host->nfc->write_by_sram) {
@@ -987,11 +993,14 @@ static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
987 993
988 for (i = 0; i < chip->ecc.steps; i++) { 994 for (i = 0; i < chip->ecc.steps; i++) {
989 for (j = 0; j < chip->ecc.bytes; j++) { 995 for (j = 0; j < chip->ecc.bytes; j++) {
990 int pos; 996 if (!oobregion.length)
997 mtd_ooblayout_ecc(mtd, section, &oobregion);
991 998
992 pos = i * chip->ecc.bytes + j; 999 chip->oob_poi[oobregion.offset] =
993 chip->oob_poi[eccpos[pos]] =
994 pmecc_readb_ecc_relaxed(host->ecc, i, j); 1000 pmecc_readb_ecc_relaxed(host->ecc, i, j);
1001 oobregion.length--;
1002 oobregion.offset++;
1003 section++;
995 } 1004 }
996 } 1005 }
997 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 1006 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1005,6 +1014,7 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
1005 struct atmel_nand_host *host = nand_get_controller_data(nand_chip); 1014 struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
1006 uint32_t val = 0; 1015 uint32_t val = 0;
1007 struct nand_ecclayout *ecc_layout; 1016 struct nand_ecclayout *ecc_layout;
1017 struct mtd_oob_region oobregion;
1008 1018
1009 pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); 1019 pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
1010 pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); 1020 pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
@@ -1056,9 +1066,10 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
1056 1066
1057 ecc_layout = nand_chip->ecc.layout; 1067 ecc_layout = nand_chip->ecc.layout;
1058 pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1); 1068 pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1);
1059 pmecc_writel(host->ecc, SADDR, ecc_layout->eccpos[0]); 1069 mtd_ooblayout_ecc(mtd, 0, &oobregion);
1070 pmecc_writel(host->ecc, SADDR, oobregion.offset);
1060 pmecc_writel(host->ecc, EADDR, 1071 pmecc_writel(host->ecc, EADDR,
1061 ecc_layout->eccpos[ecc_layout->eccbytes - 1]); 1072 oobregion.offset + ecc_layout->eccbytes - 1);
1062 /* See datasheet about PMECC Clock Control Register */ 1073 /* See datasheet about PMECC Clock Control Register */
1063 pmecc_writel(host->ecc, CLK, 2); 1074 pmecc_writel(host->ecc, CLK, 2);
1064 pmecc_writel(host->ecc, IDR, 0xff); 1075 pmecc_writel(host->ecc, IDR, 0xff);
@@ -1359,12 +1370,12 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
1359{ 1370{
1360 int eccsize = chip->ecc.size; 1371 int eccsize = chip->ecc.size;
1361 int eccbytes = chip->ecc.bytes; 1372 int eccbytes = chip->ecc.bytes;
1362 uint32_t *eccpos = chip->ecc.layout->eccpos;
1363 uint8_t *p = buf; 1373 uint8_t *p = buf;
1364 uint8_t *oob = chip->oob_poi; 1374 uint8_t *oob = chip->oob_poi;
1365 uint8_t *ecc_pos; 1375 uint8_t *ecc_pos;
1366 int stat; 1376 int stat;
1367 unsigned int max_bitflips = 0; 1377 unsigned int max_bitflips = 0;
1378 struct mtd_oob_region oobregion = {};
1368 1379
1369 /* 1380 /*
1370 * Errata: ALE is incorrectly wired up to the ECC controller 1381 * Errata: ALE is incorrectly wired up to the ECC controller
@@ -1382,19 +1393,20 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
1382 chip->read_buf(mtd, p, eccsize); 1393 chip->read_buf(mtd, p, eccsize);
1383 1394
1384 /* move to ECC position if needed */ 1395 /* move to ECC position if needed */
1385 if (eccpos[0] != 0) { 1396 mtd_ooblayout_ecc(mtd, 0, &oobregion);
1386 /* This only works on large pages 1397 if (oobregion.offset != 0) {
1387 * because the ECC controller waits for 1398 /*
1388 * NAND_CMD_RNDOUTSTART after the 1399 * This only works on large pages because the ECC controller
1389 * NAND_CMD_RNDOUT. 1400 * waits for NAND_CMD_RNDOUTSTART after the NAND_CMD_RNDOUT.
1390 * anyway, for small pages, the eccpos[0] == 0 1401 * Anyway, for small pages, the first ECC byte is at offset
1402 * 0 in the OOB area.
1391 */ 1403 */
1392 chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 1404 chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
1393 mtd->writesize + eccpos[0], -1); 1405 mtd->writesize + oobregion.offset, -1);
1394 } 1406 }
1395 1407
1396 /* the ECC controller needs to read the ECC just after the data */ 1408 /* the ECC controller needs to read the ECC just after the data */
1397 ecc_pos = oob + eccpos[0]; 1409 ecc_pos = oob + oobregion.offset;
1398 chip->read_buf(mtd, ecc_pos, eccbytes); 1410 chip->read_buf(mtd, ecc_pos, eccbytes);
1399 1411
1400 /* check if there's an error */ 1412 /* check if there's an error */