diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2017-04-20 08:28:34 +0200 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-04-20 08:28:34 +0200 |
commit | 26e42a020471ffc9a4086feb3900976a49cff42b (patch) | |
tree | 5b6435fa4021b020a371f97bab4637364f13f3aa /drivers/clocksource | |
parent | 821596a50aba6873ff4ea8fdf2b1515638c3c8a3 (diff) | |
parent | ca9ae5ec4ef0ed13833b03297ab319676965492c (diff) |
Merge tag 'arch-timer-gtdt' of git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux into timers/core
Pull arch timer GTDT support from Mark Rutland
- arch_timer cleanups and refactoring
- new common GTDT parser
- GTDT-based MMIO arch_timer support
- GTDT-based SBSA watchdog support
Fix up a trivial pr_err() conflict.
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 573 |
1 files changed, 371 insertions, 202 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 74183a7315ac..2208fa4eafee 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -33,6 +33,9 @@ #include <clocksource/arm_arch_timer.h> +#undef pr_fmt +#define pr_fmt(fmt) "arch_timer: " fmt + #define CNTTIDR 0x08 #define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4)) @@ -52,8 +55,6 @@ #define CNTV_TVAL 0x38 #define CNTV_CTL 0x3c -#define ARCH_CP15_TIMER BIT(0) -#define ARCH_MEM_TIMER BIT(1) static unsigned arch_timers_present __initdata; static void __iomem *arch_counter_base; @@ -66,20 +67,11 @@ struct arch_timer { #define to_arch_timer(e) container_of(e, struct arch_timer, evt) static u32 arch_timer_rate; - -enum ppi_nr { - PHYS_SECURE_PPI, - PHYS_NONSECURE_PPI, - VIRT_PPI, - HYP_PPI, - MAX_TIMER_PPI -}; - -static int arch_timer_ppi[MAX_TIMER_PPI]; +static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI]; static struct clock_event_device __percpu *arch_timer_evt; -static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI; +static enum arch_timer_ppi_nr arch_timer_uses_ppi = ARCH_TIMER_VIRT_PPI; static bool arch_timer_c3stop; static bool arch_timer_mem_use_virtual; static bool arch_counter_suspend_stop; @@ -683,7 +675,7 @@ static void __arch_timer_setup(unsigned type, { clk->features = CLOCK_EVT_FEAT_ONESHOT; - if (type == ARCH_CP15_TIMER) { + if (type == ARCH_TIMER_TYPE_CP15) { if (arch_timer_c3stop) clk->features |= CLOCK_EVT_FEAT_C3STOP; clk->name = "arch_sys_timer"; @@ -691,14 +683,14 @@ static void __arch_timer_setup(unsigned type, clk->cpumask = cpumask_of(smp_processor_id()); clk->irq = arch_timer_ppi[arch_timer_uses_ppi]; switch (arch_timer_uses_ppi) { - case VIRT_PPI: + case ARCH_TIMER_VIRT_PPI: clk->set_state_shutdown = arch_timer_shutdown_virt; clk->set_state_oneshot_stopped = arch_timer_shutdown_virt; clk->set_next_event = arch_timer_set_next_event_virt; break; - case PHYS_SECURE_PPI: - case PHYS_NONSECURE_PPI: - case HYP_PPI: + case ARCH_TIMER_PHYS_SECURE_PPI: + case ARCH_TIMER_PHYS_NONSECURE_PPI: + case ARCH_TIMER_HYP_PPI: clk->set_state_shutdown = arch_timer_shutdown_phys; clk->set_state_oneshot_stopped = arch_timer_shutdown_phys; clk->set_next_event = arch_timer_set_next_event_phys; @@ -786,8 +778,8 @@ static void arch_counter_set_user_access(void) static bool arch_timer_has_nonsecure_ppi(void) { - return (arch_timer_uses_ppi == PHYS_SECURE_PPI && - arch_timer_ppi[PHYS_NONSECURE_PPI]); + return (arch_timer_uses_ppi == ARCH_TIMER_PHYS_SECURE_PPI && + arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]); } static u32 check_ppi_trigger(int irq) @@ -808,14 +800,15 @@ static int arch_timer_starting_cpu(unsigned int cpu) struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); u32 flags; - __arch_timer_setup(ARCH_CP15_TIMER, clk); + __arch_timer_setup(ARCH_TIMER_TYPE_CP15, clk); flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]); enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags); if (arch_timer_has_nonsecure_ppi()) { - flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]); - enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags); + flags = check_ppi_trigger(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]); + enable_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI], + flags); } arch_counter_set_user_access(); @@ -825,43 +818,39 @@ static int arch_timer_starting_cpu(unsigned int cpu) return 0; } -static void -arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) +/* + * For historical reasons, when probing with DT we use whichever (non-zero) + * rate was probed first, and don't verify that others match. If the first node + * probed has a clock-frequency property, this overrides the HW register. + */ +static void arch_timer_of_configure_rate(u32 rate, struct device_node *np) { /* Who has more than one independent system counter? */ if (arch_timer_rate) return; - /* - * Try to determine the frequency from the device tree or CNTFRQ, - * if ACPI is enabled, get the frequency from CNTFRQ ONLY. - */ - if (!acpi_disabled || - of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { - if (cntbase) - arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); - else - arch_timer_rate = arch_timer_get_cntfrq(); - } + if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) + arch_timer_rate = rate; /* Check the timer frequency. */ if (arch_timer_rate == 0) - pr_warn("Architected timer frequency not available\n"); + pr_warn("frequency not available\n"); } static void arch_timer_banner(unsigned type) { - pr_info("Architected %s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n", - type & ARCH_CP15_TIMER ? "cp15" : "", - type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? " and " : "", - type & ARCH_MEM_TIMER ? "mmio" : "", - (unsigned long)arch_timer_rate / 1000000, - (unsigned long)(arch_timer_rate / 10000) % 100, - type & ARCH_CP15_TIMER ? - (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" : + pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n", + type & ARCH_TIMER_TYPE_CP15 ? "cp15" : "", + type == (ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM) ? + " and " : "", + type & ARCH_TIMER_TYPE_MEM ? "mmio" : "", + (unsigned long)arch_timer_rate / 1000000, + (unsigned long)(arch_timer_rate / 10000) % 100, + type & ARCH_TIMER_TYPE_CP15 ? + (arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) ? "virt" : "phys" : "", - type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", - type & ARCH_MEM_TIMER ? + type == (ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM) ? "/" : "", + type & ARCH_TIMER_TYPE_MEM ? arch_timer_mem_use_virtual ? "virt" : "phys" : ""); } @@ -896,8 +885,9 @@ static void __init arch_counter_register(unsigned type) u64 start_count; /* Register the CP15 based counter if we have one */ - if (type & ARCH_CP15_TIMER) { - if (IS_ENABLED(CONFIG_ARM64) || arch_timer_uses_ppi == VIRT_PPI) + if (type & ARCH_TIMER_TYPE_CP15) { + if (IS_ENABLED(CONFIG_ARM64) || + arch_timer_uses_ppi == ARCH_TIMER_VIRT_PPI) arch_timer_read_counter = arch_counter_get_cntvct; else arch_timer_read_counter = arch_counter_get_cntpct; @@ -922,12 +912,11 @@ static void __init arch_counter_register(unsigned type) static void arch_timer_stop(struct clock_event_device *clk) { - pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", - clk->irq, smp_processor_id()); + pr_debug("disable IRQ%d cpu #%d\n", clk->irq, smp_processor_id()); disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]); if (arch_timer_has_nonsecure_ppi()) - disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]); + disable_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]); clk->set_state_shutdown(clk); } @@ -990,24 +979,24 @@ static int __init arch_timer_register(void) ppi = arch_timer_ppi[arch_timer_uses_ppi]; switch (arch_timer_uses_ppi) { - case VIRT_PPI: + case ARCH_TIMER_VIRT_PPI: err = request_percpu_irq(ppi, arch_timer_handler_virt, "arch_timer", arch_timer_evt); break; - case PHYS_SECURE_PPI: - case PHYS_NONSECURE_PPI: + case ARCH_TIMER_PHYS_SECURE_PPI: + case ARCH_TIMER_PHYS_NONSECURE_PPI: err = request_percpu_irq(ppi, arch_timer_handler_phys, "arch_timer", arch_timer_evt); - if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) { - ppi = arch_timer_ppi[PHYS_NONSECURE_PPI]; + if (!err && arch_timer_has_nonsecure_ppi()) { + ppi = arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI]; err = request_percpu_irq(ppi, arch_timer_handler_phys, "arch_timer", arch_timer_evt); if (err) - free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], + free_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_SECURE_PPI], arch_timer_evt); } break; - case HYP_PPI: + case ARCH_TIMER_HYP_PPI: err = request_percpu_irq(ppi, arch_timer_handler_phys, "arch_timer", arch_timer_evt); break; @@ -1016,8 +1005,7 @@ static int __init arch_timer_register(void) } if (err) { - pr_err("arch_timer: can't register interrupt %d (%d)\n", - ppi, err); + pr_err("can't register interrupt %d (%d)\n", ppi, err); goto out_free; } @@ -1040,7 +1028,7 @@ out_unreg_cpupm: out_unreg_notify: free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt); if (arch_timer_has_nonsecure_ppi()) - free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], + free_percpu_irq(arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI], arch_timer_evt); out_free: @@ -1061,7 +1049,7 @@ static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq) t->base = base; t->evt.irq = irq; - __arch_timer_setup(ARCH_MEM_TIMER, &t->evt); + __arch_timer_setup(ARCH_TIMER_TYPE_MEM, &t->evt); if (arch_timer_mem_use_virtual) func = arch_timer_handler_virt_mem; @@ -1070,7 +1058,7 @@ static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq) ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &t->evt); if (ret) { - pr_err("arch_timer: Failed to request mem timer irq\n"); + pr_err("Failed to request mem timer irq\n"); kfree(t); } @@ -1088,15 +1076,28 @@ static const struct of_device_id arch_timer_mem_of_match[] __initconst = { {}, }; -static bool __init -arch_timer_needs_probing(int type, const struct of_device_id *matches) +static bool __init arch_timer_needs_of_probing(void) { struct device_node *dn; bool needs_probing = false; + unsigned int mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM; + + /* We have two timers, and both device-tree nodes are probed. */ + if ((arch_timers_present & mask) == mask) + return false; - dn = of_find_matching_node(NULL, matches); - if (dn && of_device_is_available(dn) && !(arch_timers_present & type)) + /* + * Only one type of timer is probed, + * check if we have another type of timer node in device-tree. + */ + if (arch_timers_present & ARCH_TIMER_TYPE_CP15) + dn = of_find_matching_node(NULL, arch_timer_mem_of_match); + else + dn = of_find_matching_node(NULL, arch_timer_of_match); + + if (dn && of_device_is_available(dn)) needs_probing = true; + of_node_put(dn); return needs_probing; @@ -1104,82 +1105,61 @@ arch_timer_needs_probing(int type, const struct of_device_id *matches) static int __init arch_timer_common_init(void) { - unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER; - - /* Wait until both nodes are probed if we have two timers */ - if ((arch_timers_present & mask) != mask) { - if (arch_timer_needs_probing(ARCH_MEM_TIMER, arch_timer_mem_of_match)) - return 0; - if (arch_timer_needs_probing(ARCH_CP15_TIMER, arch_timer_of_match)) - return 0; - } - arch_timer_banner(arch_timers_present); arch_counter_register(arch_timers_present); return arch_timer_arch_init(); } -static int __init arch_timer_init(void) +/** + * arch_timer_select_ppi() - Select suitable PPI for the current system. + * + * If HYP mode is available, we know that the physical timer + * has been configured to be accessible from PL1. Use it, so + * that a guest can use the virtual timer instead. + * + * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE + * accesses to CNTP_*_EL1 registers are silently redirected to + * their CNTHP_*_EL2 counterparts, and use a different PPI + * number. + * + * If no interrupt provided for virtual timer, we'll have to + * stick to the physical timer. It'd better be accessible... + * For arm64 we never use the secure interrupt. + * + * Return: a suitable PPI type for the current system. + */ +static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void) { - int ret; - /* - * If HYP mode is available, we know that the physical timer - * has been configured to be accessible from PL1. Use it, so - * that a guest can use the virtual timer instead. - * - * If no interrupt provided for virtual timer, we'll have to - * stick to the physical timer. It'd better be accessible... - * - * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE - * accesses to CNTP_*_EL1 registers are silently redirected to - * their CNTHP_*_EL2 counterparts, and use a different PPI - * number. - */ - if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) { - bool has_ppi; - - if (is_kernel_in_hyp_mode()) { - arch_timer_uses_ppi = HYP_PPI; - has_ppi = !!arch_timer_ppi[HYP_PPI]; - } else { - arch_timer_uses_ppi = PHYS_SECURE_PPI; - has_ppi = (!!arch_timer_ppi[PHYS_SECURE_PPI] || - !!arch_timer_ppi[PHYS_NONSECURE_PPI]); - } - - if (!has_ppi) { - pr_warn("arch_timer: No interrupt available, giving up\n"); - return -EINVAL; - } - } + if (is_kernel_in_hyp_mode()) + return ARCH_TIMER_HYP_PPI; - ret = arch_timer_register(); - if (ret) - return ret; + if (!is_hyp_mode_available() && arch_timer_ppi[ARCH_TIMER_VIRT_PPI]) + return ARCH_TIMER_VIRT_PPI; - ret = arch_timer_common_init(); - if (ret) - return ret; + if (IS_ENABLED(CONFIG_ARM64)) + return ARCH_TIMER_PHYS_NONSECURE_PPI; - arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI]; - - return 0; + return ARCH_TIMER_PHYS_SECURE_PPI; } static int __init arch_timer_of_init(struct device_node *np) { - int i; + int i, ret; + u32 rate; - if (arch_timers_present & ARCH_CP15_TIMER) { - pr_warn("arch_timer: multiple nodes in dt, skipping\n"); + if (arch_timers_present & ARCH_TIMER_TYPE_CP15) { + pr_warn("multiple nodes in dt, skipping\n"); return 0; } - arch_timers_present |= ARCH_CP15_TIMER; - for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) + arch_timers_present |= ARCH_TIMER_TYPE_CP15; + for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++) arch_timer_ppi[i] = irq_of_parse_and_map(np, i); - arch_timer_detect_rate(NULL, np); + arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; + + rate = arch_timer_get_cntfrq(); + arch_timer_of_configure_rate(rate, np); arch_timer_c3stop = !of_property_read_bool(np, "always-on"); @@ -1192,29 +1172,63 @@ static int __init arch_timer_of_init(struct device_node *np) */ if (IS_ENABLED(CONFIG_ARM) && of_property_read_bool(np, "arm,cpu-registers-not-fw-configured")) - arch_timer_uses_ppi = PHYS_SECURE_PPI; + arch_timer_uses_ppi = ARCH_TIMER_PHYS_SECURE_PPI; + else + arch_timer_uses_ppi = arch_timer_select_ppi(); + + if (!arch_timer_ppi[arch_timer_uses_ppi]) { + pr_err("No interrupt available, giving up\n"); + return -EINVAL; + } /* On some systems, the counter stops ticking when in suspend. */ arch_counter_suspend_stop = of_property_read_bool(np, "arm,no-tick-in-suspend"); - return arch_timer_init(); + ret = arch_timer_register(); + if (ret) + return ret; + + if (arch_timer_needs_of_probing()) + return 0; + + return arch_timer_common_init(); } CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init); CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init); -static int __init arch_timer_mem_init(struct device_node *np) +static u32 __init +arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame) +{ + void __iomem *base; + u32 rate; + + base = ioremap(frame->cntbase, frame->size); + if (!base) { + pr_err("Unable to map frame @ %pa\n", &frame->cntbase); + return 0; + } + + rate = readl_relaxed(frame + CNTFRQ); + + iounmap(frame); + + return rate; +} + +static struct arch_timer_mem_frame * __init +arch_timer_mem_find_best_frame(struct arch_timer_mem *timer_mem) { - struct device_node *frame, *best_frame = NULL; - void __iomem *cntctlbase, *base; - unsigned int irq, ret = -EINVAL; + struct arch_timer_mem_frame *frame, *best_frame = NULL; + void __iomem *cntctlbase; u32 cnttidr; + int i; - arch_timers_present |= ARCH_MEM_TIMER; - cntctlbase = of_iomap(np, 0); + cntctlbase = ioremap(timer_mem->cntctlbase, timer_mem->size); if (!cntctlbase) { - pr_err("arch_timer: Can't find CNTCTLBase\n"); - return -ENXIO; + pr_err("Can't map CNTCTLBase @ %pa\n", + &timer_mem->cntctlbase); + return NULL; } cnttidr = readl_relaxed(cntctlbase + CNTTIDR); @@ -1223,25 +1237,20 @@ static int __init arch_timer_mem_init(struct device_node *np) * Try to find a virtual capable frame. Otherwise fall back to a * physical capable frame. */ - for_each_available_child_of_node(np, frame) { - int n; - u32 cntacr; + for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) { + u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT | + CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT; - if (of_property_read_u32(frame, "frame-number", &n)) { - pr_err("arch_timer: Missing frame-number\n"); - of_node_put(frame); - goto out; - } + frame = &timer_mem->frame[i]; + if (!frame->valid) + continue; /* Try enabling everything, and see what sticks */ - cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT | - CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT; - writel_relaxed(cntacr, cntctlbase + CNTACR(n)); - cntacr = readl_relaxed(cntctlbase + CNTACR(n)); + writel_relaxed(cntacr, cntctlbase + CNTACR(i)); + cntacr = readl_relaxed(cntctlbase + CNTACR(i)); - if ((cnttidr & CNTTIDR_VIRT(n)) && + if ((cnttidr & CNTTIDR_VIRT(i)) && !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) { - of_node_put(best_frame); best_frame = frame; arch_timer_mem_use_virtual = true; break; @@ -1250,102 +1259,262 @@ static int __init arch_timer_mem_init(struct device_node *np) if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT)) continue; - of_node_put(best_frame); - best_frame = of_node_get(frame); + best_frame = frame; } - ret= -ENXIO; - base = arch_counter_base = of_io_request_and_map(best_frame, 0, - "arch_mem_timer"); - if (IS_ERR(base)) { - pr_err("arch_timer: Can't map frame's registers\n"); - goto out; - } + iounmap(cntctlbase); + + if (!best_frame) + pr_err("Unable to find a suitable frame in timer @ %pa\n", + &timer_mem->cntctlbase); + + return frame; +} + +static int __init +arch_timer_mem_frame_register(struct arch_timer_mem_frame *frame) +{ + void __iomem *base; + int ret, irq = 0; if (arch_timer_mem_use_virtual) - irq = irq_of_parse_and_map(best_frame, 1); + irq = frame->virt_irq; else - irq = irq_of_parse_and_map(best_frame, 0); + irq = frame->phys_irq; - ret = -EINVAL; if (!irq) { - pr_err("arch_timer: Frame missing %s irq\n", + pr_err("Frame missing %s irq.\n", arch_timer_mem_use_virtual ? "virt" : "phys"); - goto out; + return -EINVAL; + } + + if (!request_mem_region(frame->cntbase, frame->size, + "arch_mem_timer")) + return -EBUSY; + + base = ioremap(frame->cntbase, frame->size); + if (!base) { + pr_err("Can't map frame's registers\n"); + return -ENXIO; } - arch_timer_detect_rate(base, np); ret = arch_timer_mem_register(base, irq); - if (ret) + if (ret) { + iounmap(base); + return ret; + } + + arch_counter_base = base; + arch_timers_present |= ARCH_TIMER_TYPE_MEM; + + return 0; +} + +static int __init arch_timer_mem_of_init(struct device_node *np) +{ + struct arch_timer_mem *timer_mem; + struct arch_timer_mem_frame *frame; + struct device_node *frame_node; + struct resource res; + int ret = -EINVAL; + u32 rate; + + timer_mem = kzalloc(sizeof(*timer_mem), GFP_KERNEL); + if (!timer_mem) + return -ENOMEM; + + if (of_address_to_resource(np, 0, &res)) goto out; + timer_mem->cntctlbase = res.start; + timer_mem->size = resource_size(&res); - return arch_timer_common_init(); + for_each_available_child_of_node(np, frame_node) { + u32 n; + struct arch_timer_mem_frame *frame; + + if (of_property_read_u32(frame_node, "frame-number", &n)) { + pr_err(FW_BUG "Missing frame-number.\n"); + of_node_put(frame_node); + goto out; + } + if (n >= ARCH_TIMER_MEM_MAX_FRAMES) { + pr_err(FW_BUG "Wrong frame-number, only 0-%u are permitted.\n", + ARCH_TIMER_MEM_MAX_FRAMES - 1); + of_node_put(frame_node); + goto out; + } + frame = &timer_mem->frame[n]; + + if (frame->valid) { + pr_err(FW_BUG "Duplicated frame-number.\n"); + of_node_put(frame_node); + goto out; + } + + if (of_address_to_resource(frame_node, 0, &res)) { + of_node_put(frame_node); + goto out; + } + frame->cntbase = res.start; + frame->size = resource_size(&res); + + frame->virt_irq = irq_of_parse_and_map(frame_node, + ARCH_TIMER_VIRT_SPI); + frame->phys_irq = irq_of_parse_and_map(frame_node, + ARCH_TIMER_PHYS_SPI); + + frame->valid = true; + } + + frame = arch_timer_mem_find_best_frame(timer_mem); + if (!frame) { + ret = -EINVAL; + goto out; + } + + rate = arch_timer_mem_frame_get_cntfrq(frame); + arch_timer_of_configure_rate(rate, np); + + ret = arch_timer_mem_frame_register(frame); + if (!ret && !arch_timer_needs_of_probing()) + ret = arch_timer_common_init(); out: - iounmap(cntctlbase); - of_node_put(best_frame); + kfree(timer_mem); return ret; } CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", - arch_timer_mem_init); + arch_timer_mem_of_init); -#ifdef CONFIG_ACPI -static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags) +#ifdef CONFIG_ACPI_GTDT +static int __init +arch_timer_mem_verify_cntfrq(struct arch_timer_mem *timer_mem) { - int trigger, polarity; + struct arch_timer_mem_frame *frame; + u32 rate; + int i; - if (!interrupt) - return 0; + for (i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) { + frame = &timer_mem->frame[i]; - trigger = (flags & ACPI_GTDT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE - : ACPI_LEVEL_SENSITIVE; + if (!frame->valid) + continue; - polarity = (flags & ACPI_GTDT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW - : ACPI_ACTIVE_HIGH; + rate = arch_timer_mem_frame_get_cntfrq(frame); + if (rate == arch_timer_rate) + continue; - return acpi_register_gsi(NULL, interrupt, trigger, polarity); + pr_err(FW_BUG "CNTFRQ mismatch: frame @ %pa: (0x%08lx), CPU: (0x%08lx)\n", + &frame->cntbase, + (unsigned long)rate, (unsigned long)arch_timer_rate); + + return -EINVAL; + } + + return 0; +} + +static int __init arch_timer_mem_acpi_init(int platform_timer_count) +{ + struct arch_timer_mem *timers, *timer; + struct arch_timer_mem_frame *frame; + int timer_count, i, ret = 0; + + timers = kcalloc(platform_timer_count, sizeof(*timers), + GFP_KERNEL); + if (!timers) + return -ENOMEM; + + ret = acpi_arch_timer_mem_init(timers, &timer_count); + if (ret || !timer_count) + goto out; + + for (i = 0; i < timer_count; i++) { + ret = arch_timer_mem_verify_cntfrq(&timers[i]); + if (ret) { + pr_err("Disabling MMIO timers due to CNTFRQ mismatch\n"); + goto out; + } + } + + /* + * While unlikely, it's theoretically possible that none of the frames + * in a timer expose the combination of feature we want. + */ + for (i = i; i < timer_count; i++) { + timer = &timers[i]; + + frame = arch_timer_mem_find_best_frame(timer); + if (frame) + break; + } + + if (frame) + ret = arch_timer_mem_frame_register(frame); +out: + kfree(timers); + return ret; } -/* Initialize per-processor generic timer */ +/* Initialize per-processor generic timer and memory-mapped timer(if present) */ static int __init arch_timer_acpi_init(struct acpi_table_header *table) { - struct acpi_table_gtdt *gtdt; + int ret, platform_timer_count; - if (arch_timers_present & ARCH_CP15_TIMER) { - pr_warn("arch_timer: already initialized, skipping\n"); + if (arch_timers_present & ARCH_TIMER_TYPE_CP15) { + pr_warn("already initialized, skipping\n"); return -EINVAL; } - gtdt = container_of(table, struct acpi_table_gtdt, header); + arch_timers_present |= ARCH_TIMER_TYPE_CP15; + + ret = acpi_gtdt_init(table, &platform_timer_count); + if (ret) { + pr_err("Failed to init GTDT table.\n"); + return ret; + } - arch_timers_present |= ARCH_CP15_TIMER; + arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI] = + acpi_gtdt_map_ppi(ARCH_TIMER_PHYS_NONSECURE_PPI); - arch_timer_ppi[PHYS_SECURE_PPI] = - map_generic_timer_interrupt(gtdt->secure_el1_interrupt, - gtdt->secure_el1_flags); + arch_timer_ppi[ARCH_TIMER_VIRT_PPI] = + acpi_gtdt_map_ppi(ARCH_TIMER_VIRT_PPI); - arch_timer_ppi[PHYS_NONSECURE_PPI] = - map_generic_timer_interrupt(gtdt->non_secure_el1_interrupt, - gtdt->non_secure_el1_flags); + arch_timer_ppi[ARCH_TIMER_HYP_PPI] = + acpi_gtdt_map_ppi(ARCH_TIMER_HYP_PPI); - arch_timer_ppi[VIRT_PPI] = - map_generic_timer_interrupt(gtdt->virtual_timer_interrupt, - gtdt->virtual_timer_flags); + arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI]; - arch_timer_ppi[HYP_PPI] = - map_generic_timer_interrupt(gtdt->non_secure_el2_interrupt, - gtdt->non_secure_el2_flags); + /* + * When probing via ACPI, we have no mechanism to override the sysreg + * CNTFRQ value. This *must* be correct. + */ + arch_timer_rate = arch_timer_get_cntfrq(); + if (!arch_timer_rate) { + pr_err(FW_BUG "frequency not available.\n"); + return -EINVAL; + } - /* Get the frequency from CNTFRQ */ - arch_timer_detect_rate(NULL, NULL); + arch_timer_uses_ppi = arch_timer_select_ppi(); + if (!arch_timer_ppi[arch_timer_uses_ppi]) { + pr_err("No interrupt available, giving up\n"); + return -EINVAL; + } /* Always-on capability */ - arch_timer_c3stop = !(gtdt->non_secure_el1_flags & ACPI_GTDT_ALWAYS_ON); + arch_timer_c3stop = acpi_gtdt_c3stop(arch_timer_uses_ppi); /* Check for globally applicable workarounds */ arch_timer_check_ool_workaround(ate_match_acpi_oem_info, table); - arch_timer_init(); - return 0; + ret = arch_timer_register(); + if (ret) + return ret; + + if (platform_timer_count && + arch_timer_mem_acpi_init(platform_timer_count)) + pr_err("Failed to initialize memory-mapped timer.\n"); + + return arch_timer_common_init(); } CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init); #endif |