diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2010-04-09 01:21:53 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2010-04-09 01:21:53 +0000 |
commit | 7abf2b53a462612808d46d6d77a7f35261a0e5a3 (patch) | |
tree | 241304f7cd2b5d1c2a9e091fe56a33d2d2f8e816 /firmware/target/arm/imx31/gigabeat-s | |
parent | 43304b87b0662d1619ac60e5297a1694aa580310 (diff) | |
download | rockbox-7abf2b53a462612808d46d6d77a7f35261a0e5a3.tar.gz rockbox-7abf2b53a462612808d46d6d77a7f35261a0e5a3.zip |
Gigabeat S/i.MX31: Sort files in the /target tree into things that are SoC-generic (into /imx31) and player-specific (into /gigabeat-s, based upon current appearances). Move i2s clock init into the appropriate file. Housekeeping only-- no functional changes.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25547 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s')
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 */ | ||
37 | static 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 */ | ||
95 | static 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 | |||
112 | static 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 | |||
143 | static 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 */ | ||
248 | static struct wakeup ata_dma_wakeup; | ||
249 | |||
250 | /** SDMA **/ | ||
251 | /* Array of buffer descriptors for large transfers and alignnment */ | ||
252 | static struct buffer_descriptor ata_bda[ATA_BD_COUNT] DEVBSS_ATTR; | ||
253 | /* ATA channel descriptors */ | ||
254 | static struct channel_descriptor ata_cd_rd DEVBSS_ATTR; /* read channel */ | ||
255 | static struct channel_descriptor ata_cd_wr DEVBSS_ATTR; /* write channel */ | ||
256 | /* DMA channel to be started for transfer */ | ||
257 | static 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. */ | ||
262 | static uint32_t scatter_buffer[32/4*2] DEVBSS_ATTR; | ||
263 | /* Address of ends in destination buffer for unaligned reads - copied after | ||
264 | * DMA completes. */ | ||
265 | static 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 */ | ||
272 | static unsigned long ata_dma_selected = ATA_DMA_PIO; | ||
273 | #endif /* HAVE_ATA_DMA */ | ||
274 | |||
275 | static unsigned int get_T(void) | ||
276 | { | ||
277 | /* T = ATA clock period in nanoseconds */ | ||
278 | return 1000 * 1000 * 1000 / ccm_get_ata_clk(); | ||
279 | } | ||
280 | |||
281 | static 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. */ | ||
288 | static 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 */ | ||
296 | void 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 | |||
312 | void 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 | |||
325 | void 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 | |||
346 | bool ata_is_coldstart(void) | ||
347 | { | ||
348 | return true; | ||
349 | } | ||
350 | |||
351 | #ifdef HAVE_ATA_DMA | ||
352 | static 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 | |||
363 | static 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 | |||
381 | void 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 */ | ||
412 | static 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 | |||
425 | bool 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 | |||
542 | bool 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 | |||
623 | void 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 | |||
75 | void ata_reset(void); | ||
76 | void ata_device_init(void); | ||
77 | bool ata_is_coldstart(void); | ||
78 | |||
79 | #define ATA_SET_DEVICE_FEATURES | ||
80 | void 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 | |||
28 | static 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 | |||
48 | void 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 */ | ||
70 | void __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 */ | ||
91 | void __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 | |||
102 | void 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 | |||
134 | void 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 | |||
144 | void 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 | |||
161 | void 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 | |||
181 | static 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 | |||
196 | void 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 | |||
24 | struct 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 | |||
177 | enum INT_TYPE | ||
178 | { | ||
179 | INT_TYPE_IRQ = 0, | ||
180 | INT_TYPE_FIQ | ||
181 | }; | ||
182 | |||
183 | enum 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 | |||
205 | void avic_init(void); | ||
206 | void avic_enable_int(enum IMX31_INT_LIST ints, enum INT_TYPE intstype, | ||
207 | unsigned long ni_priority, void (*handler)(void)); | ||
208 | void avic_set_int_priority(enum IMX31_INT_LIST ints, | ||
209 | unsigned long ni_priority); | ||
210 | void avic_disable_int(enum IMX31_INT_LIST ints); | ||
211 | void 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 */ | ||
29 | extern void UIE_VECTOR(void); | ||
30 | |||
31 | /* Event lists are allocated for the specific target */ | ||
32 | #if (GPIO_EVENT_MASK & USE_GPIO1_EVENTS) | ||
33 | static __attribute__((interrupt("IRQ"))) void GPIO1_HANDLER(void); | ||
34 | extern const struct gpio_event_list gpio1_event_list; | ||
35 | #endif | ||
36 | |||
37 | #if (GPIO_EVENT_MASK & USE_GPIO2_EVENTS) | ||
38 | static __attribute__((interrupt("IRQ"))) void GPIO2_HANDLER(void); | ||
39 | extern const struct gpio_event_list gpio2_event_list; | ||
40 | #endif | ||
41 | |||
42 | #if (GPIO_EVENT_MASK & USE_GPIO3_EVENTS) | ||
43 | static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void); | ||
44 | extern const struct gpio_event_list gpio3_event_list; | ||
45 | #endif | ||
46 | |||
47 | static 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 | |||
78 | static 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) | ||
115 | static __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) | ||
122 | static __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) | ||
129 | static __attribute__((interrupt("IRQ"))) void GPIO3_HANDLER(void) | ||
130 | { | ||
131 | gpio_call_events(&gpio_descs[GPIO3_NUM]); | ||
132 | } | ||
133 | #endif | ||
134 | |||
135 | void 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 | |||
154 | bool 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 | |||
191 | void 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 */ | ||
30 | enum 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 */ | ||
46 | enum 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 */ | ||
62 | enum 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 */ | ||
73 | struct 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 */ | ||
95 | struct 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 */ | ||
103 | struct 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 | |||
110 | void gpio_init(void); | ||
111 | bool gpio_enable_event(enum gpio_event_ids id); | ||
112 | void 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) | ||
31 | static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void); | ||
32 | #endif | ||
33 | #if (I2C_MODULE_MASK & USE_I2C2_MODULE) | ||
34 | static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void); | ||
35 | #endif | ||
36 | #if (I2C_MODULE_MASK & USE_I2C3_MODULE) | ||
37 | static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void); | ||
38 | #endif | ||
39 | |||
40 | static 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 | |||
82 | static 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 | { | ||
122 | i2c_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 | |||
156 | i2c_stop: | ||
157 | /* Generate STOP signal */ | ||
158 | base->i2cr &= ~(I2C_I2CR_MSTA | I2C_I2CR_IIEN); | ||
159 | i2c_done: | ||
160 | /* Signal thread we're done */ | ||
161 | wakeup_signal(&desc->w); | ||
162 | } | ||
163 | |||
164 | #if (I2C_MODULE_MASK & USE_I2C1_MODULE) | ||
165 | static __attribute__((interrupt("IRQ"))) void I2C1_HANDLER(void) | ||
166 | { | ||
167 | i2c_interrupt(I2C1_NUM); | ||
168 | } | ||
169 | #endif | ||
170 | #if (I2C_MODULE_MASK & USE_I2C2_MODULE) | ||
171 | static __attribute__((interrupt("IRQ"))) void I2C2_HANDLER(void) | ||
172 | { | ||
173 | i2c_interrupt(I2C2_NUM); | ||
174 | } | ||
175 | #endif | ||
176 | #if (I2C_MODULE_MASK & USE_I2C3_MODULE) | ||
177 | static __attribute__((interrupt("IRQ"))) void I2C3_HANDLER(void) | ||
178 | { | ||
179 | i2c_interrupt(I2C3_NUM); | ||
180 | } | ||
181 | #endif | ||
182 | |||
183 | static 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 | |||
234 | int 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 | |||
263 | int 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 | |||
280 | void 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 | |||
297 | void 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 | |||
328 | void 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 | |||
334 | void 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 | |||
31 | enum 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 */ | ||
47 | struct 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 | |||
60 | struct 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 | |||
67 | void i2c_init(void); | ||
68 | /* Enable or disable the node - modules will be switch on/off accordingly. */ | ||
69 | void i2c_enable_node(struct i2c_node *node, bool enable); | ||
70 | /* If addr < 0, then raw read */ | ||
71 | int i2c_read(struct i2c_node *node, int addr, unsigned char *data, int count); | ||
72 | int 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 */ | ||
75 | void i2c_lock_node(struct i2c_node *node); | ||
76 | void 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 | ||
24 | void i2s_reset(void) | 25 | void 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 */ | ||
41 | static 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 | |||
54 | extern const struct mc13783_event_list mc13783_event_list; | ||
55 | |||
56 | static int mc13783_thread_stack[DEFAULT_STACK_SIZE/sizeof(int)]; | ||
57 | static const char *mc13783_thread_name = "pmic"; | ||
58 | static struct wakeup mc13783_wake; | ||
59 | |||
60 | /* Tracking for which interrupts are enabled */ | ||
61 | static uint32_t pmic_int_enabled[2] = | ||
62 | { 0x00000000, 0x00000000 }; | ||
63 | |||
64 | static const unsigned char pmic_intm_regs[2] = | ||
65 | { MC13783_INTERRUPT_MASK0, MC13783_INTERRUPT_MASK1 }; | ||
66 | |||
67 | static const unsigned char pmic_ints_regs[2] = | ||
68 | { MC13783_INTERRUPT_STATUS0, MC13783_INTERRUPT_STATUS1 }; | ||
69 | |||
70 | #ifdef PMIC_DRIVER_CLOSE | ||
71 | static bool pmic_close = false; | ||
72 | static unsigned int mc13783_thread_id = 0; | ||
73 | #endif | ||
74 | |||
75 | static 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 */ | ||
136 | void 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 | |||
144 | void 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 | ||
168 | void 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 | |||
183 | bool 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 | |||
200 | void 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 | |||
215 | uint32_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 | |||
229 | uint32_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 | |||
243 | int 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 | |||
262 | uint32_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 | |||
283 | int 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 | |||
313 | uint32_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 | |||
333 | int 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 | |||
25 | unsigned long addr_virt_to_phys(unsigned long addr) | ||
26 | { | ||
27 | return addr | CSD0_BASE_ADDR; | ||
28 | } | ||
29 | |||
30 | unsigned 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 | |||
24 | void memory_init(void); | ||
25 | void set_page_tables(void); | ||
26 | unsigned long addr_virt_to_phys(unsigned long addr); | ||
27 | unsigned 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! */ |
32 | const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = | 32 | const 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 | |||
27 | int tx_rdy(void); | ||
28 | int rx_rdy(void); | ||
29 | void tx_writec(const unsigned char c); | ||
30 | void 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) | ||
31 | static __attribute__((interrupt("IRQ"))) void CSPI1_HANDLER(void); | ||
32 | #endif | ||
33 | #if (SPI_MODULE_MASK & USE_CSPI2_MODULE) | ||
34 | static __attribute__((interrupt("IRQ"))) void CSPI2_HANDLER(void); | ||
35 | #endif | ||
36 | #if (SPI_MODULE_MASK & USE_CSPI3_MODULE) | ||
37 | static __attribute__((interrupt("IRQ"))) void CSPI3_HANDLER(void); | ||
38 | #endif | ||
39 | |||
40 | /* State data associatated with each CSPI module */ | ||
41 | static 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 */ | ||
84 | static 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) | ||
175 | static __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) | ||
182 | static __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) | ||
189 | static __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 */ | ||
196 | static 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 | |||
223 | static 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 */ | ||
233 | void 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 */ | ||
246 | void spi_lock(struct spi_node *node) | ||
247 | { | ||
248 | mutex_lock(&spi_descs[node->num].m); | ||
249 | } | ||
250 | |||
251 | /* Release mutual exclusion */ | ||
252 | void 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 */ | ||
258 | void 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 */ | ||
283 | void 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 */ | ||
308 | int 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 */ | ||
29 | enum 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 | |||
44 | struct 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 | |||
57 | struct 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 | |||
64 | struct spi_transfer | ||
65 | { | ||
66 | const void *txbuf; | ||
67 | void *rxbuf; | ||
68 | int count; | ||
69 | }; | ||
70 | |||
71 | /* One-time init of SPI driver */ | ||
72 | void spi_init(void); | ||
73 | |||
74 | /* Enable the specified module for the node */ | ||
75 | void spi_enable_module(struct spi_node *node); | ||
76 | |||
77 | /* Disabled the specified module for the node */ | ||
78 | void spi_disable_module(struct spi_node *node); | ||
79 | |||
80 | /* Lock module mutex */ | ||
81 | void spi_lock(struct spi_node *node); | ||
82 | |||
83 | /* Unlock module mutex */ | ||
84 | void spi_unlock(struct spi_node *node); | ||
85 | |||
86 | /* Send and/or receive data on the specified node */ | ||
87 | int 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 | ||
35 | static int usb_status = USB_EXTRACTED; | 35 | static 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 | ||
42 | void audiohw_init(void) | 43 | void 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 | ||