2 * linux/arch/arm/mach-aaec2000/core.c
4 * Code common to all AAEC-2000 machines
6 * Copyright (c) 2005 Nicolas Bellido Y Ortega
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 #include <linux/config.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/list.h>
17 #include <linux/errno.h>
18 #include <linux/interrupt.h>
19 #include <linux/timex.h>
20 #include <linux/signal.h>
22 #include <asm/hardware.h>
25 #include <asm/mach/irq.h>
26 #include <asm/mach/time.h>
27 #include <asm/mach/map.h>
32 * Static virtual address mappings are as follow:
34 * 0xf8000000-0xf8001ffff: Devices connected to APB bus
35 * 0xf8002000-0xf8003ffff: Devices connected to AHB bus
37 * Below 0xe8000000 is reserved for vm allocation.
39 * The machine specific code must provide the extra mapping beside the
40 * default mapping provided here.
42 static struct map_desc standard_io_desc
[] __initdata
= {
43 /* virtual physical length type */
44 { VIO_APB_BASE
, PIO_APB_BASE
, IO_APB_LENGTH
, MT_DEVICE
},
45 { VIO_AHB_BASE
, PIO_AHB_BASE
, IO_AHB_LENGTH
, MT_DEVICE
}
48 void __init
aaec2000_map_io(void)
50 iotable_init(standard_io_desc
, ARRAY_SIZE(standard_io_desc
));
54 * Interrupt handling routines
56 static void aaec2000_int_ack(unsigned int irq
)
61 static void aaec2000_int_mask(unsigned int irq
)
63 IRQ_INTENC
|= (1 << irq
);
66 static void aaec2000_int_unmask(unsigned int irq
)
68 IRQ_INTENS
|= (1 << irq
);
71 static struct irqchip aaec2000_irq_chip
= {
72 .ack
= aaec2000_int_ack
,
73 .mask
= aaec2000_int_mask
,
74 .unmask
= aaec2000_int_unmask
,
77 void __init
aaec2000_init_irq(void)
81 for (i
= 0; i
< NR_IRQS
; i
++) {
82 set_irq_handler(i
, do_level_IRQ
);
83 set_irq_chip(i
, &aaec2000_irq_chip
);
84 set_irq_flags(i
, IRQF_VALID
);
87 /* Disable all interrupts */
88 IRQ_INTENC
= 0xffffffff;
90 /* Clear any pending interrupts */
91 IRQ_INTSR
= IRQ_INTSR
;
97 /* IRQs are disabled before entering here from do_gettimeofday() */
98 static unsigned long aaec2000_gettimeoffset(void)
100 unsigned long ticks_to_match
, elapsed
, usec
;
102 /* Get ticks before next timer match */
103 ticks_to_match
= TIMER1_LOAD
- TIMER1_VAL
;
105 /* We need elapsed ticks since last match */
106 elapsed
= LATCH
- ticks_to_match
;
108 /* Now, convert them to usec */
109 usec
= (unsigned long)(elapsed
* (tick_nsec
/ 1000))/LATCH
;
114 /* We enter here with IRQs enabled */
116 aaec2000_timer_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
118 /* TODO: Check timer accuracy */
119 write_seqlock(&xtime_lock
);
124 write_sequnlock(&xtime_lock
);
129 static struct irqaction aaec2000_timer_irq
= {
130 .name
= "AAEC-2000 Timer Tick",
131 .flags
= SA_INTERRUPT
| SA_TIMER
,
132 .handler
= aaec2000_timer_interrupt
,
135 static void __init
aaec2000_timer_init(void)
137 /* Disable timer 1 */
140 /* We have somehow to generate a 100Hz clock.
141 * We then use the 508KHz timer in periodic mode.
144 TIMER1_CLEAR
= 1; /* Clear interrupt */
146 setup_irq(INT_TMR1_OFL
, &aaec2000_timer_irq
);
148 TIMER1_CTRL
= TIMER_CTRL_ENABLE
|
149 TIMER_CTRL_PERIODIC
|
150 TIMER_CTRL_CLKSEL_508K
;
153 struct sys_timer aaec2000_timer
= {
154 .init
= aaec2000_timer_init
,
155 .offset
= aaec2000_gettimeoffset
,