From 17443de2214f7bfe77e1ebc11c268adaa15ae856 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 19 Jul 2022 13:41:30 +0100 Subject: 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 --- firmware/target/mips/ingenic_x1000/nand-x1000.c | 94 +++++++++++++------------ firmware/target/mips/ingenic_x1000/nand-x1000.h | 35 +++++---- 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 -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. -- cgit v1.2.3