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/avic-imx31.c | |
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/avic-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/avic-imx31.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/firmware/target/arm/imx31/avic-imx31.c b/firmware/target/arm/imx31/avic-imx31.c new file mode 100644 index 0000000000..4ba7da4be0 --- /dev/null +++ b/firmware/target/arm/imx31/avic-imx31.c | |||
@@ -0,0 +1,212 @@ | |||
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 | } | ||