summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/ata.c2
-rw-r--r--firmware/export/ata.h3
-rw-r--r--firmware/target/arm/pp/ata-pp5020.c64
-rw-r--r--firmware/target/arm/pp/ata-target.h2
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
335static inline int ata_disk_isssd(void) 335int 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);
165long ata_last_disk_activity(void); 165long ata_last_disk_activity(void);
166int ata_spinup_time(void); /* ticks */ 166int ata_spinup_time(void); /* ticks */
167 167
168/* Returns 1 if drive is solid-state */
169int 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 */
170int ata_get_dma_mode(void); 173int 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
29void ata_reset() 30void 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*/
54static const unsigned long pio80mhz[] = {
55 0xC293, 0x43A2, 0x11A1, 0x7232, 0x3131
56};
57
46void ata_device_init() 58void 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. 84void 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
77static 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 */
86static const unsigned long tm_mwdma[] = { 96static const unsigned long tm_mwdma[] = {
87 0xF9F92, 0x56562, 0x45451 97 0xF9F92, 0x56562, 0x45451
88}; 98};
89 99
90static const unsigned long tm_udma[] = { 100static 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) {
137static ICODE_ATTR int ata_wait_intrq(void) 147static 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 */
224bool ata_dma_finish(void) { 234bool 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