summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c156
1 files changed, 105 insertions, 51 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
index a41a62294a..7a937bf7cf 100644
--- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
@@ -22,6 +22,7 @@
22#include "config.h" 22#include "config.h"
23#include "jz4740.h" 23#include "jz4740.h"
24#include "ata.h" 24#include "ata.h"
25#include "ata-nand-target.h"
25#include "nand_id.h" 26#include "nand_id.h"
26#include "system.h" 27#include "system.h"
27#include "panic.h" 28#include "panic.h"
@@ -29,31 +30,31 @@
29/* 30/*
30 * Standard NAND flash commands 31 * Standard NAND flash commands
31 */ 32 */
32#define NAND_CMD_READ0 0 33#define NAND_CMD_READ0 0
33#define NAND_CMD_READ1 1 34#define NAND_CMD_READ1 1
34#define NAND_CMD_RNDOUT 5 35#define NAND_CMD_RNDOUT 5
35#define NAND_CMD_PAGEPROG 0x10 36#define NAND_CMD_PAGEPROG 0x10
36#define NAND_CMD_READOOB 0x50 37#define NAND_CMD_READOOB 0x50
37#define NAND_CMD_ERASE1 0x60 38#define NAND_CMD_ERASE1 0x60
38#define NAND_CMD_STATUS 0x70 39#define NAND_CMD_STATUS 0x70
39#define NAND_CMD_STATUS_MULTI 0x71 40#define NAND_CMD_STATUS_MULTI 0x71
40#define NAND_CMD_SEQIN 0x80 41#define NAND_CMD_SEQIN 0x80
41#define NAND_CMD_RNDIN 0x85 42#define NAND_CMD_RNDIN 0x85
42#define NAND_CMD_READID 0x90 43#define NAND_CMD_READID 0x90
43#define NAND_CMD_ERASE2 0xd0 44#define NAND_CMD_ERASE2 0xd0
44#define NAND_CMD_RESET 0xff 45#define NAND_CMD_RESET 0xff
45 46
46/* Extended commands for large page devices */ 47/* Extended commands for large page devices */
47#define NAND_CMD_READSTART 0x30 48#define NAND_CMD_READSTART 0x30
48#define NAND_CMD_RNDOUTSTART 0xE0 49#define NAND_CMD_RNDOUTSTART 0xE0
49#define NAND_CMD_CACHEDPROG 0x15 50#define NAND_CMD_CACHEDPROG 0x15
50 51
51/* Status bits */ 52/* Status bits */
52#define NAND_STATUS_FAIL 0x01 53#define NAND_STATUS_FAIL 0x01
53#define NAND_STATUS_FAIL_N1 0x02 54#define NAND_STATUS_FAIL_N1 0x02
54#define NAND_STATUS_TRUE_READY 0x20 55#define NAND_STATUS_TRUE_READY 0x20
55#define NAND_STATUS_READY 0x40 56#define NAND_STATUS_READY 0x40
56#define NAND_STATUS_WP 0x80 57#define NAND_STATUS_WP 0x80
57 58
58/* 59/*
59 * NAND parameter struct 60 * NAND parameter struct
@@ -81,21 +82,21 @@ struct nand_param
81#define NAND_COMMPORT 0xb8008000 82#define NAND_COMMPORT 0xb8008000
82 83
83#define ECC_BLOCK 512 84#define ECC_BLOCK 512
84#define ECC_POS 6 85#define ECC_POS 6
85#define PAR_SIZE 9 86#define PAR_SIZE 9
86 87
87#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n)) 88#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
88#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n)) 89#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
89#define __nand_data8() REG8(NAND_DATAPORT) 90#define __nand_data8() REG8(NAND_DATAPORT)
90#define __nand_data16() REG16(NAND_DATAPORT) 91#define __nand_data16() REG16(NAND_DATAPORT)
91 92
92#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1) 93#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
93#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1)) 94#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
94#define __nand_ecc_rs_encoding() \ 95#define __nand_ecc_rs_encoding() \
95 (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING) 96 (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING)
96#define __nand_ecc_rs_decoding() \ 97#define __nand_ecc_rs_decoding() \
97 (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING) 98 (REG_EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_ERST | EMC_NFECR_RS | EMC_NFECR_RS_DECODING)
98#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE) 99#define __nand_ecc_disable() (REG_EMC_NFECR &= ~EMC_NFECR_ECCE)
99#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF)) 100#define __nand_ecc_encode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_ENCF))
100#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF)) 101#define __nand_ecc_decode_sync() while (!(REG_EMC_NFINTS & EMC_NFINTS_DECF))
101 102
@@ -104,14 +105,14 @@ struct nand_param
104static struct nand_info* chip_info = NULL; 105static struct nand_info* chip_info = NULL;
105static struct nand_param internal_param; 106static struct nand_param internal_param;
106 107
107static inline void nand_wait_ready(void) 108static inline void jz_nand_wait_ready(void)
108{ 109{
109 unsigned int timeout = 1000; 110 unsigned int timeout = 1000;
110 while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--); 111 while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
111 while (!(REG_GPIO_PXPIN(2) & 0x40000000)); 112 while (!(REG_GPIO_PXPIN(2) & 0x40000000));
112} 113}
113 114
114static inline void nand_read_buf16(void *buf, int count) 115static inline void jz_nand_read_buf16(void *buf, int count)
115{ 116{
116 int i; 117 int i;
117 unsigned short *p = (unsigned short *)buf; 118 unsigned short *p = (unsigned short *)buf;
@@ -120,7 +121,7 @@ static inline void nand_read_buf16(void *buf, int count)
120 *p++ = __nand_data16(); 121 *p++ = __nand_data16();
121} 122}
122 123
123static inline void nand_read_buf8(void *buf, int count) 124static inline void jz_nand_read_buf8(void *buf, int count)
124{ 125{
125 int i; 126 int i;
126 unsigned char *p = (unsigned char *)buf; 127 unsigned char *p = (unsigned char *)buf;
@@ -129,18 +130,53 @@ static inline void nand_read_buf8(void *buf, int count)
129 *p++ = __nand_data8(); 130 *p++ = __nand_data8();
130} 131}
131 132
132static inline void nand_read_buf(void *buf, int count, int bw) 133static void jz_nand_write_dma(void *source, unsigned int len, int bw)
134{
135 if(((unsigned int)source < 0xa0000000) && len)
136 dma_cache_wback_inv((unsigned long)source, len);
137
138 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0;
139 REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)source);
140 REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT);
141 REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 16;
142 REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO;
143 REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_16BYTE |
144 (bw == 8 ? DMAC_DCMD_DWDH_8 : DMAC_DCMD_DWDH_16));
145
146 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES);
147 while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) )
148 yield();
149}
150
151static void jz_nand_read_dma(void *target, unsigned int len, int bw)
152{
153 if(((unsigned int)target < 0xa0000000) && len)
154 dma_cache_wback_inv((unsigned long)target, len);
155
156 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0;
157 REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT);
158 REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)target);
159 REG_DMAC_DTCR(DMA_NAND_CHANNEL) = len / 4;
160 REG_DMAC_DRSR(DMA_NAND_CHANNEL) = DMAC_DRSR_RS_AUTO;
161 REG_DMAC_DCMD(DMA_NAND_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_DAI | DMAC_DCMD_DWDH_32 | DMAC_DCMD_DS_32BIT |
162 (bw == 8 ? DMAC_DCMD_SWDH_8 : DMAC_DCMD_SWDH_16));
163 REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = (DMAC_DCCSR_EN | DMAC_DCCSR_NDES);
164 while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) )
165 yield();
166}
167
168static inline void jz_nand_read_buf(void *buf, int count, int bw)
133{ 169{
134 if (bw == 8) 170 if (bw == 8)
135 nand_read_buf8(buf, count); 171 jz_nand_read_dma(buf, count, 8);
136 else 172 else
137 nand_read_buf16(buf, count); 173 jz_nand_read_dma(buf, count, 16);
138} 174}
139 175
140/* 176/*
141 * Correct 1~9-bit errors in 512-bytes data 177 * Correct 1~9-bit errors in 512-bytes data
142 */ 178 */
143static void rs_correct(unsigned char *dat, int idx, int mask) 179static void jz_rs_correct(unsigned char *dat, int idx, int mask)
144{ 180{
145 int i, j; 181 int i, j;
146 unsigned short d, d1, dm; 182 unsigned short d, d1, dm;
@@ -172,7 +208,7 @@ static void rs_correct(unsigned char *dat, int idx, int mask)
172/* 208/*
173 * Read oob 209 * Read oob
174 */ 210 */
175static int nand_read_oob(int page_addr, unsigned char *buf, int size) 211static int jz_nand_read_oob(int page_addr, unsigned char *buf, int size)
176{ 212{
177 struct nand_param *nandp = &internal_param; 213 struct nand_param *nandp = &internal_param;
178 int page_size, row_cycle, bus_width; 214 int page_size, row_cycle, bus_width;
@@ -210,10 +246,10 @@ static int nand_read_oob(int page_addr, unsigned char *buf, int size)
210 __nand_cmd(NAND_CMD_READSTART); 246 __nand_cmd(NAND_CMD_READSTART);
211 247
212 /* Wait for device ready */ 248 /* Wait for device ready */
213 nand_wait_ready(); 249 jz_nand_wait_ready();
214 250
215 /* Read oob data */ 251 /* Read oob data */
216 nand_read_buf(buf, size, bus_width); 252 jz_nand_read_buf(buf, size, bus_width);
217 253
218 return 0; 254 return 0;
219} 255}
@@ -228,7 +264,7 @@ static int nand_read_oob(int page_addr, unsigned char *buf, int size)
228 * page - page number within a block: 0, 1, 2, ... 264 * page - page number within a block: 0, 1, 2, ...
229 * dst - pointer to target buffer 265 * dst - pointer to target buffer
230 */ 266 */
231static int nand_read_page(int block, int page, unsigned char *dst) 267static int jz_nand_read_page(int block, int page, unsigned char *dst)
232{ 268{
233 struct nand_param *nandp = &internal_param; 269 struct nand_param *nandp = &internal_param;
234 int page_size, oob_size, page_per_block; 270 int page_size, oob_size, page_per_block;
@@ -248,7 +284,7 @@ static int nand_read_page(int block, int page, unsigned char *dst)
248 /* 284 /*
249 * Read oob data 285 * Read oob data
250 */ 286 */
251 nand_read_oob(page_addr, oob_buf, oob_size); 287 jz_nand_read_oob(page_addr, oob_buf, oob_size);
252 288
253 /* 289 /*
254 * Read page data 290 * Read page data
@@ -273,7 +309,7 @@ static int nand_read_page(int block, int page, unsigned char *dst)
273 __nand_cmd(NAND_CMD_READSTART); 309 __nand_cmd(NAND_CMD_READSTART);
274 310
275 /* Wait for device ready */ 311 /* Wait for device ready */
276 nand_wait_ready(); 312 jz_nand_wait_ready();
277 313
278 /* Read page data */ 314 /* Read page data */
279 data_buf = dst; 315 data_buf = dst;
@@ -290,7 +326,7 @@ static int nand_read_page(int block, int page, unsigned char *dst)
290 __nand_ecc_rs_decoding(); 326 __nand_ecc_rs_decoding();
291 327
292 /* Read data */ 328 /* Read data */
293 nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width); 329 jz_nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width);
294 330
295 /* Set PAR values */ 331 /* Set PAR values */
296 for (j = 0; j < PAR_SIZE; j++) 332 for (j = 0; j < PAR_SIZE; j++)
@@ -310,8 +346,10 @@ static int nand_read_page(int block, int page, unsigned char *dst)
310 if (stat & EMC_NFINTS_ERR) 346 if (stat & EMC_NFINTS_ERR)
311 { 347 {
312 /* Error occurred */ 348 /* Error occurred */
313 if (stat & EMC_NFINTS_UNCOR) { 349 if (stat & EMC_NFINTS_UNCOR)
350 {
314 /* Uncorrectable error occurred */ 351 /* Uncorrectable error occurred */
352 panicf("Uncorrectable ECC error at NAND page 0x%x block 0x%x", page, block);
315 } 353 }
316 else 354 else
317 { 355 {
@@ -323,19 +361,19 @@ static int nand_read_page(int block, int page, unsigned char *dst)
323 case 4: 361 case 4:
324 index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; 362 index = (REG_EMC_NFERR3 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
325 mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; 363 mask = (REG_EMC_NFERR3 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
326 rs_correct(data_buf, index, mask); 364 jz_rs_correct(data_buf, index, mask);
327 case 3: 365 case 3:
328 index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; 366 index = (REG_EMC_NFERR2 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
329 mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; 367 mask = (REG_EMC_NFERR2 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
330 rs_correct(data_buf, index, mask); 368 jz_rs_correct(data_buf, index, mask);
331 case 2: 369 case 2:
332 index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; 370 index = (REG_EMC_NFERR1 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
333 mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; 371 mask = (REG_EMC_NFERR1 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
334 rs_correct(data_buf, index, mask); 372 jz_rs_correct(data_buf, index, mask);
335 case 1: 373 case 1:
336 index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT; 374 index = (REG_EMC_NFERR0 & EMC_NFERR_INDEX_MASK) >> EMC_NFERR_INDEX_BIT;
337 mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT; 375 mask = (REG_EMC_NFERR0 & EMC_NFERR_MASK_MASK) >> EMC_NFERR_MASK_BIT;
338 rs_correct(data_buf, index, mask); 376 jz_rs_correct(data_buf, index, mask);
339 break; 377 break;
340 default: 378 default:
341 break; 379 break;
@@ -352,7 +390,7 @@ static int nand_read_page(int block, int page, unsigned char *dst)
352/* 390/*
353 * Enable NAND controller 391 * Enable NAND controller
354 */ 392 */
355static void nand_enable(void) 393static void jz_nand_enable(void)
356{ 394{
357 __nand_enable(); 395 __nand_enable();
358 396
@@ -362,16 +400,16 @@ static void nand_enable(void)
362/* 400/*
363 * Disable NAND controller 401 * Disable NAND controller
364 */ 402 */
365static void nand_disable(void) 403static void jz_nand_disable(void)
366{ 404{
367 __nand_disable(); 405 __nand_disable();
368} 406}
369 407
370int nand_init(void) 408static int jz_nand_init(void)
371{ 409{
372 unsigned char cData[5]; 410 unsigned char cData[5];
373 411
374 nand_enable(); 412 jz_nand_enable();
375 413
376 __nand_cmd(NAND_CMD_READID); 414 __nand_cmd(NAND_CMD_READID);
377 __nand_addr(NAND_CMD_READ0); 415 __nand_addr(NAND_CMD_READ0);
@@ -386,7 +424,7 @@ int nand_init(void)
386 { 424 {
387 panicf("Unknown NAND flash chip: 0x%x 0x%x 0x%x 0x%x 0x%x", cData[0], 425 panicf("Unknown NAND flash chip: 0x%x 0x%x 0x%x 0x%x 0x%x", cData[0],
388 cData[1], cData[2], cData[3], cData[4]); 426 cData[1], cData[2], cData[3], cData[4]);
389 return -1; 427 return -1; /* panicf() doesn't return though */
390 } 428 }
391 429
392 internal_param.bus_width = 8; 430 internal_param.bus_width = 8;
@@ -400,23 +438,39 @@ int nand_init(void)
400 438
401void jz_nand_read(int block, int page, unsigned char *buf) 439void jz_nand_read(int block, int page, unsigned char *buf)
402{ 440{
403 nand_read_page(block, page, buf); 441 jz_nand_read_page(block, page, buf);
404} 442}
405 443
406int nand_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf) 444static bool inited = false;
445int nand_init(void)
446{
447 int res = 0;
448
449 if(!inited)
450 {
451 res = jz_nand_init();
452 inited = true;
453 }
454
455 return res;
456}
457
458/* TODO */
459int nand_read_sectors(unsigned long start, int count, void* buf)
407{ 460{
408 (void)start; 461 (void)start;
409 (void)count; 462 (void)count;
410 (void)buf; 463 (void)buf;
411 return 0; 464 return -1;
412} 465}
413 466
414int nand_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* buf) 467/* TODO */
468int nand_write_sectors(unsigned long start, int count, const void* buf)
415{ 469{
416 (void)start; 470 (void)start;
417 (void)count; 471 (void)count;
418 (void)buf; 472 (void)buf;
419 return 0; 473 return -1;
420} 474}
421 475
422void nand_spindown(int seconds) 476void nand_spindown(int seconds)