diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/ata-nand-telechips.c | 81 |
1 files changed, 54 insertions, 27 deletions
diff --git a/firmware/target/arm/ata-nand-telechips.c b/firmware/target/arm/ata-nand-telechips.c index 668c8a9d69..316780d417 100644 --- a/firmware/target/arm/ata-nand-telechips.c +++ b/firmware/target/arm/ata-nand-telechips.c | |||
@@ -184,11 +184,7 @@ static void nand_chip_select(int bank) | |||
184 | else | 184 | else |
185 | { | 185 | { |
186 | /* NFC chip select */ | 186 | /* NFC chip select */ |
187 | #ifdef USE_TCC_LPT | ||
188 | if (!(bank & 1)) | ||
189 | #else | ||
190 | if (bank & 1) | 187 | if (bank & 1) |
191 | #endif | ||
192 | { | 188 | { |
193 | NFC_CTRL &= ~NFC_CS0; | 189 | NFC_CTRL &= ~NFC_CS0; |
194 | NFC_CTRL |= NFC_CS1; | 190 | NFC_CTRL |= NFC_CS1; |
@@ -524,11 +520,44 @@ static bool nand_read_sector_of_logical_segment(int log_segment, int sector, | |||
524 | } | 520 | } |
525 | 521 | ||
526 | 522 | ||
523 | /* Miscellaneous helper functions */ | ||
524 | |||
525 | static inline char get_segment_type(char* spare_buf) | ||
526 | { | ||
527 | return spare_buf[OFF_SEGMENT_TYPE]; | ||
528 | } | ||
529 | |||
530 | static inline unsigned short get_log_segment_id(char* spare_buf) | ||
531 | { | ||
532 | return (spare_buf[OFF_LOG_SEG_HIBYTE] << 8) | | ||
533 | spare_buf[OFF_LOG_SEG_LOBYTE]; | ||
534 | } | ||
535 | |||
536 | static inline unsigned short get_cached_page_id(char* spare_buf) | ||
537 | { | ||
538 | return (spare_buf[OFF_CACHE_PAGE_HIBYTE] << 8) | | ||
539 | spare_buf[OFF_CACHE_PAGE_LOBYTE]; | ||
540 | } | ||
541 | |||
542 | |||
543 | |||
527 | #ifdef USE_TCC_LPT | 544 | #ifdef USE_TCC_LPT |
528 | 545 | ||
529 | /* Reading the LPT from NAND is not yet fully understood. This code is therefore | 546 | /* Reading the LPT from NAND is not yet fully understood. This code is therefore |
530 | not enabled by default, as it gives much worse results than the bank-scanning | 547 | not enabled by default, as it gives much worse results than the bank-scanning |
531 | approach currently used. */ | 548 | approach currently used. |
549 | |||
550 | The LPT is stored in a number of physical segments marked with type 0x12. | ||
551 | These are spread non-contiguously across the NAND, and are not stored in | ||
552 | sequential order. | ||
553 | |||
554 | The LPT data is stored in Sector 0 of the first <n> pages of each segment. | ||
555 | Each 32-bit value in sequence represents the physical location of a logical | ||
556 | segment. This is stored as (physical segment number * bank number). | ||
557 | |||
558 | NOTE: The bank numbers stored appear to be in reverse order to that required | ||
559 | by the nand_chip_select() function. The reason for this anomoly is unknown. | ||
560 | */ | ||
532 | 561 | ||
533 | static void read_lpt_block(int bank, int phys_segment) | 562 | static void read_lpt_block(int bank, int phys_segment) |
534 | { | 563 | { |
@@ -553,6 +582,10 @@ static void read_lpt_block(int bank, int phys_segment) | |||
553 | int first_bank = int_buf[0] / segments_per_bank; | 582 | int first_bank = int_buf[0] / segments_per_bank; |
554 | int first_phys_segment = int_buf[0] % segments_per_bank; | 583 | int first_phys_segment = int_buf[0] % segments_per_bank; |
555 | 584 | ||
585 | /* Reverse the stored bank number */ | ||
586 | if (total_banks > 1) | ||
587 | first_bank = (total_banks-1) - first_bank; | ||
588 | |||
556 | unsigned char spare_buf[16]; | 589 | unsigned char spare_buf[16]; |
557 | 590 | ||
558 | nand_read_raw(first_bank, | 591 | nand_read_raw(first_bank, |
@@ -560,23 +593,24 @@ static void read_lpt_block(int bank, int phys_segment) | |||
560 | SECTOR_SIZE, /* offset */ | 593 | SECTOR_SIZE, /* offset */ |
561 | 16, spare_buf); | 594 | 16, spare_buf); |
562 | 595 | ||
563 | int first_log_segment = (spare_buf[OFF_LOG_SEG_HIBYTE] << 8) | | 596 | int first_log_segment = get_log_segment_id(spare_buf); |
564 | spare_buf[OFF_LOG_SEG_LOBYTE]; | ||
565 | 597 | ||
566 | lpt_ptr = &lpt_lookup[first_log_segment]; | 598 | lpt_ptr = &lpt_lookup[first_log_segment]; |
567 | |||
568 | #if defined(BOOTLOADER) && 1 | ||
569 | printf("lpt @ %lx:%lx (ls:%lx)", | ||
570 | first_bank, first_phys_segment, first_log_segment); | ||
571 | #endif | ||
572 | } | 599 | } |
573 | 600 | ||
574 | while (cont && (i < SECTOR_SIZE/4)) | 601 | while (cont && (i < SECTOR_SIZE/4)) |
575 | { | 602 | { |
576 | if (int_buf[i] != 0xFFFFFFFF) | 603 | if (int_buf[i] != 0xFFFFFFFF) |
577 | { | 604 | { |
578 | lpt_ptr->bank = int_buf[i] / segments_per_bank; | 605 | int bank = int_buf[i] / segments_per_bank; |
579 | lpt_ptr->phys_segment = int_buf[i] % segments_per_bank; | 606 | int phys_segment = int_buf[i] % segments_per_bank; |
607 | |||
608 | /* Reverse the stored bank number */ | ||
609 | if (total_banks > 1) | ||
610 | bank = (total_banks-1) - bank; | ||
611 | |||
612 | lpt_ptr->bank = bank; | ||
613 | lpt_ptr->phys_segment = phys_segment; | ||
580 | 614 | ||
581 | lpt_ptr++; | 615 | lpt_ptr++; |
582 | i++; | 616 | i++; |
@@ -612,11 +646,8 @@ static void read_write_cache_segment(int bank, int phys_segment) | |||
612 | SECTOR_SIZE, /* offset to first sector's spare */ | 646 | SECTOR_SIZE, /* offset to first sector's spare */ |
613 | 16, spare_buf); | 647 | 16, spare_buf); |
614 | 648 | ||
615 | cached_page = (spare_buf[OFF_CACHE_PAGE_HIBYTE] << 8) | | 649 | cached_page = get_cached_page_id(spare_buf); |
616 | spare_buf[OFF_CACHE_PAGE_LOBYTE]; | 650 | log_segment = get_log_segment_id(spare_buf); |
617 | |||
618 | log_segment = (spare_buf[OFF_LOG_SEG_HIBYTE] << 8) | | ||
619 | spare_buf[OFF_LOG_SEG_LOBYTE]; | ||
620 | 651 | ||
621 | if (cached_page != 0xFFFF) | 652 | if (cached_page != 0xFFFF) |
622 | { | 653 | { |
@@ -775,7 +806,7 @@ int ata_init(void) | |||
775 | SECTOR_SIZE, /* offset */ | 806 | SECTOR_SIZE, /* offset */ |
776 | 16, spare_buf); | 807 | 16, spare_buf); |
777 | 808 | ||
778 | switch (spare_buf[4]) /* block type */ | 809 | switch (get_segment_type(spare_buf)) |
779 | { | 810 | { |
780 | #ifdef USE_TCC_LPT | 811 | #ifdef USE_TCC_LPT |
781 | case SEGMENT_MAIN_LPT: | 812 | case SEGMENT_MAIN_LPT: |
@@ -788,9 +819,7 @@ int ata_init(void) | |||
788 | case SEGMENT_MAIN_DATA2: | 819 | case SEGMENT_MAIN_DATA2: |
789 | { | 820 | { |
790 | /* Main data area segment */ | 821 | /* Main data area segment */ |
791 | unsigned short log_segment | 822 | unsigned short log_segment = get_log_segment_id(spare_buf); |
792 | = (spare_buf[OFF_LOG_SEG_HIBYTE] << 8) | | ||
793 | spare_buf[OFF_LOG_SEG_LOBYTE]; | ||
794 | 823 | ||
795 | if (log_segment < MAX_SEGMENTS) | 824 | if (log_segment < MAX_SEGMENTS) |
796 | { | 825 | { |
@@ -822,14 +851,12 @@ int ata_init(void) | |||
822 | SECTOR_SIZE, /* offset */ | 851 | SECTOR_SIZE, /* offset */ |
823 | 16, spare_buf); | 852 | 16, spare_buf); |
824 | 853 | ||
825 | switch (spare_buf[4]) /* block type */ | 854 | switch (get_segment_type(spare_buf)) /* block type */ |
826 | { | 855 | { |
827 | case SEGMENT_MAIN_DATA1: | 856 | case SEGMENT_MAIN_DATA1: |
828 | { | 857 | { |
829 | /* Main data area segment */ | 858 | /* Main data area segment */ |
830 | unsigned short log_segment | 859 | unsigned short log_segment = get_log_segment_id(spare_buf); |
831 | = (spare_buf[OFF_LOG_SEG_HIBYTE] << 8) | | ||
832 | spare_buf[OFF_LOG_SEG_LOBYTE]; | ||
833 | 860 | ||
834 | if (log_segment < MAX_SEGMENTS) | 861 | if (log_segment < MAX_SEGMENTS) |
835 | { | 862 | { |