aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-23 13:34:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-23 13:34:47 -0400
commit9d0715630ebf7bf70daa5e6d8db0e3061268c61e (patch)
tree54562185002b22169d81e0fb3c21312cb510ac40
parentc0c463d34adf0c150e5e24fa412fa23f3f7ddc27 (diff)
parent06c3df49521c1b112b777cc4946e5de057c814ba (diff)
Merge branch 'timers-clocksource-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-clocksource-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: clocksource: apb: Share APB timer code with other platforms
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/include/asm/apb_timer.h22
-rw-r--r--arch/x86/kernel/apb_timer.c409
-rw-r--r--drivers/clocksource/Kconfig3
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/dw_apb_timer.c401
-rw-r--r--include/linux/dw_apb_timer.h56
7 files changed, 533 insertions, 360 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5f60ea190d5b..c3e03e46bc64 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -623,6 +623,7 @@ config HPET_EMULATE_RTC
623config APB_TIMER 623config APB_TIMER
624 def_bool y if MRST 624 def_bool y if MRST
625 prompt "Langwell APB Timer Support" if X86_MRST 625 prompt "Langwell APB Timer Support" if X86_MRST
626 select DW_APB_TIMER
626 help 627 help
627 APB timer is the replacement for 8254, HPET on X86 MID platforms. 628 APB timer is the replacement for 8254, HPET on X86 MID platforms.
628 The APBT provides a stable time base on SMP 629 The APBT provides a stable time base on SMP
diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h
index 082cf8184935..0acbac299e49 100644
--- a/arch/x86/include/asm/apb_timer.h
+++ b/arch/x86/include/asm/apb_timer.h
@@ -18,24 +18,6 @@
18 18
19#ifdef CONFIG_APB_TIMER 19#ifdef CONFIG_APB_TIMER
20 20
21/* Langwell DW APB timer registers */
22#define APBTMR_N_LOAD_COUNT 0x00
23#define APBTMR_N_CURRENT_VALUE 0x04
24#define APBTMR_N_CONTROL 0x08
25#define APBTMR_N_EOI 0x0c
26#define APBTMR_N_INT_STATUS 0x10
27
28#define APBTMRS_INT_STATUS 0xa0
29#define APBTMRS_EOI 0xa4
30#define APBTMRS_RAW_INT_STATUS 0xa8
31#define APBTMRS_COMP_VERSION 0xac
32#define APBTMRS_REG_SIZE 0x14
33
34/* register bits */
35#define APBTMR_CONTROL_ENABLE (1<<0)
36#define APBTMR_CONTROL_MODE_PERIODIC (1<<1) /*1: periodic 0:free running */
37#define APBTMR_CONTROL_INT (1<<2)
38
39/* default memory mapped register base */ 21/* default memory mapped register base */
40#define LNW_SCU_ADDR 0xFF100000 22#define LNW_SCU_ADDR 0xFF100000
41#define LNW_EXT_TIMER_OFFSET 0x1B800 23#define LNW_EXT_TIMER_OFFSET 0x1B800
@@ -43,8 +25,8 @@
43#define LNW_EXT_TIMER_PGOFFSET 0x800 25#define LNW_EXT_TIMER_PGOFFSET 0x800
44 26
45/* APBT clock speed range from PCLK to fabric base, 25-100MHz */ 27/* APBT clock speed range from PCLK to fabric base, 25-100MHz */
46#define APBT_MAX_FREQ 50 28#define APBT_MAX_FREQ 50000000
47#define APBT_MIN_FREQ 1 29#define APBT_MIN_FREQ 1000000
48#define APBT_MMAP_SIZE 1024 30#define APBT_MMAP_SIZE 1024
49 31
50#define APBT_DEV_USED 1 32#define APBT_DEV_USED 1
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index 2b6630d75e17..afdc3f756dea 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -27,15 +27,12 @@
27 * timer, but by default APB timer has higher rating than local APIC timers. 27 * timer, but by default APB timer has higher rating than local APIC timers.
28 */ 28 */
29 29
30#include <linux/clocksource.h>
31#include <linux/clockchips.h>
32#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/dw_apb_timer.h>
33#include <linux/errno.h> 32#include <linux/errno.h>
34#include <linux/init.h> 33#include <linux/init.h>
35#include <linux/sysdev.h>
36#include <linux/slab.h> 34#include <linux/slab.h>
37#include <linux/pm.h> 35#include <linux/pm.h>
38#include <linux/pci.h>
39#include <linux/sfi.h> 36#include <linux/sfi.h>
40#include <linux/interrupt.h> 37#include <linux/interrupt.h>
41#include <linux/cpu.h> 38#include <linux/cpu.h>
@@ -46,75 +43,46 @@
46#include <asm/mrst.h> 43#include <asm/mrst.h>
47#include <asm/time.h> 44#include <asm/time.h>
48 45
49#define APBT_MASK CLOCKSOURCE_MASK(32)
50#define APBT_SHIFT 22
51#define APBT_CLOCKEVENT_RATING 110 46#define APBT_CLOCKEVENT_RATING 110
52#define APBT_CLOCKSOURCE_RATING 250 47#define APBT_CLOCKSOURCE_RATING 250
53#define APBT_MIN_DELTA_USEC 200
54 48
55#define EVT_TO_APBT_DEV(evt) container_of(evt, struct apbt_dev, evt)
56#define APBT_CLOCKEVENT0_NUM (0) 49#define APBT_CLOCKEVENT0_NUM (0)
57#define APBT_CLOCKEVENT1_NUM (1)
58#define APBT_CLOCKSOURCE_NUM (2) 50#define APBT_CLOCKSOURCE_NUM (2)
59 51
60static unsigned long apbt_address; 52static phys_addr_t apbt_address;
61static int apb_timer_block_enabled; 53static int apb_timer_block_enabled;
62static void __iomem *apbt_virt_address; 54static void __iomem *apbt_virt_address;
63static int phy_cs_timer_id;
64 55
65/* 56/*
66 * Common DW APB timer info 57 * Common DW APB timer info
67 */ 58 */
68static uint64_t apbt_freq; 59static unsigned long apbt_freq;
69
70static void apbt_set_mode(enum clock_event_mode mode,
71 struct clock_event_device *evt);
72static int apbt_next_event(unsigned long delta,
73 struct clock_event_device *evt);
74static cycle_t apbt_read_clocksource(struct clocksource *cs);
75static void apbt_restart_clocksource(struct clocksource *cs);
76 60
77struct apbt_dev { 61struct apbt_dev {
78 struct clock_event_device evt; 62 struct dw_apb_clock_event_device *timer;
79 unsigned int num; 63 unsigned int num;
80 int cpu; 64 int cpu;
81 unsigned int irq; 65 unsigned int irq;
82 unsigned int tick; 66 char name[10];
83 unsigned int count;
84 unsigned int flags;
85 char name[10];
86}; 67};
87 68
88static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev); 69static struct dw_apb_clocksource *clocksource_apbt;
89 70
90#ifdef CONFIG_SMP 71static inline void __iomem *adev_virt_addr(struct apbt_dev *adev)
91static unsigned int apbt_num_timers_used;
92static struct apbt_dev *apbt_devs;
93#endif
94
95static inline unsigned long apbt_readl_reg(unsigned long a)
96{ 72{
97 return readl(apbt_virt_address + a); 73 return apbt_virt_address + adev->num * APBTMRS_REG_SIZE;
98} 74}
99 75
100static inline void apbt_writel_reg(unsigned long d, unsigned long a) 76static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
101{
102 writel(d, apbt_virt_address + a);
103}
104
105static inline unsigned long apbt_readl(int n, unsigned long a)
106{
107 return readl(apbt_virt_address + a + n * APBTMRS_REG_SIZE);
108}
109 77
110static inline void apbt_writel(int n, unsigned long d, unsigned long a) 78#ifdef CONFIG_SMP
111{ 79static unsigned int apbt_num_timers_used;
112 writel(d, apbt_virt_address + a + n * APBTMRS_REG_SIZE); 80#endif
113}
114 81
115static inline void apbt_set_mapping(void) 82static inline void apbt_set_mapping(void)
116{ 83{
117 struct sfi_timer_table_entry *mtmr; 84 struct sfi_timer_table_entry *mtmr;
85 int phy_cs_timer_id = 0;
118 86
119 if (apbt_virt_address) { 87 if (apbt_virt_address) {
120 pr_debug("APBT base already mapped\n"); 88 pr_debug("APBT base already mapped\n");
@@ -126,21 +94,18 @@ static inline void apbt_set_mapping(void)
126 APBT_CLOCKEVENT0_NUM); 94 APBT_CLOCKEVENT0_NUM);
127 return; 95 return;
128 } 96 }
129 apbt_address = (unsigned long)mtmr->phys_addr; 97 apbt_address = (phys_addr_t)mtmr->phys_addr;
130 if (!apbt_address) { 98 if (!apbt_address) {
131 printk(KERN_WARNING "No timer base from SFI, use default\n"); 99 printk(KERN_WARNING "No timer base from SFI, use default\n");
132 apbt_address = APBT_DEFAULT_BASE; 100 apbt_address = APBT_DEFAULT_BASE;
133 } 101 }
134 apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE); 102 apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE);
135 if (apbt_virt_address) { 103 if (!apbt_virt_address) {
136 pr_debug("Mapped APBT physical addr %p at virtual addr %p\n",\ 104 pr_debug("Failed mapping APBT phy address at %lu\n",\
137 (void *)apbt_address, (void *)apbt_virt_address); 105 (unsigned long)apbt_address);
138 } else {
139 pr_debug("Failed mapping APBT phy address at %p\n",\
140 (void *)apbt_address);
141 goto panic_noapbt; 106 goto panic_noapbt;
142 } 107 }
143 apbt_freq = mtmr->freq_hz / USEC_PER_SEC; 108 apbt_freq = mtmr->freq_hz;
144 sfi_free_mtmr(mtmr); 109 sfi_free_mtmr(mtmr);
145 110
146 /* Now figure out the physical timer id for clocksource device */ 111 /* Now figure out the physical timer id for clocksource device */
@@ -149,9 +114,14 @@ static inline void apbt_set_mapping(void)
149 goto panic_noapbt; 114 goto panic_noapbt;
150 115
151 /* Now figure out the physical timer id */ 116 /* Now figure out the physical timer id */
152 phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) 117 pr_debug("Use timer %d for clocksource\n",
153 / APBTMRS_REG_SIZE; 118 (int)(mtmr->phys_addr & 0xff) / APBTMRS_REG_SIZE);
154 pr_debug("Use timer %d for clocksource\n", phy_cs_timer_id); 119 phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) /
120 APBTMRS_REG_SIZE;
121
122 clocksource_apbt = dw_apb_clocksource_init(APBT_CLOCKSOURCE_RATING,
123 "apbt0", apbt_virt_address + phy_cs_timer_id *
124 APBTMRS_REG_SIZE, apbt_freq);
155 return; 125 return;
156 126
157panic_noapbt: 127panic_noapbt:
@@ -173,82 +143,6 @@ static inline int is_apbt_capable(void)
173 return apbt_virt_address ? 1 : 0; 143 return apbt_virt_address ? 1 : 0;
174} 144}
175 145
176static struct clocksource clocksource_apbt = {
177 .name = "apbt",
178 .rating = APBT_CLOCKSOURCE_RATING,
179 .read = apbt_read_clocksource,
180 .mask = APBT_MASK,
181 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
182 .resume = apbt_restart_clocksource,
183};
184
185/* boot APB clock event device */
186static struct clock_event_device apbt_clockevent = {
187 .name = "apbt0",
188 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
189 .set_mode = apbt_set_mode,
190 .set_next_event = apbt_next_event,
191 .shift = APBT_SHIFT,
192 .irq = 0,
193 .rating = APBT_CLOCKEVENT_RATING,
194};
195
196/*
197 * start count down from 0xffff_ffff. this is done by toggling the enable bit
198 * then load initial load count to ~0.
199 */
200static void apbt_start_counter(int n)
201{
202 unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
203
204 ctrl &= ~APBTMR_CONTROL_ENABLE;
205 apbt_writel(n, ctrl, APBTMR_N_CONTROL);
206 apbt_writel(n, ~0, APBTMR_N_LOAD_COUNT);
207 /* enable, mask interrupt */
208 ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
209 ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
210 apbt_writel(n, ctrl, APBTMR_N_CONTROL);
211 /* read it once to get cached counter value initialized */
212 apbt_read_clocksource(&clocksource_apbt);
213}
214
215static irqreturn_t apbt_interrupt_handler(int irq, void *data)
216{
217 struct apbt_dev *dev = (struct apbt_dev *)data;
218 struct clock_event_device *aevt = &dev->evt;
219
220 if (!aevt->event_handler) {
221 printk(KERN_INFO "Spurious APBT timer interrupt on %d\n",
222 dev->num);
223 return IRQ_NONE;
224 }
225 aevt->event_handler(aevt);
226 return IRQ_HANDLED;
227}
228
229static void apbt_restart_clocksource(struct clocksource *cs)
230{
231 apbt_start_counter(phy_cs_timer_id);
232}
233
234static void apbt_enable_int(int n)
235{
236 unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
237 /* clear pending intr */
238 apbt_readl(n, APBTMR_N_EOI);
239 ctrl &= ~APBTMR_CONTROL_INT;
240 apbt_writel(n, ctrl, APBTMR_N_CONTROL);
241}
242
243static void apbt_disable_int(int n)
244{
245 unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
246
247 ctrl |= APBTMR_CONTROL_INT;
248 apbt_writel(n, ctrl, APBTMR_N_CONTROL);
249}
250
251
252static int __init apbt_clockevent_register(void) 146static int __init apbt_clockevent_register(void)
253{ 147{
254 struct sfi_timer_table_entry *mtmr; 148 struct sfi_timer_table_entry *mtmr;
@@ -261,45 +155,21 @@ static int __init apbt_clockevent_register(void)
261 return -ENODEV; 155 return -ENODEV;
262 } 156 }
263 157
264 /*
265 * We need to calculate the scaled math multiplication factor for
266 * nanosecond to apbt tick conversion.
267 * mult = (nsec/cycle)*2^APBT_SHIFT
268 */
269 apbt_clockevent.mult = div_sc((unsigned long) mtmr->freq_hz
270 , NSEC_PER_SEC, APBT_SHIFT);
271
272 /* Calculate the min / max delta */
273 apbt_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
274 &apbt_clockevent);
275 apbt_clockevent.min_delta_ns = clockevent_delta2ns(
276 APBT_MIN_DELTA_USEC*apbt_freq,
277 &apbt_clockevent);
278 /*
279 * Start apbt with the boot cpu mask and make it
280 * global if not used for per cpu timer.
281 */
282 apbt_clockevent.cpumask = cpumask_of(smp_processor_id());
283 adev->num = smp_processor_id(); 158 adev->num = smp_processor_id();
284 memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device)); 159 adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0",
160 mrst_timer_options == MRST_TIMER_LAPIC_APBT ?
161 APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING,
162 adev_virt_addr(adev), 0, apbt_freq);
163 /* Firmware does EOI handling for us. */
164 adev->timer->eoi = NULL;
285 165
286 if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) { 166 if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) {
287 adev->evt.rating = APBT_CLOCKEVENT_RATING - 100; 167 global_clock_event = &adev->timer->ced;
288 global_clock_event = &adev->evt;
289 printk(KERN_DEBUG "%s clockevent registered as global\n", 168 printk(KERN_DEBUG "%s clockevent registered as global\n",
290 global_clock_event->name); 169 global_clock_event->name);
291 } 170 }
292 171
293 if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler, 172 dw_apb_clockevent_register(adev->timer);
294 IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
295 apbt_clockevent.name, adev)) {
296 printk(KERN_ERR "Failed request IRQ for APBT%d\n",
297 apbt_clockevent.irq);
298 }
299
300 clockevents_register_device(&adev->evt);
301 /* Start APBT 0 interrupts */
302 apbt_enable_int(APBT_CLOCKEVENT0_NUM);
303 173
304 sfi_free_mtmr(mtmr); 174 sfi_free_mtmr(mtmr);
305 return 0; 175 return 0;
@@ -317,52 +187,34 @@ static void apbt_setup_irq(struct apbt_dev *adev)
317 irq_set_affinity(adev->irq, cpumask_of(adev->cpu)); 187 irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
318 /* APB timer irqs are set up as mp_irqs, timer is edge type */ 188 /* APB timer irqs are set up as mp_irqs, timer is edge type */
319 __irq_set_handler(adev->irq, handle_edge_irq, 0, "edge"); 189 __irq_set_handler(adev->irq, handle_edge_irq, 0, "edge");
320
321 if (system_state == SYSTEM_BOOTING) {
322 if (request_irq(adev->irq, apbt_interrupt_handler,
323 IRQF_TIMER | IRQF_DISABLED |
324 IRQF_NOBALANCING,
325 adev->name, adev)) {
326 printk(KERN_ERR "Failed request IRQ for APBT%d\n",
327 adev->num);
328 }
329 } else
330 enable_irq(adev->irq);
331} 190}
332 191
333/* Should be called with per cpu */ 192/* Should be called with per cpu */
334void apbt_setup_secondary_clock(void) 193void apbt_setup_secondary_clock(void)
335{ 194{
336 struct apbt_dev *adev; 195 struct apbt_dev *adev;
337 struct clock_event_device *aevt;
338 int cpu; 196 int cpu;
339 197
340 /* Don't register boot CPU clockevent */ 198 /* Don't register boot CPU clockevent */
341 cpu = smp_processor_id(); 199 cpu = smp_processor_id();
342 if (!cpu) 200 if (!cpu)
343 return; 201 return;
344 /*
345 * We need to calculate the scaled math multiplication factor for
346 * nanosecond to apbt tick conversion.
347 * mult = (nsec/cycle)*2^APBT_SHIFT
348 */
349 printk(KERN_INFO "Init per CPU clockevent %d\n", cpu);
350 adev = &per_cpu(cpu_apbt_dev, cpu);
351 aevt = &adev->evt;
352 202
353 memcpy(aevt, &apbt_clockevent, sizeof(*aevt)); 203 adev = &__get_cpu_var(cpu_apbt_dev);
354 aevt->cpumask = cpumask_of(cpu); 204 if (!adev->timer) {
355 aevt->name = adev->name; 205 adev->timer = dw_apb_clockevent_init(cpu, adev->name,
356 aevt->mode = CLOCK_EVT_MODE_UNUSED; 206 APBT_CLOCKEVENT_RATING, adev_virt_addr(adev),
207 adev->irq, apbt_freq);
208 adev->timer->eoi = NULL;
209 } else {
210 dw_apb_clockevent_resume(adev->timer);
211 }
357 212
358 printk(KERN_INFO "Registering CPU %d clockevent device %s, mask %08x\n", 213 printk(KERN_INFO "Registering CPU %d clockevent device %s, cpu %08x\n",
359 cpu, aevt->name, *(u32 *)aevt->cpumask); 214 cpu, adev->name, adev->cpu);
360 215
361 apbt_setup_irq(adev); 216 apbt_setup_irq(adev);
362 217 dw_apb_clockevent_register(adev->timer);
363 clockevents_register_device(aevt);
364
365 apbt_enable_int(cpu);
366 218
367 return; 219 return;
368} 220}
@@ -385,13 +237,12 @@ static int apbt_cpuhp_notify(struct notifier_block *n,
385 237
386 switch (action & 0xf) { 238 switch (action & 0xf) {
387 case CPU_DEAD: 239 case CPU_DEAD:
388 disable_irq(adev->irq); 240 dw_apb_clockevent_pause(adev->timer);
389 apbt_disable_int(cpu);
390 if (system_state == SYSTEM_RUNNING) { 241 if (system_state == SYSTEM_RUNNING) {
391 pr_debug("skipping APBT CPU %lu offline\n", cpu); 242 pr_debug("skipping APBT CPU %lu offline\n", cpu);
392 } else if (adev) { 243 } else if (adev) {
393 pr_debug("APBT clockevent for cpu %lu offline\n", cpu); 244 pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
394 free_irq(adev->irq, adev); 245 dw_apb_clockevent_stop(adev->timer);
395 } 246 }
396 break; 247 break;
397 default: 248 default:
@@ -416,116 +267,16 @@ void apbt_setup_secondary_clock(void) {}
416 267
417#endif /* CONFIG_SMP */ 268#endif /* CONFIG_SMP */
418 269
419static void apbt_set_mode(enum clock_event_mode mode,
420 struct clock_event_device *evt)
421{
422 unsigned long ctrl;
423 uint64_t delta;
424 int timer_num;
425 struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
426
427 BUG_ON(!apbt_virt_address);
428
429 timer_num = adev->num;
430 pr_debug("%s CPU %d timer %d mode=%d\n",
431 __func__, first_cpu(*evt->cpumask), timer_num, mode);
432
433 switch (mode) {
434 case CLOCK_EVT_MODE_PERIODIC:
435 delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * apbt_clockevent.mult;
436 delta >>= apbt_clockevent.shift;
437 ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
438 ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
439 apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
440 /*
441 * DW APB p. 46, have to disable timer before load counter,
442 * may cause sync problem.
443 */
444 ctrl &= ~APBTMR_CONTROL_ENABLE;
445 apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
446 udelay(1);
447 pr_debug("Setting clock period %d for HZ %d\n", (int)delta, HZ);
448 apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
449 ctrl |= APBTMR_CONTROL_ENABLE;
450 apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
451 break;
452 /* APB timer does not have one-shot mode, use free running mode */
453 case CLOCK_EVT_MODE_ONESHOT:
454 ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
455 /*
456 * set free running mode, this mode will let timer reload max
457 * timeout which will give time (3min on 25MHz clock) to rearm
458 * the next event, therefore emulate the one-shot mode.
459 */
460 ctrl &= ~APBTMR_CONTROL_ENABLE;
461 ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
462
463 apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
464 /* write again to set free running mode */
465 apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
466
467 /*
468 * DW APB p. 46, load counter with all 1s before starting free
469 * running mode.
470 */
471 apbt_writel(timer_num, ~0, APBTMR_N_LOAD_COUNT);
472 ctrl &= ~APBTMR_CONTROL_INT;
473 ctrl |= APBTMR_CONTROL_ENABLE;
474 apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
475 break;
476
477 case CLOCK_EVT_MODE_UNUSED:
478 case CLOCK_EVT_MODE_SHUTDOWN:
479 apbt_disable_int(timer_num);
480 ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
481 ctrl &= ~APBTMR_CONTROL_ENABLE;
482 apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
483 break;
484
485 case CLOCK_EVT_MODE_RESUME:
486 apbt_enable_int(timer_num);
487 break;
488 }
489}
490
491static int apbt_next_event(unsigned long delta,
492 struct clock_event_device *evt)
493{
494 unsigned long ctrl;
495 int timer_num;
496
497 struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
498
499 timer_num = adev->num;
500 /* Disable timer */
501 ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
502 ctrl &= ~APBTMR_CONTROL_ENABLE;
503 apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
504 /* write new count */
505 apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
506 ctrl |= APBTMR_CONTROL_ENABLE;
507 apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
508 return 0;
509}
510
511static cycle_t apbt_read_clocksource(struct clocksource *cs)
512{
513 unsigned long current_count;
514
515 current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
516 return (cycle_t)~current_count;
517}
518
519static int apbt_clocksource_register(void) 270static int apbt_clocksource_register(void)
520{ 271{
521 u64 start, now; 272 u64 start, now;
522 cycle_t t1; 273 cycle_t t1;
523 274
524 /* Start the counter, use timer 2 as source, timer 0/1 for event */ 275 /* Start the counter, use timer 2 as source, timer 0/1 for event */
525 apbt_start_counter(phy_cs_timer_id); 276 dw_apb_clocksource_start(clocksource_apbt);
526 277
527 /* Verify whether apbt counter works */ 278 /* Verify whether apbt counter works */
528 t1 = apbt_read_clocksource(&clocksource_apbt); 279 t1 = dw_apb_clocksource_read(clocksource_apbt);
529 rdtscll(start); 280 rdtscll(start);
530 281
531 /* 282 /*
@@ -540,10 +291,10 @@ static int apbt_clocksource_register(void)
540 } while ((now - start) < 200000UL); 291 } while ((now - start) < 200000UL);
541 292
542 /* APBT is the only always on clocksource, it has to work! */ 293 /* APBT is the only always on clocksource, it has to work! */
543 if (t1 == apbt_read_clocksource(&clocksource_apbt)) 294 if (t1 == dw_apb_clocksource_read(clocksource_apbt))
544 panic("APBT counter not counting. APBT disabled\n"); 295 panic("APBT counter not counting. APBT disabled\n");
545 296
546 clocksource_register_khz(&clocksource_apbt, (u32)apbt_freq*1000); 297 dw_apb_clocksource_register(clocksource_apbt);
547 298
548 return 0; 299 return 0;
549} 300}
@@ -567,10 +318,7 @@ void __init apbt_time_init(void)
567 if (apb_timer_block_enabled) 318 if (apb_timer_block_enabled)
568 return; 319 return;
569 apbt_set_mapping(); 320 apbt_set_mapping();
570 if (apbt_virt_address) { 321 if (!apbt_virt_address)
571 pr_debug("Found APBT version 0x%lx\n",\
572 apbt_readl_reg(APBTMRS_COMP_VERSION));
573 } else
574 goto out_noapbt; 322 goto out_noapbt;
575 /* 323 /*
576 * Read the frequency and check for a sane value, for ESL model 324 * Read the frequency and check for a sane value, for ESL model
@@ -578,7 +326,7 @@ void __init apbt_time_init(void)
578 */ 326 */
579 327
580 if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) { 328 if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) {
581 pr_debug("APBT has invalid freq 0x%llx\n", apbt_freq); 329 pr_debug("APBT has invalid freq 0x%lx\n", apbt_freq);
582 goto out_noapbt; 330 goto out_noapbt;
583 } 331 }
584 if (apbt_clocksource_register()) { 332 if (apbt_clocksource_register()) {
@@ -604,30 +352,20 @@ void __init apbt_time_init(void)
604 } else { 352 } else {
605 percpu_timer = 0; 353 percpu_timer = 0;
606 apbt_num_timers_used = 1; 354 apbt_num_timers_used = 1;
607 adev = &per_cpu(cpu_apbt_dev, 0);
608 adev->flags &= ~APBT_DEV_USED;
609 } 355 }
610 pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used); 356 pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used);
611 357
612 /* here we set up per CPU timer data structure */ 358 /* here we set up per CPU timer data structure */
613 apbt_devs = kzalloc(sizeof(struct apbt_dev) * apbt_num_timers_used,
614 GFP_KERNEL);
615 if (!apbt_devs) {
616 printk(KERN_ERR "Failed to allocate APB timer devices\n");
617 return;
618 }
619 for (i = 0; i < apbt_num_timers_used; i++) { 359 for (i = 0; i < apbt_num_timers_used; i++) {
620 adev = &per_cpu(cpu_apbt_dev, i); 360 adev = &per_cpu(cpu_apbt_dev, i);
621 adev->num = i; 361 adev->num = i;
622 adev->cpu = i; 362 adev->cpu = i;
623 p_mtmr = sfi_get_mtmr(i); 363 p_mtmr = sfi_get_mtmr(i);
624 if (p_mtmr) { 364 if (p_mtmr)
625 adev->tick = p_mtmr->freq_hz;
626 adev->irq = p_mtmr->irq; 365 adev->irq = p_mtmr->irq;
627 } else 366 else
628 printk(KERN_ERR "Failed to get timer for cpu %d\n", i); 367 printk(KERN_ERR "Failed to get timer for cpu %d\n", i);
629 adev->count = 0; 368 snprintf(adev->name, sizeof(adev->name) - 1, "apbt%d", i);
630 sprintf(adev->name, "apbt%d", i);
631 } 369 }
632#endif 370#endif
633 371
@@ -639,17 +377,8 @@ out_noapbt:
639 panic("failed to enable APB timer\n"); 377 panic("failed to enable APB timer\n");
640} 378}
641 379
642static inline void apbt_disable(int n)
643{
644 if (is_apbt_capable()) {
645 unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
646 ctrl &= ~APBTMR_CONTROL_ENABLE;
647 apbt_writel(n, ctrl, APBTMR_N_CONTROL);
648 }
649}
650
651/* called before apb_timer_enable, use early map */ 380/* called before apb_timer_enable, use early map */
652unsigned long apbt_quick_calibrate() 381unsigned long apbt_quick_calibrate(void)
653{ 382{
654 int i, scale; 383 int i, scale;
655 u64 old, new; 384 u64 old, new;
@@ -658,31 +387,31 @@ unsigned long apbt_quick_calibrate()
658 u32 loop, shift; 387 u32 loop, shift;
659 388
660 apbt_set_mapping(); 389 apbt_set_mapping();
661 apbt_start_counter(phy_cs_timer_id); 390 dw_apb_clocksource_start(clocksource_apbt);
662 391
663 /* check if the timer can count down, otherwise return */ 392 /* check if the timer can count down, otherwise return */
664 old = apbt_read_clocksource(&clocksource_apbt); 393 old = dw_apb_clocksource_read(clocksource_apbt);
665 i = 10000; 394 i = 10000;
666 while (--i) { 395 while (--i) {
667 if (old != apbt_read_clocksource(&clocksource_apbt)) 396 if (old != dw_apb_clocksource_read(clocksource_apbt))
668 break; 397 break;
669 } 398 }
670 if (!i) 399 if (!i)
671 goto failed; 400 goto failed;
672 401
673 /* count 16 ms */ 402 /* count 16 ms */
674 loop = (apbt_freq * 1000) << 4; 403 loop = (apbt_freq / 1000) << 4;
675 404
676 /* restart the timer to ensure it won't get to 0 in the calibration */ 405 /* restart the timer to ensure it won't get to 0 in the calibration */
677 apbt_start_counter(phy_cs_timer_id); 406 dw_apb_clocksource_start(clocksource_apbt);
678 407
679 old = apbt_read_clocksource(&clocksource_apbt); 408 old = dw_apb_clocksource_read(clocksource_apbt);
680 old += loop; 409 old += loop;
681 410
682 t1 = __native_read_tsc(); 411 t1 = __native_read_tsc();
683 412
684 do { 413 do {
685 new = apbt_read_clocksource(&clocksource_apbt); 414 new = dw_apb_clocksource_read(clocksource_apbt);
686 } while (new < old); 415 } while (new < old);
687 416
688 t2 = __native_read_tsc(); 417 t2 = __native_read_tsc();
@@ -694,7 +423,7 @@ unsigned long apbt_quick_calibrate()
694 return 0; 423 return 0;
695 } 424 }
696 scale = (int)div_u64((t2 - t1), loop >> shift); 425 scale = (int)div_u64((t2 - t1), loop >> shift);
697 khz = (scale * apbt_freq * 1000) >> shift; 426 khz = (scale * (apbt_freq / 1000)) >> shift;
698 printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz); 427 printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz);
699 return khz; 428 return khz;
700failed: 429failed:
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index d8d3e02b912c..34e9c4f88926 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -12,3 +12,6 @@ config CLKBLD_I8253
12 12
13config CLKSRC_MMIO 13config CLKSRC_MMIO
14 bool 14 bool
15
16config DW_APB_TIMER
17 bool
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 7922a0cfc99f..85ad1646a7b7 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o
8obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o 8obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
9obj-$(CONFIG_CLKBLD_I8253) += i8253.o 9obj-$(CONFIG_CLKBLD_I8253) += i8253.o
10obj-$(CONFIG_CLKSRC_MMIO) += mmio.o 10obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
11obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
new file mode 100644
index 000000000000..580f870541a3
--- /dev/null
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -0,0 +1,401 @@
1/*
2 * (C) Copyright 2009 Intel Corporation
3 * Author: Jacob Pan (jacob.jun.pan@intel.com)
4 *
5 * Shared with ARM platforms, Jamie Iles, Picochip 2011
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 version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Support for the Synopsys DesignWare APB Timers.
12 */
13#include <linux/dw_apb_timer.h>
14#include <linux/delay.h>
15#include <linux/kernel.h>
16#include <linux/interrupt.h>
17#include <linux/irq.h>
18#include <linux/io.h>
19#include <linux/slab.h>
20
21#define APBT_MIN_PERIOD 4
22#define APBT_MIN_DELTA_USEC 200
23
24#define APBTMR_N_LOAD_COUNT 0x00
25#define APBTMR_N_CURRENT_VALUE 0x04
26#define APBTMR_N_CONTROL 0x08
27#define APBTMR_N_EOI 0x0c
28#define APBTMR_N_INT_STATUS 0x10
29
30#define APBTMRS_INT_STATUS 0xa0
31#define APBTMRS_EOI 0xa4
32#define APBTMRS_RAW_INT_STATUS 0xa8
33#define APBTMRS_COMP_VERSION 0xac
34
35#define APBTMR_CONTROL_ENABLE (1 << 0)
36/* 1: periodic, 0:free running. */
37#define APBTMR_CONTROL_MODE_PERIODIC (1 << 1)
38#define APBTMR_CONTROL_INT (1 << 2)
39
40static inline struct dw_apb_clock_event_device *
41ced_to_dw_apb_ced(struct clock_event_device *evt)
42{
43 return container_of(evt, struct dw_apb_clock_event_device, ced);
44}
45
46static inline struct dw_apb_clocksource *
47clocksource_to_dw_apb_clocksource(struct clocksource *cs)
48{
49 return container_of(cs, struct dw_apb_clocksource, cs);
50}
51
52static unsigned long apbt_readl(struct dw_apb_timer *timer, unsigned long offs)
53{
54 return readl(timer->base + offs);
55}
56
57static void apbt_writel(struct dw_apb_timer *timer, unsigned long val,
58 unsigned long offs)
59{
60 writel(val, timer->base + offs);
61}
62
63static void apbt_disable_int(struct dw_apb_timer *timer)
64{
65 unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
66
67 ctrl |= APBTMR_CONTROL_INT;
68 apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
69}
70
71/**
72 * dw_apb_clockevent_pause() - stop the clock_event_device from running
73 *
74 * @dw_ced: The APB clock to stop generating events.
75 */
76void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced)
77{
78 disable_irq(dw_ced->timer.irq);
79 apbt_disable_int(&dw_ced->timer);
80}
81
82static void apbt_eoi(struct dw_apb_timer *timer)
83{
84 apbt_readl(timer, APBTMR_N_EOI);
85}
86
87static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
88{
89 struct clock_event_device *evt = data;
90 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
91
92 if (!evt->event_handler) {
93 pr_info("Spurious APBT timer interrupt %d", irq);
94 return IRQ_NONE;
95 }
96
97 if (dw_ced->eoi)
98 dw_ced->eoi(&dw_ced->timer);
99
100 evt->event_handler(evt);
101 return IRQ_HANDLED;
102}
103
104static void apbt_enable_int(struct dw_apb_timer *timer)
105{
106 unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
107 /* clear pending intr */
108 apbt_readl(timer, APBTMR_N_EOI);
109 ctrl &= ~APBTMR_CONTROL_INT;
110 apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
111}
112
113static void apbt_set_mode(enum clock_event_mode mode,
114 struct clock_event_device *evt)
115{
116 unsigned long ctrl;
117 unsigned long period;
118 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
119
120 pr_debug("%s CPU %d mode=%d\n", __func__, first_cpu(*evt->cpumask),
121 mode);
122
123 switch (mode) {
124 case CLOCK_EVT_MODE_PERIODIC:
125 period = DIV_ROUND_UP(dw_ced->timer.freq, HZ);
126 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
127 ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
128 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
129 /*
130 * DW APB p. 46, have to disable timer before load counter,
131 * may cause sync problem.
132 */
133 ctrl &= ~APBTMR_CONTROL_ENABLE;
134 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
135 udelay(1);
136 pr_debug("Setting clock period %lu for HZ %d\n", period, HZ);
137 apbt_writel(&dw_ced->timer, period, APBTMR_N_LOAD_COUNT);
138 ctrl |= APBTMR_CONTROL_ENABLE;
139 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
140 break;
141
142 case CLOCK_EVT_MODE_ONESHOT:
143 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
144 /*
145 * set free running mode, this mode will let timer reload max
146 * timeout which will give time (3min on 25MHz clock) to rearm
147 * the next event, therefore emulate the one-shot mode.
148 */
149 ctrl &= ~APBTMR_CONTROL_ENABLE;
150 ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
151
152 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
153 /* write again to set free running mode */
154 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
155
156 /*
157 * DW APB p. 46, load counter with all 1s before starting free
158 * running mode.
159 */
160 apbt_writel(&dw_ced->timer, ~0, APBTMR_N_LOAD_COUNT);
161 ctrl &= ~APBTMR_CONTROL_INT;
162 ctrl |= APBTMR_CONTROL_ENABLE;
163 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
164 break;
165
166 case CLOCK_EVT_MODE_UNUSED:
167 case CLOCK_EVT_MODE_SHUTDOWN:
168 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
169 ctrl &= ~APBTMR_CONTROL_ENABLE;
170 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
171 break;
172
173 case CLOCK_EVT_MODE_RESUME:
174 apbt_enable_int(&dw_ced->timer);
175 break;
176 }
177}
178
179static int apbt_next_event(unsigned long delta,
180 struct clock_event_device *evt)
181{
182 unsigned long ctrl;
183 struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
184
185 /* Disable timer */
186 ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
187 ctrl &= ~APBTMR_CONTROL_ENABLE;
188 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
189 /* write new count */
190 apbt_writel(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
191 ctrl |= APBTMR_CONTROL_ENABLE;
192 apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
193
194 return 0;
195}
196
197/**
198 * dw_apb_clockevent_init() - use an APB timer as a clock_event_device
199 *
200 * @cpu: The CPU the events will be targeted at.
201 * @name: The name used for the timer and the IRQ for it.
202 * @rating: The rating to give the timer.
203 * @base: I/O base for the timer registers.
204 * @irq: The interrupt number to use for the timer.
205 * @freq: The frequency that the timer counts at.
206 *
207 * This creates a clock_event_device for using with the generic clock layer
208 * but does not start and register it. This should be done with
209 * dw_apb_clockevent_register() as the next step. If this is the first time
210 * it has been called for a timer then the IRQ will be requested, if not it
211 * just be enabled to allow CPU hotplug to avoid repeatedly requesting and
212 * releasing the IRQ.
213 */
214struct dw_apb_clock_event_device *
215dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
216 void __iomem *base, int irq, unsigned long freq)
217{
218 struct dw_apb_clock_event_device *dw_ced =
219 kzalloc(sizeof(*dw_ced), GFP_KERNEL);
220 int err;
221
222 if (!dw_ced)
223 return NULL;
224
225 dw_ced->timer.base = base;
226 dw_ced->timer.irq = irq;
227 dw_ced->timer.freq = freq;
228
229 clockevents_calc_mult_shift(&dw_ced->ced, freq, APBT_MIN_PERIOD);
230 dw_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff,
231 &dw_ced->ced);
232 dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced);
233 dw_ced->ced.cpumask = cpumask_of(cpu);
234 dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
235 dw_ced->ced.set_mode = apbt_set_mode;
236 dw_ced->ced.set_next_event = apbt_next_event;
237 dw_ced->ced.irq = dw_ced->timer.irq;
238 dw_ced->ced.rating = rating;
239 dw_ced->ced.name = name;
240
241 dw_ced->irqaction.name = dw_ced->ced.name;
242 dw_ced->irqaction.handler = dw_apb_clockevent_irq;
243 dw_ced->irqaction.dev_id = &dw_ced->ced;
244 dw_ced->irqaction.irq = irq;
245 dw_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL |
246 IRQF_NOBALANCING |
247 IRQF_DISABLED;
248
249 dw_ced->eoi = apbt_eoi;
250 err = setup_irq(irq, &dw_ced->irqaction);
251 if (err) {
252 pr_err("failed to request timer irq\n");
253 kfree(dw_ced);
254 dw_ced = NULL;
255 }
256
257 return dw_ced;
258}
259
260/**
261 * dw_apb_clockevent_resume() - resume a clock that has been paused.
262 *
263 * @dw_ced: The APB clock to resume.
264 */
265void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced)
266{
267 enable_irq(dw_ced->timer.irq);
268}
269
270/**
271 * dw_apb_clockevent_stop() - stop the clock_event_device and release the IRQ.
272 *
273 * @dw_ced: The APB clock to stop generating the events.
274 */
275void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced)
276{
277 free_irq(dw_ced->timer.irq, &dw_ced->ced);
278}
279
280/**
281 * dw_apb_clockevent_register() - register the clock with the generic layer
282 *
283 * @dw_ced: The APB clock to register as a clock_event_device.
284 */
285void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced)
286{
287 apbt_writel(&dw_ced->timer, 0, APBTMR_N_CONTROL);
288 clockevents_register_device(&dw_ced->ced);
289 apbt_enable_int(&dw_ced->timer);
290}
291
292/**
293 * dw_apb_clocksource_start() - start the clocksource counting.
294 *
295 * @dw_cs: The clocksource to start.
296 *
297 * This is used to start the clocksource before registration and can be used
298 * to enable calibration of timers.
299 */
300void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs)
301{
302 /*
303 * start count down from 0xffff_ffff. this is done by toggling the
304 * enable bit then load initial load count to ~0.
305 */
306 unsigned long ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL);
307
308 ctrl &= ~APBTMR_CONTROL_ENABLE;
309 apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
310 apbt_writel(&dw_cs->timer, ~0, APBTMR_N_LOAD_COUNT);
311 /* enable, mask interrupt */
312 ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
313 ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
314 apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
315 /* read it once to get cached counter value initialized */
316 dw_apb_clocksource_read(dw_cs);
317}
318
319static cycle_t __apbt_read_clocksource(struct clocksource *cs)
320{
321 unsigned long current_count;
322 struct dw_apb_clocksource *dw_cs =
323 clocksource_to_dw_apb_clocksource(cs);
324
325 current_count = apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
326
327 return (cycle_t)~current_count;
328}
329
330static void apbt_restart_clocksource(struct clocksource *cs)
331{
332 struct dw_apb_clocksource *dw_cs =
333 clocksource_to_dw_apb_clocksource(cs);
334
335 dw_apb_clocksource_start(dw_cs);
336}
337
338/**
339 * dw_apb_clocksource_init() - use an APB timer as a clocksource.
340 *
341 * @rating: The rating to give the clocksource.
342 * @name: The name for the clocksource.
343 * @base: The I/O base for the timer registers.
344 * @freq: The frequency that the timer counts at.
345 *
346 * This creates a clocksource using an APB timer but does not yet register it
347 * with the clocksource system. This should be done with
348 * dw_apb_clocksource_register() as the next step.
349 */
350struct dw_apb_clocksource *
351dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base,
352 unsigned long freq)
353{
354 struct dw_apb_clocksource *dw_cs = kzalloc(sizeof(*dw_cs), GFP_KERNEL);
355
356 if (!dw_cs)
357 return NULL;
358
359 dw_cs->timer.base = base;
360 dw_cs->timer.freq = freq;
361 dw_cs->cs.name = name;
362 dw_cs->cs.rating = rating;
363 dw_cs->cs.read = __apbt_read_clocksource;
364 dw_cs->cs.mask = CLOCKSOURCE_MASK(32);
365 dw_cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
366 dw_cs->cs.resume = apbt_restart_clocksource;
367
368 return dw_cs;
369}
370
371/**
372 * dw_apb_clocksource_register() - register the APB clocksource.
373 *
374 * @dw_cs: The clocksource to register.
375 */
376void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs)
377{
378 clocksource_register_hz(&dw_cs->cs, dw_cs->timer.freq);
379}
380
381/**
382 * dw_apb_clocksource_read() - read the current value of a clocksource.
383 *
384 * @dw_cs: The clocksource to read.
385 */
386cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs)
387{
388 return (cycle_t)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
389}
390
391/**
392 * dw_apb_clocksource_unregister() - unregister and free a clocksource.
393 *
394 * @dw_cs: The clocksource to unregister/free.
395 */
396void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs)
397{
398 clocksource_unregister(&dw_cs->cs);
399
400 kfree(dw_cs);
401}
diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h
new file mode 100644
index 000000000000..49638ea3b776
--- /dev/null
+++ b/include/linux/dw_apb_timer.h
@@ -0,0 +1,56 @@
1/*
2 * (C) Copyright 2009 Intel Corporation
3 * Author: Jacob Pan (jacob.jun.pan@intel.com)
4 *
5 * Shared with ARM platforms, Jamie Iles, Picochip 2011
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 version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Support for the Synopsys DesignWare APB Timers.
12 */
13#ifndef __DW_APB_TIMER_H__
14#define __DW_APB_TIMER_H__
15
16#include <linux/clockchips.h>
17#include <linux/clocksource.h>
18#include <linux/interrupt.h>
19
20#define APBTMRS_REG_SIZE 0x14
21
22struct dw_apb_timer {
23 void __iomem *base;
24 unsigned long freq;
25 int irq;
26};
27
28struct dw_apb_clock_event_device {
29 struct clock_event_device ced;
30 struct dw_apb_timer timer;
31 struct irqaction irqaction;
32 void (*eoi)(struct dw_apb_timer *);
33};
34
35struct dw_apb_clocksource {
36 struct dw_apb_timer timer;
37 struct clocksource cs;
38};
39
40void dw_apb_clockevent_register(struct dw_apb_clock_event_device *dw_ced);
41void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced);
42void dw_apb_clockevent_resume(struct dw_apb_clock_event_device *dw_ced);
43void dw_apb_clockevent_stop(struct dw_apb_clock_event_device *dw_ced);
44
45struct dw_apb_clock_event_device *
46dw_apb_clockevent_init(int cpu, const char *name, unsigned rating,
47 void __iomem *base, int irq, unsigned long freq);
48struct dw_apb_clocksource *
49dw_apb_clocksource_init(unsigned rating, char *name, void __iomem *base,
50 unsigned long freq);
51void dw_apb_clocksource_register(struct dw_apb_clocksource *dw_cs);
52void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs);
53cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs);
54void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs);
55
56#endif /* __DW_APB_TIMER_H__ */