summaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/Kconfig87
-rw-r--r--drivers/clocksource/Makefile6
-rw-r--r--drivers/clocksource/arc_timer.c6
-rw-r--r--drivers/clocksource/arm_arch_timer.c12
-rw-r--r--drivers/clocksource/arm_global_timer.c2
-rw-r--r--drivers/clocksource/armv7m_systick.c2
-rw-r--r--drivers/clocksource/asm9260_timer.c2
-rw-r--r--drivers/clocksource/bcm2835_timer.c2
-rw-r--r--drivers/clocksource/bcm_kona_timer.c4
-rw-r--r--drivers/clocksource/cadence_ttc_timer.c3
-rw-r--r--drivers/clocksource/clkevt-probe.c56
-rw-r--r--drivers/clocksource/clksrc-dbx500-prcmu.c2
-rw-r--r--drivers/clocksource/clksrc_st_lpc.c2
-rw-r--r--drivers/clocksource/clps711x-timer.c4
-rw-r--r--drivers/clocksource/dw_apb_timer_of.c8
-rw-r--r--drivers/clocksource/exynos_mct.c4
-rw-r--r--drivers/clocksource/fsl_ftm_timer.c10
-rw-r--r--drivers/clocksource/h8300_timer16.c2
-rw-r--r--drivers/clocksource/h8300_timer8.c2
-rw-r--r--drivers/clocksource/h8300_tpu.c2
-rw-r--r--drivers/clocksource/jcore-pit.c2
-rw-r--r--drivers/clocksource/meson6_timer.c2
-rw-r--r--drivers/clocksource/mips-gic-timer.c7
-rw-r--r--drivers/clocksource/moxart_timer.c256
-rw-r--r--drivers/clocksource/mps2-timer.c2
-rw-r--r--drivers/clocksource/mtk_timer.c2
-rw-r--r--drivers/clocksource/mxs_timer.c2
-rw-r--r--drivers/clocksource/nomadik-mtu.c2
-rw-r--r--drivers/clocksource/owl-timer.c172
-rw-r--r--drivers/clocksource/pxa_timer.c2
-rw-r--r--drivers/clocksource/qcom-timer.c4
-rw-r--r--drivers/clocksource/renesas-ostm.c2
-rw-r--r--drivers/clocksource/rockchip_timer.c4
-rw-r--r--drivers/clocksource/samsung_pwm_timer.c10
-rw-r--r--drivers/clocksource/sun4i_timer.c173
-rw-r--r--drivers/clocksource/tango_xtal.c2
-rw-r--r--drivers/clocksource/tcb_clksrc.c109
-rw-r--r--drivers/clocksource/tegra20_timer.c4
-rw-r--r--drivers/clocksource/time-armada-370-xp.c6
-rw-r--r--drivers/clocksource/time-efm32.c4
-rw-r--r--drivers/clocksource/time-lpc32xx.c2
-rw-r--r--drivers/clocksource/time-orion.c2
-rw-r--r--drivers/clocksource/time-pistachio.c2
-rw-r--r--drivers/clocksource/timer-atlas7.c2
-rw-r--r--drivers/clocksource/timer-atmel-pit.c2
-rw-r--r--drivers/clocksource/timer-atmel-st.c2
-rw-r--r--drivers/clocksource/timer-digicolor.c2
-rw-r--r--drivers/clocksource/timer-fttmr010.c476
-rw-r--r--drivers/clocksource/timer-imx-gpt.c24
-rw-r--r--drivers/clocksource/timer-integrator-ap.c2
-rw-r--r--drivers/clocksource/timer-keystone.c2
-rw-r--r--drivers/clocksource/timer-nps.c6
-rw-r--r--drivers/clocksource/timer-of.c171
-rw-r--r--drivers/clocksource/timer-of.h69
-rw-r--r--drivers/clocksource/timer-oxnas-rps.c4
-rw-r--r--drivers/clocksource/timer-prima2.c2
-rw-r--r--drivers/clocksource/timer-probe.c (renamed from drivers/clocksource/clksrc-probe.c)20
-rw-r--r--drivers/clocksource/timer-sp804.c4
-rw-r--r--drivers/clocksource/timer-stm32.c2
-rw-r--r--drivers/clocksource/timer-sun5i.c5
-rw-r--r--drivers/clocksource/timer-ti-32k.c2
-rw-r--r--drivers/clocksource/timer-u300.c2
-rw-r--r--drivers/clocksource/versatile.c4
-rw-r--r--drivers/clocksource/vf_pit_timer.c2
-rw-r--r--drivers/clocksource/vt8500_timer.c2
-rw-r--r--drivers/clocksource/zevio-timer.c2
66 files changed, 1019 insertions, 781 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 545d541ae20e..fcae5ca6ac92 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -1,22 +1,16 @@
menu "Clock Source drivers"
depends on !ARCH_USES_GETTIMEOFFSET
-config CLKSRC_OF
+config TIMER_OF
bool
- select CLKSRC_PROBE
-
-config CLKEVT_OF
- bool
- select CLKEVT_PROBE
-
-config CLKSRC_ACPI
- bool
- select CLKSRC_PROBE
+ depends on GENERIC_CLOCKEVENTS
+ select TIMER_PROBE
-config CLKSRC_PROBE
+config TIMER_ACPI
bool
+ select TIMER_PROBE
-config CLKEVT_PROBE
+config TIMER_PROBE
bool
config CLKSRC_I8253
@@ -65,14 +59,14 @@ config DW_APB_TIMER
config DW_APB_TIMER_OF
bool
select DW_APB_TIMER
- select CLKSRC_OF
+ select TIMER_OF
config FTTMR010_TIMER
bool "Faraday Technology timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
depends on HAS_IOMEM
select CLKSRC_MMIO
- select CLKSRC_OF
+ select TIMER_OF
select MFD_SYSCON
help
Enables support for the Faraday Technology timer block
@@ -81,7 +75,7 @@ config FTTMR010_TIMER
config ROCKCHIP_TIMER
bool "Rockchip timer driver" if COMPILE_TEST
depends on ARM || ARM64
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
Enables the support for the rockchip timer driver.
@@ -89,7 +83,7 @@ config ROCKCHIP_TIMER
config ARMADA_370_XP_TIMER
bool "Armada 370 and XP timer driver" if COMPILE_TEST
depends on ARM
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
Enables the support for the Armada 370 and XP timer driver.
@@ -104,16 +98,24 @@ config MESON6_TIMER
config ORION_TIMER
bool "Orion timer driver" if COMPILE_TEST
depends on ARM
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
Enables the support for the Orion timer driver
+config OWL_TIMER
+ bool "Owl timer driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ select CLKSRC_MMIO
+ help
+ Enables the support for the Actions Semi Owl timer driver.
+
config SUN4I_TIMER
bool "Sun4i timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
depends on HAS_IOMEM
select CLKSRC_MMIO
+ select TIMER_OF
help
Enables support for the Sun4i timer.
@@ -148,7 +150,7 @@ config ASM9260_TIMER
bool "ASM9260 timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
- select CLKSRC_OF
+ select TIMER_OF
help
Enables support for the ASM9260 timer.
@@ -188,13 +190,6 @@ config ATLAS7_TIMER
help
Enables support for the Atlas7 timer.
-config MOXART_TIMER
- bool "Moxart timer driver" if COMPILE_TEST
- depends on GENERIC_CLOCKEVENTS
- select CLKSRC_MMIO
- help
- Enables support for the Moxart timer.
-
config MXS_TIMER
bool "Mxs timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
@@ -261,21 +256,21 @@ config CLKSRC_LPC32XX
depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
depends on ARM
select CLKSRC_MMIO
- select CLKSRC_OF
+ select TIMER_OF
help
Support for the LPC32XX clocksource.
config CLKSRC_PISTACHIO
bool "Clocksource for Pistachio SoC" if COMPILE_TEST
depends on HAS_IOMEM
- select CLKSRC_OF
+ select TIMER_OF
help
Enables the clocksource for the Pistachio SoC.
config CLKSRC_TI_32K
bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
help
This option enables support for Texas Instruments 32.768 Hz clocksource
available on many OMAP-like platforms.
@@ -284,7 +279,7 @@ config CLKSRC_NPS
bool "NPS400 clocksource driver" if COMPILE_TEST
depends on !PHYS_ADDR_T_64BIT
select CLKSRC_MMIO
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
help
NPS400 clocksource support.
Got 64 bit counter with update rate up to 1000MHz.
@@ -299,12 +294,12 @@ config CLKSRC_MPS2
bool "Clocksource for MPS2 SoCs" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK
select CLKSRC_MMIO
- select CLKSRC_OF
+ select TIMER_OF
config ARC_TIMERS
bool "Support for 32-bit TIMERn counters in ARC Cores" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
- select CLKSRC_OF
+ select TIMER_OF
help
These are legacy 32-bit TIMER0 and TIMER1 counters found on all ARC cores
(ARC700 as well as ARC HS38).
@@ -314,7 +309,7 @@ config ARC_TIMERS_64BIT
bool "Support for 64-bit counters in ARC HS38 cores" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
depends on ARC_TIMERS
- select CLKSRC_OF
+ select TIMER_OF
help
This enables 2 different 64-bit timers: RTC (for UP) and GFRC (for SMP)
RTC is implemented inside the core, while GFRC sits outside the core in
@@ -323,8 +318,8 @@ config ARC_TIMERS_64BIT
config ARM_ARCH_TIMER
bool
- select CLKSRC_OF if OF
- select CLKSRC_ACPI if ACPI
+ select TIMER_OF if OF
+ select TIMER_ACPI if ACPI
config ARM_ARCH_TIMER_EVTSTREAM
bool "Enable ARM architected timer event stream generation by default"
@@ -381,7 +376,7 @@ config ARM64_ERRATUM_858921
config ARM_GLOBAL_TIMER
bool "Support for the ARM global timer" if COMPILE_TEST
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
depends on ARM
help
This options enables support for the ARM global timer unit
@@ -390,7 +385,7 @@ config ARM_TIMER_SP804
bool "Support for Dual Timer SP804 module"
depends on GENERIC_SCHED_CLOCK && CLKDEV_LOOKUP
select CLKSRC_MMIO
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
bool
@@ -401,19 +396,19 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
config ARMV7M_SYSTICK
bool "Support for the ARMv7M system time" if COMPILE_TEST
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
select CLKSRC_MMIO
help
This options enables support for the ARMv7M system timer unit
config ATMEL_PIT
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
def_bool SOC_AT91SAM9 || SOC_SAMA5
config ATMEL_ST
bool "Atmel ST timer support" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
- select CLKSRC_OF
+ select TIMER_OF
select MFD_SYSCON
help
Support for the Atmel ST timer.
@@ -456,7 +451,7 @@ config VF_PIT_TIMER
config OXNAS_RPS_TIMER
bool "Oxford Semiconductor OXNAS RPS Timers driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
This enables support for the Oxford Semiconductor OXNAS RPS timers.
@@ -467,7 +462,7 @@ config SYS_SUPPORTS_SH_CMT
config MTK_TIMER
bool "Mediatek timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
Support for Mediatek timer driver.
@@ -540,7 +535,7 @@ config EM_TIMER_STI
config CLKSRC_QCOM
bool "Qualcomm MSM timer" if COMPILE_TEST
depends on ARM
- select CLKSRC_OF
+ select TIMER_OF
help
This enables the clocksource and the per CPU clockevent driver for the
Qualcomm SoCs.
@@ -548,7 +543,7 @@ config CLKSRC_QCOM
config CLKSRC_VERSATILE
bool "ARM Versatile (Express) reference platforms clock source" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK && !ARCH_USES_GETTIMEOFFSET
- select CLKSRC_OF
+ select TIMER_OF
default y if MFD_VEXPRESS_SYSREG
help
This option enables clock source based on free running
@@ -559,12 +554,12 @@ config CLKSRC_VERSATILE
config CLKSRC_MIPS_GIC
bool
depends on MIPS_GIC
- select CLKSRC_OF
+ select TIMER_OF
config CLKSRC_TANGO_XTAL
bool "Clocksource for Tango SoC" if COMPILE_TEST
depends on ARM
- select CLKSRC_OF
+ select TIMER_OF
select CLKSRC_MMIO
help
This enables the clocksource for Tango SoC
@@ -605,7 +600,7 @@ config CLKSRC_IMX_GPT
config CLKSRC_ST_LPC
bool "Low power clocksource found in the LPC" if COMPILE_TEST
- select CLKSRC_OF if OF
+ select TIMER_OF if OF
depends on HAS_IOMEM
select CLKSRC_MMIO
help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 2b5b56a6f00f..6df949402dfc 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -1,5 +1,5 @@
-obj-$(CONFIG_CLKSRC_PROBE) += clksrc-probe.o
-obj-$(CONFIG_CLKEVT_PROBE) += clkevt-probe.o
+obj-$(CONFIG_TIMER_OF) += timer-of.o
+obj-$(CONFIG_TIMER_PROBE) += timer-probe.o
obj-$(CONFIG_ATMEL_PIT) += timer-atmel-pit.o
obj-$(CONFIG_ATMEL_ST) += timer-atmel-st.o
obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
@@ -26,7 +26,6 @@ obj-$(CONFIG_ORION_TIMER) += time-orion.o
obj-$(CONFIG_BCM2835_TIMER) += bcm2835_timer.o
obj-$(CONFIG_CLPS711X_TIMER) += clps711x-timer.o
obj-$(CONFIG_ATLAS7_TIMER) += timer-atlas7.o
-obj-$(CONFIG_MOXART_TIMER) += moxart_timer.o
obj-$(CONFIG_MXS_TIMER) += mxs_timer.o
obj-$(CONFIG_CLKSRC_PXA) += pxa_timer.o
obj-$(CONFIG_PRIMA2_TIMER) += timer-prima2.o
@@ -53,6 +52,7 @@ obj-$(CONFIG_CLKSRC_PISTACHIO) += time-pistachio.o
obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
obj-$(CONFIG_CLKSRC_NPS) += timer-nps.o
obj-$(CONFIG_OXNAS_RPS_TIMER) += timer-oxnas-rps.o
+obj-$(CONFIG_OWL_TIMER) += owl-timer.o
obj-$(CONFIG_ARC_TIMERS) += arc_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
diff --git a/drivers/clocksource/arc_timer.c b/drivers/clocksource/arc_timer.c
index 21649733827d..4927355f9cbe 100644
--- a/drivers/clocksource/arc_timer.c
+++ b/drivers/clocksource/arc_timer.c
@@ -99,7 +99,7 @@ static int __init arc_cs_setup_gfrc(struct device_node *node)
return clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq);
}
-CLOCKSOURCE_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);
#define AUX_RTC_CTRL 0x103
#define AUX_RTC_LOW 0x104
@@ -158,7 +158,7 @@ static int __init arc_cs_setup_rtc(struct device_node *node)
return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq);
}
-CLOCKSOURCE_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);
#endif
@@ -333,4 +333,4 @@ static int __init arc_of_timer_init(struct device_node *np)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);
+TIMER_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 4bed671e490e..aae87c4c546e 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1194,8 +1194,8 @@ static int __init arch_timer_of_init(struct device_node *np)
return arch_timer_common_init();
}
-CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
-CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);
+TIMER_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
+TIMER_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_of_init);
static u32 __init
arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame)
@@ -1209,9 +1209,9 @@ arch_timer_mem_frame_get_cntfrq(struct arch_timer_mem_frame *frame)
return 0;
}
- rate = readl_relaxed(frame + CNTFRQ);
+ rate = readl_relaxed(base + CNTFRQ);
- iounmap(frame);
+ iounmap(base);
return rate;
}
@@ -1382,7 +1382,7 @@ out:
kfree(timer_mem);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
+TIMER_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
arch_timer_mem_of_init);
#ifdef CONFIG_ACPI_GTDT
@@ -1516,5 +1516,5 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
return arch_timer_common_init();
}
-CLOCKSOURCE_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
+TIMER_ACPI_DECLARE(arch_timer, ACPI_SIG_GTDT, arch_timer_acpi_init);
#endif
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index 123ed20ac2ff..095bb965f621 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -339,5 +339,5 @@ out_unmap:
}
/* Only tested on r2p2 and r3p0 */
-CLOCKSOURCE_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",
+TIMER_OF_DECLARE(arm_gt, "arm,cortex-a9-global-timer",
global_timer_of_register);
diff --git a/drivers/clocksource/armv7m_systick.c b/drivers/clocksource/armv7m_systick.c
index a315491b7047..ac046d6fb0bf 100644
--- a/drivers/clocksource/armv7m_systick.c
+++ b/drivers/clocksource/armv7m_systick.c
@@ -82,5 +82,5 @@ out_unmap:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(arm_systick, "arm,armv7m-systick",
+TIMER_OF_DECLARE(arm_systick, "arm,armv7m-systick",
system_timer_of_register);
diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c
index c6780830b8ac..38cd2feb87c4 100644
--- a/drivers/clocksource/asm9260_timer.c
+++ b/drivers/clocksource/asm9260_timer.c
@@ -238,5 +238,5 @@ static int __init asm9260_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer",
+TIMER_OF_DECLARE(asm9260_timer, "alphascale,asm9260-timer",
asm9260_timer_init);
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
index dce44307469e..82828d3a4739 100644
--- a/drivers/clocksource/bcm2835_timer.c
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -148,5 +148,5 @@ err_iounmap:
iounmap(base);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer",
+TIMER_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer",
bcm2835_timer_init);
diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c
index fda5e1476638..5c40be9880f5 100644
--- a/drivers/clocksource/bcm_kona_timer.c
+++ b/drivers/clocksource/bcm_kona_timer.c
@@ -198,9 +198,9 @@ static int __init kona_timer_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(brcm_kona, "brcm,kona-timer", kona_timer_init);
+TIMER_OF_DECLARE(brcm_kona, "brcm,kona-timer", kona_timer_init);
/*
* bcm,kona-timer is deprecated by brcm,kona-timer
* being kept here for driver compatibility
*/
-CLOCKSOURCE_OF_DECLARE(bcm_kona, "bcm,kona-timer", kona_timer_init);
+TIMER_OF_DECLARE(bcm_kona, "bcm,kona-timer", kona_timer_init);
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
index 44e5e951583b..29d51755e18b 100644
--- a/drivers/clocksource/cadence_ttc_timer.c
+++ b/drivers/clocksource/cadence_ttc_timer.c
@@ -18,6 +18,7 @@
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/clockchips.h>
+#include <linux/clocksource.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
@@ -539,4 +540,4 @@ static int __init ttc_timer_init(struct device_node *timer)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init);
+TIMER_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init);
diff --git a/drivers/clocksource/clkevt-probe.c b/drivers/clocksource/clkevt-probe.c
deleted file mode 100644
index eb89b502acbd..000000000000
--- a/drivers/clocksource/clkevt-probe.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2016, Linaro Ltd. All rights reserved.
- * Daniel Lezcano <daniel.lezcano@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/clockchips.h>
-
-extern struct of_device_id __clkevt_of_table[];
-
-static const struct of_device_id __clkevt_of_table_sentinel
- __used __section(__clkevt_of_table_end);
-
-int __init clockevent_probe(void)
-{
- struct device_node *np;
- const struct of_device_id *match;
- of_init_fn_1_ret init_func;
- int ret, clockevents = 0;
-
- for_each_matching_node_and_match(np, __clkevt_of_table, &match) {
- if (!of_device_is_available(np))
- continue;
-
- init_func = match->data;
-
- ret = init_func(np);
- if (ret) {
- pr_warn("Failed to initialize '%s' (%d)\n",
- np->name, ret);
- continue;
- }
-
- clockevents++;
- }
-
- if (!clockevents) {
- pr_crit("%s: no matching clockevent found\n", __func__);
- return -ENODEV;
- }
-
- return 0;
-}
diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c
index c69e2772658d..c1b96dc5f444 100644
--- a/drivers/clocksource/clksrc-dbx500-prcmu.c
+++ b/drivers/clocksource/clksrc-dbx500-prcmu.c
@@ -86,5 +86,5 @@ static int __init clksrc_dbx500_prcmu_init(struct device_node *node)
#endif
return clocksource_register_hz(&clocksource_dbx500_prcmu, RATE_32K);
}
-CLOCKSOURCE_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4",
+TIMER_OF_DECLARE(dbx500_prcmu, "stericsson,db8500-prcmu-timer-4",
clksrc_dbx500_prcmu_init);
diff --git a/drivers/clocksource/clksrc_st_lpc.c b/drivers/clocksource/clksrc_st_lpc.c
index 03cc49217bb4..a1d01ebb81f5 100644
--- a/drivers/clocksource/clksrc_st_lpc.c
+++ b/drivers/clocksource/clksrc_st_lpc.c
@@ -132,4 +132,4 @@ static int __init st_clksrc_of_register(struct device_node *np)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(ddata, "st,stih407-lpc", st_clksrc_of_register);
+TIMER_OF_DECLARE(ddata, "st,stih407-lpc", st_clksrc_of_register);
diff --git a/drivers/clocksource/clps711x-timer.c b/drivers/clocksource/clps711x-timer.c
index 24db6d605549..a8dd80576c95 100644
--- a/drivers/clocksource/clps711x-timer.c
+++ b/drivers/clocksource/clps711x-timer.c
@@ -103,7 +103,7 @@ void __init clps711x_clksrc_init(void __iomem *tc1_base, void __iomem *tc2_base,
BUG_ON(_clps711x_clkevt_init(tc2, tc2_base, irq));
}
-#ifdef CONFIG_CLKSRC_OF
+#ifdef CONFIG_TIMER_OF
static int __init clps711x_timer_init(struct device_node *np)
{
unsigned int irq = irq_of_parse_and_map(np, 0);
@@ -119,5 +119,5 @@ static int __init clps711x_timer_init(struct device_node *np)
return -EINVAL;
}
}
-CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,ep7209-timer", clps711x_timer_init);
+TIMER_OF_DECLARE(clps711x, "cirrus,ep7209-timer", clps711x_timer_init);
#endif
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index aee6c0d39a7c..69866cd8f4bb 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -167,7 +167,7 @@ static int __init dw_apb_timer_init(struct device_node *timer)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init);
-CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init);
+TIMER_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init);
+TIMER_OF_DECLARE(apb_timer_osc, "snps,dw-apb-timer-osc", dw_apb_timer_init);
+TIMER_OF_DECLARE(apb_timer_sp, "snps,dw-apb-timer-sp", dw_apb_timer_init);
+TIMER_OF_DECLARE(apb_timer, "snps,dw-apb-timer", dw_apb_timer_init);
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index 670ff0f25b67..7a244b681876 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -610,5 +610,5 @@ static int __init mct_init_ppi(struct device_node *np)
{
return mct_init_dt(np, MCT_INT_PPI);
}
-CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi);
-CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
+TIMER_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi);
+TIMER_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
diff --git a/drivers/clocksource/fsl_ftm_timer.c b/drivers/clocksource/fsl_ftm_timer.c
index 738515b89073..3ee7e6fea621 100644
--- a/drivers/clocksource/fsl_ftm_timer.c
+++ b/drivers/clocksource/fsl_ftm_timer.c
@@ -329,13 +329,13 @@ static int __init ftm_timer_init(struct device_node *np)
priv->clkevt_base = of_iomap(np, 0);
if (!priv->clkevt_base) {
pr_err("ftm: unable to map event timer registers\n");
- goto err;
+ goto err_clkevt;
}
priv->clksrc_base = of_iomap(np, 1);
if (!priv->clksrc_base) {
pr_err("ftm: unable to map source timer registers\n");
- goto err;
+ goto err_clksrc;
}
ret = -EINVAL;
@@ -366,7 +366,11 @@ static int __init ftm_timer_init(struct device_node *np)
return 0;
err:
+ iounmap(priv->clksrc_base);
+err_clksrc:
+ iounmap(priv->clkevt_base);
+err_clkevt:
kfree(priv);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init);
+TIMER_OF_DECLARE(flextimer, "fsl,ftm-timer", ftm_timer_init);
diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c
index 5b27fb9997c2..dfbd4f8051cb 100644
--- a/drivers/clocksource/h8300_timer16.c
+++ b/drivers/clocksource/h8300_timer16.c
@@ -187,5 +187,5 @@ free_clk:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(h8300_16bit, "renesas,16bit-timer",
+TIMER_OF_DECLARE(h8300_16bit, "renesas,16bit-timer",
h8300_16timer_init);
diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c
index 804c489531d6..f6ffb0cef091 100644
--- a/drivers/clocksource/h8300_timer8.c
+++ b/drivers/clocksource/h8300_timer8.c
@@ -207,4 +207,4 @@ free_clk:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init);
+TIMER_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init);
diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c
index 72e1cf2b3096..45a8d17dac1e 100644
--- a/drivers/clocksource/h8300_tpu.c
+++ b/drivers/clocksource/h8300_tpu.c
@@ -154,4 +154,4 @@ free_clk:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init);
+TIMER_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init);
diff --git a/drivers/clocksource/jcore-pit.c b/drivers/clocksource/jcore-pit.c
index 7c61226f4359..5d3d88e0fc8c 100644
--- a/drivers/clocksource/jcore-pit.c
+++ b/drivers/clocksource/jcore-pit.c
@@ -246,4 +246,4 @@ static int __init jcore_pit_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(jcore_pit, "jcore,pit", jcore_pit_init);
+TIMER_OF_DECLARE(jcore_pit, "jcore,pit", jcore_pit_init);
diff --git a/drivers/clocksource/meson6_timer.c b/drivers/clocksource/meson6_timer.c
index 39d21f693a33..92f20991a937 100644
--- a/drivers/clocksource/meson6_timer.c
+++ b/drivers/clocksource/meson6_timer.c
@@ -174,5 +174,5 @@ static int __init meson6_timer_init(struct device_node *node)
1, 0xfffe);
return 0;
}
-CLOCKSOURCE_OF_DECLARE(meson6, "amlogic,meson6-timer",
+TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer",
meson6_timer_init);
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
index 3f52ee219923..17b861ea2626 100644
--- a/drivers/clocksource/mips-gic-timer.c
+++ b/drivers/clocksource/mips-gic-timer.c
@@ -167,10 +167,11 @@ static int __init gic_clocksource_of_init(struct device_node *node)
clk = of_clk_get(node, 0);
if (!IS_ERR(clk)) {
- if (clk_prepare_enable(clk) < 0) {
+ ret = clk_prepare_enable(clk);
+ if (ret < 0) {
pr_err("GIC failed to enable clock\n");
clk_put(clk);
- return PTR_ERR(clk);
+ return ret;
}
gic_frequency = clk_get_rate(clk);
@@ -200,5 +201,5 @@ static int __init gic_clocksource_of_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(mips_gic_timer, "mti,gic-timer",
+TIMER_OF_DECLARE(mips_gic_timer, "mti,gic-timer",
gic_clocksource_of_init);
diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c
deleted file mode 100644
index 7f3430654fbd..000000000000
--- a/drivers/clocksource/moxart_timer.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * MOXA ART SoCs timer handling.
- *
- * Copyright (C) 2013 Jonas Jensen
- *
- * Jonas Jensen <jonas.jensen@gmail.com>
- *
- * 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/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/io.h>
-#include <linux/clocksource.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-
-#define TIMER1_BASE 0x00
-#define TIMER2_BASE 0x10
-#define TIMER3_BASE 0x20
-
-#define REG_COUNT 0x0 /* writable */
-#define REG_LOAD 0x4
-#define REG_MATCH1 0x8
-#define REG_MATCH2 0xC
-
-#define TIMER_CR 0x30
-#define TIMER_INTR_STATE 0x34
-#define TIMER_INTR_MASK 0x38
-
-/*
- * Moxart TIMER_CR flags:
- *
- * MOXART_CR_*_CLOCK 0: PCLK, 1: EXT1CLK
- * MOXART_CR_*_INT overflow interrupt enable bit
- */
-#define MOXART_CR_1_ENABLE BIT(0)
-#define MOXART_CR_1_CLOCK BIT(1)
-#define MOXART_CR_1_INT BIT(2)
-#define MOXART_CR_2_ENABLE BIT(3)
-#define MOXART_CR_2_CLOCK BIT(4)
-#define MOXART_CR_2_INT BIT(5)
-#define MOXART_CR_3_ENABLE BIT(6)
-#define MOXART_CR_3_CLOCK BIT(7)
-#define MOXART_CR_3_INT BIT(8)
-#define MOXART_CR_COUNT_UP BIT(9)
-
-#define MOXART_TIMER1_ENABLE (MOXART_CR_2_ENABLE | MOXART_CR_1_ENABLE)
-#define MOXART_TIMER1_DISABLE (MOXART_CR_2_ENABLE)
-
-/*
- * The ASpeed variant of the IP block has a different layout
- * for the control register
- */
-#define ASPEED_CR_1_ENABLE BIT(0)
-#define ASPEED_CR_1_CLOCK BIT(1)
-#define ASPEED_CR_1_INT BIT(2)
-#define ASPEED_CR_2_ENABLE BIT(4)
-#define ASPEED_CR_2_CLOCK BIT(5)
-#define ASPEED_CR_2_INT BIT(6)
-#define ASPEED_CR_3_ENABLE BIT(8)
-#define ASPEED_CR_3_CLOCK BIT(9)
-#define ASPEED_CR_3_INT BIT(10)
-
-#define ASPEED_TIMER1_ENABLE (ASPEED_CR_2_ENABLE | ASPEED_CR_1_ENABLE)
-#define ASPEED_TIMER1_DISABLE (ASPEED_CR_2_ENABLE)
-
-struct moxart_timer {
- void __iomem *base;
- unsigned int t1_disable_val;
- unsigned int t1_enable_val;
- unsigned int count_per_tick;
- struct clock_event_device clkevt;
-};
-
-static inline struct moxart_timer *to_moxart(struct clock_event_device *evt)
-{
- return container_of(evt, struct moxart_timer, clkevt);
-}
-
-static inline void moxart_disable(struct clock_event_device *evt)
-{
- struct moxart_timer *timer = to_moxart(evt);
-
- writel(timer->t1_disable_val, timer->base + TIMER_CR);
-}
-
-static inline void moxart_enable(struct clock_event_device *evt)
-{
- struct moxart_timer *timer = to_moxart(evt);
-
- writel(timer->t1_enable_val, timer->base + TIMER_CR);
-}
-
-static int moxart_shutdown(struct clock_event_device *evt)
-{
- moxart_disable(evt);
- return 0;
-}
-
-static int moxart_set_oneshot(struct clock_event_device *evt)
-{
- moxart_disable(evt);
- writel(~0, to_moxart(evt)->base + TIMER1_BASE + REG_LOAD);
- return 0;
-}
-
-static int moxart_set_periodic(struct clock_event_device *evt)
-{
- struct moxart_timer *timer = to_moxart(evt);
-
- moxart_disable(evt);
- writel(timer->count_per_tick, timer->base + TIMER1_BASE + REG_LOAD);
- writel(0, timer->base + TIMER1_BASE + REG_MATCH1);
- moxart_enable(evt);
- return 0;
-}
-
-static int moxart_clkevt_next_event(unsigned long cycles,
- struct clock_event_device *evt)
-{
- struct moxart_timer *timer = to_moxart(evt);
- u32 u;
-
- moxart_disable(evt);
-
- u = readl(timer->base + TIMER1_BASE + REG_COUNT) - cycles;
- writel(u, timer->base + TIMER1_BASE + REG_MATCH1);
-
- moxart_enable(evt);
-
- return 0;
-}
-
-static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id)
-{
- struct clock_event_device *evt = dev_id;
- evt->event_handler(evt);
- return IRQ_HANDLED;
-}
-
-static int __init moxart_timer_init(struct device_node *node)
-{
- int ret, irq;
- unsigned long pclk;
- struct clk *clk;
- struct moxart_timer *timer;
-
- timer = kzalloc(sizeof(*timer), GFP_KERNEL);
- if (!timer)
- return -ENOMEM;
-
- timer->base = of_iomap(node, 0);
- if (!timer->base) {
- pr_err("%s: of_iomap failed\n", node->full_name);
- ret = -ENXIO;
- goto out_free;
- }
-
- irq = irq_of_parse_and_map(node, 0);
- if (irq <= 0) {
- pr_err("%s: irq_of_parse_and_map failed\n", node->full_name);
- ret = -EINVAL;
- goto out_unmap;
- }
-
- clk = of_clk_get(node, 0);
- if (IS_ERR(clk)) {
- pr_err("%s: of_clk_get failed\n", node->full_name);
- ret = PTR_ERR(clk);
- goto out_unmap;
- }
-
- pclk = clk_get_rate(clk);
-
- if (of_device_is_compatible(node, "moxa,moxart-timer")) {
- timer->t1_enable_val = MOXART_TIMER1_ENABLE;
- timer->t1_disable_val = MOXART_TIMER1_DISABLE;
- } else if (of_device_is_compatible(node, "aspeed,ast2400-timer")) {
- timer->t1_enable_val = ASPEED_TIMER1_ENABLE;
- timer->t1_disable_val = ASPEED_TIMER1_DISABLE;
- } else {
- pr_err("%s: unknown platform\n", node->full_name);
- ret = -EINVAL;
- goto out_unmap;
- }
-
- timer->count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ);
-
- timer->clkevt.name = node->name;
- timer->clkevt.rating = 200;
- timer->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT;
- timer->clkevt.set_state_shutdown = moxart_shutdown;
- timer->clkevt.set_state_periodic = moxart_set_periodic;
- timer->clkevt.set_state_oneshot = moxart_set_oneshot;
- timer->clkevt.tick_resume = moxart_set_oneshot;
- timer->clkevt.set_next_event = moxart_clkevt_next_event;
- timer->clkevt.cpumask = cpumask_of(0);
- timer->clkevt.irq = irq;
-
- ret = clocksource_mmio_init(timer->base + TIMER2_BASE + REG_COUNT,
- "moxart_timer", pclk, 200, 32,
- clocksource_mmio_readl_down);
- if (ret) {
- pr_err("%s: clocksource_mmio_init failed\n", node->full_name);
- goto out_unmap;
- }
-
- ret = request_irq(irq, moxart_timer_interrupt, IRQF_TIMER,
- node->name, &timer->clkevt);
- if (ret) {
- pr_err("%s: setup_irq failed\n", node->full_name);
- goto out_unmap;
- }
-
- /* Clear match registers */
- writel(0, timer->base + TIMER1_BASE + REG_MATCH1);
- writel(0, timer->base + TIMER1_BASE + REG_MATCH2);
- writel(0, timer->base + TIMER2_BASE + REG_MATCH1);
- writel(0, timer->base + TIMER2_BASE + REG_MATCH2);
-
- /*
- * Start timer 2 rolling as our main wall clock source, keep timer 1
- * disabled
- */
- writel(0, timer->base + TIMER_CR);
- writel(~0, timer->base + TIMER2_BASE + REG_LOAD);
- writel(timer->t1_disable_val, timer->base + TIMER_CR);
-
- /*
- * documentation is not publicly available:
- * min_delta / max_delta obtained by trial-and-error,
- * max_delta 0xfffffffe should be ok because count
- * register size is u32
- */
- clockevents_config_and_register(&timer->clkevt, pclk, 0x4, 0xfffffffe);
-
- return 0;
-
-out_unmap:
- iounmap(timer->base);
-out_free:
- kfree(timer);
- return ret;
-}
-CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init);
-CLOCKSOURCE_OF_DECLARE(aspeed, "aspeed,ast2400-timer", moxart_timer_init);
diff --git a/drivers/clocksource/mps2-timer.c b/drivers/clocksource/mps2-timer.c
index 3e4431ed9aa9..aa4d63af8706 100644
--- a/drivers/clocksource/mps2-timer.c
+++ b/drivers/clocksource/mps2-timer.c
@@ -274,4 +274,4 @@ static int __init mps2_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(mps2_timer, "arm,mps2-timer", mps2_timer_init);
+TIMER_OF_DECLARE(mps2_timer, "arm,mps2-timer", mps2_timer_init);
diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
index 90659493c59c..f9b724fd9950 100644
--- a/drivers/clocksource/mtk_timer.c
+++ b/drivers/clocksource/mtk_timer.c
@@ -265,4 +265,4 @@ err_kzalloc:
return -EINVAL;
}
-CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init);
+TIMER_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init);
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c
index 99b77aff0839..a03434e9fe8f 100644
--- a/drivers/clocksource/mxs_timer.c
+++ b/drivers/clocksource/mxs_timer.c
@@ -293,4 +293,4 @@ static int __init mxs_timer_init(struct device_node *np)
return setup_irq(irq, &mxs_timer_irq);
}
-CLOCKSOURCE_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init);
+TIMER_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init);
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c
index 7d44de304f37..8e4ddb9420c6 100644
--- a/drivers/clocksource/nomadik-mtu.c
+++ b/drivers/clocksource/nomadik-mtu.c
@@ -284,5 +284,5 @@ static int __init nmdk_timer_of_init(struct device_node *node)
return nmdk_timer_init(base, irq, pclk, clk);
}
-CLOCKSOURCE_OF_DECLARE(nomadik_mtu, "st,nomadik-mtu",
+TIMER_OF_DECLARE(nomadik_mtu, "st,nomadik-mtu",
nmdk_timer_of_init);
diff --git a/drivers/clocksource/owl-timer.c b/drivers/clocksource/owl-timer.c
new file mode 100644
index 000000000000..d19c53c11094
--- /dev/null
+++ b/drivers/clocksource/owl-timer.c
@@ -0,0 +1,172 @@
+/*
+ * Actions Semi Owl timer
+ *
+ * Copyright 2012 Actions Semi Inc.
+ * Author: Actions Semi, Inc.
+ *
+ * Copyright (c) 2017 SUSE Linux GmbH
+ * Author: Andreas Färber
+ *
+ * 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.
+ */
+
+#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 OWL_Tx_CTL 0x0
+#define OWL_Tx_CMP 0x4
+#define OWL_Tx_VAL 0x8
+
+#define OWL_Tx_CTL_PD BIT(0)
+#define OWL_Tx_CTL_INTEN BIT(1)
+#define OWL_Tx_CTL_EN BIT(2)
+
+static void __iomem *owl_timer_base;
+static void __iomem *owl_clksrc_base;
+static void __iomem *owl_clkevt_base;
+
+static inline void owl_timer_reset(void __iomem *base)
+{
+ writel(0, base + OWL_Tx_CTL);
+ writel(0, base + OWL_Tx_VAL);
+ writel(0, base + OWL_Tx_CMP);
+}
+
+static inline void owl_timer_set_enabled(void __iomem *base, bool enabled)
+{
+ u32 ctl = readl(base + OWL_Tx_CTL);
+
+ /* PD bit is cleared when set */
+ ctl &= ~OWL_Tx_CTL_PD;
+
+ if (enabled)
+ ctl |= OWL_Tx_CTL_EN;
+ else
+ ctl &= ~OWL_Tx_CTL_EN;
+
+ writel(ctl, base + OWL_Tx_CTL);
+}
+
+static u64 notrace owl_timer_sched_read(void)
+{
+ return (u64)readl(owl_clksrc_base + OWL_Tx_VAL);
+}
+
+static int owl_timer_set_state_shutdown(struct clock_event_device *evt)
+{
+ owl_timer_set_enabled(owl_clkevt_base, false);
+
+ return 0;
+}
+
+static int owl_timer_set_state_oneshot(struct clock_event_device *evt)
+{
+ owl_timer_reset(owl_clkevt_base);
+
+ return 0;
+}
+
+static int owl_timer_tick_resume(struct clock_event_device *evt)
+{
+ return 0;
+}
+
+static int owl_timer_set_next_event(unsigned long evt,
+ struct clock_event_device *ev)
+{
+ void __iomem *base = owl_clkevt_base;
+
+ owl_timer_set_enabled(base, false);
+ writel(OWL_Tx_CTL_INTEN, base + OWL_Tx_CTL);
+ writel(0, base + OWL_Tx_VAL);
+ writel(evt, base + OWL_Tx_CMP);
+ owl_timer_set_enabled(base, true);
+
+ return 0;
+}
+
+static struct clock_event_device owl_clockevent = {
+ .name = "owl_tick",
+ .rating = 200,
+ .features = CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_DYNIRQ,
+ .set_state_shutdown = owl_timer_set_state_shutdown,
+ .set_state_oneshot = owl_timer_set_state_oneshot,
+ .tick_resume = owl_timer_tick_resume,
+ .set_next_event = owl_timer_set_next_event,
+};
+
+static irqreturn_t owl_timer1_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+
+ writel(OWL_Tx_CTL_PD, owl_clkevt_base + OWL_Tx_CTL);
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static int __init owl_timer_init(struct device_node *node)
+{
+ struct clk *clk;
+ unsigned long rate;
+ int timer1_irq, ret;
+
+ owl_timer_base = of_io_request_and_map(node, 0, "owl-timer");
+ if (IS_ERR(owl_timer_base)) {
+ pr_err("Can't map timer registers");
+ return PTR_ERR(owl_timer_base);
+ }
+
+ owl_clksrc_base = owl_timer_base + 0x08;
+ owl_clkevt_base = owl_timer_base + 0x14;
+
+ timer1_irq = of_irq_get_byname(node, "timer1");
+ if (timer1_irq <= 0) {
+ pr_err("Can't parse timer1 IRQ");
+ return -EINVAL;
+ }
+
+ clk = of_clk_get(node, 0);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ rate = clk_get_rate(clk);
+
+ owl_timer_reset(owl_clksrc_base);
+ owl_timer_set_enabled(owl_clksrc_base, true);
+
+ sched_clock_register(owl_timer_sched_read, 32, rate);
+ clocksource_mmio_init(owl_clksrc_base + OWL_Tx_VAL, node->name,
+ rate, 200, 32, clocksource_mmio_readl_up);
+
+ owl_timer_reset(owl_clkevt_base);
+
+ ret = request_irq(timer1_irq, owl_timer1_interrupt, IRQF_TIMER,
+ "owl-timer", &owl_clockevent);
+ if (ret) {
+ pr_err("failed to request irq %d\n", timer1_irq);
+ return ret;
+ }
+
+ owl_clockevent.cpumask = cpumask_of(0);
+ owl_clockevent.irq = timer1_irq;
+
+ clockevents_config_and_register(&owl_clockevent, rate,
+ 0xf, 0xffffffff);
+
+ return 0;
+}
+CLOCKSOURCE_OF_DECLARE(owl_s500, "actions,s500-timer", owl_timer_init);
+CLOCKSOURCE_OF_DECLARE(owl_s900, "actions,s900-timer", owl_timer_init);
diff --git a/drivers/clocksource/pxa_timer.c b/drivers/clocksource/pxa_timer.c
index a10fa667325f..08cd6eaf3795 100644
--- a/drivers/clocksource/pxa_timer.c
+++ b/drivers/clocksource/pxa_timer.c
@@ -216,7 +216,7 @@ static int __init pxa_timer_dt_init(struct device_node *np)
return pxa_timer_common_init(irq, clk_get_rate(clk));
}
-CLOCKSOURCE_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init);
+TIMER_OF_DECLARE(pxa_timer, "marvell,pxa-timer", pxa_timer_dt_init);
/*
* Legacy timer init for non device-tree boards.
diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c
index ee358cdf4a07..89816f89ff3f 100644
--- a/drivers/clocksource/qcom-timer.c
+++ b/drivers/clocksource/qcom-timer.c
@@ -254,5 +254,5 @@ static int __init msm_dt_timer_init(struct device_node *np)
return msm_timer_init(freq, 32, irq, !!percpu_offset);
}
-CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
-CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
+TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
+TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
diff --git a/drivers/clocksource/renesas-ostm.c b/drivers/clocksource/renesas-ostm.c
index c76f57668fb2..6cffd7c6001a 100644
--- a/drivers/clocksource/renesas-ostm.c
+++ b/drivers/clocksource/renesas-ostm.c
@@ -262,4 +262,4 @@ err:
return 0;
}
-CLOCKSOURCE_OF_DECLARE(ostm, "renesas,ostm", ostm_init);
+TIMER_OF_DECLARE(ostm, "renesas,ostm", ostm_init);
diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
index 49c02be50eca..c27f4c850d83 100644
--- a/drivers/clocksource/rockchip_timer.c
+++ b/drivers/clocksource/rockchip_timer.c
@@ -303,5 +303,5 @@ static int __init rk_timer_init(struct device_node *np)
return -EINVAL;
}
-CLOCKSOURCE_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init);
-CLOCKSOURCE_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init);
+TIMER_OF_DECLARE(rk3288_timer, "rockchip,rk3288-timer", rk_timer_init);
+TIMER_OF_DECLARE(rk3399_timer, "rockchip,rk3399-timer", rk_timer_init);
diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c
index a68e6538c809..6d5d126357c2 100644
--- a/drivers/clocksource/samsung_pwm_timer.c
+++ b/drivers/clocksource/samsung_pwm_timer.c
@@ -418,7 +418,7 @@ void __init samsung_pwm_clocksource_init(void __iomem *base,
_samsung_pwm_clocksource_init();
}
-#ifdef CONFIG_CLKSRC_OF
+#ifdef CONFIG_TIMER_OF
static int __init samsung_pwm_alloc(struct device_node *np,
const struct samsung_pwm_variant *variant)
{
@@ -466,7 +466,7 @@ static int __init s3c2410_pwm_clocksource_init(struct device_node *np)
{
return samsung_pwm_alloc(np, &s3c24xx_variant);
}
-CLOCKSOURCE_OF_DECLARE(s3c2410_pwm, "samsung,s3c2410-pwm", s3c2410_pwm_clocksource_init);
+TIMER_OF_DECLARE(s3c2410_pwm, "samsung,s3c2410-pwm", s3c2410_pwm_clocksource_init);
static const struct samsung_pwm_variant s3c64xx_variant = {
.bits = 32,
@@ -479,7 +479,7 @@ static int __init s3c64xx_pwm_clocksource_init(struct device_node *np)
{
return samsung_pwm_alloc(np, &s3c64xx_variant);
}
-CLOCKSOURCE_OF_DECLARE(s3c6400_pwm, "samsung,s3c6400-pwm", s3c64xx_pwm_clocksource_init);
+TIMER_OF_DECLARE(s3c6400_pwm, "samsung,s3c6400-pwm", s3c64xx_pwm_clocksource_init);
static const struct samsung_pwm_variant s5p64x0_variant = {
.bits = 32,
@@ -492,7 +492,7 @@ static int __init s5p64x0_pwm_clocksource_init(struct device_node *np)
{
return samsung_pwm_alloc(np, &s5p64x0_variant);
}
-CLOCKSOURCE_OF_DECLARE(s5p6440_pwm, "samsung,s5p6440-pwm", s5p64x0_pwm_clocksource_init);
+TIMER_OF_DECLARE(s5p6440_pwm, "samsung,s5p6440-pwm", s5p64x0_pwm_clocksource_init);
static const struct samsung_pwm_variant s5p_variant = {
.bits = 32,
@@ -505,5 +505,5 @@ static int __init s5p_pwm_clocksource_init(struct device_node *np)
{
return samsung_pwm_alloc(np, &s5p_variant);
}
-CLOCKSOURCE_OF_DECLARE(s5pc100_pwm, "samsung,s5pc100-pwm", s5p_pwm_clocksource_init);
+TIMER_OF_DECLARE(s5pc100_pwm, "samsung,s5pc100-pwm", s5p_pwm_clocksource_init);
#endif
diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c
index 4452d5c8f304..6e0180aaf784 100644
--- a/drivers/clocksource/sun4i_timer.c
+++ b/drivers/clocksource/sun4i_timer.c
@@ -24,6 +24,8 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include "timer-of.h"
+
#define TIMER_IRQ_EN_REG 0x00
#define TIMER_IRQ_EN(val) BIT(val)
#define TIMER_IRQ_ST_REG 0x04
@@ -39,38 +41,37 @@
#define TIMER_SYNC_TICKS 3
-static void __iomem *timer_base;
-static u32 ticks_per_jiffy;
-
/*
* When we disable a timer, we need to wait at least for 2 cycles of
* the timer source clock. We will use for that the clocksource timer
* that is already setup and runs at the same frequency than the other
* timers, and we never will be disabled.
*/
-static void sun4i_clkevt_sync(void)
+static void sun4i_clkevt_sync(void __iomem *base)
{
- u32 old = readl(timer_base + TIMER_CNTVAL_REG(1));
+ u32 old = readl(base + TIMER_CNTVAL_REG(1));
- while ((old - readl(timer_base + TIMER_CNTVAL_REG(1))) < TIMER_SYNC_TICKS)
+ while ((old - readl(base + TIMER_CNTVAL_REG(1))) < TIMER_SYNC_TICKS)
cpu_relax();
}
-static void sun4i_clkevt_time_stop(u8 timer)
+static void sun4i_clkevt_time_stop(void __iomem *base, u8 timer)
{
- u32 val = readl(timer_base + TIMER_CTL_REG(timer));
- writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer));
- sun4i_clkevt_sync();
+ u32 val = readl(base + TIMER_CTL_REG(timer));
+ writel(val & ~TIMER_CTL_ENABLE, base + TIMER_CTL_REG(timer));
+ sun4i_clkevt_sync(base);
}
-static void sun4i_clkevt_time_setup(u8 timer, unsigned long delay)
+static void sun4i_clkevt_time_setup(void __iomem *base, u8 timer,
+ unsigned long delay)
{
- writel(delay, timer_base + TIMER_INTVAL_REG(timer));
+ writel(delay, base + TIMER_INTVAL_REG(timer));
}
-static void sun4i_clkevt_time_start(u8 timer, bool periodic)
+static void sun4i_clkevt_time_start(void __iomem *base, u8 timer,
+ bool periodic)
{
- u32 val = readl(timer_base + TIMER_CTL_REG(timer));
+ u32 val = readl(base + TIMER_CTL_REG(timer));
if (periodic)
val &= ~TIMER_CTL_ONESHOT;
@@ -78,115 +79,106 @@ static void sun4i_clkevt_time_start(u8 timer, bool periodic)
val |= TIMER_CTL_ONESHOT;
writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
- timer_base + TIMER_CTL_REG(timer));
+ base + TIMER_CTL_REG(timer));
}
static int sun4i_clkevt_shutdown(struct clock_event_device *evt)
{
- sun4i_clkevt_time_stop(0);
+ struct timer_of *to = to_timer_of(evt);
+
+ sun4i_clkevt_time_stop(timer_of_base(to), 0);
+
return 0;
}
static int sun4i_clkevt_set_oneshot(struct clock_event_device *evt)
{
- sun4i_clkevt_time_stop(0);
- sun4i_clkevt_time_start(0, false);
+ struct timer_of *to = to_timer_of(evt);
+
+ sun4i_clkevt_time_stop(timer_of_base(to), 0);
+ sun4i_clkevt_time_start(timer_of_base(to), 0, false);
+
return 0;
}
static int sun4i_clkevt_set_periodic(struct clock_event_device *evt)
{
- sun4i_clkevt_time_stop(0);
- sun4i_clkevt_time_setup(0, ticks_per_jiffy);
- sun4i_clkevt_time_start(0, true);
+ struct timer_of *to = to_timer_of(evt);
+
+ sun4i_clkevt_time_stop(timer_of_base(to), 0);
+ sun4i_clkevt_time_setup(timer_of_base(to), 0, timer_of_period(to));
+ sun4i_clkevt_time_start(timer_of_base(to), 0, true);
+
return 0;
}
static int sun4i_clkevt_next_event(unsigned long evt,
- struct clock_event_device *unused)
+ struct clock_event_device *clkevt)
{
- sun4i_clkevt_time_stop(0);
- sun4i_clkevt_time_setup(0, evt - TIMER_SYNC_TICKS);
- sun4i_clkevt_time_start(0, false);
+ struct timer_of *to = to_timer_of(clkevt);
+
+ sun4i_clkevt_time_stop(timer_of_base(to), 0);
+ sun4i_clkevt_time_setup(timer_of_base(to), 0, evt - TIMER_SYNC_TICKS);
+ sun4i_clkevt_time_start(timer_of_base(to), 0, false);
return 0;
}
-static struct clock_event_device sun4i_clockevent = {
- .name = "sun4i_tick",
- .rating = 350,
- .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .set_state_shutdown = sun4i_clkevt_shutdown,
- .set_state_periodic = sun4i_clkevt_set_periodic,
- .set_state_oneshot = sun4i_clkevt_set_oneshot,
- .tick_resume = sun4i_clkevt_shutdown,
- .set_next_event = sun4i_clkevt_next_event,
-};
-
-static void sun4i_timer_clear_interrupt(void)
+static void sun4i_timer_clear_interrupt(void __iomem *base)
{
- writel(TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_ST_REG);
+ writel(TIMER_IRQ_EN(0), base + TIMER_IRQ_ST_REG);
}
static irqreturn_t sun4i_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = (struct clock_event_device *)dev_id;
+ struct timer_of *to = to_timer_of(evt);
- sun4i_timer_clear_interrupt();
+ sun4i_timer_clear_interrupt(timer_of_base(to));
evt->event_handler(evt);
return IRQ_HANDLED;
}
-static struct irqaction sun4i_timer_irq = {
- .name = "sun4i_timer0",
- .flags = IRQF_TIMER | IRQF_IRQPOLL,
- .handler = sun4i_timer_interrupt,
- .dev_id = &sun4i_clockevent,
+static struct timer_of to = {
+ .flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE,
+
+ .clkevt = {
+ .name = "sun4i_tick",
+ .rating = 350,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_state_shutdown = sun4i_clkevt_shutdown,
+ .set_state_periodic = sun4i_clkevt_set_periodic,
+ .set_state_oneshot = sun4i_clkevt_set_oneshot,
+ .tick_resume = sun4i_clkevt_shutdown,
+ .set_next_event = sun4i_clkevt_next_event,
+ .cpumask = cpu_possible_mask,
+ },
+
+ .of_irq = {
+ .handler = sun4i_timer_interrupt,
+ .flags = IRQF_TIMER | IRQF_IRQPOLL,
+ },
};
static u64 notrace sun4i_timer_sched_read(void)
{
- return ~readl(timer_base + TIMER_CNTVAL_REG(1));
+ return ~readl(timer_of_base(&to) + TIMER_CNTVAL_REG(1));
}
static int __init sun4i_timer_init(struct device_node *node)
{
- unsigned long rate = 0;
- struct clk *clk;
- int ret, irq;
+ int ret;
u32 val;
- timer_base = of_iomap(node, 0);
- if (!timer_base) {
- pr_crit("Can't map registers\n");
- return -ENXIO;
- }
-
- irq = irq_of_parse_and_map(node, 0);
- if (irq <= 0) {
- pr_crit("Can't parse IRQ\n");
- return -EINVAL;
- }
-
- clk = of_clk_get(node, 0);
- if (IS_ERR(clk)) {
- pr_crit("Can't get timer clock\n");
- return PTR_ERR(clk);
- }
-
- ret = clk_prepare_enable(clk);
- if (ret) {
- pr_err("Failed to prepare clock\n");
+ ret = timer_of_init(node, &to);
+ if (ret)
return ret;
- }
-
- rate = clk_get_rate(clk);
- writel(~0, timer_base + TIMER_INTVAL_REG(1));
+ writel(~0, timer_of_base(&to) + TIMER_INTVAL_REG(1));
writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD |
TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
- timer_base + TIMER_CTL_REG(1));
+ timer_of_base(&to) + TIMER_CTL_REG(1));
/*
* sched_clock_register does not have priorities, and on sun6i and
@@ -195,43 +187,34 @@ static int __init sun4i_timer_init(struct device_node *node)
if (of_machine_is_compatible("allwinner,sun4i-a10") ||
of_machine_is_compatible("allwinner,sun5i-a13") ||
of_machine_is_compatible("allwinner,sun5i-a10s"))
- sched_clock_register(sun4i_timer_sched_read, 32, rate);
+ sched_clock_register(sun4i_timer_sched_read, 32,
+ timer_of_rate(&to));
- ret = clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name,
- rate, 350, 32, clocksource_mmio_readl_down);
+ ret = clocksource_mmio_init(timer_of_base(&to) + TIMER_CNTVAL_REG(1),
+ node->name, timer_of_rate(&to), 350, 32,
+ clocksource_mmio_readl_down);
if (ret) {
pr_err("Failed to register clocksource\n");
return ret;
}
- ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
-
writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M),
- timer_base + TIMER_CTL_REG(0));
+ timer_of_base(&to) + TIMER_CTL_REG(0));
/* Make sure timer is stopped before playing with interrupts */
- sun4i_clkevt_time_stop(0);
+ sun4i_clkevt_time_stop(timer_of_base(&to), 0);
/* clear timer0 interrupt */
- sun4i_timer_clear_interrupt();
-
- sun4i_clockevent.cpumask = cpu_possible_mask;
- sun4i_clockevent.irq = irq;
+ sun4i_timer_clear_interrupt(timer_of_base(&to));
- clockevents_config_and_register(&sun4i_clockevent, rate,
+ clockevents_config_and_register(&to.clkevt, timer_of_rate(&to),
TIMER_SYNC_TICKS, 0xffffffff);
- ret = setup_irq(irq, &sun4i_timer_irq);
- if (ret) {
- pr_err("failed to setup irq %d\n", irq);
- return ret;
- }
-
/* Enable timer0 interrupt */
- val = readl(timer_base + TIMER_IRQ_EN_REG);
- writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG);
+ val = readl(timer_of_base(&to) + TIMER_IRQ_EN_REG);
+ writel(val | TIMER_IRQ_EN(0), timer_of_base(&to) + TIMER_IRQ_EN_REG);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer",
+TIMER_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer",
sun4i_timer_init);
diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/tango_xtal.c
index 12fcef8cf2d3..c4e1c2e6046f 100644
--- a/drivers/clocksource/tango_xtal.c
+++ b/drivers/clocksource/tango_xtal.c
@@ -53,4 +53,4 @@ static int __init tango_clocksource_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init);
+TIMER_OF_DECLARE(tango, "sigma,tick-counter", tango_clocksource_init);
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index d4ca9962a759..59e8aee0ec16 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -9,6 +9,7 @@
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
#include <linux/atmel_tc.h>
@@ -40,6 +41,14 @@
*/
static void __iomem *tcaddr;
+static struct
+{
+ u32 cmr;
+ u32 imr;
+ u32 rc;
+ bool clken;
+} tcb_cache[3];
+static u32 bmr_cache;
static u64 tc_get_cycles(struct clocksource *cs)
{
@@ -48,9 +57,9 @@ static u64 tc_get_cycles(struct clocksource *cs)
raw_local_irq_save(flags);
do {
- upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV));
- lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
- } while (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)));
+ upper = readl_relaxed(tcaddr + ATMEL_TC_REG(1, CV));
+ lower = readl_relaxed(tcaddr + ATMEL_TC_REG(0, CV));
+ } while (upper != readl_relaxed(tcaddr + ATMEL_TC_REG(1, CV)));
raw_local_irq_restore(flags);
return (upper << 16) | lower;
@@ -58,7 +67,47 @@ static u64 tc_get_cycles(struct clocksource *cs)
static u64 tc_get_cycles32(struct clocksource *cs)
{
- return __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
+ return readl_relaxed(tcaddr + ATMEL_TC_REG(0, CV));
+}
+
+void tc_clksrc_suspend(struct clocksource *cs)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) {
+ tcb_cache[i].cmr = readl(tcaddr + ATMEL_TC_REG(i, CMR));
+ tcb_cache[i].imr = readl(tcaddr + ATMEL_TC_REG(i, IMR));
+ tcb_cache[i].rc = readl(tcaddr + ATMEL_TC_REG(i, RC));
+ tcb_cache[i].clken = !!(readl(tcaddr + ATMEL_TC_REG(i, SR)) &
+ ATMEL_TC_CLKSTA);
+ }
+
+ bmr_cache = readl(tcaddr + ATMEL_TC_BMR);
+}
+
+void tc_clksrc_resume(struct clocksource *cs)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tcb_cache); i++) {
+ /* Restore registers for the channel, RA and RB are not used */
+ writel(tcb_cache[i].cmr, tcaddr + ATMEL_TC_REG(i, CMR));
+ writel(tcb_cache[i].rc, tcaddr + ATMEL_TC_REG(i, RC));
+ writel(0, tcaddr + ATMEL_TC_REG(i, RA));
+ writel(0, tcaddr + ATMEL_TC_REG(i, RB));
+ /* Disable all the interrupts */
+ writel(0xff, tcaddr + ATMEL_TC_REG(i, IDR));
+ /* Reenable interrupts that were enabled before suspending */
+ writel(tcb_cache[i].imr, tcaddr + ATMEL_TC_REG(i, IER));
+ /* Start the clock if it was used */
+ if (tcb_cache[i].clken)
+ writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(i, CCR));
+ }
+
+ /* Dual channel, chain channels */
+ writel(bmr_cache, tcaddr + ATMEL_TC_BMR);
+ /* Finally, trigger all the channels*/
+ writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
}
static struct clocksource clksrc = {
@@ -67,6 +116,8 @@ static struct clocksource clksrc = {
.read = tc_get_cycles,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .suspend = tc_clksrc_suspend,
+ .resume = tc_clksrc_resume,
};
#ifdef CONFIG_GENERIC_CLOCKEVENTS
@@ -96,8 +147,8 @@ static int tc_shutdown(struct clock_event_device *d)
struct tc_clkevt_device *tcd = to_tc_clkevt(d);
void __iomem *regs = tcd->regs;
- __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
- __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
+ writel(0xff, regs + ATMEL_TC_REG(2, IDR));
+ writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
if (!clockevent_state_detached(d))
clk_disable(tcd->clk);
@@ -115,9 +166,9 @@ static int tc_set_oneshot(struct clock_event_device *d)
clk_enable(tcd->clk);
/* slow clock, count up to RC, then irq and stop */
- __raw_writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE |
+ writel(timer_clock | ATMEL_TC_CPCSTOP | ATMEL_TC_WAVE |
ATMEL_TC_WAVESEL_UP_AUTO, regs + ATMEL_TC_REG(2, CMR));
- __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
+ writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
/* set_next_event() configures and starts the timer */
return 0;
@@ -137,25 +188,25 @@ static int tc_set_periodic(struct clock_event_device *d)
clk_enable(tcd->clk);
/* slow clock, count up to RC, then irq and restart */
- __raw_writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
+ writel(timer_clock | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO,
regs + ATMEL_TC_REG(2, CMR));
- __raw_writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
+ writel((32768 + HZ / 2) / HZ, tcaddr + ATMEL_TC_REG(2, RC));
/* Enable clock and interrupts on RC compare */
- __raw_writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
+ writel(ATMEL_TC_CPCS, regs + ATMEL_TC_REG(2, IER));
/* go go gadget! */
- __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs +
+ writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, regs +
ATMEL_TC_REG(2, CCR));
return 0;
}
static int tc_next_event(unsigned long delta, struct clock_event_device *d)
{
- __raw_writel(delta, tcaddr + ATMEL_TC_REG(2, RC));
+ writel_relaxed(delta, tcaddr + ATMEL_TC_REG(2, RC));
/* go go gadget! */
- __raw_writel(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
+ writel_relaxed(ATMEL_TC_CLKEN | ATMEL_TC_SWTRG,
tcaddr + ATMEL_TC_REG(2, CCR));
return 0;
}
@@ -179,7 +230,7 @@ static irqreturn_t ch2_irq(int irq, void *handle)
struct tc_clkevt_device *dev = handle;
unsigned int sr;
- sr = __raw_readl(dev->regs + ATMEL_TC_REG(2, SR));
+ sr = readl_relaxed(dev->regs + ATMEL_TC_REG(2, SR));
if (sr & ATMEL_TC_CPCS) {
dev->clkevt.event_handler(&dev->clkevt);
return IRQ_HANDLED;
@@ -239,43 +290,43 @@ static int __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
static void __init tcb_setup_dual_chan(struct atmel_tc *tc, int mck_divisor_idx)
{
/* channel 0: waveform mode, input mclk/8, clock TIOA0 on overflow */
- __raw_writel(mck_divisor_idx /* likely divide-by-8 */
+ writel(mck_divisor_idx /* likely divide-by-8 */
| ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP /* free-run */
| ATMEL_TC_ACPA_SET /* TIOA0 rises at 0 */
| ATMEL_TC_ACPC_CLEAR, /* (duty cycle 50%) */
tcaddr + ATMEL_TC_REG(0, CMR));
- __raw_writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA));
- __raw_writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC));
- __raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
- __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
+ writel(0x0000, tcaddr + ATMEL_TC_REG(0, RA));
+ writel(0x8000, tcaddr + ATMEL_TC_REG(0, RC));
+ writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
+ writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
/* channel 1: waveform mode, input TIOA0 */
- __raw_writel(ATMEL_TC_XC1 /* input: TIOA0 */
+ writel(ATMEL_TC_XC1 /* input: TIOA0 */
| ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP, /* free-run */
tcaddr + ATMEL_TC_REG(1, CMR));
- __raw_writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR)); /* no irqs */
- __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR));
+ writel(0xff, tcaddr + ATMEL_TC_REG(1, IDR)); /* no irqs */
+ writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(1, CCR));
/* chain channel 0 to channel 1*/
- __raw_writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR);
+ writel(ATMEL_TC_TC1XC1S_TIOA0, tcaddr + ATMEL_TC_BMR);
/* then reset all the timers */
- __raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
+ writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
}
static void __init tcb_setup_single_chan(struct atmel_tc *tc, int mck_divisor_idx)
{
/* channel 0: waveform mode, input mclk/8 */
- __raw_writel(mck_divisor_idx /* likely divide-by-8 */
+ writel(mck_divisor_idx /* likely divide-by-8 */
| ATMEL_TC_WAVE
| ATMEL_TC_WAVESEL_UP, /* free-run */
tcaddr + ATMEL_TC_REG(0, CMR));
- __raw_writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
- __raw_writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
+ writel(0xff, tcaddr + ATMEL_TC_REG(0, IDR)); /* no irqs */
+ writel(ATMEL_TC_CLKEN, tcaddr + ATMEL_TC_REG(0, CCR));
/* then reset all the timers */
- __raw_writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
+ writel(ATMEL_TC_SYNC, tcaddr + ATMEL_TC_BCR);
}
static int __init tcb_clksrc_init(void)
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index b9990b9c98c5..c337a8100a7b 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -237,7 +237,7 @@ static int __init tegra20_init_timer(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer);
+TIMER_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer);
static int __init tegra20_init_rtc(struct device_node *np)
{
@@ -261,4 +261,4 @@ static int __init tegra20_init_rtc(struct device_node *np)
return register_persistent_clock(NULL, tegra_read_persistent_clock64);
}
-CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
+TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
index aea4380129ea..edf1a46269f1 100644
--- a/drivers/clocksource/time-armada-370-xp.c
+++ b/drivers/clocksource/time-armada-370-xp.c
@@ -351,7 +351,7 @@ static int __init armada_xp_timer_init(struct device_node *np)
return armada_370_xp_timer_common_init(np);
}
-CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
+TIMER_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
armada_xp_timer_init);
static int __init armada_375_timer_init(struct device_node *np)
@@ -389,7 +389,7 @@ static int __init armada_375_timer_init(struct device_node *np)
return armada_370_xp_timer_common_init(np);
}
-CLOCKSOURCE_OF_DECLARE(armada_375, "marvell,armada-375-timer",
+TIMER_OF_DECLARE(armada_375, "marvell,armada-375-timer",
armada_375_timer_init);
static int __init armada_370_timer_init(struct device_node *np)
@@ -412,5 +412,5 @@ static int __init armada_370_timer_init(struct device_node *np)
return armada_370_xp_timer_common_init(np);
}
-CLOCKSOURCE_OF_DECLARE(armada_370, "marvell,armada-370-timer",
+TIMER_OF_DECLARE(armada_370, "marvell,armada-370-timer",
armada_370_timer_init);
diff --git a/drivers/clocksource/time-efm32.c b/drivers/clocksource/time-efm32.c
index ce0f97b4e5db..257e810ec1ad 100644
--- a/drivers/clocksource/time-efm32.c
+++ b/drivers/clocksource/time-efm32.c
@@ -283,5 +283,5 @@ static int __init efm32_timer_init(struct device_node *np)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init);
-CLOCKSOURCE_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init);
+TIMER_OF_DECLARE(efm32compat, "efm32,timer", efm32_timer_init);
+TIMER_OF_DECLARE(efm32, "energymicro,efm32-timer", efm32_timer_init);
diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c
index 9649cfdb9213..d51a62a79ef7 100644
--- a/drivers/clocksource/time-lpc32xx.c
+++ b/drivers/clocksource/time-lpc32xx.c
@@ -311,4 +311,4 @@ static int __init lpc32xx_timer_init(struct device_node *np)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init);
+TIMER_OF_DECLARE(lpc32xx_timer, "nxp,lpc3220-timer", lpc32xx_timer_init);
diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c
index b9b97f630c4d..12202067fe4b 100644
--- a/drivers/clocksource/time-orion.c
+++ b/drivers/clocksource/time-orion.c
@@ -189,4 +189,4 @@ static int __init orion_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init);
+TIMER_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init);
diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c
index 3710e4d9dcba..a2dd85d0c1d7 100644
--- a/drivers/clocksource/time-pistachio.c
+++ b/drivers/clocksource/time-pistachio.c
@@ -214,5 +214,5 @@ static int __init pistachio_clksrc_of_init(struct device_node *node)
sched_clock_register(pistachio_read_sched_clock, 32, rate);
return clocksource_register_hz(&pcs_gpt.cs, rate);
}
-CLOCKSOURCE_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
+TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
pistachio_clksrc_of_init);
diff --git a/drivers/clocksource/timer-atlas7.c b/drivers/clocksource/timer-atlas7.c
index 50300eec4a39..62c4bbc55a7e 100644
--- a/drivers/clocksource/timer-atlas7.c
+++ b/drivers/clocksource/timer-atlas7.c
@@ -283,4 +283,4 @@ static int __init sirfsoc_of_timer_init(struct device_node *np)
return sirfsoc_atlas7_timer_init(np);
}
-CLOCKSOURCE_OF_DECLARE(sirfsoc_atlas7_timer, "sirf,atlas7-tick", sirfsoc_of_timer_init);
+TIMER_OF_DECLARE(sirfsoc_atlas7_timer, "sirf,atlas7-tick", sirfsoc_of_timer_init);
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
index cc112351dc70..ec8a4376f74f 100644
--- a/drivers/clocksource/timer-atmel-pit.c
+++ b/drivers/clocksource/timer-atmel-pit.c
@@ -255,5 +255,5 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
+TIMER_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
at91sam926x_pit_dt_init);
diff --git a/drivers/clocksource/timer-atmel-st.c b/drivers/clocksource/timer-atmel-st.c
index be4ac7604136..d2e660f475af 100644
--- a/drivers/clocksource/timer-atmel-st.c
+++ b/drivers/clocksource/timer-atmel-st.c
@@ -260,5 +260,5 @@ static int __init atmel_st_timer_init(struct device_node *node)
/* register clocksource */
return clocksource_register_hz(&clk32k, sclk_rate);
}
-CLOCKSOURCE_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
+TIMER_OF_DECLARE(atmel_st_timer, "atmel,at91rm9200-st",
atmel_st_timer_init);
diff --git a/drivers/clocksource/timer-digicolor.c b/drivers/clocksource/timer-digicolor.c
index 94a161eb9cce..1e984a4d8ad0 100644
--- a/drivers/clocksource/timer-digicolor.c
+++ b/drivers/clocksource/timer-digicolor.c
@@ -203,5 +203,5 @@ static int __init digicolor_timer_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer",
+TIMER_OF_DECLARE(conexant_digicolor, "cnxt,cx92755-timer",
digicolor_timer_init);
diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c
index b4a6f1e4bc54..66dd909960c6 100644
--- a/drivers/clocksource/timer-fttmr010.c
+++ b/drivers/clocksource/timer-fttmr010.c
@@ -11,12 +11,13 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/sched_clock.h>
#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
/*
* Register definitions for the timers
@@ -37,267 +38,368 @@
#define TIMER_INTR_STATE (0x34)
#define TIMER_INTR_MASK (0x38)
-#define TIMER_1_CR_ENABLE (1 << 0)
-#define TIMER_1_CR_CLOCK (1 << 1)
-#define TIMER_1_CR_INT (1 << 2)
-#define TIMER_2_CR_ENABLE (1 << 3)
-#define TIMER_2_CR_CLOCK (1 << 4)
-#define TIMER_2_CR_INT (1 << 5)
-#define TIMER_3_CR_ENABLE (1 << 6)
-#define TIMER_3_CR_CLOCK (1 << 7)
-#define TIMER_3_CR_INT (1 << 8)
-#define TIMER_1_CR_UPDOWN (1 << 9)
-#define TIMER_2_CR_UPDOWN (1 << 10)
-#define TIMER_3_CR_UPDOWN (1 << 11)
-#define TIMER_DEFAULT_FLAGS (TIMER_1_CR_UPDOWN | \
- TIMER_3_CR_ENABLE | \
- TIMER_3_CR_UPDOWN)
-
-#define TIMER_1_INT_MATCH1 (1 << 0)
-#define TIMER_1_INT_MATCH2 (1 << 1)
-#define TIMER_1_INT_OVERFLOW (1 << 2)
-#define TIMER_2_INT_MATCH1 (1 << 3)
-#define TIMER_2_INT_MATCH2 (1 << 4)
-#define TIMER_2_INT_OVERFLOW (1 << 5)
-#define TIMER_3_INT_MATCH1 (1 << 6)
-#define TIMER_3_INT_MATCH2 (1 << 7)
-#define TIMER_3_INT_OVERFLOW (1 << 8)
+#define TIMER_1_CR_ENABLE BIT(0)
+#define TIMER_1_CR_CLOCK BIT(1)
+#define TIMER_1_CR_INT BIT(2)
+#define TIMER_2_CR_ENABLE BIT(3)
+#define TIMER_2_CR_CLOCK BIT(4)
+#define TIMER_2_CR_INT BIT(5)
+#define TIMER_3_CR_ENABLE BIT(6)
+#define TIMER_3_CR_CLOCK BIT(7)
+#define TIMER_3_CR_INT BIT(8)
+#define TIMER_1_CR_UPDOWN BIT(9)
+#define TIMER_2_CR_UPDOWN BIT(10)
+#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.
+ */
+#define TIMER_1_CR_ASPEED_ENABLE BIT(0)
+#define TIMER_1_CR_ASPEED_CLOCK BIT(1)
+#define TIMER_1_CR_ASPEED_INT BIT(2)
+#define TIMER_2_CR_ASPEED_ENABLE BIT(4)
+#define TIMER_2_CR_ASPEED_CLOCK BIT(5)
+#define TIMER_2_CR_ASPEED_INT BIT(6)
+#define TIMER_3_CR_ASPEED_ENABLE BIT(8)
+#define TIMER_3_CR_ASPEED_CLOCK BIT(9)
+#define TIMER_3_CR_ASPEED_INT BIT(10)
+
+#define TIMER_1_INT_MATCH1 BIT(0)
+#define TIMER_1_INT_MATCH2 BIT(1)
+#define TIMER_1_INT_OVERFLOW BIT(2)
+#define TIMER_2_INT_MATCH1 BIT(3)
+#define TIMER_2_INT_MATCH2 BIT(4)
+#define TIMER_2_INT_OVERFLOW BIT(5)
+#define TIMER_3_INT_MATCH1 BIT(6)
+#define TIMER_3_INT_MATCH2 BIT(7)
+#define TIMER_3_INT_OVERFLOW BIT(8)
#define TIMER_INT_ALL_MASK 0x1ff
-static unsigned int tick_rate;
-static void __iomem *base;
+struct fttmr010 {
+ void __iomem *base;
+ unsigned int tick_rate;
+ bool count_down;
+ u32 t1_enable_val;
+ struct clock_event_device clkevt;
+#ifdef CONFIG_ARM
+ struct delay_timer delay_timer;
+#endif
+};
+
+/*
+ * A local singleton used by sched_clock and delay timer reads, which are
+ * fast and stateless
+ */
+static struct fttmr010 *local_fttmr;
+
+static inline struct fttmr010 *to_fttmr010(struct clock_event_device *evt)
+{
+ return container_of(evt, struct fttmr010, clkevt);
+}
+
+static unsigned long fttmr010_read_current_timer_up(void)
+{
+ return readl(local_fttmr->base + TIMER2_COUNT);
+}
+
+static unsigned long fttmr010_read_current_timer_down(void)
+{
+ return ~readl(local_fttmr->base + TIMER2_COUNT);
+}
+
+static u64 notrace fttmr010_read_sched_clock_up(void)
+{
+ return fttmr010_read_current_timer_up();
+}
-static u64 notrace fttmr010_read_sched_clock(void)
+static u64 notrace fttmr010_read_sched_clock_down(void)
{
- return readl(base + TIMER3_COUNT);
+ return fttmr010_read_current_timer_down();
}
static int fttmr010_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
+ struct fttmr010 *fttmr010 = to_fttmr010(evt);
u32 cr;
- /* Setup the match register */
- cr = readl(base + TIMER1_COUNT);
- writel(cr + cycles, base + TIMER1_MATCH1);
- if (readl(base + TIMER1_COUNT) - cr > cycles)
- return -ETIME;
+ /* Stop */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr &= ~fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
+
+ /* Setup the match register forward/backward in time */
+ cr = readl(fttmr010->base + TIMER1_COUNT);
+ if (fttmr010->count_down)
+ cr -= cycles;
+ else
+ cr += cycles;
+ writel(cr, fttmr010->base + TIMER1_MATCH1);
+
+ /* Start */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr |= fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
return 0;
}
static int fttmr010_timer_shutdown(struct clock_event_device *evt)
{
+ struct fttmr010 *fttmr010 = to_fttmr010(evt);
u32 cr;
- /*
- * Disable also for oneshot: the set_next() call will arm the timer
- * instead.
- */
- /* Stop timer and interrupt. */
- cr = readl(base + TIMER_CR);
- cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
- writel(cr, base + TIMER_CR);
+ /* Stop */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr &= ~fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
+
+ return 0;
+}
+
+static int fttmr010_timer_set_oneshot(struct clock_event_device *evt)
+{
+ struct fttmr010 *fttmr010 = to_fttmr010(evt);
+ u32 cr;
+
+ /* Stop */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr &= ~fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
- /* Setup counter start from 0 */
- writel(0, base + TIMER1_COUNT);
- writel(0, base + TIMER1_LOAD);
+ /* Setup counter start from 0 or ~0 */
+ writel(0, fttmr010->base + TIMER1_COUNT);
+ if (fttmr010->count_down)
+ writel(~0, fttmr010->base + TIMER1_LOAD);
+ else
+ writel(0, fttmr010->base + TIMER1_LOAD);
- /* enable interrupt */
- cr = readl(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, base + TIMER_INTR_MASK);
-
- /* start the timer */
- cr = readl(base + TIMER_CR);
- cr |= TIMER_1_CR_ENABLE;
- writel(cr, base + TIMER_CR);
+ writel(cr, fttmr010->base + TIMER_INTR_MASK);
return 0;
}
static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
{
- u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ);
+ struct fttmr010 *fttmr010 = to_fttmr010(evt);
+ u32 period = DIV_ROUND_CLOSEST(fttmr010->tick_rate, HZ);
u32 cr;
- /* Stop timer and interrupt */
- cr = readl(base + TIMER_CR);
- cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
- writel(cr, base + TIMER_CR);
-
- /* Setup timer to fire at 1/HT intervals. */
- cr = 0xffffffff - (period - 1);
- writel(cr, base + TIMER1_COUNT);
- writel(cr, base + TIMER1_LOAD);
-
- /* enable interrupt on overflow */
- cr = readl(base + TIMER_INTR_MASK);
- cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
- cr |= TIMER_1_INT_OVERFLOW;
- writel(cr, base + TIMER_INTR_MASK);
+ /* Stop */
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr &= ~fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
+
+ /* Setup timer to fire at 1/HZ intervals. */
+ if (fttmr010->count_down) {
+ writel(period, fttmr010->base + TIMER1_LOAD);
+ writel(0, fttmr010->base + TIMER1_MATCH1);
+ } else {
+ cr = 0xffffffff - (period - 1);
+ writel(cr, fttmr010->base + TIMER1_COUNT);
+ writel(cr, fttmr010->base + TIMER1_LOAD);
+
+ /* Enable interrupt on overflow */
+ cr = readl(fttmr010->base + TIMER_INTR_MASK);
+ cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
+ cr |= TIMER_1_INT_OVERFLOW;
+ writel(cr, fttmr010->base + TIMER_INTR_MASK);
+ }
/* Start the timer */
- cr = readl(base + TIMER_CR);
- cr |= TIMER_1_CR_ENABLE;
- cr |= TIMER_1_CR_INT;
- writel(cr, base + TIMER_CR);
+ cr = readl(fttmr010->base + TIMER_CR);
+ cr |= fttmr010->t1_enable_val;
+ writel(cr, fttmr010->base + TIMER_CR);
return 0;
}
-/* Use TIMER1 as clock event */
-static struct clock_event_device fttmr010_clockevent = {
- .name = "TIMER1",
- /* Reasonably fast and accurate clock event */
- .rating = 300,
- .shift = 32,
- .features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT,
- .set_next_event = fttmr010_timer_set_next_event,
- .set_state_shutdown = fttmr010_timer_shutdown,
- .set_state_periodic = fttmr010_timer_set_periodic,
- .set_state_oneshot = fttmr010_timer_shutdown,
- .tick_resume = fttmr010_timer_shutdown,
-};
-
/*
* IRQ handler for the timer
*/
static irqreturn_t fttmr010_timer_interrupt(int irq, void *dev_id)
{
- struct clock_event_device *evt = &fttmr010_clockevent;
+ struct clock_event_device *evt = dev_id;
evt->event_handler(evt);
return IRQ_HANDLED;
}
-static struct irqaction fttmr010_timer_irq = {
- .name = "Faraday FTTMR010 Timer Tick",
- .flags = IRQF_TIMER,
- .handler = fttmr010_timer_interrupt,
-};
-
-static int __init fttmr010_timer_common_init(struct device_node *np)
+static int __init fttmr010_common_init(struct device_node *np, bool is_aspeed)
{
+ struct fttmr010 *fttmr010;
int irq;
+ struct clk *clk;
+ int ret;
+ u32 val;
+
+ /*
+ * These implementations require a clock reference.
+ * FIXME: we currently only support clocking using PCLK
+ * and using EXTCLK is not supported in the driver.
+ */
+ clk = of_clk_get_by_name(np, "PCLK");
+ if (IS_ERR(clk)) {
+ pr_err("could not get PCLK\n");
+ return PTR_ERR(clk);
+ }
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ pr_err("failed to enable PCLK\n");
+ return ret;
+ }
- base = of_iomap(np, 0);
- if (!base) {
+ fttmr010 = kzalloc(sizeof(*fttmr010), GFP_KERNEL);
+ if (!fttmr010) {
+ ret = -ENOMEM;
+ goto out_disable_clock;
+ }
+ fttmr010->tick_rate = clk_get_rate(clk);
+
+ fttmr010->base = of_iomap(np, 0);
+ if (!fttmr010->base) {
pr_err("Can't remap registers");
- return -ENXIO;
+ ret = -ENXIO;
+ goto out_free;
}
/* IRQ for timer 1 */
irq = irq_of_parse_and_map(np, 0);
if (irq <= 0) {
pr_err("Can't parse IRQ");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_unmap;
+ }
+
+ /*
+ * The Aspeed AST2400 moves bits around in the control register,
+ * otherwise it works the same.
+ */
+ if (is_aspeed) {
+ fttmr010->t1_enable_val = TIMER_1_CR_ASPEED_ENABLE |
+ TIMER_1_CR_ASPEED_INT;
+ /* Downward not available */
+ fttmr010->count_down = 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, base + TIMER_INTR_MASK);
- writel(0, base + TIMER_INTR_STATE);
- writel(TIMER_DEFAULT_FLAGS, base + TIMER_CR);
+ 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,
+ * where everything just counts down.
+ */
+ 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;
+ }
+ writel(val, fttmr010->base + TIMER_CR);
/*
* Setup free-running clocksource timer (interrupts
* disabled.)
*/
- writel(0, base + TIMER3_COUNT);
- writel(0, base + TIMER3_LOAD);
- writel(0, base + TIMER3_MATCH1);
- writel(0, base + TIMER3_MATCH2);
- clocksource_mmio_init(base + TIMER3_COUNT,
- "fttmr010_clocksource", tick_rate,
- 300, 32, clocksource_mmio_readl_up);
- sched_clock_register(fttmr010_read_sched_clock, 32, tick_rate);
+ local_fttmr = fttmr010;
+ writel(0, fttmr010->base + TIMER2_COUNT);
+ writel(0, fttmr010->base + TIMER2_MATCH1);
+ writel(0, fttmr010->base + TIMER2_MATCH2);
+
+ if (fttmr010->count_down) {
+ writel(~0, fttmr010->base + TIMER2_LOAD);
+ clocksource_mmio_init(fttmr010->base + TIMER2_COUNT,
+ "FTTMR010-TIMER2",
+ fttmr010->tick_rate,
+ 300, 32, clocksource_mmio_readl_down);
+ sched_clock_register(fttmr010_read_sched_clock_down, 32,
+ fttmr010->tick_rate);
+ } else {
+ writel(0, fttmr010->base + TIMER2_LOAD);
+ clocksource_mmio_init(fttmr010->base + TIMER2_COUNT,
+ "FTTMR010-TIMER2",
+ fttmr010->tick_rate,
+ 300, 32, clocksource_mmio_readl_up);
+ sched_clock_register(fttmr010_read_sched_clock_up, 32,
+ fttmr010->tick_rate);
+ }
/*
- * Setup clockevent timer (interrupt-driven.)
+ * Setup clockevent timer (interrupt-driven) on timer 1.
*/
- writel(0, base + TIMER1_COUNT);
- writel(0, base + TIMER1_LOAD);
- writel(0, base + TIMER1_MATCH1);
- writel(0, base + TIMER1_MATCH2);
- setup_irq(irq, &fttmr010_timer_irq);
- fttmr010_clockevent.cpumask = cpumask_of(0);
- clockevents_config_and_register(&fttmr010_clockevent, tick_rate,
+ writel(0, fttmr010->base + TIMER1_COUNT);
+ writel(0, fttmr010->base + TIMER1_LOAD);
+ writel(0, fttmr010->base + TIMER1_MATCH1);
+ writel(0, fttmr010->base + TIMER1_MATCH2);
+ ret = request_irq(irq, fttmr010_timer_interrupt, IRQF_TIMER,
+ "FTTMR010-TIMER1", &fttmr010->clkevt);
+ if (ret) {
+ pr_err("FTTMR010-TIMER1 no IRQ\n");
+ goto out_unmap;
+ }
+
+ fttmr010->clkevt.name = "FTTMR010-TIMER1";
+ /* Reasonably fast and accurate clock event */
+ fttmr010->clkevt.rating = 300;
+ fttmr010->clkevt.features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT;
+ fttmr010->clkevt.set_next_event = fttmr010_timer_set_next_event;
+ fttmr010->clkevt.set_state_shutdown = fttmr010_timer_shutdown;
+ fttmr010->clkevt.set_state_periodic = fttmr010_timer_set_periodic;
+ fttmr010->clkevt.set_state_oneshot = fttmr010_timer_set_oneshot;
+ fttmr010->clkevt.tick_resume = fttmr010_timer_shutdown;
+ fttmr010->clkevt.cpumask = cpumask_of(0);
+ fttmr010->clkevt.irq = irq;
+ clockevents_config_and_register(&fttmr010->clkevt,
+ fttmr010->tick_rate,
1, 0xffffffff);
- return 0;
-}
+#ifdef CONFIG_ARM
+ /* Also use this timer for delays */
+ if (fttmr010->count_down)
+ fttmr010->delay_timer.read_current_timer =
+ fttmr010_read_current_timer_down;
+ else
+ fttmr010->delay_timer.read_current_timer =
+ fttmr010_read_current_timer_up;
+ fttmr010->delay_timer.freq = fttmr010->tick_rate;
+ register_current_timer_delay(&fttmr010->delay_timer);
+#endif
-static int __init fttmr010_timer_of_init(struct device_node *np)
-{
- /*
- * These implementations require a clock reference.
- * FIXME: we currently only support clocking using PCLK
- * and using EXTCLK is not supported in the driver.
- */
- struct clk *clk;
+ return 0;
- clk = of_clk_get_by_name(np, "PCLK");
- if (IS_ERR(clk)) {
- pr_err("could not get PCLK");
- return PTR_ERR(clk);
- }
- tick_rate = clk_get_rate(clk);
+out_unmap:
+ iounmap(fttmr010->base);
+out_free:
+ kfree(fttmr010);
+out_disable_clock:
+ clk_disable_unprepare(clk);
- return fttmr010_timer_common_init(np);
+ return ret;
}
-CLOCKSOURCE_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_of_init);
-/*
- * Gemini-specific: relevant registers in the global syscon
- */
-#define GLOBAL_STATUS 0x04
-#define CPU_AHB_RATIO_MASK (0x3 << 18)
-#define CPU_AHB_1_1 (0x0 << 18)
-#define CPU_AHB_3_2 (0x1 << 18)
-#define CPU_AHB_24_13 (0x2 << 18)
-#define CPU_AHB_2_1 (0x3 << 18)
-#define REG_TO_AHB_SPEED(reg) ((((reg) >> 15) & 0x7) * 10 + 130)
-
-static int __init gemini_timer_of_init(struct device_node *np)
+static __init int aspeed_timer_init(struct device_node *np)
{
- static struct regmap *map;
- int ret;
- u32 val;
-
- map = syscon_regmap_lookup_by_phandle(np, "syscon");
- if (IS_ERR(map)) {
- pr_err("Can't get regmap for syscon handle\n");
- return -ENODEV;
- }
- ret = regmap_read(map, GLOBAL_STATUS, &val);
- if (ret) {
- pr_err("Can't read syscon status register\n");
- return -ENXIO;
- }
-
- tick_rate = REG_TO_AHB_SPEED(val) * 1000000;
- pr_info("Bus: %dMHz ", tick_rate / 1000000);
-
- tick_rate /= 6; /* APB bus run AHB*(1/6) */
-
- switch (val & CPU_AHB_RATIO_MASK) {
- case CPU_AHB_1_1:
- pr_cont("(1/1)\n");
- break;
- case CPU_AHB_3_2:
- pr_cont("(3/2)\n");
- break;
- case CPU_AHB_24_13:
- pr_cont("(24/13)\n");
- break;
- case CPU_AHB_2_1:
- pr_cont("(2/1)\n");
- break;
- }
+ return fttmr010_common_init(np, true);
+}
- return fttmr010_timer_common_init(np);
+static __init int fttmr010_timer_init(struct device_node *np)
+{
+ return fttmr010_common_init(np, false);
}
-CLOCKSOURCE_OF_DECLARE(gemini, "cortina,gemini-timer", gemini_timer_of_init);
+
+TIMER_OF_DECLARE(fttmr010, "faraday,fttmr010", fttmr010_timer_init);
+TIMER_OF_DECLARE(gemini, "cortina,gemini-timer", fttmr010_timer_init);
+TIMER_OF_DECLARE(moxart, "moxa,moxart-timer", fttmr010_timer_init);
+TIMER_OF_DECLARE(ast2400, "aspeed,ast2400-timer", aspeed_timer_init);
+TIMER_OF_DECLARE(ast2500, "aspeed,ast2500-timer", aspeed_timer_init);
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c
index f595460bfc58..6ec6d79b237c 100644
--- a/drivers/clocksource/timer-imx-gpt.c
+++ b/drivers/clocksource/timer-imx-gpt.c
@@ -545,15 +545,15 @@ static int __init imx6dl_timer_init_dt(struct device_node *np)
return mxc_timer_init_dt(np, GPT_TYPE_IMX6DL);
}
-CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
-CLOCKSOURCE_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);
+TIMER_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt);
+TIMER_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt);
+TIMER_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt);
+TIMER_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt);
+TIMER_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt);
+TIMER_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt);
+TIMER_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt);
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c
index 04ad3066e190..2ff64d9d4fb3 100644
--- a/drivers/clocksource/timer-integrator-ap.c
+++ b/drivers/clocksource/timer-integrator-ap.c
@@ -232,5 +232,5 @@ static int __init integrator_ap_timer_init_of(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer",
+TIMER_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer",
integrator_ap_timer_init_of);
diff --git a/drivers/clocksource/timer-keystone.c b/drivers/clocksource/timer-keystone.c
index ab68a47ab3b4..0eee03250cfc 100644
--- a/drivers/clocksource/timer-keystone.c
+++ b/drivers/clocksource/timer-keystone.c
@@ -226,5 +226,5 @@ err:
return error;
}
-CLOCKSOURCE_OF_DECLARE(keystone_timer, "ti,keystone-timer",
+TIMER_OF_DECLARE(keystone_timer, "ti,keystone-timer",
keystone_timer_init);
diff --git a/drivers/clocksource/timer-nps.c b/drivers/clocksource/timer-nps.c
index e74ea1722ad3..7b6bb0df96ae 100644
--- a/drivers/clocksource/timer-nps.c
+++ b/drivers/clocksource/timer-nps.c
@@ -110,9 +110,9 @@ static int __init nps_setup_clocksource(struct device_node *node)
return ret;
}
-CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
+TIMER_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
nps_setup_clocksource);
-CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1",
+TIMER_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1",
nps_setup_clocksource);
#ifdef CONFIG_EZNPS_MTM_EXT
@@ -279,6 +279,6 @@ static int __init nps_setup_clockevent(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0",
+TIMER_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0",
nps_setup_clockevent);
#endif /* CONFIG_EZNPS_MTM_EXT */
diff --git a/drivers/clocksource/timer-of.c b/drivers/clocksource/timer-of.c
new file mode 100644
index 000000000000..f6e7491c873c
--- /dev/null
+++ b/drivers/clocksource/timer-of.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017, Linaro Ltd. All rights reserved.
+ *
+ * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+#include "timer-of.h"
+
+static __init void timer_irq_exit(struct of_timer_irq *of_irq)
+{
+ struct timer_of *to = container_of(of_irq, struct timer_of, of_irq);
+
+ struct clock_event_device *clkevt = &to->clkevt;
+
+ of_irq->percpu ? free_percpu_irq(of_irq->irq, clkevt) :
+ free_irq(of_irq->irq, clkevt);
+}
+
+static __init int timer_irq_init(struct device_node *np,
+ struct of_timer_irq *of_irq)
+{
+ int ret;
+ struct timer_of *to = container_of(of_irq, struct timer_of, of_irq);
+ struct clock_event_device *clkevt = &to->clkevt;
+
+ of_irq->irq = of_irq->name ? of_irq_get_byname(np, of_irq->name):
+ irq_of_parse_and_map(np, of_irq->index);
+ if (!of_irq->irq) {
+ pr_err("Failed to map interrupt for %s\n", np->full_name);
+ return -EINVAL;
+ }
+
+ ret = of_irq->percpu ?
+ request_percpu_irq(of_irq->irq, of_irq->handler,
+ np->full_name, clkevt) :
+ request_irq(of_irq->irq, of_irq->handler,
+ of_irq->flags ? of_irq->flags : IRQF_TIMER,
+ np->full_name, clkevt);
+ if (ret) {
+ pr_err("Failed to request irq %d for %s\n", of_irq->irq,
+ np->full_name);
+ return ret;
+ }
+
+ clkevt->irq = of_irq->irq;
+
+ return 0;
+}
+
+static __init void timer_clk_exit(struct of_timer_clk *of_clk)
+{
+ of_clk->rate = 0;
+ clk_disable_unprepare(of_clk->clk);
+ clk_put(of_clk->clk);
+}
+
+static __init int timer_clk_init(struct device_node *np,
+ struct of_timer_clk *of_clk)
+{
+ int ret;
+
+ of_clk->clk = of_clk->name ? of_clk_get_by_name(np, of_clk->name) :
+ of_clk_get(np, of_clk->index);
+ if (IS_ERR(of_clk->clk)) {
+ pr_err("Failed to get clock for %s\n", np->full_name);
+ return PTR_ERR(of_clk->clk);
+ }
+
+ ret = clk_prepare_enable(of_clk->clk);
+ if (ret) {
+ pr_err("Failed for enable clock for %s\n", np->full_name);
+ goto out_clk_put;
+ }
+
+ of_clk->rate = clk_get_rate(of_clk->clk);
+ if (!of_clk->rate) {
+ ret = -EINVAL;
+ pr_err("Failed to get clock rate for %s\n", np->full_name);
+ goto out_clk_disable;
+ }
+
+ of_clk->period = DIV_ROUND_UP(of_clk->rate, HZ);
+out:
+ return ret;
+
+out_clk_disable:
+ clk_disable_unprepare(of_clk->clk);
+out_clk_put:
+ clk_put(of_clk->clk);
+
+ goto out;
+}
+
+static __init void timer_base_exit(struct of_timer_base *of_base)
+{
+ iounmap(of_base->base);
+}
+
+static __init int timer_base_init(struct device_node *np,
+ struct of_timer_base *of_base)
+{
+ const char *name = of_base->name ? of_base->name : np->full_name;
+
+ of_base->base = of_io_request_and_map(np, of_base->index, name);
+ if (!of_base->base) {
+ pr_err("Failed to iomap (%s)\n", name);
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+int __init timer_of_init(struct device_node *np, struct timer_of *to)
+{
+ int ret = -EINVAL;
+ int flags = 0;
+
+ if (to->flags & TIMER_OF_BASE) {
+ ret = timer_base_init(np, &to->of_base);
+ if (ret)
+ goto out_fail;
+ flags |= TIMER_OF_BASE;
+ }
+
+ if (to->flags & TIMER_OF_CLOCK) {
+ ret = timer_clk_init(np, &to->of_clk);
+ if (ret)
+ goto out_fail;
+ flags |= TIMER_OF_CLOCK;
+ }
+
+ if (to->flags & TIMER_OF_IRQ) {
+ ret = timer_irq_init(np, &to->of_irq);
+ if (ret)
+ goto out_fail;
+ flags |= TIMER_OF_IRQ;
+ }
+
+ if (!to->clkevt.name)
+ to->clkevt.name = np->name;
+ return ret;
+
+out_fail:
+ if (flags & TIMER_OF_IRQ)
+ timer_irq_exit(&to->of_irq);
+
+ if (flags & TIMER_OF_CLOCK)
+ timer_clk_exit(&to->of_clk);
+
+ if (flags & TIMER_OF_BASE)
+ timer_base_exit(&to->of_base);
+ return ret;
+}
diff --git a/drivers/clocksource/timer-of.h b/drivers/clocksource/timer-of.h
new file mode 100644
index 000000000000..e0d727255f72
--- /dev/null
+++ b/drivers/clocksource/timer-of.h
@@ -0,0 +1,69 @@
+#ifndef __TIMER_OF_H__
+#define __TIMER_OF_H__
+
+#include <linux/clockchips.h>
+
+#define TIMER_OF_BASE 0x1
+#define TIMER_OF_CLOCK 0x2
+#define TIMER_OF_IRQ 0x4
+
+struct of_timer_irq {
+ int irq;
+ int index;
+ int percpu;
+ const char *name;
+ unsigned long flags;
+ irq_handler_t handler;
+};
+
+struct of_timer_base {
+ void __iomem *base;
+ const char *name;
+ int index;
+};
+
+struct of_timer_clk {
+ struct clk *clk;
+ const char *name;
+ int index;
+ unsigned long rate;
+ unsigned long period;
+};
+
+struct timer_of {
+ unsigned int flags;
+ struct clock_event_device clkevt;
+ struct of_timer_base of_base;
+ struct of_timer_irq of_irq;
+ struct of_timer_clk of_clk;
+ void *private_data;
+};
+
+static inline struct timer_of *to_timer_of(struct clock_event_device *clkevt)
+{
+ return container_of(clkevt, struct timer_of, clkevt);
+}
+
+static inline void __iomem *timer_of_base(struct timer_of *to)
+{
+ return to->of_base.base;
+}
+
+static inline int timer_of_irq(struct timer_of *to)
+{
+ return to->of_irq.irq;
+}
+
+static inline unsigned long timer_of_rate(struct timer_of *to)
+{
+ return to->of_clk.rate;
+}
+
+static inline unsigned long timer_of_period(struct timer_of *to)
+{
+ return to->of_clk.period;
+}
+
+extern int __init timer_of_init(struct device_node *np,
+ struct timer_of *to);
+#endif
diff --git a/drivers/clocksource/timer-oxnas-rps.c b/drivers/clocksource/timer-oxnas-rps.c
index d630bf417773..eed6feff8b5f 100644
--- a/drivers/clocksource/timer-oxnas-rps.c
+++ b/drivers/clocksource/timer-oxnas-rps.c
@@ -293,7 +293,7 @@ err_alloc:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(ox810se_rps,
+TIMER_OF_DECLARE(ox810se_rps,
"oxsemi,ox810se-rps-timer", oxnas_rps_timer_init);
-CLOCKSOURCE_OF_DECLARE(ox820_rps,
+TIMER_OF_DECLARE(ox820_rps,
"oxsemi,ox820se-rps-timer", oxnas_rps_timer_init);
diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c
index b4122ed1accb..20ff33b698df 100644
--- a/drivers/clocksource/timer-prima2.c
+++ b/drivers/clocksource/timer-prima2.c
@@ -245,5 +245,5 @@ static int __init sirfsoc_prima2_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(sirfsoc_prima2_timer,
+TIMER_OF_DECLARE(sirfsoc_prima2_timer,
"sirf,prima2-tick", sirfsoc_prima2_timer_init);
diff --git a/drivers/clocksource/clksrc-probe.c b/drivers/clocksource/timer-probe.c
index ac701ffb8d59..da81e5de74fe 100644
--- a/drivers/clocksource/clksrc-probe.c
+++ b/drivers/clocksource/timer-probe.c
@@ -19,20 +19,20 @@
#include <linux/of.h>
#include <linux/clocksource.h>
-extern struct of_device_id __clksrc_of_table[];
+extern struct of_device_id __timer_of_table[];
-static const struct of_device_id __clksrc_of_table_sentinel
- __used __section(__clksrc_of_table_end);
+static const struct of_device_id __timer_of_table_sentinel
+ __used __section(__timer_of_table_end);
-void __init clocksource_probe(void)
+void __init timer_probe(void)
{
struct device_node *np;
const struct of_device_id *match;
of_init_fn_1_ret init_func_ret;
- unsigned clocksources = 0;
+ unsigned timers = 0;
int ret;
- for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
+ for_each_matching_node_and_match(np, __timer_of_table, &match) {
if (!of_device_is_available(np))
continue;
@@ -45,11 +45,11 @@ void __init clocksource_probe(void)
continue;
}
- clocksources++;
+ timers++;
}
- clocksources += acpi_probe_device_table(clksrc);
+ timers += acpi_probe_device_table(timer);
- if (!clocksources)
- pr_crit("%s: no matching clocksources found\n", __func__);
+ if (!timers)
+ pr_crit("%s: no matching timers found\n", __func__);
}
diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index 2d575a8c0939..3ac9dec9a038 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -287,7 +287,7 @@ err:
iounmap(base);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(sp804, "arm,sp804", sp804_of_init);
+TIMER_OF_DECLARE(sp804, "arm,sp804", sp804_of_init);
static int __init integrator_cp_of_init(struct device_node *np)
{
@@ -335,4 +335,4 @@ err:
iounmap(base);
return ret;
}
-CLOCKSOURCE_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init);
+TIMER_OF_DECLARE(intcp, "arm,integrator-cp-timer", integrator_cp_of_init);
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 1b2574c4fb97..174d1243ea93 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -187,4 +187,4 @@ err_clk_get:
return ret;
}
-CLOCKSOURCE_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init);
+TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init);
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
index 2e9c830ae1cd..2a3fe83ec337 100644
--- a/drivers/clocksource/timer-sun5i.c
+++ b/drivers/clocksource/timer-sun5i.c
@@ -12,6 +12,7 @@
#include <linux/clk.h>
#include <linux/clockchips.h>
+#include <linux/clocksource.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -358,7 +359,7 @@ static int __init sun5i_timer_init(struct device_node *node)
return sun5i_setup_clockevent(node, timer_base, clk, irq);
}
-CLOCKSOURCE_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
+TIMER_OF_DECLARE(sun5i_a13, "allwinner,sun5i-a13-hstimer",
sun5i_timer_init);
-CLOCKSOURCE_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
+TIMER_OF_DECLARE(sun7i_a20, "allwinner,sun7i-a20-hstimer",
sun5i_timer_init);
diff --git a/drivers/clocksource/timer-ti-32k.c b/drivers/clocksource/timer-ti-32k.c
index 624067712ef0..880a861ab3c8 100644
--- a/drivers/clocksource/timer-ti-32k.c
+++ b/drivers/clocksource/timer-ti-32k.c
@@ -124,5 +124,5 @@ static int __init ti_32k_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k",
+TIMER_OF_DECLARE(ti_32k_timer, "ti,omap-counter32k",
ti_32k_timer_init);
diff --git a/drivers/clocksource/timer-u300.c b/drivers/clocksource/timer-u300.c
index 704e40c6f151..be34b116d4d2 100644
--- a/drivers/clocksource/timer-u300.c
+++ b/drivers/clocksource/timer-u300.c
@@ -458,5 +458,5 @@ static int __init u300_timer_init_of(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(u300_timer, "stericsson,u300-apptimer",
+TIMER_OF_DECLARE(u300_timer, "stericsson,u300-apptimer",
u300_timer_init_of);
diff --git a/drivers/clocksource/versatile.c b/drivers/clocksource/versatile.c
index 220b490a8142..39725d38aede 100644
--- a/drivers/clocksource/versatile.c
+++ b/drivers/clocksource/versatile.c
@@ -38,7 +38,7 @@ static int __init versatile_sched_clock_init(struct device_node *node)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(vexpress, "arm,vexpress-sysreg",
+TIMER_OF_DECLARE(vexpress, "arm,vexpress-sysreg",
versatile_sched_clock_init);
-CLOCKSOURCE_OF_DECLARE(versatile, "arm,versatile-sysreg",
+TIMER_OF_DECLARE(versatile, "arm,versatile-sysreg",
versatile_sched_clock_init);
diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c
index e0849e20a307..0f92089ec08c 100644
--- a/drivers/clocksource/vf_pit_timer.c
+++ b/drivers/clocksource/vf_pit_timer.c
@@ -201,4 +201,4 @@ static int __init pit_timer_init(struct device_node *np)
return pit_clockevent_init(clk_rate, irq);
}
-CLOCKSOURCE_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init);
+TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init);
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c
index d02b51075ad1..e0f7489cfc8e 100644
--- a/drivers/clocksource/vt8500_timer.c
+++ b/drivers/clocksource/vt8500_timer.c
@@ -165,4 +165,4 @@ static int __init vt8500_timer_init(struct device_node *np)
return 0;
}
-CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init);
+TIMER_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init);
diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c
index 9a53f5ef6157..a6a0338eea77 100644
--- a/drivers/clocksource/zevio-timer.c
+++ b/drivers/clocksource/zevio-timer.c
@@ -215,4 +215,4 @@ static int __init zevio_timer_init(struct device_node *node)
return zevio_timer_add(node);
}
-CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init);
+TIMER_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_init);