summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-07-19 13:41:30 +0100
committerAidan MacDonald <amachronic@protonmail.com>2022-09-17 10:14:26 -0400
commit17443de2214f7bfe77e1ebc11c268adaa15ae856 (patch)
tree5e24de75e2d8e0cfe733bf38b2decf30966a5300
parent189dee08eabbb211932907b34b3f340ab15421eb (diff)
downloadrockbox-17443de221.tar.gz
rockbox-17443de221.zip
x1000: refactor NAND chip identification
Decouple chip IDs from chips, and allow the chip ID table to list which read ID method should be used. Use a safe controller setup during identification instead of using the first chip's parameters. Change-Id: Ia725959c31b2838f4a3a30e5bb7fa6652ef377ed
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.c94
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.h35
2 files changed, 69 insertions, 60 deletions
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c
index 827a79ebce..6255597165 100644
--- a/firmware/target/mips/ingenic_x1000/nand-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c
@@ -25,34 +25,30 @@
#include "logf.h"
#include <string.h>
-const struct nand_chip supported_nand_chips[] = {
-#if defined(FIIO_M3K) || defined(SHANLING_Q1) || defined(EROS_QN)
- {
- /* ATO25D1GA */
- .mf_id = 0x9b,
- .dev_id = 0x12,
- .log2_ppb = 6, /* 64 pages */
- .page_size = 2048,
- .oob_size = 64,
- .nr_blocks = 1024,
- .bbm_pos = 2048,
- .clock_freq = 150000000,
- .dev_conf = jz_orf(SFC_DEV_CONF,
- CE_DL(1), HOLD_DL(1), WP_DL(1),
- CPHA(0), CPOL(0),
- TSH(7), TSETUP(0), THOLD(0),
- STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS),
- SMP_DELAY(1)),
- .flags = NAND_CHIPFLAG_QUAD | NAND_CHIPFLAG_HAS_QE_BIT,
- .cmd_page_read = NANDCMD_PAGE_READ,
- .cmd_program_execute = NANDCMD_PROGRAM_EXECUTE,
- .cmd_block_erase = NANDCMD_BLOCK_ERASE,
- .cmd_read_cache = NANDCMD_READ_CACHE_x4,
- .cmd_program_load = NANDCMD_PROGRAM_LOAD_x4,
- },
-#else
- { 0 },
-#endif
+static const struct nand_chip chip_ato25d1ga = {
+ .log2_ppb = 6, /* 64 pages */
+ .page_size = 2048,
+ .oob_size = 64,
+ .nr_blocks = 1024,
+ .bbm_pos = 2048,
+ .clock_freq = 150000000,
+ .dev_conf = jz_orf(SFC_DEV_CONF,
+ CE_DL(1), HOLD_DL(1), WP_DL(1),
+ CPHA(0), CPOL(0),
+ TSH(7), TSETUP(0), THOLD(0),
+ STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS),
+ SMP_DELAY(1)),
+ .flags = NAND_CHIPFLAG_QUAD | NAND_CHIPFLAG_HAS_QE_BIT,
+ .cmd_page_read = NANDCMD_PAGE_READ,
+ .cmd_program_execute = NANDCMD_PROGRAM_EXECUTE,
+ .cmd_block_erase = NANDCMD_BLOCK_ERASE,
+ .cmd_read_cache = NANDCMD_READ_CACHE_x4,
+ .cmd_program_load = NANDCMD_PROGRAM_LOAD_x4,
+};
+
+
+const struct nand_chip_id supported_nand_chips[] = {
+ NAND_CHIP_ID(&chip_ato25d1ga, NAND_READID_ADDR, 0x9b, 0x12),
};
const size_t nr_supported_nand_chips = ARRAYLEN(supported_nand_chips);
@@ -94,6 +90,19 @@ static void nand_upd_reg(struct nand_drv* drv, uint8_t reg, uint8_t msk, uint8_t
nand_set_reg(drv, reg, x);
}
+static const struct nand_chip* identify_chip_method(uint8_t method,
+ const uint8_t* id_buf)
+{
+ for (size_t i = 0; i < nr_supported_nand_chips; ++i) {
+ const struct nand_chip_id* chip_id = &supported_nand_chips[i];
+ if (chip_id->method == method &&
+ !memcmp(chip_id->id_bytes, id_buf, chip_id->num_id_bytes))
+ return chip_id->chip;
+ }
+
+ return NULL;
+}
+
static bool identify_chip(struct nand_drv* drv)
{
/* Read ID command has some variations; Linux handles these 3:
@@ -101,25 +110,13 @@ static bool identify_chip(struct nand_drv* drv)
* - 1 byte address, no dummy byte
* - no address byte, 1 byte dummy
*
- * Currently we use the 2nd method, aka. address read ID.
+ * Currently we use the 2nd method, aka. address read ID, the
+ * other methods can be added when needed.
*/
sfc_exec(NANDCMD_READID_ADDR, 0, drv->scratch_buf, 4|SFC_READ);
- drv->mf_id = drv->scratch_buf[0];
- drv->dev_id = drv->scratch_buf[1];
- drv->dev_id2 = drv->scratch_buf[2];
-
- for(size_t i = 0; i < nr_supported_nand_chips; ++i) {
- const struct nand_chip* chip = &supported_nand_chips[i];
- if(chip->mf_id != drv->mf_id || chip->dev_id != drv->dev_id)
- continue;
-
- if((chip->flags & NAND_CHIPFLAG_HAS_DEVID2) &&
- chip->dev_id2 != drv->dev_id2)
- continue;
-
- drv->chip = chip;
+ drv->chip = identify_chip_method(NAND_READID_ADDR, drv->scratch_buf);
+ if (drv->chip)
return true;
- }
return false;
}
@@ -164,8 +161,13 @@ int nand_open(struct nand_drv* drv)
/* Initialize the controller */
sfc_open();
- sfc_set_dev_conf(supported_nand_chips[0].dev_conf);
- sfc_set_clock(supported_nand_chips[0].clock_freq);
+ sfc_set_dev_conf(jz_orf(SFC_DEV_CONF,
+ CE_DL(1), HOLD_DL(1), WP_DL(1),
+ CPHA(0), CPOL(0),
+ TSH(15), TSETUP(0), THOLD(0),
+ STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS),
+ SMP_DELAY(0)));
+ sfc_set_clock(X1000_EXCLK_FREQ);
/* Send the software reset command */
sfc_exec(NANDCMD_RESET, 0, NULL, 0);
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.h b/firmware/target/mips/ingenic_x1000/nand-x1000.h
index 227c71e3f4..2c3294cfad 100644
--- a/firmware/target/mips/ingenic_x1000/nand-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.h
@@ -42,10 +42,8 @@
#define NAND_CHIPFLAG_QUAD 0x0001
/* Chip requires QE bit set to enable quad I/O mode */
#define NAND_CHIPFLAG_HAS_QE_BIT 0x0002
-/* Chip has 2nd device ID byte */
-#define NAND_CHIPFLAG_HAS_DEVID2 0x0004
/* True if the chip has on-die ECC */
-#define NAND_CHIPFLAG_ON_DIE_ECC 0x0008
+#define NAND_CHIPFLAG_ON_DIE_ECC 0x0004
/* cmd mode a d phase format has data */
#define NANDCMD_RESET SFC_CMD(0xff, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 0)
@@ -103,11 +101,6 @@ typedef uint32_t nand_page_t;
struct nand_drv;
struct nand_chip {
- /* Manufacturer and device ID bytes */
- uint8_t mf_id;
- uint8_t dev_id;
- uint8_t dev_id2;
-
/* Base2 logarithm of the number of pages per block */
unsigned log2_ppb;
@@ -141,6 +134,25 @@ struct nand_chip {
void(*setup_chip)(struct nand_drv* drv);
};
+enum nand_readid_method {
+ NAND_READID_OPCODE,
+ NAND_READID_ADDR,
+ NAND_READID_DUMMY,
+};
+
+struct nand_chip_id {
+ uint8_t method;
+ uint8_t num_id_bytes;
+ uint8_t id_bytes[4];
+ const struct nand_chip* chip;
+};
+
+#define NAND_CHIP_ID(_chip, _method, ...) \
+ { .method = _method, \
+ .num_id_bytes = ARRAYLEN(((uint8_t[]){__VA_ARGS__})), \
+ .id_bytes = {__VA_ARGS__}, \
+ .chip = _chip }
+
struct nand_drv {
/* NAND access lock. Needs to be held during any operations. */
struct mutex mutex;
@@ -170,14 +182,9 @@ struct nand_drv {
/* Full page size = chip->page_size + chip->oob_size */
unsigned fpage_size;
-
- /* Probed mf_id / dev_id for debugging, in case identification fails. */
- uint8_t mf_id;
- uint8_t dev_id;
- uint8_t dev_id2;
};
-extern const struct nand_chip supported_nand_chips[];
+extern const struct nand_chip_id supported_nand_chips[];
extern const size_t nr_supported_nand_chips;
/* Return the static NAND driver instance.