1
2
3
4
5
6
7
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
28static 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
38static 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
47static 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
56static 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
62static 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
71static 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
80static 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
86static 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
95static 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
104static 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
110static 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
119static 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
128static 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
134static 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
143static 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
152static 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
158static 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
167static 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
176static 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
182static void cl7500_no_action(unsigned int irq)
183{
184}
185
186static struct irqchip clps7500_no_chip = {
187 .ack = cl7500_no_action,
188 .mask = cl7500_no_action,
189 .unmask = cl7500_no_action,
190};
191
192static struct irqaction irq_isa = { no_action, 0, CPU_MASK_NONE, "isa", NULL, NULL };
193
194static 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
258static struct map_desc cl7500_io_desc[] __initdata = {
259 { IO_BASE, IO_START, IO_SIZE, MT_DEVICE },
260 { ISA_BASE, ISA_START, ISA_SIZE, MT_DEVICE },
261 { FLASH_BASE, FLASH_START, FLASH_SIZE, MT_DEVICE },
262 { LED_BASE, LED_START, LED_SIZE, MT_DEVICE }
263};
264
265static void __init clps7500_map_io(void)
266{
267 iotable_init(cl7500_io_desc, ARRAY_SIZE(cl7500_io_desc));
268}
269
270extern void ioctime_init(void);
271extern unsigned long ioc_timer_gettimeoffset(void);
272
273static irqreturn_t
274clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
275{
276 write_seqlock(&xtime_lock);
277
278 timer_tick(regs);
279
280
281 {
282
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
296static struct irqaction clps7500_timer_irq = {
297 .name = "CLPS7500 Timer Tick",
298 .flags = SA_INTERRUPT,
299 .handler = clps7500_timer_interrupt
300};
301
302
303
304
305static void __init clps7500_timer_init(void)
306{
307 ioctime_init();
308
309 setup_irq(IRQ_TIMER, &clps7500_timer_irq);
310}
311
312static struct clps7500_timer = {
313 .init = clps7500_timer_init,
314 .offset = ioc_timer_gettimeoffset,
315};
316
317static 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
353static struct platform_device serial_device = {
354 .name = "serial8250",
355 .id = 0,
356 .dev = {
357 .platform_data = serial_platform_data,
358 },
359};
360
361static int __init clps7500_init(void)
362{
363 return platform_register_device(&serial_device);
364}
365
366MACHINE_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,
372MACHINE_END
373
374