summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sparmann <theseven@gmx.net>2014-07-18 23:15:21 +0200
committerMarcin Bukat <marcin.bukat@gmail.com>2014-09-22 10:16:35 +0200
commit582035c5cbd4f04588615d2f9b91b2f97c80f949 (patch)
tree0cb45355d380df40acd7739e462b877b8ce5f202
parent3e131abe27840bf7dd43ea729b4b91636cee33db (diff)
downloadrockbox-582035c5cbd4f04588615d2f9b91b2f97c80f949.tar.gz
rockbox-582035c5cbd4f04588615d2f9b91b2f97c80f949.zip
iPod Classic: Fix several ATA driver bugs.
This improves compatibility with various HDD and CF/SD card mods. It should also reduce power consumption while the drive is powered down. Change-Id: I4b22c59b5d9ae2daea2ec5892e348e7e1934ca3e Reviewed-on: http://gerrit.rockbox.org/897 Tested: Franklin Wei <frankhwei536@gmail.com> Tested: Nial Shui <nialv7@gmail.com> Tested: Michael Sparmann <theseven@gmx.net> Reviewed-by: Marcin Bukat <marcin.bukat@gmail.com>
-rwxr-xr-x[-rw-r--r--]firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c159
1 files changed, 108 insertions, 51 deletions
diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c
index 0fd74787d1..955a33a595 100644..100755
--- a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c
@@ -78,18 +78,31 @@ uint64_t ata_virtual_sectors;
78uint32_t ata_last_offset; 78uint32_t ata_last_offset;
79uint64_t ata_last_phys; 79uint64_t ata_last_phys;
80 80
81static int ata_reset(void);
82static void ata_power_down(void);
81int ata_rw_sectors_internal(uint64_t sector, uint32_t count, 83int ata_rw_sectors_internal(uint64_t sector, uint32_t count,
82 void* buffer, bool write); 84 void* buffer, bool write);
83 85
84int ata_bbt_read_sectors(uint32_t sector, uint32_t count, void* buffer) 86int ata_bbt_read_sectors(uint32_t sector, uint32_t count, void* buffer)
85{ 87{
86 if (ata_last_phys != sector - 1 && ata_last_phys > sector - 64) ata_soft_reset(); 88 if (ata_last_phys != sector - 1 && ata_last_phys > sector - 64) ata_reset();
87 int rc = ata_rw_sectors_internal(sector, count, buffer, false); 89 int rc = ata_rw_sectors_internal(sector, count, buffer, false);
88 if (rc) rc = ata_rw_sectors_internal(sector, count, buffer, false); 90 if (rc) rc = ata_rw_sectors_internal(sector, count, buffer, false);
91 if (rc)
92 {
93 ata_reset();
94 rc = ata_rw_sectors_internal(sector, count, buffer, false);
95 }
96 if (rc)
97 {
98 ata_power_down();
99 sleep(HZ * 10);
100 rc = ata_rw_sectors_internal(sector, count, buffer, false);
101 }
89 ata_last_phys = sector + count - 1; 102 ata_last_phys = sector + count - 1;
90 ata_last_offset = 0; 103 ata_last_offset = 0;
91 if (IS_ERR(rc)) 104 if (IS_ERR(rc))
92 panicf("ATA: Error %08X while reading BBT (sector %d, count %d)\n", 105 panicf("ATA: Error %08X while reading BBT (sector %d, count %d)",
93 (unsigned int)rc, (unsigned int)sector, (unsigned int)count); 106 (unsigned int)rc, (unsigned int)sector, (unsigned int)count);
94 return rc; 107 return rc;
95} 108}
@@ -486,20 +499,20 @@ static int ceata_rw_multiple_block(bool write, void* buf, uint32_t count, long t
486 | SDCI_CMD_CMD_TYPE_ADTC | cmdtype | responsetype 499 | SDCI_CMD_CMD_TYPE_ADTC | cmdtype | responsetype
487 | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, 500 | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR,
488 direction | MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT(count), 501 direction | MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT(count),
489 NULL, CEATA_COMMAND_TIMEOUT), 4, 0); 502 NULL, CEATA_COMMAND_TIMEOUT), 3, 0);
490 if (write) SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX; 503 if (write) SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX;
491 if (semaphore_wait(&mmc_wakeup, timeout) == OBJ_WAIT_TIMEDOUT) 504 if (semaphore_wait(&mmc_wakeup, timeout) == OBJ_WAIT_TIMEDOUT)
492 { 505 {
493 PASS_RC(ceata_cancel_command(), 4, 1); 506 PASS_RC(ceata_cancel_command(), 3, 1);
494 RET_ERR(2); 507 RET_ERR(2);
495 } 508 }
496 PASS_RC(mmc_dsta_check_data_success(), 4, 3); 509 PASS_RC(mmc_dsta_check_data_success(), 3, 3);
497 if (semaphore_wait(&mmc_comp_wakeup, timeout) == OBJ_WAIT_TIMEDOUT) 510 if (semaphore_wait(&mmc_comp_wakeup, timeout) == OBJ_WAIT_TIMEDOUT)
498 { 511 {
499 PASS_RC(ceata_cancel_command(), 4, 4); 512 PASS_RC(ceata_cancel_command(), 3, 4);
500 RET_ERR(4); 513 RET_ERR(5);
501 } 514 }
502 PASS_RC(ceata_check_error(), 4, 5); 515 PASS_RC(ceata_check_error(), 3, 6);
503 return 0; 516 return 0;
504} 517}
505 518
@@ -540,23 +553,42 @@ bool ata_disk_is_active(void)
540 553
541static int ata_set_feature(uint32_t feature, uint32_t param) 554static int ata_set_feature(uint32_t feature, uint32_t param)
542{ 555{
543 PASS_RC(ata_wait_for_rdy(500000), 1, 0); 556 if (ceata)
544 ata_write_cbr(&ATA_PIO_DVR, 0); 557 {
545 ata_write_cbr(&ATA_PIO_FED, 3); 558 memset(ceata_taskfile, 0, 16);
546 ata_write_cbr(&ATA_PIO_SCR, param); 559 ceata_taskfile[0x1] = feature;
547 ata_write_cbr(&ATA_PIO_CSD, feature); 560 ceata_taskfile[0x2] = param;
548 PASS_RC(ata_wait_for_rdy(500000), 1, 1); 561 ceata_taskfile[0xf] = 0xef;
562 PASS_RC(ceata_wait_idle(), 2, 0);
563 PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1);
564 PASS_RC(ceata_wait_idle(), 2, 2);
565 }
566 else
567 {
568 PASS_RC(ata_wait_for_rdy(2000000), 2, 0);
569 ata_write_cbr(&ATA_PIO_DVR, 0);
570 ata_write_cbr(&ATA_PIO_FED, feature);
571 ata_write_cbr(&ATA_PIO_SCR, param);
572 ata_write_cbr(&ATA_PIO_CSD, 0xef);
573 PASS_RC(ata_wait_for_rdy(2000000), 2, 1);
574 }
549 return 0; 575 return 0;
550} 576}
551 577
552static int ata_power_up(void) 578static int ata_power_up(void)
553{ 579{
554 ata_set_active(); 580 ata_set_active();
555 if (ata_powered) return 0;
556 ide_power_enable(true); 581 ide_power_enable(true);
557 long spinup_start = current_tick; 582 long spinup_start = current_tick;
558 if (ceata) 583 if (ceata)
559 { 584 {
585 ata_lba48 = true;
586 ata_dma = true;
587 PCON(8) = 0x33333333;
588 PCON(9) = 0x00000033;
589 PCON(11) |= 0xf;
590 *((uint32_t volatile*)0x38a00000) = 0;
591 *((uint32_t volatile*)0x38700000) = 0;
560 PWRCON(0) &= ~(1 << 9); 592 PWRCON(0) &= ~(1 << 9);
561 SDCI_RESET = 0xa5; 593 SDCI_RESET = 0xa5;
562 sleep(HZ / 100); 594 sleep(HZ / 100);
@@ -567,15 +599,19 @@ static int ata_power_up(void)
567 SDCI_CDIV = SDCI_CDIV_CLKDIV(260); 599 SDCI_CDIV = SDCI_CDIV_CLKDIV(260);
568 *((uint32_t volatile*)0x3cf00200) = 0xb000f; 600 *((uint32_t volatile*)0x3cf00200) = 0xb000f;
569 SDCI_IRQ_MASK = SDCI_IRQ_MASK_MASK_DAT_DONE_INT | SDCI_IRQ_MASK_MASK_IOCARD_IRQ_INT; 601 SDCI_IRQ_MASK = SDCI_IRQ_MASK_MASK_DAT_DONE_INT | SDCI_IRQ_MASK_MASK_IOCARD_IRQ_INT;
570 PASS_RC(mmc_init(), 2, 0); 602 PASS_RC(mmc_init(), 3, 0);
571 SDCI_CDIV = SDCI_CDIV_CLKDIV(4); 603 SDCI_CDIV = SDCI_CDIV_CLKDIV(4);
572 sleep(HZ / 100); 604 sleep(HZ / 100);
573 PASS_RC(ceata_init(8), 2, 1); 605 PASS_RC(ceata_init(8), 3, 1);
574 PASS_RC(ata_identify(ata_identify_data), 2, 2); 606 PASS_RC(ata_identify(ata_identify_data), 3, 2);
575 dma_mode = 0x44; 607 dma_mode = 0x44;
576 } 608 }
577 else 609 else
578 { 610 {
611 PCON(7) = 0x44444444;
612 PCON(8) = 0x44444444;
613 PCON(9) = 0x44444444;
614 PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
579 PWRCON(0) &= ~(1 << 5); 615 PWRCON(0) &= ~(1 << 5);
580 ATA_CFG = BIT(0); 616 ATA_CFG = BIT(0);
581 sleep(HZ / 100); 617 sleep(HZ / 100);
@@ -591,7 +627,7 @@ static int ata_power_up(void)
591 ATA_PIO_LHR = 0; 627 ATA_PIO_LHR = 0;
592 if (!ata_swap) ATA_CFG = BIT(6); 628 if (!ata_swap) ATA_CFG = BIT(6);
593 while (!(ATA_PIO_READY & BIT(1))) yield(); 629 while (!(ATA_PIO_READY & BIT(1))) yield();
594 PASS_RC(ata_identify(ata_identify_data), 2, 0); 630 PASS_RC(ata_identify(ata_identify_data), 3, 3);
595 uint32_t piotime = 0x11f3; 631 uint32_t piotime = 0x11f3;
596 uint32_t mdmatime = 0x1c175; 632 uint32_t mdmatime = 0x1c175;
597 uint32_t udmatime = 0x5071152; 633 uint32_t udmatime = 0x5071152;
@@ -648,14 +684,15 @@ static int ata_power_up(void)
648 } 684 }
649 ata_dma = param ? true : false; 685 ata_dma = param ? true : false;
650 dma_mode = param; 686 dma_mode = param;
651 PASS_RC(ata_set_feature(0xef, param), 2, 1); 687 PASS_RC(ata_set_feature(0x03, param), 3, 4);
652 if (ata_identify_data[82] & BIT(5)) PASS_RC(ata_set_feature(0x02, 0), 2, 2);
653 if (ata_identify_data[82] & BIT(6)) PASS_RC(ata_set_feature(0x55, 0), 2, 3);
654 ATA_PIO_TIME = piotime; 688 ATA_PIO_TIME = piotime;
655 ATA_MDMA_TIME = mdmatime; 689 ATA_MDMA_TIME = mdmatime;
656 ATA_UDMA_TIME = udmatime; 690 ATA_UDMA_TIME = udmatime;
657 } 691 }
658 spinup_time = current_tick - spinup_start; 692 spinup_time = current_tick - spinup_start;
693 if (ata_identify_data[82] & BIT(5))
694 PASS_RC(ata_set_feature(ata_bbt ? 0x82 : 0x02, 0), 3, 5);
695 if (ata_identify_data[82] & BIT(6)) PASS_RC(ata_set_feature(0xaa, 0), 3, 6);
659 if (ata_lba48) 696 if (ata_lba48)
660 ata_total_sectors = ata_identify_data[100] 697 ata_total_sectors = ata_identify_data[100]
661 | (((uint64_t)ata_identify_data[101]) << 16) 698 | (((uint64_t)ata_identify_data[101]) << 16)
@@ -678,6 +715,7 @@ static void ata_power_down(void)
678 ceata_taskfile[0xf] = 0xe0; 715 ceata_taskfile[0xf] = 0xe0;
679 ceata_wait_idle(); 716 ceata_wait_idle();
680 ceata_write_multiple_register(0, ceata_taskfile, 16); 717 ceata_write_multiple_register(0, ceata_taskfile, 16);
718 ceata_wait_idle();
681 sleep(HZ); 719 sleep(HZ);
682 PWRCON(0) |= (1 << 9); 720 PWRCON(0) |= (1 << 9);
683 } 721 }
@@ -692,6 +730,11 @@ static void ata_power_down(void)
692 while (!(ATA_CONTROL & BIT(1))) yield(); 730 while (!(ATA_CONTROL & BIT(1))) yield();
693 PWRCON(0) |= (1 << 5); 731 PWRCON(0) |= (1 << 5);
694 } 732 }
733 PCON(7) = 0;
734 PCON(8) = 0;
735 PCON(9) = 0;
736 PCON(10) &= ~0xffff;
737 PCON(11) &= ~0xf;
695 ide_power_enable(false); 738 ide_power_enable(false);
696} 739}
697 740
@@ -886,7 +929,7 @@ static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool wr
886 uint32_t cnt; 929 uint32_t cnt;
887 PASS_RC(ata_bbt_translate(sector, count, &phys, &cnt), 0, 0); 930 PASS_RC(ata_bbt_translate(sector, count, &phys, &cnt), 0, 0);
888 uint32_t offset = phys - sector; 931 uint32_t offset = phys - sector;
889 if (offset != ata_last_offset && phys - ata_last_phys < 64) ata_soft_reset(); 932 if (offset != ata_last_offset && phys - ata_last_phys < 64) ata_reset();
890 ata_last_offset = offset; 933 ata_last_offset = offset;
891 ata_last_phys = phys + cnt; 934 ata_last_phys = phys + cnt;
892 PASS_RC(ata_rw_sectors_internal(phys, cnt, buffer, write), 0, 0); 935 PASS_RC(ata_rw_sectors_internal(phys, cnt, buffer, write), 0, 0);
@@ -912,7 +955,7 @@ int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool
912 uint32_t cnt = MIN(ata_lba48 ? 8192 : 32, count); 955 uint32_t cnt = MIN(ata_lba48 ? 8192 : 32, count);
913 int rc = -1; 956 int rc = -1;
914 rc = ata_rw_chunk(sector, cnt, buffer, write); 957 rc = ata_rw_chunk(sector, cnt, buffer, write);
915 if (rc && ata_error_srst) ata_soft_reset(); 958 if (rc && ata_error_srst) ata_reset();
916 if (rc && ata_retries) 959 if (rc && ata_retries)
917 { 960 {
918 void* buf = buffer; 961 void* buf = buffer;
@@ -924,7 +967,7 @@ int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool
924 while (tries-- && rc) 967 while (tries-- && rc)
925 { 968 {
926 rc = ata_rw_chunk(sect, 1, buf, write); 969 rc = ata_rw_chunk(sect, 1, buf, write);
927 if (rc && ata_error_srst) ata_soft_reset(); 970 if (rc && ata_error_srst) ata_reset();
928 } 971 }
929 if (rc) break; 972 if (rc) break;
930 buf += SECTOR_SIZE; 973 buf += SECTOR_SIZE;
@@ -959,7 +1002,7 @@ int ata_soft_reset(void)
959{ 1002{
960 int rc; 1003 int rc;
961 mutex_lock(&ata_mutex); 1004 mutex_lock(&ata_mutex);
962 if (!ata_powered) ata_power_up(); 1005 if (!ata_powered) PASS_RC(ata_power_up(), 1, 0);
963 ata_set_active(); 1006 ata_set_active();
964 if (ceata) rc = ceata_soft_reset(); 1007 if (ceata) rc = ceata_soft_reset();
965 else 1008 else
@@ -967,13 +1010,42 @@ int ata_soft_reset(void)
967 ata_write_cbr(&ATA_PIO_DAD, BIT(1) | BIT(2)); 1010 ata_write_cbr(&ATA_PIO_DAD, BIT(1) | BIT(2));
968 udelay(10); 1011 udelay(10);
969 ata_write_cbr(&ATA_PIO_DAD, 0); 1012 ata_write_cbr(&ATA_PIO_DAD, 0);
970 rc = ata_wait_for_rdy(20000000); 1013 rc = ata_wait_for_rdy(3000000);
971 } 1014 }
1015 ata_set_active();
1016 mutex_unlock(&ata_mutex);
1017 PASS_RC(rc, 1, 1);
1018 return 0;
1019}
1020
1021int ata_hard_reset(void)
1022{
1023 mutex_lock(&ata_mutex);
1024 PASS_RC(ata_power_up(), 0, 0);
1025 ata_set_active();
1026 mutex_unlock(&ata_mutex);
1027 return 0;
1028}
1029
1030static int ata_reset(void)
1031{
1032 int rc;
1033 mutex_lock(&ata_mutex);
1034 if (!ata_powered) PASS_RC(ata_power_up(), 2, 0);
1035 ata_set_active();
1036 rc = ata_soft_reset();
972 if (IS_ERR(rc)) 1037 if (IS_ERR(rc))
973 { 1038 {
974 ata_power_down(); 1039 rc = ata_hard_reset();
975 sleep(HZ * 3); 1040 if (IS_ERR(rc))
976 ata_power_up(); 1041 {
1042 rc = ERR_RC((rc << 2) | 1);
1043 ata_power_down();
1044 sleep(HZ * 3);
1045 int rc2 = ata_power_up();
1046 if (IS_ERR(rc2)) rc = ERR_RC((rc << 2) | 2);
1047 }
1048 else rc = 1;
977 } 1049 }
978 ata_set_active(); 1050 ata_set_active();
979 mutex_unlock(&ata_mutex); 1051 mutex_unlock(&ata_mutex);
@@ -1052,11 +1124,11 @@ void ata_bbt_disable(void)
1052 mutex_unlock(&ata_mutex); 1124 mutex_unlock(&ata_mutex);
1053} 1125}
1054 1126
1055void ata_bbt_reload(void) 1127int ata_bbt_reload(void)
1056{ 1128{
1057 mutex_lock(&ata_mutex); 1129 mutex_lock(&ata_mutex);
1058 ata_bbt_disable(); 1130 ata_bbt_disable();
1059 ata_power_up(); 1131 PASS_RC(ata_power_up(), 1, 0);
1060 uint32_t* buf = (uint32_t*)(ata_bbt_buf + sizeof(ata_bbt_buf) - SECTOR_SIZE); 1132 uint32_t* buf = (uint32_t*)(ata_bbt_buf + sizeof(ata_bbt_buf) - SECTOR_SIZE);
1061 if (buf) 1133 if (buf)
1062 { 1134 {
@@ -1064,6 +1136,7 @@ void ata_bbt_reload(void)
1064 ata_virtual_sectors = ata_total_sectors; 1136 ata_virtual_sectors = ata_total_sectors;
1065 else if (!memcmp(buf, "emBIbbth", 8)) 1137 else if (!memcmp(buf, "emBIbbth", 8))
1066 { 1138 {
1139 if (ata_identify_data[82] & BIT(5)) PASS_RC(ata_set_feature(0x02, 0), 1, 1);
1067 ata_virtual_sectors = (((uint64_t)buf[0x1fd]) << 32) | buf[0x1fc]; 1140 ata_virtual_sectors = (((uint64_t)buf[0x1fd]) << 32) | buf[0x1fc];
1068 uint32_t count = buf[0x1ff]; 1141 uint32_t count = buf[0x1ff];
1069 if (count > ATA_BBT_PAGES / 64) 1142 if (count > ATA_BBT_PAGES / 64)
@@ -1089,6 +1162,7 @@ void ata_bbt_reload(void)
1089 } 1162 }
1090 else ata_virtual_sectors = ata_total_sectors; 1163 else ata_virtual_sectors = ata_total_sectors;
1091 mutex_unlock(&ata_mutex); 1164 mutex_unlock(&ata_mutex);
1165 return 0;
1092} 1166}
1093#endif 1167#endif
1094 1168
@@ -1099,29 +1173,11 @@ int ata_init(void)
1099 semaphore_init(&mmc_wakeup, 1, 0); 1173 semaphore_init(&mmc_wakeup, 1, 0);
1100 semaphore_init(&mmc_comp_wakeup, 1, 0); 1174 semaphore_init(&mmc_comp_wakeup, 1, 0);
1101 ceata = PDAT(11) & BIT(1); 1175 ceata = PDAT(11) & BIT(1);
1102 if (ceata)
1103 {
1104 ata_lba48 = true;
1105 ata_dma = true;
1106 PCON(8) = 0x33333333;
1107 PCON(9) = (PCON(9) & ~0xff) | 0x33;
1108 PCON(11) |= 0xf;
1109 *((uint32_t volatile*)0x38a00000) = 0;
1110 *((uint32_t volatile*)0x38700000) = 0;
1111 }
1112 else
1113 {
1114 PCON(7) = 0x44444444;
1115 PCON(8) = 0x44444444;
1116 PCON(9) = 0x44444444;
1117 PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
1118 }
1119 ata_swap = false; 1176 ata_swap = false;
1120 ata_powered = false; 1177 ata_powered = false;
1121 ata_total_sectors = 0; 1178 ata_total_sectors = 0;
1122 ata_power_up();
1123#ifdef ATA_HAVE_BBT 1179#ifdef ATA_HAVE_BBT
1124 ata_bbt_reload(); 1180 PASS_RC(ata_bbt_reload(), 0, 0);
1125#endif 1181#endif
1126 1182
1127 /* HDD data endianness check: 1183 /* HDD data endianness check:
@@ -1191,3 +1247,4 @@ void INT_MMC(void)
1191 if (irq & SDCI_IRQ_IOCARD_IRQ_INT) semaphore_release(&mmc_comp_wakeup); 1247 if (irq & SDCI_IRQ_IOCARD_IRQ_INT) semaphore_release(&mmc_comp_wakeup);
1192 SDCI_IRQ = irq; 1248 SDCI_IRQ = irq;
1193} 1249}
1250