Commit b4cee21e authored by Linus Torvalds's avatar Linus Torvalds

Merge branches 'timers-core-for-linus' and 'timers-urgent-for-linus' of...

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

Pull timer updates - and a leftover fix - from Thomas Gleixner:
 "A rather large (commit wise) update from the timer side:

   - A bulk update to make compile tests work in the clocksource drivers

   - An overhaul of the h8300 timers

   - Some more Y2038 work

   - A few overflow prevention checks in the timekeeping/ntp code

   - The usual pile of fixes and improvements to the various
     clocksource/clockevent drivers and core code"

Also:
 "A single fix for the posix-clock poll code which did not make it into
  4.4"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (84 commits)
  clocksource/drivers/acpi_pm: Convert to pr_* macros
  clocksource: Make clocksource validation work for all clocksources
  timekeeping: Cap adjustments so they don't exceed the maxadj value
  ntp: Fix second_overflow's input parameter type to be 64bits
  ntp: Change time_reftime to time64_t and utilize 64bit __ktime_get_real_seconds
  timekeeping: Provide internal function __ktime_get_real_seconds
  clocksource/drivers/h8300: Use ioread / iowrite
  clocksource/drivers/h8300: Initializer cleanup.
  clocksource/drivers/h8300: Simplify delta handling
  clocksource/drivers/h8300: Fix timer not overflow case
  clocksource/drivers/h8300: Change to overflow interrupt
  clocksource/drivers/lpc32: Correct pr_err() output format
  clocksource/drivers/arm_global_timer: Fix suspend resume
  clocksource/drivers/pistachio: Fix wrong calculated clocksource read value
  clockevents/drivers/arm_global_timer: Use writel_relaxed in gt_compare_set
  clocksource/drivers/dw_apb_timer: Inline apbt_readl and apbt_writel
  clocksource/drivers/dw_apb_timer: Use {readl|writel}_relaxed in critical path
  clocksource/drivers/dw_apb_timer: Fix apbt_readl return types
  clocksource/drivers/tango-xtal: Replace code by clocksource_mmio_init
  clocksource/drivers/h8300: Increase the compilation test coverage
  ...

* 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  posix-clock: Fix return code on the poll method's error path
......@@ -9364,7 +9364,7 @@ M: Andreas Noever <andreas.noever@gmail.com>
S: Maintained
F: drivers/thunderbolt/
TIMEKEEPING, CLOCKSOURCE CORE, NTP
TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER
M: John Stultz <john.stultz@linaro.org>
M: Thomas Gleixner <tglx@linutronix.de>
L: linux-kernel@vger.kernel.org
......@@ -9377,6 +9377,7 @@ F: include/uapi/linux/time.h
F: include/uapi/linux/timex.h
F: kernel/time/clocksource.c
F: kernel/time/time*.c
F: kernel/time/alarmtimer.c
F: kernel/time/ntp.c
F: tools/testing/selftests/timers/
......
......@@ -611,6 +611,7 @@ config ARCH_PXA
select AUTO_ZRELADDR
select COMMON_CLK
select CLKDEV_LOOKUP
select CLKSRC_PXA
select CLKSRC_MMIO
select CLKSRC_OF
select GENERIC_CLOCKEVENTS
......@@ -650,6 +651,8 @@ config ARCH_SA1100
select ARCH_SPARSEMEM_ENABLE
select CLKDEV_LOOKUP
select CLKSRC_MMIO
select CLKSRC_PXA
select CLKSRC_OF if OF
select CPU_FREQ
select CPU_SA1100
select GENERIC_CLOCKEVENTS
......
......@@ -27,6 +27,7 @@ menuconfig ARCH_EXYNOS
select SRAM
select THERMAL
select MFD_SYSCON
select CLKSRC_EXYNOS_MCT
help
Support for SAMSUNG EXYNOS SoCs (EXYNOS4/5)
......
......@@ -3,6 +3,7 @@ menuconfig ARCH_STI
select ARM_GIC
select ST_IRQCHIP
select ARM_GLOBAL_TIMER
select CLKSRC_ST_LPC
select PINCTRL
select PINCTRL_ST
select MFD_SYSCON
......
......@@ -32,6 +32,7 @@ config UX500_SOC_DB8500
select PINCTRL_AB8540
select REGULATOR
select REGULATOR_DB8500_PRCMU
select CLKSRC_DBX500_PRCMU
select PM_GENERIC_DOMAINS if PM
config MACH_MOP500
......
......@@ -17,6 +17,7 @@ config H8300
select HAVE_MEMBLOCK
select HAVE_DMA_ATTRS
select CLKSRC_OF
select H8300_TMR8
config RWSEM_GENERIC_SPINLOCK
def_bool y
......
......@@ -3,40 +3,45 @@
#ifdef __KERNEL__
#include <asm-generic/io.h>
/* H8/300 internal I/O functions */
static inline unsigned char ctrl_inb(unsigned long addr)
#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
return *(volatile unsigned char *)addr;
return *(volatile u8 *)addr;
}
static inline unsigned short ctrl_inw(unsigned long addr)
#define __raw_readw __raw_readw
static inline u16 __raw_readw(const volatile void __iomem *addr)
{
return *(volatile unsigned short *)addr;
return *(volatile u16 *)addr;
}
static inline unsigned long ctrl_inl(unsigned long addr)
#define __raw_readl __raw_readl
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
return *(volatile unsigned long *)addr;
return *(volatile u32 *)addr;
}
static inline void ctrl_outb(unsigned char b, unsigned long addr)
#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 b, const volatile void __iomem *addr)
{
*(volatile unsigned char *)addr = b;
*(volatile u8 *)addr = b;
}
static inline void ctrl_outw(unsigned short b, unsigned long addr)
#define __raw_writew __raw_writew
static inline void __raw_writew(u16 b, const volatile void __iomem *addr)
{
*(volatile unsigned short *)addr = b;
*(volatile u16 *)addr = b;
}
static inline void ctrl_outl(unsigned long b, unsigned long addr)
#define __raw_writel __raw_writel
static inline void __raw_writel(u32 b, const volatile void __iomem *addr)
{
*(volatile unsigned long *)addr = b;
*(volatile u32 *)addr = b;
}
static inline void ctrl_bclr(int b, unsigned char *addr)
static inline void ctrl_bclr(int b, void __iomem *addr)
{
if (__builtin_constant_p(b))
__asm__("bclr %1,%0" : "+WU"(*addr): "i"(b));
......@@ -44,7 +49,7 @@ static inline void ctrl_bclr(int b, unsigned char *addr)
__asm__("bclr %w1,%0" : "+WU"(*addr): "r"(b));
}
static inline void ctrl_bset(int b, unsigned char *addr)
static inline void ctrl_bset(int b, void __iomem *addr)
{
if (__builtin_constant_p(b))
__asm__("bset %1,%0" : "+WU"(*addr): "i"(b));
......@@ -52,6 +57,8 @@ static inline void ctrl_bset(int b, unsigned char *addr)
__asm__("bset %w1,%0" : "+WU"(*addr): "r"(b));
}
#include <asm-generic/io.h>
#endif /* __KERNEL__ */
#endif /* _H8300_IO_H */
......@@ -207,14 +207,14 @@ device_initcall(device_probe);
#define get_wait(base, addr) ({ \
int baddr; \
baddr = ((addr) / 0x200000 * 2); \
w *= (ctrl_inw((unsigned long)(base) + 2) & (3 << baddr)) + 1; \
w *= (readw((base) + 2) & (3 << baddr)) + 1; \
})
#endif
#if defined(CONFIG_CPU_H8S)
#define get_wait(base, addr) ({ \
int baddr; \
baddr = ((addr) / 0x200000 * 16); \
w *= (ctrl_inl((unsigned long)(base) + 2) & (7 << baddr)) + 1; \
w *= (readl((base) + 2) & (7 << baddr)) + 1; \
})
#endif
......@@ -228,8 +228,8 @@ static __init int access_timing(void)
bsc = of_find_compatible_node(NULL, NULL, "renesas,h8300-bsc");
base = of_iomap(bsc, 0);
w = (ctrl_inb((unsigned long)base + 0) & bit)?2:1;
if (ctrl_inb((unsigned long)base + 1) & bit)
w = (readb(base + 0) & bit)?2:1;
if (readb(base + 1) & bit)
w *= get_wait(base, addr);
else
w *= 2;
......
......@@ -28,10 +28,16 @@ config CLKSRC_MMIO
bool
config DIGICOLOR_TIMER
bool
bool "Digicolor timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
help
Enables the support for the digicolor timer driver.
config DW_APB_TIMER
bool
bool "DW APB timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
help
Enables the support for the dw_apb timer.
config DW_APB_TIMER_OF
bool
......@@ -39,47 +45,77 @@ config DW_APB_TIMER_OF
select CLKSRC_OF
config ROCKCHIP_TIMER
bool
bool "Rockchip timer driver" if COMPILE_TEST
depends on ARM || ARM64
select CLKSRC_OF
help
Enables the support for the rockchip timer driver.
config ARMADA_370_XP_TIMER
bool
bool "Armada 370 and XP timer driver" if COMPILE_TEST
depends on ARM
select CLKSRC_OF
help
Enables the support for the Armada 370 and XP timer driver.
config MESON6_TIMER
bool
bool "Meson6 timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
help
Enables the support for the Meson6 timer driver.
config ORION_TIMER
bool "Orion timer driver" if COMPILE_TEST
depends on ARM
select CLKSRC_OF
select CLKSRC_MMIO
bool
help
Enables the support for the Orion timer driver
config SUN4I_TIMER
bool "Sun4i timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
bool
help
Enables support for the Sun4i timer.
config SUN5I_HSTIMER
bool "Sun5i timer driver" if COMPILE_TEST
select CLKSRC_MMIO
bool
depends on COMMON_CLK
help
Enables support the Sun5i timer.
config TEGRA_TIMER
bool
bool "Tegra timer driver" if COMPILE_TEST
depends on ARM
help
Enables support for the Tegra driver.
config VT8500_TIMER
bool
bool "VT8500 timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
help
Enables support for the VT8500 driver.
config CADENCE_TTC_TIMER
bool
bool "Cadence TTC timer driver" if COMPILE_TEST
depends on COMMON_CLK
help
Enables support for the cadence ttc driver.
config ASM9260_TIMER
bool
bool "ASM9260 timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
select CLKSRC_OF
help
Enables support for the ASM9260 timer.
config CLKSRC_NOMADIK_MTU
bool
depends on (ARCH_NOMADIK || ARCH_U8500)
bool "Nomakdik clocksource driver" if COMPILE_TEST
depends on ARM
select CLKSRC_MMIO
help
Support for Multi Timer Unit. MTU provides access
......@@ -93,9 +129,8 @@ config CLKSRC_NOMADIK_MTU_SCHED_CLOCK
Use the Multi Timer Unit as the sched_clock.
config CLKSRC_DBX500_PRCMU
bool "Clocksource PRCMU Timer"
depends on UX500_SOC_DB8500
default y
bool "Clocksource PRCMU Timer" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
help
Use the always on PRCMU Timer as clocksource
......@@ -116,13 +151,18 @@ config CLKSRC_EFM32
event device.
config CLKSRC_LPC32XX
bool
bool "Clocksource for LPC32XX" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
select CLKSRC_OF
help
Support for the LPC32XX clocksource.
config CLKSRC_PISTACHIO
bool
bool "Clocksource for Pistachio SoC" if COMPILE_TEST
select CLKSRC_OF
help
Enables the clocksource for the Pistachio SoC.
config CLKSRC_TI_32K
bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST
......@@ -199,13 +239,14 @@ config CLKSRC_METAG_GENERIC
This option enables support for the Meta per-thread timers.
config CLKSRC_EXYNOS_MCT
def_bool y if ARCH_EXYNOS
depends on !ARM64
bool "Exynos multi core timer driver" if COMPILE_TEST
depends on ARM
help
Support for Multi Core Timer controller on Exynos SoCs.
config CLKSRC_SAMSUNG_PWM
bool
bool "PWM timer drvier for Samsung S3C, S5P" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
help
This is a new clocksource driver for the PWM timer found in
Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver
......@@ -213,7 +254,8 @@ config CLKSRC_SAMSUNG_PWM
needed only on systems that do not have the Exynos MCT available.
config FSL_FTM_TIMER
bool
bool "Freescale FlexTimer Module driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
help
Support for Freescale FlexTimer Module (FTM) timer.
......@@ -226,9 +268,12 @@ config SYS_SUPPORTS_SH_CMT
bool
config MTK_TIMER
bool "Mediatek timer driver" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
select CLKSRC_OF
select CLKSRC_MMIO
bool
help
Support for Mediatek timer driver.
config SYS_SUPPORTS_SH_MTU2
bool
......@@ -279,7 +324,12 @@ config EM_TIMER_STI
such as EMEV2 from former NEC Electronics.
config CLKSRC_QCOM
bool
bool "Qualcomm MSM timer" if COMPILE_TEST
depends on ARM
select CLKSRC_OF
help
This enables the clocksource and the per CPU clockevent driver for the
Qualcomm SoCs.
config CLKSRC_VERSATILE
bool "ARM Versatile (Express) reference platforms clock source"
......@@ -298,21 +348,40 @@ config CLKSRC_MIPS_GIC
select CLKSRC_OF
config CLKSRC_TANGO_XTAL
bool
bool "Clocksource for Tango SoC" if COMPILE_TEST
depends on ARM
select CLKSRC_OF
select CLKSRC_MMIO
help
This enables the clocksource for Tango SoC
config CLKSRC_PXA
def_bool y if ARCH_PXA || ARCH_SA1100
select CLKSRC_OF if OF
bool "Clocksource for PXA or SA-11x0 platform" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
help
This enables OST0 support available on PXA and SA-11x0
platforms.
config H8300_TMR8
bool "Clockevent timer for the H8300 platform" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
help
This enables the 8 bits timer for the H8300 platform.
config H8300_TMR16
bool
bool "Clockevent timer for the H83069 platform" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
help
This enables the 16 bits timer for the H8300 platform with the
H83069 cpu.
config H8300_TPU
bool
bool "Clocksource for the H8300 platform" if COMPILE_TEST
depends on GENERIC_CLOCKEVENTS
help
This enables the clocksource for the H8300 platform with the
H8S2678 cpu.
config CLKSRC_IMX_GPT
bool "Clocksource using i.MX GPT" if COMPILE_TEST
......@@ -320,8 +389,7 @@ config CLKSRC_IMX_GPT
select CLKSRC_MMIO
config CLKSRC_ST_LPC
bool
depends on ARCH_STI
bool "Low power clocksource found in the LPC" if COMPILE_TEST
select CLKSRC_OF if OF
help
Enable this option to use the Low Power controller timer
......
......@@ -60,7 +60,7 @@ obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o
obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o
obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o
obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
obj-$(CONFIG_H8300) += h8300_timer8.o
obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o
obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o
obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
......
......@@ -109,10 +109,8 @@ static void acpi_pm_check_blacklist(struct pci_dev *dev)
/* the bug has been fixed in PIIX4M */
if (dev->revision < 3) {
printk(KERN_WARNING "* Found PM-Timer Bug on the chipset."
" Due to workarounds for a bug,\n"
"* this clock source is slow. Consider trying"
" other clock sources\n");
pr_warn("* Found PM-Timer Bug on the chipset. Due to workarounds for a bug,\n"
"* this clock source is slow. Consider trying other clock sources\n");
acpi_pm_need_workaround();
}
......@@ -125,12 +123,9 @@ static void acpi_pm_check_graylist(struct pci_dev *dev)
if (acpi_pm_good)
return;
printk(KERN_WARNING "* The chipset may have PM-Timer Bug. Due to"
" workarounds for a bug,\n"
"* this clock source is slow. If you are sure your timer"
" does not have\n"
"* this bug, please use \"acpi_pm_good\" to disable the"
" workaround\n");
pr_warn("* The chipset may have PM-Timer Bug. Due to workarounds for a bug,\n"
"* this clock source is slow. If you are sure your timer does not have\n"
"* this bug, please use \"acpi_pm_good\" to disable the workaround\n");
acpi_pm_need_workaround();
}
......@@ -162,8 +157,7 @@ static int verify_pmtmr_rate(void)
/* Check that the PMTMR delta is within 5% of what we expect */
if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 ||
delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% "
"of normal - aborting.\n",
pr_info("PM-Timer running at invalid rate: %lu%% of normal - aborting.\n",
100UL * delta / PMTMR_EXPECTED_RATE);
return -1;
}
......@@ -199,15 +193,14 @@ static int __init init_acpi_pm_clocksource(void)
break;
if ((value2 < value1) && ((value2) < 0xFFF))
break;
printk(KERN_INFO "PM-Timer had inconsistent results:"
" %#llx, %#llx - aborting.\n",
value1, value2);
pr_info("PM-Timer had inconsistent results: %#llx, %#llx - aborting.\n",
value1, value2);
pmtmr_ioport = 0;
return -EINVAL;
}
if (i == ACPI_PM_READ_CHECKS) {
printk(KERN_INFO "PM-Timer failed consistency check "
" (%#llx) - aborting.\n", value1);
pr_info("PM-Timer failed consistency check (%#llx) - aborting.\n",
value1);
pmtmr_ioport = 0;
return -ENODEV;
}
......
......@@ -99,17 +99,17 @@ static void gt_compare_set(unsigned long delta, int periodic)
counter += delta;
ctrl = GT_CONTROL_TIMER_ENABLE;
writel(ctrl, gt_base + GT_CONTROL);
writel(lower_32_bits(counter), gt_base + GT_COMP0);
writel(upper_32_bits(counter), gt_base + GT_COMP1);
writel_relaxed(ctrl, gt_base + GT_CONTROL);
writel_relaxed(lower_32_bits(counter), gt_base + GT_COMP0);
writel_relaxed(upper_32_bits(counter), gt_base + GT_COMP1);
if (periodic) {
writel(delta, gt_base + GT_AUTO_INC);
writel_relaxed(delta, gt_base + GT_AUTO_INC);
ctrl |= GT_CONTROL_AUTO_INC;
}
ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE;
writel(ctrl, gt_base + GT_CONTROL);
writel_relaxed(ctrl, gt_base + GT_CONTROL);
}
static int gt_clockevent_shutdown(struct clock_event_device *evt)
......@@ -195,12 +195,23 @@ static cycle_t gt_clocksource_read(struct clocksource *cs)
return gt_counter_read();
}
static void gt_resume(struct clocksource *cs)
{
unsigned long ctrl;
ctrl = readl(gt_base + GT_CONTROL);
if (!(ctrl & GT_CONTROL_TIMER_ENABLE))
/* re-enable timer on resume */
writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
}
static struct clocksource gt_clocksource = {
.name = "arm_global_timer",
.rating = 300,
.read = gt_clocksource_read,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
.resume = gt_resume,
};
#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
......
......@@ -49,20 +49,31 @@ clocksource_to_dw_apb_clocksource(struct clocksource *cs)
return container_of(cs, struct dw_apb_clocksource, cs);
}
static unsigned long apbt_readl(struct dw_apb_timer *timer, unsigned long offs)
static inline u32 apbt_readl(struct dw_apb_timer *timer, unsigned long offs)
{
return readl(timer->base + offs);
}
static void apbt_writel(struct dw_apb_timer *timer, unsigned long val,
unsigned long offs)
static inline void apbt_writel(struct dw_apb_timer *timer, u32 val,
unsigned long offs)
{
writel(val, timer->base + offs);
}
static inline u32 apbt_readl_relaxed(struct dw_apb_timer *timer, unsigned long offs)
{
return readl_relaxed(timer->base + offs);
}
static inline void apbt_writel_relaxed(struct dw_apb_timer *timer, u32 val,
unsigned long offs)
{
writel_relaxed(val, timer->base + offs);
}
static void apbt_disable_int(struct dw_apb_timer *timer)
{
unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
ctrl |= APBTMR_CONTROL_INT;
apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
......@@ -81,7 +92,7 @@ void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced)
static void apbt_eoi(struct dw_apb_timer *timer)
{
apbt_readl(timer, APBTMR_N_EOI);
apbt_readl_relaxed(timer, APBTMR_N_EOI);
}
static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
......@@ -103,7 +114,7 @@ static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
static void apbt_enable_int(struct dw_apb_timer *timer)
{
unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
/* clear pending intr */
apbt_readl(timer, APBTMR_N_EOI);
ctrl &= ~APBTMR_CONTROL_INT;
......@@ -113,7 +124,7 @@ static void apbt_enable_int(struct dw_apb_timer *timer)
static int apbt_shutdown(struct clock_event_device *evt)
{
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
unsigned long ctrl;
u32 ctrl;
pr_debug("%s CPU %d state=shutdown\n", __func__,
cpumask_first(evt->cpumask));
......@@ -127,7 +138,7 @@ static int apbt_shutdown(struct clock_event_device *evt)
static int apbt_set_oneshot(struct clock_event_device *evt)
{
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
unsigned long ctrl;
u32 ctrl;
pr_debug("%s CPU %d state=oneshot\n", __func__,
cpumask_first(evt->cpumask));
......@@ -160,7 +171,7 @@ static int apbt_set_periodic(struct clock_event_device *evt)
{
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ);
unsigned long ctrl;
u32 ctrl;
pr_debug("%s CPU %d state=periodic\n", __func__,
cpumask_first(evt->cpumask));
......@@ -196,17 +207,17 @@ static int apbt_resume(struct clock_event_device *evt)
static int apbt_next_event(unsigned long delta,
struct clock_event_device *evt)
{
unsigned long ctrl;
u32 ctrl;
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
/* Disable timer */
ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL);
ctrl &= ~APBTMR_CONTROL_ENABLE;
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
/* write new count */
apbt_writel(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
ctrl |= APBTMR_CONTROL_ENABLE;
apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
return 0;
}
......@@ -323,7 +334,7 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs)
* start count down from 0xffff_ffff. this is done by toggling the
* enable bit then load initial load count to ~0.
*/
unsigned long ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL);
u32 ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL);
ctrl &= ~APBTMR_CONTROL_ENABLE;
apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
......@@ -338,11 +349,12 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs)
static cycle_t __apbt_read_clocksource(struct clocksource *cs)
{
unsigned long current_count;
u32 current_count;
struct dw_apb_clocksource *dw_cs =
clocksource_to_dw_apb_clocksource(cs);
current_count = apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
current_count = apbt_readl_relaxed(&dw_cs->timer,
APBTMR_N_CURRENT_VALUE);
return (cycle_t)~current_count;
}
......
......@@ -16,6 +16,7 @@
* 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/delay.h>
#include <linux/dw_apb_timer.h>
#include <linux/of.h>
#include <linux/of_address.h>
......@@ -130,6 +131,17 @@ static void __init init_sched_clock(void)
sched_clock_register(read_sched_clock, 32, sched_rate);
}
#ifdef CONFIG_ARM
static unsigned long dw_apb_delay_timer_read(void)
{
return ~readl_relaxed(sched_io_base);
}
static struct delay_timer dw_apb_delay_timer = {
.read_current_timer = dw_apb_delay_timer_read,
};
#endif
static int num_called;
static void __init dw_apb_timer_init(struct device_node *timer)
{
......@@ -142,6 +154,10 @@ static void __init dw_apb_timer_init(struct device_node *timer)
pr_debug("%s: found clocksource timer\n", __func__);
add_clocksource(timer);
init_sched_clock();
#ifdef CONFIG_ARM
dw_apb_delay_timer.freq = sched_rate;
register_current_timer_delay(&dw_apb_delay_timer);
#endif
break;
default:
break;
......
......@@ -4,85 +4,56 @@
* Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp>
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/clocksource.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/of.h>
#include <asm/segment.h>
#include <asm/irq.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#define TSTR 0
#define TSNC 1
#define TMDR 2
#define TOLR 3
#define TISRA 4