diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/mips/ingenic_x1000/nand-x1000.c | 20 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/nand-x1000.h | 3 |
2 files changed, 23 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c index 2b62e8fb42..286dc3c64b 100644 --- a/firmware/target/mips/ingenic_x1000/nand-x1000.c +++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "nand-x1000.h" | 22 | #include "nand-x1000.h" |
23 | #include "sfc-x1000.h" | 23 | #include "sfc-x1000.h" |
24 | #include "system.h" | 24 | #include "system.h" |
25 | #include "logf.h" | ||
25 | #include <string.h> | 26 | #include <string.h> |
26 | 27 | ||
27 | const struct nand_chip supported_nand_chips[] = { | 28 | const struct nand_chip supported_nand_chips[] = { |
@@ -151,6 +152,11 @@ static void setup_chip_registers(struct nand_drv* drv) | |||
151 | en ? FREG_CFG_QUAD_ENABLE : 0); | 152 | en ? FREG_CFG_QUAD_ENABLE : 0); |
152 | } | 153 | } |
153 | 154 | ||
155 | if(drv->chip->flags & NAND_CHIPFLAG_ON_DIE_ECC) { | ||
156 | /* Enable on-die ECC */ | ||
157 | nand_upd_reg(drv, FREG_CFG, FREG_CFG_ECC_ENABLE, FREG_CFG_ECC_ENABLE); | ||
158 | } | ||
159 | |||
154 | /* Clear OTP bit to access the main data array */ | 160 | /* Clear OTP bit to access the main data array */ |
155 | nand_upd_reg(drv, FREG_CFG, FREG_CFG_OTP_ENABLE, 0); | 161 | nand_upd_reg(drv, FREG_CFG, FREG_CFG_OTP_ENABLE, 0); |
156 | 162 | ||
@@ -249,6 +255,20 @@ int nand_page_read(struct nand_drv* drv, nand_page_t page, void* buffer) | |||
249 | sfc_exec(drv->cmd_page_read, page, NULL, 0); | 255 | sfc_exec(drv->cmd_page_read, page, NULL, 0); |
250 | nand_wait_busy(drv); | 256 | nand_wait_busy(drv); |
251 | sfc_exec(drv->cmd_read_cache, 0, buffer, drv->fpage_size|SFC_READ); | 257 | sfc_exec(drv->cmd_read_cache, 0, buffer, drv->fpage_size|SFC_READ); |
258 | |||
259 | if(drv->chip->flags & NAND_CHIPFLAG_ON_DIE_ECC) { | ||
260 | uint8_t status = nand_get_reg(drv, FREG_STATUS); | ||
261 | |||
262 | if(status & FREG_STATUS_ECC_UNCOR_ERR) { | ||
263 | logf("ecc uncorrectable error on page %08lx", (unsigned long)page); | ||
264 | return NAND_ERR_ECC_FAIL; | ||
265 | } | ||
266 | |||
267 | if(status & FREG_STATUS_ECC_HAS_FLIPS) { | ||
268 | logf("ecc corrected bitflips on page %08lx", (unsigned long)page); | ||
269 | } | ||
270 | } | ||
271 | |||
252 | return NAND_SUCCESS; | 272 | return NAND_SUCCESS; |
253 | } | 273 | } |
254 | 274 | ||
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.h b/firmware/target/mips/ingenic_x1000/nand-x1000.h index 0a22a4ff3c..61e0bbebc9 100644 --- a/firmware/target/mips/ingenic_x1000/nand-x1000.h +++ b/firmware/target/mips/ingenic_x1000/nand-x1000.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define NAND_ERR_PROGRAM_FAIL (-2) | 32 | #define NAND_ERR_PROGRAM_FAIL (-2) |
33 | #define NAND_ERR_ERASE_FAIL (-3) | 33 | #define NAND_ERR_ERASE_FAIL (-3) |
34 | #define NAND_ERR_UNALIGNED (-4) | 34 | #define NAND_ERR_UNALIGNED (-4) |
35 | #define NAND_ERR_ECC_FAIL (-5) | ||
35 | 36 | ||
36 | /* keep max page size in sync with the NAND chip table in the .c file */ | 37 | /* keep max page size in sync with the NAND chip table in the .c file */ |
37 | #define NAND_DRV_SCRATCHSIZE 32 | 38 | #define NAND_DRV_SCRATCHSIZE 32 |
@@ -43,6 +44,8 @@ | |||
43 | #define NAND_CHIPFLAG_HAS_QE_BIT 0x0002 | 44 | #define NAND_CHIPFLAG_HAS_QE_BIT 0x0002 |
44 | /* Chip has 2nd device ID byte */ | 45 | /* Chip has 2nd device ID byte */ |
45 | #define NAND_CHIPFLAG_HAS_DEVID2 0x0004 | 46 | #define NAND_CHIPFLAG_HAS_DEVID2 0x0004 |
47 | /* True if the chip has on-die ECC */ | ||
48 | #define NAND_CHIPFLAG_ON_DIE_ECC 0x0008 | ||
46 | 49 | ||
47 | /* cmd mode a d phase format has data */ | 50 | /* cmd mode a d phase format has data */ |
48 | #define NANDCMD_RESET SFC_CMD(0xff, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 0) | 51 | #define NANDCMD_RESET SFC_CMD(0xff, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 0) |