diff options
Diffstat (limited to 'firmware/target/arm/ata-nand-telechips.c')
-rw-r--r-- | firmware/target/arm/ata-nand-telechips.c | 92 |
1 files changed, 46 insertions, 46 deletions
diff --git a/firmware/target/arm/ata-nand-telechips.c b/firmware/target/arm/ata-nand-telechips.c index d61c223219..453a51ed1b 100644 --- a/firmware/target/arm/ata-nand-telechips.c +++ b/firmware/target/arm/ata-nand-telechips.c | |||
@@ -179,7 +179,7 @@ static int phys_segment_to_page_addr(int phys_segment, int page_in_seg) | |||
179 | break; | 179 | break; |
180 | } | 180 | } |
181 | } | 181 | } |
182 | 182 | ||
183 | page_addr += (page_in_seg / nand_data->planes); | 183 | page_addr += (page_in_seg / nand_data->planes); |
184 | 184 | ||
185 | return page_addr; | 185 | return page_addr; |
@@ -222,7 +222,7 @@ static void nand_chip_select(int bank) | |||
222 | static void nand_read_id(int bank, unsigned char* id_buf) | 222 | static void nand_read_id(int bank, unsigned char* id_buf) |
223 | { | 223 | { |
224 | int i; | 224 | int i; |
225 | 225 | ||
226 | /* Enable NFC bus clock */ | 226 | /* Enable NFC bus clock */ |
227 | BCLKCTR |= DEV_NAND; | 227 | BCLKCTR |= DEV_NAND; |
228 | 228 | ||
@@ -358,7 +358,7 @@ static void nand_setup_read(int bank, int row, int column) | |||
358 | static void nand_end_read(void) | 358 | static void nand_end_read(void) |
359 | { | 359 | { |
360 | nand_chip_select(-1); | 360 | nand_chip_select(-1); |
361 | 361 | ||
362 | /* Disable NFC bus clock */ | 362 | /* Disable NFC bus clock */ |
363 | BCLKCTR &= ~DEV_NAND; | 363 | BCLKCTR &= ~DEV_NAND; |
364 | } | 364 | } |
@@ -367,7 +367,7 @@ static void nand_end_read(void) | |||
367 | static void nand_read_raw(int bank, int row, int column, int size, void* buf) | 367 | static void nand_read_raw(int bank, int row, int column, int size, void* buf) |
368 | { | 368 | { |
369 | int i; | 369 | int i; |
370 | 370 | ||
371 | nand_setup_read(bank, row, column); | 371 | nand_setup_read(bank, row, column); |
372 | 372 | ||
373 | /* Read data into page buffer */ | 373 | /* Read data into page buffer */ |
@@ -388,7 +388,7 @@ static void nand_read_raw(int bank, int row, int column, int size, void* buf) | |||
388 | ((unsigned int*)buf)[i] = NFC_WDATA; | 388 | ((unsigned int*)buf)[i] = NFC_WDATA; |
389 | } | 389 | } |
390 | } | 390 | } |
391 | 391 | ||
392 | nand_end_read(); | 392 | nand_end_read(); |
393 | } | 393 | } |
394 | 394 | ||
@@ -422,7 +422,7 @@ static void nand_get_chip_info(void) | |||
422 | sectors_per_page = nand_data->page_size / SECTOR_SIZE; | 422 | sectors_per_page = nand_data->page_size / SECTOR_SIZE; |
423 | 423 | ||
424 | sectors_per_segment = bytes_per_segment / SECTOR_SIZE; | 424 | sectors_per_segment = bytes_per_segment / SECTOR_SIZE; |
425 | 425 | ||
426 | pages_per_segment = sectors_per_segment / sectors_per_page; | 426 | pages_per_segment = sectors_per_segment / sectors_per_page; |
427 | 427 | ||
428 | /* Establish how many banks are present */ | 428 | /* Establish how many banks are present */ |
@@ -494,7 +494,7 @@ static bool nand_read_sector_of_phys_page(int bank, int page, | |||
494 | 494 | ||
495 | #ifdef USE_ECC_CORRECTION | 495 | #ifdef USE_ECC_CORRECTION |
496 | unsigned long spare_buf[4]; | 496 | unsigned long spare_buf[4]; |
497 | 497 | ||
498 | /* Set up the ECC controller to monitor reads from NFC_WDATA */ | 498 | /* Set up the ECC controller to monitor reads from NFC_WDATA */ |
499 | BCLKCTR |= DEV_ECC; | 499 | BCLKCTR |= DEV_ECC; |
500 | ECC_BASE = (unsigned long)&NFC_WDATA; | 500 | ECC_BASE = (unsigned long)&NFC_WDATA; |
@@ -514,27 +514,27 @@ static bool nand_read_sector_of_phys_page(int bank, int page, | |||
514 | This way, reads are always done through NFC_WDATA - otherwise they | 514 | This way, reads are always done through NFC_WDATA - otherwise they |
515 | would not be 'seen' by the ECC controller. */ | 515 | would not be 'seen' by the ECC controller. */ |
516 | static char temp_buf[SECTOR_SIZE]; | 516 | static char temp_buf[SECTOR_SIZE]; |
517 | 517 | ||
518 | unsigned int* ptr = (unsigned int*) temp_buf; | 518 | unsigned int* ptr = (unsigned int*) temp_buf; |
519 | 519 | ||
520 | for (i = 0; i < (SECTOR_SIZE/4); i++) | 520 | for (i = 0; i < (SECTOR_SIZE/4); i++) |
521 | { | 521 | { |
522 | *ptr++ = NFC_WDATA; | 522 | *ptr++ = NFC_WDATA; |
523 | } | 523 | } |
524 | 524 | ||
525 | memcpy(buf, temp_buf, SECTOR_SIZE); | 525 | memcpy(buf, temp_buf, SECTOR_SIZE); |
526 | } | 526 | } |
527 | else | 527 | else |
528 | { | 528 | { |
529 | /* Use straight word copy as buffer and size are both word-aligned */ | 529 | /* Use straight word copy as buffer and size are both word-aligned */ |
530 | unsigned int* ptr = (unsigned int*) buf; | 530 | unsigned int* ptr = (unsigned int*) buf; |
531 | 531 | ||
532 | for (i = 0; i < (SECTOR_SIZE/4); i++) | 532 | for (i = 0; i < (SECTOR_SIZE/4); i++) |
533 | { | 533 | { |
534 | *ptr++ = NFC_WDATA; | 534 | *ptr++ = NFC_WDATA; |
535 | } | 535 | } |
536 | } | 536 | } |
537 | 537 | ||
538 | #ifdef USE_ECC_CORRECTION | 538 | #ifdef USE_ECC_CORRECTION |
539 | /* Stop monitoring before we read the OOB data */ | 539 | /* Stop monitoring before we read the OOB data */ |
540 | ECC_CTRL &= ~ECC_M4EN; | 540 | ECC_CTRL &= ~ECC_M4EN; |
@@ -549,29 +549,29 @@ static bool nand_read_sector_of_phys_page(int bank, int page, | |||
549 | /* Calculate MLC4 ECC using bytes 0,1,8-15 */ | 549 | /* Calculate MLC4 ECC using bytes 0,1,8-15 */ |
550 | BCLKCTR |= DEV_ECC; | 550 | BCLKCTR |= DEV_ECC; |
551 | ECC_CTRL |= ECC_M4EN; | 551 | ECC_CTRL |= ECC_M4EN; |
552 | 552 | ||
553 | MLC_ECC0W = *(unsigned short*)spare_buf; | 553 | MLC_ECC0W = *(unsigned short*)spare_buf; |
554 | MLC_ECC1W = spare_buf[2]; | 554 | MLC_ECC1W = spare_buf[2]; |
555 | MLC_ECC2W = spare_buf[3]; | 555 | MLC_ECC2W = spare_buf[3]; |
556 | 556 | ||
557 | while (!(ECC_CTRL & ECC_READY)) {}; | 557 | while (!(ECC_CTRL & ECC_READY)) {}; |
558 | 558 | ||
559 | int errors = ECC_ERR_NUM & 7; | 559 | int errors = ECC_ERR_NUM & 7; |
560 | 560 | ||
561 | switch (errors) | 561 | switch (errors) |
562 | { | 562 | { |
563 | case 4: /* nothing to correct */ | 563 | case 4: /* nothing to correct */ |
564 | break; | 564 | break; |
565 | 565 | ||
566 | case 7: /* fail, can't correct */ | 566 | case 7: /* fail, can't correct */ |
567 | ret = false; | 567 | ret = false; |
568 | break; | 568 | break; |
569 | 569 | ||
570 | default: /* between 1 and 4 errors */ | 570 | default: /* between 1 and 4 errors */ |
571 | { | 571 | { |
572 | int i; | 572 | int i; |
573 | unsigned char* char_buf = (unsigned char*)buf; | 573 | unsigned char* char_buf = (unsigned char*)buf; |
574 | 574 | ||
575 | for (i = 0; i < errors + 1; i++) | 575 | for (i = 0; i < errors + 1; i++) |
576 | { | 576 | { |
577 | int offset = 0x207 - ECC_ERRADDR(i); | 577 | int offset = 0x207 - ECC_ERRADDR(i); |
@@ -584,7 +584,7 @@ static bool nand_read_sector_of_phys_page(int bank, int page, | |||
584 | ECC_CTRL &= ~ECC_M4EN; | 584 | ECC_CTRL &= ~ECC_M4EN; |
585 | BCLKCTR &= ~DEV_ECC; | 585 | BCLKCTR &= ~DEV_ECC; |
586 | #endif | 586 | #endif |
587 | 587 | ||
588 | nand_end_read(); | 588 | nand_end_read(); |
589 | 589 | ||
590 | return ret; | 590 | return ret; |
@@ -619,7 +619,7 @@ static bool nand_read_sector_of_logical_segment(int log_segment, int sector, | |||
619 | 619 | ||
620 | int cache_num = 0; | 620 | int cache_num = 0; |
621 | bool found = false; | 621 | bool found = false; |
622 | 622 | ||
623 | while (!found && cache_num < write_caches_in_use) | 623 | while (!found && cache_num < write_caches_in_use) |
624 | { | 624 | { |
625 | if (write_caches[cache_num].log_segment == log_segment) | 625 | if (write_caches[cache_num].log_segment == log_segment) |
@@ -628,10 +628,10 @@ static bool nand_read_sector_of_logical_segment(int log_segment, int sector, | |||
628 | { | 628 | { |
629 | /* data is located in random pages cache */ | 629 | /* data is located in random pages cache */ |
630 | found = true; | 630 | found = true; |
631 | 631 | ||
632 | bank = write_caches[cache_num].random_bank; | 632 | bank = write_caches[cache_num].random_bank; |
633 | phys_segment = write_caches[cache_num].random_phys_segment; | 633 | phys_segment = write_caches[cache_num].random_phys_segment; |
634 | 634 | ||
635 | page_in_segment = | 635 | page_in_segment = |
636 | write_caches[cache_num].page_map[page_in_segment]; | 636 | write_caches[cache_num].page_map[page_in_segment]; |
637 | } | 637 | } |
@@ -640,7 +640,7 @@ static bool nand_read_sector_of_logical_segment(int log_segment, int sector, | |||
640 | { | 640 | { |
641 | /* data is located in in-place pages cache */ | 641 | /* data is located in in-place pages cache */ |
642 | found = true; | 642 | found = true; |
643 | 643 | ||
644 | bank = write_caches[cache_num].inplace_bank; | 644 | bank = write_caches[cache_num].inplace_bank; |
645 | phys_segment = write_caches[cache_num].inplace_phys_segment; | 645 | phys_segment = write_caches[cache_num].inplace_phys_segment; |
646 | } | 646 | } |
@@ -664,7 +664,7 @@ static inline unsigned char get_sector_type(char* spare_buf) | |||
664 | static inline unsigned short get_log_segment_id(int phys_seg, char* spare_buf) | 664 | static inline unsigned short get_log_segment_id(int phys_seg, char* spare_buf) |
665 | { | 665 | { |
666 | (void)phys_seg; | 666 | (void)phys_seg; |
667 | 667 | ||
668 | return ((spare_buf[OFF_LOG_SEG_HIBYTE] << 8) | | 668 | return ((spare_buf[OFF_LOG_SEG_HIBYTE] << 8) | |
669 | spare_buf[OFF_LOG_SEG_LOBYTE]) | 669 | spare_buf[OFF_LOG_SEG_LOBYTE]) |
670 | #if defined(FTL_V1) | 670 | #if defined(FTL_V1) |
@@ -702,7 +702,7 @@ static void read_random_writes_cache(int bank, int phys_segment) | |||
702 | 16, spare_buf); | 702 | 16, spare_buf); |
703 | 703 | ||
704 | log_segment = get_log_segment_id(phys_segment, spare_buf); | 704 | log_segment = get_log_segment_id(phys_segment, spare_buf); |
705 | 705 | ||
706 | if (log_segment == -1) | 706 | if (log_segment == -1) |
707 | return; | 707 | return; |
708 | 708 | ||
@@ -734,13 +734,13 @@ static void read_random_writes_cache(int bank, int phys_segment) | |||
734 | page++) | 734 | page++) |
735 | { | 735 | { |
736 | unsigned short cached_page; | 736 | unsigned short cached_page; |
737 | 737 | ||
738 | nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page), | 738 | nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page), |
739 | SECTOR_SIZE, /* offset to first sector's spare */ | 739 | SECTOR_SIZE, /* offset to first sector's spare */ |
740 | 16, spare_buf); | 740 | 16, spare_buf); |
741 | 741 | ||
742 | cached_page = get_cached_page_id(spare_buf); | 742 | cached_page = get_cached_page_id(spare_buf); |
743 | 743 | ||
744 | if (cached_page != 0xFFFF) | 744 | if (cached_page != 0xFFFF) |
745 | write_caches[cache_no].page_map[cached_page] = page; | 745 | write_caches[cache_no].page_map[cached_page] = page; |
746 | } | 746 | } |
@@ -759,10 +759,10 @@ static void read_inplace_writes_cache(int bank, int phys_segment) | |||
759 | 16, spare_buf); | 759 | 16, spare_buf); |
760 | 760 | ||
761 | log_segment = get_log_segment_id(phys_segment, spare_buf); | 761 | log_segment = get_log_segment_id(phys_segment, spare_buf); |
762 | 762 | ||
763 | if (log_segment == -1) | 763 | if (log_segment == -1) |
764 | return; | 764 | return; |
765 | 765 | ||
766 | /* Find which cache this is related to */ | 766 | /* Find which cache this is related to */ |
767 | int cache_no = find_write_cache(log_segment); | 767 | int cache_no = find_write_cache(log_segment); |
768 | 768 | ||
@@ -780,7 +780,7 @@ static void read_inplace_writes_cache(int bank, int phys_segment) | |||
780 | } | 780 | } |
781 | 781 | ||
782 | write_caches[cache_no].log_segment = log_segment; | 782 | write_caches[cache_no].log_segment = log_segment; |
783 | 783 | ||
784 | /* Find how many pages have been written to the new segment */ | 784 | /* Find how many pages have been written to the new segment */ |
785 | while (log_segment != -1 && | 785 | while (log_segment != -1 && |
786 | page < (nand_data->pages_per_block * nand_data->planes) - 1) | 786 | page < (nand_data->pages_per_block * nand_data->planes) - 1) |
@@ -791,7 +791,7 @@ static void read_inplace_writes_cache(int bank, int phys_segment) | |||
791 | 791 | ||
792 | log_segment = get_log_segment_id(phys_segment, spare_buf); | 792 | log_segment = get_log_segment_id(phys_segment, spare_buf); |
793 | } | 793 | } |
794 | 794 | ||
795 | if (page != 0) | 795 | if (page != 0) |
796 | { | 796 | { |
797 | write_caches[cache_no].inplace_bank = bank; | 797 | write_caches[cache_no].inplace_bank = bank; |
@@ -801,7 +801,7 @@ static void read_inplace_writes_cache(int bank, int phys_segment) | |||
801 | } | 801 | } |
802 | 802 | ||
803 | 803 | ||
804 | int nand_read_sectors(IF_MD(int drive,) unsigned long start, int incount, | 804 | int nand_read_sectors(IF_MD(int drive,) sector_t start, int incount, |
805 | void* inbuf) | 805 | void* inbuf) |
806 | { | 806 | { |
807 | #ifdef HAVE_MULTIDRIVE | 807 | #ifdef HAVE_MULTIDRIVE |
@@ -809,15 +809,15 @@ int nand_read_sectors(IF_MD(int drive,) unsigned long start, int incount, | |||
809 | #endif | 809 | #endif |
810 | 810 | ||
811 | int ret = 0; | 811 | int ret = 0; |
812 | 812 | ||
813 | mutex_lock(&ata_mtx); | 813 | mutex_lock(&ata_mtx); |
814 | 814 | ||
815 | led(true); | 815 | led(true); |
816 | 816 | ||
817 | while (incount > 0) | 817 | while (incount > 0) |
818 | { | 818 | { |
819 | int done = 0; | 819 | int done = 0; |
820 | int segment = start / sectors_per_segment; | 820 | sector_t segment = start / sectors_per_segment; |
821 | int secmod = start % sectors_per_segment; | 821 | int secmod = start % sectors_per_segment; |
822 | 822 | ||
823 | while (incount > 0 && secmod < sectors_per_segment) | 823 | while (incount > 0 && secmod < sectors_per_segment) |
@@ -839,7 +839,7 @@ int nand_read_sectors(IF_MD(int drive,) unsigned long start, int incount, | |||
839 | secmod++; | 839 | secmod++; |
840 | done++; | 840 | done++; |
841 | } | 841 | } |
842 | 842 | ||
843 | if (done < 0) | 843 | if (done < 0) |
844 | { | 844 | { |
845 | ret = -1; | 845 | ret = -1; |
@@ -852,11 +852,11 @@ nand_read_error: | |||
852 | 852 | ||
853 | mutex_unlock(&ata_mtx); | 853 | mutex_unlock(&ata_mtx); |
854 | led(false); | 854 | led(false); |
855 | 855 | ||
856 | return ret; | 856 | return ret; |
857 | } | 857 | } |
858 | 858 | ||
859 | int nand_write_sectors(IF_MD(int drive,) unsigned long start, int count, | 859 | int nand_write_sectors(IF_MD(int drive,) sector_t start, int count, |
860 | const void* outbuf) | 860 | const void* outbuf) |
861 | { | 861 | { |
862 | #ifdef HAVE_MULTIDRIVE | 862 | #ifdef HAVE_MULTIDRIVE |
@@ -903,7 +903,7 @@ int nand_init(void) | |||
903 | unsigned char spare_buf[16]; | 903 | unsigned char spare_buf[16]; |
904 | 904 | ||
905 | if (initialized) return 0; | 905 | if (initialized) return 0; |
906 | 906 | ||
907 | mutex_init(&ata_mtx); | 907 | mutex_init(&ata_mtx); |
908 | 908 | ||
909 | /* Set GPIO direction for chip select & write protect */ | 909 | /* Set GPIO direction for chip select & write protect */ |
@@ -924,7 +924,7 @@ int nand_init(void) | |||
924 | 924 | ||
925 | memset(lpt_lookup, 0xff, lptbuf_size); | 925 | memset(lpt_lookup, 0xff, lptbuf_size); |
926 | memset(write_caches, 0xff, sizeof(write_caches)); | 926 | memset(write_caches, 0xff, sizeof(write_caches)); |
927 | 927 | ||
928 | write_caches_in_use = 0; | 928 | write_caches_in_use = 0; |
929 | 929 | ||
930 | /* Scan banks to build up block translation table */ | 930 | /* Scan banks to build up block translation table */ |
@@ -936,7 +936,7 @@ int nand_init(void) | |||
936 | nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, 0), | 936 | nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, 0), |
937 | SECTOR_SIZE, /* offset */ | 937 | SECTOR_SIZE, /* offset */ |
938 | 16, spare_buf); | 938 | 16, spare_buf); |
939 | 939 | ||
940 | int type = get_sector_type(spare_buf); | 940 | int type = get_sector_type(spare_buf); |
941 | 941 | ||
942 | #ifdef FTL_V2 | 942 | #ifdef FTL_V2 |
@@ -948,7 +948,7 @@ int nand_init(void) | |||
948 | nand_read_raw(bank, phys_segment_to_page_addr | 948 | nand_read_raw(bank, phys_segment_to_page_addr |
949 | (phys_segment, pages_per_segment - 1), | 949 | (phys_segment, pages_per_segment - 1), |
950 | SECTOR_SIZE, 16, spare_buf); | 950 | SECTOR_SIZE, 16, spare_buf); |
951 | 951 | ||
952 | if (get_sector_type(spare_buf) != 0xff) | 952 | if (get_sector_type(spare_buf) != 0xff) |
953 | { | 953 | { |
954 | type = SECTYPE_MAIN_DATA; | 954 | type = SECTYPE_MAIN_DATA; |
@@ -982,14 +982,14 @@ int nand_init(void) | |||
982 | } | 982 | } |
983 | break; | 983 | break; |
984 | } | 984 | } |
985 | 985 | ||
986 | case SECTYPE_MAIN_RANDOM_CACHE: | 986 | case SECTYPE_MAIN_RANDOM_CACHE: |
987 | { | 987 | { |
988 | /* Newly-written random page data (Main data area) */ | 988 | /* Newly-written random page data (Main data area) */ |
989 | read_random_writes_cache(bank, phys_segment); | 989 | read_random_writes_cache(bank, phys_segment); |
990 | break; | 990 | break; |
991 | } | 991 | } |
992 | 992 | ||
993 | case SECTYPE_MAIN_INPLACE_CACHE: | 993 | case SECTYPE_MAIN_INPLACE_CACHE: |
994 | { | 994 | { |
995 | /* Newly-written sequential page data (Main data area) */ | 995 | /* Newly-written sequential page data (Main data area) */ |
@@ -999,7 +999,7 @@ int nand_init(void) | |||
999 | } | 999 | } |
1000 | } | 1000 | } |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | initialized = true; | 1003 | initialized = true; |
1004 | 1004 | ||
1005 | return 0; | 1005 | return 0; |
@@ -1029,7 +1029,7 @@ int nand_num_drives(int first_drive) | |||
1029 | { | 1029 | { |
1030 | /* We don't care which logical drive number we have been assigned */ | 1030 | /* We don't care which logical drive number we have been assigned */ |
1031 | (void)first_drive; | 1031 | (void)first_drive; |
1032 | 1032 | ||
1033 | return 1; | 1033 | return 1; |
1034 | } | 1034 | } |
1035 | 1035 | ||