aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/arm_arch_timer.c
diff options
context:
space:
mode:
authorRobin Murphy <robin.murphy@arm.com>2016-02-01 07:00:48 -0500
committerDaniel Lezcano <daniel.lezcano@linaro.org>2016-02-25 08:30:15 -0500
commite392d603f61767cb2de4d82bb55a035918f8342c (patch)
tree1051148f6bec4a0bea199d2302858621a9ce9c5d /drivers/clocksource/arm_arch_timer.c
parentbbf66d897adf2bb0c310db96c97e8db6369f39e1 (diff)
clocksource/drivers/arm_arch_timer: Enable and verify MMIO access
So far, we have been blindly assuming that having access to a memory-mapped timer frame implies that the individual elements of that frame frame are already enabled. Whilst it's the firmware's job to give us non-secure access to frames in the first place, we should not rely on implementations always being generous enough to also configure CNTACR for those non-secure frames (e.g. [1]). Explicitly enable feature-level access per-frame, and verify that the access we want is really implemented before trying to make use of it. [1]:https://github.com/ARM-software/tf-issues/issues/170 Acked-by: Mark Rutland <mark.rutland@arm.com> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Tested-by: Stephen Boyd <sboyd@codeaurora.org> Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r--drivers/clocksource/arm_arch_timer.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index c64d543d64bf..7c567f0c87f5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -32,6 +32,14 @@
32#define CNTTIDR 0x08 32#define CNTTIDR 0x08
33#define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4)) 33#define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4))
34 34
35#define CNTACR(n) (0x40 + ((n) * 4))
36#define CNTACR_RPCT BIT(0)
37#define CNTACR_RVCT BIT(1)
38#define CNTACR_RFRQ BIT(2)
39#define CNTACR_RVOFF BIT(3)
40#define CNTACR_RWVT BIT(4)
41#define CNTACR_RWPT BIT(5)
42
35#define CNTVCT_LO 0x08 43#define CNTVCT_LO 0x08
36#define CNTVCT_HI 0x0c 44#define CNTVCT_HI 0x0c
37#define CNTFRQ 0x10 45#define CNTFRQ 0x10
@@ -757,7 +765,6 @@ static void __init arch_timer_mem_init(struct device_node *np)
757 } 765 }
758 766
759 cnttidr = readl_relaxed(cntctlbase + CNTTIDR); 767 cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
760 iounmap(cntctlbase);
761 768
762 /* 769 /*
763 * Try to find a virtual capable frame. Otherwise fall back to a 770 * Try to find a virtual capable frame. Otherwise fall back to a
@@ -765,20 +772,31 @@ static void __init arch_timer_mem_init(struct device_node *np)
765 */ 772 */
766 for_each_available_child_of_node(np, frame) { 773 for_each_available_child_of_node(np, frame) {
767 int n; 774 int n;
775 u32 cntacr;
768 776
769 if (of_property_read_u32(frame, "frame-number", &n)) { 777 if (of_property_read_u32(frame, "frame-number", &n)) {
770 pr_err("arch_timer: Missing frame-number\n"); 778 pr_err("arch_timer: Missing frame-number\n");
771 of_node_put(best_frame);
772 of_node_put(frame); 779 of_node_put(frame);
773 return; 780 goto out;
774 } 781 }
775 782
776 if (cnttidr & CNTTIDR_VIRT(n)) { 783 /* Try enabling everything, and see what sticks */
784 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
785 CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
786 writel_relaxed(cntacr, cntctlbase + CNTACR(n));
787 cntacr = readl_relaxed(cntctlbase + CNTACR(n));
788
789 if ((cnttidr & CNTTIDR_VIRT(n)) &&
790 !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) {
777 of_node_put(best_frame); 791 of_node_put(best_frame);
778 best_frame = frame; 792 best_frame = frame;
779 arch_timer_mem_use_virtual = true; 793 arch_timer_mem_use_virtual = true;
780 break; 794 break;
781 } 795 }
796
797 if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT))
798 continue;
799
782 of_node_put(best_frame); 800 of_node_put(best_frame);
783 best_frame = of_node_get(frame); 801 best_frame = of_node_get(frame);
784 } 802 }
@@ -786,24 +804,26 @@ static void __init arch_timer_mem_init(struct device_node *np)
786 base = arch_counter_base = of_iomap(best_frame, 0); 804 base = arch_counter_base = of_iomap(best_frame, 0);
787 if (!base) { 805 if (!base) {
788 pr_err("arch_timer: Can't map frame's registers\n"); 806 pr_err("arch_timer: Can't map frame's registers\n");
789 of_node_put(best_frame); 807 goto out;
790 return;
791 } 808 }
792 809
793 if (arch_timer_mem_use_virtual) 810 if (arch_timer_mem_use_virtual)
794 irq = irq_of_parse_and_map(best_frame, 1); 811 irq = irq_of_parse_and_map(best_frame, 1);
795 else 812 else
796 irq = irq_of_parse_and_map(best_frame, 0); 813 irq = irq_of_parse_and_map(best_frame, 0);
797 of_node_put(best_frame); 814
798 if (!irq) { 815 if (!irq) {
799 pr_err("arch_timer: Frame missing %s irq", 816 pr_err("arch_timer: Frame missing %s irq",
800 arch_timer_mem_use_virtual ? "virt" : "phys"); 817 arch_timer_mem_use_virtual ? "virt" : "phys");
801 return; 818 goto out;
802 } 819 }
803 820
804 arch_timer_detect_rate(base, np); 821 arch_timer_detect_rate(base, np);
805 arch_timer_mem_register(base, irq); 822 arch_timer_mem_register(base, irq);
806 arch_timer_common_init(); 823 arch_timer_common_init();
824out:
825 iounmap(cntctlbase);
826 of_node_put(best_frame);
807} 827}
808CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", 828CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
809 arch_timer_mem_init); 829 arch_timer_mem_init);