18a4da6e3SMark Rutland /* 28a4da6e3SMark Rutland * linux/drivers/clocksource/arm_arch_timer.c 38a4da6e3SMark Rutland * 48a4da6e3SMark Rutland * Copyright (C) 2011 ARM Ltd. 58a4da6e3SMark Rutland * All Rights Reserved 68a4da6e3SMark Rutland * 78a4da6e3SMark Rutland * This program is free software; you can redistribute it and/or modify 88a4da6e3SMark Rutland * it under the terms of the GNU General Public License version 2 as 98a4da6e3SMark Rutland * published by the Free Software Foundation. 108a4da6e3SMark Rutland */ 11f005bd7eSMarc Zyngier 12f005bd7eSMarc Zyngier #define pr_fmt(fmt) "arm_arch_timer: " fmt 13f005bd7eSMarc Zyngier 148a4da6e3SMark Rutland #include <linux/init.h> 158a4da6e3SMark Rutland #include <linux/kernel.h> 168a4da6e3SMark Rutland #include <linux/device.h> 178a4da6e3SMark Rutland #include <linux/smp.h> 188a4da6e3SMark Rutland #include <linux/cpu.h> 19346e7480SSudeep KarkadaNagesha #include <linux/cpu_pm.h> 208a4da6e3SMark Rutland #include <linux/clockchips.h> 217c8f1e78SRichard Cochran #include <linux/clocksource.h> 228a4da6e3SMark Rutland #include <linux/interrupt.h> 238a4da6e3SMark Rutland #include <linux/of_irq.h> 2422006994SStephen Boyd #include <linux/of_address.h> 258a4da6e3SMark Rutland #include <linux/io.h> 2622006994SStephen Boyd #include <linux/slab.h> 27e6017571SIngo Molnar #include <linux/sched/clock.h> 2865cd4f6cSStephen Boyd #include <linux/sched_clock.h> 29b09ca1ecSHanjun Guo #include <linux/acpi.h> 308a4da6e3SMark Rutland 318a4da6e3SMark Rutland #include <asm/arch_timer.h> 328266891eSMarc Zyngier #include <asm/virt.h> 338a4da6e3SMark Rutland 348a4da6e3SMark Rutland #include <clocksource/arm_arch_timer.h> 358a4da6e3SMark Rutland 3622006994SStephen Boyd #define CNTTIDR 0x08 3722006994SStephen Boyd #define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4)) 3822006994SStephen Boyd 39e392d603SRobin Murphy #define CNTACR(n) (0x40 + ((n) * 4)) 40e392d603SRobin Murphy #define CNTACR_RPCT BIT(0) 41e392d603SRobin Murphy #define CNTACR_RVCT BIT(1) 42e392d603SRobin Murphy #define CNTACR_RFRQ BIT(2) 43e392d603SRobin Murphy #define CNTACR_RVOFF BIT(3) 44e392d603SRobin Murphy #define CNTACR_RWVT BIT(4) 45e392d603SRobin Murphy #define CNTACR_RWPT BIT(5) 46e392d603SRobin Murphy 4722006994SStephen Boyd #define CNTVCT_LO 0x08 4822006994SStephen Boyd #define CNTVCT_HI 0x0c 4922006994SStephen Boyd #define CNTFRQ 0x10 5022006994SStephen Boyd #define CNTP_TVAL 0x28 5122006994SStephen Boyd #define CNTP_CTL 0x2c 5222006994SStephen Boyd #define CNTV_TVAL 0x38 5322006994SStephen Boyd #define CNTV_CTL 0x3c 5422006994SStephen Boyd 5522006994SStephen Boyd #define ARCH_CP15_TIMER BIT(0) 5622006994SStephen Boyd #define ARCH_MEM_TIMER BIT(1) 5722006994SStephen Boyd static unsigned arch_timers_present __initdata; 5822006994SStephen Boyd 5922006994SStephen Boyd static void __iomem *arch_counter_base; 6022006994SStephen Boyd 6122006994SStephen Boyd struct arch_timer { 6222006994SStephen Boyd void __iomem *base; 6322006994SStephen Boyd struct clock_event_device evt; 6422006994SStephen Boyd }; 6522006994SStephen Boyd 6622006994SStephen Boyd #define to_arch_timer(e) container_of(e, struct arch_timer, evt) 6722006994SStephen Boyd 688a4da6e3SMark Rutland static u32 arch_timer_rate; 698a4da6e3SMark Rutland 708a4da6e3SMark Rutland enum ppi_nr { 718a4da6e3SMark Rutland PHYS_SECURE_PPI, 728a4da6e3SMark Rutland PHYS_NONSECURE_PPI, 738a4da6e3SMark Rutland VIRT_PPI, 748a4da6e3SMark Rutland HYP_PPI, 758a4da6e3SMark Rutland MAX_TIMER_PPI 768a4da6e3SMark Rutland }; 778a4da6e3SMark Rutland 788a4da6e3SMark Rutland static int arch_timer_ppi[MAX_TIMER_PPI]; 798a4da6e3SMark Rutland 808a4da6e3SMark Rutland static struct clock_event_device __percpu *arch_timer_evt; 818a4da6e3SMark Rutland 82f81f03faSMarc Zyngier static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI; 8382a56194SLorenzo Pieralisi static bool arch_timer_c3stop; 8422006994SStephen Boyd static bool arch_timer_mem_use_virtual; 85d8ec7595SBrian Norris static bool arch_counter_suspend_stop; 868a4da6e3SMark Rutland 8746fd5c6bSWill Deacon static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); 8846fd5c6bSWill Deacon 8946fd5c6bSWill Deacon static int __init early_evtstrm_cfg(char *buf) 9046fd5c6bSWill Deacon { 9146fd5c6bSWill Deacon return strtobool(buf, &evtstrm_enable); 9246fd5c6bSWill Deacon } 9346fd5c6bSWill Deacon early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg); 9446fd5c6bSWill Deacon 958a4da6e3SMark Rutland /* 968a4da6e3SMark Rutland * Architected system timer support. 978a4da6e3SMark Rutland */ 988a4da6e3SMark Rutland 99*f4e00a1aSMarc Zyngier static __always_inline 100*f4e00a1aSMarc Zyngier void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val, 101*f4e00a1aSMarc Zyngier struct clock_event_device *clk) 102*f4e00a1aSMarc Zyngier { 103*f4e00a1aSMarc Zyngier if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { 104*f4e00a1aSMarc Zyngier struct arch_timer *timer = to_arch_timer(clk); 105*f4e00a1aSMarc Zyngier switch (reg) { 106*f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_CTRL: 107*f4e00a1aSMarc Zyngier writel_relaxed(val, timer->base + CNTP_CTL); 108*f4e00a1aSMarc Zyngier break; 109*f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_TVAL: 110*f4e00a1aSMarc Zyngier writel_relaxed(val, timer->base + CNTP_TVAL); 111*f4e00a1aSMarc Zyngier break; 112*f4e00a1aSMarc Zyngier } 113*f4e00a1aSMarc Zyngier } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { 114*f4e00a1aSMarc Zyngier struct arch_timer *timer = to_arch_timer(clk); 115*f4e00a1aSMarc Zyngier switch (reg) { 116*f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_CTRL: 117*f4e00a1aSMarc Zyngier writel_relaxed(val, timer->base + CNTV_CTL); 118*f4e00a1aSMarc Zyngier break; 119*f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_TVAL: 120*f4e00a1aSMarc Zyngier writel_relaxed(val, timer->base + CNTV_TVAL); 121*f4e00a1aSMarc Zyngier break; 122*f4e00a1aSMarc Zyngier } 123*f4e00a1aSMarc Zyngier } else { 124*f4e00a1aSMarc Zyngier arch_timer_reg_write_cp15(access, reg, val); 125*f4e00a1aSMarc Zyngier } 126*f4e00a1aSMarc Zyngier } 127*f4e00a1aSMarc Zyngier 128*f4e00a1aSMarc Zyngier static __always_inline 129*f4e00a1aSMarc Zyngier u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, 130*f4e00a1aSMarc Zyngier struct clock_event_device *clk) 131*f4e00a1aSMarc Zyngier { 132*f4e00a1aSMarc Zyngier u32 val; 133*f4e00a1aSMarc Zyngier 134*f4e00a1aSMarc Zyngier if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { 135*f4e00a1aSMarc Zyngier struct arch_timer *timer = to_arch_timer(clk); 136*f4e00a1aSMarc Zyngier switch (reg) { 137*f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_CTRL: 138*f4e00a1aSMarc Zyngier val = readl_relaxed(timer->base + CNTP_CTL); 139*f4e00a1aSMarc Zyngier break; 140*f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_TVAL: 141*f4e00a1aSMarc Zyngier val = readl_relaxed(timer->base + CNTP_TVAL); 142*f4e00a1aSMarc Zyngier break; 143*f4e00a1aSMarc Zyngier } 144*f4e00a1aSMarc Zyngier } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { 145*f4e00a1aSMarc Zyngier struct arch_timer *timer = to_arch_timer(clk); 146*f4e00a1aSMarc Zyngier switch (reg) { 147*f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_CTRL: 148*f4e00a1aSMarc Zyngier val = readl_relaxed(timer->base + CNTV_CTL); 149*f4e00a1aSMarc Zyngier break; 150*f4e00a1aSMarc Zyngier case ARCH_TIMER_REG_TVAL: 151*f4e00a1aSMarc Zyngier val = readl_relaxed(timer->base + CNTV_TVAL); 152*f4e00a1aSMarc Zyngier break; 153*f4e00a1aSMarc Zyngier } 154*f4e00a1aSMarc Zyngier } else { 155*f4e00a1aSMarc Zyngier val = arch_timer_reg_read_cp15(access, reg); 156*f4e00a1aSMarc Zyngier } 157*f4e00a1aSMarc Zyngier 158*f4e00a1aSMarc Zyngier return val; 159*f4e00a1aSMarc Zyngier } 160*f4e00a1aSMarc Zyngier 161f6dc1576SScott Wood #ifdef CONFIG_FSL_ERRATUM_A008585 16216d10ef2SDing Tianhong /* 16316d10ef2SDing Tianhong * The number of retries is an arbitrary value well beyond the highest number 16416d10ef2SDing Tianhong * of iterations the loop has been observed to take. 16516d10ef2SDing Tianhong */ 16616d10ef2SDing Tianhong #define __fsl_a008585_read_reg(reg) ({ \ 16716d10ef2SDing Tianhong u64 _old, _new; \ 16816d10ef2SDing Tianhong int _retries = 200; \ 16916d10ef2SDing Tianhong \ 17016d10ef2SDing Tianhong do { \ 17116d10ef2SDing Tianhong _old = read_sysreg(reg); \ 17216d10ef2SDing Tianhong _new = read_sysreg(reg); \ 17316d10ef2SDing Tianhong _retries--; \ 17416d10ef2SDing Tianhong } while (unlikely(_old != _new) && _retries); \ 17516d10ef2SDing Tianhong \ 17616d10ef2SDing Tianhong WARN_ON_ONCE(!_retries); \ 17716d10ef2SDing Tianhong _new; \ 17816d10ef2SDing Tianhong }) 179f6dc1576SScott Wood 18016d10ef2SDing Tianhong static u32 notrace fsl_a008585_read_cntp_tval_el0(void) 181f6dc1576SScott Wood { 182f6dc1576SScott Wood return __fsl_a008585_read_reg(cntp_tval_el0); 183f6dc1576SScott Wood } 184f6dc1576SScott Wood 18516d10ef2SDing Tianhong static u32 notrace fsl_a008585_read_cntv_tval_el0(void) 186f6dc1576SScott Wood { 187f6dc1576SScott Wood return __fsl_a008585_read_reg(cntv_tval_el0); 188f6dc1576SScott Wood } 189f6dc1576SScott Wood 19016d10ef2SDing Tianhong static u64 notrace fsl_a008585_read_cntvct_el0(void) 191f6dc1576SScott Wood { 192f6dc1576SScott Wood return __fsl_a008585_read_reg(cntvct_el0); 193f6dc1576SScott Wood } 19416d10ef2SDing Tianhong #endif 19516d10ef2SDing Tianhong 196bb42ca47SDing Tianhong #ifdef CONFIG_HISILICON_ERRATUM_161010101 197bb42ca47SDing Tianhong /* 198bb42ca47SDing Tianhong * Verify whether the value of the second read is larger than the first by 199bb42ca47SDing Tianhong * less than 32 is the only way to confirm the value is correct, so clear the 200bb42ca47SDing Tianhong * lower 5 bits to check whether the difference is greater than 32 or not. 201bb42ca47SDing Tianhong * Theoretically the erratum should not occur more than twice in succession 202bb42ca47SDing Tianhong * when reading the system counter, but it is possible that some interrupts 203bb42ca47SDing Tianhong * may lead to more than twice read errors, triggering the warning, so setting 204bb42ca47SDing Tianhong * the number of retries far beyond the number of iterations the loop has been 205bb42ca47SDing Tianhong * observed to take. 206bb42ca47SDing Tianhong */ 207bb42ca47SDing Tianhong #define __hisi_161010101_read_reg(reg) ({ \ 208bb42ca47SDing Tianhong u64 _old, _new; \ 209bb42ca47SDing Tianhong int _retries = 50; \ 210bb42ca47SDing Tianhong \ 211bb42ca47SDing Tianhong do { \ 212bb42ca47SDing Tianhong _old = read_sysreg(reg); \ 213bb42ca47SDing Tianhong _new = read_sysreg(reg); \ 214bb42ca47SDing Tianhong _retries--; \ 215bb42ca47SDing Tianhong } while (unlikely((_new - _old) >> 5) && _retries); \ 216bb42ca47SDing Tianhong \ 217bb42ca47SDing Tianhong WARN_ON_ONCE(!_retries); \ 218bb42ca47SDing Tianhong _new; \ 219bb42ca47SDing Tianhong }) 220bb42ca47SDing Tianhong 221bb42ca47SDing Tianhong static u32 notrace hisi_161010101_read_cntp_tval_el0(void) 222bb42ca47SDing Tianhong { 223bb42ca47SDing Tianhong return __hisi_161010101_read_reg(cntp_tval_el0); 224bb42ca47SDing Tianhong } 225bb42ca47SDing Tianhong 226bb42ca47SDing Tianhong static u32 notrace hisi_161010101_read_cntv_tval_el0(void) 227bb42ca47SDing Tianhong { 228bb42ca47SDing Tianhong return __hisi_161010101_read_reg(cntv_tval_el0); 229bb42ca47SDing Tianhong } 230bb42ca47SDing Tianhong 231bb42ca47SDing Tianhong static u64 notrace hisi_161010101_read_cntvct_el0(void) 232bb42ca47SDing Tianhong { 233bb42ca47SDing Tianhong return __hisi_161010101_read_reg(cntvct_el0); 234bb42ca47SDing Tianhong } 235bb42ca47SDing Tianhong #endif 236bb42ca47SDing Tianhong 23716d10ef2SDing Tianhong #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND 23816d10ef2SDing Tianhong const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL; 23916d10ef2SDing Tianhong EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); 24016d10ef2SDing Tianhong 24116d10ef2SDing Tianhong DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled); 24216d10ef2SDing Tianhong EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled); 24316d10ef2SDing Tianhong 24416d10ef2SDing Tianhong static const struct arch_timer_erratum_workaround ool_workarounds[] = { 24516d10ef2SDing Tianhong #ifdef CONFIG_FSL_ERRATUM_A008585 24616d10ef2SDing Tianhong { 247651bb2e9SMarc Zyngier .match_type = ate_match_dt, 24816d10ef2SDing Tianhong .id = "fsl,erratum-a008585", 249651bb2e9SMarc Zyngier .desc = "Freescale erratum a005858", 25016d10ef2SDing Tianhong .read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0, 25116d10ef2SDing Tianhong .read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0, 25216d10ef2SDing Tianhong .read_cntvct_el0 = fsl_a008585_read_cntvct_el0, 25316d10ef2SDing Tianhong }, 25416d10ef2SDing Tianhong #endif 255bb42ca47SDing Tianhong #ifdef CONFIG_HISILICON_ERRATUM_161010101 256bb42ca47SDing Tianhong { 257651bb2e9SMarc Zyngier .match_type = ate_match_dt, 258bb42ca47SDing Tianhong .id = "hisilicon,erratum-161010101", 259651bb2e9SMarc Zyngier .desc = "HiSilicon erratum 161010101", 260bb42ca47SDing Tianhong .read_cntp_tval_el0 = hisi_161010101_read_cntp_tval_el0, 261bb42ca47SDing Tianhong .read_cntv_tval_el0 = hisi_161010101_read_cntv_tval_el0, 262bb42ca47SDing Tianhong .read_cntvct_el0 = hisi_161010101_read_cntvct_el0, 263bb42ca47SDing Tianhong }, 264bb42ca47SDing Tianhong #endif 26516d10ef2SDing Tianhong }; 266651bb2e9SMarc Zyngier 267651bb2e9SMarc Zyngier typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *, 268651bb2e9SMarc Zyngier const void *); 269651bb2e9SMarc Zyngier 270651bb2e9SMarc Zyngier static 271651bb2e9SMarc Zyngier bool arch_timer_check_dt_erratum(const struct arch_timer_erratum_workaround *wa, 272651bb2e9SMarc Zyngier const void *arg) 273651bb2e9SMarc Zyngier { 274651bb2e9SMarc Zyngier const struct device_node *np = arg; 275651bb2e9SMarc Zyngier 276651bb2e9SMarc Zyngier return of_property_read_bool(np, wa->id); 277651bb2e9SMarc Zyngier } 278651bb2e9SMarc Zyngier 2790064030cSMarc Zyngier static 2800064030cSMarc Zyngier bool arch_timer_check_local_cap_erratum(const struct arch_timer_erratum_workaround *wa, 2810064030cSMarc Zyngier const void *arg) 2820064030cSMarc Zyngier { 2830064030cSMarc Zyngier return this_cpu_has_cap((uintptr_t)wa->id); 2840064030cSMarc Zyngier } 2850064030cSMarc Zyngier 286651bb2e9SMarc Zyngier static const struct arch_timer_erratum_workaround * 287651bb2e9SMarc Zyngier arch_timer_iterate_errata(enum arch_timer_erratum_match_type type, 288651bb2e9SMarc Zyngier ate_match_fn_t match_fn, 289651bb2e9SMarc Zyngier void *arg) 290651bb2e9SMarc Zyngier { 291651bb2e9SMarc Zyngier int i; 292651bb2e9SMarc Zyngier 293651bb2e9SMarc Zyngier for (i = 0; i < ARRAY_SIZE(ool_workarounds); i++) { 294651bb2e9SMarc Zyngier if (ool_workarounds[i].match_type != type) 295651bb2e9SMarc Zyngier continue; 296651bb2e9SMarc Zyngier 297651bb2e9SMarc Zyngier if (match_fn(&ool_workarounds[i], arg)) 298651bb2e9SMarc Zyngier return &ool_workarounds[i]; 299651bb2e9SMarc Zyngier } 300651bb2e9SMarc Zyngier 301651bb2e9SMarc Zyngier return NULL; 302651bb2e9SMarc Zyngier } 303651bb2e9SMarc Zyngier 304651bb2e9SMarc Zyngier static 305651bb2e9SMarc Zyngier void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa) 306651bb2e9SMarc Zyngier { 307651bb2e9SMarc Zyngier timer_unstable_counter_workaround = wa; 308651bb2e9SMarc Zyngier static_branch_enable(&arch_timer_read_ool_enabled); 309651bb2e9SMarc Zyngier } 310651bb2e9SMarc Zyngier 311651bb2e9SMarc Zyngier static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type, 312651bb2e9SMarc Zyngier void *arg) 313651bb2e9SMarc Zyngier { 314651bb2e9SMarc Zyngier const struct arch_timer_erratum_workaround *wa; 315651bb2e9SMarc Zyngier ate_match_fn_t match_fn = NULL; 3160064030cSMarc Zyngier bool local = false; 317651bb2e9SMarc Zyngier 318651bb2e9SMarc Zyngier switch (type) { 319651bb2e9SMarc Zyngier case ate_match_dt: 320651bb2e9SMarc Zyngier match_fn = arch_timer_check_dt_erratum; 321651bb2e9SMarc Zyngier break; 3220064030cSMarc Zyngier case ate_match_local_cap_id: 3230064030cSMarc Zyngier match_fn = arch_timer_check_local_cap_erratum; 3240064030cSMarc Zyngier local = true; 3250064030cSMarc Zyngier break; 326651bb2e9SMarc Zyngier default: 327651bb2e9SMarc Zyngier WARN_ON(1); 328651bb2e9SMarc Zyngier return; 329651bb2e9SMarc Zyngier } 330651bb2e9SMarc Zyngier 331651bb2e9SMarc Zyngier wa = arch_timer_iterate_errata(type, match_fn, arg); 332651bb2e9SMarc Zyngier if (!wa) 333651bb2e9SMarc Zyngier return; 334651bb2e9SMarc Zyngier 3350064030cSMarc Zyngier if (needs_unstable_timer_counter_workaround()) { 3360064030cSMarc Zyngier if (wa != timer_unstable_counter_workaround) 3370064030cSMarc Zyngier pr_warn("Can't enable workaround for %s (clashes with %s\n)", 3380064030cSMarc Zyngier wa->desc, 3390064030cSMarc Zyngier timer_unstable_counter_workaround->desc); 3400064030cSMarc Zyngier return; 3410064030cSMarc Zyngier } 3420064030cSMarc Zyngier 343651bb2e9SMarc Zyngier arch_timer_enable_workaround(wa); 3440064030cSMarc Zyngier pr_info("Enabling %s workaround for %s\n", 3450064030cSMarc Zyngier local ? "local" : "global", wa->desc); 346651bb2e9SMarc Zyngier } 347651bb2e9SMarc Zyngier 348651bb2e9SMarc Zyngier #else 349651bb2e9SMarc Zyngier #define arch_timer_check_ool_workaround(t,a) do { } while(0) 35016d10ef2SDing Tianhong #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ 351f6dc1576SScott Wood 352e09f3cc0SStephen Boyd static __always_inline irqreturn_t timer_handler(const int access, 3538a4da6e3SMark Rutland struct clock_event_device *evt) 3548a4da6e3SMark Rutland { 3558a4da6e3SMark Rutland unsigned long ctrl; 356cfb6d656SThomas Gleixner 35760faddf6SStephen Boyd ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, evt); 3588a4da6e3SMark Rutland if (ctrl & ARCH_TIMER_CTRL_IT_STAT) { 3598a4da6e3SMark Rutland ctrl |= ARCH_TIMER_CTRL_IT_MASK; 36060faddf6SStephen Boyd arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, evt); 3618a4da6e3SMark Rutland evt->event_handler(evt); 3628a4da6e3SMark Rutland return IRQ_HANDLED; 3638a4da6e3SMark Rutland } 3648a4da6e3SMark Rutland 3658a4da6e3SMark Rutland return IRQ_NONE; 3668a4da6e3SMark Rutland } 3678a4da6e3SMark Rutland 3688a4da6e3SMark Rutland static irqreturn_t arch_timer_handler_virt(int irq, void *dev_id) 3698a4da6e3SMark Rutland { 3708a4da6e3SMark Rutland struct clock_event_device *evt = dev_id; 3718a4da6e3SMark Rutland 3728a4da6e3SMark Rutland return timer_handler(ARCH_TIMER_VIRT_ACCESS, evt); 3738a4da6e3SMark Rutland } 3748a4da6e3SMark Rutland 3758a4da6e3SMark Rutland static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id) 3768a4da6e3SMark Rutland { 3778a4da6e3SMark Rutland struct clock_event_device *evt = dev_id; 3788a4da6e3SMark Rutland 3798a4da6e3SMark Rutland return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt); 3808a4da6e3SMark Rutland } 3818a4da6e3SMark Rutland 38222006994SStephen Boyd static irqreturn_t arch_timer_handler_phys_mem(int irq, void *dev_id) 38322006994SStephen Boyd { 38422006994SStephen Boyd struct clock_event_device *evt = dev_id; 38522006994SStephen Boyd 38622006994SStephen Boyd return timer_handler(ARCH_TIMER_MEM_PHYS_ACCESS, evt); 38722006994SStephen Boyd } 38822006994SStephen Boyd 38922006994SStephen Boyd static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id) 39022006994SStephen Boyd { 39122006994SStephen Boyd struct clock_event_device *evt = dev_id; 39222006994SStephen Boyd 39322006994SStephen Boyd return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt); 39422006994SStephen Boyd } 39522006994SStephen Boyd 39646c5bfddSViresh Kumar static __always_inline int timer_shutdown(const int access, 39760faddf6SStephen Boyd struct clock_event_device *clk) 3988a4da6e3SMark Rutland { 3998a4da6e3SMark Rutland unsigned long ctrl; 40046c5bfddSViresh Kumar 40160faddf6SStephen Boyd ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); 4028a4da6e3SMark Rutland ctrl &= ~ARCH_TIMER_CTRL_ENABLE; 40360faddf6SStephen Boyd arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); 40446c5bfddSViresh Kumar 40546c5bfddSViresh Kumar return 0; 4068a4da6e3SMark Rutland } 4078a4da6e3SMark Rutland 40846c5bfddSViresh Kumar static int arch_timer_shutdown_virt(struct clock_event_device *clk) 4098a4da6e3SMark Rutland { 41046c5bfddSViresh Kumar return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk); 4118a4da6e3SMark Rutland } 4128a4da6e3SMark Rutland 41346c5bfddSViresh Kumar static int arch_timer_shutdown_phys(struct clock_event_device *clk) 4148a4da6e3SMark Rutland { 41546c5bfddSViresh Kumar return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk); 4168a4da6e3SMark Rutland } 4178a4da6e3SMark Rutland 41846c5bfddSViresh Kumar static int arch_timer_shutdown_virt_mem(struct clock_event_device *clk) 41922006994SStephen Boyd { 42046c5bfddSViresh Kumar return timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk); 42122006994SStephen Boyd } 42222006994SStephen Boyd 42346c5bfddSViresh Kumar static int arch_timer_shutdown_phys_mem(struct clock_event_device *clk) 42422006994SStephen Boyd { 42546c5bfddSViresh Kumar return timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk); 42622006994SStephen Boyd } 42722006994SStephen Boyd 42860faddf6SStephen Boyd static __always_inline void set_next_event(const int access, unsigned long evt, 42960faddf6SStephen Boyd struct clock_event_device *clk) 4308a4da6e3SMark Rutland { 4318a4da6e3SMark Rutland unsigned long ctrl; 43260faddf6SStephen Boyd ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); 4338a4da6e3SMark Rutland ctrl |= ARCH_TIMER_CTRL_ENABLE; 4348a4da6e3SMark Rutland ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; 43560faddf6SStephen Boyd arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk); 43660faddf6SStephen Boyd arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); 4378a4da6e3SMark Rutland } 4388a4da6e3SMark Rutland 43916d10ef2SDing Tianhong #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND 44016d10ef2SDing Tianhong static __always_inline void erratum_set_next_event_generic(const int access, 441f6dc1576SScott Wood unsigned long evt, struct clock_event_device *clk) 442f6dc1576SScott Wood { 443f6dc1576SScott Wood unsigned long ctrl; 444f6dc1576SScott Wood u64 cval = evt + arch_counter_get_cntvct(); 445f6dc1576SScott Wood 446f6dc1576SScott Wood ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); 447f6dc1576SScott Wood ctrl |= ARCH_TIMER_CTRL_ENABLE; 448f6dc1576SScott Wood ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; 449f6dc1576SScott Wood 450f6dc1576SScott Wood if (access == ARCH_TIMER_PHYS_ACCESS) 451f6dc1576SScott Wood write_sysreg(cval, cntp_cval_el0); 452f6dc1576SScott Wood else if (access == ARCH_TIMER_VIRT_ACCESS) 453f6dc1576SScott Wood write_sysreg(cval, cntv_cval_el0); 454f6dc1576SScott Wood 455f6dc1576SScott Wood arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); 456f6dc1576SScott Wood } 457f6dc1576SScott Wood 45816d10ef2SDing Tianhong static int erratum_set_next_event_virt(unsigned long evt, 459f6dc1576SScott Wood struct clock_event_device *clk) 460f6dc1576SScott Wood { 46116d10ef2SDing Tianhong erratum_set_next_event_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk); 462f6dc1576SScott Wood return 0; 463f6dc1576SScott Wood } 464f6dc1576SScott Wood 46516d10ef2SDing Tianhong static int erratum_set_next_event_phys(unsigned long evt, 466f6dc1576SScott Wood struct clock_event_device *clk) 467f6dc1576SScott Wood { 46816d10ef2SDing Tianhong erratum_set_next_event_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk); 469f6dc1576SScott Wood return 0; 470f6dc1576SScott Wood } 47116d10ef2SDing Tianhong #endif /* CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND */ 472f6dc1576SScott Wood 4738a4da6e3SMark Rutland static int arch_timer_set_next_event_virt(unsigned long evt, 47460faddf6SStephen Boyd struct clock_event_device *clk) 4758a4da6e3SMark Rutland { 47660faddf6SStephen Boyd set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); 4778a4da6e3SMark Rutland return 0; 4788a4da6e3SMark Rutland } 4798a4da6e3SMark Rutland 4808a4da6e3SMark Rutland static int arch_timer_set_next_event_phys(unsigned long evt, 48160faddf6SStephen Boyd struct clock_event_device *clk) 4828a4da6e3SMark Rutland { 48360faddf6SStephen Boyd set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); 4848a4da6e3SMark Rutland return 0; 4858a4da6e3SMark Rutland } 4868a4da6e3SMark Rutland 48722006994SStephen Boyd static int arch_timer_set_next_event_virt_mem(unsigned long evt, 48822006994SStephen Boyd struct clock_event_device *clk) 4898a4da6e3SMark Rutland { 49022006994SStephen Boyd set_next_event(ARCH_TIMER_MEM_VIRT_ACCESS, evt, clk); 49122006994SStephen Boyd return 0; 49222006994SStephen Boyd } 49322006994SStephen Boyd 49422006994SStephen Boyd static int arch_timer_set_next_event_phys_mem(unsigned long evt, 49522006994SStephen Boyd struct clock_event_device *clk) 49622006994SStephen Boyd { 49722006994SStephen Boyd set_next_event(ARCH_TIMER_MEM_PHYS_ACCESS, evt, clk); 49822006994SStephen Boyd return 0; 49922006994SStephen Boyd } 50022006994SStephen Boyd 50116d10ef2SDing Tianhong static void erratum_workaround_set_sne(struct clock_event_device *clk) 502f6dc1576SScott Wood { 50316d10ef2SDing Tianhong #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND 504f6dc1576SScott Wood if (!static_branch_unlikely(&arch_timer_read_ool_enabled)) 505f6dc1576SScott Wood return; 506f6dc1576SScott Wood 507f6dc1576SScott Wood if (arch_timer_uses_ppi == VIRT_PPI) 50816d10ef2SDing Tianhong clk->set_next_event = erratum_set_next_event_virt; 509f6dc1576SScott Wood else 51016d10ef2SDing Tianhong clk->set_next_event = erratum_set_next_event_phys; 511f6dc1576SScott Wood #endif 512f6dc1576SScott Wood } 513f6dc1576SScott Wood 514cfb6d656SThomas Gleixner static void __arch_timer_setup(unsigned type, 51522006994SStephen Boyd struct clock_event_device *clk) 51622006994SStephen Boyd { 51722006994SStephen Boyd clk->features = CLOCK_EVT_FEAT_ONESHOT; 51822006994SStephen Boyd 51922006994SStephen Boyd if (type == ARCH_CP15_TIMER) { 52082a56194SLorenzo Pieralisi if (arch_timer_c3stop) 52122006994SStephen Boyd clk->features |= CLOCK_EVT_FEAT_C3STOP; 5228a4da6e3SMark Rutland clk->name = "arch_sys_timer"; 5238a4da6e3SMark Rutland clk->rating = 450; 52422006994SStephen Boyd clk->cpumask = cpumask_of(smp_processor_id()); 525f81f03faSMarc Zyngier clk->irq = arch_timer_ppi[arch_timer_uses_ppi]; 526f81f03faSMarc Zyngier switch (arch_timer_uses_ppi) { 527f81f03faSMarc Zyngier case VIRT_PPI: 52846c5bfddSViresh Kumar clk->set_state_shutdown = arch_timer_shutdown_virt; 529cf8c5009SViresh Kumar clk->set_state_oneshot_stopped = arch_timer_shutdown_virt; 5308a4da6e3SMark Rutland clk->set_next_event = arch_timer_set_next_event_virt; 531f81f03faSMarc Zyngier break; 532f81f03faSMarc Zyngier case PHYS_SECURE_PPI: 533f81f03faSMarc Zyngier case PHYS_NONSECURE_PPI: 534f81f03faSMarc Zyngier case HYP_PPI: 53546c5bfddSViresh Kumar clk->set_state_shutdown = arch_timer_shutdown_phys; 536cf8c5009SViresh Kumar clk->set_state_oneshot_stopped = arch_timer_shutdown_phys; 5378a4da6e3SMark Rutland clk->set_next_event = arch_timer_set_next_event_phys; 538f81f03faSMarc Zyngier break; 539f81f03faSMarc Zyngier default: 540f81f03faSMarc Zyngier BUG(); 5418a4da6e3SMark Rutland } 542f6dc1576SScott Wood 5430064030cSMarc Zyngier arch_timer_check_ool_workaround(ate_match_local_cap_id, NULL); 5440064030cSMarc Zyngier 54516d10ef2SDing Tianhong erratum_workaround_set_sne(clk); 54622006994SStephen Boyd } else { 5477b52ad2eSStephen Boyd clk->features |= CLOCK_EVT_FEAT_DYNIRQ; 54822006994SStephen Boyd clk->name = "arch_mem_timer"; 54922006994SStephen Boyd clk->rating = 400; 55022006994SStephen Boyd clk->cpumask = cpu_all_mask; 55122006994SStephen Boyd if (arch_timer_mem_use_virtual) { 55246c5bfddSViresh Kumar clk->set_state_shutdown = arch_timer_shutdown_virt_mem; 553cf8c5009SViresh Kumar clk->set_state_oneshot_stopped = arch_timer_shutdown_virt_mem; 55422006994SStephen Boyd clk->set_next_event = 55522006994SStephen Boyd arch_timer_set_next_event_virt_mem; 55622006994SStephen Boyd } else { 55746c5bfddSViresh Kumar clk->set_state_shutdown = arch_timer_shutdown_phys_mem; 558cf8c5009SViresh Kumar clk->set_state_oneshot_stopped = arch_timer_shutdown_phys_mem; 55922006994SStephen Boyd clk->set_next_event = 56022006994SStephen Boyd arch_timer_set_next_event_phys_mem; 56122006994SStephen Boyd } 56222006994SStephen Boyd } 5638a4da6e3SMark Rutland 56446c5bfddSViresh Kumar clk->set_state_shutdown(clk); 5658a4da6e3SMark Rutland 56622006994SStephen Boyd clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); 56722006994SStephen Boyd } 5688a4da6e3SMark Rutland 569e1ce5c7aSNathan Lynch static void arch_timer_evtstrm_enable(int divider) 570e1ce5c7aSNathan Lynch { 571e1ce5c7aSNathan Lynch u32 cntkctl = arch_timer_get_cntkctl(); 572e1ce5c7aSNathan Lynch 573e1ce5c7aSNathan Lynch cntkctl &= ~ARCH_TIMER_EVT_TRIGGER_MASK; 574e1ce5c7aSNathan Lynch /* Set the divider and enable virtual event stream */ 575e1ce5c7aSNathan Lynch cntkctl |= (divider << ARCH_TIMER_EVT_TRIGGER_SHIFT) 576e1ce5c7aSNathan Lynch | ARCH_TIMER_VIRT_EVT_EN; 577e1ce5c7aSNathan Lynch arch_timer_set_cntkctl(cntkctl); 578e1ce5c7aSNathan Lynch elf_hwcap |= HWCAP_EVTSTRM; 579e1ce5c7aSNathan Lynch #ifdef CONFIG_COMPAT 580e1ce5c7aSNathan Lynch compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM; 581e1ce5c7aSNathan Lynch #endif 582e1ce5c7aSNathan Lynch } 583e1ce5c7aSNathan Lynch 584037f6377SWill Deacon static void arch_timer_configure_evtstream(void) 585037f6377SWill Deacon { 586037f6377SWill Deacon int evt_stream_div, pos; 587037f6377SWill Deacon 588037f6377SWill Deacon /* Find the closest power of two to the divisor */ 589037f6377SWill Deacon evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ; 590037f6377SWill Deacon pos = fls(evt_stream_div); 591037f6377SWill Deacon if (pos > 1 && !(evt_stream_div & (1 << (pos - 2)))) 592037f6377SWill Deacon pos--; 593037f6377SWill Deacon /* enable event stream */ 594037f6377SWill Deacon arch_timer_evtstrm_enable(min(pos, 15)); 595037f6377SWill Deacon } 596037f6377SWill Deacon 5978b8dde00SNathan Lynch static void arch_counter_set_user_access(void) 5988b8dde00SNathan Lynch { 5998b8dde00SNathan Lynch u32 cntkctl = arch_timer_get_cntkctl(); 6008b8dde00SNathan Lynch 6018b8dde00SNathan Lynch /* Disable user access to the timers and the physical counter */ 6028b8dde00SNathan Lynch /* Also disable virtual event stream */ 6038b8dde00SNathan Lynch cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN 6048b8dde00SNathan Lynch | ARCH_TIMER_USR_VT_ACCESS_EN 6058b8dde00SNathan Lynch | ARCH_TIMER_VIRT_EVT_EN 6068b8dde00SNathan Lynch | ARCH_TIMER_USR_PCT_ACCESS_EN); 6078b8dde00SNathan Lynch 6088b8dde00SNathan Lynch /* Enable user access to the virtual counter */ 6098b8dde00SNathan Lynch cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; 6108b8dde00SNathan Lynch 6118b8dde00SNathan Lynch arch_timer_set_cntkctl(cntkctl); 6128b8dde00SNathan Lynch } 6138b8dde00SNathan Lynch 614f81f03faSMarc Zyngier static bool arch_timer_has_nonsecure_ppi(void) 615f81f03faSMarc Zyngier { 616f81f03faSMarc Zyngier return (arch_timer_uses_ppi == PHYS_SECURE_PPI && 617f81f03faSMarc Zyngier arch_timer_ppi[PHYS_NONSECURE_PPI]); 618f81f03faSMarc Zyngier } 619f81f03faSMarc Zyngier 620f005bd7eSMarc Zyngier static u32 check_ppi_trigger(int irq) 621f005bd7eSMarc Zyngier { 622f005bd7eSMarc Zyngier u32 flags = irq_get_trigger_type(irq); 623f005bd7eSMarc Zyngier 624f005bd7eSMarc Zyngier if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) { 625f005bd7eSMarc Zyngier pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq); 626f005bd7eSMarc Zyngier pr_warn("WARNING: Please fix your firmware\n"); 627f005bd7eSMarc Zyngier flags = IRQF_TRIGGER_LOW; 628f005bd7eSMarc Zyngier } 629f005bd7eSMarc Zyngier 630f005bd7eSMarc Zyngier return flags; 631f005bd7eSMarc Zyngier } 632f005bd7eSMarc Zyngier 6337e86e8bdSRichard Cochran static int arch_timer_starting_cpu(unsigned int cpu) 63422006994SStephen Boyd { 6357e86e8bdSRichard Cochran struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); 636f005bd7eSMarc Zyngier u32 flags; 6377e86e8bdSRichard Cochran 63822006994SStephen Boyd __arch_timer_setup(ARCH_CP15_TIMER, clk); 6398a4da6e3SMark Rutland 640f005bd7eSMarc Zyngier flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]); 641f005bd7eSMarc Zyngier enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags); 642f81f03faSMarc Zyngier 643f005bd7eSMarc Zyngier if (arch_timer_has_nonsecure_ppi()) { 644f005bd7eSMarc Zyngier flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]); 645f005bd7eSMarc Zyngier enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags); 646f005bd7eSMarc Zyngier } 6478a4da6e3SMark Rutland 6488a4da6e3SMark Rutland arch_counter_set_user_access(); 64946fd5c6bSWill Deacon if (evtstrm_enable) 650037f6377SWill Deacon arch_timer_configure_evtstream(); 6518a4da6e3SMark Rutland 6528a4da6e3SMark Rutland return 0; 6538a4da6e3SMark Rutland } 6548a4da6e3SMark Rutland 65522006994SStephen Boyd static void 65622006994SStephen Boyd arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) 6578a4da6e3SMark Rutland { 65822006994SStephen Boyd /* Who has more than one independent system counter? */ 65922006994SStephen Boyd if (arch_timer_rate) 66022006994SStephen Boyd return; 6618a4da6e3SMark Rutland 662b09ca1ecSHanjun Guo /* 663b09ca1ecSHanjun Guo * Try to determine the frequency from the device tree or CNTFRQ, 664b09ca1ecSHanjun Guo * if ACPI is enabled, get the frequency from CNTFRQ ONLY. 665b09ca1ecSHanjun Guo */ 666b09ca1ecSHanjun Guo if (!acpi_disabled || 667b09ca1ecSHanjun Guo of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { 66822006994SStephen Boyd if (cntbase) 66922006994SStephen Boyd arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); 67022006994SStephen Boyd else 67122006994SStephen Boyd arch_timer_rate = arch_timer_get_cntfrq(); 67222006994SStephen Boyd } 6738a4da6e3SMark Rutland 6748a4da6e3SMark Rutland /* Check the timer frequency. */ 67522006994SStephen Boyd if (arch_timer_rate == 0) 6768a4da6e3SMark Rutland pr_warn("Architected timer frequency not available\n"); 6778a4da6e3SMark Rutland } 6788a4da6e3SMark Rutland 67922006994SStephen Boyd static void arch_timer_banner(unsigned type) 68022006994SStephen Boyd { 68122006994SStephen Boyd pr_info("Architected %s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n", 68222006994SStephen Boyd type & ARCH_CP15_TIMER ? "cp15" : "", 68322006994SStephen Boyd type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? " and " : "", 68422006994SStephen Boyd type & ARCH_MEM_TIMER ? "mmio" : "", 6858a4da6e3SMark Rutland (unsigned long)arch_timer_rate / 1000000, 6868a4da6e3SMark Rutland (unsigned long)(arch_timer_rate / 10000) % 100, 68722006994SStephen Boyd type & ARCH_CP15_TIMER ? 688f81f03faSMarc Zyngier (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" : 68922006994SStephen Boyd "", 69022006994SStephen Boyd type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", 69122006994SStephen Boyd type & ARCH_MEM_TIMER ? 69222006994SStephen Boyd arch_timer_mem_use_virtual ? "virt" : "phys" : 69322006994SStephen Boyd ""); 6948a4da6e3SMark Rutland } 6958a4da6e3SMark Rutland 6968a4da6e3SMark Rutland u32 arch_timer_get_rate(void) 6978a4da6e3SMark Rutland { 6988a4da6e3SMark Rutland return arch_timer_rate; 6998a4da6e3SMark Rutland } 7008a4da6e3SMark Rutland 70122006994SStephen Boyd static u64 arch_counter_get_cntvct_mem(void) 7028a4da6e3SMark Rutland { 70322006994SStephen Boyd u32 vct_lo, vct_hi, tmp_hi; 70422006994SStephen Boyd 70522006994SStephen Boyd do { 70622006994SStephen Boyd vct_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); 70722006994SStephen Boyd vct_lo = readl_relaxed(arch_counter_base + CNTVCT_LO); 70822006994SStephen Boyd tmp_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); 70922006994SStephen Boyd } while (vct_hi != tmp_hi); 71022006994SStephen Boyd 71122006994SStephen Boyd return ((u64) vct_hi << 32) | vct_lo; 7128a4da6e3SMark Rutland } 7138a4da6e3SMark Rutland 71422006994SStephen Boyd /* 71522006994SStephen Boyd * Default to cp15 based access because arm64 uses this function for 71622006994SStephen Boyd * sched_clock() before DT is probed and the cp15 method is guaranteed 71722006994SStephen Boyd * to exist on arm64. arm doesn't use this before DT is probed so even 71822006994SStephen Boyd * if we don't have the cp15 accessors we won't have a problem. 71922006994SStephen Boyd */ 72022006994SStephen Boyd u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct; 72122006994SStephen Boyd 722a5a1d1c2SThomas Gleixner static u64 arch_counter_read(struct clocksource *cs) 7238a4da6e3SMark Rutland { 72422006994SStephen Boyd return arch_timer_read_counter(); 7258a4da6e3SMark Rutland } 7268a4da6e3SMark Rutland 727a5a1d1c2SThomas Gleixner static u64 arch_counter_read_cc(const struct cyclecounter *cc) 7288a4da6e3SMark Rutland { 72922006994SStephen Boyd return arch_timer_read_counter(); 7308a4da6e3SMark Rutland } 7318a4da6e3SMark Rutland 7328a4da6e3SMark Rutland static struct clocksource clocksource_counter = { 7338a4da6e3SMark Rutland .name = "arch_sys_counter", 7348a4da6e3SMark Rutland .rating = 400, 7358a4da6e3SMark Rutland .read = arch_counter_read, 7368a4da6e3SMark Rutland .mask = CLOCKSOURCE_MASK(56), 737d8ec7595SBrian Norris .flags = CLOCK_SOURCE_IS_CONTINUOUS, 7388a4da6e3SMark Rutland }; 7398a4da6e3SMark Rutland 7403d837bc0SBhumika Goyal static struct cyclecounter cyclecounter __ro_after_init = { 7418a4da6e3SMark Rutland .read = arch_counter_read_cc, 7428a4da6e3SMark Rutland .mask = CLOCKSOURCE_MASK(56), 7438a4da6e3SMark Rutland }; 7448a4da6e3SMark Rutland 745b4d6ce97SJulien Grall static struct arch_timer_kvm_info arch_timer_kvm_info; 746b4d6ce97SJulien Grall 747b4d6ce97SJulien Grall struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) 748b4d6ce97SJulien Grall { 749b4d6ce97SJulien Grall return &arch_timer_kvm_info; 750b4d6ce97SJulien Grall } 7518a4da6e3SMark Rutland 75222006994SStephen Boyd static void __init arch_counter_register(unsigned type) 75322006994SStephen Boyd { 75422006994SStephen Boyd u64 start_count; 75522006994SStephen Boyd 75622006994SStephen Boyd /* Register the CP15 based counter if we have one */ 757423bd69eSNathan Lynch if (type & ARCH_CP15_TIMER) { 758f81f03faSMarc Zyngier if (IS_ENABLED(CONFIG_ARM64) || arch_timer_uses_ppi == VIRT_PPI) 75922006994SStephen Boyd arch_timer_read_counter = arch_counter_get_cntvct; 7600b46b8a7SSonny Rao else 7610b46b8a7SSonny Rao arch_timer_read_counter = arch_counter_get_cntpct; 762f6dc1576SScott Wood 7631d8f51d4SScott Wood clocksource_counter.archdata.vdso_direct = true; 7641d8f51d4SScott Wood 76516d10ef2SDing Tianhong #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND 766f6dc1576SScott Wood /* 767f6dc1576SScott Wood * Don't use the vdso fastpath if errata require using 768f6dc1576SScott Wood * the out-of-line counter accessor. 769f6dc1576SScott Wood */ 770f6dc1576SScott Wood if (static_branch_unlikely(&arch_timer_read_ool_enabled)) 7711d8f51d4SScott Wood clocksource_counter.archdata.vdso_direct = false; 772f6dc1576SScott Wood #endif 773423bd69eSNathan Lynch } else { 77422006994SStephen Boyd arch_timer_read_counter = arch_counter_get_cntvct_mem; 775423bd69eSNathan Lynch } 776423bd69eSNathan Lynch 777d8ec7595SBrian Norris if (!arch_counter_suspend_stop) 778d8ec7595SBrian Norris clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; 77922006994SStephen Boyd start_count = arch_timer_read_counter(); 78022006994SStephen Boyd clocksource_register_hz(&clocksource_counter, arch_timer_rate); 78122006994SStephen Boyd cyclecounter.mult = clocksource_counter.mult; 78222006994SStephen Boyd cyclecounter.shift = clocksource_counter.shift; 783b4d6ce97SJulien Grall timecounter_init(&arch_timer_kvm_info.timecounter, 784b4d6ce97SJulien Grall &cyclecounter, start_count); 7854a7d3e8aSThierry Reding 7864a7d3e8aSThierry Reding /* 56 bits minimum, so we assume worst case rollover */ 7874a7d3e8aSThierry Reding sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate); 78822006994SStephen Boyd } 78922006994SStephen Boyd 7908c37bb3aSPaul Gortmaker static void arch_timer_stop(struct clock_event_device *clk) 7918a4da6e3SMark Rutland { 7928a4da6e3SMark Rutland pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", 7938a4da6e3SMark Rutland clk->irq, smp_processor_id()); 7948a4da6e3SMark Rutland 795f81f03faSMarc Zyngier disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]); 796f81f03faSMarc Zyngier if (arch_timer_has_nonsecure_ppi()) 7978a4da6e3SMark Rutland disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); 7988a4da6e3SMark Rutland 79946c5bfddSViresh Kumar clk->set_state_shutdown(clk); 8008a4da6e3SMark Rutland } 8018a4da6e3SMark Rutland 8027e86e8bdSRichard Cochran static int arch_timer_dying_cpu(unsigned int cpu) 8038a4da6e3SMark Rutland { 8047e86e8bdSRichard Cochran struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); 8058a4da6e3SMark Rutland 8067e86e8bdSRichard Cochran arch_timer_stop(clk); 8077e86e8bdSRichard Cochran return 0; 8088a4da6e3SMark Rutland } 8098a4da6e3SMark Rutland 810346e7480SSudeep KarkadaNagesha #ifdef CONFIG_CPU_PM 811346e7480SSudeep KarkadaNagesha static unsigned int saved_cntkctl; 812346e7480SSudeep KarkadaNagesha static int arch_timer_cpu_pm_notify(struct notifier_block *self, 813346e7480SSudeep KarkadaNagesha unsigned long action, void *hcpu) 814346e7480SSudeep KarkadaNagesha { 815346e7480SSudeep KarkadaNagesha if (action == CPU_PM_ENTER) 816346e7480SSudeep KarkadaNagesha saved_cntkctl = arch_timer_get_cntkctl(); 817346e7480SSudeep KarkadaNagesha else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) 818346e7480SSudeep KarkadaNagesha arch_timer_set_cntkctl(saved_cntkctl); 819346e7480SSudeep KarkadaNagesha return NOTIFY_OK; 820346e7480SSudeep KarkadaNagesha } 821346e7480SSudeep KarkadaNagesha 822346e7480SSudeep KarkadaNagesha static struct notifier_block arch_timer_cpu_pm_notifier = { 823346e7480SSudeep KarkadaNagesha .notifier_call = arch_timer_cpu_pm_notify, 824346e7480SSudeep KarkadaNagesha }; 825346e7480SSudeep KarkadaNagesha 826346e7480SSudeep KarkadaNagesha static int __init arch_timer_cpu_pm_init(void) 827346e7480SSudeep KarkadaNagesha { 828346e7480SSudeep KarkadaNagesha return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier); 829346e7480SSudeep KarkadaNagesha } 8307e86e8bdSRichard Cochran 8317e86e8bdSRichard Cochran static void __init arch_timer_cpu_pm_deinit(void) 8327e86e8bdSRichard Cochran { 8337e86e8bdSRichard Cochran WARN_ON(cpu_pm_unregister_notifier(&arch_timer_cpu_pm_notifier)); 8347e86e8bdSRichard Cochran } 8357e86e8bdSRichard Cochran 836346e7480SSudeep KarkadaNagesha #else 837346e7480SSudeep KarkadaNagesha static int __init arch_timer_cpu_pm_init(void) 838346e7480SSudeep KarkadaNagesha { 839346e7480SSudeep KarkadaNagesha return 0; 840346e7480SSudeep KarkadaNagesha } 8417e86e8bdSRichard Cochran 8427e86e8bdSRichard Cochran static void __init arch_timer_cpu_pm_deinit(void) 8437e86e8bdSRichard Cochran { 8447e86e8bdSRichard Cochran } 845346e7480SSudeep KarkadaNagesha #endif 846346e7480SSudeep KarkadaNagesha 8478a4da6e3SMark Rutland static int __init arch_timer_register(void) 8488a4da6e3SMark Rutland { 8498a4da6e3SMark Rutland int err; 8508a4da6e3SMark Rutland int ppi; 8518a4da6e3SMark Rutland 8528a4da6e3SMark Rutland arch_timer_evt = alloc_percpu(struct clock_event_device); 8538a4da6e3SMark Rutland if (!arch_timer_evt) { 8548a4da6e3SMark Rutland err = -ENOMEM; 8558a4da6e3SMark Rutland goto out; 8568a4da6e3SMark Rutland } 8578a4da6e3SMark Rutland 858f81f03faSMarc Zyngier ppi = arch_timer_ppi[arch_timer_uses_ppi]; 859f81f03faSMarc Zyngier switch (arch_timer_uses_ppi) { 860f81f03faSMarc Zyngier case VIRT_PPI: 8618a4da6e3SMark Rutland err = request_percpu_irq(ppi, arch_timer_handler_virt, 8628a4da6e3SMark Rutland "arch_timer", arch_timer_evt); 863f81f03faSMarc Zyngier break; 864f81f03faSMarc Zyngier case PHYS_SECURE_PPI: 865f81f03faSMarc Zyngier case PHYS_NONSECURE_PPI: 8668a4da6e3SMark Rutland err = request_percpu_irq(ppi, arch_timer_handler_phys, 8678a4da6e3SMark Rutland "arch_timer", arch_timer_evt); 8688a4da6e3SMark Rutland if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) { 8698a4da6e3SMark Rutland ppi = arch_timer_ppi[PHYS_NONSECURE_PPI]; 8708a4da6e3SMark Rutland err = request_percpu_irq(ppi, arch_timer_handler_phys, 8718a4da6e3SMark Rutland "arch_timer", arch_timer_evt); 8728a4da6e3SMark Rutland if (err) 8738a4da6e3SMark Rutland free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], 8748a4da6e3SMark Rutland arch_timer_evt); 8758a4da6e3SMark Rutland } 876f81f03faSMarc Zyngier break; 877f81f03faSMarc Zyngier case HYP_PPI: 878f81f03faSMarc Zyngier err = request_percpu_irq(ppi, arch_timer_handler_phys, 879f81f03faSMarc Zyngier "arch_timer", arch_timer_evt); 880f81f03faSMarc Zyngier break; 881f81f03faSMarc Zyngier default: 882f81f03faSMarc Zyngier BUG(); 8838a4da6e3SMark Rutland } 8848a4da6e3SMark Rutland 8858a4da6e3SMark Rutland if (err) { 8868a4da6e3SMark Rutland pr_err("arch_timer: can't register interrupt %d (%d)\n", 8878a4da6e3SMark Rutland ppi, err); 8888a4da6e3SMark Rutland goto out_free; 8898a4da6e3SMark Rutland } 8908a4da6e3SMark Rutland 891346e7480SSudeep KarkadaNagesha err = arch_timer_cpu_pm_init(); 892346e7480SSudeep KarkadaNagesha if (err) 893346e7480SSudeep KarkadaNagesha goto out_unreg_notify; 894346e7480SSudeep KarkadaNagesha 8958a4da6e3SMark Rutland 8967e86e8bdSRichard Cochran /* Register and immediately configure the timer on the boot CPU */ 8977e86e8bdSRichard Cochran err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING, 89873c1b41eSThomas Gleixner "clockevents/arm/arch_timer:starting", 8997e86e8bdSRichard Cochran arch_timer_starting_cpu, arch_timer_dying_cpu); 9007e86e8bdSRichard Cochran if (err) 9017e86e8bdSRichard Cochran goto out_unreg_cpupm; 9028a4da6e3SMark Rutland return 0; 9038a4da6e3SMark Rutland 9047e86e8bdSRichard Cochran out_unreg_cpupm: 9057e86e8bdSRichard Cochran arch_timer_cpu_pm_deinit(); 9067e86e8bdSRichard Cochran 907346e7480SSudeep KarkadaNagesha out_unreg_notify: 908f81f03faSMarc Zyngier free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt); 909f81f03faSMarc Zyngier if (arch_timer_has_nonsecure_ppi()) 9108a4da6e3SMark Rutland free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 9118a4da6e3SMark Rutland arch_timer_evt); 9128a4da6e3SMark Rutland 9138a4da6e3SMark Rutland out_free: 9148a4da6e3SMark Rutland free_percpu(arch_timer_evt); 9158a4da6e3SMark Rutland out: 9168a4da6e3SMark Rutland return err; 9178a4da6e3SMark Rutland } 9188a4da6e3SMark Rutland 91922006994SStephen Boyd static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq) 92022006994SStephen Boyd { 92122006994SStephen Boyd int ret; 92222006994SStephen Boyd irq_handler_t func; 92322006994SStephen Boyd struct arch_timer *t; 92422006994SStephen Boyd 92522006994SStephen Boyd t = kzalloc(sizeof(*t), GFP_KERNEL); 92622006994SStephen Boyd if (!t) 92722006994SStephen Boyd return -ENOMEM; 92822006994SStephen Boyd 92922006994SStephen Boyd t->base = base; 93022006994SStephen Boyd t->evt.irq = irq; 93122006994SStephen Boyd __arch_timer_setup(ARCH_MEM_TIMER, &t->evt); 93222006994SStephen Boyd 93322006994SStephen Boyd if (arch_timer_mem_use_virtual) 93422006994SStephen Boyd func = arch_timer_handler_virt_mem; 93522006994SStephen Boyd else 93622006994SStephen Boyd func = arch_timer_handler_phys_mem; 93722006994SStephen Boyd 93822006994SStephen Boyd ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &t->evt); 93922006994SStephen Boyd if (ret) { 94022006994SStephen Boyd pr_err("arch_timer: Failed to request mem timer irq\n"); 94122006994SStephen Boyd kfree(t); 94222006994SStephen Boyd } 94322006994SStephen Boyd 94422006994SStephen Boyd return ret; 94522006994SStephen Boyd } 94622006994SStephen Boyd 94722006994SStephen Boyd static const struct of_device_id arch_timer_of_match[] __initconst = { 94822006994SStephen Boyd { .compatible = "arm,armv7-timer", }, 94922006994SStephen Boyd { .compatible = "arm,armv8-timer", }, 95022006994SStephen Boyd {}, 95122006994SStephen Boyd }; 95222006994SStephen Boyd 95322006994SStephen Boyd static const struct of_device_id arch_timer_mem_of_match[] __initconst = { 95422006994SStephen Boyd { .compatible = "arm,armv7-timer-mem", }, 95522006994SStephen Boyd {}, 95622006994SStephen Boyd }; 95722006994SStephen Boyd 958c387f07eSSudeep Holla static bool __init 959566e6dfaSLaurent Pinchart arch_timer_needs_probing(int type, const struct of_device_id *matches) 960c387f07eSSudeep Holla { 961c387f07eSSudeep Holla struct device_node *dn; 962566e6dfaSLaurent Pinchart bool needs_probing = false; 963c387f07eSSudeep Holla 964c387f07eSSudeep Holla dn = of_find_matching_node(NULL, matches); 96559aa896dSMarc Zyngier if (dn && of_device_is_available(dn) && !(arch_timers_present & type)) 966566e6dfaSLaurent Pinchart needs_probing = true; 967c387f07eSSudeep Holla of_node_put(dn); 968c387f07eSSudeep Holla 969566e6dfaSLaurent Pinchart return needs_probing; 970c387f07eSSudeep Holla } 971c387f07eSSudeep Holla 9723c0731dbSDaniel Lezcano static int __init arch_timer_common_init(void) 97322006994SStephen Boyd { 97422006994SStephen Boyd unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER; 97522006994SStephen Boyd 97622006994SStephen Boyd /* Wait until both nodes are probed if we have two timers */ 97722006994SStephen Boyd if ((arch_timers_present & mask) != mask) { 978566e6dfaSLaurent Pinchart if (arch_timer_needs_probing(ARCH_MEM_TIMER, arch_timer_mem_of_match)) 9793c0731dbSDaniel Lezcano return 0; 980566e6dfaSLaurent Pinchart if (arch_timer_needs_probing(ARCH_CP15_TIMER, arch_timer_of_match)) 9813c0731dbSDaniel Lezcano return 0; 98222006994SStephen Boyd } 98322006994SStephen Boyd 98422006994SStephen Boyd arch_timer_banner(arch_timers_present); 98522006994SStephen Boyd arch_counter_register(arch_timers_present); 9863c0731dbSDaniel Lezcano return arch_timer_arch_init(); 98722006994SStephen Boyd } 98822006994SStephen Boyd 9893c0731dbSDaniel Lezcano static int __init arch_timer_init(void) 9908a4da6e3SMark Rutland { 9913c0731dbSDaniel Lezcano int ret; 99265b5732dSDoug Anderson /* 9938266891eSMarc Zyngier * If HYP mode is available, we know that the physical timer 9948266891eSMarc Zyngier * has been configured to be accessible from PL1. Use it, so 9958266891eSMarc Zyngier * that a guest can use the virtual timer instead. 9968266891eSMarc Zyngier * 9978a4da6e3SMark Rutland * If no interrupt provided for virtual timer, we'll have to 9988a4da6e3SMark Rutland * stick to the physical timer. It'd better be accessible... 999f81f03faSMarc Zyngier * 1000f81f03faSMarc Zyngier * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE 1001f81f03faSMarc Zyngier * accesses to CNTP_*_EL1 registers are silently redirected to 1002f81f03faSMarc Zyngier * their CNTHP_*_EL2 counterparts, and use a different PPI 1003f81f03faSMarc Zyngier * number. 10048a4da6e3SMark Rutland */ 10058266891eSMarc Zyngier if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) { 1006f81f03faSMarc Zyngier bool has_ppi; 10078a4da6e3SMark Rutland 1008f81f03faSMarc Zyngier if (is_kernel_in_hyp_mode()) { 1009f81f03faSMarc Zyngier arch_timer_uses_ppi = HYP_PPI; 1010f81f03faSMarc Zyngier has_ppi = !!arch_timer_ppi[HYP_PPI]; 1011f81f03faSMarc Zyngier } else { 1012f81f03faSMarc Zyngier arch_timer_uses_ppi = PHYS_SECURE_PPI; 1013f81f03faSMarc Zyngier has_ppi = (!!arch_timer_ppi[PHYS_SECURE_PPI] || 1014f81f03faSMarc Zyngier !!arch_timer_ppi[PHYS_NONSECURE_PPI]); 1015f81f03faSMarc Zyngier } 1016f81f03faSMarc Zyngier 1017f81f03faSMarc Zyngier if (!has_ppi) { 10188a4da6e3SMark Rutland pr_warn("arch_timer: No interrupt available, giving up\n"); 10193c0731dbSDaniel Lezcano return -EINVAL; 10208a4da6e3SMark Rutland } 10218a4da6e3SMark Rutland } 10228a4da6e3SMark Rutland 10233c0731dbSDaniel Lezcano ret = arch_timer_register(); 10243c0731dbSDaniel Lezcano if (ret) 10253c0731dbSDaniel Lezcano return ret; 10263c0731dbSDaniel Lezcano 10273c0731dbSDaniel Lezcano ret = arch_timer_common_init(); 10283c0731dbSDaniel Lezcano if (ret) 10293c0731dbSDaniel Lezcano return ret; 1030d9b5e415SJulien Grall 1031d9b5e415SJulien Grall arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI]; 10323c0731dbSDaniel Lezcano 10333c0731dbSDaniel Lezcano return 0; 10348a4da6e3SMark Rutland } 1035b09ca1ecSHanjun Guo 10363c0731dbSDaniel Lezcano static int __init arch_timer_of_init(struct device_node *np) 1037b09ca1ecSHanjun Guo { 1038b09ca1ecSHanjun Guo int i; 1039b09ca1ecSHanjun Guo 1040b09ca1ecSHanjun Guo if (arch_timers_present & ARCH_CP15_TIMER) { 1041b09ca1ecSHanjun Guo pr_warn("arch_timer: multiple nodes in dt, skipping\n"); 10423c0731dbSDaniel Lezcano return 0; 1043b09ca1ecSHanjun Guo } 1044b09ca1ecSHanjun Guo 1045b09ca1ecSHanjun Guo arch_timers_present |= ARCH_CP15_TIMER; 1046b09ca1ecSHanjun Guo for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) 1047b09ca1ecSHanjun Guo arch_timer_ppi[i] = irq_of_parse_and_map(np, i); 1048b09ca1ecSHanjun Guo 1049b09ca1ecSHanjun Guo arch_timer_detect_rate(NULL, np); 1050b09ca1ecSHanjun Guo 1051b09ca1ecSHanjun Guo arch_timer_c3stop = !of_property_read_bool(np, "always-on"); 1052b09ca1ecSHanjun Guo 1053651bb2e9SMarc Zyngier /* Check for globally applicable workarounds */ 1054651bb2e9SMarc Zyngier arch_timer_check_ool_workaround(ate_match_dt, np); 1055f6dc1576SScott Wood 1056b09ca1ecSHanjun Guo /* 1057b09ca1ecSHanjun Guo * If we cannot rely on firmware initializing the timer registers then 1058b09ca1ecSHanjun Guo * we should use the physical timers instead. 1059b09ca1ecSHanjun Guo */ 1060b09ca1ecSHanjun Guo if (IS_ENABLED(CONFIG_ARM) && 1061b09ca1ecSHanjun Guo of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) 1062f81f03faSMarc Zyngier arch_timer_uses_ppi = PHYS_SECURE_PPI; 1063b09ca1ecSHanjun Guo 1064d8ec7595SBrian Norris /* On some systems, the counter stops ticking when in suspend. */ 1065d8ec7595SBrian Norris arch_counter_suspend_stop = of_property_read_bool(np, 1066d8ec7595SBrian Norris "arm,no-tick-in-suspend"); 1067d8ec7595SBrian Norris 10683c0731dbSDaniel Lezcano return arch_timer_init(); 1069b09ca1ecSHanjun Guo } 1070177cf6e5SDaniel Lezcano CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); 1071177cf6e5SDaniel Lezcano CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init); 107222006994SStephen Boyd 10733c0731dbSDaniel Lezcano static int __init arch_timer_mem_init(struct device_node *np) 107422006994SStephen Boyd { 107522006994SStephen Boyd struct device_node *frame, *best_frame = NULL; 107622006994SStephen Boyd void __iomem *cntctlbase, *base; 10773c0731dbSDaniel Lezcano unsigned int irq, ret = -EINVAL; 107822006994SStephen Boyd u32 cnttidr; 107922006994SStephen Boyd 108022006994SStephen Boyd arch_timers_present |= ARCH_MEM_TIMER; 108122006994SStephen Boyd cntctlbase = of_iomap(np, 0); 108222006994SStephen Boyd if (!cntctlbase) { 108322006994SStephen Boyd pr_err("arch_timer: Can't find CNTCTLBase\n"); 10843c0731dbSDaniel Lezcano return -ENXIO; 108522006994SStephen Boyd } 108622006994SStephen Boyd 108722006994SStephen Boyd cnttidr = readl_relaxed(cntctlbase + CNTTIDR); 108822006994SStephen Boyd 108922006994SStephen Boyd /* 109022006994SStephen Boyd * Try to find a virtual capable frame. Otherwise fall back to a 109122006994SStephen Boyd * physical capable frame. 109222006994SStephen Boyd */ 109322006994SStephen Boyd for_each_available_child_of_node(np, frame) { 109422006994SStephen Boyd int n; 1095e392d603SRobin Murphy u32 cntacr; 109622006994SStephen Boyd 109722006994SStephen Boyd if (of_property_read_u32(frame, "frame-number", &n)) { 109822006994SStephen Boyd pr_err("arch_timer: Missing frame-number\n"); 109922006994SStephen Boyd of_node_put(frame); 1100e392d603SRobin Murphy goto out; 110122006994SStephen Boyd } 110222006994SStephen Boyd 1103e392d603SRobin Murphy /* Try enabling everything, and see what sticks */ 1104e392d603SRobin Murphy cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT | 1105e392d603SRobin Murphy CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT; 1106e392d603SRobin Murphy writel_relaxed(cntacr, cntctlbase + CNTACR(n)); 1107e392d603SRobin Murphy cntacr = readl_relaxed(cntctlbase + CNTACR(n)); 1108e392d603SRobin Murphy 1109e392d603SRobin Murphy if ((cnttidr & CNTTIDR_VIRT(n)) && 1110e392d603SRobin Murphy !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) { 111122006994SStephen Boyd of_node_put(best_frame); 111222006994SStephen Boyd best_frame = frame; 111322006994SStephen Boyd arch_timer_mem_use_virtual = true; 111422006994SStephen Boyd break; 111522006994SStephen Boyd } 1116e392d603SRobin Murphy 1117e392d603SRobin Murphy if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT)) 1118e392d603SRobin Murphy continue; 1119e392d603SRobin Murphy 112022006994SStephen Boyd of_node_put(best_frame); 112122006994SStephen Boyd best_frame = of_node_get(frame); 112222006994SStephen Boyd } 112322006994SStephen Boyd 11243c0731dbSDaniel Lezcano ret= -ENXIO; 1125f947ee14SStephen Boyd base = arch_counter_base = of_io_request_and_map(best_frame, 0, 1126f947ee14SStephen Boyd "arch_mem_timer"); 1127f947ee14SStephen Boyd if (IS_ERR(base)) { 112822006994SStephen Boyd pr_err("arch_timer: Can't map frame's registers\n"); 1129e392d603SRobin Murphy goto out; 113022006994SStephen Boyd } 113122006994SStephen Boyd 113222006994SStephen Boyd if (arch_timer_mem_use_virtual) 113322006994SStephen Boyd irq = irq_of_parse_and_map(best_frame, 1); 113422006994SStephen Boyd else 113522006994SStephen Boyd irq = irq_of_parse_and_map(best_frame, 0); 1136e392d603SRobin Murphy 11373c0731dbSDaniel Lezcano ret = -EINVAL; 113822006994SStephen Boyd if (!irq) { 113922006994SStephen Boyd pr_err("arch_timer: Frame missing %s irq", 114022006994SStephen Boyd arch_timer_mem_use_virtual ? "virt" : "phys"); 1141e392d603SRobin Murphy goto out; 114222006994SStephen Boyd } 114322006994SStephen Boyd 114422006994SStephen Boyd arch_timer_detect_rate(base, np); 11453c0731dbSDaniel Lezcano ret = arch_timer_mem_register(base, irq); 11463c0731dbSDaniel Lezcano if (ret) 11473c0731dbSDaniel Lezcano goto out; 11483c0731dbSDaniel Lezcano 11493c0731dbSDaniel Lezcano return arch_timer_common_init(); 1150e392d603SRobin Murphy out: 1151e392d603SRobin Murphy iounmap(cntctlbase); 1152e392d603SRobin Murphy of_node_put(best_frame); 11533c0731dbSDaniel Lezcano return ret; 115422006994SStephen Boyd } 1155177cf6e5SDaniel Lezcano CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", 115622006994SStephen Boyd arch_timer_mem_init); 1157b09ca1ecSHanjun Guo 1158b09ca1ecSHanjun Guo #ifdef CONFIG_ACPI 1159b09ca1ecSHanjun Guo static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags) 1160b09ca1ecSHanjun Guo { 1161b09ca1ecSHanjun Guo int trigger, polarity; 1162b09ca1ecSHanjun Guo 1163b09ca1ecSHanjun Guo if (!interrupt) 1164b09ca1ecSHanjun Guo return 0; 1165b09ca1ecSHanjun Guo 1166b09ca1ecSHanjun Guo trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE 1167b09ca1ecSHanjun Guo : ACPI_LEVEL_SENSITIVE; 1168b09ca1ecSHanjun Guo 1169b09ca1ecSHanjun Guo polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW 1170b09ca1ecSHanjun Guo : ACPI_ACTIVE_HIGH; 1171b09ca1ecSHanjun Guo 1172b09ca1ecSHanjun Guo return acpi_register_gsi(NULL, interrupt, trigger, polarity); 1173b09ca1ecSHanjun Guo } 1174b09ca1ecSHanjun Guo 1175b09ca1ecSHanjun Guo /* Initialize per-processor generic timer */ 1176b09ca1ecSHanjun Guo static int __init arch_timer_acpi_init(struct acpi_table_header *table) 1177b09ca1ecSHanjun Guo { 1178b09ca1ecSHanjun Guo struct acpi_table_gtdt *gtdt; 1179b09ca1ecSHanjun Guo 1180b09ca1ecSHanjun Guo if (arch_timers_present & ARCH_CP15_TIMER) { 1181b09ca1ecSHanjun Guo pr_warn("arch_timer: already initialized, skipping\n"); 1182b09ca1ecSHanjun Guo return -EINVAL; 1183b09ca1ecSHanjun Guo } 1184b09ca1ecSHanjun Guo 1185b09ca1ecSHanjun Guo gtdt = container_of(table, struct acpi_table_gtdt, header); 1186b09ca1ecSHanjun Guo 1187b09ca1ecSHanjun Guo arch_timers_present |= ARCH_CP15_TIMER; 1188b09ca1ecSHanjun Guo 1189b09ca1ecSHanjun Guo arch_timer_ppi[PHYS_SECURE_PPI] = 1190b09ca1ecSHanjun Guo map_generic_timer_interrupt(gtdt->secure_el1_interrupt, 1191b09ca1ecSHanjun Guo gtdt->secure_el1_flags); 1192b09ca1ecSHanjun Guo 1193b09ca1ecSHanjun Guo arch_timer_ppi[PHYS_NONSECURE_PPI] = 1194b09ca1ecSHanjun Guo map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt, 1195b09ca1ecSHanjun Guo gtdt->non_secure_el1_flags); 1196b09ca1ecSHanjun Guo 1197b09ca1ecSHanjun Guo arch_timer_ppi[VIRT_PPI] = 1198b09ca1ecSHanjun Guo map_generic_timer_interrupt(gtdt->virtual_timer_interrupt, 1199b09ca1ecSHanjun Guo gtdt->virtual_timer_flags); 1200b09ca1ecSHanjun Guo 1201b09ca1ecSHanjun Guo arch_timer_ppi[HYP_PPI] = 1202b09ca1ecSHanjun Guo map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt, 1203b09ca1ecSHanjun Guo gtdt->non_secure_el2_flags); 1204b09ca1ecSHanjun Guo 1205b09ca1ecSHanjun Guo /* Get the frequency from CNTFRQ */ 1206b09ca1ecSHanjun Guo arch_timer_detect_rate(NULL, NULL); 1207b09ca1ecSHanjun Guo 1208b09ca1ecSHanjun Guo /* Always-on capability */ 1209b09ca1ecSHanjun Guo arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); 1210b09ca1ecSHanjun Guo 1211b09ca1ecSHanjun Guo arch_timer_init(); 1212b09ca1ecSHanjun Guo return 0; 1213b09ca1ecSHanjun Guo } 1214ae281cbdSMarc Zyngier CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init); 1215b09ca1ecSHanjun Guo #endif 1216