diff options
-rw-r--r-- | firmware/export/config/gogearhdd1630.h | 5 | ||||
-rw-r--r-- | firmware/export/config/ipod4g.h | 5 | ||||
-rw-r--r-- | firmware/export/config/ipodcolor.h | 5 | ||||
-rw-r--r-- | firmware/export/config/ipodmini1g.h | 5 | ||||
-rw-r--r-- | firmware/export/config/ipodmini2g.h | 5 | ||||
-rw-r--r-- | firmware/export/config/ipodnano1g.h | 5 | ||||
-rw-r--r-- | firmware/export/config/ipodvideo.h | 4 | ||||
-rw-r--r-- | firmware/export/config/iriverh10.h | 5 | ||||
-rw-r--r-- | firmware/export/config/iriverh10_5gb.h | 5 | ||||
-rw-r--r-- | firmware/export/config/mrobe100.h | 5 | ||||
-rw-r--r-- | firmware/export/config/samsungyh820.h | 5 | ||||
-rw-r--r-- | firmware/export/config/samsungyh920.h | 5 | ||||
-rw-r--r-- | firmware/export/config/samsungyh925.h | 5 | ||||
-rw-r--r-- | firmware/export/config/tatungtpj1022.h | 5 | ||||
-rw-r--r-- | firmware/target/arm/ata-pp5020.c | 183 | ||||
-rw-r--r-- | firmware/target/arm/ata-target.h | 34 |
16 files changed, 286 insertions, 0 deletions
diff --git a/firmware/export/config/gogearhdd1630.h b/firmware/export/config/gogearhdd1630.h index 912ba427c0..8bb14801b0 100644 --- a/firmware/export/config/gogearhdd1630.h +++ b/firmware/export/config/gogearhdd1630.h | |||
@@ -200,3 +200,8 @@ | |||
200 | 200 | ||
201 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 201 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
202 | 202 | ||
203 | |||
204 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
205 | * writes appear to be ~25% slower. | ||
206 | */ | ||
207 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/ipod4g.h b/firmware/export/config/ipod4g.h index e6bdc35bd8..cd71434c10 100644 --- a/firmware/export/config/ipod4g.h +++ b/firmware/export/config/ipod4g.h | |||
@@ -207,3 +207,8 @@ | |||
207 | 207 | ||
208 | #define IRAM_LCDFRAMEBUFFER IBSS_ATTR /* put the lcd frame buffer in IRAM */ | 208 | #define IRAM_LCDFRAMEBUFFER IBSS_ATTR /* put the lcd frame buffer in IRAM */ |
209 | 209 | ||
210 | |||
211 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
212 | * writes appear to be ~25% slower. | ||
213 | */ | ||
214 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/ipodcolor.h b/firmware/export/config/ipodcolor.h index 0f1de4fdba..c0168d9886 100644 --- a/firmware/export/config/ipodcolor.h +++ b/firmware/export/config/ipodcolor.h | |||
@@ -182,3 +182,8 @@ | |||
182 | #define IPOD_ACCESSORY_PROTOCOL | 182 | #define IPOD_ACCESSORY_PROTOCOL |
183 | #define HAVE_SERIAL | 183 | #define HAVE_SERIAL |
184 | 184 | ||
185 | |||
186 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
187 | * writes appear to be ~25% slower. | ||
188 | */ | ||
189 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/ipodmini1g.h b/firmware/export/config/ipodmini1g.h index 129829ffbb..3ab96e3a62 100644 --- a/firmware/export/config/ipodmini1g.h +++ b/firmware/export/config/ipodmini1g.h | |||
@@ -193,3 +193,8 @@ | |||
193 | 193 | ||
194 | #define IRAM_LCDFRAMEBUFFER IBSS_ATTR /* put the lcd frame buffer in IRAM */ | 194 | #define IRAM_LCDFRAMEBUFFER IBSS_ATTR /* put the lcd frame buffer in IRAM */ |
195 | 195 | ||
196 | |||
197 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
198 | * writes appear to be ~25% slower. | ||
199 | */ | ||
200 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/ipodmini2g.h b/firmware/export/config/ipodmini2g.h index 8087269485..72e04a30db 100644 --- a/firmware/export/config/ipodmini2g.h +++ b/firmware/export/config/ipodmini2g.h | |||
@@ -203,3 +203,8 @@ | |||
203 | 203 | ||
204 | #define IRAM_LCDFRAMEBUFFER IBSS_ATTR /* put the lcd frame buffer in IRAM */ | 204 | #define IRAM_LCDFRAMEBUFFER IBSS_ATTR /* put the lcd frame buffer in IRAM */ |
205 | 205 | ||
206 | |||
207 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
208 | * writes appear to be ~25% slower. | ||
209 | */ | ||
210 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/ipodnano1g.h b/firmware/export/config/ipodnano1g.h index 5f63c269ed..562c940df4 100644 --- a/firmware/export/config/ipodnano1g.h +++ b/firmware/export/config/ipodnano1g.h | |||
@@ -192,3 +192,8 @@ | |||
192 | #define IPOD_ACCESSORY_PROTOCOL | 192 | #define IPOD_ACCESSORY_PROTOCOL |
193 | #define HAVE_SERIAL | 193 | #define HAVE_SERIAL |
194 | 194 | ||
195 | |||
196 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
197 | * writes appear to be ~25% slower. | ||
198 | */ | ||
199 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/ipodvideo.h b/firmware/export/config/ipodvideo.h index 9aa1d49547..d188696e64 100644 --- a/firmware/export/config/ipodvideo.h +++ b/firmware/export/config/ipodvideo.h | |||
@@ -224,3 +224,7 @@ | |||
224 | #define IPOD_ACCESSORY_PROTOCOL | 224 | #define IPOD_ACCESSORY_PROTOCOL |
225 | #define HAVE_SERIAL | 225 | #define HAVE_SERIAL |
226 | 226 | ||
227 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
228 | * writes appear to be ~25% slower. | ||
229 | */ | ||
230 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/iriverh10.h b/firmware/export/config/iriverh10.h index cde1b6075e..5365c83239 100644 --- a/firmware/export/config/iriverh10.h +++ b/firmware/export/config/iriverh10.h | |||
@@ -186,3 +186,8 @@ | |||
186 | 186 | ||
187 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 187 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
188 | 188 | ||
189 | |||
190 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
191 | * writes appear to be ~25% slower. | ||
192 | */ | ||
193 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/iriverh10_5gb.h b/firmware/export/config/iriverh10_5gb.h index e69f6c2b20..bfc9b8ac2e 100644 --- a/firmware/export/config/iriverh10_5gb.h +++ b/firmware/export/config/iriverh10_5gb.h | |||
@@ -169,3 +169,8 @@ | |||
169 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 169 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
170 | 170 | ||
171 | #endif | 171 | #endif |
172 | |||
173 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
174 | * writes appear to be ~25% slower. | ||
175 | */ | ||
176 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/mrobe100.h b/firmware/export/config/mrobe100.h index 90419914b2..2bbb03919d 100644 --- a/firmware/export/config/mrobe100.h +++ b/firmware/export/config/mrobe100.h | |||
@@ -200,3 +200,8 @@ | |||
200 | 200 | ||
201 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 201 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
202 | 202 | ||
203 | |||
204 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
205 | * writes appear to be ~25% slower. | ||
206 | */ | ||
207 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/samsungyh820.h b/firmware/export/config/samsungyh820.h index 4968960803..0ca244ae39 100644 --- a/firmware/export/config/samsungyh820.h +++ b/firmware/export/config/samsungyh820.h | |||
@@ -181,3 +181,8 @@ | |||
181 | 181 | ||
182 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 182 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
183 | 183 | ||
184 | |||
185 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
186 | * writes appear to be ~25% slower. | ||
187 | */ | ||
188 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/samsungyh920.h b/firmware/export/config/samsungyh920.h index 310fa1374c..a6a57f7227 100644 --- a/firmware/export/config/samsungyh920.h +++ b/firmware/export/config/samsungyh920.h | |||
@@ -187,3 +187,8 @@ | |||
187 | 187 | ||
188 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 188 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
189 | 189 | ||
190 | |||
191 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
192 | * writes appear to be ~25% slower. | ||
193 | */ | ||
194 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/samsungyh925.h b/firmware/export/config/samsungyh925.h index 55d46ae1e1..c19901c019 100644 --- a/firmware/export/config/samsungyh925.h +++ b/firmware/export/config/samsungyh925.h | |||
@@ -185,3 +185,8 @@ | |||
185 | 185 | ||
186 | #define ICODE_ATTR_TREMOR_NOT_MDCT | 186 | #define ICODE_ATTR_TREMOR_NOT_MDCT |
187 | 187 | ||
188 | |||
189 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
190 | * writes appear to be ~25% slower. | ||
191 | */ | ||
192 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/export/config/tatungtpj1022.h b/firmware/export/config/tatungtpj1022.h index 079be73c86..aca131df8b 100644 --- a/firmware/export/config/tatungtpj1022.h +++ b/firmware/export/config/tatungtpj1022.h | |||
@@ -137,3 +137,8 @@ | |||
137 | #define BOOTFILE "rockbox." BOOTFILE_EXT | 137 | #define BOOTFILE "rockbox." BOOTFILE_EXT |
138 | #define BOOTDIR "/.rockbox" | 138 | #define BOOTDIR "/.rockbox" |
139 | 139 | ||
140 | |||
141 | /* DMA is used only for reading on PP502x because although reads are ~8x faster | ||
142 | * writes appear to be ~25% slower. | ||
143 | */ | ||
144 | #define HAVE_ATA_DMA | ||
diff --git a/firmware/target/arm/ata-pp5020.c b/firmware/target/arm/ata-pp5020.c index 8e2200c901..c8ce148dd7 100644 --- a/firmware/target/arm/ata-pp5020.c +++ b/firmware/target/arm/ata-pp5020.c | |||
@@ -48,6 +48,12 @@ void ata_device_init() | |||
48 | #ifdef SAMSUNG_YH920 | 48 | #ifdef SAMSUNG_YH920 |
49 | CPU_INT_DIS = (1<<IDE_IRQ); | 49 | CPU_INT_DIS = (1<<IDE_IRQ); |
50 | #endif | 50 | #endif |
51 | #ifdef HAVE_ATA_DMA | ||
52 | IDE_DMA_CONTROL |= 2; | ||
53 | IDE_DMA_CONTROL &= ~1; | ||
54 | IDE0_CFG &= ~0x8010; | ||
55 | IDE0_CFG |= 0x20; | ||
56 | #else | ||
51 | 57 | ||
52 | /* From ipod-ide.c:ipod_ide_register() */ | 58 | /* From ipod-ide.c:ipod_ide_register() */ |
53 | IDE0_CFG |= (1<<5); | 59 | IDE0_CFG |= (1<<5); |
@@ -56,7 +62,184 @@ void ata_device_init() | |||
56 | #else | 62 | #else |
57 | IDE0_CFG &=~(0x10000000); /* cpu < 65MHz */ | 63 | IDE0_CFG &=~(0x10000000); /* cpu < 65MHz */ |
58 | #endif | 64 | #endif |
65 | #endif | ||
59 | 66 | ||
60 | IDE0_PRI_TIMING0 = 0x10; | 67 | IDE0_PRI_TIMING0 = 0x10; |
61 | IDE0_PRI_TIMING1 = 0x80002150; | 68 | IDE0_PRI_TIMING1 = 0x80002150; |
62 | } | 69 | } |
70 | |||
71 | /* These are PIO timings for 80 Mhz. At 24 Mhz, | ||
72 | the first value is 0 but the rest are the same. | ||
73 | They go in IDE0_PRI_TIMING0. | ||
74 | |||
75 | Rockbox used 0x10, and test_disk shows that leads to faster PIO. | ||
76 | If 0x10 is incorrect, these timings may be needed with some devices. | ||
77 | static const unsigned long pio80mhz[] = { | ||
78 | 0xC293, 0x43A2, 0x11A1, 0x7232, 0x3131 | ||
79 | }; | ||
80 | */ | ||
81 | |||
82 | #ifdef HAVE_ATA_DMA | ||
83 | /* Timings for multi-word and ultra DMA modes. | ||
84 | These go in IDE0_PRI_TIMING1 | ||
85 | */ | ||
86 | static const unsigned long tm_mwdma[] = { | ||
87 | 0xF9F92, 0x56562, 0x45451 | ||
88 | }; | ||
89 | |||
90 | static const unsigned long tm_udma[] = { | ||
91 | 0x800037C1, 0x80003491, 0x80003371, | ||
92 | #if ATA_MAX_UDMA > 2 | ||
93 | 0x80003271, 0x80003071 | ||
94 | #endif | ||
95 | }; | ||
96 | |||
97 | #if ATA_MAX_UDMA > 2 | ||
98 | static bool dma_boosted = false; | ||
99 | static bool dma_needs_boost; | ||
100 | #endif | ||
101 | |||
102 | /* This function sets up registers for 80 Mhz. | ||
103 | Ultra DMA mode 2 works at 30 Mhz. | ||
104 | */ | ||
105 | void ata_dma_set_mode(unsigned char mode) { | ||
106 | int modeidx; | ||
107 | |||
108 | (*(volatile unsigned long *)(0x600060C4)) = 0xC0000000; /* 80 Mhz */ | ||
109 | IDE0_CFG &= ~0x10000000; | ||
110 | |||
111 | modeidx = mode & 7; | ||
112 | mode &= 0xF8; | ||
113 | if (mode == 0x40 && modeidx <= ATA_MAX_UDMA) { | ||
114 | IDE0_PRI_TIMING1 = tm_udma[modeidx]; | ||
115 | #if ATA_MAX_UDMA > 2 | ||
116 | if (modeidx > 2) | ||
117 | dma_needs_boost = true; | ||
118 | else | ||
119 | dma_needs_boost = false; | ||
120 | #endif | ||
121 | } else if (mode == 0x20 && modeidx <= ATA_MAX_MWDMA) | ||
122 | IDE0_PRI_TIMING1 = tm_mwdma[modeidx]; | ||
123 | |||
124 | IDE0_CFG |= 0x20000000; /* >= 50 Mhz */ | ||
125 | } | ||
126 | |||
127 | #define IDE_CFG_INTRQ 8 | ||
128 | #define IDE_DMA_CONTROL_READ 8 | ||
129 | |||
130 | /* This waits for an ATA interrupt using polling. | ||
131 | In ATA_CONTROL, CONTROL_nIEN must be cleared. | ||
132 | */ | ||
133 | STATICIRAM ICODE_ATTR int ata_wait_intrq(void) | ||
134 | { | ||
135 | long timeout = current_tick + HZ*10; | ||
136 | |||
137 | do | ||
138 | { | ||
139 | if (IDE0_CFG & IDE_CFG_INTRQ) | ||
140 | return 1; | ||
141 | ata_keep_active(); | ||
142 | yield(); | ||
143 | } while (TIME_BEFORE(current_tick, timeout)); | ||
144 | |||
145 | return 0; /* timeout */ | ||
146 | } | ||
147 | |||
148 | /* This function checks if parameters are appropriate for DMA, | ||
149 | and if they are, it sets up for DMA. | ||
150 | |||
151 | If return value is false, caller may use PIO for this transfer. | ||
152 | |||
153 | If return value is true, caller must issue a DMA ATA command | ||
154 | and then call ata_dma_finish(). | ||
155 | */ | ||
156 | bool ata_dma_setup(void *addr, unsigned long bytes, bool write) { | ||
157 | /* Require cacheline alignment for reads to prevent interference. */ | ||
158 | if (!write && ((unsigned long)addr & 15)) | ||
159 | return false; | ||
160 | |||
161 | /* Writes only need to be word-aligned, but by default DMA | ||
162 | * is not used for writing as it appears to be slower. | ||
163 | */ | ||
164 | #ifdef ATA_DMA_WRITES | ||
165 | if (write && ((unsigned long)addr & 3)) | ||
166 | return false; | ||
167 | #else | ||
168 | if (write) | ||
169 | return false; | ||
170 | #endif | ||
171 | |||
172 | #if ATA_MAX_UDMA > 2 | ||
173 | if (dma_needs_boost && !dma_boosted) { | ||
174 | cpu_boost(true); | ||
175 | dma_boosted = true; | ||
176 | } | ||
177 | #endif | ||
178 | |||
179 | if (write) { | ||
180 | /* If unflushed, old data may be written to disk */ | ||
181 | cpucache_flush(); | ||
182 | } | ||
183 | else { | ||
184 | /* Invalidate cache because new data may be present in RAM */ | ||
185 | cpucache_invalidate(); | ||
186 | } | ||
187 | |||
188 | /* Clear pending interrupts so ata_dma_finish() can wait for an | ||
189 | interrupt from this transfer | ||
190 | */ | ||
191 | IDE0_CFG |= IDE_CFG_INTRQ; | ||
192 | |||
193 | IDE_DMA_CONTROL |= 2; | ||
194 | IDE_DMA_LENGTH = bytes - 4; | ||
195 | |||
196 | #ifndef BOOTLOADER | ||
197 | if ((unsigned long)addr < DRAM_START) | ||
198 | /* Rockbox remaps DRAM to start at 0 */ | ||
199 | IDE_DMA_ADDR = (unsigned long)addr + DRAM_START; | ||
200 | else | ||
201 | #endif | ||
202 | IDE_DMA_ADDR = (unsigned long)addr; | ||
203 | |||
204 | if (write) | ||
205 | IDE_DMA_CONTROL &= ~IDE_DMA_CONTROL_READ; | ||
206 | else | ||
207 | IDE_DMA_CONTROL |= IDE_DMA_CONTROL_READ; | ||
208 | |||
209 | IDE0_CFG |= 0x8000; | ||
210 | |||
211 | return true; | ||
212 | } | ||
213 | |||
214 | /* This function waits for a DMA transfer to end. | ||
215 | It must be called to finish what ata_dma_setup started. | ||
216 | |||
217 | Return value is true if DMA completed before the timeout, and false | ||
218 | if a timeout happened. | ||
219 | */ | ||
220 | bool ata_dma_finish(void) { | ||
221 | bool res; | ||
222 | |||
223 | /* It may be okay to put this at the end of setup */ | ||
224 | IDE_DMA_CONTROL |= 1; | ||
225 | |||
226 | /* Wait for end of transfer. | ||
227 | Reading standard ATA status while DMA is in progress causes | ||
228 | failures and hangs. Because of that, another wait is used. | ||
229 | */ | ||
230 | res = ata_wait_intrq(); | ||
231 | |||
232 | IDE0_CFG &= ~0x8000; | ||
233 | IDE_DMA_CONTROL &= ~0x80000001; | ||
234 | |||
235 | #if ATA_MAX_UDMA > 2 | ||
236 | if (dma_boosted) { | ||
237 | cpu_boost(false); | ||
238 | dma_boosted = false; | ||
239 | } | ||
240 | #endif | ||
241 | |||
242 | return res; | ||
243 | } | ||
244 | |||
245 | #endif /* HAVE_ATA_DMA */ | ||
diff --git a/firmware/target/arm/ata-target.h b/firmware/target/arm/ata-target.h index 0881aaef35..82c5a5f555 100644 --- a/firmware/target/arm/ata-target.h +++ b/firmware/target/arm/ata-target.h | |||
@@ -81,3 +81,37 @@ void copy_write_sectors(const unsigned char* buf, int wordcount); | |||
81 | void ata_reset(void); | 81 | void ata_reset(void); |
82 | bool ata_is_coldstart(void); | 82 | bool ata_is_coldstart(void); |
83 | void ata_device_init(void); | 83 | void ata_device_init(void); |
84 | |||
85 | #ifdef HAVE_ATA_DMA | ||
86 | |||
87 | /* IDE DMA controller registers */ | ||
88 | #define IDE_DMA_CONTROL (*(volatile unsigned long *)(0xc3000400)) | ||
89 | #define IDE_DMA_LENGTH (*(volatile unsigned long *)(0xc3000408)) | ||
90 | #define IDE_DMA_ADDR (*(volatile unsigned long *)(0xc300040C)) | ||
91 | |||
92 | /* Maximum multi-word DMA mode supported by the controller */ | ||
93 | #define ATA_MAX_MWDMA 2 | ||
94 | |||
95 | #ifndef BOOTLOADER | ||
96 | /* The PP5020 supports UDMA 4, but it needs cpu boosting and only | ||
97 | * improves performance by ~10% with a stock disk. | ||
98 | * UDMA 2 is stable at 30 Mhz. | ||
99 | * UDMA 1 is stable at 24 Mhz. | ||
100 | */ | ||
101 | #if CPUFREQ_NORMAL >= 30000000 | ||
102 | #define ATA_MAX_UDMA 2 | ||
103 | #elif CPUFREQ_NORMAL >= 24000000 | ||
104 | #define ATA_MAX_UDMA 1 | ||
105 | #else | ||
106 | #error "CPU speeds under 24Mhz have not been tested with DMA" | ||
107 | #endif | ||
108 | #else | ||
109 | /* The bootloader runs at 24 Mhz and needs a slower mode */ | ||
110 | #define ATA_MAX_UDMA 1 | ||
111 | #endif | ||
112 | |||
113 | void ata_dma_set_mode(unsigned char mode); | ||
114 | bool ata_dma_setup(void *addr, unsigned long bytes, bool write); | ||
115 | bool ata_dma_finish(void); | ||
116 | |||
117 | #endif /* HAVE_ATA_DMA */ | ||