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} |