Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <noamc@ezchip.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Stultz <john.stultz@linaro.org>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>

authored by

Noam Camus and committed by
Vineet Gupta
a5322457 ebc326be

+124
+15
Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
··· 1 + NPS Network Processor 2 + 3 + Required properties: 4 + 5 + - compatible : should be "ezchip,nps400-timer" 6 + 7 + Clocks required for compatible = "ezchip,nps400-timer": 8 + - clocks : Must contain a single entry describing the clock input 9 + 10 + Example: 11 + 12 + timer { 13 + compatible = "ezchip,nps400-timer"; 14 + clocks = <&sysclk>; 15 + };
+10
drivers/clocksource/Kconfig
··· 181 181 This option enables support for Texas Instruments 32.768 Hz clocksource 182 182 available on many OMAP-like platforms. 183 183 184 + config CLKSRC_NPS 185 + bool "NPS400 clocksource driver" if COMPILE_TEST 186 + depends on !PHYS_ADDR_T_64BIT 187 + select CLKSRC_MMIO 188 + select CLKSRC_OF if OF 189 + help 190 + NPS400 clocksource support. 191 + Got 64 bit counter with update rate up to 1000MHz. 192 + This counter is accessed via couple of 32 bit memory mapped registers. 193 + 184 194 config CLKSRC_STM32 185 195 bool "Clocksource for STM32 SoCs" if !ARCH_STM32 186 196 depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
+1
drivers/clocksource/Makefile
··· 46 46 obj-$(CONFIG_MTK_TIMER) += mtk_timer.o 47 47 obj-$(CONFIG_CLKSRC_PISTACHIO) += time-pistachio.o 48 48 obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o 49 + obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o 49 50 50 51 obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o 51 52 obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
+98
drivers/clocksource/timer-nps.c
··· 1 + /* 2 + * Copyright (c) 2016, Mellanox Technologies. All rights reserved. 3 + * 4 + * This software is available to you under a choice of one of two 5 + * licenses. You may choose to be licensed under the terms of the GNU 6 + * General Public License (GPL) Version 2, available from the file 7 + * COPYING in the main directory of this source tree, or the 8 + * OpenIB.org BSD license below: 9 + * 10 + * Redistribution and use in source and binary forms, with or 11 + * without modification, are permitted provided that the following 12 + * conditions are met: 13 + * 14 + * - Redistributions of source code must retain the above 15 + * copyright notice, this list of conditions and the following 16 + * disclaimer. 17 + * 18 + * - Redistributions in binary form must reproduce the above 19 + * copyright notice, this list of conditions and the following 20 + * disclaimer in the documentation and/or other materials 21 + * provided with the distribution. 22 + * 23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 + * SOFTWARE. 31 + */ 32 + 33 + #include <linux/interrupt.h> 34 + #include <linux/clocksource.h> 35 + #include <linux/clockchips.h> 36 + #include <linux/clk.h> 37 + #include <linux/of.h> 38 + #include <linux/of_irq.h> 39 + #include <linux/cpu.h> 40 + #include <soc/nps/common.h> 41 + 42 + #define NPS_MSU_TICK_LOW 0xC8 43 + #define NPS_CLUSTER_OFFSET 8 44 + #define NPS_CLUSTER_NUM 16 45 + 46 + /* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */ 47 + static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly; 48 + 49 + static unsigned long nps_timer_rate; 50 + 51 + static cycle_t nps_clksrc_read(struct clocksource *clksrc) 52 + { 53 + int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET; 54 + 55 + return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]); 56 + } 57 + 58 + static void __init nps_setup_clocksource(struct device_node *node, 59 + struct clk *clk) 60 + { 61 + int ret, cluster; 62 + 63 + for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++) 64 + nps_msu_reg_low_addr[cluster] = 65 + nps_host_reg((cluster << NPS_CLUSTER_OFFSET), 66 + NPS_MSU_BLKID, NPS_MSU_TICK_LOW); 67 + 68 + ret = clk_prepare_enable(clk); 69 + if (ret) { 70 + pr_err("Couldn't enable parent clock\n"); 71 + return; 72 + } 73 + 74 + nps_timer_rate = clk_get_rate(clk); 75 + 76 + ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick", 77 + nps_timer_rate, 301, 32, nps_clksrc_read); 78 + if (ret) { 79 + pr_err("Couldn't register clock source.\n"); 80 + clk_disable_unprepare(clk); 81 + } 82 + } 83 + 84 + static void __init nps_timer_init(struct device_node *node) 85 + { 86 + struct clk *clk; 87 + 88 + clk = of_clk_get(node, 0); 89 + if (IS_ERR(clk)) { 90 + pr_err("Can't get timer clock.\n"); 91 + return; 92 + } 93 + 94 + nps_setup_clocksource(node, clk); 95 + } 96 + 97 + CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer", 98 + nps_timer_init);