summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/ata-e200.c154
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/hotswap-target.h2
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
420static void sd_select_bank(unsigned char bank) 420static 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 */
591card_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)
569int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, 602int 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
624ata_read_error: 666ata_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
749ata_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
809int ata_init(void) 862int 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
25typedef struct 25typedef 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 */