Commit 81d79bec348ab06cba9ae9fc03eb015b6b83703a
Committed by
Linus Torvalds
1 parent
6e6d74cfac
[PATCH] V850: user ARRAY_SIZE macro when appropriate
Use ARRAY_SIZE macro already defined in linux/kernel.h Signed-off-by: Ahmed S. Darwish <darwish.07@gmail.com> Cc: Miles Bader <uclinux-v850@lsi.nec.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 10 changed files with 13 additions and 15 deletions Inline Diff
arch/v850/kernel/anna.c
1 | /* | 1 | /* |
2 | * arch/v850/kernel/anna.c -- Anna V850E2 evaluation chip/board | 2 | * arch/v850/kernel/anna.c -- Anna V850E2 evaluation chip/board |
3 | * | 3 | * |
4 | * Copyright (C) 2002,03 NEC Electronics Corporation | 4 | * Copyright (C) 2002,03 NEC Electronics Corporation |
5 | * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/bootmem.h> | 17 | #include <linux/bootmem.h> |
18 | #include <linux/major.h> | 18 | #include <linux/major.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | 20 | ||
21 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
22 | #include <asm/atomic.h> | 22 | #include <asm/atomic.h> |
23 | #include <asm/page.h> | 23 | #include <asm/page.h> |
24 | #include <asm/v850e_timer_d.h> | 24 | #include <asm/v850e_timer_d.h> |
25 | #include <asm/v850e_uart.h> | 25 | #include <asm/v850e_uart.h> |
26 | 26 | ||
27 | #include "mach.h" | 27 | #include "mach.h" |
28 | 28 | ||
29 | 29 | ||
30 | /* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see | 30 | /* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see |
31 | mach_reserve_bootmem for details); use both as one big area. */ | 31 | mach_reserve_bootmem for details); use both as one big area. */ |
32 | #define RAM_START SRAM_ADDR | 32 | #define RAM_START SRAM_ADDR |
33 | #define RAM_END (SDRAM_ADDR + SDRAM_SIZE) | 33 | #define RAM_END (SDRAM_ADDR + SDRAM_SIZE) |
34 | 34 | ||
35 | /* The bits of this port are connected to an 8-LED bar-graph. */ | 35 | /* The bits of this port are connected to an 8-LED bar-graph. */ |
36 | #define LEDS_PORT 0 | 36 | #define LEDS_PORT 0 |
37 | 37 | ||
38 | 38 | ||
39 | static void anna_led_tick (void); | 39 | static void anna_led_tick (void); |
40 | 40 | ||
41 | 41 | ||
42 | void __init mach_early_init (void) | 42 | void __init mach_early_init (void) |
43 | { | 43 | { |
44 | ANNA_ILBEN = 0; | 44 | ANNA_ILBEN = 0; |
45 | 45 | ||
46 | V850E2_CSC(0) = 0x402F; | 46 | V850E2_CSC(0) = 0x402F; |
47 | V850E2_CSC(1) = 0x4000; | 47 | V850E2_CSC(1) = 0x4000; |
48 | V850E2_BPC = 0; | 48 | V850E2_BPC = 0; |
49 | V850E2_BSC = 0xAAAA; | 49 | V850E2_BSC = 0xAAAA; |
50 | V850E2_BEC = 0; | 50 | V850E2_BEC = 0; |
51 | 51 | ||
52 | #if 0 | 52 | #if 0 |
53 | V850E2_BHC = 0xFFFF; /* icache all memory, dcache all */ | 53 | V850E2_BHC = 0xFFFF; /* icache all memory, dcache all */ |
54 | #else | 54 | #else |
55 | V850E2_BHC = 0; /* cache no memory */ | 55 | V850E2_BHC = 0; /* cache no memory */ |
56 | #endif | 56 | #endif |
57 | V850E2_BCT(0) = 0xB088; | 57 | V850E2_BCT(0) = 0xB088; |
58 | V850E2_BCT(1) = 0x0008; | 58 | V850E2_BCT(1) = 0x0008; |
59 | V850E2_DWC(0) = 0x0027; | 59 | V850E2_DWC(0) = 0x0027; |
60 | V850E2_DWC(1) = 0; | 60 | V850E2_DWC(1) = 0; |
61 | V850E2_BCC = 0x0006; | 61 | V850E2_BCC = 0x0006; |
62 | V850E2_ASC = 0; | 62 | V850E2_ASC = 0; |
63 | V850E2_LBS = 0x0089; | 63 | V850E2_LBS = 0x0089; |
64 | V850E2_SCR(3) = 0x21A9; | 64 | V850E2_SCR(3) = 0x21A9; |
65 | V850E2_RFS(3) = 0x8121; | 65 | V850E2_RFS(3) = 0x8121; |
66 | 66 | ||
67 | v850e_intc_disable_irqs (); | 67 | v850e_intc_disable_irqs (); |
68 | } | 68 | } |
69 | 69 | ||
70 | void __init mach_setup (char **cmdline) | 70 | void __init mach_setup (char **cmdline) |
71 | { | 71 | { |
72 | ANNA_PORT_PM (LEDS_PORT) = 0; /* Make all LED pins output pins. */ | 72 | ANNA_PORT_PM (LEDS_PORT) = 0; /* Make all LED pins output pins. */ |
73 | mach_tick = anna_led_tick; | 73 | mach_tick = anna_led_tick; |
74 | } | 74 | } |
75 | 75 | ||
76 | void __init mach_get_physical_ram (unsigned long *ram_start, | 76 | void __init mach_get_physical_ram (unsigned long *ram_start, |
77 | unsigned long *ram_len) | 77 | unsigned long *ram_len) |
78 | { | 78 | { |
79 | *ram_start = RAM_START; | 79 | *ram_start = RAM_START; |
80 | *ram_len = RAM_END - RAM_START; | 80 | *ram_len = RAM_END - RAM_START; |
81 | } | 81 | } |
82 | 82 | ||
83 | void __init mach_reserve_bootmem () | 83 | void __init mach_reserve_bootmem () |
84 | { | 84 | { |
85 | /* The space between SRAM and SDRAM is filled with duplicate | 85 | /* The space between SRAM and SDRAM is filled with duplicate |
86 | images of SRAM. Prevent the kernel from using them. */ | 86 | images of SRAM. Prevent the kernel from using them. */ |
87 | reserve_bootmem (SRAM_ADDR + SRAM_SIZE, | 87 | reserve_bootmem (SRAM_ADDR + SRAM_SIZE, |
88 | SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE)); | 88 | SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE)); |
89 | } | 89 | } |
90 | 90 | ||
91 | void mach_gettimeofday (struct timespec *tv) | 91 | void mach_gettimeofday (struct timespec *tv) |
92 | { | 92 | { |
93 | tv->tv_sec = 0; | 93 | tv->tv_sec = 0; |
94 | tv->tv_nsec = 0; | 94 | tv->tv_nsec = 0; |
95 | } | 95 | } |
96 | 96 | ||
97 | void __init mach_sched_init (struct irqaction *timer_action) | 97 | void __init mach_sched_init (struct irqaction *timer_action) |
98 | { | 98 | { |
99 | /* Start hardware timer. */ | 99 | /* Start hardware timer. */ |
100 | v850e_timer_d_configure (0, HZ); | 100 | v850e_timer_d_configure (0, HZ); |
101 | /* Install timer interrupt handler. */ | 101 | /* Install timer interrupt handler. */ |
102 | setup_irq (IRQ_INTCMD(0), timer_action); | 102 | setup_irq (IRQ_INTCMD(0), timer_action); |
103 | } | 103 | } |
104 | 104 | ||
105 | static struct v850e_intc_irq_init irq_inits[] = { | 105 | static struct v850e_intc_irq_init irq_inits[] = { |
106 | { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, | 106 | { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, |
107 | { "PIN", IRQ_INTP(0), IRQ_INTP_NUM, 1, 4 }, | 107 | { "PIN", IRQ_INTP(0), IRQ_INTP_NUM, 1, 4 }, |
108 | { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 }, | 108 | { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 }, |
109 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, | 109 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, |
110 | { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 }, | 110 | { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 }, |
111 | { "DMXER", IRQ_INTDMXER,1, 1, 2 }, | 111 | { "DMXER", IRQ_INTDMXER,1, 1, 2 }, |
112 | { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 }, | 112 | { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 }, |
113 | { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 }, | 113 | { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 }, |
114 | { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 }, | 114 | { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 }, |
115 | { 0 } | 115 | { 0 } |
116 | }; | 116 | }; |
117 | #define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) | 117 | #define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1) |
118 | 118 | ||
119 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; | 119 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; |
120 | 120 | ||
121 | void __init mach_init_irqs (void) | 121 | void __init mach_init_irqs (void) |
122 | { | 122 | { |
123 | v850e_intc_init_irq_types (irq_inits, hw_itypes); | 123 | v850e_intc_init_irq_types (irq_inits, hw_itypes); |
124 | } | 124 | } |
125 | 125 | ||
126 | void machine_restart (char *__unused) | 126 | void machine_restart (char *__unused) |
127 | { | 127 | { |
128 | #ifdef CONFIG_RESET_GUARD | 128 | #ifdef CONFIG_RESET_GUARD |
129 | disable_reset_guard (); | 129 | disable_reset_guard (); |
130 | #endif | 130 | #endif |
131 | asm ("jmp r0"); /* Jump to the reset vector. */ | 131 | asm ("jmp r0"); /* Jump to the reset vector. */ |
132 | } | 132 | } |
133 | 133 | ||
134 | void machine_halt (void) | 134 | void machine_halt (void) |
135 | { | 135 | { |
136 | #ifdef CONFIG_RESET_GUARD | 136 | #ifdef CONFIG_RESET_GUARD |
137 | disable_reset_guard (); | 137 | disable_reset_guard (); |
138 | #endif | 138 | #endif |
139 | local_irq_disable (); /* Ignore all interrupts. */ | 139 | local_irq_disable (); /* Ignore all interrupts. */ |
140 | ANNA_PORT_IO(LEDS_PORT) = 0xAA; /* Note that we halted. */ | 140 | ANNA_PORT_IO(LEDS_PORT) = 0xAA; /* Note that we halted. */ |
141 | for (;;) | 141 | for (;;) |
142 | asm ("halt; nop; nop; nop; nop; nop"); | 142 | asm ("halt; nop; nop; nop; nop; nop"); |
143 | } | 143 | } |
144 | 144 | ||
145 | void machine_power_off (void) | 145 | void machine_power_off (void) |
146 | { | 146 | { |
147 | machine_halt (); | 147 | machine_halt (); |
148 | } | 148 | } |
149 | 149 | ||
150 | /* Called before configuring an on-chip UART. */ | 150 | /* Called before configuring an on-chip UART. */ |
151 | void anna_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) | 151 | void anna_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) |
152 | { | 152 | { |
153 | /* The Anna connects some general-purpose I/O pins on the CPU to | 153 | /* The Anna connects some general-purpose I/O pins on the CPU to |
154 | the RTS/CTS lines of UART 1's serial connection. I/O pins P07 | 154 | the RTS/CTS lines of UART 1's serial connection. I/O pins P07 |
155 | and P37 are RTS and CTS respectively. */ | 155 | and P37 are RTS and CTS respectively. */ |
156 | if (chan == 1) { | 156 | if (chan == 1) { |
157 | ANNA_PORT_PM(0) &= ~0x80; /* P07 in output mode */ | 157 | ANNA_PORT_PM(0) &= ~0x80; /* P07 in output mode */ |
158 | ANNA_PORT_PM(3) |= 0x80; /* P37 in input mode */ | 158 | ANNA_PORT_PM(3) |= 0x80; /* P37 in input mode */ |
159 | } | 159 | } |
160 | } | 160 | } |
161 | 161 | ||
162 | /* Minimum and maximum bounds for the moving upper LED boundary in the | 162 | /* Minimum and maximum bounds for the moving upper LED boundary in the |
163 | clock tick display. We can't use the last bit because it's used for | 163 | clock tick display. We can't use the last bit because it's used for |
164 | UART0's CTS output. */ | 164 | UART0's CTS output. */ |
165 | #define MIN_MAX_POS 0 | 165 | #define MIN_MAX_POS 0 |
166 | #define MAX_MAX_POS 6 | 166 | #define MAX_MAX_POS 6 |
167 | 167 | ||
168 | /* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if | 168 | /* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if |
169 | we pick 6 and 0 as above, we get 49 cycles, which is when divided into | 169 | we pick 6 and 0 as above, we get 49 cycles, which is when divided into |
170 | the standard 100 value for HZ, gives us an almost 1s total time. */ | 170 | the standard 100 value for HZ, gives us an almost 1s total time. */ |
171 | #define TICKS_PER_FRAME \ | 171 | #define TICKS_PER_FRAME \ |
172 | (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS)) | 172 | (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS)) |
173 | 173 | ||
174 | static void anna_led_tick () | 174 | static void anna_led_tick () |
175 | { | 175 | { |
176 | static unsigned counter = 0; | 176 | static unsigned counter = 0; |
177 | 177 | ||
178 | if (++counter == TICKS_PER_FRAME) { | 178 | if (++counter == TICKS_PER_FRAME) { |
179 | static int pos = 0, max_pos = MAX_MAX_POS, dir = 1; | 179 | static int pos = 0, max_pos = MAX_MAX_POS, dir = 1; |
180 | 180 | ||
181 | if (dir > 0 && pos == max_pos) { | 181 | if (dir > 0 && pos == max_pos) { |
182 | dir = -1; | 182 | dir = -1; |
183 | if (max_pos == MIN_MAX_POS) | 183 | if (max_pos == MIN_MAX_POS) |
184 | max_pos = MAX_MAX_POS; | 184 | max_pos = MAX_MAX_POS; |
185 | else | 185 | else |
186 | max_pos--; | 186 | max_pos--; |
187 | } else { | 187 | } else { |
188 | if (dir < 0 && pos == 0) | 188 | if (dir < 0 && pos == 0) |
189 | dir = 1; | 189 | dir = 1; |
190 | 190 | ||
191 | if (pos + dir <= max_pos) { | 191 | if (pos + dir <= max_pos) { |
192 | /* Each bit of port 0 has a LED. */ | 192 | /* Each bit of port 0 has a LED. */ |
193 | clear_bit (pos, &ANNA_PORT_IO(LEDS_PORT)); | 193 | clear_bit (pos, &ANNA_PORT_IO(LEDS_PORT)); |
194 | pos += dir; | 194 | pos += dir; |
195 | set_bit (pos, &ANNA_PORT_IO(LEDS_PORT)); | 195 | set_bit (pos, &ANNA_PORT_IO(LEDS_PORT)); |
196 | } | 196 | } |
197 | } | 197 | } |
198 | 198 | ||
199 | counter = 0; | 199 | counter = 0; |
200 | } | 200 | } |
201 | } | 201 | } |
202 | 202 |
arch/v850/kernel/as85ep1.c
1 | /* | 1 | /* |
2 | * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board | 2 | * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board |
3 | * | 3 | * |
4 | * Copyright (C) 2002,03 NEC Electronics Corporation | 4 | * Copyright (C) 2002,03 NEC Electronics Corporation |
5 | * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/bootmem.h> | 17 | #include <linux/bootmem.h> |
18 | #include <linux/major.h> | 18 | #include <linux/major.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | 20 | ||
21 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
22 | #include <asm/atomic.h> | 22 | #include <asm/atomic.h> |
23 | #include <asm/page.h> | 23 | #include <asm/page.h> |
24 | #include <asm/v850e_timer_d.h> | 24 | #include <asm/v850e_timer_d.h> |
25 | #include <asm/v850e_uart.h> | 25 | #include <asm/v850e_uart.h> |
26 | 26 | ||
27 | #include "mach.h" | 27 | #include "mach.h" |
28 | 28 | ||
29 | 29 | ||
30 | /* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see | 30 | /* SRAM and SDRAM are vaguely contiguous (with a big hole in between; see |
31 | mach_reserve_bootmem for details); use both as one big area. */ | 31 | mach_reserve_bootmem for details); use both as one big area. */ |
32 | #define RAM_START SRAM_ADDR | 32 | #define RAM_START SRAM_ADDR |
33 | #define RAM_END (SDRAM_ADDR + SDRAM_SIZE) | 33 | #define RAM_END (SDRAM_ADDR + SDRAM_SIZE) |
34 | 34 | ||
35 | /* The bits of this port are connected to an 8-LED bar-graph. */ | 35 | /* The bits of this port are connected to an 8-LED bar-graph. */ |
36 | #define LEDS_PORT 4 | 36 | #define LEDS_PORT 4 |
37 | 37 | ||
38 | 38 | ||
39 | static void as85ep1_led_tick (void); | 39 | static void as85ep1_led_tick (void); |
40 | 40 | ||
41 | extern char _intv_copy_src_start, _intv_copy_src_end; | 41 | extern char _intv_copy_src_start, _intv_copy_src_end; |
42 | extern char _intv_copy_dst_start; | 42 | extern char _intv_copy_dst_start; |
43 | 43 | ||
44 | 44 | ||
45 | void __init mach_early_init (void) | 45 | void __init mach_early_init (void) |
46 | { | 46 | { |
47 | #ifndef CONFIG_ROM_KERNEL | 47 | #ifndef CONFIG_ROM_KERNEL |
48 | const u32 *src; | 48 | const u32 *src; |
49 | register u32 *dst asm ("ep"); | 49 | register u32 *dst asm ("ep"); |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | AS85EP1_CSC(0) = 0x0403; | 52 | AS85EP1_CSC(0) = 0x0403; |
53 | AS85EP1_BCT(0) = 0xB8B8; | 53 | AS85EP1_BCT(0) = 0xB8B8; |
54 | AS85EP1_DWC(0) = 0x0104; | 54 | AS85EP1_DWC(0) = 0x0104; |
55 | AS85EP1_BCC = 0x0012; | 55 | AS85EP1_BCC = 0x0012; |
56 | AS85EP1_ASC = 0; | 56 | AS85EP1_ASC = 0; |
57 | AS85EP1_LBS = 0x00A9; | 57 | AS85EP1_LBS = 0x00A9; |
58 | 58 | ||
59 | AS85EP1_PORT_PMC(6) = 0xFF; /* valid A0,A1,A20-A25 */ | 59 | AS85EP1_PORT_PMC(6) = 0xFF; /* valid A0,A1,A20-A25 */ |
60 | AS85EP1_PORT_PMC(7) = 0x0E; /* valid CS1-CS3 */ | 60 | AS85EP1_PORT_PMC(7) = 0x0E; /* valid CS1-CS3 */ |
61 | AS85EP1_PORT_PMC(9) = 0xFF; /* valid D16-D23 */ | 61 | AS85EP1_PORT_PMC(9) = 0xFF; /* valid D16-D23 */ |
62 | AS85EP1_PORT_PMC(10) = 0xFF; /* valid D24-D31 */ | 62 | AS85EP1_PORT_PMC(10) = 0xFF; /* valid D24-D31 */ |
63 | 63 | ||
64 | AS85EP1_RFS(1) = 0x800c; | 64 | AS85EP1_RFS(1) = 0x800c; |
65 | AS85EP1_RFS(3) = 0x800c; | 65 | AS85EP1_RFS(3) = 0x800c; |
66 | AS85EP1_SCR(1) = 0x20A9; | 66 | AS85EP1_SCR(1) = 0x20A9; |
67 | AS85EP1_SCR(3) = 0x20A9; | 67 | AS85EP1_SCR(3) = 0x20A9; |
68 | 68 | ||
69 | #ifndef CONFIG_ROM_KERNEL | 69 | #ifndef CONFIG_ROM_KERNEL |
70 | /* The early chip we have is buggy, and writing the interrupt | 70 | /* The early chip we have is buggy, and writing the interrupt |
71 | vectors into low RAM may screw up, so for non-ROM kernels, we | 71 | vectors into low RAM may screw up, so for non-ROM kernels, we |
72 | only rely on the reset vector being downloaded, and copy the | 72 | only rely on the reset vector being downloaded, and copy the |
73 | rest of the interrupt vectors into place here. The specific bug | 73 | rest of the interrupt vectors into place here. The specific bug |
74 | is that writing address N, where (N & 0x10) == 0x10, will _also_ | 74 | is that writing address N, where (N & 0x10) == 0x10, will _also_ |
75 | write to address (N - 0x10). We avoid this (effectively) by | 75 | write to address (N - 0x10). We avoid this (effectively) by |
76 | writing in 16-byte chunks backwards from the end. */ | 76 | writing in 16-byte chunks backwards from the end. */ |
77 | 77 | ||
78 | AS85EP1_IRAMM = 0x3; /* "write-mode" for the internal instruction memory */ | 78 | AS85EP1_IRAMM = 0x3; /* "write-mode" for the internal instruction memory */ |
79 | 79 | ||
80 | src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF); | 80 | src = (u32 *)(((u32)&_intv_copy_src_end - 1) & ~0xF); |
81 | dst = (u32 *)&_intv_copy_dst_start | 81 | dst = (u32 *)&_intv_copy_dst_start |
82 | + (src - (u32 *)&_intv_copy_src_start); | 82 | + (src - (u32 *)&_intv_copy_src_start); |
83 | do { | 83 | do { |
84 | u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3]; | 84 | u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3]; |
85 | dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3; | 85 | dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3; |
86 | dst -= 4; | 86 | dst -= 4; |
87 | src -= 4; | 87 | src -= 4; |
88 | } while (src > (u32 *)&_intv_copy_src_start); | 88 | } while (src > (u32 *)&_intv_copy_src_start); |
89 | 89 | ||
90 | AS85EP1_IRAMM = 0x0; /* "read-mode" for the internal instruction memory */ | 90 | AS85EP1_IRAMM = 0x0; /* "read-mode" for the internal instruction memory */ |
91 | #endif /* !CONFIG_ROM_KERNEL */ | 91 | #endif /* !CONFIG_ROM_KERNEL */ |
92 | 92 | ||
93 | v850e_intc_disable_irqs (); | 93 | v850e_intc_disable_irqs (); |
94 | } | 94 | } |
95 | 95 | ||
96 | void __init mach_setup (char **cmdline) | 96 | void __init mach_setup (char **cmdline) |
97 | { | 97 | { |
98 | AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */ | 98 | AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */ |
99 | AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins. */ | 99 | AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins. */ |
100 | mach_tick = as85ep1_led_tick; | 100 | mach_tick = as85ep1_led_tick; |
101 | } | 101 | } |
102 | 102 | ||
103 | void __init mach_get_physical_ram (unsigned long *ram_start, | 103 | void __init mach_get_physical_ram (unsigned long *ram_start, |
104 | unsigned long *ram_len) | 104 | unsigned long *ram_len) |
105 | { | 105 | { |
106 | *ram_start = RAM_START; | 106 | *ram_start = RAM_START; |
107 | *ram_len = RAM_END - RAM_START; | 107 | *ram_len = RAM_END - RAM_START; |
108 | } | 108 | } |
109 | 109 | ||
110 | /* Convenience macros. */ | 110 | /* Convenience macros. */ |
111 | #define SRAM_END (SRAM_ADDR + SRAM_SIZE) | 111 | #define SRAM_END (SRAM_ADDR + SRAM_SIZE) |
112 | #define SDRAM_END (SDRAM_ADDR + SDRAM_SIZE) | 112 | #define SDRAM_END (SDRAM_ADDR + SDRAM_SIZE) |
113 | 113 | ||
114 | void __init mach_reserve_bootmem () | 114 | void __init mach_reserve_bootmem () |
115 | { | 115 | { |
116 | if (SDRAM_ADDR < RAM_END && SDRAM_ADDR > RAM_START) | 116 | if (SDRAM_ADDR < RAM_END && SDRAM_ADDR > RAM_START) |
117 | /* We can't use the space between SRAM and SDRAM, so | 117 | /* We can't use the space between SRAM and SDRAM, so |
118 | prevent the kernel from trying. */ | 118 | prevent the kernel from trying. */ |
119 | reserve_bootmem (SRAM_END, SDRAM_ADDR - SRAM_END); | 119 | reserve_bootmem (SRAM_END, SDRAM_ADDR - SRAM_END); |
120 | } | 120 | } |
121 | 121 | ||
122 | void mach_gettimeofday (struct timespec *tv) | 122 | void mach_gettimeofday (struct timespec *tv) |
123 | { | 123 | { |
124 | tv->tv_sec = 0; | 124 | tv->tv_sec = 0; |
125 | tv->tv_nsec = 0; | 125 | tv->tv_nsec = 0; |
126 | } | 126 | } |
127 | 127 | ||
128 | void __init mach_sched_init (struct irqaction *timer_action) | 128 | void __init mach_sched_init (struct irqaction *timer_action) |
129 | { | 129 | { |
130 | /* Start hardware timer. */ | 130 | /* Start hardware timer. */ |
131 | v850e_timer_d_configure (0, HZ); | 131 | v850e_timer_d_configure (0, HZ); |
132 | /* Install timer interrupt handler. */ | 132 | /* Install timer interrupt handler. */ |
133 | setup_irq (IRQ_INTCMD(0), timer_action); | 133 | setup_irq (IRQ_INTCMD(0), timer_action); |
134 | } | 134 | } |
135 | 135 | ||
136 | static struct v850e_intc_irq_init irq_inits[] = { | 136 | static struct v850e_intc_irq_init irq_inits[] = { |
137 | { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, | 137 | { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, |
138 | { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 }, | 138 | { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 }, |
139 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, | 139 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, |
140 | { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 }, | 140 | { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 }, |
141 | { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 }, | 141 | { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 }, |
142 | { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 }, | 142 | { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 }, |
143 | { 0 } | 143 | { 0 } |
144 | }; | 144 | }; |
145 | #define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) | 145 | #define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1) |
146 | 146 | ||
147 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; | 147 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; |
148 | 148 | ||
149 | void __init mach_init_irqs (void) | 149 | void __init mach_init_irqs (void) |
150 | { | 150 | { |
151 | v850e_intc_init_irq_types (irq_inits, hw_itypes); | 151 | v850e_intc_init_irq_types (irq_inits, hw_itypes); |
152 | } | 152 | } |
153 | 153 | ||
154 | void machine_restart (char *__unused) | 154 | void machine_restart (char *__unused) |
155 | { | 155 | { |
156 | #ifdef CONFIG_RESET_GUARD | 156 | #ifdef CONFIG_RESET_GUARD |
157 | disable_reset_guard (); | 157 | disable_reset_guard (); |
158 | #endif | 158 | #endif |
159 | asm ("jmp r0"); /* Jump to the reset vector. */ | 159 | asm ("jmp r0"); /* Jump to the reset vector. */ |
160 | } | 160 | } |
161 | 161 | ||
162 | void machine_halt (void) | 162 | void machine_halt (void) |
163 | { | 163 | { |
164 | #ifdef CONFIG_RESET_GUARD | 164 | #ifdef CONFIG_RESET_GUARD |
165 | disable_reset_guard (); | 165 | disable_reset_guard (); |
166 | #endif | 166 | #endif |
167 | local_irq_disable (); /* Ignore all interrupts. */ | 167 | local_irq_disable (); /* Ignore all interrupts. */ |
168 | AS85EP1_PORT_IO (LEDS_PORT) = 0xAA; /* Note that we halted. */ | 168 | AS85EP1_PORT_IO (LEDS_PORT) = 0xAA; /* Note that we halted. */ |
169 | for (;;) | 169 | for (;;) |
170 | asm ("halt; nop; nop; nop; nop; nop"); | 170 | asm ("halt; nop; nop; nop; nop; nop"); |
171 | } | 171 | } |
172 | 172 | ||
173 | void machine_power_off (void) | 173 | void machine_power_off (void) |
174 | { | 174 | { |
175 | machine_halt (); | 175 | machine_halt (); |
176 | } | 176 | } |
177 | 177 | ||
178 | /* Called before configuring an on-chip UART. */ | 178 | /* Called before configuring an on-chip UART. */ |
179 | void as85ep1_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) | 179 | void as85ep1_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) |
180 | { | 180 | { |
181 | /* Make the shared uart/port pins be uart pins. */ | 181 | /* Make the shared uart/port pins be uart pins. */ |
182 | AS85EP1_PORT_PMC(3) |= (0x5 << chan); | 182 | AS85EP1_PORT_PMC(3) |= (0x5 << chan); |
183 | 183 | ||
184 | /* The AS85EP1 connects some general-purpose I/O pins on the CPU to | 184 | /* The AS85EP1 connects some general-purpose I/O pins on the CPU to |
185 | the RTS/CTS lines of UART 1's serial connection. I/O pins P53 | 185 | the RTS/CTS lines of UART 1's serial connection. I/O pins P53 |
186 | and P54 are RTS and CTS respectively. */ | 186 | and P54 are RTS and CTS respectively. */ |
187 | if (chan == 1) { | 187 | if (chan == 1) { |
188 | /* Put P53 & P54 in I/O port mode. */ | 188 | /* Put P53 & P54 in I/O port mode. */ |
189 | AS85EP1_PORT_PMC(5) &= ~0x18; | 189 | AS85EP1_PORT_PMC(5) &= ~0x18; |
190 | /* Make P53 an output, and P54 an input. */ | 190 | /* Make P53 an output, and P54 an input. */ |
191 | AS85EP1_PORT_PM(5) |= 0x10; | 191 | AS85EP1_PORT_PM(5) |= 0x10; |
192 | } | 192 | } |
193 | } | 193 | } |
194 | 194 | ||
195 | /* Minimum and maximum bounds for the moving upper LED boundary in the | 195 | /* Minimum and maximum bounds for the moving upper LED boundary in the |
196 | clock tick display. */ | 196 | clock tick display. */ |
197 | #define MIN_MAX_POS 0 | 197 | #define MIN_MAX_POS 0 |
198 | #define MAX_MAX_POS 7 | 198 | #define MAX_MAX_POS 7 |
199 | 199 | ||
200 | /* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if | 200 | /* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if |
201 | we pick 6 and 0 as above, we get 49 cycles, which is when divided into | 201 | we pick 6 and 0 as above, we get 49 cycles, which is when divided into |
202 | the standard 100 value for HZ, gives us an almost 1s total time. */ | 202 | the standard 100 value for HZ, gives us an almost 1s total time. */ |
203 | #define TICKS_PER_FRAME \ | 203 | #define TICKS_PER_FRAME \ |
204 | (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS)) | 204 | (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS)) |
205 | 205 | ||
206 | static void as85ep1_led_tick () | 206 | static void as85ep1_led_tick () |
207 | { | 207 | { |
208 | static unsigned counter = 0; | 208 | static unsigned counter = 0; |
209 | 209 | ||
210 | if (++counter == TICKS_PER_FRAME) { | 210 | if (++counter == TICKS_PER_FRAME) { |
211 | static int pos = 0, max_pos = MAX_MAX_POS, dir = 1; | 211 | static int pos = 0, max_pos = MAX_MAX_POS, dir = 1; |
212 | 212 | ||
213 | if (dir > 0 && pos == max_pos) { | 213 | if (dir > 0 && pos == max_pos) { |
214 | dir = -1; | 214 | dir = -1; |
215 | if (max_pos == MIN_MAX_POS) | 215 | if (max_pos == MIN_MAX_POS) |
216 | max_pos = MAX_MAX_POS; | 216 | max_pos = MAX_MAX_POS; |
217 | else | 217 | else |
218 | max_pos--; | 218 | max_pos--; |
219 | } else { | 219 | } else { |
220 | if (dir < 0 && pos == 0) | 220 | if (dir < 0 && pos == 0) |
221 | dir = 1; | 221 | dir = 1; |
222 | 222 | ||
223 | if (pos + dir <= max_pos) { | 223 | if (pos + dir <= max_pos) { |
224 | /* Each bit of port 0 has a LED. */ | 224 | /* Each bit of port 0 has a LED. */ |
225 | set_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT)); | 225 | set_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT)); |
226 | pos += dir; | 226 | pos += dir; |
227 | clear_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT)); | 227 | clear_bit (pos, &AS85EP1_PORT_IO(LEDS_PORT)); |
228 | } | 228 | } |
229 | } | 229 | } |
230 | 230 | ||
231 | counter = 0; | 231 | counter = 0; |
232 | } | 232 | } |
233 | } | 233 | } |
234 | 234 |
arch/v850/kernel/fpga85e2c.c
1 | /* | 1 | /* |
2 | * arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for | 2 | * arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for |
3 | * FPGA implementation of V850E2/NA85E2C | 3 | * FPGA implementation of V850E2/NA85E2C |
4 | * | 4 | * |
5 | * Copyright (C) 2002,03 NEC Electronics Corporation | 5 | * Copyright (C) 2002,03 NEC Electronics Corporation |
6 | * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> | 6 | * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General | 8 | * This file is subject to the terms and conditions of the GNU General |
9 | * Public License. See the file COPYING in the main directory of this | 9 | * Public License. See the file COPYING in the main directory of this |
10 | * archive for more details. | 10 | * archive for more details. |
11 | * | 11 | * |
12 | * Written by Miles Bader <miles@gnu.org> | 12 | * Written by Miles Bader <miles@gnu.org> |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/swap.h> | 19 | #include <linux/swap.h> |
20 | #include <linux/bootmem.h> | 20 | #include <linux/bootmem.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
23 | 23 | ||
24 | #include <asm/atomic.h> | 24 | #include <asm/atomic.h> |
25 | #include <asm/page.h> | 25 | #include <asm/page.h> |
26 | #include <asm/machdep.h> | 26 | #include <asm/machdep.h> |
27 | 27 | ||
28 | #include "mach.h" | 28 | #include "mach.h" |
29 | 29 | ||
30 | extern void memcons_setup (void); | 30 | extern void memcons_setup (void); |
31 | 31 | ||
32 | 32 | ||
33 | #define REG_DUMP_ADDR 0x220000 | 33 | #define REG_DUMP_ADDR 0x220000 |
34 | 34 | ||
35 | 35 | ||
36 | extern struct irqaction reg_snap_action; /* fwd decl */ | 36 | extern struct irqaction reg_snap_action; /* fwd decl */ |
37 | 37 | ||
38 | 38 | ||
39 | void __init mach_early_init (void) | 39 | void __init mach_early_init (void) |
40 | { | 40 | { |
41 | int i; | 41 | int i; |
42 | const u32 *src; | 42 | const u32 *src; |
43 | register u32 *dst asm ("ep"); | 43 | register u32 *dst asm ("ep"); |
44 | extern u32 _intv_end, _intv_load_start; | 44 | extern u32 _intv_end, _intv_load_start; |
45 | 45 | ||
46 | /* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit, | 46 | /* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit, |
47 | everything else 32-bit. */ | 47 | everything else 32-bit. */ |
48 | V850E2_BSC = 0x2AA6; | 48 | V850E2_BSC = 0x2AA6; |
49 | for (i = 2; i <= 6; i++) | 49 | for (i = 2; i <= 6; i++) |
50 | CSDEV(i) = 0; /* 32 bit */ | 50 | CSDEV(i) = 0; /* 32 bit */ |
51 | 51 | ||
52 | /* Ensure that the simulator halts on a panic, instead of going | 52 | /* Ensure that the simulator halts on a panic, instead of going |
53 | into an infinite loop inside the panic function. */ | 53 | into an infinite loop inside the panic function. */ |
54 | panic_timeout = -1; | 54 | panic_timeout = -1; |
55 | 55 | ||
56 | /* Move the interrupt vectors into their real location. Note that | 56 | /* Move the interrupt vectors into their real location. Note that |
57 | any relocations there are relative to the real location, so we | 57 | any relocations there are relative to the real location, so we |
58 | don't have to fix anything up. We use a loop instead of calling | 58 | don't have to fix anything up. We use a loop instead of calling |
59 | memcpy to keep this a leaf function (to avoid a function | 59 | memcpy to keep this a leaf function (to avoid a function |
60 | prologue being generated). */ | 60 | prologue being generated). */ |
61 | dst = 0x10; /* &_intv_start + 0x10. */ | 61 | dst = 0x10; /* &_intv_start + 0x10. */ |
62 | src = &_intv_load_start; | 62 | src = &_intv_load_start; |
63 | do { | 63 | do { |
64 | u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3]; | 64 | u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3]; |
65 | u32 t4 = src[4], t5 = src[5], t6 = src[6], t7 = src[7]; | 65 | u32 t4 = src[4], t5 = src[5], t6 = src[6], t7 = src[7]; |
66 | dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3; | 66 | dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3; |
67 | dst[4] = t4; dst[5] = t5; dst[6] = t6; dst[7] = t7; | 67 | dst[4] = t4; dst[5] = t5; dst[6] = t6; dst[7] = t7; |
68 | dst += 8; | 68 | dst += 8; |
69 | src += 8; | 69 | src += 8; |
70 | } while (dst < &_intv_end); | 70 | } while (dst < &_intv_end); |
71 | } | 71 | } |
72 | 72 | ||
73 | void __init mach_setup (char **cmdline) | 73 | void __init mach_setup (char **cmdline) |
74 | { | 74 | { |
75 | memcons_setup (); | 75 | memcons_setup (); |
76 | 76 | ||
77 | /* Setup up NMI0 to copy the registers to a known memory location. | 77 | /* Setup up NMI0 to copy the registers to a known memory location. |
78 | The FGPA board has a button that produces NMI0 when pressed, so | 78 | The FGPA board has a button that produces NMI0 when pressed, so |
79 | this allows us to push the button, and then look at memory to see | 79 | this allows us to push the button, and then look at memory to see |
80 | what's in the registers (there's no other way to easily do so). | 80 | what's in the registers (there's no other way to easily do so). |
81 | We have to use `setup_irq' instead of `request_irq' because it's | 81 | We have to use `setup_irq' instead of `request_irq' because it's |
82 | still too early to do memory allocation. */ | 82 | still too early to do memory allocation. */ |
83 | setup_irq (IRQ_NMI (0), ®_snap_action); | 83 | setup_irq (IRQ_NMI (0), ®_snap_action); |
84 | } | 84 | } |
85 | 85 | ||
86 | void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len) | 86 | void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len) |
87 | { | 87 | { |
88 | *ram_start = ERAM_ADDR; | 88 | *ram_start = ERAM_ADDR; |
89 | *ram_len = ERAM_SIZE; | 89 | *ram_len = ERAM_SIZE; |
90 | } | 90 | } |
91 | 91 | ||
92 | void __init mach_sched_init (struct irqaction *timer_action) | 92 | void __init mach_sched_init (struct irqaction *timer_action) |
93 | { | 93 | { |
94 | /* Setup up the timer interrupt. The FPGA peripheral control | 94 | /* Setup up the timer interrupt. The FPGA peripheral control |
95 | registers _only_ work with single-bit writes (set1/clr1)! */ | 95 | registers _only_ work with single-bit writes (set1/clr1)! */ |
96 | __clear_bit (RPU_GTMC_CE_BIT, &RPU_GTMC); | 96 | __clear_bit (RPU_GTMC_CE_BIT, &RPU_GTMC); |
97 | __clear_bit (RPU_GTMC_CLK_BIT, &RPU_GTMC); | 97 | __clear_bit (RPU_GTMC_CLK_BIT, &RPU_GTMC); |
98 | __set_bit (RPU_GTMC_CE_BIT, &RPU_GTMC); | 98 | __set_bit (RPU_GTMC_CE_BIT, &RPU_GTMC); |
99 | 99 | ||
100 | /* We use the first RPU interrupt, which occurs every 8.192ms. */ | 100 | /* We use the first RPU interrupt, which occurs every 8.192ms. */ |
101 | setup_irq (IRQ_RPU (0), timer_action); | 101 | setup_irq (IRQ_RPU (0), timer_action); |
102 | } | 102 | } |
103 | 103 | ||
104 | 104 | ||
105 | void mach_gettimeofday (struct timespec *tv) | 105 | void mach_gettimeofday (struct timespec *tv) |
106 | { | 106 | { |
107 | tv->tv_sec = 0; | 107 | tv->tv_sec = 0; |
108 | tv->tv_nsec = 0; | 108 | tv->tv_nsec = 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | void machine_halt (void) __attribute__ ((noreturn)); | 111 | void machine_halt (void) __attribute__ ((noreturn)); |
112 | void machine_halt (void) | 112 | void machine_halt (void) |
113 | { | 113 | { |
114 | for (;;) { | 114 | for (;;) { |
115 | DWC(0) = 0x7777; | 115 | DWC(0) = 0x7777; |
116 | DWC(1) = 0x7777; | 116 | DWC(1) = 0x7777; |
117 | ASC = 0xffff; | 117 | ASC = 0xffff; |
118 | FLGREG(0) = 1; /* Halt immediately. */ | 118 | FLGREG(0) = 1; /* Halt immediately. */ |
119 | asm ("di; halt; nop; nop; nop; nop; nop"); | 119 | asm ("di; halt; nop; nop; nop; nop; nop"); |
120 | } | 120 | } |
121 | } | 121 | } |
122 | 122 | ||
123 | void machine_restart (char *__unused) | 123 | void machine_restart (char *__unused) |
124 | { | 124 | { |
125 | machine_halt (); | 125 | machine_halt (); |
126 | } | 126 | } |
127 | 127 | ||
128 | void machine_power_off (void) | 128 | void machine_power_off (void) |
129 | { | 129 | { |
130 | machine_halt (); | 130 | machine_halt (); |
131 | } | 131 | } |
132 | 132 | ||
133 | 133 | ||
134 | /* Interrupts */ | 134 | /* Interrupts */ |
135 | 135 | ||
136 | struct v850e_intc_irq_init irq_inits[] = { | 136 | struct v850e_intc_irq_init irq_inits[] = { |
137 | { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, | 137 | { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, |
138 | { "RPU", IRQ_RPU(0), IRQ_RPU_NUM, 1, 6 }, | 138 | { "RPU", IRQ_RPU(0), IRQ_RPU_NUM, 1, 6 }, |
139 | { 0 } | 139 | { 0 } |
140 | }; | 140 | }; |
141 | #define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) | 141 | #define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1) |
142 | 142 | ||
143 | struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; | 143 | struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; |
144 | 144 | ||
145 | /* Initialize interrupts. */ | 145 | /* Initialize interrupts. */ |
146 | void __init mach_init_irqs (void) | 146 | void __init mach_init_irqs (void) |
147 | { | 147 | { |
148 | v850e_intc_init_irq_types (irq_inits, hw_itypes); | 148 | v850e_intc_init_irq_types (irq_inits, hw_itypes); |
149 | } | 149 | } |
150 | 150 | ||
151 | 151 | ||
152 | /* An interrupt handler that copies the registers to a known memory location, | 152 | /* An interrupt handler that copies the registers to a known memory location, |
153 | for debugging purposes. */ | 153 | for debugging purposes. */ |
154 | 154 | ||
155 | static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs) | 155 | static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs) |
156 | { | 156 | { |
157 | (*(unsigned *)REG_DUMP_ADDR)++; | 157 | (*(unsigned *)REG_DUMP_ADDR)++; |
158 | (*(struct pt_regs *)(REG_DUMP_ADDR + sizeof (unsigned))) = *regs; | 158 | (*(struct pt_regs *)(REG_DUMP_ADDR + sizeof (unsigned))) = *regs; |
159 | } | 159 | } |
160 | 160 | ||
161 | static int reg_snap_dev_id; | 161 | static int reg_snap_dev_id; |
162 | static struct irqaction reg_snap_action = { | 162 | static struct irqaction reg_snap_action = { |
163 | make_reg_snap, 0, CPU_MASK_NONE, "reg_snap", ®_snap_dev_id, 0 | 163 | make_reg_snap, 0, CPU_MASK_NONE, "reg_snap", ®_snap_dev_id, 0 |
164 | }; | 164 | }; |
165 | 165 |
arch/v850/kernel/gbus_int.c
1 | /* | 1 | /* |
2 | * arch/v850/kernel/gbus_int.c -- Midas labs GBUS interrupt support | 2 | * arch/v850/kernel/gbus_int.c -- Midas labs GBUS interrupt support |
3 | * | 3 | * |
4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation | 4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation |
5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/signal.h> | 18 | #include <linux/signal.h> |
19 | #include <linux/kernel.h> | ||
19 | 20 | ||
20 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
21 | 22 | ||
22 | 23 | ||
23 | /* The number of shared GINT interrupts. */ | 24 | /* The number of shared GINT interrupts. */ |
24 | #define NUM_GINTS 4 | 25 | #define NUM_GINTS 4 |
25 | 26 | ||
26 | /* For each GINT interrupt, how many GBUS interrupts are using it. */ | 27 | /* For each GINT interrupt, how many GBUS interrupts are using it. */ |
27 | static unsigned gint_num_active_irqs[NUM_GINTS] = { 0 }; | 28 | static unsigned gint_num_active_irqs[NUM_GINTS] = { 0 }; |
28 | 29 | ||
29 | /* A table of GINTn interrupts we actually use. | 30 | /* A table of GINTn interrupts we actually use. |
30 | Note that we don't use GINT0 because all the boards we support treat it | 31 | Note that we don't use GINT0 because all the boards we support treat it |
31 | specially. */ | 32 | specially. */ |
32 | struct used_gint { | 33 | struct used_gint { |
33 | unsigned gint; | 34 | unsigned gint; |
34 | unsigned priority; | 35 | unsigned priority; |
35 | } used_gint[] = { | 36 | } used_gint[] = { |
36 | { 1, GBUS_INT_PRIORITY_HIGH }, | 37 | { 1, GBUS_INT_PRIORITY_HIGH }, |
37 | { 3, GBUS_INT_PRIORITY_LOW } | 38 | { 3, GBUS_INT_PRIORITY_LOW } |
38 | }; | 39 | }; |
39 | #define NUM_USED_GINTS (sizeof used_gint / sizeof used_gint[0]) | 40 | #define NUM_USED_GINTS ARRAY_SIZE(used_gint) |
40 | 41 | ||
41 | /* A table of which GINT is used by each GBUS interrupts (they are | 42 | /* A table of which GINT is used by each GBUS interrupts (they are |
42 | assigned based on priority). */ | 43 | assigned based on priority). */ |
43 | static unsigned char gbus_int_gint[IRQ_GBUS_INT_NUM]; | 44 | static unsigned char gbus_int_gint[IRQ_GBUS_INT_NUM]; |
44 | 45 | ||
45 | 46 | ||
46 | /* Interrupt enabling/disabling. */ | 47 | /* Interrupt enabling/disabling. */ |
47 | 48 | ||
48 | /* Enable interrupt handling for interrupt IRQ. */ | 49 | /* Enable interrupt handling for interrupt IRQ. */ |
49 | void gbus_int_enable_irq (unsigned irq) | 50 | void gbus_int_enable_irq (unsigned irq) |
50 | { | 51 | { |
51 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; | 52 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; |
52 | GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint) | 53 | GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint) |
53 | |= GBUS_INT_IRQ_MASK (irq); | 54 | |= GBUS_INT_IRQ_MASK (irq); |
54 | } | 55 | } |
55 | 56 | ||
56 | /* Disable interrupt handling for interrupt IRQ. Note that any | 57 | /* Disable interrupt handling for interrupt IRQ. Note that any |
57 | interrupts received while disabled will be delivered once the | 58 | interrupts received while disabled will be delivered once the |
58 | interrupt is enabled again, unless they are explicitly cleared using | 59 | interrupt is enabled again, unless they are explicitly cleared using |
59 | `gbus_int_clear_pending_irq'. */ | 60 | `gbus_int_clear_pending_irq'. */ |
60 | void gbus_int_disable_irq (unsigned irq) | 61 | void gbus_int_disable_irq (unsigned irq) |
61 | { | 62 | { |
62 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; | 63 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; |
63 | GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint) | 64 | GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint) |
64 | &= ~GBUS_INT_IRQ_MASK (irq); | 65 | &= ~GBUS_INT_IRQ_MASK (irq); |
65 | } | 66 | } |
66 | 67 | ||
67 | /* Return true if interrupt handling for interrupt IRQ is enabled. */ | 68 | /* Return true if interrupt handling for interrupt IRQ is enabled. */ |
68 | int gbus_int_irq_enabled (unsigned irq) | 69 | int gbus_int_irq_enabled (unsigned irq) |
69 | { | 70 | { |
70 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; | 71 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; |
71 | return (GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint) | 72 | return (GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint) |
72 | & GBUS_INT_IRQ_MASK(irq)); | 73 | & GBUS_INT_IRQ_MASK(irq)); |
73 | } | 74 | } |
74 | 75 | ||
75 | /* Disable all GBUS irqs. */ | 76 | /* Disable all GBUS irqs. */ |
76 | void gbus_int_disable_irqs () | 77 | void gbus_int_disable_irqs () |
77 | { | 78 | { |
78 | unsigned w, n; | 79 | unsigned w, n; |
79 | for (w = 0; w < GBUS_INT_NUM_WORDS; w++) | 80 | for (w = 0; w < GBUS_INT_NUM_WORDS; w++) |
80 | for (n = 0; n < IRQ_GINT_NUM; n++) | 81 | for (n = 0; n < IRQ_GINT_NUM; n++) |
81 | GBUS_INT_ENABLE (w, n) = 0; | 82 | GBUS_INT_ENABLE (w, n) = 0; |
82 | } | 83 | } |
83 | 84 | ||
84 | /* Clear any pending interrupts for IRQ. */ | 85 | /* Clear any pending interrupts for IRQ. */ |
85 | void gbus_int_clear_pending_irq (unsigned irq) | 86 | void gbus_int_clear_pending_irq (unsigned irq) |
86 | { | 87 | { |
87 | GBUS_INT_CLEAR (GBUS_INT_IRQ_WORD(irq)) = GBUS_INT_IRQ_MASK (irq); | 88 | GBUS_INT_CLEAR (GBUS_INT_IRQ_WORD(irq)) = GBUS_INT_IRQ_MASK (irq); |
88 | } | 89 | } |
89 | 90 | ||
90 | /* Return true if interrupt IRQ is pending (but disabled). */ | 91 | /* Return true if interrupt IRQ is pending (but disabled). */ |
91 | int gbus_int_irq_pending (unsigned irq) | 92 | int gbus_int_irq_pending (unsigned irq) |
92 | { | 93 | { |
93 | return (GBUS_INT_STATUS (GBUS_INT_IRQ_WORD(irq)) | 94 | return (GBUS_INT_STATUS (GBUS_INT_IRQ_WORD(irq)) |
94 | & GBUS_INT_IRQ_MASK(irq)); | 95 | & GBUS_INT_IRQ_MASK(irq)); |
95 | } | 96 | } |
96 | 97 | ||
97 | 98 | ||
98 | /* Delegating interrupts. */ | 99 | /* Delegating interrupts. */ |
99 | 100 | ||
100 | /* Handle a shared GINT interrupt by passing to the appropriate GBUS | 101 | /* Handle a shared GINT interrupt by passing to the appropriate GBUS |
101 | interrupt handler. */ | 102 | interrupt handler. */ |
102 | static irqreturn_t gbus_int_handle_irq (int irq, void *dev_id, | 103 | static irqreturn_t gbus_int_handle_irq (int irq, void *dev_id, |
103 | struct pt_regs *regs) | 104 | struct pt_regs *regs) |
104 | { | 105 | { |
105 | unsigned w; | 106 | unsigned w; |
106 | irqreturn_t rval = IRQ_NONE; | 107 | irqreturn_t rval = IRQ_NONE; |
107 | unsigned gint = irq - IRQ_GINT (0); | 108 | unsigned gint = irq - IRQ_GINT (0); |
108 | 109 | ||
109 | for (w = 0; w < GBUS_INT_NUM_WORDS; w++) { | 110 | for (w = 0; w < GBUS_INT_NUM_WORDS; w++) { |
110 | unsigned status = GBUS_INT_STATUS (w); | 111 | unsigned status = GBUS_INT_STATUS (w); |
111 | unsigned enable = GBUS_INT_ENABLE (w, gint); | 112 | unsigned enable = GBUS_INT_ENABLE (w, gint); |
112 | 113 | ||
113 | /* Only pay attention to enabled interrupts. */ | 114 | /* Only pay attention to enabled interrupts. */ |
114 | status &= enable; | 115 | status &= enable; |
115 | if (status) { | 116 | if (status) { |
116 | irq = IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD); | 117 | irq = IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD); |
117 | do { | 118 | do { |
118 | /* There's an active interrupt in word | 119 | /* There's an active interrupt in word |
119 | W, find out which one, and call its | 120 | W, find out which one, and call its |
120 | handler. */ | 121 | handler. */ |
121 | 122 | ||
122 | while (! (status & 0x1)) { | 123 | while (! (status & 0x1)) { |
123 | irq++; | 124 | irq++; |
124 | status >>= 1; | 125 | status >>= 1; |
125 | } | 126 | } |
126 | status &= ~0x1; | 127 | status &= ~0x1; |
127 | 128 | ||
128 | /* Recursively call handle_irq to handle it. */ | 129 | /* Recursively call handle_irq to handle it. */ |
129 | handle_irq (irq, regs); | 130 | handle_irq (irq, regs); |
130 | rval = IRQ_HANDLED; | 131 | rval = IRQ_HANDLED; |
131 | } while (status); | 132 | } while (status); |
132 | } | 133 | } |
133 | } | 134 | } |
134 | 135 | ||
135 | /* Toggle the `all enable' bit back and forth, which should cause | 136 | /* Toggle the `all enable' bit back and forth, which should cause |
136 | another edge transition if there are any other interrupts | 137 | another edge transition if there are any other interrupts |
137 | still pending, and so result in another CPU interrupt. */ | 138 | still pending, and so result in another CPU interrupt. */ |
138 | GBUS_INT_ENABLE (0, gint) &= ~0x1; | 139 | GBUS_INT_ENABLE (0, gint) &= ~0x1; |
139 | GBUS_INT_ENABLE (0, gint) |= 0x1; | 140 | GBUS_INT_ENABLE (0, gint) |= 0x1; |
140 | 141 | ||
141 | return rval; | 142 | return rval; |
142 | } | 143 | } |
143 | 144 | ||
144 | 145 | ||
145 | /* Initialize GBUS interrupt sources. */ | 146 | /* Initialize GBUS interrupt sources. */ |
146 | 147 | ||
147 | static void irq_nop (unsigned irq) { } | 148 | static void irq_nop (unsigned irq) { } |
148 | 149 | ||
149 | static unsigned gbus_int_startup_irq (unsigned irq) | 150 | static unsigned gbus_int_startup_irq (unsigned irq) |
150 | { | 151 | { |
151 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; | 152 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; |
152 | 153 | ||
153 | if (gint_num_active_irqs[gint] == 0) { | 154 | if (gint_num_active_irqs[gint] == 0) { |
154 | /* First enable the CPU interrupt. */ | 155 | /* First enable the CPU interrupt. */ |
155 | int rval = | 156 | int rval = |
156 | request_irq (IRQ_GINT(gint), gbus_int_handle_irq, | 157 | request_irq (IRQ_GINT(gint), gbus_int_handle_irq, |
157 | IRQF_DISABLED, | 158 | IRQF_DISABLED, |
158 | "gbus_int_handler", | 159 | "gbus_int_handler", |
159 | &gint_num_active_irqs[gint]); | 160 | &gint_num_active_irqs[gint]); |
160 | if (rval != 0) | 161 | if (rval != 0) |
161 | return rval; | 162 | return rval; |
162 | } | 163 | } |
163 | 164 | ||
164 | gint_num_active_irqs[gint]++; | 165 | gint_num_active_irqs[gint]++; |
165 | 166 | ||
166 | gbus_int_clear_pending_irq (irq); | 167 | gbus_int_clear_pending_irq (irq); |
167 | gbus_int_enable_irq (irq); | 168 | gbus_int_enable_irq (irq); |
168 | 169 | ||
169 | return 0; | 170 | return 0; |
170 | } | 171 | } |
171 | 172 | ||
172 | static void gbus_int_shutdown_irq (unsigned irq) | 173 | static void gbus_int_shutdown_irq (unsigned irq) |
173 | { | 174 | { |
174 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; | 175 | unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; |
175 | 176 | ||
176 | gbus_int_disable_irq (irq); | 177 | gbus_int_disable_irq (irq); |
177 | 178 | ||
178 | if (--gint_num_active_irqs[gint] == 0) | 179 | if (--gint_num_active_irqs[gint] == 0) |
179 | /* Disable the CPU interrupt. */ | 180 | /* Disable the CPU interrupt. */ |
180 | free_irq (IRQ_GINT(gint), &gint_num_active_irqs[gint]); | 181 | free_irq (IRQ_GINT(gint), &gint_num_active_irqs[gint]); |
181 | } | 182 | } |
182 | 183 | ||
183 | /* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array | 184 | /* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array |
184 | INITS (which is terminated by an entry with the name field == 0). */ | 185 | INITS (which is terminated by an entry with the name field == 0). */ |
185 | void __init gbus_int_init_irq_types (struct gbus_int_irq_init *inits, | 186 | void __init gbus_int_init_irq_types (struct gbus_int_irq_init *inits, |
186 | struct hw_interrupt_type *hw_irq_types) | 187 | struct hw_interrupt_type *hw_irq_types) |
187 | { | 188 | { |
188 | struct gbus_int_irq_init *init; | 189 | struct gbus_int_irq_init *init; |
189 | for (init = inits; init->name; init++) { | 190 | for (init = inits; init->name; init++) { |
190 | unsigned i; | 191 | unsigned i; |
191 | struct hw_interrupt_type *hwit = hw_irq_types++; | 192 | struct hw_interrupt_type *hwit = hw_irq_types++; |
192 | 193 | ||
193 | hwit->typename = init->name; | 194 | hwit->typename = init->name; |
194 | 195 | ||
195 | hwit->startup = gbus_int_startup_irq; | 196 | hwit->startup = gbus_int_startup_irq; |
196 | hwit->shutdown = gbus_int_shutdown_irq; | 197 | hwit->shutdown = gbus_int_shutdown_irq; |
197 | hwit->enable = gbus_int_enable_irq; | 198 | hwit->enable = gbus_int_enable_irq; |
198 | hwit->disable = gbus_int_disable_irq; | 199 | hwit->disable = gbus_int_disable_irq; |
199 | hwit->ack = irq_nop; | 200 | hwit->ack = irq_nop; |
200 | hwit->end = irq_nop; | 201 | hwit->end = irq_nop; |
201 | 202 | ||
202 | /* Initialize kernel IRQ infrastructure for this interrupt. */ | 203 | /* Initialize kernel IRQ infrastructure for this interrupt. */ |
203 | init_irq_handlers(init->base, init->num, init->interval, hwit); | 204 | init_irq_handlers(init->base, init->num, init->interval, hwit); |
204 | 205 | ||
205 | /* Set the interrupt priorities. */ | 206 | /* Set the interrupt priorities. */ |
206 | for (i = 0; i < init->num; i++) { | 207 | for (i = 0; i < init->num; i++) { |
207 | unsigned j; | 208 | unsigned j; |
208 | for (j = 0; j < NUM_USED_GINTS; j++) | 209 | for (j = 0; j < NUM_USED_GINTS; j++) |
209 | if (used_gint[j].priority > init->priority) | 210 | if (used_gint[j].priority > init->priority) |
210 | break; | 211 | break; |
211 | /* Wherever we stopped looking is one past the | 212 | /* Wherever we stopped looking is one past the |
212 | GINT we want. */ | 213 | GINT we want. */ |
213 | gbus_int_gint[init->base + i * init->interval | 214 | gbus_int_gint[init->base + i * init->interval |
214 | - GBUS_INT_BASE_IRQ] | 215 | - GBUS_INT_BASE_IRQ] |
215 | = used_gint[j > 0 ? j - 1 : 0].gint; | 216 | = used_gint[j > 0 ? j - 1 : 0].gint; |
216 | } | 217 | } |
217 | } | 218 | } |
218 | } | 219 | } |
219 | 220 | ||
220 | 221 | ||
221 | /* Initialize IRQS. */ | 222 | /* Initialize IRQS. */ |
222 | 223 | ||
223 | /* Chip interrupts (GINTn) shared among GBUS interrupts. */ | 224 | /* Chip interrupts (GINTn) shared among GBUS interrupts. */ |
224 | static struct hw_interrupt_type gint_hw_itypes[NUM_USED_GINTS]; | 225 | static struct hw_interrupt_type gint_hw_itypes[NUM_USED_GINTS]; |
225 | 226 | ||
226 | 227 | ||
227 | /* GBUS interrupts themselves. */ | 228 | /* GBUS interrupts themselves. */ |
228 | 229 | ||
229 | struct gbus_int_irq_init gbus_irq_inits[] __initdata = { | 230 | struct gbus_int_irq_init gbus_irq_inits[] __initdata = { |
230 | /* First set defaults. */ | 231 | /* First set defaults. */ |
231 | { "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6}, | 232 | { "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6}, |
232 | { 0 } | 233 | { 0 } |
233 | }; | 234 | }; |
234 | #define NUM_GBUS_IRQ_INITS \ | 235 | #define NUM_GBUS_IRQ_INITS (ARRAY_SIZE(gbus_irq_inits) - 1) |
235 | ((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1) | ||
236 | 236 | ||
237 | static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS]; | 237 | static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS]; |
238 | 238 | ||
239 | 239 | ||
240 | /* Initialize GBUS interrupts. */ | 240 | /* Initialize GBUS interrupts. */ |
241 | void __init gbus_int_init_irqs (void) | 241 | void __init gbus_int_init_irqs (void) |
242 | { | 242 | { |
243 | unsigned i; | 243 | unsigned i; |
244 | 244 | ||
245 | /* First initialize the shared gint interrupts. */ | 245 | /* First initialize the shared gint interrupts. */ |
246 | for (i = 0; i < NUM_USED_GINTS; i++) { | 246 | for (i = 0; i < NUM_USED_GINTS; i++) { |
247 | unsigned gint = used_gint[i].gint; | 247 | unsigned gint = used_gint[i].gint; |
248 | struct v850e_intc_irq_init gint_irq_init[2]; | 248 | struct v850e_intc_irq_init gint_irq_init[2]; |
249 | 249 | ||
250 | /* We initialize one GINT interrupt at a time. */ | 250 | /* We initialize one GINT interrupt at a time. */ |
251 | gint_irq_init[0].name = "GINT"; | 251 | gint_irq_init[0].name = "GINT"; |
252 | gint_irq_init[0].base = IRQ_GINT (gint); | 252 | gint_irq_init[0].base = IRQ_GINT (gint); |
253 | gint_irq_init[0].num = 1; | 253 | gint_irq_init[0].num = 1; |
254 | gint_irq_init[0].interval = 1; | 254 | gint_irq_init[0].interval = 1; |
255 | gint_irq_init[0].priority = used_gint[i].priority; | 255 | gint_irq_init[0].priority = used_gint[i].priority; |
256 | 256 | ||
257 | gint_irq_init[1].name = 0; /* Terminate the vector. */ | 257 | gint_irq_init[1].name = 0; /* Terminate the vector. */ |
258 | 258 | ||
259 | v850e_intc_init_irq_types (gint_irq_init, gint_hw_itypes); | 259 | v850e_intc_init_irq_types (gint_irq_init, gint_hw_itypes); |
260 | } | 260 | } |
261 | 261 | ||
262 | /* Then the GBUS interrupts. */ | 262 | /* Then the GBUS interrupts. */ |
263 | gbus_int_disable_irqs (); | 263 | gbus_int_disable_irqs (); |
264 | gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes); | 264 | gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes); |
265 | /* Turn on the `all enable' bits, which are ANDed with | 265 | /* Turn on the `all enable' bits, which are ANDed with |
266 | individual interrupt enable bits; we only want to bother with | 266 | individual interrupt enable bits; we only want to bother with |
267 | the latter. They are the first bit in the first word of each | 267 | the latter. They are the first bit in the first word of each |
268 | interrupt-enable area. */ | 268 | interrupt-enable area. */ |
269 | for (i = 0; i < NUM_USED_GINTS; i++) | 269 | for (i = 0; i < NUM_USED_GINTS; i++) |
270 | GBUS_INT_ENABLE (0, used_gint[i].gint) = 0x1; | 270 | GBUS_INT_ENABLE (0, used_gint[i].gint) = 0x1; |
271 | } | 271 | } |
arch/v850/kernel/ma.c
1 | /* | 1 | /* |
2 | * arch/v850/kernel/ma.c -- V850E/MA series of cpu chips | 2 | * arch/v850/kernel/ma.c -- V850E/MA series of cpu chips |
3 | * | 3 | * |
4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation | 4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation |
5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/swap.h> | 17 | #include <linux/swap.h> |
18 | #include <linux/bootmem.h> | 18 | #include <linux/bootmem.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | 20 | ||
21 | #include <asm/atomic.h> | 21 | #include <asm/atomic.h> |
22 | #include <asm/page.h> | 22 | #include <asm/page.h> |
23 | #include <asm/machdep.h> | 23 | #include <asm/machdep.h> |
24 | #include <asm/v850e_timer_d.h> | 24 | #include <asm/v850e_timer_d.h> |
25 | 25 | ||
26 | #include "mach.h" | 26 | #include "mach.h" |
27 | 27 | ||
28 | void __init mach_sched_init (struct irqaction *timer_action) | 28 | void __init mach_sched_init (struct irqaction *timer_action) |
29 | { | 29 | { |
30 | /* Start hardware timer. */ | 30 | /* Start hardware timer. */ |
31 | v850e_timer_d_configure (0, HZ); | 31 | v850e_timer_d_configure (0, HZ); |
32 | /* Install timer interrupt handler. */ | 32 | /* Install timer interrupt handler. */ |
33 | setup_irq (IRQ_INTCMD(0), timer_action); | 33 | setup_irq (IRQ_INTCMD(0), timer_action); |
34 | } | 34 | } |
35 | 35 | ||
36 | static struct v850e_intc_irq_init irq_inits[] = { | 36 | static struct v850e_intc_irq_init irq_inits[] = { |
37 | { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, | 37 | { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, |
38 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, | 38 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, |
39 | { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 }, | 39 | { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 }, |
40 | { "CSI", IRQ_INTCSI(0), IRQ_INTCSI_NUM, 4, 4 }, | 40 | { "CSI", IRQ_INTCSI(0), IRQ_INTCSI_NUM, 4, 4 }, |
41 | { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 4, 3 }, | 41 | { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 4, 3 }, |
42 | { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 4, 4 }, | 42 | { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 4, 4 }, |
43 | { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 4, 5 }, | 43 | { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 4, 5 }, |
44 | { 0 } | 44 | { 0 } |
45 | }; | 45 | }; |
46 | #define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) | 46 | #define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1) |
47 | 47 | ||
48 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; | 48 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; |
49 | 49 | ||
50 | /* Initialize MA chip interrupts. */ | 50 | /* Initialize MA chip interrupts. */ |
51 | void __init ma_init_irqs (void) | 51 | void __init ma_init_irqs (void) |
52 | { | 52 | { |
53 | v850e_intc_init_irq_types (irq_inits, hw_itypes); | 53 | v850e_intc_init_irq_types (irq_inits, hw_itypes); |
54 | } | 54 | } |
55 | 55 | ||
56 | /* Called before configuring an on-chip UART. */ | 56 | /* Called before configuring an on-chip UART. */ |
57 | void ma_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) | 57 | void ma_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) |
58 | { | 58 | { |
59 | /* We only know about the first two UART channels (though | 59 | /* We only know about the first two UART channels (though |
60 | specific chips may have more). */ | 60 | specific chips may have more). */ |
61 | if (chan < 2) { | 61 | if (chan < 2) { |
62 | unsigned bits = 0x3 << (chan * 3); | 62 | unsigned bits = 0x3 << (chan * 3); |
63 | /* Specify that the relevant pins on the chip should do | 63 | /* Specify that the relevant pins on the chip should do |
64 | serial I/O, not direct I/O. */ | 64 | serial I/O, not direct I/O. */ |
65 | MA_PORT4_PMC |= bits; | 65 | MA_PORT4_PMC |= bits; |
66 | /* Specify that we're using the UART, not the CSI device. */ | 66 | /* Specify that we're using the UART, not the CSI device. */ |
67 | MA_PORT4_PFC |= bits; | 67 | MA_PORT4_PFC |= bits; |
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 |
arch/v850/kernel/me2.c
1 | /* | 1 | /* |
2 | * arch/v850/kernel/me2.c -- V850E/ME2 chip-specific support | 2 | * arch/v850/kernel/me2.c -- V850E/ME2 chip-specific support |
3 | * | 3 | * |
4 | * Copyright (C) 2003 NEC Corporation | 4 | * Copyright (C) 2003 NEC Corporation |
5 | * Copyright (C) 2003 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2003 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/swap.h> | 17 | #include <linux/swap.h> |
18 | #include <linux/bootmem.h> | 18 | #include <linux/bootmem.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | 20 | ||
21 | #include <asm/atomic.h> | 21 | #include <asm/atomic.h> |
22 | #include <asm/page.h> | 22 | #include <asm/page.h> |
23 | #include <asm/machdep.h> | 23 | #include <asm/machdep.h> |
24 | #include <asm/v850e_timer_d.h> | 24 | #include <asm/v850e_timer_d.h> |
25 | 25 | ||
26 | #include "mach.h" | 26 | #include "mach.h" |
27 | 27 | ||
28 | void __init mach_sched_init (struct irqaction *timer_action) | 28 | void __init mach_sched_init (struct irqaction *timer_action) |
29 | { | 29 | { |
30 | /* Start hardware timer. */ | 30 | /* Start hardware timer. */ |
31 | v850e_timer_d_configure (0, HZ); | 31 | v850e_timer_d_configure (0, HZ); |
32 | /* Install timer interrupt handler. */ | 32 | /* Install timer interrupt handler. */ |
33 | setup_irq (IRQ_INTCMD(0), timer_action); | 33 | setup_irq (IRQ_INTCMD(0), timer_action); |
34 | } | 34 | } |
35 | 35 | ||
36 | static struct v850e_intc_irq_init irq_inits[] = { | 36 | static struct v850e_intc_irq_init irq_inits[] = { |
37 | { "IRQ", 0, NUM_CPU_IRQS, 1, 7 }, | 37 | { "IRQ", 0, NUM_CPU_IRQS, 1, 7 }, |
38 | { "INTP", IRQ_INTP(0), IRQ_INTP_NUM, 1, 5 }, | 38 | { "INTP", IRQ_INTP(0), IRQ_INTP_NUM, 1, 5 }, |
39 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 3 }, | 39 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 3 }, |
40 | { "UBTIRE", IRQ_INTUBTIRE(0), IRQ_INTUBTIRE_NUM, 5, 4 }, | 40 | { "UBTIRE", IRQ_INTUBTIRE(0), IRQ_INTUBTIRE_NUM, 5, 4 }, |
41 | { "UBTIR", IRQ_INTUBTIR(0), IRQ_INTUBTIR_NUM, 5, 4 }, | 41 | { "UBTIR", IRQ_INTUBTIR(0), IRQ_INTUBTIR_NUM, 5, 4 }, |
42 | { "UBTIT", IRQ_INTUBTIT(0), IRQ_INTUBTIT_NUM, 5, 4 }, | 42 | { "UBTIT", IRQ_INTUBTIT(0), IRQ_INTUBTIT_NUM, 5, 4 }, |
43 | { "UBTIF", IRQ_INTUBTIF(0), IRQ_INTUBTIF_NUM, 5, 4 }, | 43 | { "UBTIF", IRQ_INTUBTIF(0), IRQ_INTUBTIF_NUM, 5, 4 }, |
44 | { "UBTITO", IRQ_INTUBTITO(0), IRQ_INTUBTITO_NUM, 5, 4 }, | 44 | { "UBTITO", IRQ_INTUBTITO(0), IRQ_INTUBTITO_NUM, 5, 4 }, |
45 | { 0 } | 45 | { 0 } |
46 | }; | 46 | }; |
47 | #define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) | 47 | #define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1) |
48 | 48 | ||
49 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; | 49 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; |
50 | 50 | ||
51 | /* Initialize V850E/ME2 chip interrupts. */ | 51 | /* Initialize V850E/ME2 chip interrupts. */ |
52 | void __init me2_init_irqs (void) | 52 | void __init me2_init_irqs (void) |
53 | { | 53 | { |
54 | v850e_intc_init_irq_types (irq_inits, hw_itypes); | 54 | v850e_intc_init_irq_types (irq_inits, hw_itypes); |
55 | } | 55 | } |
56 | 56 | ||
57 | /* Called before configuring an on-chip UART. */ | 57 | /* Called before configuring an on-chip UART. */ |
58 | void me2_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) | 58 | void me2_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) |
59 | { | 59 | { |
60 | if (chan == 0) { | 60 | if (chan == 0) { |
61 | /* Specify that the relevent pins on the chip should do | 61 | /* Specify that the relevent pins on the chip should do |
62 | serial I/O, not direct I/O. */ | 62 | serial I/O, not direct I/O. */ |
63 | ME2_PORT1_PMC |= 0xC; | 63 | ME2_PORT1_PMC |= 0xC; |
64 | /* Specify that we're using the UART, not the CSI device. */ | 64 | /* Specify that we're using the UART, not the CSI device. */ |
65 | ME2_PORT1_PFC |= 0xC; | 65 | ME2_PORT1_PFC |= 0xC; |
66 | } else if (chan == 1) { | 66 | } else if (chan == 1) { |
67 | /* Specify that the relevent pins on the chip should do | 67 | /* Specify that the relevent pins on the chip should do |
68 | serial I/O, not direct I/O. */ | 68 | serial I/O, not direct I/O. */ |
69 | ME2_PORT2_PMC |= 0x6; | 69 | ME2_PORT2_PMC |= 0x6; |
70 | /* Specify that we're using the UART, not the CSI device. */ | 70 | /* Specify that we're using the UART, not the CSI device. */ |
71 | ME2_PORT2_PFC |= 0x6; | 71 | ME2_PORT2_PFC |= 0x6; |
72 | } | 72 | } |
73 | } | 73 | } |
74 | 74 |
arch/v850/kernel/rte_cb.c
1 | /* | 1 | /* |
2 | * include/asm-v850/rte_cb.c -- Midas lab RTE-CB series of evaluation boards | 2 | * include/asm-v850/rte_cb.c -- Midas lab RTE-CB series of evaluation boards |
3 | * | 3 | * |
4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation | 4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation |
5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/kernel.h> | ||
18 | 19 | ||
19 | #include <asm/machdep.h> | 20 | #include <asm/machdep.h> |
20 | #include <asm/v850e_uart.h> | 21 | #include <asm/v850e_uart.h> |
21 | 22 | ||
22 | #include "mach.h" | 23 | #include "mach.h" |
23 | 24 | ||
24 | static void led_tick (void); | 25 | static void led_tick (void); |
25 | 26 | ||
26 | /* LED access routines. */ | 27 | /* LED access routines. */ |
27 | extern unsigned read_leds (int pos, char *buf, int len); | 28 | extern unsigned read_leds (int pos, char *buf, int len); |
28 | extern unsigned write_leds (int pos, const char *buf, int len); | 29 | extern unsigned write_leds (int pos, const char *buf, int len); |
29 | 30 | ||
30 | #ifdef CONFIG_RTE_CB_MULTI | 31 | #ifdef CONFIG_RTE_CB_MULTI |
31 | extern void multi_init (void); | 32 | extern void multi_init (void); |
32 | #endif | 33 | #endif |
33 | 34 | ||
34 | 35 | ||
35 | void __init rte_cb_early_init (void) | 36 | void __init rte_cb_early_init (void) |
36 | { | 37 | { |
37 | v850e_intc_disable_irqs (); | 38 | v850e_intc_disable_irqs (); |
38 | 39 | ||
39 | #ifdef CONFIG_RTE_CB_MULTI | 40 | #ifdef CONFIG_RTE_CB_MULTI |
40 | multi_init (); | 41 | multi_init (); |
41 | #endif | 42 | #endif |
42 | } | 43 | } |
43 | 44 | ||
44 | void __init mach_setup (char **cmdline) | 45 | void __init mach_setup (char **cmdline) |
45 | { | 46 | { |
46 | #ifdef CONFIG_RTE_MB_A_PCI | 47 | #ifdef CONFIG_RTE_MB_A_PCI |
47 | /* Probe for Mother-A, and print a message if we find it. */ | 48 | /* Probe for Mother-A, and print a message if we find it. */ |
48 | *(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF; | 49 | *(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF; |
49 | if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) { | 50 | if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) { |
50 | *(volatile unsigned long *)MB_A_SRAM_ADDR = 0x12345678; | 51 | *(volatile unsigned long *)MB_A_SRAM_ADDR = 0x12345678; |
51 | if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0x12345678) | 52 | if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0x12345678) |
52 | printk (KERN_INFO | 53 | printk (KERN_INFO |
53 | " NEC SolutionGear/Midas lab" | 54 | " NEC SolutionGear/Midas lab" |
54 | " RTE-MOTHER-A motherboard\n"); | 55 | " RTE-MOTHER-A motherboard\n"); |
55 | } | 56 | } |
56 | #endif /* CONFIG_RTE_MB_A_PCI */ | 57 | #endif /* CONFIG_RTE_MB_A_PCI */ |
57 | 58 | ||
58 | mach_tick = led_tick; | 59 | mach_tick = led_tick; |
59 | } | 60 | } |
60 | 61 | ||
61 | void machine_restart (char *__unused) | 62 | void machine_restart (char *__unused) |
62 | { | 63 | { |
63 | #ifdef CONFIG_RESET_GUARD | 64 | #ifdef CONFIG_RESET_GUARD |
64 | disable_reset_guard (); | 65 | disable_reset_guard (); |
65 | #endif | 66 | #endif |
66 | asm ("jmp r0"); /* Jump to the reset vector. */ | 67 | asm ("jmp r0"); /* Jump to the reset vector. */ |
67 | } | 68 | } |
68 | 69 | ||
69 | /* This says `HALt.' in LEDese. */ | 70 | /* This says `HALt.' in LEDese. */ |
70 | static unsigned char halt_leds_msg[] = { 0x76, 0x77, 0x38, 0xF8 }; | 71 | static unsigned char halt_leds_msg[] = { 0x76, 0x77, 0x38, 0xF8 }; |
71 | 72 | ||
72 | void machine_halt (void) | 73 | void machine_halt (void) |
73 | { | 74 | { |
74 | #ifdef CONFIG_RESET_GUARD | 75 | #ifdef CONFIG_RESET_GUARD |
75 | disable_reset_guard (); | 76 | disable_reset_guard (); |
76 | #endif | 77 | #endif |
77 | 78 | ||
78 | /* Ignore all interrupts. */ | 79 | /* Ignore all interrupts. */ |
79 | local_irq_disable (); | 80 | local_irq_disable (); |
80 | 81 | ||
81 | /* Write a little message. */ | 82 | /* Write a little message. */ |
82 | write_leds (0, halt_leds_msg, sizeof halt_leds_msg); | 83 | write_leds (0, halt_leds_msg, sizeof halt_leds_msg); |
83 | 84 | ||
84 | /* Really halt. */ | 85 | /* Really halt. */ |
85 | for (;;) | 86 | for (;;) |
86 | asm ("halt; nop; nop; nop; nop; nop"); | 87 | asm ("halt; nop; nop; nop; nop; nop"); |
87 | } | 88 | } |
88 | 89 | ||
89 | void machine_power_off (void) | 90 | void machine_power_off (void) |
90 | { | 91 | { |
91 | machine_halt (); | 92 | machine_halt (); |
92 | } | 93 | } |
93 | 94 | ||
94 | 95 | ||
95 | /* Animated LED display for timer tick. */ | 96 | /* Animated LED display for timer tick. */ |
96 | 97 | ||
97 | #define TICK_UPD_FREQ 6 | 98 | #define TICK_UPD_FREQ 6 |
98 | static int tick_frames[][10] = { | 99 | static int tick_frames[][10] = { |
99 | { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, -1 }, | 100 | { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, -1 }, |
100 | { 0x63, 0x5c, -1 }, | 101 | { 0x63, 0x5c, -1 }, |
101 | { 0x5c, 0x00, -1 }, | 102 | { 0x5c, 0x00, -1 }, |
102 | { 0x63, 0x00, -1 }, | 103 | { 0x63, 0x00, -1 }, |
103 | { -1 } | 104 | { -1 } |
104 | }; | 105 | }; |
105 | 106 | ||
106 | static void led_tick () | 107 | static void led_tick () |
107 | { | 108 | { |
108 | static unsigned counter = 0; | 109 | static unsigned counter = 0; |
109 | 110 | ||
110 | if (++counter == (HZ / TICK_UPD_FREQ)) { | 111 | if (++counter == (HZ / TICK_UPD_FREQ)) { |
111 | /* Which frame we're currently displaying for each digit. */ | 112 | /* Which frame we're currently displaying for each digit. */ |
112 | static unsigned frame_nums[LED_NUM_DIGITS] = { 0 }; | 113 | static unsigned frame_nums[LED_NUM_DIGITS] = { 0 }; |
113 | /* Display image. */ | 114 | /* Display image. */ |
114 | static unsigned char image[LED_NUM_DIGITS] = { 0 }; | 115 | static unsigned char image[LED_NUM_DIGITS] = { 0 }; |
115 | unsigned char prev_image[LED_NUM_DIGITS]; | 116 | unsigned char prev_image[LED_NUM_DIGITS]; |
116 | int write_to_leds = 1; /* true if we should actually display */ | 117 | int write_to_leds = 1; /* true if we should actually display */ |
117 | int digit; | 118 | int digit; |
118 | 119 | ||
119 | /* We check to see if the physical LEDs contains what we last | 120 | /* We check to see if the physical LEDs contains what we last |
120 | wrote to them; if not, we suppress display (this is so that | 121 | wrote to them; if not, we suppress display (this is so that |
121 | users can write to the LEDs, and not have their output | 122 | users can write to the LEDs, and not have their output |
122 | overwritten). As a special case, we start writing again if | 123 | overwritten). As a special case, we start writing again if |
123 | all the LEDs are blank, or our display image is all zeros | 124 | all the LEDs are blank, or our display image is all zeros |
124 | (indicating that this is the initial update, when the actual | 125 | (indicating that this is the initial update, when the actual |
125 | LEDs might contain random data). */ | 126 | LEDs might contain random data). */ |
126 | read_leds (0, prev_image, LED_NUM_DIGITS); | 127 | read_leds (0, prev_image, LED_NUM_DIGITS); |
127 | for (digit = 0; digit < LED_NUM_DIGITS; digit++) | 128 | for (digit = 0; digit < LED_NUM_DIGITS; digit++) |
128 | if (image[digit] != prev_image[digit] | 129 | if (image[digit] != prev_image[digit] |
129 | && image[digit] && prev_image[digit]) | 130 | && image[digit] && prev_image[digit]) |
130 | { | 131 | { |
131 | write_to_leds = 0; | 132 | write_to_leds = 0; |
132 | break; | 133 | break; |
133 | } | 134 | } |
134 | 135 | ||
135 | /* Update display image. */ | 136 | /* Update display image. */ |
136 | for (digit = 0; | 137 | for (digit = 0; |
137 | digit < LED_NUM_DIGITS && tick_frames[digit][0] >= 0; | 138 | digit < LED_NUM_DIGITS && tick_frames[digit][0] >= 0; |
138 | digit++) | 139 | digit++) |
139 | { | 140 | { |
140 | int frame = tick_frames[digit][frame_nums[digit]]; | 141 | int frame = tick_frames[digit][frame_nums[digit]]; |
141 | if (frame < 0) { | 142 | if (frame < 0) { |
142 | image[digit] = tick_frames[digit][0]; | 143 | image[digit] = tick_frames[digit][0]; |
143 | frame_nums[digit] = 1; | 144 | frame_nums[digit] = 1; |
144 | } else { | 145 | } else { |
145 | image[digit] = frame; | 146 | image[digit] = frame; |
146 | frame_nums[digit]++; | 147 | frame_nums[digit]++; |
147 | break; | 148 | break; |
148 | } | 149 | } |
149 | } | 150 | } |
150 | 151 | ||
151 | if (write_to_leds) | 152 | if (write_to_leds) |
152 | /* Write the display image to the physical LEDs. */ | 153 | /* Write the display image to the physical LEDs. */ |
153 | write_leds (0, image, LED_NUM_DIGITS); | 154 | write_leds (0, image, LED_NUM_DIGITS); |
154 | 155 | ||
155 | counter = 0; | 156 | counter = 0; |
156 | } | 157 | } |
157 | } | 158 | } |
158 | 159 | ||
159 | 160 | ||
160 | /* Mother-A interrupts. */ | 161 | /* Mother-A interrupts. */ |
161 | 162 | ||
162 | #ifdef CONFIG_RTE_GBUS_INT | 163 | #ifdef CONFIG_RTE_GBUS_INT |
163 | 164 | ||
164 | #define L GBUS_INT_PRIORITY_LOW | 165 | #define L GBUS_INT_PRIORITY_LOW |
165 | #define M GBUS_INT_PRIORITY_MEDIUM | 166 | #define M GBUS_INT_PRIORITY_MEDIUM |
166 | #define H GBUS_INT_PRIORITY_HIGH | 167 | #define H GBUS_INT_PRIORITY_HIGH |
167 | 168 | ||
168 | static struct gbus_int_irq_init gbus_irq_inits[] = { | 169 | static struct gbus_int_irq_init gbus_irq_inits[] = { |
169 | #ifdef CONFIG_RTE_MB_A_PCI | 170 | #ifdef CONFIG_RTE_MB_A_PCI |
170 | { "MB_A_LAN", IRQ_MB_A_LAN, 1, 1, L }, | 171 | { "MB_A_LAN", IRQ_MB_A_LAN, 1, 1, L }, |
171 | { "MB_A_PCI1", IRQ_MB_A_PCI1(0), IRQ_MB_A_PCI1_NUM, 1, L }, | 172 | { "MB_A_PCI1", IRQ_MB_A_PCI1(0), IRQ_MB_A_PCI1_NUM, 1, L }, |
172 | { "MB_A_PCI2", IRQ_MB_A_PCI2(0), IRQ_MB_A_PCI2_NUM, 1, L }, | 173 | { "MB_A_PCI2", IRQ_MB_A_PCI2(0), IRQ_MB_A_PCI2_NUM, 1, L }, |
173 | { "MB_A_EXT", IRQ_MB_A_EXT(0), IRQ_MB_A_EXT_NUM, 1, L }, | 174 | { "MB_A_EXT", IRQ_MB_A_EXT(0), IRQ_MB_A_EXT_NUM, 1, L }, |
174 | { "MB_A_USB_OC",IRQ_MB_A_USB_OC(0), IRQ_MB_A_USB_OC_NUM, 1, L }, | 175 | { "MB_A_USB_OC",IRQ_MB_A_USB_OC(0), IRQ_MB_A_USB_OC_NUM, 1, L }, |
175 | { "MB_A_PCMCIA_OC",IRQ_MB_A_PCMCIA_OC, 1, 1, L }, | 176 | { "MB_A_PCMCIA_OC",IRQ_MB_A_PCMCIA_OC, 1, 1, L }, |
176 | #endif | 177 | #endif |
177 | { 0 } | 178 | { 0 } |
178 | }; | 179 | }; |
179 | #define NUM_GBUS_IRQ_INITS \ | 180 | #define NUM_GBUS_IRQ_INITS (ARRAY_SIZE(gbus_irq_inits) - 1) |
180 | ((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1) | ||
181 | 181 | ||
182 | static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS]; | 182 | static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS]; |
183 | 183 | ||
184 | #endif /* CONFIG_RTE_GBUS_INT */ | 184 | #endif /* CONFIG_RTE_GBUS_INT */ |
185 | 185 | ||
186 | 186 | ||
187 | void __init rte_cb_init_irqs (void) | 187 | void __init rte_cb_init_irqs (void) |
188 | { | 188 | { |
189 | #ifdef CONFIG_RTE_GBUS_INT | 189 | #ifdef CONFIG_RTE_GBUS_INT |
190 | gbus_int_init_irqs (); | 190 | gbus_int_init_irqs (); |
191 | gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes); | 191 | gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes); |
192 | #endif /* CONFIG_RTE_GBUS_INT */ | 192 | #endif /* CONFIG_RTE_GBUS_INT */ |
193 | } | 193 | } |
arch/v850/kernel/rte_mb_a_pci.c
1 | /* | 1 | /* |
2 | * arch/v850/kernel/mb_a_pci.c -- PCI support for Midas lab RTE-MOTHER-A board | 2 | * arch/v850/kernel/mb_a_pci.c -- PCI support for Midas lab RTE-MOTHER-A board |
3 | * | 3 | * |
4 | * Copyright (C) 2001,02,03,05 NEC Electronics Corporation | 4 | * Copyright (C) 2001,02,03,05 NEC Electronics Corporation |
5 | * Copyright (C) 2001,02,03,05 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2001,02,03,05 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
19 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
20 | 20 | ||
21 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
22 | 22 | ||
23 | /* __nomods_init is like __devinit, but is a no-op when modules are enabled. | 23 | /* __nomods_init is like __devinit, but is a no-op when modules are enabled. |
24 | This is used by some routines that can be called either during boot | 24 | This is used by some routines that can be called either during boot |
25 | or by a module. */ | 25 | or by a module. */ |
26 | #ifdef CONFIG_MODULES | 26 | #ifdef CONFIG_MODULES |
27 | #define __nomods_init /*nothing*/ | 27 | #define __nomods_init /*nothing*/ |
28 | #else | 28 | #else |
29 | #define __nomods_init __devinit | 29 | #define __nomods_init __devinit |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | /* PCI devices on the Mother-A board can only do DMA to/from the MB SRAM | 32 | /* PCI devices on the Mother-A board can only do DMA to/from the MB SRAM |
33 | (the RTE-V850E/MA1-CB cpu board doesn't support PCI access to | 33 | (the RTE-V850E/MA1-CB cpu board doesn't support PCI access to |
34 | CPU-board memory), and since linux DMA buffers are allocated in | 34 | CPU-board memory), and since linux DMA buffers are allocated in |
35 | normal kernel memory, we basically have to copy DMA blocks around | 35 | normal kernel memory, we basically have to copy DMA blocks around |
36 | (this is like a `bounce buffer'). When a DMA block is `mapped', we | 36 | (this is like a `bounce buffer'). When a DMA block is `mapped', we |
37 | allocate an identically sized block in MB SRAM, and if we're doing | 37 | allocate an identically sized block in MB SRAM, and if we're doing |
38 | output to the device, copy the CPU-memory block to the MB-SRAM block. | 38 | output to the device, copy the CPU-memory block to the MB-SRAM block. |
39 | When an active block is `unmapped', we will copy the block back to | 39 | When an active block is `unmapped', we will copy the block back to |
40 | CPU memory if necessary, and then deallocate the MB SRAM block. | 40 | CPU memory if necessary, and then deallocate the MB SRAM block. |
41 | Ack. */ | 41 | Ack. */ |
42 | 42 | ||
43 | /* Where the motherboard SRAM is in the PCI-bus address space (the | 43 | /* Where the motherboard SRAM is in the PCI-bus address space (the |
44 | first 512K of it is also mapped at PCI address 0). */ | 44 | first 512K of it is also mapped at PCI address 0). */ |
45 | #define PCI_MB_SRAM_ADDR 0x800000 | 45 | #define PCI_MB_SRAM_ADDR 0x800000 |
46 | 46 | ||
47 | /* Convert CPU-view MB SRAM address to/from PCI-view addresses of the | 47 | /* Convert CPU-view MB SRAM address to/from PCI-view addresses of the |
48 | same memory. */ | 48 | same memory. */ |
49 | #define MB_SRAM_TO_PCI(mb_sram_addr) \ | 49 | #define MB_SRAM_TO_PCI(mb_sram_addr) \ |
50 | ((dma_addr_t)mb_sram_addr - MB_A_SRAM_ADDR + PCI_MB_SRAM_ADDR) | 50 | ((dma_addr_t)mb_sram_addr - MB_A_SRAM_ADDR + PCI_MB_SRAM_ADDR) |
51 | #define PCI_TO_MB_SRAM(pci_addr) \ | 51 | #define PCI_TO_MB_SRAM(pci_addr) \ |
52 | (void *)(pci_addr - PCI_MB_SRAM_ADDR + MB_A_SRAM_ADDR) | 52 | (void *)(pci_addr - PCI_MB_SRAM_ADDR + MB_A_SRAM_ADDR) |
53 | 53 | ||
54 | static void pcibios_assign_resources (void); | 54 | static void pcibios_assign_resources (void); |
55 | 55 | ||
56 | struct mb_pci_dev_irq { | 56 | struct mb_pci_dev_irq { |
57 | unsigned dev; /* PCI device number */ | 57 | unsigned dev; /* PCI device number */ |
58 | unsigned irq_base; /* First IRQ */ | 58 | unsigned irq_base; /* First IRQ */ |
59 | unsigned query_pin; /* True if we should read the device's | 59 | unsigned query_pin; /* True if we should read the device's |
60 | Interrupt Pin info, and allocate | 60 | Interrupt Pin info, and allocate |
61 | interrupt IRQ_BASE + PIN. */ | 61 | interrupt IRQ_BASE + PIN. */ |
62 | }; | 62 | }; |
63 | 63 | ||
64 | /* PCI interrupts are mapped statically to GBUS interrupts. */ | 64 | /* PCI interrupts are mapped statically to GBUS interrupts. */ |
65 | static struct mb_pci_dev_irq mb_pci_dev_irqs[] = { | 65 | static struct mb_pci_dev_irq mb_pci_dev_irqs[] = { |
66 | /* Motherboard SB82558 ethernet controller */ | 66 | /* Motherboard SB82558 ethernet controller */ |
67 | { 10, IRQ_MB_A_LAN, 0 }, | 67 | { 10, IRQ_MB_A_LAN, 0 }, |
68 | /* PCI slot 1 */ | 68 | /* PCI slot 1 */ |
69 | { 8, IRQ_MB_A_PCI1(0), 1 }, | 69 | { 8, IRQ_MB_A_PCI1(0), 1 }, |
70 | /* PCI slot 2 */ | 70 | /* PCI slot 2 */ |
71 | { 9, IRQ_MB_A_PCI2(0), 1 } | 71 | { 9, IRQ_MB_A_PCI2(0), 1 } |
72 | }; | 72 | }; |
73 | #define NUM_MB_PCI_DEV_IRQS \ | 73 | #define NUM_MB_PCI_DEV_IRQS ARRAY_SIZE(mb_pci_dev_irqs) |
74 | (sizeof mb_pci_dev_irqs / sizeof mb_pci_dev_irqs[0]) | ||
75 | 74 | ||
76 | 75 | ||
77 | /* PCI configuration primitives. */ | 76 | /* PCI configuration primitives. */ |
78 | 77 | ||
79 | #define CONFIG_DMCFGA(bus, devfn, offs) \ | 78 | #define CONFIG_DMCFGA(bus, devfn, offs) \ |
80 | (0x80000000 \ | 79 | (0x80000000 \ |
81 | | ((offs) & ~0x3) \ | 80 | | ((offs) & ~0x3) \ |
82 | | ((devfn) << 8) \ | 81 | | ((devfn) << 8) \ |
83 | | ((bus)->number << 16)) | 82 | | ((bus)->number << 16)) |
84 | 83 | ||
85 | static int | 84 | static int |
86 | mb_pci_read (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 *rval) | 85 | mb_pci_read (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 *rval) |
87 | { | 86 | { |
88 | u32 addr; | 87 | u32 addr; |
89 | int flags; | 88 | int flags; |
90 | 89 | ||
91 | local_irq_save (flags); | 90 | local_irq_save (flags); |
92 | 91 | ||
93 | MB_A_PCI_PCICR = 0x7; | 92 | MB_A_PCI_PCICR = 0x7; |
94 | MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs); | 93 | MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs); |
95 | 94 | ||
96 | addr = MB_A_PCI_IO_ADDR + (offs & 0x3); | 95 | addr = MB_A_PCI_IO_ADDR + (offs & 0x3); |
97 | 96 | ||
98 | switch (size) { | 97 | switch (size) { |
99 | case 1: *rval = *(volatile u8 *)addr; break; | 98 | case 1: *rval = *(volatile u8 *)addr; break; |
100 | case 2: *rval = *(volatile u16 *)addr; break; | 99 | case 2: *rval = *(volatile u16 *)addr; break; |
101 | case 4: *rval = *(volatile u32 *)addr; break; | 100 | case 4: *rval = *(volatile u32 *)addr; break; |
102 | } | 101 | } |
103 | 102 | ||
104 | if (MB_A_PCI_PCISR & 0x2000) { | 103 | if (MB_A_PCI_PCISR & 0x2000) { |
105 | MB_A_PCI_PCISR = 0x2000; | 104 | MB_A_PCI_PCISR = 0x2000; |
106 | *rval = ~0; | 105 | *rval = ~0; |
107 | } | 106 | } |
108 | 107 | ||
109 | MB_A_PCI_DMCFGA = 0; | 108 | MB_A_PCI_DMCFGA = 0; |
110 | 109 | ||
111 | local_irq_restore (flags); | 110 | local_irq_restore (flags); |
112 | 111 | ||
113 | return PCIBIOS_SUCCESSFUL; | 112 | return PCIBIOS_SUCCESSFUL; |
114 | } | 113 | } |
115 | 114 | ||
116 | static int | 115 | static int |
117 | mb_pci_write (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 val) | 116 | mb_pci_write (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 val) |
118 | { | 117 | { |
119 | u32 addr; | 118 | u32 addr; |
120 | int flags; | 119 | int flags; |
121 | 120 | ||
122 | local_irq_save (flags); | 121 | local_irq_save (flags); |
123 | 122 | ||
124 | MB_A_PCI_PCICR = 0x7; | 123 | MB_A_PCI_PCICR = 0x7; |
125 | MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs); | 124 | MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs); |
126 | 125 | ||
127 | addr = MB_A_PCI_IO_ADDR + (offs & 0x3); | 126 | addr = MB_A_PCI_IO_ADDR + (offs & 0x3); |
128 | 127 | ||
129 | switch (size) { | 128 | switch (size) { |
130 | case 1: *(volatile u8 *)addr = val; break; | 129 | case 1: *(volatile u8 *)addr = val; break; |
131 | case 2: *(volatile u16 *)addr = val; break; | 130 | case 2: *(volatile u16 *)addr = val; break; |
132 | case 4: *(volatile u32 *)addr = val; break; | 131 | case 4: *(volatile u32 *)addr = val; break; |
133 | } | 132 | } |
134 | 133 | ||
135 | if (MB_A_PCI_PCISR & 0x2000) | 134 | if (MB_A_PCI_PCISR & 0x2000) |
136 | MB_A_PCI_PCISR = 0x2000; | 135 | MB_A_PCI_PCISR = 0x2000; |
137 | 136 | ||
138 | MB_A_PCI_DMCFGA = 0; | 137 | MB_A_PCI_DMCFGA = 0; |
139 | 138 | ||
140 | local_irq_restore (flags); | 139 | local_irq_restore (flags); |
141 | 140 | ||
142 | return PCIBIOS_SUCCESSFUL; | 141 | return PCIBIOS_SUCCESSFUL; |
143 | } | 142 | } |
144 | 143 | ||
145 | static struct pci_ops mb_pci_config_ops = { | 144 | static struct pci_ops mb_pci_config_ops = { |
146 | .read = mb_pci_read, | 145 | .read = mb_pci_read, |
147 | .write = mb_pci_write, | 146 | .write = mb_pci_write, |
148 | }; | 147 | }; |
149 | 148 | ||
150 | 149 | ||
151 | /* PCI Initialization. */ | 150 | /* PCI Initialization. */ |
152 | 151 | ||
153 | static struct pci_bus *mb_pci_bus = 0; | 152 | static struct pci_bus *mb_pci_bus = 0; |
154 | 153 | ||
155 | /* Do initial PCI setup. */ | 154 | /* Do initial PCI setup. */ |
156 | static int __devinit pcibios_init (void) | 155 | static int __devinit pcibios_init (void) |
157 | { | 156 | { |
158 | u32 id = MB_A_PCI_PCIHIDR; | 157 | u32 id = MB_A_PCI_PCIHIDR; |
159 | u16 vendor = id & 0xFFFF; | 158 | u16 vendor = id & 0xFFFF; |
160 | u16 device = (id >> 16) & 0xFFFF; | 159 | u16 device = (id >> 16) & 0xFFFF; |
161 | 160 | ||
162 | if (vendor == PCI_VENDOR_ID_PLX && device == PCI_DEVICE_ID_PLX_9080) { | 161 | if (vendor == PCI_VENDOR_ID_PLX && device == PCI_DEVICE_ID_PLX_9080) { |
163 | printk (KERN_INFO | 162 | printk (KERN_INFO |
164 | "PCI: PLX Technology PCI9080 HOST/PCI bridge\n"); | 163 | "PCI: PLX Technology PCI9080 HOST/PCI bridge\n"); |
165 | 164 | ||
166 | MB_A_PCI_PCICR = 0x147; | 165 | MB_A_PCI_PCICR = 0x147; |
167 | 166 | ||
168 | MB_A_PCI_PCIBAR0 = 0x007FFF00; | 167 | MB_A_PCI_PCIBAR0 = 0x007FFF00; |
169 | MB_A_PCI_PCIBAR1 = 0x0000FF00; | 168 | MB_A_PCI_PCIBAR1 = 0x0000FF00; |
170 | MB_A_PCI_PCIBAR2 = 0x00800000; | 169 | MB_A_PCI_PCIBAR2 = 0x00800000; |
171 | 170 | ||
172 | MB_A_PCI_PCILTR = 0x20; | 171 | MB_A_PCI_PCILTR = 0x20; |
173 | 172 | ||
174 | MB_A_PCI_PCIPBAM |= 0x3; | 173 | MB_A_PCI_PCIPBAM |= 0x3; |
175 | 174 | ||
176 | MB_A_PCI_PCISR = ~0; /* Clear errors. */ | 175 | MB_A_PCI_PCISR = ~0; /* Clear errors. */ |
177 | 176 | ||
178 | /* Reprogram the motherboard's IO/config address space, | 177 | /* Reprogram the motherboard's IO/config address space, |
179 | as we don't support the GCS7 address space that the | 178 | as we don't support the GCS7 address space that the |
180 | default uses. */ | 179 | default uses. */ |
181 | 180 | ||
182 | /* Significant address bits used for decoding PCI GCS5 space | 181 | /* Significant address bits used for decoding PCI GCS5 space |
183 | accessess. */ | 182 | accessess. */ |
184 | MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1); | 183 | MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1); |
185 | 184 | ||
186 | /* I don't understand this, but the SolutionGear example code | 185 | /* I don't understand this, but the SolutionGear example code |
187 | uses such an offset, and it doesn't work without it. XXX */ | 186 | uses such an offset, and it doesn't work without it. XXX */ |
188 | #if GCS5_SIZE == 0x00800000 | 187 | #if GCS5_SIZE == 0x00800000 |
189 | #define GCS5_CFG_OFFS 0x00800000 | 188 | #define GCS5_CFG_OFFS 0x00800000 |
190 | #else | 189 | #else |
191 | #define GCS5_CFG_OFFS 0 | 190 | #define GCS5_CFG_OFFS 0 |
192 | #endif | 191 | #endif |
193 | 192 | ||
194 | /* Address bit values for matching. Note that we have to give | 193 | /* Address bit values for matching. Note that we have to give |
195 | the address from the motherboard's point of view, which is | 194 | the address from the motherboard's point of view, which is |
196 | different than the CPU's. */ | 195 | different than the CPU's. */ |
197 | /* PCI memory space. */ | 196 | /* PCI memory space. */ |
198 | MB_A_PCI_DMLBAM = GCS5_CFG_OFFS + 0x0; | 197 | MB_A_PCI_DMLBAM = GCS5_CFG_OFFS + 0x0; |
199 | /* PCI I/O space. */ | 198 | /* PCI I/O space. */ |
200 | MB_A_PCI_DMLBAI = | 199 | MB_A_PCI_DMLBAI = |
201 | GCS5_CFG_OFFS + (MB_A_PCI_IO_ADDR - GCS5_ADDR); | 200 | GCS5_CFG_OFFS + (MB_A_PCI_IO_ADDR - GCS5_ADDR); |
202 | 201 | ||
203 | mb_pci_bus = pci_scan_bus (0, &mb_pci_config_ops, 0); | 202 | mb_pci_bus = pci_scan_bus (0, &mb_pci_config_ops, 0); |
204 | 203 | ||
205 | pcibios_assign_resources (); | 204 | pcibios_assign_resources (); |
206 | } else | 205 | } else |
207 | printk (KERN_ERR "PCI: HOST/PCI bridge not found\n"); | 206 | printk (KERN_ERR "PCI: HOST/PCI bridge not found\n"); |
208 | 207 | ||
209 | return 0; | 208 | return 0; |
210 | } | 209 | } |
211 | 210 | ||
212 | subsys_initcall (pcibios_init); | 211 | subsys_initcall (pcibios_init); |
213 | 212 | ||
214 | char __devinit *pcibios_setup (char *option) | 213 | char __devinit *pcibios_setup (char *option) |
215 | { | 214 | { |
216 | /* Don't handle any options. */ | 215 | /* Don't handle any options. */ |
217 | return option; | 216 | return option; |
218 | } | 217 | } |
219 | 218 | ||
220 | 219 | ||
221 | int __nomods_init pcibios_enable_device (struct pci_dev *dev, int mask) | 220 | int __nomods_init pcibios_enable_device (struct pci_dev *dev, int mask) |
222 | { | 221 | { |
223 | u16 cmd, old_cmd; | 222 | u16 cmd, old_cmd; |
224 | int idx; | 223 | int idx; |
225 | struct resource *r; | 224 | struct resource *r; |
226 | 225 | ||
227 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | 226 | pci_read_config_word(dev, PCI_COMMAND, &cmd); |
228 | old_cmd = cmd; | 227 | old_cmd = cmd; |
229 | for (idx = 0; idx < 6; idx++) { | 228 | for (idx = 0; idx < 6; idx++) { |
230 | r = &dev->resource[idx]; | 229 | r = &dev->resource[idx]; |
231 | if (!r->start && r->end) { | 230 | if (!r->start && r->end) { |
232 | printk(KERN_ERR "PCI: Device %s not available because " | 231 | printk(KERN_ERR "PCI: Device %s not available because " |
233 | "of resource collisions\n", pci_name(dev)); | 232 | "of resource collisions\n", pci_name(dev)); |
234 | return -EINVAL; | 233 | return -EINVAL; |
235 | } | 234 | } |
236 | if (r->flags & IORESOURCE_IO) | 235 | if (r->flags & IORESOURCE_IO) |
237 | cmd |= PCI_COMMAND_IO; | 236 | cmd |= PCI_COMMAND_IO; |
238 | if (r->flags & IORESOURCE_MEM) | 237 | if (r->flags & IORESOURCE_MEM) |
239 | cmd |= PCI_COMMAND_MEMORY; | 238 | cmd |= PCI_COMMAND_MEMORY; |
240 | } | 239 | } |
241 | if (cmd != old_cmd) { | 240 | if (cmd != old_cmd) { |
242 | printk("PCI: Enabling device %s (%04x -> %04x)\n", | 241 | printk("PCI: Enabling device %s (%04x -> %04x)\n", |
243 | pci_name(dev), old_cmd, cmd); | 242 | pci_name(dev), old_cmd, cmd); |
244 | pci_write_config_word(dev, PCI_COMMAND, cmd); | 243 | pci_write_config_word(dev, PCI_COMMAND, cmd); |
245 | } | 244 | } |
246 | return 0; | 245 | return 0; |
247 | } | 246 | } |
248 | 247 | ||
249 | 248 | ||
250 | /* Resource allocation. */ | 249 | /* Resource allocation. */ |
251 | static void __devinit pcibios_assign_resources (void) | 250 | static void __devinit pcibios_assign_resources (void) |
252 | { | 251 | { |
253 | struct pci_dev *dev = NULL; | 252 | struct pci_dev *dev = NULL; |
254 | struct resource *r; | 253 | struct resource *r; |
255 | 254 | ||
256 | for_each_pci_dev(dev) { | 255 | for_each_pci_dev(dev) { |
257 | unsigned di_num; | 256 | unsigned di_num; |
258 | unsigned class = dev->class >> 8; | 257 | unsigned class = dev->class >> 8; |
259 | 258 | ||
260 | if (class && class != PCI_CLASS_BRIDGE_HOST) { | 259 | if (class && class != PCI_CLASS_BRIDGE_HOST) { |
261 | unsigned r_num; | 260 | unsigned r_num; |
262 | for(r_num = 0; r_num < 6; r_num++) { | 261 | for(r_num = 0; r_num < 6; r_num++) { |
263 | r = &dev->resource[r_num]; | 262 | r = &dev->resource[r_num]; |
264 | if (!r->start && r->end) | 263 | if (!r->start && r->end) |
265 | pci_assign_resource (dev, r_num); | 264 | pci_assign_resource (dev, r_num); |
266 | } | 265 | } |
267 | } | 266 | } |
268 | 267 | ||
269 | /* Assign interrupts. */ | 268 | /* Assign interrupts. */ |
270 | for (di_num = 0; di_num < NUM_MB_PCI_DEV_IRQS; di_num++) { | 269 | for (di_num = 0; di_num < NUM_MB_PCI_DEV_IRQS; di_num++) { |
271 | struct mb_pci_dev_irq *di = &mb_pci_dev_irqs[di_num]; | 270 | struct mb_pci_dev_irq *di = &mb_pci_dev_irqs[di_num]; |
272 | 271 | ||
273 | if (di->dev == PCI_SLOT (dev->devfn)) { | 272 | if (di->dev == PCI_SLOT (dev->devfn)) { |
274 | unsigned irq = di->irq_base; | 273 | unsigned irq = di->irq_base; |
275 | 274 | ||
276 | if (di->query_pin) { | 275 | if (di->query_pin) { |
277 | /* Find out which interrupt pin | 276 | /* Find out which interrupt pin |
278 | this device uses (each PCI | 277 | this device uses (each PCI |
279 | slot has 4). */ | 278 | slot has 4). */ |
280 | u8 irq_pin; | 279 | u8 irq_pin; |
281 | 280 | ||
282 | pci_read_config_byte (dev, | 281 | pci_read_config_byte (dev, |
283 | PCI_INTERRUPT_PIN, | 282 | PCI_INTERRUPT_PIN, |
284 | &irq_pin); | 283 | &irq_pin); |
285 | 284 | ||
286 | if (irq_pin == 0) | 285 | if (irq_pin == 0) |
287 | /* Doesn't use interrupts. */ | 286 | /* Doesn't use interrupts. */ |
288 | continue; | 287 | continue; |
289 | else | 288 | else |
290 | irq += irq_pin - 1; | 289 | irq += irq_pin - 1; |
291 | } | 290 | } |
292 | 291 | ||
293 | pcibios_update_irq (dev, irq); | 292 | pcibios_update_irq (dev, irq); |
294 | } | 293 | } |
295 | } | 294 | } |
296 | } | 295 | } |
297 | } | 296 | } |
298 | 297 | ||
299 | void __devinit pcibios_update_irq (struct pci_dev *dev, int irq) | 298 | void __devinit pcibios_update_irq (struct pci_dev *dev, int irq) |
300 | { | 299 | { |
301 | dev->irq = irq; | 300 | dev->irq = irq; |
302 | pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); | 301 | pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); |
303 | } | 302 | } |
304 | 303 | ||
305 | void __devinit | 304 | void __devinit |
306 | pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | 305 | pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, |
307 | struct resource *res) | 306 | struct resource *res) |
308 | { | 307 | { |
309 | unsigned long offset = 0; | 308 | unsigned long offset = 0; |
310 | 309 | ||
311 | if (res->flags & IORESOURCE_IO) { | 310 | if (res->flags & IORESOURCE_IO) { |
312 | offset = MB_A_PCI_IO_ADDR; | 311 | offset = MB_A_PCI_IO_ADDR; |
313 | } else if (res->flags & IORESOURCE_MEM) { | 312 | } else if (res->flags & IORESOURCE_MEM) { |
314 | offset = MB_A_PCI_MEM_ADDR; | 313 | offset = MB_A_PCI_MEM_ADDR; |
315 | } | 314 | } |
316 | 315 | ||
317 | region->start = res->start - offset; | 316 | region->start = res->start - offset; |
318 | region->end = res->end - offset; | 317 | region->end = res->end - offset; |
319 | } | 318 | } |
320 | 319 | ||
321 | 320 | ||
322 | /* Stubs for things we don't use. */ | 321 | /* Stubs for things we don't use. */ |
323 | 322 | ||
324 | /* Called after each bus is probed, but before its children are examined. */ | 323 | /* Called after each bus is probed, but before its children are examined. */ |
325 | void pcibios_fixup_bus(struct pci_bus *b) | 324 | void pcibios_fixup_bus(struct pci_bus *b) |
326 | { | 325 | { |
327 | } | 326 | } |
328 | 327 | ||
329 | void | 328 | void |
330 | pcibios_align_resource (void *data, struct resource *res, | 329 | pcibios_align_resource (void *data, struct resource *res, |
331 | resource_size_t size, resource_size_t align) | 330 | resource_size_t size, resource_size_t align) |
332 | { | 331 | { |
333 | } | 332 | } |
334 | 333 | ||
335 | void pcibios_set_master (struct pci_dev *dev) | 334 | void pcibios_set_master (struct pci_dev *dev) |
336 | { | 335 | { |
337 | } | 336 | } |
338 | 337 | ||
339 | 338 | ||
340 | /* Mother-A SRAM memory allocation. This is a simple first-fit allocator. */ | 339 | /* Mother-A SRAM memory allocation. This is a simple first-fit allocator. */ |
341 | 340 | ||
342 | /* A memory free-list node. */ | 341 | /* A memory free-list node. */ |
343 | struct mb_sram_free_area { | 342 | struct mb_sram_free_area { |
344 | void *mem; | 343 | void *mem; |
345 | unsigned long size; | 344 | unsigned long size; |
346 | struct mb_sram_free_area *next; | 345 | struct mb_sram_free_area *next; |
347 | }; | 346 | }; |
348 | 347 | ||
349 | /* The tail of the free-list, which starts out containing all the SRAM. */ | 348 | /* The tail of the free-list, which starts out containing all the SRAM. */ |
350 | static struct mb_sram_free_area mb_sram_free_tail = { | 349 | static struct mb_sram_free_area mb_sram_free_tail = { |
351 | (void *)MB_A_SRAM_ADDR, MB_A_SRAM_SIZE, 0 | 350 | (void *)MB_A_SRAM_ADDR, MB_A_SRAM_SIZE, 0 |
352 | }; | 351 | }; |
353 | 352 | ||
354 | /* The free-list. */ | 353 | /* The free-list. */ |
355 | static struct mb_sram_free_area *mb_sram_free_areas = &mb_sram_free_tail; | 354 | static struct mb_sram_free_area *mb_sram_free_areas = &mb_sram_free_tail; |
356 | 355 | ||
357 | /* The free-list of free free-list nodes. (:-) */ | 356 | /* The free-list of free free-list nodes. (:-) */ |
358 | static struct mb_sram_free_area *mb_sram_free_free_areas = 0; | 357 | static struct mb_sram_free_area *mb_sram_free_free_areas = 0; |
359 | 358 | ||
360 | /* Spinlock protecting the above globals. */ | 359 | /* Spinlock protecting the above globals. */ |
361 | static DEFINE_SPINLOCK(mb_sram_lock); | 360 | static DEFINE_SPINLOCK(mb_sram_lock); |
362 | 361 | ||
363 | /* Allocate a memory block at least SIZE bytes long in the Mother-A SRAM | 362 | /* Allocate a memory block at least SIZE bytes long in the Mother-A SRAM |
364 | space. */ | 363 | space. */ |
365 | static void *alloc_mb_sram (size_t size) | 364 | static void *alloc_mb_sram (size_t size) |
366 | { | 365 | { |
367 | struct mb_sram_free_area *prev, *fa; | 366 | struct mb_sram_free_area *prev, *fa; |
368 | unsigned long flags; | 367 | unsigned long flags; |
369 | void *mem = 0; | 368 | void *mem = 0; |
370 | 369 | ||
371 | spin_lock_irqsave (mb_sram_lock, flags); | 370 | spin_lock_irqsave (mb_sram_lock, flags); |
372 | 371 | ||
373 | /* Look for a free area that can contain SIZE bytes. */ | 372 | /* Look for a free area that can contain SIZE bytes. */ |
374 | for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next) | 373 | for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next) |
375 | if (fa->size >= size) { | 374 | if (fa->size >= size) { |
376 | /* Found one! */ | 375 | /* Found one! */ |
377 | mem = fa->mem; | 376 | mem = fa->mem; |
378 | 377 | ||
379 | if (fa->size == size) { | 378 | if (fa->size == size) { |
380 | /* In fact, it fits exactly, so remove | 379 | /* In fact, it fits exactly, so remove |
381 | this node from the free-list. */ | 380 | this node from the free-list. */ |
382 | if (prev) | 381 | if (prev) |
383 | prev->next = fa->next; | 382 | prev->next = fa->next; |
384 | else | 383 | else |
385 | mb_sram_free_areas = fa->next; | 384 | mb_sram_free_areas = fa->next; |
386 | /* Put it on the free-list-entry-free-list. */ | 385 | /* Put it on the free-list-entry-free-list. */ |
387 | fa->next = mb_sram_free_free_areas; | 386 | fa->next = mb_sram_free_free_areas; |
388 | mb_sram_free_free_areas = fa; | 387 | mb_sram_free_free_areas = fa; |
389 | } else { | 388 | } else { |
390 | /* FA is bigger than SIZE, so just | 389 | /* FA is bigger than SIZE, so just |
391 | reduce its size to account for this | 390 | reduce its size to account for this |
392 | allocation. */ | 391 | allocation. */ |
393 | fa->mem += size; | 392 | fa->mem += size; |
394 | fa->size -= size; | 393 | fa->size -= size; |
395 | } | 394 | } |
396 | 395 | ||
397 | break; | 396 | break; |
398 | } | 397 | } |
399 | 398 | ||
400 | spin_unlock_irqrestore (mb_sram_lock, flags); | 399 | spin_unlock_irqrestore (mb_sram_lock, flags); |
401 | 400 | ||
402 | return mem; | 401 | return mem; |
403 | } | 402 | } |
404 | 403 | ||
405 | /* Return the memory area MEM of size SIZE to the MB SRAM free pool. */ | 404 | /* Return the memory area MEM of size SIZE to the MB SRAM free pool. */ |
406 | static void free_mb_sram (void *mem, size_t size) | 405 | static void free_mb_sram (void *mem, size_t size) |
407 | { | 406 | { |
408 | struct mb_sram_free_area *prev, *fa, *new_fa; | 407 | struct mb_sram_free_area *prev, *fa, *new_fa; |
409 | unsigned long flags; | 408 | unsigned long flags; |
410 | void *end = mem + size; | 409 | void *end = mem + size; |
411 | 410 | ||
412 | spin_lock_irqsave (mb_sram_lock, flags); | 411 | spin_lock_irqsave (mb_sram_lock, flags); |
413 | 412 | ||
414 | retry: | 413 | retry: |
415 | /* Find an adjacent free-list entry. */ | 414 | /* Find an adjacent free-list entry. */ |
416 | for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next) | 415 | for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next) |
417 | if (fa->mem == end) { | 416 | if (fa->mem == end) { |
418 | /* FA is just after MEM, grow down to encompass it. */ | 417 | /* FA is just after MEM, grow down to encompass it. */ |
419 | fa->mem = mem; | 418 | fa->mem = mem; |
420 | fa->size += size; | 419 | fa->size += size; |
421 | goto done; | 420 | goto done; |
422 | } else if (fa->mem + fa->size == mem) { | 421 | } else if (fa->mem + fa->size == mem) { |
423 | struct mb_sram_free_area *next_fa = fa->next; | 422 | struct mb_sram_free_area *next_fa = fa->next; |
424 | 423 | ||
425 | /* FA is just before MEM, expand to encompass it. */ | 424 | /* FA is just before MEM, expand to encompass it. */ |
426 | fa->size += size; | 425 | fa->size += size; |
427 | 426 | ||
428 | /* See if FA can now be merged with its successor. */ | 427 | /* See if FA can now be merged with its successor. */ |
429 | if (next_fa && fa->mem + fa->size == next_fa->mem) { | 428 | if (next_fa && fa->mem + fa->size == next_fa->mem) { |
430 | /* Yup; merge NEXT_FA's info into FA. */ | 429 | /* Yup; merge NEXT_FA's info into FA. */ |
431 | fa->size += next_fa->size; | 430 | fa->size += next_fa->size; |
432 | fa->next = next_fa->next; | 431 | fa->next = next_fa->next; |
433 | /* Free NEXT_FA. */ | 432 | /* Free NEXT_FA. */ |
434 | next_fa->next = mb_sram_free_free_areas; | 433 | next_fa->next = mb_sram_free_free_areas; |
435 | mb_sram_free_free_areas = next_fa; | 434 | mb_sram_free_free_areas = next_fa; |
436 | } | 435 | } |
437 | goto done; | 436 | goto done; |
438 | } else if (fa->mem > mem) | 437 | } else if (fa->mem > mem) |
439 | /* We've reached the right spot in the free-list | 438 | /* We've reached the right spot in the free-list |
440 | without finding an adjacent free-area, so add | 439 | without finding an adjacent free-area, so add |
441 | a new free area to hold mem. */ | 440 | a new free area to hold mem. */ |
442 | break; | 441 | break; |
443 | 442 | ||
444 | /* Make a new free-list entry. */ | 443 | /* Make a new free-list entry. */ |
445 | 444 | ||
446 | /* First, get a free-list entry. */ | 445 | /* First, get a free-list entry. */ |
447 | if (! mb_sram_free_free_areas) { | 446 | if (! mb_sram_free_free_areas) { |
448 | /* There are none, so make some. */ | 447 | /* There are none, so make some. */ |
449 | void *block; | 448 | void *block; |
450 | size_t block_size = sizeof (struct mb_sram_free_area) * 8; | 449 | size_t block_size = sizeof (struct mb_sram_free_area) * 8; |
451 | 450 | ||
452 | /* Don't hold the lock while calling kmalloc (I'm not | 451 | /* Don't hold the lock while calling kmalloc (I'm not |
453 | sure whether it would be a problem, since we use | 452 | sure whether it would be a problem, since we use |
454 | GFP_ATOMIC, but it makes me nervous). */ | 453 | GFP_ATOMIC, but it makes me nervous). */ |
455 | spin_unlock_irqrestore (mb_sram_lock, flags); | 454 | spin_unlock_irqrestore (mb_sram_lock, flags); |
456 | 455 | ||
457 | block = kmalloc (block_size, GFP_ATOMIC); | 456 | block = kmalloc (block_size, GFP_ATOMIC); |
458 | if (! block) | 457 | if (! block) |
459 | panic ("free_mb_sram: can't allocate free-list entry"); | 458 | panic ("free_mb_sram: can't allocate free-list entry"); |
460 | 459 | ||
461 | /* Now get the lock back. */ | 460 | /* Now get the lock back. */ |
462 | spin_lock_irqsave (mb_sram_lock, flags); | 461 | spin_lock_irqsave (mb_sram_lock, flags); |
463 | 462 | ||
464 | /* Add the new free free-list entries. */ | 463 | /* Add the new free free-list entries. */ |
465 | while (block_size > 0) { | 464 | while (block_size > 0) { |
466 | struct mb_sram_free_area *nfa = block; | 465 | struct mb_sram_free_area *nfa = block; |
467 | nfa->next = mb_sram_free_free_areas; | 466 | nfa->next = mb_sram_free_free_areas; |
468 | mb_sram_free_free_areas = nfa; | 467 | mb_sram_free_free_areas = nfa; |
469 | block += sizeof *nfa; | 468 | block += sizeof *nfa; |
470 | block_size -= sizeof *nfa; | 469 | block_size -= sizeof *nfa; |
471 | } | 470 | } |
472 | 471 | ||
473 | /* Since we dropped the lock to call kmalloc, the | 472 | /* Since we dropped the lock to call kmalloc, the |
474 | free-list could have changed, so retry from the | 473 | free-list could have changed, so retry from the |
475 | beginning. */ | 474 | beginning. */ |
476 | goto retry; | 475 | goto retry; |
477 | } | 476 | } |
478 | 477 | ||
479 | /* Remove NEW_FA from the free-list of free-list entries. */ | 478 | /* Remove NEW_FA from the free-list of free-list entries. */ |
480 | new_fa = mb_sram_free_free_areas; | 479 | new_fa = mb_sram_free_free_areas; |
481 | mb_sram_free_free_areas = new_fa->next; | 480 | mb_sram_free_free_areas = new_fa->next; |
482 | 481 | ||
483 | /* NEW_FA initially holds only MEM. */ | 482 | /* NEW_FA initially holds only MEM. */ |
484 | new_fa->mem = mem; | 483 | new_fa->mem = mem; |
485 | new_fa->size = size; | 484 | new_fa->size = size; |
486 | 485 | ||
487 | /* Insert NEW_FA in the free-list between PREV and FA. */ | 486 | /* Insert NEW_FA in the free-list between PREV and FA. */ |
488 | new_fa->next = fa; | 487 | new_fa->next = fa; |
489 | if (prev) | 488 | if (prev) |
490 | prev->next = new_fa; | 489 | prev->next = new_fa; |
491 | else | 490 | else |
492 | mb_sram_free_areas = new_fa; | 491 | mb_sram_free_areas = new_fa; |
493 | 492 | ||
494 | done: | 493 | done: |
495 | spin_unlock_irqrestore (mb_sram_lock, flags); | 494 | spin_unlock_irqrestore (mb_sram_lock, flags); |
496 | } | 495 | } |
497 | 496 | ||
498 | 497 | ||
499 | /* Maintainence of CPU -> Mother-A DMA mappings. */ | 498 | /* Maintainence of CPU -> Mother-A DMA mappings. */ |
500 | 499 | ||
501 | struct dma_mapping { | 500 | struct dma_mapping { |
502 | void *cpu_addr; | 501 | void *cpu_addr; |
503 | void *mb_sram_addr; | 502 | void *mb_sram_addr; |
504 | size_t size; | 503 | size_t size; |
505 | struct dma_mapping *next; | 504 | struct dma_mapping *next; |
506 | }; | 505 | }; |
507 | 506 | ||
508 | /* A list of mappings from CPU addresses to MB SRAM addresses for active | 507 | /* A list of mappings from CPU addresses to MB SRAM addresses for active |
509 | DMA blocks (that have been `granted' to the PCI device). */ | 508 | DMA blocks (that have been `granted' to the PCI device). */ |
510 | static struct dma_mapping *active_dma_mappings = 0; | 509 | static struct dma_mapping *active_dma_mappings = 0; |
511 | 510 | ||
512 | /* A list of free mapping objects. */ | 511 | /* A list of free mapping objects. */ |
513 | static struct dma_mapping *free_dma_mappings = 0; | 512 | static struct dma_mapping *free_dma_mappings = 0; |
514 | 513 | ||
515 | /* Spinlock protecting the above globals. */ | 514 | /* Spinlock protecting the above globals. */ |
516 | static DEFINE_SPINLOCK(dma_mappings_lock); | 515 | static DEFINE_SPINLOCK(dma_mappings_lock); |
517 | 516 | ||
518 | static struct dma_mapping *new_dma_mapping (size_t size) | 517 | static struct dma_mapping *new_dma_mapping (size_t size) |
519 | { | 518 | { |
520 | unsigned long flags; | 519 | unsigned long flags; |
521 | struct dma_mapping *mapping; | 520 | struct dma_mapping *mapping; |
522 | void *mb_sram_block = alloc_mb_sram (size); | 521 | void *mb_sram_block = alloc_mb_sram (size); |
523 | 522 | ||
524 | if (! mb_sram_block) | 523 | if (! mb_sram_block) |
525 | return 0; | 524 | return 0; |
526 | 525 | ||
527 | spin_lock_irqsave (dma_mappings_lock, flags); | 526 | spin_lock_irqsave (dma_mappings_lock, flags); |
528 | 527 | ||
529 | if (! free_dma_mappings) { | 528 | if (! free_dma_mappings) { |
530 | /* We're out of mapping structures, make more. */ | 529 | /* We're out of mapping structures, make more. */ |
531 | void *mblock; | 530 | void *mblock; |
532 | size_t mblock_size = sizeof (struct dma_mapping) * 8; | 531 | size_t mblock_size = sizeof (struct dma_mapping) * 8; |
533 | 532 | ||
534 | /* Don't hold the lock while calling kmalloc (I'm not | 533 | /* Don't hold the lock while calling kmalloc (I'm not |
535 | sure whether it would be a problem, since we use | 534 | sure whether it would be a problem, since we use |
536 | GFP_ATOMIC, but it makes me nervous). */ | 535 | GFP_ATOMIC, but it makes me nervous). */ |
537 | spin_unlock_irqrestore (dma_mappings_lock, flags); | 536 | spin_unlock_irqrestore (dma_mappings_lock, flags); |
538 | 537 | ||
539 | mblock = kmalloc (mblock_size, GFP_ATOMIC); | 538 | mblock = kmalloc (mblock_size, GFP_ATOMIC); |
540 | if (! mblock) { | 539 | if (! mblock) { |
541 | free_mb_sram (mb_sram_block, size); | 540 | free_mb_sram (mb_sram_block, size); |
542 | return 0; | 541 | return 0; |
543 | } | 542 | } |
544 | 543 | ||
545 | /* Get the lock back. */ | 544 | /* Get the lock back. */ |
546 | spin_lock_irqsave (dma_mappings_lock, flags); | 545 | spin_lock_irqsave (dma_mappings_lock, flags); |
547 | 546 | ||
548 | /* Add the new mapping structures to the free-list. */ | 547 | /* Add the new mapping structures to the free-list. */ |
549 | while (mblock_size > 0) { | 548 | while (mblock_size > 0) { |
550 | struct dma_mapping *fm = mblock; | 549 | struct dma_mapping *fm = mblock; |
551 | fm->next = free_dma_mappings; | 550 | fm->next = free_dma_mappings; |
552 | free_dma_mappings = fm; | 551 | free_dma_mappings = fm; |
553 | mblock += sizeof *fm; | 552 | mblock += sizeof *fm; |
554 | mblock_size -= sizeof *fm; | 553 | mblock_size -= sizeof *fm; |
555 | } | 554 | } |
556 | } | 555 | } |
557 | 556 | ||
558 | /* Get a mapping struct from the freelist. */ | 557 | /* Get a mapping struct from the freelist. */ |
559 | mapping = free_dma_mappings; | 558 | mapping = free_dma_mappings; |
560 | free_dma_mappings = mapping->next; | 559 | free_dma_mappings = mapping->next; |
561 | 560 | ||
562 | /* Initialize the mapping. Other fields should be filled in by | 561 | /* Initialize the mapping. Other fields should be filled in by |
563 | caller. */ | 562 | caller. */ |
564 | mapping->mb_sram_addr = mb_sram_block; | 563 | mapping->mb_sram_addr = mb_sram_block; |
565 | mapping->size = size; | 564 | mapping->size = size; |
566 | 565 | ||
567 | /* Add it to the list of active mappings. */ | 566 | /* Add it to the list of active mappings. */ |
568 | mapping->next = active_dma_mappings; | 567 | mapping->next = active_dma_mappings; |
569 | active_dma_mappings = mapping; | 568 | active_dma_mappings = mapping; |
570 | 569 | ||
571 | spin_unlock_irqrestore (dma_mappings_lock, flags); | 570 | spin_unlock_irqrestore (dma_mappings_lock, flags); |
572 | 571 | ||
573 | return mapping; | 572 | return mapping; |
574 | } | 573 | } |
575 | 574 | ||
576 | static struct dma_mapping *find_dma_mapping (void *mb_sram_addr) | 575 | static struct dma_mapping *find_dma_mapping (void *mb_sram_addr) |
577 | { | 576 | { |
578 | unsigned long flags; | 577 | unsigned long flags; |
579 | struct dma_mapping *mapping; | 578 | struct dma_mapping *mapping; |
580 | 579 | ||
581 | spin_lock_irqsave (dma_mappings_lock, flags); | 580 | spin_lock_irqsave (dma_mappings_lock, flags); |
582 | 581 | ||
583 | for (mapping = active_dma_mappings; mapping; mapping = mapping->next) | 582 | for (mapping = active_dma_mappings; mapping; mapping = mapping->next) |
584 | if (mapping->mb_sram_addr == mb_sram_addr) { | 583 | if (mapping->mb_sram_addr == mb_sram_addr) { |
585 | spin_unlock_irqrestore (dma_mappings_lock, flags); | 584 | spin_unlock_irqrestore (dma_mappings_lock, flags); |
586 | return mapping; | 585 | return mapping; |
587 | } | 586 | } |
588 | 587 | ||
589 | panic ("find_dma_mapping: unmapped PCI DMA addr 0x%x", | 588 | panic ("find_dma_mapping: unmapped PCI DMA addr 0x%x", |
590 | MB_SRAM_TO_PCI (mb_sram_addr)); | 589 | MB_SRAM_TO_PCI (mb_sram_addr)); |
591 | } | 590 | } |
592 | 591 | ||
593 | static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr) | 592 | static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr) |
594 | { | 593 | { |
595 | unsigned long flags; | 594 | unsigned long flags; |
596 | struct dma_mapping *mapping, *prev; | 595 | struct dma_mapping *mapping, *prev; |
597 | 596 | ||
598 | spin_lock_irqsave (dma_mappings_lock, flags); | 597 | spin_lock_irqsave (dma_mappings_lock, flags); |
599 | 598 | ||
600 | for (prev = 0, mapping = active_dma_mappings; | 599 | for (prev = 0, mapping = active_dma_mappings; |
601 | mapping; | 600 | mapping; |
602 | prev = mapping, mapping = mapping->next) | 601 | prev = mapping, mapping = mapping->next) |
603 | { | 602 | { |
604 | if (mapping->mb_sram_addr == mb_sram_addr) { | 603 | if (mapping->mb_sram_addr == mb_sram_addr) { |
605 | /* This is the MAPPING; deactivate it. */ | 604 | /* This is the MAPPING; deactivate it. */ |
606 | if (prev) | 605 | if (prev) |
607 | prev->next = mapping->next; | 606 | prev->next = mapping->next; |
608 | else | 607 | else |
609 | active_dma_mappings = mapping->next; | 608 | active_dma_mappings = mapping->next; |
610 | 609 | ||
611 | spin_unlock_irqrestore (dma_mappings_lock, flags); | 610 | spin_unlock_irqrestore (dma_mappings_lock, flags); |
612 | 611 | ||
613 | return mapping; | 612 | return mapping; |
614 | } | 613 | } |
615 | } | 614 | } |
616 | 615 | ||
617 | panic ("deactivate_dma_mapping: unmapped PCI DMA addr 0x%x", | 616 | panic ("deactivate_dma_mapping: unmapped PCI DMA addr 0x%x", |
618 | MB_SRAM_TO_PCI (mb_sram_addr)); | 617 | MB_SRAM_TO_PCI (mb_sram_addr)); |
619 | } | 618 | } |
620 | 619 | ||
621 | /* Return MAPPING to the freelist. */ | 620 | /* Return MAPPING to the freelist. */ |
622 | static inline void | 621 | static inline void |
623 | free_dma_mapping (struct dma_mapping *mapping) | 622 | free_dma_mapping (struct dma_mapping *mapping) |
624 | { | 623 | { |
625 | unsigned long flags; | 624 | unsigned long flags; |
626 | 625 | ||
627 | free_mb_sram (mapping->mb_sram_addr, mapping->size); | 626 | free_mb_sram (mapping->mb_sram_addr, mapping->size); |
628 | 627 | ||
629 | spin_lock_irqsave (dma_mappings_lock, flags); | 628 | spin_lock_irqsave (dma_mappings_lock, flags); |
630 | 629 | ||
631 | mapping->next = free_dma_mappings; | 630 | mapping->next = free_dma_mappings; |
632 | free_dma_mappings = mapping; | 631 | free_dma_mappings = mapping; |
633 | 632 | ||
634 | spin_unlock_irqrestore (dma_mappings_lock, flags); | 633 | spin_unlock_irqrestore (dma_mappings_lock, flags); |
635 | } | 634 | } |
636 | 635 | ||
637 | 636 | ||
638 | /* Single PCI DMA mappings. */ | 637 | /* Single PCI DMA mappings. */ |
639 | 638 | ||
640 | /* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA. The | 639 | /* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA. The |
641 | 32-bit PCI bus mastering address to use is returned. the device owns | 640 | 32-bit PCI bus mastering address to use is returned. the device owns |
642 | this memory until either pci_unmap_single or pci_dma_sync_single is | 641 | this memory until either pci_unmap_single or pci_dma_sync_single is |
643 | performed. */ | 642 | performed. */ |
644 | dma_addr_t | 643 | dma_addr_t |
645 | pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir) | 644 | pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir) |
646 | { | 645 | { |
647 | struct dma_mapping *mapping = new_dma_mapping (size); | 646 | struct dma_mapping *mapping = new_dma_mapping (size); |
648 | 647 | ||
649 | if (! mapping) | 648 | if (! mapping) |
650 | return 0; | 649 | return 0; |
651 | 650 | ||
652 | mapping->cpu_addr = cpu_addr; | 651 | mapping->cpu_addr = cpu_addr; |
653 | 652 | ||
654 | if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_TODEVICE) | 653 | if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_TODEVICE) |
655 | memcpy (mapping->mb_sram_addr, cpu_addr, size); | 654 | memcpy (mapping->mb_sram_addr, cpu_addr, size); |
656 | 655 | ||
657 | return MB_SRAM_TO_PCI (mapping->mb_sram_addr); | 656 | return MB_SRAM_TO_PCI (mapping->mb_sram_addr); |
658 | } | 657 | } |
659 | 658 | ||
660 | /* Return to the CPU the PCI DMA memory block previously `granted' to | 659 | /* Return to the CPU the PCI DMA memory block previously `granted' to |
661 | PDEV, at DMA_ADDR. */ | 660 | PDEV, at DMA_ADDR. */ |
662 | void pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, | 661 | void pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, |
663 | int dir) | 662 | int dir) |
664 | { | 663 | { |
665 | void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr); | 664 | void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr); |
666 | struct dma_mapping *mapping = deactivate_dma_mapping (mb_sram_addr); | 665 | struct dma_mapping *mapping = deactivate_dma_mapping (mb_sram_addr); |
667 | 666 | ||
668 | if (size != mapping->size) | 667 | if (size != mapping->size) |
669 | panic ("pci_unmap_single: size (%d) doesn't match" | 668 | panic ("pci_unmap_single: size (%d) doesn't match" |
670 | " size of mapping at PCI DMA addr 0x%x (%d)\n", | 669 | " size of mapping at PCI DMA addr 0x%x (%d)\n", |
671 | size, dma_addr, mapping->size); | 670 | size, dma_addr, mapping->size); |
672 | 671 | ||
673 | /* Copy back the DMA'd contents if necessary. */ | 672 | /* Copy back the DMA'd contents if necessary. */ |
674 | if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_FROMDEVICE) | 673 | if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_FROMDEVICE) |
675 | memcpy (mapping->cpu_addr, mb_sram_addr, size); | 674 | memcpy (mapping->cpu_addr, mb_sram_addr, size); |
676 | 675 | ||
677 | /* Return mapping to the freelist. */ | 676 | /* Return mapping to the freelist. */ |
678 | free_dma_mapping (mapping); | 677 | free_dma_mapping (mapping); |
679 | } | 678 | } |
680 | 679 | ||
681 | /* Make physical memory consistent for a single streaming mode DMA | 680 | /* Make physical memory consistent for a single streaming mode DMA |
682 | translation after a transfer. | 681 | translation after a transfer. |
683 | 682 | ||
684 | If you perform a pci_map_single() but wish to interrogate the | 683 | If you perform a pci_map_single() but wish to interrogate the |
685 | buffer using the cpu, yet do not wish to teardown the PCI dma | 684 | buffer using the cpu, yet do not wish to teardown the PCI dma |
686 | mapping, you must call this function before doing so. At the next | 685 | mapping, you must call this function before doing so. At the next |
687 | point you give the PCI dma address back to the card, you must first | 686 | point you give the PCI dma address back to the card, you must first |
688 | perform a pci_dma_sync_for_device, and then the device again owns | 687 | perform a pci_dma_sync_for_device, and then the device again owns |
689 | the buffer. */ | 688 | the buffer. */ |
690 | void | 689 | void |
691 | pci_dma_sync_single_for_cpu (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, | 690 | pci_dma_sync_single_for_cpu (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, |
692 | int dir) | 691 | int dir) |
693 | { | 692 | { |
694 | void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr); | 693 | void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr); |
695 | struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr); | 694 | struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr); |
696 | 695 | ||
697 | /* Synchronize the DMA buffer with the CPU buffer if necessary. */ | 696 | /* Synchronize the DMA buffer with the CPU buffer if necessary. */ |
698 | if (dir == PCI_DMA_FROMDEVICE) | 697 | if (dir == PCI_DMA_FROMDEVICE) |
699 | memcpy (mapping->cpu_addr, mb_sram_addr, size); | 698 | memcpy (mapping->cpu_addr, mb_sram_addr, size); |
700 | else if (dir == PCI_DMA_TODEVICE) | 699 | else if (dir == PCI_DMA_TODEVICE) |
701 | ; /* nothing to do */ | 700 | ; /* nothing to do */ |
702 | else | 701 | else |
703 | panic("pci_dma_sync_single: unsupported sync dir: %d", dir); | 702 | panic("pci_dma_sync_single: unsupported sync dir: %d", dir); |
704 | } | 703 | } |
705 | 704 | ||
706 | void | 705 | void |
707 | pci_dma_sync_single_for_device (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, | 706 | pci_dma_sync_single_for_device (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, |
708 | int dir) | 707 | int dir) |
709 | { | 708 | { |
710 | void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr); | 709 | void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr); |
711 | struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr); | 710 | struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr); |
712 | 711 | ||
713 | /* Synchronize the DMA buffer with the CPU buffer if necessary. */ | 712 | /* Synchronize the DMA buffer with the CPU buffer if necessary. */ |
714 | if (dir == PCI_DMA_FROMDEVICE) | 713 | if (dir == PCI_DMA_FROMDEVICE) |
715 | ; /* nothing to do */ | 714 | ; /* nothing to do */ |
716 | else if (dir == PCI_DMA_TODEVICE) | 715 | else if (dir == PCI_DMA_TODEVICE) |
717 | memcpy (mb_sram_addr, mapping->cpu_addr, size); | 716 | memcpy (mb_sram_addr, mapping->cpu_addr, size); |
718 | else | 717 | else |
719 | panic("pci_dma_sync_single: unsupported sync dir: %d", dir); | 718 | panic("pci_dma_sync_single: unsupported sync dir: %d", dir); |
720 | } | 719 | } |
721 | 720 | ||
722 | 721 | ||
723 | /* Scatter-gather PCI DMA mappings. */ | 722 | /* Scatter-gather PCI DMA mappings. */ |
724 | 723 | ||
725 | /* Do multiple DMA mappings at once. */ | 724 | /* Do multiple DMA mappings at once. */ |
726 | int | 725 | int |
727 | pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir) | 726 | pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir) |
728 | { | 727 | { |
729 | BUG (); | 728 | BUG (); |
730 | return 0; | 729 | return 0; |
731 | } | 730 | } |
732 | 731 | ||
733 | /* Unmap multiple DMA mappings at once. */ | 732 | /* Unmap multiple DMA mappings at once. */ |
734 | void | 733 | void |
735 | pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,int dir) | 734 | pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,int dir) |
736 | { | 735 | { |
737 | BUG (); | 736 | BUG (); |
738 | } | 737 | } |
739 | 738 | ||
740 | /* Make physical memory consistent for a set of streaming mode DMA | 739 | /* Make physical memory consistent for a set of streaming mode DMA |
741 | translations after a transfer. The same as pci_dma_sync_single_* but | 740 | translations after a transfer. The same as pci_dma_sync_single_* but |
742 | for a scatter-gather list, same rules and usage. */ | 741 | for a scatter-gather list, same rules and usage. */ |
743 | 742 | ||
744 | void | 743 | void |
745 | pci_dma_sync_sg_for_cpu (struct pci_dev *dev, | 744 | pci_dma_sync_sg_for_cpu (struct pci_dev *dev, |
746 | struct scatterlist *sg, int sg_len, | 745 | struct scatterlist *sg, int sg_len, |
747 | int dir) | 746 | int dir) |
748 | { | 747 | { |
749 | BUG (); | 748 | BUG (); |
750 | } | 749 | } |
751 | 750 | ||
752 | void | 751 | void |
753 | pci_dma_sync_sg_for_device (struct pci_dev *dev, | 752 | pci_dma_sync_sg_for_device (struct pci_dev *dev, |
754 | struct scatterlist *sg, int sg_len, | 753 | struct scatterlist *sg, int sg_len, |
755 | int dir) | 754 | int dir) |
756 | { | 755 | { |
757 | BUG (); | 756 | BUG (); |
758 | } | 757 | } |
759 | 758 | ||
760 | 759 | ||
761 | /* PCI mem mapping. */ | 760 | /* PCI mem mapping. */ |
762 | 761 | ||
763 | /* Allocate and map kernel buffer using consistent mode DMA for PCI | 762 | /* Allocate and map kernel buffer using consistent mode DMA for PCI |
764 | device. Returns non-NULL cpu-view pointer to the buffer if | 763 | device. Returns non-NULL cpu-view pointer to the buffer if |
765 | successful and sets *DMA_ADDR to the pci side dma address as well, | 764 | successful and sets *DMA_ADDR to the pci side dma address as well, |
766 | else DMA_ADDR is undefined. */ | 765 | else DMA_ADDR is undefined. */ |
767 | void * | 766 | void * |
768 | pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr) | 767 | pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr) |
769 | { | 768 | { |
770 | void *mb_sram_mem = alloc_mb_sram (size); | 769 | void *mb_sram_mem = alloc_mb_sram (size); |
771 | if (mb_sram_mem) | 770 | if (mb_sram_mem) |
772 | *dma_addr = MB_SRAM_TO_PCI (mb_sram_mem); | 771 | *dma_addr = MB_SRAM_TO_PCI (mb_sram_mem); |
773 | return mb_sram_mem; | 772 | return mb_sram_mem; |
774 | } | 773 | } |
775 | 774 | ||
776 | /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must | 775 | /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must |
777 | be values that were returned from pci_alloc_consistent. SIZE must be | 776 | be values that were returned from pci_alloc_consistent. SIZE must be |
778 | the same as what as passed into pci_alloc_consistent. References to | 777 | the same as what as passed into pci_alloc_consistent. References to |
779 | the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past | 778 | the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past |
780 | this call are illegal. */ | 779 | this call are illegal. */ |
781 | void | 780 | void |
782 | pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr, | 781 | pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr, |
783 | dma_addr_t dma_addr) | 782 | dma_addr_t dma_addr) |
784 | { | 783 | { |
785 | void *mb_sram_mem = PCI_TO_MB_SRAM (dma_addr); | 784 | void *mb_sram_mem = PCI_TO_MB_SRAM (dma_addr); |
786 | free_mb_sram (mb_sram_mem, size); | 785 | free_mb_sram (mb_sram_mem, size); |
787 | } | 786 | } |
788 | 787 | ||
789 | 788 | ||
790 | /* iomap/iomap */ | 789 | /* iomap/iomap */ |
791 | 790 | ||
792 | void __iomem *pci_iomap (struct pci_dev *dev, int bar, unsigned long max) | 791 | void __iomem *pci_iomap (struct pci_dev *dev, int bar, unsigned long max) |
793 | { | 792 | { |
794 | unsigned long start = pci_resource_start (dev, bar); | 793 | unsigned long start = pci_resource_start (dev, bar); |
795 | unsigned long len = pci_resource_len (dev, bar); | 794 | unsigned long len = pci_resource_len (dev, bar); |
796 | 795 | ||
797 | if (!start || len == 0) | 796 | if (!start || len == 0) |
798 | return 0; | 797 | return 0; |
799 | 798 | ||
800 | /* None of the ioremap functions actually do anything, other than | 799 | /* None of the ioremap functions actually do anything, other than |
801 | re-casting their argument, so don't bother differentiating them. */ | 800 | re-casting their argument, so don't bother differentiating them. */ |
802 | return ioremap (start, len); | 801 | return ioremap (start, len); |
803 | } | 802 | } |
804 | 803 | ||
805 | void pci_iounmap (struct pci_dev *dev, void __iomem *addr) | 804 | void pci_iounmap (struct pci_dev *dev, void __iomem *addr) |
806 | { | 805 | { |
807 | /* nothing */ | 806 | /* nothing */ |
808 | } | 807 | } |
809 | 808 | ||
810 | 809 | ||
811 | /* symbol exports (for modules) */ | 810 | /* symbol exports (for modules) */ |
812 | 811 | ||
813 | EXPORT_SYMBOL (pci_map_single); | 812 | EXPORT_SYMBOL (pci_map_single); |
814 | EXPORT_SYMBOL (pci_unmap_single); | 813 | EXPORT_SYMBOL (pci_unmap_single); |
815 | EXPORT_SYMBOL (pci_alloc_consistent); | 814 | EXPORT_SYMBOL (pci_alloc_consistent); |
816 | EXPORT_SYMBOL (pci_free_consistent); | 815 | EXPORT_SYMBOL (pci_free_consistent); |
817 | EXPORT_SYMBOL (pci_dma_sync_single_for_cpu); | 816 | EXPORT_SYMBOL (pci_dma_sync_single_for_cpu); |
818 | EXPORT_SYMBOL (pci_dma_sync_single_for_device); | 817 | EXPORT_SYMBOL (pci_dma_sync_single_for_device); |
819 | EXPORT_SYMBOL (pci_iomap); | 818 | EXPORT_SYMBOL (pci_iomap); |
820 | EXPORT_SYMBOL (pci_iounmap); | 819 | EXPORT_SYMBOL (pci_iounmap); |
821 | 820 |
arch/v850/kernel/rte_me2_cb.c
1 | /* | 1 | /* |
2 | * arch/v850/kernel/rte_me2_cb.c -- Midas labs RTE-V850E/ME2-CB board | 2 | * arch/v850/kernel/rte_me2_cb.c -- Midas labs RTE-V850E/ME2-CB board |
3 | * | 3 | * |
4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation | 4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation |
5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/bootmem.h> | 16 | #include <linux/bootmem.h> |
17 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | #include <linux/major.h> | 19 | #include <linux/major.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | 22 | ||
23 | #include <asm/atomic.h> | 23 | #include <asm/atomic.h> |
24 | #include <asm/page.h> | 24 | #include <asm/page.h> |
25 | #include <asm/me2.h> | 25 | #include <asm/me2.h> |
26 | #include <asm/rte_me2_cb.h> | 26 | #include <asm/rte_me2_cb.h> |
27 | #include <asm/machdep.h> | 27 | #include <asm/machdep.h> |
28 | #include <asm/v850e_intc.h> | 28 | #include <asm/v850e_intc.h> |
29 | #include <asm/v850e_cache.h> | 29 | #include <asm/v850e_cache.h> |
30 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
31 | 31 | ||
32 | #include "mach.h" | 32 | #include "mach.h" |
33 | 33 | ||
34 | extern unsigned long *_intv_start; | 34 | extern unsigned long *_intv_start; |
35 | extern unsigned long *_intv_end; | 35 | extern unsigned long *_intv_end; |
36 | 36 | ||
37 | /* LED access routines. */ | 37 | /* LED access routines. */ |
38 | extern unsigned read_leds (int pos, char *buf, int len); | 38 | extern unsigned read_leds (int pos, char *buf, int len); |
39 | extern unsigned write_leds (int pos, const char *buf, int len); | 39 | extern unsigned write_leds (int pos, const char *buf, int len); |
40 | 40 | ||
41 | 41 | ||
42 | /* SDRAM are almost contiguous (with a small hole in between; | 42 | /* SDRAM are almost contiguous (with a small hole in between; |
43 | see mach_reserve_bootmem for details), so just use both as one big area. */ | 43 | see mach_reserve_bootmem for details), so just use both as one big area. */ |
44 | #define RAM_START SDRAM_ADDR | 44 | #define RAM_START SDRAM_ADDR |
45 | #define RAM_END (SDRAM_ADDR + SDRAM_SIZE) | 45 | #define RAM_END (SDRAM_ADDR + SDRAM_SIZE) |
46 | 46 | ||
47 | 47 | ||
48 | void __init mach_get_physical_ram (unsigned long *ram_start, | 48 | void __init mach_get_physical_ram (unsigned long *ram_start, |
49 | unsigned long *ram_len) | 49 | unsigned long *ram_len) |
50 | { | 50 | { |
51 | *ram_start = RAM_START; | 51 | *ram_start = RAM_START; |
52 | *ram_len = RAM_END - RAM_START; | 52 | *ram_len = RAM_END - RAM_START; |
53 | } | 53 | } |
54 | 54 | ||
55 | void mach_gettimeofday (struct timespec *tv) | 55 | void mach_gettimeofday (struct timespec *tv) |
56 | { | 56 | { |
57 | tv->tv_sec = 0; | 57 | tv->tv_sec = 0; |
58 | tv->tv_nsec = 0; | 58 | tv->tv_nsec = 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | /* Called before configuring an on-chip UART. */ | 61 | /* Called before configuring an on-chip UART. */ |
62 | void rte_me2_cb_uart_pre_configure (unsigned chan, | 62 | void rte_me2_cb_uart_pre_configure (unsigned chan, |
63 | unsigned cflags, unsigned baud) | 63 | unsigned cflags, unsigned baud) |
64 | { | 64 | { |
65 | /* The RTE-V850E/ME2-CB connects some general-purpose I/O | 65 | /* The RTE-V850E/ME2-CB connects some general-purpose I/O |
66 | pins on the CPU to the RTS/CTS lines of UARTB channel 0's | 66 | pins on the CPU to the RTS/CTS lines of UARTB channel 0's |
67 | serial connection. | 67 | serial connection. |
68 | I/O pins P21 and P22 are RTS and CTS respectively. */ | 68 | I/O pins P21 and P22 are RTS and CTS respectively. */ |
69 | if (chan == 0) { | 69 | if (chan == 0) { |
70 | /* Put P21 & P22 in I/O port mode. */ | 70 | /* Put P21 & P22 in I/O port mode. */ |
71 | ME2_PORT2_PMC &= ~0x6; | 71 | ME2_PORT2_PMC &= ~0x6; |
72 | /* Make P21 and output, and P22 an input. */ | 72 | /* Make P21 and output, and P22 an input. */ |
73 | ME2_PORT2_PM = (ME2_PORT2_PM & ~0xC) | 0x4; | 73 | ME2_PORT2_PM = (ME2_PORT2_PM & ~0xC) | 0x4; |
74 | } | 74 | } |
75 | 75 | ||
76 | me2_uart_pre_configure (chan, cflags, baud); | 76 | me2_uart_pre_configure (chan, cflags, baud); |
77 | } | 77 | } |
78 | 78 | ||
79 | void __init mach_init_irqs (void) | 79 | void __init mach_init_irqs (void) |
80 | { | 80 | { |
81 | /* Initialize interrupts. */ | 81 | /* Initialize interrupts. */ |
82 | me2_init_irqs (); | 82 | me2_init_irqs (); |
83 | rte_me2_cb_init_irqs (); | 83 | rte_me2_cb_init_irqs (); |
84 | } | 84 | } |
85 | 85 | ||
86 | #ifdef CONFIG_ROM_KERNEL | 86 | #ifdef CONFIG_ROM_KERNEL |
87 | /* Initialization for kernel in ROM. */ | 87 | /* Initialization for kernel in ROM. */ |
88 | static inline rom_kernel_init (void) | 88 | static inline rom_kernel_init (void) |
89 | { | 89 | { |
90 | /* If the kernel is in ROM, we have to copy any initialized data | 90 | /* If the kernel is in ROM, we have to copy any initialized data |
91 | from ROM into RAM. */ | 91 | from ROM into RAM. */ |
92 | extern unsigned long _data_load_start, _sdata, _edata; | 92 | extern unsigned long _data_load_start, _sdata, _edata; |
93 | register unsigned long *src = &_data_load_start; | 93 | register unsigned long *src = &_data_load_start; |
94 | register unsigned long *dst = &_sdata, *end = &_edata; | 94 | register unsigned long *dst = &_sdata, *end = &_edata; |
95 | 95 | ||
96 | while (dst != end) | 96 | while (dst != end) |
97 | *dst++ = *src++; | 97 | *dst++ = *src++; |
98 | } | 98 | } |
99 | #endif /* CONFIG_ROM_KERNEL */ | 99 | #endif /* CONFIG_ROM_KERNEL */ |
100 | 100 | ||
101 | static void install_interrupt_vectors (void) | 101 | static void install_interrupt_vectors (void) |
102 | { | 102 | { |
103 | unsigned long *p1, *p2; | 103 | unsigned long *p1, *p2; |
104 | 104 | ||
105 | ME2_IRAMM = 0x03; /* V850E/ME2 iRAM write mode */ | 105 | ME2_IRAMM = 0x03; /* V850E/ME2 iRAM write mode */ |
106 | 106 | ||
107 | /* vector copy to iRAM */ | 107 | /* vector copy to iRAM */ |
108 | p1 = (unsigned long *)0; /* v85x vector start */ | 108 | p1 = (unsigned long *)0; /* v85x vector start */ |
109 | p2 = (unsigned long *)&_intv_start; | 109 | p2 = (unsigned long *)&_intv_start; |
110 | while (p2 < (unsigned long *)&_intv_end) | 110 | while (p2 < (unsigned long *)&_intv_end) |
111 | *p1++ = *p2++; | 111 | *p1++ = *p2++; |
112 | 112 | ||
113 | ME2_IRAMM = 0x00; /* V850E/ME2 iRAM read mode */ | 113 | ME2_IRAMM = 0x00; /* V850E/ME2 iRAM read mode */ |
114 | } | 114 | } |
115 | 115 | ||
116 | /* CompactFlash */ | 116 | /* CompactFlash */ |
117 | 117 | ||
118 | static void cf_power_on (void) | 118 | static void cf_power_on (void) |
119 | { | 119 | { |
120 | /* CF card detected? */ | 120 | /* CF card detected? */ |
121 | if (CB_CF_STS0 & 0x0030) | 121 | if (CB_CF_STS0 & 0x0030) |
122 | return; | 122 | return; |
123 | 123 | ||
124 | CB_CF_REG0 = 0x0002; /* reest on */ | 124 | CB_CF_REG0 = 0x0002; /* reest on */ |
125 | mdelay (10); | 125 | mdelay (10); |
126 | CB_CF_REG0 = 0x0003; /* power on */ | 126 | CB_CF_REG0 = 0x0003; /* power on */ |
127 | mdelay (10); | 127 | mdelay (10); |
128 | CB_CF_REG0 = 0x0001; /* reset off */ | 128 | CB_CF_REG0 = 0x0001; /* reset off */ |
129 | mdelay (10); | 129 | mdelay (10); |
130 | } | 130 | } |
131 | 131 | ||
132 | static void cf_power_off (void) | 132 | static void cf_power_off (void) |
133 | { | 133 | { |
134 | CB_CF_REG0 = 0x0003; /* power on */ | 134 | CB_CF_REG0 = 0x0003; /* power on */ |
135 | mdelay (10); | 135 | mdelay (10); |
136 | CB_CF_REG0 = 0x0002; /* reest on */ | 136 | CB_CF_REG0 = 0x0002; /* reest on */ |
137 | mdelay (10); | 137 | mdelay (10); |
138 | } | 138 | } |
139 | 139 | ||
140 | void __init mach_early_init (void) | 140 | void __init mach_early_init (void) |
141 | { | 141 | { |
142 | install_interrupt_vectors (); | 142 | install_interrupt_vectors (); |
143 | 143 | ||
144 | /* CS1 SDRAM instruction cache enable */ | 144 | /* CS1 SDRAM instruction cache enable */ |
145 | v850e_cache_enable (0x04, 0x03, 0); | 145 | v850e_cache_enable (0x04, 0x03, 0); |
146 | 146 | ||
147 | rte_cb_early_init (); | 147 | rte_cb_early_init (); |
148 | 148 | ||
149 | /* CompactFlash power on */ | 149 | /* CompactFlash power on */ |
150 | cf_power_on (); | 150 | cf_power_on (); |
151 | 151 | ||
152 | #if defined (CONFIG_ROM_KERNEL) | 152 | #if defined (CONFIG_ROM_KERNEL) |
153 | rom_kernel_init (); | 153 | rom_kernel_init (); |
154 | #endif | 154 | #endif |
155 | } | 155 | } |
156 | 156 | ||
157 | 157 | ||
158 | /* RTE-V850E/ME2-CB Programmable Interrupt Controller. */ | 158 | /* RTE-V850E/ME2-CB Programmable Interrupt Controller. */ |
159 | 159 | ||
160 | static struct cb_pic_irq_init cb_pic_irq_inits[] = { | 160 | static struct cb_pic_irq_init cb_pic_irq_inits[] = { |
161 | { "CB_EXTTM0", IRQ_CB_EXTTM0, 1, 1, 6 }, | 161 | { "CB_EXTTM0", IRQ_CB_EXTTM0, 1, 1, 6 }, |
162 | { "CB_EXTSIO", IRQ_CB_EXTSIO, 1, 1, 6 }, | 162 | { "CB_EXTSIO", IRQ_CB_EXTSIO, 1, 1, 6 }, |
163 | { "CB_TOVER", IRQ_CB_TOVER, 1, 1, 6 }, | 163 | { "CB_TOVER", IRQ_CB_TOVER, 1, 1, 6 }, |
164 | { "CB_GINT0", IRQ_CB_GINT0, 1, 1, 6 }, | 164 | { "CB_GINT0", IRQ_CB_GINT0, 1, 1, 6 }, |
165 | { "CB_USB", IRQ_CB_USB, 1, 1, 6 }, | 165 | { "CB_USB", IRQ_CB_USB, 1, 1, 6 }, |
166 | { "CB_LANC", IRQ_CB_LANC, 1, 1, 6 }, | 166 | { "CB_LANC", IRQ_CB_LANC, 1, 1, 6 }, |
167 | { "CB_USB_VBUS_ON", IRQ_CB_USB_VBUS_ON, 1, 1, 6 }, | 167 | { "CB_USB_VBUS_ON", IRQ_CB_USB_VBUS_ON, 1, 1, 6 }, |
168 | { "CB_USB_VBUS_OFF", IRQ_CB_USB_VBUS_OFF, 1, 1, 6 }, | 168 | { "CB_USB_VBUS_OFF", IRQ_CB_USB_VBUS_OFF, 1, 1, 6 }, |
169 | { "CB_EXTTM1", IRQ_CB_EXTTM1, 1, 1, 6 }, | 169 | { "CB_EXTTM1", IRQ_CB_EXTTM1, 1, 1, 6 }, |
170 | { "CB_EXTTM2", IRQ_CB_EXTTM2, 1, 1, 6 }, | 170 | { "CB_EXTTM2", IRQ_CB_EXTTM2, 1, 1, 6 }, |
171 | { 0 } | 171 | { 0 } |
172 | }; | 172 | }; |
173 | #define NUM_CB_PIC_IRQ_INITS \ | 173 | #define NUM_CB_PIC_IRQ_INITS (ARRAY_SIZE(cb_pic_irq_inits) - 1) |
174 | ((sizeof cb_pic_irq_inits / sizeof cb_pic_irq_inits[0]) - 1) | ||
175 | 174 | ||
176 | static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS]; | 175 | static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS]; |
177 | static unsigned char cb_pic_active_irqs = 0; | 176 | static unsigned char cb_pic_active_irqs = 0; |
178 | 177 | ||
179 | void __init rte_me2_cb_init_irqs (void) | 178 | void __init rte_me2_cb_init_irqs (void) |
180 | { | 179 | { |
181 | cb_pic_init_irq_types (cb_pic_irq_inits, cb_pic_hw_itypes); | 180 | cb_pic_init_irq_types (cb_pic_irq_inits, cb_pic_hw_itypes); |
182 | 181 | ||
183 | /* Initalize on board PIC1 (not PIC0) enable */ | 182 | /* Initalize on board PIC1 (not PIC0) enable */ |
184 | CB_PIC_INT0M = 0x0000; | 183 | CB_PIC_INT0M = 0x0000; |
185 | CB_PIC_INT1M = 0x0000; | 184 | CB_PIC_INT1M = 0x0000; |
186 | CB_PIC_INTR = 0x0000; | 185 | CB_PIC_INTR = 0x0000; |
187 | CB_PIC_INTEN |= CB_PIC_INT1EN; | 186 | CB_PIC_INTEN |= CB_PIC_INT1EN; |
188 | 187 | ||
189 | ME2_PORT2_PMC |= 0x08; /* INTP23/SCK1 mode */ | 188 | ME2_PORT2_PMC |= 0x08; /* INTP23/SCK1 mode */ |
190 | ME2_PORT2_PFC &= ~0x08; /* INTP23 mode */ | 189 | ME2_PORT2_PFC &= ~0x08; /* INTP23 mode */ |
191 | ME2_INTR(2) &= ~0x08; /* INTP23 falling-edge detect */ | 190 | ME2_INTR(2) &= ~0x08; /* INTP23 falling-edge detect */ |
192 | ME2_INTF(2) &= ~0x08; /* " */ | 191 | ME2_INTF(2) &= ~0x08; /* " */ |
193 | 192 | ||
194 | rte_cb_init_irqs (); /* gbus &c */ | 193 | rte_cb_init_irqs (); /* gbus &c */ |
195 | } | 194 | } |
196 | 195 | ||
197 | 196 | ||
198 | /* Enable interrupt handling for interrupt IRQ. */ | 197 | /* Enable interrupt handling for interrupt IRQ. */ |
199 | void cb_pic_enable_irq (unsigned irq) | 198 | void cb_pic_enable_irq (unsigned irq) |
200 | { | 199 | { |
201 | CB_PIC_INT1M |= 1 << (irq - CB_PIC_BASE_IRQ); | 200 | CB_PIC_INT1M |= 1 << (irq - CB_PIC_BASE_IRQ); |
202 | } | 201 | } |
203 | 202 | ||
204 | void cb_pic_disable_irq (unsigned irq) | 203 | void cb_pic_disable_irq (unsigned irq) |
205 | { | 204 | { |
206 | CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ)); | 205 | CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ)); |
207 | } | 206 | } |
208 | 207 | ||
209 | void cb_pic_shutdown_irq (unsigned irq) | 208 | void cb_pic_shutdown_irq (unsigned irq) |
210 | { | 209 | { |
211 | cb_pic_disable_irq (irq); | 210 | cb_pic_disable_irq (irq); |
212 | 211 | ||
213 | if (--cb_pic_active_irqs == 0) | 212 | if (--cb_pic_active_irqs == 0) |
214 | free_irq (IRQ_CB_PIC, 0); | 213 | free_irq (IRQ_CB_PIC, 0); |
215 | 214 | ||
216 | CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ)); | 215 | CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ)); |
217 | } | 216 | } |
218 | 217 | ||
219 | static irqreturn_t cb_pic_handle_irq (int irq, void *dev_id, | 218 | static irqreturn_t cb_pic_handle_irq (int irq, void *dev_id, |
220 | struct pt_regs *regs) | 219 | struct pt_regs *regs) |
221 | { | 220 | { |
222 | irqreturn_t rval = IRQ_NONE; | 221 | irqreturn_t rval = IRQ_NONE; |
223 | unsigned status = CB_PIC_INTR; | 222 | unsigned status = CB_PIC_INTR; |
224 | unsigned enable = CB_PIC_INT1M; | 223 | unsigned enable = CB_PIC_INT1M; |
225 | 224 | ||
226 | /* Only pay attention to enabled interrupts. */ | 225 | /* Only pay attention to enabled interrupts. */ |
227 | status &= enable; | 226 | status &= enable; |
228 | 227 | ||
229 | CB_PIC_INTEN &= ~CB_PIC_INT1EN; | 228 | CB_PIC_INTEN &= ~CB_PIC_INT1EN; |
230 | 229 | ||
231 | if (status) { | 230 | if (status) { |
232 | unsigned mask = 1; | 231 | unsigned mask = 1; |
233 | 232 | ||
234 | irq = CB_PIC_BASE_IRQ; | 233 | irq = CB_PIC_BASE_IRQ; |
235 | do { | 234 | do { |
236 | /* There's an active interrupt, find out which one, | 235 | /* There's an active interrupt, find out which one, |
237 | and call its handler. */ | 236 | and call its handler. */ |
238 | while (! (status & mask)) { | 237 | while (! (status & mask)) { |
239 | irq++; | 238 | irq++; |
240 | mask <<= 1; | 239 | mask <<= 1; |
241 | } | 240 | } |
242 | status &= ~mask; | 241 | status &= ~mask; |
243 | 242 | ||
244 | CB_PIC_INTR = mask; | 243 | CB_PIC_INTR = mask; |
245 | 244 | ||
246 | /* Recursively call handle_irq to handle it. */ | 245 | /* Recursively call handle_irq to handle it. */ |
247 | handle_irq (irq, regs); | 246 | handle_irq (irq, regs); |
248 | rval = IRQ_HANDLED; | 247 | rval = IRQ_HANDLED; |
249 | } while (status); | 248 | } while (status); |
250 | } | 249 | } |
251 | 250 | ||
252 | CB_PIC_INTEN |= CB_PIC_INT1EN; | 251 | CB_PIC_INTEN |= CB_PIC_INT1EN; |
253 | 252 | ||
254 | return rval; | 253 | return rval; |
255 | } | 254 | } |
256 | 255 | ||
257 | 256 | ||
258 | static void irq_nop (unsigned irq) { } | 257 | static void irq_nop (unsigned irq) { } |
259 | 258 | ||
260 | static unsigned cb_pic_startup_irq (unsigned irq) | 259 | static unsigned cb_pic_startup_irq (unsigned irq) |
261 | { | 260 | { |
262 | int rval; | 261 | int rval; |
263 | 262 | ||
264 | if (cb_pic_active_irqs == 0) { | 263 | if (cb_pic_active_irqs == 0) { |
265 | rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq, | 264 | rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq, |
266 | IRQF_DISABLED, "cb_pic_handler", 0); | 265 | IRQF_DISABLED, "cb_pic_handler", 0); |
267 | if (rval != 0) | 266 | if (rval != 0) |
268 | return rval; | 267 | return rval; |
269 | } | 268 | } |
270 | 269 | ||
271 | cb_pic_active_irqs++; | 270 | cb_pic_active_irqs++; |
272 | 271 | ||
273 | cb_pic_enable_irq (irq); | 272 | cb_pic_enable_irq (irq); |
274 | 273 | ||
275 | return 0; | 274 | return 0; |
276 | } | 275 | } |
277 | 276 | ||
278 | /* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array | 277 | /* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array |
279 | INITS (which is terminated by an entry with the name field == 0). */ | 278 | INITS (which is terminated by an entry with the name field == 0). */ |
280 | void __init cb_pic_init_irq_types (struct cb_pic_irq_init *inits, | 279 | void __init cb_pic_init_irq_types (struct cb_pic_irq_init *inits, |
281 | struct hw_interrupt_type *hw_irq_types) | 280 | struct hw_interrupt_type *hw_irq_types) |
282 | { | 281 | { |
283 | struct cb_pic_irq_init *init; | 282 | struct cb_pic_irq_init *init; |
284 | for (init = inits; init->name; init++) { | 283 | for (init = inits; init->name; init++) { |
285 | struct hw_interrupt_type *hwit = hw_irq_types++; | 284 | struct hw_interrupt_type *hwit = hw_irq_types++; |
286 | 285 | ||
287 | hwit->typename = init->name; | 286 | hwit->typename = init->name; |
288 | 287 | ||
289 | hwit->startup = cb_pic_startup_irq; | 288 | hwit->startup = cb_pic_startup_irq; |
290 | hwit->shutdown = cb_pic_shutdown_irq; | 289 | hwit->shutdown = cb_pic_shutdown_irq; |
291 | hwit->enable = cb_pic_enable_irq; | 290 | hwit->enable = cb_pic_enable_irq; |
292 | hwit->disable = cb_pic_disable_irq; | 291 | hwit->disable = cb_pic_disable_irq; |
293 | hwit->ack = irq_nop; | 292 | hwit->ack = irq_nop; |
294 | hwit->end = irq_nop; | 293 | hwit->end = irq_nop; |
295 | 294 | ||
296 | /* Initialize kernel IRQ infrastructure for this interrupt. */ | 295 | /* Initialize kernel IRQ infrastructure for this interrupt. */ |
297 | init_irq_handlers(init->base, init->num, init->interval, hwit); | 296 | init_irq_handlers(init->base, init->num, init->interval, hwit); |
298 | } | 297 | } |
299 | } | 298 | } |
300 | 299 |
arch/v850/kernel/teg.c
1 | /* | 1 | /* |
2 | * arch/v850/kernel/teg.c -- NB85E-TEG cpu chip | 2 | * arch/v850/kernel/teg.c -- NB85E-TEG cpu chip |
3 | * | 3 | * |
4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation | 4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation |
5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/swap.h> | 17 | #include <linux/swap.h> |
18 | #include <linux/bootmem.h> | 18 | #include <linux/bootmem.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | 20 | ||
21 | #include <asm/atomic.h> | 21 | #include <asm/atomic.h> |
22 | #include <asm/page.h> | 22 | #include <asm/page.h> |
23 | #include <asm/machdep.h> | 23 | #include <asm/machdep.h> |
24 | #include <asm/v850e_timer_d.h> | 24 | #include <asm/v850e_timer_d.h> |
25 | 25 | ||
26 | #include "mach.h" | 26 | #include "mach.h" |
27 | 27 | ||
28 | void __init mach_sched_init (struct irqaction *timer_action) | 28 | void __init mach_sched_init (struct irqaction *timer_action) |
29 | { | 29 | { |
30 | /* Select timer interrupt instead of external pin. */ | 30 | /* Select timer interrupt instead of external pin. */ |
31 | TEG_ISS |= 0x1; | 31 | TEG_ISS |= 0x1; |
32 | /* Start hardware timer. */ | 32 | /* Start hardware timer. */ |
33 | v850e_timer_d_configure (0, HZ); | 33 | v850e_timer_d_configure (0, HZ); |
34 | /* Install timer interrupt handler. */ | 34 | /* Install timer interrupt handler. */ |
35 | setup_irq (IRQ_INTCMD(0), timer_action); | 35 | setup_irq (IRQ_INTCMD(0), timer_action); |
36 | } | 36 | } |
37 | 37 | ||
38 | static struct v850e_intc_irq_init irq_inits[] = { | 38 | static struct v850e_intc_irq_init irq_inits[] = { |
39 | { "IRQ", 0, NUM_CPU_IRQS, 1, 7 }, | 39 | { "IRQ", 0, NUM_CPU_IRQS, 1, 7 }, |
40 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, | 40 | { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, |
41 | { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 1, 3 }, | 41 | { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 1, 3 }, |
42 | { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 1, 4 }, | 42 | { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 1, 4 }, |
43 | { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 1, 5 }, | 43 | { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 1, 5 }, |
44 | { 0 } | 44 | { 0 } |
45 | }; | 45 | }; |
46 | #define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) | 46 | #define NUM_IRQ_INITS (ARRAY_SIZE(irq_inits) - 1) |
47 | 47 | ||
48 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; | 48 | static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; |
49 | 49 | ||
50 | /* Initialize MA chip interrupts. */ | 50 | /* Initialize MA chip interrupts. */ |
51 | void __init teg_init_irqs (void) | 51 | void __init teg_init_irqs (void) |
52 | { | 52 | { |
53 | v850e_intc_init_irq_types (irq_inits, hw_itypes); | 53 | v850e_intc_init_irq_types (irq_inits, hw_itypes); |
54 | } | 54 | } |
55 | 55 | ||
56 | /* Called before configuring an on-chip UART. */ | 56 | /* Called before configuring an on-chip UART. */ |
57 | void teg_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) | 57 | void teg_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) |
58 | { | 58 | { |
59 | /* Enable UART I/O pins instead of external interrupt pins, and | 59 | /* Enable UART I/O pins instead of external interrupt pins, and |
60 | UART interrupts instead of external pin interrupts. */ | 60 | UART interrupts instead of external pin interrupts. */ |
61 | TEG_ISS |= 0x4E; | 61 | TEG_ISS |= 0x4E; |
62 | } | 62 | } |
63 | 63 |