diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-08 18:33:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-08 18:33:45 -0500 |
commit | 04a94babd68952a4e3cdd54ebf8ce8891f9b0f2e (patch) | |
tree | 9d4a01f6b6d0093397c2122c4d85abbb57f3e349 /arch/blackfin/mach-common | |
parent | 765cdb6cef63c0b41c3f6c9285769080b3f41bb0 (diff) | |
parent | 920e526f93009a81e09809edb7a755a5b22e907d (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6: (24 commits)
[Blackfin] arch: import defines for BF547 -- it is just like the BF548, but no CAN
[Blackfin] arch: fix build fails only include header files when enabled
[Blackfin] arch: declare default INSTALL_PATH for Blackfin ports
[Blackfin] arch: Encourage users to use the spidev character driver: Provide platform support
[Blackfin] arch: Enable UART2 and UART3 for bf548
[Blackfin] arch: Enable NET2272 on BF561-EZkit - remove request_mem_region
[Blackfin] arch:Fix BUG [#3876] pfbutton test for BTN3 on bf533 don't show complete info
[Blackfin] arch: remove duplicated definitions of the line discipline numbers N_* in asm-blackfin/termios.h
[Blackfin] arch: fix building with mtd uclinux by putting the mtd_phys option into the function it actually gets used in
[Blackfin] arch: simpler header and update dates
[Blackfin] arch: move the init sections to the end of memory
[Blackfin] arch: change the trace buffer control start/stop logic in the exception handlers
[Blackfin] arch: fix typo in printk message
[Blackfin] arch: this is an ezkit, not a stamp, so fixup the init function name
[Blackfin] arch: add slightly better help text for CPLB_INFO
[Blackfin] arch: Fix BUG - Enable ISP1362 driver to work ok with BF561
[Blackfin] arch: Fix header file information
[Blackfin] arch: Add Support for ISP1362
[Blackfin] arch: add support for cmdline partitioning to the BF533-STAMP flash map driver and enable it as a module by default
[Blackfin] arch: hook up set_irq_wake in Blackfin's irq code
...
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r-- | arch/blackfin/mach-common/Makefile | 4 | ||||
-rw-r--r-- | arch/blackfin/mach-common/dpmc.S | 32 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 12 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority-dc.c | 484 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c (renamed from arch/blackfin/mach-common/ints-priority-sc.c) | 271 | ||||
-rw-r--r-- | arch/blackfin/mach-common/pm.c | 44 |
6 files changed, 279 insertions, 568 deletions
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile index 8636d4284bdb..15e33ca1ce80 100644 --- a/arch/blackfin/mach-common/Makefile +++ b/arch/blackfin/mach-common/Makefile | |||
@@ -4,8 +4,6 @@ | |||
4 | 4 | ||
5 | obj-y := \ | 5 | obj-y := \ |
6 | cache.o cacheinit.o entry.o \ | 6 | cache.o cacheinit.o entry.o \ |
7 | interrupt.o lock.o irqpanic.o arch_checks.o | 7 | interrupt.o lock.o irqpanic.o arch_checks.o ints-priority.o |
8 | 8 | ||
9 | obj-$(CONFIG_BFIN_SINGLE_CORE) += ints-priority-sc.o | ||
10 | obj-$(CONFIG_BFIN_DUAL_CORE) += ints-priority-dc.o | ||
11 | obj-$(CONFIG_PM) += pm.o dpmc.o | 9 | obj-$(CONFIG_PM) += pm.o dpmc.o |
diff --git a/arch/blackfin/mach-common/dpmc.S b/arch/blackfin/mach-common/dpmc.S index b82c096e1980..b80ddd8b232d 100644 --- a/arch/blackfin/mach-common/dpmc.S +++ b/arch/blackfin/mach-common/dpmc.S | |||
@@ -191,6 +191,9 @@ ENTRY(_sleep_mode) | |||
191 | call _test_pll_locked; | 191 | call _test_pll_locked; |
192 | 192 | ||
193 | R0 = IWR_ENABLE(0); | 193 | R0 = IWR_ENABLE(0); |
194 | R1 = IWR_DISABLE_ALL; | ||
195 | R2 = IWR_DISABLE_ALL; | ||
196 | |||
194 | call _set_sic_iwr; | 197 | call _set_sic_iwr; |
195 | 198 | ||
196 | P0.H = hi(PLL_CTL); | 199 | P0.H = hi(PLL_CTL); |
@@ -237,6 +240,10 @@ ENTRY(_deep_sleep) | |||
237 | 240 | ||
238 | CLI R4; | 241 | CLI R4; |
239 | 242 | ||
243 | R0 = IWR_ENABLE(0); | ||
244 | R1 = IWR_DISABLE_ALL; | ||
245 | R2 = IWR_DISABLE_ALL; | ||
246 | |||
240 | call _set_sic_iwr; | 247 | call _set_sic_iwr; |
241 | 248 | ||
242 | call _set_dram_srfs; | 249 | call _set_dram_srfs; |
@@ -261,6 +268,9 @@ ENTRY(_deep_sleep) | |||
261 | call _test_pll_locked; | 268 | call _test_pll_locked; |
262 | 269 | ||
263 | R0 = IWR_ENABLE(0); | 270 | R0 = IWR_ENABLE(0); |
271 | R1 = IWR_DISABLE_ALL; | ||
272 | R2 = IWR_DISABLE_ALL; | ||
273 | |||
264 | call _set_sic_iwr; | 274 | call _set_sic_iwr; |
265 | 275 | ||
266 | P0.H = hi(PLL_CTL); | 276 | P0.H = hi(PLL_CTL); |
@@ -286,7 +296,13 @@ ENTRY(_sleep_deeper) | |||
286 | CLI R4; | 296 | CLI R4; |
287 | 297 | ||
288 | P3 = R0; | 298 | P3 = R0; |
299 | P4 = R1; | ||
300 | P5 = R2; | ||
301 | |||
289 | R0 = IWR_ENABLE(0); | 302 | R0 = IWR_ENABLE(0); |
303 | R1 = IWR_DISABLE_ALL; | ||
304 | R2 = IWR_DISABLE_ALL; | ||
305 | |||
290 | call _set_sic_iwr; | 306 | call _set_sic_iwr; |
291 | call _set_dram_srfs; /* Set SDRAM Self Refresh */ | 307 | call _set_dram_srfs; /* Set SDRAM Self Refresh */ |
292 | 308 | ||
@@ -327,6 +343,8 @@ ENTRY(_sleep_deeper) | |||
327 | call _test_pll_locked; | 343 | call _test_pll_locked; |
328 | 344 | ||
329 | R0 = P3; | 345 | R0 = P3; |
346 | R1 = P4; | ||
347 | R3 = P5; | ||
330 | call _set_sic_iwr; /* Set Awake from IDLE */ | 348 | call _set_sic_iwr; /* Set Awake from IDLE */ |
331 | 349 | ||
332 | P0.H = hi(PLL_CTL); | 350 | P0.H = hi(PLL_CTL); |
@@ -340,6 +358,9 @@ ENTRY(_sleep_deeper) | |||
340 | call _test_pll_locked; | 358 | call _test_pll_locked; |
341 | 359 | ||
342 | R0 = IWR_ENABLE(0); | 360 | R0 = IWR_ENABLE(0); |
361 | R1 = IWR_DISABLE_ALL; | ||
362 | R2 = IWR_DISABLE_ALL; | ||
363 | |||
343 | call _set_sic_iwr; /* Set Awake from IDLE PLL */ | 364 | call _set_sic_iwr; /* Set Awake from IDLE PLL */ |
344 | 365 | ||
345 | P0.H = hi(VR_CTL); | 366 | P0.H = hi(VR_CTL); |
@@ -417,14 +438,23 @@ ENTRY(_unset_dram_srfs) | |||
417 | RTS; | 438 | RTS; |
418 | 439 | ||
419 | ENTRY(_set_sic_iwr) | 440 | ENTRY(_set_sic_iwr) |
420 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) | 441 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) |
421 | P0.H = hi(SIC_IWR0); | 442 | P0.H = hi(SIC_IWR0); |
422 | P0.L = lo(SIC_IWR0); | 443 | P0.L = lo(SIC_IWR0); |
444 | P1.H = hi(SIC_IWR1); | ||
445 | P1.L = lo(SIC_IWR1); | ||
446 | [P1] = R1; | ||
447 | #if defined(CONFIG_BF54x) | ||
448 | P1.H = hi(SIC_IWR2); | ||
449 | P1.L = lo(SIC_IWR2); | ||
450 | [P1] = R2; | ||
451 | #endif | ||
423 | #else | 452 | #else |
424 | P0.H = hi(SIC_IWR); | 453 | P0.H = hi(SIC_IWR); |
425 | P0.L = lo(SIC_IWR); | 454 | P0.L = lo(SIC_IWR); |
426 | #endif | 455 | #endif |
427 | [P0] = R0; | 456 | [P0] = R0; |
457 | |||
428 | SSYNC; | 458 | SSYNC; |
429 | RTS; | 459 | RTS; |
430 | 460 | ||
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index fdd9bf43361e..2cbb7a0bc38e 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S | |||
@@ -121,6 +121,7 @@ ENTRY(_ex_icplb_miss) | |||
121 | (R7:6,P5:4) = [sp++]; | 121 | (R7:6,P5:4) = [sp++]; |
122 | ASTAT = [sp++]; | 122 | ASTAT = [sp++]; |
123 | SAVE_ALL_SYS | 123 | SAVE_ALL_SYS |
124 | DEBUG_HWTRACE_SAVE(p5, r7) | ||
124 | #ifdef CONFIG_MPU | 125 | #ifdef CONFIG_MPU |
125 | R0 = SEQSTAT; | 126 | R0 = SEQSTAT; |
126 | R1 = SP; | 127 | R1 = SP; |
@@ -132,14 +133,13 @@ ENTRY(_ex_icplb_miss) | |||
132 | #else | 133 | #else |
133 | call __cplb_hdr; | 134 | call __cplb_hdr; |
134 | #endif | 135 | #endif |
135 | DEBUG_START_HWTRACE(p5, r7) | 136 | DEBUG_HWTRACE_RESTORE(p5, r7) |
136 | RESTORE_ALL_SYS | 137 | RESTORE_ALL_SYS |
137 | SP = EX_SCRATCH_REG; | 138 | SP = EX_SCRATCH_REG; |
138 | rtx; | 139 | rtx; |
139 | ENDPROC(_ex_icplb_miss) | 140 | ENDPROC(_ex_icplb_miss) |
140 | 141 | ||
141 | ENTRY(_ex_syscall) | 142 | ENTRY(_ex_syscall) |
142 | DEBUG_START_HWTRACE(p5, r7) | ||
143 | (R7:6,P5:4) = [sp++]; | 143 | (R7:6,P5:4) = [sp++]; |
144 | ASTAT = [sp++]; | 144 | ASTAT = [sp++]; |
145 | raise 15; /* invoked by TRAP #0, for sys call */ | 145 | raise 15; /* invoked by TRAP #0, for sys call */ |
@@ -178,7 +178,6 @@ ENTRY(_ex_single_step) | |||
178 | ENDPROC(_ex_single_step) | 178 | ENDPROC(_ex_single_step) |
179 | 179 | ||
180 | ENTRY(_bfin_return_from_exception) | 180 | ENTRY(_bfin_return_from_exception) |
181 | DEBUG_START_HWTRACE(p5, r7) | ||
182 | #if ANOMALY_05000257 | 181 | #if ANOMALY_05000257 |
183 | R7=LC0; | 182 | R7=LC0; |
184 | LC0=R7; | 183 | LC0=R7; |
@@ -200,10 +199,9 @@ ENTRY(_handle_bad_cplb) | |||
200 | * need to make a CPLB exception look like a normal exception | 199 | * need to make a CPLB exception look like a normal exception |
201 | */ | 200 | */ |
202 | 201 | ||
203 | DEBUG_START_HWTRACE(p5, r7) | ||
204 | RESTORE_ALL_SYS | 202 | RESTORE_ALL_SYS |
205 | [--sp] = ASTAT; | 203 | [--sp] = ASTAT; |
206 | [--sp] = (R7:6, P5:4); | 204 | [--sp] = (R7:6,P5:4); |
207 | 205 | ||
208 | ENTRY(_ex_replaceable) | 206 | ENTRY(_ex_replaceable) |
209 | nop; | 207 | nop; |
@@ -253,7 +251,6 @@ ENTRY(_ex_trap_c) | |||
253 | R6 = SEQSTAT; | 251 | R6 = SEQSTAT; |
254 | [P5] = R6; | 252 | [P5] = R6; |
255 | 253 | ||
256 | DEBUG_START_HWTRACE(p5, r7) | ||
257 | (R7:6,P5:4) = [sp++]; | 254 | (R7:6,P5:4) = [sp++]; |
258 | ASTAT = [sp++]; | 255 | ASTAT = [sp++]; |
259 | SP = EX_SCRATCH_REG; | 256 | SP = EX_SCRATCH_REG; |
@@ -382,8 +379,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ | |||
382 | sp.h = _exception_stack_top; | 379 | sp.h = _exception_stack_top; |
383 | /* Try to deal with syscalls quickly. */ | 380 | /* Try to deal with syscalls quickly. */ |
384 | [--sp] = ASTAT; | 381 | [--sp] = ASTAT; |
385 | [--sp] = (R7:6, P5:4); | 382 | [--sp] = (R7:6,P5:4); |
386 | DEBUG_STOP_HWTRACE(p5, r7) | ||
387 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ | 383 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ |
388 | r6.l = lo(SEQSTAT_EXCAUSE); | 384 | r6.l = lo(SEQSTAT_EXCAUSE); |
389 | r6.h = hi(SEQSTAT_EXCAUSE); | 385 | r6.h = hi(SEQSTAT_EXCAUSE); |
diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c deleted file mode 100644 index 8d18d6b163bb..000000000000 --- a/arch/blackfin/mach-common/ints-priority-dc.c +++ /dev/null | |||
@@ -1,484 +0,0 @@ | |||
1 | /* | ||
2 | * File: arch/blackfin/mach-common/ints-priority-dc.c | ||
3 | * Based on: | ||
4 | * Author: | ||
5 | * | ||
6 | * Created: ? | ||
7 | * Description: Set up the interrupt priorities | ||
8 | * | ||
9 | * Modified: | ||
10 | * 1996 Roman Zippel | ||
11 | * 1999 D. Jeff Dionne <jeff@uclinux.org> | ||
12 | * 2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca> | ||
13 | * 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> | ||
14 | * 2003 Metrowerks/Motorola | ||
15 | * 2003 Bas Vermeulen <bas@buyways.nl> | ||
16 | * Copyright 2004-2006 Analog Devices Inc. | ||
17 | * | ||
18 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation; either version 2 of the License, or | ||
23 | * (at your option) any later version. | ||
24 | * | ||
25 | * This program is distributed in the hope that it will be useful, | ||
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
28 | * GNU General Public License for more details. | ||
29 | * | ||
30 | * You should have received a copy of the GNU General Public License | ||
31 | * along with this program; if not, see the file COPYING, or write | ||
32 | * to the Free Software Foundation, Inc., | ||
33 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/kernel_stat.h> | ||
38 | #include <linux/seq_file.h> | ||
39 | #include <linux/irq.h> | ||
40 | #ifdef CONFIG_KGDB | ||
41 | #include <linux/kgdb.h> | ||
42 | #endif | ||
43 | #include <asm/traps.h> | ||
44 | #include <asm/blackfin.h> | ||
45 | #include <asm/gpio.h> | ||
46 | #include <asm/irq_handler.h> | ||
47 | |||
48 | /* | ||
49 | * NOTES: | ||
50 | * - we have separated the physical Hardware interrupt from the | ||
51 | * levels that the LINUX kernel sees (see the description in irq.h) | ||
52 | * - | ||
53 | */ | ||
54 | |||
55 | /* Initialize this to an actual value to force it into the .data | ||
56 | * section so that we know it is properly initialized at entry into | ||
57 | * the kernel but before bss is initialized to zero (which is where | ||
58 | * it would live otherwise). The 0x1f magic represents the IRQs we | ||
59 | * cannot actually mask out in hardware. | ||
60 | */ | ||
61 | unsigned long irq_flags = 0x1f; | ||
62 | |||
63 | /* The number of spurious interrupts */ | ||
64 | atomic_t num_spurious; | ||
65 | |||
66 | struct ivgx { | ||
67 | /* irq number for request_irq, available in mach-bf561/irq.h */ | ||
68 | int irqno; | ||
69 | /* corresponding bit in the SICA_ISR0 register */ | ||
70 | int isrflag0; | ||
71 | /* corresponding bit in the SICA_ISR1 register */ | ||
72 | int isrflag1; | ||
73 | } ivg_table[NR_PERI_INTS]; | ||
74 | |||
75 | struct ivg_slice { | ||
76 | /* position of first irq in ivg_table for given ivg */ | ||
77 | struct ivgx *ifirst; | ||
78 | struct ivgx *istop; | ||
79 | } ivg7_13[IVG13 - IVG7 + 1]; | ||
80 | |||
81 | static void search_IAR(void); | ||
82 | |||
83 | /* | ||
84 | * Search SIC_IAR and fill tables with the irqvalues | ||
85 | * and their positions in the SIC_ISR register. | ||
86 | */ | ||
87 | static void __init search_IAR(void) | ||
88 | { | ||
89 | unsigned ivg, irq_pos = 0; | ||
90 | for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) { | ||
91 | int irqn; | ||
92 | |||
93 | ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos]; | ||
94 | |||
95 | for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { | ||
96 | int iar_shift = (irqn & 7) * 4; | ||
97 | if (ivg == | ||
98 | (0xf & | ||
99 | bfin_read32((unsigned long *)SICA_IAR0 + | ||
100 | (irqn >> 3)) >> iar_shift)) { | ||
101 | ivg_table[irq_pos].irqno = IVG7 + irqn; | ||
102 | ivg_table[irq_pos].isrflag0 = | ||
103 | (irqn < 32 ? (1 << irqn) : 0); | ||
104 | ivg_table[irq_pos].isrflag1 = | ||
105 | (irqn < 32 ? 0 : (1 << (irqn - 32))); | ||
106 | ivg7_13[ivg].istop++; | ||
107 | irq_pos++; | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * This is for BF561 internal IRQs | ||
115 | */ | ||
116 | |||
117 | static void ack_noop(unsigned int irq) | ||
118 | { | ||
119 | /* Dummy function. */ | ||
120 | } | ||
121 | |||
122 | static void bf561_core_mask_irq(unsigned int irq) | ||
123 | { | ||
124 | irq_flags &= ~(1 << irq); | ||
125 | if (!irqs_disabled()) | ||
126 | local_irq_enable(); | ||
127 | } | ||
128 | |||
129 | static void bf561_core_unmask_irq(unsigned int irq) | ||
130 | { | ||
131 | irq_flags |= 1 << irq; | ||
132 | /* | ||
133 | * If interrupts are enabled, IMASK must contain the same value | ||
134 | * as irq_flags. Make sure that invariant holds. If interrupts | ||
135 | * are currently disabled we need not do anything; one of the | ||
136 | * callers will take care of setting IMASK to the proper value | ||
137 | * when reenabling interrupts. | ||
138 | * local_irq_enable just does "STI irq_flags", so it's exactly | ||
139 | * what we need. | ||
140 | */ | ||
141 | if (!irqs_disabled()) | ||
142 | local_irq_enable(); | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | static void bf561_internal_mask_irq(unsigned int irq) | ||
147 | { | ||
148 | unsigned long irq_mask; | ||
149 | if ((irq - (IRQ_CORETMR + 1)) < 32) { | ||
150 | irq_mask = (1 << (irq - (IRQ_CORETMR + 1))); | ||
151 | bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() & ~irq_mask); | ||
152 | } else { | ||
153 | irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32)); | ||
154 | bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() & ~irq_mask); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | static void bf561_internal_unmask_irq(unsigned int irq) | ||
159 | { | ||
160 | unsigned long irq_mask; | ||
161 | |||
162 | if ((irq - (IRQ_CORETMR + 1)) < 32) { | ||
163 | irq_mask = (1 << (irq - (IRQ_CORETMR + 1))); | ||
164 | bfin_write_SICA_IMASK0(bfin_read_SICA_IMASK0() | irq_mask); | ||
165 | } else { | ||
166 | irq_mask = (1 << (irq - (IRQ_CORETMR + 1) - 32)); | ||
167 | bfin_write_SICA_IMASK1(bfin_read_SICA_IMASK1() | irq_mask); | ||
168 | } | ||
169 | SSYNC(); | ||
170 | } | ||
171 | |||
172 | static struct irq_chip bf561_core_irqchip = { | ||
173 | .ack = ack_noop, | ||
174 | .mask = bf561_core_mask_irq, | ||
175 | .unmask = bf561_core_unmask_irq, | ||
176 | }; | ||
177 | |||
178 | static struct irq_chip bf561_internal_irqchip = { | ||
179 | .ack = ack_noop, | ||
180 | .mask = bf561_internal_mask_irq, | ||
181 | .unmask = bf561_internal_unmask_irq, | ||
182 | }; | ||
183 | |||
184 | static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)]; | ||
185 | static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)]; | ||
186 | |||
187 | static void bf561_gpio_ack_irq(unsigned int irq) | ||
188 | { | ||
189 | u16 gpionr = irq - IRQ_PF0; | ||
190 | |||
191 | if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { | ||
192 | set_gpio_data(gpionr, 0); | ||
193 | SSYNC(); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | static void bf561_gpio_mask_ack_irq(unsigned int irq) | ||
198 | { | ||
199 | u16 gpionr = irq - IRQ_PF0; | ||
200 | |||
201 | if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) { | ||
202 | set_gpio_data(gpionr, 0); | ||
203 | SSYNC(); | ||
204 | } | ||
205 | |||
206 | set_gpio_maska(gpionr, 0); | ||
207 | SSYNC(); | ||
208 | } | ||
209 | |||
210 | static void bf561_gpio_mask_irq(unsigned int irq) | ||
211 | { | ||
212 | set_gpio_maska(irq - IRQ_PF0, 0); | ||
213 | SSYNC(); | ||
214 | } | ||
215 | |||
216 | static void bf561_gpio_unmask_irq(unsigned int irq) | ||
217 | { | ||
218 | set_gpio_maska(irq - IRQ_PF0, 1); | ||
219 | SSYNC(); | ||
220 | } | ||
221 | |||
222 | static unsigned int bf561_gpio_irq_startup(unsigned int irq) | ||
223 | { | ||
224 | unsigned int ret; | ||
225 | char buf[8]; | ||
226 | u16 gpionr = irq - IRQ_PF0; | ||
227 | |||
228 | if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { | ||
229 | snprintf(buf, sizeof buf, "IRQ %d", irq); | ||
230 | ret = gpio_request(gpionr, buf); | ||
231 | if (ret) | ||
232 | return ret; | ||
233 | |||
234 | } | ||
235 | |||
236 | gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); | ||
237 | bf561_gpio_unmask_irq(irq); | ||
238 | |||
239 | return ret; | ||
240 | |||
241 | } | ||
242 | |||
243 | static void bf561_gpio_irq_shutdown(unsigned int irq) | ||
244 | { | ||
245 | bf561_gpio_mask_irq(irq); | ||
246 | gpio_free(irq - IRQ_PF0); | ||
247 | gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0); | ||
248 | } | ||
249 | |||
250 | static int bf561_gpio_irq_type(unsigned int irq, unsigned int type) | ||
251 | { | ||
252 | |||
253 | unsigned int ret; | ||
254 | char buf[8]; | ||
255 | u16 gpionr = irq - IRQ_PF0; | ||
256 | |||
257 | |||
258 | if (type == IRQ_TYPE_PROBE) { | ||
259 | /* only probe unenabled GPIO interrupt lines */ | ||
260 | if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)) | ||
261 | return 0; | ||
262 | type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | ||
263 | |||
264 | } | ||
265 | |||
266 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING | | ||
267 | IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { | ||
268 | |||
269 | if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) { | ||
270 | snprintf(buf, sizeof buf, "IRQ %d", irq); | ||
271 | ret = gpio_request(gpionr, buf); | ||
272 | if (ret) | ||
273 | return ret; | ||
274 | |||
275 | } | ||
276 | |||
277 | gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr); | ||
278 | } else { | ||
279 | gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | |||
284 | set_gpio_dir(gpionr, 0); | ||
285 | set_gpio_inen(gpionr, 1); | ||
286 | |||
287 | |||
288 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | ||
289 | gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr); | ||
290 | set_gpio_edge(gpionr, 1); | ||
291 | } else { | ||
292 | set_gpio_edge(gpionr, 0); | ||
293 | gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); | ||
294 | } | ||
295 | |||
296 | if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) | ||
297 | == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) | ||
298 | set_gpio_both(gpionr, 1); | ||
299 | else | ||
300 | set_gpio_both(gpionr, 0); | ||
301 | |||
302 | if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))) | ||
303 | set_gpio_polar(gpionr, 1); /* low or falling edge denoted by one */ | ||
304 | else | ||
305 | set_gpio_polar(gpionr, 0); /* high or rising edge denoted by zero */ | ||
306 | |||
307 | SSYNC(); | ||
308 | |||
309 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) | ||
310 | set_irq_handler(irq, handle_edge_irq); | ||
311 | else | ||
312 | set_irq_handler(irq, handle_level_irq); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static struct irq_chip bf561_gpio_irqchip = { | ||
318 | .ack = bf561_gpio_ack_irq, | ||
319 | .mask = bf561_gpio_mask_irq, | ||
320 | .mask_ack = bf561_gpio_mask_ack_irq, | ||
321 | .unmask = bf561_gpio_unmask_irq, | ||
322 | .set_type = bf561_gpio_irq_type, | ||
323 | .startup = bf561_gpio_irq_startup, | ||
324 | .shutdown = bf561_gpio_irq_shutdown | ||
325 | }; | ||
326 | |||
327 | static void bf561_demux_gpio_irq(unsigned int inta_irq, | ||
328 | struct irq_desc *intb_desc) | ||
329 | { | ||
330 | int irq, flag_d, mask; | ||
331 | u16 gpio; | ||
332 | |||
333 | switch (inta_irq) { | ||
334 | case IRQ_PROG0_INTA: | ||
335 | irq = IRQ_PF0; | ||
336 | break; | ||
337 | case IRQ_PROG1_INTA: | ||
338 | irq = IRQ_PF16; | ||
339 | break; | ||
340 | case IRQ_PROG2_INTA: | ||
341 | irq = IRQ_PF32; | ||
342 | break; | ||
343 | default: | ||
344 | dump_stack(); | ||
345 | return; | ||
346 | } | ||
347 | |||
348 | gpio = irq - IRQ_PF0; | ||
349 | |||
350 | flag_d = get_gpiop_data(gpio); | ||
351 | mask = flag_d & (gpio_enabled[gpio_bank(gpio)] & | ||
352 | get_gpiop_maska(gpio)); | ||
353 | |||
354 | do { | ||
355 | if (mask & 1) { | ||
356 | struct irq_desc *desc = irq_desc + irq; | ||
357 | desc->handle_irq(irq, desc); | ||
358 | } | ||
359 | irq++; | ||
360 | mask >>= 1; | ||
361 | } while (mask); | ||
362 | |||
363 | |||
364 | } | ||
365 | |||
366 | void __init init_exception_vectors(void) | ||
367 | { | ||
368 | SSYNC(); | ||
369 | |||
370 | /* cannot program in software: | ||
371 | * evt0 - emulation (jtag) | ||
372 | * evt1 - reset | ||
373 | */ | ||
374 | bfin_write_EVT2(evt_nmi); | ||
375 | bfin_write_EVT3(trap); | ||
376 | bfin_write_EVT5(evt_ivhw); | ||
377 | bfin_write_EVT6(evt_timer); | ||
378 | bfin_write_EVT7(evt_evt7); | ||
379 | bfin_write_EVT8(evt_evt8); | ||
380 | bfin_write_EVT9(evt_evt9); | ||
381 | bfin_write_EVT10(evt_evt10); | ||
382 | bfin_write_EVT11(evt_evt11); | ||
383 | bfin_write_EVT12(evt_evt12); | ||
384 | bfin_write_EVT13(evt_evt13); | ||
385 | bfin_write_EVT14(evt14_softirq); | ||
386 | bfin_write_EVT15(evt_system_call); | ||
387 | CSYNC(); | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * This function should be called during kernel startup to initialize | ||
392 | * the BFin IRQ handling routines. | ||
393 | */ | ||
394 | int __init init_arch_irq(void) | ||
395 | { | ||
396 | int irq; | ||
397 | unsigned long ilat = 0; | ||
398 | /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ | ||
399 | bfin_write_SICA_IMASK0(SIC_UNMASK_ALL); | ||
400 | bfin_write_SICA_IMASK1(SIC_UNMASK_ALL); | ||
401 | SSYNC(); | ||
402 | |||
403 | bfin_write_SICA_IWR0(IWR_ENABLE_ALL); | ||
404 | bfin_write_SICA_IWR1(IWR_ENABLE_ALL); | ||
405 | |||
406 | local_irq_disable(); | ||
407 | |||
408 | init_exception_buff(); | ||
409 | |||
410 | for (irq = 0; irq <= SYS_IRQS; irq++) { | ||
411 | if (irq <= IRQ_CORETMR) | ||
412 | set_irq_chip(irq, &bf561_core_irqchip); | ||
413 | else | ||
414 | set_irq_chip(irq, &bf561_internal_irqchip); | ||
415 | |||
416 | if ((irq != IRQ_PROG0_INTA) && | ||
417 | (irq != IRQ_PROG1_INTA) && | ||
418 | (irq != IRQ_PROG2_INTA)) | ||
419 | set_irq_handler(irq, handle_simple_irq); | ||
420 | else | ||
421 | set_irq_chained_handler(irq, bf561_demux_gpio_irq); | ||
422 | } | ||
423 | |||
424 | for (irq = IRQ_PF0; irq <= IRQ_PF47; irq++) { | ||
425 | set_irq_chip(irq, &bf561_gpio_irqchip); | ||
426 | /* if configured as edge, then will be changed to do_edge_IRQ */ | ||
427 | set_irq_handler(irq, handle_level_irq); | ||
428 | } | ||
429 | |||
430 | bfin_write_IMASK(0); | ||
431 | CSYNC(); | ||
432 | ilat = bfin_read_ILAT(); | ||
433 | CSYNC(); | ||
434 | bfin_write_ILAT(ilat); | ||
435 | CSYNC(); | ||
436 | |||
437 | printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n"); | ||
438 | /* IMASK=xxx is equivalent to STI xx or irq_flags=xx, | ||
439 | * local_irq_enable() | ||
440 | */ | ||
441 | program_IAR(); | ||
442 | /* Therefore it's better to setup IARs before interrupts enabled */ | ||
443 | search_IAR(); | ||
444 | |||
445 | /* Enable interrupts IVG7-15 */ | ||
446 | irq_flags = irq_flags | IMASK_IVG15 | | ||
447 | IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | | ||
448 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | #ifdef CONFIG_DO_IRQ_L1 | ||
454 | __attribute__((l1_text)) | ||
455 | #endif | ||
456 | void do_irq(int vec, struct pt_regs *fp) | ||
457 | { | ||
458 | if (vec == EVT_IVTMR_P) { | ||
459 | vec = IRQ_CORETMR; | ||
460 | } else { | ||
461 | struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; | ||
462 | struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; | ||
463 | unsigned long sic_status0, sic_status1; | ||
464 | |||
465 | SSYNC(); | ||
466 | sic_status0 = bfin_read_SICA_IMASK0() & bfin_read_SICA_ISR0(); | ||
467 | sic_status1 = bfin_read_SICA_IMASK1() & bfin_read_SICA_ISR1(); | ||
468 | |||
469 | for (;; ivg++) { | ||
470 | if (ivg >= ivg_stop) { | ||
471 | atomic_inc(&num_spurious); | ||
472 | return; | ||
473 | } else if ((sic_status0 & ivg->isrflag0) || | ||
474 | (sic_status1 & ivg->isrflag1)) | ||
475 | break; | ||
476 | } | ||
477 | vec = ivg->irqno; | ||
478 | } | ||
479 | asm_do_IRQ(vec, fp); | ||
480 | |||
481 | #ifdef CONFIG_KGDB | ||
482 | kgdb_process_breakpoint(); | ||
483 | #endif | ||
484 | } | ||
diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority.c index dec42acb5de0..880595afe98d 100644 --- a/arch/blackfin/mach-common/ints-priority-sc.c +++ b/arch/blackfin/mach-common/ints-priority.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * File: arch/blackfin/mach-common/ints-priority-sc.c | 2 | * File: arch/blackfin/mach-common/ints-priority.c |
3 | * Based on: | 3 | * Based on: |
4 | * Author: | 4 | * Author: |
5 | * | 5 | * |
@@ -13,7 +13,7 @@ | |||
13 | * 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> | 13 | * 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> |
14 | * 2003 Metrowerks/Motorola | 14 | * 2003 Metrowerks/Motorola |
15 | * 2003 Bas Vermeulen <bas@buyways.nl> | 15 | * 2003 Bas Vermeulen <bas@buyways.nl> |
16 | * Copyright 2004-2007 Analog Devices Inc. | 16 | * Copyright 2004-2008 Analog Devices Inc. |
17 | * | 17 | * |
18 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 18 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
19 | * | 19 | * |
@@ -69,6 +69,10 @@ unsigned long irq_flags = 0x1f; | |||
69 | /* The number of spurious interrupts */ | 69 | /* The number of spurious interrupts */ |
70 | atomic_t num_spurious; | 70 | atomic_t num_spurious; |
71 | 71 | ||
72 | #ifdef CONFIG_PM | ||
73 | unsigned long bfin_sic_iwr[3]; /* Up to 3 SIC_IWRx registers */ | ||
74 | #endif | ||
75 | |||
72 | struct ivgx { | 76 | struct ivgx { |
73 | /* irq number for request_irq, available in mach-bf533/irq.h */ | 77 | /* irq number for request_irq, available in mach-bf533/irq.h */ |
74 | unsigned int irqno; | 78 | unsigned int irqno; |
@@ -98,8 +102,7 @@ static void __init search_IAR(void) | |||
98 | 102 | ||
99 | for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { | 103 | for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { |
100 | int iar_shift = (irqn & 7) * 4; | 104 | int iar_shift = (irqn & 7) * 4; |
101 | if (ivg == | 105 | if (ivg == (0xf & |
102 | (0xf & | ||
103 | #ifndef CONFIG_BF52x | 106 | #ifndef CONFIG_BF52x |
104 | bfin_read32((unsigned long *)SIC_IAR0 + | 107 | bfin_read32((unsigned long *)SIC_IAR0 + |
105 | (irqn >> 3)) >> iar_shift)) { | 108 | (irqn >> 3)) >> iar_shift)) { |
@@ -179,6 +182,27 @@ static void bfin_internal_unmask_irq(unsigned int irq) | |||
179 | SSYNC(); | 182 | SSYNC(); |
180 | } | 183 | } |
181 | 184 | ||
185 | #ifdef CONFIG_PM | ||
186 | int bfin_internal_set_wake(unsigned int irq, unsigned int state) | ||
187 | { | ||
188 | unsigned bank, bit; | ||
189 | unsigned long flags; | ||
190 | bank = (irq - (IRQ_CORETMR + 1)) / 32; | ||
191 | bit = (irq - (IRQ_CORETMR + 1)) % 32; | ||
192 | |||
193 | local_irq_save(flags); | ||
194 | |||
195 | if (state) | ||
196 | bfin_sic_iwr[bank] |= (1 << bit); | ||
197 | else | ||
198 | bfin_sic_iwr[bank] &= ~(1 << bit); | ||
199 | |||
200 | local_irq_restore(flags); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | #endif | ||
205 | |||
182 | static struct irq_chip bfin_core_irqchip = { | 206 | static struct irq_chip bfin_core_irqchip = { |
183 | .ack = ack_noop, | 207 | .ack = ack_noop, |
184 | .mask = bfin_core_mask_irq, | 208 | .mask = bfin_core_mask_irq, |
@@ -189,6 +213,9 @@ static struct irq_chip bfin_internal_irqchip = { | |||
189 | .ack = ack_noop, | 213 | .ack = ack_noop, |
190 | .mask = bfin_internal_mask_irq, | 214 | .mask = bfin_internal_mask_irq, |
191 | .unmask = bfin_internal_unmask_irq, | 215 | .unmask = bfin_internal_unmask_irq, |
216 | #ifdef CONFIG_PM | ||
217 | .set_wake = bfin_internal_set_wake, | ||
218 | #endif | ||
192 | }; | 219 | }; |
193 | 220 | ||
194 | #ifdef BF537_GENERIC_ERROR_INT_DEMUX | 221 | #ifdef BF537_GENERIC_ERROR_INT_DEMUX |
@@ -206,8 +233,7 @@ static void bfin_generic_error_mask_irq(unsigned int irq) | |||
206 | if (!error_int_mask) { | 233 | if (!error_int_mask) { |
207 | local_irq_disable(); | 234 | local_irq_disable(); |
208 | bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & | 235 | bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & |
209 | ~(1 << | 236 | ~(1 << (IRQ_GENERIC_ERROR - |
210 | (IRQ_GENERIC_ERROR - | ||
211 | (IRQ_CORETMR + 1)))); | 237 | (IRQ_CORETMR + 1)))); |
212 | SSYNC(); | 238 | SSYNC(); |
213 | local_irq_enable(); | 239 | local_irq_enable(); |
@@ -232,7 +258,7 @@ static struct irq_chip bfin_generic_error_irqchip = { | |||
232 | }; | 258 | }; |
233 | 259 | ||
234 | static void bfin_demux_error_irq(unsigned int int_err_irq, | 260 | static void bfin_demux_error_irq(unsigned int int_err_irq, |
235 | struct irq_desc *intb_desc) | 261 | struct irq_desc *inta_desc) |
236 | { | 262 | { |
237 | int irq = 0; | 263 | int irq = 0; |
238 | 264 | ||
@@ -404,16 +430,8 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
404 | return 0; | 430 | return 0; |
405 | } | 431 | } |
406 | 432 | ||
433 | set_gpio_inen(gpionr, 0); | ||
407 | set_gpio_dir(gpionr, 0); | 434 | set_gpio_dir(gpionr, 0); |
408 | set_gpio_inen(gpionr, 1); | ||
409 | |||
410 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | ||
411 | gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr); | ||
412 | set_gpio_edge(gpionr, 1); | ||
413 | } else { | ||
414 | set_gpio_edge(gpionr, 0); | ||
415 | gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); | ||
416 | } | ||
417 | 435 | ||
418 | if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) | 436 | if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) |
419 | == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) | 437 | == (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) |
@@ -426,6 +444,18 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
426 | else | 444 | else |
427 | set_gpio_polar(gpionr, 0); /* high or rising edge denoted by zero */ | 445 | set_gpio_polar(gpionr, 0); /* high or rising edge denoted by zero */ |
428 | 446 | ||
447 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) { | ||
448 | set_gpio_edge(gpionr, 1); | ||
449 | set_gpio_inen(gpionr, 1); | ||
450 | gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr); | ||
451 | set_gpio_data(gpionr, 0); | ||
452 | |||
453 | } else { | ||
454 | set_gpio_edge(gpionr, 0); | ||
455 | gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr); | ||
456 | set_gpio_inen(gpionr, 1); | ||
457 | } | ||
458 | |||
429 | SSYNC(); | 459 | SSYNC(); |
430 | 460 | ||
431 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) | 461 | if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) |
@@ -436,6 +466,20 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
436 | return 0; | 466 | return 0; |
437 | } | 467 | } |
438 | 468 | ||
469 | #ifdef CONFIG_PM | ||
470 | int bfin_gpio_set_wake(unsigned int irq, unsigned int state) | ||
471 | { | ||
472 | unsigned gpio = irq_to_gpio(irq); | ||
473 | |||
474 | if (state) | ||
475 | gpio_pm_wakeup_request(gpio, PM_WAKE_IGNORE); | ||
476 | else | ||
477 | gpio_pm_wakeup_free(gpio); | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | #endif | ||
482 | |||
439 | static struct irq_chip bfin_gpio_irqchip = { | 483 | static struct irq_chip bfin_gpio_irqchip = { |
440 | .ack = bfin_gpio_ack_irq, | 484 | .ack = bfin_gpio_ack_irq, |
441 | .mask = bfin_gpio_mask_irq, | 485 | .mask = bfin_gpio_mask_irq, |
@@ -443,30 +487,87 @@ static struct irq_chip bfin_gpio_irqchip = { | |||
443 | .unmask = bfin_gpio_unmask_irq, | 487 | .unmask = bfin_gpio_unmask_irq, |
444 | .set_type = bfin_gpio_irq_type, | 488 | .set_type = bfin_gpio_irq_type, |
445 | .startup = bfin_gpio_irq_startup, | 489 | .startup = bfin_gpio_irq_startup, |
446 | .shutdown = bfin_gpio_irq_shutdown | 490 | .shutdown = bfin_gpio_irq_shutdown, |
491 | #ifdef CONFIG_PM | ||
492 | .set_wake = bfin_gpio_set_wake, | ||
493 | #endif | ||
447 | }; | 494 | }; |
448 | 495 | ||
449 | static void bfin_demux_gpio_irq(unsigned int intb_irq, | 496 | static void bfin_demux_gpio_irq(unsigned int inta_irq, |
450 | struct irq_desc *intb_desc) | 497 | struct irq_desc *desc) |
451 | { | 498 | { |
452 | u16 i; | 499 | unsigned int i, gpio, mask, irq, search = 0; |
453 | struct irq_desc *desc; | ||
454 | 500 | ||
455 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) { | 501 | switch (inta_irq) { |
456 | int irq = IRQ_PF0 + i; | 502 | #if defined(CONFIG_BF53x) |
457 | int flag_d = get_gpiop_data(i); | 503 | case IRQ_PROG_INTA: |
458 | int mask = | 504 | irq = IRQ_PF0; |
459 | flag_d & (gpio_enabled[gpio_bank(i)] & get_gpiop_maska(i)); | 505 | search = 1; |
506 | break; | ||
507 | # if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) | ||
508 | case IRQ_MAC_RX: | ||
509 | irq = IRQ_PH0; | ||
510 | break; | ||
511 | # endif | ||
512 | #elif defined(CONFIG_BF52x) | ||
513 | case IRQ_PORTF_INTA: | ||
514 | irq = IRQ_PF0; | ||
515 | break; | ||
516 | case IRQ_PORTG_INTA: | ||
517 | irq = IRQ_PG0; | ||
518 | break; | ||
519 | case IRQ_PORTH_INTA: | ||
520 | irq = IRQ_PH0; | ||
521 | break; | ||
522 | #elif defined(CONFIG_BF561) | ||
523 | case IRQ_PROG0_INTA: | ||
524 | irq = IRQ_PF0; | ||
525 | break; | ||
526 | case IRQ_PROG1_INTA: | ||
527 | irq = IRQ_PF16; | ||
528 | break; | ||
529 | case IRQ_PROG2_INTA: | ||
530 | irq = IRQ_PF32; | ||
531 | break; | ||
532 | #endif | ||
533 | default: | ||
534 | BUG(); | ||
535 | return; | ||
536 | } | ||
460 | 537 | ||
461 | while (mask) { | 538 | if (search) { |
462 | if (mask & 1) { | 539 | for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { |
463 | desc = irq_desc + irq; | 540 | irq += i; |
464 | desc->handle_irq(irq, desc); | 541 | |
542 | mask = get_gpiop_data(i) & | ||
543 | (gpio_enabled[gpio_bank(i)] & | ||
544 | get_gpiop_maska(i)); | ||
545 | |||
546 | while (mask) { | ||
547 | if (mask & 1) { | ||
548 | desc = irq_desc + irq; | ||
549 | desc->handle_irq(irq, desc); | ||
550 | } | ||
551 | irq++; | ||
552 | mask >>= 1; | ||
465 | } | 553 | } |
466 | irq++; | ||
467 | mask >>= 1; | ||
468 | } | 554 | } |
555 | } else { | ||
556 | gpio = irq_to_gpio(irq); | ||
557 | mask = get_gpiop_data(gpio) & | ||
558 | (gpio_enabled[gpio_bank(gpio)] & | ||
559 | get_gpiop_maska(gpio)); | ||
560 | |||
561 | do { | ||
562 | if (mask & 1) { | ||
563 | desc = irq_desc + irq; | ||
564 | desc->handle_irq(irq, desc); | ||
565 | } | ||
566 | irq++; | ||
567 | mask >>= 1; | ||
568 | } while (mask); | ||
469 | } | 569 | } |
570 | |||
470 | } | 571 | } |
471 | 572 | ||
472 | #else /* CONFIG_BF54x */ | 573 | #else /* CONFIG_BF54x */ |
@@ -711,6 +812,74 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type) | |||
711 | return 0; | 812 | return 0; |
712 | } | 813 | } |
713 | 814 | ||
815 | #ifdef CONFIG_PM | ||
816 | u32 pint_saved_masks[NR_PINT_SYS_IRQS]; | ||
817 | u32 pint_wakeup_masks[NR_PINT_SYS_IRQS]; | ||
818 | |||
819 | int bfin_gpio_set_wake(unsigned int irq, unsigned int state) | ||
820 | { | ||
821 | u32 pint_irq; | ||
822 | u8 pint_val = irq2pint_lut[irq - SYS_IRQS]; | ||
823 | u32 bank = PINT_2_BANK(pint_val); | ||
824 | u32 pintbit = PINT_BIT(pint_val); | ||
825 | |||
826 | switch (bank) { | ||
827 | case 0: | ||
828 | pint_irq = IRQ_PINT0; | ||
829 | break; | ||
830 | case 2: | ||
831 | pint_irq = IRQ_PINT2; | ||
832 | break; | ||
833 | case 3: | ||
834 | pint_irq = IRQ_PINT3; | ||
835 | break; | ||
836 | case 1: | ||
837 | pint_irq = IRQ_PINT1; | ||
838 | break; | ||
839 | default: | ||
840 | return -EINVAL; | ||
841 | } | ||
842 | |||
843 | bfin_internal_set_wake(pint_irq, state); | ||
844 | |||
845 | if (state) | ||
846 | pint_wakeup_masks[bank] |= pintbit; | ||
847 | else | ||
848 | pint_wakeup_masks[bank] &= ~pintbit; | ||
849 | |||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | u32 bfin_pm_setup(void) | ||
854 | { | ||
855 | u32 val, i; | ||
856 | |||
857 | for (i = 0; i < NR_PINT_SYS_IRQS; i++) { | ||
858 | val = pint[i]->mask_clear; | ||
859 | pint_saved_masks[i] = val; | ||
860 | if (val ^ pint_wakeup_masks[i]) { | ||
861 | pint[i]->mask_clear = val; | ||
862 | pint[i]->mask_set = pint_wakeup_masks[i]; | ||
863 | } | ||
864 | } | ||
865 | |||
866 | return 0; | ||
867 | } | ||
868 | |||
869 | void bfin_pm_restore(void) | ||
870 | { | ||
871 | u32 i, val; | ||
872 | |||
873 | for (i = 0; i < NR_PINT_SYS_IRQS; i++) { | ||
874 | val = pint_saved_masks[i]; | ||
875 | if (val ^ pint_wakeup_masks[i]) { | ||
876 | pint[i]->mask_clear = pint[i]->mask_clear; | ||
877 | pint[i]->mask_set = val; | ||
878 | } | ||
879 | } | ||
880 | } | ||
881 | #endif | ||
882 | |||
714 | static struct irq_chip bfin_gpio_irqchip = { | 883 | static struct irq_chip bfin_gpio_irqchip = { |
715 | .ack = bfin_gpio_ack_irq, | 884 | .ack = bfin_gpio_ack_irq, |
716 | .mask = bfin_gpio_mask_irq, | 885 | .mask = bfin_gpio_mask_irq, |
@@ -718,17 +887,19 @@ static struct irq_chip bfin_gpio_irqchip = { | |||
718 | .unmask = bfin_gpio_unmask_irq, | 887 | .unmask = bfin_gpio_unmask_irq, |
719 | .set_type = bfin_gpio_irq_type, | 888 | .set_type = bfin_gpio_irq_type, |
720 | .startup = bfin_gpio_irq_startup, | 889 | .startup = bfin_gpio_irq_startup, |
721 | .shutdown = bfin_gpio_irq_shutdown | 890 | .shutdown = bfin_gpio_irq_shutdown, |
891 | #ifdef CONFIG_PM | ||
892 | .set_wake = bfin_gpio_set_wake, | ||
893 | #endif | ||
722 | }; | 894 | }; |
723 | 895 | ||
724 | static void bfin_demux_gpio_irq(unsigned int intb_irq, | 896 | static void bfin_demux_gpio_irq(unsigned int inta_irq, |
725 | struct irq_desc *intb_desc) | 897 | struct irq_desc *desc) |
726 | { | 898 | { |
727 | u8 bank, pint_val; | 899 | u8 bank, pint_val; |
728 | u32 request, irq; | 900 | u32 request, irq; |
729 | struct irq_desc *desc; | ||
730 | 901 | ||
731 | switch (intb_irq) { | 902 | switch (inta_irq) { |
732 | case IRQ_PINT0: | 903 | case IRQ_PINT0: |
733 | bank = 0; | 904 | bank = 0; |
734 | break; | 905 | break; |
@@ -795,7 +966,7 @@ int __init init_arch_irq(void) | |||
795 | int irq; | 966 | int irq; |
796 | unsigned long ilat = 0; | 967 | unsigned long ilat = 0; |
797 | /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ | 968 | /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ |
798 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) | 969 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) |
799 | bfin_write_SIC_IMASK0(SIC_UNMASK_ALL); | 970 | bfin_write_SIC_IMASK0(SIC_UNMASK_ALL); |
800 | bfin_write_SIC_IMASK1(SIC_UNMASK_ALL); | 971 | bfin_write_SIC_IMASK1(SIC_UNMASK_ALL); |
801 | bfin_write_SIC_IWR0(IWR_ENABLE_ALL); | 972 | bfin_write_SIC_IWR0(IWR_ENABLE_ALL); |
@@ -812,6 +983,8 @@ int __init init_arch_irq(void) | |||
812 | 983 | ||
813 | local_irq_disable(); | 984 | local_irq_disable(); |
814 | 985 | ||
986 | init_exception_buff(); | ||
987 | |||
815 | #ifdef CONFIG_BF54x | 988 | #ifdef CONFIG_BF54x |
816 | # ifdef CONFIG_PINTx_REASSIGN | 989 | # ifdef CONFIG_PINTx_REASSIGN |
817 | pint[0]->assign = CONFIG_PINT0_ASSIGN; | 990 | pint[0]->assign = CONFIG_PINT0_ASSIGN; |
@@ -874,6 +1047,19 @@ int __init init_arch_irq(void) | |||
874 | set_irq_chained_handler(irq, | 1047 | set_irq_chained_handler(irq, |
875 | bfin_demux_gpio_irq); | 1048 | bfin_demux_gpio_irq); |
876 | break; | 1049 | break; |
1050 | #elif defined(CONFIG_BF561) | ||
1051 | case IRQ_PROG0_INTA: | ||
1052 | set_irq_chained_handler(irq, | ||
1053 | bfin_demux_gpio_irq); | ||
1054 | break; | ||
1055 | case IRQ_PROG1_INTA: | ||
1056 | set_irq_chained_handler(irq, | ||
1057 | bfin_demux_gpio_irq); | ||
1058 | break; | ||
1059 | case IRQ_PROG2_INTA: | ||
1060 | set_irq_chained_handler(irq, | ||
1061 | bfin_demux_gpio_irq); | ||
1062 | break; | ||
877 | #endif | 1063 | #endif |
878 | default: | 1064 | default: |
879 | set_irq_handler(irq, handle_simple_irq); | 1065 | set_irq_handler(irq, handle_simple_irq); |
@@ -893,11 +1079,8 @@ int __init init_arch_irq(void) | |||
893 | } | 1079 | } |
894 | #endif | 1080 | #endif |
895 | 1081 | ||
896 | #ifndef CONFIG_BF54x | 1082 | for (irq = GPIO_IRQ_BASE; irq < NR_IRQS; irq++) { |
897 | for (irq = IRQ_PF0; irq < NR_IRQS; irq++) { | 1083 | |
898 | #else | ||
899 | for (irq = IRQ_PA0; irq < NR_IRQS; irq++) { | ||
900 | #endif | ||
901 | set_irq_chip(irq, &bfin_gpio_irqchip); | 1084 | set_irq_chip(irq, &bfin_gpio_irqchip); |
902 | /* if configured as edge, then will be changed to do_edge_IRQ */ | 1085 | /* if configured as edge, then will be changed to do_edge_IRQ */ |
903 | set_irq_handler(irq, handle_level_irq); | 1086 | set_irq_handler(irq, handle_level_irq); |
@@ -936,7 +1119,7 @@ void do_irq(int vec, struct pt_regs *fp) | |||
936 | } else { | 1119 | } else { |
937 | struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; | 1120 | struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; |
938 | struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; | 1121 | struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; |
939 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) | 1122 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) |
940 | unsigned long sic_status[3]; | 1123 | unsigned long sic_status[3]; |
941 | 1124 | ||
942 | SSYNC(); | 1125 | SSYNC(); |
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index 81930f7d06f1..0be805ca423f 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Author: Cliff Brake <cbrake@accelent.com> Copyright (c) 2001 | 4 | * Author: Cliff Brake <cbrake@accelent.com> Copyright (c) 2001 |
5 | * | 5 | * |
6 | * Created: 2001 | 6 | * Created: 2001 |
7 | * Description: Power management for the bfin | 7 | * Description: Blackfin power management |
8 | * | 8 | * |
9 | * Modified: Nicolas Pitre - PXA250 support | 9 | * Modified: Nicolas Pitre - PXA250 support |
10 | * Copyright (c) 2002 Monta Vista Software, Inc. | 10 | * Copyright (c) 2002 Monta Vista Software, Inc. |
@@ -12,7 +12,7 @@ | |||
12 | * Copyright (c) 2002 Monta Vista Software, Inc. | 12 | * Copyright (c) 2002 Monta Vista Software, Inc. |
13 | * Dirk Behme <dirk.behme@de.bosch.com> - OMAP1510/1610 | 13 | * Dirk Behme <dirk.behme@de.bosch.com> - OMAP1510/1610 |
14 | * Copyright 2004 | 14 | * Copyright 2004 |
15 | * Copyright 2004-2006 Analog Devices Inc. | 15 | * Copyright 2004-2008 Analog Devices Inc. |
16 | * | 16 | * |
17 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 17 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
18 | * | 18 | * |
@@ -67,42 +67,30 @@ void bfin_pm_suspend_standby_enter(void) | |||
67 | gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE); | 67 | gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE); |
68 | #endif | 68 | #endif |
69 | 69 | ||
70 | #if defined(CONFIG_PM_WAKEUP_BY_GPIO) || defined(CONFIG_PM_WAKEUP_GPIO_API) | 70 | u32 flags; |
71 | { | ||
72 | u32 flags; | ||
73 | 71 | ||
74 | local_irq_save(flags); | 72 | local_irq_save(flags); |
73 | bfin_pm_setup(); | ||
75 | 74 | ||
76 | sleep_deeper(gpio_pm_setup()); /*Goto Sleep*/ | 75 | #ifdef CONFIG_PM_BFIN_SLEEP_DEEPER |
77 | 76 | sleep_deeper(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); | |
78 | gpio_pm_restore(); | ||
79 | |||
80 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) | ||
81 | bfin_write_SIC_IWR0(IWR_ENABLE_ALL); | ||
82 | bfin_write_SIC_IWR1(IWR_ENABLE_ALL); | ||
83 | # ifdef CONFIG_BF54x | ||
84 | bfin_write_SIC_IWR2(IWR_ENABLE_ALL); | ||
85 | # endif | ||
86 | #else | 77 | #else |
87 | bfin_write_SIC_IWR(IWR_ENABLE_ALL); | 78 | sleep_mode(bfin_sic_iwr[0], bfin_sic_iwr[1], bfin_sic_iwr[2]); |
88 | #endif | 79 | #endif |
89 | 80 | ||
90 | local_irq_restore(flags); | 81 | bfin_pm_restore(); |
91 | } | ||
92 | #endif | ||
93 | 82 | ||
94 | #if defined(CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR) | 83 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) |
95 | sleep_deeper(CONFIG_PM_WAKEUP_SIC_IWR); | ||
96 | # if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) | ||
97 | bfin_write_SIC_IWR0(IWR_ENABLE_ALL); | 84 | bfin_write_SIC_IWR0(IWR_ENABLE_ALL); |
98 | bfin_write_SIC_IWR1(IWR_ENABLE_ALL); | 85 | bfin_write_SIC_IWR1(IWR_ENABLE_ALL); |
99 | # ifdef CONFIG_BF54x | 86 | # ifdef CONFIG_BF54x |
100 | bfin_write_SIC_IWR2(IWR_ENABLE_ALL); | 87 | bfin_write_SIC_IWR2(IWR_ENABLE_ALL); |
101 | # endif | ||
102 | # else | ||
103 | bfin_write_SIC_IWR(IWR_ENABLE_ALL); | ||
104 | # endif | 88 | # endif |
105 | #endif /* CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR */ | 89 | #else |
90 | bfin_write_SIC_IWR(IWR_ENABLE_ALL); | ||
91 | #endif | ||
92 | |||
93 | local_irq_restore(flags); | ||
106 | } | 94 | } |
107 | 95 | ||
108 | /* | 96 | /* |