diff options
author | Torne Wuff <torne@wolfpuppy.org.uk> | 2013-05-12 22:38:52 +0100 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2020-11-04 03:03:19 +0000 |
commit | 5db83c155affd1968872044fc6a3a156cf966ba4 (patch) | |
tree | 50fd4d2ef7bed155feaa79c3023af10e47075d8f | |
parent | 090bd9592df1e05e289e658c2530ae277a205318 (diff) | |
download | rockbox-5db83c155affd1968872044fc6a3a156cf966ba4.tar.gz rockbox-5db83c155affd1968872044fc6a3a156cf966ba4.zip |
pp5020: use ipod firmware timings for ATA PIO.
Some mSATA adapters seem to have trouble working with Rockbox using our
normal PIO timings; the timing value we use is probably out of spec and
is different to the OF. Switch to using the OF's timings according to
which PIO mode we select. This may not completely resolve problems with
these adapters but allows Rockbox to boot and play audio.
Change-Id: If73210700eb4af01864b373709ee1d15c775fb11
-rw-r--r-- | firmware/drivers/ata.c | 2 | ||||
-rw-r--r-- | firmware/export/ata.h | 3 | ||||
-rw-r--r-- | firmware/target/arm/pp/ata-pp5020.c | 64 | ||||
-rw-r--r-- | firmware/target/arm/pp/ata-target.h | 2 |
4 files changed, 43 insertions, 28 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c index db39255256..ba0d6d169e 100644 --- a/firmware/drivers/ata.c +++ b/firmware/drivers/ata.c | |||
@@ -332,7 +332,7 @@ static ICODE_ATTR void copy_write_sectors(const unsigned char* buf, | |||
332 | } | 332 | } |
333 | #endif /* !ATA_OPTIMIZED_WRITING */ | 333 | #endif /* !ATA_OPTIMIZED_WRITING */ |
334 | 334 | ||
335 | static inline int ata_disk_isssd(void) | 335 | int ata_disk_isssd(void) |
336 | { | 336 | { |
337 | /* offset 217 is "Nominal Rotation rate" | 337 | /* offset 217 is "Nominal Rotation rate" |
338 | 0x0000 == Not reported | 338 | 0x0000 == Not reported |
diff --git a/firmware/export/ata.h b/firmware/export/ata.h index e6ca9422ea..7c5fd3a8d0 100644 --- a/firmware/export/ata.h +++ b/firmware/export/ata.h | |||
@@ -165,6 +165,9 @@ int ata_num_drives(int first_drive); | |||
165 | long ata_last_disk_activity(void); | 165 | long ata_last_disk_activity(void); |
166 | int ata_spinup_time(void); /* ticks */ | 166 | int ata_spinup_time(void); /* ticks */ |
167 | 167 | ||
168 | /* Returns 1 if drive is solid-state */ | ||
169 | int ata_disk_isssd(void); | ||
170 | |||
168 | #ifdef HAVE_ATA_DMA | 171 | #ifdef HAVE_ATA_DMA |
169 | /* Returns current DMA mode */ | 172 | /* Returns current DMA mode */ |
170 | int ata_get_dma_mode(void); | 173 | int ata_get_dma_mode(void); |
diff --git a/firmware/target/arm/pp/ata-pp5020.c b/firmware/target/arm/pp/ata-pp5020.c index 9b3158ecc7..77e77cae92 100644 --- a/firmware/target/arm/pp/ata-pp5020.c +++ b/firmware/target/arm/pp/ata-pp5020.c | |||
@@ -25,8 +25,9 @@ | |||
25 | #include "system.h" | 25 | #include "system.h" |
26 | #include "kernel.h" | 26 | #include "kernel.h" |
27 | #include "ata-driver.h" | 27 | #include "ata-driver.h" |
28 | #include "ata.h" | ||
28 | 29 | ||
29 | void ata_reset() | 30 | void ata_reset() |
30 | { | 31 | { |
31 | 32 | ||
32 | } | 33 | } |
@@ -43,6 +44,17 @@ bool ata_is_coldstart() | |||
43 | /* TODO: Implement coldstart variable */ | 44 | /* TODO: Implement coldstart variable */ |
44 | } | 45 | } |
45 | 46 | ||
47 | /* These are PIO timings for 80 Mhz. At 24 Mhz, the first value is 0 but the | ||
48 | rest are the same. They go in IDE0_PRI_TIMING0. | ||
49 | |||
50 | Rockbox used to use 0x10, and test_disk shows that leads to faster PIO. | ||
51 | However on some disks connected with mSATA adapters this causes corrupt data | ||
52 | so we now just use these timings from the OF. | ||
53 | */ | ||
54 | static const unsigned long pio80mhz[] = { | ||
55 | 0xC293, 0x43A2, 0x11A1, 0x7232, 0x3131 | ||
56 | }; | ||
57 | |||
46 | void ata_device_init() | 58 | void ata_device_init() |
47 | { | 59 | { |
48 | #ifdef SAMSUNG_YH920 | 60 | #ifdef SAMSUNG_YH920 |
@@ -52,7 +64,7 @@ void ata_device_init() | |||
52 | IDE_DMA_CONTROL |= 2; | 64 | IDE_DMA_CONTROL |= 2; |
53 | IDE_DMA_CONTROL &= ~1; | 65 | IDE_DMA_CONTROL &= ~1; |
54 | IDE0_CFG &= ~0x8010; | 66 | IDE0_CFG &= ~0x8010; |
55 | IDE0_CFG |= 0x20; | 67 | IDE0_CFG |= 0x20; |
56 | #else | 68 | #else |
57 | 69 | ||
58 | /* From ipod-ide.c:ipod_ide_register() */ | 70 | /* From ipod-ide.c:ipod_ide_register() */ |
@@ -64,33 +76,31 @@ void ata_device_init() | |||
64 | #endif | 76 | #endif |
65 | #endif | 77 | #endif |
66 | 78 | ||
67 | IDE0_PRI_TIMING0 = 0x10; | 79 | IDE0_PRI_TIMING0 = pio80mhz[0]; |
68 | IDE0_PRI_TIMING1 = 0x80002150; | 80 | IDE0_PRI_TIMING1 = 0x80002150; |
69 | } | 81 | } |
70 | 82 | ||
71 | /* These are PIO timings for 80 Mhz. At 24 Mhz, | 83 | /* Setup the timing for PIO mode */ |
72 | the first value is 0 but the rest are the same. | 84 | void ata_set_pio_timings(int mode) |
73 | They go in IDE0_PRI_TIMING0. | 85 | { |
74 | 86 | if (ata_disk_isssd()) | |
75 | Rockbox used 0x10, and test_disk shows that leads to faster PIO. | 87 | IDE0_PRI_TIMING0 = pio80mhz[mode]; |
76 | If 0x10 is incorrect, these timings may be needed with some devices. | 88 | else |
77 | static const unsigned long pio80mhz[] = { | 89 | IDE0_PRI_TIMING0 = 0x10; |
78 | 0xC293, 0x43A2, 0x11A1, 0x7232, 0x3131 | 90 | } |
79 | }; | ||
80 | */ | ||
81 | 91 | ||
82 | #ifdef HAVE_ATA_DMA | 92 | #ifdef HAVE_ATA_DMA |
83 | /* Timings for multi-word and ultra DMA modes. | 93 | /* Timings for multi-word and ultra DMA modes. |
84 | These go in IDE0_PRI_TIMING1 | 94 | These go in IDE0_PRI_TIMING1 |
85 | */ | 95 | */ |
86 | static const unsigned long tm_mwdma[] = { | 96 | static const unsigned long tm_mwdma[] = { |
87 | 0xF9F92, 0x56562, 0x45451 | 97 | 0xF9F92, 0x56562, 0x45451 |
88 | }; | 98 | }; |
89 | 99 | ||
90 | static const unsigned long tm_udma[] = { | 100 | static const unsigned long tm_udma[] = { |
91 | 0x800037C1, 0x80003491, 0x80003371, | 101 | 0x800037C1, 0x80003491, 0x80003371, |
92 | #if ATA_MAX_UDMA > 2 | 102 | #if ATA_MAX_UDMA > 2 |
93 | 0x80003271, 0x80003071 | 103 | 0x80003271, 0x80003071 |
94 | #endif | 104 | #endif |
95 | }; | 105 | }; |
96 | 106 | ||
@@ -126,7 +136,7 @@ void ata_dma_set_mode(unsigned char mode) { | |||
126 | #if !defined(IPOD_NANO) | 136 | #if !defined(IPOD_NANO) |
127 | IDE0_CFG |= 0x20000000; /* >= 50 Mhz */ | 137 | IDE0_CFG |= 0x20000000; /* >= 50 Mhz */ |
128 | #endif | 138 | #endif |
129 | } | 139 | } |
130 | 140 | ||
131 | #define IDE_CFG_INTRQ 8 | 141 | #define IDE_CFG_INTRQ 8 |
132 | #define IDE_DMA_CONTROL_READ 8 | 142 | #define IDE_DMA_CONTROL_READ 8 |
@@ -137,8 +147,8 @@ void ata_dma_set_mode(unsigned char mode) { | |||
137 | static ICODE_ATTR int ata_wait_intrq(void) | 147 | static ICODE_ATTR int ata_wait_intrq(void) |
138 | { | 148 | { |
139 | long timeout = current_tick + HZ*10; | 149 | long timeout = current_tick + HZ*10; |
140 | 150 | ||
141 | do | 151 | do |
142 | { | 152 | { |
143 | if (IDE0_CFG & IDE_CFG_INTRQ) | 153 | if (IDE0_CFG & IDE_CFG_INTRQ) |
144 | return 1; | 154 | return 1; |
@@ -149,11 +159,11 @@ static ICODE_ATTR int ata_wait_intrq(void) | |||
149 | return 0; /* timeout */ | 159 | return 0; /* timeout */ |
150 | } | 160 | } |
151 | 161 | ||
152 | /* This function checks if parameters are appropriate for DMA, | 162 | /* This function checks if parameters are appropriate for DMA, |
153 | and if they are, it sets up for DMA. | 163 | and if they are, it sets up for DMA. |
154 | 164 | ||
155 | If return value is false, caller may use PIO for this transfer. | 165 | If return value is false, caller may use PIO for this transfer. |
156 | 166 | ||
157 | If return value is true, caller must issue a DMA ATA command | 167 | If return value is true, caller must issue a DMA ATA command |
158 | and then call ata_dma_finish(). | 168 | and then call ata_dma_finish(). |
159 | */ | 169 | */ |
@@ -217,18 +227,18 @@ bool ata_dma_setup(void *addr, unsigned long bytes, bool write) { | |||
217 | 227 | ||
218 | /* This function waits for a DMA transfer to end. | 228 | /* This function waits for a DMA transfer to end. |
219 | It must be called to finish what ata_dma_setup started. | 229 | It must be called to finish what ata_dma_setup started. |
220 | 230 | ||
221 | Return value is true if DMA completed before the timeout, and false | 231 | Return value is true if DMA completed before the timeout, and false |
222 | if a timeout happened. | 232 | if a timeout happened. |
223 | */ | 233 | */ |
224 | bool ata_dma_finish(void) { | 234 | bool ata_dma_finish(void) { |
225 | bool res; | 235 | bool res; |
226 | 236 | ||
227 | /* It may be okay to put this at the end of setup */ | 237 | /* It may be okay to put this at the end of setup */ |
228 | IDE_DMA_CONTROL |= 1; | 238 | IDE_DMA_CONTROL |= 1; |
229 | 239 | ||
230 | /* Wait for end of transfer. | 240 | /* Wait for end of transfer. |
231 | Reading standard ATA status while DMA is in progress causes | 241 | Reading standard ATA status while DMA is in progress causes |
232 | failures and hangs. Because of that, another wait is used. | 242 | failures and hangs. Because of that, another wait is used. |
233 | */ | 243 | */ |
234 | res = ata_wait_intrq(); | 244 | res = ata_wait_intrq(); |
diff --git a/firmware/target/arm/pp/ata-target.h b/firmware/target/arm/pp/ata-target.h index a11aeda36d..75570bf3cd 100644 --- a/firmware/target/arm/pp/ata-target.h +++ b/firmware/target/arm/pp/ata-target.h | |||
@@ -49,6 +49,8 @@ | |||
49 | #define ATA_OPTIMIZED_READING | 49 | #define ATA_OPTIMIZED_READING |
50 | #define ATA_OPTIMIZED_WRITING | 50 | #define ATA_OPTIMIZED_WRITING |
51 | 51 | ||
52 | #define ATA_SET_PIO_TIMING | ||
53 | |||
52 | #endif /* CONFIG_CPU */ | 54 | #endif /* CONFIG_CPU */ |
53 | 55 | ||
54 | #ifdef HAVE_ATA_DMA | 56 | #ifdef HAVE_ATA_DMA |