diff options
author | Olof Johansson <olof@lixom.net> | 2014-12-05 02:32:16 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2014-12-05 02:32:16 -0500 |
commit | 6b34df9e30c8b596f9d0173ca17714076474458e (patch) | |
tree | a47b26e4ebb4d0aea10b3abbb620efa2a004ba8c | |
parent | e58e501a9b3e0db722263b02d6c06f1656a5dee7 (diff) | |
parent | 65b5732d241b8b39e07653794eefffd0d8028cbb (diff) |
Merge branch 'clocksource/physical-timers' into next/drivers
* clocksource/physical-timers:
clocksource: arch_timer: Allow the device tree to specify uninitialized timer registers
clocksource: arch_timer: Fix code to use physical timers when requested
-rw-r--r-- | Documentation/devicetree/bindings/arm/arch_timer.txt | 8 | ||||
-rw-r--r-- | arch/arm/include/asm/arch_timer.h | 9 | ||||
-rw-r--r-- | arch/arm64/include/asm/arch_timer.h | 9 | ||||
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 13 |
4 files changed, 38 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt index 37b2cafa4e52..256b4d8bab7b 100644 --- a/Documentation/devicetree/bindings/arm/arch_timer.txt +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt | |||
@@ -22,6 +22,14 @@ to deliver its interrupts via SPIs. | |||
22 | - always-on : a boolean property. If present, the timer is powered through an | 22 | - always-on : a boolean property. If present, the timer is powered through an |
23 | always-on power domain, therefore it never loses context. | 23 | always-on power domain, therefore it never loses context. |
24 | 24 | ||
25 | ** Optional properties: | ||
26 | |||
27 | - arm,cpu-registers-not-fw-configured : Firmware does not initialize | ||
28 | any of the generic timer CPU registers, which contain their | ||
29 | architecturally-defined reset values. Only supported for 32-bit | ||
30 | systems which follow the ARMv7 architected reset values. | ||
31 | |||
32 | |||
25 | Example: | 33 | Example: |
26 | 34 | ||
27 | timer { | 35 | timer { |
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index 92793ba69c40..d4ebf5679f1f 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h | |||
@@ -78,6 +78,15 @@ static inline u32 arch_timer_get_cntfrq(void) | |||
78 | return val; | 78 | return val; |
79 | } | 79 | } |
80 | 80 | ||
81 | static inline u64 arch_counter_get_cntpct(void) | ||
82 | { | ||
83 | u64 cval; | ||
84 | |||
85 | isb(); | ||
86 | asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); | ||
87 | return cval; | ||
88 | } | ||
89 | |||
81 | static inline u64 arch_counter_get_cntvct(void) | 90 | static inline u64 arch_counter_get_cntvct(void) |
82 | { | 91 | { |
83 | u64 cval; | 92 | u64 cval; |
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index f19097134b02..b1fa4e614718 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h | |||
@@ -104,6 +104,15 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl) | |||
104 | asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); | 104 | asm volatile("msr cntkctl_el1, %0" : : "r" (cntkctl)); |
105 | } | 105 | } |
106 | 106 | ||
107 | static inline u64 arch_counter_get_cntpct(void) | ||
108 | { | ||
109 | /* | ||
110 | * AArch64 kernel and user space mandate the use of CNTVCT. | ||
111 | */ | ||
112 | BUG(); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
107 | static inline u64 arch_counter_get_cntvct(void) | 116 | static inline u64 arch_counter_get_cntvct(void) |
108 | { | 117 | { |
109 | u64 cval; | 118 | u64 cval; |
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 43005d4d3348..6a79fc4f900c 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -462,7 +462,10 @@ static void __init arch_counter_register(unsigned type) | |||
462 | 462 | ||
463 | /* Register the CP15 based counter if we have one */ | 463 | /* Register the CP15 based counter if we have one */ |
464 | if (type & ARCH_CP15_TIMER) { | 464 | if (type & ARCH_CP15_TIMER) { |
465 | arch_timer_read_counter = arch_counter_get_cntvct; | 465 | if (arch_timer_use_virtual) |
466 | arch_timer_read_counter = arch_counter_get_cntvct; | ||
467 | else | ||
468 | arch_timer_read_counter = arch_counter_get_cntpct; | ||
466 | } else { | 469 | } else { |
467 | arch_timer_read_counter = arch_counter_get_cntvct_mem; | 470 | arch_timer_read_counter = arch_counter_get_cntvct_mem; |
468 | 471 | ||
@@ -702,6 +705,14 @@ static void __init arch_timer_init(struct device_node *np) | |||
702 | arch_timer_detect_rate(NULL, np); | 705 | arch_timer_detect_rate(NULL, np); |
703 | 706 | ||
704 | /* | 707 | /* |
708 | * If we cannot rely on firmware initializing the timer registers then | ||
709 | * we should use the physical timers instead. | ||
710 | */ | ||
711 | if (IS_ENABLED(CONFIG_ARM) && | ||
712 | of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) | ||
713 | arch_timer_use_virtual = false; | ||
714 | |||
715 | /* | ||
705 | * If HYP mode is available, we know that the physical timer | 716 | * If HYP mode is available, we know that the physical timer |
706 | * has been configured to be accessible from PL1. Use it, so | 717 | * has been configured to be accessible from PL1. Use it, so |
707 | * that a guest can use the virtual timer instead. | 718 | * that a guest can use the virtual timer instead. |