whiterose

linux unikernel
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/whiterose

commit 9f687dddc4e1a3101f1ceb7fbaddbf93f93a7788
parent e4b99d415c3908581d4703203e1e805f043a3e71
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Tue, 25 Dec 2018 15:44:08 -0800

Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer updates from Thomas Gleixner:
 "The timer department delivers the following christmas presents:

  Core code:

   - Use proper seqcount initializer to make lockdep happy

   - SPDX annotations and cleanup of license boilerplates

   - Use DEFINE_SHOW_ATTRIBUTE() instead of open coding it

   - Minor cleanups

  Driver code:

   - Add the sched_clock for the arc timer (Alexey Brodkin)

   - Change the file timer names for riscv, rockchip, tegra20, sun4i and
     meson6 (Daniel Lezcano)

   - Add the DT bindings for r8a7796, r8a77470 and r8a774a1 (Biju Das)

   - Remove the early platform driver registration for timer-ti-dm
     (Bartosz Golaszewski)

   - Provide the sched_clock for the riscv timer (Anup Patel)

   - Add support for ARM64 for the imx-gpt and convert the imx-tpm to
     the timer-of API (Anson Huang)

   - Remove useless irq protection for the imx-gpt (Clément Péron)

   - Remove a duplicate function name for the vt8500 (Dan Carpenter)

   - Remove obsolete inclusion of <asm/smp_twd.h> for the tegra20 (Geert
     Uytterhoeven)

   - Demote the prcmu and the custom sched_clock for the dbx500 and the
     ux500 (Linus Walleij)

   - Add a new timer clock for the RDA8810PL (Manivannan Sadhasivam)

   - Rename the macro to stick to the register name and add the delay
     timer (Martin Blumenstingl)

   - Switch the bcm2835 to the SPDX identifier (Stefan Wahren)

   - Fix the interrupt register access on the fttmr010 (Tao Ren)

   - Add missing of_node_put in the initialization path on the
     integrator-ap (Yangtao Li)"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (39 commits)
  dt-bindings: timer: Document RDA8810PL SoC timer
  clocksource/drivers/rda: Add clock driver for RDA8810PL SoC
  clocksource/drivers/meson6: Change name meson6_timer timer-meson6
  clocksource/drivers/sun4i: Change name sun4i_timer to timer-sun4i
  clocksource/drivers/tegra20: Change name tegra20_timer to timer-tegra20
  clocksource/drivers/rockchip: Change name rockchip_timer to timer-rockchip
  clocksource/drivers/riscv: Change name riscv_timer to timer-riscv
  clocksource/drivers/riscv_timer: Provide the sched_clock
  clocksource/drivers/timer-imx-tpm: Specify clock name for timer-of
  clocksource/drivers/fttmr010: Fix invalid interrupt register access
  clocksource/drivers/integrator-ap: Add missing of_node_put()
  clocksource/drivers/bcm2835: Switch to SPDX identifier
  dt-bindings: timer: renesas, cmt: Document r8a774a1 CMT support
  clocksource/drivers/timer-imx-tpm: Convert the driver to timer-of
  clocksource/drivers/arc_timer: Utilize generic sched_clock
  dt-bindings: timer: renesas, cmt: Document r8a77470 CMT support
  dt-bindings: timer: renesas, cmt: Document r8a7796 CMT support
  clocksource/drivers/imx-gpt: Remove unnecessary irq protection
  clocksource/drivers/imx-gpt: Add support for ARM64
  clocksource/drivers/meson6_timer: Implement the ARM delay timer
  ...

Diffstat:
ADocumentation/devicetree/bindings/timer/rda,8810pl-timer.txt | 20++++++++++++++++++++
MDocumentation/devicetree/bindings/timer/renesas,cmt.txt | 15++++++++++++---
March/arc/Kconfig | 1+
Mdrivers/clocksource/Kconfig | 26+++++++++++---------------
Mdrivers/clocksource/Makefile | 11++++++-----
Mdrivers/clocksource/arc_timer.c | 22++++++++++++++++++++++
Mdrivers/clocksource/bcm2835_timer.c | 15+--------------
Mdrivers/clocksource/clksrc-dbx500-prcmu.c | 22++--------------------
Ddrivers/clocksource/meson6_timer.c | 178-------------------------------------------------------------------------------
Mdrivers/clocksource/nomadik-mtu.c | 4----
Ddrivers/clocksource/riscv_timer.c | 109-------------------------------------------------------------------------------
Ddrivers/clocksource/tegra20_timer.c | 264-------------------------------------------------------------------------------
Mdrivers/clocksource/timer-fttmr010.c | 73++++++++++++++++++++++++++++++++++++++++++-------------------------------
Mdrivers/clocksource/timer-imx-gpt.c | 21++++-----------------
Mdrivers/clocksource/timer-imx-tpm.c | 139+++++++++++++++++++++++++++++++++----------------------------------------------
Mdrivers/clocksource/timer-integrator-ap.c | 25++++++++++++++++---------
Adrivers/clocksource/timer-meson6.c | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adrivers/clocksource/timer-rda.c | 195+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adrivers/clocksource/timer-riscv.c | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rdrivers/clocksource/rockchip_timer.c -> drivers/clocksource/timer-rockchip.c | 0
Rdrivers/clocksource/sun4i_timer.c -> drivers/clocksource/timer-sun4i.c | 0
Adrivers/clocksource/timer-tegra20.c | 263+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdrivers/clocksource/timer-ti-dm.c | 1-
Mdrivers/clocksource/timer-vt8500.c | 2+-
Minclude/linux/hrtimer.h | 5+----
Mkernel/time/alarmtimer.c | 5+----
Mkernel/time/clockevents.c | 18++++--------------
Mkernel/time/clocksource.c | 20+-------------------
Mkernel/time/hrtimer.c | 19+++++--------------
Mkernel/time/itimer.c | 2--
Mkernel/time/jiffies.c | 28++++++----------------------
Mkernel/time/ntp.c | 1-
Mkernel/time/posix-clock.c | 17++---------------
Mkernel/time/posix-stubs.c | 5+----
Mkernel/time/posix-timers.c | 25++-----------------------
Mkernel/time/sched_clock.c | 9+++------
Mkernel/time/test_udelay.c | 10+---------
Mkernel/time/tick-broadcast-hrtimer.c | 4+---
Mkernel/time/tick-broadcast.c | 6+-----
Mkernel/time/tick-common.c | 6+-----
Mkernel/time/tick-oneshot.c | 6+-----
Mkernel/time/tick-sched.c | 5+----
Mkernel/time/time.c | 13+++++--------
Mkernel/time/timeconst.bc | 2++
Mkernel/time/timeconv.c | 1+
Mkernel/time/timecounter.c | 17++---------------
Mkernel/time/timekeeping.c | 15++++++---------
Mkernel/time/timekeeping_debug.c | 26+++-----------------------
Mkernel/time/timer.c | 3+--
Mkernel/time/timer_list.c | 7+------
50 files changed, 1045 insertions(+), 974 deletions(-)

diff --git a/Documentation/devicetree/bindings/timer/rda,8810pl-timer.txt b/Documentation/devicetree/bindings/timer/rda,8810pl-timer.txt @@ -0,0 +1,20 @@ +RDA Micro RDA8810PL Timer + +Required properties: +- compatible : "rda,8810pl-timer" +- reg : Offset and length of the register set for the device. +- interrupts : Should contain two interrupts. +- interrupt-names : Should be "hwtimer", "ostimer". + +Example: + + apb@20900000 { + compatible = "simple-bus"; + ... + timer@10000 { + compatible = "rda,8810pl-timer"; + reg = <0x10000 0x1000>; + interrupts = <16 IRQ_TYPE_LEVEL_HIGH>, + <17 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "hwtimer", "ostimer"; + }; diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt b/Documentation/devicetree/bindings/timer/renesas,cmt.txt @@ -28,6 +28,10 @@ Required Properties: - "renesas,r8a7744-cmt1" for the 48-bit CMT1 device included in r8a7744. - "renesas,r8a7745-cmt0" for the 32-bit CMT0 device included in r8a7745. - "renesas,r8a7745-cmt1" for the 48-bit CMT1 device included in r8a7745. + - "renesas,r8a77470-cmt0" for the 32-bit CMT0 device included in r8a77470. + - "renesas,r8a77470-cmt1" for the 48-bit CMT1 device included in r8a77470. + - "renesas,r8a774a1-cmt0" for the 32-bit CMT0 device included in r8a774a1. + - "renesas,r8a774a1-cmt1" for the 48-bit CMT1 device included in r8a774a1. - "renesas,r8a7790-cmt0" for the 32-bit CMT0 device included in r8a7790. - "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790. - "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791. @@ -36,6 +40,8 @@ Required Properties: - "renesas,r8a7793-cmt1" for the 48-bit CMT1 device included in r8a7793. - "renesas,r8a7794-cmt0" for the 32-bit CMT0 device included in r8a7794. - "renesas,r8a7794-cmt1" for the 48-bit CMT1 device included in r8a7794. + - "renesas,r8a7796-cmt0" for the 32-bit CMT0 device included in r8a7796. + - "renesas,r8a7796-cmt1" for the 48-bit CMT1 device included in r8a7796. - "renesas,r8a77970-cmt0" for the 32-bit CMT0 device included in r8a77970. - "renesas,r8a77970-cmt1" for the 48-bit CMT1 device included in r8a77970. - "renesas,r8a77980-cmt0" for the 32-bit CMT0 device included in r8a77980. @@ -47,9 +53,12 @@ Required Properties: and RZ/G1. These are fallbacks for r8a73a4, R-Car Gen2 and RZ/G1 entries listed above. - - "renesas,rcar-gen3-cmt0" for 32-bit CMT0 devices included in R-Car Gen3. - - "renesas,rcar-gen3-cmt1" for 48-bit CMT1 devices included in R-Car Gen3. - These are fallbacks for R-Car Gen3 entries listed above. + - "renesas,rcar-gen3-cmt0" for 32-bit CMT0 devices included in R-Car Gen3 + and RZ/G2. + - "renesas,rcar-gen3-cmt1" for 48-bit CMT1 devices included in R-Car Gen3 + and RZ/G2. + These are fallbacks for R-Car Gen3 and RZ/G2 entries listed + above. - reg: base address and length of the registers block for the timer module. - interrupts: interrupt-specifier for the timer, one per channel. diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig @@ -26,6 +26,7 @@ config ARC select GENERIC_IRQ_SHOW select GENERIC_PCI_IOMAP select GENERIC_PENDING_IRQ if SMP + select GENERIC_SCHED_CLOCK select GENERIC_SMP_IDLE_THREAD select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig @@ -105,6 +105,14 @@ config OWL_TIMER help Enables the support for the Actions Semi Owl timer driver. +config RDA_TIMER + bool "RDA timer driver" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS + select CLKSRC_MMIO + select TIMER_OF + help + Enables the support for the RDA Micro timer driver. + config SUN4I_TIMER bool "Sun4i timer driver" if COMPILE_TEST depends on HAS_IOMEM @@ -163,12 +171,6 @@ config CLKSRC_NOMADIK_MTU to multiple interrupt generating programmable 32-bit free running decrementing counters. -config CLKSRC_NOMADIK_MTU_SCHED_CLOCK - bool - depends on CLKSRC_NOMADIK_MTU - help - Use the Multi Timer Unit as the sched_clock. - config CLKSRC_DBX500_PRCMU bool "Clocksource PRCMU Timer" if COMPILE_TEST depends on HAS_IOMEM @@ -226,13 +228,6 @@ config INTEGRATOR_AP_TIMER help Enables support for the Integrator-ap timer. -config CLKSRC_DBX500_PRCMU_SCHED_CLOCK - bool "Clocksource PRCMU Timer sched_clock" - depends on (CLKSRC_DBX500_PRCMU && !CLKSRC_NOMADIK_MTU_SCHED_CLOCK) - default y - help - Use the always on PRCMU Timer as sched_clock - config CLKSRC_EFM32 bool "Clocksource for Energy Micro's EFM32 SoCs" if !ARCH_EFM32 depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST) @@ -290,6 +285,7 @@ config CLKSRC_MPS2 config ARC_TIMERS bool "Support for 32-bit TIMERn counters in ARC Cores" if COMPILE_TEST + depends on GENERIC_SCHED_CLOCK select TIMER_OF help These are legacy 32-bit TIMER0 and TIMER1 counters found on all ARC cores @@ -580,7 +576,7 @@ config H8300_TPU config CLKSRC_IMX_GPT bool "Clocksource using i.MX GPT" if COMPILE_TEST - depends on ARM && CLKDEV_LOOKUP + depends on (ARM || ARM64) && CLKDEV_LOOKUP select CLKSRC_MMIO config CLKSRC_IMX_TPM @@ -611,7 +607,7 @@ config ATCPIT100_TIMER config RISCV_TIMER bool "Timer for the RISC-V platform" - depends on RISCV + depends on GENERIC_SCHED_CLOCK && RISCV default y select TIMER_PROBE select TIMER_OF diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile @@ -20,7 +20,7 @@ obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.o -obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o +obj-$(CONFIG_ROCKCHIP_TIMER) += timer-rockchip.o obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o obj-$(CONFIG_ARMADA_370_XP_TIMER) += timer-armada-370-xp.o @@ -32,10 +32,10 @@ obj-$(CONFIG_MXS_TIMER) += mxs_timer.o obj-$(CONFIG_CLKSRC_PXA) += pxa_timer.o obj-$(CONFIG_PRIMA2_TIMER) += timer-prima2.o obj-$(CONFIG_U300_TIMER) += timer-u300.o -obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o +obj-$(CONFIG_SUN4I_TIMER) += timer-sun4i.o obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o -obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o -obj-$(CONFIG_TEGRA_TIMER) += tegra20_timer.o +obj-$(CONFIG_MESON6_TIMER) += timer-meson6.o +obj-$(CONFIG_TEGRA_TIMER) += timer-tegra20.o obj-$(CONFIG_VT8500_TIMER) += timer-vt8500.o obj-$(CONFIG_NSPIRE_TIMER) += timer-zevio.o obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o @@ -57,6 +57,7 @@ obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o obj-$(CONFIG_OWL_TIMER) += timer-owl.o obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o +obj-$(CONFIG_RDA_TIMER) += timer-rda.o obj-$(CONFIG_ARC_TIMERS) += arc_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o @@ -78,6 +79,6 @@ obj-$(CONFIG_H8300_TPU) += h8300_tpu.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o obj-$(CONFIG_X86_NUMACHIP) += numachip.o obj-$(CONFIG_ATCPIT100_TIMER) += timer-atcpit100.o -obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o +obj-$(CONFIG_RISCV_TIMER) += timer-riscv.o obj-$(CONFIG_CSKY_MP_TIMER) += timer-mp-csky.o obj-$(CONFIG_GX6605S_TIMER) += timer-gx6605s.o diff --git a/drivers/clocksource/arc_timer.c b/drivers/clocksource/arc_timer.c @@ -23,6 +23,7 @@ #include <linux/cpu.h> #include <linux/of.h> #include <linux/of_irq.h> +#include <linux/sched_clock.h> #include <soc/arc/timers.h> #include <soc/arc/mcip.h> @@ -88,6 +89,11 @@ static u64 arc_read_gfrc(struct clocksource *cs) return (((u64)h) << 32) | l; } +static notrace u64 arc_gfrc_clock_read(void) +{ + return arc_read_gfrc(NULL); +} + static struct clocksource arc_counter_gfrc = { .name = "ARConnect GFRC", .rating = 400, @@ -111,6 +117,8 @@ static int __init arc_cs_setup_gfrc(struct device_node *node) if (ret) return ret; + sched_clock_register(arc_gfrc_clock_read, 64, arc_timer_freq); + return clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq); } TIMER_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc); @@ -139,6 +147,11 @@ static u64 arc_read_rtc(struct clocksource *cs) return (((u64)h) << 32) | l; } +static notrace u64 arc_rtc_clock_read(void) +{ + return arc_read_rtc(NULL); +} + static struct clocksource arc_counter_rtc = { .name = "ARCv2 RTC", .rating = 350, @@ -170,6 +183,8 @@ static int __init arc_cs_setup_rtc(struct device_node *node) write_aux_reg(AUX_RTC_CTRL, 1); + sched_clock_register(arc_rtc_clock_read, 64, arc_timer_freq); + return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq); } TIMER_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc); @@ -185,6 +200,11 @@ static u64 arc_read_timer1(struct clocksource *cs) return (u64) read_aux_reg(ARC_REG_TIMER1_CNT); } +static notrace u64 arc_timer1_clock_read(void) +{ + return arc_read_timer1(NULL); +} + static struct clocksource arc_counter_timer1 = { .name = "ARC Timer1", .rating = 300, @@ -209,6 +229,8 @@ static int __init arc_cs_setup_timer1(struct device_node *node) write_aux_reg(ARC_REG_TIMER1_CNT, 0); write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH); + sched_clock_register(arc_timer1_clock_read, 32, arc_timer_freq); + return clocksource_register_hz(&arc_counter_timer1, arc_timer_freq); } diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2012 Simon Arlott - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/bitops.h> diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c @@ -15,7 +15,6 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/clockchips.h> -#include <linux/sched_clock.h> #define RATE_32K 32768 @@ -26,8 +25,6 @@ #define PRCMU_TIMER_DOWNCOUNT 0x4 #define PRCMU_TIMER_MODE 0x8 -#define SCHED_CLOCK_MIN_WRAP 131072 /* 2^32 / 32768 */ - static void __iomem *clksrc_dbx500_timer_base; static u64 notrace clksrc_dbx500_prcmu_read(struct clocksource *cs) @@ -46,24 +43,12 @@ static u64 notrace clksrc_dbx500_prcmu_read(struct clocksource *cs) static struct clocksource clocksource_dbx500_prcmu = { .name = "dbx500-prcmu-timer", - .rating = 300, + .rating = 100, .read = clksrc_dbx500_prcmu_read, .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP, }; -#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK - -static u64 notrace dbx500_prcmu_sched_clock_read(void) -{ - if (unlikely(!clksrc_dbx500_timer_base)) - return 0; - - return clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu); -} - -#endif - static int __init clksrc_dbx500_prcmu_init(struct device_node *node) { clksrc_dbx500_timer_base = of_iomap(node, 0); @@ -81,9 +66,6 @@ static int __init clksrc_dbx500_prcmu_init(struct device_node *node) writel(TIMER_DOWNCOUNT_VAL, clksrc_dbx500_timer_base + PRCMU_TIMER_REF); } -#ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK - sched_clock_register(dbx500_prcmu_sched_clock_read, 32, RATE_32K); -#endif return clocksource_register_hz(&clocksource_dbx500_prcmu, RATE_32K); } TIMER_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4", diff --git a/drivers/clocksource/meson6_timer.c b/drivers/clocksource/meson6_timer.c @@ -1,178 +0,0 @@ -/* - * Amlogic Meson6 SoCs timer handling. - * - * Copyright (C) 2014 Carlo Caione <carlo@caione.org> - * - * Based on code from Amlogic, Inc - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/clk.h> -#include <linux/clockchips.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/irqreturn.h> -#include <linux/sched_clock.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> - -#define CED_ID 0 -#define CSD_ID 4 - -#define TIMER_ISA_MUX 0 -#define TIMER_ISA_VAL(t) (((t) + 1) << 2) - -#define TIMER_INPUT_BIT(t) (2 * (t)) -#define TIMER_ENABLE_BIT(t) (16 + (t)) -#define TIMER_PERIODIC_BIT(t) (12 + (t)) - -#define TIMER_CED_INPUT_MASK (3UL << TIMER_INPUT_BIT(CED_ID)) -#define TIMER_CSD_INPUT_MASK (7UL << TIMER_INPUT_BIT(CSD_ID)) - -#define TIMER_CED_UNIT_1US 0 -#define TIMER_CSD_UNIT_1US 1 - -static void __iomem *timer_base; - -static u64 notrace meson6_timer_sched_read(void) -{ - return (u64)readl(timer_base + TIMER_ISA_VAL(CSD_ID)); -} - -static void meson6_clkevt_time_stop(unsigned char timer) -{ - u32 val = readl(timer_base + TIMER_ISA_MUX); - - writel(val & ~TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX); -} - -static void meson6_clkevt_time_setup(unsigned char timer, unsigned long delay) -{ - writel(delay, timer_base + TIMER_ISA_VAL(timer)); -} - -static void meson6_clkevt_time_start(unsigned char timer, bool periodic) -{ - u32 val = readl(timer_base + TIMER_ISA_MUX); - - if (periodic) - val |= TIMER_PERIODIC_BIT(timer); - else - val &= ~TIMER_PERIODIC_BIT(timer); - - writel(val | TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX); -} - -static int meson6_shutdown(struct clock_event_device *evt) -{ - meson6_clkevt_time_stop(CED_ID); - return 0; -} - -static int meson6_set_oneshot(struct clock_event_device *evt) -{ - meson6_clkevt_time_stop(CED_ID); - meson6_clkevt_time_start(CED_ID, false); - return 0; -} - -static int meson6_set_periodic(struct clock_event_device *evt) -{ - meson6_clkevt_time_stop(CED_ID); - meson6_clkevt_time_setup(CED_ID, USEC_PER_SEC / HZ - 1); - meson6_clkevt_time_start(CED_ID, true); - return 0; -} - -static int meson6_clkevt_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - meson6_clkevt_time_stop(CED_ID); - meson6_clkevt_time_setup(CED_ID, evt); - meson6_clkevt_time_start(CED_ID, false); - - return 0; -} - -static struct clock_event_device meson6_clockevent = { - .name = "meson6_tick", - .rating = 400, - .features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT, - .set_state_shutdown = meson6_shutdown, - .set_state_periodic = meson6_set_periodic, - .set_state_oneshot = meson6_set_oneshot, - .tick_resume = meson6_shutdown, - .set_next_event = meson6_clkevt_next_event, -}; - -static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = (struct clock_event_device *)dev_id; - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction meson6_timer_irq = { - .name = "meson6_timer", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = meson6_timer_interrupt, - .dev_id = &meson6_clockevent, -}; - -static int __init meson6_timer_init(struct device_node *node) -{ - u32 val; - int ret, irq; - - timer_base = of_io_request_and_map(node, 0, "meson6-timer"); - if (IS_ERR(timer_base)) { - pr_err("Can't map registers\n"); - return -ENXIO; - } - - irq = irq_of_parse_and_map(node, 0); - if (irq <= 0) { - pr_err("Can't parse IRQ\n"); - return -EINVAL; - } - - /* Set 1us for timer E */ - val = readl(timer_base + TIMER_ISA_MUX); - val &= ~TIMER_CSD_INPUT_MASK; - val |= TIMER_CSD_UNIT_1US << TIMER_INPUT_BIT(CSD_ID); - writel(val, timer_base + TIMER_ISA_MUX); - - sched_clock_register(meson6_timer_sched_read, 32, USEC_PER_SEC); - clocksource_mmio_init(timer_base + TIMER_ISA_VAL(CSD_ID), node->name, - 1000 * 1000, 300, 32, clocksource_mmio_readl_up); - - /* Timer A base 1us */ - val &= ~TIMER_CED_INPUT_MASK; - val |= TIMER_CED_UNIT_1US << TIMER_INPUT_BIT(CED_ID); - writel(val, timer_base + TIMER_ISA_MUX); - - /* Stop the timer A */ - meson6_clkevt_time_stop(CED_ID); - - ret = setup_irq(irq, &meson6_timer_irq); - if (ret) { - pr_warn("failed to setup irq %d\n", irq); - return ret; - } - - meson6_clockevent.cpumask = cpu_possible_mask; - meson6_clockevent.irq = irq; - - clockevents_config_and_register(&meson6_clockevent, USEC_PER_SEC, - 1, 0xfffe); - return 0; -} -TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer", - meson6_timer_init); diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c @@ -69,7 +69,6 @@ static u32 clk_prescale; static u32 nmdk_cycle; /* write-once */ static struct delay_timer mtu_delay_timer; -#ifdef CONFIG_CLKSRC_NOMADIK_MTU_SCHED_CLOCK /* * Override the global weak sched_clock symbol with this * local implementation which uses the clocksource to get some @@ -82,7 +81,6 @@ static u64 notrace nomadik_read_sched_clock(void) return -readl(mtu_base + MTU_VAL(0)); } -#endif static unsigned long nmdk_timer_read_current_timer(void) { @@ -234,9 +232,7 @@ static int __init nmdk_timer_init(void __iomem *base, int irq, return ret; } -#ifdef CONFIG_CLKSRC_NOMADIK_MTU_SCHED_CLOCK sched_clock_register(nomadik_read_sched_clock, 32, rate); -#endif /* Timer 1 is used for events, register irq and clockevents */ setup_irq(irq, &nmdk_timer_irq); diff --git a/drivers/clocksource/riscv_timer.c b/drivers/clocksource/riscv_timer.c @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2012 Regents of the University of California - * Copyright (C) 2017 SiFive - */ -#include <linux/clocksource.h> -#include <linux/clockchips.h> -#include <linux/cpu.h> -#include <linux/delay.h> -#include <linux/irq.h> -#include <asm/smp.h> -#include <asm/sbi.h> - -/* - * All RISC-V systems have a timer attached to every hart. These timers can be - * read by the 'rdcycle' pseudo instruction, and can use the SBI to setup - * events. In order to abstract the architecture-specific timer reading and - * setting functions away from the clock event insertion code, we provide - * function pointers to the clockevent subsystem that perform two basic - * operations: rdtime() reads the timer on the current CPU, and - * next_event(delta) sets the next timer event to 'delta' cycles in the future. - * As the timers are inherently a per-cpu resource, these callbacks perform - * operations on the current hart. There is guaranteed to be exactly one timer - * per hart on all RISC-V systems. - */ - -static int riscv_clock_next_event(unsigned long delta, - struct clock_event_device *ce) -{ - csr_set(sie, SIE_STIE); - sbi_set_timer(get_cycles64() + delta); - return 0; -} - -static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = { - .name = "riscv_timer_clockevent", - .features = CLOCK_EVT_FEAT_ONESHOT, - .rating = 100, - .set_next_event = riscv_clock_next_event, -}; - -/* - * It is guaranteed that all the timers across all the harts are synchronized - * within one tick of each other, so while this could technically go - * backwards when hopping between CPUs, practically it won't happen. - */ -static unsigned long long riscv_clocksource_rdtime(struct clocksource *cs) -{ - return get_cycles64(); -} - -static DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = { - .name = "riscv_clocksource", - .rating = 300, - .mask = CLOCKSOURCE_MASK(BITS_PER_LONG), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, - .read = riscv_clocksource_rdtime, -}; - -static int riscv_timer_starting_cpu(unsigned int cpu) -{ - struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu); - - ce->cpumask = cpumask_of(cpu); - clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff); - - csr_set(sie, SIE_STIE); - return 0; -} - -static int riscv_timer_dying_cpu(unsigned int cpu) -{ - csr_clear(sie, SIE_STIE); - return 0; -} - -/* called directly from the low-level interrupt handler */ -void riscv_timer_interrupt(void) -{ - struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event); - - csr_clear(sie, SIE_STIE); - evdev->event_handler(evdev); -} - -static int __init riscv_timer_init_dt(struct device_node *n) -{ - int cpuid, hartid, error; - struct clocksource *cs; - - hartid = riscv_of_processor_hartid(n); - cpuid = riscv_hartid_to_cpuid(hartid); - - if (cpuid != smp_processor_id()) - return 0; - - cs = per_cpu_ptr(&riscv_clocksource, cpuid); - clocksource_register_hz(cs, riscv_timebase); - - error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING, - "clockevents/riscv/timer:starting", - riscv_timer_starting_cpu, riscv_timer_dying_cpu); - if (error) - pr_err("RISCV timer register failed [%d] for cpu = [%d]\n", - error, cpuid); - return error; -} - -TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt); diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2010 Google, Inc. - * - * Author: - * Colin Cross <ccross@google.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/init.h> -#include <linux/err.h> -#include <linux/time.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/clockchips.h> -#include <linux/clocksource.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/sched_clock.h> -#include <linux/delay.h> - -#include <asm/mach/time.h> -#include <asm/smp_twd.h> - -#define RTC_SECONDS 0x08 -#define RTC_SHADOW_SECONDS 0x0c -#define RTC_MILLISECONDS 0x10 - -#define TIMERUS_CNTR_1US 0x10 -#define TIMERUS_USEC_CFG 0x14 -#define TIMERUS_CNTR_FREEZE 0x4c - -#define TIMER1_BASE 0x0 -#define TIMER2_BASE 0x8 -#define TIMER3_BASE 0x50 -#define TIMER4_BASE 0x58 - -#define TIMER_PTV 0x0 -#define TIMER_PCR 0x4 - -static void __iomem *timer_reg_base; -static void __iomem *rtc_base; - -static struct timespec64 persistent_ts; -static u64 persistent_ms, last_persistent_ms; - -static struct delay_timer tegra_delay_timer; - -#define timer_writel(value, reg) \ - writel_relaxed(value, timer_reg_base + (reg)) -#define timer_readl(reg) \ - readl_relaxed(timer_reg_base + (reg)) - -static int tegra_timer_set_next_event(unsigned long cycles, - struct clock_event_device *evt) -{ - u32 reg; - - reg = 0x80000000 | ((cycles > 1) ? (cycles-1) : 0); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); - - return 0; -} - -static inline void timer_shutdown(struct clock_event_device *evt) -{ - timer_writel(0, TIMER3_BASE + TIMER_PTV); -} - -static int tegra_timer_shutdown(struct clock_event_device *evt) -{ - timer_shutdown(evt); - return 0; -} - -static int tegra_timer_set_periodic(struct clock_event_device *evt) -{ - u32 reg = 0xC0000000 | ((1000000 / HZ) - 1); - - timer_shutdown(evt); - timer_writel(reg, TIMER3_BASE + TIMER_PTV); - return 0; -} - -static struct clock_event_device tegra_clockevent = { - .name = "timer0", - .rating = 300, - .features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_DYNIRQ, - .set_next_event = tegra_timer_set_next_event, - .set_state_shutdown = tegra_timer_shutdown, - .set_state_periodic = tegra_timer_set_periodic, - .set_state_oneshot = tegra_timer_shutdown, - .tick_resume = tegra_timer_shutdown, -}; - -static u64 notrace tegra_read_sched_clock(void) -{ - return timer_readl(TIMERUS_CNTR_1US); -} - -/* - * tegra_rtc_read - Reads the Tegra RTC registers - * Care must be taken that this funciton is not called while the - * tegra_rtc driver could be executing to avoid race conditions - * on the RTC shadow register - */ -static u64 tegra_rtc_read_ms(void) -{ - u32 ms = readl(rtc_base + RTC_MILLISECONDS); - u32 s = readl(rtc_base + RTC_SHADOW_SECONDS); - return (u64)s * MSEC_PER_SEC + ms; -} - -/* - * tegra_read_persistent_clock64 - Return time from a persistent clock. - * - * Reads the time from a source which isn't disabled during PM, the - * 32k sync timer. Convert the cycles elapsed since last read into - * nsecs and adds to a monotonically increasing timespec64. - * Care must be taken that this funciton is not called while the - * tegra_rtc driver could be executing to avoid race conditions - * on the RTC shadow register - */ -static void tegra_read_persistent_clock64(struct timespec64 *ts) -{ - u64 delta; - - last_persistent_ms = persistent_ms; - persistent_ms = tegra_rtc_read_ms(); - delta = persistent_ms - last_persistent_ms; - - timespec64_add_ns(&persistent_ts, delta * NSEC_PER_MSEC); - *ts = persistent_ts; -} - -static unsigned long tegra_delay_timer_read_counter_long(void) -{ - return readl(timer_reg_base + TIMERUS_CNTR_1US); -} - -static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = (struct clock_event_device *)dev_id; - timer_writel(1<<30, TIMER3_BASE + TIMER_PCR); - evt->event_handler(evt); - return IRQ_HANDLED; -} - -static struct irqaction tegra_timer_irq = { - .name = "timer0", - .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH, - .handler = tegra_timer_interrupt, - .dev_id = &tegra_clockevent, -}; - -static int __init tegra20_init_timer(struct device_node *np) -{ - struct clk *clk; - unsigned long rate; - int ret; - - timer_reg_base = of_iomap(np, 0); - if (!timer_reg_base) { - pr_err("Can't map timer registers\n"); - return -ENXIO; - } - - tegra_timer_irq.irq = irq_of_parse_and_map(np, 2); - if (tegra_timer_irq.irq <= 0) { - pr_err("Failed to map timer IRQ\n"); - return -EINVAL; - } - - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) { - pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n"); - rate = 12000000; - } else { - clk_prepare_enable(clk); - rate = clk_get_rate(clk); - } - - switch (rate) { - case 12000000: - timer_writel(0x000b, TIMERUS_USEC_CFG); - break; - case 13000000: - timer_writel(0x000c, TIMERUS_USEC_CFG); - break; - case 19200000: - timer_writel(0x045f, TIMERUS_USEC_CFG); - break; - case 26000000: - timer_writel(0x0019, TIMERUS_USEC_CFG); - break; - default: - WARN(1, "Unknown clock rate"); - } - - sched_clock_register(tegra_read_sched_clock, 32, 1000000); - - ret = clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, - "timer_us", 1000000, 300, 32, - clocksource_mmio_readl_up); - if (ret) { - pr_err("Failed to register clocksource\n"); - return ret; - } - - tegra_delay_timer.read_current_timer = - tegra_delay_timer_read_counter_long; - tegra_delay_timer.freq = 1000000; - register_current_timer_delay(&tegra_delay_timer); - - ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq); - if (ret) { - pr_err("Failed to register timer IRQ: %d\n", ret); - return ret; - } - - tegra_clockevent.cpumask = cpu_possible_mask; - tegra_clockevent.irq = tegra_timer_irq.irq; - clockevents_config_and_register(&tegra_clockevent, 1000000, - 0x1, 0x1fffffff); - - return 0; -} -TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer); - -static int __init tegra20_init_rtc(struct device_node *np) -{ - struct clk *clk; - - rtc_base = of_iomap(np, 0); - if (!rtc_base) { - pr_err("Can't map RTC registers\n"); - return -ENXIO; - } - - /* - * rtc registers are used by read_persistent_clock, keep the rtc clock - * enabled - */ - clk = of_clk_get(np, 0); - if (IS_ERR(clk)) - pr_warn("Unable to get rtc-tegra clock\n"); - else - clk_prepare_enable(clk); - - return register_persistent_clock(tegra_read_persistent_clock64); -} -TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c @@ -21,7 +21,7 @@ #include <linux/delay.h> /* - * Register definitions for the timers + * Register definitions common for all the timer variants. */ #define TIMER1_COUNT (0x00) #define TIMER1_LOAD (0x04) @@ -36,9 +36,10 @@ #define TIMER3_MATCH1 (0x28) #define TIMER3_MATCH2 (0x2c) #define TIMER_CR (0x30) -#define TIMER_INTR_STATE (0x34) -#define TIMER_INTR_MASK (0x38) +/* + * Control register (TMC30) bit fields for fttmr010/gemini/moxart timers. + */ #define TIMER_1_CR_ENABLE BIT(0) #define TIMER_1_CR_CLOCK BIT(1) #define TIMER_1_CR_INT BIT(2) @@ -53,8 +54,9 @@ #define TIMER_3_CR_UPDOWN BIT(11) /* - * The Aspeed AST2400 moves bits around in the control register - * and lacks bits for setting the timer to count upwards. + * Control register (TMC30) bit fields for aspeed ast2400/ast2500 timers. + * The aspeed timers move bits around in the control register and lacks + * bits for setting the timer to count upwards. */ #define TIMER_1_CR_ASPEED_ENABLE BIT(0) #define TIMER_1_CR_ASPEED_CLOCK BIT(1) @@ -66,6 +68,18 @@ #define TIMER_3_CR_ASPEED_CLOCK BIT(9) #define TIMER_3_CR_ASPEED_INT BIT(10) +/* + * Interrupt status/mask register definitions for fttmr010/gemini/moxart + * timers. + * The registers don't exist and they are not needed on aspeed timers + * because: + * - aspeed timer overflow interrupt is controlled by bits in Control + * Register (TMC30). + * - aspeed timers always generate interrupt when either one of the + * Match registers equals to Status register. + */ +#define TIMER_INTR_STATE (0x34) +#define TIMER_INTR_MASK (0x38) #define TIMER_1_INT_MATCH1 BIT(0) #define TIMER_1_INT_MATCH2 BIT(1) #define TIMER_1_INT_OVERFLOW BIT(2) @@ -80,7 +94,7 @@ struct fttmr010 { void __iomem *base; unsigned int tick_rate; - bool count_down; + bool is_aspeed; u32 t1_enable_val; struct clock_event_device clkevt; #ifdef CONFIG_ARM @@ -130,7 +144,7 @@ static int fttmr010_timer_set_next_event(unsigned long cycles, cr &= ~fttmr010->t1_enable_val; writel(cr, fttmr010->base + TIMER_CR); - if (fttmr010->count_down) { + if (fttmr010->is_aspeed) { /* * ASPEED Timer Controller will load TIMER1_LOAD register * into TIMER1_COUNT register when the timer is re-enabled. @@ -175,16 +189,17 @@ static int fttmr010_timer_set_oneshot(struct clock_event_device *evt) /* Setup counter start from 0 or ~0 */ writel(0, fttmr010->base + TIMER1_COUNT); - if (fttmr010->count_down) + if (fttmr010->is_aspeed) { writel(~0, fttmr010->base + TIMER1_LOAD); - else + } else { writel(0, fttmr010->base + TIMER1_LOAD); - /* Enable interrupt */ - cr = readl(fttmr010->base + TIMER_INTR_MASK); - cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2); - cr |= TIMER_1_INT_MATCH1; - writel(cr, fttmr010->base + TIMER_INTR_MASK); + /* Enable interrupt */ + cr = readl(fttmr010->base + TIMER_INTR_MASK); + cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2); + cr |= TIMER_1_INT_MATCH1; + writel(cr, fttmr010->base + TIMER_INTR_MASK); + } return 0; } @@ -201,9 +216,8 @@ static int fttmr010_timer_set_periodic(struct clock_event_device *evt) writel(cr, fttmr010->base + TIMER_CR); /* Setup timer to fire at 1/HZ intervals. */ - if (fttmr010->count_down) { + if (fttmr010->is_aspeed) { writel(period, fttmr010->base + TIMER1_LOAD); - writel(0, fttmr010->base + TIMER1_MATCH1); } else { cr = 0xffffffff - (period - 1); writel(cr, fttmr010->base + TIMER1_COUNT); @@ -281,23 +295,21 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) } /* - * The Aspeed AST2400 moves bits around in the control register, - * otherwise it works the same. + * The Aspeed timers move bits around in the control register. */ if (is_aspeed) { fttmr010->t1_enable_val = TIMER_1_CR_ASPEED_ENABLE | TIMER_1_CR_ASPEED_INT; - /* Downward not available */ - fttmr010->count_down = true; + fttmr010->is_aspeed = true; } else { fttmr010->t1_enable_val = TIMER_1_CR_ENABLE | TIMER_1_CR_INT; - } - /* - * Reset the interrupt mask and status - */ - writel(TIMER_INT_ALL_MASK, fttmr010->base + TIMER_INTR_MASK); - writel(0, fttmr010->base + TIMER_INTR_STATE); + /* + * Reset the interrupt mask and status + */ + writel(TIMER_INT_ALL_MASK, fttmr010->base + TIMER_INTR_MASK); + writel(0, fttmr010->base + TIMER_INTR_STATE); + } /* * Enable timer 1 count up, timer 2 count up, except on Aspeed, @@ -306,9 +318,8 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) if (is_aspeed) val = TIMER_2_CR_ASPEED_ENABLE; else { - val = TIMER_2_CR_ENABLE; - if (!fttmr010->count_down) - val |= TIMER_1_CR_UPDOWN | TIMER_2_CR_UPDOWN; + val = TIMER_2_CR_ENABLE | TIMER_1_CR_UPDOWN | + TIMER_2_CR_UPDOWN; } writel(val, fttmr010->base + TIMER_CR); @@ -321,7 +332,7 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) writel(0, fttmr010->base + TIMER2_MATCH1); writel(0, fttmr010->base + TIMER2_MATCH2); - if (fttmr010->count_down) { + if (fttmr010->is_aspeed) { writel(~0, fttmr010->base + TIMER2_LOAD); clocksource_mmio_init(fttmr010->base + TIMER2_COUNT, "FTTMR010-TIMER2", @@ -371,7 +382,7 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) #ifdef CONFIG_ARM /* Also use this timer for delays */ - if (fttmr010->count_down) + if (fttmr010->is_aspeed) fttmr010->delay_timer.read_current_timer = fttmr010_read_current_timer_down; else diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c @@ -141,21 +141,25 @@ static u64 notrace mxc_read_sched_clock(void) return sched_clock_reg ? readl_relaxed(sched_clock_reg) : 0; } +#if defined(CONFIG_ARM) static struct delay_timer imx_delay_timer; static unsigned long imx_read_current_timer(void) { return readl_relaxed(sched_clock_reg); } +#endif static int __init mxc_clocksource_init(struct imx_timer *imxtm) { unsigned int c = clk_get_rate(imxtm->clk_per); void __iomem *reg = imxtm->base + imxtm->gpt->reg_tcn; +#if defined(CONFIG_ARM) imx_delay_timer.read_current_timer = &imx_read_current_timer; imx_delay_timer.freq = c; register_current_timer_delay(&imx_delay_timer); +#endif sched_clock_reg = reg; @@ -198,15 +202,8 @@ static int v2_set_next_event(unsigned long evt, static int mxc_shutdown(struct clock_event_device *ced) { struct imx_timer *imxtm = to_imx_timer(ced); - unsigned long flags; u32 tcn; - /* - * The timer interrupt generation is disabled at least - * for enough time to call mxc_set_next_event() - */ - local_irq_save(flags); - /* Disable interrupt in GPT module */ imxtm->gpt->gpt_irq_disable(imxtm); @@ -221,21 +218,12 @@ static int mxc_shutdown(struct clock_event_device *ced) printk(KERN_INFO "%s: changing mode\n", __func__); #endif /* DEBUG */ - local_irq_restore(flags); - return 0; } static int mxc_set_oneshot(struct clock_event_device *ced) { struct imx_timer *imxtm = to_imx_timer(ced); - unsigned long flags; - - /* - * The timer interrupt generation is disabled at least - * for enough time to call mxc_set_next_event() - */ - local_irq_save(flags); /* Disable interrupt in GPT module */ imxtm->gpt->gpt_irq_disable(imxtm); @@ -260,7 +248,6 @@ static int mxc_set_oneshot(struct clock_event_device *ced) * mode switching */ imxtm->gpt->gpt_irq_enable(imxtm); - local_irq_restore(flags); return 0; } diff --git a/drivers/clocksource/timer-imx-tpm.c b/drivers/clocksource/timer-imx-tpm.c @@ -12,6 +12,8 @@ #include <linux/of_irq.h> #include <linux/sched_clock.h> +#include "timer-of.h" + #define TPM_PARAM 0x4 #define TPM_PARAM_WIDTH_SHIFT 16 #define TPM_PARAM_WIDTH_MASK (0xff << 16) @@ -33,9 +35,7 @@ #define TPM_C0V 0x24 static int counter_width; -static int rating; static void __iomem *timer_base; -static struct clock_event_device clockevent_tpm; static inline void tpm_timer_disable(void) { @@ -80,19 +80,6 @@ static u64 notrace tpm_read_sched_clock(void) return tpm_read_counter(); } -static int __init tpm_clocksource_init(unsigned long rate) -{ - tpm_delay_timer.read_current_timer = &tpm_read_current_timer; - tpm_delay_timer.freq = rate; - register_current_timer_delay(&tpm_delay_timer); - - sched_clock_register(tpm_read_sched_clock, counter_width, rate); - - return clocksource_mmio_init(timer_base + TPM_CNT, "imx-tpm", - rate, rating, counter_width, - clocksource_mmio_readl_up); -} - static int tpm_set_next_event(unsigned long delta, struct clock_event_device *evt) { @@ -137,74 +124,80 @@ static irqreturn_t tpm_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static struct clock_event_device clockevent_tpm = { - .name = "i.MX7ULP TPM Timer", - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_state_oneshot = tpm_set_state_oneshot, - .set_next_event = tpm_set_next_event, - .set_state_shutdown = tpm_set_state_shutdown, +static struct timer_of to_tpm = { + .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK, + .clkevt = { + .name = "i.MX7ULP TPM Timer", + .rating = 200, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = tpm_set_state_shutdown, + .set_state_oneshot = tpm_set_state_oneshot, + .set_next_event = tpm_set_next_event, + .cpumask = cpu_possible_mask, + }, + .of_irq = { + .handler = tpm_timer_interrupt, + .flags = IRQF_TIMER | IRQF_IRQPOLL, + }, + .of_clk = { + .name = "per", + }, }; -static int __init tpm_clockevent_init(unsigned long rate, int irq) +static int __init tpm_clocksource_init(void) { - int ret; + tpm_delay_timer.read_current_timer = &tpm_read_current_timer; + tpm_delay_timer.freq = timer_of_rate(&to_tpm) >> 3; + register_current_timer_delay(&tpm_delay_timer); - ret = request_irq(irq, tpm_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, - "i.MX7ULP TPM Timer", &clockevent_tpm); + sched_clock_register(tpm_read_sched_clock, counter_width, + timer_of_rate(&to_tpm) >> 3); - clockevent_tpm.rating = rating; - clockevent_tpm.cpumask = cpumask_of(0); - clockevent_tpm.irq = irq; - clockevents_config_and_register(&clockevent_tpm, rate, 300, - GENMASK(counter_width - 1, 1)); + return clocksource_mmio_init(timer_base + TPM_CNT, + "imx-tpm", + timer_of_rate(&to_tpm) >> 3, + to_tpm.clkevt.rating, + counter_width, + clocksource_mmio_readl_up); +} - return ret; +static void __init tpm_clockevent_init(void) +{ + clockevents_config_and_register(&to_tpm.clkevt, + timer_of_rate(&to_tpm) >> 3, + 300, + GENMASK(counter_width - 1, + 1)); } static int __init tpm_timer_init(struct device_node *np) { - struct clk *ipg, *per; - int irq, ret; - u32 rate; - - timer_base = of_iomap(np, 0); - if (!timer_base) { - pr_err("tpm: failed to get base address\n"); - return -ENXIO; - } - - irq = irq_of_parse_and_map(np, 0); - if (!irq) { - pr_err("tpm: failed to get irq\n"); - ret = -ENOENT; - goto err_iomap; - } + struct clk *ipg; + int ret; ipg = of_clk_get_by_name(np, "ipg"); - per = of_clk_get_by_name(np, "per"); - if (IS_ERR(ipg) || IS_ERR(per)) { - pr_err("tpm: failed to get ipg or per clk\n"); - ret = -ENODEV; - goto err_clk_get; + if (IS_ERR(ipg)) { + pr_err("tpm: failed to get ipg clk\n"); + return -ENODEV; } - /* enable clk before accessing registers */ ret = clk_prepare_enable(ipg); if (ret) { pr_err("tpm: ipg clock enable failed (%d)\n", ret); - goto err_clk_get; + clk_put(ipg); + return ret; } - ret = clk_prepare_enable(per); - if (ret) { - pr_err("tpm: per clock enable failed (%d)\n", ret); - goto err_per_clk_enable; - } + ret = timer_of_init(np, &to_tpm); + if (ret) + return ret; + + timer_base = timer_of_base(&to_tpm); - counter_width = (readl(timer_base + TPM_PARAM) & TPM_PARAM_WIDTH_MASK) - >> TPM_PARAM_WIDTH_SHIFT; + counter_width = (readl(timer_base + TPM_PARAM) + & TPM_PARAM_WIDTH_MASK) >> TPM_PARAM_WIDTH_SHIFT; /* use rating 200 for 32-bit counter and 150 for 16-bit counter */ - rating = counter_width == 0x20 ? 200 : 150; + to_tpm.clkevt.rating = counter_width == 0x20 ? 200 : 150; /* * Initialize tpm module to a known state @@ -229,29 +222,13 @@ static int __init tpm_timer_init(struct device_node *np) writel(TPM_SC_CMOD_INC_PER_CNT | (counter_width == 0x20 ? TPM_SC_CMOD_DIV_DEFAULT : TPM_SC_CMOD_DIV_MAX), - timer_base + TPM_SC); + timer_base + TPM_SC); /* set MOD register to maximum for free running mode */ writel(GENMASK(counter_width - 1, 0), timer_base + TPM_MOD); - rate = clk_get_rate(per) >> 3; - ret = tpm_clocksource_init(rate); - if (ret) - goto err_per_clk_enable; - - ret = tpm_clockevent_init(rate, irq); - if (ret) - goto err_per_clk_enable; - - return 0; + tpm_clockevent_init(); -err_per_clk_enable: - clk_disable_unprepare(ipg); -err_clk_get: - clk_put(per); - clk_put(ipg); -err_iomap: - iounmap(timer_base); - return ret; + return tpm_clocksource_init(); } TIMER_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init); diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c @@ -181,8 +181,7 @@ static int __init integrator_ap_timer_init_of(struct device_node *node) int irq; struct clk *clk; unsigned long rate; - struct device_node *pri_node; - struct device_node *sec_node; + struct device_node *alias_node; base = of_io_request_and_map(node, 0, "integrator-timer"); if (IS_ERR(base)) @@ -204,7 +203,18 @@ static int __init integrator_ap_timer_init_of(struct device_node *node) return err; } - pri_node = of_find_node_by_path(path); + alias_node = of_find_node_by_path(path); + + /* + * The pointer is used as an identifier not as a pointer, we + * can drop the refcount on the of__node immediately after + * getting it. + */ + of_node_put(alias_node); + + if (node == alias_node) + /* The primary timer lacks IRQ, use as clocksource */ + return integrator_clocksource_init(rate, base); err = of_property_read_string(of_aliases, "arm,timer-secondary", &path); @@ -213,14 +223,11 @@ static int __init integrator_ap_timer_init_of(struct device_node *node) return err; } + alias_node = of_find_node_by_path(path); - sec_node = of_find_node_by_path(path); - - if (node == pri_node) - /* The primary timer lacks IRQ, use as clocksource */ - return integrator_clocksource_init(rate, base); + of_node_put(alias_node); - if (node == sec_node) { + if (node == alias_node) { /* The secondary timer will drive the clock event */ irq = irq_of_parse_and_map(node, 0); return integrator_clockevent_init(rate, base, irq); diff --git a/drivers/clocksource/timer-meson6.c b/drivers/clocksource/timer-meson6.c @@ -0,0 +1,220 @@ +/* + * Amlogic Meson6 SoCs timer handling. + * + * Copyright (C) 2014 Carlo Caione <carlo@caione.org> + * + * Based on code from Amlogic, Inc + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/clk.h> +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqreturn.h> +#include <linux/sched_clock.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> + +#ifdef CONFIG_ARM +#include <linux/delay.h> +#endif + +#define MESON_ISA_TIMER_MUX 0x00 +#define MESON_ISA_TIMER_MUX_TIMERD_EN BIT(19) +#define MESON_ISA_TIMER_MUX_TIMERC_EN BIT(18) +#define MESON_ISA_TIMER_MUX_TIMERB_EN BIT(17) +#define MESON_ISA_TIMER_MUX_TIMERA_EN BIT(16) +#define MESON_ISA_TIMER_MUX_TIMERD_MODE BIT(15) +#define MESON_ISA_TIMER_MUX_TIMERC_MODE BIT(14) +#define MESON_ISA_TIMER_MUX_TIMERB_MODE BIT(13) +#define MESON_ISA_TIMER_MUX_TIMERA_MODE BIT(12) +#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK GENMASK(10, 8) +#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_SYSTEM_CLOCK 0x0 +#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1US 0x1 +#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_10US 0x2 +#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_100US 0x3 +#define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1MS 0x4 +#define MESON_ISA_TIMER_MUX_TIMERD_INPUT_CLOCK_MASK GENMASK(7, 6) +#define MESON_ISA_TIMER_MUX_TIMERC_INPUT_CLOCK_MASK GENMASK(5, 4) +#define MESON_ISA_TIMER_MUX_TIMERB_INPUT_CLOCK_MASK GENMASK(3, 2) +#define MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK GENMASK(1, 0) +#define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1US 0x0 +#define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_10US 0x1 +#define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_100US 0x0 +#define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1MS 0x3 + +#define MESON_ISA_TIMERA 0x04 +#define MESON_ISA_TIMERB 0x08 +#define MESON_ISA_TIMERC 0x0c +#define MESON_ISA_TIMERD 0x10 +#define MESON_ISA_TIMERE 0x14 + +static void __iomem *timer_base; + +#ifdef CONFIG_ARM +static unsigned long meson6_read_current_timer(void) +{ + return readl_relaxed(timer_base + MESON_ISA_TIMERE); +} + +static struct delay_timer meson6_delay_timer = { + .read_current_timer = meson6_read_current_timer, + .freq = 1000 * 1000, +}; +#endif + +static u64 notrace meson6_timer_sched_read(void) +{ + return (u64)readl(timer_base + MESON_ISA_TIMERE); +} + +static void meson6_clkevt_time_stop(void) +{ + u32 val = readl(timer_base + MESON_ISA_TIMER_MUX); + + writel(val & ~MESON_ISA_TIMER_MUX_TIMERA_EN, + timer_base + MESON_ISA_TIMER_MUX); +} + +static void meson6_clkevt_time_setup(unsigned long delay) +{ + writel(delay, timer_base + MESON_ISA_TIMERA); +} + +static void meson6_clkevt_time_start(bool periodic) +{ + u32 val = readl(timer_base + MESON_ISA_TIMER_MUX); + + if (periodic) + val |= MESON_ISA_TIMER_MUX_TIMERA_MODE; + else + val &= ~MESON_ISA_TIMER_MUX_TIMERA_MODE; + + writel(val | MESON_ISA_TIMER_MUX_TIMERA_EN, + timer_base + MESON_ISA_TIMER_MUX); +} + +static int meson6_shutdown(struct clock_event_device *evt) +{ + meson6_clkevt_time_stop(); + return 0; +} + +static int meson6_set_oneshot(struct clock_event_device *evt) +{ + meson6_clkevt_time_stop(); + meson6_clkevt_time_start(false); + return 0; +} + +static int meson6_set_periodic(struct clock_event_device *evt) +{ + meson6_clkevt_time_stop(); + meson6_clkevt_time_setup(USEC_PER_SEC / HZ - 1); + meson6_clkevt_time_start(true); + return 0; +} + +static int meson6_clkevt_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + meson6_clkevt_time_stop(); + meson6_clkevt_time_setup(evt); + meson6_clkevt_time_start(false); + + return 0; +} + +static struct clock_event_device meson6_clockevent = { + .name = "meson6_tick", + .rating = 400, + .features = CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = meson6_shutdown, + .set_state_periodic = meson6_set_periodic, + .set_state_oneshot = meson6_set_oneshot, + .tick_resume = meson6_shutdown, + .set_next_event = meson6_clkevt_next_event, +}; + +static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction meson6_timer_irq = { + .name = "meson6_timer", + .flags = IRQF_TIMER | IRQF_IRQPOLL, + .handler = meson6_timer_interrupt, + .dev_id = &meson6_clockevent, +}; + +static int __init meson6_timer_init(struct device_node *node) +{ + u32 val; + int ret, irq; + + timer_base = of_io_request_and_map(node, 0, "meson6-timer"); + if (IS_ERR(timer_base)) { + pr_err("Can't map registers\n"); + return -ENXIO; + } + + irq = irq_of_parse_and_map(node, 0); + if (irq <= 0) { + pr_err("Can't parse IRQ\n"); + return -EINVAL; + } + + /* Set 1us for timer E */ + val = readl(timer_base + MESON_ISA_TIMER_MUX); + val &= ~MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK; + val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK, + MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1US); + writel(val, timer_base + MESON_ISA_TIMER_MUX); + + sched_clock_register(meson6_timer_sched_read, 32, USEC_PER_SEC); + clocksource_mmio_init(timer_base + MESON_ISA_TIMERE, node->name, + 1000 * 1000, 300, 32, clocksource_mmio_readl_up); + + /* Timer A base 1us */ + val &= ~MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK; + val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK, + MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1US); + writel(val, timer_base + MESON_ISA_TIMER_MUX); + + /* Stop the timer A */ + meson6_clkevt_time_stop(); + + ret = setup_irq(irq, &meson6_timer_irq); + if (ret) { + pr_warn("failed to setup irq %d\n", irq); + return ret; + } + + meson6_clockevent.cpumask = cpu_possible_mask; + meson6_clockevent.irq = irq; + + clockevents_config_and_register(&meson6_clockevent, USEC_PER_SEC, + 1, 0xfffe); + +#ifdef CONFIG_ARM + /* Also use MESON_ISA_TIMERE for delays */ + register_current_timer_delay(&meson6_delay_timer); +#endif + + return 0; +} +TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer", + meson6_timer_init); diff --git a/drivers/clocksource/timer-rda.c b/drivers/clocksource/timer-rda.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * RDA8810PL SoC timer driver + * + * Copyright RDA Microelectronics Company Limited + * Copyright (c) 2017 Andreas Färber + * Copyright (c) 2018 Manivannan Sadhasivam + * + * RDA8810PL has two independent timers: OSTIMER (56 bit) and HWTIMER (64 bit). + * Each timer provides optional interrupt support. In this driver, OSTIMER is + * used for clockevents and HWTIMER is used for clocksource. + */ + +#include <linux/init.h> +#include <linux/interrupt.h> + +#include "timer-of.h" + +#define RDA_OSTIMER_LOADVAL_L 0x000 +#define RDA_OSTIMER_CTRL 0x004 +#define RDA_HWTIMER_LOCKVAL_L 0x024 +#define RDA_HWTIMER_LOCKVAL_H 0x028 +#define RDA_TIMER_IRQ_MASK_SET 0x02c +#define RDA_TIMER_IRQ_MASK_CLR 0x030 +#define RDA_TIMER_IRQ_CLR 0x034 + +#define RDA_OSTIMER_CTRL_ENABLE BIT(24) +#define RDA_OSTIMER_CTRL_REPEAT BIT(28) +#define RDA_OSTIMER_CTRL_LOAD BIT(30) + +#define RDA_TIMER_IRQ_MASK_OSTIMER BIT(0) + +#define RDA_TIMER_IRQ_CLR_OSTIMER BIT(0) + +static int rda_ostimer_start(void __iomem *base, bool periodic, u64 cycles) +{ + u32 ctrl, load_l; + + load_l = (u32)cycles; + ctrl = ((cycles >> 32) & 0xffffff); + ctrl |= RDA_OSTIMER_CTRL_LOAD | RDA_OSTIMER_CTRL_ENABLE; + if (periodic) + ctrl |= RDA_OSTIMER_CTRL_REPEAT; + + /* Enable ostimer interrupt first */ + writel_relaxed(RDA_TIMER_IRQ_MASK_OSTIMER, + base + RDA_TIMER_IRQ_MASK_SET); + + /* Write low 32 bits first, high 24 bits are with ctrl */ + writel_relaxed(load_l, base + RDA_OSTIMER_LOADVAL_L); + writel_relaxed(ctrl, base + RDA_OSTIMER_CTRL); + + return 0; +} + +static int rda_ostimer_stop(void __iomem *base) +{ + /* Disable ostimer interrupt first */ + writel_relaxed(RDA_TIMER_IRQ_MASK_OSTIMER, + base + RDA_TIMER_IRQ_MASK_CLR); + + writel_relaxed(0, base + RDA_OSTIMER_CTRL); + + return 0; +} + +static int rda_ostimer_set_state_shutdown(struct clock_event_device *evt) +{ + struct timer_of *to = to_timer_of(evt); + + rda_ostimer_stop(timer_of_base(to)); + + return 0; +} + +static int rda_ostimer_set_state_oneshot(struct clock_event_device *evt) +{ + struct timer_of *to = to_timer_of(evt); + + rda_ostimer_stop(timer_of_base(to)); + + return 0; +} + +static int rda_ostimer_set_state_periodic(struct clock_event_device *evt) +{ + struct timer_of *to = to_timer_of(evt); + unsigned long cycles_per_jiffy; + + rda_ostimer_stop(timer_of_base(to)); + + cycles_per_jiffy = ((unsigned long long)NSEC_PER_SEC / HZ * + evt->mult) >> evt->shift; + rda_ostimer_start(timer_of_base(to), true, cycles_per_jiffy); + + return 0; +} + +static int rda_ostimer_tick_resume(struct clock_event_device *evt) +{ + return 0; +} + +static int rda_ostimer_set_next_event(unsigned long evt, + struct clock_event_device *ev) +{ + struct timer_of *to = to_timer_of(ev); + + rda_ostimer_start(timer_of_base(to), false, evt); + + return 0; +} + +static irqreturn_t rda_ostimer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + struct timer_of *to = to_timer_of(evt); + + /* clear timer int */ + writel_relaxed(RDA_TIMER_IRQ_CLR_OSTIMER, + timer_of_base(to) + RDA_TIMER_IRQ_CLR); + + if (evt->event_handler) + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct timer_of rda_ostimer_of = { + .flags = TIMER_OF_IRQ | TIMER_OF_BASE, + + .clkevt = { + .name = "rda-ostimer", + .rating = 250, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_DYNIRQ, + .set_state_shutdown = rda_ostimer_set_state_shutdown, + .set_state_oneshot = rda_ostimer_set_state_oneshot, + .set_state_periodic = rda_ostimer_set_state_periodic, + .tick_resume = rda_ostimer_tick_resume, + .set_next_event = rda_ostimer_set_next_event, + }, + + .of_base = { + .name = "rda-timer", + .index = 0, + }, + + .of_irq = { + .name = "ostimer", + .handler = rda_ostimer_interrupt, + .flags = IRQF_TIMER, + }, +}; + +static u64 rda_hwtimer_read(struct clocksource *cs) +{ + void __iomem *base = timer_of_base(&rda_ostimer_of); + u32 lo, hi; + + /* Always read low 32 bits first */ + do { + lo = readl_relaxed(base + RDA_HWTIMER_LOCKVAL_L); + hi = readl_relaxed(base + RDA_HWTIMER_LOCKVAL_H); + } while (hi != readl_relaxed(base + RDA_HWTIMER_LOCKVAL_H)); + + return ((u64)hi << 32) | lo; +} + +static struct clocksource rda_hwtimer_clocksource = { + .name = "rda-timer", + .rating = 400, + .read = rda_hwtimer_read, + .mask = CLOCKSOURCE_MASK(64), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int __init rda_timer_init(struct device_node *np) +{ + unsigned long rate = 2000000; + int ret; + + ret = timer_of_init(np, &rda_ostimer_of); + if (ret) + return ret; + + clocksource_register_hz(&rda_hwtimer_clocksource, rate); + + clockevents_config_and_register(&rda_ostimer_of.clkevt, rate, + 0x2, UINT_MAX); + + return 0; +} + +TIMER_OF_DECLARE(rda8810pl, "rda,8810pl-timer", rda_timer_init); diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012 Regents of the University of California + * Copyright (C) 2017 SiFive + */ +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/cpu.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/sched_clock.h> +#include <asm/smp.h> +#include <asm/sbi.h> + +/* + * All RISC-V systems have a timer attached to every hart. These timers can be + * read by the 'rdcycle' pseudo instruction, and can use the SBI to setup + * events. In order to abstract the architecture-specific timer reading and + * setting functions away from the clock event insertion code, we provide + * function pointers to the clockevent subsystem that perform two basic + * operations: rdtime() reads the timer on the current CPU, and + * next_event(delta) sets the next timer event to 'delta' cycles in the future. + * As the timers are inherently a per-cpu resource, these callbacks perform + * operations on the current hart. There is guaranteed to be exactly one timer + * per hart on all RISC-V systems. + */ + +static int riscv_clock_next_event(unsigned long delta, + struct clock_event_device *ce) +{ + csr_set(sie, SIE_STIE); + sbi_set_timer(get_cycles64() + delta); + return 0; +} + +static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = { + .name = "riscv_timer_clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 100, + .set_next_event = riscv_clock_next_event, +}; + +/* + * It is guaranteed that all the timers across all the harts are synchronized + * within one tick of each other, so while this could technically go + * backwards when hopping between CPUs, practically it won't happen. + */ +static unsigned long long riscv_clocksource_rdtime(struct clocksource *cs) +{ + return get_cycles64(); +} + +static u64 riscv_sched_clock(void) +{ + return get_cycles64(); +} + +static DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = { + .name = "riscv_clocksource", + .rating = 300, + .mask = CLOCKSOURCE_MASK(BITS_PER_LONG), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, + .read = riscv_clocksource_rdtime, +}; + +static int riscv_timer_starting_cpu(unsigned int cpu) +{ + struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu); + + ce->cpumask = cpumask_of(cpu); + clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff); + + csr_set(sie, SIE_STIE); + return 0; +} + +static int riscv_timer_dying_cpu(unsigned int cpu) +{ + csr_clear(sie, SIE_STIE); + return 0; +} + +/* called directly from the low-level interrupt handler */ +void riscv_timer_interrupt(void) +{ + struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event); + + csr_clear(sie, SIE_STIE); + evdev->event_handler(evdev); +} + +static int __init riscv_timer_init_dt(struct device_node *n) +{ + int cpuid, hartid, error; + struct clocksource *cs; + + hartid = riscv_of_processor_hartid(n); + cpuid = riscv_hartid_to_cpuid(hartid); + + if (cpuid != smp_processor_id()) + return 0; + + cs = per_cpu_ptr(&riscv_clocksource, cpuid); + clocksource_register_hz(cs, riscv_timebase); + + sched_clock_register(riscv_sched_clock, + BITS_PER_LONG, riscv_timebase); + + error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING, + "clockevents/riscv/timer:starting", + riscv_timer_starting_cpu, riscv_timer_dying_cpu); + if (error) + pr_err("RISCV timer register failed [%d] for cpu = [%d]\n", + error, cpuid); + return error; +} + +TIMER_OF_DECLARE(riscv_timer, "riscv", riscv_timer_init_dt); diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/timer-rockchip.c diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/timer-sun4i.c diff --git a/drivers/clocksource/timer-tegra20.c b/drivers/clocksource/timer-tegra20.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2010 Google, Inc. + * + * Author: + * Colin Cross <ccross@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/init.h> +#include <linux/err.h> +#include <linux/time.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/clockchips.h> +#include <linux/clocksource.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/sched_clock.h> +#include <linux/delay.h> + +#include <asm/mach/time.h> + +#define RTC_SECONDS 0x08 +#define RTC_SHADOW_SECONDS 0x0c +#define RTC_MILLISECONDS 0x10 + +#define TIMERUS_CNTR_1US 0x10 +#define TIMERUS_USEC_CFG 0x14 +#define TIMERUS_CNTR_FREEZE 0x4c + +#define TIMER1_BASE 0x0 +#define TIMER2_BASE 0x8 +#define TIMER3_BASE 0x50 +#define TIMER4_BASE 0x58 + +#define TIMER_PTV 0x0 +#define TIMER_PCR 0x4 + +static void __iomem *timer_reg_base; +static void __iomem *rtc_base; + +static struct timespec64 persistent_ts; +static u64 persistent_ms, last_persistent_ms; + +static struct delay_timer tegra_delay_timer; + +#define timer_writel(value, reg) \ + writel_relaxed(value, timer_reg_base + (reg)) +#define timer_readl(reg) \ + readl_relaxed(timer_reg_base + (reg)) + +static int tegra_timer_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + u32 reg; + + reg = 0x80000000 | ((cycles > 1) ? (cycles-1) : 0); + timer_writel(reg, TIMER3_BASE + TIMER_PTV); + + return 0; +} + +static inline void timer_shutdown(struct clock_event_device *evt) +{ + timer_writel(0, TIMER3_BASE + TIMER_PTV); +} + +static int tegra_timer_shutdown(struct clock_event_device *evt) +{ + timer_shutdown(evt); + return 0; +} + +static int tegra_timer_set_periodic(struct clock_event_device *evt) +{ + u32 reg = 0xC0000000 | ((1000000 / HZ) - 1); + + timer_shutdown(evt); + timer_writel(reg, TIMER3_BASE + TIMER_PTV); + return 0; +} + +static struct clock_event_device tegra_clockevent = { + .name = "timer0", + .rating = 300, + .features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC | + CLOCK_EVT_FEAT_DYNIRQ, + .set_next_event = tegra_timer_set_next_event, + .set_state_shutdown = tegra_timer_shutdown, + .set_state_periodic = tegra_timer_set_periodic, + .set_state_oneshot = tegra_timer_shutdown, + .tick_resume = tegra_timer_shutdown, +}; + +static u64 notrace tegra_read_sched_clock(void) +{ + return timer_readl(TIMERUS_CNTR_1US); +} + +/* + * tegra_rtc_read - Reads the Tegra RTC registers + * Care must be taken that this funciton is not called while the + * tegra_rtc driver could be executing to avoid race conditions + * on the RTC shadow register + */ +static u64 tegra_rtc_read_ms(void) +{ + u32 ms = readl(rtc_base + RTC_MILLISECONDS); + u32 s = readl(rtc_base + RTC_SHADOW_SECONDS); + return (u64)s * MSEC_PER_SEC + ms; +} + +/* + * tegra_read_persistent_clock64 - Return time from a persistent clock. + * + * Reads the time from a source which isn't disabled during PM, the + * 32k sync timer. Convert the cycles elapsed since last read into + * nsecs and adds to a monotonically increasing timespec64. + * Care must be taken that this funciton is not called while the + * tegra_rtc driver could be executing to avoid race conditions + * on the RTC shadow register + */ +static void tegra_read_persistent_clock64(struct timespec64 *ts) +{ + u64 delta; + + last_persistent_ms = persistent_ms; + persistent_ms = tegra_rtc_read_ms(); + delta = persistent_ms - last_persistent_ms; + + timespec64_add_ns(&persistent_ts, delta * NSEC_PER_MSEC); + *ts = persistent_ts; +} + +static unsigned long tegra_delay_timer_read_counter_long(void) +{ + return readl(timer_reg_base + TIMERUS_CNTR_1US); +} + +static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + timer_writel(1<<30, TIMER3_BASE + TIMER_PCR); + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static struct irqaction tegra_timer_irq = { + .name = "timer0", + .flags = IRQF_TIMER | IRQF_TRIGGER_HIGH, + .handler = tegra_timer_interrupt, + .dev_id = &tegra_clockevent, +}; + +static int __init tegra20_init_timer(struct device_node *np) +{ + struct clk *clk; + unsigned long rate; + int ret; + + timer_reg_base = of_iomap(np, 0); + if (!timer_reg_base) { + pr_err("Can't map timer registers\n"); + return -ENXIO; + } + + tegra_timer_irq.irq = irq_of_parse_and_map(np, 2); + if (tegra_timer_irq.irq <= 0) { + pr_err("Failed to map timer IRQ\n"); + return -EINVAL; + } + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n"); + rate = 12000000; + } else { + clk_prepare_enable(clk); + rate = clk_get_rate(clk); + } + + switch (rate) { + case 12000000: + timer_writel(0x000b, TIMERUS_USEC_CFG); + break; + case 13000000: + timer_writel(0x000c, TIMERUS_USEC_CFG); + break; + case 19200000: + timer_writel(0x045f, TIMERUS_USEC_CFG); + break; + case 26000000: + timer_writel(0x0019, TIMERUS_USEC_CFG); + break; + default: + WARN(1, "Unknown clock rate"); + } + + sched_clock_register(tegra_read_sched_clock, 32, 1000000); + + ret = clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, + "timer_us", 1000000, 300, 32, + clocksource_mmio_readl_up); + if (ret) { + pr_err("Failed to register clocksource\n"); + return ret; + } + + tegra_delay_timer.read_current_timer = + tegra_delay_timer_read_counter_long; + tegra_delay_timer.freq = 1000000; + register_current_timer_delay(&tegra_delay_timer); + + ret = setup_irq(tegra_timer_irq.irq, &tegra_timer_irq); + if (ret) { + pr_err("Failed to register timer IRQ: %d\n", ret); + return ret; + } + + tegra_clockevent.cpumask = cpu_possible_mask; + tegra_clockevent.irq = tegra_timer_irq.irq; + clockevents_config_and_register(&tegra_clockevent, 1000000, + 0x1, 0x1fffffff); + + return 0; +} +TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer); + +static int __init tegra20_init_rtc(struct device_node *np) +{ + struct clk *clk; + + rtc_base = of_iomap(np, 0); + if (!rtc_base) { + pr_err("Can't map RTC registers\n"); + return -ENXIO; + } + + /* + * rtc registers are used by read_persistent_clock, keep the rtc clock + * enabled + */ + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) + pr_warn("Unable to get rtc-tegra clock\n"); + else + clk_prepare_enable(clk); + + return register_persistent_clock(tegra_read_persistent_clock64); +} +TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c @@ -991,7 +991,6 @@ static struct platform_driver omap_dm_timer_driver = { }, }; -early_platform_init("earlytimer", &omap_dm_timer_driver); module_platform_driver(omap_dm_timer_driver); MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver"); diff --git a/drivers/clocksource/timer-vt8500.c b/drivers/clocksource/timer-vt8500.c @@ -145,7 +145,7 @@ static int __init vt8500_timer_init(struct device_node *np) ret = clocksource_register_hz(&clocksource, VT8500_TIMER_HZ); if (ret) { - pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n", + pr_err("%s: clocksource_register failed for %s\n", __func__, clocksource.name); return ret; } diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h @@ -1,6 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * include/linux/hrtimer.h - * * hrtimers - High-resolution kernel timers * * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de> @@ -9,8 +8,6 @@ * data type definitions, declarations, prototypes * * Started by: Thomas Gleixner and Ingo Molnar - * - * For licencing details see kernel-base/COPYING */ #ifndef _LINUX_HRTIMER_H #define _LINUX_HRTIMER_H diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Alarmtimer interface * @@ -10,10 +11,6 @@ * Copyright (C) 2010 IBM Corperation * * Author: John Stultz <john.stultz@linaro.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/time.h> #include <linux/hrtimer.h> diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/time/clockevents.c - * * This file contains functions which manage clock event devices. * * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner - * - * This code is licenced under the GPL version 2. For details see - * kernel-base/COPYING. */ #include <linux/clockchips.h> @@ -39,10 +35,8 @@ static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt, u64 clc = (u64) latch << evt->shift; u64 rnd; - if (unlikely(!evt->mult)) { + if (WARN_ON(!evt->mult)) evt->mult = 1; - WARN_ON(1); - } rnd = (u64) evt->mult - 1; /* @@ -164,10 +158,8 @@ void clockevents_switch_state(struct clock_event_device *dev, * on it, so fix it up and emit a warning: */ if (clockevent_state_oneshot(dev)) { - if (unlikely(!dev->mult)) { + if (WARN_ON(!dev->mult)) dev->mult = 1; - WARN_ON(1); - } } } } @@ -315,10 +307,8 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires, int64_t delta; int rc; - if (unlikely(expires < 0)) { - WARN_ON_ONCE(1); + if (WARN_ON_ONCE(expires < 0)) return -ETIME; - } dev->next_event = expires; diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c @@ -1,26 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * linux/kernel/time/clocksource.c - * * This file contains the functions which manage clocksource drivers. * * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * TODO WishList: - * o Allow clocksource drivers to be unregistered */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c @@ -1,34 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/hrtimer.c - * * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar * Copyright(C) 2006-2007 Timesys Corp., Thomas Gleixner * * High-resolution kernel timers * - * In contrast to the low-resolution timeout API implemented in - * kernel/timer.c, hrtimers provide finer resolution and accuracy - * depending on system configuration and capabilities. - * - * These timers are currently used for: - * - itimers - * - POSIX timers - * - nanosleep - * - precise in-kernel timing + * In contrast to the low-resolution timeout API, aka timer wheel, + * hrtimers provide finer resolution and accuracy depending on system + * configuration and capabilities. * * Started by: Thomas Gleixner and Ingo Molnar * * Credits: - * based on kernel/timer.c + * Based on the original timer wheel code * * Help, testing, suggestions, bugfixes, improvements were * provided by: * * George Anzinger, Andrew Morton, Steven Rostedt, Roman Zippel * et. al. - * - * For licencing details see kernel-base/COPYING */ #include <linux/cpu.h> diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/itimer.c - * * Copyright (C) 1992 Darren Senn */ diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c @@ -1,25 +1,9 @@ -/*********************************************************************** -* linux/kernel/time/jiffies.c -* -* This file contains the jiffies based clocksource. -* -* Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -************************************************************************/ +// SPDX-License-Identifier: GPL-2.0+ +/* + * This file contains the jiffies based clocksource. + * + * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) + */ #include <linux/clocksource.h> #include <linux/jiffies.h> #include <linux/module.h> diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c @@ -17,7 +17,6 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/rtc.h> -#include <linux/math64.h> #include "ntp_internal.h" #include "timekeeping_internal.h" diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c @@ -1,21 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * posix-clock.c - support for dynamic clock devices + * Support for dynamic clock devices * * Copyright (C) 2010 OMICRON electronics GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/device.h> #include <linux/export.h> diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Dummy stubs used when CONFIG_POSIX_TIMERS=n * * Created by: Nicolas Pitre, July 2016 * Copyright: (C) 2016 Linaro Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/linkage.h> diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c @@ -1,34 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * linux/kernel/posix-timers.c - * - * * 2002-10-15 Posix Clocks & timers * by George Anzinger george@mvista.com - * * Copyright (C) 2002 2003 by MontaVista Software. * * 2004-06-01 Fix CLOCK_REALTIME clock/timer TIMER_ABSTIME bug. * Copyright (C) 2004 Boris Hu * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * MontaVista Software | 1237 East Arques Avenue | Sunnyvale | CA 94085 | USA - */ - -/* These are all the functions necessary to implement - * POSIX clocks & timers + * These are all the functions necessary to implement POSIX clocks & timers */ #include <linux/mm.h> #include <linux/interrupt.h> diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c @@ -1,10 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * sched_clock.c: Generic sched_clock() support, to extend low level - * hardware time counters to full 64-bit ns values. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Generic sched_clock() support, to extend low level hardware time + * counters to full 64-bit ns values. */ #include <linux/clocksource.h> #include <linux/init.h> diff --git a/kernel/time/test_udelay.c b/kernel/time/test_udelay.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * udelay() test kernel module * @@ -7,15 +8,6 @@ * Specifying usecs of 0 or negative values will run multiples tests. * * Copyright (C) 2014 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/debugfs.h> diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/time/tick-broadcast-hrtimer.c - * This file emulates a local clock event device - * via a pseudo clock device. + * Emulate a local clock event device via a pseudo clock device. */ #include <linux/cpu.h> #include <linux/err.h> diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c @@ -1,15 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/time/tick-broadcast.c - * * This file contains functions which emulate a local clock-event * device via a broadcast event source. * * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner - * - * This code is licenced under the GPL version 2. For details see - * kernel-base/COPYING. */ #include <linux/cpu.h> #include <linux/err.h> diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c @@ -1,15 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/time/tick-common.c - * * This file contains the base functions to manage periodic tick * related events. * * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner - * - * This code is licenced under the GPL version 2. For details see - * kernel-base/COPYING. */ #include <linux/cpu.h> #include <linux/err.h> diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c @@ -1,15 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/time/tick-oneshot.c - * * This file contains functions which manage high resolution tick * related events. * * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner - * - * This code is licenced under the GPL version 2. For details see - * kernel-base/COPYING. */ #include <linux/cpu.h> #include <linux/err.h> diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c @@ -1,6 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/time/tick-sched.c - * * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de> * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar * Copyright(C) 2006-2007 Timesys Corp., Thomas Gleixner @@ -8,8 +7,6 @@ * No idle tick implementation for low and high resolution timers * * Started by: Thomas Gleixner and Ingo Molnar - * - * Distribute under GPLv2. */ #include <linux/cpu.h> #include <linux/err.h> diff --git a/kernel/time/time.c b/kernel/time/time.c @@ -1,14 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/time.c - * * Copyright (C) 1991, 1992 Linus Torvalds * - * This file contains the interface functions for the various - * time related system calls: time, stime, gettimeofday, settimeofday, - * adjtime - */ -/* - * Modification history kernel/time.c + * This file contains the interface functions for the various time related + * system calls: time, stime, gettimeofday, settimeofday, adjtime + * + * Modification history: * * 1993-09-02 Philip Gladstone * Created file with time related functions from sched/core.c and adjtimex() diff --git a/kernel/time/timeconst.bc b/kernel/time/timeconst.bc @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + scale=0 define gcd(a,b) { diff --git a/kernel/time/timeconv.c b/kernel/time/timeconv.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: LGPL-2.0+ /* * Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. * This file is part of the GNU C Library. diff --git a/kernel/time/timecounter.c b/kernel/time/timecounter.c @@ -1,20 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * linux/kernel/time/timecounter.c - * - * based on code that migrated away from - * linux/kernel/time/clocksource.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Based on clocksource code. See commit 74d23cc704d1 */ - #include <linux/export.h> #include <linux/timecounter.h> diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c @@ -1,13 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/time/timekeeping.c - * - * Kernel timekeeping code and accessor functions - * - * This code was moved from linux/kernel/timer.c. - * Please see that file for copyright and history logs. - * + * Kernel timekeeping code and accessor functions. Based on code from + * timer.c, moved in commit 8524070b7982. */ - #include <linux/timekeeper_internal.h> #include <linux/module.h> #include <linux/interrupt.h> @@ -50,7 +45,9 @@ enum timekeeping_adv_mode { static struct { seqcount_t seq; struct timekeeper timekeeper; -} tk_core ____cacheline_aligned; +} tk_core ____cacheline_aligned = { + .seq = SEQCNT_ZERO(tk_core.seq), +}; static DEFINE_RAW_SPINLOCK(timekeeper_lock); static struct timekeeper shadow_timekeeper; diff --git a/kernel/time/timekeeping_debug.c b/kernel/time/timekeeping_debug.c @@ -1,17 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * debugfs file to track time spent in suspend * * Copyright (c) 2011, Google, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. */ #include <linux/debugfs.h> @@ -28,7 +19,7 @@ static unsigned int sleep_time_bin[NUM_BINS] = {0}; -static int tk_debug_show_sleep_time(struct seq_file *s, void *data) +static int tk_debug_sleep_time_show(struct seq_file *s, void *data) { unsigned int bin; seq_puts(s, " time (secs) count\n"); @@ -42,18 +33,7 @@ static int tk_debug_show_sleep_time(struct seq_file *s, void *data) } return 0; } - -static int tk_debug_sleep_time_open(struct inode *inode, struct file *file) -{ - return single_open(file, tk_debug_show_sleep_time, NULL); -} - -static const struct file_operations tk_debug_sleep_time_fops = { - .open = tk_debug_sleep_time_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(tk_debug_sleep_time); static int __init tk_debug_sleep_time_init(void) { diff --git a/kernel/time/timer.c b/kernel/time/timer.c @@ -1,6 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * linux/kernel/timer.c - * * Kernel internal timers * * Copyright (C) 1991, 1992 Linus Torvalds diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c @@ -1,13 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * kernel/time/timer_list.c - * * List pending timers * * Copyright(C) 2006, Red Hat, Inc., Ingo Molnar - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/proc_fs.h>