diff options
37 files changed, 622 insertions, 622 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 233f83464814..87d1ca7ca56a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -9366,7 +9366,7 @@ M: Andreas Noever <andreas.noever@gmail.com> | |||
9366 | S: Maintained | 9366 | S: Maintained |
9367 | F: drivers/thunderbolt/ | 9367 | F: drivers/thunderbolt/ |
9368 | 9368 | ||
9369 | TIMEKEEPING, CLOCKSOURCE CORE, NTP | 9369 | TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER |
9370 | M: John Stultz <john.stultz@linaro.org> | 9370 | M: John Stultz <john.stultz@linaro.org> |
9371 | M: Thomas Gleixner <tglx@linutronix.de> | 9371 | M: Thomas Gleixner <tglx@linutronix.de> |
9372 | L: linux-kernel@vger.kernel.org | 9372 | L: linux-kernel@vger.kernel.org |
@@ -9379,6 +9379,7 @@ F: include/uapi/linux/time.h | |||
9379 | F: include/uapi/linux/timex.h | 9379 | F: include/uapi/linux/timex.h |
9380 | F: kernel/time/clocksource.c | 9380 | F: kernel/time/clocksource.c |
9381 | F: kernel/time/time*.c | 9381 | F: kernel/time/time*.c |
9382 | F: kernel/time/alarmtimer.c | ||
9382 | F: kernel/time/ntp.c | 9383 | F: kernel/time/ntp.c |
9383 | F: tools/testing/selftests/timers/ | 9384 | F: tools/testing/selftests/timers/ |
9384 | 9385 | ||
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 34e1569a11ee..688dc7b0d951 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -611,6 +611,7 @@ config ARCH_PXA | |||
611 | select AUTO_ZRELADDR | 611 | select AUTO_ZRELADDR |
612 | select COMMON_CLK | 612 | select COMMON_CLK |
613 | select CLKDEV_LOOKUP | 613 | select CLKDEV_LOOKUP |
614 | select CLKSRC_PXA | ||
614 | select CLKSRC_MMIO | 615 | select CLKSRC_MMIO |
615 | select CLKSRC_OF | 616 | select CLKSRC_OF |
616 | select GENERIC_CLOCKEVENTS | 617 | select GENERIC_CLOCKEVENTS |
@@ -650,6 +651,8 @@ config ARCH_SA1100 | |||
650 | select ARCH_SPARSEMEM_ENABLE | 651 | select ARCH_SPARSEMEM_ENABLE |
651 | select CLKDEV_LOOKUP | 652 | select CLKDEV_LOOKUP |
652 | select CLKSRC_MMIO | 653 | select CLKSRC_MMIO |
654 | select CLKSRC_PXA | ||
655 | select CLKSRC_OF if OF | ||
653 | select CPU_FREQ | 656 | select CPU_FREQ |
654 | select CPU_SA1100 | 657 | select CPU_SA1100 |
655 | select GENERIC_CLOCKEVENTS | 658 | select GENERIC_CLOCKEVENTS |
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 3a10f1a8317a..ff105399aae4 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig | |||
@@ -27,6 +27,7 @@ menuconfig ARCH_EXYNOS | |||
27 | select SRAM | 27 | select SRAM |
28 | select THERMAL | 28 | select THERMAL |
29 | select MFD_SYSCON | 29 | select MFD_SYSCON |
30 | select CLKSRC_EXYNOS_MCT | ||
30 | help | 31 | help |
31 | Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5) | 32 | Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5) |
32 | 33 | ||
diff --git a/arch/arm/mach-sti/Kconfig b/arch/arm/mach-sti/Kconfig index 125865daaf17..12dd1dc0a041 100644 --- a/arch/arm/mach-sti/Kconfig +++ b/arch/arm/mach-sti/Kconfig | |||
@@ -3,6 +3,7 @@ menuconfig ARCH_STI | |||
3 | select ARM_GIC | 3 | select ARM_GIC |
4 | select ST_IRQCHIP | 4 | select ST_IRQCHIP |
5 | select ARM_GLOBAL_TIMER | 5 | select ARM_GLOBAL_TIMER |
6 | select CLKSRC_ST_LPC | ||
6 | select PINCTRL | 7 | select PINCTRL |
7 | select PINCTRL_ST | 8 | select PINCTRL_ST |
8 | select MFD_SYSCON | 9 | select MFD_SYSCON |
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index c9ac19b24e5a..5eacdd61e61c 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig | |||
@@ -32,6 +32,7 @@ config UX500_SOC_DB8500 | |||
32 | select PINCTRL_AB8540 | 32 | select PINCTRL_AB8540 |
33 | select REGULATOR | 33 | select REGULATOR |
34 | select REGULATOR_DB8500_PRCMU | 34 | select REGULATOR_DB8500_PRCMU |
35 | select CLKSRC_DBX500_PRCMU | ||
35 | select PM_GENERIC_DOMAINS if PM | 36 | select PM_GENERIC_DOMAINS if PM |
36 | 37 | ||
37 | config MACH_MOP500 | 38 | config MACH_MOP500 |
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index dd3ac75776ad..2e20333cbce9 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig | |||
@@ -17,6 +17,7 @@ config H8300 | |||
17 | select HAVE_MEMBLOCK | 17 | select HAVE_MEMBLOCK |
18 | select HAVE_DMA_ATTRS | 18 | select HAVE_DMA_ATTRS |
19 | select CLKSRC_OF | 19 | select CLKSRC_OF |
20 | select H8300_TMR8 | ||
20 | 21 | ||
21 | config RWSEM_GENERIC_SPINLOCK | 22 | config RWSEM_GENERIC_SPINLOCK |
22 | def_bool y | 23 | def_bool y |
diff --git a/arch/h8300/include/asm/io.h b/arch/h8300/include/asm/io.h index bb837cded268..f0e14f3a800d 100644 --- a/arch/h8300/include/asm/io.h +++ b/arch/h8300/include/asm/io.h | |||
@@ -3,40 +3,45 @@ | |||
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | #ifdef __KERNEL__ |
5 | 5 | ||
6 | #include <asm-generic/io.h> | ||
7 | |||
8 | /* H8/300 internal I/O functions */ | 6 | /* H8/300 internal I/O functions */ |
9 | static inline unsigned char ctrl_inb(unsigned long addr) | 7 | |
8 | #define __raw_readb __raw_readb | ||
9 | static inline u8 __raw_readb(const volatile void __iomem *addr) | ||
10 | { | 10 | { |
11 | return *(volatile unsigned char *)addr; | 11 | return *(volatile u8 *)addr; |
12 | } | 12 | } |
13 | 13 | ||
14 | static inline unsigned short ctrl_inw(unsigned long addr) | 14 | #define __raw_readw __raw_readw |
15 | static inline u16 __raw_readw(const volatile void __iomem *addr) | ||
15 | { | 16 | { |
16 | return *(volatile unsigned short *)addr; | 17 | return *(volatile u16 *)addr; |
17 | } | 18 | } |
18 | 19 | ||
19 | static inline unsigned long ctrl_inl(unsigned long addr) | 20 | #define __raw_readl __raw_readl |
21 | static inline u32 __raw_readl(const volatile void __iomem *addr) | ||
20 | { | 22 | { |
21 | return *(volatile unsigned long *)addr; | 23 | return *(volatile u32 *)addr; |
22 | } | 24 | } |
23 | 25 | ||
24 | static inline void ctrl_outb(unsigned char b, unsigned long addr) | 26 | #define __raw_writeb __raw_writeb |
27 | static inline void __raw_writeb(u8 b, const volatile void __iomem *addr) | ||
25 | { | 28 | { |
26 | *(volatile unsigned char *)addr = b; | 29 | *(volatile u8 *)addr = b; |
27 | } | 30 | } |
28 | 31 | ||
29 | static inline void ctrl_outw(unsigned short b, unsigned long addr) | 32 | #define __raw_writew __raw_writew |
33 | static inline void __raw_writew(u16 b, const volatile void __iomem *addr) | ||
30 | { | 34 | { |
31 | *(volatile unsigned short *)addr = b; | 35 | *(volatile u16 *)addr = b; |
32 | } | 36 | } |
33 | 37 | ||
34 | static inline void ctrl_outl(unsigned long b, unsigned long addr) | 38 | #define __raw_writel __raw_writel |
39 | static inline void __raw_writel(u32 b, const volatile void __iomem *addr) | ||
35 | { | 40 | { |
36 | *(volatile unsigned long *)addr = b; | 41 | *(volatile u32 *)addr = b; |
37 | } | 42 | } |
38 | 43 | ||
39 | static inline void ctrl_bclr(int b, unsigned char *addr) | 44 | static inline void ctrl_bclr(int b, void __iomem *addr) |
40 | { | 45 | { |
41 | if (__builtin_constant_p(b)) | 46 | if (__builtin_constant_p(b)) |
42 | __asm__("bclr %1,%0" : "+WU"(*addr): "i"(b)); | 47 | __asm__("bclr %1,%0" : "+WU"(*addr): "i"(b)); |
@@ -44,7 +49,7 @@ static inline void ctrl_bclr(int b, unsigned char *addr) | |||
44 | __asm__("bclr %w1,%0" : "+WU"(*addr): "r"(b)); | 49 | __asm__("bclr %w1,%0" : "+WU"(*addr): "r"(b)); |
45 | } | 50 | } |
46 | 51 | ||
47 | static inline void ctrl_bset(int b, unsigned char *addr) | 52 | static inline void ctrl_bset(int b, void __iomem *addr) |
48 | { | 53 | { |
49 | if (__builtin_constant_p(b)) | 54 | if (__builtin_constant_p(b)) |
50 | __asm__("bset %1,%0" : "+WU"(*addr): "i"(b)); | 55 | __asm__("bset %1,%0" : "+WU"(*addr): "i"(b)); |
@@ -52,6 +57,8 @@ static inline void ctrl_bset(int b, unsigned char *addr) | |||
52 | __asm__("bset %w1,%0" : "+WU"(*addr): "r"(b)); | 57 | __asm__("bset %w1,%0" : "+WU"(*addr): "r"(b)); |
53 | } | 58 | } |
54 | 59 | ||
60 | #include <asm-generic/io.h> | ||
61 | |||
55 | #endif /* __KERNEL__ */ | 62 | #endif /* __KERNEL__ */ |
56 | 63 | ||
57 | #endif /* _H8300_IO_H */ | 64 | #endif /* _H8300_IO_H */ |
diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c index c772abe6d19c..e4985dfa91dc 100644 --- a/arch/h8300/kernel/setup.c +++ b/arch/h8300/kernel/setup.c | |||
@@ -207,14 +207,14 @@ device_initcall(device_probe); | |||
207 | #define get_wait(base, addr) ({ \ | 207 | #define get_wait(base, addr) ({ \ |
208 | int baddr; \ | 208 | int baddr; \ |
209 | baddr = ((addr) / 0x200000 * 2); \ | 209 | baddr = ((addr) / 0x200000 * 2); \ |
210 | w *= (ctrl_inw((unsigned long)(base) + 2) & (3 << baddr)) + 1; \ | 210 | w *= (readw((base) + 2) & (3 << baddr)) + 1; \ |
211 | }) | 211 | }) |
212 | #endif | 212 | #endif |
213 | #if defined(CONFIG_CPU_H8S) | 213 | #if defined(CONFIG_CPU_H8S) |
214 | #define get_wait(base, addr) ({ \ | 214 | #define get_wait(base, addr) ({ \ |
215 | int baddr; \ | 215 | int baddr; \ |
216 | baddr = ((addr) / 0x200000 * 16); \ | 216 | baddr = ((addr) / 0x200000 * 16); \ |
217 | w *= (ctrl_inl((unsigned long)(base) + 2) & (7 << baddr)) + 1; \ | 217 | w *= (readl((base) + 2) & (7 << baddr)) + 1; \ |
218 | }) | 218 | }) |
219 | #endif | 219 | #endif |
220 | 220 | ||
@@ -228,8 +228,8 @@ static __init int access_timing(void) | |||
228 | 228 | ||
229 | bsc = of_find_compatible_node(NULL, NULL, "renesas,h8300-bsc"); | 229 | bsc = of_find_compatible_node(NULL, NULL, "renesas,h8300-bsc"); |
230 | base = of_iomap(bsc, 0); | 230 | base = of_iomap(bsc, 0); |
231 | w = (ctrl_inb((unsigned long)base + 0) & bit)?2:1; | 231 | w = (readb(base + 0) & bit)?2:1; |
232 | if (ctrl_inb((unsigned long)base + 1) & bit) | 232 | if (readb(base + 1) & bit) |
233 | w *= get_wait(base, addr); | 233 | w *= get_wait(base, addr); |
234 | else | 234 | else |
235 | w *= 2; | 235 | w *= 2; |
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 2eb5f0efae90..56777f04d2d9 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -28,10 +28,16 @@ config CLKSRC_MMIO | |||
28 | bool | 28 | bool |
29 | 29 | ||
30 | config DIGICOLOR_TIMER | 30 | config DIGICOLOR_TIMER |
31 | bool | 31 | bool "Digicolor timer driver" if COMPILE_TEST |
32 | depends on GENERIC_CLOCKEVENTS | ||
33 | help | ||
34 | Enables the support for the digicolor timer driver. | ||
32 | 35 | ||
33 | config DW_APB_TIMER | 36 | config DW_APB_TIMER |
34 | bool | 37 | bool "DW APB timer driver" if COMPILE_TEST |
38 | depends on GENERIC_CLOCKEVENTS | ||
39 | help | ||
40 | Enables the support for the dw_apb timer. | ||
35 | 41 | ||
36 | config DW_APB_TIMER_OF | 42 | config DW_APB_TIMER_OF |
37 | bool | 43 | bool |
@@ -39,47 +45,77 @@ config DW_APB_TIMER_OF | |||
39 | select CLKSRC_OF | 45 | select CLKSRC_OF |
40 | 46 | ||
41 | config ROCKCHIP_TIMER | 47 | config ROCKCHIP_TIMER |
42 | bool | 48 | bool "Rockchip timer driver" if COMPILE_TEST |
49 | depends on ARM || ARM64 | ||
43 | select CLKSRC_OF | 50 | select CLKSRC_OF |
51 | help | ||
52 | Enables the support for the rockchip timer driver. | ||
44 | 53 | ||
45 | config ARMADA_370_XP_TIMER | 54 | config ARMADA_370_XP_TIMER |
46 | bool | 55 | bool "Armada 370 and XP timer driver" if COMPILE_TEST |
56 | depends on ARM | ||
47 | select CLKSRC_OF | 57 | select CLKSRC_OF |
58 | help | ||
59 | Enables the support for the Armada 370 and XP timer driver. | ||
48 | 60 | ||
49 | config MESON6_TIMER | 61 | config MESON6_TIMER |
50 | bool | 62 | bool "Meson6 timer driver" if COMPILE_TEST |
63 | depends on GENERIC_CLOCKEVENTS | ||
51 | select CLKSRC_MMIO | 64 | select CLKSRC_MMIO |
65 | help | ||
66 | Enables the support for the Meson6 timer driver. | ||
52 | 67 | ||
53 | config ORION_TIMER | 68 | config ORION_TIMER |
69 | bool "Orion timer driver" if COMPILE_TEST | ||
70 | depends on ARM | ||
54 | select CLKSRC_OF | 71 | select CLKSRC_OF |
55 | select CLKSRC_MMIO | 72 | select CLKSRC_MMIO |
56 | bool | 73 | help |
74 | Enables the support for the Orion timer driver | ||
57 | 75 | ||
58 | config SUN4I_TIMER | 76 | config SUN4I_TIMER |
77 | bool "Sun4i timer driver" if COMPILE_TEST | ||
78 | depends on GENERIC_CLOCKEVENTS | ||
59 | select CLKSRC_MMIO | 79 | select CLKSRC_MMIO |
60 | bool | 80 | help |
81 | Enables support for the Sun4i timer. | ||
61 | 82 | ||
62 | config SUN5I_HSTIMER | 83 | config SUN5I_HSTIMER |
84 | bool "Sun5i timer driver" if COMPILE_TEST | ||
63 | select CLKSRC_MMIO | 85 | select CLKSRC_MMIO |
64 | bool | 86 | depends on COMMON_CLK |
87 | help | ||
88 | Enables support the Sun5i timer. | ||
65 | 89 | ||
66 | config TEGRA_TIMER | 90 | config TEGRA_TIMER |
67 | bool | 91 | bool "Tegra timer driver" if COMPILE_TEST |
92 | depends on ARM | ||
93 | help | ||
94 | Enables support for the Tegra driver. | ||
68 | 95 | ||
69 | config VT8500_TIMER | 96 | config VT8500_TIMER |
70 | bool | 97 | bool "VT8500 timer driver" if COMPILE_TEST |
98 | depends on GENERIC_CLOCKEVENTS | ||
99 | help | ||
100 | Enables support for the VT8500 driver. | ||
71 | 101 | ||
72 | config CADENCE_TTC_TIMER | 102 | config CADENCE_TTC_TIMER |
73 | bool | 103 | bool "Cadence TTC timer driver" if COMPILE_TEST |
104 | depends on COMMON_CLK | ||
105 | help | ||
106 | Enables support for the cadence ttc driver. | ||
74 | 107 | ||
75 | config ASM9260_TIMER | 108 | config ASM9260_TIMER |
76 | bool | 109 | bool "ASM9260 timer driver" if COMPILE_TEST |
110 | depends on GENERIC_CLOCKEVENTS | ||
77 | select CLKSRC_MMIO | 111 | select CLKSRC_MMIO |
78 | select CLKSRC_OF | 112 | select CLKSRC_OF |
113 | help | ||
114 | Enables support for the ASM9260 timer. | ||
79 | 115 | ||
80 | config CLKSRC_NOMADIK_MTU | 116 | config CLKSRC_NOMADIK_MTU |
81 | bool | 117 | bool "Nomakdik clocksource driver" if COMPILE_TEST |
82 | depends on (ARCH_NOMADIK || ARCH_U8500) | 118 | depends on ARM |
83 | select CLKSRC_MMIO | 119 | select CLKSRC_MMIO |
84 | help | 120 | help |
85 | Support for Multi Timer Unit. MTU provides access | 121 | Support for Multi Timer Unit. MTU provides access |
@@ -93,9 +129,8 @@ config CLKSRC_NOMADIK_MTU_SCHED_CLOCK | |||
93 | Use the Multi Timer Unit as the sched_clock. | 129 | Use the Multi Timer Unit as the sched_clock. |
94 | 130 | ||
95 | config CLKSRC_DBX500_PRCMU | 131 | config CLKSRC_DBX500_PRCMU |
96 | bool "Clocksource PRCMU Timer" | 132 | bool "Clocksource PRCMU Timer" if COMPILE_TEST |
97 | depends on UX500_SOC_DB8500 | 133 | depends on GENERIC_CLOCKEVENTS |
98 | default y | ||
99 | help | 134 | help |
100 | Use the always on PRCMU Timer as clocksource | 135 | Use the always on PRCMU Timer as clocksource |
101 | 136 | ||
@@ -116,13 +151,19 @@ config CLKSRC_EFM32 | |||
116 | event device. | 151 | event device. |
117 | 152 | ||
118 | config CLKSRC_LPC32XX | 153 | config CLKSRC_LPC32XX |
119 | bool | 154 | bool "Clocksource for LPC32XX" if COMPILE_TEST |
155 | depends on GENERIC_CLOCKEVENTS && HAS_IOMEM | ||
120 | select CLKSRC_MMIO | 156 | select CLKSRC_MMIO |
121 | select CLKSRC_OF | 157 | select CLKSRC_OF |
158 | help | ||
159 | Support for the LPC32XX clocksource. | ||
122 | 160 | ||
123 | config CLKSRC_PISTACHIO | 161 | config CLKSRC_PISTACHIO |
124 | bool | 162 | bool "Clocksource for Pistachio SoC" if COMPILE_TEST |
163 | depends on HAS_IOMEM | ||
125 | select CLKSRC_OF | 164 | select CLKSRC_OF |
165 | help | ||
166 | Enables the clocksource for the Pistachio SoC. | ||
126 | 167 | ||
127 | config CLKSRC_TI_32K | 168 | config CLKSRC_TI_32K |
128 | bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST | 169 | bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST |
@@ -199,13 +240,14 @@ config CLKSRC_METAG_GENERIC | |||
199 | This option enables support for the Meta per-thread timers. | 240 | This option enables support for the Meta per-thread timers. |
200 | 241 | ||
201 | config CLKSRC_EXYNOS_MCT | 242 | config CLKSRC_EXYNOS_MCT |
202 | def_bool y if ARCH_EXYNOS | 243 | bool "Exynos multi core timer driver" if COMPILE_TEST |
203 | depends on !ARM64 | 244 | depends on ARM |
204 | help | 245 | help |
205 | Support for Multi Core Timer controller on Exynos SoCs. | 246 | Support for Multi Core Timer controller on Exynos SoCs. |
206 | 247 | ||
207 | config CLKSRC_SAMSUNG_PWM | 248 | config CLKSRC_SAMSUNG_PWM |
208 | bool | 249 | bool "PWM timer drvier for Samsung S3C, S5P" if COMPILE_TEST |
250 | depends on GENERIC_CLOCKEVENTS | ||
209 | help | 251 | help |
210 | This is a new clocksource driver for the PWM timer found in | 252 | This is a new clocksource driver for the PWM timer found in |
211 | Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver | 253 | Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver |
@@ -213,7 +255,9 @@ config CLKSRC_SAMSUNG_PWM | |||
213 | needed only on systems that do not have the Exynos MCT available. | 255 | needed only on systems that do not have the Exynos MCT available. |
214 | 256 | ||
215 | config FSL_FTM_TIMER | 257 | config FSL_FTM_TIMER |
216 | bool | 258 | bool "Freescale FlexTimer Module driver" if COMPILE_TEST |
259 | depends on GENERIC_CLOCKEVENTS | ||
260 | select CLKSRC_MMIO | ||
217 | help | 261 | help |
218 | Support for Freescale FlexTimer Module (FTM) timer. | 262 | Support for Freescale FlexTimer Module (FTM) timer. |
219 | 263 | ||
@@ -226,9 +270,12 @@ config SYS_SUPPORTS_SH_CMT | |||
226 | bool | 270 | bool |
227 | 271 | ||
228 | config MTK_TIMER | 272 | config MTK_TIMER |
273 | bool "Mediatek timer driver" if COMPILE_TEST | ||
274 | depends on GENERIC_CLOCKEVENTS && HAS_IOMEM | ||
229 | select CLKSRC_OF | 275 | select CLKSRC_OF |
230 | select CLKSRC_MMIO | 276 | select CLKSRC_MMIO |
231 | bool | 277 | help |
278 | Support for Mediatek timer driver. | ||
232 | 279 | ||
233 | config SYS_SUPPORTS_SH_MTU2 | 280 | config SYS_SUPPORTS_SH_MTU2 |
234 | bool | 281 | bool |
@@ -279,7 +326,12 @@ config EM_TIMER_STI | |||
279 | such as EMEV2 from former NEC Electronics. | 326 | such as EMEV2 from former NEC Electronics. |
280 | 327 | ||
281 | config CLKSRC_QCOM | 328 | config CLKSRC_QCOM |
282 | bool | 329 | bool "Qualcomm MSM timer" if COMPILE_TEST |
330 | depends on ARM | ||
331 | select CLKSRC_OF | ||
332 | help | ||
333 | This enables the clocksource and the per CPU clockevent driver for the | ||
334 | Qualcomm SoCs. | ||
283 | 335 | ||
284 | config CLKSRC_VERSATILE | 336 | config CLKSRC_VERSATILE |
285 | bool "ARM Versatile (Express) reference platforms clock source" | 337 | bool "ARM Versatile (Express) reference platforms clock source" |
@@ -298,21 +350,40 @@ config CLKSRC_MIPS_GIC | |||
298 | select CLKSRC_OF | 350 | select CLKSRC_OF |
299 | 351 | ||
300 | config CLKSRC_TANGO_XTAL | 352 | config CLKSRC_TANGO_XTAL |
301 | bool | 353 | bool "Clocksource for Tango SoC" if COMPILE_TEST |
354 | depends on ARM | ||
302 | select CLKSRC_OF | 355 | select CLKSRC_OF |
356 | select CLKSRC_MMIO | ||
357 | help | ||
358 | This enables the clocksource for Tango SoC | ||
303 | 359 | ||
304 | config CLKSRC_PXA | 360 | config CLKSRC_PXA |
305 | def_bool y if ARCH_PXA || ARCH_SA1100 | 361 | bool "Clocksource for PXA or SA-11x0 platform" if COMPILE_TEST |
306 | select CLKSRC_OF if OF | 362 | depends on GENERIC_CLOCKEVENTS |
363 | select CLKSRC_MMIO | ||
307 | help | 364 | help |
308 | This enables OST0 support available on PXA and SA-11x0 | 365 | This enables OST0 support available on PXA and SA-11x0 |
309 | platforms. | 366 | platforms. |
310 | 367 | ||
368 | config H8300_TMR8 | ||
369 | bool "Clockevent timer for the H8300 platform" if COMPILE_TEST | ||
370 | depends on GENERIC_CLOCKEVENTS && HAS_IOMEM | ||
371 | help | ||
372 | This enables the 8 bits timer for the H8300 platform. | ||
373 | |||
311 | config H8300_TMR16 | 374 | config H8300_TMR16 |
312 | bool | 375 | bool "Clockevent timer for the H83069 platform" if COMPILE_TEST |
376 | depends on GENERIC_CLOCKEVENTS && HAS_IOMEM | ||
377 | help | ||
378 | This enables the 16 bits timer for the H8300 platform with the | ||
379 | H83069 cpu. | ||
313 | 380 | ||
314 | config H8300_TPU | 381 | config H8300_TPU |
315 | bool | 382 | bool "Clocksource for the H8300 platform" if COMPILE_TEST |
383 | depends on GENERIC_CLOCKEVENTS && HAS_IOMEM | ||
384 | help | ||
385 | This enables the clocksource for the H8300 platform with the | ||
386 | H8S2678 cpu. | ||
316 | 387 | ||
317 | config CLKSRC_IMX_GPT | 388 | config CLKSRC_IMX_GPT |
318 | bool "Clocksource using i.MX GPT" if COMPILE_TEST | 389 | bool "Clocksource using i.MX GPT" if COMPILE_TEST |
@@ -320,9 +391,9 @@ config CLKSRC_IMX_GPT | |||
320 | select CLKSRC_MMIO | 391 | select CLKSRC_MMIO |
321 | 392 | ||
322 | config CLKSRC_ST_LPC | 393 | config CLKSRC_ST_LPC |
323 | bool | 394 | bool "Low power clocksource found in the LPC" if COMPILE_TEST |
324 | depends on ARCH_STI | ||
325 | select CLKSRC_OF if OF | 395 | select CLKSRC_OF if OF |
396 | depends on HAS_IOMEM | ||
326 | help | 397 | help |
327 | Enable this option to use the Low Power controller timer | 398 | Enable this option to use the Low Power controller timer |
328 | as clocksource. | 399 | as clocksource. |
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 56bd16e77ae3..dc2b8997f6e6 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
@@ -60,7 +60,7 @@ obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o | |||
60 | obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o | 60 | obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o |
61 | obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o | 61 | obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o |
62 | obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o | 62 | obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o |
63 | obj-$(CONFIG_H8300) += h8300_timer8.o | 63 | obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o |
64 | obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o | 64 | obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o |
65 | obj-$(CONFIG_H8300_TPU) += h8300_tpu.o | 65 | obj-$(CONFIG_H8300_TPU) += h8300_tpu.o |
66 | obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o | 66 | obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o |
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 6eab88985670..28037d0b8dcd 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c | |||
@@ -109,10 +109,8 @@ static void acpi_pm_check_blacklist(struct pci_dev *dev) | |||
109 | 109 | ||
110 | /* the bug has been fixed in PIIX4M */ | 110 | /* the bug has been fixed in PIIX4M */ |
111 | if (dev->revision < 3) { | 111 | if (dev->revision < 3) { |
112 | printk(KERN_WARNING "* Found PM-Timer Bug on the chipset." | 112 | pr_warn("* Found PM-Timer Bug on the chipset. Due to workarounds for a bug,\n" |
113 | " Due to workarounds for a bug,\n" | 113 | "* this clock source is slow. Consider trying other clock sources\n"); |
114 | "* this clock source is slow. Consider trying" | ||
115 | " other clock sources\n"); | ||
116 | 114 | ||
117 | acpi_pm_need_workaround(); | 115 | acpi_pm_need_workaround(); |
118 | } | 116 | } |
@@ -125,12 +123,9 @@ static void acpi_pm_check_graylist(struct pci_dev *dev) | |||
125 | if (acpi_pm_good) | 123 | if (acpi_pm_good) |
126 | return; | 124 | return; |
127 | 125 | ||
128 | printk(KERN_WARNING "* The chipset may have PM-Timer Bug. Due to" | 126 | pr_warn("* The chipset may have PM-Timer Bug. Due to workarounds for a bug,\n" |
129 | " workarounds for a bug,\n" | 127 | "* this clock source is slow. If you are sure your timer does not have\n" |
130 | "* this clock source is slow. If you are sure your timer" | 128 | "* this bug, please use \"acpi_pm_good\" to disable the workaround\n"); |
131 | " does not have\n" | ||
132 | "* this bug, please use \"acpi_pm_good\" to disable the" | ||
133 | " workaround\n"); | ||
134 | 129 | ||
135 | acpi_pm_need_workaround(); | 130 | acpi_pm_need_workaround(); |
136 | } | 131 | } |
@@ -162,8 +157,7 @@ static int verify_pmtmr_rate(void) | |||
162 | /* Check that the PMTMR delta is within 5% of what we expect */ | 157 | /* Check that the PMTMR delta is within 5% of what we expect */ |
163 | if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 || | 158 | if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 || |
164 | delta > (PMTMR_EXPECTED_RATE * 21) / 20) { | 159 | delta > (PMTMR_EXPECTED_RATE * 21) / 20) { |
165 | printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% " | 160 | pr_info("PM-Timer running at invalid rate: %lu%% of normal - aborting.\n", |
166 | "of normal - aborting.\n", | ||
167 | 100UL * delta / PMTMR_EXPECTED_RATE); | 161 | 100UL * delta / PMTMR_EXPECTED_RATE); |
168 | return -1; | 162 | return -1; |
169 | } | 163 | } |
@@ -199,15 +193,14 @@ static int __init init_acpi_pm_clocksource(void) | |||
199 | break; | 193 | break; |
200 | if ((value2 < value1) && ((value2) < 0xFFF)) | 194 | if ((value2 < value1) && ((value2) < 0xFFF)) |
201 | break; | 195 | break; |
202 | printk(KERN_INFO "PM-Timer had inconsistent results:" | 196 | pr_info("PM-Timer had inconsistent results: %#llx, %#llx - aborting.\n", |
203 | " %#llx, %#llx - aborting.\n", | 197 | value1, value2); |
204 | value1, value2); | ||
205 | pmtmr_ioport = 0; | 198 | pmtmr_ioport = 0; |
206 | return -EINVAL; | 199 | return -EINVAL; |
207 | } | 200 | } |
208 | if (i == ACPI_PM_READ_CHECKS) { | 201 | if (i == ACPI_PM_READ_CHECKS) { |
209 | printk(KERN_INFO "PM-Timer failed consistency check " | 202 | pr_info("PM-Timer failed consistency check (%#llx) - aborting.\n", |
210 | " (%#llx) - aborting.\n", value1); | 203 | value1); |
211 | pmtmr_ioport = 0; | 204 | pmtmr_ioport = 0; |
212 | return -ENODEV; | 205 | return -ENODEV; |
213 | } | 206 | } |
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c index a2cb6fae9295..d189d8cb69f7 100644 --- a/drivers/clocksource/arm_global_timer.c +++ b/drivers/clocksource/arm_global_timer.c | |||
@@ -99,17 +99,17 @@ static void gt_compare_set(unsigned long delta, int periodic) | |||
99 | 99 | ||
100 | counter += delta; | 100 | counter += delta; |
101 | ctrl = GT_CONTROL_TIMER_ENABLE; | 101 | ctrl = GT_CONTROL_TIMER_ENABLE; |
102 | writel(ctrl, gt_base + GT_CONTROL); | 102 | writel_relaxed(ctrl, gt_base + GT_CONTROL); |
103 | writel(lower_32_bits(counter), gt_base + GT_COMP0); | 103 | writel_relaxed(lower_32_bits(counter), gt_base + GT_COMP0); |
104 | writel(upper_32_bits(counter), gt_base + GT_COMP1); | 104 | writel_relaxed(upper_32_bits(counter), gt_base + GT_COMP1); |
105 | 105 | ||
106 | if (periodic) { | 106 | if (periodic) { |
107 | writel(delta, gt_base + GT_AUTO_INC); | 107 | writel_relaxed(delta, gt_base + GT_AUTO_INC); |
108 | ctrl |= GT_CONTROL_AUTO_INC; | 108 | ctrl |= GT_CONTROL_AUTO_INC; |
109 | } | 109 | } |
110 | 110 | ||
111 | ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE; | 111 | ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE; |
112 | writel(ctrl, gt_base + GT_CONTROL); | 112 | writel_relaxed(ctrl, gt_base + GT_CONTROL); |
113 | } | 113 | } |
114 | 114 | ||
115 | static int gt_clockevent_shutdown(struct clock_event_device *evt) | 115 | static int gt_clockevent_shutdown(struct clock_event_device *evt) |
@@ -195,12 +195,23 @@ static cycle_t gt_clocksource_read(struct clocksource *cs) | |||
195 | return gt_counter_read(); | 195 | return gt_counter_read(); |
196 | } | 196 | } |
197 | 197 | ||
198 | static void gt_resume(struct clocksource *cs) | ||
199 | { | ||
200 | unsigned long ctrl; | ||
201 | |||
202 | ctrl = readl(gt_base + GT_CONTROL); | ||
203 | if (!(ctrl & GT_CONTROL_TIMER_ENABLE)) | ||
204 | /* re-enable timer on resume */ | ||
205 | writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL); | ||
206 | } | ||
207 | |||
198 | static struct clocksource gt_clocksource = { | 208 | static struct clocksource gt_clocksource = { |
199 | .name = "arm_global_timer", | 209 | .name = "arm_global_timer", |
200 | .rating = 300, | 210 | .rating = 300, |
201 | .read = gt_clocksource_read, | 211 | .read = gt_clocksource_read, |
202 | .mask = CLOCKSOURCE_MASK(64), | 212 | .mask = CLOCKSOURCE_MASK(64), |
203 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 213 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
214 | .resume = gt_resume, | ||
204 | }; | 215 | }; |
205 | 216 | ||
206 | #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK | 217 | #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK |
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c index c76c75006ea6..63345260244d 100644 --- a/drivers/clocksource/dw_apb_timer.c +++ b/drivers/clocksource/dw_apb_timer.c | |||
@@ -49,20 +49,31 @@ clocksource_to_dw_apb_clocksource(struct clocksource *cs) | |||
49 | return container_of(cs, struct dw_apb_clocksource, cs); | 49 | return container_of(cs, struct dw_apb_clocksource, cs); |
50 | } | 50 | } |
51 | 51 | ||
52 | static unsigned long apbt_readl(struct dw_apb_timer *timer, unsigned long offs) | 52 | static inline u32 apbt_readl(struct dw_apb_timer *timer, unsigned long offs) |
53 | { | 53 | { |
54 | return readl(timer->base + offs); | 54 | return readl(timer->base + offs); |
55 | } | 55 | } |
56 | 56 | ||
57 | static void apbt_writel(struct dw_apb_timer *timer, unsigned long val, | 57 | static inline void apbt_writel(struct dw_apb_timer *timer, u32 val, |
58 | unsigned long offs) | 58 | unsigned long offs) |
59 | { | 59 | { |
60 | writel(val, timer->base + offs); | 60 | writel(val, timer->base + offs); |
61 | } | 61 | } |
62 | 62 | ||
63 | static inline u32 apbt_readl_relaxed(struct dw_apb_timer *timer, unsigned long offs) | ||
64 | { | ||
65 | return readl_relaxed(timer->base + offs); | ||
66 | } | ||
67 | |||
68 | static inline void apbt_writel_relaxed(struct dw_apb_timer *timer, u32 val, | ||
69 | unsigned long offs) | ||
70 | { | ||
71 | writel_relaxed(val, timer->base + offs); | ||
72 | } | ||
73 | |||
63 | static void apbt_disable_int(struct dw_apb_timer *timer) | 74 | static void apbt_disable_int(struct dw_apb_timer *timer) |
64 | { | 75 | { |
65 | unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL); | 76 | u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL); |
66 | 77 | ||
67 | ctrl |= APBTMR_CONTROL_INT; | 78 | ctrl |= APBTMR_CONTROL_INT; |
68 | apbt_writel(timer, ctrl, APBTMR_N_CONTROL); | 79 | apbt_writel(timer, ctrl, APBTMR_N_CONTROL); |
@@ -81,7 +92,7 @@ void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced) | |||
81 | 92 | ||
82 | static void apbt_eoi(struct dw_apb_timer *timer) | 93 | static void apbt_eoi(struct dw_apb_timer *timer) |
83 | { | 94 | { |
84 | apbt_readl(timer, APBTMR_N_EOI); | 95 | apbt_readl_relaxed(timer, APBTMR_N_EOI); |
85 | } | 96 | } |
86 | 97 | ||
87 | static irqreturn_t dw_apb_clockevent_irq(int irq, void *data) | 98 | static irqreturn_t dw_apb_clockevent_irq(int irq, void *data) |
@@ -103,7 +114,7 @@ static irqreturn_t dw_apb_clockevent_irq(int irq, void *data) | |||
103 | 114 | ||
104 | static void apbt_enable_int(struct dw_apb_timer *timer) | 115 | static void apbt_enable_int(struct dw_apb_timer *timer) |
105 | { | 116 | { |
106 | unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL); | 117 | u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL); |
107 | /* clear pending intr */ | 118 | /* clear pending intr */ |
108 | apbt_readl(timer, APBTMR_N_EOI); | 119 | apbt_readl(timer, APBTMR_N_EOI); |
109 | ctrl &= ~APBTMR_CONTROL_INT; | 120 | ctrl &= ~APBTMR_CONTROL_INT; |
@@ -113,7 +124,7 @@ static void apbt_enable_int(struct dw_apb_timer *timer) | |||
113 | static int apbt_shutdown(struct clock_event_device *evt) | 124 | static int apbt_shutdown(struct clock_event_device *evt) |
114 | { | 125 | { |
115 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); | 126 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); |
116 | unsigned long ctrl; | 127 | u32 ctrl; |
117 | 128 | ||
118 | pr_debug("%s CPU %d state=shutdown\n", __func__, | 129 | pr_debug("%s CPU %d state=shutdown\n", __func__, |
119 | cpumask_first(evt->cpumask)); | 130 | cpumask_first(evt->cpumask)); |
@@ -127,7 +138,7 @@ static int apbt_shutdown(struct clock_event_device *evt) | |||
127 | static int apbt_set_oneshot(struct clock_event_device *evt) | 138 | static int apbt_set_oneshot(struct clock_event_device *evt) |
128 | { | 139 | { |
129 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); | 140 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); |
130 | unsigned long ctrl; | 141 | u32 ctrl; |
131 | 142 | ||
132 | pr_debug("%s CPU %d state=oneshot\n", __func__, | 143 | pr_debug("%s CPU %d state=oneshot\n", __func__, |
133 | cpumask_first(evt->cpumask)); | 144 | cpumask_first(evt->cpumask)); |
@@ -160,7 +171,7 @@ static int apbt_set_periodic(struct clock_event_device *evt) | |||
160 | { | 171 | { |
161 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); | 172 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); |
162 | unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ); | 173 | unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ); |
163 | unsigned long ctrl; | 174 | u32 ctrl; |
164 | 175 | ||
165 | pr_debug("%s CPU %d state=periodic\n", __func__, | 176 | pr_debug("%s CPU %d state=periodic\n", __func__, |
166 | cpumask_first(evt->cpumask)); | 177 | cpumask_first(evt->cpumask)); |
@@ -196,17 +207,17 @@ static int apbt_resume(struct clock_event_device *evt) | |||
196 | static int apbt_next_event(unsigned long delta, | 207 | static int apbt_next_event(unsigned long delta, |
197 | struct clock_event_device *evt) | 208 | struct clock_event_device *evt) |
198 | { | 209 | { |
199 | unsigned long ctrl; | 210 | u32 ctrl; |
200 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); | 211 | struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt); |
201 | 212 | ||
202 | /* Disable timer */ | 213 | /* Disable timer */ |
203 | ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL); | 214 | ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL); |
204 | ctrl &= ~APBTMR_CONTROL_ENABLE; | 215 | ctrl &= ~APBTMR_CONTROL_ENABLE; |
205 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | 216 | apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); |
206 | /* write new count */ | 217 | /* write new count */ |
207 | apbt_writel(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT); | 218 | apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT); |
208 | ctrl |= APBTMR_CONTROL_ENABLE; | 219 | ctrl |= APBTMR_CONTROL_ENABLE; |
209 | apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); | 220 | apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL); |
210 | 221 | ||
211 | return 0; | 222 | return 0; |
212 | } | 223 | } |
@@ -323,7 +334,7 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs) | |||
323 | * start count down from 0xffff_ffff. this is done by toggling the | 334 | * start count down from 0xffff_ffff. this is done by toggling the |
324 | * enable bit then load initial load count to ~0. | 335 | * enable bit then load initial load count to ~0. |
325 | */ | 336 | */ |
326 | unsigned long ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL); | 337 | u32 ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL); |
327 | 338 | ||
328 | ctrl &= ~APBTMR_CONTROL_ENABLE; | 339 | ctrl &= ~APBTMR_CONTROL_ENABLE; |
329 | apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); | 340 | apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL); |
@@ -338,11 +349,12 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs) | |||
338 | 349 | ||
339 | static cycle_t __apbt_read_clocksource(struct clocksource *cs) | 350 | static cycle_t __apbt_read_clocksource(struct clocksource *cs) |
340 | { | 351 | { |
341 | unsigned long current_count; | 352 | u32 current_count; |
342 | struct dw_apb_clocksource *dw_cs = | 353 | struct dw_apb_clocksource *dw_cs = |
343 | clocksource_to_dw_apb_clocksource(cs); | 354 | clocksource_to_dw_apb_clocksource(cs); |
344 | 355 | ||
345 | current_count = apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE); | 356 | current_count = apbt_readl_relaxed(&dw_cs->timer, |
357 | APBTMR_N_CURRENT_VALUE); | ||
346 | 358 | ||
347 | return (cycle_t)~current_count; | 359 | return (cycle_t)~current_count; |
348 | } | 360 | } |
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index a19a3f619cc7..860843cef572 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | */ | 18 | */ |
19 | #include <linux/delay.h> | ||
19 | #include <linux/dw_apb_timer.h> | 20 | #include <linux/dw_apb_timer.h> |
20 | #include <linux/of.h> | 21 | #include <linux/of.h> |
21 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
@@ -130,6 +131,17 @@ static void __init init_sched_clock(void) | |||
130 | sched_clock_register(read_sched_clock, 32, sched_rate); | 131 | sched_clock_register(read_sched_clock, 32, sched_rate); |
131 | } | 132 | } |
132 | 133 | ||
134 | #ifdef CONFIG_ARM | ||
135 | static unsigned long dw_apb_delay_timer_read(void) | ||
136 | { | ||
137 | return ~readl_relaxed(sched_io_base); | ||
138 | } | ||
139 | |||
140 | static struct delay_timer dw_apb_delay_timer = { | ||
141 | .read_current_timer = dw_apb_delay_timer_read, | ||
142 | }; | ||
143 | #endif | ||
144 | |||
133 | static int num_called; | 145 | static int num_called; |
134 | static void __init dw_apb_timer_init(struct device_node *timer) | 146 | static void __init dw_apb_timer_init(struct device_node *timer) |
135 | { | 147 | { |
@@ -142,6 +154,10 @@ static void __init dw_apb_timer_init(struct device_node *timer) | |||
142 | pr_debug("%s: found clocksource timer\n", __func__); | 154 | pr_debug("%s: found clocksource timer\n", __func__); |
143 | add_clocksource(timer); | 155 | add_clocksource(timer); |
144 | init_sched_clock(); | 156 | init_sched_clock(); |
157 | #ifdef CONFIG_ARM | ||
158 | dw_apb_delay_timer.freq = sched_rate; | ||
159 | register_current_timer_delay(&dw_apb_delay_timer); | ||
160 | #endif | ||
145 | break; | 161 | break; |
146 | default: | 162 | default: |
147 | break; | 163 | break; |
diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c index 0e076c6fc006..75c44079b345 100644 --- a/drivers/clocksource/h8300_timer16.c +++ b/drivers/clocksource/h8300_timer16.c | |||
@@ -4,85 +4,56 @@ | |||
4 | * Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp> | 4 | * Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/errno.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/param.h> | ||
10 | #include <linux/string.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/interrupt.h> | 7 | #include <linux/interrupt.h> |
13 | #include <linux/init.h> | 8 | #include <linux/init.h> |
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/clocksource.h> | 9 | #include <linux/clocksource.h> |
16 | #include <linux/module.h> | ||
17 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
18 | #include <linux/io.h> | 11 | #include <linux/io.h> |
19 | #include <linux/of.h> | 12 | #include <linux/of.h> |
20 | 13 | #include <linux/of_address.h> | |
21 | #include <asm/segment.h> | 14 | #include <linux/of_irq.h> |
22 | #include <asm/irq.h> | ||
23 | 15 | ||
24 | #define TSTR 0 | 16 | #define TSTR 0 |
25 | #define TSNC 1 | ||
26 | #define TMDR 2 | ||
27 | #define TOLR 3 | ||
28 | #define TISRA 4 | ||
29 | #define TISRB 5 | ||
30 | #define TISRC 6 | 17 | #define TISRC 6 |
31 | 18 | ||
32 | #define TCR 0 | 19 | #define TCR 0 |
33 | #define TIOR 1 | ||
34 | #define TCNT 2 | 20 | #define TCNT 2 |
35 | #define GRA 4 | ||
36 | #define GRB 6 | ||
37 | |||
38 | #define FLAG_REPROGRAM (1 << 0) | ||
39 | #define FLAG_SKIPEVENT (1 << 1) | ||
40 | #define FLAG_IRQCONTEXT (1 << 2) | ||
41 | #define FLAG_STARTED (1 << 3) | ||
42 | 21 | ||
43 | #define ONESHOT 0 | 22 | #define bset(b, a) iowrite8(ioread8(a) | (1 << (b)), (a)) |
44 | #define PERIODIC 1 | 23 | #define bclr(b, a) iowrite8(ioread8(a) & ~(1 << (b)), (a)) |
45 | |||
46 | #define RELATIVE 0 | ||
47 | #define ABSOLUTE 1 | ||
48 | 24 | ||
49 | struct timer16_priv { | 25 | struct timer16_priv { |
50 | struct platform_device *pdev; | ||
51 | struct clocksource cs; | 26 | struct clocksource cs; |
52 | struct irqaction irqaction; | ||
53 | unsigned long total_cycles; | 27 | unsigned long total_cycles; |
54 | unsigned long mapbase; | 28 | void __iomem *mapbase; |
55 | unsigned long mapcommon; | 29 | void __iomem *mapcommon; |
56 | unsigned long flags; | ||
57 | unsigned short gra; | ||
58 | unsigned short cs_enabled; | 30 | unsigned short cs_enabled; |
59 | unsigned char enb; | 31 | unsigned char enb; |
60 | unsigned char imfa; | ||
61 | unsigned char imiea; | ||
62 | unsigned char ovf; | 32 | unsigned char ovf; |
63 | raw_spinlock_t lock; | 33 | unsigned char ovie; |
64 | struct clk *clk; | ||
65 | }; | 34 | }; |
66 | 35 | ||
67 | static unsigned long timer16_get_counter(struct timer16_priv *p) | 36 | static unsigned long timer16_get_counter(struct timer16_priv *p) |
68 | { | 37 | { |
69 | unsigned long v1, v2, v3; | 38 | unsigned short v1, v2, v3; |
70 | int o1, o2; | 39 | unsigned char o1, o2; |
71 | 40 | ||
72 | o1 = ctrl_inb(p->mapcommon + TISRC) & p->ovf; | 41 | o1 = ioread8(p->mapcommon + TISRC) & p->ovf; |
73 | 42 | ||
74 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ | 43 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ |
75 | do { | 44 | do { |
76 | o2 = o1; | 45 | o2 = o1; |
77 | v1 = ctrl_inw(p->mapbase + TCNT); | 46 | v1 = ioread16be(p->mapbase + TCNT); |
78 | v2 = ctrl_inw(p->mapbase + TCNT); | 47 | v2 = ioread16be(p->mapbase + TCNT); |
79 | v3 = ctrl_inw(p->mapbase + TCNT); | 48 | v3 = ioread16be(p->mapbase + TCNT); |
80 | o1 = ctrl_inb(p->mapcommon + TISRC) & p->ovf; | 49 | o1 = ioread8(p->mapcommon + TISRC) & p->ovf; |
81 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) | 50 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) |
82 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); | 51 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); |
83 | 52 | ||
84 | v2 |= 0x10000; | 53 | if (likely(!o1)) |
85 | return v2; | 54 | return v2; |
55 | else | ||
56 | return v2 + 0x10000; | ||
86 | } | 57 | } |
87 | 58 | ||
88 | 59 | ||
@@ -90,8 +61,7 @@ static irqreturn_t timer16_interrupt(int irq, void *dev_id) | |||
90 | { | 61 | { |
91 | struct timer16_priv *p = (struct timer16_priv *)dev_id; | 62 | struct timer16_priv *p = (struct timer16_priv *)dev_id; |
92 | 63 | ||
93 | ctrl_outb(ctrl_inb(p->mapcommon + TISRA) & ~p->imfa, | 64 | bclr(p->ovf, p->mapcommon + TISRC); |
94 | p->mapcommon + TISRA); | ||
95 | p->total_cycles += 0x10000; | 65 | p->total_cycles += 0x10000; |
96 | 66 | ||
97 | return IRQ_HANDLED; | 67 | return IRQ_HANDLED; |
@@ -105,13 +75,10 @@ static inline struct timer16_priv *cs_to_priv(struct clocksource *cs) | |||
105 | static cycle_t timer16_clocksource_read(struct clocksource *cs) | 75 | static cycle_t timer16_clocksource_read(struct clocksource *cs) |
106 | { | 76 | { |
107 | struct timer16_priv *p = cs_to_priv(cs); | 77 | struct timer16_priv *p = cs_to_priv(cs); |
108 | unsigned long flags, raw; | 78 | unsigned long raw, value; |
109 | unsigned long value; | ||
110 | 79 | ||
111 | raw_spin_lock_irqsave(&p->lock, flags); | ||
112 | value = p->total_cycles; | 80 | value = p->total_cycles; |
113 | raw = timer16_get_counter(p); | 81 | raw = timer16_get_counter(p); |
114 | raw_spin_unlock_irqrestore(&p->lock, flags); | ||
115 | 82 | ||
116 | return value + raw; | 83 | return value + raw; |
117 | } | 84 | } |
@@ -123,10 +90,10 @@ static int timer16_enable(struct clocksource *cs) | |||
123 | WARN_ON(p->cs_enabled); | 90 | WARN_ON(p->cs_enabled); |
124 | 91 | ||
125 | p->total_cycles = 0; | 92 | p->total_cycles = 0; |
126 | ctrl_outw(0x0000, p->mapbase + TCNT); | 93 | iowrite16be(0x0000, p->mapbase + TCNT); |
127 | ctrl_outb(0x83, p->mapbase + TCR); | 94 | iowrite8(0x83, p->mapbase + TCR); |
128 | ctrl_outb(ctrl_inb(p->mapcommon + TSTR) | p->enb, | 95 | bset(p->ovie, p->mapcommon + TISRC); |
129 | p->mapcommon + TSTR); | 96 | bset(p->enb, p->mapcommon + TSTR); |
130 | 97 | ||
131 | p->cs_enabled = true; | 98 | p->cs_enabled = true; |
132 | return 0; | 99 | return 0; |
@@ -138,116 +105,83 @@ static void timer16_disable(struct clocksource *cs) | |||
138 | 105 | ||
139 | WARN_ON(!p->cs_enabled); | 106 | WARN_ON(!p->cs_enabled); |
140 | 107 | ||
141 | ctrl_outb(ctrl_inb(p->mapcommon + TSTR) & ~p->enb, | 108 | bclr(p->ovie, p->mapcommon + TISRC); |
142 | p->mapcommon + TSTR); | 109 | bclr(p->enb, p->mapcommon + TSTR); |
143 | 110 | ||
144 | p->cs_enabled = false; | 111 | p->cs_enabled = false; |
145 | } | 112 | } |
146 | 113 | ||
114 | static struct timer16_priv timer16_priv = { | ||
115 | .cs = { | ||
116 | .name = "h8300_16timer", | ||
117 | .rating = 200, | ||
118 | .read = timer16_clocksource_read, | ||
119 | .enable = timer16_enable, | ||
120 | .disable = timer16_disable, | ||
121 | .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8), | ||
122 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
123 | }, | ||
124 | }; | ||
125 | |||
147 | #define REG_CH 0 | 126 | #define REG_CH 0 |
148 | #define REG_COMM 1 | 127 | #define REG_COMM 1 |
149 | 128 | ||
150 | static int timer16_setup(struct timer16_priv *p, struct platform_device *pdev) | 129 | static void __init h8300_16timer_init(struct device_node *node) |
151 | { | 130 | { |
152 | struct resource *res[2]; | 131 | void __iomem *base[2]; |
153 | int ret, irq; | 132 | int ret, irq; |
154 | unsigned int ch; | 133 | unsigned int ch; |
134 | struct clk *clk; | ||
155 | 135 | ||
156 | p->pdev = pdev; | 136 | clk = of_clk_get(node, 0); |
157 | 137 | if (IS_ERR(clk)) { | |
158 | res[REG_CH] = platform_get_resource(p->pdev, | 138 | pr_err("failed to get clock for clocksource\n"); |
159 | IORESOURCE_MEM, REG_CH); | 139 | return; |
160 | res[REG_COMM] = platform_get_resource(p->pdev, | ||
161 | IORESOURCE_MEM, REG_COMM); | ||
162 | if (!res[REG_CH] || !res[REG_COMM]) { | ||
163 | dev_err(&p->pdev->dev, "failed to get I/O memory\n"); | ||
164 | return -ENXIO; | ||
165 | } | ||
166 | irq = platform_get_irq(p->pdev, 0); | ||
167 | if (irq < 0) { | ||
168 | dev_err(&p->pdev->dev, "failed to get irq\n"); | ||
169 | return irq; | ||
170 | } | 140 | } |
171 | 141 | ||
172 | p->clk = clk_get(&p->pdev->dev, "fck"); | 142 | base[REG_CH] = of_iomap(node, 0); |
173 | if (IS_ERR(p->clk)) { | 143 | if (!base[REG_CH]) { |
174 | dev_err(&p->pdev->dev, "can't get clk\n"); | 144 | pr_err("failed to map registers for clocksource\n"); |
175 | return PTR_ERR(p->clk); | 145 | goto free_clk; |
176 | } | 146 | } |
177 | of_property_read_u32(p->pdev->dev.of_node, "renesas,channel", &ch); | ||
178 | |||
179 | p->pdev = pdev; | ||
180 | p->mapbase = res[REG_CH]->start; | ||
181 | p->mapcommon = res[REG_COMM]->start; | ||
182 | p->enb = 1 << ch; | ||
183 | p->imfa = 1 << ch; | ||
184 | p->imiea = 1 << (4 + ch); | ||
185 | p->cs.name = pdev->name; | ||
186 | p->cs.rating = 200; | ||
187 | p->cs.read = timer16_clocksource_read; | ||
188 | p->cs.enable = timer16_enable; | ||
189 | p->cs.disable = timer16_disable; | ||
190 | p->cs.mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); | ||
191 | p->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; | ||
192 | 147 | ||
193 | ret = request_irq(irq, timer16_interrupt, | 148 | base[REG_COMM] = of_iomap(node, 1); |
194 | IRQF_TIMER, pdev->name, p); | 149 | if (!base[REG_COMM]) { |
195 | if (ret < 0) { | 150 | pr_err("failed to map registers for clocksource\n"); |
196 | dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); | 151 | goto unmap_ch; |
197 | return ret; | ||
198 | } | 152 | } |
199 | 153 | ||
200 | clocksource_register_hz(&p->cs, clk_get_rate(p->clk) / 8); | 154 | irq = irq_of_parse_and_map(node, 0); |
201 | 155 | if (!irq) { | |
202 | return 0; | 156 | pr_err("failed to get irq for clockevent\n"); |
203 | } | 157 | goto unmap_comm; |
204 | |||
205 | static int timer16_probe(struct platform_device *pdev) | ||
206 | { | ||
207 | struct timer16_priv *p = platform_get_drvdata(pdev); | ||
208 | |||
209 | if (p) { | ||
210 | dev_info(&pdev->dev, "kept as earlytimer\n"); | ||
211 | return 0; | ||
212 | } | 158 | } |
213 | 159 | ||
214 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); | 160 | of_property_read_u32(node, "renesas,channel", &ch); |
215 | if (!p) | ||
216 | return -ENOMEM; | ||
217 | 161 | ||
218 | return timer16_setup(p, pdev); | 162 | timer16_priv.mapbase = base[REG_CH]; |
219 | } | 163 | timer16_priv.mapcommon = base[REG_COMM]; |
220 | 164 | timer16_priv.enb = ch; | |
221 | static int timer16_remove(struct platform_device *pdev) | 165 | timer16_priv.ovf = ch; |
222 | { | 166 | timer16_priv.ovie = 4 + ch; |
223 | return -EBUSY; | ||
224 | } | ||
225 | 167 | ||
226 | static const struct of_device_id timer16_of_table[] = { | 168 | ret = request_irq(irq, timer16_interrupt, |
227 | { .compatible = "renesas,16bit-timer" }, | 169 | IRQF_TIMER, timer16_priv.cs.name, &timer16_priv); |
228 | { } | 170 | if (ret < 0) { |
229 | }; | 171 | pr_err("failed to request irq %d of clocksource\n", irq); |
230 | static struct platform_driver timer16_driver = { | 172 | goto unmap_comm; |
231 | .probe = timer16_probe, | ||
232 | .remove = timer16_remove, | ||
233 | .driver = { | ||
234 | .name = "h8300h-16timer", | ||
235 | .of_match_table = of_match_ptr(timer16_of_table), | ||
236 | } | 173 | } |
237 | }; | ||
238 | 174 | ||
239 | static int __init timer16_init(void) | 175 | clocksource_register_hz(&timer16_priv.cs, |
240 | { | 176 | clk_get_rate(clk) / 8); |
241 | return platform_driver_register(&timer16_driver); | 177 | return; |
242 | } | ||
243 | 178 | ||
244 | static void __exit timer16_exit(void) | 179 | unmap_comm: |
245 | { | 180 | iounmap(base[REG_COMM]); |
246 | platform_driver_unregister(&timer16_driver); | 181 | unmap_ch: |
182 | iounmap(base[REG_CH]); | ||
183 | free_clk: | ||
184 | clk_put(clk); | ||
247 | } | 185 | } |
248 | 186 | ||
249 | subsys_initcall(timer16_init); | 187 | CLOCKSOURCE_OF_DECLARE(h8300_16bit, "renesas,16bit-timer", h8300_16timer_init); |
250 | module_exit(timer16_exit); | ||
251 | MODULE_AUTHOR("Yoshinori Sato"); | ||
252 | MODULE_DESCRIPTION("H8/300H 16bit Timer Driver"); | ||
253 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c index 44375d8b9bc4..c151941e1956 100644 --- a/drivers/clocksource/h8300_timer8.c +++ b/drivers/clocksource/h8300_timer8.c | |||
@@ -8,19 +8,15 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/sched.h> | ||
12 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
13 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
14 | #include <linux/init.h> | 13 | #include <linux/init.h> |
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/clockchips.h> | 14 | #include <linux/clockchips.h> |
18 | #include <linux/module.h> | ||
19 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
20 | #include <linux/io.h> | 16 | #include <linux/io.h> |
21 | #include <linux/of.h> | 17 | #include <linux/of.h> |
22 | 18 | #include <linux/of_address.h> | |
23 | #include <asm/irq.h> | 19 | #include <linux/of_irq.h> |
24 | 20 | ||
25 | #define _8TCR 0 | 21 | #define _8TCR 0 |
26 | #define _8TCSR 2 | 22 | #define _8TCSR 2 |
@@ -28,126 +24,74 @@ | |||
28 | #define TCORB 6 | 24 | #define TCORB 6 |
29 | #define _8TCNT 8 | 25 | #define _8TCNT 8 |
30 | 26 | ||
31 | #define FLAG_REPROGRAM (1 << 0) | 27 | #define CMIEA 6 |
32 | #define FLAG_SKIPEVENT (1 << 1) | 28 | #define CMFA 6 |
33 | #define FLAG_IRQCONTEXT (1 << 2) | 29 | |
34 | #define FLAG_STARTED (1 << 3) | 30 | #define FLAG_STARTED (1 << 3) |
35 | 31 | ||
36 | #define ONESHOT 0 | 32 | #define SCALE 64 |
37 | #define PERIODIC 1 | ||
38 | 33 | ||
39 | #define RELATIVE 0 | 34 | #define bset(b, a) iowrite8(ioread8(a) | (1 << (b)), (a)) |
40 | #define ABSOLUTE 1 | 35 | #define bclr(b, a) iowrite8(ioread8(a) & ~(1 << (b)), (a)) |
41 | 36 | ||
42 | struct timer8_priv { | 37 | struct timer8_priv { |
43 | struct platform_device *pdev; | ||
44 | struct clock_event_device ced; | 38 | struct clock_event_device ced; |
45 | struct irqaction irqaction; | 39 | void __iomem *mapbase; |
46 | unsigned long mapbase; | ||
47 | raw_spinlock_t lock; | ||
48 | unsigned long flags; | 40 | unsigned long flags; |
49 | unsigned int rate; | 41 | unsigned int rate; |
50 | unsigned int tcora; | ||
51 | struct clk *pclk; | ||
52 | }; | 42 | }; |
53 | 43 | ||
54 | static unsigned long timer8_get_counter(struct timer8_priv *p) | ||
55 | { | ||
56 | unsigned long v1, v2, v3; | ||
57 | int o1, o2; | ||
58 | |||
59 | o1 = ctrl_inb(p->mapbase + _8TCSR) & 0x20; | ||
60 | |||
61 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ | ||
62 | do { | ||
63 | o2 = o1; | ||
64 | v1 = ctrl_inw(p->mapbase + _8TCNT); | ||
65 | v2 = ctrl_inw(p->mapbase + _8TCNT); | ||
66 | v3 = ctrl_inw(p->mapbase + _8TCNT); | ||
67 | o1 = ctrl_inb(p->mapbase + _8TCSR) & 0x20; | ||
68 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) | ||
69 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); | ||
70 | |||
71 | v2 |= o1 << 10; | ||
72 | return v2; | ||
73 | } | ||
74 | |||
75 | static irqreturn_t timer8_interrupt(int irq, void *dev_id) | 44 | static irqreturn_t timer8_interrupt(int irq, void *dev_id) |
76 | { | 45 | { |
77 | struct timer8_priv *p = dev_id; | 46 | struct timer8_priv *p = dev_id; |
78 | 47 | ||
79 | ctrl_outb(ctrl_inb(p->mapbase + _8TCSR) & ~0x40, | 48 | if (clockevent_state_oneshot(&p->ced)) |
80 | p->mapbase + _8TCSR); | 49 | iowrite16be(0x0000, p->mapbase + _8TCR); |
81 | p->flags |= FLAG_IRQCONTEXT; | 50 | |
82 | ctrl_outw(p->tcora, p->mapbase + TCORA); | 51 | p->ced.event_handler(&p->ced); |
83 | if (!(p->flags & FLAG_SKIPEVENT)) { | 52 | |
84 | if (clockevent_state_oneshot(&p->ced)) | 53 | bclr(CMFA, p->mapbase + _8TCSR); |
85 | ctrl_outw(0x0000, p->mapbase + _8TCR); | ||
86 | p->ced.event_handler(&p->ced); | ||
87 | } | ||
88 | p->flags &= ~(FLAG_SKIPEVENT | FLAG_IRQCONTEXT); | ||
89 | 54 | ||
90 | return IRQ_HANDLED; | 55 | return IRQ_HANDLED; |
91 | } | 56 | } |
92 | 57 | ||
93 | static void timer8_set_next(struct timer8_priv *p, unsigned long delta) | 58 | static void timer8_set_next(struct timer8_priv *p, unsigned long delta) |
94 | { | 59 | { |
95 | unsigned long flags; | ||
96 | unsigned long now; | ||
97 | |||
98 | raw_spin_lock_irqsave(&p->lock, flags); | ||
99 | if (delta >= 0x10000) | 60 | if (delta >= 0x10000) |
100 | dev_warn(&p->pdev->dev, "delta out of range\n"); | 61 | pr_warn("delta out of range\n"); |
101 | now = timer8_get_counter(p); | 62 | bclr(CMIEA, p->mapbase + _8TCR); |
102 | p->tcora = delta; | 63 | iowrite16be(delta, p->mapbase + TCORA); |
103 | ctrl_outb(ctrl_inb(p->mapbase + _8TCR) | 0x40, p->mapbase + _8TCR); | 64 | iowrite16be(0x0000, p->mapbase + _8TCNT); |
104 | if (delta > now) | 65 | bclr(CMFA, p->mapbase + _8TCSR); |
105 | ctrl_outw(delta, p->mapbase + TCORA); | 66 | bset(CMIEA, p->mapbase + _8TCR); |
106 | else | ||
107 | ctrl_outw(now + 1, p->mapbase + TCORA); | ||
108 | |||
109 | raw_spin_unlock_irqrestore(&p->lock, flags); | ||
110 | } | 67 | } |
111 | 68 | ||
112 | static int timer8_enable(struct timer8_priv *p) | 69 | static int timer8_enable(struct timer8_priv *p) |
113 | { | 70 | { |
114 | p->rate = clk_get_rate(p->pclk) / 64; | 71 | iowrite16be(0xffff, p->mapbase + TCORA); |
115 | ctrl_outw(0xffff, p->mapbase + TCORA); | 72 | iowrite16be(0x0000, p->mapbase + _8TCNT); |
116 | ctrl_outw(0x0000, p->mapbase + _8TCNT); | 73 | iowrite16be(0x0c02, p->mapbase + _8TCR); |
117 | ctrl_outw(0x0c02, p->mapbase + _8TCR); | ||
118 | 74 | ||
119 | return 0; | 75 | return 0; |
120 | } | 76 | } |
121 | 77 | ||
122 | static int timer8_start(struct timer8_priv *p) | 78 | static int timer8_start(struct timer8_priv *p) |
123 | { | 79 | { |
124 | int ret = 0; | 80 | int ret; |
125 | unsigned long flags; | ||
126 | |||
127 | raw_spin_lock_irqsave(&p->lock, flags); | ||
128 | |||
129 | if (!(p->flags & FLAG_STARTED)) | ||
130 | ret = timer8_enable(p); | ||
131 | 81 | ||
132 | if (ret) | 82 | if ((p->flags & FLAG_STARTED)) |
133 | goto out; | 83 | return 0; |
134 | p->flags |= FLAG_STARTED; | ||
135 | 84 | ||
136 | out: | 85 | ret = timer8_enable(p); |
137 | raw_spin_unlock_irqrestore(&p->lock, flags); | 86 | if (!ret) |
87 | p->flags |= FLAG_STARTED; | ||
138 | 88 | ||
139 | return ret; | 89 | return ret; |
140 | } | 90 | } |
141 | 91 | ||
142 | static void timer8_stop(struct timer8_priv *p) | 92 | static void timer8_stop(struct timer8_priv *p) |
143 | { | 93 | { |
144 | unsigned long flags; | 94 | iowrite16be(0x0000, p->mapbase + _8TCR); |
145 | |||
146 | raw_spin_lock_irqsave(&p->lock, flags); | ||
147 | |||
148 | ctrl_outw(0x0000, p->mapbase + _8TCR); | ||
149 | |||
150 | raw_spin_unlock_irqrestore(&p->lock, flags); | ||
151 | } | 95 | } |
152 | 96 | ||
153 | static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced) | 97 | static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced) |
@@ -155,7 +99,7 @@ static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced) | |||
155 | return container_of(ced, struct timer8_priv, ced); | 99 | return container_of(ced, struct timer8_priv, ced); |
156 | } | 100 | } |
157 | 101 | ||
158 | static void timer8_clock_event_start(struct timer8_priv *p, int periodic) | 102 | static void timer8_clock_event_start(struct timer8_priv *p, unsigned long delta) |
159 | { | 103 | { |
160 | struct clock_event_device *ced = &p->ced; | 104 | struct clock_event_device *ced = &p->ced; |
161 | 105 | ||
@@ -166,7 +110,7 @@ static void timer8_clock_event_start(struct timer8_priv *p, int periodic) | |||
166 | ced->max_delta_ns = clockevent_delta2ns(0xffff, ced); | 110 | ced->max_delta_ns = clockevent_delta2ns(0xffff, ced); |
167 | ced->min_delta_ns = clockevent_delta2ns(0x0001, ced); | 111 | ced->min_delta_ns = clockevent_delta2ns(0x0001, ced); |
168 | 112 | ||
169 | timer8_set_next(p, periodic?(p->rate + HZ/2) / HZ:0x10000); | 113 | timer8_set_next(p, delta); |
170 | } | 114 | } |
171 | 115 | ||
172 | static int timer8_clock_event_shutdown(struct clock_event_device *ced) | 116 | static int timer8_clock_event_shutdown(struct clock_event_device *ced) |
@@ -179,9 +123,9 @@ static int timer8_clock_event_periodic(struct clock_event_device *ced) | |||
179 | { | 123 | { |
180 | struct timer8_priv *p = ced_to_priv(ced); | 124 | struct timer8_priv *p = ced_to_priv(ced); |
181 | 125 | ||
182 | dev_info(&p->pdev->dev, "used for periodic clock events\n"); | 126 | pr_info("%s: used for periodic clock events\n", ced->name); |
183 | timer8_stop(p); | 127 | timer8_stop(p); |
184 | timer8_clock_event_start(p, PERIODIC); | 128 | timer8_clock_event_start(p, (p->rate + HZ/2) / HZ); |
185 | 129 | ||
186 | return 0; | 130 | return 0; |
187 | } | 131 | } |
@@ -190,9 +134,9 @@ static int timer8_clock_event_oneshot(struct clock_event_device *ced) | |||
190 | { | 134 | { |
191 | struct timer8_priv *p = ced_to_priv(ced); | 135 | struct timer8_priv *p = ced_to_priv(ced); |
192 | 136 | ||
193 | dev_info(&p->pdev->dev, "used for oneshot clock events\n"); | 137 | pr_info("%s: used for oneshot clock events\n", ced->name); |
194 | timer8_stop(p); | 138 | timer8_stop(p); |
195 | timer8_clock_event_start(p, ONESHOT); | 139 | timer8_clock_event_start(p, 0x10000); |
196 | 140 | ||
197 | return 0; | 141 | return 0; |
198 | } | 142 | } |
@@ -208,110 +152,64 @@ static int timer8_clock_event_next(unsigned long delta, | |||
208 | return 0; | 152 | return 0; |
209 | } | 153 | } |
210 | 154 | ||
211 | static int timer8_setup(struct timer8_priv *p, | 155 | static struct timer8_priv timer8_priv = { |
212 | struct platform_device *pdev) | 156 | .ced = { |
157 | .name = "h8300_8timer", | ||
158 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
159 | .rating = 200, | ||
160 | .set_next_event = timer8_clock_event_next, | ||
161 | .set_state_shutdown = timer8_clock_event_shutdown, | ||
162 | .set_state_periodic = timer8_clock_event_periodic, | ||
163 | .set_state_oneshot = timer8_clock_event_oneshot, | ||
164 | }, | ||
165 | }; | ||
166 | |||
167 | static void __init h8300_8timer_init(struct device_node *node) | ||
213 | { | 168 | { |
214 | struct resource *res; | 169 | void __iomem *base; |
215 | int irq; | 170 | int irq; |
216 | int ret; | 171 | struct clk *clk; |
217 | 172 | ||
218 | p->pdev = pdev; | 173 | clk = of_clk_get(node, 0); |
219 | 174 | if (IS_ERR(clk)) { | |
220 | res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); | 175 | pr_err("failed to get clock for clockevent\n"); |
221 | if (!res) { | 176 | return; |
222 | dev_err(&p->pdev->dev, "failed to get I/O memory\n"); | ||
223 | return -ENXIO; | ||
224 | } | 177 | } |
225 | 178 | ||
226 | irq = platform_get_irq(p->pdev, 0); | 179 | base = of_iomap(node, 0); |
227 | if (irq < 0) { | 180 | if (!base) { |
228 | dev_err(&p->pdev->dev, "failed to get irq\n"); | 181 | pr_err("failed to map registers for clockevent\n"); |
229 | return -ENXIO; | 182 | goto free_clk; |
230 | } | 183 | } |
231 | 184 | ||
232 | p->mapbase = res->start; | 185 | irq = irq_of_parse_and_map(node, 0); |
233 | 186 | if (!irq) { | |
234 | p->irqaction.name = dev_name(&p->pdev->dev); | 187 | pr_err("failed to get irq for clockevent\n"); |
235 | p->irqaction.handler = timer8_interrupt; | 188 | goto unmap_reg; |
236 | p->irqaction.dev_id = p; | ||
237 | p->irqaction.flags = IRQF_TIMER; | ||
238 | |||
239 | p->pclk = clk_get(&p->pdev->dev, "fck"); | ||
240 | if (IS_ERR(p->pclk)) { | ||
241 | dev_err(&p->pdev->dev, "can't get clk\n"); | ||
242 | return PTR_ERR(p->pclk); | ||
243 | } | 189 | } |
244 | 190 | ||
245 | p->ced.name = pdev->name; | 191 | timer8_priv.mapbase = base; |
246 | p->ced.features = CLOCK_EVT_FEAT_PERIODIC | | ||
247 | CLOCK_EVT_FEAT_ONESHOT; | ||
248 | p->ced.rating = 200; | ||
249 | p->ced.cpumask = cpumask_of(0); | ||
250 | p->ced.set_next_event = timer8_clock_event_next; | ||
251 | p->ced.set_state_shutdown = timer8_clock_event_shutdown; | ||
252 | p->ced.set_state_periodic = timer8_clock_event_periodic; | ||
253 | p->ced.set_state_oneshot = timer8_clock_event_oneshot; | ||
254 | |||
255 | ret = setup_irq(irq, &p->irqaction); | ||
256 | if (ret < 0) { | ||
257 | dev_err(&p->pdev->dev, | ||
258 | "failed to request irq %d\n", irq); | ||
259 | return ret; | ||
260 | } | ||
261 | clockevents_register_device(&p->ced); | ||
262 | platform_set_drvdata(pdev, p); | ||
263 | 192 | ||
264 | return 0; | 193 | timer8_priv.rate = clk_get_rate(clk) / SCALE; |
265 | } | 194 | if (!timer8_priv.rate) { |
266 | 195 | pr_err("Failed to get rate for the clocksource\n"); | |
267 | static int timer8_probe(struct platform_device *pdev) | 196 | goto unmap_reg; |
268 | { | ||
269 | struct timer8_priv *p = platform_get_drvdata(pdev); | ||
270 | |||
271 | if (p) { | ||
272 | dev_info(&pdev->dev, "kept as earlytimer\n"); | ||
273 | return 0; | ||
274 | } | 197 | } |
275 | 198 | ||
276 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); | 199 | if (request_irq(irq, timer8_interrupt, IRQF_TIMER, |
277 | if (!p) | 200 | timer8_priv.ced.name, &timer8_priv) < 0) { |
278 | return -ENOMEM; | 201 | pr_err("failed to request irq %d for clockevent\n", irq); |
279 | 202 | goto unmap_reg; | |
280 | return timer8_setup(p, pdev); | ||
281 | } | ||
282 | |||
283 | static int timer8_remove(struct platform_device *pdev) | ||
284 | { | ||
285 | return -EBUSY; | ||
286 | } | ||
287 | |||
288 | static const struct of_device_id timer8_of_table[] __maybe_unused = { | ||
289 | { .compatible = "renesas,8bit-timer" }, | ||
290 | { } | ||
291 | }; | ||
292 | |||
293 | MODULE_DEVICE_TABLE(of, timer8_of_table); | ||
294 | static struct platform_driver timer8_driver = { | ||
295 | .probe = timer8_probe, | ||
296 | .remove = timer8_remove, | ||
297 | .driver = { | ||
298 | .name = "h8300-8timer", | ||
299 | .of_match_table = of_match_ptr(timer8_of_table), | ||
300 | } | 203 | } |
301 | }; | ||
302 | 204 | ||
303 | static int __init timer8_init(void) | 205 | clockevents_config_and_register(&timer8_priv.ced, |
304 | { | 206 | timer8_priv.rate, 1, 0x0000ffff); |
305 | return platform_driver_register(&timer8_driver); | ||
306 | } | ||
307 | 207 | ||
308 | static void __exit timer8_exit(void) | 208 | return; |
309 | { | 209 | unmap_reg: |
310 | platform_driver_unregister(&timer8_driver); | 210 | iounmap(base); |
211 | free_clk: | ||
212 | clk_put(clk); | ||
311 | } | 213 | } |
312 | 214 | ||
313 | subsys_initcall(timer8_init); | 215 | CLOCKSOURCE_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init); |
314 | module_exit(timer8_exit); | ||
315 | MODULE_AUTHOR("Yoshinori Sato"); | ||
316 | MODULE_DESCRIPTION("H8/300 8bit Timer Driver"); | ||
317 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c index 5487410bfabb..d4c1a287c262 100644 --- a/drivers/clocksource/h8300_tpu.c +++ b/drivers/clocksource/h8300_tpu.c | |||
@@ -1,42 +1,30 @@ | |||
1 | /* | 1 | /* |
2 | * H8/300 TPU Driver | 2 | * H8S TPU Driver |
3 | * | 3 | * |
4 | * Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp> | 4 | * Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp> |
5 | * | 5 | * |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
9 | #include <linux/sched.h> | ||
10 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/init.h> | 10 | #include <linux/init.h> |
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/clocksource.h> | 11 | #include <linux/clocksource.h> |
16 | #include <linux/module.h> | ||
17 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
18 | #include <linux/io.h> | 13 | #include <linux/io.h> |
19 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | #include <linux/of_address.h> | ||
16 | #include <linux/of_irq.h> | ||
20 | 17 | ||
21 | #include <asm/irq.h> | 18 | #define TCR 0x0 |
19 | #define TSR 0x5 | ||
20 | #define TCNT 0x6 | ||
22 | 21 | ||
23 | #define TCR 0 | 22 | #define TCFV 0x10 |
24 | #define TMDR 1 | ||
25 | #define TIOR 2 | ||
26 | #define TER 4 | ||
27 | #define TSR 5 | ||
28 | #define TCNT 6 | ||
29 | #define TGRA 8 | ||
30 | #define TGRB 10 | ||
31 | #define TGRC 12 | ||
32 | #define TGRD 14 | ||
33 | 23 | ||
34 | struct tpu_priv { | 24 | struct tpu_priv { |
35 | struct platform_device *pdev; | ||
36 | struct clocksource cs; | 25 | struct clocksource cs; |
37 | struct clk *clk; | 26 | void __iomem *mapbase1; |
38 | unsigned long mapbase1; | 27 | void __iomem *mapbase2; |
39 | unsigned long mapbase2; | ||
40 | raw_spinlock_t lock; | 28 | raw_spinlock_t lock; |
41 | unsigned int cs_enabled; | 29 | unsigned int cs_enabled; |
42 | }; | 30 | }; |
@@ -45,8 +33,8 @@ static inline unsigned long read_tcnt32(struct tpu_priv *p) | |||
45 | { | 33 | { |
46 | unsigned long tcnt; | 34 | unsigned long tcnt; |
47 | 35 | ||
48 | tcnt = ctrl_inw(p->mapbase1 + TCNT) << 16; | 36 | tcnt = ioread16be(p->mapbase1 + TCNT) << 16; |
49 | tcnt |= ctrl_inw(p->mapbase2 + TCNT); | 37 | tcnt |= ioread16be(p->mapbase2 + TCNT); |
50 | return tcnt; | 38 | return tcnt; |
51 | } | 39 | } |
52 | 40 | ||
@@ -55,7 +43,7 @@ static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val) | |||
55 | unsigned long v1, v2, v3; | 43 | unsigned long v1, v2, v3; |
56 | int o1, o2; | 44 | int o1, o2; |
57 | 45 | ||
58 | o1 = ctrl_inb(p->mapbase1 + TSR) & 0x10; | 46 | o1 = ioread8(p->mapbase1 + TSR) & TCFV; |
59 | 47 | ||
60 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ | 48 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ |
61 | do { | 49 | do { |
@@ -63,7 +51,7 @@ static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val) | |||
63 | v1 = read_tcnt32(p); | 51 | v1 = read_tcnt32(p); |
64 | v2 = read_tcnt32(p); | 52 | v2 = read_tcnt32(p); |
65 | v3 = read_tcnt32(p); | 53 | v3 = read_tcnt32(p); |
66 | o1 = ctrl_inb(p->mapbase1 + TSR) & 0x10; | 54 | o1 = ioread8(p->mapbase1 + TSR) & TCFV; |
67 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) | 55 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) |
68 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); | 56 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); |
69 | 57 | ||
@@ -96,10 +84,10 @@ static int tpu_clocksource_enable(struct clocksource *cs) | |||
96 | 84 | ||
97 | WARN_ON(p->cs_enabled); | 85 | WARN_ON(p->cs_enabled); |
98 | 86 | ||
99 | ctrl_outw(0, p->mapbase1 + TCNT); | 87 | iowrite16be(0, p->mapbase1 + TCNT); |
100 | ctrl_outw(0, p->mapbase2 + TCNT); | 88 | iowrite16be(0, p->mapbase2 + TCNT); |
101 | ctrl_outb(0x0f, p->mapbase1 + TCR); | 89 | iowrite8(0x0f, p->mapbase1 + TCR); |
102 | ctrl_outb(0x03, p->mapbase2 + TCR); | 90 | iowrite8(0x03, p->mapbase2 + TCR); |
103 | 91 | ||
104 | p->cs_enabled = true; | 92 | p->cs_enabled = true; |
105 | return 0; | 93 | return 0; |
@@ -111,96 +99,59 @@ static void tpu_clocksource_disable(struct clocksource *cs) | |||
111 | 99 | ||
112 | WARN_ON(!p->cs_enabled); | 100 | WARN_ON(!p->cs_enabled); |
113 | 101 | ||
114 | ctrl_outb(0, p->mapbase1 + TCR); | 102 | iowrite8(0, p->mapbase1 + TCR); |
115 | ctrl_outb(0, p->mapbase2 + TCR); | 103 | iowrite8(0, p->mapbase2 + TCR); |
116 | p->cs_enabled = false; | 104 | p->cs_enabled = false; |
117 | } | 105 | } |
118 | 106 | ||
107 | static struct tpu_priv tpu_priv = { | ||
108 | .cs = { | ||
109 | .name = "H8S_TPU", | ||
110 | .rating = 200, | ||
111 | .read = tpu_clocksource_read, | ||
112 | .enable = tpu_clocksource_enable, | ||
113 | .disable = tpu_clocksource_disable, | ||
114 | .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8), | ||
115 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | #define CH_L 0 | 119 | #define CH_L 0 |
120 | #define CH_H 1 | 120 | #define CH_H 1 |
121 | 121 | ||
122 | static int __init tpu_setup(struct tpu_priv *p, struct platform_device *pdev) | 122 | static void __init h8300_tpu_init(struct device_node *node) |
123 | { | 123 | { |
124 | struct resource *res[2]; | 124 | void __iomem *base[2]; |
125 | 125 | struct clk *clk; | |
126 | p->pdev = pdev; | ||
127 | 126 | ||
128 | res[CH_L] = platform_get_resource(p->pdev, IORESOURCE_MEM, CH_L); | 127 | clk = of_clk_get(node, 0); |
129 | res[CH_H] = platform_get_resource(p->pdev, IORESOURCE_MEM, CH_H); | 128 | if (IS_ERR(clk)) { |
130 | if (!res[CH_L] || !res[CH_H]) { | 129 | pr_err("failed to get clock for clocksource\n"); |
131 | dev_err(&p->pdev->dev, "failed to get I/O memory\n"); | 130 | return; |
132 | return -ENXIO; | ||
133 | } | 131 | } |
134 | 132 | ||
135 | p->clk = clk_get(&p->pdev->dev, "fck"); | 133 | base[CH_L] = of_iomap(node, CH_L); |
136 | if (IS_ERR(p->clk)) { | 134 | if (!base[CH_L]) { |
137 | dev_err(&p->pdev->dev, "can't get clk\n"); | 135 | pr_err("failed to map registers for clocksource\n"); |
138 | return PTR_ERR(p->clk); | 136 | goto free_clk; |
139 | } | 137 | } |
140 | 138 | base[CH_H] = of_iomap(node, CH_H); | |
141 | p->mapbase1 = res[CH_L]->start; | 139 | if (!base[CH_H]) { |
142 | p->mapbase2 = res[CH_H]->start; | 140 | pr_err("failed to map registers for clocksource\n"); |
143 | 141 | goto unmap_L; | |
144 | p->cs.name = pdev->name; | ||
145 | p->cs.rating = 200; | ||
146 | p->cs.read = tpu_clocksource_read; | ||
147 | p->cs.enable = tpu_clocksource_enable; | ||
148 | p->cs.disable = tpu_clocksource_disable; | ||
149 | p->cs.mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); | ||
150 | p->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; | ||
151 | clocksource_register_hz(&p->cs, clk_get_rate(p->clk) / 64); | ||
152 | platform_set_drvdata(pdev, p); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int tpu_probe(struct platform_device *pdev) | ||
158 | { | ||
159 | struct tpu_priv *p = platform_get_drvdata(pdev); | ||
160 | |||
161 | if (p) { | ||
162 | dev_info(&pdev->dev, "kept as earlytimer\n"); | ||
163 | return 0; | ||
164 | } | 142 | } |
165 | 143 | ||
166 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); | 144 | tpu_priv.mapbase1 = base[CH_L]; |
167 | if (!p) | 145 | tpu_priv.mapbase2 = base[CH_H]; |
168 | return -ENOMEM; | ||
169 | 146 | ||
170 | return tpu_setup(p, pdev); | 147 | clocksource_register_hz(&tpu_priv.cs, clk_get_rate(clk) / 64); |
171 | } | ||
172 | |||
173 | static int tpu_remove(struct platform_device *pdev) | ||
174 | { | ||
175 | return -EBUSY; | ||
176 | } | ||
177 | |||
178 | static const struct of_device_id tpu_of_table[] = { | ||
179 | { .compatible = "renesas,tpu" }, | ||
180 | { } | ||
181 | }; | ||
182 | 148 | ||
183 | static struct platform_driver tpu_driver = { | 149 | return; |
184 | .probe = tpu_probe, | ||
185 | .remove = tpu_remove, | ||
186 | .driver = { | ||
187 | .name = "h8s-tpu", | ||
188 | .of_match_table = of_match_ptr(tpu_of_table), | ||
189 | } | ||
190 | }; | ||
191 | |||
192 | static int __init tpu_init(void) | ||
193 | { | ||
194 | return platform_driver_register(&tpu_driver); | ||
195 | } | ||
196 | 150 | ||
197 | static void __exit tpu_exit(void) | 151 | unmap_L: |
198 | { | 152 | iounmap(base[CH_H]); |
199 | platform_driver_unregister(&tpu_driver); | 153 | free_clk: |
154 | clk_put(clk); | ||
200 | } | 155 | } |
201 | 156 | ||
202 | subsys_initcall(tpu_init); | 157 | CLOCKSOURCE_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init); |
203 | module_exit(tpu_exit); | ||
204 | MODULE_AUTHOR("Yoshinori Sato"); | ||
205 | MODULE_DESCRIPTION("H8S Timer Pulse Unit Driver"); | ||
206 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c index fbfc74685e6a..d67bc356488f 100644 --- a/drivers/clocksource/mtk_timer.c +++ b/drivers/clocksource/mtk_timer.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
19 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
20 | #include <linux/clockchips.h> | 22 | #include <linux/clockchips.h> |
21 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
@@ -187,10 +189,8 @@ static void __init mtk_timer_init(struct device_node *node) | |||
187 | struct clk *clk; | 189 | struct clk *clk; |
188 | 190 | ||
189 | evt = kzalloc(sizeof(*evt), GFP_KERNEL); | 191 | evt = kzalloc(sizeof(*evt), GFP_KERNEL); |
190 | if (!evt) { | 192 | if (!evt) |
191 | pr_warn("Can't allocate mtk clock event driver struct"); | ||
192 | return; | 193 | return; |
193 | } | ||
194 | 194 | ||
195 | evt->dev.name = "mtk_tick"; | 195 | evt->dev.name = "mtk_tick"; |
196 | evt->dev.rating = 300; | 196 | evt->dev.rating = 300; |
@@ -204,31 +204,31 @@ static void __init mtk_timer_init(struct device_node *node) | |||
204 | 204 | ||
205 | evt->gpt_base = of_io_request_and_map(node, 0, "mtk-timer"); | 205 | evt->gpt_base = of_io_request_and_map(node, 0, "mtk-timer"); |
206 | if (IS_ERR(evt->gpt_base)) { | 206 | if (IS_ERR(evt->gpt_base)) { |
207 | pr_warn("Can't get resource\n"); | 207 | pr_err("Can't get resource\n"); |
208 | return; | 208 | goto err_kzalloc; |
209 | } | 209 | } |
210 | 210 | ||
211 | evt->dev.irq = irq_of_parse_and_map(node, 0); | 211 | evt->dev.irq = irq_of_parse_and_map(node, 0); |
212 | if (evt->dev.irq <= 0) { | 212 | if (evt->dev.irq <= 0) { |
213 | pr_warn("Can't parse IRQ"); | 213 | pr_err("Can't parse IRQ\n"); |
214 | goto err_mem; | 214 | goto err_mem; |
215 | } | 215 | } |
216 | 216 | ||
217 | clk = of_clk_get(node, 0); | 217 | clk = of_clk_get(node, 0); |
218 | if (IS_ERR(clk)) { | 218 | if (IS_ERR(clk)) { |
219 | pr_warn("Can't get timer clock"); | 219 | pr_err("Can't get timer clock\n"); |
220 | goto err_irq; | 220 | goto err_irq; |
221 | } | 221 | } |
222 | 222 | ||
223 | if (clk_prepare_enable(clk)) { | 223 | if (clk_prepare_enable(clk)) { |
224 | pr_warn("Can't prepare clock"); | 224 | pr_err("Can't prepare clock\n"); |
225 | goto err_clk_put; | 225 | goto err_clk_put; |
226 | } | 226 | } |
227 | rate = clk_get_rate(clk); | 227 | rate = clk_get_rate(clk); |
228 | 228 | ||
229 | if (request_irq(evt->dev.irq, mtk_timer_interrupt, | 229 | if (request_irq(evt->dev.irq, mtk_timer_interrupt, |
230 | IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) { | 230 | IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) { |
231 | pr_warn("failed to setup irq %d\n", evt->dev.irq); | 231 | pr_err("failed to setup irq %d\n", evt->dev.irq); |
232 | goto err_clk_disable; | 232 | goto err_clk_disable; |
233 | } | 233 | } |
234 | 234 | ||
@@ -260,5 +260,7 @@ err_mem: | |||
260 | iounmap(evt->gpt_base); | 260 | iounmap(evt->gpt_base); |
261 | of_address_to_resource(node, 0, &res); | 261 | of_address_to_resource(node, 0, &res); |
262 | release_mem_region(res.start, resource_size(&res)); | 262 | release_mem_region(res.start, resource_size(&res)); |
263 | err_kzalloc: | ||
264 | kfree(evt); | ||
263 | } | 265 | } |
264 | CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init); | 266 | CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init); |
diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c index d3c1742ded1a..8c77a529d0d4 100644 --- a/drivers/clocksource/rockchip_timer.c +++ b/drivers/clocksource/rockchip_timer.c | |||
@@ -17,16 +17,16 @@ | |||
17 | 17 | ||
18 | #define TIMER_NAME "rk_timer" | 18 | #define TIMER_NAME "rk_timer" |
19 | 19 | ||
20 | #define TIMER_LOAD_COUNT0 0x00 | 20 | #define TIMER_LOAD_COUNT0 0x00 |
21 | #define TIMER_LOAD_COUNT1 0x04 | 21 | #define TIMER_LOAD_COUNT1 0x04 |
22 | #define TIMER_CONTROL_REG 0x10 | 22 | #define TIMER_CONTROL_REG 0x10 |
23 | #define TIMER_INT_STATUS 0x18 | 23 | #define TIMER_INT_STATUS 0x18 |
24 | 24 | ||
25 | #define TIMER_DISABLE 0x0 | 25 | #define TIMER_DISABLE 0x0 |
26 | #define TIMER_ENABLE 0x1 | 26 | #define TIMER_ENABLE 0x1 |
27 | #define TIMER_MODE_FREE_RUNNING (0 << 1) | 27 | #define TIMER_MODE_FREE_RUNNING (0 << 1) |
28 | #define TIMER_MODE_USER_DEFINED_COUNT (1 << 1) | 28 | #define TIMER_MODE_USER_DEFINED_COUNT (1 << 1) |
29 | #define TIMER_INT_UNMASK (1 << 2) | 29 | #define TIMER_INT_UNMASK (1 << 2) |
30 | 30 | ||
31 | struct bc_timer { | 31 | struct bc_timer { |
32 | struct clock_event_device ce; | 32 | struct clock_event_device ce; |
@@ -49,14 +49,12 @@ static inline void __iomem *rk_base(struct clock_event_device *ce) | |||
49 | static inline void rk_timer_disable(struct clock_event_device *ce) | 49 | static inline void rk_timer_disable(struct clock_event_device *ce) |
50 | { | 50 | { |
51 | writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG); | 51 | writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG); |
52 | dsb(); | ||
53 | } | 52 | } |
54 | 53 | ||
55 | static inline void rk_timer_enable(struct clock_event_device *ce, u32 flags) | 54 | static inline void rk_timer_enable(struct clock_event_device *ce, u32 flags) |
56 | { | 55 | { |
57 | writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags, | 56 | writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags, |
58 | rk_base(ce) + TIMER_CONTROL_REG); | 57 | rk_base(ce) + TIMER_CONTROL_REG); |
59 | dsb(); | ||
60 | } | 58 | } |
61 | 59 | ||
62 | static void rk_timer_update_counter(unsigned long cycles, | 60 | static void rk_timer_update_counter(unsigned long cycles, |
@@ -64,13 +62,11 @@ static void rk_timer_update_counter(unsigned long cycles, | |||
64 | { | 62 | { |
65 | writel_relaxed(cycles, rk_base(ce) + TIMER_LOAD_COUNT0); | 63 | writel_relaxed(cycles, rk_base(ce) + TIMER_LOAD_COUNT0); |
66 | writel_relaxed(0, rk_base(ce) + TIMER_LOAD_COUNT1); | 64 | writel_relaxed(0, rk_base(ce) + TIMER_LOAD_COUNT1); |
67 | dsb(); | ||
68 | } | 65 | } |
69 | 66 | ||
70 | static void rk_timer_interrupt_clear(struct clock_event_device *ce) | 67 | static void rk_timer_interrupt_clear(struct clock_event_device *ce) |
71 | { | 68 | { |
72 | writel_relaxed(1, rk_base(ce) + TIMER_INT_STATUS); | 69 | writel_relaxed(1, rk_base(ce) + TIMER_INT_STATUS); |
73 | dsb(); | ||
74 | } | 70 | } |
75 | 71 | ||
76 | static inline int rk_timer_set_next_event(unsigned long cycles, | 72 | static inline int rk_timer_set_next_event(unsigned long cycles, |
@@ -173,4 +169,5 @@ static void __init rk_timer_init(struct device_node *np) | |||
173 | 169 | ||
174 | clockevents_config_and_register(ce, bc_timer.freq, 1, UINT_MAX); | 170 | clockevents_config_and_register(ce, bc_timer.freq, 1, UINT_MAX); |
175 | } | 171 | } |
172 | |||
176 | CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init); | 173 | CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init); |
diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/tango_xtal.c index d297b30d2bc0..2bcecafdeaea 100644 --- a/drivers/clocksource/tango_xtal.c +++ b/drivers/clocksource/tango_xtal.c | |||
@@ -19,19 +19,6 @@ static u64 notrace read_sched_clock(void) | |||
19 | return read_xtal_counter(); | 19 | return read_xtal_counter(); |
20 | } | 20 | } |
21 | 21 | ||
22 | static cycle_t read_clocksource(struct clocksource *cs) | ||
23 | { | ||
24 | return read_xtal_counter(); | ||
25 | } | ||
26 | |||
27 | static struct clocksource tango_xtal = { | ||
28 | .name = "tango-xtal", | ||
29 | .rating = 350, | ||
30 | .read = read_clocksource, | ||
31 | .mask = CLOCKSOURCE_MASK(32), | ||
32 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
33 | }; | ||
34 | |||
35 | static void __init tango_clocksource_init(struct device_node *np) | 22 | static void __init tango_clocksource_init(struct device_node *np) |
36 | { | 23 | { |
37 | struct clk *clk; | 24 | struct clk *clk; |
@@ -53,8 +40,9 @@ static void __init tango_clocksource_init(struct device_node *np) | |||
53 | delay_timer.freq = xtal_freq; | 40 | delay_timer.freq = xtal_freq; |
54 | delay_timer.read_current_timer = read_xtal_counter; | 41 | delay_timer.read_current_timer = read_xtal_counter; |
55 | 42 | ||
56 | ret = clocksource_register_hz(&tango_xtal, xtal_freq); | 43 | ret = clocksource_mmio_init(xtal_in_cnt, "tango-xtal", xtal_freq, 350, |
57 | if (ret != 0) { | 44 | 32, clocksource_mmio_readl_up); |
45 | if (!ret) { | ||
58 | pr_err("%s: registration failed\n", np->full_name); | 46 | pr_err("%s: registration failed\n", np->full_name); |
59 | return; | 47 | return; |
60 | } | 48 | } |
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index 6ebda1177e79..38333aba3055 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c | |||
@@ -96,7 +96,8 @@ static struct clock_event_device tegra_clockevent = { | |||
96 | .name = "timer0", | 96 | .name = "timer0", |
97 | .rating = 300, | 97 | .rating = 300, |
98 | .features = CLOCK_EVT_FEAT_ONESHOT | | 98 | .features = CLOCK_EVT_FEAT_ONESHOT | |
99 | CLOCK_EVT_FEAT_PERIODIC, | 99 | CLOCK_EVT_FEAT_PERIODIC | |
100 | CLOCK_EVT_FEAT_DYNIRQ, | ||
100 | .set_next_event = tegra_timer_set_next_event, | 101 | .set_next_event = tegra_timer_set_next_event, |
101 | .set_state_shutdown = tegra_timer_shutdown, | 102 | .set_state_shutdown = tegra_timer_shutdown, |
102 | .set_state_periodic = tegra_timer_set_periodic, | 103 | .set_state_periodic = tegra_timer_set_periodic, |
diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c index a1c06a2bc77c..1316876b487a 100644 --- a/drivers/clocksource/time-lpc32xx.c +++ b/drivers/clocksource/time-lpc32xx.c | |||
@@ -125,7 +125,7 @@ static int __init lpc32xx_clocksource_init(struct device_node *np) | |||
125 | 125 | ||
126 | clk = of_clk_get_by_name(np, "timerclk"); | 126 | clk = of_clk_get_by_name(np, "timerclk"); |
127 | if (IS_ERR(clk)) { | 127 | if (IS_ERR(clk)) { |
128 | pr_err("clock get failed (%lu)\n", PTR_ERR(clk)); | 128 | pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); |
129 | return PTR_ERR(clk); | 129 | return PTR_ERR(clk); |
130 | } | 130 | } |
131 | 131 | ||
@@ -184,7 +184,7 @@ static int __init lpc32xx_clockevent_init(struct device_node *np) | |||
184 | 184 | ||
185 | clk = of_clk_get_by_name(np, "timerclk"); | 185 | clk = of_clk_get_by_name(np, "timerclk"); |
186 | if (IS_ERR(clk)) { | 186 | if (IS_ERR(clk)) { |
187 | pr_err("clock get failed (%lu)\n", PTR_ERR(clk)); | 187 | pr_err("clock get failed (%ld)\n", PTR_ERR(clk)); |
188 | return PTR_ERR(clk); | 188 | return PTR_ERR(clk); |
189 | } | 189 | } |
190 | 190 | ||
diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c index bba679900054..3269d9ef7a18 100644 --- a/drivers/clocksource/time-pistachio.c +++ b/drivers/clocksource/time-pistachio.c | |||
@@ -84,7 +84,7 @@ pistachio_clocksource_read_cycles(struct clocksource *cs) | |||
84 | counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0); | 84 | counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0); |
85 | raw_spin_unlock_irqrestore(&pcs->lock, flags); | 85 | raw_spin_unlock_irqrestore(&pcs->lock, flags); |
86 | 86 | ||
87 | return ~(cycle_t)counter; | 87 | return (cycle_t)~counter; |
88 | } | 88 | } |
89 | 89 | ||
90 | static u64 notrace pistachio_read_sched_clock(void) | 90 | static u64 notrace pistachio_read_sched_clock(void) |
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c index bca9573e036a..24c83f9efd87 100644 --- a/drivers/clocksource/timer-sun5i.c +++ b/drivers/clocksource/timer-sun5i.c | |||
@@ -152,13 +152,6 @@ static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id) | |||
152 | return IRQ_HANDLED; | 152 | return IRQ_HANDLED; |
153 | } | 153 | } |
154 | 154 | ||
155 | static cycle_t sun5i_clksrc_read(struct clocksource *clksrc) | ||
156 | { | ||
157 | struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc); | ||
158 | |||
159 | return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1)); | ||
160 | } | ||
161 | |||
162 | static int sun5i_rate_cb_clksrc(struct notifier_block *nb, | 155 | static int sun5i_rate_cb_clksrc(struct notifier_block *nb, |
163 | unsigned long event, void *data) | 156 | unsigned long event, void *data) |
164 | { | 157 | { |
@@ -217,13 +210,8 @@ static int __init sun5i_setup_clocksource(struct device_node *node, | |||
217 | writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, | 210 | writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, |
218 | base + TIMER_CTL_REG(1)); | 211 | base + TIMER_CTL_REG(1)); |
219 | 212 | ||
220 | cs->clksrc.name = node->name; | 213 | ret = clocksource_mmio_init(base + TIMER_CNTVAL_LO_REG(1), node->name, |
221 | cs->clksrc.rating = 340; | 214 | rate, 340, 32, clocksource_mmio_readl_down); |
222 | cs->clksrc.read = sun5i_clksrc_read; | ||
223 | cs->clksrc.mask = CLOCKSOURCE_MASK(32); | ||
224 | cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS; | ||
225 | |||
226 | ret = clocksource_register_hz(&cs->clksrc, rate); | ||
227 | if (ret) { | 215 | if (ret) { |
228 | pr_err("Couldn't register clock source.\n"); | 216 | pr_err("Couldn't register clock source.\n"); |
229 | goto err_remove_notifier; | 217 | goto err_remove_notifier; |
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index dfc3bb410b00..ddb409274f45 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/clocksource.h> | 30 | #include <linux/clocksource.h> |
31 | #include <linux/clockchips.h> | 31 | #include <linux/clockchips.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <asm/mach/time.h> | ||
34 | 33 | ||
35 | #include <linux/of.h> | 34 | #include <linux/of.h> |
36 | #include <linux/of_address.h> | 35 | #include <linux/of_address.h> |
diff --git a/drivers/irqchip/irq-renesas-h8300h.c b/drivers/irqchip/irq-renesas-h8300h.c index 6fd30d5ee14d..c378768d75b3 100644 --- a/drivers/irqchip/irq-renesas-h8300h.c +++ b/drivers/irqchip/irq-renesas-h8300h.c | |||
@@ -21,9 +21,9 @@ static const char ipr_bit[] = { | |||
21 | 10, 10, 10, 10, 9, 9, 9, 9, | 21 | 10, 10, 10, 10, 9, 9, 9, 9, |
22 | }; | 22 | }; |
23 | 23 | ||
24 | static void *intc_baseaddr; | 24 | static void __iomem *intc_baseaddr; |
25 | 25 | ||
26 | #define IPR ((unsigned long)intc_baseaddr + 6) | 26 | #define IPR (intc_baseaddr + 6) |
27 | 27 | ||
28 | static void h8300h_disable_irq(struct irq_data *data) | 28 | static void h8300h_disable_irq(struct irq_data *data) |
29 | { | 29 | { |
@@ -81,8 +81,8 @@ static int __init h8300h_intc_of_init(struct device_node *intc, | |||
81 | BUG_ON(!intc_baseaddr); | 81 | BUG_ON(!intc_baseaddr); |
82 | 82 | ||
83 | /* All interrupt priority low */ | 83 | /* All interrupt priority low */ |
84 | ctrl_outb(0x00, IPR + 0); | 84 | writeb(0x00, IPR + 0); |
85 | ctrl_outb(0x00, IPR + 1); | 85 | writeb(0x00, IPR + 1); |
86 | 86 | ||
87 | domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, NULL); | 87 | domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, NULL); |
88 | BUG_ON(!domain); | 88 | BUG_ON(!domain); |
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 7784b597e959..6013021a3b39 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h | |||
@@ -62,12 +62,18 @@ struct module; | |||
62 | * @suspend: suspend function for the clocksource, if necessary | 62 | * @suspend: suspend function for the clocksource, if necessary |
63 | * @resume: resume function for the clocksource, if necessary | 63 | * @resume: resume function for the clocksource, if necessary |
64 | * @owner: module reference, must be set by clocksource in modules | 64 | * @owner: module reference, must be set by clocksource in modules |
65 | * | ||
66 | * Note: This struct is not used in hotpathes of the timekeeping code | ||
67 | * because the timekeeper caches the hot path fields in its own data | ||
68 | * structure, so no line cache alignment is required, | ||
69 | * | ||
70 | * The pointer to the clocksource itself is handed to the read | ||
71 | * callback. If you need extra information there you can wrap struct | ||
72 | * clocksource into your own struct. Depending on the amount of | ||
73 | * information you need you should consider to cache line align that | ||
74 | * structure. | ||
65 | */ | 75 | */ |
66 | struct clocksource { | 76 | struct clocksource { |
67 | /* | ||
68 | * Hotpath data, fits in a single cache line when the | ||
69 | * clocksource itself is cacheline aligned. | ||
70 | */ | ||
71 | cycle_t (*read)(struct clocksource *cs); | 77 | cycle_t (*read)(struct clocksource *cs); |
72 | cycle_t mask; | 78 | cycle_t mask; |
73 | u32 mult; | 79 | u32 mult; |
@@ -95,7 +101,7 @@ struct clocksource { | |||
95 | cycle_t wd_last; | 101 | cycle_t wd_last; |
96 | #endif | 102 | #endif |
97 | struct module *owner; | 103 | struct module *owner; |
98 | } ____cacheline_aligned; | 104 | }; |
99 | 105 | ||
100 | /* | 106 | /* |
101 | * Clock source flags bits:: | 107 | * Clock source flags bits:: |
diff --git a/include/linux/sched_clock.h b/include/linux/sched_clock.h index efa931c5cef1..411b52e424e1 100644 --- a/include/linux/sched_clock.h +++ b/include/linux/sched_clock.h | |||
@@ -10,11 +10,17 @@ | |||
10 | 10 | ||
11 | #ifdef CONFIG_GENERIC_SCHED_CLOCK | 11 | #ifdef CONFIG_GENERIC_SCHED_CLOCK |
12 | extern void sched_clock_postinit(void); | 12 | extern void sched_clock_postinit(void); |
13 | #else | ||
14 | static inline void sched_clock_postinit(void) { } | ||
15 | #endif | ||
16 | 13 | ||
17 | extern void sched_clock_register(u64 (*read)(void), int bits, | 14 | extern void sched_clock_register(u64 (*read)(void), int bits, |
18 | unsigned long rate); | 15 | unsigned long rate); |
16 | #else | ||
17 | static inline void sched_clock_postinit(void) { } | ||
18 | |||
19 | static inline void sched_clock_register(u64 (*read)(void), int bits, | ||
20 | unsigned long rate) | ||
21 | { | ||
22 | ; | ||
23 | } | ||
24 | #endif | ||
19 | 25 | ||
20 | #endif | 26 | #endif |
diff --git a/include/linux/time.h b/include/linux/time.h index beebe3a02d43..297f09f23896 100644 --- a/include/linux/time.h +++ b/include/linux/time.h | |||
@@ -125,6 +125,32 @@ static inline bool timeval_valid(const struct timeval *tv) | |||
125 | 125 | ||
126 | extern struct timespec timespec_trunc(struct timespec t, unsigned gran); | 126 | extern struct timespec timespec_trunc(struct timespec t, unsigned gran); |
127 | 127 | ||
128 | /* | ||
129 | * Validates if a timespec/timeval used to inject a time offset is valid. | ||
130 | * Offsets can be postive or negative. The value of the timeval/timespec | ||
131 | * is the sum of its fields, but *NOTE*: the field tv_usec/tv_nsec must | ||
132 | * always be non-negative. | ||
133 | */ | ||
134 | static inline bool timeval_inject_offset_valid(const struct timeval *tv) | ||
135 | { | ||
136 | /* We don't check the tv_sec as it can be positive or negative */ | ||
137 | |||
138 | /* Can't have more microseconds then a second */ | ||
139 | if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC) | ||
140 | return false; | ||
141 | return true; | ||
142 | } | ||
143 | |||
144 | static inline bool timespec_inject_offset_valid(const struct timespec *ts) | ||
145 | { | ||
146 | /* We don't check the tv_sec as it can be positive or negative */ | ||
147 | |||
148 | /* Can't have more nanoseconds then a second */ | ||
149 | if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC) | ||
150 | return false; | ||
151 | return true; | ||
152 | } | ||
153 | |||
128 | #define CURRENT_TIME (current_kernel_time()) | 154 | #define CURRENT_TIME (current_kernel_time()) |
129 | #define CURRENT_TIME_SEC ((struct timespec) { get_seconds(), 0 }) | 155 | #define CURRENT_TIME_SEC ((struct timespec) { get_seconds(), 0 }) |
130 | 156 | ||
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 7fbba635a549..e840ed867a5d 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -271,11 +271,27 @@ static int alarmtimer_suspend(struct device *dev) | |||
271 | __pm_wakeup_event(ws, MSEC_PER_SEC); | 271 | __pm_wakeup_event(ws, MSEC_PER_SEC); |
272 | return ret; | 272 | return ret; |
273 | } | 273 | } |
274 | |||
275 | static int alarmtimer_resume(struct device *dev) | ||
276 | { | ||
277 | struct rtc_device *rtc; | ||
278 | |||
279 | rtc = alarmtimer_get_rtcdev(); | ||
280 | if (rtc) | ||
281 | rtc_timer_cancel(rtc, &rtctimer); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
274 | #else | 285 | #else |
275 | static int alarmtimer_suspend(struct device *dev) | 286 | static int alarmtimer_suspend(struct device *dev) |
276 | { | 287 | { |
277 | return 0; | 288 | return 0; |
278 | } | 289 | } |
290 | |||
291 | static int alarmtimer_resume(struct device *dev) | ||
292 | { | ||
293 | return 0; | ||
294 | } | ||
279 | #endif | 295 | #endif |
280 | 296 | ||
281 | static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) | 297 | static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) |
@@ -800,6 +816,7 @@ out: | |||
800 | /* Suspend hook structures */ | 816 | /* Suspend hook structures */ |
801 | static const struct dev_pm_ops alarmtimer_pm_ops = { | 817 | static const struct dev_pm_ops alarmtimer_pm_ops = { |
802 | .suspend = alarmtimer_suspend, | 818 | .suspend = alarmtimer_suspend, |
819 | .resume = alarmtimer_resume, | ||
803 | }; | 820 | }; |
804 | 821 | ||
805 | static struct platform_driver alarmtimer_driver = { | 822 | static struct platform_driver alarmtimer_driver = { |
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 1347882d131e..664de539299b 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c | |||
@@ -218,8 +218,8 @@ static void clocksource_watchdog(unsigned long data) | |||
218 | 218 | ||
219 | /* Check the deviation from the watchdog clocksource. */ | 219 | /* Check the deviation from the watchdog clocksource. */ |
220 | if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) { | 220 | if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) { |
221 | pr_warn("timekeeping watchdog: Marking clocksource '%s' as unstable because the skew is too large:\n", | 221 | pr_warn("timekeeping watchdog on CPU%d: Marking clocksource '%s' as unstable because the skew is too large:\n", |
222 | cs->name); | 222 | smp_processor_id(), cs->name); |
223 | pr_warn(" '%s' wd_now: %llx wd_last: %llx mask: %llx\n", | 223 | pr_warn(" '%s' wd_now: %llx wd_last: %llx mask: %llx\n", |
224 | watchdog->name, wdnow, wdlast, watchdog->mask); | 224 | watchdog->name, wdnow, wdlast, watchdog->mask); |
225 | pr_warn(" '%s' cs_now: %llx cs_last: %llx mask: %llx\n", | 225 | pr_warn(" '%s' cs_now: %llx cs_last: %llx mask: %llx\n", |
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 149cc8086aea..36f2ca09aa5e 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -16,8 +16,11 @@ | |||
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/rtc.h> | 18 | #include <linux/rtc.h> |
19 | #include <linux/math64.h> | ||
19 | 20 | ||
20 | #include "ntp_internal.h" | 21 | #include "ntp_internal.h" |
22 | #include "timekeeping_internal.h" | ||
23 | |||
21 | 24 | ||
22 | /* | 25 | /* |
23 | * NTP timekeeping variables: | 26 | * NTP timekeeping variables: |
@@ -70,7 +73,7 @@ static long time_esterror = NTP_PHASE_LIMIT; | |||
70 | static s64 time_freq; | 73 | static s64 time_freq; |
71 | 74 | ||
72 | /* time at last adjustment (secs): */ | 75 | /* time at last adjustment (secs): */ |
73 | static long time_reftime; | 76 | static time64_t time_reftime; |
74 | 77 | ||
75 | static long time_adjust; | 78 | static long time_adjust; |
76 | 79 | ||
@@ -297,25 +300,27 @@ static void ntp_update_offset(long offset) | |||
297 | if (!(time_status & STA_PLL)) | 300 | if (!(time_status & STA_PLL)) |
298 | return; | 301 | return; |
299 | 302 | ||
300 | if (!(time_status & STA_NANO)) | 303 | if (!(time_status & STA_NANO)) { |
304 | /* Make sure the multiplication below won't overflow */ | ||
305 | offset = clamp(offset, -USEC_PER_SEC, USEC_PER_SEC); | ||
301 | offset *= NSEC_PER_USEC; | 306 | offset *= NSEC_PER_USEC; |
307 | } | ||
302 | 308 | ||
303 | /* | 309 | /* |
304 | * Scale the phase adjustment and | 310 | * Scale the phase adjustment and |
305 | * clamp to the operating range. | 311 | * clamp to the operating range. |
306 | */ | 312 | */ |
307 | offset = min(offset, MAXPHASE); | 313 | offset = clamp(offset, -MAXPHASE, MAXPHASE); |
308 | offset = max(offset, -MAXPHASE); | ||
309 | 314 | ||
310 | /* | 315 | /* |
311 | * Select how the frequency is to be controlled | 316 | * Select how the frequency is to be controlled |
312 | * and in which mode (PLL or FLL). | 317 | * and in which mode (PLL or FLL). |
313 | */ | 318 | */ |
314 | secs = get_seconds() - time_reftime; | 319 | secs = (long)(__ktime_get_real_seconds() - time_reftime); |
315 | if (unlikely(time_status & STA_FREQHOLD)) | 320 | if (unlikely(time_status & STA_FREQHOLD)) |
316 | secs = 0; | 321 | secs = 0; |
317 | 322 | ||
318 | time_reftime = get_seconds(); | 323 | time_reftime = __ktime_get_real_seconds(); |
319 | 324 | ||
320 | offset64 = offset; | 325 | offset64 = offset; |
321 | freq_adj = ntp_update_offset_fll(offset64, secs); | 326 | freq_adj = ntp_update_offset_fll(offset64, secs); |
@@ -390,10 +395,11 @@ ktime_t ntp_get_next_leap(void) | |||
390 | * | 395 | * |
391 | * Also handles leap second processing, and returns leap offset | 396 | * Also handles leap second processing, and returns leap offset |
392 | */ | 397 | */ |
393 | int second_overflow(unsigned long secs) | 398 | int second_overflow(time64_t secs) |
394 | { | 399 | { |
395 | s64 delta; | 400 | s64 delta; |
396 | int leap = 0; | 401 | int leap = 0; |
402 | s32 rem; | ||
397 | 403 | ||
398 | /* | 404 | /* |
399 | * Leap second processing. If in leap-insert state at the end of the | 405 | * Leap second processing. If in leap-insert state at the end of the |
@@ -404,19 +410,19 @@ int second_overflow(unsigned long secs) | |||
404 | case TIME_OK: | 410 | case TIME_OK: |
405 | if (time_status & STA_INS) { | 411 | if (time_status & STA_INS) { |
406 | time_state = TIME_INS; | 412 | time_state = TIME_INS; |
407 | ntp_next_leap_sec = secs + SECS_PER_DAY - | 413 | div_s64_rem(secs, SECS_PER_DAY, &rem); |
408 | (secs % SECS_PER_DAY); | 414 | ntp_next_leap_sec = secs + SECS_PER_DAY - rem; |
409 | } else if (time_status & STA_DEL) { | 415 | } else if (time_status & STA_DEL) { |
410 | time_state = TIME_DEL; | 416 | time_state = TIME_DEL; |
411 | ntp_next_leap_sec = secs + SECS_PER_DAY - | 417 | div_s64_rem(secs + 1, SECS_PER_DAY, &rem); |
412 | ((secs+1) % SECS_PER_DAY); | 418 | ntp_next_leap_sec = secs + SECS_PER_DAY - rem; |
413 | } | 419 | } |
414 | break; | 420 | break; |
415 | case TIME_INS: | 421 | case TIME_INS: |
416 | if (!(time_status & STA_INS)) { | 422 | if (!(time_status & STA_INS)) { |
417 | ntp_next_leap_sec = TIME64_MAX; | 423 | ntp_next_leap_sec = TIME64_MAX; |
418 | time_state = TIME_OK; | 424 | time_state = TIME_OK; |
419 | } else if (secs % SECS_PER_DAY == 0) { | 425 | } else if (secs == ntp_next_leap_sec) { |
420 | leap = -1; | 426 | leap = -1; |
421 | time_state = TIME_OOP; | 427 | time_state = TIME_OOP; |
422 | printk(KERN_NOTICE | 428 | printk(KERN_NOTICE |
@@ -427,7 +433,7 @@ int second_overflow(unsigned long secs) | |||
427 | if (!(time_status & STA_DEL)) { | 433 | if (!(time_status & STA_DEL)) { |
428 | ntp_next_leap_sec = TIME64_MAX; | 434 | ntp_next_leap_sec = TIME64_MAX; |
429 | time_state = TIME_OK; | 435 | time_state = TIME_OK; |
430 | } else if ((secs + 1) % SECS_PER_DAY == 0) { | 436 | } else if (secs == ntp_next_leap_sec) { |
431 | leap = 1; | 437 | leap = 1; |
432 | ntp_next_leap_sec = TIME64_MAX; | 438 | ntp_next_leap_sec = TIME64_MAX; |
433 | time_state = TIME_WAIT; | 439 | time_state = TIME_WAIT; |
@@ -590,7 +596,7 @@ static inline void process_adj_status(struct timex *txc, struct timespec64 *ts) | |||
590 | * reference time to current time. | 596 | * reference time to current time. |
591 | */ | 597 | */ |
592 | if (!(time_status & STA_PLL) && (txc->status & STA_PLL)) | 598 | if (!(time_status & STA_PLL) && (txc->status & STA_PLL)) |
593 | time_reftime = get_seconds(); | 599 | time_reftime = __ktime_get_real_seconds(); |
594 | 600 | ||
595 | /* only set allowed bits */ | 601 | /* only set allowed bits */ |
596 | time_status &= STA_RONLY; | 602 | time_status &= STA_RONLY; |
@@ -674,8 +680,14 @@ int ntp_validate_timex(struct timex *txc) | |||
674 | return -EINVAL; | 680 | return -EINVAL; |
675 | } | 681 | } |
676 | 682 | ||
677 | if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME))) | 683 | if (txc->modes & ADJ_SETOFFSET) { |
678 | return -EPERM; | 684 | /* In order to inject time, you gotta be super-user! */ |
685 | if (!capable(CAP_SYS_TIME)) | ||
686 | return -EPERM; | ||
687 | |||
688 | if (!timeval_inject_offset_valid(&txc->time)) | ||
689 | return -EINVAL; | ||
690 | } | ||
679 | 691 | ||
680 | /* | 692 | /* |
681 | * Check for potential multiplication overflows that can | 693 | * Check for potential multiplication overflows that can |
diff --git a/kernel/time/ntp_internal.h b/kernel/time/ntp_internal.h index af924470eac0..d8a7c11fa71a 100644 --- a/kernel/time/ntp_internal.h +++ b/kernel/time/ntp_internal.h | |||
@@ -6,7 +6,7 @@ extern void ntp_clear(void); | |||
6 | /* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */ | 6 | /* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */ |
7 | extern u64 ntp_tick_length(void); | 7 | extern u64 ntp_tick_length(void); |
8 | extern ktime_t ntp_get_next_leap(void); | 8 | extern ktime_t ntp_get_next_leap(void); |
9 | extern int second_overflow(unsigned long secs); | 9 | extern int second_overflow(time64_t secs); |
10 | extern int ntp_validate_timex(struct timex *); | 10 | extern int ntp_validate_timex(struct timex *); |
11 | extern int __do_adjtimex(struct timex *, struct timespec64 *, s32 *); | 11 | extern int __do_adjtimex(struct timex *, struct timespec64 *, s32 *); |
12 | extern void __hardpps(const struct timespec64 *, const struct timespec64 *); | 12 | extern void __hardpps(const struct timespec64 *, const struct timespec64 *); |
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 7c7ec4515983..7ea28ed3109d 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c | |||
@@ -603,15 +603,31 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, | |||
603 | 603 | ||
604 | /* | 604 | /* |
605 | * If the tick is due in the next period, keep it ticking or | 605 | * If the tick is due in the next period, keep it ticking or |
606 | * restart it proper. | 606 | * force prod the timer. |
607 | */ | 607 | */ |
608 | delta = next_tick - basemono; | 608 | delta = next_tick - basemono; |
609 | if (delta <= (u64)TICK_NSEC) { | 609 | if (delta <= (u64)TICK_NSEC) { |
610 | tick.tv64 = 0; | 610 | tick.tv64 = 0; |
611 | /* | ||
612 | * We've not stopped the tick yet, and there's a timer in the | ||
613 | * next period, so no point in stopping it either, bail. | ||
614 | */ | ||
611 | if (!ts->tick_stopped) | 615 | if (!ts->tick_stopped) |
612 | goto out; | 616 | goto out; |
617 | |||
618 | /* | ||
619 | * If, OTOH, we did stop it, but there's a pending (expired) | ||
620 | * timer reprogram the timer hardware to fire now. | ||
621 | * | ||
622 | * We will not restart the tick proper, just prod the timer | ||
623 | * hardware into firing an interrupt to process the pending | ||
624 | * timers. Just like tick_irq_exit() will not restart the tick | ||
625 | * for 'normal' interrupts. | ||
626 | * | ||
627 | * Only once we exit the idle loop will we re-enable the tick, | ||
628 | * see tick_nohz_idle_exit(). | ||
629 | */ | ||
613 | if (delta == 0) { | 630 | if (delta == 0) { |
614 | /* Tick is stopped, but required now. Enforce it */ | ||
615 | tick_nohz_restart(ts, now); | 631 | tick_nohz_restart(ts, now); |
616 | goto out; | 632 | goto out; |
617 | } | 633 | } |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d563c1960302..34b4cedfa80d 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -305,8 +305,7 @@ static inline s64 timekeeping_get_ns(struct tk_read_base *tkr) | |||
305 | 305 | ||
306 | delta = timekeeping_get_delta(tkr); | 306 | delta = timekeeping_get_delta(tkr); |
307 | 307 | ||
308 | nsec = delta * tkr->mult + tkr->xtime_nsec; | 308 | nsec = (delta * tkr->mult + tkr->xtime_nsec) >> tkr->shift; |
309 | nsec >>= tkr->shift; | ||
310 | 309 | ||
311 | /* If arch requires, add in get_arch_timeoffset() */ | 310 | /* If arch requires, add in get_arch_timeoffset() */ |
312 | return nsec + arch_gettimeoffset(); | 311 | return nsec + arch_gettimeoffset(); |
@@ -846,6 +845,19 @@ time64_t ktime_get_real_seconds(void) | |||
846 | } | 845 | } |
847 | EXPORT_SYMBOL_GPL(ktime_get_real_seconds); | 846 | EXPORT_SYMBOL_GPL(ktime_get_real_seconds); |
848 | 847 | ||
848 | /** | ||
849 | * __ktime_get_real_seconds - The same as ktime_get_real_seconds | ||
850 | * but without the sequence counter protect. This internal function | ||
851 | * is called just when timekeeping lock is already held. | ||
852 | */ | ||
853 | time64_t __ktime_get_real_seconds(void) | ||
854 | { | ||
855 | struct timekeeper *tk = &tk_core.timekeeper; | ||
856 | |||
857 | return tk->xtime_sec; | ||
858 | } | ||
859 | |||
860 | |||
849 | #ifdef CONFIG_NTP_PPS | 861 | #ifdef CONFIG_NTP_PPS |
850 | 862 | ||
851 | /** | 863 | /** |
@@ -959,7 +971,7 @@ int timekeeping_inject_offset(struct timespec *ts) | |||
959 | struct timespec64 ts64, tmp; | 971 | struct timespec64 ts64, tmp; |
960 | int ret = 0; | 972 | int ret = 0; |
961 | 973 | ||
962 | if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) | 974 | if (!timespec_inject_offset_valid(ts)) |
963 | return -EINVAL; | 975 | return -EINVAL; |
964 | 976 | ||
965 | ts64 = timespec_to_timespec64(*ts); | 977 | ts64 = timespec_to_timespec64(*ts); |
@@ -1592,9 +1604,12 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk, | |||
1592 | { | 1604 | { |
1593 | s64 interval = tk->cycle_interval; | 1605 | s64 interval = tk->cycle_interval; |
1594 | s64 xinterval = tk->xtime_interval; | 1606 | s64 xinterval = tk->xtime_interval; |
1607 | u32 base = tk->tkr_mono.clock->mult; | ||
1608 | u32 max = tk->tkr_mono.clock->maxadj; | ||
1609 | u32 cur_adj = tk->tkr_mono.mult; | ||
1595 | s64 tick_error; | 1610 | s64 tick_error; |
1596 | bool negative; | 1611 | bool negative; |
1597 | u32 adj; | 1612 | u32 adj_scale; |
1598 | 1613 | ||
1599 | /* Remove any current error adj from freq calculation */ | 1614 | /* Remove any current error adj from freq calculation */ |
1600 | if (tk->ntp_err_mult) | 1615 | if (tk->ntp_err_mult) |
@@ -1613,13 +1628,33 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk, | |||
1613 | /* preserve the direction of correction */ | 1628 | /* preserve the direction of correction */ |
1614 | negative = (tick_error < 0); | 1629 | negative = (tick_error < 0); |
1615 | 1630 | ||
1616 | /* Sort out the magnitude of the correction */ | 1631 | /* If any adjustment would pass the max, just return */ |
1632 | if (negative && (cur_adj - 1) <= (base - max)) | ||
1633 | return; | ||
1634 | if (!negative && (cur_adj + 1) >= (base + max)) | ||
1635 | return; | ||
1636 | /* | ||
1637 | * Sort out the magnitude of the correction, but | ||
1638 | * avoid making so large a correction that we go | ||
1639 | * over the max adjustment. | ||
1640 | */ | ||
1641 | adj_scale = 0; | ||
1617 | tick_error = abs(tick_error); | 1642 | tick_error = abs(tick_error); |
1618 | for (adj = 0; tick_error > interval; adj++) | 1643 | while (tick_error > interval) { |
1644 | u32 adj = 1 << (adj_scale + 1); | ||
1645 | |||
1646 | /* Check if adjustment gets us within 1 unit from the max */ | ||
1647 | if (negative && (cur_adj - adj) <= (base - max)) | ||
1648 | break; | ||
1649 | if (!negative && (cur_adj + adj) >= (base + max)) | ||
1650 | break; | ||
1651 | |||
1652 | adj_scale++; | ||
1619 | tick_error >>= 1; | 1653 | tick_error >>= 1; |
1654 | } | ||
1620 | 1655 | ||
1621 | /* scale the corrections */ | 1656 | /* scale the corrections */ |
1622 | timekeeping_apply_adjustment(tk, offset, negative, adj); | 1657 | timekeeping_apply_adjustment(tk, offset, negative, adj_scale); |
1623 | } | 1658 | } |
1624 | 1659 | ||
1625 | /* | 1660 | /* |
diff --git a/kernel/time/timekeeping_internal.h b/kernel/time/timekeeping_internal.h index 4ea005a7f9da..5be76270ec4a 100644 --- a/kernel/time/timekeeping_internal.h +++ b/kernel/time/timekeeping_internal.h | |||
@@ -17,7 +17,11 @@ static inline cycle_t clocksource_delta(cycle_t now, cycle_t last, cycle_t mask) | |||
17 | { | 17 | { |
18 | cycle_t ret = (now - last) & mask; | 18 | cycle_t ret = (now - last) & mask; |
19 | 19 | ||
20 | return (s64) ret > 0 ? ret : 0; | 20 | /* |
21 | * Prevent time going backwards by checking the MSB of mask in | ||
22 | * the result. If set, return 0. | ||
23 | */ | ||
24 | return ret & ~(mask >> 1) ? 0 : ret; | ||
21 | } | 25 | } |
22 | #else | 26 | #else |
23 | static inline cycle_t clocksource_delta(cycle_t now, cycle_t last, cycle_t mask) | 27 | static inline cycle_t clocksource_delta(cycle_t now, cycle_t last, cycle_t mask) |
@@ -26,4 +30,6 @@ static inline cycle_t clocksource_delta(cycle_t now, cycle_t last, cycle_t mask) | |||
26 | } | 30 | } |
27 | #endif | 31 | #endif |
28 | 32 | ||
33 | extern time64_t __ktime_get_real_seconds(void); | ||
34 | |||
29 | #endif /* _TIMEKEEPING_INTERNAL_H */ | 35 | #endif /* _TIMEKEEPING_INTERNAL_H */ |
diff --git a/tools/testing/selftests/timers/clocksource-switch.c b/tools/testing/selftests/timers/clocksource-switch.c index 627ec7425f78..fd88e3025bed 100644 --- a/tools/testing/selftests/timers/clocksource-switch.c +++ b/tools/testing/selftests/timers/clocksource-switch.c | |||
@@ -97,7 +97,7 @@ int get_cur_clocksource(char *buf, size_t size) | |||
97 | int change_clocksource(char *clocksource) | 97 | int change_clocksource(char *clocksource) |
98 | { | 98 | { |
99 | int fd; | 99 | int fd; |
100 | size_t size; | 100 | ssize_t size; |
101 | 101 | ||
102 | fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_WRONLY); | 102 | fd = open("/sys/devices/system/clocksource/clocksource0/current_clocksource", O_WRONLY); |
103 | 103 | ||