Commit 615740fd authored by Thomas Gleixner's avatar Thomas Gleixner

Merge branch 'clockevents/4.21' of...

Merge branch 'clockevents/4.21' of http://git.linaro.org/people/daniel.lezcano/linux into timers/core

Pull clocksource/event changes from Daniel Lezcano:

 - 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)
parents 07daef8b 7f83a132
...@@ -28,6 +28,10 @@ Required Properties: ...@@ -28,6 +28,10 @@ Required Properties:
- "renesas,r8a7744-cmt1" for the 48-bit CMT1 device included in r8a7744. - "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-cmt0" for the 32-bit CMT0 device included in r8a7745.
- "renesas,r8a7745-cmt1" for the 48-bit CMT1 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-cmt0" for the 32-bit CMT0 device included in r8a7790.
- "renesas,r8a7790-cmt1" for the 48-bit CMT1 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. - "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791.
...@@ -36,6 +40,8 @@ Required Properties: ...@@ -36,6 +40,8 @@ Required Properties:
- "renesas,r8a7793-cmt1" for the 48-bit CMT1 device included in r8a7793. - "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-cmt0" for the 32-bit CMT0 device included in r8a7794.
- "renesas,r8a7794-cmt1" for the 48-bit CMT1 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-cmt0" for the 32-bit CMT0 device included in r8a77970.
- "renesas,r8a77970-cmt1" for the 48-bit CMT1 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. - "renesas,r8a77980-cmt0" for the 32-bit CMT0 device included in r8a77980.
...@@ -47,9 +53,12 @@ Required Properties: ...@@ -47,9 +53,12 @@ Required Properties:
and RZ/G1. and RZ/G1.
These are fallbacks for r8a73a4, R-Car Gen2 and RZ/G1 entries These are fallbacks for r8a73a4, R-Car Gen2 and RZ/G1 entries
listed above. listed above.
- "renesas,rcar-gen3-cmt0" for 32-bit CMT0 devices included in R-Car Gen3. - "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. and RZ/G2.
These are fallbacks for R-Car Gen3 entries listed above. - "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. - reg: base address and length of the registers block for the timer module.
- interrupts: interrupt-specifier for the timer, one per channel. - interrupts: interrupt-specifier for the timer, one per channel.
......
...@@ -26,6 +26,7 @@ config ARC ...@@ -26,6 +26,7 @@ config ARC
select GENERIC_IRQ_SHOW select GENERIC_IRQ_SHOW
select GENERIC_PCI_IOMAP select GENERIC_PCI_IOMAP
select GENERIC_PENDING_IRQ if SMP select GENERIC_PENDING_IRQ if SMP
select GENERIC_SCHED_CLOCK
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select HAVE_ARCH_KGDB select HAVE_ARCH_KGDB
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
......
...@@ -105,6 +105,14 @@ config OWL_TIMER ...@@ -105,6 +105,14 @@ config OWL_TIMER
help help
Enables the support for the Actions Semi Owl timer driver. 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 config SUN4I_TIMER
bool "Sun4i timer driver" if COMPILE_TEST bool "Sun4i timer driver" if COMPILE_TEST
depends on HAS_IOMEM depends on HAS_IOMEM
...@@ -163,12 +171,6 @@ config CLKSRC_NOMADIK_MTU ...@@ -163,12 +171,6 @@ config CLKSRC_NOMADIK_MTU
to multiple interrupt generating programmable to multiple interrupt generating programmable
32-bit free running decrementing counters. 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 config CLKSRC_DBX500_PRCMU
bool "Clocksource PRCMU Timer" if COMPILE_TEST bool "Clocksource PRCMU Timer" if COMPILE_TEST
depends on HAS_IOMEM depends on HAS_IOMEM
...@@ -226,13 +228,6 @@ config INTEGRATOR_AP_TIMER ...@@ -226,13 +228,6 @@ config INTEGRATOR_AP_TIMER
help help
Enables support for the Integrator-ap timer. 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 config CLKSRC_EFM32
bool "Clocksource for Energy Micro's EFM32 SoCs" if !ARCH_EFM32 bool "Clocksource for Energy Micro's EFM32 SoCs" if !ARCH_EFM32
depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST) depends on OF && ARM && (ARCH_EFM32 || COMPILE_TEST)
...@@ -290,6 +285,7 @@ config CLKSRC_MPS2 ...@@ -290,6 +285,7 @@ config CLKSRC_MPS2
config ARC_TIMERS config ARC_TIMERS
bool "Support for 32-bit TIMERn counters in ARC Cores" if COMPILE_TEST bool "Support for 32-bit TIMERn counters in ARC Cores" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK
select TIMER_OF select TIMER_OF
help help
These are legacy 32-bit TIMER0 and TIMER1 counters found on all ARC cores These are legacy 32-bit TIMER0 and TIMER1 counters found on all ARC cores
...@@ -580,7 +576,7 @@ config H8300_TPU ...@@ -580,7 +576,7 @@ config H8300_TPU
config CLKSRC_IMX_GPT config CLKSRC_IMX_GPT
bool "Clocksource using i.MX GPT" if COMPILE_TEST bool "Clocksource using i.MX GPT" if COMPILE_TEST
depends on ARM && CLKDEV_LOOKUP depends on (ARM || ARM64) && CLKDEV_LOOKUP
select CLKSRC_MMIO select CLKSRC_MMIO
config CLKSRC_IMX_TPM config CLKSRC_IMX_TPM
...@@ -611,7 +607,7 @@ config ATCPIT100_TIMER ...@@ -611,7 +607,7 @@ config ATCPIT100_TIMER
config RISCV_TIMER config RISCV_TIMER
bool "Timer for the RISC-V platform" bool "Timer for the RISC-V platform"
depends on RISCV depends on GENERIC_SCHED_CLOCK && RISCV
default y default y
select TIMER_PROBE select TIMER_PROBE
select TIMER_OF select TIMER_OF
......
...@@ -20,7 +20,7 @@ obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o ...@@ -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) += dw_apb_timer.o
obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o
obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.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_NOMADIK_MTU) += nomadik-mtu.o
obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
obj-$(CONFIG_ARMADA_370_XP_TIMER) += timer-armada-370-xp.o obj-$(CONFIG_ARMADA_370_XP_TIMER) += timer-armada-370-xp.o
...@@ -32,10 +32,10 @@ obj-$(CONFIG_MXS_TIMER) += mxs_timer.o ...@@ -32,10 +32,10 @@ obj-$(CONFIG_MXS_TIMER) += mxs_timer.o
obj-$(CONFIG_CLKSRC_PXA) += pxa_timer.o obj-$(CONFIG_CLKSRC_PXA) += pxa_timer.o
obj-$(CONFIG_PRIMA2_TIMER) += timer-prima2.o obj-$(CONFIG_PRIMA2_TIMER) += timer-prima2.o
obj-$(CONFIG_U300_TIMER) += timer-u300.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_SUN5I_HSTIMER) += timer-sun5i.o
obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o obj-$(CONFIG_MESON6_TIMER) += timer-meson6.o
obj-$(CONFIG_TEGRA_TIMER) += tegra20_timer.o obj-$(CONFIG_TEGRA_TIMER) += timer-tegra20.o
obj-$(CONFIG_VT8500_TIMER) += timer-vt8500.o obj-$(CONFIG_VT8500_TIMER) += timer-vt8500.o
obj-$(CONFIG_NSPIRE_TIMER) += timer-zevio.o obj-$(CONFIG_NSPIRE_TIMER) += timer-zevio.o
obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o obj-$(CONFIG_BCM_KONA_TIMER) += bcm_kona_timer.o
...@@ -57,6 +57,7 @@ obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o ...@@ -57,6 +57,7 @@ obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o
obj-$(CONFIG_OWL_TIMER) += timer-owl.o obj-$(CONFIG_OWL_TIMER) += timer-owl.o
obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o
obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o
obj-$(CONFIG_RDA_TIMER) += timer-rda.o
obj-$(CONFIG_ARC_TIMERS) += arc_timer.o obj-$(CONFIG_ARC_TIMERS) += arc_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
...@@ -78,6 +79,6 @@ obj-$(CONFIG_H8300_TPU) += h8300_tpu.o ...@@ -78,6 +79,6 @@ obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
obj-$(CONFIG_X86_NUMACHIP) += numachip.o obj-$(CONFIG_X86_NUMACHIP) += numachip.o
obj-$(CONFIG_ATCPIT100_TIMER) += timer-atcpit100.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_CSKY_MP_TIMER) += timer-mp-csky.o
obj-$(CONFIG_GX6605S_TIMER) += timer-gx6605s.o obj-$(CONFIG_GX6605S_TIMER) += timer-gx6605s.o
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/sched_clock.h>
#include <soc/arc/timers.h> #include <soc/arc/timers.h>
#include <soc/arc/mcip.h> #include <soc/arc/mcip.h>
...@@ -88,6 +89,11 @@ static u64 arc_read_gfrc(struct clocksource *cs) ...@@ -88,6 +89,11 @@ static u64 arc_read_gfrc(struct clocksource *cs)
return (((u64)h) << 32) | l; return (((u64)h) << 32) | l;
} }
static notrace u64 arc_gfrc_clock_read(void)
{
return arc_read_gfrc(NULL);
}
static struct clocksource arc_counter_gfrc = { static struct clocksource arc_counter_gfrc = {
.name = "ARConnect GFRC", .name = "ARConnect GFRC",
.rating = 400, .rating = 400,
...@@ -111,6 +117,8 @@ static int __init arc_cs_setup_gfrc(struct device_node *node) ...@@ -111,6 +117,8 @@ static int __init arc_cs_setup_gfrc(struct device_node *node)
if (ret) if (ret)
return ret; return ret;
sched_clock_register(arc_gfrc_clock_read, 64, arc_timer_freq);
return clocksource_register_hz(&arc_counter_gfrc, 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); 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) ...@@ -139,6 +147,11 @@ static u64 arc_read_rtc(struct clocksource *cs)
return (((u64)h) << 32) | l; return (((u64)h) << 32) | l;
} }
static notrace u64 arc_rtc_clock_read(void)
{
return arc_read_rtc(NULL);
}
static struct clocksource arc_counter_rtc = { static struct clocksource arc_counter_rtc = {
.name = "ARCv2 RTC", .name = "ARCv2 RTC",
.rating = 350, .rating = 350,
...@@ -170,6 +183,8 @@ static int __init arc_cs_setup_rtc(struct device_node *node) ...@@ -170,6 +183,8 @@ static int __init arc_cs_setup_rtc(struct device_node *node)
write_aux_reg(AUX_RTC_CTRL, 1); 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); return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq);
} }
TIMER_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc); 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) ...@@ -185,6 +200,11 @@ static u64 arc_read_timer1(struct clocksource *cs)
return (u64) read_aux_reg(ARC_REG_TIMER1_CNT); 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 = { static struct clocksource arc_counter_timer1 = {
.name = "ARC Timer1", .name = "ARC Timer1",
.rating = 300, .rating = 300,
...@@ -209,6 +229,8 @@ static int __init arc_cs_setup_timer1(struct device_node *node) ...@@ -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_CNT, 0);
write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH); 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); return clocksource_register_hz(&arc_counter_timer1, arc_timer_freq);
} }
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* Copyright 2012 Simon Arlott * 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> #include <linux/bitops.h>
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/sched_clock.h>
#define RATE_32K 32768 #define RATE_32K 32768
...@@ -26,8 +25,6 @@ ...@@ -26,8 +25,6 @@
#define PRCMU_TIMER_DOWNCOUNT 0x4 #define PRCMU_TIMER_DOWNCOUNT 0x4
#define PRCMU_TIMER_MODE 0x8 #define PRCMU_TIMER_MODE 0x8
#define SCHED_CLOCK_MIN_WRAP 131072 /* 2^32 / 32768 */
static void __iomem *clksrc_dbx500_timer_base; static void __iomem *clksrc_dbx500_timer_base;
static u64 notrace clksrc_dbx500_prcmu_read(struct clocksource *cs) static u64 notrace clksrc_dbx500_prcmu_read(struct clocksource *cs)
...@@ -46,24 +43,12 @@ 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 = { static struct clocksource clocksource_dbx500_prcmu = {
.name = "dbx500-prcmu-timer", .name = "dbx500-prcmu-timer",
.rating = 300, .rating = 100,
.read = clksrc_dbx500_prcmu_read, .read = clksrc_dbx500_prcmu_read,
.mask = CLOCKSOURCE_MASK(32), .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) static int __init clksrc_dbx500_prcmu_init(struct device_node *node)
{ {
clksrc_dbx500_timer_base = of_iomap(node, 0); clksrc_dbx500_timer_base = of_iomap(node, 0);
...@@ -81,9 +66,6 @@ static int __init clksrc_dbx500_prcmu_init(struct device_node *node) ...@@ -81,9 +66,6 @@ static int __init clksrc_dbx500_prcmu_init(struct device_node *node)
writel(TIMER_DOWNCOUNT_VAL, writel(TIMER_DOWNCOUNT_VAL,
clksrc_dbx500_timer_base + PRCMU_TIMER_REF); 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); return clocksource_register_hz(&clocksource_dbx500_prcmu, RATE_32K);
} }
TIMER_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4", TIMER_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4",
......
...@@ -69,7 +69,6 @@ static u32 clk_prescale; ...@@ -69,7 +69,6 @@ static u32 clk_prescale;
static u32 nmdk_cycle; /* write-once */ static u32 nmdk_cycle; /* write-once */
static struct delay_timer mtu_delay_timer; static struct delay_timer mtu_delay_timer;
#ifdef CONFIG_CLKSRC_NOMADIK_MTU_SCHED_CLOCK
/* /*
* Override the global weak sched_clock symbol with this * Override the global weak sched_clock symbol with this
* local implementation which uses the clocksource to get some * local implementation which uses the clocksource to get some
...@@ -82,7 +81,6 @@ static u64 notrace nomadik_read_sched_clock(void) ...@@ -82,7 +81,6 @@ static u64 notrace nomadik_read_sched_clock(void)
return -readl(mtu_base + MTU_VAL(0)); return -readl(mtu_base + MTU_VAL(0));
} }
#endif
static unsigned long nmdk_timer_read_current_timer(void) static unsigned long nmdk_timer_read_current_timer(void)
{ {
...@@ -234,9 +232,7 @@ static int __init nmdk_timer_init(void __iomem *base, int irq, ...@@ -234,9 +232,7 @@ static int __init nmdk_timer_init(void __iomem *base, int irq,
return ret; return ret;
} }
#ifdef CONFIG_CLKSRC_NOMADIK_MTU_SCHED_CLOCK
sched_clock_register(nomadik_read_sched_clock, 32, rate); sched_clock_register(nomadik_read_sched_clock, 32, rate);
#endif
/* Timer 1 is used for events, register irq and clockevents */ /* Timer 1 is used for events, register irq and clockevents */
setup_irq(irq, &nmdk_timer_irq); setup_irq(irq, &nmdk_timer_irq);
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <linux/delay.h> #include <linux/delay.h>
/* /*
* Register definitions for the timers * Register definitions common for all the timer variants.
*/ */
#define TIMER1_COUNT (0x00) #define TIMER1_COUNT (0x00)
#define TIMER1_LOAD (0x04) #define TIMER1_LOAD (0x04)
...@@ -36,9 +36,10 @@ ...@@ -36,9 +36,10 @@
#define TIMER3_MATCH1 (0x28) #define TIMER3_MATCH1 (0x28)
#define TIMER3_MATCH2 (0x2c) #define TIMER3_MATCH2 (0x2c)
#define TIMER_CR (0x30) #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_ENABLE BIT(0)
#define TIMER_1_CR_CLOCK BIT(1) #define TIMER_1_CR_CLOCK BIT(1)
#define TIMER_1_CR_INT BIT(2) #define TIMER_1_CR_INT BIT(2)
...@@ -53,8 +54,9 @@ ...@@ -53,8 +54,9 @@
#define TIMER_3_CR_UPDOWN BIT(11) #define TIMER_3_CR_UPDOWN BIT(11)
/* /*
* The Aspeed AST2400 moves bits around in the control register * Control register (TMC30) bit fields for aspeed ast2400/ast2500 timers.
* and lacks bits for setting the timer to count upwards. * 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_ENABLE BIT(0)
#define TIMER_1_CR_ASPEED_CLOCK BIT(1) #define TIMER_1_CR_ASPEED_CLOCK BIT(1)
...@@ -66,6 +68,18 @@ ...@@ -66,6 +68,18 @@
#define TIMER_3_CR_ASPEED_CLOCK BIT(9) #define TIMER_3_CR_ASPEED_CLOCK BIT(9)
#define TIMER_3_CR_ASPEED_INT BIT(10) #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_MATCH1 BIT(0)
#define TIMER_1_INT_MATCH2 BIT(1) #define TIMER_1_INT_MATCH2 BIT(1)
#define TIMER_1_INT_OVERFLOW BIT(2) #define TIMER_1_INT_OVERFLOW BIT(2)
...@@ -80,7 +94,7 @@ ...@@ -80,7 +94,7 @@
struct fttmr010 { struct fttmr010 {
void __iomem *base; void __iomem *base;
unsigned int tick_rate; unsigned int tick_rate;
bool count_down; bool is_aspeed;
u32 t1_enable_val; u32 t1_enable_val;
struct clock_event_device clkevt; struct clock_event_device clkevt;
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
...@@ -130,7 +144,7 @@ static int fttmr010_timer_set_next_event(unsigned long cycles, ...@@ -130,7 +144,7 @@ static int fttmr010_timer_set_next_event(unsigned long cycles,
cr &= ~fttmr010->t1_enable_val; cr &= ~fttmr010->t1_enable_val;
writel(cr, fttmr010->base + TIMER_CR); writel(cr, fttmr010->base + TIMER_CR);
if (fttmr010->count_down) { if (fttmr010->is_aspeed) {
/* /*
* ASPEED Timer Controller will load TIMER1_LOAD register * ASPEED Timer Controller will load TIMER1_LOAD register
* into TIMER1_COUNT register when the timer is re-enabled. * 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) ...@@ -175,16 +189,17 @@ static int fttmr010_timer_set_oneshot(struct clock_event_device *evt)
/* Setup counter start from 0 or ~0 */ /* Setup counter start from 0 or ~0 */
writel(0, fttmr010->base + TIMER1_COUNT); writel(0, fttmr010->base + TIMER1_COUNT);
if (fttmr010->count_down) if (fttmr010->is_aspeed) {
writel(~0, fttmr010->base + TIMER1_LOAD); writel(~0, fttmr010->base + TIMER1_LOAD);
else } else {
writel(0, fttmr010->base + TIMER1_LOAD); writel(0, fttmr010->base + TIMER1_LOAD);
/* Enable interrupt */ /* Enable interrupt */
cr = readl(fttmr010->base + TIMER_INTR_MASK); cr = readl(fttmr010->base + TIMER_INTR_MASK);
cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2); cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
cr |= TIMER_1_INT_MATCH1; cr |= TIMER_1_INT_MATCH1;
writel(cr, fttmr010->base + TIMER_INTR_MASK); writel(cr, fttmr010->base + TIMER_INTR_MASK);
}
return 0; return 0;
} }
...@@ -201,9 +216,8 @@ static int fttmr010_timer_set_periodic(struct clock_event_device *evt) ...@@ -201,9 +216,8 @@ static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
writel(cr, fttmr010->base + TIMER_CR); writel(cr, fttmr010->base + TIMER_CR);
/* Setup timer to fire at 1/HZ intervals. */ /* Setup timer to fire at 1/HZ intervals. */
if (fttmr010->count_down) { if (fttmr010->is_aspeed) {
writel(period, fttmr010->base + TIMER1_LOAD); writel(period, fttmr010->base + TIMER1_LOAD);
writel(0, fttmr010->base + TIMER1_MATCH1);
} else { } else {
cr = 0xffffffff - (period - 1); cr = 0xffffffff - (period - 1);
writel(cr, fttmr010->base + TIMER1_COUNT); writel(cr, fttmr010->base + TIMER1_COUNT);
...@@ -281,23 +295,21 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) ...@@ -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, * The Aspeed timers move bits around in the control register.
* otherwise it works the same.
*/ */
if (is_aspeed) { if (is_aspeed) {
fttmr010->t1_enable_val = TIMER_1_CR_ASPEED_ENABLE | fttmr010->t1_enable_val = TIMER_1_CR_ASPEED_ENABLE |
TIMER_1_CR_ASPEED_INT; TIMER_1_CR_ASPEED_INT;
/* Downward not available */ fttmr010->is_aspeed = true;
fttmr010->count_down = true;
} else { } else {
fttmr010->t1_enable_val = TIMER_1_CR_ENABLE | TIMER_1_CR_INT; fttmr010->t1_enable_val = TIMER_1_CR_ENABLE | TIMER_1_CR_INT;
}
/* /*
* Reset the interrupt mask and status * Reset the interrupt mask and status
*/ */
writel(TIMER_INT_ALL_MASK, fttmr010->base + TIMER_INTR_MASK); writel(TIMER_INT_ALL_MASK, fttmr010->base + TIMER_INTR_MASK);
writel(0, fttmr010->base + TIMER_INTR_STATE); writel(0, fttmr010->base + TIMER_INTR_STATE);
}
/* /*
* Enable timer 1 count up, timer 2 count up, except on Aspeed, * 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) ...@@ -306,9 +318,8 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed)
if (is_aspeed) if (is_aspeed)
val = TIMER_2_CR_ASPEED_ENABLE; val = TIMER_2_CR_ASPEED_ENABLE;
else { else {
val = TIMER_2_CR_ENABLE; val = TIMER_2_CR_ENABLE | TIMER_1_CR_UPDOWN |
if (!fttmr010->count_down) TIMER_2_CR_UPDOWN;
val |= TIMER_1_CR_UPDOWN | TIMER_2_CR_UPDOWN;
} }
writel(val, fttmr010->base + TIMER_CR); writel(val, fttmr010->base + TIMER_CR);
...@@ -321,7 +332,7 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) ...@@ -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_MATCH1);
writel(0, fttmr010->base + TIMER2_MATCH2); writel(0, fttmr010->base + TIMER2_MATCH2);
if (fttmr010->count_down) { if (fttmr010->is_aspeed) {
writel(~0, fttmr010->base + TIMER2_LOAD); writel(~0, fttmr010->base + TIMER2_LOAD);
clocksource_mmio_init(fttmr010->base + TIMER2_COUNT, clocksource_mmio_init(fttmr010->base + TIMER2_COUNT,
"FTTMR010-TIMER2", "FTTMR010-TIMER2",
...@@ -371,7 +382,7 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed) ...@@ -371,7 +382,7 @@ static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed)
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
/* Also use this timer for delays */ /* Also use this timer for delays */
if (fttmr010->count_down) if (fttmr010->is_aspeed)
fttmr010->delay_timer.read_current_timer = fttmr010->delay_timer.read_current_timer =
fttmr010_read_current_timer_down; fttmr010_read_current_timer_down;
else else
......
...@@ -141,21 +141,25 @@ static u64 notrace mxc_read_sched_clock(void) ...@@ -141,21 +141,25 @@ static u64 notrace mxc_read_sched_clock(void)
return sched_clock_reg ? readl_relaxed(sched_clock_reg) : 0; return sched_clock_reg ? readl_relaxed(sched_clock_reg) : 0;
} }
#if defined(CONFIG_ARM)
static struct delay_timer imx_delay_timer; static struct delay_timer imx_delay_timer;
static unsigned long imx_read_current_timer(void) static unsigned long imx_read_current_timer(void)
{ {
return readl_relaxed(sched_clock_reg); return readl_relaxed(sched_clock_reg);
} }
#endif
static int __init mxc_clocksource_init(struct imx_timer *imxtm) static int __init mxc_clocksource_init(struct imx_timer *imxtm)
{ {
unsigned int c = clk_get_rate(imxtm->clk_per); unsigned int c = clk_get_rate(imxtm->clk_per);
void __iomem *reg = imxtm->base + imxtm->gpt->reg_tcn; 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.read_current_timer = &imx_read_current_timer;
imx_delay_timer.freq = c; imx_delay_timer.freq = c;
register_current_timer_delay(&imx_delay_timer); register_current_timer_delay(&imx_delay_timer);
#endif
sched_clock_reg = reg; sched_clock_reg = reg;
...@@ -198,15 +202,8 @@ static int v2_set_next_event(unsigned long evt, ...@@ -198,15 +202,8 @@ static int v2_set_next_event(unsigned long evt,
static int mxc_shutdown(struct clock_event_device *ced) static int mxc_shutdown(struct clock_event_device *ced)
{ {
struct imx_timer *imxtm = to_imx_timer(ced); struct imx_timer *imxtm = to_imx_timer(ced);
unsigned long flags;
u32 tcn; 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 */ /* Disable interrupt in GPT module */
imxtm->gpt->gpt_irq_disable(imxtm); imxtm->gpt->gpt_irq_disable(imxtm);
...@@ -221,21 +218,12 @@ static int mxc_shutdown(struct clock_event_device *ced) ...@@ -221,21 +218,12 @@ static int mxc_shutdown(struct clock_event_device *ced)
printk(KERN_INFO "%s: changing mode\n", __func__); printk(KERN_INFO "%s: changing mode\n", __func__);
#endif /* DEBUG */ #endif /* DEBUG */
local_irq_restore(flags);
return 0; return 0;
} }
static int mxc_set_oneshot(struct clock_event_device *ced) static int mxc_set_oneshot(struct clock_event_device *ced)
{ {
struct imx_timer *imxtm = to_imx_timer(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 */ /* Disable interrupt in GPT module */
imxtm->gpt->gpt_irq_disable(imxtm); imxtm->gpt->gpt_irq_disable(imxtm);
...@@ -260,7 +248,6 @@ static int mxc_set_oneshot(struct clock_event_device *ced) ...@@ -260,7 +248,6 @@ static int mxc_set_oneshot(struct clock_event_device *ced)
* mode switching * mode switching
*/ */
imxtm->gpt->gpt_irq_enable(imxtm); imxtm->gpt->gpt_irq_enable(imxtm);
local_irq_restore(flags);
return 0; return 0;
} }
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/sched_clock.h> #include <linux/sched_clock.h>
#include "timer-of.h"
#define TPM_PARAM 0x4 #define TPM_PARAM 0x4
#define TPM_PARAM_WIDTH_SHIFT 16 #define TPM_PARAM_WIDTH_SHIFT 16
#define TPM_PARAM_WIDTH_MASK (0xff << 16) #define TPM_PARAM_WIDTH_MASK (0xff << 16)
...@@ -33,9 +35,7 @@ ...@@ -33,9 +35,7 @@
#define TPM_C0V 0x24 #define TPM_C0V 0x24
static int counter_width; static int counter_width;
static int rating;
static void __iomem *timer_base; static void __iomem *timer_base;
static struct clock_event_device clockevent_tpm;
static inline void tpm_timer_disable(void) static inline void tpm_timer_disable(void)
{ {
...@@ -80,19 +80,6 @@ static u64 notrace tpm_read_sched_clock(void) ...@@ -80,19 +80,6 @@ static u64 notrace tpm_read_sched_clock(void)
return tpm_read_counter(); 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, static int tpm_set_next_event(unsigned long delta,
struct clock_event_device *evt) struct clock_event_device *evt)
{ {
...@@ -137,74 +124,80 @@ static irqreturn_t tpm_timer_interrupt(int irq, void *dev_id) ...@@ -137,74 +124,80 @@ static irqreturn_t tpm_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static struct clock_event_device clockevent_tpm = { static struct timer_of to_tpm = {
.name = "i.MX7ULP TPM Timer", .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
.features = CLOCK_EVT_FEAT_ONESHOT, .clkevt = {
.set_state_oneshot = tpm_set_state_oneshot, .name = "i.MX7ULP TPM Timer",
.set_next_event = tpm_set_next_event, .rating = 200,
.set_state_shutdown = tpm_set_state_shutdown, .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, sched_clock_register(tpm_read_sched_clock, counter_width,
"i.MX7ULP TPM Timer", &clockevent_tpm); timer_of_rate(&to_tpm) >> 3);
clockevent_tpm.rating = rating; return clocksource_mmio_init(timer_base + TPM_CNT,
clockevent_tpm.cpumask = cpumask_of(0); "imx-tpm",
clockevent_tpm.irq = irq; timer_of_rate(&to_tpm) >> 3,
clockevents_config_and_register(&clockevent_tpm, rate, 300, to_tpm.clkevt.rating,
GENMASK(counter_width - 1, 1)); 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) static int __init tpm_timer_init(struct device_node *np)
{ {
struct clk *ipg, *per; struct clk *ipg;
int irq, ret; int 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;
}
ipg = of_clk_get_by_name(np, "ipg"); ipg = of_clk_get_by_name(np, "ipg");
per = of_clk_get_by_name(np, "per"); if (IS_ERR(ipg)) {
if (IS_ERR(ipg) || IS_ERR(per)) { pr_err("tpm: failed to get ipg clk\n");
pr_err("tpm: failed to get ipg or per clk\n"); return -ENODEV;
ret = -ENODEV;
goto err_clk_get;
} }
/* enable clk before accessing registers */ /* enable clk before accessing registers */
ret = clk_prepare_enable(ipg); ret = clk_prepare_enable(ipg);
if (ret) { if (ret) {
pr_err("tpm: ipg clock enable failed (%d)\n", 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); ret = timer_of_init(np, &to_tpm);
if (ret) { if (ret)
pr_err("tpm: per clock enable failed (%d)\n", ret); return ret;
goto err_per_clk_enable;
} timer_base = timer_of_base(&to_tpm);
counter_width = (readl(timer_base + TPM_PARAM) & TPM_PARAM_WIDTH_MASK) counter_width = (readl(timer_base + TPM_PARAM)
>> TPM_PARAM_WIDTH_SHIFT; & TPM_PARAM_WIDTH_MASK) >> TPM_PARAM_WIDTH_SHIFT;
/* use rating 200 for 32-bit counter and 150 for 16-bit counter */ /* 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 * Initialize tpm module to a known state
...@@ -229,29 +222,13 @@ static int __init tpm_timer_init(struct device_node *np) ...@@ -229,29 +222,13 @@ static int __init tpm_timer_init(struct device_node *np)
writel(TPM_SC_CMOD_INC_PER_CNT | writel(TPM_SC_CMOD_INC_PER_CNT |
(counter_width == 0x20 ? (counter_width == 0x20 ?
TPM_SC_CMOD_DIV_DEFAULT : TPM_SC_CMOD_DIV_MAX), 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 */ /* set MOD register to maximum for free running mode */
writel(GENMASK(counter_width - 1, 0), timer_base + TPM_MOD); writel(GENMASK(counter_width - 1, 0), timer_base + TPM_MOD);
rate = clk_get_rate(per) >> 3; tpm_clockevent_init();
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;
err_per_clk_enable: return tpm_clocksource_init();
clk_disable_unprepare(ipg);
err_clk_get:
clk_put(per);
clk_put(ipg);
err_iomap:
iounmap(timer_base);
return ret;
} }
TIMER_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init); TIMER_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init);
...@@ -181,8 +181,7 @@ static int __init integrator_ap_timer_init_of(struct device_node *node) ...@@ -181,8 +181,7 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)
int irq; int irq;
struct clk *clk; struct clk *clk;
unsigned long rate; unsigned long rate;
struct device_node *pri_node; struct device_node *alias_node;
struct device_node *sec_node;
base = of_io_request_and_map(node, 0, "integrator-timer"); base = of_io_request_and_map(node, 0, "integrator-timer");
if (IS_ERR(base)) if (IS_ERR(base))
...@@ -204,7 +203,18 @@ static int __init integrator_ap_timer_init_of(struct device_node *node) ...@@ -204,7 +203,18 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)
return err; 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, err = of_property_read_string(of_aliases,
"arm,timer-secondary", &path); "arm,timer-secondary", &path);
...@@ -213,14 +223,11 @@ static int __init integrator_ap_timer_init_of(struct device_node *node) ...@@ -213,14 +223,11 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)
return err; return err;
} }
alias_node = of_find_node_by_path(path);
sec_node = of_find_node_by_path(path); of_node_put(alias_node);
if (node == pri_node)
/* The primary timer lacks IRQ, use as clocksource */
return integrator_clocksource_init(rate, base);
if (node == sec_node) { if (node == alias_node) {
/* The secondary timer will drive the clock event */ /* The secondary timer will drive the clock event */
irq = irq_of_parse_and_map(node, 0); irq = irq_of_parse_and_map(node, 0);
return integrator_clockevent_init(rate, base, irq); return integrator_clockevent_init(rate, base, irq);
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
* warranty of any kind, whether express or implied. * warranty of any kind, whether express or implied.
*/ */
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -20,80 +22,112 @@ ...@@ -20,80 +22,112 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#define CED_ID 0 #ifdef CONFIG_ARM
#define CSD_ID 4 #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
#define TIMER_ISA_MUX 0 static void __iomem *timer_base;
#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 #ifdef CONFIG_ARM
#define TIMER_CSD_UNIT_1US 1 static unsigned long meson6_read_current_timer(void)
{
return readl_relaxed(timer_base + MESON_ISA_TIMERE);
}
static void __iomem *timer_base; 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) static u64 notrace meson6_timer_sched_read(void)
{ {
return (u64)readl(timer_base + TIMER_ISA_VAL(CSD_ID)); return (u64)readl(timer_base + MESON_ISA_TIMERE);
} }
static void meson6_clkevt_time_stop(unsigned char timer) static void meson6_clkevt_time_stop(void)
{ {
u32 val = readl(timer_base + TIMER_ISA_MUX); u32 val = readl(timer_base + MESON_ISA_TIMER_MUX);
writel(val & ~TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX); writel(val & ~MESON_ISA_TIMER_MUX_TIMERA_EN,
timer_base + MESON_ISA_TIMER_MUX);
} }
static void meson6_clkevt_time_setup(unsigned char timer, unsigned long delay) static void meson6_clkevt_time_setup(unsigned long delay)
{ {
writel(delay, timer_base + TIMER_ISA_VAL(timer)); writel(delay, timer_base + MESON_ISA_TIMERA);
} }
static void meson6_clkevt_time_start(unsigned char timer, bool periodic) static void meson6_clkevt_time_start(bool periodic)
{ {
u32 val = readl(timer_base + TIMER_ISA_MUX); u32 val = readl(timer_base + MESON_ISA_TIMER_MUX);
if (periodic) if (periodic)
val |= TIMER_PERIODIC_BIT(timer); val |= MESON_ISA_TIMER_MUX_TIMERA_MODE;
else else
val &= ~TIMER_PERIODIC_BIT(timer); val &= ~MESON_ISA_TIMER_MUX_TIMERA_MODE;
writel(val | TIMER_ENABLE_BIT(timer), timer_base + TIMER_ISA_MUX); writel(val | MESON_ISA_TIMER_MUX_TIMERA_EN,
timer_base + MESON_ISA_TIMER_MUX);
} }
static int meson6_shutdown(struct clock_event_device *evt) static int meson6_shutdown(struct clock_event_device *evt)
{ {
meson6_clkevt_time_stop(CED_ID); meson6_clkevt_time_stop();
return 0; return 0;
} }
static int meson6_set_oneshot(struct clock_event_device *evt) static int meson6_set_oneshot(struct clock_event_device *evt)
{ {
meson6_clkevt_time_stop(CED_ID); meson6_clkevt_time_stop();
meson6_clkevt_time_start(CED_ID, false); meson6_clkevt_time_start(false);
return 0; return 0;
} }
static int meson6_set_periodic(struct clock_event_device *evt) static int meson6_set_periodic(struct clock_event_device *evt)
{ {
meson6_clkevt_time_stop(CED_ID); meson6_clkevt_time_stop();
meson6_clkevt_time_setup(CED_ID, USEC_PER_SEC / HZ - 1); meson6_clkevt_time_setup(USEC_PER_SEC / HZ - 1);
meson6_clkevt_time_start(CED_ID, true); meson6_clkevt_time_start(true);
return 0; return 0;
} }
static int meson6_clkevt_next_event(unsigned long evt, static int meson6_clkevt_next_event(unsigned long evt,
struct clock_event_device *unused) struct clock_event_device *unused)
{ {
meson6_clkevt_time_stop(CED_ID); meson6_clkevt_time_stop();
meson6_clkevt_time_setup(CED_ID, evt); meson6_clkevt_time_setup(evt);
meson6_clkevt_time_start(CED_ID, false); meson6_clkevt_time_start(false);
return 0; return 0;
} }
...@@ -144,22 +178,24 @@ static int __init meson6_timer_init(struct device_node *node) ...@@ -144,22 +178,24 @@ static int __init meson6_timer_init(struct device_node *node)
} }
/* Set 1us for timer E */ /* Set 1us for timer E */
val = readl(timer_base + TIMER_ISA_MUX); val = readl(timer_base + MESON_ISA_TIMER_MUX);
val &= ~TIMER_CSD_INPUT_MASK; val &= ~MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK;
val |= TIMER_CSD_UNIT_1US << TIMER_INPUT_BIT(CSD_ID); val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK,
writel(val, timer_base + TIMER_ISA_MUX); 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); sched_clock_register(meson6_timer_sched_read, 32, USEC_PER_SEC);
clocksource_mmio_init(timer_base + TIMER_ISA_VAL(CSD_ID), node->name, clocksource_mmio_init(timer_base + MESON_ISA_TIMERE, node->name,
1000 * 1000, 300, 32, clocksource_mmio_readl_up); 1000 * 1000, 300, 32, clocksource_mmio_readl_up);
/* Timer A base 1us */ /* Timer A base 1us */
val &= ~TIMER_CED_INPUT_MASK; val &= ~MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK;
val |= TIMER_CED_UNIT_1US << TIMER_INPUT_BIT(CED_ID); val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK,
writel(val, timer_base + TIMER_ISA_MUX); MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1US);
writel(val, timer_base + MESON_ISA_TIMER_MUX);
/* Stop the timer A */ /* Stop the timer A */
meson6_clkevt_time_stop(CED_ID); meson6_clkevt_time_stop();
ret = setup_irq(irq, &meson6_timer_irq); ret = setup_irq(irq, &meson6_timer_irq);
if (ret) { if (ret) {
...@@ -172,6 +208,12 @@ static int __init meson6_timer_init(struct device_node *node) ...@@ -172,6 +208,12 @@ static int __init meson6_timer_init(struct device_node *node)
clockevents_config_and_register(&meson6_clockevent, USEC_PER_SEC, clockevents_config_and_register(&meson6_clockevent, USEC_PER_SEC,
1, 0xfffe); 1, 0xfffe);
#ifdef CONFIG_ARM
/* Also use MESON_ISA_TIMERE for delays */
register_current_timer_delay(&meson6_delay_timer);
#endif
return 0; return 0;
} }
TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer", TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer",
......
// 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);
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/sched_clock.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/sbi.h> #include <asm/sbi.h>
...@@ -49,6 +50,11 @@ static unsigned long long riscv_clocksource_rdtime(struct clocksource *cs) ...@@ -49,6 +50,11 @@ static unsigned long long riscv_clocksource_rdtime(struct clocksource *cs)
return get_cycles64(); return get_cycles64();
} }
static u64 riscv_sched_clock(void)
{
return get_cycles64();
}
static DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = { static DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = {
.name = "riscv_clocksource", .name = "riscv_clocksource",
.rating = 300, .rating = 300,
...@@ -97,6 +103,9 @@ static int __init riscv_timer_init_dt(struct device_node *n) ...@@ -97,6 +103,9 @@ static int __init riscv_timer_init_dt(struct device_node *n)
cs = per_cpu_ptr(&riscv_clocksource, cpuid); cs = per_cpu_ptr(&riscv_clocksource, cpuid);
clocksource_register_hz(cs, riscv_timebase); 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, error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING,
"clockevents/riscv/timer:starting", "clockevents/riscv/timer:starting",
riscv_timer_starting_cpu, riscv_timer_dying_cpu); riscv_timer_starting_cpu, riscv_timer_dying_cpu);
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
#include <asm/smp_twd.h>
#define RTC_SECONDS 0x08 #define RTC_SECONDS 0x08
#define RTC_SHADOW_SECONDS 0x0c #define RTC_SHADOW_SECONDS 0x0c
......
...@@ -991,7 +991,6 @@ static struct platform_driver omap_dm_timer_driver = { ...@@ -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_platform_driver(omap_dm_timer_driver);
MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver"); MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
......
...@@ -145,7 +145,7 @@ static int __init vt8500_timer_init(struct device_node *np) ...@@ -145,7 +145,7 @@ static int __init vt8500_timer_init(struct device_node *np)
ret = clocksource_register_hz(&clocksource, VT8500_TIMER_HZ); ret = clocksource_register_hz(&clocksource, VT8500_TIMER_HZ);
if (ret) { 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); __func__, clocksource.name);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment