diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2018-11-30 19:53:10 -0500 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2019-03-25 05:22:24 -0400 |
commit | 2ed16626f58f88892864ed0cd68f841872ed1ca1 (patch) | |
tree | 99d01f9998f5d8a3a438525dcb2511d146b84aea /arch/m68k | |
parent | 3384df06c131833ef5fbc117cccfe6aac331bdda (diff) |
m68k: hp300: Convert to clocksource API
Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68k')
-rw-r--r-- | arch/m68k/hp300/time.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c index d30b03ea93a2..90982803a629 100644 --- a/arch/m68k/hp300/time.c +++ b/arch/m68k/hp300/time.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <asm/ptrace.h> | 10 | #include <asm/ptrace.h> |
11 | #include <linux/clocksource.h> | ||
11 | #include <linux/types.h> | 12 | #include <linux/types.h> |
12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
13 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
@@ -19,6 +20,18 @@ | |||
19 | #include <asm/traps.h> | 20 | #include <asm/traps.h> |
20 | #include <asm/blinken.h> | 21 | #include <asm/blinken.h> |
21 | 22 | ||
23 | static u64 hp300_read_clk(struct clocksource *cs); | ||
24 | |||
25 | static struct clocksource hp300_clk = { | ||
26 | .name = "timer", | ||
27 | .rating = 250, | ||
28 | .read = hp300_read_clk, | ||
29 | .mask = CLOCKSOURCE_MASK(32), | ||
30 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
31 | }; | ||
32 | |||
33 | static u32 clk_total; | ||
34 | |||
22 | /* Clock hardware definitions */ | 35 | /* Clock hardware definitions */ |
23 | 36 | ||
24 | #define CLOCKBASE 0xf05f8000 | 37 | #define CLOCKBASE 0xf05f8000 |
@@ -32,9 +45,10 @@ | |||
32 | #define CLKMSB3 0xD | 45 | #define CLKMSB3 0xD |
33 | 46 | ||
34 | /* This is for machines which generate the exact clock. */ | 47 | /* This is for machines which generate the exact clock. */ |
35 | #define USECS_PER_JIFFY (1000000/HZ) | ||
36 | 48 | ||
37 | #define INTVAL ((10000 / 4) - 1) | 49 | #define HP300_TIMER_CLOCK_FREQ 250000 |
50 | #define HP300_TIMER_CYCLES (HP300_TIMER_CLOCK_FREQ / HZ) | ||
51 | #define INTVAL (HP300_TIMER_CYCLES - 1) | ||
38 | 52 | ||
39 | static irqreturn_t hp300_tick(int irq, void *dev_id) | 53 | static irqreturn_t hp300_tick(int irq, void *dev_id) |
40 | { | 54 | { |
@@ -45,6 +59,7 @@ static irqreturn_t hp300_tick(int irq, void *dev_id) | |||
45 | local_irq_save(flags); | 59 | local_irq_save(flags); |
46 | in_8(CLOCKBASE + CLKSR); | 60 | in_8(CLOCKBASE + CLKSR); |
47 | asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE)); | 61 | asm volatile ("movpw %1@(5),%0" : "=d" (tmp) : "a" (CLOCKBASE)); |
62 | clk_total += INTVAL; | ||
48 | timer_routine(0, NULL); | 63 | timer_routine(0, NULL); |
49 | local_irq_restore(flags); | 64 | local_irq_restore(flags); |
50 | 65 | ||
@@ -53,20 +68,26 @@ static irqreturn_t hp300_tick(int irq, void *dev_id) | |||
53 | return IRQ_HANDLED; | 68 | return IRQ_HANDLED; |
54 | } | 69 | } |
55 | 70 | ||
56 | u32 hp300_gettimeoffset(void) | 71 | static u64 hp300_read_clk(struct clocksource *cs) |
57 | { | 72 | { |
58 | /* Read current timer 1 value */ | 73 | unsigned long flags; |
59 | unsigned char lsb, msb1, msb2; | 74 | unsigned char lsb, msb1, msb2; |
60 | unsigned short ticks; | 75 | u32 ticks; |
61 | 76 | ||
77 | local_irq_save(flags); | ||
78 | /* Read current timer 1 value */ | ||
62 | msb1 = in_8(CLOCKBASE + 5); | 79 | msb1 = in_8(CLOCKBASE + 5); |
63 | lsb = in_8(CLOCKBASE + 7); | 80 | lsb = in_8(CLOCKBASE + 7); |
64 | msb2 = in_8(CLOCKBASE + 5); | 81 | msb2 = in_8(CLOCKBASE + 5); |
65 | if (msb1 != msb2) | 82 | if (msb1 != msb2) |
66 | /* A carry happened while we were reading. Read it again */ | 83 | /* A carry happened while we were reading. Read it again */ |
67 | lsb = in_8(CLOCKBASE + 7); | 84 | lsb = in_8(CLOCKBASE + 7); |
85 | |||
68 | ticks = INTVAL - ((msb2 << 8) | lsb); | 86 | ticks = INTVAL - ((msb2 << 8) | lsb); |
69 | return ((USECS_PER_JIFFY * ticks) / INTVAL) * 1000; | 87 | ticks += clk_total; |
88 | local_irq_restore(flags); | ||
89 | |||
90 | return ticks; | ||
70 | } | 91 | } |
71 | 92 | ||
72 | void __init hp300_sched_init(irq_handler_t vector) | 93 | void __init hp300_sched_init(irq_handler_t vector) |
@@ -76,9 +97,11 @@ void __init hp300_sched_init(irq_handler_t vector) | |||
76 | 97 | ||
77 | asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); | 98 | asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); |
78 | 99 | ||
79 | if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector)) | 100 | if (request_irq(IRQ_AUTO_6, hp300_tick, IRQF_TIMER, "timer tick", vector)) |
80 | pr_err("Couldn't register timer interrupt\n"); | 101 | pr_err("Couldn't register timer interrupt\n"); |
81 | 102 | ||
82 | out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ | 103 | out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */ |
83 | out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */ | 104 | out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */ |
105 | |||
106 | clocksource_register_hz(&hp300_clk, HP300_TIMER_CLOCK_FREQ); | ||
84 | } | 107 | } |