diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-04 11:38:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-04 11:38:26 -0400 |
commit | ac3c1c4f1c77190408162aee559c655090597072 (patch) | |
tree | 6c0e1ddbada6d6dbfb59b7f8d766dfd38b7321f1 | |
parent | 5e0b3a4e88012d259e8b2c0f02f393c79686daf9 (diff) | |
parent | cfb6d656d569510ac9239583ce09e4c92ad54719 (diff) |
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer changes from Ingo Molnar:
"Various clocksource driver updates: extend the core with memory mapped
hardware (mmio) support and add new (ARM) Moxart SoC and sun4i
hardware support"
* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
clocksource: arch_timer: Add support for memory mapped timers
clocksource: arch_timer: Push the read/write wrappers deeper
Documentation: Add memory mapped ARM architected timer binding
clocksource: arch_timer: Pass clock event to set_mode callback
clocksource: arch_timer: Make register accessors less error-prone
ARM: clocksource: moxart: documentation: Update device tree bindings document
ARM: clocksource: moxart: Add bitops.h include
ARM: clocksource: moxart: documentation: Fix device tree bindings document
ARM: clocksource: Add support for MOXA ART SoCs
clocksource: cadence_ttc: Reuse clocksource as sched_clock
clocksource: cadence_ttc: Remove unused header
clocksource: sun4i: Fix bug when switching from periodic to oneshot modes
clocksource: sun4i: Cleanup parent clock setup
clocksource: sun4i: Remove TIMER_SCAL variable
clocksource: sun4i: Factor out some timer code
clocksource: sun4i: Fix the next event code
clocksource: sun4i: Don't forget to enable the clock we use
clocksource: sun4i: Add clocksource and sched clock drivers
clocksource: sun4i: rename AUTORELOAD define to RELOAD
clocksource: sun4i: Wrap macros arguments in parenthesis
...
-rw-r--r-- | Documentation/devicetree/bindings/arm/arch_timer.txt | 59 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt | 17 | ||||
-rw-r--r-- | MAINTAINERS | 10 | ||||
-rw-r--r-- | arch/arm/include/asm/arch_timer.h | 14 | ||||
-rw-r--r-- | arch/arm64/include/asm/arch_timer.h | 23 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 447 | ||||
-rw-r--r-- | drivers/clocksource/cadence_ttc_timer.c | 13 | ||||
-rw-r--r-- | drivers/clocksource/moxart_timer.c | 165 | ||||
-rw-r--r-- | drivers/clocksource/sun4i_timer.c | 110 | ||||
-rw-r--r-- | drivers/clocksource/time-orion.c | 2 | ||||
-rw-r--r-- | include/clocksource/arm_arch_timer.h | 10 |
12 files changed, 738 insertions, 133 deletions
diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt index 20746e5abe6f..06fc7602593a 100644 --- a/Documentation/devicetree/bindings/arm/arch_timer.txt +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt | |||
@@ -1,10 +1,14 @@ | |||
1 | * ARM architected timer | 1 | * ARM architected timer |
2 | 2 | ||
3 | ARM cores may have a per-core architected timer, which provides per-cpu timers. | 3 | ARM cores may have a per-core architected timer, which provides per-cpu timers, |
4 | or a memory mapped architected timer, which provides up to 8 frames with a | ||
5 | physical and optional virtual timer per frame. | ||
4 | 6 | ||
5 | The timer is attached to a GIC to deliver its per-processor interrupts. | 7 | The per-core architected timer is attached to a GIC to deliver its |
8 | per-processor interrupts via PPIs. The memory mapped timer is attached to a GIC | ||
9 | to deliver its interrupts via SPIs. | ||
6 | 10 | ||
7 | ** Timer node properties: | 11 | ** CP15 Timer node properties: |
8 | 12 | ||
9 | - compatible : Should at least contain one of | 13 | - compatible : Should at least contain one of |
10 | "arm,armv7-timer" | 14 | "arm,armv7-timer" |
@@ -26,3 +30,52 @@ Example: | |||
26 | <1 10 0xf08>; | 30 | <1 10 0xf08>; |
27 | clock-frequency = <100000000>; | 31 | clock-frequency = <100000000>; |
28 | }; | 32 | }; |
33 | |||
34 | ** Memory mapped timer node properties: | ||
35 | |||
36 | - compatible : Should at least contain "arm,armv7-timer-mem". | ||
37 | |||
38 | - clock-frequency : The frequency of the main counter, in Hz. Optional. | ||
39 | |||
40 | - reg : The control frame base address. | ||
41 | |||
42 | Note that #address-cells, #size-cells, and ranges shall be present to ensure | ||
43 | the CPU can address a frame's registers. | ||
44 | |||
45 | A timer node has up to 8 frame sub-nodes, each with the following properties: | ||
46 | |||
47 | - frame-number: 0 to 7. | ||
48 | |||
49 | - interrupts : Interrupt list for physical and virtual timers in that order. | ||
50 | The virtual timer interrupt is optional. | ||
51 | |||
52 | - reg : The first and second view base addresses in that order. The second view | ||
53 | base address is optional. | ||
54 | |||
55 | - status : "disabled" indicates the frame is not available for use. Optional. | ||
56 | |||
57 | Example: | ||
58 | |||
59 | timer@f0000000 { | ||
60 | compatible = "arm,armv7-timer-mem"; | ||
61 | #address-cells = <1>; | ||
62 | #size-cells = <1>; | ||
63 | ranges; | ||
64 | reg = <0xf0000000 0x1000>; | ||
65 | clock-frequency = <50000000>; | ||
66 | |||
67 | frame@f0001000 { | ||
68 | frame-number = <0> | ||
69 | interrupts = <0 13 0x8>, | ||
70 | <0 14 0x8>; | ||
71 | reg = <0xf0001000 0x1000>, | ||
72 | <0xf0002000 0x1000>; | ||
73 | }; | ||
74 | |||
75 | frame@f0003000 { | ||
76 | frame-number = <1> | ||
77 | interrupts = <0 15 0x8>; | ||
78 | reg = <0xf0003000 0x1000>; | ||
79 | status = "disabled"; | ||
80 | }; | ||
81 | }; | ||
diff --git a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt new file mode 100644 index 000000000000..da2d510cae47 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | MOXA ART timer | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible : Must be "moxa,moxart-timer" | ||
6 | - reg : Should contain registers location and length | ||
7 | - interrupts : Should contain the timer interrupt number | ||
8 | - clocks : Should contain phandle for the clock that drives the counter | ||
9 | |||
10 | Example: | ||
11 | |||
12 | timer: timer@98400000 { | ||
13 | compatible = "moxa,moxart-timer"; | ||
14 | reg = <0x98400000 0x42>; | ||
15 | interrupts = <19 1>; | ||
16 | clocks = <&coreclk>; | ||
17 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 5b32bc220d56..79dccf75252c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2125,6 +2125,13 @@ M: Russell King <linux@arm.linux.org.uk> | |||
2125 | S: Maintained | 2125 | S: Maintained |
2126 | F: include/linux/clk.h | 2126 | F: include/linux/clk.h |
2127 | 2127 | ||
2128 | CLOCKSOURCE, CLOCKEVENT DRIVERS | ||
2129 | M: Daniel Lezcano <daniel.lezcano@linaro.org> | ||
2130 | M: Thomas Gleixner <tglx@linutronix.de> | ||
2131 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core | ||
2132 | S: Supported | ||
2133 | F: drivers/clocksource | ||
2134 | |||
2128 | CISCO FCOE HBA DRIVER | 2135 | CISCO FCOE HBA DRIVER |
2129 | M: Hiral Patel <hiralpat@cisco.com> | 2136 | M: Hiral Patel <hiralpat@cisco.com> |
2130 | M: Suma Ramars <sramars@cisco.com> | 2137 | M: Suma Ramars <sramars@cisco.com> |
@@ -7156,7 +7163,7 @@ S: Maintained | |||
7156 | F: include/linux/mmc/dw_mmc.h | 7163 | F: include/linux/mmc/dw_mmc.h |
7157 | F: drivers/mmc/host/dw_mmc* | 7164 | F: drivers/mmc/host/dw_mmc* |
7158 | 7165 | ||
7159 | TIMEKEEPING, NTP | 7166 | TIMEKEEPING, CLOCKSOURCE CORE, NTP |
7160 | M: John Stultz <john.stultz@linaro.org> | 7167 | M: John Stultz <john.stultz@linaro.org> |
7161 | M: Thomas Gleixner <tglx@linutronix.de> | 7168 | M: Thomas Gleixner <tglx@linutronix.de> |
7162 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core | 7169 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core |
@@ -7169,7 +7176,6 @@ F: include/uapi/linux/timex.h | |||
7169 | F: kernel/time/clocksource.c | 7176 | F: kernel/time/clocksource.c |
7170 | F: kernel/time/time*.c | 7177 | F: kernel/time/time*.c |
7171 | F: kernel/time/ntp.c | 7178 | F: kernel/time/ntp.c |
7172 | F: drivers/clocksource | ||
7173 | 7179 | ||
7174 | TLG2300 VIDEO4LINUX-2 DRIVER | 7180 | TLG2300 VIDEO4LINUX-2 DRIVER |
7175 | M: Huang Shijie <shijie8@gmail.com> | 7181 | M: Huang Shijie <shijie8@gmail.com> |
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index e406d575c94f..5665134bfa3e 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h | |||
@@ -17,7 +17,8 @@ int arch_timer_arch_init(void); | |||
17 | * nicely work out which register we want, and chuck away the rest of | 17 | * nicely work out which register we want, and chuck away the rest of |
18 | * the code. At least it does so with a recent GCC (4.6.3). | 18 | * the code. At least it does so with a recent GCC (4.6.3). |
19 | */ | 19 | */ |
20 | static inline void arch_timer_reg_write(const int access, const int reg, u32 val) | 20 | static __always_inline |
21 | void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) | ||
21 | { | 22 | { |
22 | if (access == ARCH_TIMER_PHYS_ACCESS) { | 23 | if (access == ARCH_TIMER_PHYS_ACCESS) { |
23 | switch (reg) { | 24 | switch (reg) { |
@@ -28,9 +29,7 @@ static inline void arch_timer_reg_write(const int access, const int reg, u32 val | |||
28 | asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); | 29 | asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); |
29 | break; | 30 | break; |
30 | } | 31 | } |
31 | } | 32 | } else if (access == ARCH_TIMER_VIRT_ACCESS) { |
32 | |||
33 | if (access == ARCH_TIMER_VIRT_ACCESS) { | ||
34 | switch (reg) { | 33 | switch (reg) { |
35 | case ARCH_TIMER_REG_CTRL: | 34 | case ARCH_TIMER_REG_CTRL: |
36 | asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val)); | 35 | asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val)); |
@@ -44,7 +43,8 @@ static inline void arch_timer_reg_write(const int access, const int reg, u32 val | |||
44 | isb(); | 43 | isb(); |
45 | } | 44 | } |
46 | 45 | ||
47 | static inline u32 arch_timer_reg_read(const int access, const int reg) | 46 | static __always_inline |
47 | u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) | ||
48 | { | 48 | { |
49 | u32 val = 0; | 49 | u32 val = 0; |
50 | 50 | ||
@@ -57,9 +57,7 @@ static inline u32 arch_timer_reg_read(const int access, const int reg) | |||
57 | asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); | 57 | asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); |
58 | break; | 58 | break; |
59 | } | 59 | } |
60 | } | 60 | } else if (access == ARCH_TIMER_VIRT_ACCESS) { |
61 | |||
62 | if (access == ARCH_TIMER_VIRT_ACCESS) { | ||
63 | switch (reg) { | 61 | switch (reg) { |
64 | case ARCH_TIMER_REG_CTRL: | 62 | case ARCH_TIMER_REG_CTRL: |
65 | asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); | 63 | asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); |
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 98abd476992d..c9f1d2816c2b 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h | |||
@@ -26,7 +26,13 @@ | |||
26 | 26 | ||
27 | #include <clocksource/arm_arch_timer.h> | 27 | #include <clocksource/arm_arch_timer.h> |
28 | 28 | ||
29 | static inline void arch_timer_reg_write(int access, int reg, u32 val) | 29 | /* |
30 | * These register accessors are marked inline so the compiler can | ||
31 | * nicely work out which register we want, and chuck away the rest of | ||
32 | * the code. | ||
33 | */ | ||
34 | static __always_inline | ||
35 | void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) | ||
30 | { | 36 | { |
31 | if (access == ARCH_TIMER_PHYS_ACCESS) { | 37 | if (access == ARCH_TIMER_PHYS_ACCESS) { |
32 | switch (reg) { | 38 | switch (reg) { |
@@ -36,8 +42,6 @@ static inline void arch_timer_reg_write(int access, int reg, u32 val) | |||
36 | case ARCH_TIMER_REG_TVAL: | 42 | case ARCH_TIMER_REG_TVAL: |
37 | asm volatile("msr cntp_tval_el0, %0" : : "r" (val)); | 43 | asm volatile("msr cntp_tval_el0, %0" : : "r" (val)); |
38 | break; | 44 | break; |
39 | default: | ||
40 | BUILD_BUG(); | ||
41 | } | 45 | } |
42 | } else if (access == ARCH_TIMER_VIRT_ACCESS) { | 46 | } else if (access == ARCH_TIMER_VIRT_ACCESS) { |
43 | switch (reg) { | 47 | switch (reg) { |
@@ -47,17 +51,14 @@ static inline void arch_timer_reg_write(int access, int reg, u32 val) | |||
47 | case ARCH_TIMER_REG_TVAL: | 51 | case ARCH_TIMER_REG_TVAL: |
48 | asm volatile("msr cntv_tval_el0, %0" : : "r" (val)); | 52 | asm volatile("msr cntv_tval_el0, %0" : : "r" (val)); |
49 | break; | 53 | break; |
50 | default: | ||
51 | BUILD_BUG(); | ||
52 | } | 54 | } |
53 | } else { | ||
54 | BUILD_BUG(); | ||
55 | } | 55 | } |
56 | 56 | ||
57 | isb(); | 57 | isb(); |
58 | } | 58 | } |
59 | 59 | ||
60 | static inline u32 arch_timer_reg_read(int access, int reg) | 60 | static __always_inline |
61 | u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) | ||
61 | { | 62 | { |
62 | u32 val; | 63 | u32 val; |
63 | 64 | ||
@@ -69,8 +70,6 @@ static inline u32 arch_timer_reg_read(int access, int reg) | |||
69 | case ARCH_TIMER_REG_TVAL: | 70 | case ARCH_TIMER_REG_TVAL: |
70 | asm volatile("mrs %0, cntp_tval_el0" : "=r" (val)); | 71 | asm volatile("mrs %0, cntp_tval_el0" : "=r" (val)); |
71 | break; | 72 | break; |
72 | default: | ||
73 | BUILD_BUG(); | ||
74 | } | 73 | } |
75 | } else if (access == ARCH_TIMER_VIRT_ACCESS) { | 74 | } else if (access == ARCH_TIMER_VIRT_ACCESS) { |
76 | switch (reg) { | 75 | switch (reg) { |
@@ -80,11 +79,7 @@ static inline u32 arch_timer_reg_read(int access, int reg) | |||
80 | case ARCH_TIMER_REG_TVAL: | 79 | case ARCH_TIMER_REG_TVAL: |
81 | asm volatile("mrs %0, cntv_tval_el0" : "=r" (val)); | 80 | asm volatile("mrs %0, cntv_tval_el0" : "=r" (val)); |
82 | break; | 81 | break; |
83 | default: | ||
84 | BUILD_BUG(); | ||
85 | } | 82 | } |
86 | } else { | ||
87 | BUILD_BUG(); | ||
88 | } | 83 | } |
89 | 84 | ||
90 | return val; | 85 | return val; |
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 8b00c5cebfa4..704d6d342adc 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
@@ -18,6 +18,7 @@ obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o | |||
18 | obj-$(CONFIG_ORION_TIMER) += time-orion.o | 18 | obj-$(CONFIG_ORION_TIMER) += time-orion.o |
19 | obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o | 19 | obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o |
20 | obj-$(CONFIG_ARCH_MARCO) += timer-marco.o | 20 | obj-$(CONFIG_ARCH_MARCO) += timer-marco.o |
21 | obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o | ||
21 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o | 22 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o |
22 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o | 23 | obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o |
23 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o | 24 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o |
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index ffadd836e0b5..fbd9ccd5e114 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -16,13 +16,39 @@ | |||
16 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/of_irq.h> | 18 | #include <linux/of_irq.h> |
19 | #include <linux/of_address.h> | ||
19 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/slab.h> | ||
20 | 22 | ||
21 | #include <asm/arch_timer.h> | 23 | #include <asm/arch_timer.h> |
22 | #include <asm/virt.h> | 24 | #include <asm/virt.h> |
23 | 25 | ||
24 | #include <clocksource/arm_arch_timer.h> | 26 | #include <clocksource/arm_arch_timer.h> |
25 | 27 | ||
28 | #define CNTTIDR 0x08 | ||
29 | #define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4)) | ||
30 | |||
31 | #define CNTVCT_LO 0x08 | ||
32 | #define CNTVCT_HI 0x0c | ||
33 | #define CNTFRQ 0x10 | ||
34 | #define CNTP_TVAL 0x28 | ||
35 | #define CNTP_CTL 0x2c | ||
36 | #define CNTV_TVAL 0x38 | ||
37 | #define CNTV_CTL 0x3c | ||
38 | |||
39 | #define ARCH_CP15_TIMER BIT(0) | ||
40 | #define ARCH_MEM_TIMER BIT(1) | ||
41 | static unsigned arch_timers_present __initdata; | ||
42 | |||
43 | static void __iomem *arch_counter_base; | ||
44 | |||
45 | struct arch_timer { | ||
46 | void __iomem *base; | ||
47 | struct clock_event_device evt; | ||
48 | }; | ||
49 | |||
50 | #define to_arch_timer(e) container_of(e, struct arch_timer, evt) | ||
51 | |||
26 | static u32 arch_timer_rate; | 52 | static u32 arch_timer_rate; |
27 | 53 | ||
28 | enum ppi_nr { | 54 | enum ppi_nr { |
@@ -38,19 +64,83 @@ static int arch_timer_ppi[MAX_TIMER_PPI]; | |||
38 | static struct clock_event_device __percpu *arch_timer_evt; | 64 | static struct clock_event_device __percpu *arch_timer_evt; |
39 | 65 | ||
40 | static bool arch_timer_use_virtual = true; | 66 | static bool arch_timer_use_virtual = true; |
67 | static bool arch_timer_mem_use_virtual; | ||
41 | 68 | ||
42 | /* | 69 | /* |
43 | * Architected system timer support. | 70 | * Architected system timer support. |
44 | */ | 71 | */ |
45 | 72 | ||
46 | static inline irqreturn_t timer_handler(const int access, | 73 | static __always_inline |
74 | void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val, | ||
75 | struct clock_event_device *clk) | ||
76 | { | ||
77 | if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { | ||
78 | struct arch_timer *timer = to_arch_timer(clk); | ||
79 | switch (reg) { | ||
80 | case ARCH_TIMER_REG_CTRL: | ||
81 | writel_relaxed(val, timer->base + CNTP_CTL); | ||
82 | break; | ||
83 | case ARCH_TIMER_REG_TVAL: | ||
84 | writel_relaxed(val, timer->base + CNTP_TVAL); | ||
85 | break; | ||
86 | } | ||
87 | } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { | ||
88 | struct arch_timer *timer = to_arch_timer(clk); | ||
89 | switch (reg) { | ||
90 | case ARCH_TIMER_REG_CTRL: | ||
91 | writel_relaxed(val, timer->base + CNTV_CTL); | ||
92 | break; | ||
93 | case ARCH_TIMER_REG_TVAL: | ||
94 | writel_relaxed(val, timer->base + CNTV_TVAL); | ||
95 | break; | ||
96 | } | ||
97 | } else { | ||
98 | arch_timer_reg_write_cp15(access, reg, val); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | static __always_inline | ||
103 | u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, | ||
104 | struct clock_event_device *clk) | ||
105 | { | ||
106 | u32 val; | ||
107 | |||
108 | if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { | ||
109 | struct arch_timer *timer = to_arch_timer(clk); | ||
110 | switch (reg) { | ||
111 | case ARCH_TIMER_REG_CTRL: | ||
112 | val = readl_relaxed(timer->base + CNTP_CTL); | ||
113 | break; | ||
114 | case ARCH_TIMER_REG_TVAL: | ||
115 | val = readl_relaxed(timer->base + CNTP_TVAL); | ||
116 | break; | ||
117 | } | ||
118 | } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { | ||
119 | struct arch_timer *timer = to_arch_timer(clk); | ||
120 | switch (reg) { | ||
121 | case ARCH_TIMER_REG_CTRL: | ||
122 | val = readl_relaxed(timer->base + CNTV_CTL); | ||
123 | break; | ||
124 | case ARCH_TIMER_REG_TVAL: | ||
125 | val = readl_relaxed(timer->base + CNTV_TVAL); | ||
126 | break; | ||
127 | } | ||
128 | } else { | ||
129 | val = arch_timer_reg_read_cp15(access, reg); | ||
130 | } | ||
131 | |||
132 | return val; | ||
133 | } | ||
134 | |||
135 | static __always_inline irqreturn_t timer_handler(const int access, | ||
47 | struct clock_event_device *evt) | 136 | struct clock_event_device *evt) |
48 | { | 137 | { |
49 | unsigned long ctrl; | 138 | unsigned long ctrl; |
50 | ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL); | 139 | |
140 | ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, evt); | ||
51 | if (ctrl & ARCH_TIMER_CTRL_IT_STAT) { | 141 | if (ctrl & ARCH_TIMER_CTRL_IT_STAT) { |
52 | ctrl |= ARCH_TIMER_CTRL_IT_MASK; | 142 | ctrl |= ARCH_TIMER_CTRL_IT_MASK; |
53 | arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl); | 143 | arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, evt); |
54 | evt->event_handler(evt); | 144 | evt->event_handler(evt); |
55 | return IRQ_HANDLED; | 145 | return IRQ_HANDLED; |
56 | } | 146 | } |
@@ -72,15 +162,30 @@ static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id) | |||
72 | return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt); | 162 | return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt); |
73 | } | 163 | } |
74 | 164 | ||
75 | static inline void timer_set_mode(const int access, int mode) | 165 | static irqreturn_t arch_timer_handler_phys_mem(int irq, void *dev_id) |
166 | { | ||
167 | struct clock_event_device *evt = dev_id; | ||
168 | |||
169 | return timer_handler(ARCH_TIMER_MEM_PHYS_ACCESS, evt); | ||
170 | } | ||
171 | |||
172 | static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id) | ||
173 | { | ||
174 | struct clock_event_device *evt = dev_id; | ||
175 | |||
176 | return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt); | ||
177 | } | ||
178 | |||
179 | static __always_inline void timer_set_mode(const int access, int mode, | ||
180 | struct clock_event_device *clk) | ||
76 | { | 181 | { |
77 | unsigned long ctrl; | 182 | unsigned long ctrl; |
78 | switch (mode) { | 183 | switch (mode) { |
79 | case CLOCK_EVT_MODE_UNUSED: | 184 | case CLOCK_EVT_MODE_UNUSED: |
80 | case CLOCK_EVT_MODE_SHUTDOWN: | 185 | case CLOCK_EVT_MODE_SHUTDOWN: |
81 | ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL); | 186 | ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); |
82 | ctrl &= ~ARCH_TIMER_CTRL_ENABLE; | 187 | ctrl &= ~ARCH_TIMER_CTRL_ENABLE; |
83 | arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl); | 188 | arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); |
84 | break; | 189 | break; |
85 | default: | 190 | default: |
86 | break; | 191 | break; |
@@ -90,60 +195,108 @@ static inline void timer_set_mode(const int access, int mode) | |||
90 | static void arch_timer_set_mode_virt(enum clock_event_mode mode, | 195 | static void arch_timer_set_mode_virt(enum clock_event_mode mode, |
91 | struct clock_event_device *clk) | 196 | struct clock_event_device *clk) |
92 | { | 197 | { |
93 | timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode); | 198 | timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode, clk); |
94 | } | 199 | } |
95 | 200 | ||
96 | static void arch_timer_set_mode_phys(enum clock_event_mode mode, | 201 | static void arch_timer_set_mode_phys(enum clock_event_mode mode, |
97 | struct clock_event_device *clk) | 202 | struct clock_event_device *clk) |
98 | { | 203 | { |
99 | timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode); | 204 | timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode, clk); |
205 | } | ||
206 | |||
207 | static void arch_timer_set_mode_virt_mem(enum clock_event_mode mode, | ||
208 | struct clock_event_device *clk) | ||
209 | { | ||
210 | timer_set_mode(ARCH_TIMER_MEM_VIRT_ACCESS, mode, clk); | ||
100 | } | 211 | } |
101 | 212 | ||
102 | static inline void set_next_event(const int access, unsigned long evt) | 213 | static void arch_timer_set_mode_phys_mem(enum clock_event_mode mode, |
214 | struct clock_event_device *clk) | ||
215 | { | ||
216 | timer_set_mode(ARCH_TIMER_MEM_PHYS_ACCESS, mode, clk); | ||
217 | } | ||
218 | |||
219 | static __always_inline void set_next_event(const int access, unsigned long evt, | ||
220 | struct clock_event_device *clk) | ||
103 | { | 221 | { |
104 | unsigned long ctrl; | 222 | unsigned long ctrl; |
105 | ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL); | 223 | ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); |
106 | ctrl |= ARCH_TIMER_CTRL_ENABLE; | 224 | ctrl |= ARCH_TIMER_CTRL_ENABLE; |
107 | ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; | 225 | ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; |
108 | arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt); | 226 | arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk); |
109 | arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl); | 227 | arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); |
110 | } | 228 | } |
111 | 229 | ||
112 | static int arch_timer_set_next_event_virt(unsigned long evt, | 230 | static int arch_timer_set_next_event_virt(unsigned long evt, |
113 | struct clock_event_device *unused) | 231 | struct clock_event_device *clk) |
114 | { | 232 | { |
115 | set_next_event(ARCH_TIMER_VIRT_ACCESS, evt); | 233 | set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); |
116 | return 0; | 234 | return 0; |
117 | } | 235 | } |
118 | 236 | ||
119 | static int arch_timer_set_next_event_phys(unsigned long evt, | 237 | static int arch_timer_set_next_event_phys(unsigned long evt, |
120 | struct clock_event_device *unused) | 238 | struct clock_event_device *clk) |
121 | { | 239 | { |
122 | set_next_event(ARCH_TIMER_PHYS_ACCESS, evt); | 240 | set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); |
123 | return 0; | 241 | return 0; |
124 | } | 242 | } |
125 | 243 | ||
126 | static int arch_timer_setup(struct clock_event_device *clk) | 244 | static int arch_timer_set_next_event_virt_mem(unsigned long evt, |
245 | struct clock_event_device *clk) | ||
127 | { | 246 | { |
128 | clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; | 247 | set_next_event(ARCH_TIMER_MEM_VIRT_ACCESS, evt, clk); |
129 | clk->name = "arch_sys_timer"; | 248 | return 0; |
130 | clk->rating = 450; | 249 | } |
131 | if (arch_timer_use_virtual) { | 250 | |
132 | clk->irq = arch_timer_ppi[VIRT_PPI]; | 251 | static int arch_timer_set_next_event_phys_mem(unsigned long evt, |
133 | clk->set_mode = arch_timer_set_mode_virt; | 252 | struct clock_event_device *clk) |
134 | clk->set_next_event = arch_timer_set_next_event_virt; | 253 | { |
254 | set_next_event(ARCH_TIMER_MEM_PHYS_ACCESS, evt, clk); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static void __arch_timer_setup(unsigned type, | ||
259 | struct clock_event_device *clk) | ||
260 | { | ||
261 | clk->features = CLOCK_EVT_FEAT_ONESHOT; | ||
262 | |||
263 | if (type == ARCH_CP15_TIMER) { | ||
264 | clk->features |= CLOCK_EVT_FEAT_C3STOP; | ||
265 | clk->name = "arch_sys_timer"; | ||
266 | clk->rating = 450; | ||
267 | clk->cpumask = cpumask_of(smp_processor_id()); | ||
268 | if (arch_timer_use_virtual) { | ||
269 | clk->irq = arch_timer_ppi[VIRT_PPI]; | ||
270 | clk->set_mode = arch_timer_set_mode_virt; | ||
271 | clk->set_next_event = arch_timer_set_next_event_virt; | ||
272 | } else { | ||
273 | clk->irq = arch_timer_ppi[PHYS_SECURE_PPI]; | ||
274 | clk->set_mode = arch_timer_set_mode_phys; | ||
275 | clk->set_next_event = arch_timer_set_next_event_phys; | ||
276 | } | ||
135 | } else { | 277 | } else { |
136 | clk->irq = arch_timer_ppi[PHYS_SECURE_PPI]; | 278 | clk->name = "arch_mem_timer"; |
137 | clk->set_mode = arch_timer_set_mode_phys; | 279 | clk->rating = 400; |
138 | clk->set_next_event = arch_timer_set_next_event_phys; | 280 | clk->cpumask = cpu_all_mask; |
281 | if (arch_timer_mem_use_virtual) { | ||
282 | clk->set_mode = arch_timer_set_mode_virt_mem; | ||
283 | clk->set_next_event = | ||
284 | arch_timer_set_next_event_virt_mem; | ||
285 | } else { | ||
286 | clk->set_mode = arch_timer_set_mode_phys_mem; | ||
287 | clk->set_next_event = | ||
288 | arch_timer_set_next_event_phys_mem; | ||
289 | } | ||
139 | } | 290 | } |
140 | 291 | ||
141 | clk->cpumask = cpumask_of(smp_processor_id()); | 292 | clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, clk); |
142 | 293 | ||
143 | clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, NULL); | 294 | clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); |
295 | } | ||
144 | 296 | ||
145 | clockevents_config_and_register(clk, arch_timer_rate, | 297 | static int arch_timer_setup(struct clock_event_device *clk) |
146 | 0xf, 0x7fffffff); | 298 | { |
299 | __arch_timer_setup(ARCH_CP15_TIMER, clk); | ||
147 | 300 | ||
148 | if (arch_timer_use_virtual) | 301 | if (arch_timer_use_virtual) |
149 | enable_percpu_irq(arch_timer_ppi[VIRT_PPI], 0); | 302 | enable_percpu_irq(arch_timer_ppi[VIRT_PPI], 0); |
@@ -158,27 +311,41 @@ static int arch_timer_setup(struct clock_event_device *clk) | |||
158 | return 0; | 311 | return 0; |
159 | } | 312 | } |
160 | 313 | ||
161 | static int arch_timer_available(void) | 314 | static void |
315 | arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) | ||
162 | { | 316 | { |
163 | u32 freq; | 317 | /* Who has more than one independent system counter? */ |
164 | 318 | if (arch_timer_rate) | |
165 | if (arch_timer_rate == 0) { | 319 | return; |
166 | freq = arch_timer_get_cntfrq(); | ||
167 | |||
168 | /* Check the timer frequency. */ | ||
169 | if (freq == 0) { | ||
170 | pr_warn("Architected timer frequency not available\n"); | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | 320 | ||
174 | arch_timer_rate = freq; | 321 | /* Try to determine the frequency from the device tree or CNTFRQ */ |
322 | if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { | ||
323 | if (cntbase) | ||
324 | arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); | ||
325 | else | ||
326 | arch_timer_rate = arch_timer_get_cntfrq(); | ||
175 | } | 327 | } |
176 | 328 | ||
177 | pr_info_once("Architected local timer running at %lu.%02luMHz (%s).\n", | 329 | /* Check the timer frequency. */ |
330 | if (arch_timer_rate == 0) | ||
331 | pr_warn("Architected timer frequency not available\n"); | ||
332 | } | ||
333 | |||
334 | static void arch_timer_banner(unsigned type) | ||
335 | { | ||
336 | pr_info("Architected %s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n", | ||
337 | type & ARCH_CP15_TIMER ? "cp15" : "", | ||
338 | type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? " and " : "", | ||
339 | type & ARCH_MEM_TIMER ? "mmio" : "", | ||
178 | (unsigned long)arch_timer_rate / 1000000, | 340 | (unsigned long)arch_timer_rate / 1000000, |
179 | (unsigned long)(arch_timer_rate / 10000) % 100, | 341 | (unsigned long)(arch_timer_rate / 10000) % 100, |
180 | arch_timer_use_virtual ? "virt" : "phys"); | 342 | type & ARCH_CP15_TIMER ? |
181 | return 0; | 343 | arch_timer_use_virtual ? "virt" : "phys" : |
344 | "", | ||
345 | type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", | ||
346 | type & ARCH_MEM_TIMER ? | ||
347 | arch_timer_mem_use_virtual ? "virt" : "phys" : | ||
348 | ""); | ||
182 | } | 349 | } |
183 | 350 | ||
184 | u32 arch_timer_get_rate(void) | 351 | u32 arch_timer_get_rate(void) |
@@ -186,19 +353,35 @@ u32 arch_timer_get_rate(void) | |||
186 | return arch_timer_rate; | 353 | return arch_timer_rate; |
187 | } | 354 | } |
188 | 355 | ||
189 | u64 arch_timer_read_counter(void) | 356 | static u64 arch_counter_get_cntvct_mem(void) |
190 | { | 357 | { |
191 | return arch_counter_get_cntvct(); | 358 | u32 vct_lo, vct_hi, tmp_hi; |
359 | |||
360 | do { | ||
361 | vct_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); | ||
362 | vct_lo = readl_relaxed(arch_counter_base + CNTVCT_LO); | ||
363 | tmp_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); | ||
364 | } while (vct_hi != tmp_hi); | ||
365 | |||
366 | return ((u64) vct_hi << 32) | vct_lo; | ||
192 | } | 367 | } |
193 | 368 | ||
369 | /* | ||
370 | * Default to cp15 based access because arm64 uses this function for | ||
371 | * sched_clock() before DT is probed and the cp15 method is guaranteed | ||
372 | * to exist on arm64. arm doesn't use this before DT is probed so even | ||
373 | * if we don't have the cp15 accessors we won't have a problem. | ||
374 | */ | ||
375 | u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct; | ||
376 | |||
194 | static cycle_t arch_counter_read(struct clocksource *cs) | 377 | static cycle_t arch_counter_read(struct clocksource *cs) |
195 | { | 378 | { |
196 | return arch_counter_get_cntvct(); | 379 | return arch_timer_read_counter(); |
197 | } | 380 | } |
198 | 381 | ||
199 | static cycle_t arch_counter_read_cc(const struct cyclecounter *cc) | 382 | static cycle_t arch_counter_read_cc(const struct cyclecounter *cc) |
200 | { | 383 | { |
201 | return arch_counter_get_cntvct(); | 384 | return arch_timer_read_counter(); |
202 | } | 385 | } |
203 | 386 | ||
204 | static struct clocksource clocksource_counter = { | 387 | static struct clocksource clocksource_counter = { |
@@ -221,6 +404,23 @@ struct timecounter *arch_timer_get_timecounter(void) | |||
221 | return &timecounter; | 404 | return &timecounter; |
222 | } | 405 | } |
223 | 406 | ||
407 | static void __init arch_counter_register(unsigned type) | ||
408 | { | ||
409 | u64 start_count; | ||
410 | |||
411 | /* Register the CP15 based counter if we have one */ | ||
412 | if (type & ARCH_CP15_TIMER) | ||
413 | arch_timer_read_counter = arch_counter_get_cntvct; | ||
414 | else | ||
415 | arch_timer_read_counter = arch_counter_get_cntvct_mem; | ||
416 | |||
417 | start_count = arch_timer_read_counter(); | ||
418 | clocksource_register_hz(&clocksource_counter, arch_timer_rate); | ||
419 | cyclecounter.mult = clocksource_counter.mult; | ||
420 | cyclecounter.shift = clocksource_counter.shift; | ||
421 | timecounter_init(&timecounter, &cyclecounter, start_count); | ||
422 | } | ||
423 | |||
224 | static void arch_timer_stop(struct clock_event_device *clk) | 424 | static void arch_timer_stop(struct clock_event_device *clk) |
225 | { | 425 | { |
226 | pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", | 426 | pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", |
@@ -265,22 +465,12 @@ static int __init arch_timer_register(void) | |||
265 | int err; | 465 | int err; |
266 | int ppi; | 466 | int ppi; |
267 | 467 | ||
268 | err = arch_timer_available(); | ||
269 | if (err) | ||
270 | goto out; | ||
271 | |||
272 | arch_timer_evt = alloc_percpu(struct clock_event_device); | 468 | arch_timer_evt = alloc_percpu(struct clock_event_device); |
273 | if (!arch_timer_evt) { | 469 | if (!arch_timer_evt) { |
274 | err = -ENOMEM; | 470 | err = -ENOMEM; |
275 | goto out; | 471 | goto out; |
276 | } | 472 | } |
277 | 473 | ||
278 | clocksource_register_hz(&clocksource_counter, arch_timer_rate); | ||
279 | cyclecounter.mult = clocksource_counter.mult; | ||
280 | cyclecounter.shift = clocksource_counter.shift; | ||
281 | timecounter_init(&timecounter, &cyclecounter, | ||
282 | arch_counter_get_cntvct()); | ||
283 | |||
284 | if (arch_timer_use_virtual) { | 474 | if (arch_timer_use_virtual) { |
285 | ppi = arch_timer_ppi[VIRT_PPI]; | 475 | ppi = arch_timer_ppi[VIRT_PPI]; |
286 | err = request_percpu_irq(ppi, arch_timer_handler_virt, | 476 | err = request_percpu_irq(ppi, arch_timer_handler_virt, |
@@ -331,24 +521,77 @@ out: | |||
331 | return err; | 521 | return err; |
332 | } | 522 | } |
333 | 523 | ||
524 | static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq) | ||
525 | { | ||
526 | int ret; | ||
527 | irq_handler_t func; | ||
528 | struct arch_timer *t; | ||
529 | |||
530 | t = kzalloc(sizeof(*t), GFP_KERNEL); | ||
531 | if (!t) | ||
532 | return -ENOMEM; | ||
533 | |||
534 | t->base = base; | ||
535 | t->evt.irq = irq; | ||
536 | __arch_timer_setup(ARCH_MEM_TIMER, &t->evt); | ||
537 | |||
538 | if (arch_timer_mem_use_virtual) | ||
539 | func = arch_timer_handler_virt_mem; | ||
540 | else | ||
541 | func = arch_timer_handler_phys_mem; | ||
542 | |||
543 | ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &t->evt); | ||
544 | if (ret) { | ||
545 | pr_err("arch_timer: Failed to request mem timer irq\n"); | ||
546 | kfree(t); | ||
547 | } | ||
548 | |||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | static const struct of_device_id arch_timer_of_match[] __initconst = { | ||
553 | { .compatible = "arm,armv7-timer", }, | ||
554 | { .compatible = "arm,armv8-timer", }, | ||
555 | {}, | ||
556 | }; | ||
557 | |||
558 | static const struct of_device_id arch_timer_mem_of_match[] __initconst = { | ||
559 | { .compatible = "arm,armv7-timer-mem", }, | ||
560 | {}, | ||
561 | }; | ||
562 | |||
563 | static void __init arch_timer_common_init(void) | ||
564 | { | ||
565 | unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER; | ||
566 | |||
567 | /* Wait until both nodes are probed if we have two timers */ | ||
568 | if ((arch_timers_present & mask) != mask) { | ||
569 | if (of_find_matching_node(NULL, arch_timer_mem_of_match) && | ||
570 | !(arch_timers_present & ARCH_MEM_TIMER)) | ||
571 | return; | ||
572 | if (of_find_matching_node(NULL, arch_timer_of_match) && | ||
573 | !(arch_timers_present & ARCH_CP15_TIMER)) | ||
574 | return; | ||
575 | } | ||
576 | |||
577 | arch_timer_banner(arch_timers_present); | ||
578 | arch_counter_register(arch_timers_present); | ||
579 | arch_timer_arch_init(); | ||
580 | } | ||
581 | |||
334 | static void __init arch_timer_init(struct device_node *np) | 582 | static void __init arch_timer_init(struct device_node *np) |
335 | { | 583 | { |
336 | u32 freq; | ||
337 | int i; | 584 | int i; |
338 | 585 | ||
339 | if (arch_timer_get_rate()) { | 586 | if (arch_timers_present & ARCH_CP15_TIMER) { |
340 | pr_warn("arch_timer: multiple nodes in dt, skipping\n"); | 587 | pr_warn("arch_timer: multiple nodes in dt, skipping\n"); |
341 | return; | 588 | return; |
342 | } | 589 | } |
343 | 590 | ||
344 | /* Try to determine the frequency from the device tree or CNTFRQ */ | 591 | arch_timers_present |= ARCH_CP15_TIMER; |
345 | if (!of_property_read_u32(np, "clock-frequency", &freq)) | ||
346 | arch_timer_rate = freq; | ||
347 | |||
348 | for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) | 592 | for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) |
349 | arch_timer_ppi[i] = irq_of_parse_and_map(np, i); | 593 | arch_timer_ppi[i] = irq_of_parse_and_map(np, i); |
350 | 594 | arch_timer_detect_rate(NULL, np); | |
351 | of_node_put(np); | ||
352 | 595 | ||
353 | /* | 596 | /* |
354 | * If HYP mode is available, we know that the physical timer | 597 | * If HYP mode is available, we know that the physical timer |
@@ -369,7 +612,73 @@ static void __init arch_timer_init(struct device_node *np) | |||
369 | } | 612 | } |
370 | 613 | ||
371 | arch_timer_register(); | 614 | arch_timer_register(); |
372 | arch_timer_arch_init(); | 615 | arch_timer_common_init(); |
373 | } | 616 | } |
374 | CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_init); | 617 | CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_init); |
375 | CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init); | 618 | CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init); |
619 | |||
620 | static void __init arch_timer_mem_init(struct device_node *np) | ||
621 | { | ||
622 | struct device_node *frame, *best_frame = NULL; | ||
623 | void __iomem *cntctlbase, *base; | ||
624 | unsigned int irq; | ||
625 | u32 cnttidr; | ||
626 | |||
627 | arch_timers_present |= ARCH_MEM_TIMER; | ||
628 | cntctlbase = of_iomap(np, 0); | ||
629 | if (!cntctlbase) { | ||
630 | pr_err("arch_timer: Can't find CNTCTLBase\n"); | ||
631 | return; | ||
632 | } | ||
633 | |||
634 | cnttidr = readl_relaxed(cntctlbase + CNTTIDR); | ||
635 | iounmap(cntctlbase); | ||
636 | |||
637 | /* | ||
638 | * Try to find a virtual capable frame. Otherwise fall back to a | ||
639 | * physical capable frame. | ||
640 | */ | ||
641 | for_each_available_child_of_node(np, frame) { | ||
642 | int n; | ||
643 | |||
644 | if (of_property_read_u32(frame, "frame-number", &n)) { | ||
645 | pr_err("arch_timer: Missing frame-number\n"); | ||
646 | of_node_put(best_frame); | ||
647 | of_node_put(frame); | ||
648 | return; | ||
649 | } | ||
650 | |||
651 | if (cnttidr & CNTTIDR_VIRT(n)) { | ||
652 | of_node_put(best_frame); | ||
653 | best_frame = frame; | ||
654 | arch_timer_mem_use_virtual = true; | ||
655 | break; | ||
656 | } | ||
657 | of_node_put(best_frame); | ||
658 | best_frame = of_node_get(frame); | ||
659 | } | ||
660 | |||
661 | base = arch_counter_base = of_iomap(best_frame, 0); | ||
662 | if (!base) { | ||
663 | pr_err("arch_timer: Can't map frame's registers\n"); | ||
664 | of_node_put(best_frame); | ||
665 | return; | ||
666 | } | ||
667 | |||
668 | if (arch_timer_mem_use_virtual) | ||
669 | irq = irq_of_parse_and_map(best_frame, 1); | ||
670 | else | ||
671 | irq = irq_of_parse_and_map(best_frame, 0); | ||
672 | of_node_put(best_frame); | ||
673 | if (!irq) { | ||
674 | pr_err("arch_timer: Frame missing %s irq", | ||
675 | arch_timer_mem_use_virtual ? "virt" : "phys"); | ||
676 | return; | ||
677 | } | ||
678 | |||
679 | arch_timer_detect_rate(base, np); | ||
680 | arch_timer_mem_register(base, irq); | ||
681 | arch_timer_common_init(); | ||
682 | } | ||
683 | CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", | ||
684 | arch_timer_mem_init); | ||
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 4cbe28c74631..b2bb3a4bc205 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/of_address.h> | 21 | #include <linux/of_address.h> |
22 | #include <linux/of_irq.h> | 22 | #include <linux/of_irq.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/clk-provider.h> | 24 | #include <linux/sched_clock.h> |
25 | 25 | ||
26 | /* | 26 | /* |
27 | * This driver configures the 2 16-bit count-up timers as follows: | 27 | * This driver configures the 2 16-bit count-up timers as follows: |
@@ -95,6 +95,8 @@ struct ttc_timer_clockevent { | |||
95 | #define to_ttc_timer_clkevent(x) \ | 95 | #define to_ttc_timer_clkevent(x) \ |
96 | container_of(x, struct ttc_timer_clockevent, ce) | 96 | container_of(x, struct ttc_timer_clockevent, ce) |
97 | 97 | ||
98 | static void __iomem *ttc_sched_clock_val_reg; | ||
99 | |||
98 | /** | 100 | /** |
99 | * ttc_set_interval - Set the timer interval value | 101 | * ttc_set_interval - Set the timer interval value |
100 | * | 102 | * |
@@ -156,6 +158,11 @@ static cycle_t __ttc_clocksource_read(struct clocksource *cs) | |||
156 | TTC_COUNT_VAL_OFFSET); | 158 | TTC_COUNT_VAL_OFFSET); |
157 | } | 159 | } |
158 | 160 | ||
161 | static u32 notrace ttc_sched_clock_read(void) | ||
162 | { | ||
163 | return __raw_readl(ttc_sched_clock_val_reg); | ||
164 | } | ||
165 | |||
159 | /** | 166 | /** |
160 | * ttc_set_next_event - Sets the time interval for next event | 167 | * ttc_set_next_event - Sets the time interval for next event |
161 | * | 168 | * |
@@ -297,6 +304,10 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) | |||
297 | kfree(ttccs); | 304 | kfree(ttccs); |
298 | return; | 305 | return; |
299 | } | 306 | } |
307 | |||
308 | ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; | ||
309 | setup_sched_clock(ttc_sched_clock_read, 16, | ||
310 | clk_get_rate(ttccs->ttc.clk) / PRESCALE); | ||
300 | } | 311 | } |
301 | 312 | ||
302 | static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, | 313 | static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, |
diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c new file mode 100644 index 000000000000..5eb2c35932b1 --- /dev/null +++ b/drivers/clocksource/moxart_timer.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * MOXA ART SoCs timer handling. | ||
3 | * | ||
4 | * Copyright (C) 2013 Jonas Jensen | ||
5 | * | ||
6 | * Jonas Jensen <jonas.jensen@gmail.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/clockchips.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <linux/irqreturn.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/of_irq.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/clocksource.h> | ||
23 | #include <linux/bitops.h> | ||
24 | |||
25 | #define TIMER1_BASE 0x00 | ||
26 | #define TIMER2_BASE 0x10 | ||
27 | #define TIMER3_BASE 0x20 | ||
28 | |||
29 | #define REG_COUNT 0x0 /* writable */ | ||
30 | #define REG_LOAD 0x4 | ||
31 | #define REG_MATCH1 0x8 | ||
32 | #define REG_MATCH2 0xC | ||
33 | |||
34 | #define TIMER_CR 0x30 | ||
35 | #define TIMER_INTR_STATE 0x34 | ||
36 | #define TIMER_INTR_MASK 0x38 | ||
37 | |||
38 | /* | ||
39 | * TIMER_CR flags: | ||
40 | * | ||
41 | * TIMEREG_CR_*_CLOCK 0: PCLK, 1: EXT1CLK | ||
42 | * TIMEREG_CR_*_INT overflow interrupt enable bit | ||
43 | */ | ||
44 | #define TIMEREG_CR_1_ENABLE BIT(0) | ||
45 | #define TIMEREG_CR_1_CLOCK BIT(1) | ||
46 | #define TIMEREG_CR_1_INT BIT(2) | ||
47 | #define TIMEREG_CR_2_ENABLE BIT(3) | ||
48 | #define TIMEREG_CR_2_CLOCK BIT(4) | ||
49 | #define TIMEREG_CR_2_INT BIT(5) | ||
50 | #define TIMEREG_CR_3_ENABLE BIT(6) | ||
51 | #define TIMEREG_CR_3_CLOCK BIT(7) | ||
52 | #define TIMEREG_CR_3_INT BIT(8) | ||
53 | #define TIMEREG_CR_COUNT_UP BIT(9) | ||
54 | |||
55 | #define TIMER1_ENABLE (TIMEREG_CR_2_ENABLE | TIMEREG_CR_1_ENABLE) | ||
56 | #define TIMER1_DISABLE (TIMEREG_CR_2_ENABLE) | ||
57 | |||
58 | static void __iomem *base; | ||
59 | static unsigned int clock_count_per_tick; | ||
60 | |||
61 | static void moxart_clkevt_mode(enum clock_event_mode mode, | ||
62 | struct clock_event_device *clk) | ||
63 | { | ||
64 | switch (mode) { | ||
65 | case CLOCK_EVT_MODE_RESUME: | ||
66 | case CLOCK_EVT_MODE_ONESHOT: | ||
67 | writel(TIMER1_DISABLE, base + TIMER_CR); | ||
68 | writel(~0, base + TIMER1_BASE + REG_LOAD); | ||
69 | break; | ||
70 | case CLOCK_EVT_MODE_PERIODIC: | ||
71 | writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD); | ||
72 | writel(TIMER1_ENABLE, base + TIMER_CR); | ||
73 | break; | ||
74 | case CLOCK_EVT_MODE_UNUSED: | ||
75 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
76 | default: | ||
77 | writel(TIMER1_DISABLE, base + TIMER_CR); | ||
78 | break; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | static int moxart_clkevt_next_event(unsigned long cycles, | ||
83 | struct clock_event_device *unused) | ||
84 | { | ||
85 | u32 u; | ||
86 | |||
87 | writel(TIMER1_DISABLE, base + TIMER_CR); | ||
88 | |||
89 | u = readl(base + TIMER1_BASE + REG_COUNT) - cycles; | ||
90 | writel(u, base + TIMER1_BASE + REG_MATCH1); | ||
91 | |||
92 | writel(TIMER1_ENABLE, base + TIMER_CR); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static struct clock_event_device moxart_clockevent = { | ||
98 | .name = "moxart_timer", | ||
99 | .rating = 200, | ||
100 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
101 | .set_mode = moxart_clkevt_mode, | ||
102 | .set_next_event = moxart_clkevt_next_event, | ||
103 | }; | ||
104 | |||
105 | static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id) | ||
106 | { | ||
107 | struct clock_event_device *evt = dev_id; | ||
108 | evt->event_handler(evt); | ||
109 | return IRQ_HANDLED; | ||
110 | } | ||
111 | |||
112 | static struct irqaction moxart_timer_irq = { | ||
113 | .name = "moxart-timer", | ||
114 | .flags = IRQF_TIMER, | ||
115 | .handler = moxart_timer_interrupt, | ||
116 | .dev_id = &moxart_clockevent, | ||
117 | }; | ||
118 | |||
119 | static void __init moxart_timer_init(struct device_node *node) | ||
120 | { | ||
121 | int ret, irq; | ||
122 | unsigned long pclk; | ||
123 | struct clk *clk; | ||
124 | |||
125 | base = of_iomap(node, 0); | ||
126 | if (!base) | ||
127 | panic("%s: of_iomap failed\n", node->full_name); | ||
128 | |||
129 | irq = irq_of_parse_and_map(node, 0); | ||
130 | if (irq <= 0) | ||
131 | panic("%s: irq_of_parse_and_map failed\n", node->full_name); | ||
132 | |||
133 | ret = setup_irq(irq, &moxart_timer_irq); | ||
134 | if (ret) | ||
135 | panic("%s: setup_irq failed\n", node->full_name); | ||
136 | |||
137 | clk = of_clk_get(node, 0); | ||
138 | if (IS_ERR(clk)) | ||
139 | panic("%s: of_clk_get failed\n", node->full_name); | ||
140 | |||
141 | pclk = clk_get_rate(clk); | ||
142 | |||
143 | if (clocksource_mmio_init(base + TIMER2_BASE + REG_COUNT, | ||
144 | "moxart_timer", pclk, 200, 32, | ||
145 | clocksource_mmio_readl_down)) | ||
146 | panic("%s: clocksource_mmio_init failed\n", node->full_name); | ||
147 | |||
148 | clock_count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ); | ||
149 | |||
150 | writel(~0, base + TIMER2_BASE + REG_LOAD); | ||
151 | writel(TIMEREG_CR_2_ENABLE, base + TIMER_CR); | ||
152 | |||
153 | moxart_clockevent.cpumask = cpumask_of(0); | ||
154 | moxart_clockevent.irq = irq; | ||
155 | |||
156 | /* | ||
157 | * documentation is not publicly available: | ||
158 | * min_delta / max_delta obtained by trial-and-error, | ||
159 | * max_delta 0xfffffffe should be ok because count | ||
160 | * register size is u32 | ||
161 | */ | ||
162 | clockevents_config_and_register(&moxart_clockevent, pclk, | ||
163 | 0x4, 0xfffffffe); | ||
164 | } | ||
165 | CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init); | ||
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index d4674e78ef35..8ead0258740a 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c | |||
@@ -19,42 +19,83 @@ | |||
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | #include <linux/irqreturn.h> | 21 | #include <linux/irqreturn.h> |
22 | #include <linux/sched_clock.h> | ||
22 | #include <linux/of.h> | 23 | #include <linux/of.h> |
23 | #include <linux/of_address.h> | 24 | #include <linux/of_address.h> |
24 | #include <linux/of_irq.h> | 25 | #include <linux/of_irq.h> |
25 | 26 | ||
26 | #define TIMER_IRQ_EN_REG 0x00 | 27 | #define TIMER_IRQ_EN_REG 0x00 |
27 | #define TIMER_IRQ_EN(val) (1 << val) | 28 | #define TIMER_IRQ_EN(val) BIT(val) |
28 | #define TIMER_IRQ_ST_REG 0x04 | 29 | #define TIMER_IRQ_ST_REG 0x04 |
29 | #define TIMER_CTL_REG(val) (0x10 * val + 0x10) | 30 | #define TIMER_CTL_REG(val) (0x10 * val + 0x10) |
30 | #define TIMER_CTL_ENABLE (1 << 0) | 31 | #define TIMER_CTL_ENABLE BIT(0) |
31 | #define TIMER_CTL_AUTORELOAD (1 << 1) | 32 | #define TIMER_CTL_RELOAD BIT(1) |
32 | #define TIMER_CTL_ONESHOT (1 << 7) | 33 | #define TIMER_CTL_CLK_SRC(val) (((val) & 0x3) << 2) |
33 | #define TIMER_INTVAL_REG(val) (0x10 * val + 0x14) | 34 | #define TIMER_CTL_CLK_SRC_OSC24M (1) |
34 | #define TIMER_CNTVAL_REG(val) (0x10 * val + 0x18) | 35 | #define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4) |
35 | 36 | #define TIMER_CTL_ONESHOT BIT(7) | |
36 | #define TIMER_SCAL 16 | 37 | #define TIMER_INTVAL_REG(val) (0x10 * (val) + 0x14) |
38 | #define TIMER_CNTVAL_REG(val) (0x10 * (val) + 0x18) | ||
37 | 39 | ||
38 | static void __iomem *timer_base; | 40 | static void __iomem *timer_base; |
41 | static u32 ticks_per_jiffy; | ||
42 | |||
43 | /* | ||
44 | * When we disable a timer, we need to wait at least for 2 cycles of | ||
45 | * the timer source clock. We will use for that the clocksource timer | ||
46 | * that is already setup and runs at the same frequency than the other | ||
47 | * timers, and we never will be disabled. | ||
48 | */ | ||
49 | static void sun4i_clkevt_sync(void) | ||
50 | { | ||
51 | u32 old = readl(timer_base + TIMER_CNTVAL_REG(1)); | ||
52 | |||
53 | while ((old - readl(timer_base + TIMER_CNTVAL_REG(1))) < 3) | ||
54 | cpu_relax(); | ||
55 | } | ||
56 | |||
57 | static void sun4i_clkevt_time_stop(u8 timer) | ||
58 | { | ||
59 | u32 val = readl(timer_base + TIMER_CTL_REG(timer)); | ||
60 | writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); | ||
61 | sun4i_clkevt_sync(); | ||
62 | } | ||
63 | |||
64 | static void sun4i_clkevt_time_setup(u8 timer, unsigned long delay) | ||
65 | { | ||
66 | writel(delay, timer_base + TIMER_INTVAL_REG(timer)); | ||
67 | } | ||
68 | |||
69 | static void sun4i_clkevt_time_start(u8 timer, bool periodic) | ||
70 | { | ||
71 | u32 val = readl(timer_base + TIMER_CTL_REG(timer)); | ||
72 | |||
73 | if (periodic) | ||
74 | val &= ~TIMER_CTL_ONESHOT; | ||
75 | else | ||
76 | val |= TIMER_CTL_ONESHOT; | ||
77 | |||
78 | writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, | ||
79 | timer_base + TIMER_CTL_REG(timer)); | ||
80 | } | ||
39 | 81 | ||
40 | static void sun4i_clkevt_mode(enum clock_event_mode mode, | 82 | static void sun4i_clkevt_mode(enum clock_event_mode mode, |
41 | struct clock_event_device *clk) | 83 | struct clock_event_device *clk) |
42 | { | 84 | { |
43 | u32 u = readl(timer_base + TIMER_CTL_REG(0)); | ||
44 | |||
45 | switch (mode) { | 85 | switch (mode) { |
46 | case CLOCK_EVT_MODE_PERIODIC: | 86 | case CLOCK_EVT_MODE_PERIODIC: |
47 | u &= ~(TIMER_CTL_ONESHOT); | 87 | sun4i_clkevt_time_stop(0); |
48 | writel(u | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0)); | 88 | sun4i_clkevt_time_setup(0, ticks_per_jiffy); |
89 | sun4i_clkevt_time_start(0, true); | ||
49 | break; | 90 | break; |
50 | |||
51 | case CLOCK_EVT_MODE_ONESHOT: | 91 | case CLOCK_EVT_MODE_ONESHOT: |
52 | writel(u | TIMER_CTL_ONESHOT, timer_base + TIMER_CTL_REG(0)); | 92 | sun4i_clkevt_time_stop(0); |
93 | sun4i_clkevt_time_start(0, false); | ||
53 | break; | 94 | break; |
54 | case CLOCK_EVT_MODE_UNUSED: | 95 | case CLOCK_EVT_MODE_UNUSED: |
55 | case CLOCK_EVT_MODE_SHUTDOWN: | 96 | case CLOCK_EVT_MODE_SHUTDOWN: |
56 | default: | 97 | default: |
57 | writel(u & ~(TIMER_CTL_ENABLE), timer_base + TIMER_CTL_REG(0)); | 98 | sun4i_clkevt_time_stop(0); |
58 | break; | 99 | break; |
59 | } | 100 | } |
60 | } | 101 | } |
@@ -62,10 +103,9 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode, | |||
62 | static int sun4i_clkevt_next_event(unsigned long evt, | 103 | static int sun4i_clkevt_next_event(unsigned long evt, |
63 | struct clock_event_device *unused) | 104 | struct clock_event_device *unused) |
64 | { | 105 | { |
65 | u32 u = readl(timer_base + TIMER_CTL_REG(0)); | 106 | sun4i_clkevt_time_stop(0); |
66 | writel(evt, timer_base + TIMER_CNTVAL_REG(0)); | 107 | sun4i_clkevt_time_setup(0, evt); |
67 | writel(u | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD, | 108 | sun4i_clkevt_time_start(0, false); |
68 | timer_base + TIMER_CTL_REG(0)); | ||
69 | 109 | ||
70 | return 0; | 110 | return 0; |
71 | } | 111 | } |
@@ -96,6 +136,11 @@ static struct irqaction sun4i_timer_irq = { | |||
96 | .dev_id = &sun4i_clockevent, | 136 | .dev_id = &sun4i_clockevent, |
97 | }; | 137 | }; |
98 | 138 | ||
139 | static u32 sun4i_timer_sched_read(void) | ||
140 | { | ||
141 | return ~readl(timer_base + TIMER_CNTVAL_REG(1)); | ||
142 | } | ||
143 | |||
99 | static void __init sun4i_timer_init(struct device_node *node) | 144 | static void __init sun4i_timer_init(struct device_node *node) |
100 | { | 145 | { |
101 | unsigned long rate = 0; | 146 | unsigned long rate = 0; |
@@ -114,22 +159,23 @@ static void __init sun4i_timer_init(struct device_node *node) | |||
114 | clk = of_clk_get(node, 0); | 159 | clk = of_clk_get(node, 0); |
115 | if (IS_ERR(clk)) | 160 | if (IS_ERR(clk)) |
116 | panic("Can't get timer clock"); | 161 | panic("Can't get timer clock"); |
162 | clk_prepare_enable(clk); | ||
117 | 163 | ||
118 | rate = clk_get_rate(clk); | 164 | rate = clk_get_rate(clk); |
119 | 165 | ||
120 | writel(rate / (TIMER_SCAL * HZ), | 166 | writel(~0, timer_base + TIMER_INTVAL_REG(1)); |
121 | timer_base + TIMER_INTVAL_REG(0)); | 167 | writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD | |
168 | TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), | ||
169 | timer_base + TIMER_CTL_REG(1)); | ||
170 | |||
171 | setup_sched_clock(sun4i_timer_sched_read, 32, rate); | ||
172 | clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, | ||
173 | rate, 300, 32, clocksource_mmio_readl_down); | ||
122 | 174 | ||
123 | /* set clock source to HOSC, 16 pre-division */ | 175 | ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); |
124 | val = readl(timer_base + TIMER_CTL_REG(0)); | ||
125 | val &= ~(0x07 << 4); | ||
126 | val &= ~(0x03 << 2); | ||
127 | val |= (4 << 4) | (1 << 2); | ||
128 | writel(val, timer_base + TIMER_CTL_REG(0)); | ||
129 | 176 | ||
130 | /* set mode to auto reload */ | 177 | writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), |
131 | val = readl(timer_base + TIMER_CTL_REG(0)); | 178 | timer_base + TIMER_CTL_REG(0)); |
132 | writel(val | TIMER_CTL_AUTORELOAD, timer_base + TIMER_CTL_REG(0)); | ||
133 | 179 | ||
134 | ret = setup_irq(irq, &sun4i_timer_irq); | 180 | ret = setup_irq(irq, &sun4i_timer_irq); |
135 | if (ret) | 181 | if (ret) |
@@ -141,8 +187,8 @@ static void __init sun4i_timer_init(struct device_node *node) | |||
141 | 187 | ||
142 | sun4i_clockevent.cpumask = cpumask_of(0); | 188 | sun4i_clockevent.cpumask = cpumask_of(0); |
143 | 189 | ||
144 | clockevents_config_and_register(&sun4i_clockevent, rate / TIMER_SCAL, | 190 | clockevents_config_and_register(&sun4i_clockevent, rate, 0x1, |
145 | 0x1, 0xff); | 191 | 0xffffffff); |
146 | } | 192 | } |
147 | CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer", | 193 | CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer", |
148 | sun4i_timer_init); | 194 | sun4i_timer_init); |
diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index ecbeb6810215..9c7f018a67ca 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
20 | #include <linux/of_irq.h> | 20 | #include <linux/of_irq.h> |
21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | #include <asm/sched_clock.h> | 22 | #include <linux/sched_clock.h> |
23 | 23 | ||
24 | #define TIMER_CTRL 0x00 | 24 | #define TIMER_CTRL 0x00 |
25 | #define TIMER0_EN BIT(0) | 25 | #define TIMER0_EN BIT(0) |
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index c463ce990c48..93b7f96f9c59 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h | |||
@@ -23,16 +23,20 @@ | |||
23 | #define ARCH_TIMER_CTRL_IT_MASK (1 << 1) | 23 | #define ARCH_TIMER_CTRL_IT_MASK (1 << 1) |
24 | #define ARCH_TIMER_CTRL_IT_STAT (1 << 2) | 24 | #define ARCH_TIMER_CTRL_IT_STAT (1 << 2) |
25 | 25 | ||
26 | #define ARCH_TIMER_REG_CTRL 0 | 26 | enum arch_timer_reg { |
27 | #define ARCH_TIMER_REG_TVAL 1 | 27 | ARCH_TIMER_REG_CTRL, |
28 | ARCH_TIMER_REG_TVAL, | ||
29 | }; | ||
28 | 30 | ||
29 | #define ARCH_TIMER_PHYS_ACCESS 0 | 31 | #define ARCH_TIMER_PHYS_ACCESS 0 |
30 | #define ARCH_TIMER_VIRT_ACCESS 1 | 32 | #define ARCH_TIMER_VIRT_ACCESS 1 |
33 | #define ARCH_TIMER_MEM_PHYS_ACCESS 2 | ||
34 | #define ARCH_TIMER_MEM_VIRT_ACCESS 3 | ||
31 | 35 | ||
32 | #ifdef CONFIG_ARM_ARCH_TIMER | 36 | #ifdef CONFIG_ARM_ARCH_TIMER |
33 | 37 | ||
34 | extern u32 arch_timer_get_rate(void); | 38 | extern u32 arch_timer_get_rate(void); |
35 | extern u64 arch_timer_read_counter(void); | 39 | extern u64 (*arch_timer_read_counter)(void); |
36 | extern struct timecounter *arch_timer_get_timecounter(void); | 40 | extern struct timecounter *arch_timer_get_timecounter(void); |
37 | 41 | ||
38 | #else | 42 | #else |