summaryrefslogtreecommitdiff
path: root/firmware/target/mips
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-06-07 19:30:59 +0100
committerAidan MacDonald <amachronic@protonmail.com>2022-07-10 15:22:32 +0100
commit47cbeb2e67288dcff95a47261b58306c107b4bd6 (patch)
treee2a802a77f30da12647861f4274df449323a9a0f /firmware/target/mips
parentdf29c7991ab70c764165da08807e5610055031b0 (diff)
downloadrockbox-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')
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.c20
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.h3
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
27const struct nand_chip supported_nand_chips[] = { 28const 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)