Linux-2.6.12-rc2
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / v850 / kernel / rte_me2_cb.c
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 \f
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 \f
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 \f
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 }