vserver 1.9.5.x5
[linux-2.6.git] / arch / arm / mach-clps7500 / core.c
1 /*
2  *  linux/arch/arm/mach-clps7500/core.c
3  *
4  *  Copyright (C) 1998 Russell King
5  *  Copyright (C) 1999 Nexus Electronics Ltd
6  *
7  * Extra MM routines for CL7500 architecture
8  */
9 #include <linux/kernel.h>
10 #include <linux/types.h>
11 #include <linux/interrupt.h>
12 #include <linux/list.h>
13 #include <linux/sched.h>
14 #include <linux/init.h>
15 #include <linux/serial_8250.h>
16
17 #include <asm/mach/arch.h>
18 #include <asm/mach/map.h>
19 #include <asm/mach/irq.h>
20 #include <asm/mach/time.h>
21
22 #include <asm/hardware.h>
23 #include <asm/hardware/iomd.h>
24 #include <asm/io.h>
25 #include <asm/irq.h>
26 #include <asm/mach-types.h>
27
28 static void cl7500_ack_irq_a(unsigned int irq)
29 {
30         unsigned int val, mask;
31
32         mask = 1 << irq;
33         val = iomd_readb(IOMD_IRQMASKA);
34         iomd_writeb(val & ~mask, IOMD_IRQMASKA);
35         iomd_writeb(mask, IOMD_IRQCLRA);
36 }
37
38 static void cl7500_mask_irq_a(unsigned int irq)
39 {
40         unsigned int val, mask;
41
42         mask = 1 << irq;
43         val = iomd_readb(IOMD_IRQMASKA);
44         iomd_writeb(val & ~mask, IOMD_IRQMASKA);
45 }
46
47 static void cl7500_unmask_irq_a(unsigned int irq)
48 {
49         unsigned int val, mask;
50
51         mask = 1 << irq;
52         val = iomd_readb(IOMD_IRQMASKA);
53         iomd_writeb(val | mask, IOMD_IRQMASKA);
54 }
55
56 static struct irqchip clps7500_a_chip = {
57         .ack    = cl7500_ack_irq_a,
58         .mask   = cl7500_mask_irq_a,
59         .unmask = cl7500_unmask_irq_a,
60 };
61
62 static void cl7500_mask_irq_b(unsigned int irq)
63 {
64         unsigned int val, mask;
65
66         mask = 1 << (irq & 7);
67         val = iomd_readb(IOMD_IRQMASKB);
68         iomd_writeb(val & ~mask, IOMD_IRQMASKB);
69 }
70
71 static void cl7500_unmask_irq_b(unsigned int irq)
72 {
73         unsigned int val, mask;
74
75         mask = 1 << (irq & 7);
76         val = iomd_readb(IOMD_IRQMASKB);
77         iomd_writeb(val | mask, IOMD_IRQMASKB);
78 }
79
80 static struct irqchip clps7500_b_chip = {
81         .ack    = cl7500_mask_irq_b,
82         .mask   = cl7500_mask_irq_b,
83         .unmask = cl7500_unmask_irq_b,
84 };
85
86 static void cl7500_mask_irq_c(unsigned int irq)
87 {
88         unsigned int val, mask;
89
90         mask = 1 << (irq & 7);
91         val = iomd_readb(IOMD_IRQMASKC);
92         iomd_writeb(val & ~mask, IOMD_IRQMASKC);
93 }
94
95 static void cl7500_unmask_irq_c(unsigned int irq)
96 {
97         unsigned int val, mask;
98
99         mask = 1 << (irq & 7);
100         val = iomd_readb(IOMD_IRQMASKC);
101         iomd_writeb(val | mask, IOMD_IRQMASKC);
102 }
103
104 static struct irqchip clps7500_c_chip = {
105         .ack    = cl7500_mask_irq_c,
106         .mask   = cl7500_mask_irq_c,
107         .unmask = cl7500_unmask_irq_c,
108 };
109
110 static void cl7500_mask_irq_d(unsigned int irq)
111 {
112         unsigned int val, mask;
113
114         mask = 1 << (irq & 7);
115         val = iomd_readb(IOMD_IRQMASKD);
116         iomd_writeb(val & ~mask, IOMD_IRQMASKD);
117 }
118
119 static void cl7500_unmask_irq_d(unsigned int irq)
120 {
121         unsigned int val, mask;
122
123         mask = 1 << (irq & 7);
124         val = iomd_readb(IOMD_IRQMASKD);
125         iomd_writeb(val | mask, IOMD_IRQMASKD);
126 }
127
128 static struct irqchip clps7500_d_chip = {
129         .ack    = cl7500_mask_irq_d,
130         .mask   = cl7500_mask_irq_d,
131         .unmask = cl7500_unmask_irq_d,
132 };
133
134 static void cl7500_mask_irq_dma(unsigned int irq)
135 {
136         unsigned int val, mask;
137
138         mask = 1 << (irq & 7);
139         val = iomd_readb(IOMD_DMAMASK);
140         iomd_writeb(val & ~mask, IOMD_DMAMASK);
141 }
142
143 static void cl7500_unmask_irq_dma(unsigned int irq)
144 {
145         unsigned int val, mask;
146
147         mask = 1 << (irq & 7);
148         val = iomd_readb(IOMD_DMAMASK);
149         iomd_writeb(val | mask, IOMD_DMAMASK);
150 }
151
152 static struct irqchip clps7500_dma_chip = {
153         .ack    = cl7500_mask_irq_dma,
154         .mask   = cl7500_mask_irq_dma,
155         .unmask = cl7500_unmask_irq_dma,
156 };
157
158 static void cl7500_mask_irq_fiq(unsigned int irq)
159 {
160         unsigned int val, mask;
161
162         mask = 1 << (irq & 7);
163         val = iomd_readb(IOMD_FIQMASK);
164         iomd_writeb(val & ~mask, IOMD_FIQMASK);
165 }
166
167 static void cl7500_unmask_irq_fiq(unsigned int irq)
168 {
169         unsigned int val, mask;
170
171         mask = 1 << (irq & 7);
172         val = iomd_readb(IOMD_FIQMASK);
173         iomd_writeb(val | mask, IOMD_FIQMASK);
174 }
175
176 static struct irqchip clps7500_fiq_chip = {
177         .ack    = cl7500_mask_irq_fiq,
178         .mask   = cl7500_mask_irq_fiq,
179         .unmask = cl7500_unmask_irq_fiq,
180 };
181
182 static void cl7500_no_action(unsigned int irq)
183 {
184 }
185
186 static struct irqchip clps7500_no_chip = {
187         .ack    = cl7500_no_action,
188         .mask   = cl7500_no_action,
189         .unmask = cl7500_no_action,
190 };
191
192 static struct irqaction irq_isa = { no_action, 0, CPU_MASK_NONE, "isa", NULL, NULL };
193
194 static void __init clps7500_init_irq(void)
195 {
196         unsigned int irq, flags;
197
198         iomd_writeb(0, IOMD_IRQMASKA);
199         iomd_writeb(0, IOMD_IRQMASKB);
200         iomd_writeb(0, IOMD_FIQMASK);
201         iomd_writeb(0, IOMD_DMAMASK);
202
203         for (irq = 0; irq < NR_IRQS; irq++) {
204                 flags = IRQF_VALID;
205
206                 if (irq <= 6 || (irq >= 9 && irq <= 15) ||
207                     (irq >= 48 && irq <= 55))
208                         flags |= IRQF_PROBE;
209
210                 switch (irq) {
211                 case 0 ... 7:
212                         set_irq_chip(irq, &clps7500_a_chip);
213                         set_irq_handler(irq, do_level_IRQ);
214                         set_irq_flags(irq, flags);
215                         break;
216
217                 case 8 ... 15:
218                         set_irq_chip(irq, &clps7500_b_chip);
219                         set_irq_handler(irq, do_level_IRQ);
220                         set_irq_flags(irq, flags);
221                         break;
222
223                 case 16 ... 22:
224                         set_irq_chip(irq, &clps7500_dma_chip);
225                         set_irq_handler(irq, do_level_IRQ);
226                         set_irq_flags(irq, flags);
227                         break;
228
229                 case 24 ... 31:
230                         set_irq_chip(irq, &clps7500_c_chip);
231                         set_irq_handler(irq, do_level_IRQ);
232                         set_irq_flags(irq, flags);
233                         break;
234
235                 case 40 ... 47:
236                         set_irq_chip(irq, &clps7500_d_chip);
237                         set_irq_handler(irq, do_level_IRQ);
238                         set_irq_flags(irq, flags);
239                         break;
240
241                 case 48 ... 55:
242                         set_irq_chip(irq, &clps7500_no_chip);
243                         set_irq_handler(irq, do_level_IRQ);
244                         set_irq_flags(irq, flags);
245                         break;
246
247                 case 64 ... 72:
248                         set_irq_chip(irq, &clps7500_fiq_chip);
249                         set_irq_handler(irq, do_level_IRQ);
250                         set_irq_flags(irq, flags);
251                         break;
252                 }
253         }
254
255         setup_irq(IRQ_ISA, &irq_isa);
256 }
257
258 static struct map_desc cl7500_io_desc[] __initdata = {
259         { IO_BASE,      IO_START,       IO_SIZE,    MT_DEVICE },        /* IO space     */
260         { ISA_BASE,     ISA_START,      ISA_SIZE,   MT_DEVICE },        /* ISA space    */
261         { FLASH_BASE,   FLASH_START,    FLASH_SIZE, MT_DEVICE },        /* Flash        */
262         { LED_BASE,     LED_START,      LED_SIZE,   MT_DEVICE }         /* LED          */
263 };
264
265 static void __init clps7500_map_io(void)
266 {
267         iotable_init(cl7500_io_desc, ARRAY_SIZE(cl7500_io_desc));
268 }
269
270 extern void ioctime_init(void);
271 extern unsigned long ioc_timer_gettimeoffset(void);
272
273 static irqreturn_t
274 clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
275 {
276         write_seqlock(&xtime_lock);
277
278         timer_tick(regs);
279
280         /* Why not using do_leds interface?? */
281         {
282                 /* Twinkle the lights. */
283                 static int count, state = 0xff00;
284                 if (count-- == 0) {
285                         state ^= 0x100;
286                         count = 25;
287                         *((volatile unsigned int *)LED_ADDRESS) = state;
288                 }
289         }
290
291         write_sequnlock(&xtime_lock);
292
293         return IRQ_HANDLED;
294 }
295
296 static struct irqaction clps7500_timer_irq = {
297         .name           = "CLPS7500 Timer Tick",
298         .flags          = SA_INTERRUPT,
299         .handler        = clps7500_timer_interrupt
300 };
301
302 /*
303  * Set up timer interrupt.
304  */
305 static void __init clps7500_timer_init(void)
306 {
307         ioctime_init();
308
309         setup_irq(IRQ_TIMER, &clps7500_timer_irq);
310 }
311
312 static struct clps7500_timer = {
313         .init           = clps7500_timer_init,
314         .offset         = ioc_timer_gettimeoffset,
315 };
316
317 static struct plat_serial8250_port serial_platform_data[] = {
318         {
319                 .mapbase        = 0x03010fe0,
320                 .irq            = 10,
321                 .uartclk        = 1843200,
322                 .regshift       = 2,
323                 .iotype         = UPIO_MEM,
324                 .flags          = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST,
325         },
326         {
327                 .mapbase        = 0x03010be0,
328                 .irq            = 0,
329                 .uartclk        = 1843200,
330                 .regshift       = 2,
331                 .iotype         = UPIO_MEM,
332                 .flags          = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST,
333         },
334         {
335                 .iobase         = ISASLOT_IO + 0x2e8,
336                 .irq            = 41,
337                 .uartclk        = 1843200,
338                 .regshift       = 0,
339                 .iotype         = UPIO_PORT,
340                 .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
341         },
342         {
343                 .iobase         = ISASLOT_IO + 0x3e8,
344                 .irq            = 40,
345                 .uartclk        = 1843200,
346                 .regshift       = 0,
347                 .iotype         = UPIO_PORT,
348                 .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
349         },
350         { },
351 };
352
353 static struct platform_device serial_device = {
354         .name                   = "serial8250",
355         .id                     = 0,
356         .dev                    = {
357                 .platform_data  = serial_platform_data,
358         },
359 };
360
361 static int __init clps7500_init(void)
362 {
363         return platform_register_device(&serial_device);
364 }
365
366 MACHINE_START(CLPS7500, "CL-PS7500")
367         MAINTAINER("Philip Blundell")
368         BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
369         MAPIO(clps7500_map_io)
370         INITIRQ(clps7500_init_irq)
371         .timer          = &clps7500_timer,
372 MACHINE_END
373