aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-orion/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-orion/time.c')
-rw-r--r--arch/arm/plat-orion/time.c119
1 files changed, 74 insertions, 45 deletions
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
index c3da2478b2aa..742b0323c57b 100644
--- a/arch/arm/plat-orion/time.c
+++ b/arch/arm/plat-orion/time.c
@@ -18,28 +18,42 @@
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/irq.h> 19#include <linux/irq.h>
20#include <asm/sched_clock.h> 20#include <asm/sched_clock.h>
21#include <asm/mach/time.h>
22#include <mach/bridge-regs.h>
23#include <mach/hardware.h>
24 21
25/* 22/*
26 * Number of timer ticks per jiffy. 23 * MBus bridge block registers.
27 */ 24 */
28static u32 ticks_per_jiffy; 25#define BRIDGE_CAUSE_OFF 0x0110
26#define BRIDGE_MASK_OFF 0x0114
27#define BRIDGE_INT_TIMER0 0x0002
28#define BRIDGE_INT_TIMER1 0x0004
29 29
30 30
31/* 31/*
32 * Timer block registers. 32 * Timer block registers.
33 */ 33 */
34#define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000) 34#define TIMER_CTRL_OFF 0x0000
35#define TIMER0_EN 0x0001 35#define TIMER0_EN 0x0001
36#define TIMER0_RELOAD_EN 0x0002 36#define TIMER0_RELOAD_EN 0x0002
37#define TIMER1_EN 0x0004 37#define TIMER1_EN 0x0004
38#define TIMER1_RELOAD_EN 0x0008 38#define TIMER1_RELOAD_EN 0x0008
39#define TIMER0_RELOAD (TIMER_VIRT_BASE + 0x0010) 39#define TIMER0_RELOAD_OFF 0x0010
40#define TIMER0_VAL (TIMER_VIRT_BASE + 0x0014) 40#define TIMER0_VAL_OFF 0x0014
41#define TIMER1_RELOAD (TIMER_VIRT_BASE + 0x0018) 41#define TIMER1_RELOAD_OFF 0x0018
42#define TIMER1_VAL (TIMER_VIRT_BASE + 0x001c) 42#define TIMER1_VAL_OFF 0x001c
43
44
45/*
46 * SoC-specific data.
47 */
48static void __iomem *bridge_base;
49static u32 bridge_timer1_clr_mask;
50static void __iomem *timer_base;
51
52
53/*
54 * Number of timer ticks per jiffy.
55 */
56static u32 ticks_per_jiffy;
43 57
44 58
45/* 59/*
@@ -50,14 +64,14 @@ static DEFINE_CLOCK_DATA(cd);
50 64
51unsigned long long notrace sched_clock(void) 65unsigned long long notrace sched_clock(void)
52{ 66{
53 u32 cyc = 0xffffffff - readl(TIMER0_VAL); 67 u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF);
54 return cyc_to_sched_clock(&cd, cyc, (u32)~0); 68 return cyc_to_sched_clock(&cd, cyc, (u32)~0);
55} 69}
56 70
57 71
58static void notrace orion_update_sched_clock(void) 72static void notrace orion_update_sched_clock(void)
59{ 73{
60 u32 cyc = 0xffffffff - readl(TIMER0_VAL); 74 u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF);
61 update_sched_clock(&cd, cyc, (u32)~0); 75 update_sched_clock(&cd, cyc, (u32)~0);
62} 76}
63 77
@@ -71,7 +85,7 @@ static void __init setup_sched_clock(unsigned long tclk)
71 */ 85 */
72static cycle_t orion_clksrc_read(struct clocksource *cs) 86static cycle_t orion_clksrc_read(struct clocksource *cs)
73{ 87{
74 return 0xffffffff - readl(TIMER0_VAL); 88 return 0xffffffff - readl(timer_base + TIMER0_VAL_OFF);
75} 89}
76 90
77static struct clocksource orion_clksrc = { 91static struct clocksource orion_clksrc = {
@@ -101,23 +115,23 @@ orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
101 /* 115 /*
102 * Clear and enable clockevent timer interrupt. 116 * Clear and enable clockevent timer interrupt.
103 */ 117 */
104 writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE); 118 writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
105 119
106 u = readl(BRIDGE_MASK); 120 u = readl(bridge_base + BRIDGE_MASK_OFF);
107 u |= BRIDGE_INT_TIMER1; 121 u |= BRIDGE_INT_TIMER1;
108 writel(u, BRIDGE_MASK); 122 writel(u, bridge_base + BRIDGE_MASK_OFF);
109 123
110 /* 124 /*
111 * Setup new clockevent timer value. 125 * Setup new clockevent timer value.
112 */ 126 */
113 writel(delta, TIMER1_VAL); 127 writel(delta, timer_base + TIMER1_VAL_OFF);
114 128
115 /* 129 /*
116 * Enable the timer. 130 * Enable the timer.
117 */ 131 */
118 u = readl(TIMER_CTRL); 132 u = readl(timer_base + TIMER_CTRL_OFF);
119 u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN; 133 u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN;
120 writel(u, TIMER_CTRL); 134 writel(u, timer_base + TIMER_CTRL_OFF);
121 135
122 local_irq_restore(flags); 136 local_irq_restore(flags);
123 137
@@ -135,37 +149,38 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
135 /* 149 /*
136 * Setup timer to fire at 1/HZ intervals. 150 * Setup timer to fire at 1/HZ intervals.
137 */ 151 */
138 writel(ticks_per_jiffy - 1, TIMER1_RELOAD); 152 writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
139 writel(ticks_per_jiffy - 1, TIMER1_VAL); 153 writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF);
140 154
141 /* 155 /*
142 * Enable timer interrupt. 156 * Enable timer interrupt.
143 */ 157 */
144 u = readl(BRIDGE_MASK); 158 u = readl(bridge_base + BRIDGE_MASK_OFF);
145 writel(u | BRIDGE_INT_TIMER1, BRIDGE_MASK); 159 writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
146 160
147 /* 161 /*
148 * Enable timer. 162 * Enable timer.
149 */ 163 */
150 u = readl(TIMER_CTRL); 164 u = readl(timer_base + TIMER_CTRL_OFF);
151 writel(u | TIMER1_EN | TIMER1_RELOAD_EN, TIMER_CTRL); 165 writel(u | TIMER1_EN | TIMER1_RELOAD_EN,
166 timer_base + TIMER_CTRL_OFF);
152 } else { 167 } else {
153 /* 168 /*
154 * Disable timer. 169 * Disable timer.
155 */ 170 */
156 u = readl(TIMER_CTRL); 171 u = readl(timer_base + TIMER_CTRL_OFF);
157 writel(u & ~TIMER1_EN, TIMER_CTRL); 172 writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF);
158 173
159 /* 174 /*
160 * Disable timer interrupt. 175 * Disable timer interrupt.
161 */ 176 */
162 u = readl(BRIDGE_MASK); 177 u = readl(bridge_base + BRIDGE_MASK_OFF);
163 writel(u & ~BRIDGE_INT_TIMER1, BRIDGE_MASK); 178 writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
164 179
165 /* 180 /*
166 * ACK pending timer interrupt. 181 * ACK pending timer interrupt.
167 */ 182 */
168 writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE); 183 writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
169 184
170 } 185 }
171 local_irq_restore(flags); 186 local_irq_restore(flags);
@@ -185,7 +200,7 @@ static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
185 /* 200 /*
186 * ACK timer interrupt and call event handler. 201 * ACK timer interrupt and call event handler.
187 */ 202 */
188 writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE); 203 writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
189 orion_clkevt.event_handler(&orion_clkevt); 204 orion_clkevt.event_handler(&orion_clkevt);
190 205
191 return IRQ_HANDLED; 206 return IRQ_HANDLED;
@@ -197,31 +212,45 @@ static struct irqaction orion_timer_irq = {
197 .handler = orion_timer_interrupt 212 .handler = orion_timer_interrupt
198}; 213};
199 214
200void __init orion_time_init(unsigned int irq, unsigned int tclk) 215void __init
216orion_time_set_base(u32 _timer_base)
217{
218 timer_base = (void __iomem *)_timer_base;
219}
220
221void __init
222orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
223 unsigned int irq, unsigned int tclk)
201{ 224{
202 u32 u; 225 u32 u;
203 226
227 /*
228 * Set SoC-specific data.
229 */
230 bridge_base = (void __iomem *)_bridge_base;
231 bridge_timer1_clr_mask = _bridge_timer1_clr_mask;
232
204 ticks_per_jiffy = (tclk + HZ/2) / HZ; 233 ticks_per_jiffy = (tclk + HZ/2) / HZ;
205 234
206 /* 235 /*
207 * Set scale and timer for sched_clock 236 * Set scale and timer for sched_clock.
208 */ 237 */
209 setup_sched_clock(tclk); 238 setup_sched_clock(tclk);
210 239
211 /* 240 /*
212 * Setup free-running clocksource timer (interrupts 241 * Setup free-running clocksource timer (interrupts
213 * disabled.) 242 * disabled).
214 */ 243 */
215 writel(0xffffffff, TIMER0_VAL); 244 writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
216 writel(0xffffffff, TIMER0_RELOAD); 245 writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
217 u = readl(BRIDGE_MASK); 246 u = readl(bridge_base + BRIDGE_MASK_OFF);
218 writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK); 247 writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF);
219 u = readl(TIMER_CTRL); 248 u = readl(timer_base + TIMER_CTRL_OFF);
220 writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL); 249 writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
221 clocksource_register_hz(&orion_clksrc, tclk); 250 clocksource_register_hz(&orion_clksrc, tclk);
222 251
223 /* 252 /*
224 * Setup clockevent timer (interrupt-driven.) 253 * Setup clockevent timer (interrupt-driven).
225 */ 254 */
226 setup_irq(irq, &orion_timer_irq); 255 setup_irq(irq, &orion_timer_irq);
227 orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift); 256 orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);