From b4d6ce9776e0fb773418efe8bc81d8c5ccca3493 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Mon, 11 Apr 2016 16:32:51 +0100 Subject: clocksource: arm_arch_timer: Gather KVM specific information in a structure Introduce a structure which are filled up by the arch timer driver and used by the virtual timer in KVM. The first member of this structure will be the timecounter. More members will be added later. A stub for the new helper isn't introduced because KVM requires the arch timer for both ARM64 and ARM32. The function arch_timer_get_timecounter is kept for the time being and will be dropped in a subsequent patch. Signed-off-by: Julien Grall Acked-by: Christoffer Dall Signed-off-by: Christoffer Dall --- drivers/clocksource/arm_arch_timer.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 5152b3898155..62bdfe7067e3 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -468,11 +468,16 @@ static struct cyclecounter cyclecounter = { .mask = CLOCKSOURCE_MASK(56), }; -static struct timecounter timecounter; +static struct arch_timer_kvm_info arch_timer_kvm_info; + +struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) +{ + return &arch_timer_kvm_info; +} struct timecounter *arch_timer_get_timecounter(void) { - return &timecounter; + return &arch_timer_kvm_info.timecounter; } static void __init arch_counter_register(unsigned type) @@ -500,7 +505,8 @@ static void __init arch_counter_register(unsigned type) clocksource_register_hz(&clocksource_counter, arch_timer_rate); cyclecounter.mult = clocksource_counter.mult; cyclecounter.shift = clocksource_counter.shift; - timecounter_init(&timecounter, &cyclecounter, start_count); + timecounter_init(&arch_timer_kvm_info.timecounter, + &cyclecounter, start_count); /* 56 bits minimum, so we assume worst case rollover */ sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate); -- cgit v1.3-8-gc7d7 From d9b5e41591ca6bc6678e287b5ffe7fac2e07436e Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Mon, 11 Apr 2016 16:32:52 +0100 Subject: clocksource: arm_arch_timer: Extend arch_timer_kvm_info to get the virtual IRQ Currently, the firmware table is parsed by the virtual timer code in order to retrieve the virtual timer interrupt. However, this is already done by the arch timer driver. To avoid code duplication, extend arch_timer_kvm_info to get the virtual IRQ. Note that the KVM code will be modified in a subsequent patch. Signed-off-by: Julien Grall Acked-by: Christoffer Dall Signed-off-by: Christoffer Dall --- drivers/clocksource/arm_arch_timer.c | 2 ++ include/clocksource/arm_arch_timer.h | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 62bdfe7067e3..bb58224eea36 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -750,6 +750,8 @@ static void __init arch_timer_init(void) arch_timer_register(); arch_timer_common_init(); + + arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI]; } static void __init arch_timer_of_init(struct device_node *np) diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index 9101ed6b5550..9dd996a67e9e 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h @@ -51,6 +51,7 @@ enum arch_timer_reg { struct arch_timer_kvm_info { struct timecounter timecounter; + int virtual_irq; }; #ifdef CONFIG_ARM_ARCH_TIMER -- cgit v1.3-8-gc7d7 From a53d892dfb6f14f77c508e1027f5e1bdb400fd23 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Mon, 11 Apr 2016 16:33:00 +0100 Subject: clocksource: arm_arch_timer: Remove arch_timer_get_timecounter The only call of arch_timer_get_timecounter (in KVM) has been removed. Signed-off-by: Julien Grall Acked-by: Christoffer Dall Signed-off-by: Christoffer Dall --- drivers/clocksource/arm_arch_timer.c | 5 ----- include/clocksource/arm_arch_timer.h | 6 ------ 2 files changed, 11 deletions(-) (limited to 'drivers/clocksource') diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index bb58224eea36..4814446a0024 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -475,11 +475,6 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void) return &arch_timer_kvm_info; } -struct timecounter *arch_timer_get_timecounter(void) -{ - return &arch_timer_kvm_info.timecounter; -} - static void __init arch_counter_register(unsigned type) { u64 start_count; diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index 9dd996a67e9e..caedb74c9210 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h @@ -58,7 +58,6 @@ struct arch_timer_kvm_info { extern u32 arch_timer_get_rate(void); extern u64 (*arch_timer_read_counter)(void); -extern struct timecounter *arch_timer_get_timecounter(void); extern struct arch_timer_kvm_info *arch_timer_get_kvm_info(void); #else @@ -73,11 +72,6 @@ static inline u64 arch_timer_read_counter(void) return 0; } -static inline struct timecounter *arch_timer_get_timecounter(void) -{ - return NULL; -} - #endif #endif -- cgit v1.3-8-gc7d7 From a53224577e317d010f61aa1b1b8b18f2b168a137 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 17 Oct 2015 22:37:30 +0300 Subject: clocksource: Add NPS400 timers driver Add internal tick generator which is shared by all cores. Each cluster of cores view it through dedicated address. This is used for SMP system where all CPUs synced by same clock source. Signed-off-by: Noam Camus Cc: Daniel Lezcano Cc: Rob Herring Cc: Thomas Gleixner Cc: John Stultz Acked-by: Vineet Gupta Acked-by: Daniel Lezcano --- .../bindings/timer/ezchip,nps400-timer.txt | 15 ++++ drivers/clocksource/Kconfig | 10 +++ drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-nps.c | 98 ++++++++++++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt create mode 100644 drivers/clocksource/timer-nps.c (limited to 'drivers/clocksource') diff --git a/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt new file mode 100644 index 000000000000..c8c03d700382 --- /dev/null +++ b/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt @@ -0,0 +1,15 @@ +NPS Network Processor + +Required properties: + +- compatible : should be "ezchip,nps400-timer" + +Clocks required for compatible = "ezchip,nps400-timer": +- clocks : Must contain a single entry describing the clock input + +Example: + +timer { + compatible = "ezchip,nps400-timer"; + clocks = <&sysclk>; +}; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index c346be650892..3932d093b6e8 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -181,6 +181,16 @@ config CLKSRC_TI_32K This option enables support for Texas Instruments 32.768 Hz clocksource available on many OMAP-like platforms. +config CLKSRC_NPS + bool "NPS400 clocksource driver" if COMPILE_TEST + depends on !PHYS_ADDR_T_64BIT + select CLKSRC_MMIO + select CLKSRC_OF if OF + help + NPS400 clocksource support. + Got 64 bit counter with update rate up to 1000MHz. + This counter is accessed via couple of 32 bit memory mapped registers. + config CLKSRC_STM32 bool "Clocksource for STM32 SoCs" if !ARCH_STM32 depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST) diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index dc2b8997f6e6..0b0a4b5a6d20 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_CLKSRC_QCOM) += qcom-timer.o obj-$(CONFIG_MTK_TIMER) += mtk_timer.o obj-$(CONFIG_CLKSRC_PISTACHIO) += time-pistachio.o obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o +obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c new file mode 100644 index 000000000000..d46108920b2c --- /dev/null +++ b/drivers/clocksource/timer-nps.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, Mellanox Technologies. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NPS_MSU_TICK_LOW 0xC8 +#define NPS_CLUSTER_OFFSET 8 +#define NPS_CLUSTER_NUM 16 + +/* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */ +static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly; + +static unsigned long nps_timer_rate; + +static cycle_t nps_clksrc_read(struct clocksource *clksrc) +{ + int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET; + + return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]); +} + +static void __init nps_setup_clocksource(struct device_node *node, + struct clk *clk) +{ + int ret, cluster; + + for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++) + nps_msu_reg_low_addr[cluster] = + nps_host_reg((cluster << NPS_CLUSTER_OFFSET), + NPS_MSU_BLKID, NPS_MSU_TICK_LOW); + + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("Couldn't enable parent clock\n"); + return; + } + + nps_timer_rate = clk_get_rate(clk); + + ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick", + nps_timer_rate, 301, 32, nps_clksrc_read); + if (ret) { + pr_err("Couldn't register clock source.\n"); + clk_disable_unprepare(clk); + } +} + +static void __init nps_timer_init(struct device_node *node) +{ + struct clk *clk; + + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) { + pr_err("Can't get timer clock.\n"); + return; + } + + nps_setup_clocksource(node, clk); +} + +CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer", + nps_timer_init); -- cgit v1.3-8-gc7d7