diff options
48 files changed, 673 insertions, 602 deletions
diff --git a/Documentation/devicetree/bindings/timer/rda,8810pl-timer.txt b/Documentation/devicetree/bindings/timer/rda,8810pl-timer.txt new file mode 100644 index 000000000000..4db542c9a0fd --- /dev/null +++ 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 index 33992679a8bd..862a80f0380a 100644 --- 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 index 6dd783557330..dadb494d83fd 100644 --- 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 index 55c77e44bb2d..a9e26f6a81a1 100644 --- 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 index dd9138104568..cdd210ff89ea 100644 --- 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 index 20da9b1d7f7d..b28970ca4a7a 100644 --- 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 index 60da2537bef9..2b196cbfadb6 100644 --- 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 index c1b96dc5f444..51d53c4e646f 100644 --- 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 deleted file mode 100644 index 92f20991a937..000000000000 --- a/drivers/clocksource/meson6_timer.c +++ /dev/null @@ -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 index 8e4ddb9420c6..19b336c9b417 100644 --- 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/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c index cf93f6419b51..fadff7915dd9 100644 --- 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) |
