diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2022-06-07 19:30:59 +0100 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2022-07-10 15:22:32 +0100 |
commit | 47cbeb2e67288dcff95a47261b58306c107b4bd6 (patch) | |
tree | e2a802a77f30da12647861f4274df449323a9a0f /firmware/target/mips/ingenic_x1000/nand-x1000.c | |
parent | df29c7991ab70c764165da08807e5610055031b0 (diff) | |
download | rockbox-47cbeb2e67288dcff95a47261b58306c107b4bd6.tar.gz rockbox-47cbeb2e67288dcff95a47261b58306c107b4bd6.zip |
x1000: add support for simple on-die ECC with NAND flash
Many SPI NAND flash chips have on-die ECC engines that report
ECC status via the status feature register. This code handles
the common case where ECC status is reported with 2 bits: one
bit to indicate if flips were detected & corrected, and another
bit to indicate an uncorrectable error.
Change-Id: I5d587cd960ca9d090d2629e890724a6bc411e70c
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/nand-x1000.c')
-rw-r--r-- | firmware/target/mips/ingenic_x1000/nand-x1000.c | 20 |
1 files changed, 20 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 | ||