diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/ata-e200.c | 154 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/hotswap-target.h | 2 |
2 files changed, 107 insertions, 49 deletions
diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c index fea6773ac9..ca8cc1b3d9 100644 --- a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #define REG_12 (*(volatile unsigned int *)(0x70008244)) | 47 | #define REG_12 (*(volatile unsigned int *)(0x70008244)) |
48 | #define DATA_REG (*(volatile unsigned int *)(0x70008280)) | 48 | #define DATA_REG (*(volatile unsigned int *)(0x70008280)) |
49 | 49 | ||
50 | /* STATUS_REG bits */ | ||
50 | #define DATA_DONE (1 << 12) | 51 | #define DATA_DONE (1 << 12) |
51 | #define CMD_DONE (1 << 13) | 52 | #define CMD_DONE (1 << 13) |
52 | #define ERROR_BITS (0x3f) | 53 | #define ERROR_BITS (0x3f) |
@@ -54,6 +55,9 @@ | |||
54 | #define FIFO_FULL (1 << 7) | 55 | #define FIFO_FULL (1 << 7) |
55 | #define FIFO_EMPTY (1 << 6) | 56 | #define FIFO_EMPTY (1 << 6) |
56 | 57 | ||
58 | #define CMD_OK 0x0 /* Command was successful */ | ||
59 | #define CMD_ERROR_2 0x2 /* Seen when SD card is not inserted */ | ||
60 | |||
57 | /* SD States */ | 61 | /* SD States */ |
58 | #define IDLE 0 | 62 | #define IDLE 0 |
59 | #define READY 1 | 63 | #define READY 1 |
@@ -168,22 +172,18 @@ static bool sd_command(unsigned int cmd, unsigned long arg1, | |||
168 | int i, words; /* Number of 16 bit words to read from RESPONSE_REG */ | 172 | int i, words; /* Number of 16 bit words to read from RESPONSE_REG */ |
169 | unsigned int data[9]; | 173 | unsigned int data[9]; |
170 | 174 | ||
171 | while (1) | 175 | CMD_REG0 = cmd; |
172 | { | 176 | CMD_REG1 = (unsigned int)((arg1 & 0xffff0000) >> 16); |
173 | CMD_REG0 = cmd; | 177 | CMD_REG2 = (unsigned int)((arg1 & 0xffff)); |
174 | CMD_REG1 = (unsigned int)((arg1 & 0xffff0000) >> 16); | 178 | UNKNOWN = type; |
175 | CMD_REG2 = (unsigned int)((arg1 & 0xffff)); | ||
176 | UNKNOWN = type; | ||
177 | 179 | ||
178 | sd_poll_status(CMD_DONE, 100000, EC_COMMAND | DO_PANIC); | 180 | sd_poll_status(CMD_DONE, 100000, EC_COMMAND | DO_PANIC); |
179 | 181 | ||
180 | if ((STATUS_REG & ERROR_BITS) == 0) | 182 | if ((STATUS_REG & ERROR_BITS) != CMD_OK) |
181 | break; | 183 | return false; /* Error sending command */ |
182 | |||
183 | priority_yield(); | ||
184 | } | ||
185 | 184 | ||
186 | if (cmd == GO_IDLE_STATE) return true; /* no response here */ | 185 | if (cmd == GO_IDLE_STATE) |
186 | return true; /* no response here */ | ||
187 | 187 | ||
188 | words = (type == 2) ? 9 : 3; | 188 | words = (type == 2) ? 9 : 3; |
189 | 189 | ||
@@ -417,7 +417,7 @@ static inline void copy_write_sectors(const unsigned char* buf) | |||
417 | } while (buf < bufend); /* tail loop is faster */ | 417 | } while (buf < bufend); /* tail loop is faster */ |
418 | } | 418 | } |
419 | 419 | ||
420 | static void sd_select_bank(unsigned char bank) | 420 | static bool sd_select_bank(unsigned char bank) |
421 | { | 421 | { |
422 | unsigned int response; | 422 | unsigned int response; |
423 | unsigned char card_data[512]; | 423 | unsigned char card_data[512]; |
@@ -428,7 +428,10 @@ static void sd_select_bank(unsigned char bank) | |||
428 | sd_wait_for_state(TRAN, EC_TRAN_SEL_BANK); | 428 | sd_wait_for_state(TRAN, EC_TRAN_SEL_BANK); |
429 | BLOCK_SIZE_REG = 512; | 429 | BLOCK_SIZE_REG = 512; |
430 | BLOCK_COUNT_REG = 1; | 430 | BLOCK_COUNT_REG = 1; |
431 | sd_command(35, 0, &response, 0x1c0d); /* CMD35 is vendor specific */ | 431 | |
432 | if (!sd_command(35, 0, &response, 0x1c0d)) /* CMD35 is vendor specific */ | ||
433 | return false; | ||
434 | |||
432 | SD_STATE_REG = PRG; | 435 | SD_STATE_REG = PRG; |
433 | 436 | ||
434 | card_data[0] = bank; | 437 | card_data[0] = bank; |
@@ -448,6 +451,8 @@ static void sd_select_bank(unsigned char bank) | |||
448 | sd_poll_status(DATA_DONE, 10000, EC_FIFO_SEL_BANK_DONE | DO_PANIC); | 451 | sd_poll_status(DATA_DONE, 10000, EC_FIFO_SEL_BANK_DONE | DO_PANIC); |
449 | 452 | ||
450 | currcard->current_bank = bank; | 453 | currcard->current_bank = bank; |
454 | |||
455 | return true; | ||
451 | } | 456 | } |
452 | 457 | ||
453 | /* lock must already be aquired */ | 458 | /* lock must already be aquired */ |
@@ -508,18 +513,30 @@ static void sd_init_device(int card_no) | |||
508 | SD_STATE_REG = TRAN; | 513 | SD_STATE_REG = TRAN; |
509 | 514 | ||
510 | REG_5 = 0xf; | 515 | REG_5 = 0xf; |
511 | sd_command(GO_IDLE_STATE, 0, &dummy, 256); | 516 | |
517 | if (!sd_command(GO_IDLE_STATE, 0, &dummy, 256)) | ||
518 | goto card_init_error; | ||
519 | |||
512 | check_time[EC_POWER_UP] = USEC_TIMER; | 520 | check_time[EC_POWER_UP] = USEC_TIMER; |
513 | while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */ | 521 | while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */ |
514 | { | 522 | { |
515 | sd_command(APP_CMD, currcard->rca, &dummy, 1); | 523 | if (!sd_command(APP_CMD, currcard->rca, &dummy, 1)) |
516 | sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3); | 524 | goto card_init_error; |
525 | |||
526 | if (!sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3)) | ||
527 | goto card_init_error; | ||
528 | |||
517 | sd_check_timeout(5000000, EC_POWER_UP); | 529 | sd_check_timeout(5000000, EC_POWER_UP); |
518 | } | 530 | } |
519 | 531 | ||
520 | sd_command(ALL_SEND_CID, 0, currcard->cid, 2); | 532 | if (!sd_command(ALL_SEND_CID, 0, currcard->cid, 2)) |
521 | sd_command(SEND_RELATIVE_ADDR, 0, &currcard->rca, 1); | 533 | goto card_init_error; |
522 | sd_command(SEND_CSD, currcard->rca, currcard->csd, 2); | 534 | |
535 | if (!sd_command(SEND_RELATIVE_ADDR, 0, &currcard->rca, 1)) | ||
536 | goto card_init_error; | ||
537 | |||
538 | if (!sd_command(SEND_CSD, currcard->rca, currcard->csd, 2)) | ||
539 | goto card_init_error; | ||
523 | 540 | ||
524 | /* These calculations come from the Sandisk SD card product manual */ | 541 | /* These calculations come from the Sandisk SD card product manual */ |
525 | c_size = ((currcard->csd[2] & 0x3ff) << 2) + (currcard->csd[1] >> 30) + 1; | 542 | c_size = ((currcard->csd[2] & 0x3ff) << 2) + (currcard->csd[1] >> 30) + 1; |
@@ -531,10 +548,18 @@ static void sd_init_device(int card_no) | |||
531 | 548 | ||
532 | REG_1 = 0; | 549 | REG_1 = 0; |
533 | 550 | ||
534 | sd_command(SELECT_CARD, currcard->rca , &dummy, 129); | 551 | if (!sd_command(SELECT_CARD, currcard->rca, &dummy, 129)) |
535 | sd_command(APP_CMD, currcard->rca , &dummy, 1); | 552 | goto card_init_error; |
536 | sd_command(SET_BUS_WIDTH, currcard->rca | 2 , &dummy, 1); /* 4 bit */ | 553 | |
537 | sd_command(SET_BLOCKLEN, currcard->block_size, &dummy, 1); | 554 | if (!sd_command(APP_CMD, currcard->rca, &dummy, 1)) |
555 | goto card_init_error; | ||
556 | |||
557 | if (!sd_command(SET_BUS_WIDTH, currcard->rca | 2, &dummy, 1)) /* 4 bit */ | ||
558 | goto card_init_error; | ||
559 | |||
560 | if (!sd_command(SET_BLOCKLEN, currcard->block_size, &dummy, 1)) | ||
561 | goto card_init_error; | ||
562 | |||
538 | BLOCK_SIZE_REG = currcard->block_size; | 563 | BLOCK_SIZE_REG = currcard->block_size; |
539 | 564 | ||
540 | /* If this card is > 4Gb, then we need to enable bank switching */ | 565 | /* If this card is > 4Gb, then we need to enable bank switching */ |
@@ -542,7 +567,10 @@ static void sd_init_device(int card_no) | |||
542 | { | 567 | { |
543 | SD_STATE_REG = TRAN; | 568 | SD_STATE_REG = TRAN; |
544 | BLOCK_COUNT_REG = 1; | 569 | BLOCK_COUNT_REG = 1; |
545 | sd_command(SWITCH_FUNC, 0x80ffffef, &dummy, 0x1c05); | 570 | |
571 | if (!sd_command(SWITCH_FUNC, 0x80ffffef, &dummy, 0x1c05)) | ||
572 | goto card_init_error; | ||
573 | |||
546 | /* Read 512 bytes from the card. | 574 | /* Read 512 bytes from the card. |
547 | The first 512 bits contain the status information | 575 | The first 512 bits contain the status information |
548 | TODO: Do something useful with this! */ | 576 | TODO: Do something useful with this! */ |
@@ -556,7 +584,12 @@ static void sd_init_device(int card_no) | |||
556 | } | 584 | } |
557 | } | 585 | } |
558 | 586 | ||
559 | currcard->initialized = true; | 587 | currcard->initialized = 1; |
588 | return; | ||
589 | |||
590 | /* Card failed to initialize so disable it */ | ||
591 | card_init_error: | ||
592 | currcard->initialized = -1; | ||
560 | } | 593 | } |
561 | 594 | ||
562 | /* API Functions */ | 595 | /* API Functions */ |
@@ -569,7 +602,7 @@ void ata_led(bool onoff) | |||
569 | int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | 602 | int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, |
570 | void* inbuf) | 603 | void* inbuf) |
571 | { | 604 | { |
572 | int ret = 0; | 605 | int ret = -9; |
573 | unsigned char *buf, *buf_end; | 606 | unsigned char *buf, *buf_end; |
574 | unsigned int dummy; | 607 | unsigned int dummy; |
575 | int bank; | 608 | int bank; |
@@ -581,27 +614,32 @@ int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | |||
581 | ata_led(true); | 614 | ata_led(true); |
582 | 615 | ||
583 | if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0) | 616 | if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0) |
584 | { | ||
585 | /* no external sd-card inserted */ | 617 | /* no external sd-card inserted */ |
586 | ret = -9; | ||
587 | goto ata_read_error; | 618 | goto ata_read_error; |
588 | } | ||
589 | 619 | ||
590 | if (&card_info[drive] != currcard || !card_info[drive].initialized) | 620 | if (&card_info[drive] != currcard || card_info[drive].initialized == 0) |
621 | { | ||
591 | sd_init_device(drive); | 622 | sd_init_device(drive); |
592 | 623 | ||
624 | if (card_info[drive].initialized < 0) | ||
625 | goto ata_read_error; | ||
626 | } | ||
627 | |||
593 | last_disk_activity = current_tick; | 628 | last_disk_activity = current_tick; |
594 | 629 | ||
595 | bank = start / BLOCKS_PER_BANK; | 630 | bank = start / BLOCKS_PER_BANK; |
596 | 631 | ||
597 | if (currcard->current_bank != bank) | 632 | if (currcard->current_bank != bank && !sd_select_bank(bank)) |
598 | sd_select_bank(bank); | 633 | goto ata_read_error; |
599 | 634 | ||
600 | start -= bank * BLOCKS_PER_BANK; | 635 | start -= bank * BLOCKS_PER_BANK; |
601 | 636 | ||
602 | sd_wait_for_state(TRAN, EC_TRAN_READ_ENTRY); | 637 | sd_wait_for_state(TRAN, EC_TRAN_READ_ENTRY); |
603 | BLOCK_COUNT_REG = incount; | 638 | BLOCK_COUNT_REG = incount; |
604 | sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, &dummy, 0x1c25); | 639 | |
640 | if (!sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, &dummy, 0x1c25)) | ||
641 | goto ata_read_error; | ||
642 | |||
605 | /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ | 643 | /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ |
606 | 644 | ||
607 | buf_end = (unsigned char *)inbuf + incount * currcard->block_size; | 645 | buf_end = (unsigned char *)inbuf + incount * currcard->block_size; |
@@ -618,9 +656,13 @@ int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | |||
618 | #if 0 | 656 | #if 0 |
619 | udelay(75); | 657 | udelay(75); |
620 | #endif | 658 | #endif |
621 | sd_command(STOP_TRANSMISSION, 0, &dummy, 1); | 659 | if (!sd_command(STOP_TRANSMISSION, 0, &dummy, 1)) |
660 | goto ata_read_error; | ||
661 | |||
622 | sd_wait_for_state(TRAN, EC_TRAN_READ_EXIT); | 662 | sd_wait_for_state(TRAN, EC_TRAN_READ_EXIT); |
623 | 663 | ||
664 | ret = 0; | ||
665 | |||
624 | ata_read_error: | 666 | ata_read_error: |
625 | ata_led(false); | 667 | ata_led(false); |
626 | 668 | ||
@@ -637,7 +679,7 @@ int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, | |||
637 | to improve performance */ | 679 | to improve performance */ |
638 | unsigned int response; | 680 | unsigned int response; |
639 | void const* buf, *buf_end; | 681 | void const* buf, *buf_end; |
640 | int ret = 0; | 682 | int ret = -9; |
641 | int bank; | 683 | int bank; |
642 | 684 | ||
643 | spinlock_lock(&sd_mtx); | 685 | spinlock_lock(&sd_mtx); |
@@ -645,26 +687,33 @@ int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, | |||
645 | ata_led(true); | 687 | ata_led(true); |
646 | 688 | ||
647 | if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0) | 689 | if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0) |
648 | { | ||
649 | /* no external sd-card inserted */ | 690 | /* no external sd-card inserted */ |
650 | ret = -9; | 691 | goto ata_write_error; |
651 | goto error; | ||
652 | } | ||
653 | 692 | ||
654 | if (&card_info[drive] != currcard || !card_info[drive].initialized) | 693 | if (&card_info[drive] != currcard || card_info[drive].initialized == 0) |
694 | { | ||
655 | sd_init_device(drive); | 695 | sd_init_device(drive); |
656 | 696 | ||
697 | if (card_info[drive].initialized < 0) | ||
698 | goto ata_write_error; | ||
699 | } | ||
700 | |||
657 | bank = start / BLOCKS_PER_BANK; | 701 | bank = start / BLOCKS_PER_BANK; |
658 | 702 | ||
659 | if (currcard->current_bank != bank) | 703 | if (currcard->current_bank != bank && !sd_select_bank(bank)) |
660 | sd_select_bank(bank); | 704 | goto ata_write_error; |
661 | 705 | ||
662 | start -= bank * BLOCKS_PER_BANK; | 706 | start -= bank * BLOCKS_PER_BANK; |
663 | 707 | ||
664 | check_time[EC_WRITE_TIMEOUT] = USEC_TIMER; | 708 | check_time[EC_WRITE_TIMEOUT] = USEC_TIMER; |
665 | sd_wait_for_state(TRAN, EC_TRAN_WRITE_ENTRY); | 709 | sd_wait_for_state(TRAN, EC_TRAN_WRITE_ENTRY); |
666 | BLOCK_COUNT_REG = count; | 710 | BLOCK_COUNT_REG = count; |
667 | sd_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, &response, 0x1c2d); | 711 | |
712 | if (!sd_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, | ||
713 | &response, 0x1c2d)) | ||
714 | { | ||
715 | goto ata_write_error; | ||
716 | } | ||
668 | 717 | ||
669 | buf_end = outbuf + count * currcard->block_size; | 718 | buf_end = outbuf + count * currcard->block_size; |
670 | for (buf = outbuf; buf < buf_end; buf += 2 * FIFO_SIZE) | 719 | for (buf = outbuf; buf < buf_end; buf += 2 * FIFO_SIZE) |
@@ -690,10 +739,14 @@ int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, | |||
690 | sd_poll_status(DATA_DONE, 0x80000, EC_FIFO_WR_DONE | DO_PANIC); | 739 | sd_poll_status(DATA_DONE, 0x80000, EC_FIFO_WR_DONE | DO_PANIC); |
691 | sd_check_timeout(0x80000, EC_WRITE_TIMEOUT); | 740 | sd_check_timeout(0x80000, EC_WRITE_TIMEOUT); |
692 | 741 | ||
693 | sd_command(STOP_TRANSMISSION, 0, &response, 1); | 742 | if (!sd_command(STOP_TRANSMISSION, 0, &response, 1)) |
743 | goto ata_write_error; | ||
744 | |||
694 | sd_wait_for_state(TRAN, EC_TRAN_WRITE_EXIT); | 745 | sd_wait_for_state(TRAN, EC_TRAN_WRITE_EXIT); |
695 | 746 | ||
696 | error: | 747 | ret = 0; |
748 | |||
749 | ata_write_error: | ||
697 | ata_led(false); | 750 | ata_led(false); |
698 | spinlock_unlock(&sd_mtx); | 751 | spinlock_unlock(&sd_mtx); |
699 | 752 | ||
@@ -808,6 +861,8 @@ void ata_enable(bool on) | |||
808 | 861 | ||
809 | int ata_init(void) | 862 | int ata_init(void) |
810 | { | 863 | { |
864 | int ret = 0; | ||
865 | |||
811 | ata_led(false); | 866 | ata_led(false); |
812 | 867 | ||
813 | /* NOTE: This init isn't dual core safe */ | 868 | /* NOTE: This init isn't dual core safe */ |
@@ -837,6 +892,9 @@ int ata_init(void) | |||
837 | 892 | ||
838 | sd_init_device(0); | 893 | sd_init_device(0); |
839 | 894 | ||
895 | if (currcard->initialized <= 0) | ||
896 | ret = -1; | ||
897 | |||
840 | queue_init(&sd_queue, true); | 898 | queue_init(&sd_queue, true); |
841 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), | 899 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), |
842 | sd_thread_name IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU, false)); | 900 | sd_thread_name IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU, false)); |
@@ -856,7 +914,7 @@ int ata_init(void) | |||
856 | spinlock_unlock(&sd_mtx); | 914 | spinlock_unlock(&sd_mtx); |
857 | } | 915 | } |
858 | 916 | ||
859 | return 0; | 917 | return ret; |
860 | } | 918 | } |
861 | 919 | ||
862 | /* move the sd-card info to mmc struct */ | 920 | /* move the sd-card info to mmc struct */ |
diff --git a/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h b/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h index 95cb26d2f7..cab2afe163 100644 --- a/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h +++ b/firmware/target/arm/sandisk/sansa-e200/hotswap-target.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | typedef struct | 25 | typedef struct |
26 | { | 26 | { |
27 | bool initialized; | 27 | int initialized; |
28 | 28 | ||
29 | unsigned int ocr; /* OCR register */ | 29 | unsigned int ocr; /* OCR register */ |
30 | unsigned int csd[4]; /* CSD register */ | 30 | unsigned int csd[4]; /* CSD register */ |