summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2009-03-12 06:31:40 +0000
committerMichael Sevakis <jethead71@rockbox.org>2009-03-12 06:31:40 +0000
commita1a332e04bf937d164746f06c8f71fab547fc271 (patch)
tree71fbd805fb2689746e69fabf980e88ed661ab893
parentbc8cab4c24a0891182ac9711c67165a9e3373b1c (diff)
downloadrockbox-a1a332e04bf937d164746f06c8f71fab547fc271.tar.gz
rockbox-a1a332e04bf937d164746f06c8f71fab547fc271.zip
Gigabeat S: Implement MDMA and UDMA disk access for bootloader and main binary. Add a needed SDMA API to check channel errors. Increase audio DMA channels' priority as required. Reads and writes measure faster accross all test_disk tests and especially at 4KB and 1MB.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20299 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/export/config-gigabeat-s.h3
-rwxr-xr-xfirmware/export/imx31l.h4
-rw-r--r--firmware/target/arm/imx31/boot.lds2
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-imx31.c551
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-target.h11
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c2
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c4
-rw-r--r--firmware/target/arm/imx31/sdma-imx31.c8
-rw-r--r--firmware/target/arm/imx31/sdma-imx31.h3
10 files changed, 563 insertions, 27 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 29ee03d040..d7d2b6939d 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -760,6 +760,7 @@ target/arm/lcd-as-memframe.S
760target/arm/mmu-arm.S 760target/arm/mmu-arm.S
761target/arm/imx31/debug-imx31.c 761target/arm/imx31/debug-imx31.c
762target/arm/imx31/rolo_restart.S 762target/arm/imx31/rolo_restart.S
763target/arm/imx31/sdma-imx31.c
763target/arm/imx31/gigabeat-s/adc-imx31.c 764target/arm/imx31/gigabeat-s/adc-imx31.c
764target/arm/imx31/gigabeat-s/ata-imx31.c 765target/arm/imx31/gigabeat-s/ata-imx31.c
765target/arm/imx31/gigabeat-s/avic-imx31.c 766target/arm/imx31/gigabeat-s/avic-imx31.c
@@ -782,7 +783,6 @@ target/arm/imx31/gigabeat-s/system-imx31.c
782target/arm/imx31/gigabeat-s/usb-imx31.c 783target/arm/imx31/gigabeat-s/usb-imx31.c
783target/arm/imx31/gigabeat-s/wmcodec-imx31.c 784target/arm/imx31/gigabeat-s/wmcodec-imx31.c
784#ifndef BOOTLOADER 785#ifndef BOOTLOADER
785target/arm/imx31/sdma-imx31.c
786target/arm/imx31/gigabeat-s/audio-gigabeat-s.c 786target/arm/imx31/gigabeat-s/audio-gigabeat-s.c
787target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c 787target/arm/imx31/gigabeat-s/fmradio-i2c-gigabeat-s.c
788target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c 788target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c
diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h
index f55a4fd382..17ee39352c 100644
--- a/firmware/export/config-gigabeat-s.h
+++ b/firmware/export/config-gigabeat-s.h
@@ -186,6 +186,9 @@
186/* Define this if you have ATA power-off control */ 186/* Define this if you have ATA power-off control */
187#define HAVE_ATA_POWER_OFF 187#define HAVE_ATA_POWER_OFF
188 188
189/* Define this to add support for ATA DMA */
190#define HAVE_ATA_DMA
191
189/* Virtual LED (icon) */ 192/* Virtual LED (icon) */
190#define CONFIG_LED LED_VIRTUAL 193#define CONFIG_LED LED_VIRTUAL
191 194
diff --git a/firmware/export/imx31l.h b/firmware/export/imx31l.h
index 49084c0d8e..ea2187e0c2 100755
--- a/firmware/export/imx31l.h
+++ b/firmware/export/imx31l.h
@@ -497,11 +497,11 @@
497#define ATA_IORDY_EN (1 << 0) 497#define ATA_IORDY_EN (1 << 0)
498 498
499/* ATA_INTERRUPT_PENDING, ATA_INTERRUPT_ENABLE, ATA_INTERRUPT_CLEAR flags */ 499/* ATA_INTERRUPT_PENDING, ATA_INTERRUPT_ENABLE, ATA_INTERRUPT_CLEAR flags */
500#define ATA_INTRQ1 (1 << 7) 500#define ATA_INTRQ1 (1 << 7) /* INTRQ to the DMA */
501#define ATA_FIFO_UNDERFLOW (1 << 6) 501#define ATA_FIFO_UNDERFLOW (1 << 6)
502#define ATA_FIFO_OVERFLOW (1 << 5) 502#define ATA_FIFO_OVERFLOW (1 << 5)
503#define ATA_CONTROLLER_IDLE (1 << 4) 503#define ATA_CONTROLLER_IDLE (1 << 4)
504#define ATA_INTRQ2 (1 << 3) 504#define ATA_INTRQ2 (1 << 3) /* INTRQ to the MCU */
505 505
506/* EPIT */ 506/* EPIT */
507#define EPITCR1 (*(REG32_PTR_T)(EPIT1_BASE_ADDR+0x00)) 507#define EPITCR1 (*(REG32_PTR_T)(EPIT1_BASE_ADDR+0x00))
diff --git a/firmware/target/arm/imx31/boot.lds b/firmware/target/arm/imx31/boot.lds
index b108ba181d..e08b4bfb7a 100644
--- a/firmware/target/arm/imx31/boot.lds
+++ b/firmware/target/arm/imx31/boot.lds
@@ -55,6 +55,8 @@ SECTIONS
55 *(.idata) 55 *(.idata)
56 *(.data*) 56 *(.data*)
57 . = ALIGN(0x4); 57 . = ALIGN(0x4);
58 *(.sdmacode)
59 . = ALIGN(0x4);
58 _dataend = . ; 60 _dataend = . ;
59 } > DRAM 61 } > DRAM
60 62
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c b/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c
index 59b89c02c9..c32dead30a 100644
--- a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c
@@ -28,7 +28,12 @@
28#include "ata.h" 28#include "ata.h"
29#include "ata-target.h" 29#include "ata-target.h"
30#include "clkctl-imx31.h" 30#include "clkctl-imx31.h"
31#ifdef HAVE_ATA_DMA
32#include "sdma-imx31.h"
33#include "mmu-imx31.h"
34#endif
31 35
36/* PIO modes timing info */
32static const struct ata_pio_timings 37static const struct ata_pio_timings
33{ 38{
34 uint16_t time_2w; /* t2 during write */ 39 uint16_t time_2w; /* t2 during write */
@@ -83,26 +88,217 @@ static const struct ata_pio_timings
83 .time_ax = 35, 88 .time_ax = 35,
84 .time_4 = 10, 89 .time_4 = 10,
85 .time_9 = 10 90 .time_9 = 10
91 }
92};
93
94/* Track first init */
95static bool initialized = false;
96
97#ifdef HAVE_ATA_DMA
98/* One DMA channel for reads, the other for writes othewise one channel would
99 * have to be reinitialized every time the direction changed. (Different
100 * SDMA scripts are used for reading or writing) */
101#define ATA_DMA_CH_NUM_RD 3
102#define ATA_DMA_CH_NUM_WR 4
103/* Use default priority for these channels (1) - ATA isn't realtime urgent. */
104/* Maximum DMA size per buffer descriptor (32-byte aligned) */
105#define ATA_MAX_BD_SIZE (65534 & ~31) /* 65504 */
106
107/* Number of buffer descriptors required for a maximum sector count trasfer.
108 * NOTE: Assumes LBA28 and 512-byte sectors! */
109#define ATA_BASE_BD_COUNT ((256*512 + (ATA_MAX_BD_SIZE-1)) / ATA_MAX_BD_SIZE)
110#define ATA_BD_COUNT (ATA_BASE_BD_COUNT + 2)
111
112static const struct ata_mdma_timings
113{
114 uint8_t time_m; /* tM */
115 uint8_t time_jn; /* tH */
116 uint8_t time_d; /* tD */
117 uint8_t time_k; /* tKW */
118} mdma_timings[] =
119{
120 [0] = /* MDMA mode 0 */
121 {
122 .time_m = 50,
123 .time_jn = 20,
124 .time_d = 215,
125 .time_k = 215
86 }, 126 },
127 [1] = /* MDMA mode 1 */
128 {
129 .time_m = 30,
130 .time_jn = 15,
131 .time_d = 80,
132 .time_k = 50
133 },
134 [2] = /* MDMA mode 2 */
135 {
136 .time_m = 25,
137 .time_jn = 10,
138 .time_d = 70,
139 .time_k = 25
140 }
87}; 141};
88 142
89static int pio_mode = 0; /* Setup mode 0 by default */ 143static const struct ata_udma_timings
144{
145 uint8_t time_ack; /* tACK */
146 uint8_t time_env; /* tENV */
147 uint8_t time_rpx; /* tRP */
148 uint8_t time_zah; /* tZAH */
149 uint8_t time_mlix; /* tMLI */
150 uint8_t time_dvh; /* tDVH */
151 uint8_t time_dzfs; /* tDVS+tDVH? */
152 uint8_t time_dvs; /* tDVS */
153 uint8_t time_cvh; /* ?? */
154 uint8_t time_ss; /* tSS */
155 uint8_t time_cyc; /* tCYC */
156} udma_timings[] =
157{
158 [0] = /* UDMA mode 0 */
159 {
160 .time_ack = 20,
161 .time_env = 20,
162 .time_rpx = 160,
163 .time_zah = 20,
164 .time_mlix = 20,
165 .time_dvh = 6,
166 .time_dzfs = 80,
167 .time_dvs = 70,
168 .time_cvh = 6,
169 .time_ss = 50,
170 .time_cyc = 114
171 },
172 [1] = /* UDMA mode 1 */
173 {
174 .time_ack = 20,
175 .time_env = 20,
176 .time_rpx = 125,
177 .time_zah = 20,
178 .time_mlix = 20,
179 .time_dvh = 6,
180 .time_dzfs = 63,
181 .time_dvs = 48,
182 .time_cvh = 6,
183 .time_ss = 50,
184 .time_cyc = 75
185 },
186 [2] = /* UDMA mode 2 */
187 {
188 .time_ack = 20,
189 .time_env = 20,
190 .time_rpx = 100,
191 .time_zah = 20,
192 .time_mlix = 20,
193 .time_dvh = 6,
194 .time_dzfs = 47,
195 .time_dvs = 34,
196 .time_cvh = 6,
197 .time_ss = 50,
198 .time_cyc = 55
199 },
200 [3] = /* UDMA mode 3 */
201 {
202 .time_ack = 20,
203 .time_env = 20,
204 .time_rpx = 100,
205 .time_zah = 20,
206 .time_mlix = 20,
207 .time_dvh = 6,
208 .time_dzfs = 35,
209 .time_dvs = 20,
210 .time_cvh = 6,
211 .time_ss = 50,
212 .time_cyc = 39
213 },
214 [4] = /* UDMA mode 4 */
215 {
216 .time_ack = 20,
217 .time_env = 20,
218 .time_rpx = 100,
219 .time_zah = 20,
220 .time_mlix = 20,
221 .time_dvh = 6,
222 .time_dzfs = 25,
223 .time_dvs = 7,
224 .time_cvh = 6,
225 .time_ss = 50,
226 .time_cyc = 25
227 },
228#if 0
229 [5] = /* UDMA mode 5 (bus clock 80MHz or higher only) */
230 {
231 .time_ack = 20,
232 .time_env = 20,
233 .time_rpx = 85,
234 .time_zah = 20,
235 .time_mlix = 20,
236 .time_dvh = 6,
237 .time_dzfs = 40,
238 .time_dvs = 5,
239 .time_cvh = 10,
240 .time_ss = 50,
241 .time_cyc = 17
242 }
243#endif
244};
245
246/** Threading **/
247/* Signal to tell thread when DMA is done */
248static struct wakeup ata_dma_wakeup;
249
250/** SDMA **/
251/* Array of buffer descriptors for large transfers and alignnment */
252static struct buffer_descriptor ata_bda[ATA_BD_COUNT] DEVBSS_ATTR;
253/* ATA channel descriptors */
254static struct channel_descriptor ata_cd_rd DEVBSS_ATTR; /* read channel */
255static struct channel_descriptor ata_cd_wr DEVBSS_ATTR; /* write channel */
256/* DMA channel to be started for transfer */
257static unsigned int current_channel = 0;
258
259/** Buffers **/
260/* Scatter buffer for first and last 32 bytes of a non cache-aligned transfer
261 * to cached RAM. */
262static uint32_t scatter_buffer[32/4*2] DEVBSS_ATTR;
263/* Address of ends in destination buffer for unaligned reads - copied after
264 * DMA completes. */
265static void *sb_dst[2] = { NULL, NULL };
266
267/** Modes **/
268#define ATA_DMA_MWDMA 0x00000000 /* Using multiword DMA */
269#define ATA_DMA_UDMA ATA_DMA_ULTRA_SELECTED /* Using Ultra DMA */
270#define ATA_DMA_PIO 0x80000000 /* Using PIO */
271#define ATA_DMA_DISABLED 0x80000001 /* DMA init error - use PIO */
272static unsigned long ata_dma_selected = ATA_DMA_PIO;
273#endif /* HAVE_ATA_DMA */
274
275static unsigned int get_T(void)
276{
277 /* T = ATA clock period in nanoseconds */
278 return 1000 * 1000 * 1000 / imx31_clkctl_get_ata_clk();
279}
90 280
91static void ata_wait_for_idle(void) 281static void ata_wait_for_idle(void)
92{ 282{
93 while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE)); 283 while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE));
94} 284}
95 285
286/* Route the INTRQ to either the MCU or SDMA depending upon whether there is
287 * a DMA transfer in progress. */
288static inline void ata_set_intrq(bool to_dma)
289{
290 ATA_INTERRUPT_ENABLE =
291 (ATA_INTERRUPT_ENABLE & ~(ATA_INTRQ1 | ATA_INTRQ2)) |
292 (to_dma ? ATA_INTRQ1 : ATA_INTRQ2);
293}
294
96/* Setup the timing for PIO mode */ 295/* Setup the timing for PIO mode */
97void ata_set_pio_timings(int mode) 296void ata_set_pio_timings(int mode)
98{ 297{
99 ata_wait_for_idle();
100
101 const struct ata_pio_timings * const timings = &pio_timings[mode]; 298 const struct ata_pio_timings * const timings = &pio_timings[mode];
102 /* T = period in nanoseconds */ 299 unsigned int T = get_T();
103 int T = 1000 * 1000 * 1000 / imx31_clkctl_get_ata_clk();
104 300
105 pio_mode = mode; 301 ata_wait_for_idle();
106 302
107 ATA_TIME_1 = (timings->time_1 + T) / T; 303 ATA_TIME_1 = (timings->time_1 + T) / T;
108 ATA_TIME_2W = (timings->time_2w + T) / T; 304 ATA_TIME_2W = (timings->time_2w + T) / T;
@@ -118,10 +314,10 @@ void ata_reset(void)
118 /* Be sure we're not busy */ 314 /* Be sure we're not busy */
119 ata_wait_for_idle(); 315 ata_wait_for_idle();
120 316
121 ATA_INTF_CONTROL &= ~ATA_ATA_RST; 317 ATA_INTF_CONTROL &= ~(ATA_ATA_RST | ATA_FIFO_RST);
122 sleep(1); 318 sleep(HZ/100);
123 ATA_INTF_CONTROL |= ATA_ATA_RST; 319 ATA_INTF_CONTROL = ATA_ATA_RST | ATA_FIFO_RST;
124 sleep(1); 320 sleep(HZ/100);
125 321
126 ata_wait_for_idle(); 322 ata_wait_for_idle();
127} 323}
@@ -130,16 +326,17 @@ void ata_enable(bool on)
130{ 326{
131 /* Unconditionally clock module before writing regs */ 327 /* Unconditionally clock module before writing regs */
132 imx31_clkctl_module_clock_gating(CG_ATA, CGM_ON_ALL); 328 imx31_clkctl_module_clock_gating(CG_ATA, CGM_ON_ALL);
329 ata_wait_for_idle();
133 330
134 if (on) 331 if (on)
135 { 332 {
136 ATA_INTF_CONTROL |= ATA_ATA_RST; 333 ATA_INTF_CONTROL = ATA_ATA_RST | ATA_FIFO_RST;
334 sleep(HZ/100);
137 } 335 }
138 else 336 else
139 { 337 {
140 ata_wait_for_idle(); 338 ATA_INTF_CONTROL &= ~(ATA_ATA_RST | ATA_FIFO_RST);
141 339 sleep(HZ/100);
142 ATA_INTF_CONTROL &= ~ATA_ATA_RST;
143 340
144 /* Disable off - unclock ATA module */ 341 /* Disable off - unclock ATA module */
145 imx31_clkctl_module_clock_gating(CG_ATA, CGM_OFF); 342 imx31_clkctl_module_clock_gating(CG_ATA, CGM_OFF);
@@ -151,16 +348,338 @@ bool ata_is_coldstart(void)
151 return true; 348 return true;
152} 349}
153 350
351#ifdef HAVE_ATA_DMA
352static void ata_set_mdma_timings(unsigned int mode)
353{
354 const struct ata_mdma_timings * const timings = &mdma_timings[mode];
355 unsigned int T = get_T();
356
357 ATA_TIME_M = (timings->time_m + T) / T;
358 ATA_TIME_JN = (timings->time_jn + T) / T;
359 ATA_TIME_D = (timings->time_d + T) / T;
360 ATA_TIME_K = (timings->time_k + T) / T;
361}
362
363static void ata_set_udma_timings(unsigned int mode)
364{
365 const struct ata_udma_timings * const timings = &udma_timings[mode];
366 unsigned int T = get_T();
367
368 ATA_TIME_ACK = (timings->time_ack + T) / T;
369 ATA_TIME_ENV = (timings->time_env + T) / T;
370 ATA_TIME_RPX = (timings->time_rpx + T) / T;
371 ATA_TIME_ZAH = (timings->time_zah + T) / T;
372 ATA_TIME_MLIX = (timings->time_mlix + T) / T;
373 ATA_TIME_DVH = (timings->time_dvh + T) / T + 1;
374 ATA_TIME_DZFS = (timings->time_dzfs + T) / T;
375 ATA_TIME_DVS = (timings->time_dvs + T) / T;
376 ATA_TIME_CVH = (timings->time_cvh + T) / T;
377 ATA_TIME_SS = (timings->time_ss + T) / T;
378 ATA_TIME_CYC = (timings->time_cyc + T) / T;
379}
380
381void ata_dma_set_mode(unsigned char mode)
382{
383 unsigned int modeidx = mode & 0x07;
384 unsigned int dmamode = mode & 0xf8;
385
386 ata_wait_for_idle();
387
388 if (ata_dma_selected == ATA_DMA_DISABLED)
389 {
390 /* Configuration error - no DMA */
391 }
392 else if (dmamode == 0x40 && modeidx <= ATA_MAX_UDMA)
393 {
394 /* Using Ultra DMA */
395 ata_set_udma_timings(dmamode);
396 ata_dma_selected = ATA_DMA_UDMA;
397 }
398 else if (dmamode == 0x20 && modeidx <= ATA_MAX_MWDMA)
399 {
400 /* Using Multiword DMA */
401 ata_set_mdma_timings(dmamode);
402 ata_dma_selected = ATA_DMA_MWDMA;
403 }
404 else
405 {
406 /* Don't understand this - force PIO. */
407 ata_dma_selected = ATA_DMA_PIO;
408 }
409}
410
411/* Called by SDMA when transfer is complete */
412static void ata_dma_callback(void)
413{
414 /* Clear FIFO if not empty - shouldn't happen */
415 while (ATA_FIFO_FILL != 0)
416 ATA_FIFO_DATA_32;
417
418 /* Clear FIFO interrupts (the only ones that can be) */
419 ATA_INTERRUPT_CLEAR = ATA_INTERRUPT_PENDING;
420
421 ata_set_intrq(false); /* Return INTRQ to MCU */
422 wakeup_signal(&ata_dma_wakeup); /* Signal waiting thread */
423}
424
425bool ata_dma_setup(void *addr, unsigned long bytes, bool write)
426{
427 struct buffer_descriptor *bd_p;
428 unsigned char *buf;
429
430 if (UNLIKELY(bytes > ATA_BASE_BD_COUNT*ATA_MAX_BD_SIZE ||
431 (ata_dma_selected & ATA_DMA_PIO)))
432 {
433 /* Too much? Implies BD count should be reevaluated since this
434 * shouldn't be reached based upon size. Otherwise we simply didn't
435 * understand the DMA mode setup. Force PIO in both cases. */
436 ATA_INTF_CONTROL = ATA_FIFO_RST | ATA_ATA_RST;
437 return false;
438 }
439
440 bd_p = &ata_bda[0];
441 buf = (unsigned char *)addr_virt_to_phys((unsigned long)addr);
442 sb_dst[0] = NULL; /* Assume not needed */
443
444 if (write)
445 {
446 /* No cache alignment concerns */
447 current_channel = ATA_DMA_CH_NUM_WR;
448
449 if (LIKELY(buf != addr))
450 {
451 /* addr is virtual */
452 clean_dcache_range(addr, bytes);
453 }
454
455 /* Setup ATA controller for DMA transmit */
456 ATA_INTF_CONTROL = ATA_FIFO_RST | ATA_ATA_RST | ATA_FIFO_TX_EN |
457 ATA_DMA_PENDING | ata_dma_selected | ATA_DMA_WRITE;
458 ATA_FIFO_ALARM = SDMA_ATA_WML / 2;
459 }
460 else
461 {
462 current_channel = ATA_DMA_CH_NUM_RD;
463
464 /* Setup ATA controller for DMA receive */
465 ATA_INTF_CONTROL = ATA_FIFO_RST | ATA_ATA_RST | ATA_FIFO_RCV_EN |
466 ATA_DMA_PENDING | ata_dma_selected;
467 ATA_FIFO_ALARM = SDMA_ATA_WML / 2;
468
469 if (LIKELY(buf != addr))
470 {
471 /* addr is virtual */
472 dump_dcache_range(addr, bytes);
473
474 if ((unsigned long)addr & 31)
475 {
476 /* Not cache aligned, must use scatter buffers for first and
477 * last 32 bytes. */
478 unsigned char *bufstart = buf;
479
480 sb_dst[0] = addr;
481 bd_p->buf_addr = scatter_buffer;
482 bd_p->mode.count = 32;
483 bd_p->mode.status = BD_DONE | BD_CONT;
484
485 buf += 32;
486 bytes -= 32;
487 bd_p++;
488
489 while (bytes > ATA_MAX_BD_SIZE)
490 {
491 bd_p->buf_addr = buf;
492 bd_p->mode.count = ATA_MAX_BD_SIZE;
493 bd_p->mode.status = BD_DONE | BD_CONT;
494 buf += ATA_MAX_BD_SIZE;
495 bytes -= ATA_MAX_BD_SIZE;
496 bd_p++;
497 }
498
499 if (bytes > 32)
500 {
501 unsigned long size = bytes - 32;
502 bd_p->buf_addr = buf;
503 bd_p->mode.count = size;
504 bd_p->mode.status = BD_DONE | BD_CONT;
505 buf += size;
506 bd_p++;
507 }
508
509 /* There will be exactly 32 bytes left */
510
511 /* Final buffer - wrap to base bd, interrupt */
512 sb_dst[1] = addr + (buf - bufstart);
513 bd_p->buf_addr = &scatter_buffer[32/4];
514 bd_p->mode.count = 32;
515 bd_p->mode.status = BD_DONE | BD_WRAP | BD_INTR;
516
517 return true;
518 }
519 }
520 }
521
522 /* Setup buffer descriptors for both cache-aligned reads and all write
523 * operations. */
524 while (bytes > ATA_MAX_BD_SIZE)
525 {
526 bd_p->buf_addr = buf;
527 bd_p->mode.count = ATA_MAX_BD_SIZE;
528 bd_p->mode.status = BD_DONE | BD_CONT;
529 buf += ATA_MAX_BD_SIZE;
530 bytes -= ATA_MAX_BD_SIZE;
531 bd_p++;
532 }
533
534 /* Final buffer - wrap to base bd, interrupt */
535 bd_p->buf_addr = buf;
536 bd_p->mode.count = bytes;
537 bd_p->mode.status = BD_DONE | BD_WRAP | BD_INTR;
538
539 return true;
540}
541
542bool ata_dma_finish(void)
543{
544 unsigned int channel = current_channel;
545 long timeout = current_tick + HZ*10;
546
547 current_channel = 0;
548
549 ata_set_intrq(true); /* Give INTRQ to DMA */
550 sdma_channel_run(channel); /* Kick the channel to wait for events */
551
552 while (1)
553 {
554 int oldirq;
555
556 if (LIKELY(wakeup_wait(&ata_dma_wakeup, HZ/2) == OBJ_WAIT_SUCCEEDED))
557 break;
558
559 ata_keep_active();
560
561 if (TIME_BEFORE(current_tick, timeout))
562 continue;
563
564 /* Epic fail - timed out - maybe. */
565 oldirq = disable_irq_save();
566 ata_set_intrq(false); /* Strip INTRQ from DMA */
567 sdma_channel_stop(channel); /* Stop DMA */
568 restore_irq(oldirq);
569
570 if (wakeup_wait(&ata_dma_wakeup, TIMEOUT_NOBLOCK) == OBJ_WAIT_SUCCEEDED)
571 break; /* DMA really did finish after timeout */
572
573 sdma_channel_reset(channel); /* Reset everything + clear error */
574 return false;
575 }
576
577 if (sdma_channel_is_error(channel))
578 {
579 /* Channel error in one or more descriptors */
580 sdma_channel_reset(channel); /* Reset everything + clear error */
581 return false;
582 }
583
584 if (sb_dst[0] != NULL)
585 {
586 /* NOTE: This requires that unaligned access support be enabled! */
587 register void *sbs = scatter_buffer;
588 register void *sbd0 = sb_dst[0];
589 register void *sbd1 = sb_dst[1];
590 asm volatile(
591 "add r0, %1, #32 \n" /* Prefetch at DMA-direct boundaries */
592 "mcrr p15, 2, r0, r0, c12 \n"
593 "mcrr p15, 2, %2, %2, c12 \n"
594 "ldmia %0!, { r0-r3 } \n" /* Copy the 32-bytes to destination */
595 "str r0, [%1], #4 \n" /* stmia doesn't work unaligned */
596 "str r1, [%1], #4 \n"
597 "str r2, [%1], #4 \n"
598 "str r3, [%1], #4 \n"
599 "ldmia %0!, { r0-r3 } \n"
600 "str r0, [%1], #4 \n"
601 "str r1, [%1], #4 \n"
602 "str r2, [%1], #4 \n"
603 "str r3, [%1] \n"
604 "ldmia %0!, { r0-r3 } \n" /* Copy the 32-bytes to destination */
605 "str r0, [%2], #4 \n" /* stmia doesn't work unaligned */
606 "str r1, [%2], #4 \n"
607 "str r2, [%2], #4 \n"
608 "str r3, [%2], #4 \n"
609 "ldmia %0!, { r0-r3 } \n"
610 "str r0, [%2], #4 \n"
611 "str r1, [%2], #4 \n"
612 "str r2, [%2], #4 \n"
613 "str r3, [%2] \n"
614 : "+r"(sbs), "+r"(sbd0), "+r"(sbd1)
615 :
616 : "r0", "r1", "r2", "r3");
617 }
618
619 return true;
620}
621#endif /* HAVE_ATA_DMA */
622
154void ata_device_init(void) 623void ata_device_init(void)
155{ 624{
156 /* Make sure we're not in reset mode */ 625 /* Make sure we're not in reset mode */
157 ata_enable(true); 626 ata_enable(true);
158 627
628 if (!initialized)
629 {
630 ATA_INTERRUPT_ENABLE = 0;
631 ATA_INTERRUPT_CLEAR = ATA_INTERRUPT_PENDING;
632 }
633
634 ata_set_intrq(false);
635
636 if (initialized)
637 return;
638
159 /* All modes use same tOFF/tON */ 639 /* All modes use same tOFF/tON */
160 ATA_TIME_OFF = 3; 640 ATA_TIME_OFF = 3;
161 ATA_TIME_ON = 3; 641 ATA_TIME_ON = 3;
162 642
163 /* mode may be switched later once identify info is ready in which 643 /* Setup mode 0 for all by default
644 * Mode may be switched later once identify info is ready in which
164 * case the main driver calls back */ 645 * case the main driver calls back */
165 ata_set_pio_timings(pio_mode); 646 ata_set_pio_timings(0);
647
648#ifdef HAVE_ATA_DMA
649 ata_set_mdma_timings(0);
650 ata_set_udma_timings(0);
651
652 ata_dma_selected = ATA_DMA_PIO;
653
654 /* Called for first time at startup */
655 wakeup_init(&ata_dma_wakeup);
656
657 /* Read/write channels share buffer descriptors */
658 ata_cd_rd.bd_count = ATA_BD_COUNT;
659 ata_cd_rd.callback = ata_dma_callback;
660 ata_cd_rd.shp_addr = SDMA_PER_ADDR_ATA_RX;
661 ata_cd_rd.wml = SDMA_ATA_WML;
662 ata_cd_rd.per_type = SDMA_PER_ATA;
663 ata_cd_rd.tran_type = SDMA_TRAN_PER_2_EMI;
664 ata_cd_rd.event_id1 = SDMA_REQ_ATA_TXFER_END;
665 ata_cd_rd.event_id2 = SDMA_REQ_ATA_RX;
666
667 ata_cd_wr.bd_count = ATA_BD_COUNT;
668 ata_cd_wr.callback = ata_dma_callback;
669 ata_cd_wr.shp_addr = SDMA_PER_ADDR_ATA_TX;
670 ata_cd_wr.wml = SDMA_ATA_WML;
671 ata_cd_wr.per_type = SDMA_PER_ATA;
672 ata_cd_wr.tran_type = SDMA_TRAN_EMI_2_PER;
673 ata_cd_wr.event_id1 = SDMA_REQ_ATA_TXFER_END;
674 ata_cd_wr.event_id2 = SDMA_REQ_ATA_TX;
675
676 if (!sdma_channel_init(ATA_DMA_CH_NUM_RD, &ata_cd_rd, ata_bda) ||
677 !sdma_channel_init(ATA_DMA_CH_NUM_WR, &ata_cd_wr, ata_bda))
678 {
679 /* Channel init error - disable DMA forever */
680 ata_dma_selected = ATA_DMA_DISABLED;
681 }
682#endif /* HAVE_ATA_DMA */
683
684 initialized = true;
166} 685}
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-target.h b/firmware/target/arm/imx31/gigabeat-s/ata-target.h
index f9579a242d..8b308f28b5 100644
--- a/firmware/target/arm/imx31/gigabeat-s/ata-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/ata-target.h
@@ -26,13 +26,14 @@
26#endif 26#endif
27 27
28/* Plain C read & write loops */ 28/* Plain C read & write loops */
29/* They likely won't be used anyway since DMA potentially works for any
30 * sector number and alignment. */
29#define PREFER_C_READING 31#define PREFER_C_READING
30#define PREFER_C_WRITING 32#define PREFER_C_WRITING
31#if 0 33
32#if !defined(BOOTLOADER) 34#ifdef HAVE_ATA_DMA
33#define ATA_OPTIMIZED_WRITING 35#define ATA_MAX_MWDMA 2
34void copy_write_sectors(const unsigned char* buf, int wordcount); 36#define ATA_MAX_UDMA 4
35#endif
36#endif 37#endif
37 38
38#define ATA_DATA ATA_DRIVE_DATA 39#define ATA_DATA ATA_DRIVE_DATA
diff --git a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
index ff0c47abc2..a2f3d779eb 100644
--- a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
@@ -65,9 +65,7 @@ void tick_start(unsigned int interval_in_ms)
65 65
66void kernel_device_init(void) 66void kernel_device_init(void)
67{ 67{
68#ifndef BOOTLOADER
69 sdma_init(); 68 sdma_init();
70#endif
71 spi_init(); 69 spi_init();
72 mc13783_init(); 70 mc13783_init();
73} 71}
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
index 649186ab2e..deaa2a0dcd 100644
--- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
@@ -29,6 +29,8 @@
29 29
30#define DMA_PLAY_CH_NUM 2 30#define DMA_PLAY_CH_NUM 2
31#define DMA_REC_CH_NUM 1 31#define DMA_REC_CH_NUM 1
32#define DMA_PLAY_CH_PRIORITY 6
33#define DMA_REC_CH_PRIORITY 6
32 34
33static struct buffer_descriptor dma_play_bd DEVBSS_ATTR; 35static struct buffer_descriptor dma_play_bd DEVBSS_ATTR;
34static struct channel_descriptor dma_play_cd DEVBSS_ATTR; 36static struct channel_descriptor dma_play_cd DEVBSS_ATTR;
@@ -126,6 +128,7 @@ void pcm_play_dma_init(void)
126 dma_play_cd.event_id1 = SDMA_REQ_SSI2_TX1; 128 dma_play_cd.event_id1 = SDMA_REQ_SSI2_TX1;
127 129
128 sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd); 130 sdma_channel_init(DMA_PLAY_CH_NUM, &dma_play_cd, &dma_play_bd);
131 sdma_channel_set_priority(DMA_PLAY_CH_NUM, DMA_PLAY_CH_PRIORITY);
129 132
130 imx31_clkctl_module_clock_gating(CG_SSI1, CGM_ON_ALL); 133 imx31_clkctl_module_clock_gating(CG_SSI1, CGM_ON_ALL);
131 imx31_clkctl_module_clock_gating(CG_SSI2, CGM_ON_ALL); 134 imx31_clkctl_module_clock_gating(CG_SSI2, CGM_ON_ALL);
@@ -518,6 +521,7 @@ void pcm_rec_dma_init(void)
518 dma_rec_cd.event_id1 = SDMA_REQ_SSI1_RX1; 521 dma_rec_cd.event_id1 = SDMA_REQ_SSI1_RX1;
519 522
520 sdma_channel_init(DMA_REC_CH_NUM, &dma_rec_cd, &dma_rec_bd); 523 sdma_channel_init(DMA_REC_CH_NUM, &dma_rec_cd, &dma_rec_bd);
524 sdma_channel_set_priority(DMA_REC_CH_NUM, DMA_REC_CH_PRIORITY);
521} 525}
522 526
523const void * pcm_rec_dma_get_peak_buffer(int *count) 527const void * pcm_rec_dma_get_peak_buffer(int *count)
diff --git a/firmware/target/arm/imx31/sdma-imx31.c b/firmware/target/arm/imx31/sdma-imx31.c
index d1611d6332..4c5674afb9 100644
--- a/firmware/target/arm/imx31/sdma-imx31.c
+++ b/firmware/target/arm/imx31/sdma-imx31.c
@@ -468,6 +468,8 @@ static bool setup_channel(struct channel_control_block *ccb_p)
468 CHANNEL_CONTEXT_ADDR(channel), 468 CHANNEL_CONTEXT_ADDR(channel),
469 sizeof (context_buffer)/4); 469 sizeof (context_buffer)/4);
470 470
471 ccb_p->status.error = 0; /* Clear channel-wide error flag */
472
471 if (cd_p->is_setup != 0) 473 if (cd_p->is_setup != 0)
472 return true; /* No more to do */ 474 return true; /* No more to do */
473 475
@@ -759,6 +761,12 @@ void sdma_channel_close(unsigned int channel)
759 memset(ccb_p, 0x00, sizeof (struct channel_control_block)); 761 memset(ccb_p, 0x00, sizeof (struct channel_control_block));
760} 762}
761 763
764/* Check channel-wide error flag */
765bool sdma_channel_is_error(unsigned int channel)
766{
767 return channel < CH_NUM && ccb_array[channel].status.error;
768}
769
762/* Write 32-bit words to SDMA core memory. Host endian->SDMA endian. */ 770/* Write 32-bit words to SDMA core memory. Host endian->SDMA endian. */
763void sdma_write_words(const unsigned long *buf, unsigned long start, int count) 771void sdma_write_words(const unsigned long *buf, unsigned long start, int count)
764{ 772{
diff --git a/firmware/target/arm/imx31/sdma-imx31.h b/firmware/target/arm/imx31/sdma-imx31.h
index b7e0ab42a4..17c1b9e4f8 100644
--- a/firmware/target/arm/imx31/sdma-imx31.h
+++ b/firmware/target/arm/imx31/sdma-imx31.h
@@ -85,7 +85,7 @@ enum SDMA_REQUEST_TYPE
85{ 85{
86 SDMA_REQ_EXT0 = 0, /* Extern DMA request from MCU1_0 */ 86 SDMA_REQ_EXT0 = 0, /* Extern DMA request from MCU1_0 */
87 SDMA_REQ_CCM = 1, /* DVFS/DPTC event (ccm_dvfs_sdma_int) */ 87 SDMA_REQ_CCM = 1, /* DVFS/DPTC event (ccm_dvfs_sdma_int) */
88 SDMA_REQ_ATA_TX_END = 2, /* ata_txfer_end_alarm (event_id) */ 88 SDMA_REQ_ATA_TXFER_END = 2, /* ata_txfer_end_alarm (event_id1) */
89 SDMA_REQ_ATA_TX = 3, /* ata_tx_fifo_alarm (event_id2) */ 89 SDMA_REQ_ATA_TX = 3, /* ata_tx_fifo_alarm (event_id2) */
90 SDMA_REQ_ATA_RX = 4, /* ata_rcv_fifo_alarm (event_id2) */ 90 SDMA_REQ_ATA_RX = 4, /* ata_rcv_fifo_alarm (event_id2) */
91 SDMA_REQ_SIM = 5, /* */ 91 SDMA_REQ_SIM = 5, /* */
@@ -223,5 +223,6 @@ bool sdma_channel_init(unsigned int channel,
223 struct channel_descriptor *cd_p, 223 struct channel_descriptor *cd_p,
224 struct buffer_descriptor *base_bd_p); 224 struct buffer_descriptor *base_bd_p);
225void sdma_channel_close(unsigned int channel); 225void sdma_channel_close(unsigned int channel);
226bool sdma_channel_is_error(unsigned int channel);
226 227
227#endif /* SDMA_IMX31_H */ 228#endif /* SDMA_IMX31_H */