diff options
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c index c9ca85cfaf..57361370dc 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c | |||
@@ -30,6 +30,7 @@ | |||
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 | //#define LOGF_ENABLE | ||
33 | #include "logf.h" | 34 | #include "logf.h" |
34 | 35 | ||
35 | //#define USE_DMA | 36 | //#define USE_DMA |
@@ -114,8 +115,9 @@ static struct nand_info* banks[4]; | |||
114 | static unsigned int nr_banks = 1; | 115 | static unsigned int nr_banks = 1; |
115 | static unsigned long bank_size; | 116 | static unsigned long bank_size; |
116 | static struct nand_param internal_param; | 117 | static struct nand_param internal_param; |
117 | #ifdef USE_DMA | ||
118 | static struct mutex nand_mtx; | 118 | static struct mutex nand_mtx; |
119 | #ifdef USE_DMA | ||
120 | static struct mutex nand_dma_mtx; | ||
119 | static struct wakeup nand_wkup; | 121 | static struct wakeup nand_wkup; |
120 | #endif | 122 | #endif |
121 | static unsigned char temp_page[4096]; /* Max page size */ | 123 | static unsigned char temp_page[4096]; /* Max page size */ |
@@ -148,7 +150,7 @@ static inline void jz_nand_read_buf8(void *buf, int count) | |||
148 | #else | 150 | #else |
149 | static void jz_nand_write_dma(void *source, unsigned int len, int bw) | 151 | static void jz_nand_write_dma(void *source, unsigned int len, int bw) |
150 | { | 152 | { |
151 | mutex_lock(&nand_mtx); | 153 | mutex_lock(&nand_dma_mtx); |
152 | 154 | ||
153 | if(((unsigned int)source < 0xa0000000) && len) | 155 | if(((unsigned int)source < 0xa0000000) && len) |
154 | dma_cache_wback_inv((unsigned long)source, len); | 156 | dma_cache_wback_inv((unsigned long)source, len); |
@@ -176,12 +178,12 @@ static void jz_nand_write_dma(void *source, unsigned int len, int bw) | |||
176 | 178 | ||
177 | dma_disable(); | 179 | dma_disable(); |
178 | 180 | ||
179 | mutex_unlock(&nand_mtx); | 181 | mutex_unlock(&nand_dma_mtx); |
180 | } | 182 | } |
181 | 183 | ||
182 | static void jz_nand_read_dma(void *target, unsigned int len, int bw) | 184 | static void jz_nand_read_dma(void *target, unsigned int len, int bw) |
183 | { | 185 | { |
184 | mutex_lock(&nand_mtx); | 186 | mutex_lock(&nand_dma_mtx); |
185 | 187 | ||
186 | if(((unsigned int)target < 0xa0000000) && len) | 188 | if(((unsigned int)target < 0xa0000000) && len) |
187 | dma_cache_wback_inv((unsigned long)target, len); | 189 | dma_cache_wback_inv((unsigned long)target, len); |
@@ -208,7 +210,7 @@ static void jz_nand_read_dma(void *target, unsigned int len, int bw) | |||
208 | 210 | ||
209 | dma_disable(); | 211 | dma_disable(); |
210 | 212 | ||
211 | mutex_unlock(&nand_mtx); | 213 | mutex_unlock(&nand_dma_mtx); |
212 | } | 214 | } |
213 | 215 | ||
214 | void DMA_CALLBACK(DMA_NAND_CHANNEL)(void) | 216 | void DMA_CALLBACK(DMA_NAND_CHANNEL)(void) |
@@ -427,7 +429,7 @@ static int jz_nand_read_page(unsigned long page_addr, unsigned char *dst) | |||
427 | if (stat & EMC_NFINTS_UNCOR) | 429 | if (stat & EMC_NFINTS_UNCOR) |
428 | { | 430 | { |
429 | /* Uncorrectable error occurred */ | 431 | /* Uncorrectable error occurred */ |
430 | panicf("Uncorrectable ECC error at NAND page address 0x%lx", page_addr); | 432 | logf("Uncorrectable ECC error at NAND page address 0x%lx", page_addr); |
431 | return -1; | 433 | return -1; |
432 | } | 434 | } |
433 | else | 435 | else |
@@ -596,8 +598,9 @@ int nand_init(void) | |||
596 | if(!inited) | 598 | if(!inited) |
597 | { | 599 | { |
598 | res = jz_nand_init(); | 600 | res = jz_nand_init(); |
599 | #ifdef USE_DMA | ||
600 | mutex_init(&nand_mtx); | 601 | mutex_init(&nand_mtx); |
602 | #ifdef USE_DMA | ||
603 | mutex_init(&nand_dma_mtx); | ||
601 | wakeup_init(&nand_wkup); | 604 | wakeup_init(&nand_wkup); |
602 | system_enable_irq(DMA_IRQ(DMA_NAND_CHANNEL)); | 605 | system_enable_irq(DMA_IRQ(DMA_NAND_CHANNEL)); |
603 | #endif | 606 | #endif |
@@ -608,38 +611,58 @@ int nand_init(void) | |||
608 | return res; | 611 | return res; |
609 | } | 612 | } |
610 | 613 | ||
611 | int nand_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf) | 614 | static inline int read_sector(unsigned long start, unsigned int count, |
615 | void* buf, unsigned int chip_size) | ||
612 | { | 616 | { |
613 | int i, ret = 0, chip_size = chip_info->page_size; | 617 | register int ret; |
618 | |||
619 | if(UNLIKELY(start % chip_size == 0 && count == chip_size)) | ||
620 | ret = jz_nand_read_page(start / chip_size, buf); | ||
621 | else | ||
622 | { | ||
623 | ret = jz_nand_read_page(start / chip_size, temp_page); | ||
624 | memcpy(buf, temp_page + (start % chip_size), count); | ||
625 | } | ||
614 | 626 | ||
615 | logf("nand_read_sectors(%ld, %d, 0x%x)", start, count, (int)buf); | 627 | return ret; |
628 | } | ||
629 | |||
630 | int nand_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf) | ||
631 | { | ||
632 | int ret = 0; | ||
633 | unsigned int i, _count, chip_size = chip_info->page_size; | ||
634 | unsigned long _start; | ||
616 | 635 | ||
617 | start *= 512; | 636 | logf("start"); |
618 | count *= 512; | 637 | mutex_lock(&nand_mtx); |
638 | |||
639 | _start = start << 9; | ||
640 | _count = count << 9; | ||
619 | 641 | ||
620 | if(count <= chip_size) | 642 | if(_count <= chip_size) |
621 | { | 643 | { |
622 | jz_nand_select(start / 512 / bank_size); | 644 | jz_nand_select(start / bank_size); |
623 | 645 | ret = read_sector(_start, _count, buf, chip_size); | |
624 | ret = jz_nand_read_page(start/chip_size, temp_page); | 646 | jz_nand_deselect(start / bank_size); |
625 | memcpy(buf, temp_page+(start%chip_size), count); | ||
626 | |||
627 | jz_nand_deselect(start / 512 / bank_size); | ||
628 | } | 647 | } |
629 | else | 648 | else |
630 | { | 649 | { |
631 | for(i=0; i<count && ret==0; i+=chip_size) | 650 | for(i=0; i<_count && ret==0; i+=chip_size) |
632 | { | 651 | { |
633 | jz_nand_select((start/512+i) / bank_size); | 652 | jz_nand_select((start+(i>>9)) / bank_size); |
634 | 653 | ||
635 | ret = jz_nand_read_page((start+i)/chip_size, temp_page); | 654 | ret = read_sector(_start+i, (_count-i < chip_size ? |
636 | memcpy(buf+i, temp_page+((start+i)%chip_size), | 655 | _count-i : chip_size), |
637 | (count-i < chip_size ? count-i : chip_size)); | 656 | buf+i, chip_size); |
638 | 657 | ||
639 | jz_nand_deselect((start/512+i) / bank_size); | 658 | jz_nand_deselect((start+(i>>9)) / bank_size); |
640 | } | 659 | } |
641 | } | 660 | } |
642 | 661 | ||
662 | mutex_unlock(&nand_mtx); | ||
663 | |||
664 | logf("nand_read_sectors(%ld, %d, 0x%x): %d", start, count, (int)buf, ret); | ||
665 | |||
643 | return ret; | 666 | return ret; |
644 | } | 667 | } |
645 | 668 | ||