VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[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
16 #include <asm/mach/arch.h>
17 #include <asm/mach/map.h>
18 #include <asm/mach/irq.h>
19 #include <asm/mach/time.h>
20
21 #include <asm/hardware.h>
22 #include <asm/hardware/iomd.h>
23 #include <asm/io.h>
24 #include <asm/irq.h>
25 #include <asm/mach-types.h>
26
27 static void cl7500_ack_irq_a(unsigned int irq)
28 {
29         unsigned int val, mask;
30
31         mask = 1 << irq;
32         val = iomd_readb(IOMD_IRQMASKA);
33         iomd_writeb(val & ~mask, IOMD_IRQMASKA);
34         iomd_writeb(mask, IOMD_IRQCLRA);
35 }
36
37 static void cl7500_mask_irq_a(unsigned int irq)
38 {
39         unsigned int val, mask;
40
41         mask = 1 << irq;
42         val = iomd_readb(IOMD_IRQMASKA);
43         iomd_writeb(val & ~mask, IOMD_IRQMASKA);
44 }
45
46 static void cl7500_unmask_irq_a(unsigned int irq)
47 {
48         unsigned int val, mask;
49
50         mask = 1 << irq;
51         val = iomd_readb(IOMD_IRQMASKA);
52         iomd_writeb(val | mask, IOMD_IRQMASKA);
53 }
54
55 static struct irqchip clps7500_a_chip = {
56         .ack    = cl7500_ack_irq_a,
57         .mask   = cl7500_mask_irq_a,
58         .unmask = cl7500_unmask_irq_a,
59 };
60
61 static void cl7500_mask_irq_b(unsigned int irq)
62 {
63         unsigned int val, mask;
64
65         mask = 1 << (irq & 7);
66         val = iomd_readb(IOMD_IRQMASKB);
67         iomd_writeb(val & ~mask, IOMD_IRQMASKB);
68 }
69
70 static void cl7500_unmask_irq_b(unsigned int irq)
71 {
72         unsigned int val, mask;
73
74         mask = 1 << (irq & 7);
75         val = iomd_readb(IOMD_IRQMASKB);
76         iomd_writeb(val | mask, IOMD_IRQMASKB);
77 }
78
79 static struct irqchip clps7500_b_chip = {
80         .ack    = cl7500_mask_irq_b,
81         .mask   = cl7500_mask_irq_b,
82         .unmask = cl7500_unmask_irq_b,
83 };
84
85 static void cl7500_mask_irq_c(unsigned int irq)
86 {
87         unsigned int val, mask;
88
89         mask = 1 << (irq & 7);
90         val = iomd_readb(IOMD_IRQMASKC);
91         iomd_writeb(val & ~mask, IOMD_IRQMASKC);
92 }
93
94 static void cl7500_unmask_irq_c(unsigned int irq)
95 {
96         unsigned int val, mask;
97
98         mask = 1 << (irq & 7);
99         val = iomd_readb(IOMD_IRQMASKC);
100         iomd_writeb(val | mask, IOMD_IRQMASKC);
101 }
102
103 static struct irqchip clps7500_c_chip = {
104         .ack    = cl7500_mask_irq_c,
105         .mask   = cl7500_mask_irq_c,
106         .unmask = cl7500_unmask_irq_c,
107 };
108
109 static void cl7500_mask_irq_d(unsigned int irq)
110 {
111         unsigned int val, mask;
112
113         mask = 1 << (irq & 7);
114         val = iomd_readb(IOMD_IRQMASKD);
115         iomd_writeb(val & ~mask, IOMD_IRQMASKD);
116 }
117
118 static void cl7500_unmask_irq_d(unsigned int irq)
119 {
120         unsigned int val, mask;
121
122         mask = 1 << (irq & 7);
123         val = iomd_readb(IOMD_IRQMASKD);
124         iomd_writeb(val | mask, IOMD_IRQMASKD);
125 }
126
127 static struct irqchip clps7500_d_chip = {
128         .ack    = cl7500_mask_irq_d,
129         .mask   = cl7500_mask_irq_d,
130         .unmask = cl7500_unmask_irq_d,
131 };
132
133 static void cl7500_mask_irq_dma(unsigned int irq)
134 {
135         unsigned int val, mask;
136
137         mask = 1 << (irq & 7);
138         val = iomd_readb(IOMD_DMAMASK);
139         iomd_writeb(val & ~mask, IOMD_DMAMASK);
140 }
141
142 static void cl7500_unmask_irq_dma(unsigned int irq)
143 {
144         unsigned int val, mask;
145
146         mask = 1 << (irq & 7);
147         val = iomd_readb(IOMD_DMAMASK);
148         iomd_writeb(val | mask, IOMD_DMAMASK);
149 }
150
151 static struct irqchip clps7500_dma_chip = {
152         .ack    = cl7500_mask_irq_dma,
153         .mask   = cl7500_mask_irq_dma,
154         .unmask = cl7500_unmask_irq_dma,
155 };
156
157 static void cl7500_mask_irq_fiq(unsigned int irq)
158 {
159         unsigned int val, mask;
160
161         mask = 1 << (irq & 7);
162         val = iomd_readb(IOMD_FIQMASK);
163         iomd_writeb(val & ~mask, IOMD_FIQMASK);
164 }
165
166 static void cl7500_unmask_irq_fiq(unsigned int irq)
167 {
168         unsigned int val, mask;
169
170         mask = 1 << (irq & 7);
171         val = iomd_readb(IOMD_FIQMASK);
172         iomd_writeb(val | mask, IOMD_FIQMASK);
173 }
174
175 static struct irqchip clps7500_fiq_chip = {
176         .ack    = cl7500_mask_irq_fiq,
177         .mask   = cl7500_mask_irq_fiq,
178         .unmask = cl7500_unmask_irq_fiq,
179 };
180
181 static void cl7500_no_action(unsigned int irq)
182 {
183 }
184
185 static struct irqchip clps7500_no_chip = {
186         .ack    = cl7500_no_action,
187         .mask   = cl7500_no_action,
188         .unmask = cl7500_no_action,
189 };
190
191 static struct irqaction irq_isa = { no_action, 0, CPU_MASK_NONE, "isa", NULL, NULL };
192
193 static void __init clps7500_init_irq(void)
194 {
195         unsigned int irq, flags;
196
197         iomd_writeb(0, IOMD_IRQMASKA);
198         iomd_writeb(0, IOMD_IRQMASKB);
199         iomd_writeb(0, IOMD_FIQMASK);
200         iomd_writeb(0, IOMD_DMAMASK);
201
202         for (irq = 0; irq < NR_IRQS; irq++) {
203                 flags = IRQF_VALID;
204
205                 if (irq <= 6 || (irq >= 9 && irq <= 15) ||
206                     (irq >= 48 && irq <= 55))
207                         flags |= IRQF_PROBE;
208
209                 switch (irq) {
210                 case 0 ... 7:
211                         set_irq_chip(irq, &clps7500_a_chip);
212                         set_irq_handler(irq, do_level_IRQ);
213                         set_irq_flags(irq, flags);
214                         break;
215
216                 case 8 ... 15:
217                         set_irq_chip(irq, &clps7500_b_chip);
218                         set_irq_handler(irq, do_level_IRQ);
219                         set_irq_flags(irq, flags);
220                         break;
221
222                 case 16 ... 22:
223                         set_irq_chip(irq, &clps7500_dma_chip);
224                         set_irq_handler(irq, do_level_IRQ);
225                         set_irq_flags(irq, flags);
226                         break;
227
228                 case 24 ... 31:
229                         set_irq_chip(irq, &clps7500_c_chip);
230                         set_irq_handler(irq, do_level_IRQ);
231                         set_irq_flags(irq, flags);
232                         break;
233
234                 case 40 ... 47:
235                         set_irq_chip(irq, &clps7500_d_chip);
236                         set_irq_handler(irq, do_level_IRQ);
237                         set_irq_flags(irq, flags);
238                         break;
239
240                 case 48 ... 55:
241                         set_irq_chip(irq, &clps7500_no_chip);
242                         set_irq_handler(irq, do_level_IRQ);
243                         set_irq_flags(irq, flags);
244                         break;
245
246                 case 64 ... 72:
247                         set_irq_chip(irq, &clps7500_fiq_chip);
248                         set_irq_handler(irq, do_level_IRQ);
249                         set_irq_flags(irq, flags);
250                         break;
251                 }
252         }
253
254         setup_irq(IRQ_ISA, &irq_isa);
255 }
256
257 static struct map_desc cl7500_io_desc[] __initdata = {
258         { IO_BASE,      IO_START,       IO_SIZE,    MT_DEVICE },        /* IO space     */
259         { ISA_BASE,     ISA_START,      ISA_SIZE,   MT_DEVICE },        /* ISA space    */
260         { FLASH_BASE,   FLASH_START,    FLASH_SIZE, MT_DEVICE },        /* Flash        */
261         { LED_BASE,     LED_START,      LED_SIZE,   MT_DEVICE }         /* LED          */
262 };
263
264 static void __init clps7500_map_io(void)
265 {
266         iotable_init(cl7500_io_desc, ARRAY_SIZE(cl7500_io_desc));
267 }
268
269 extern void ioctime_init(void);
270
271 static irqreturn_t
272 clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
273 {
274         timer_tick(regs);
275
276         /* Why not using do_leds interface?? */
277         {
278                 /* Twinkle the lights. */
279                 static int count, state = 0xff00;
280                 if (count-- == 0) {
281                         state ^= 0x100;
282                         count = 25;
283                         *((volatile unsigned int *)LED_ADDRESS) = state;
284                 }
285         }
286         return IRQ_HANDLED;
287 }
288
289 static struct irqaction clps7500_timer_irq = {
290         .name           = "CLPS7500 Timer Tick",
291         .flags          = SA_INTERRUPT,
292         .handler        = clps7500_timer_interrupt
293 };
294
295 /*
296  * Set up timer interrupt.
297  */
298 void __init clps7500_init_time(void)
299 {
300         ioctime_init();
301
302         setup_irq(IRQ_TIMER, &clps7500_timer_irq);
303 }
304
305 MACHINE_START(CLPS7500, "CL-PS7500")
306         MAINTAINER("Philip Blundell")
307         BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
308         MAPIO(clps7500_map_io)
309         INITIRQ(clps7500_init_irq)
310         INITTIME(clps7500_init_time)
311 MACHINE_END
312