summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/nand-x1000.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/nand-x1000.c')
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.c686
1 files changed, 300 insertions, 386 deletions
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c
index 5a21b1f8c2..b76efe65e5 100644
--- a/firmware/target/mips/ingenic_x1000/nand-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c
@@ -22,480 +22,394 @@
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 <stddef.h> 25#include <string.h>
26 26
27/* NAND command numbers */ 27/* cmd mode a d phase format has data */
28#define NAND_CMD_READ_ID 0x9f 28#define NANDCMD_RESET SFC_CMD(0xff, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 0)
29#define NAND_CMD_WRITE_ENABLE 0x06 29#define NANDCMD_READID(x,y) SFC_CMD(0x9f, SFC_TMODE_1_1_1, x, y, SFC_PFMT_ADDR_FIRST, 1)
30#define NAND_CMD_GET_FEATURE 0x0f 30#define NANDCMD_WR_EN SFC_CMD(0x06, SFC_TMODE_1_1_1, 0, 0, SFC_PFMT_ADDR_FIRST, 0)
31#define NAND_CMD_SET_FEATURE 0x1f 31#define NANDCMD_GET_FEATURE SFC_CMD(0x0f, SFC_TMODE_1_1_1, 1, 0, SFC_PFMT_ADDR_FIRST, 1)
32#define NAND_CMD_PAGE_READ_TO_CACHE 0x13 32#define NANDCMD_SET_FEATURE SFC_CMD(0x1f, SFC_TMODE_1_1_1, 1, 0, SFC_PFMT_ADDR_FIRST, 1)
33#define NAND_CMD_READ_FROM_CACHE 0x0b 33#define NANDCMD_PAGE_READ(x) SFC_CMD(0x13, SFC_TMODE_1_1_1, x, 0, SFC_PFMT_ADDR_FIRST, 0)
34#define NAND_CMD_READ_FROM_CACHEx4 0x6b 34#define NANDCMD_READ_CACHE(x) SFC_CMD(0x0b, SFC_TMODE_1_1_1, x, 8, SFC_PFMT_ADDR_FIRST, 1)
35#define NAND_CMD_PROGRAM_LOAD 0x02 35#define NANDCMD_READ_CACHE_x4(x) SFC_CMD(0x6b, SFC_TMODE_1_1_4, x, 8, SFC_PFMT_ADDR_FIRST, 1)
36#define NAND_CMD_PROGRAM_LOADx4 0x32 36#define NANDCMD_PROGRAM_LOAD(x) SFC_CMD(0x02, SFC_TMODE_1_1_1, x, 0, SFC_PFMT_ADDR_FIRST, 1)
37#define NAND_CMD_PROGRAM_EXECUTE 0x10 37#define NANDCMD_PROGRAM_LOAD_x4(x) SFC_CMD(0x32, SFC_TMODE_1_1_4, x, 0, SFC_PFMT_ADDR_FIRST, 1)
38#define NAND_CMD_BLOCK_ERASE 0xd8 38#define NANDCMD_PROGRAM_EXECUTE(x) SFC_CMD(0x10, SFC_TMODE_1_1_1, x, 0, SFC_PFMT_ADDR_FIRST, 0)
39 39#define NANDCMD_BLOCK_ERASE(x) SFC_CMD(0xd8, SFC_TMODE_1_1_1, x, 0, SFC_PFMT_ADDR_FIRST, 0)
40/* NAND device register addresses for GET_FEATURE / SET_FEATURE */ 40
41#define NAND_FREG_PROTECTION 0xa0 41/* Feature registers are found in linux/mtd/spinand.h,
42#define NAND_FREG_FEATURE 0xb0 42 * apparently these are pretty standardized */
43#define NAND_FREG_STATUS 0xc0 43#define FREG_PROT 0xa0
44 44#define FREG_PROT_UNLOCK 0x00
45/* Protection register bits */ 45
46#define NAND_FREG_PROTECTION_BRWD 0x80 46#define FREG_CFG 0xb0
47#define NAND_FREG_PROTECTION_BP2 0x20 47#define FREG_CFG_OTP_ENABLE (1 << 6)
48#define NAND_FREG_PROTECTION_BP1 0x10 48#define FREG_CFG_ECC_ENABLE (1 << 4)
49#define NAND_FREG_PROTECTION_BP0 0x08 49#define FREG_CFG_QUAD_ENABLE (1 << 0)
50/* Mask of BP bits 0-2 */ 50
51#define NAND_FREG_PROTECTION_ALLBP 0x38 51#define FREG_STATUS 0xc0
52 52#define FREG_STATUS_BUSY (1 << 0)
53/* Feature register bits */ 53#define FREG_STATUS_EFAIL (1 << 2)
54#define NAND_FREG_FEATURE_QE 0x01 54#define FREG_STATUS_PFAIL (1 << 3)
55 55#define FREG_STATUS_ECC_MASK (3 << 4)
56/* Status register bits */ 56#define FREG_STATUS_ECC_NO_FLIPS (0 << 4)
57#define NAND_FREG_STATUS_OIP 0x01 57#define FREG_STATUS_ECC_HAS_FLIPS (1 << 4)
58#define NAND_FREG_STATUS_WEL 0x02 58#define FREG_STATUS_ECC_UNCOR_ERR (2 << 4)
59#define NAND_FREG_STATUS_E_FAIL 0x04 59
60#define NAND_FREG_STATUS_P_FAIL 0x08 60const nand_chip supported_nand_chips[] = {
61 61#if defined(FIIO_M3K)
62/* NAND chip config */
63const nand_chip_data target_nand_chip_data[] = {
64#ifdef FIIO_M3K
65 { 62 {
66 /* ATO25D1GA */ 63 /* ATO25D1GA */
67 .mf_id = 0x9b, 64 .mf_id = 0x9b,
68 .dev_id = 0x12, 65 .dev_id = 0x12,
69 .dev_conf = jz_orf(SFC_DEV_CONF, CE_DL(1), HOLD_DL(1), WP_DL(1), 66 .row_cycles = 3,
70 CPHA(0), CPOL(0), TSH(7), TSETUP(0), THOLD(0), 67 .col_cycles = 2,
71 STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS), SMP_DELAY(1)), 68 .log2_ppb = 6, /* 64 pages */
69 .page_size = 2048,
70 .oob_size = 64,
71 .nr_blocks = 1024,
72 .clock_freq = 150000000, 72 .clock_freq = 150000000,
73 .log2_page_size = 11, /* = 2048 bytes */ 73 .dev_conf = jz_orf(SFC_DEV_CONF,
74 .log2_block_size = 6, /* = 64 pages */ 74 CE_DL(1), HOLD_DL(1), WP_DL(1),
75 .rowaddr_width = 3, 75 CPHA(0), CPOL(0),
76 .coladdr_width = 2, 76 TSH(7), TSETUP(0), THOLD(0),
77 .flags = NANDCHIP_FLAG_QUAD, 77 STA_TYPE_V(1BYTE), CMD_TYPE_V(8BITS),
78 } 78 SMP_DELAY(1)),
79 .flags = NAND_CHIPFLAG_QUAD | NAND_CHIPFLAG_HAS_QE_BIT,
80 },
79#else 81#else
80 /* Nobody will use this anyway if the device has no NAND flash */
81 { 0 }, 82 { 0 },
82#endif 83#endif
83}; 84};
84 85
85const size_t target_nand_chip_count = 86const size_t nr_supported_nand_chips =
86 sizeof(target_nand_chip_data) / sizeof(nand_chip_data); 87 sizeof(supported_nand_chips) / sizeof(nand_chip);
87
88/* NAND ops -- high level primitives used by the driver */
89static int nandop_wait_status(int errbit);
90static int nandop_read_page(uint32_t row_addr, uint8_t* buf);
91static int nandop_write_page(uint32_t row_addr, const uint8_t* buf);
92static int nandop_erase_block(uint32_t block_addr);
93static int nandop_set_write_protect(bool en);
94
95/* NAND commands -- 1-to-1 mapping between chip commands and functions */
96static int nandcmd_read_id(int* mf_id, int* dev_id);
97static int nandcmd_write_enable(void);
98static int nandcmd_get_feature(uint8_t reg);
99static int nandcmd_set_feature(uint8_t reg, uint8_t val);
100static int nandcmd_page_read_to_cache(uint32_t row_addr);
101static int nandcmd_read_from_cache(uint8_t* buf);
102static int nandcmd_program_load(const uint8_t* buf);
103static int nandcmd_program_execute(uint32_t row_addr);
104static int nandcmd_block_erase(uint32_t block_addr);
105
106struct nand_drv {
107 const nand_chip_data* chip_data;
108 bool write_enabled;
109};
110 88
111static struct nand_drv nand_drv; 89static nand_drv static_nand_drv;
112static uint8_t nand_auxbuf[32] CACHEALIGN_ATTR; 90static uint8_t static_scratch_buf[NAND_DRV_SCRATCHSIZE] CACHEALIGN_ATTR;
91static uint8_t static_page_buf[NAND_DRV_MAXPAGESIZE] CACHEALIGN_ATTR;
113 92
114static void nand_drv_reset(void) 93nand_drv* nand_init(void)
115{ 94{
116 nand_drv.chip_data = NULL; 95 static bool inited = false;
117 nand_drv.write_enabled = false; 96 if(!inited) {
97 mutex_init(&static_nand_drv.mutex);
98 static_nand_drv.scratch_buf = static_scratch_buf;
99 static_nand_drv.page_buf = static_page_buf;
100 static_nand_drv.refcount = 0;
101 }
102
103 return &static_nand_drv;
118} 104}
119 105
120int nand_open(void) 106static uint8_t nand_get_reg(nand_drv* drv, uint8_t reg)
121{ 107{
122 sfc_init(); 108 sfc_exec(NANDCMD_GET_FEATURE, reg, drv->scratch_buf, 1|SFC_READ);
123 sfc_lock(); 109 return drv->scratch_buf[0];
124
125 nand_drv_reset();
126 sfc_open();
127
128 const nand_chip_data* chip_data = &target_nand_chip_data[0];
129 sfc_set_dev_conf(chip_data->dev_conf);
130 sfc_set_clock(chip_data->clock_freq);
131
132 sfc_unlock();
133 return NAND_SUCCESS;
134} 110}
135 111
136void nand_close(void) 112static void nand_set_reg(nand_drv* drv, uint8_t reg, uint8_t val)
137{ 113{
138 sfc_lock(); 114 drv->scratch_buf[0] = val;
139 sfc_close(); 115 sfc_exec(NANDCMD_SET_FEATURE, reg, drv->scratch_buf, 1|SFC_WRITE);
140 nand_drv_reset();
141 sfc_unlock();
142} 116}
143 117
144int nand_identify(int* mf_id, int* dev_id) 118static void nand_upd_reg(nand_drv* drv, uint8_t reg, uint8_t msk, uint8_t val)
145{ 119{
146 sfc_lock(); 120 uint8_t x = nand_get_reg(drv, reg);
147 121 x &= ~msk;
148 int status = nandcmd_read_id(mf_id, dev_id); 122 x |= val;
149 if(status < 0) 123 nand_set_reg(drv, reg, x);
150 goto error; 124}
151 125
152 for(size_t i = 0; i < target_nand_chip_count; ++i) { 126static bool identify_chip(nand_drv* drv)
153 const nand_chip_data* data = &target_nand_chip_data[i]; 127{
154 if(data->mf_id == *mf_id && data->dev_id == *dev_id) { 128 /* Read ID command has some variations; Linux handles these 3:
155 nand_drv.chip_data = data; 129 * - no address or dummy bytes
156 break; 130 * - 1 byte address, no dummy byte
131 * - no address byte, 1 byte dummy
132 *
133 * Right now there is only a need for the 2nd variation, as that is
134 * the method used by the ATO25D1GA.
135 *
136 * Some chips also output more than 2 ID bytes.
137 */
138 sfc_exec(NANDCMD_READID(1, 0), 0, drv->scratch_buf, 2|SFC_READ);
139 drv->mf_id = drv->scratch_buf[0];
140 drv->dev_id = drv->scratch_buf[1];
141
142 for(size_t i = 0; i < nr_supported_nand_chips; ++i) {
143 const nand_chip* chip = &supported_nand_chips[i];
144 if(chip->mf_id == drv->mf_id && chip->dev_id == drv->dev_id) {
145 drv->chip = chip;
146 return true;
157 } 147 }
158 } 148 }
159 149
160 if(!nand_drv.chip_data) { 150 return false;
161 status = NAND_ERR_UNKNOWN_CHIP; 151}
162 goto error;
163 }
164
165 /* Set parameters according to new chip data */
166 sfc_set_dev_conf(nand_drv.chip_data->dev_conf);
167 sfc_set_clock(nand_drv.chip_data->clock_freq);
168 status = NAND_SUCCESS;
169 152
170 error: 153static void setup_chip_data(nand_drv* drv)
171 sfc_unlock(); 154{
172 return status; 155 drv->ppb = 1 << drv->chip->log2_ppb;
156 drv->fpage_size = drv->chip->page_size + drv->chip->oob_size;
173} 157}
174 158
175const nand_chip_data* nand_get_chip_data(void) 159static void setup_chip_commands(nand_drv* drv)
176{ 160{
177 return nand_drv.chip_data; 161 /* Select commands appropriate for the chip */
162 drv->cmd_page_read = NANDCMD_PAGE_READ(drv->chip->row_cycles);
163 drv->cmd_program_execute = NANDCMD_PROGRAM_EXECUTE(drv->chip->row_cycles);
164 drv->cmd_block_erase = NANDCMD_BLOCK_ERASE(drv->chip->row_cycles);
165
166 if(drv->chip->flags & NAND_CHIPFLAG_QUAD) {
167 drv->cmd_read_cache = NANDCMD_READ_CACHE_x4(drv->chip->col_cycles);
168 drv->cmd_program_load = NANDCMD_PROGRAM_LOAD_x4(drv->chip->col_cycles);
169 } else {
170 drv->cmd_read_cache = NANDCMD_READ_CACHE(drv->chip->col_cycles);
171 drv->cmd_program_load = NANDCMD_PROGRAM_LOAD(drv->chip->col_cycles);
172 }
178} 173}
179 174
180extern int nand_enable_writes(bool en) 175static void setup_chip_registers(nand_drv* drv)
181{ 176{
182 if(en == nand_drv.write_enabled) 177 /* Set chip registers to enter normal operation */
183 return NAND_SUCCESS; 178 if(drv->chip->flags & NAND_CHIPFLAG_HAS_QE_BIT) {
179 bool en = (drv->chip->flags & NAND_CHIPFLAG_QUAD) != 0;
180 nand_upd_reg(drv, FREG_CFG, FREG_CFG_QUAD_ENABLE,
181 en ? FREG_CFG_QUAD_ENABLE : 0);
182 }
184 183
185 int rc = nandop_set_write_protect(!en); 184 /* Clear OTP bit to access the main data array */
186 if(rc == NAND_SUCCESS) 185 nand_upd_reg(drv, FREG_CFG, FREG_CFG_OTP_ENABLE, 0);
187 nand_drv.write_enabled = en;
188 186
189 return rc; 187 /* Clear write protection bits */
188 nand_set_reg(drv, FREG_PROT, FREG_PROT_UNLOCK);
190} 189}
191 190
192static int nand_rdwr(bool write, uint32_t addr, uint32_t size, uint8_t* buf) 191int nand_open(nand_drv* drv)
193{ 192{
194 const uint32_t page_size = (1 << nand_drv.chip_data->log2_page_size); 193 if(drv->refcount > 0)
195
196 if(addr & (page_size - 1))
197 return NAND_ERR_UNALIGNED;
198 if(size & (page_size - 1))
199 return NAND_ERR_UNALIGNED;
200 if(size <= 0)
201 return NAND_SUCCESS; 194 return NAND_SUCCESS;
202 if(write && !nand_drv.write_enabled)
203 return NAND_ERR_WRITE_PROTECT;
204 if((uint32_t)buf & (CACHEALIGN_SIZE - 1))
205 return NAND_ERR_UNALIGNED;
206 195
207 addr >>= nand_drv.chip_data->log2_page_size; 196 /* Initialize the controller */
208 size >>= nand_drv.chip_data->log2_page_size; 197 sfc_open();
198 sfc_set_dev_conf(supported_nand_chips[0].dev_conf);
199 sfc_set_clock(supported_nand_chips[0].clock_freq);
209 200
210 int rc = NAND_SUCCESS; 201 /* Send the software reset command */
211 sfc_lock(); 202 sfc_exec(NANDCMD_RESET, 0, NULL, 0);
203 mdelay(10);
212 204
213 for(; size > 0; --size, ++addr, buf += page_size) { 205 /* Chip identification and setup */
214 if(write) 206 if(!identify_chip(drv))
215 rc = nandop_write_page(addr, buf); 207 return NAND_ERR_UNKNOWN_CHIP;
216 else
217 rc = nandop_read_page(addr, buf);
218 208
219 if(rc) 209 setup_chip_data(drv);
220 break; 210 setup_chip_commands(drv);
221 }
222 211
223 sfc_unlock(); 212 /* Set new SFC parameters */
224 return rc; 213 sfc_set_dev_conf(drv->chip->dev_conf);
225} 214 sfc_set_clock(drv->chip->clock_freq);
226 215
227int nand_read(uint32_t addr, uint32_t size, uint8_t* buf) 216 /* Enter normal operating mode */
228{ 217 setup_chip_registers(drv);
229 return nand_rdwr(false, addr, size, buf);
230}
231 218
232int nand_write(uint32_t addr, uint32_t size, const uint8_t* buf) 219 drv->refcount++;
233{ 220 return NAND_SUCCESS;
234 return nand_rdwr(true, addr, size, (uint8_t*)buf);
235} 221}
236 222
237int nand_erase(uint32_t addr, uint32_t size) 223void nand_close(nand_drv* drv)
238{ 224{
239 const uint32_t page_size = 1 << nand_drv.chip_data->log2_page_size; 225 if(drv->refcount == 0)
240 const uint32_t block_size = page_size << nand_drv.chip_data->log2_block_size; 226 return;
241 const uint32_t pages_per_block = 1 << nand_drv.chip_data->log2_block_size;
242 227
243 if(addr & (block_size - 1)) 228 /* Let's reset the chip... the idea is to restore the registers
244 return NAND_ERR_UNALIGNED; 229 * to whatever they should "normally" be */
245 if(size & (block_size - 1)) 230 sfc_exec(NANDCMD_RESET, 0, NULL, 0);
246 return NAND_ERR_UNALIGNED; 231 mdelay(10);
247 if(size <= 0)
248 return NAND_SUCCESS;
249 if(!nand_drv.write_enabled)
250 return NAND_ERR_WRITE_PROTECT;
251
252 addr >>= nand_drv.chip_data->log2_page_size;
253 size >>= nand_drv.chip_data->log2_page_size;
254 size >>= nand_drv.chip_data->log2_block_size;
255 232
256 int rc = NAND_SUCCESS; 233 sfc_close();
257 sfc_lock(); 234 drv->refcount--;
258
259 for(; size > 0; --size, addr += pages_per_block)
260 if((rc = nandop_erase_block(addr)))
261 break;
262
263 sfc_unlock();
264 return rc;
265} 235}
266 236
267/* 237static uint8_t nand_wait_busy(nand_drv* drv)
268 * NAND ops
269 */
270
271static int nandop_wait_status(int errbit)
272{ 238{
273 int reg; 239 uint8_t reg;
274 do { 240 do {
275 reg = nandcmd_get_feature(NAND_FREG_STATUS); 241 reg = nand_get_reg(drv, FREG_STATUS);
276 if(reg < 0) 242 } while(reg & FREG_STATUS_BUSY);
277 return reg;
278 } while(reg & NAND_FREG_STATUS_OIP);
279
280 if(reg & errbit)
281 return NAND_ERR_COMMAND;
282
283 return reg; 243 return reg;
284} 244}
285 245
286static int nandop_read_page(uint32_t row_addr, uint8_t* buf) 246int nand_block_erase(nand_drv* drv, nand_block_t block)
287{ 247{
288 int status; 248 sfc_exec(NANDCMD_WR_EN, 0, NULL, 0);
289 249 sfc_exec(drv->cmd_block_erase, block, NULL, 0);
290 if((status = nandcmd_page_read_to_cache(row_addr)) < 0)
291 return status;
292 if((status = nandop_wait_status(0)) < 0)
293 return status;
294 if((status = nandcmd_read_from_cache(buf)) < 0)
295 return status;
296 250
297 return NAND_SUCCESS; 251 uint8_t status = nand_wait_busy(drv);
252 if(status & FREG_STATUS_EFAIL)
253 return NAND_ERR_ERASE_FAIL;
254 else
255 return NAND_SUCCESS;
298} 256}
299 257
300static int nandop_write_page(uint32_t row_addr, const uint8_t* buf) 258int nand_page_program(nand_drv* drv, nand_page_t page, const void* buffer)
301{ 259{
302 int status; 260 sfc_exec(NANDCMD_WR_EN, 0, NULL, 0);
303 261 sfc_exec(drv->cmd_program_load, 0, (void*)buffer, drv->fpage_size|SFC_WRITE);
304 if((status = nandcmd_write_enable()) < 0) 262 sfc_exec(drv->cmd_program_execute, page, NULL, 0);
305 return status; 263
306 if((status = nandcmd_program_load(buf)) < 0) 264 uint8_t status = nand_wait_busy(drv);
307 return status; 265 if(status & FREG_STATUS_PFAIL)
308 if((status = nandcmd_program_execute(row_addr)) < 0) 266 return NAND_ERR_PROGRAM_FAIL;
309 return status; 267 else
310 if((status = nandop_wait_status(NAND_FREG_STATUS_P_FAIL)) < 0) 268 return NAND_SUCCESS;
311 return status;
312
313 return NAND_SUCCESS;
314} 269}
315 270
316static int nandop_erase_block(uint32_t block_addr) 271int nand_page_read(nand_drv* drv, nand_page_t page, void* buffer)
317{ 272{
318 int status; 273 sfc_exec(drv->cmd_page_read, page, NULL, 0);
319 274 nand_wait_busy(drv);
320 if((status = nandcmd_write_enable()) < 0) 275 sfc_exec(drv->cmd_read_cache, 0, buffer, drv->fpage_size|SFC_READ);
321 return status;
322 if((status = nandcmd_block_erase(block_addr)) < 0)
323 return status;
324 if((status = nandop_wait_status(NAND_FREG_STATUS_E_FAIL)) < 0)
325 return status;
326
327 return NAND_SUCCESS; 276 return NAND_SUCCESS;
328} 277}
329 278
330static int nandop_set_write_protect(bool en) 279int nand_read_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, void* buffer)
331{ 280{
332 int val = nandcmd_get_feature(NAND_FREG_PROTECTION); 281 if(byte_len == 0)
333 if(val < 0) 282 return NAND_SUCCESS;
334 return val;
335
336 if(en) {
337 val |= NAND_FREG_PROTECTION_ALLBP;
338 if(nand_drv.chip_data->flags & NANDCHIP_FLAG_USE_BRWD)
339 val |= NAND_FREG_PROTECTION_BRWD;
340 } else {
341 val &= ~NAND_FREG_PROTECTION_ALLBP;
342 if(nand_drv.chip_data->flags & NANDCHIP_FLAG_USE_BRWD)
343 val &= ~NAND_FREG_PROTECTION_BRWD;
344 }
345
346 /* NOTE: The WP pin typically only protects changes to the protection
347 * register -- it doesn't actually prevent writing to the chip. That's
348 * why it should be re-enabled after setting the new protection status.
349 */
350 sfc_set_wp_enable(false);
351 int status = nandcmd_set_feature(NAND_FREG_PROTECTION, val);
352 sfc_set_wp_enable(true);
353
354 if(status < 0)
355 return status;
356 283
357 return NAND_SUCCESS; 284 int rc;
358} 285 unsigned pg_size = drv->chip->page_size;
286 nand_page_t page = byte_addr / pg_size;
287 unsigned offset = byte_addr % pg_size;
288 while(1) {
289 rc = nand_page_read(drv, page, drv->page_buf);
290 if(rc < 0)
291 return rc;
359 292
360/* 293 memcpy(buffer, &drv->page_buf[offset], MIN(pg_size, byte_len));
361 * Low-level NAND commands
362 */
363 294
364static int nandcmd_read_id(int* mf_id, int* dev_id) 295 if(byte_len <= pg_size)
365{ 296 break;
366 sfc_op op = {0};
367 op.command = NAND_CMD_READ_ID;
368 op.flags = SFC_FLAG_READ;
369 op.addr_bytes = 1;
370 op.addr_lo = 0;
371 op.data_bytes = 2;
372 op.buffer = nand_auxbuf;
373 if(sfc_exec(&op))
374 return NAND_ERR_CONTROLLER;
375
376 *mf_id = nand_auxbuf[0];
377 *dev_id = nand_auxbuf[1];
378 return NAND_SUCCESS;
379}
380 297
381static int nandcmd_write_enable(void) 298 offset = 0;
382{ 299 byte_len -= pg_size;
383 sfc_op op = {0}; 300 buffer += pg_size;
384 op.command = NAND_CMD_WRITE_ENABLE; 301 page++;
385 if(sfc_exec(&op)) 302 }
386 return NAND_ERR_CONTROLLER;
387 303
388 return NAND_SUCCESS; 304 return NAND_SUCCESS;
389} 305}
390 306
391static int nandcmd_get_feature(uint8_t reg) 307int nand_write_bytes(nand_drv* drv, uint32_t byte_addr, uint32_t byte_len, const void* buffer)
392{ 308{
393 sfc_op op = {0}; 309 if(byte_len == 0)
394 op.command = NAND_CMD_GET_FEATURE; 310 return NAND_SUCCESS;
395 op.flags = SFC_FLAG_READ;
396 op.addr_bytes = 1;
397 op.addr_lo = reg;
398 op.data_bytes = 1;
399 op.buffer = nand_auxbuf;
400 if(sfc_exec(&op))
401 return NAND_ERR_CONTROLLER;
402
403 return nand_auxbuf[0];
404}
405
406static int nandcmd_set_feature(uint8_t reg, uint8_t val)
407{
408 sfc_op op = {0};
409 op.command = NAND_CMD_SET_FEATURE;
410 op.flags = SFC_FLAG_WRITE;
411 op.addr_bytes = 1;
412 op.addr_lo = reg;
413 op.data_bytes = 1;
414 op.buffer = nand_auxbuf;
415 nand_auxbuf[0] = val;
416 if(sfc_exec(&op))
417 return NAND_ERR_CONTROLLER;
418 311
419 return NAND_SUCCESS; 312 int rc;
420} 313 unsigned pg_size = drv->chip->page_size;
314 unsigned blk_size = pg_size << drv->chip->log2_ppb;
421 315
422static int nandcmd_page_read_to_cache(uint32_t row_addr) 316 if(byte_addr % blk_size != 0)
423{ 317 return NAND_ERR_UNALIGNED;
424 sfc_op op = {0}; 318 if(byte_len % blk_size != 0)
425 op.command = NAND_CMD_PAGE_READ_TO_CACHE; 319 return NAND_ERR_UNALIGNED;
426 op.addr_bytes = nand_drv.chip_data->rowaddr_width;
427 op.addr_lo = row_addr;
428 if(sfc_exec(&op))
429 return NAND_ERR_CONTROLLER;
430 320
431 return NAND_SUCCESS; 321 nand_page_t page = byte_addr / pg_size;
432} 322 nand_page_t end_page = page + (byte_len / pg_size);
433 323
434static int nandcmd_read_from_cache(uint8_t* buf) 324 for(nand_block_t blk = page; blk < end_page; blk += drv->ppb) {
435{ 325 rc = nand_block_erase(drv, blk);
436 sfc_op op = {0}; 326 if(rc < 0)
437 if(nand_drv.chip_data->flags & NANDCHIP_FLAG_QUAD) { 327 return rc;
438 op.command = NAND_CMD_READ_FROM_CACHEx4;
439 op.mode = SFC_MODE_QUAD_IO;
440 } else {
441 op.command = NAND_CMD_READ_FROM_CACHE;
442 op.mode = SFC_MODE_STANDARD;
443 } 328 }
444 329
445 op.flags = SFC_FLAG_READ; 330 for(; page != end_page; ++page) {
446 op.addr_bytes = nand_drv.chip_data->coladdr_width; 331 memcpy(drv->page_buf, buffer, pg_size);
447 op.addr_lo = 0; 332 memset(&drv->page_buf[pg_size], 0xff, drv->chip->oob_size);
448 op.dummy_bits = 8; // NOTE: this may need a chip_data parameter 333 buffer += pg_size;
449 op.data_bytes = (1 << nand_drv.chip_data->log2_page_size);
450 op.buffer = buf;
451 if(sfc_exec(&op))
452 return NAND_ERR_CONTROLLER;
453
454 return NAND_SUCCESS;
455}
456 334
457static int nandcmd_program_load(const uint8_t* buf) 335 rc = nand_page_program(drv, page, drv->page_buf);
458{ 336 if(rc < 0)
459 sfc_op op = {0}; 337 return rc;
460 if(nand_drv.chip_data->flags & NANDCHIP_FLAG_QUAD) {
461 op.command = NAND_CMD_PROGRAM_LOADx4;
462 op.mode = SFC_MODE_QUAD_IO;
463 } else {
464 op.command = NAND_CMD_PROGRAM_LOAD;
465 op.mode = SFC_MODE_STANDARD;
466 } 338 }
467 339
468 op.flags = SFC_FLAG_WRITE;
469 op.addr_bytes = nand_drv.chip_data->coladdr_width;
470 op.addr_lo = 0;
471 op.data_bytes = (1 << nand_drv.chip_data->log2_page_size);
472 op.buffer = (void*)buf;
473 if(sfc_exec(&op))
474 return NAND_ERR_CONTROLLER;
475
476 return NAND_SUCCESS;
477}
478
479static int nandcmd_program_execute(uint32_t row_addr)
480{
481 sfc_op op = {0};
482 op.command = NAND_CMD_PROGRAM_EXECUTE;
483 op.addr_bytes = nand_drv.chip_data->rowaddr_width;
484 op.addr_lo = row_addr;
485 if(sfc_exec(&op))
486 return NAND_ERR_CONTROLLER;
487
488 return NAND_SUCCESS; 340 return NAND_SUCCESS;
489} 341}
490 342
491static int nandcmd_block_erase(uint32_t block_addr) 343/* TODO - NAND driver future improvements
492{ 344 *
493 sfc_op op = {0}; 345 * 1. Support sofware or on-die ECC transparently. Support debug ECC bypass.
494 op.command = NAND_CMD_BLOCK_ERASE; 346 *
495 op.addr_bytes = nand_drv.chip_data->rowaddr_width; 347 * It's probably best to add an API call to turn ECC on or off. Software
496 op.addr_lo = block_addr; 348 * ECC and most or all on-die ECC implementations require some OOB bytes
497 if(sfc_exec(&op)) 349 * to function; which leads us to the next problem...
498 return NAND_ERR_CONTROLLER; 350 *
499 351 * 2. Allow safe access to OOB areas
500 return NAND_SUCCESS; 352 *
501} 353 * The OOB data area is not fully available to users; it is also occupied
354 * by ECC data and bad block markings. The NAND driver needs to provide a
355 * mapping which allows OOB data users to map around those reserved areas,
356 * otherwise it's not really possible to use OOB data.
357 *
358 * 3. Support partial page programming.
359 *
360 * This might already work. My understanding of NAND flash is that bits are
361 * represented by charge deposited on flash cells. In the case of SLC flash,
362 * cells are one bit. For MLC flash, cells can store more than one bit; but
363 * MLC flash is much less reliable than SLC. We probably don't have to be
364 * concerned about MLC flash, and its does not support partial programming
365 * anyway due to the cell characteristics, so I will only consider SLC here.
366 *
367 * For SLC there are two cell states -- an uncharged cell represents a "1"
368 * and a charged cell represents "0". Programming can only deposit charge
369 * on a cell and erasing can only remove charge. Therefore, "programming" a
370 * cell to 1 is actually a no-op.
371 *
372 * So, there's no datasheet which spells this out, but I suspect you just
373 * set the areas you're not interested in programming to 0xff. Programming
374 * can never change a written 0 back to a 1, so programming a 1 bit works
375 * more like a "don't care" (= keep whatever value is already there).
376 *
377 * What _is_ given by the datasheets is limits on how many times you can
378 * reprogram the same page without erasing it. This is an overall limit
379 * called NOP (number of programs) in many datasheets. In addition to this,
380 * sub-regions of the page have further limits: it's common for a 2048+64
381 * byte page to be split into 8 regions, with four 512-byte main areas and
382 * four 16-byte OOB areas. Usually, each subregion can only be programmed
383 * once. However, you can write multiple subregions with a single program.
384 *
385 * Violating programming constraints could cause data loss, so we need to
386 * communicate to upper layers what the limitations are here if they want
387 * to use partial programming safely.
388 *
389 * Programming the same page more than once increases the overall stress
390 * on the flash cells and can cause bitflips. For this reason, it's best
391 * to keep the number of programs as low as possible. Some sources suggest
392 * that programming the pages in a block in linear order is also better to
393 * reduce stress, although I don't know why this would be.
394 *
395 * These program/read stresses can flip bits, but it's only due to residual
396 * charge building up on uncharged cells; cells are not permanently damaged
397 * by these kind of stresses. Erasing the block will remove the charge and
398 * restore all the cells to a clean state.
399 *
400 * These slides are fairly informative on this subject:
401 * - https://cushychicken.github.io/assets/cooke_inconvenient_truths.pdf
402 *
403 * 4. Bad block management
404 *
405 * This probably doesn't belong in the NAND layer but it seems wise to keep
406 * at least a bad block table at the level of the NAND driver. Factory bad
407 * block marks are usually some non-0xFF byte in the OOB area, but bad blocks
408 * which develop over the device lifetime usually won't be marked; after all
409 * they are unreliable, so we can't program a marking on them and expect it
410 * to stick. So, most FTL systems keep a bad block table somewhere in flash
411 * and update it whenever a block goes bad.
412 *
413 * So, in addition to a bad block marker scan, we should try to gather bad
414 * block information from such tables.
415 */