diff options
Diffstat (limited to 'arch/arm/mach-at91')
-rw-r--r-- | arch/arm/mach-at91/Kconfig | 25 | ||||
-rw-r--r-- | arch/arm/mach-at91/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91rm9200_time.c | 195 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91x40.c | 67 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91x40_time.c | 80 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-eb01.c | 44 | ||||
-rw-r--r-- | arch/arm/mach-at91/generic.h | 3 |
7 files changed, 353 insertions, 66 deletions
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index a31157f1655a..05a9f8a1b45e 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig | |||
@@ -7,6 +7,8 @@ choice | |||
7 | 7 | ||
8 | config ARCH_AT91RM9200 | 8 | config ARCH_AT91RM9200 |
9 | bool "AT91RM9200" | 9 | bool "AT91RM9200" |
10 | select GENERIC_TIME | ||
11 | select GENERIC_CLOCKEVENTS | ||
10 | 12 | ||
11 | config ARCH_AT91SAM9260 | 13 | config ARCH_AT91SAM9260 |
12 | bool "AT91SAM9260 or AT91SAM9XE" | 14 | bool "AT91SAM9260 or AT91SAM9XE" |
@@ -20,8 +22,15 @@ config ARCH_AT91SAM9263 | |||
20 | config ARCH_AT91SAM9RL | 22 | config ARCH_AT91SAM9RL |
21 | bool "AT91SAM9RL" | 23 | bool "AT91SAM9RL" |
22 | 24 | ||
25 | config ARCH_AT91X40 | ||
26 | bool "AT91x40" | ||
27 | |||
23 | endchoice | 28 | endchoice |
24 | 29 | ||
30 | config AT91_PMC_UNIT | ||
31 | bool | ||
32 | default !ARCH_AT91X40 | ||
33 | |||
25 | # ---------------------------------------------------------- | 34 | # ---------------------------------------------------------- |
26 | 35 | ||
27 | if ARCH_AT91RM9200 | 36 | if ARCH_AT91RM9200 |
@@ -169,6 +178,22 @@ endif | |||
169 | 178 | ||
170 | # ---------------------------------------------------------- | 179 | # ---------------------------------------------------------- |
171 | 180 | ||
181 | if ARCH_AT91X40 | ||
182 | |||
183 | comment "AT91X40 Board Type" | ||
184 | |||
185 | config MACH_AT91EB01 | ||
186 | bool "Atmel AT91EB01 Evaluation Kit" | ||
187 | help | ||
188 | Select this if you are using Atmel's AT91EB01 Evaluation Kit. | ||
189 | It is also a popular target for simulators such as GDB's | ||
190 | ARM simulator (commonly known as the ARMulator) and the | ||
191 | Skyeye simulator. | ||
192 | |||
193 | endif | ||
194 | |||
195 | # ---------------------------------------------------------- | ||
196 | |||
172 | comment "AT91 Board Options" | 197 | comment "AT91 Board Options" |
173 | 198 | ||
174 | config MTD_AT91_DATAFLASH_CARD | 199 | config MTD_AT91_DATAFLASH_CARD |
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index a4d80eb056ee..a21f08c64ea6 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile | |||
@@ -2,11 +2,12 @@ | |||
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := clock.o irq.o gpio.o | 5 | obj-y := irq.o gpio.o |
6 | obj-m := | 6 | obj-m := |
7 | obj-n := | 7 | obj-n := |
8 | obj- := | 8 | obj- := |
9 | 9 | ||
10 | obj-$(CONFIG_AT91_PMC_UNIT) += clock.o | ||
10 | obj-$(CONFIG_PM) += pm.o | 11 | obj-$(CONFIG_PM) += pm.o |
11 | 12 | ||
12 | # CPU-specific support | 13 | # CPU-specific support |
@@ -15,6 +16,7 @@ obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_d | |||
15 | obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o | 16 | obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o |
16 | obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o | 17 | obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o |
17 | obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o | 18 | obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o |
19 | obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o | ||
18 | 20 | ||
19 | # AT91RM9200 board-specific support | 21 | # AT91RM9200 board-specific support |
20 | obj-$(CONFIG_MACH_ONEARM) += board-1arm.o | 22 | obj-$(CONFIG_MACH_ONEARM) += board-1arm.o |
@@ -27,6 +29,7 @@ obj-$(CONFIG_MACH_KB9200) += board-kb9202.o | |||
27 | obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o | 29 | obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o |
28 | obj-$(CONFIG_MACH_KAFA) += board-kafa.o | 30 | obj-$(CONFIG_MACH_KAFA) += board-kafa.o |
29 | obj-$(CONFIG_MACH_PICOTUX2XX) += board-picotux200.o | 31 | obj-$(CONFIG_MACH_PICOTUX2XX) += board-picotux200.o |
32 | obj-$(CONFIG_MACH_AT91EB01) += board-eb01.o | ||
30 | 33 | ||
31 | # AT91SAM9260 board-specific support | 34 | # AT91SAM9260 board-specific support |
32 | obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o | 35 | obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o |
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index a6340357585d..50392ff71513 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c | |||
@@ -19,70 +19,64 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/init.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/clockchips.h> |
26 | #include <linux/sched.h> | ||
27 | #include <linux/time.h> | ||
28 | 26 | ||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/mach/time.h> | 27 | #include <asm/mach/time.h> |
32 | 28 | ||
33 | #include <asm/arch/at91_st.h> | 29 | #include <asm/arch/at91_st.h> |
34 | 30 | ||
35 | static unsigned long last_crtr; | 31 | static unsigned long last_crtr; |
32 | static u32 irqmask; | ||
33 | static struct clock_event_device clkevt; | ||
36 | 34 | ||
37 | /* | 35 | /* |
38 | * The ST_CRTR is updated asynchronously to the master clock. It is therefore | 36 | * The ST_CRTR is updated asynchronously to the master clock ... but |
39 | * necessary to read it twice (with the same value) to ensure accuracy. | 37 | * the updates as seen by the CPU don't seem to be strictly monotonic. |
38 | * Waiting until we read the same value twice avoids glitching. | ||
40 | */ | 39 | */ |
41 | static inline unsigned long read_CRTR(void) { | 40 | static inline unsigned long read_CRTR(void) |
41 | { | ||
42 | unsigned long x1, x2; | 42 | unsigned long x1, x2; |
43 | 43 | ||
44 | x1 = at91_sys_read(AT91_ST_CRTR); | ||
44 | do { | 45 | do { |
45 | x1 = at91_sys_read(AT91_ST_CRTR); | ||
46 | x2 = at91_sys_read(AT91_ST_CRTR); | 46 | x2 = at91_sys_read(AT91_ST_CRTR); |
47 | } while (x1 != x2); | 47 | if (x1 == x2) |
48 | 48 | break; | |
49 | x1 = x2; | ||
50 | } while (1); | ||
49 | return x1; | 51 | return x1; |
50 | } | 52 | } |
51 | 53 | ||
52 | /* | 54 | /* |
53 | * Returns number of microseconds since last timer interrupt. Note that interrupts | ||
54 | * will have been disabled by do_gettimeofday() | ||
55 | * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. | ||
56 | * 'tick' is usecs per jiffy (linux/timex.h). | ||
57 | */ | ||
58 | static unsigned long at91rm9200_gettimeoffset(void) | ||
59 | { | ||
60 | unsigned long elapsed; | ||
61 | |||
62 | elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV; | ||
63 | |||
64 | return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * IRQ handler for the timer. | 55 | * IRQ handler for the timer. |
69 | */ | 56 | */ |
70 | static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id) | 57 | static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id) |
71 | { | 58 | { |
72 | if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */ | 59 | u32 sr = at91_sys_read(AT91_ST_SR) & irqmask; |
73 | write_seqlock(&xtime_lock); | ||
74 | 60 | ||
75 | while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) { | 61 | /* simulate "oneshot" timer with alarm */ |
76 | timer_tick(); | 62 | if (sr & AT91_ST_ALMS) { |
77 | last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV; | 63 | clkevt.event_handler(&clkevt); |
78 | } | 64 | return IRQ_HANDLED; |
65 | } | ||
79 | 66 | ||
80 | write_sequnlock(&xtime_lock); | 67 | /* periodic mode should handle delayed ticks */ |
68 | if (sr & AT91_ST_PITS) { | ||
69 | u32 crtr = read_CRTR(); | ||
81 | 70 | ||
71 | while (((crtr - last_crtr) & AT91_ST_CRTV) >= LATCH) { | ||
72 | last_crtr += LATCH; | ||
73 | clkevt.event_handler(&clkevt); | ||
74 | } | ||
82 | return IRQ_HANDLED; | 75 | return IRQ_HANDLED; |
83 | } | 76 | } |
84 | else | 77 | |
85 | return IRQ_NONE; /* not handled */ | 78 | /* this irq is shared ... */ |
79 | return IRQ_NONE; | ||
86 | } | 80 | } |
87 | 81 | ||
88 | static struct irqaction at91rm9200_timer_irq = { | 82 | static struct irqaction at91rm9200_timer_irq = { |
@@ -91,56 +85,127 @@ static struct irqaction at91rm9200_timer_irq = { | |||
91 | .handler = at91rm9200_timer_interrupt | 85 | .handler = at91rm9200_timer_interrupt |
92 | }; | 86 | }; |
93 | 87 | ||
94 | void at91rm9200_timer_reset(void) | 88 | static cycle_t read_clk32k(void) |
95 | { | 89 | { |
96 | last_crtr = 0; | 90 | return read_CRTR(); |
91 | } | ||
97 | 92 | ||
98 | /* Real time counter incremented every 30.51758 microseconds */ | 93 | static struct clocksource clk32k = { |
99 | at91_sys_write(AT91_ST_RTMR, 1); | 94 | .name = "32k_counter", |
95 | .rating = 150, | ||
96 | .read = read_clk32k, | ||
97 | .mask = CLOCKSOURCE_MASK(20), | ||
98 | .shift = 10, | ||
99 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
100 | }; | ||
101 | |||
102 | static void | ||
103 | clkevt32k_mode(enum clock_event_mode mode, struct clock_event_device *dev) | ||
104 | { | ||
105 | /* Disable and flush pending timer interrupts */ | ||
106 | at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_ALMS); | ||
107 | (void) at91_sys_read(AT91_ST_SR); | ||
100 | 108 | ||
101 | /* Set Period Interval timer */ | 109 | last_crtr = read_CRTR(); |
102 | at91_sys_write(AT91_ST_PIMR, LATCH); | 110 | switch (mode) { |
111 | case CLOCK_EVT_MODE_PERIODIC: | ||
112 | /* PIT for periodic irqs; fixed rate of 1/HZ */ | ||
113 | irqmask = AT91_ST_PITS; | ||
114 | at91_sys_write(AT91_ST_PIMR, LATCH); | ||
115 | break; | ||
116 | case CLOCK_EVT_MODE_ONESHOT: | ||
117 | /* ALM for oneshot irqs, set by next_event() | ||
118 | * before 32 seconds have passed | ||
119 | */ | ||
120 | irqmask = AT91_ST_ALMS; | ||
121 | at91_sys_write(AT91_ST_RTAR, last_crtr); | ||
122 | break; | ||
123 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
124 | case CLOCK_EVT_MODE_UNUSED: | ||
125 | case CLOCK_EVT_MODE_RESUME: | ||
126 | irqmask = 0; | ||
127 | break; | ||
128 | } | ||
129 | at91_sys_write(AT91_ST_IER, irqmask); | ||
130 | } | ||
103 | 131 | ||
104 | /* Clear any pending interrupts */ | 132 | static int |
133 | clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) | ||
134 | { | ||
135 | unsigned long flags; | ||
136 | u32 alm; | ||
137 | int status = 0; | ||
138 | |||
139 | BUG_ON(delta < 2); | ||
140 | |||
141 | /* Use "raw" primitives so we behave correctly on RT kernels. */ | ||
142 | raw_local_irq_save(flags); | ||
143 | |||
144 | /* The alarm IRQ uses absolute time (now+delta), not the relative | ||
145 | * time (delta) in our calling convention. Like all clockevents | ||
146 | * using such "match" hardware, we have a race to defend against. | ||
147 | * | ||
148 | * Our defense here is to have set up the clockevent device so the | ||
149 | * delta is at least two. That way we never end up writing RTAR | ||
150 | * with the value then held in CRTR ... which would mean the match | ||
151 | * wouldn't trigger until 32 seconds later, after CRTR wraps. | ||
152 | */ | ||
153 | alm = read_CRTR(); | ||
154 | |||
155 | /* Cancel any pending alarm; flush any pending IRQ */ | ||
156 | at91_sys_write(AT91_ST_RTAR, alm); | ||
105 | (void) at91_sys_read(AT91_ST_SR); | 157 | (void) at91_sys_read(AT91_ST_SR); |
106 | 158 | ||
107 | /* Enable Period Interval Timer interrupt */ | 159 | /* Schedule alarm by writing RTAR. */ |
108 | at91_sys_write(AT91_ST_IER, AT91_ST_PITS); | 160 | alm += delta; |
161 | at91_sys_write(AT91_ST_RTAR, alm); | ||
162 | |||
163 | raw_local_irq_restore(flags); | ||
164 | return status; | ||
109 | } | 165 | } |
110 | 166 | ||
167 | static struct clock_event_device clkevt = { | ||
168 | .name = "at91_tick", | ||
169 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
170 | .shift = 32, | ||
171 | .rating = 150, | ||
172 | .cpumask = CPU_MASK_CPU0, | ||
173 | .set_next_event = clkevt32k_next_event, | ||
174 | .set_mode = clkevt32k_mode, | ||
175 | }; | ||
176 | |||
111 | /* | 177 | /* |
112 | * Set up timer interrupt. | 178 | * ST (system timer) module supports both clockevents and clocksource. |
113 | */ | 179 | */ |
114 | void __init at91rm9200_timer_init(void) | 180 | void __init at91rm9200_timer_init(void) |
115 | { | 181 | { |
116 | /* Disable all timer interrupts */ | 182 | /* Disable all timer interrupts, and clear any pending ones */ |
117 | at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); | 183 | at91_sys_write(AT91_ST_IDR, |
118 | (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */ | 184 | AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); |
185 | (void) at91_sys_read(AT91_ST_SR); | ||
119 | 186 | ||
120 | /* Make IRQs happen for the system timer */ | 187 | /* Make IRQs happen for the system timer */ |
121 | setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); | 188 | setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); |
122 | 189 | ||
123 | /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */ | 190 | /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used |
124 | tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE; | 191 | * directly for the clocksource and all clockevents, after adjusting |
192 | * its prescaler from the 1 Hz default. | ||
193 | */ | ||
194 | at91_sys_write(AT91_ST_RTMR, 1); | ||
125 | 195 | ||
126 | /* Initialize and enable the timer interrupt */ | 196 | /* Setup timer clockevent, with minimum of two ticks (important!!) */ |
127 | at91rm9200_timer_reset(); | 197 | clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift); |
128 | } | 198 | clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt); |
199 | clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1; | ||
200 | clkevt.cpumask = cpumask_of_cpu(0); | ||
201 | clockevents_register_device(&clkevt); | ||
129 | 202 | ||
130 | #ifdef CONFIG_PM | 203 | /* register clocksource */ |
131 | static void at91rm9200_timer_suspend(void) | 204 | clk32k.mult = clocksource_hz2mult(AT91_SLOW_CLOCK, clk32k.shift); |
132 | { | 205 | clocksource_register(&clk32k); |
133 | /* disable Period Interval Timer interrupt */ | ||
134 | at91_sys_write(AT91_ST_IDR, AT91_ST_PITS); | ||
135 | } | 206 | } |
136 | #else | ||
137 | #define at91rm9200_timer_suspend NULL | ||
138 | #endif | ||
139 | 207 | ||
140 | struct sys_timer at91rm9200_timer = { | 208 | struct sys_timer at91rm9200_timer = { |
141 | .init = at91rm9200_timer_init, | 209 | .init = at91rm9200_timer_init, |
142 | .offset = at91rm9200_gettimeoffset, | ||
143 | .suspend = at91rm9200_timer_suspend, | ||
144 | .resume = at91rm9200_timer_reset, | ||
145 | }; | 210 | }; |
146 | 211 | ||
diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c new file mode 100644 index 000000000000..1de121fc55f4 --- /dev/null +++ b/arch/arm/mach-at91/at91x40.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-at91/at91x40.c | ||
3 | * | ||
4 | * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com> | ||
5 | * Copyright (C) 2005 SAN People | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <asm/mach/arch.h> | ||
17 | #include <asm/arch/at91x40.h> | ||
18 | #include <asm/arch/at91_st.h> | ||
19 | #include "generic.h" | ||
20 | |||
21 | /* | ||
22 | * This is used in the gpio code, stub locally. | ||
23 | */ | ||
24 | int clk_enable(struct clk *clk) | ||
25 | { | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | void __init at91x40_initialize(unsigned long main_clock) | ||
30 | { | ||
31 | at91_extern_irq = (1 << AT91X40_ID_IRQ0) | (1 << AT91X40_ID_IRQ1) | ||
32 | | (1 << AT91X40_ID_IRQ2); | ||
33 | } | ||
34 | |||
35 | /* | ||
36 | * The default interrupt priority levels (0 = lowest, 7 = highest). | ||
37 | */ | ||
38 | static unsigned int at91x40_default_irq_priority[NR_AIC_IRQS] __initdata = { | ||
39 | 7, /* Advanced Interrupt Controller (FIQ) */ | ||
40 | 0, /* System Peripherals */ | ||
41 | 0, /* USART 0 */ | ||
42 | 0, /* USART 1 */ | ||
43 | 2, /* Timer Counter 0 */ | ||
44 | 2, /* Timer Counter 1 */ | ||
45 | 2, /* Timer Counter 2 */ | ||
46 | 0, /* Watchdog timer */ | ||
47 | 0, /* Parallel IO Controller A */ | ||
48 | 0, /* Reserved */ | ||
49 | 0, /* Reserved */ | ||
50 | 0, /* Reserved */ | ||
51 | 0, /* Reserved */ | ||
52 | 0, /* Reserved */ | ||
53 | 0, /* Reserved */ | ||
54 | 0, /* Reserved */ | ||
55 | 0, /* External IRQ0 */ | ||
56 | 0, /* External IRQ1 */ | ||
57 | 0, /* External IRQ2 */ | ||
58 | }; | ||
59 | |||
60 | void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS]) | ||
61 | { | ||
62 | if (!priority) | ||
63 | priority = at91x40_default_irq_priority; | ||
64 | |||
65 | at91_aic_init(priority); | ||
66 | } | ||
67 | |||
diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c new file mode 100644 index 000000000000..eddc882f1b4a --- /dev/null +++ b/arch/arm/mach-at91/at91x40_time.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-at91/at91x40_time.c | ||
3 | * | ||
4 | * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/irq.h> | ||
25 | #include <linux/time.h> | ||
26 | #include <asm/hardware.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/mach/time.h> | ||
29 | #include <asm/arch/at91_tc.h> | ||
30 | |||
31 | /* | ||
32 | * 3 counter/timer units present. | ||
33 | */ | ||
34 | #define AT91_TC_CLK0BASE 0 | ||
35 | #define AT91_TC_CLK1BASE 0x40 | ||
36 | #define AT91_TC_CLK2BASE 0x80 | ||
37 | |||
38 | static unsigned long at91x40_gettimeoffset(void) | ||
39 | { | ||
40 | return (at91_sys_read(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 / (AT91X40_MASTER_CLOCK / 128)); | ||
41 | } | ||
42 | |||
43 | static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id) | ||
44 | { | ||
45 | at91_sys_read(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_SR); | ||
46 | timer_tick(); | ||
47 | return IRQ_HANDLED; | ||
48 | } | ||
49 | |||
50 | static struct irqaction at91x40_timer_irq = { | ||
51 | .name = "at91_tick", | ||
52 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
53 | .handler = at91x40_timer_interrupt | ||
54 | }; | ||
55 | |||
56 | void __init at91x40_timer_init(void) | ||
57 | { | ||
58 | unsigned int v; | ||
59 | |||
60 | at91_sys_write(AT91_TC + AT91_TC_BCR, 0); | ||
61 | v = at91_sys_read(AT91_TC + AT91_TC_BMR); | ||
62 | v = (v & ~AT91_TC_TC1XC1S) | AT91_TC_TC1XC1S_NONE; | ||
63 | at91_sys_write(AT91_TC + AT91_TC_BMR, v); | ||
64 | |||
65 | at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CCR, AT91_TC_CLKDIS); | ||
66 | at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CMR, (AT91_TC_TIMER_CLOCK4 | AT91_TC_CPCTRG)); | ||
67 | at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_IDR, 0xffffffff); | ||
68 | at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_RC, (AT91X40_MASTER_CLOCK / 128) / HZ - 1); | ||
69 | at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_IER, (1<<4)); | ||
70 | |||
71 | setup_irq(AT91X40_ID_TC1, &at91x40_timer_irq); | ||
72 | |||
73 | at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CCR, (AT91_TC_SWTRG | AT91_TC_CLKEN)); | ||
74 | } | ||
75 | |||
76 | struct sys_timer at91x40_timer = { | ||
77 | .init = at91x40_timer_init, | ||
78 | .offset = at91x40_gettimeoffset, | ||
79 | }; | ||
80 | |||
diff --git a/arch/arm/mach-at91/board-eb01.c b/arch/arm/mach-at91/board-eb01.c new file mode 100644 index 000000000000..0c1e3858e7df --- /dev/null +++ b/arch/arm/mach-at91/board-eb01.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-at91/board-eb01.c | ||
3 | * | ||
4 | * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <asm/mach-types.h> | ||
27 | #include <asm/hardware.h> | ||
28 | #include <asm/mach/arch.h> | ||
29 | #include <asm/mach/map.h> | ||
30 | #include <asm/arch/board.h> | ||
31 | #include "generic.h" | ||
32 | |||
33 | static void __init at91eb01_map_io(void) | ||
34 | { | ||
35 | at91x40_initialize(40000000); | ||
36 | } | ||
37 | |||
38 | MACHINE_START(AT91EB01, "Atmel AT91 EB01") | ||
39 | /* Maintainer: Greg Ungerer <gerg@snapgear.com> */ | ||
40 | .timer = &at91x40_timer, | ||
41 | .init_irq = at91x40_init_interrupts, | ||
42 | .map_io = at91eb01_map_io, | ||
43 | MACHINE_END | ||
44 | |||
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index 68ed71a3e6c6..77d4c0a37842 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h | |||
@@ -14,6 +14,7 @@ extern void __init at91sam9260_initialize(unsigned long main_clock); | |||
14 | extern void __init at91sam9261_initialize(unsigned long main_clock); | 14 | extern void __init at91sam9261_initialize(unsigned long main_clock); |
15 | extern void __init at91sam9263_initialize(unsigned long main_clock); | 15 | extern void __init at91sam9263_initialize(unsigned long main_clock); |
16 | extern void __init at91sam9rl_initialize(unsigned long main_clock); | 16 | extern void __init at91sam9rl_initialize(unsigned long main_clock); |
17 | extern void __init at91x40_initialize(unsigned long main_clock); | ||
17 | 18 | ||
18 | /* Interrupts */ | 19 | /* Interrupts */ |
19 | extern void __init at91rm9200_init_interrupts(unsigned int priority[]); | 20 | extern void __init at91rm9200_init_interrupts(unsigned int priority[]); |
@@ -21,12 +22,14 @@ extern void __init at91sam9260_init_interrupts(unsigned int priority[]); | |||
21 | extern void __init at91sam9261_init_interrupts(unsigned int priority[]); | 22 | extern void __init at91sam9261_init_interrupts(unsigned int priority[]); |
22 | extern void __init at91sam9263_init_interrupts(unsigned int priority[]); | 23 | extern void __init at91sam9263_init_interrupts(unsigned int priority[]); |
23 | extern void __init at91sam9rl_init_interrupts(unsigned int priority[]); | 24 | extern void __init at91sam9rl_init_interrupts(unsigned int priority[]); |
25 | extern void __init at91x40_init_interrupts(unsigned int priority[]); | ||
24 | extern void __init at91_aic_init(unsigned int priority[]); | 26 | extern void __init at91_aic_init(unsigned int priority[]); |
25 | 27 | ||
26 | /* Timer */ | 28 | /* Timer */ |
27 | struct sys_timer; | 29 | struct sys_timer; |
28 | extern struct sys_timer at91rm9200_timer; | 30 | extern struct sys_timer at91rm9200_timer; |
29 | extern struct sys_timer at91sam926x_timer; | 31 | extern struct sys_timer at91sam926x_timer; |
32 | extern struct sys_timer at91x40_timer; | ||
30 | 33 | ||
31 | /* Clocks */ | 34 | /* Clocks */ |
32 | extern int __init at91_clock_init(unsigned long main_clock); | 35 | extern int __init at91_clock_init(unsigned long main_clock); |