summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/adc-imx31.c)0
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-imx31.c685
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-target.h82
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/avic-imx31.c212
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/avic-imx31.h213
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/backlight-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c)0
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/button-imx31.c)0
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c213
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h114
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c338
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/i2c-imx31.h78
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/i2s-imx31.c)21
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c)0
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c)0
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c2
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c360
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c33
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mmu-imx31.h29
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c)0
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/power-imx31.c)2
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.h (renamed from firmware/target/arm/imx31/gigabeat-s/power-imx31.h)0
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/powermgmt-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c)2
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/serial-imx31.h32
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/spi-imx31.c352
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/spi-imx31.h89
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/system-imx31.c)0
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/timer-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/timer-imx31.c)0
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/usb-imx31.c)4
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/wmcodec-gigabeat-s.c (renamed from firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c)20
29 files changed, 27 insertions, 2854 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c b/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c
index 52293228f8..52293228f8 100644
--- a/firmware/target/arm/imx31/gigabeat-s/adc-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/adc-gigabeat-s.c
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c b/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c
deleted file mode 100644
index 5ce7ad0a03..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c
+++ /dev/null
@@ -1,685 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Will Robertson
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "cpu.h"
23#include "kernel.h"
24#include "thread.h"
25#include "system.h"
26#include "power.h"
27#include "panic.h"
28#include "ata.h"
29#include "ata-target.h"
30#include "ccm-imx31.h"
31#ifdef HAVE_ATA_DMA
32#include "sdma-imx31.h"
33#include "mmu-imx31.h"
34#endif
35
36/* PIO modes timing info */
37static const struct ata_pio_timings
38{
39 uint16_t time_2w; /* t2 during write */
40 uint16_t time_2r; /* t2 during read */
41 uint8_t time_ax; /* tA */
42 uint8_t time_1; /* t1 */
43 uint8_t time_4; /* t4 */
44 uint8_t time_9; /* t9 */
45} pio_timings[5] =
46{
47 [0] = /* PIO mode 0 */
48 {
49 .time_1 = 70,
50 .time_2w = 290,
51 .time_2r = 290,
52 .time_ax = 35,
53 .time_4 = 30,
54 .time_9 = 20
55 },
56 [1] = /* PIO mode 1 */
57 {
58 .time_1 = 50,
59 .time_2w = 290,
60 .time_2r = 290,
61 .time_ax = 35,
62 .time_4 = 20,
63 .time_9 = 15
64 },
65 [2] = /* PIO mode 2 */
66 {
67 .time_1 = 30,
68 .time_2w = 290,
69 .time_2r = 290,
70 .time_ax = 35,
71 .time_4 = 15,
72 .time_9 = 10
73 },
74 [3] = /* PIO mode 3 */
75 {
76 .time_1 = 30,
77 .time_2w = 80,
78 .time_2r = 80,
79 .time_ax = 35,
80 .time_4 = 10,
81 .time_9 = 10
82 },
83 [4] = /* PIO mode 4 */
84 {
85 .time_1 = 25,
86 .time_2w = 70,
87 .time_2r = 70,
88 .time_ax = 35,
89 .time_4 = 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
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 }
141};
142
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 / ccm_get_ata_clk();
279}
280
281static void ata_wait_for_idle(void)
282{
283 while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE));
284}
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
295/* Setup the timing for PIO mode */
296void ata_set_pio_timings(int mode)
297{
298 const struct ata_pio_timings * const timings = &pio_timings[mode];
299 unsigned int T = get_T();
300
301 ata_wait_for_idle();
302
303 ATA_TIME_1 = (timings->time_1 + T) / T;
304 ATA_TIME_2W = (timings->time_2w + T) / T;
305 ATA_TIME_2R = (timings->time_2r + T) / T;
306 ATA_TIME_AX = (timings->time_ax + T) / T + 2; /* 1.5 + tAX */
307 ATA_TIME_PIO_RDX = 1;
308 ATA_TIME_4 = (timings->time_4 + T) / T;
309 ATA_TIME_9 = (timings->time_9 + T) / T;
310}
311
312void ata_reset(void)
313{
314 /* Be sure we're not busy */
315 ata_wait_for_idle();
316
317 ATA_INTF_CONTROL &= ~(ATA_ATA_RST | ATA_FIFO_RST);
318 sleep(HZ/100);
319 ATA_INTF_CONTROL = ATA_ATA_RST | ATA_FIFO_RST;
320 sleep(HZ/100);
321
322 ata_wait_for_idle();
323}
324
325void ata_enable(bool on)
326{
327 /* Unconditionally clock module before writing regs */
328 ccm_module_clock_gating(CG_ATA, CGM_ON_RUN_WAIT);
329 ata_wait_for_idle();
330
331 if (on)
332 {
333 ATA_INTF_CONTROL = ATA_ATA_RST | ATA_FIFO_RST;
334 sleep(HZ/100);
335 }
336 else
337 {
338 ATA_INTF_CONTROL &= ~(ATA_ATA_RST | ATA_FIFO_RST);
339 sleep(HZ/100);
340
341 /* Disable off - unclock ATA module */
342 ccm_module_clock_gating(CG_ATA, CGM_OFF);
343 }
344}
345
346bool ata_is_coldstart(void)
347{
348 return true;
349}
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
623void ata_device_init(void)
624{
625 /* Make sure we're not in reset mode */
626 ata_enable(true);
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
639 /* All modes use same tOFF/tON */
640 ATA_TIME_OFF = 3;
641 ATA_TIME_ON = 3;
642
643 /* Setup mode 0 for all by default
644 * Mode may be switched later once identify info is ready in which
645 * case the main driver calls back */
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;
685}
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-target.h b/firmware/target/arm/imx31/gigabeat-s/ata-target.h
deleted file mode 100644
index f7f84f82e9..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/ata-target.h
+++ /dev/null
@@ -1,82 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Linus Nielsen Feltzing
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef ATA_TARGET_H
22#define ATA_TARGET_H
23
24#ifdef BOOTLOADER
25#define ATA_DRIVER_CLOSE
26#endif
27
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. */
31#define PREFER_C_READING
32#define PREFER_C_WRITING
33
34#ifdef HAVE_ATA_DMA
35#define ATA_MAX_MWDMA 2
36#define ATA_MAX_UDMA 4
37#endif
38
39#define ATA_DATA ATA_DRIVE_DATA
40#define ATA_ERROR ATA_DRIVE_FEATURES
41#define ATA_NSECTOR ATA_DRIVE_SECTOR_COUNT
42#define ATA_SECTOR ATA_DRIVE_SECTOR_NUM
43#define ATA_LCYL ATA_DRIVE_CYL_LOW
44#define ATA_HCYL ATA_DRIVE_CYL_HIGH
45#define ATA_SELECT ATA_DRIVE_CYL_HEAD
46#define ATA_COMMAND ATA_DRIVE_COMMAND
47#define ATA_CONTROL ATA_DRIVE_CONTROL
48
49#define STATUS_BSY 0x80
50#define STATUS_RDY 0x40
51#define STATUS_DF 0x20
52#define STATUS_DRQ 0x08
53#define STATUS_ERR 0x01
54#define ERROR_ABRT 0x04
55#define ERROR_IDNF 0x10
56
57#define WRITE_PATTERN1 0xa5
58#define WRITE_PATTERN2 0x5a
59#define WRITE_PATTERN3 0xaa
60#define WRITE_PATTERN4 0x55
61
62#define READ_PATTERN1 0xa5
63#define READ_PATTERN2 0x5a
64#define READ_PATTERN3 0xaa
65#define READ_PATTERN4 0x55
66
67#define READ_PATTERN1_MASK 0xff
68#define READ_PATTERN2_MASK 0xff
69#define READ_PATTERN3_MASK 0xff
70#define READ_PATTERN4_MASK 0xff
71
72#define SET_REG(reg,val) reg = (val)
73#define SET_16BITREG(reg,val) reg = (val)
74
75void ata_reset(void);
76void ata_device_init(void);
77bool ata_is_coldstart(void);
78
79#define ATA_SET_DEVICE_FEATURES
80void ata_set_pio_timings(int mode);
81
82#endif /* ATA_TARGET_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
deleted file mode 100644
index 4ba7da4be0..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.c
+++ /dev/null
@@ -1,212 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by James Espinoza
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdio.h>
22#include "system.h"
23#include "imx31l.h"
24#include "avic-imx31.h"
25#include "panic.h"
26#include "debug.h"
27
28static const char * avic_int_names[64] =
29{
30 "RESERVED0", "RESERVED1", "RESERVED2", "I2C3",
31 "I2C2", "MPEG4_ENCODER", "RTIC", "FIR",
32 "MMC/SDHC2", "MMC/SDHC1", "I2C1", "SSI2",
33 "SSI1", "CSPI2", "CSPI1", "ATA",
34 "MBX", "CSPI3", "UART3", "IIM",
35 "SIM1", "SIM2", "RNGA", "EVTMON",
36 "KPP", "RTC", "PWN", "EPIT2",
37 "EPIT1", "GPT", "PWR_FAIL", "CCM_DVFS",
38 "UART2", "NANDFC", "SDMA", "USB_HOST1",
39 "USB_HOST2", "USB_OTG", "RESERVED3", "MSHC1",
40 "MSHC2", "IPU_ERR", "IPU", "RESERVED4",
41 "RESERVED5", "UART1", "UART4", "UART5",
42 "ETC_IRQ", "SCC_SCM", "SCC_SMN", "GPIO2",
43 "GPIO1", "CCM_CLK", "PCMCIA", "WDOG",
44 "GPIO3", "RESERVED6", "EXT_PWMG", "EXT_TEMP",
45 "EXT_SENS1", "EXT_SENS2", "EXT_WDOG", "EXT_TV"
46};
47
48void UIE_VECTOR(void)
49{
50 int mode;
51 int offset;
52
53 asm volatile (
54 "mrs %0, cpsr \n" /* Mask core IRQ/FIQ */
55 "orr %0, %0, #0xc0 \n"
56 "msr cpsr_c, %0 \n"
57 "and %0, %0, #0x1f \n" /* Get mode bits */
58 : "=&r"(mode)
59 );
60
61 offset = mode == 0x11 ?
62 (int32_t)AVIC_FIVECSR : ((int32_t)AVIC_NIVECSR >> 16);
63
64 panicf("Unhandled %s %d: %s",
65 mode == 0x11 ? "FIQ" : "IRQ", offset,
66 offset >= 0 ? avic_int_names[offset] : "<Unknown>");
67}
68
69/* We use the AVIC */
70void __attribute__((interrupt("IRQ"))) irq_handler(void)
71{
72 const int offset = (int32_t)AVIC_NIVECSR >> 16;
73
74 if (offset == -1)
75 {
76 /* This is called occasionally for some unknown reason even with the
77 * avic enabled but returning normally appears to cause no harm. The
78 * KPP and ATA seem to have a part in it (common but multiplexed pins
79 * that can interfere). It will be investigated more thoroughly but
80 * for now it is simply an occasional irritant. */
81 return;
82 }
83
84 disable_interrupt(IRQ_FIQ_STATUS);
85 panicf("Unhandled IRQ %d in irq_handler: %s", offset,
86 offset >= 0 ? avic_int_names[offset] : "<Unknown>");
87}
88
89/* Accoring to section 9.3.5 of the UM, the AVIC doesn't accelerate
90 * fast interrupts and they must be dispatched */
91void __attribute__((naked)) fiq_handler(void)
92{
93 asm volatile (
94 "mov r10, #0x68000000 \n" /* load AVIC base address */
95 "ldr r9, [r10, #0x44] \n" /* read FIVECSR of AVIC */
96 "add r10, r10, #0x100 \n" /* move pointer to base of VECTOR table */
97 "ldr r8, [r10, r9, lsl #2] \n" /* read FIQ vector from VECTOR table */
98 "bx r8 \n" /* jump to FIQ service routine */
99 );
100}
101
102void avic_init(void)
103{
104 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
105 int i;
106
107 /* Disable all interrupts and set to unhandled */
108 avic_disable_int(INT_ALL);
109
110 /* Reset AVIC control */
111 avic->intcntl = 0;
112
113 /* Init all interrupts to type IRQ */
114 avic_set_int_type(INT_ALL, INT_TYPE_IRQ);
115
116 /* Set all normal to lowest priority */
117 for (i = 0; i < 8; i++)
118 avic->nipriority[i] = 0;
119
120 /* Set NM bit to enable VIC */
121 avic->intcntl |= AVIC_INTCNTL_NM;
122
123 /* Enable VE bit in CP15 Control reg to enable VIC */
124 asm volatile (
125 "mrc p15, 0, r0, c1, c0, 0 \n"
126 "orr r0, r0, #(1 << 24) \n"
127 "mcr p15, 0, r0, c1, c0, 0 \n"
128 : : : "r0");
129
130 /* Enable normal interrupts at all priorities */
131 avic->nimask = 0x1f;
132}
133
134void avic_set_int_priority(enum IMX31_INT_LIST ints,
135 unsigned long ni_priority)
136{
137 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
138 volatile uint32_t *reg = &avic->nipriority[7 - (ints >> 3)];
139 unsigned int shift = (ints & 0x7) << 2;
140 uint32_t mask = 0xful << shift;
141 *reg = (*reg & ~mask) | ((ni_priority << shift) & mask);
142}
143
144void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype,
145 unsigned long ni_priority, void (*handler)(void))
146{
147 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
148 int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
149
150 if (ints != INT_ALL) /* No mass-enable allowed */
151 {
152 avic_set_int_type(ints, intstype);
153 avic->vector[ints] = (long)handler;
154 avic->intennum = ints;
155 avic_set_int_priority(ints, ni_priority);
156 }
157
158 restore_interrupt(oldstatus);
159}
160
161void avic_disable_int(enum IMX31_INT_LIST ints)
162{
163 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
164 uint32_t i;
165
166 if (ints == INT_ALL)
167 {
168 for (i = 0; i < 64; i++)
169 {
170 avic->intdisnum = i;
171 avic->vector[i] = (long)UIE_VECTOR;
172 }
173 }
174 else
175 {
176 avic->intdisnum = ints;
177 avic->vector[ints] = (long)UIE_VECTOR;
178 }
179}
180
181static void set_int_type(int i, enum INT_TYPE intstype)
182{
183 /* INTTYPEH: vectors 63-32, INTTYPEL: vectors 31-0 */
184 struct avic_map * const avic = (struct avic_map *)AVIC_BASE_ADDR;
185 volatile uint32_t *reg = &avic->inttype[1 - (i >> 5)];
186 uint32_t val = 1L << (i & 0x1f);
187
188 if (intstype == INT_TYPE_IRQ)
189 val = *reg & ~val;
190 else
191 val = *reg | val;
192
193 *reg = val;
194}
195
196void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype)
197{
198 int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
199
200 if (ints == INT_ALL)
201 {
202 int i;
203 for (i = 0; i < 64; i++)
204 set_int_type(i, intstype);
205 }
206 else
207 {
208 set_int_type(ints, intstype);
209 }
210
211 restore_interrupt(oldstatus);
212}
diff --git a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.h b/firmware/target/arm/imx31/gigabeat-s/avic-imx31.h
deleted file mode 100644
index a049713600..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/avic-imx31.h
+++ /dev/null
@@ -1,213 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by James Espinoza
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef AVIC_IMX31_H
22#define AVIC_IMX31_H
23
24struct avic_map
25{
26 volatile uint32_t intcntl; /* 00h */
27 volatile uint32_t nimask; /* 04h */
28 volatile uint32_t intennum; /* 08h */
29 volatile uint32_t intdisnum; /* 0Ch */
30 union /* 10h */
31 {
32 struct
33 {
34 volatile uint32_t intenableh; /* 10h */
35 volatile uint32_t intenablel; /* 14h */
36 };
37 volatile uint32_t intenable[2]; /* H,L */
38 };
39 union
40 {
41 struct
42 {
43 volatile uint32_t inttypeh; /* 18h */
44 volatile uint32_t inttypel; /* 1Ch */
45 };
46 volatile uint32_t inttype[2]; /* H,L */
47 };
48 union
49 {
50 struct
51 {
52 volatile uint32_t nipriority7; /* 20h */
53 volatile uint32_t nipriority6; /* 24h */
54 volatile uint32_t nipriority5; /* 28h */
55 volatile uint32_t nipriority4; /* 2Ch */
56 volatile uint32_t nipriority3; /* 30h */
57 volatile uint32_t nipriority2; /* 34h */
58 volatile uint32_t nipriority1; /* 38h */
59 volatile uint32_t nipriority0; /* 3Ch */
60 };
61 volatile uint32_t nipriority[8]; /* 7-0 */
62 };
63 volatile uint32_t nivecsr; /* 40h */
64 volatile uint32_t fivecsr; /* 44h */
65 union
66 {
67 struct
68 {
69 volatile uint32_t intsrch; /* 48h */
70 volatile uint32_t intsrcl; /* 4Ch */
71 };
72 volatile uint32_t intsrc[2]; /* H,L */
73 };
74 union
75 {
76 struct
77 {
78 volatile uint32_t intfrch; /* 50h */
79 volatile uint32_t intfrcl; /* 54h */
80 };
81 volatile uint32_t intfrc[2]; /* H,L */
82 };
83 union
84 {
85 struct
86 {
87 volatile uint32_t nipndh; /* 58h */
88 volatile uint32_t nipndl; /* 5Ch */
89 };
90 volatile uint32_t nipnd[2]; /* H,L */
91 };
92 union
93 {
94 struct
95 {
96 volatile uint32_t fipndh; /* 60h */
97 volatile uint32_t fipndl; /* 64h */
98 };
99 volatile uint32_t fipnd[2]; /* H,L */
100 };
101 volatile uint32_t skip1[0x26]; /* 68h */
102 union /* 100h */
103 {
104 struct
105 {
106 volatile uint32_t reserved0;
107 volatile uint32_t reserved1;
108 volatile uint32_t reserved2;
109 volatile uint32_t i2c3;
110 volatile uint32_t i2c2;
111 volatile uint32_t mpeg4encoder;
112 volatile uint32_t rtic;
113 volatile uint32_t fir;
114 volatile uint32_t mmc_sdhc2;
115 volatile uint32_t mmc_sdhc1;
116 volatile uint32_t i2c1;
117 volatile uint32_t ssi2;
118 volatile uint32_t ssi1;
119 volatile uint32_t cspi2;
120 volatile uint32_t cspi1;
121 volatile uint32_t ata;
122 volatile uint32_t mbx;
123 volatile uint32_t cspi3;
124 volatile uint32_t uart3;
125 volatile uint32_t iim;
126 volatile uint32_t sim1;
127 volatile uint32_t sim2;
128 volatile uint32_t rnga;
129 volatile uint32_t evtmon;
130 volatile uint32_t kpp;
131 volatile uint32_t rtc;
132 volatile uint32_t pwn;
133 volatile uint32_t epit2;
134 volatile uint32_t epit1;
135 volatile uint32_t gpt;
136 volatile uint32_t pwr_fail;
137 volatile uint32_t ccm_dvfs;
138 volatile uint32_t uart2;
139 volatile uint32_t nandfc;
140 volatile uint32_t sdma;
141 volatile uint32_t usb_host1;
142 volatile uint32_t usb_host2;
143 volatile uint32_t usb_otg;
144 volatile uint32_t reserved3;
145 volatile uint32_t mshc1;
146 volatile uint32_t mshc2;
147 volatile uint32_t ipu_err;
148 volatile uint32_t ipu;
149 volatile uint32_t reserved4;
150 volatile uint32_t reserved5;
151 volatile uint32_t uart1;
152 volatile uint32_t uart4;
153 volatile uint32_t uart5;
154 volatile uint32_t etc_irq;
155 volatile uint32_t scc_scm;
156 volatile uint32_t scc_smn;
157 volatile uint32_t gpio2;
158 volatile uint32_t gpio1;
159 volatile uint32_t ccm_clk;
160 volatile uint32_t pcmcia;
161 volatile uint32_t wdog;
162 volatile uint32_t gpio3;
163 volatile uint32_t reserved6;
164 volatile uint32_t ext_pwmg;
165 volatile uint32_t ext_temp;
166 volatile uint32_t ext_sense1;
167 volatile uint32_t ext_sense2;
168 volatile uint32_t ext_wdog;
169 volatile uint32_t ext_tv;
170 };
171 volatile uint32_t vector[0x40]; /* 100h */
172 };
173};
174
175#define INT_PRIO_DEFAULT 7
176
177enum INT_TYPE
178{
179 INT_TYPE_IRQ = 0,
180 INT_TYPE_FIQ
181};
182
183enum IMX31_INT_LIST
184{
185 __IMX31_INT_FIRST = -1,
186 INT_RESERVED0, INT_RESERVED1, INT_RESERVED2, INT_I2C3,
187 INT_I2C2, INT_MPEG4_ENCODER, INT_RTIC, INT_FIR,
188 INT_MMC_SDHC2, INT_MMC_SDHC1, INT_I2C1, INT_SSI2,
189 INT_SSI1, INT_CSPI2, INT_CSPI1, INT_ATA,
190 INT_MBX, INT_CSPI3, INT_UART3, INT_IIM,
191 INT_SIM1, INT_SIM2, INT_RNGA, INT_EVTMON,
192 INT_KPP, INT_RTC, INT_PWN, INT_EPIT2,
193 INT_EPIT1, INT_GPT, INT_PWR_FAIL, INT_CCM_DVFS,
194 INT_UART2, INT_NANDFC, INT_SDMA, INT_USB_HOST1,
195 INT_USB_HOST2, INT_USB_OTG, INT_RESERVED3, INT_MSHC1,
196 INT_MSHC2, INT_IPU_ERR, INT_IPU, INT_RESERVED4,
197 INT_RESERVED5, INT_UART1, INT_UART4, INT_UART5,
198 INT_ETC_IRQ, INT_SCC_SCM, INT_SCC_SMN, INT_GPIO2,
199 INT_GPIO1, INT_CCM_CLK, INT_PCMCIA, INT_WDOG,
200 INT_GPIO3, INT_RESERVED6, INT_EXT_PWMG, INT_EXT_TEMP,
201 INT_EXT_SENS1, INT_EXT_SENS2, INT_EXT_WDOG, INT_EXT_TV,
202 INT_ALL
203};
204
205void avic_init(void);
206void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype,
207 unsigned long ni_priority, void (*handler)(void));
208void avic_set_int_priority(enum IMX31_INT_LIST ints,
209 unsigned long ni_priority);
210void avic_disable_int(enum IMX31_INT_LIST ints);
211void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype);
212
213#endif /* AVIC_IMX31_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c b/firmware/target/arm/imx31/gigabeat-s/backlight-gigabeat-s.c
index ec7bf7e8a9..ec7bf7e8a9 100644
--- a/firmware/target/arm/imx31/gigabeat-s/backlight-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/backlight-gigabeat-s.c
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c b/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c
index ae158b811d..ae158b811d 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c
deleted file mode 100644
index 944f70eae3..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.c
+++ /dev/null
@@ -1,213 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2008 by Michael Sevakis
11 *
12 * IMX31 GPIO event manager
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "config.h"
24#include "system.h"
25#include "avic-imx31.h"
26#include "gpio-imx31.h"
27
28/* UIE vector found in avic-imx31.c */
29extern void UIE_VECTOR(void);
30
31/* Event lists are allocated for the specific target */
32#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
33static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void);
34extern const struct gpio_event_list gpio1_event_list;
35#endif
36
37#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
38static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void);
39extern const struct gpio_event_list gpio2_event_list;
40#endif
41
42#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
43static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void);
44extern const struct gpio_event_list gpio3_event_list;
45#endif
46
47static struct gpio_module_descriptor
48{
49 struct gpio_map * const base; /* Module base address */
50 enum IMX31_INT_LIST ints; /* AVIC int number */
51 void (*handler)(void); /* Interrupt function */
52 const struct gpio_event_list *list; /* Event handler list */
53} gpio_descs[GPIO_NUM_GPIO] =
54{
55#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
56 {
57 .base = (struct gpio_map *)GPIO1_BASE_ADDR,
58 .ints = INT_GPIO1,
59 .handler = GPIO1_HANDLER,
60 },
61#endif
62#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
63 {
64 .base = (struct gpio_map *)GPIO2_BASE_ADDR,
65 .ints = INT_GPIO2,
66 .handler = GPIO2_HANDLER,
67 },
68#endif
69#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
70 {
71 .base = (struct gpio_map *)GPIO3_BASE_ADDR,
72 .ints = INT_GPIO3,
73 .handler = GPIO3_HANDLER,
74 },
75#endif
76};
77
78static void gpio_call_events(const struct gpio_module_descriptor * const desc)
79{
80 const struct gpio_event_list * const list = desc->list;
81 struct gpio_map * const base = desc->base;
82 const struct gpio_event * event, *event_last;
83
84 /* Intersect pending and unmasked bits */
85 uint32_t pnd = base->isr & base->imr;
86
87 event = list->events;
88 event_last = event + list->count;
89
90 /* Call each event handler in order */
91 /* .count is surely expected to be > 0 */
92 do
93 {
94 uint32_t mask = event->mask;
95
96 if (pnd & mask)
97 {
98 event->callback();
99 pnd &= ~mask;
100 }
101
102 if (pnd == 0)
103 break; /* Teminate early if nothing more to service */
104 }
105 while (++event < event_last);
106
107 if (pnd != 0)
108 {
109 /* One or more weren't handled */
110 UIE_VECTOR();
111 }
112}
113
114#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
115static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void)
116{
117 gpio_call_events(&gpio_descs[GPIO1_NUM]);
118}
119#endif
120
121#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
122static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void)
123{
124 gpio_call_events(&gpio_descs[GPIO2_NUM]);
125}
126#endif
127
128#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
129static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void)
130{
131 gpio_call_events(&gpio_descs[GPIO3_NUM]);
132}
133#endif
134
135void gpio_init(void)
136{
137 /* Mask-out GPIO interrupts - enable what's wanted later */
138 GPIO1_IMR = 0;
139 GPIO2_IMR = 0;
140 GPIO3_IMR = 0;
141
142 /* Init the externally-defined event lists for each port */
143#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
144 gpio_descs[GPIO1_NUM].list = &gpio1_event_list;
145#endif
146#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
147 gpio_descs[GPIO2_NUM].list = &gpio2_event_list;
148#endif
149#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
150 gpio_descs[GPIO3_NUM].list = &gpio3_event_list;
151#endif
152}
153
154bool gpio_enable_event(enum gpio_event_ids id)
155{
156 const struct gpio_module_descriptor * const desc = &gpio_descs[id >> 5];
157 const struct gpio_event * const event = &desc->list->events[id & 31];
158 struct gpio_map * const base = desc->base;
159 volatile uint32_t *icr;
160 uint32_t mask, line;
161 uint32_t imr;
162 int shift;
163
164 int oldlevel = disable_irq_save();
165
166 imr = base->imr;
167
168 if (imr == 0)
169 {
170 /* First enabled interrupt for this GPIO */
171 avic_enable_int(desc->ints, INT_TYPE_IRQ, desc->list->ints_priority,
172 desc->handler);
173 }
174
175 /* Set the line sense */
176 line = find_first_set_bit(event->mask);
177 icr = &base->icr[line >> 4];
178 shift = (line & 15) << 1;
179 mask = GPIO_SENSE_CONFIG_MASK << shift;
180
181 *icr = (*icr & ~mask) | ((event->sense << shift) & mask);
182
183 /* Unmask the line */
184 base->imr = imr | event->mask;
185
186 restore_irq(oldlevel);
187
188 return true;
189}
190
191void gpio_disable_event(enum gpio_event_ids id)
192{
193 const struct gpio_module_descriptor * const desc = &gpio_descs[id >> 5];
194 const struct gpio_event * const event = &desc->list->events[id & 31];
195 struct gpio_map * const base = desc->base;
196 uint32_t imr;
197
198 int oldlevel = disable_irq_save();
199
200 /* Remove bit from mask */
201 imr = base->imr & ~event->mask;
202
203 /* Mask the line */
204 base->imr = imr;
205
206 if (imr == 0)
207 {
208 /* No events remain enabled */
209 avic_disable_int(desc->ints);
210 }
211
212 restore_irq(oldlevel);
213}
diff --git a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h b/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h
deleted file mode 100644
index 72956d4efa..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/gpio-imx31.h
+++ /dev/null
@@ -1,114 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2008 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef GPIO_IMX31_H
22#define GPIO_IMX31_H
23
24/* Static registration mechanism for imx31 GPIO interrupts */
25#define USE_GPIO1_EVENTS (1 << 0)
26#define USE_GPIO2_EVENTS (1 << 1)
27#define USE_GPIO3_EVENTS (1 << 2)
28
29/* Module indexes defined by which GPIO modules are used */
30enum gpio_module_number
31{
32 __GPIO_NUM_START = -1,
33#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
34 GPIO1_NUM,
35#endif
36#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
37 GPIO2_NUM,
38#endif
39#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
40 GPIO3_NUM,
41#endif
42 GPIO_NUM_GPIO,
43};
44
45/* Module corresponding to the event ID is identified by range */
46enum gpio_event_bases
47{
48#if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS)
49 GPIO1_EVENT_FIRST = 32*GPIO1_NUM,
50#endif
51#if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS)
52 GPIO2_EVENT_FIRST = 32*GPIO2_NUM,
53#endif
54#if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS)
55 GPIO3_EVENT_FIRST = 32*GPIO3_NUM,
56#endif
57};
58
59#include "gpio-target.h"
60
61/* Possible values for gpio interrupt line config */
62enum gpio_int_sense_enum
63{
64 GPIO_SENSE_LOW_LEVEL = 0, /* High-level sensitive */
65 GPIO_SENSE_HIGH_LEVEL, /* Low-level sensitive */
66 GPIO_SENSE_RISING, /* Rising-edge sensitive */
67 GPIO_SENSE_FALLING, /* Falling-edge sensitive */
68};
69
70#define GPIO_SENSE_CONFIG_MASK 0x3
71
72/* Register map for each module */
73struct gpio_map
74{
75 volatile uint32_t dr; /* 00h */
76 volatile uint32_t gdir; /* 04h */
77 volatile uint32_t psr; /* 08h */
78 union
79 {
80 struct
81 {
82 volatile uint32_t icr1; /* 0Ch */
83 volatile uint32_t icr2; /* 10h */
84 };
85 volatile uint32_t icr[2]; /* 0Ch */
86 };
87 volatile uint32_t imr; /* 14h */
88 volatile uint32_t isr; /* 18h */
89};
90
91/* Pending events will be called in array order which allows easy
92 * pioritization */
93
94/* Describes a single event for a pin */
95struct gpio_event
96{
97 uint32_t mask; /* mask: 1 << (0...31) */
98 enum gpio_int_sense_enum sense; /* Type of sense */
99 void (*callback)(void); /* Callback function */
100};
101
102/* Describes the events attached to a port */
103struct gpio_event_list
104{
105 int ints_priority; /* Interrupt priority for this GPIO */
106 unsigned count; /* Count of events for the module */
107 const struct gpio_event *events; /* List of events */
108};
109
110void gpio_init(void);
111bool gpio_enable_event(enum gpio_event_ids id);
112void gpio_disable_event(enum gpio_event_ids id);
113
114#endif /* GPIO_IMX31_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c b/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c
deleted file mode 100644
index 1ffdce38ea..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.c
+++ /dev/null
@@ -1,338 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdlib.h>
22#include "config.h"
23#include "system.h"
24#include "kernel.h"
25#include "avic-imx31.h"
26#include "ccm-imx31.h"
27#include "i2c-imx31.h"
28
29/* Forward interrupt handler declarations */
30#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
31static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void);
32#endif
33#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
34static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void);
35#endif
36#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
37static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void);
38#endif
39
40static struct i2c_module_descriptor
41{
42 struct i2c_map *base; /* Module base address */
43 enum IMX31_CG_LIST cg; /* Clock gating index */
44 enum IMX31_INT_LIST ints; /* Module interrupt number */
45 int enable; /* Enable count */
46 void (*handler)(void); /* Module interrupt handler */
47 struct mutex m; /* Node mutual-exclusion */
48 struct wakeup w; /* I2C done signal */
49 unsigned char *addr_data; /* Additional addressing data */
50 int addr_count; /* Addressing byte count */
51 unsigned char *data; /* TX/RX buffer (actual data) */
52 int data_count; /* TX/RX byte count */
53 unsigned char addr; /* Address + r/w bit */
54} i2c_descs[I2C_NUM_I2C] =
55{
56#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
57 {
58 .base = (struct i2c_map *)I2C1_BASE_ADDR,
59 .cg = CG_I2C1,
60 .ints = INT_I2C1,
61 .handler = I2C1_HANDLER,
62 },
63#endif
64#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
65 {
66 .base = (struct i2c_map *)I2C2_BASE_ADDR,
67 .cg = CG_I2C2,
68 .ints = INT_I2C2,
69 .handler = I2C2_HANDLER,
70 },
71#endif
72#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
73 {
74 .base = (struct i2c_map *)I2C3_BASE_ADDR,
75 .cg = CG_I2C3,
76 .ints = INT_I2C3,
77 .handler = I2C3_HANDLER,
78 },
79#endif
80};
81
82static void i2c_interrupt(enum i2c_module_number i2c)
83{
84 struct i2c_module_descriptor *const desc = &i2c_descs[i2c];
85 struct i2c_map * const base = desc->base;
86 uint16_t i2sr = base->i2sr;
87
88 base->i2sr = 0; /* Clear IIF */
89
90 if (desc->addr_count >= 0)
91 {
92 /* ADDR cycle - either done or more to send */
93 if ((i2sr & I2C_I2SR_RXAK) != 0)
94 {
95 goto i2c_stop; /* problem */
96 }
97
98 if (--desc->addr_count < 0)
99 {
100 /* Switching to data cycle */
101 if (desc->addr & 0x1)
102 {
103 base->i2cr &= ~I2C_I2CR_MTX; /* Switch to RX mode */
104 base->i2dr; /* Dummy read */
105 return;
106 }
107 /* else remaining data is TX - handle below */
108 goto i2c_transmit;
109 }
110 else
111 {
112 base->i2dr = *desc->addr_data++; /* Send next addressing byte */
113 return;
114 }
115 }
116
117 if (base->i2cr & I2C_I2CR_MTX)
118 {
119 /* Transmitting data */
120 if ((i2sr & I2C_I2SR_RXAK) == 0)
121 {
122i2c_transmit:
123 if (desc->data_count > 0)
124 {
125 /* More bytes to send, got ACK from previous byte */
126 base->i2dr = *desc->data++;
127 desc->data_count--;
128 return;
129 }
130 }
131 /* else done or no ACK received */
132 }
133 else
134 {
135 /* Receiving data */
136 if (--desc->data_count > 0)
137 {
138 if (desc->data_count == 1)
139 {
140 /* 2nd to Last byte - NACK */
141 base->i2cr |= I2C_I2CR_TXAK;
142 }
143
144 *desc->data++ = base->i2dr; /* Read data from I2DR and store */
145 return;
146 }
147 else
148 {
149 /* Generate STOP signal before reading data */
150 base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
151 *desc->data++ = base->i2dr; /* Read data from I2DR and store */
152 goto i2c_done;
153 }
154 }
155
156i2c_stop:
157 /* Generate STOP signal */
158 base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
159i2c_done:
160 /* Signal thread we're done */
161 wakeup_signal(&desc->w);
162}
163
164#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
165static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void)
166{
167 i2c_interrupt(I2C1_NUM);
168}
169#endif
170#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
171static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void)
172{
173 i2c_interrupt(I2C2_NUM);
174}
175#endif
176#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
177static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void)
178{
179 i2c_interrupt(I2C3_NUM);
180}
181#endif
182
183static int i2c_transfer(struct i2c_node * const node,
184 struct i2c_module_descriptor *const desc)
185{
186 struct i2c_map * const base = desc->base;
187 int count = desc->data_count;
188 uint16_t i2cr;
189
190 /* Make sure bus is idle. */
191 while (base->i2sr & I2C_I2SR_IBB);
192
193 /* Set speed */
194 base->ifdr = node->ifdr;
195
196 /* Enable module */
197 base->i2cr = I2C_I2CR_IEN;
198
199 /* Enable Interrupt, Master */
200 i2cr = I2C_I2CR_IEN | I2C_I2CR_IIEN | I2C_I2CR_MTX;
201
202 if ((desc->addr & 0x1) && desc->data_count < 2)
203 {
204 /* Receiving less than two bytes - disable ACK generation */
205 i2cr |= I2C_I2CR_TXAK;
206 }
207
208 /* Set config */
209 base->i2cr = i2cr;
210
211 /* Generate START */
212 base->i2cr = i2cr | I2C_I2CR_MSTA;
213
214 /* Address slave (first byte sent) and begin session. */
215 base->i2dr = desc->addr;
216
217 /* Wait for transfer to complete */
218 if (wakeup_wait(&desc->w, HZ) == OBJ_WAIT_SUCCEEDED)
219 {
220 count -= desc->data_count;
221 }
222 else
223 {
224 /* Generate STOP if timeout */
225 base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN);
226 count = -1;
227 }
228
229 desc->addr_count = 0;
230
231 return count;
232}
233
234int i2c_read(struct i2c_node *node, int reg,
235 unsigned char *data, int data_count)
236{
237 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
238 unsigned char ad[1];
239
240 mutex_lock(&desc->m);
241
242 desc->addr = (node->addr & 0xfe) | 0x1; /* Slave address/rd */
243
244 if (reg >= 0)
245 {
246 /* Sub-address */
247 desc->addr_count = 1;
248 desc->addr_data = ad;
249 ad[0] = reg;
250 }
251 /* else raw read from slave */
252
253 desc->data = data;
254 desc->data_count = data_count;
255
256 data_count = i2c_transfer(node, desc);
257
258 mutex_unlock(&desc->m);
259
260 return data_count;
261}
262
263int i2c_write(struct i2c_node *node, const unsigned char *data, int data_count)
264{
265 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
266
267 mutex_lock(&desc->m);
268
269 desc->addr = node->addr & 0xfe; /* Slave address/wr */
270 desc->data = (unsigned char *)data;
271 desc->data_count = data_count;
272
273 data_count = i2c_transfer(node, desc);
274
275 mutex_unlock(&desc->m);
276
277 return data_count;
278}
279
280void i2c_init(void)
281{
282 int i;
283
284 /* Do one-time inits for each module that will be used - leave
285 * module disabled and unclocked until something wants it */
286 for (i = 0; i < I2C_NUM_I2C; i++)
287 {
288 struct i2c_module_descriptor *const desc = &i2c_descs[i];
289 ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT);
290 mutex_init(&desc->m);
291 wakeup_init(&desc->w);
292 desc->base->i2cr = 0;
293 ccm_module_clock_gating(desc->cg, CGM_OFF);
294 }
295}
296
297void i2c_enable_node(struct i2c_node *node, bool enable)
298{
299 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
300
301 mutex_lock(&desc->m);
302
303 if (enable)
304 {
305 if (++desc->enable == 1)
306 {
307 /* First enable */
308 ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT);
309 avic_enable_int(desc->ints, INT_TYPE_IRQ, INT_PRIO_DEFAULT,
310 desc->handler);
311 }
312 }
313 else
314 {
315 if (desc->enable > 0 && --desc->enable == 0)
316 {
317 /* Last enable */
318 while (desc->base->i2sr & I2C_I2SR_IBB); /* Wait for STOP */
319 desc->base->i2cr &= ~I2C_I2CR_IEN;
320 avic_disable_int(desc->ints);
321 ccm_module_clock_gating(desc->cg, CGM_OFF);
322 }
323 }
324
325 mutex_unlock(&desc->m);
326}
327
328void i2c_lock_node(struct i2c_node *node)
329{
330 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
331 mutex_lock(&desc->m);
332}
333
334void i2c_unlock_node(struct i2c_node *node)
335{
336 struct i2c_module_descriptor *const desc = &i2c_descs[node->num];
337 mutex_unlock(&desc->m);
338}
diff --git a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.h b/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.h
deleted file mode 100644
index b36acecfcb..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/i2c-imx31.h
+++ /dev/null
@@ -1,78 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef I2C_IMX31_H
22#define I2C_IMX31_H
23
24#include <stdbool.h>
25
26/* I2C module usage masks */
27#define USE_I2C1_MODULE (1 << 0)
28#define USE_I2C2_MODULE (1 << 1)
29#define USE_I2C3_MODULE (1 << 2)
30
31enum i2c_module_number
32{
33 __I2C_NUM_START = -1,
34#if (I2C_MODULE_MASK & USE_I2C1_MODULE)
35 I2C1_NUM,
36#endif
37#if (I2C_MODULE_MASK & USE_I2C2_MODULE)
38 I2C2_NUM,
39#endif
40#if (I2C_MODULE_MASK & USE_I2C3_MODULE)
41 I2C3_NUM,
42#endif
43 I2C_NUM_I2C,
44};
45
46/* Module interface map structure */
47struct i2c_map
48{
49 volatile uint16_t iadr; /* 0x00 */
50 volatile uint16_t unused1;
51 volatile uint16_t ifdr; /* 0x04 */
52 volatile uint16_t unused2;
53 volatile uint16_t i2cr; /* 0x08 */
54 volatile uint16_t unused3;
55 volatile uint16_t i2sr; /* 0x0C */
56 volatile uint16_t unused4;
57 volatile uint16_t i2dr; /* 0x10 */
58};
59
60struct i2c_node
61{
62 enum i2c_module_number num; /* Module that this node uses */
63 unsigned int ifdr; /* Maximum frequency for node */
64 unsigned char addr; /* Slave address on module */
65};
66
67void i2c_init(void);
68/* Enable or disable the node - modules will be switch on/off accordingly. */
69void i2c_enable_node(struct i2c_node *node, bool enable);
70/* If addr < 0, then raw read */
71int i2c_read(struct i2c_node *node, int addr, unsigned char *data, int count);
72int i2c_write(struct i2c_node *node, const unsigned char *data, int count);
73/* Gain mutually-exclusive access to the node and module to perform multiple
74 * operations atomically */
75void i2c_lock_node(struct i2c_node *node);
76void i2c_unlock_node(struct i2c_node *node);
77
78#endif /* I2C_IMX31_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/i2s-imx31.c b/firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c
index d1c917a209..c2ec0d6cab 100644
--- a/firmware/target/arm/imx31/gigabeat-s/i2s-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/i2s-gigabeat-s.c
@@ -18,9 +18,28 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21 21#include "config.h"
22#include "system.h"
22#include "i2s.h" 23#include "i2s.h"
23 24
24void i2s_reset(void) 25void i2s_reset(void)
25{ 26{
27 /* How SYSCLK for codec is derived (USBPLL=338.688MHz).
28 *
29 * SSI post dividers (SSI2 PODF=4, SSI2 PRE PODF=0):
30 * 338688000Hz / 5 = 67737600Hz = ssi1_clk
31 *
32 * SSI bit clock dividers (DIV2=1, PSR=0, PM=0):
33 * ssi1_clk / 4 = 16934400Hz = INT_BIT_CLK (MCLK)
34 *
35 * WM Codec post divider (MCLKDIV=1.5):
36 * INT_BIT_CLK (MCLK) / 1.5 = 11289600Hz = 256*fs = SYSCLK
37 */
38 imx31_regmod32(&CCM_PDR1,
39 ((1-1) << CCM_PDR1_SSI1_PRE_PODF_POS) |
40 ((5-1) << CCM_PDR1_SSI1_PODF_POS) |
41 ((8-1) << CCM_PDR1_SSI2_PRE_PODF_POS) |
42 ((64-1) << CCM_PDR1_SSI2_PODF_POS),
43 CCM_PDR1_SSI1_PODF | CCM_PDR1_SSI2_PODF |
44 CCM_PDR1_SSI1_PRE_PODF | CCM_PDR1_SSI2_PRE_PODF);
26} 45}
diff --git a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c b/firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c
index 8e81447bd3..8e81447bd3 100644
--- a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/kernel-gigabeat-s.c
diff --git a/firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c b/firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c
index 71d8e4bef4..71d8e4bef4 100644
--- a/firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/lcd-gigabeat-s.c
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c
index fc9ad719a6..2060b7bc6a 100644
--- a/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-gigabeat-s.c
@@ -27,7 +27,7 @@
27#include "adc-target.h" 27#include "adc-target.h"
28#include "button-target.h" 28#include "button-target.h"
29#include "usb-target.h" 29#include "usb-target.h"
30#include "power-imx31.h" 30#include "power-gigabeat-s.h"
31#include "powermgmt-target.h" 31#include "powermgmt-target.h"
32 32
33/* Gigabeat S definitions for static MC13783 event registration */ 33/* Gigabeat S definitions for static MC13783 event registration */
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
deleted file mode 100644
index 2c5af8d5b7..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/mc13783-imx31.c
+++ /dev/null
@@ -1,360 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2008 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "system.h"
22#include "cpu.h"
23#include "spi-imx31.h"
24#include "gpio-imx31.h"
25#include "mc13783.h"
26#include "debug.h"
27#include "kernel.h"
28
29#include "power-imx31.h"
30#include "button-target.h"
31#include "adc-target.h"
32#include "usb-target.h"
33
34#ifdef BOOTLOADER
35#define PMIC_DRIVER_CLOSE
36#endif
37
38/* This is all based on communicating with the MC13783 PMU which is on
39 * CSPI2 with the chip select at 0. The LCD controller resides on
40 * CSPI3 cs1, but we have no idea how to communicate to it */
41static struct spi_node mc13783_spi =
42{
43 CSPI2_NUM, /* CSPI module 2 */
44 CSPI_CONREG_CHIP_SELECT_SS0 | /* Chip select 0 */
45 CSPI_CONREG_DRCTL_DONT_CARE | /* Don't care about CSPI_RDY */
46 CSPI_CONREG_DATA_RATE_DIV_4 | /* Clock = IPG_CLK/4 - 16.5MHz */
47 CSPI_BITCOUNT(32-1) | /* All 32 bits are to be transferred */
48 CSPI_CONREG_SSPOL | /* SS active high */
49 CSPI_CONREG_SSCTL | /* Negate SS between SPI bursts */
50 CSPI_CONREG_MODE, /* Master mode */
51 0, /* SPI clock - no wait states */
52};
53
54extern const struct mc13783_event_list mc13783_event_list;
55
56static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)];
57static const char *mc13783_thread_name = "pmic";
58static struct wakeup mc13783_wake;
59
60/* Tracking for which interrupts are enabled */
61static uint32_t pmic_int_enabled[2] =
62 { 0x00000000, 0x00000000 };
63
64static const unsigned char pmic_intm_regs[2] =
65 { MC13783_INTERRUPT_MASK0, MC13783_INTERRUPT_MASK1 };
66
67static const unsigned char pmic_ints_regs[2] =
68 { MC13783_INTERRUPT_STATUS0, MC13783_INTERRUPT_STATUS1 };
69
70#ifdef PMIC_DRIVER_CLOSE
71static bool pmic_close = false;
72static unsigned int mc13783_thread_id = 0;
73#endif
74
75static void mc13783_interrupt_thread(void)
76{
77 uint32_t pending[2];
78
79 /* Enable mc13783 GPIO event */
80 gpio_enable_event(MC13783_EVENT_ID);
81
82 while (1)
83 {
84 const struct mc13783_event *event, *event_last;
85
86 wakeup_wait(&mc13783_wake, TIMEOUT_BLOCK);
87
88#ifdef PMIC_DRIVER_CLOSE
89 if (pmic_close)
90 break;
91#endif
92
93 mc13783_read_regset(pmic_ints_regs, pending, 2);
94
95 /* Only clear interrupts being dispatched */
96 pending[0] &= pmic_int_enabled[0];
97 pending[1] &= pmic_int_enabled[1];
98
99 mc13783_write_regset(pmic_ints_regs, pending, 2);
100
101 /* Whatever is going to be serviced in this loop has been
102 * acknowledged. Reenable interrupt and if anything was still
103 * pending or became pending again, another signal will be
104 * generated. */
105 imx31_regset32(&MC13783_GPIO_IMR, 1ul << MC13783_GPIO_LINE);
106
107 event = mc13783_event_list.events;
108 event_last = event + mc13783_event_list.count;
109
110 /* .count is surely expected to be > 0 */
111 do
112 {
113 enum mc13783_event_sets set = event->set;
114 uint32_t pnd = pending[set];
115 uint32_t mask = event->mask;
116
117 if (pnd & mask)
118 {
119 event->callback();
120 pnd &= ~mask;
121 pending[set] = pnd;
122 }
123
124 if ((pending[0] | pending[1]) == 0)
125 break; /* Teminate early if nothing more to service */
126 }
127 while (++event < event_last);
128 }
129
130#ifdef PMIC_DRIVER_CLOSE
131 gpio_disable_event(MC13783_EVENT_ID);
132#endif
133}
134
135/* GPIO interrupt handler for mc13783 */
136void mc13783_event(void)
137{
138 /* Mask the interrupt (unmasked when PMIC thread services it). */
139 imx31_regclr32(&MC13783_GPIO_IMR, 1ul << MC13783_GPIO_LINE);
140 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE);
141 wakeup_signal(&mc13783_wake);
142}
143
144void mc13783_init(void)
145{
146 /* Serial interface must have been initialized first! */
147 wakeup_init(&mc13783_wake);
148
149 /* Enable the PMIC SPI module */
150 spi_enable_module(&mc13783_spi);
151
152 /* Mask any PMIC interrupts for now - modules will enable them as
153 * required */
154 mc13783_write(MC13783_INTERRUPT_MASK0, 0xffffff);
155 mc13783_write(MC13783_INTERRUPT_MASK1, 0xffffff);
156
157 MC13783_GPIO_ISR = (1ul << MC13783_GPIO_LINE);
158
159#ifdef PMIC_DRIVER_CLOSE
160 mc13783_thread_id =
161#endif
162 create_thread(mc13783_interrupt_thread,
163 mc13783_thread_stack, sizeof(mc13783_thread_stack), 0,
164 mc13783_thread_name IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
165}
166
167#ifdef PMIC_DRIVER_CLOSE
168void mc13783_close(void)
169{
170 unsigned int thread_id = mc13783_thread_id;
171
172 if (thread_id == 0)
173 return;
174
175 mc13783_thread_id = 0;
176
177 pmic_close = true;
178 wakeup_signal(&mc13783_wake);
179 thread_wait(thread_id);
180}
181#endif /* PMIC_DRIVER_CLOSE */
182
183bool mc13783_enable_event(enum mc13783_event_ids id)
184{
185 const struct mc13783_event * const event =
186 &mc13783_event_list.events[id];
187 int set = event->set;
188 uint32_t mask = event->mask;
189
190 spi_lock(&mc13783_spi);
191
192 pmic_int_enabled[set] |= mask;
193 mc13783_clear(pmic_intm_regs[set], mask);
194
195 spi_unlock(&mc13783_spi);
196
197 return true;
198}
199
200void mc13783_disable_event(enum mc13783_event_ids id)
201{
202 const struct mc13783_event * const event =
203 &mc13783_event_list.events[id];
204 int set = event->set;
205 uint32_t mask = event->mask;
206
207 spi_lock(&mc13783_spi);
208
209 pmic_int_enabled[set] &= ~mask;
210 mc13783_set(pmic_intm_regs[set], mask);
211
212 spi_unlock(&mc13783_spi);
213}
214
215uint32_t mc13783_set(unsigned address, uint32_t bits)
216{
217 spi_lock(&mc13783_spi);
218
219 uint32_t data = mc13783_read(address);
220
221 if (data != MC13783_DATA_ERROR)
222 mc13783_write(address, data | bits);
223
224 spi_unlock(&mc13783_spi);
225
226 return data;
227}
228
229uint32_t mc13783_clear(unsigned address, uint32_t bits)
230{
231 spi_lock(&mc13783_spi);
232
233 uint32_t data = mc13783_read(address);
234
235 if (data != MC13783_DATA_ERROR)
236 mc13783_write(address, data & ~bits);
237
238 spi_unlock(&mc13783_spi);
239
240 return data;
241}
242
243int mc13783_write(unsigned address, uint32_t data)
244{
245 struct spi_transfer xfer;
246 uint32_t packet;
247
248 if (address >= MC13783_NUM_REGS)
249 return -1;
250
251 packet = (1 << 31) | (address << 25) | (data & 0xffffff);
252 xfer.txbuf = &packet;
253 xfer.rxbuf = &packet;
254 xfer.count = 1;
255
256 if (!spi_transfer(&mc13783_spi, &xfer))
257 return -1;
258
259 return 1 - xfer.count;
260}
261
262uint32_t mc13783_write_masked(unsigned address, uint32_t data, uint32_t mask)
263{
264 uint32_t old;
265
266 spi_lock(&mc13783_spi);
267
268 old = mc13783_read(address);
269
270 if (old != MC13783_DATA_ERROR)
271 {
272 data = (old & ~mask) | (data & mask);
273
274 if (mc13783_write(address, data) != 1)
275 old = MC13783_DATA_ERROR;
276 }
277
278 spi_unlock(&mc13783_spi);
279
280 return old;
281}
282
283int mc13783_write_regset(const unsigned char *regs, const uint32_t *data,
284 int count)
285{
286 int i;
287 struct spi_transfer xfer;
288 uint32_t packets[MC13783_NUM_REGS];
289
290 if ((unsigned)count > MC13783_NUM_REGS)
291 return -1;
292
293 for (i = 0; i < count; i++)
294 {
295 uint32_t reg = regs[i];
296
297 if (reg >= MC13783_NUM_REGS)
298 return -1;
299
300 packets[i] = (1 << 31) | (reg << 25) | (data[i] & 0xffffff);
301 }
302
303 xfer.txbuf = packets;
304 xfer.rxbuf = packets;
305 xfer.count = count;
306
307 if (!spi_transfer(&mc13783_spi, &xfer))
308 return -1;
309
310 return count - xfer.count;
311}
312
313uint32_t mc13783_read(unsigned address)
314{
315 uint32_t packet;
316 struct spi_transfer xfer;
317
318 if (address >= MC13783_NUM_REGS)
319 return MC13783_DATA_ERROR;
320
321 packet = address << 25;
322
323 xfer.txbuf = &packet;
324 xfer.rxbuf = &packet;
325 xfer.count = 1;
326
327 if (!spi_transfer(&mc13783_spi, &xfer))
328 return MC13783_DATA_ERROR;
329
330 return packet;
331}
332
333int mc13783_read_regset(const unsigned char *regs, uint32_t *buffer,
334 int count)
335{
336 int i;
337 struct spi_transfer xfer;
338
339 if ((unsigned)count > MC13783_NUM_REGS)
340 return -1;
341
342 for (i = 0; i < count; i++)
343 {
344 unsigned reg = regs[i];
345
346 if (reg >= MC13783_NUM_REGS)
347 return -1;
348
349 buffer[i] = reg << 25;
350 }
351
352 xfer.txbuf = buffer;
353 xfer.rxbuf = buffer;
354 xfer.count = count;
355
356 if (!spi_transfer(&mc13783_spi, &xfer))
357 return -1;
358
359 return count - xfer.count;
360}
diff --git a/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c
deleted file mode 100644
index 920a8c9fd3..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c
+++ /dev/null
@@ -1,33 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Will Robertson
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "cpu.h"
22#include "mmu-imx31.h"
23#include "mmu-arm.h"
24
25unsigned long addr_virt_to_phys(unsigned long addr)
26{
27 return addr | CSD0_BASE_ADDR;
28}
29
30unsigned long addr_phys_to_virt(unsigned long addr)
31{
32 return addr & ~CSD0_BASE_ADDR;
33}
diff --git a/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.h b/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.h
deleted file mode 100644
index c66a3d941d..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.h
+++ /dev/null
@@ -1,29 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006,2007 by Greg White
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef MMU_IMX31_H
22#define MMU_IMX31_H
23
24void memory_init(void);
25void set_page_tables(void);
26unsigned long addr_virt_to_phys(unsigned long addr);
27unsigned long addr_phys_to_virt(unsigned long addr);
28
29#endif /* MMU_IMX31_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
index 6cec3ecdd3..6cec3ecdd3 100644
--- a/firmware/target/arm/imx31/gigabeat-s/pcm-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
diff --git a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c
index b29d3cd0fb..7e3b39dba8 100644
--- a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.c
@@ -23,7 +23,7 @@
23#include "usb.h" 23#include "usb.h"
24#include "usb_core.h" 24#include "usb_core.h"
25#include "power.h" 25#include "power.h"
26#include "power-imx31.h" 26#include "power-gigabeat-s.h"
27#include "backlight.h" 27#include "backlight.h"
28#include "backlight-target.h" 28#include "backlight-target.h"
29#include "avic-imx31.h" 29#include "avic-imx31.h"
diff --git a/firmware/target/arm/imx31/gigabeat-s/power-imx31.h b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.h
index 9294de102c..9294de102c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/power-imx31.h
+++ b/firmware/target/arm/imx31/gigabeat-s/power-gigabeat-s.h
diff --git a/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c b/firmware/target/arm/imx31/gigabeat-s/powermgmt-gigabeat-s.c
index bb9b8c23af..34abf04940 100644
--- a/firmware/target/arm/imx31/gigabeat-s/powermgmt-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/powermgmt-gigabeat-s.c
@@ -26,7 +26,7 @@
26#include "adc.h" 26#include "adc.h"
27#include "powermgmt.h" 27#include "powermgmt.h"
28#include "power.h" 28#include "power.h"
29#include "power-imx31.h" 29#include "power-gigabeat-s.h"
30 30
31/* TODO: Battery tests to get the right values! */ 31/* TODO: Battery tests to get the right values! */
32const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = 32const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
diff --git a/firmware/target/arm/imx31/gigabeat-s/serial-imx31.h b/firmware/target/arm/imx31/gigabeat-s/serial-imx31.h
deleted file mode 100644
index cbb7be2ec3..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/serial-imx31.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by James Espinoza
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef SERIAL_IMX31_H
22#define SERIAL_IMX31_H
23
24#include <stdarg.h>
25#include <stdio.h>
26
27int tx_rdy(void);
28int rx_rdy(void);
29void tx_writec(const unsigned char c);
30void dprintf(const char * str, ... );
31
32#endif /* SERIAL_IMX31_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c
deleted file mode 100644
index ac063f9b10..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.c
+++ /dev/null
@@ -1,352 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2007 Will Robertson
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "system.h"
23#include "spi-imx31.h"
24#include "avic-imx31.h"
25#include "ccm-imx31.h"
26#include "debug.h"
27#include "kernel.h"
28
29/* Forward interrupt handler declarations */
30#if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
31static __attribute__((interrupt("IRQ"))) void CSPI1_HANDLER(void);
32#endif
33#if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
34static __attribute__((interrupt("IRQ"))) void CSPI2_HANDLER(void);
35#endif
36#if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
37static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void);
38#endif
39
40/* State data associatated with each CSPI module */
41static struct spi_module_descriptor
42{
43 struct cspi_map * const base;
44 int enab;
45 struct spi_node *last;
46 enum IMX31_CG_LIST cg;
47 enum IMX31_INT_LIST ints;
48 int byte_size;
49 void (*handler)(void);
50 struct mutex m;
51 struct wakeup w;
52 struct spi_transfer *trans;
53 int rxcount;
54} spi_descs[SPI_NUM_CSPI] =
55/* Init non-zero members */
56{
57#if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
58 {
59 .base = (struct cspi_map *)CSPI1_BASE_ADDR,
60 .cg = CG_CSPI1,
61 .ints = INT_CSPI1,
62 .handler = CSPI1_HANDLER,
63 },
64#endif
65#if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
66 {
67 .base = (struct cspi_map *)CSPI2_BASE_ADDR,
68 .cg = CG_CSPI2,
69 .ints = INT_CSPI2,
70 .handler = CSPI2_HANDLER,
71 },
72#endif
73#if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
74 {
75 .base = (struct cspi_map *)CSPI3_BASE_ADDR,
76 .cg = CG_CSPI3,
77 .ints = INT_CSPI3,
78 .handler = CSPI3_HANDLER,
79 },
80#endif
81};
82
83/* Common code for interrupt handlers */
84static void spi_interrupt(enum spi_module_number spi)
85{
86 struct spi_module_descriptor *desc = &spi_descs[spi];
87 struct cspi_map * const base = desc->base;
88 struct spi_transfer *trans = desc->trans;
89 int inc = desc->byte_size + 1;
90
91 if (desc->rxcount > 0)
92 {
93 /* Data received - empty out RXFIFO */
94 while ((base->statreg & CSPI_STATREG_RR) != 0)
95 {
96 uint32_t word = base->rxdata;
97
98 switch (desc->byte_size & 3)
99 {
100 case 3:
101 *(unsigned char *)(trans->rxbuf + 3) = word >> 24;
102 case 2:
103 *(unsigned char *)(trans->rxbuf + 2) = word >> 16;
104 case 1:
105 *(unsigned char *)(trans->rxbuf + 1) = word >> 8;
106 case 0:
107 *(unsigned char *)(trans->rxbuf + 0) = word;
108 }
109
110 trans->rxbuf += inc;
111
112 if (--desc->rxcount < 4)
113 {
114 unsigned long intreg = base->intreg;
115
116 if (desc->rxcount <= 0)
117 {
118 /* No more to receive - stop RX interrupts */
119 intreg &= ~(CSPI_INTREG_RHEN | CSPI_INTREG_RREN);
120 base->intreg = intreg;
121 break;
122 }
123 else if (!(intreg & CSPI_INTREG_RREN))
124 {
125 /* < 4 words expected - switch to RX ready */
126 intreg &= ~CSPI_INTREG_RHEN;
127 base->intreg = intreg | CSPI_INTREG_RREN;
128 }
129 }
130 }
131 }
132
133 if (trans->count > 0)
134 {
135 /* Data to transmit - fill TXFIFO or write until exhausted */
136 while ((base->statreg & CSPI_STATREG_TF) == 0)
137 {
138 uint32_t word = 0;
139
140 switch (desc->byte_size & 3)
141 {
142 case 3:
143 word = *(unsigned char *)(trans->txbuf + 3) << 24;
144 case 2:
145 word |= *(unsigned char *)(trans->txbuf + 2) << 16;
146 case 1:
147 word |= *(unsigned char *)(trans->txbuf + 1) << 8;
148 case 0:
149 word |= *(unsigned char *)(trans->txbuf + 0);
150 }
151
152 trans->txbuf += inc;
153
154 base->txdata = word;
155
156 if (--trans->count <= 0)
157 {
158 /* Out of data - stop TX interrupts */
159 base->intreg &= ~CSPI_INTREG_THEN;
160 break;
161 }
162 }
163 }
164
165 /* If all interrupts have been remasked - we're done */
166 if (base->intreg == 0)
167 {
168 base->statreg = CSPI_STATREG_TC | CSPI_STATREG_BO;
169 wakeup_signal(&desc->w);
170 }
171}
172
173/* Interrupt handlers for each CSPI module */
174#if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
175static __attribute__((interrupt("IRQ"))) void CSPI1_HANDLER(void)
176{
177 spi_interrupt(CSPI1_NUM);
178}
179#endif
180
181#if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
182static __attribute__((interrupt("IRQ"))) void CSPI2_HANDLER(void)
183{
184 spi_interrupt(CSPI2_NUM);
185}
186#endif
187
188#if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
189static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void)
190{
191 spi_interrupt(CSPI3_NUM);
192}
193#endif
194
195/* Write the context for the node and remember it to avoid unneeded reconfigure */
196static bool spi_set_context(struct spi_node *node,
197 struct spi_module_descriptor *desc)
198{
199 struct cspi_map * const base = desc->base;
200
201 if ((base->conreg & CSPI_CONREG_EN) == 0)
202 return false;
203
204 if (node != desc->last)
205 {
206 /* Switch the module's node */
207 desc->last = node;
208 desc->byte_size = (((node->conreg >> 8) & 0x1f) + 1 + 7) / 8 - 1;
209
210 /* Keep reserved and start bits cleared. Keep enabled bit. */
211 base->conreg =
212 (node->conreg & ~(0xfcc8e000 | CSPI_CONREG_XCH | CSPI_CONREG_SMC))
213 | CSPI_CONREG_EN;
214 /* Set the wait-states */
215 base->periodreg = node->periodreg & 0xffff;
216 /* Clear out any spuriously-pending interrupts */
217 base->statreg = CSPI_STATREG_TC | CSPI_STATREG_BO;
218 }
219
220 return true;
221}
222
223static void spi_reset(struct cspi_map * const base)
224{
225 /* Reset */
226 base->conreg &= ~CSPI_CONREG_EN;
227 base->conreg |= CSPI_CONREG_EN;
228 base->intreg = 0;
229 base->statreg = CSPI_STATREG_TC | CSPI_STATREG_BO;
230}
231
232/* Initialize each of the used SPI descriptors */
233void spi_init(void)
234{
235 int i;
236
237 for (i = 0; i < SPI_NUM_CSPI; i++)
238 {
239 struct spi_module_descriptor * const desc = &spi_descs[i];
240 mutex_init(&desc->m);
241 wakeup_init(&desc->w);
242 }
243}
244
245/* Get mutually-exclusive access to the node */
246void spi_lock(struct spi_node *node)
247{
248 mutex_lock(&spi_descs[node->num].m);
249}
250
251/* Release mutual exclusion */
252void spi_unlock(struct spi_node *node)
253{
254 mutex_unlock(&spi_descs[node->num].m);
255}
256
257/* Enable the specified module for the node */
258void spi_enable_module(struct spi_node *node)
259{
260 struct spi_module_descriptor * const desc = &spi_descs[node->num];
261
262 mutex_lock(&desc->m);
263
264 if (++desc->enab == 1)
265 {
266 /* First enable for this module */
267 struct cspi_map * const base = desc->base;
268
269 /* Enable clock-gating register */
270 ccm_module_clock_gating(desc->cg, CGM_ON_RUN_WAIT);
271 /* Reset */
272 spi_reset(base);
273 desc->last = NULL;
274 /* Enable interrupt at controller level */
275 avic_enable_int(desc->ints, INT_TYPE_IRQ, INT_PRIO_DEFAULT,
276 desc->handler);
277 }
278
279 mutex_unlock(&desc->m);
280}
281
282/* Disabled the specified module for the node */
283void spi_disable_module(struct spi_node *node)
284{
285 struct spi_module_descriptor * const desc = &spi_descs[node->num];
286
287 mutex_lock(&desc->m);
288
289 if (desc->enab > 0 && --desc->enab == 0)
290 {
291 /* Last enable for this module */
292 struct cspi_map * const base = desc->base;
293
294 /* Disable interrupt at controller level */
295 avic_disable_int(desc->ints);
296
297 /* Disable interface */
298 base->conreg &= ~CSPI_CONREG_EN;
299
300 /* Disable interface clock */
301 ccm_module_clock_gating(desc->cg, CGM_OFF);
302 }
303
304 mutex_unlock(&desc->m);
305}
306
307/* Send and/or receive data on the specified node */
308int spi_transfer(struct spi_node *node, struct spi_transfer *trans)
309{
310 struct spi_module_descriptor * const desc = &spi_descs[node->num];
311 int retval;
312
313 if (trans->count <= 0)
314 return true;
315
316 mutex_lock(&desc->m);
317
318 retval = spi_set_context(node, desc);
319
320 if (retval)
321 {
322 struct cspi_map * const base = desc->base;
323 unsigned long intreg;
324
325 desc->trans = trans;
326 desc->rxcount = trans->count;
327
328 /* Enable needed interrupts - FIFOs will start filling */
329 intreg = CSPI_INTREG_THEN;
330
331 intreg |= (trans->count < 4) ?
332 CSPI_INTREG_RREN : /* Must grab data on every word */
333 CSPI_INTREG_RHEN; /* Enough data to wait for half-full */
334
335 base->intreg = intreg;
336
337 /* Start transfer */
338 base->conreg |= CSPI_CONREG_XCH;
339
340 if (wakeup_wait(&desc->w, HZ) != OBJ_WAIT_SUCCEEDED)
341 {
342 base->intreg = 0; /* Stop SPI ints */
343 spi_reset(base); /* Reset module (esp. to empty FIFOs) */
344 desc->last = NULL; /* Force reconfigure */
345 retval = false;
346 }
347 }
348
349 mutex_unlock(&desc->m);
350
351 return retval;
352}
diff --git a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h b/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h
deleted file mode 100644
index cf536b646d..0000000000
--- a/firmware/target/arm/imx31/gigabeat-s/spi-imx31.h
+++ /dev/null
@@ -1,89 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2007 Will Robertson
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef SPI_IMX31_H
22#define SPI_IMX31_H
23
24#define USE_CSPI1_MODULE (1 << 0)
25#define USE_CSPI2_MODULE (1 << 1)
26#define USE_CSPI3_MODULE (1 << 2)
27
28/* SPI_MODULE_MASK is set in target's config */
29enum spi_module_number
30{
31 __CSPI_NUM_START = -1, /* The first will be 0 */
32#if (SPI_MODULE_MASK & USE_CSPI1_MODULE)
33 CSPI1_NUM,
34#endif
35#if (SPI_MODULE_MASK & USE_CSPI2_MODULE)
36 CSPI2_NUM,
37#endif
38#if (SPI_MODULE_MASK & USE_CSPI3_MODULE)
39 CSPI3_NUM,
40#endif
41 SPI_NUM_CSPI,
42};
43
44struct cspi_map
45{
46 volatile uint32_t rxdata; /* 00h */
47 volatile uint32_t txdata; /* 04h */
48 volatile uint32_t conreg; /* 08h */
49 volatile uint32_t intreg; /* 0Ch */
50 volatile uint32_t dmareg; /* 10h */
51 volatile uint32_t statreg; /* 14h */
52 volatile uint32_t periodreg; /* 18h */
53 volatile uint32_t skip1[0x69]; /* 1Ch */
54 volatile uint32_t testreg; /* 1C0h */
55};
56
57struct spi_node
58{
59 enum spi_module_number num; /* Module number (CSPIx_NUM) */
60 unsigned long conreg; /* CSPI conreg setup */
61 unsigned long periodreg; /* CSPI periodreg setup */
62};
63
64struct spi_transfer
65{
66 const void *txbuf;
67 void *rxbuf;
68 int count;
69};
70
71/* One-time init of SPI driver */
72void spi_init(void);
73
74/* Enable the specified module for the node */
75void spi_enable_module(struct spi_node *node);
76
77/* Disabled the specified module for the node */
78void spi_disable_module(struct spi_node *node);
79
80/* Lock module mutex */
81void spi_lock(struct spi_node *node);
82
83/* Unlock module mutex */
84void spi_unlock(struct spi_node *node);
85
86/* Send and/or receive data on the specified node */
87int spi_transfer(struct spi_node *node, struct spi_transfer *trans);
88
89#endif /* SPI_IMX31_H */
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c b/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c
index cd684e77ac..cd684e77ac 100644
--- a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/system-gigabeat-s.c
diff --git a/firmware/target/arm/imx31/gigabeat-s/timer-imx31.c b/firmware/target/arm/imx31/gigabeat-s/timer-gigabeat-s.c
index f3f78a1ee1..f3f78a1ee1 100644
--- a/firmware/target/arm/imx31/gigabeat-s/timer-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/timer-gigabeat-s.c
diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c
index 64ff04e7ae..d873c19ed3 100644
--- a/firmware/target/arm/imx31/gigabeat-s/usb-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c
@@ -27,10 +27,10 @@
27#include "usb_core.h" 27#include "usb_core.h"
28#include "usb_drv.h" 28#include "usb_drv.h"
29#include "usb-target.h" 29#include "usb-target.h"
30#include "mc13783.h"
30#include "ccm-imx31.h" 31#include "ccm-imx31.h"
31#include "power-imx31.h"
32#include "avic-imx31.h" 32#include "avic-imx31.h"
33#include "mc13783.h" 33#include "power-gigabeat-s.h"
34 34
35static int usb_status = USB_EXTRACTED; 35static int usb_status = USB_EXTRACTED;
36 36
diff --git a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c b/firmware/target/arm/imx31/gigabeat-s/wmcodec-gigabeat-s.c
index 06bb4d6306..96324cc162 100644
--- a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/wmcodec-gigabeat-s.c
@@ -25,6 +25,7 @@
25#include "kernel.h" 25#include "kernel.h"
26#include "sound.h" 26#include "sound.h"
27#include "wmcodec.h" 27#include "wmcodec.h"
28#include "i2s.h"
28#include "i2c-imx31.h" 29#include "i2c-imx31.h"
29 30
30/* NOTE: Some port-specific bits will have to be moved away (node and GPIO 31/* NOTE: Some port-specific bits will have to be moved away (node and GPIO
@@ -41,24 +42,7 @@ static struct i2c_node wm8978_i2c_node =
41 42
42void audiohw_init(void) 43void audiohw_init(void)
43{ 44{
44 /* How SYSCLK for codec is derived (USBPLL=338.688MHz). 45 i2s_reset();
45 *
46 * SSI post dividers (SSI2 PODF=4, SSI2 PRE PODF=0):
47 * 338688000Hz / 5 = 67737600Hz = ssi1_clk
48 *
49 * SSI bit clock dividers (DIV2=1, PSR=0, PM=0):
50 * ssi1_clk / 4 = 16934400Hz = INT_BIT_CLK (MCLK)
51 *
52 * WM Codec post divider (MCLKDIV=1.5):
53 * INT_BIT_CLK (MCLK) / 1.5 = 11289600Hz = 256*fs = SYSCLK
54 */
55 imx31_regmod32(&CCM_PDR1,
56 ((1-1) << CCM_PDR1_SSI1_PRE_PODF_POS) |
57 ((5-1) << CCM_PDR1_SSI1_PODF_POS) |
58 ((8-1) << CCM_PDR1_SSI2_PRE_PODF_POS) |
59 ((64-1) << CCM_PDR1_SSI2_PODF_POS),
60 CCM_PDR1_SSI1_PODF | CCM_PDR1_SSI2_PODF |
61 CCM_PDR1_SSI1_PRE_PODF | CCM_PDR1_SSI2_PRE_PODF);
62 46
63 i2c_enable_node(&wm8978_i2c_node, true); 47 i2c_enable_node(&wm8978_i2c_node, true);
64 48