summaryrefslogtreecommitdiff
path: root/firmware/target/mips
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c78
1 files changed, 42 insertions, 36 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
index 8c4ad40f72..851472bf62 100644
--- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
@@ -30,8 +30,10 @@
30#include "storage.h" 30#include "storage.h"
31#include "buffer.h" 31#include "buffer.h"
32#include "string.h" 32#include "string.h"
33#include "logf.h"
33 34
34//#define USE_DMA 35//#define USE_DMA
36//#define USE_ECC
35 37
36/* 38/*
37 * Standard NAND flash commands 39 * Standard NAND flash commands
@@ -51,9 +53,9 @@
51#define NAND_CMD_RESET 0xff 53#define NAND_CMD_RESET 0xff
52 54
53/* Extended commands for large page devices */ 55/* Extended commands for large page devices */
54#define NAND_CMD_READSTART 0x30 56#define NAND_CMD_READSTART 0x30
55#define NAND_CMD_RNDOUTSTART 0xE0 57#define NAND_CMD_RNDOUTSTART 0xE0
56#define NAND_CMD_CACHEDPROG 0x15 58#define NAND_CMD_CACHEDPROG 0x15
57 59
58/* Status bits */ 60/* Status bits */
59#define NAND_STATUS_FAIL 0x01 61#define NAND_STATUS_FAIL 0x01
@@ -69,8 +71,8 @@ struct nand_param
69{ 71{
70 unsigned int bus_width; /* data bus width: 8-bit/16-bit */ 72 unsigned int bus_width; /* data bus width: 8-bit/16-bit */
71 unsigned int row_cycle; /* row address cycles: 2/3 */ 73 unsigned int row_cycle; /* row address cycles: 2/3 */
72 unsigned int page_size; /* page size in bytes: 512/2048 */ 74 unsigned int page_size; /* page size in bytes: 512/2048/4096 */
73 unsigned int oob_size; /* oob size in bytes: 16/64 */ 75 unsigned int oob_size; /* oob size in bytes: 16/64/128 */
74 unsigned int page_per_block; /* pages per block: 32/64/128 */ 76 unsigned int page_per_block; /* pages per block: 32/64/128 */
75}; 77};
76 78
@@ -83,9 +85,9 @@ struct nand_param
83 * 85 *
84 */ 86 */
85 87
86#define NAND_DATAPORT 0xb8000000 88#define NAND_DATAPORT 0xB8000000
87#define NAND_ADDRPORT 0xb8010000 89#define NAND_ADDRPORT 0xB8010000
88#define NAND_COMMPORT 0xb8008000 90#define NAND_COMMPORT 0xB8008000
89 91
90#define ECC_BLOCK 512 92#define ECC_BLOCK 512
91#define ECC_POS 6 93#define ECC_POS 6
@@ -93,8 +95,8 @@ struct nand_param
93 95
94#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n)) 96#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
95#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n)) 97#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
96#define __nand_data8() REG8(NAND_DATAPORT) 98#define __nand_data8() (REG8(NAND_DATAPORT))
97#define __nand_data16() REG16(NAND_DATAPORT) 99#define __nand_data16() (REG16(NAND_DATAPORT))
98 100
99#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1) 101#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
100#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1)) 102#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
@@ -118,17 +120,16 @@ static unsigned char temp_page[4096]; /* Max page size */
118 120
119static inline void jz_nand_wait_ready(void) 121static inline void jz_nand_wait_ready(void)
120{ 122{
121 unsigned int timeout = 1000; 123 register unsigned int timeout = 1000;
122 while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--); 124 while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
123 while (!(REG_GPIO_PXPIN(2) & 0x40000000)); 125 while (!(REG_GPIO_PXPIN(2) & 0x40000000));
124} 126}
125 127
126#ifndef USE_DMA 128#ifndef USE_DMA
127
128static inline void jz_nand_read_buf16(void *buf, int count) 129static inline void jz_nand_read_buf16(void *buf, int count)
129{ 130{
130 int i; 131 register int i;
131 unsigned short *p = (unsigned short *)buf; 132 register unsigned short *p = (unsigned short *)buf;
132 133
133 for (i = 0; i < count; i += 2) 134 for (i = 0; i < count; i += 2)
134 *p++ = __nand_data16(); 135 *p++ = __nand_data16();
@@ -136,15 +137,13 @@ static inline void jz_nand_read_buf16(void *buf, int count)
136 137
137static inline void jz_nand_read_buf8(void *buf, int count) 138static inline void jz_nand_read_buf8(void *buf, int count)
138{ 139{
139 int i; 140 register int i;
140 unsigned char *p = (unsigned char *)buf; 141 register unsigned char *p = (unsigned char *)buf;
141 142
142 for (i = 0; i < count; i++) 143 for (i = 0; i < count; i++)
143 *p++ = __nand_data8(); 144 *p++ = __nand_data8();
144} 145}
145
146#else 146#else
147
148static void jz_nand_write_dma(void *source, unsigned int len, int bw) 147static void jz_nand_write_dma(void *source, unsigned int len, int bw)
149{ 148{
150 mutex_lock(&nand_mtx); 149 mutex_lock(&nand_mtx);
@@ -226,8 +225,7 @@ void DMA_CALLBACK(DMA_NAND_CHANNEL)(void)
226 225
227 wakeup_signal(&nand_wkup); 226 wakeup_signal(&nand_wkup);
228} 227}
229 228#endif /* USE_DMA */
230#endif
231 229
232static inline void jz_nand_read_buf(void *buf, int count, int bw) 230static inline void jz_nand_read_buf(void *buf, int count, int bw)
233{ 231{
@@ -244,6 +242,7 @@ static inline void jz_nand_read_buf(void *buf, int count, int bw)
244#endif 242#endif
245} 243}
246 244
245#ifdef USE_ECC
247/* 246/*
248 * Correct 1~9-bit errors in 512-bytes data 247 * Correct 1~9-bit errors in 512-bytes data
249 */ 248 */
@@ -258,7 +257,8 @@ static void jz_rs_correct(unsigned char *dat, int idx, int mask)
258 i = (j == 0) ? (i - 1) : i; 257 i = (j == 0) ? (i - 1) : i;
259 j = (j == 0) ? 7 : (j - 1); 258 j = (j == 0) ? 7 : (j - 1);
260 259
261 if (i > 512) return; 260 if (i > 512)
261 return;
262 262
263 if (i == 512) 263 if (i == 512)
264 d = dat[i - 1]; 264 d = dat[i - 1];
@@ -275,11 +275,12 @@ static void jz_rs_correct(unsigned char *dat, int idx, int mask)
275 if (i < 512) 275 if (i < 512)
276 dat[i] = (d >> 8) & 0xff; 276 dat[i] = (d >> 8) & 0xff;
277} 277}
278#endif
278 279
279/* 280/*
280 * Read oob 281 * Read oob
281 */ 282 */
282static int jz_nand_read_oob(int page_addr, unsigned char *buf, int size) 283static int jz_nand_read_oob(unsigned long page_addr, unsigned char *buf, int size)
283{ 284{
284 struct nand_param *nandp = &internal_param; 285 struct nand_param *nandp = &internal_param;
285 int page_size, row_cycle, bus_width; 286 int page_size, row_cycle, bus_width;
@@ -335,14 +336,14 @@ static int jz_nand_read_oob(int page_addr, unsigned char *buf, int size)
335 * page - page number within a block: 0, 1, 2, ... 336 * page - page number within a block: 0, 1, 2, ...
336 * dst - pointer to target buffer 337 * dst - pointer to target buffer
337 */ 338 */
338static int jz_nand_read_page(int block, int page, unsigned char *dst) 339static int jz_nand_read_page(unsigned long page_addr, unsigned char *dst)
339{ 340{
340 struct nand_param *nandp = &internal_param; 341 struct nand_param *nandp = &internal_param;
341 int page_size, oob_size, page_per_block; 342 int page_size, oob_size, page_per_block;
342 int row_cycle, bus_width, ecc_count; 343 int row_cycle, bus_width, ecc_count;
343 int page_addr, i, j; 344 int i, j;
344 unsigned char *data_buf; 345 unsigned char *data_buf;
345 unsigned char oob_buf[128]; 346 unsigned char oob_buf[nandp->oob_size];
346 347
347 page_size = nandp->page_size; 348 page_size = nandp->page_size;
348 oob_size = nandp->oob_size; 349 oob_size = nandp->oob_size;
@@ -350,8 +351,6 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
350 row_cycle = nandp->row_cycle; 351 row_cycle = nandp->row_cycle;
351 bus_width = nandp->bus_width; 352 bus_width = nandp->bus_width;
352 353
353 page_addr = page + block * page_per_block;
354
355 /* 354 /*
356 * Read oob data 355 * Read oob data
357 */ 356 */
@@ -372,7 +371,7 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
372 /* Send page address */ 371 /* Send page address */
373 __nand_addr(page_addr & 0xff); 372 __nand_addr(page_addr & 0xff);
374 __nand_addr((page_addr >> 8) & 0xff); 373 __nand_addr((page_addr >> 8) & 0xff);
375 if (row_cycle == 3) 374 if (row_cycle >= 3)
376 __nand_addr((page_addr >> 16) & 0xff); 375 __nand_addr((page_addr >> 16) & 0xff);
377 376
378 /* Send READSTART command for 2048 ps NAND */ 377 /* Send READSTART command for 2048 ps NAND */
@@ -389,16 +388,19 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
389 388
390 for (i = 0; i < ecc_count; i++) 389 for (i = 0; i < ecc_count; i++)
391 { 390 {
391#ifdef USE_ECC
392 volatile unsigned char *paraddr = (volatile unsigned char *)EMC_NFPAR0; 392 volatile unsigned char *paraddr = (volatile unsigned char *)EMC_NFPAR0;
393 unsigned int stat; 393 unsigned int stat;
394 394
395 /* Enable RS decoding */ 395 /* Enable RS decoding */
396 REG_EMC_NFINTS = 0x0; 396 REG_EMC_NFINTS = 0x0;
397 __nand_ecc_rs_decoding(); 397 __nand_ecc_rs_decoding();
398#endif
398 399
399 /* Read data */ 400 /* Read data */
400 jz_nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width); 401 jz_nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width);
401 402
403#ifdef USE_ECC
402 /* Set PAR values */ 404 /* Set PAR values */
403 for (j = 0; j < PAR_SIZE; j++) 405 for (j = 0; j < PAR_SIZE; j++)
404 *paraddr++ = oob_buf[ECC_POS + i*PAR_SIZE + j]; 406 *paraddr++ = oob_buf[ECC_POS + i*PAR_SIZE + j];
@@ -420,7 +422,7 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
420 if (stat & EMC_NFINTS_UNCOR) 422 if (stat & EMC_NFINTS_UNCOR)
421 { 423 {
422 /* Uncorrectable error occurred */ 424 /* Uncorrectable error occurred */
423 panicf("Uncorrectable ECC error at NAND page 0x%x block 0x%x", page, block); 425 panicf("Uncorrectable ECC error at NAND page address 0x%lx", page_addr);
424 return -1; 426 return -1;
425 } 427 }
426 else 428 else
@@ -452,6 +454,7 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
452 } 454 }
453 } 455 }
454 } 456 }
457#endif
455 458
456 data_buf += ECC_BLOCK; 459 data_buf += ECC_BLOCK;
457 } 460 }
@@ -502,7 +505,7 @@ static int jz_nand_init(void)
502 internal_param.bus_width = 8; 505 internal_param.bus_width = 8;
503 internal_param.row_cycle = chip_info->row_cycles; 506 internal_param.row_cycle = chip_info->row_cycles;
504 internal_param.page_size = chip_info->page_size; 507 internal_param.page_size = chip_info->page_size;
505 internal_param.oob_size = chip_info->page_size/32; 508 internal_param.oob_size = chip_info->spare_size;
506 internal_param.page_per_block = chip_info->pages_per_block; 509 internal_param.page_per_block = chip_info->pages_per_block;
507 510
508 return 0; 511 return 0;
@@ -532,21 +535,24 @@ int nand_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* b
532{ 535{
533 int i, ret = 0; 536 int i, ret = 0;
534 537
538 logf("nand_read_sectors(%ld, %d, 0x%x)", start, count, (int)buf);
539
535 start *= 512; 540 start *= 512;
536 count *= 512; 541 count *= 512;
537 542
538 if(count <= chip_info->page_size) 543 if(count <= chip_info->page_size)
539 { 544 {
540 ret = jz_nand_read_page(start % (chip_info->page_size * chip_info->pages_per_block), start % chip_info->page_size, temp_page); 545 ret = jz_nand_read_page(start/chip_info->page_size, temp_page);
541 memcpy(buf, temp_page, count); 546 memcpy(buf, temp_page+(start%chip_info->page_size), count);
542 return ret; 547 return ret;
543 } 548 }
544 else 549 else
545 { 550 {
546 for(i=0; i<count && ret == 0; i+=chip_info->page_size) 551 for(i=0; i<count && ret==0; i+=chip_info->page_size)
547 { 552 {
548 ret = jz_nand_read_page((start+i) % (chip_info->page_size * chip_info->pages_per_block), (start+i) % chip_info->page_size, temp_page); 553 ret = jz_nand_read_page((start+i)/chip_info->page_size, temp_page);
549 memcpy(buf+i, temp_page, (count-i < chip_info->page_size ? count-i : chip_info->page_size)); 554 memcpy(buf+i, temp_page+((start+i)%chip_info->page_size),
555 (count-i < chip_info->page_size ? count-i : chip_info->page_size));
550 } 556 }
551 return ret; 557 return ret;
552 } 558 }
@@ -607,7 +613,7 @@ void nand_get_info(IF_MV2(int drive,) struct storage_info *info)
607 613
608 /* blocks count */ 614 /* blocks count */
609 /* TODO: proper amount of sectors! */ 615 /* TODO: proper amount of sectors! */
610 info->num_sectors = (chip_info->page_size / 512) * chip_info->pages_per_block * chip_info->blocks_per_bank; 616 info->num_sectors = ((chip_info->page_size+chip_info->spare_size) / 512) * chip_info->pages_per_block * chip_info->blocks_per_bank;
611 info->sector_size = 512; 617 info->sector_size = 512;
612} 618}
613#endif 619#endif