time.c (6fae9c25134baffbeeb20031479e7ff6f6d8eec0) time.c (4ee1f6b574765a6c97f945e6b0277e5ccac38cb5)
1/*
2 * arch/arm/plat-orion/time.c
3 *
4 * Marvell Orion SoC timer handling.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.

--- 4 unchanged lines hidden (view full) ---

13
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/timer.h>
17#include <linux/clockchips.h>
18#include <linux/interrupt.h>
19#include <linux/irq.h>
20#include <asm/sched_clock.h>
1/*
2 * arch/arm/plat-orion/time.c
3 *
4 * Marvell Orion SoC timer handling.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.

--- 4 unchanged lines hidden (view full) ---

13
14#include <linux/kernel.h>
15#include <linux/sched.h>
16#include <linux/timer.h>
17#include <linux/clockchips.h>
18#include <linux/interrupt.h>
19#include <linux/irq.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
25/*
21
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
30
31/*
32 * Timer block registers.
33 */
29
30
31/*
32 * Timer block registers.
33 */
34#define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000)
35#define TIMER0_EN 0x0001
36#define TIMER0_RELOAD_EN 0x0002
37#define TIMER1_EN 0x0004
38#define TIMER1_RELOAD_EN 0x0008
39#define TIMER0_RELOAD (TIMER_VIRT_BASE + 0x0010)
40#define TIMER0_VAL (TIMER_VIRT_BASE + 0x0014)
41#define TIMER1_RELOAD (TIMER_VIRT_BASE + 0x0018)
42#define TIMER1_VAL (TIMER_VIRT_BASE + 0x001c)
34#define TIMER_CTRL_OFF 0x0000
35#define TIMER0_EN 0x0001
36#define TIMER0_RELOAD_EN 0x0002
37#define TIMER1_EN 0x0004
38#define TIMER1_RELOAD_EN 0x0008
39#define TIMER0_RELOAD_OFF 0x0010
40#define TIMER0_VAL_OFF 0x0014
41#define TIMER1_RELOAD_OFF 0x0018
42#define TIMER1_VAL_OFF 0x001c
43
44
45/*
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;
57
58
59/*
46 * Orion's sched_clock implementation. It has a resolution of
47 * at least 7.5ns (133MHz TCLK).
48 */
49static DEFINE_CLOCK_DATA(cd);
50
51unsigned long long notrace sched_clock(void)
52{
60 * Orion's sched_clock implementation. It has a resolution of
61 * at least 7.5ns (133MHz TCLK).
62 */
63static DEFINE_CLOCK_DATA(cd);
64
65unsigned long long notrace sched_clock(void)
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);
55}
56
57
58static void notrace orion_update_sched_clock(void)
59{
68 return cyc_to_sched_clock(&cd, cyc, (u32)~0);
69}
70
71
72static void notrace orion_update_sched_clock(void)
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);
62}
63
64static void __init setup_sched_clock(unsigned long tclk)
65{
66 init_sched_clock(&cd, orion_update_sched_clock, 32, tclk);
67}
68
69/*
70 * Clocksource handling.
71 */
72static cycle_t orion_clksrc_read(struct clocksource *cs)
73{
75 update_sched_clock(&cd, cyc, (u32)~0);
76}
77
78static void __init setup_sched_clock(unsigned long tclk)
79{
80 init_sched_clock(&cd, orion_update_sched_clock, 32, tclk);
81}
82
83/*
84 * Clocksource handling.
85 */
86static cycle_t orion_clksrc_read(struct clocksource *cs)
87{
74 return 0xffffffff - readl(TIMER0_VAL);
88 return 0xffffffff - readl(timer_base + TIMER0_VAL_OFF);
75}
76
77static struct clocksource orion_clksrc = {
78 .name = "orion_clocksource",
79 .rating = 300,
80 .read = orion_clksrc_read,
81 .mask = CLOCKSOURCE_MASK(32),
82 .flags = CLOCK_SOURCE_IS_CONTINUOUS,

--- 13 unchanged lines hidden (view full) ---

96 if (delta == 0)
97 return -ETIME;
98
99 local_irq_save(flags);
100
101 /*
102 * Clear and enable clockevent timer interrupt.
103 */
89}
90
91static struct clocksource orion_clksrc = {
92 .name = "orion_clocksource",
93 .rating = 300,
94 .read = orion_clksrc_read,
95 .mask = CLOCKSOURCE_MASK(32),
96 .flags = CLOCK_SOURCE_IS_CONTINUOUS,

--- 13 unchanged lines hidden (view full) ---

110 if (delta == 0)
111 return -ETIME;
112
113 local_irq_save(flags);
114
115 /*
116 * Clear and enable clockevent timer interrupt.
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
110 /*
111 * Setup new clockevent timer value.
112 */
123
124 /*
125 * Setup new clockevent timer value.
126 */
113 writel(delta, TIMER1_VAL);
127 writel(delta, timer_base + TIMER1_VAL_OFF);
114
115 /*
116 * Enable the timer.
117 */
128
129 /*
130 * Enable the timer.
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
122 local_irq_restore(flags);
123
124 return 0;
125}
126
127static void
128orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
129{
130 unsigned long flags;
131 u32 u;
132
133 local_irq_save(flags);
134 if (mode == CLOCK_EVT_MODE_PERIODIC) {
135 /*
136 * Setup timer to fire at 1/HZ intervals.
137 */
135
136 local_irq_restore(flags);
137
138 return 0;
139}
140
141static void
142orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
143{
144 unsigned long flags;
145 u32 u;
146
147 local_irq_save(flags);
148 if (mode == CLOCK_EVT_MODE_PERIODIC) {
149 /*
150 * Setup timer to fire at 1/HZ intervals.
151 */
138 writel(ticks_per_jiffy - 1, TIMER1_RELOAD);
139 writel(ticks_per_jiffy - 1, TIMER1_VAL);
152 writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
153 writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF);
140
141 /*
142 * Enable timer interrupt.
143 */
154
155 /*
156 * Enable timer interrupt.
157 */
144 u = readl(BRIDGE_MASK);
145 writel(u | BRIDGE_INT_TIMER1, BRIDGE_MASK);
158 u = readl(bridge_base + BRIDGE_MASK_OFF);
159 writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
146
147 /*
148 * Enable timer.
149 */
160
161 /*
162 * Enable timer.
163 */
150 u = readl(TIMER_CTRL);
151 writel(u | TIMER1_EN | TIMER1_RELOAD_EN, TIMER_CTRL);
164 u = readl(timer_base + TIMER_CTRL_OFF);
165 writel(u | TIMER1_EN | TIMER1_RELOAD_EN,
166 timer_base + TIMER_CTRL_OFF);
152 } else {
153 /*
154 * Disable timer.
155 */
167 } else {
168 /*
169 * Disable timer.
170 */
156 u = readl(TIMER_CTRL);
157 writel(u & ~TIMER1_EN, TIMER_CTRL);
171 u = readl(timer_base + TIMER_CTRL_OFF);
172 writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF);
158
159 /*
160 * Disable timer interrupt.
161 */
173
174 /*
175 * Disable timer interrupt.
176 */
162 u = readl(BRIDGE_MASK);
163 writel(u & ~BRIDGE_INT_TIMER1, BRIDGE_MASK);
177 u = readl(bridge_base + BRIDGE_MASK_OFF);
178 writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
164
165 /*
166 * ACK pending timer interrupt.
167 */
179
180 /*
181 * ACK pending timer interrupt.
182 */
168 writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
183 writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
169
170 }
171 local_irq_restore(flags);
172}
173
174static struct clock_event_device orion_clkevt = {
175 .name = "orion_tick",
176 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
177 .shift = 32,
178 .rating = 300,
179 .set_next_event = orion_clkevt_next_event,
180 .set_mode = orion_clkevt_mode,
181};
182
183static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
184{
185 /*
186 * ACK timer interrupt and call event handler.
187 */
184
185 }
186 local_irq_restore(flags);
187}
188
189static struct clock_event_device orion_clkevt = {
190 .name = "orion_tick",
191 .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
192 .shift = 32,
193 .rating = 300,
194 .set_next_event = orion_clkevt_next_event,
195 .set_mode = orion_clkevt_mode,
196};
197
198static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
199{
200 /*
201 * ACK timer interrupt and call event handler.
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);
190
191 return IRQ_HANDLED;
192}
193
194static struct irqaction orion_timer_irq = {
195 .name = "orion_tick",
196 .flags = IRQF_DISABLED | IRQF_TIMER,
197 .handler = orion_timer_interrupt
198};
199
204 orion_clkevt.event_handler(&orion_clkevt);
205
206 return IRQ_HANDLED;
207}
208
209static struct irqaction orion_timer_irq = {
210 .name = "orion_tick",
211 .flags = IRQF_DISABLED | IRQF_TIMER,
212 .handler = orion_timer_interrupt
213};
214
200void __init orion_time_init(unsigned int irq, unsigned int tclk)
215void __init
216orion_time_set_base(u32 _timer_base)
201{
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)
224{
202 u32 u;
203
225 u32 u;
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;
205
206 /*
233 ticks_per_jiffy = (tclk + HZ/2) / HZ;
234
235 /*
207 * Set scale and timer for sched_clock
236 * Set scale and timer for sched_clock.
208 */
209 setup_sched_clock(tclk);
210
211 /*
212 * Setup free-running clocksource timer (interrupts
237 */
238 setup_sched_clock(tclk);
239
240 /*
241 * Setup free-running clocksource timer (interrupts
213 * disabled.)
242 * disabled).
214 */
243 */
215 writel(0xffffffff, TIMER0_VAL);
216 writel(0xffffffff, TIMER0_RELOAD);
217 u = readl(BRIDGE_MASK);
218 writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK);
219 u = readl(TIMER_CTRL);
220 writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL);
244 writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
245 writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
246 u = readl(bridge_base + BRIDGE_MASK_OFF);
247 writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF);
248 u = readl(timer_base + TIMER_CTRL_OFF);
249 writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
221 clocksource_register_hz(&orion_clksrc, tclk);
222
223 /*
250 clocksource_register_hz(&orion_clksrc, tclk);
251
252 /*
224 * Setup clockevent timer (interrupt-driven.)
253 * Setup clockevent timer (interrupt-driven).
225 */
226 setup_irq(irq, &orion_timer_irq);
227 orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
228 orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt);
229 orion_clkevt.min_delta_ns = clockevent_delta2ns(1, &orion_clkevt);
230 orion_clkevt.cpumask = cpumask_of(0);
231 clockevents_register_device(&orion_clkevt);
232}
254 */
255 setup_irq(irq, &orion_timer_irq);
256 orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
257 orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt);
258 orion_clkevt.min_delta_ns = clockevent_delta2ns(1, &orion_clkevt);
259 orion_clkevt.cpumask = cpumask_of(0);
260 clockevents_register_device(&orion_clkevt);
261}