diff options
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/nand-x1000.c')
-rw-r--r-- | firmware/target/mips/ingenic_x1000/nand-x1000.c | 94 |
1 files changed, 48 insertions, 46 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 @@ | |||
25 | #include "logf.h" | 25 | #include "logf.h" |
26 | #include <string.h> | 26 | #include <string.h> |
27 | 27 | ||
28 | const struct nand_chip supported_nand_chips[] = { | 28 | static const struct nand_chip chip_ato25d1ga = { |
29 | #if defined(FIIO_M3K) || defined(SHANLING_Q1) || defined(EROS_QN) | 29 | .log2_ppb = 6, /* 64 pages */ |
30 | { | 30 | .page_size = 2048, |
31 | /* ATO25D1GA */ | 31 | .oob_size = 64, |
32 | .mf_id = 0x9b, | 32 | .nr_blocks = 1024, |
33 | .dev_id = 0x12, | 33 | .bbm_pos = 2048, |
34 | .log2_ppb = 6, /* 64 pages */ | 34 | .clock_freq = 150000000, |
35 | .page_size = 2048, | 35 | .dev_conf = jz_orf(SFC_DEV_CONF, |
36 | .oob_size = 64, | 36 | CE_DL(1), HOLD_DL(1), WP_DL(1), |
37 | .nr_blocks = 1024, | 37 | CPHA(0), CPOL(0), |
38 | .bbm_pos = 2048, | 38 | TSH(7), TSETUP(0), THOLD(0), |
39 | .clock_freq = 150000000, | 39 | STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS), |
40 | .dev_conf = jz_orf(SFC_DEV_CONF, | 40 | SMP_DELAY(1)), |
41 | CE_DL(1), HOLD_DL(1), WP_DL(1), | 41 | .flags = NAND_CHIPFLAG_QUAD | NAND_CHIPFLAG_HAS_QE_BIT, |
42 | CPHA(0), CPOL(0), | 42 | .cmd_page_read = NANDCMD_PAGE_READ, |
43 | TSH(7), TSETUP(0), THOLD(0), | 43 | .cmd_program_execute = NANDCMD_PROGRAM_EXECUTE, |
44 | STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS), | 44 | .cmd_block_erase = NANDCMD_BLOCK_ERASE, |
45 | SMP_DELAY(1)), | 45 | .cmd_read_cache = NANDCMD_READ_CACHE_x4, |
46 | .flags = NAND_CHIPFLAG_QUAD | NAND_CHIPFLAG_HAS_QE_BIT, | 46 | .cmd_program_load = NANDCMD_PROGRAM_LOAD_x4, |
47 | .cmd_page_read = NANDCMD_PAGE_READ, | 47 | }; |
48 | .cmd_program_execute = NANDCMD_PROGRAM_EXECUTE, | 48 | |
49 | .cmd_block_erase = NANDCMD_BLOCK_ERASE, | 49 | |
50 | .cmd_read_cache = NANDCMD_READ_CACHE_x4, | 50 | const struct nand_chip_id supported_nand_chips[] = { |
51 | .cmd_program_load = NANDCMD_PROGRAM_LOAD_x4, | 51 | NAND_CHIP_ID(&chip_ato25d1ga, NAND_READID_ADDR, 0x9b, 0x12), |
52 | }, | ||
53 | #else | ||
54 | { 0 }, | ||
55 | #endif | ||
56 | }; | 52 | }; |
57 | 53 | ||
58 | const size_t nr_supported_nand_chips = ARRAYLEN(supported_nand_chips); | 54 | 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 | |||
94 | nand_set_reg(drv, reg, x); | 90 | nand_set_reg(drv, reg, x); |
95 | } | 91 | } |
96 | 92 | ||
93 | static const struct nand_chip* identify_chip_method(uint8_t method, | ||
94 | const uint8_t* id_buf) | ||
95 | { | ||
96 | for (size_t i = 0; i < nr_supported_nand_chips; ++i) { | ||
97 | const struct nand_chip_id* chip_id = &supported_nand_chips[i]; | ||
98 | if (chip_id->method == method && | ||
99 | !memcmp(chip_id->id_bytes, id_buf, chip_id->num_id_bytes)) | ||
100 | return chip_id->chip; | ||
101 | } | ||
102 | |||
103 | return NULL; | ||
104 | } | ||
105 | |||
97 | static bool identify_chip(struct nand_drv* drv) | 106 | static bool identify_chip(struct nand_drv* drv) |
98 | { | 107 | { |
99 | /* Read ID command has some variations; Linux handles these 3: | 108 | /* Read ID command has some variations; Linux handles these 3: |
@@ -101,25 +110,13 @@ static bool identify_chip(struct nand_drv* drv) | |||
101 | * - 1 byte address, no dummy byte | 110 | * - 1 byte address, no dummy byte |
102 | * - no address byte, 1 byte dummy | 111 | * - no address byte, 1 byte dummy |
103 | * | 112 | * |
104 | * Currently we use the 2nd method, aka. address read ID. | 113 | * Currently we use the 2nd method, aka. address read ID, the |
114 | * other methods can be added when needed. | ||
105 | */ | 115 | */ |
106 | sfc_exec(NANDCMD_READID_ADDR, 0, drv->scratch_buf, 4|SFC_READ); | 116 | sfc_exec(NANDCMD_READID_ADDR, 0, drv->scratch_buf, 4|SFC_READ); |
107 | drv->mf_id = drv->scratch_buf[0]; | 117 | drv->chip = identify_chip_method(NAND_READID_ADDR, drv->scratch_buf); |
108 | drv->dev_id = drv->scratch_buf[1]; | 118 | if (drv->chip) |
109 | drv->dev_id2 = drv->scratch_buf[2]; | ||
110 | |||
111 | for(size_t i = 0; i < nr_supported_nand_chips; ++i) { | ||
112 | const struct nand_chip* chip = &supported_nand_chips[i]; | ||
113 | if(chip->mf_id != drv->mf_id || chip->dev_id != drv->dev_id) | ||
114 | continue; | ||
115 | |||
116 | if((chip->flags & NAND_CHIPFLAG_HAS_DEVID2) && | ||
117 | chip->dev_id2 != drv->dev_id2) | ||
118 | continue; | ||
119 | |||
120 | drv->chip = chip; | ||
121 | return true; | 119 | return true; |
122 | } | ||
123 | 120 | ||
124 | return false; | 121 | return false; |
125 | } | 122 | } |
@@ -164,8 +161,13 @@ int nand_open(struct nand_drv* drv) | |||
164 | 161 | ||
165 | /* Initialize the controller */ | 162 | /* Initialize the controller */ |
166 | sfc_open(); | 163 | sfc_open(); |
167 | sfc_set_dev_conf(supported_nand_chips[0].dev_conf); | 164 | sfc_set_dev_conf(jz_orf(SFC_DEV_CONF, |
168 | sfc_set_clock(supported_nand_chips[0].clock_freq); | 165 | CE_DL(1), HOLD_DL(1), WP_DL(1), |
166 | CPHA(0), CPOL(0), | ||
167 | TSH(15), TSETUP(0), THOLD(0), | ||
168 | STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS), | ||
169 | SMP_DELAY(0))); | ||
170 | sfc_set_clock(X1000_EXCLK_FREQ); | ||
169 | 171 | ||
170 | /* Send the software reset command */ | 172 | /* Send the software reset command */ |
171 | sfc_exec(NANDCMD_RESET, 0, NULL, 0); | 173 | sfc_exec(NANDCMD_RESET, 0, NULL, 0); |