summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s5l8702/ipod6g
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s5l8702/ipod6g')
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c103
1 files changed, 60 insertions, 43 deletions
diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c
index 87450aca73..21c6f3f7c0 100644
--- a/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c
@@ -83,6 +83,7 @@ static uint32_t ata_dma_flags;
83static long ata_last_activity_value = -1; 83static long ata_last_activity_value = -1;
84static long ata_sleep_timeout = 7 * HZ; 84static long ata_sleep_timeout = 7 * HZ;
85static bool ata_powered; 85static bool ata_powered;
86static bool canflush = true;
86static struct semaphore mmc_wakeup; 87static struct semaphore mmc_wakeup;
87static struct semaphore mmc_comp_wakeup; 88static struct semaphore mmc_comp_wakeup;
88static int spinup_time = 0; 89static int spinup_time = 0;
@@ -578,7 +579,7 @@ static void ata_set_active(void)
578 579
579bool ata_disk_is_active(void) 580bool ata_disk_is_active(void)
580{ 581{
581 return ata_disk_can_poweroff() ? ata_powered : 0; 582 return ata_powered;
582} 583}
583 584
584static int ata_set_feature(uint32_t feature, uint32_t param) 585static int ata_set_feature(uint32_t feature, uint32_t param)
@@ -745,6 +746,8 @@ static int ata_power_up(void)
745 ata_dma = param ? true : false; 746 ata_dma = param ? true : false;
746 dma_mode = param; 747 dma_mode = param;
747 PASS_RC(ata_set_feature(0x03, param), 3, 4); /* Transfer mode */ 748 PASS_RC(ata_set_feature(0x03, param), 3, 4); /* Transfer mode */
749
750 /* SET_FEATURE only supported on PATA, not CE-ATA */
748 if (ata_identify_data[82] & BIT(5)) 751 if (ata_identify_data[82] & BIT(5))
749 PASS_RC(ata_set_feature(0x02, 0), 3, 5); /* Enable volatile write cache */ 752 PASS_RC(ata_set_feature(0x02, 0), 3, 5); /* Enable volatile write cache */
750 if (ata_identify_data[82] & BIT(6)) 753 if (ata_identify_data[82] & BIT(6))
@@ -753,7 +756,10 @@ static int ata_power_up(void)
753 PASS_RC(ata_set_feature(0x05, 0x80), 3, 7); /* Enable lowest power mode w/o standby */ 756 PASS_RC(ata_set_feature(0x05, 0x80), 3, 7); /* Enable lowest power mode w/o standby */
754 if (ata_identify_data[83] & BIT(9)) 757 if (ata_identify_data[83] & BIT(9))
755 PASS_RC(ata_set_feature(0x42, 0x80), 3, 8); /* Enable lowest noise mode */ 758 PASS_RC(ata_set_feature(0x42, 0x80), 3, 8); /* Enable lowest noise mode */
759
760 PASS_RC(ata_identify(ata_identify_data), 3, 9); /* Finally, re-read identify info */
756 } 761 }
762
757 spinup_time = current_tick - spinup_start; 763 spinup_time = current_tick - spinup_start;
758 764
759 ata_total_sectors = (ata_identify_data[61] << 16) | ata_identify_data[60]; 765 ata_total_sectors = (ata_identify_data[61] << 16) | ata_identify_data[60];
@@ -778,28 +784,6 @@ static void ata_power_down(void)
778{ 784{
779 if (!ata_powered) 785 if (!ata_powered)
780 return; 786 return;
781 if (ceata)
782 {
783 memset(ceata_taskfile, 0, 16);
784 ceata_taskfile[0xf] = CMD_STANDBY_IMMEDIATE;
785 ceata_wait_idle();
786 ceata_write_multiple_register(0, ceata_taskfile, 16);
787 ceata_wait_idle();
788 sleep(HZ);
789 PWRCON(0) |= (1 << 9);
790 }
791 else
792 {
793 ata_wait_for_rdy(1000000);
794 ata_write_cbr(&ATA_PIO_DVR, 0);
795 ata_write_cbr(&ATA_PIO_CSD, CMD_STANDBY_IMMEDIATE);
796 ata_wait_for_rdy(1000000);
797 sleep(HZ / 30);
798 ATA_CONTROL = 0;
799 while (!(ATA_CONTROL & BIT(1)))
800 yield();
801 PWRCON(0) |= (1 << 5);
802 }
803 PCON(7) = 0; 787 PCON(7) = 0;
804 PCON(8) = 0; 788 PCON(8) = 0;
805 PCON(9) = 0; 789 PCON(9) = 0;
@@ -1080,26 +1064,27 @@ static void ata_flush_cache(void)
1080{ 1064{
1081 uint8_t cmd; 1065 uint8_t cmd;
1082 1066
1083 if (ata_identify_data[83] & BIT(13)) { 1067 if (ceata) {
1084 cmd = CMD_FLUSH_CACHE_EXT;
1085 } else if (ata_identify_data[83] & BIT(12)) {
1086 cmd = CMD_FLUSH_CACHE;
1087 } else {
1088 /* If neither (mandatory!) command is supported
1089 then don't issue it. */
1090 return;
1091 }
1092
1093 if (ceata)
1094 {
1095 memset(ceata_taskfile, 0, 16); 1068 memset(ceata_taskfile, 0, 16);
1096 ceata_taskfile[0xf] = cmd; 1069 ceata_taskfile[0xf] = CMD_FLUSH_CACHE_EXT; /* CE-ATA only supports EXT */
1097 ceata_wait_idle(); 1070 ceata_wait_idle();
1098 ceata_write_multiple_register(0, ceata_taskfile, 16); 1071 ceata_write_multiple_register(0, ceata_taskfile, 16);
1099 ceata_wait_idle(); 1072 ceata_wait_idle();
1100 } 1073 } else {
1101 else 1074 if (!canflush) {
1102 { 1075 return;
1076 } else if (ata_lba48 && ata_identify_data[83] & BIT(13)) {
1077 cmd = CMD_FLUSH_CACHE_EXT; /* Flag, optional, ATA-6 and up, for use with LBA48 devices. Mandatory for CE-ATA */
1078 } else if (ata_identify_data[83] & BIT(12)) {
1079 cmd = CMD_FLUSH_CACHE; /* Flag, mandatory, ATA-6 and up */
1080 } else if (ata_identify_data[80] >= BIT(5)) { /* Use >= instead of '&' because bits lower than the latest standard we support don't have to be set */
1081 cmd = CMD_FLUSH_CACHE; /* No flag, mandatory, ATA-5 (Optional for ATA-4) */
1082 } else {
1083 /* If neither command is supported then don't issue it. */
1084 canflush = 0;
1085 return;
1086 }
1087
1103 ata_wait_for_rdy(1000000); 1088 ata_wait_for_rdy(1000000);
1104 ata_write_cbr(&ATA_PIO_DVR, 0); 1089 ata_write_cbr(&ATA_PIO_DVR, 0);
1105 ata_write_cbr(&ATA_PIO_CSD, cmd); 1090 ata_write_cbr(&ATA_PIO_CSD, cmd);
@@ -1107,14 +1092,46 @@ static void ata_flush_cache(void)
1107 } 1092 }
1108} 1093}
1109 1094
1095int ata_flush(void)
1096{
1097 if (ata_powered) {
1098 mutex_lock(&ata_mutex);
1099 ata_flush_cache();
1100 mutex_unlock(&ata_mutex);
1101 }
1102 return 0;
1103}
1104
1110void ata_sleepnow(void) 1105void ata_sleepnow(void)
1111{ 1106{
1112 mutex_lock(&ata_mutex); 1107 mutex_lock(&ata_mutex);
1113 1108
1114 if (ata_disk_can_poweroff()) 1109 ata_flush_cache();
1115 ata_power_down(); 1110
1116 else 1111 if (ata_disk_can_sleep()) {
1117 ata_flush_cache(); 1112 if (ceata) {
1113 memset(ceata_taskfile, 0, 16);
1114 ceata_taskfile[0xf] = CMD_STANDBY_IMMEDIATE;
1115 ceata_wait_idle();
1116 ceata_write_multiple_register(0, ceata_taskfile, 16);
1117 ceata_wait_idle();
1118 sleep(HZ);
1119 PWRCON(0) |= (1 << 9);
1120 } else {
1121 ata_wait_for_rdy(1000000);
1122 ata_write_cbr(&ATA_PIO_DVR, 0);
1123 ata_write_cbr(&ATA_PIO_CSD, CMD_STANDBY_IMMEDIATE);
1124 ata_wait_for_rdy(1000000);
1125 sleep(HZ / 30);
1126 ATA_CONTROL = 0;
1127 while (!(ATA_CONTROL & BIT(1)))
1128 yield();
1129 PWRCON(0) |= (1 << 5);
1130 }
1131 }
1132
1133 if (ata_disk_can_sleep() || canflush)
1134 ata_power_down(); // XXX add a powerdown delay similar to main ATA driver?
1118 1135
1119 mutex_unlock(&ata_mutex); 1136 mutex_unlock(&ata_mutex);
1120} 1137}