diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/v850/kernel/rte_me2_cb.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/v850/kernel/rte_me2_cb.c')
-rw-r--r-- | arch/v850/kernel/rte_me2_cb.c | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/arch/v850/kernel/rte_me2_cb.c b/arch/v850/kernel/rte_me2_cb.c new file mode 100644 index 000000000000..faaf3d95e6cf --- /dev/null +++ b/arch/v850/kernel/rte_me2_cb.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * arch/v850/kernel/rte_me2_cb.c -- Midas labs RTE-V850E/ME2-CB board | ||
3 | * | ||
4 | * Copyright (C) 2001,02,03 NEC Electronics Corporation | ||
5 | * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> | ||
6 | * | ||
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 | ||
9 | * archive for more details. | ||
10 | * | ||
11 | * Written by Miles Bader <miles@gnu.org> | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/bootmem.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/major.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/delay.h> | ||
23 | |||
24 | #include <asm/atomic.h> | ||
25 | #include <asm/page.h> | ||
26 | #include <asm/me2.h> | ||
27 | #include <asm/rte_me2_cb.h> | ||
28 | #include <asm/machdep.h> | ||
29 | #include <asm/v850e_intc.h> | ||
30 | #include <asm/v850e_cache.h> | ||
31 | #include <asm/irq.h> | ||
32 | |||
33 | #include "mach.h" | ||
34 | |||
35 | extern unsigned long *_intv_start; | ||
36 | extern unsigned long *_intv_end; | ||
37 | |||
38 | /* LED access routines. */ | ||
39 | extern unsigned read_leds (int pos, char *buf, int len); | ||
40 | extern unsigned write_leds (int pos, const char *buf, int len); | ||
41 | |||
42 | |||
43 | /* SDRAM are almost contiguous (with a small hole in between; | ||
44 | see mach_reserve_bootmem for details), so just use both as one big area. */ | ||
45 | #define RAM_START SDRAM_ADDR | ||
46 | #define RAM_END (SDRAM_ADDR + SDRAM_SIZE) | ||
47 | |||
48 | |||
49 | void __init mach_get_physical_ram (unsigned long *ram_start, | ||
50 | unsigned long *ram_len) | ||
51 | { | ||
52 | *ram_start = RAM_START; | ||
53 | *ram_len = RAM_END - RAM_START; | ||
54 | } | ||
55 | |||
56 | void mach_gettimeofday (struct timespec *tv) | ||
57 | { | ||
58 | tv->tv_sec = 0; | ||
59 | tv->tv_nsec = 0; | ||
60 | } | ||
61 | |||
62 | /* Called before configuring an on-chip UART. */ | ||
63 | void rte_me2_cb_uart_pre_configure (unsigned chan, | ||
64 | unsigned cflags, unsigned baud) | ||
65 | { | ||
66 | /* The RTE-V850E/ME2-CB connects some general-purpose I/O | ||
67 | pins on the CPU to the RTS/CTS lines of UARTB channel 0's | ||
68 | serial connection. | ||
69 | I/O pins P21 and P22 are RTS and CTS respectively. */ | ||
70 | if (chan == 0) { | ||
71 | /* Put P21 & P22 in I/O port mode. */ | ||
72 | ME2_PORT2_PMC &= ~0x6; | ||
73 | /* Make P21 and output, and P22 an input. */ | ||
74 | ME2_PORT2_PM = (ME2_PORT2_PM & ~0xC) | 0x4; | ||
75 | } | ||
76 | |||
77 | me2_uart_pre_configure (chan, cflags, baud); | ||
78 | } | ||
79 | |||
80 | void __init mach_init_irqs (void) | ||
81 | { | ||
82 | /* Initialize interrupts. */ | ||
83 | me2_init_irqs (); | ||
84 | rte_me2_cb_init_irqs (); | ||
85 | } | ||
86 | |||
87 | #ifdef CONFIG_ROM_KERNEL | ||
88 | /* Initialization for kernel in ROM. */ | ||
89 | static inline rom_kernel_init (void) | ||
90 | { | ||
91 | /* If the kernel is in ROM, we have to copy any initialized data | ||
92 | from ROM into RAM. */ | ||
93 | extern unsigned long _data_load_start, _sdata, _edata; | ||
94 | register unsigned long *src = &_data_load_start; | ||
95 | register unsigned long *dst = &_sdata, *end = &_edata; | ||
96 | |||
97 | while (dst != end) | ||
98 | *dst++ = *src++; | ||
99 | } | ||
100 | #endif /* CONFIG_ROM_KERNEL */ | ||
101 | |||
102 | static void install_interrupt_vectors (void) | ||
103 | { | ||
104 | unsigned long *p1, *p2; | ||
105 | |||
106 | ME2_IRAMM = 0x03; /* V850E/ME2 iRAM write mode */ | ||
107 | |||
108 | /* vector copy to iRAM */ | ||
109 | p1 = (unsigned long *)0; /* v85x vector start */ | ||
110 | p2 = (unsigned long *)&_intv_start; | ||
111 | while (p2 < (unsigned long *)&_intv_end) | ||
112 | *p1++ = *p2++; | ||
113 | |||
114 | ME2_IRAMM = 0x00; /* V850E/ME2 iRAM read mode */ | ||
115 | } | ||
116 | |||
117 | /* CompactFlash */ | ||
118 | |||
119 | static void cf_power_on (void) | ||
120 | { | ||
121 | /* CF card detected? */ | ||
122 | if (CB_CF_STS0 & 0x0030) | ||
123 | return; | ||
124 | |||
125 | CB_CF_REG0 = 0x0002; /* reest on */ | ||
126 | mdelay (10); | ||
127 | CB_CF_REG0 = 0x0003; /* power on */ | ||
128 | mdelay (10); | ||
129 | CB_CF_REG0 = 0x0001; /* reset off */ | ||
130 | mdelay (10); | ||
131 | } | ||
132 | |||
133 | static void cf_power_off (void) | ||
134 | { | ||
135 | CB_CF_REG0 = 0x0003; /* power on */ | ||
136 | mdelay (10); | ||
137 | CB_CF_REG0 = 0x0002; /* reest on */ | ||
138 | mdelay (10); | ||
139 | } | ||
140 | |||
141 | void __init mach_early_init (void) | ||
142 | { | ||
143 | install_interrupt_vectors (); | ||
144 | |||
145 | /* CS1 SDRAM instruction cache enable */ | ||
146 | v850e_cache_enable (0x04, 0x03, 0); | ||
147 | |||
148 | rte_cb_early_init (); | ||
149 | |||
150 | /* CompactFlash power on */ | ||
151 | cf_power_on (); | ||
152 | |||
153 | #if defined (CONFIG_ROM_KERNEL) | ||
154 | rom_kernel_init (); | ||
155 | #endif | ||
156 | } | ||
157 | |||
158 | |||
159 | /* RTE-V850E/ME2-CB Programmable Interrupt Controller. */ | ||
160 | |||
161 | static struct cb_pic_irq_init cb_pic_irq_inits[] = { | ||
162 | { "CB_EXTTM0", IRQ_CB_EXTTM0, 1, 1, 6 }, | ||
163 | { "CB_EXTSIO", IRQ_CB_EXTSIO, 1, 1, 6 }, | ||
164 | { "CB_TOVER", IRQ_CB_TOVER, 1, 1, 6 }, | ||
165 | { "CB_GINT0", IRQ_CB_GINT0, 1, 1, 6 }, | ||
166 | { "CB_USB", IRQ_CB_USB, 1, 1, 6 }, | ||
167 | { "CB_LANC", IRQ_CB_LANC, 1, 1, 6 }, | ||
168 | { "CB_USB_VBUS_ON", IRQ_CB_USB_VBUS_ON, 1, 1, 6 }, | ||
169 | { "CB_USB_VBUS_OFF", IRQ_CB_USB_VBUS_OFF, 1, 1, 6 }, | ||
170 | { "CB_EXTTM1", IRQ_CB_EXTTM1, 1, 1, 6 }, | ||
171 | { "CB_EXTTM2", IRQ_CB_EXTTM2, 1, 1, 6 }, | ||
172 | { 0 } | ||
173 | }; | ||
174 | #define NUM_CB_PIC_IRQ_INITS \ | ||
175 | ((sizeof cb_pic_irq_inits / sizeof cb_pic_irq_inits[0]) - 1) | ||
176 | |||
177 | static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS]; | ||
178 | static unsigned char cb_pic_active_irqs = 0; | ||
179 | |||
180 | void __init rte_me2_cb_init_irqs (void) | ||
181 | { | ||
182 | cb_pic_init_irq_types (cb_pic_irq_inits, cb_pic_hw_itypes); | ||
183 | |||
184 | /* Initalize on board PIC1 (not PIC0) enable */ | ||
185 | CB_PIC_INT0M = 0x0000; | ||
186 | CB_PIC_INT1M = 0x0000; | ||
187 | CB_PIC_INTR = 0x0000; | ||
188 | CB_PIC_INTEN |= CB_PIC_INT1EN; | ||
189 | |||
190 | ME2_PORT2_PMC |= 0x08; /* INTP23/SCK1 mode */ | ||
191 | ME2_PORT2_PFC &= ~0x08; /* INTP23 mode */ | ||
192 | ME2_INTR(2) &= ~0x08; /* INTP23 falling-edge detect */ | ||
193 | ME2_INTF(2) &= ~0x08; /* " */ | ||
194 | |||
195 | rte_cb_init_irqs (); /* gbus &c */ | ||
196 | } | ||
197 | |||
198 | |||
199 | /* Enable interrupt handling for interrupt IRQ. */ | ||
200 | void cb_pic_enable_irq (unsigned irq) | ||
201 | { | ||
202 | CB_PIC_INT1M |= 1 << (irq - CB_PIC_BASE_IRQ); | ||
203 | } | ||
204 | |||
205 | void cb_pic_disable_irq (unsigned irq) | ||
206 | { | ||
207 | CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ)); | ||
208 | } | ||
209 | |||
210 | void cb_pic_shutdown_irq (unsigned irq) | ||
211 | { | ||
212 | cb_pic_disable_irq (irq); | ||
213 | |||
214 | if (--cb_pic_active_irqs == 0) | ||
215 | free_irq (IRQ_CB_PIC, 0); | ||
216 | |||
217 | CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ)); | ||
218 | } | ||
219 | |||
220 | static irqreturn_t cb_pic_handle_irq (int irq, void *dev_id, | ||
221 | struct pt_regs *regs) | ||
222 | { | ||
223 | irqreturn_t rval = IRQ_NONE; | ||
224 | unsigned status = CB_PIC_INTR; | ||
225 | unsigned enable = CB_PIC_INT1M; | ||
226 | |||
227 | /* Only pay attention to enabled interrupts. */ | ||
228 | status &= enable; | ||
229 | |||
230 | CB_PIC_INTEN &= ~CB_PIC_INT1EN; | ||
231 | |||
232 | if (status) { | ||
233 | unsigned mask = 1; | ||
234 | |||
235 | irq = CB_PIC_BASE_IRQ; | ||
236 | do { | ||
237 | /* There's an active interrupt, find out which one, | ||
238 | and call its handler. */ | ||
239 | while (! (status & mask)) { | ||
240 | irq++; | ||
241 | mask <<= 1; | ||
242 | } | ||
243 | status &= ~mask; | ||
244 | |||
245 | CB_PIC_INTR = mask; | ||
246 | |||
247 | /* Recursively call handle_irq to handle it. */ | ||
248 | handle_irq (irq, regs); | ||
249 | rval = IRQ_HANDLED; | ||
250 | } while (status); | ||
251 | } | ||
252 | |||
253 | CB_PIC_INTEN |= CB_PIC_INT1EN; | ||
254 | |||
255 | return rval; | ||
256 | } | ||
257 | |||
258 | |||
259 | static void irq_nop (unsigned irq) { } | ||
260 | |||
261 | static unsigned cb_pic_startup_irq (unsigned irq) | ||
262 | { | ||
263 | int rval; | ||
264 | |||
265 | if (cb_pic_active_irqs == 0) { | ||
266 | rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq, | ||
267 | SA_INTERRUPT, "cb_pic_handler", 0); | ||
268 | if (rval != 0) | ||
269 | return rval; | ||
270 | } | ||
271 | |||
272 | cb_pic_active_irqs++; | ||
273 | |||
274 | cb_pic_enable_irq (irq); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | /* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array | ||
280 | INITS (which is terminated by an entry with the name field == 0). */ | ||
281 | void __init cb_pic_init_irq_types (struct cb_pic_irq_init *inits, | ||
282 | struct hw_interrupt_type *hw_irq_types) | ||
283 | { | ||
284 | struct cb_pic_irq_init *init; | ||
285 | for (init = inits; init->name; init++) { | ||
286 | struct hw_interrupt_type *hwit = hw_irq_types++; | ||
287 | |||
288 | hwit->typename = init->name; | ||
289 | |||
290 | hwit->startup = cb_pic_startup_irq; | ||
291 | hwit->shutdown = cb_pic_shutdown_irq; | ||
292 | hwit->enable = cb_pic_enable_irq; | ||
293 | hwit->disable = cb_pic_disable_irq; | ||
294 | hwit->ack = irq_nop; | ||
295 | hwit->end = irq_nop; | ||
296 | |||
297 | /* Initialize kernel IRQ infrastructure for this interrupt. */ | ||
298 | init_irq_handlers(init->base, init->num, init->interval, hwit); | ||
299 | } | ||
300 | } | ||