2013-07-06

Linus,

please pull the timers-core-for-linus git tree from:

git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers-core-for-linus

The timer changes contain:

* posix timer code consolidation and fixes for odd corner cases

* sched_clock implementation moved from ARM to core code to avoid

duplication by other architectures

* alarm timer updates

* clocksource and clockevents unregistration facilities

* clocksource/events support for new hardware

* precise nanoseconds RTC readout (Xen feature)

* generic support for Xen suspend/resume oddities

* the usual lot of fixes and cleanups all over the place

The parts which touch other areas (ARM/XEN) have been coordinated with

the relevant maintainers. Though this results in an handful of trivial

to solve merge conflicts, which we preferred over nasty cross tree

merge dependencies.

The patches which have been committed in the last few days are bug

fixes plus the posix timer lot. The latter was in akpms queue and next

for quite some time; they just got forgotten and Frederic collected

them last minute.

Thanks,

tglx

------------------>

Bart Van Assche (1):

timer: Fix jiffies wrap behavior of round_jiffies_common()

Baruch Siach (2):

clocksource: dw_apb: Remove unused header

clocksource: dw_apb: Fix error check

Colin Cross (1):

power: Add option to log time spent in suspend

Daniel Borkmann (1):

ktime: Add __must_check prefix to ktime_to_timespec_cond

Daniel Tang (1):

clocksource: Add TI-Nspire timer support

David Vrabel (7):

x86: Increase precision of x86_platform.get/set_wallclock()

hrtimers: Support resuming with two or more CPUs online (but stopped)

xen: Remove clock_was_set() call in the resume path

timekeeping: Pass flags instead of multiple bools to timekeeping_update()

timekeeping: Indicate that clock was set in the pvclock gtod notifier

x86: xen: Sync the wallclock when the system time is set

x86: xen: Sync the CMOS RTC as well as the Xen wallclock

Fabio Estevam (1):

clocksource: vf_pit_timer: Use linux/sched_clock.h

Frederic Weisbecker (6):

posix_cpu_timer: consolidate expiry time type

posix_cpu_timers: consolidate timer list cleanups

posix_cpu_timers: consolidate expired timers check

selftests: add basic posix timers selftests

posix-timers: correctly get dying task time sample in posix_cpu_timer_schedule()

posix_timers: fix racy timer delta caching on task exit

Jingchang Lu (1):

clocksource: Add Freescale Vybrid pit timer support

John Stultz (2):

x86: Fix vrtc_get_time/set_mmss to use new timespec interface

Revert "dw_apb_timer_of.c: Remove parts that were picoxcell-specific"

KOSAKI Motohiro (1):

posix-cpu-timers: don't account cpu timer after stopped thread runtime accounting

Liu Ying (1):

ktime: Use macro NSEC_PER_USEC where appropriate

Marcus Gelderie (1):

alarmtimer: Export symbols of functions declared in linux/alarmtimer.h

Mark Rutland (1):

clocksource: Add generic dummy timer driver

Pavel Machek (1):

dw_apb_timer_of.c: Remove parts that were picoxcell-specific

Stephen Boyd (6):

ARM: sched_clock: Remove unused needs_suspend member

ARM: sched_clock: Return suspended count earlier

sched_clock: Make ARM's sched_clock generic for all architectures

ARM: sched_clock: Load cycle count after epoch stabilizes

sched_clock: Add temporary asm/sched_clock.h

clockevents: Prefer CPU local devices over global devices

Thomas Gleixner (23):

clocksource: apb_timer: Remove unsused function

clocksource: Always verify highres capability

clocksource: Let timekeeping_notify return success/error

clocksource: Add module refcount

clocksource: Allow clocksource select to skip current clocksource

clocksource: Split out user string input

clocksource: Provide unbind interface in sysfs

clocksource: Let clocksource_unregister() return success/error

clockevents: Get rid of the notifier chain

clockevents: Simplify locking

clockevents: Move the tick_notify() switch case to clockevents_notify()

clockevents: Add module refcount

clockevents: Provide sysfs interface

clockevents: Split out selection logic

clockevents: Implement unbind functionality

clockevents: Define CS_NAME_LEN unconditionally

clocksource: Implement clocksource_select_fallback() for CONFIG_ARCH_USES_GETTIMEOFFSET=y

tick: Make oneshot broadcast robust vs. CPU offlining

tick: Prevent uncontrolled switch to oneshot mode

tick: Sanitize broadcast control logic

clocksource: Reselect clocksource when watchdog validated high-res capability

hrtimers: Move SMP function call to thread context

hrtimer: Remove unused variable

Todd Poynor (2):

alarmtimer: Add functions for timerfd support

timerfd: Add alarm timers

.../devicetree/bindings/timer/lsi,zevio-timer.txt | 33 ++

arch/arm/Kconfig | 1 +

arch/arm/common/timer-sp.c | 2 +-

arch/arm/include/asm/sched_clock.h | 18 +-

arch/arm/kernel/Makefile | 2 +-

arch/arm/kernel/arch_timer.c | 2 +-

arch/arm/kernel/time.c | 4 +-

arch/arm/mach-davinci/time.c | 2 +-

arch/arm/mach-imx/time.c | 2 +-

arch/arm/mach-integrator/integrator_ap.c | 2 +-

arch/arm/mach-ixp4xx/common.c | 2 +-

arch/arm/mach-mmp/time.c | 2 +-

arch/arm/mach-msm/timer.c | 2 +-

arch/arm/mach-omap1/time.c | 2 +-

arch/arm/mach-omap2/timer.c | 2 +-

arch/arm/mach-pxa/time.c | 2 +-

arch/arm/mach-sa1100/time.c | 2 +-

arch/arm/mach-u300/timer.c | 2 +-

arch/arm/plat-iop/time.c | 2 +-

arch/arm/plat-omap/counter_32k.c | 2 +-

arch/arm/plat-orion/time.c | 2 +-

arch/arm/plat-samsung/samsung-time.c | 2 +-

arch/arm/plat-versatile/sched-clock.c | 2 +-

arch/x86/include/asm/mc146818rtc.h | 4 +-

arch/x86/include/asm/mrst-vrtc.h | 4 +-

arch/x86/include/asm/x86_init.h | 6 +-

arch/x86/kernel/kvmclock.c | 9 +-

arch/x86/kernel/rtc.c | 17 +-

arch/x86/lguest/boot.c | 4 +-

arch/x86/platform/efi/efi.c | 10 +-

arch/x86/platform/mrst/vrtc.c | 11 +-

arch/x86/xen/time.c | 58 ++-

drivers/clocksource/Kconfig | 5 +

drivers/clocksource/Makefile | 3 +

drivers/clocksource/bcm2835_timer.c | 2 +-

drivers/clocksource/clksrc-dbx500-prcmu.c | 3 +-

drivers/clocksource/dummy_timer.c | 69 ++++

drivers/clocksource/dw_apb_timer.c | 12 -

drivers/clocksource/dw_apb_timer_of.c | 6 +-

drivers/clocksource/mxs_timer.c | 2 +-

drivers/clocksource/nomadik-mtu.c | 2 +-

drivers/clocksource/samsung_pwm_timer.c | 2 +-

drivers/clocksource/tegra20_timer.c | 2 +-

drivers/clocksource/time-armada-370-xp.c | 2 +-

drivers/clocksource/timer-marco.c | 2 +-

drivers/clocksource/timer-prima2.c | 2 +-

drivers/clocksource/vf_pit_timer.c | 194 ++++++++++

drivers/clocksource/zevio-timer.c | 215 +++++++++++

drivers/xen/manage.c | 3 -

fs/timerfd.c | 131 +++++--

include/linux/alarmtimer.h | 4 +

include/linux/clockchips.h | 5 +-

include/linux/clocksource.h | 8 +-

include/linux/dw_apb_timer.h | 1 -

include/linux/efi.h | 4 +-

include/linux/ktime.h | 10 +-

include/linux/posix-timers.h | 16 +-

include/linux/pvclock_gtod.h | 7 +

include/linux/sched_clock.h | 21 ++

init/Kconfig | 3 +

init/main.c | 2 +

kernel/hrtimer.c | 32 +-

kernel/posix-cpu-timers.c | 395 +++++++-------------

kernel/sched/stats.h | 39 +-

kernel/time/Makefile | 2 +

kernel/time/alarmtimer.c | 47 ++-

kernel/time/clockevents.c | 271 ++++++++++++--

kernel/time/clocksource.c | 266 +++++++++----

{arch/arm/kernel => kernel/time}/sched_clock.c | 17 +-

kernel/time/tick-broadcast.c | 126 +++++--

kernel/time/tick-common.c | 197 ++++------

kernel/time/tick-internal.h | 17 +-

kernel/time/timekeeping.c | 65 ++--

kernel/time/timekeeping_debug.c | 72 ++++

kernel/time/timekeeping_internal.h | 14 +

kernel/timer.c | 8 +-

tools/testing/selftests/Makefile | 1 +

tools/testing/selftests/timers/Makefile | 8 +

tools/testing/selftests/timers/posix_timers.c | 221 +++++++++++

79 files changed, 2050 insertions(+), 703 deletions(-)

create mode 100644 Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt

create mode 100644 drivers/clocksource/dummy_timer.c

create mode 100644 drivers/clocksource/vf_pit_timer.c

create mode 100644 drivers/clocksource/zevio-timer.c

create mode 100644 include/linux/sched_clock.h

rename {arch/arm/kernel => kernel/time}/sched_clock.c (94%)

create mode 100644 kernel/time/timekeeping_debug.c

create mode 100644 kernel/time/timekeeping_internal.h

create mode 100644 tools/testing/selftests/timers/Makefile

create mode 100644 tools/testing/selftests/timers/posix_timers.c

diff --git a/Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt b/Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt

new file mode 100644

index 0000000..b2d07ad

--- /dev/null

+++ b/Documentation/devicetree/bindings/timer/lsi,zevio-timer.txt

@@ -0,0 +1,33 @@

+TI-NSPIRE timer

+

+Required properties:

+

+- compatible : should be "lsi,zevio-timer".

+- reg : The physical base address and size of the timer (always first).

+- clocks: phandle to the source clock.

+

+Optional properties:

+

+- interrupts : The interrupt number of the first timer.

+- reg : The interrupt acknowledgement registers

+ (always after timer base address)

+

+If any of the optional properties are not given, the timer is added as a

+clock-source only.

+

+Example:

+

+timer {

+ compatible = "lsi,zevio-timer";

+ reg = <0x900D0000 0x1000>, <0x900A0020 0x8>;

+ interrupts = <19>;

+ clocks = <&timer_clk>;

+};

+

+Example (no clock-events):

+

+timer {

+ compatible = "lsi,zevio-timer";

+ reg = <0x900D0000 0x1000>;

+ clocks = <&timer_clk>;

+};

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig

index 136f263..b02e6bb 100644

--- a/arch/arm/Kconfig

+++ b/arch/arm/Kconfig

@@ -14,6 +14,7 @@ config ARM

select GENERIC_IRQ_PROBE

select GENERIC_IRQ_SHOW

select GENERIC_PCI_IOMAP

+ select GENERIC_SCHED_CLOCK

select GENERIC_SMP_IDLE_THREAD

select GENERIC_IDLE_POLL_SETUP

select GENERIC_STRNCPY_FROM_USER

diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c

index ddc7407..023ee63 100644

--- a/arch/arm/common/timer-sp.c

+++ b/arch/arm/common/timer-sp.c

@@ -28,8 +28,8 @@

#include <linux/of.h>

#include <linux/of_address.h>

#include <linux/of_irq.h>

+#include <linux/sched_clock.h>

-#include <asm/sched_clock.h>

#include <asm/hardware/arm_timer.h>

#include <asm/hardware/timer-sp.h>

diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h

index 3d520dd..2389b71 100644

--- a/arch/arm/include/asm/sched_clock.h

+++ b/arch/arm/include/asm/sched_clock.h

@@ -1,16 +1,4 @@

-/*

- * sched_clock.h: support for extending counters to full 64-bit ns counter

- *

- * This program is free software; you can redistribute it and/or modify

- * it under the terms of the GNU General Public License version 2 as

- * published by the Free Software Foundation.

+/* You shouldn't include this file. Use linux/sched_clock.h instead.

+ * Temporary file until all asm/sched_clock.h users are gone

*/

-#ifndef ASM_SCHED_CLOCK

-#define ASM_SCHED_CLOCK

-

-extern void sched_clock_postinit(void);

-extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);

-

-extern unsigned long long (*sched_clock_func)(void);

-

-#endif

+#include <linux/sched_clock.h>

diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile

index 5f3338e..97cb057 100644

--- a/arch/arm/kernel/Makefile

+++ b/arch/arm/kernel/Makefile

@@ -16,7 +16,7 @@ CFLAGS_REMOVE_return_address.o = -pg

# Object file lists.

obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \

- process.o ptrace.o return_address.o sched_clock.o \

+ process.o ptrace.o return_address.o \

setup.o signal.o stacktrace.o sys_arm.o time.o traps.o

obj-$(CONFIG_ATAGS) += atags_parse.o

diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c

index 59dcdce..221f07b 100644

--- a/arch/arm/kernel/arch_timer.c

+++ b/arch/arm/kernel/arch_timer.c

@@ -11,9 +11,9 @@

#include <linux/init.h>

#include <linux/types.h>

#include <linux/errno.h>

+#include <linux/sched_clock.h>

#include <asm/delay.h>

-#include <asm/sched_clock.h>

#include <clocksource/arm_arch_timer.h>

diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c

index abff4e9..98aee32 100644

--- a/arch/arm/kernel/time.c

+++ b/arch/arm/kernel/time.c

@@ -24,9 +24,9 @@

#include <linux/timer.h>

#include <linux/clocksource.h>

#include <linux/irq.h>

+#include <linux/sched_clock.h>

#include <asm/thread_info.h>

-#include <asm/sched_clock.h>

#include <asm/stacktrace.h>

#include <asm/mach/arch.h>

#include <asm/mach/time.h>

@@ -120,6 +120,4 @@ void __init time_init(void)

machine_desc->init_time();

else

clocksource_of_init();

-

- sched_clock_postinit();

}

diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c

index bad361e..7a55b5c 100644

--- a/arch/arm/mach-davinci/time.c

+++ b/arch/arm/mach-davinci/time.c

@@ -18,8 +18,8 @@

#include <linux/clk.h>

#include <linux/err.h>

#include <linux/platform_device.h>

+#include <linux/sched_clock.h>

-#include <asm/sched_clock.h>

#include <asm/mach/irq.h>

#include <asm/mach/time.h>

diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c

index fea9131..cd46529 100644

--- a/arch/arm/mach-imx/time.c

+++ b/arch/arm/mach-imx/time.c

@@ -26,8 +26,8 @@

#include <linux/clockchips.h>

#include <linux/clk.h>

#include <linux/err.h>

+#include <linux/sched_clock.h>

-#include <asm/sched_clock.h>

#include <asm/mach/time.h>

#include "common.h"

diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c

index b23c8e4..aa43462 100644

--- a/arch/arm/mach-integrator/integrator_ap.c

+++ b/arch/arm/mach-integrator/integrator_ap.c

@@ -41,6 +41,7 @@

#include <linux/stat.h>

#include <linux/sys_soc.h>

#include <linux/termios.h>

+#include <linux/sched_clock.h>

#include <video/vga.h>

#include <mach/hardware.h>

@@ -49,7 +50,6 @@

#include <asm/setup.h>

#include <asm/param.h> /* HZ */

#include <asm/mach-types.h>

-#include <asm/sched_clock.h>

#include <mach/lm.h>

#include <mach/irqs.h>

diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c

index 6600cff..58307cf 100644

--- a/arch/arm/mach-ixp4xx/common.c

+++ b/arch/arm/mach-ixp4xx/common.c

@@ -30,6 +30,7 @@

#include <linux/export.h>

#include <linux/gpio.h>

#include <linux/cpu.h>

+#include <linux/sched_clock.h>

#include <mach/udc.h>

#include <mach/hardware.h>

@@ -38,7 +39,6 @@

#include <asm/pgtable.h>

#include <asm/page.h>

#include <asm/irq.h>

-#include <asm/sched_clock.h>

#include <asm/system_misc.h>

#include <asm/mach/map.h>

diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c

index 86a18b3..7ac41e8 100644

--- a/arch/arm/mach-mmp/time.c

+++ b/arch/arm/mach-mmp/time.c

@@ -28,8 +28,8 @@

#include <linux/of.h>

#include <linux/of_address.h>

#include <linux/of_irq.h>

+#include <linux/sched_clock.h>

-#include <asm/sched_clock.h>

#include <mach/addr-map.h>

#include <mach/regs-timers.h>

#include <mach/regs-apbc.h>

diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c

index 284313f..b6418fd 100644

--- a/arch/arm/mach-msm/timer.c

+++ b/arch/arm/mach-msm/timer.c

@@ -23,10 +23,10 @@

#include <linux/of.h>

#include <linux/of_address.h>

#include <linux/of_irq.h>

+#include <linux/sched_clock.h>

#include <asm/mach/time.h>

#include <asm/localtimer.h>

-#include <asm/sched_clock.h>

#include "common.h"

diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c

index 726ec23..80603d2 100644

--- a/arch/arm/mach-omap1/time.c

+++ b/arch/arm/mach-omap1/time.c

@@ -43,9 +43,9 @@

#include <linux/clocksource.h>

#include <linux/clockchips.h>

#include <linux/io.h>

+#include <linux/sched_clock.h>

#include <asm/irq.h>

-#include <asm/sched_clock.h>

#include <mach/hardware.h>

#include <asm/mach/irq.h>

diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c

index f8b23b8..4c069b0 100644

--- a/arch/arm/mach-omap2/timer.c

+++ b/arch/arm/mach-omap2/timer.c

@@ -41,10 +41,10 @@

#include <linux/of_irq.h>

#include <linux/platform_device.h>

#include <linux/platform_data/dmtimer-omap.h>

+#include <linux/sched_clock.h>

#include <asm/mach/time.h>

#include <asm/smp_twd.h>

-#include <asm/sched_clock.h>

#include "omap_hwmod.h"

#include "omap_device.h"

diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c

index 8f1ee92..9aa852a 100644

--- a/arch/arm/mach-pxa/time.c

+++ b/arch/arm/mach-pxa/time.c

@@ -16,11 +16,11 @@

#include <linux/init.h>

#include <linux/interrupt.h>

#include <linux/clockchips.h>

+#include <linux/sched_clock.h>

#include <asm/div64.h>

#include <asm/mach/irq.h>

#include <asm/mach/time.h>

-#include <asm/sched_clock.h>

#include <mach/regs-ost.h>

#include <mach/irqs.h>

diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c

index a59a13a..713c86c 100644

--- a/arch/arm/mach-sa1100/time.c

+++ b/arch/arm/mach-sa1100/time.c

@@ -14,9 +14,9 @@

#include <linux/irq.h>

#include <linux/timex.h>

#include <linux/clockchips.h>

+#include <linux/sched_clock.h>

#include <asm/mach/time.h>

-#include <asm/sched_clock.h>

#include <mach/hardware.h>

#include <mach/irqs.h>

diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c

index d9e7320..af771b7 100644

--- a/arch/arm/mach-u300/timer.c

+++ b/arch/arm/mach-u300/timer.c

@@ -18,12 +18,12 @@

#include <linux/clk.h>

#include <linux/err.h>

#include <linux/irq.h>

+#include <linux/sched_clock.h>

#include <mach/hardware.h>

#include <mach/irqs.h>

/* Generic stuff */

-#include <asm/sched_clock.h>

#include <asm/mach/map.h>

#include <asm/mach/time.h>

diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c

index 837a2d5..29606bd7 100644

--- a/arch/arm/plat-iop/time.c

+++ b/arch/arm/plat-iop/time.c

@@ -22,9 +22,9 @@

#include <linux/clocksource.h>

#include <linux/clockchips.h>

#include <linux/export.h>

+#include <linux/sched_clock.h>

#include <mach/hardware.h>

#include <asm/irq.h>

-#include <asm/sched_clock.h>

#include <asm/uaccess.h>

#include <asm/mach/irq.h>

#include <asm/mach/time.h>

diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c

index 5b0b86b..d9bc98e 100644

--- a/arch/arm/plat-omap/counter_32k.c

+++ b/arch/arm/plat-omap/counter_32k.c

@@ -18,9 +18,9 @@

#include <linux/err.h>

#include <linux/io.h>

#include <linux/clocksource.h>

+#include <linux/sched_clock.h>

#include <asm/mach/time.h>

-#include <asm/sched_clock.h>

#include <plat/counter-32k.h>

diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c

index 5d5ac0f..9d2b2ac 100644

--- a/arch/arm/plat-orion/time.c

+++ b/arch/arm/plat-orion/time.c

@@ -16,7 +16,7 @@

#include <linux/clockchips.h>

#include <linux/interrupt.h>

#include <linux/irq.h>

-#include <asm/sched_clock.h>

+#include <linux/sched_clock.h>

/*

* MBus bridge block registers.

diff --git a/arch/arm/plat-samsung/samsung-time.c b/arch/arm/plat-samsung/samsung-time.c

index f899cbc..2957075 100644

--- a/arch/arm/plat-samsung/samsung-time.c

+++ b/arch/arm/plat-samsung/samsung-time.c

@@ -15,12 +15,12 @@

#include <linux/clk.h>

#include <linux/clockchips.h>

#include <linux/platform_device.h>

+#include <linux/sched_clock.h>

#include <asm/smp_twd.h>

#include <asm/mach/time.h>

#include <asm/mach/arch.h>

#include <asm/mach/map.h>

-#include <asm/sched_clock.h>

#include <mach/map.h>

#include <plat/devs.h>

diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c

index b33b74c..51b109e 100644

--- a/arch/arm/plat-versatile/sched-clock.c

+++ b/arch/arm/plat-versatile/sched-clock.c

@@ -20,8 +20,8 @@

*/

#include <linux/kernel.h>

#include <linux/io.h>

+#include <linux/sched_clock.h>

-#include <asm/sched_clock.h>

#include <plat/sched_clock.h>

static void __iomem *ctr;

diff --git a/arch/x86/include/asm/mc146818rtc.h b/arch/x86/include/asm/mc146818rtc.h

index d354fb7..a55c7ef 100644

--- a/arch/x86/include/asm/mc146818rtc.h

+++ b/arch/x86/include/asm/mc146818rtc.h

@@ -95,8 +95,8 @@ static inline unsigned char current_lock_cmos_reg(void)

unsigned char rtc_cmos_read(unsigned char addr);

void rtc_cmos_write(unsigned char val, unsigned char addr);

-extern int mach_set_rtc_mmss(unsigned long nowtime);

-extern unsigned long mach_get_cmos_time(void);

+extern int mach_set_rtc_mmss(const struct timespec *now);

+extern void mach_get_cmos_time(struct timespec *now);

#define RTC_IRQ 8

diff --git a/arch/x86/include/asm/mrst-vrtc.h b/arch/x86/include/asm/mrst-vrtc.h

index 73668ab..1e69a75 100644

--- a/arch/x86/include/asm/mrst-vrtc.h

+++ b/arch/x86/include/asm/mrst-vrtc.h

@@ -3,7 +3,7 @@

extern unsigned char vrtc_cmos_read(unsigned char reg);

extern void vrtc_cmos_write(unsigned char val, unsigned char reg);

-extern unsigned long vrtc_get_time(void);

-extern int vrtc_set_mmss(unsigned long nowtime);

+extern void vrtc_get_time(struct timespec *now);

+extern int vrtc_set_mmss(const struct timespec *now);

#endif

diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h

index d8d9922..828a156 100644

--- a/arch/x86/include/asm/x86_init.h

+++ b/arch/x86/include/asm/x86_init.h

@@ -142,6 +142,8 @@ struct x86_cpuinit_ops {

void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node);

};

+struct timespec;

+

/**

* struct x86_platform_ops - platform specific runtime functions

* @calibrate_tsc: calibrate TSC

@@ -156,8 +158,8 @@ struct x86_cpuinit_ops {

*/

struct x86_platform_ops {

unsigned long (*calibrate_tsc)(void);

- unsigned long (*get_wallclock)(void);

- int (*set_wallclock)(unsigned long nowtime);

+ void (*get_wallclock)(struct timespec *ts);

+ int (*set_wallclock)(const struct timespec *ts);

void (*iommu_shutdown)(void);

bool (*is_untracked_pat_range)(u64 start, u64 end);

void (*nmi_init)(void);

diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c

index 3dd37eb..1f354f4 100644

--- a/arch/x86/kernel/kvmclock.c

+++ b/arch/x86/kernel/kvmclock.c

@@ -48,10 +48,9 @@ static struct pvclock_wall_clock wall_clock;

* have elapsed since the hypervisor wrote the data. So we try to account for

* that with system time

*/

-static unsigned long kvm_get_wallclock(void)

+static void kvm_get_wallclock(struct timespec *now)

{

struct pvclock_vcpu_time_info *vcpu_time;

- struct timespec ts;

int low, high;

int cpu;

@@ -64,14 +63,12 @@ static unsigned long kvm_get_wallclock(void)

cpu = smp_processor_id();

vcpu_time = &hv_clock[cpu].pvti;

- pvclock_read_wallclock(&wall_clock, vcpu_time, &ts);

+ pvclock_read_wallclock(&wall_clock, vcpu_time, now);

preempt_enable();

-

- return ts.tv_sec;

}

-static int kvm_set_wallclock(unsigned long now)

+static int kvm_set_wallclock(const struct timespec *now)

{

return -1;

}

diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c

index 198eb20..0aa2939 100644

--- a/arch/x86/kernel/rtc.c

+++ b/arch/x86/kernel/rtc.c

@@ -38,8 +38,9 @@ EXPORT_SYMBOL(rtc_lock);

* jump to the next second precisely 500 ms later. Check the Motorola

* MC146818A or Dallas DS12887 data sheet for details.

*/

-int mach_set_rtc_mmss(unsigned long nowtime)

+int mach_set_rtc_mmss(const struct timespec *now)

{

+ unsigned long nowtime = now->tv_sec;

struct rtc_time tm;

int retval = 0;

@@ -58,7 +59,7 @@ int mach_set_rtc_mmss(unsigned long nowtime)

return retval;

}

-unsigned long mach_get_cmos_time(void)

+void mach_get_cmos_time(struct timespec *now)

{

unsigned int status, year, mon, day, hour, min, sec, century = 0;

unsigned long flags;

@@ -107,7 +108,8 @@ unsigned long mach_get_cmos_time(void)

} else

year += CMOS_YEARS_OFFS;

- return mktime(year, mon, day, hour, min, sec);

+ now->tv_sec = mktime(year, mon, day, hour, min, sec);

+ now->tv_nsec = 0;

}

/* Routines for accessing the CMOS RAM/RTC. */

@@ -135,18 +137,13 @@ EXPORT_SYMBOL(rtc_cmos_write);

int update_persistent_clock(struct timespec now)

{

- return x86_platform.set_wallclock(now.tv_sec);

+ return x86_platform.set_wallclock(&now);

}

/* not static: needed by APM */

void read_persistent_clock(struct timespec *ts)

{

- unsigned long retval;

-

- retval = x86_platform.get_wallclock();

-

- ts->tv_sec = retval;

- ts->tv_nsec = 0;

+ x86_platform.get_wallclock(ts);

}

diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c

index 7114c63..8424d5a 100644

--- a/arch/x86/lguest/boot.c

+++ b/arch/x86/lguest/boot.c

@@ -882,9 +882,9 @@ int lguest_setup_irq(unsigned int irq)

* It would be far better for everyone if the Guest had its own clock, but

* until then the Host gives us the time on every interrupt.

*/

-static unsigned long lguest_get_wallclock(void)

+static void lguest_get_wallclock(struct timespec *now)

{

- return lguest_data.time.tv_sec;

+ *now = lguest_data.time;

}

/*

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c

index d2fbced..90f6ed1 100644

--- a/arch/x86/platform/efi/efi.c

+++ b/arch/x86/platform/efi/efi.c

@@ -274,8 +274,9 @@ static efi_status_t __init phys_efi_get_time(efi_time_t *tm,

return status;

}

-int efi_set_rtc_mmss(unsigned long nowtime)

+int efi_set_rtc_mmss(const struct timespec *now)

{

+ unsigned long nowtime = now->tv_sec;

efi_status_t status;

efi_time_t eft;

efi_time_cap_t cap;

@@ -310,7 +311,7 @@ int efi_set_rtc_mmss(unsigned long nowtime)

return 0;

}

-unsigned long efi_get_time(void)

+void efi_get_time(struct timespec *now)

{

efi_status_t status;

efi_time_t eft;

@@ -320,8 +321,9 @@ unsigned long efi_get_time(void)

if (status != EFI_SUCCESS)

pr_err("Oops: efitime: can't read time!\n");

- return mktime(eft.year, eft.month, eft.day, eft.hour,

- eft.minute, eft.second);

+ now->tv_sec = mktime(eft.year, eft.month, eft.day, eft.hour,

+ eft.minute, eft.second);

+ now->tv_nsec = 0;

}

/*

diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c

index d62b0a3..5e355b1 100644

--- a/arch/x86/platform/mrst/vrtc.c

+++ b/arch/x86/platform/mrst/vrtc.c

@@ -56,7 +56,7 @@ void vrtc_cmos_write(unsigned char val, unsigned char reg)

}

EXPORT_SYMBOL_GPL(vrtc_cmos_write);

-unsigned long vrtc_get_time(void)

+void vrtc_get_time(struct timespec *now)

{

u8 sec, min, hour, mday, mon;

unsigned long flags;

@@ -82,17 +82,18 @@ unsigned long vrtc_get_time(void)

printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "

"mon: %d year: %d\n", sec, min, hour, mday, mon, year);

- return mktime(year, mon, mday, hour, min, sec);

+ now->tv_sec = mktime(year, mon, mday, hour, min, sec);

+ now->tv_nsec = 0;

}

-int vrtc_set_mmss(unsigned long nowtime)

+int vrtc_set_mmss(const struct timespec *now)

{

unsigned long flags;

struct rtc_time tm;

int year;

int retval = 0;

- rtc_time_to_tm(nowtime, &tm);

+ rtc_time_to_tm(now->tv_sec, &tm);

if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) {

/*

* tm.year is the number of years since 1900, and the

@@ -110,7 +111,7 @@ int vrtc_set_mmss(unsigned long nowtime)

} else {

printk(KERN_ERR

"%s: Invalid vRTC value: write of %lx to vRTC failed\n",

- __FUNCTION__, nowtime);

+ __FUNCTION__, now->tv_sec);

retval = -EINVAL;

}

return retval;

diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c

index 3d88bfd..7a5671b 100644

--- a/arch/x86/xen/time.c

+++ b/arch/x86/xen/time.c

@@ -14,6 +14,7 @@

#include <linux/kernel_stat.h>

#include <linux/math64.h>

#include <linux/gfp.h>

+#include <linux/pvclock_gtod.h>

#include <asm/pvclock.h>

#include <asm/xen/hypervisor.h>

@@ -191,34 +192,56 @@ static void xen_read_wallclock(struct timespec *ts)

put_cpu_var(xen_vcpu);

}

-static unsigned long xen_get_wallclock(void)

+static void xen_get_wallclock(struct timespec *now)

{

- struct timespec ts;

+ xen_read_wallclock(now);

+}

- xen_read_wallclock(&ts);

- return ts.tv_sec;

+static int xen_set_wallclock(const struct timespec *now)

+{

+ return -1;

}

-static int xen_set_wallclock(unsigned long now)

+static int xen_pvclock_gtod_notify(struct notifier_block *nb,

+ unsigned long was_set, void *priv)

{

+ /* Protected by the calling core code serialization */

+ static struct timespec next_sync;

+

struct xen_platform_op op;

- int rc;

+ struct timespec now;

- /* do nothing for domU */

- if (!xen_initial_domain())

- return -1;

+ now = __current_kernel_time();

+

+ /*

+ * We only take the expensive HV call when the clock was set

+ * or when the 11 minutes RTC synchronization time elapsed.

+ */

+ if (!was_set && timespec_compare(&now, &next_sync) < 0)

+ return NOTIFY_OK;

op.cmd = XENPF_settime;

- op.u.settime.secs = now;

- op.u.settime.nsecs = 0;

+ op.u.settime.secs = now.tv_sec;

+ op.u.settime.nsecs = now.tv_nsec;

op.u.settime.system_time = xen_clocksource_read();

- rc = HYPERVISOR_dom0_op(&op);

- WARN(rc != 0, "XENPF_settime failed: now=%ld\n", now);

+ (void)HYPERVISOR_dom0_op(&op);

- return rc;

+ /*

+ * Move the next drift compensation time 11 minutes

+ * ahead. That's emulating the sync_cmos_clock() update for

+ * the hardware RTC.

+ */

+ next_sync = now;

+ next_sync.tv_sec += 11 * 60;

+

+ return NOTIFY_OK;

}

+static struct notifier_block xen_pvclock_gtod_notifier = {

+ .notifier_call = xen_pvclock_gtod_notify,

+};

+

static struct clocksource xen_clocksource __read_mostly = {

.name = "xen",

.rating = 400,

@@ -480,6 +503,9 @@ static void __init xen_time_init(void)

xen_setup_runstate_info(cpu);

xen_setup_timer(cpu);

xen_setup_cpu_clockevents();

+

+ if (xen_initial_domain())

+ pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier);

}

void __init xen_init_time_ops(void)

@@ -492,7 +518,9 @@ void __init xen_init_time_ops(void)

x86_platform.calibrate_tsc = xen_tsc_khz;

x86_platform.get_wallclock = xen_get_wallclock;

- x86_platform.set_wallclock = xen_set_wallclock;

+ /* Dom0 uses the native method to set the hardware RTC. */

+ if (!xen_initial_domain())

+ x86_platform.set_wallclock = xen_set_wallclock;

}

#ifdef CONFIG_XEN_PVHVM

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig

index f151c6c..0a04257 100644

--- a/drivers/clocksource/Kconfig

+++ b/drivers/clocksource/Kconfig

@@ -85,3 +85,8 @@ config CLKSRC_SAMSUNG_PWM

Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver

for all devicetree enabled platforms. This driver will be

needed only on systems that do not have the Exynos MCT available.

+

+config VF_PIT_TIMER

+ bool

+ help

+ Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.

diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile

index 8d979c7..9ba8b4d 100644

--- a/drivers/clocksource/Makefile

+++ b/drivers/clocksource/Makefile

@@ -22,10 +22,13 @@ obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o

obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o

obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o

obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o

+obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o

obj-$(CONFIG_ARCH_BCM) += bcm_kona_timer.o

obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o

obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o

obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o

+obj-$(CONFIG_VF_PIT_TIMER) += vf_pit_timer.o

obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o

obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o

+obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o

diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c

index 766611d..07ea7ce 100644

--- a/drivers/clocksource/bcm2835_timer.c

+++ b/drivers/clocksource/bcm2835_timer.c

@@ -28,8 +28,8 @@

#include <linux/of_platform.h>

#include <linux/slab.h>

#include <linux/string.h>

+#include <linux/sched_clock.h>

-#include <asm/sched_clock.h>

#include <asm/irq.h>

#define REG_CONTROL 0x00

diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c

index 54f3d11..0a7fb24 100644

--- a/drivers/clocksource/clksrc-dbx500-prcmu.c

+++ b/drivers/clocksource/clksrc-dbx500-prcmu.c

@@ -14,8 +14,7 @@

*/

#include <linux/clockchips.h>

#include <linux/clksrc-dbx500-prcmu.h>

-

-#include <asm/sched_clock.h>

+#include <linux/sched_clock.h>

#define RATE_32K 32768

diff --git a/drivers/clocksource/dummy_timer.c b/drivers/clocksource/dummy_timer.c

new file mode 100644

index 0000000..1f55f96

--- /dev/null

+++ b/drivers/clocksource/dummy_timer.c

@@ -0,0 +1,69 @@

+/*

+ * linux/drivers/clocksource/dummy_timer.c

+ *

+ * Copyright (C) 2013 ARM Ltd.

+ * All Rights Reserved

+ *

+ * This program is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License version 2 as

+ * published by the Free Software Foundation.

+ */

+#include <linux/clockchips.h>

+#include <linux/cpu.h>

+#include <linux/init.h>

+#include <linux/percpu.h>

+#include <linux/cpumask.h>

+

+static DEFINE_PER_CPU(struct clock_event_device, dummy_timer_evt);

+

+static void dummy_timer_set_mode(enum clock_event_mode mode,

+ struct clock_event_device *evt)

+{

+ /*

+ * Core clockevents code will call this when exchanging timer devices.

+ * We don't need to do anything here.

+ */

+}

+

+static void __cpuinit dummy_timer_setup(void)

+{

+ int cpu = smp_processor_id();

+ struct clock_event_device *evt = __this_cpu_ptr(&dummy_timer_evt);

+

+ evt->name = "dummy_timer";

+ evt->features = CLOCK_EVT_FEAT_PERIODIC |

+ CLOCK_EVT_FEAT_ONESHOT |

+ CLOCK_EVT_FEAT_DUMMY;

+ evt->rating = 100;

+ evt->set_mode = dummy_timer_set_mode;

+ evt->cpumask = cpumask_of(cpu);

+

+ clockevents_register_device(evt);

+}

+

+static int __cpuinit dummy_timer_cpu_notify(struct notifier_block *self,

+ unsigned long action, void *hcpu)

+{

+ if ((action & ~CPU_TASKS_FROZEN) == CPU_STARTING)

+ dummy_timer_setup();

+

+ return NOTIFY_OK;

+}

+

+static struct notifier_block dummy_timer_cpu_nb __cpuinitdata = {

+ .notifier_call = dummy_timer_cpu_notify,

+};

+

+static int __init dummy_timer_register(void)

+{

+ int err = register_cpu_notifier(&dummy_timer_cpu_nb);

+ if (err)

+ return err;

+

+ /* We won't get a call on the boot CPU, so register immediately */

+ if (num_possible_cpus() > 1)

+ dummy_timer_setup();

+

+ return 0;

+}

+early_initcall(dummy_timer_register);

diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c

index 8c2a35f..e54ca10 100644

--- a/drivers/clocksource/dw_apb_timer.c

+++ b/drivers/clocksource/dw_apb_timer.c

@@ -387,15 +387,3 @@ cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs)

{

return (cycle_t)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);

}

-

-/**

- * dw_apb_clocksource_unregister() - unregister and free a clocksource.

- *

- * @dw_cs: The clocksource to unregister/free.

- */

-void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs)

-{

- clocksource_unregister(&dw_cs->cs);

-

- kfree(dw_cs);

-}

diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c

index ab09ed3..d9a1e8d 100644

--- a/drivers/clocksource/dw_apb_timer_of.c

+++ b/drivers/clocksource/dw_apb_timer_of.c

@@ -20,9 +20,7 @@

#include <linux/of.h>

#include <linux/of_address.h>

#include <linux/of_irq.h>

-

-#include <asm/mach/time.h>

-#include <asm/sched_clock.h>

+#include <linux/sched_clock.h>

static void timer_get_base_and_rate(struct device_node *np,

void __iomem **base, u32 *rate)

@@ -44,7 +42,7 @@ static void add_clockevent(struct device_node *event_timer)

u32 irq, rate;

irq = irq_of_parse_and_map(event_timer, 0);

- if (irq == NO_IRQ)

+ if (irq == 0)

panic("No IRQ for clock event timer");

timer_get_base_and_rate(event_timer, &iobase, &rate);

diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c

index 02af420..0f5e65f 100644

--- a/drivers/clocksource/mxs_timer.c

+++ b/drivers/clocksource/mxs_timer.c

@@ -29,9 +29,9 @@

#include <linux/of_address.h>

#include <linux/of_irq.h>

#include <linux/stmp_device.h>

+#include <linux/sched_clock.h>

#include <asm/mach/time.h>

-#include <asm/sched_clock.h>

/*

* There are 2 versions of the timrot on Freescale MXS-based SoCs.

diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c

index e405531..8864c17 100644

--- a/drivers/clocksource/nomadik-mtu.c

+++ b/drivers/clocksource/nomadik-mtu.c

@@ -18,8 +18,8 @@

#include <linux/delay.h>

#include <linux/err.h>

#include <linux/platform_data/clocksource-nomadik-mtu.h>

+#include <linux/sched_clock.h>

#include <asm/mach/time.h>

-#include <asm/sched_clock.h>

/*

* The MTU device hosts four different counters, with 4 set of

diff --git a/drivers/clocksource/samsung_pwm_timer.c b/drivers/clocksource/samsung_pwm_timer.c

index 0234c8d..584b547 100644

--- a/drivers/clocksource/samsung_pwm_timer.c

+++ b/drivers/clocksource/samsung_pwm_timer.c

@@ -21,10 +21,10 @@

#include <linux/of_irq.h>

#include <linux/platform_device.h>

#include <linux/slab.h>

+#include <linux/sched_clock.h>

#include <clocksource/samsung_pwm.h>

-#include <asm/sched_clock.h>

/*

* Clocksource driver

diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c

index ae877b0..9396170 100644

--- a/drivers/clocksource/tegra20_timer.c

+++ b/drivers/clocksource/tegra20_timer.c

@@ -26,10 +26,10 @@

#include <linux/io.h>

#include <linux/of_address.h>

#include <linux/of_irq.h>

+#include <linux/sched_clock.h>

#include <asm/mach/time.h>

#include <asm/smp_twd.h>

-#include <asm/sched_clock.h>

#define RTC_SECONDS 0x08

#define RTC_SHADOW_SECONDS 0x0c

diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c

index 47a6730..efdca32 100644

--- a/drivers/clocksource/time-armada-370-xp.c

+++ b/drivers/clocksource/time-armada-370-xp.c

@@ -27,8 +27,8 @@

#include <linux/of_address.h>

#include <linux/irq.h>

#include <linux/module.h>

+#include <linux/sched_clock.h>

-#include <asm/sched_clock.h>

#include <asm/localtimer.h>

#include <linux/percpu.h>

/*

diff --git a/drivers/clocksource/timer-marco.c b/drivers/clocksource/timer-marco.c

index 97738db..e5dc912 100644

--- a/drivers/clocksource/timer-marco.c

+++ b/drivers/clocksource/timer-marco.c

@@ -17,7 +17,7 @@

#include <linux/of.h>

#include <linux/of_irq.h>

#include <linux/of_address.h>

-#include <asm/sched_clock.h>

+#include <linux/sched_clock.h>

#include <asm/localtimer.h>

#include <asm/mach/time.h>

diff --git a/drivers/clocksource/timer-prima2.c b/drivers/clocksource/timer-prima2.c

index 7608826..ef3cfb2 100644

--- a/drivers/clocksource/timer-prima2.c

+++ b/drivers/clocksource/timer-prima2.c

@@ -18,7 +18,7 @@

#include <linux/of.h>

#include <linux/of_irq.h>

#include <linux/of_address.h>

-#include <asm/sched_clock.h>

+#include <linux/sched_clock.h>

#include <asm/mach/time.h>

#define SIRFSOC_TIMER_COUNTER_LO 0x0000

diff --git a/drivers/clocksource/vf_pit_timer.c b/drivers/clocksource/vf_pit_timer.c

new file mode 100644

index 0000000..587e020

--- /dev/null

+++ b/drivers/clocksource/vf_pit_timer.c

@@ -0,0 +1,194 @@

+/*

+ * Copyright 2012-2013 Freescale Semiconductor, Inc.

+ *

+ * This program is free software; you can redistribute it and/or

+ * modify it under the terms of the GNU General Public License

+ * as published by the Free Software Foundation; either version 2

+ * of the License, or (at your option) any later version.

+ */

+

+#include <linux/interrupt.h>

+#include <linux/clockchips.h>

+#include <linux/clk.h>

+#include <linux/of_address.h>

+#include <linux/of_irq.h>

+#include <linux/sched_clock.h>

+

+/*

+ * Each pit takes 0x10 Bytes register space

+ */

+#define PITMCR 0x00

+#define PIT0_OFFSET 0x100

+#define PITn_OFFSET(n) (PIT0_OFFSET + 0x10 * (n))

+#define PITLDVAL 0x00

+#define PITCVAL 0x04

+#define PITTCTRL 0x08

+#define PITTFLG 0x0c

+

+#define PITMCR_MDIS (0x1 << 1)

+

+#define PITTCTRL_TEN (0x1 << 0)

+#define PITTCTRL_TIE (0x1 << 1)

+#define PITCTRL_CHN (0x1 << 2)

+

+#define PITTFLG_TIF 0x1

+

+static void __iomem *clksrc_base;

+static void __iomem *clkevt_base;

+static unsigned long cycle_per_jiffy;

+

+static inline void pit_timer_enable(void)

+{

+ __raw_writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL);

+}

+

+static inline void pit_timer_disable(void)

+{

+ __raw_writel(0, clkevt_base + PITTCTRL);

+}

+

+static inline void pit_irq_acknowledge(void)

+{

+ __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);

+}

+

+static unsigned int pit_read_sched_clock(void)

+{

+ return __raw_readl(clksrc_base + PITCVAL);

+}

+

+static int __init pit_clocksource_init(unsigned long rate)

+{

+ /* set the max load value and start the clock source counter */

+ __raw_writel(0, clksrc_base + PITTCTRL);

+ __raw_writel(~0UL, clksrc_base + PITLDVAL);

+ __raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL);

+

+ setup_sched_clock(pit_read_sched_clock, 32, rate);

+ return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate,

+ 300, 32, clocksource_mmio_readl_down);

+}

+

+static int pit_set_next_event(unsigned long delta,

+ struct clock_event_device *unused)

+{

+ /*

+ * set a new value to PITLDVAL register will not restart the timer,

+ * to abort the current cycle and start a timer period with the new

+ * value, the timer must be disabled and enabled again.

+ * and the PITLAVAL should be set to delta minus one according to pit

+ * hardware requirement.

+ */

+ pit_timer_disable();

+ __raw_writel(delta - 1, clkevt_base + PITLDVAL);

+ pit_timer_enable();

+

+ return 0;

+}

+

+static void pit_set_mode(enum clock_event_mode mode,

+ struct clock_event_device *evt)

+{

+ switch (mode) {

+ case CLOCK_EVT_MODE_PERIODIC:

+ pit_set_next_event(cycle_per_jiffy, evt);

+ break;

+ default:

+ break;

+ }

+}

+

+static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)

+{

+ struct clock_event_device *evt = dev_id;

+

+ pit_irq_acknowledge();

+

+ /*

+ * pit hardware doesn't support oneshot, it will generate an interrupt

+ * and reload the counter value from PITLDVAL when PITCVAL reach zero,

+ * and start the counter again. So software need to disable the timer

+ * to stop the counter loop in ONESHOT mode.

+ */

+ if (likely(evt->mode == CLOCK_EVT_MODE_ONESHOT))

+ pit_timer_disable();

+

+ evt->event_handler(evt);

+

+ return IRQ_HANDLED;

+}

+

+static struct clock_event_device clockevent_pit = {

+ .name = "VF pit timer",

+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,

+ .set_mode = pit_set_mode,

+ .set_next_event = pit_set_next_event,

+ .rating = 300,

+};

+

+static struct irqaction pit_timer_irq = {

+ .name = "VF pit timer",

+ .flags = IRQF_TIMER | IRQF_IRQPOLL,

+ .handler = pit_timer_interrupt,

+ .dev_id = &clockevent_pit,

+};

+

+static int __init pit_clockevent_init(unsigned long rate, int irq)

+{

+ __raw_writel(0, clkevt_base + PITTCTRL);

+ __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);

+

+ BUG_ON(setup_irq(irq, &pit_timer_irq));

+

+ clockevent_pit.cpumask = cpumask_of(0);

+ clockevent_pit.irq = irq;

+ /*

+ * The value for the LDVAL register trigger is calculated as:

+ * LDVAL trigger = (period / clock period) - 1

+ * The pit is a 32-bit down count timer, when the conter value

+ * reaches 0, it will generate an interrupt, thus the minimal

+ * LDVAL trigger value is 1. And then the min_delta is

+ * minimal LDVAL trigger value + 1, and the max_delta is full 32-bit.

+ */

+ clockevents_config_and_register(&clockevent_pit, rate, 2, 0xffffffff);

+

+ return 0;

+}

+

+static void __init pit_timer_init(struct device_node *np)

+{

+ struct clk *pit_clk;

+ void __iomem *timer_base;

+ unsigned long clk_rate;

+ int irq;

+

+ timer_base = of_iomap(np, 0);

+ BUG_ON(!timer_base);

+

+ /*

+ * PIT0 and PIT1 can be chained to build a 64-bit timer,

+ * so choose PIT2 as clocksource, PIT3 as clockevent device,

+ * and leave PIT0 and PIT1 unused for anyone else who needs them.

+ */

+ clksrc_base = timer_base + PITn_OFFSET(2);

+ clkevt_base = timer_base + PITn_OFFSET(3);

+

+ irq = irq_of_parse_and_map(np, 0);

+ BUG_ON(irq <= 0);

+

+ pit_clk = of_clk_get(np, 0);

+ BUG_ON(IS_ERR(pit_clk));

+

+ BUG_ON(clk_prepare_enable(pit_clk));

+

+ clk_rate = clk_get_rate(pit_clk);

+ cycle_per_jiffy = clk_rate / (HZ);

+

+ /* enable the pit module */

+ __raw_writel(~PITMCR_MDIS, timer_base + PITMCR);

+

+ BUG_ON(pit_clocksource_init(clk_rate));

+

+ pit_clockevent_init(clk_rate, irq);

+}

+CLOCKSOURCE_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init);

diff --git a/drivers/clocksource/zevio-timer.c b/drivers/clocksource/zevio-timer.c

new file mode 100644

index 0000000..ca81809

--- /dev/null

+++ b/drivers/clocksource/zevio-timer.c

@@ -0,0 +1,215 @@

+/*

+ * linux/drivers/clocksource/zevio-timer.c

+ *

+ * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>

+ *

+ * This program is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License version 2, as

+ * published by the Free Software Foundation.

+ *

+ */

+

+#include <linux/io.h>

+#include <linux/irq.h>

+#include <linux/of.h>

+#include <linux/of_address.h>

+#include <linux/of_irq.h>

+#include <linux/clk.h>

+#include <linux/clockchips.h>

+#include <linux/cpumask.h>

+#include <linux/interrupt.h>

+#include <linux/slab.h>

+

+#define IO_CURRENT_VAL 0x00

+#define IO_DIVIDER 0x04

+#define IO_CONTROL 0x08

+

+#define IO_TIMER1 0x00

+#define IO_TIMER2 0x0C

+

+#define IO_MATCH_BEGIN 0x18

+#define IO_MATCH(x) (IO_MATCH_BEGIN + ((x) << 2))

+

+#define IO_INTR_STS 0x00

+#define IO_INTR_ACK 0x00

+#define IO_INTR_MSK 0x04

+

+#define CNTL_STOP_TIMER (1 << 4)

+#define CNTL_RUN_TIMER (0 << 4)

+

+#define CNTL_INC (1 << 3)

+#define CNTL_DEC (0 << 3)

+

+#define CNTL_TOZERO 0

+#define CNTL_MATCH(x) ((x) + 1)

+#define CNTL_FOREVER 7

+

+/* There are 6 match registers but we only use one. */

+#define TIMER_MATCH 0

+

+#define TIMER_INTR_MSK (1 << (TIMER_MATCH))

+#define TIMER_INTR_ALL 0x3F

+

+struct zevio_timer {

+ void __iomem *base;

+ void __iomem *timer1, *timer2;

+ void __iomem *interrupt_regs;

+

+ struct clk *clk;

+ struct clock_event_device clkevt;

+ struct irqaction clkevt_irq;

+

+ char clocksource_name[64];

+ char clockevent_name[64];

+};

+

+static int zevio_timer_set_event(unsigned long delta,

+ struct clock_event_device *dev)

+{

+ struct zevio_timer *timer = container_of(dev, struct zevio_timer,

+ clkevt);

+

+ writel(delta, timer->timer1 + IO_CURRENT_VAL);

+ writel(CNTL_RUN_TIMER | CNTL_DEC | CNTL_MATCH(TIMER_MATCH),

+ timer->timer1 + IO_CONTROL);

+

+ return 0;

+}

+

+static void zevio_timer_set_mode(enum clock_event_mode mode,

+ struct clock_event_device *dev)

+{

+ struct zevio_timer *timer = container_of(dev, struct zevio_timer,

+ clkevt);

+

+ switch (mode) {

+ case CLOCK_EVT_MODE_RESUME:

+ case CLOCK_EVT_MODE_ONESHOT:

+ /* Enable timer interrupts */

+ writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_MSK);

+ writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);

+ break;

+ case CLOCK_EVT_MODE_SHUTDOWN:

+ case CLOCK_EVT_MODE_UNUSED:

+ /* Disable timer interrupts */

+ writel(0, timer->interrupt_regs + IO_INTR_MSK);

+ writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);

+ /* Stop timer */

+ writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);

+ break;

+ case CLOCK_EVT_MODE_PERIODIC:

+ default:

+ /* Unsupported */

+ break;

+ }

+}

+

+static irqreturn_t zevio_timer_interrupt(int irq, void *dev_id)

+{

+ struct zevio_timer *timer = dev_id;

+ u32 intr;

+

+ intr = readl(timer->interrupt_regs + IO_INTR_ACK);

+ if (!(intr & TIMER_INTR_MSK))

+ return IRQ_NONE;

+

+ writel(TIMER_INTR_MSK, timer->interrupt_regs + IO_INTR_ACK);

+ writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);

+

+ if (timer->clkevt.event_handler)

+ timer->clkevt.event_handler(&timer->clkevt);

+

+ return IRQ_HANDLED;

+}

+

+static int __init zevio_timer_add(struct device_node *node)

+{

+ struct zevio_timer *timer;

+ struct resource res;

+ int irqnr, ret;

+

+ timer = kzalloc(sizeof(*timer), GFP_KERNEL);

+ if (!timer)

+ return -ENOMEM;

+

+ timer->base = of_iomap(node, 0);

+ if (!timer->base) {

+ ret = -EINVAL;

+ goto error_free;

+ }

+ timer->timer1 = timer->base + IO_TIMER1;

+ timer->timer2 = timer->base + IO_TIMER2;

+

+ timer->clk = of_clk_get(node, 0);

+ if (IS_ERR(timer->clk)) {

+ ret = PTR_ERR(timer->clk);

+ pr_err("Timer clock not found! (error %d)\n", ret);

+ goto error_unmap;

+ }

+

+ timer->interrupt_regs = of_iomap(node, 1);

+ irqnr = irq_of_parse_and_map(node, 0);

+

+ of_address_to_resource(node, 0, &res);

+ scnprintf(timer->clocksource_name, sizeof(timer->clocksource_name),

+ "%llx.%s_clocksource",

+ (unsigned long long)res.start, node->name);

+

+ scnprintf(timer->clockevent_name, sizeof(timer->clockevent_name),

+ "%llx.%s_clockevent",

+ (unsigned long long)res.start, node->name);

+

+ if (timer->interrupt_regs && irqnr) {

+ timer->clkevt.name = timer->clockevent_name;

+ timer->clkevt.set_next_event = zevio_timer_set_event;

+ timer->clkevt.set_mode = zevio_timer_set_mode;

+ timer->clkevt.rating = 200;

+ timer->clkevt.cpumask = cpu_all_mask;

+ timer->clkevt.features = CLOCK_EVT_FEAT_ONESHOT;

+ timer->clkevt.irq = irqnr;

+

+ writel(CNTL_STOP_TIMER, timer->timer1 + IO_CONTROL);

+ writel(0, timer->timer1 + IO_DIVIDER);

+

+ /* Start with timer interrupts disabled */

+ writel(0, timer->interrupt_regs + IO_INTR_MSK);

+ writel(TIMER_INTR_ALL, timer->interrupt_regs + IO_INTR_ACK);

+

+ /* Interrupt to occur when timer value matches 0 */

+ writel(0, timer->base + IO_MATCH(TIMER_MATCH));

+

+ timer->clkevt_irq.name = timer->clockevent_name;

+ timer->clkevt_irq.handler = zevio_timer_interrupt;

+ timer->clkevt_irq.dev_id = timer;

+ timer->clkevt_irq.flags = IRQF_TIMER | IRQF_IRQPOLL;

+

+ setup_irq(irqnr, &timer->clkevt_irq);

+

+ clockevents_config_and_register(&timer->clkevt,

+ clk_get_rate(timer->clk), 0x0001, 0xffff);

+ pr_info("Added %s as clockevent\n", timer->clockevent_name);

+ }

+

+ writel(CNTL_STOP_TIMER, timer->timer2 + IO_CONTROL);

+ writel(0, timer->timer2 + IO_CURRENT_VAL);

+ writel(0, timer->timer2 + IO_DIVIDER);

+ writel(CNTL_RUN_TIMER | CNTL_FOREVER | CNTL_INC,

+ timer->timer2 + IO_CONTROL);

+

+ clocksource_mmio_init(timer->timer2 + IO_CURRENT_VAL,

+ timer->clocksource_name,

+ clk_get_rate(timer->clk),

+ 200, 16,

+ clocksource_mmio_readw_up);

+

+ pr_info("Added %s as clocksource\n", timer->clocksource_name);

+

+ return 0;

+error_unmap:

+ iounmap(timer->base);

+error_free:

+ kfree(timer);

+ return ret;

+}

+

+CLOCKSOURCE_OF_DECLARE(zevio_timer, "lsi,zevio-timer", zevio_timer_add);

diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c

index 412b96c..421da85 100644

--- a/drivers/xen/manage.c

+++ b/drivers/xen/manage.c

@@ -166,9 +166,6 @@ out_resume:

dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);

- /* Make sure timer events get retriggered on all CPUs */

- clock_was_set();

-

out_thaw:

#ifdef CONFIG_PREEMPT

thaw_processes();

diff --git a/fs/timerfd.c b/fs/timerfd.c

index 32b644f..9293121 100644

--- a/fs/timerfd.c

+++ b/fs/timerfd.c

@@ -8,6 +8,7 @@

*

*/

+#include <linux/alarmtimer.h>

#include <linux/file.h>

#include <linux/poll.h>

#include <linux/init.h>

@@ -26,7 +27,10 @@

#include <linux/rcupdate.h>

struct timerfd_ctx {

- struct hrtimer tmr;

+ union {

+ struct hrtimer tmr;

+ struct alarm alarm;

+ } t;

ktime_t tintv;

ktime_t moffs;

wait_queue_head_t wqh;

@@ -41,14 +45,19 @@ struct timerfd_ctx {

static LIST_HEAD(cancel_list);

static DEFINE_SPINLOCK(cancel_lock);

+static inline bool isalarm(struct timerfd_ctx *ctx)

+{

+ return ctx->clockid == CLOCK_REALTIME_ALARM ||

+ ctx->clockid == CLOCK_BOOTTIME_ALARM;

+}

+

/*

* This gets called when the timer event triggers. We set the "expired"

* flag, but we do not re-arm the timer (in case it's necessary,

* tintv.tv64 != 0) until the timer is accessed.

*/

-static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)

+static void timerfd_triggered(struct timerfd_ctx *ctx)

{

- struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr);

unsigned long flags;

spin_lock_irqsave(&ctx->wqh.lock, flags);

@@ -56,10 +65,25 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)

ctx->ticks++;

wake_up_locked(&ctx->wqh);

spin_unlock_irqrestore(&ctx->wqh.lock, flags);

+}

+static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)

+{

+ struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx,

+ t.tmr);

+ timerfd_triggered(ctx);

return HRTIMER_NORESTART;

}

+static enum alarmtimer_restart timerfd_alarmproc(struct alarm *alarm,

+ ktime_t now)

+{

+ struct timerfd_ctx *ctx = container_of(alarm, struct timerfd_ctx,

+ t.alarm);

+ timerfd_triggered(ctx);

+ return ALARMTIMER_NORESTART;

+}

+

/*

* Called when the clock was set to cancel the timers in the cancel

* list. This will wake up processes waiting on these timers. The

@@ -107,8 +131,9 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx)

static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)

{

- if (ctx->clockid == CLOCK_REALTIME && (flags & TFD_TIMER_ABSTIME) &&

- (flags & TFD_TIMER_CANCEL_ON_SET)) {

+ if ((ctx->clockid == CLOCK_REALTIME ||

+ ctx->clockid == CLOCK_REALTIME_ALARM) &&

+ (flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {

if (!ctx->might_cancel) {

ctx->might_cancel = true;

spin_lock(&cancel_lock);

@@ -124,7 +149,11 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)

{

ktime_t remaining;

- remaining = hrtimer_expires_remaining(&ctx->tmr);

+ if (isalarm(ctx))

+ remaining = alarm_expires_remaining(&ctx->t.alarm);

+ else

+ remaining = hrtimer_expires_remaining(&ctx->t.tmr);

+

return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;

}

@@ -142,11 +171,28 @@ static int timerfd_setup(struct timerfd_ctx *ctx, int flags,

ctx->expired = 0;

ctx->ticks = 0;

ctx->tintv = timespec_to_ktime(ktmr->it_interval);

- hrtimer_init(&ctx->tmr, clockid, htmode);

- hrtimer_set_expires(&ctx->tmr, texp);

- ctx->tmr.function = timerfd_tmrproc;

+

+ if (isalarm(ctx)) {

+ alarm_init(&ctx->t.alarm,

+ ctx->clockid == CLOCK_REALTIME_ALARM ?

+ ALARM_REALTIME : ALARM_BOOTTIME,

+ timerfd_alarmproc);

+ } else {

+ hrtimer_init(&ctx->t.tmr, clockid, htmode);

+ hrtimer_set_expires(&ctx->t.tmr, texp);

+ ctx->t.tmr.function = timerfd_tmrproc;

+ }

+

if (texp.tv64 != 0) {

- hrtimer_start(&ctx->tmr, texp, htmode);

+ if (isalarm(ctx)) {

+ if (flags & TFD_TIMER_ABSTIME)

+ alarm_start(&ctx->t.ala

Show more