Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Apr 2014 18:00:07 +0000 (11:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Apr 2014 18:00:07 +0000 (11:00 -0700)
Pull timer changes from Thomas Gleixner:
 "This assorted collection provides:

   - A new timer based timer broadcast feature for systems which do not
     provide a global accessible timer device.  That allows those
     systems to put CPUs into deep idle states where the per cpu timer
     device stops.

   - A few NOHZ_FULL related improvements to the timer wheel

   - The usual updates to timer devices found in ARM SoCs

   - Small improvements and updates all over the place"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (44 commits)
  tick: Remove code duplication in tick_handle_periodic()
  tick: Fix spelling mistake in tick_handle_periodic()
  x86: hpet: Use proper destructor for delayed work
  workqueue: Provide destroy_delayed_work_on_stack()
  clocksource: CMT, MTU2, TMU and STI should depend on GENERIC_CLOCKEVENTS
  timer: Remove code redundancy while calling get_nohz_timer_target()
  hrtimer: Rearrange comments in the order struct members are declared
  timer: Use variable head instead of &work_list in __run_timers()
  clocksource: exynos_mct: silence a static checker warning
  arm: zynq: Add support for cpufreq
  arm: zynq: Don't use arm_global_timer with cpufreq
  clocksource/cadence_ttc: Overhaul clocksource frequency adjustment
  clocksource/cadence_ttc: Call clockevents_update_freq() with IRQs enabled
  clocksource: Add Kconfig entries for CMT, MTU2, TMU and STI
  sh: Remove Kconfig entries for TMU, CMT and MTU2
  ARM: shmobile: Remove CMT, TMU and STI Kconfig entries
  clocksource: armada-370-xp: Use atomic access for shared registers
  clocksource: orion: Use atomic access for shared registers
  clocksource: timer-keystone: Delete unnecessary variable
  clocksource: timer-keystone: introduce clocksource driver for Keystone
  ...

45 files changed:
Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt
Documentation/devicetree/bindings/timer/ti,keystone-timer.txt [new file with mode: 0644]
MAINTAINERS
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i-a10s.dtsi
arch/arm/boot/dts/sun5i-a13.dtsi
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/zynq-7000.dtsi
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-u300/Makefile
arch/arm/mach-u300/timer.c [deleted file]
arch/arm/mach-zynq/Kconfig
arch/arm/mach-zynq/common.c
arch/sh/Kconfig
arch/x86/kernel/hpet.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/cadence_ttc_timer.c
drivers/clocksource/exynos_mct.c
drivers/clocksource/sun4i_timer.c
drivers/clocksource/time-armada-370-xp.c
drivers/clocksource/time-orion.c
drivers/clocksource/timer-keystone.c [new file with mode: 0644]
drivers/clocksource/timer-u300.c [new file with mode: 0644]
drivers/cpuidle/cpuidle.c
fs/timerfd.c
include/linux/clockchips.h
include/linux/hrtimer.h
include/linux/sched.h
include/linux/workqueue.h
kernel/hrtimer.c
kernel/sched/core.c
kernel/time/Kconfig
kernel/time/Makefile
kernel/time/clockevents.c
kernel/time/ntp.c
kernel/time/tick-broadcast-hrtimer.c [new file with mode: 0644]
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-internal.h
kernel/time/timekeeping_debug.c
kernel/timer.c
kernel/workqueue.c

index 48aeb78..5c2e235 100644 (file)
@@ -2,7 +2,7 @@ Allwinner A1X SoCs Timer Controller
 
 Required properties:
 
-- compatible : should be "allwinner,sun4i-timer"
+- compatible : should be "allwinner,sun4i-a10-timer"
 - reg : Specifies base physical address and size of the registers.
 - interrupts : The interrupt of the first timer
 - clocks: phandle to the source clock (usually a 24 MHz fixed clock)
@@ -10,7 +10,7 @@ Required properties:
 Example:
 
 timer {
-       compatible = "allwinner,sun4i-timer";
+       compatible = "allwinner,sun4i-a10-timer";
        reg = <0x01c20c00 0x400>;
        interrupts = <22>;
        clocks = <&osc>;
diff --git a/Documentation/devicetree/bindings/timer/ti,keystone-timer.txt b/Documentation/devicetree/bindings/timer/ti,keystone-timer.txt
new file mode 100644 (file)
index 0000000..5fbe361
--- /dev/null
@@ -0,0 +1,29 @@
+* Device tree bindings for Texas instruments Keystone timer
+
+This document provides bindings for the 64-bit timer in the KeyStone
+architecture devices. The timer can be configured as a general-purpose 64-bit
+timer, dual general-purpose 32-bit timers. When configured as dual 32-bit
+timers, each half can operate in conjunction (chain mode) or independently
+(unchained mode) of each other.
+
+It is global timer is a free running up-counter and can generate interrupt
+when the counter reaches preset counter values.
+
+Documentation:
+http://www.ti.com/lit/ug/sprugv5a/sprugv5a.pdf
+
+Required properties:
+
+- compatible : should be "ti,keystone-timer".
+- reg : specifies base physical address and count of the registers.
+- interrupts : interrupt generated by the timer.
+- clocks : the clock feeding the timer clock.
+
+Example:
+
+timer@22f0000 {
+       compatible = "ti,keystone-timer";
+       reg = <0x022f0000 0x80>;
+       interrupts = <GIC_SPI 110 IRQ_TYPE_EDGE_RISING>;
+       clocks = <&clktimer15>;
+};
index 79031a5..d1f3cb3 100644 (file)
@@ -1320,6 +1320,7 @@ M:        Linus Walleij <linus.walleij@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     arch/arm/mach-u300/
+F:     drivers/clocksource/timer-u300.c
 F:     drivers/i2c/busses/i2c-stu300.c
 F:     drivers/rtc/rtc-coh901331.c
 F:     drivers/watchdog/coh901327_wdt.c
index d4d2763..2ce6122 100644 (file)
                };
 
                timer@01c20c00 {
-                       compatible = "allwinner,sun4i-timer";
+                       compatible = "allwinner,sun4i-a10-timer";
                        reg = <0x01c20c00 0x90>;
                        interrupts = <22>;
                        clocks = <&osc24M>;
index 79fd412..29dd32d 100644 (file)
                };
 
                timer@01c20c00 {
-                       compatible = "allwinner,sun4i-timer";
+                       compatible = "allwinner,sun4i-a10-timer";
                        reg = <0x01c20c00 0x90>;
                        interrupts = <22>;
                        clocks = <&osc24M>;
index c463fd7..e63bb38 100644 (file)
                };
 
                timer@01c20c00 {
-                       compatible = "allwinner,sun4i-timer";
+                       compatible = "allwinner,sun4i-a10-timer";
                        reg = <0x01c20c00 0x90>;
                        interrupts = <22>;
                        clocks = <&osc24M>;
index 5256ad9..996fff5 100644 (file)
                };
 
                timer@01c20c00 {
-                       compatible = "allwinner,sun4i-timer";
+                       compatible = "allwinner,sun4i-a10-timer";
                        reg = <0x01c20c00 0xa0>;
                        interrupts = <0 18 4>,
                                     <0 19 4>,
index 6f25cf5..dddc8ac 100644 (file)
                };
 
                timer@01c20c00 {
-                       compatible = "allwinner,sun4i-timer";
+                       compatible = "allwinner,sun4i-a10-timer";
                        reg = <0x01c20c00 0x90>;
                        interrupts = <0 22 4>,
                                     <0 23 4>,
index 8b67b19..789d0ba 100644 (file)
                        device_type = "cpu";
                        reg = <0>;
                        clocks = <&clkc 3>;
+                       operating-points = <
+                               /* kHz    uV */
+                               666667  1000000
+                               333334  1000000
+                               222223  1000000
+                       >;
                };
 
                cpu@1 {
index 05fa505..f6db7dc 100644 (file)
@@ -24,17 +24,21 @@ comment "Renesas ARM SoCs System Type"
 
 config ARCH_EMEV2
        bool "Emma Mobile EV2"
+       select SYS_SUPPORTS_EM_STI
 
 config ARCH_R7S72100
        bool "RZ/A1H (R7S72100)"
+       select SYS_SUPPORTS_SH_MTU2
 
 config ARCH_R8A7790
        bool "R-Car H2 (R8A77900)"
        select RENESAS_IRQC
+       select SYS_SUPPORTS_SH_CMT
 
 config ARCH_R8A7791
        bool "R-Car M2 (R8A77910)"
        select RENESAS_IRQC
+       select SYS_SUPPORTS_SH_CMT
 
 comment "Renesas ARM SoCs Board Type"
 
@@ -68,6 +72,8 @@ config ARCH_SH7372
        select ARM_CPU_SUSPEND if PM || CPU_IDLE
        select CPU_V7
        select SH_CLK_CPG
+       select SYS_SUPPORTS_SH_CMT
+       select SYS_SUPPORTS_SH_TMU
 
 config ARCH_SH73A0
        bool "SH-Mobile AG5 (R8A73A00)"
@@ -77,6 +83,8 @@ config ARCH_SH73A0
        select I2C
        select SH_CLK_CPG
        select RENESAS_INTC_IRQPIN
+       select SYS_SUPPORTS_SH_CMT
+       select SYS_SUPPORTS_SH_TMU
 
 config ARCH_R8A73A4
        bool "R-Mobile APE6 (R8A73A40)"
@@ -87,6 +95,8 @@ config ARCH_R8A73A4
        select RENESAS_IRQC
        select ARCH_HAS_CPUFREQ
        select ARCH_HAS_OPP
+       select SYS_SUPPORTS_SH_CMT
+       select SYS_SUPPORTS_SH_TMU
 
 config ARCH_R8A7740
        bool "R-Mobile A1 (R8A77400)"
@@ -95,6 +105,8 @@ config ARCH_R8A7740
        select CPU_V7
        select SH_CLK_CPG
        select RENESAS_INTC_IRQPIN
+       select SYS_SUPPORTS_SH_CMT
+       select SYS_SUPPORTS_SH_TMU
 
 config ARCH_R8A7778
        bool "R-Car M1A (R8A77781)"
@@ -104,6 +116,7 @@ config ARCH_R8A7778
        select ARM_GIC
        select USB_ARCH_HAS_EHCI
        select USB_ARCH_HAS_OHCI
+       select SYS_SUPPORTS_SH_TMU
 
 config ARCH_R8A7779
        bool "R-Car H1 (R8A77790)"
@@ -114,6 +127,7 @@ config ARCH_R8A7779
        select USB_ARCH_HAS_EHCI
        select USB_ARCH_HAS_OHCI
        select RENESAS_INTC_IRQPIN
+       select SYS_SUPPORTS_SH_TMU
 
 config ARCH_R8A7790
        bool "R-Car H2 (R8A77900)"
@@ -123,6 +137,7 @@ config ARCH_R8A7790
        select MIGHT_HAVE_PCI
        select SH_CLK_CPG
        select RENESAS_IRQC
+       select SYS_SUPPORTS_SH_CMT
 
 config ARCH_R8A7791
        bool "R-Car M2 (R8A77910)"
@@ -132,6 +147,7 @@ config ARCH_R8A7791
        select MIGHT_HAVE_PCI
        select SH_CLK_CPG
        select RENESAS_IRQC
+       select SYS_SUPPORTS_SH_CMT
 
 config ARCH_EMEV2
        bool "Emma Mobile EV2"
@@ -141,6 +157,7 @@ config ARCH_EMEV2
        select MIGHT_HAVE_PCI
        select USE_OF
        select AUTO_ZRELADDR
+       select SYS_SUPPORTS_EM_STI
 
 config ARCH_R7S72100
        bool "RZ/A1H (R7S72100)"
@@ -148,6 +165,7 @@ config ARCH_R7S72100
        select ARM_GIC
        select CPU_V7
        select SH_CLK_CPG
+       select SYS_SUPPORTS_SH_MTU2
 
 comment "Renesas ARM SoCs Board Type"
 
@@ -321,24 +339,6 @@ config SHMOBILE_TIMER_HZ
          want to select a HZ value such as 128 that can evenly divide RCLK.
          A HZ value that does not divide evenly may cause timer drift.
 
-config SH_TIMER_CMT
-       bool "CMT timer driver"
-       default y
-       help
-         This enables build of the CMT timer driver.
-
-config SH_TIMER_TMU
-       bool "TMU timer driver"
-       default y
-       help
-         This enables build of the TMU timer driver.
-
-config EM_TIMER_STI
-       bool "STI timer driver"
-       default y
-       help
-         This enables build of the STI timer driver.
-
 endmenu
 
 endif
index 0f362b6..3ec74ac 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel, U300 machine.
 #
 
-obj-y          := core.o timer.o
+obj-y          := core.o
 obj-m          :=
 obj-n          :=
 obj-           :=
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
deleted file mode 100644 (file)
index fe08fd3..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/timer.c
- *
- *
- * Copyright (C) 2007-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * Timer COH 901 328, runs the OS timer interrupt.
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/clockchips.h>
-#include <linux/clocksource.h>
-#include <linux/types.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/sched_clock.h>
-
-/* Generic stuff */
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-
-/*
- * APP side special timer registers
- * This timer contains four timers which can fire an interrupt each.
- * OS (operating system) timer @ 32768 Hz
- * DD (device driver) timer @ 1 kHz
- * GP1 (general purpose 1) timer @ 1MHz
- * GP2 (general purpose 2) timer @ 1MHz
- */
-
-/* Reset OS Timer 32bit (-/W) */
-#define U300_TIMER_APP_ROST                                    (0x0000)
-#define U300_TIMER_APP_ROST_TIMER_RESET                                (0x00000000)
-/* Enable OS Timer 32bit (-/W) */
-#define U300_TIMER_APP_EOST                                    (0x0004)
-#define U300_TIMER_APP_EOST_TIMER_ENABLE                       (0x00000000)
-/* Disable OS Timer 32bit (-/W) */
-#define U300_TIMER_APP_DOST                                    (0x0008)
-#define U300_TIMER_APP_DOST_TIMER_DISABLE                      (0x00000000)
-/* OS Timer Mode Register 32bit (-/W) */
-#define U300_TIMER_APP_SOSTM                                   (0x000c)
-#define U300_TIMER_APP_SOSTM_MODE_CONTINUOUS                   (0x00000000)
-#define U300_TIMER_APP_SOSTM_MODE_ONE_SHOT                     (0x00000001)
-/* OS Timer Status Register 32bit (R/-) */
-#define U300_TIMER_APP_OSTS                                    (0x0010)
-#define U300_TIMER_APP_OSTS_TIMER_STATE_MASK                   (0x0000000F)
-#define U300_TIMER_APP_OSTS_TIMER_STATE_IDLE                   (0x00000001)
-#define U300_TIMER_APP_OSTS_TIMER_STATE_ACTIVE                 (0x00000002)
-#define U300_TIMER_APP_OSTS_ENABLE_IND                         (0x00000010)
-#define U300_TIMER_APP_OSTS_MODE_MASK                          (0x00000020)
-#define U300_TIMER_APP_OSTS_MODE_CONTINUOUS                    (0x00000000)
-#define U300_TIMER_APP_OSTS_MODE_ONE_SHOT                      (0x00000020)
-#define U300_TIMER_APP_OSTS_IRQ_ENABLED_IND                    (0x00000040)
-#define U300_TIMER_APP_OSTS_IRQ_PENDING_IND                    (0x00000080)
-/* OS Timer Current Count Register 32bit (R/-) */
-#define U300_TIMER_APP_OSTCC                                   (0x0014)
-/* OS Timer Terminal Count Register 32bit (R/W) */
-#define U300_TIMER_APP_OSTTC                                   (0x0018)
-/* OS Timer Interrupt Enable Register 32bit (-/W) */
-#define U300_TIMER_APP_OSTIE                                   (0x001c)
-#define U300_TIMER_APP_OSTIE_IRQ_DISABLE                       (0x00000000)
-#define U300_TIMER_APP_OSTIE_IRQ_ENABLE                                (0x00000001)
-/* OS Timer Interrupt Acknowledge Register 32bit (-/W) */
-#define U300_TIMER_APP_OSTIA                                   (0x0020)
-#define U300_TIMER_APP_OSTIA_IRQ_ACK                           (0x00000080)
-
-/* Reset DD Timer 32bit (-/W) */
-#define U300_TIMER_APP_RDDT                                    (0x0040)
-#define U300_TIMER_APP_RDDT_TIMER_RESET                                (0x00000000)
-/* Enable DD Timer 32bit (-/W) */
-#define U300_TIMER_APP_EDDT                                    (0x0044)
-#define U300_TIMER_APP_EDDT_TIMER_ENABLE                       (0x00000000)
-/* Disable DD Timer 32bit (-/W) */
-#define U300_TIMER_APP_DDDT                                    (0x0048)
-#define U300_TIMER_APP_DDDT_TIMER_DISABLE                      (0x00000000)
-/* DD Timer Mode Register 32bit (-/W) */
-#define U300_TIMER_APP_SDDTM                                   (0x004c)
-#define U300_TIMER_APP_SDDTM_MODE_CONTINUOUS                   (0x00000000)
-#define U300_TIMER_APP_SDDTM_MODE_ONE_SHOT                     (0x00000001)
-/* DD Timer Status Register 32bit (R/-) */
-#define U300_TIMER_APP_DDTS                                    (0x0050)
-#define U300_TIMER_APP_DDTS_TIMER_STATE_MASK                   (0x0000000F)
-#define U300_TIMER_APP_DDTS_TIMER_STATE_IDLE                   (0x00000001)
-#define U300_TIMER_APP_DDTS_TIMER_STATE_ACTIVE                 (0x00000002)
-#define U300_TIMER_APP_DDTS_ENABLE_IND                         (0x00000010)
-#define U300_TIMER_APP_DDTS_MODE_MASK                          (0x00000020)
-#define U300_TIMER_APP_DDTS_MODE_CONTINUOUS                    (0x00000000)
-#define U300_TIMER_APP_DDTS_MODE_ONE_SHOT                      (0x00000020)
-#define U300_TIMER_APP_DDTS_IRQ_ENABLED_IND                    (0x00000040)
-#define U300_TIMER_APP_DDTS_IRQ_PENDING_IND                    (0x00000080)
-/* DD Timer Current Count Register 32bit (R/-) */
-#define U300_TIMER_APP_DDTCC                                   (0x0054)
-/* DD Timer Terminal Count Register 32bit (R/W) */
-#define U300_TIMER_APP_DDTTC                                   (0x0058)
-/* DD Timer Interrupt Enable Register 32bit (-/W) */
-#define U300_TIMER_APP_DDTIE                                   (0x005c)
-#define U300_TIMER_APP_DDTIE_IRQ_DISABLE                       (0x00000000)
-#define U300_TIMER_APP_DDTIE_IRQ_ENABLE                                (0x00000001)
-/* DD Timer Interrupt Acknowledge Register 32bit (-/W) */
-#define U300_TIMER_APP_DDTIA                                   (0x0060)
-#define U300_TIMER_APP_DDTIA_IRQ_ACK                           (0x00000080)
-
-/* Reset GP1 Timer 32bit (-/W) */
-#define U300_TIMER_APP_RGPT1                                   (0x0080)
-#define U300_TIMER_APP_RGPT1_TIMER_RESET                       (0x00000000)
-/* Enable GP1 Timer 32bit (-/W) */
-#define U300_TIMER_APP_EGPT1                                   (0x0084)
-#define U300_TIMER_APP_EGPT1_TIMER_ENABLE                      (0x00000000)
-/* Disable GP1 Timer 32bit (-/W) */
-#define U300_TIMER_APP_DGPT1                                   (0x0088)
-#define U300_TIMER_APP_DGPT1_TIMER_DISABLE                     (0x00000000)
-/* GP1 Timer Mode Register 32bit (-/W) */
-#define U300_TIMER_APP_SGPT1M                                  (0x008c)
-#define U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS                  (0x00000000)
-#define U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT                    (0x00000001)
-/* GP1 Timer Status Register 32bit (R/-) */
-#define U300_TIMER_APP_GPT1S                                   (0x0090)
-#define U300_TIMER_APP_GPT1S_TIMER_STATE_MASK                  (0x0000000F)
-#define U300_TIMER_APP_GPT1S_TIMER_STATE_IDLE                  (0x00000001)
-#define U300_TIMER_APP_GPT1S_TIMER_STATE_ACTIVE                        (0x00000002)
-#define U300_TIMER_APP_GPT1S_ENABLE_IND                                (0x00000010)
-#define U300_TIMER_APP_GPT1S_MODE_MASK                         (0x00000020)
-#define U300_TIMER_APP_GPT1S_MODE_CONTINUOUS                   (0x00000000)
-#define U300_TIMER_APP_GPT1S_MODE_ONE_SHOT                     (0x00000020)
-#define U300_TIMER_APP_GPT1S_IRQ_ENABLED_IND                   (0x00000040)
-#define U300_TIMER_APP_GPT1S_IRQ_PENDING_IND                   (0x00000080)
-/* GP1 Timer Current Count Register 32bit (R/-) */
-#define U300_TIMER_APP_GPT1CC                                  (0x0094)
-/* GP1 Timer Terminal Count Register 32bit (R/W) */
-#define U300_TIMER_APP_GPT1TC                                  (0x0098)
-/* GP1 Timer Interrupt Enable Register 32bit (-/W) */
-#define U300_TIMER_APP_GPT1IE                                  (0x009c)
-#define U300_TIMER_APP_GPT1IE_IRQ_DISABLE                      (0x00000000)
-#define U300_TIMER_APP_GPT1IE_IRQ_ENABLE                       (0x00000001)
-/* GP1 Timer Interrupt Acknowledge Register 32bit (-/W) */
-#define U300_TIMER_APP_GPT1IA                                  (0x00a0)
-#define U300_TIMER_APP_GPT1IA_IRQ_ACK                          (0x00000080)
-
-/* Reset GP2 Timer 32bit (-/W) */
-#define U300_TIMER_APP_RGPT2                                   (0x00c0)
-#define U300_TIMER_APP_RGPT2_TIMER_RESET                       (0x00000000)
-/* Enable GP2 Timer 32bit (-/W) */
-#define U300_TIMER_APP_EGPT2                                   (0x00c4)
-#define U300_TIMER_APP_EGPT2_TIMER_ENABLE                      (0x00000000)
-/* Disable GP2 Timer 32bit (-/W) */
-#define U300_TIMER_APP_DGPT2                                   (0x00c8)
-#define U300_TIMER_APP_DGPT2_TIMER_DISABLE                     (0x00000000)
-/* GP2 Timer Mode Register 32bit (-/W) */
-#define U300_TIMER_APP_SGPT2M                                  (0x00cc)
-#define U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS                  (0x00000000)
-#define U300_TIMER_APP_SGPT2M_MODE_ONE_SHOT                    (0x00000001)
-/* GP2 Timer Status Register 32bit (R/-) */
-#define U300_TIMER_APP_GPT2S                                   (0x00d0)
-#define U300_TIMER_APP_GPT2S_TIMER_STATE_MASK                  (0x0000000F)
-#define U300_TIMER_APP_GPT2S_TIMER_STATE_IDLE                  (0x00000001)
-#define U300_TIMER_APP_GPT2S_TIMER_STATE_ACTIVE                        (0x00000002)
-#define U300_TIMER_APP_GPT2S_ENABLE_IND                                (0x00000010)
-#define U300_TIMER_APP_GPT2S_MODE_MASK                         (0x00000020)
-#define U300_TIMER_APP_GPT2S_MODE_CONTINUOUS                   (0x00000000)
-#define U300_TIMER_APP_GPT2S_MODE_ONE_SHOT                     (0x00000020)
-#define U300_TIMER_APP_GPT2S_IRQ_ENABLED_IND                   (0x00000040)
-#define U300_TIMER_APP_GPT2S_IRQ_PENDING_IND                   (0x00000080)
-/* GP2 Timer Current Count Register 32bit (R/-) */
-#define U300_TIMER_APP_GPT2CC                                  (0x00d4)
-/* GP2 Timer Terminal Count Register 32bit (R/W) */
-#define U300_TIMER_APP_GPT2TC                                  (0x00d8)
-/* GP2 Timer Interrupt Enable Register 32bit (-/W) */
-#define U300_TIMER_APP_GPT2IE                                  (0x00dc)
-#define U300_TIMER_APP_GPT2IE_IRQ_DISABLE                      (0x00000000)
-#define U300_TIMER_APP_GPT2IE_IRQ_ENABLE                       (0x00000001)
-/* GP2 Timer Interrupt Acknowledge Register 32bit (-/W) */
-#define U300_TIMER_APP_GPT2IA                                  (0x00e0)
-#define U300_TIMER_APP_GPT2IA_IRQ_ACK                          (0x00000080)
-
-/* Clock request control register - all four timers */
-#define U300_TIMER_APP_CRC                                     (0x100)
-#define U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE                        (0x00000001)
-
-static void __iomem *u300_timer_base;
-
-struct u300_clockevent_data {
-       struct clock_event_device cevd;
-       unsigned ticks_per_jiffy;
-};
-
-/*
- * The u300_set_mode() function is always called first, if we
- * have oneshot timer active, the oneshot scheduling function
- * u300_set_next_event() is called immediately after.
- */
-static void u300_set_mode(enum clock_event_mode mode,
-                         struct clock_event_device *evt)
-{
-       struct u300_clockevent_data *cevdata =
-               container_of(evt, struct u300_clockevent_data, cevd);
-
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               /* Disable interrupts on GPT1 */
-               writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
-                      u300_timer_base + U300_TIMER_APP_GPT1IE);
-               /* Disable GP1 while we're reprogramming it. */
-               writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
-                      u300_timer_base + U300_TIMER_APP_DGPT1);
-               /*
-                * Set the periodic mode to a certain number of ticks per
-                * jiffy.
-                */
-               writel(cevdata->ticks_per_jiffy,
-                      u300_timer_base + U300_TIMER_APP_GPT1TC);
-               /*
-                * Set continuous mode, so the timer keeps triggering
-                * interrupts.
-                */
-               writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS,
-                      u300_timer_base + U300_TIMER_APP_SGPT1M);
-               /* Enable timer interrupts */
-               writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
-                      u300_timer_base + U300_TIMER_APP_GPT1IE);
-               /* Then enable the OS timer again */
-               writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
-                      u300_timer_base + U300_TIMER_APP_EGPT1);
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-               /* Just break; here? */
-               /*
-                * The actual event will be programmed by the next event hook,
-                * so we just set a dummy value somewhere at the end of the
-                * universe here.
-                */
-               /* Disable interrupts on GPT1 */
-               writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
-                      u300_timer_base + U300_TIMER_APP_GPT1IE);
-               /* Disable GP1 while we're reprogramming it. */
-               writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
-                      u300_timer_base + U300_TIMER_APP_DGPT1);
-               /*
-                * Expire far in the future, u300_set_next_event() will be
-                * called soon...
-                */
-               writel(0xFFFFFFFF, u300_timer_base + U300_TIMER_APP_GPT1TC);
-               /* We run one shot per tick here! */
-               writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
-                      u300_timer_base + U300_TIMER_APP_SGPT1M);
-               /* Enable interrupts for this timer */
-               writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
-                      u300_timer_base + U300_TIMER_APP_GPT1IE);
-               /* Enable timer */
-               writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
-                      u300_timer_base + U300_TIMER_APP_EGPT1);
-               break;
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               /* Disable interrupts on GP1 */
-               writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
-                      u300_timer_base + U300_TIMER_APP_GPT1IE);
-               /* Disable GP1 */
-               writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
-                      u300_timer_base + U300_TIMER_APP_DGPT1);
-               break;
-       case CLOCK_EVT_MODE_RESUME:
-               /* Ignore this call */
-               break;
-       }
-}
-
-/*
- * The app timer in one shot mode obviously has to be reprogrammed
- * in EXACTLY this sequence to work properly. Do NOT try to e.g. replace
- * the interrupt disable + timer disable commands with a reset command,
- * it will fail miserably. Apparently (and I found this the hard way)
- * the timer is very sensitive to the instruction order, though you don't
- * get that impression from the data sheet.
- */
-static int u300_set_next_event(unsigned long cycles,
-                              struct clock_event_device *evt)
-
-{
-       /* Disable interrupts on GPT1 */
-       writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
-              u300_timer_base + U300_TIMER_APP_GPT1IE);
-       /* Disable GP1 while we're reprogramming it. */
-       writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
-              u300_timer_base + U300_TIMER_APP_DGPT1);
-       /* Reset the General Purpose timer 1. */
-       writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
-              u300_timer_base + U300_TIMER_APP_RGPT1);
-       /* IRQ in n * cycles */
-       writel(cycles, u300_timer_base + U300_TIMER_APP_GPT1TC);
-       /*
-        * We run one shot per tick here! (This is necessary to reconfigure,
-        * the timer will tilt if you don't!)
-        */
-       writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
-              u300_timer_base + U300_TIMER_APP_SGPT1M);
-       /* Enable timer interrupts */
-       writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
-              u300_timer_base + U300_TIMER_APP_GPT1IE);
-       /* Then enable the OS timer again */
-       writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
-              u300_timer_base + U300_TIMER_APP_EGPT1);
-       return 0;
-}
-
-static struct u300_clockevent_data u300_clockevent_data = {
-       /* Use general purpose timer 1 as clock event */
-       .cevd = {
-               .name           = "GPT1",
-               /* Reasonably fast and accurate clock event */
-               .rating         = 300,
-               .features       = CLOCK_EVT_FEAT_PERIODIC |
-                       CLOCK_EVT_FEAT_ONESHOT,
-               .set_next_event = u300_set_next_event,
-               .set_mode       = u300_set_mode,
-       },
-};
-
-/* Clock event timer interrupt handler */
-static irqreturn_t u300_timer_interrupt(int irq, void *dev_id)
-{
-       struct clock_event_device *evt = &u300_clockevent_data.cevd;
-       /* ACK/Clear timer IRQ for the APP GPT1 Timer */
-
-       writel(U300_TIMER_APP_GPT1IA_IRQ_ACK,
-               u300_timer_base + U300_TIMER_APP_GPT1IA);
-       evt->event_handler(evt);
-       return IRQ_HANDLED;
-}
-
-static struct irqaction u300_timer_irq = {
-       .name           = "U300 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = u300_timer_interrupt,
-};
-
-/*
- * Override the global weak sched_clock symbol with this
- * local implementation which uses the clocksource to get some
- * better resolution when scheduling the kernel. We accept that
- * this wraps around for now, since it is just a relative time
- * stamp. (Inspired by OMAP implementation.)
- */
-
-static u64 notrace u300_read_sched_clock(void)
-{
-       return readl(u300_timer_base + U300_TIMER_APP_GPT2CC);
-}
-
-static unsigned long u300_read_current_timer(void)
-{
-       return readl(u300_timer_base + U300_TIMER_APP_GPT2CC);
-}
-
-static struct delay_timer u300_delay_timer;
-
-/*
- * This sets up the system timers, clock source and clock event.
- */
-static void __init u300_timer_init_of(struct device_node *np)
-{
-       unsigned int irq;
-       struct clk *clk;
-       unsigned long rate;
-
-       u300_timer_base = of_iomap(np, 0);
-       if (!u300_timer_base)
-               panic("could not ioremap system timer\n");
-
-       /* Get the IRQ for the GP1 timer */
-       irq = irq_of_parse_and_map(np, 2);
-       if (!irq)
-               panic("no IRQ for system timer\n");
-
-       pr_info("U300 GP1 timer @ base: %p, IRQ: %u\n", u300_timer_base, irq);
-
-       /* Clock the interrupt controller */
-       clk = of_clk_get(np, 0);
-       BUG_ON(IS_ERR(clk));
-       clk_prepare_enable(clk);
-       rate = clk_get_rate(clk);
-
-       u300_clockevent_data.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
-
-       sched_clock_register(u300_read_sched_clock, 32, rate);
-
-       u300_delay_timer.read_current_timer = &u300_read_current_timer;
-       u300_delay_timer.freq = rate;
-       register_current_timer_delay(&u300_delay_timer);
-
-       /*
-        * Disable the "OS" and "DD" timers - these are designed for Symbian!
-        * Example usage in cnh1601578 cpu subsystem pd_timer_app.c
-        */
-       writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE,
-               u300_timer_base + U300_TIMER_APP_CRC);
-       writel(U300_TIMER_APP_ROST_TIMER_RESET,
-               u300_timer_base + U300_TIMER_APP_ROST);
-       writel(U300_TIMER_APP_DOST_TIMER_DISABLE,
-               u300_timer_base + U300_TIMER_APP_DOST);
-       writel(U300_TIMER_APP_RDDT_TIMER_RESET,
-               u300_timer_base + U300_TIMER_APP_RDDT);
-       writel(U300_TIMER_APP_DDDT_TIMER_DISABLE,
-               u300_timer_base + U300_TIMER_APP_DDDT);
-
-       /* Reset the General Purpose timer 1. */
-       writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
-               u300_timer_base + U300_TIMER_APP_RGPT1);
-
-       /* Set up the IRQ handler */
-       setup_irq(irq, &u300_timer_irq);
-
-       /* Reset the General Purpose timer 2 */
-       writel(U300_TIMER_APP_RGPT2_TIMER_RESET,
-               u300_timer_base + U300_TIMER_APP_RGPT2);
-       /* Set this timer to run around forever */
-       writel(0xFFFFFFFFU, u300_timer_base + U300_TIMER_APP_GPT2TC);
-       /* Set continuous mode so it wraps around */
-       writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS,
-              u300_timer_base + U300_TIMER_APP_SGPT2M);
-       /* Disable timer interrupts */
-       writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE,
-               u300_timer_base + U300_TIMER_APP_GPT2IE);
-       /* Then enable the GP2 timer to use as a free running us counter */
-       writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
-               u300_timer_base + U300_TIMER_APP_EGPT2);
-
-       /* Use general purpose timer 2 as clock source */
-       if (clocksource_mmio_init(u300_timer_base + U300_TIMER_APP_GPT2CC,
-                       "GPT2", rate, 300, 32, clocksource_mmio_readl_up))
-               pr_err("timer: failed to initialize U300 clock source\n");
-
-       /* Configure and register the clockevent */
-       clockevents_config_and_register(&u300_clockevent_data.cevd, rate,
-                                       1, 0xffffffff);
-
-       /*
-        * TODO: init and register the rest of the timers too, they can be
-        * used by hrtimers!
-        */
-}
-
-CLOCKSOURCE_OF_DECLARE(u300_timer, "stericsson,u300-apptimer",
-                      u300_timer_init_of);
index 6b04260..f03e75b 100644 (file)
@@ -2,6 +2,8 @@ config ARCH_ZYNQ
        bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7
        select ARM_AMBA
        select ARM_GIC
+       select ARCH_HAS_CPUFREQ
+       select ARCH_HAS_OPP
        select COMMON_CLK
        select CPU_V7
        select GENERIC_CLOCKEVENTS
@@ -13,6 +15,6 @@ config ARCH_ZYNQ
        select HAVE_SMP
        select SPARSE_IRQ
        select CADENCE_TTC_TIMER
-       select ARM_GLOBAL_TIMER
+       select ARM_GLOBAL_TIMER if !CPU_FREQ
        help
          Support for Xilinx Zynq ARM Cortex A9 Platform
index 8c09a83..a39be8e 100644 (file)
@@ -64,6 +64,8 @@ static struct platform_device zynq_cpuidle_device = {
  */
 static void __init zynq_init_machine(void)
 {
+       struct platform_device_info devinfo = { .name = "cpufreq-cpu0", };
+
        /*
         * 64KB way size, 8-way associativity, parity disabled
         */
@@ -72,6 +74,7 @@ static void __init zynq_init_machine(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
        platform_device_register(&zynq_cpuidle_device);
+       platform_device_register_full(&devinfo);
 }
 
 static void __init zynq_timer_init(void)
index 6357710..364d204 100644 (file)
@@ -123,15 +123,6 @@ config SYS_SUPPORTS_NUMA
 config SYS_SUPPORTS_PCI
        bool
 
-config SYS_SUPPORTS_CMT
-       bool
-
-config SYS_SUPPORTS_MTU2
-       bool
-
-config SYS_SUPPORTS_TMU
-       bool
-
 config STACKTRACE_SUPPORT
        def_bool y
 
@@ -191,14 +182,14 @@ config CPU_SH3
        bool
        select CPU_HAS_INTEVT
        select CPU_HAS_SR_RB
-       select SYS_SUPPORTS_TMU
+       select SYS_SUPPORTS_SH_TMU
 
 config CPU_SH4
        bool
        select CPU_HAS_INTEVT
        select CPU_HAS_SR_RB
        select CPU_HAS_FPU if !CPU_SH4AL_DSP
-       select SYS_SUPPORTS_TMU
+       select SYS_SUPPORTS_SH_TMU
        select SYS_SUPPORTS_HUGETLBFS if MMU
 
 config CPU_SH4A
@@ -213,7 +204,7 @@ config CPU_SH4AL_DSP
 config CPU_SH5
        bool
        select CPU_HAS_FPU
-       select SYS_SUPPORTS_TMU
+       select SYS_SUPPORTS_SH_TMU
        select SYS_SUPPORTS_HUGETLBFS if MMU
 
 config CPU_SHX2
@@ -250,7 +241,7 @@ choice
 config CPU_SUBTYPE_SH7619
        bool "Support SH7619 processor"
        select CPU_SH2
-       select SYS_SUPPORTS_CMT
+       select SYS_SUPPORTS_SH_CMT
 
 # SH-2A Processor Support
 
@@ -258,50 +249,50 @@ config CPU_SUBTYPE_SH7201
        bool "Support SH7201 processor"
        select CPU_SH2A
        select CPU_HAS_FPU
-       select SYS_SUPPORTS_MTU2
+       select SYS_SUPPORTS_SH_MTU2
  
 config CPU_SUBTYPE_SH7203
        bool "Support SH7203 processor"
        select CPU_SH2A
        select CPU_HAS_FPU
-       select SYS_SUPPORTS_CMT
-       select SYS_SUPPORTS_MTU2
+       select SYS_SUPPORTS_SH_CMT
+       select SYS_SUPPORTS_SH_MTU2
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select PINCTRL
 
 config CPU_SUBTYPE_SH7206
        bool "Support SH7206 processor"
        select CPU_SH2A
-       select SYS_SUPPORTS_CMT
-       select SYS_SUPPORTS_MTU2
+       select SYS_SUPPORTS_SH_CMT
+       select SYS_SUPPORTS_SH_MTU2
 
 config CPU_SUBTYPE_SH7263
        bool "Support SH7263 processor"
        select CPU_SH2A
        select CPU_HAS_FPU
-       select SYS_SUPPORTS_CMT
-       select SYS_SUPPORTS_MTU2
+       select SYS_SUPPORTS_SH_CMT
+       select SYS_SUPPORTS_SH_MTU2
 
 config CPU_SUBTYPE_SH7264
        bool "Support SH7264 processor"
        select CPU_SH2A
        select CPU_HAS_FPU
-       select SYS_SUPPORTS_CMT
-       select SYS_SUPPORTS_MTU2
+       select SYS_SUPPORTS_SH_CMT
+       select SYS_SUPPORTS_SH_MTU2
        select PINCTRL
 
 config CPU_SUBTYPE_SH7269
        bool "Support SH7269 processor"
        select CPU_SH2A
        select CPU_HAS_FPU
-       select SYS_SUPPORTS_CMT
-       select SYS_SUPPORTS_MTU2
+       select SYS_SUPPORTS_SH_CMT
+       select SYS_SUPPORTS_SH_MTU2
        select PINCTRL
 
 config CPU_SUBTYPE_MXG
        bool "Support MX-G processor"
        select CPU_SH2A
-       select SYS_SUPPORTS_MTU2
+       select SYS_SUPPORTS_SH_MTU2
        help
          Select MX-G if running on an R8A03022BG part.
 
@@ -354,7 +345,7 @@ config CPU_SUBTYPE_SH7720
        bool "Support SH7720 processor"
        select CPU_SH3
        select CPU_HAS_DSP
-       select SYS_SUPPORTS_CMT
+       select SYS_SUPPORTS_SH_CMT
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select USB_ARCH_HAS_OHCI
        select USB_OHCI_SH if USB_OHCI_HCD
@@ -366,7 +357,7 @@ config CPU_SUBTYPE_SH7721
        bool "Support SH7721 processor"
        select CPU_SH3
        select CPU_HAS_DSP
-       select SYS_SUPPORTS_CMT
+       select SYS_SUPPORTS_SH_CMT
        select USB_ARCH_HAS_OHCI
        select USB_OHCI_SH if USB_OHCI_HCD
        help
@@ -422,7 +413,7 @@ config CPU_SUBTYPE_SH7723
        select CPU_SHX2
        select ARCH_SHMOBILE
        select ARCH_SPARSEMEM_ENABLE
-       select SYS_SUPPORTS_CMT
+       select SYS_SUPPORTS_SH_CMT
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select PINCTRL
        help
@@ -434,7 +425,7 @@ config CPU_SUBTYPE_SH7724
        select CPU_SHX2
        select ARCH_SHMOBILE
        select ARCH_SPARSEMEM_ENABLE
-       select SYS_SUPPORTS_CMT
+       select SYS_SUPPORTS_SH_CMT
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select PINCTRL
        help
@@ -514,7 +505,7 @@ config CPU_SUBTYPE_SH7343
        bool "Support SH7343 processor"
        select CPU_SH4AL_DSP
        select ARCH_SHMOBILE
-       select SYS_SUPPORTS_CMT
+       select SYS_SUPPORTS_SH_CMT
 
 config CPU_SUBTYPE_SH7722
        bool "Support SH7722 processor"
@@ -523,7 +514,7 @@ config CPU_SUBTYPE_SH7722
        select ARCH_SHMOBILE
        select ARCH_SPARSEMEM_ENABLE
        select SYS_SUPPORTS_NUMA
-       select SYS_SUPPORTS_CMT
+       select SYS_SUPPORTS_SH_CMT
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select PINCTRL
 
@@ -534,7 +525,7 @@ config CPU_SUBTYPE_SH7366
        select ARCH_SHMOBILE
        select ARCH_SPARSEMEM_ENABLE
        select SYS_SUPPORTS_NUMA
-       select SYS_SUPPORTS_CMT
+       select SYS_SUPPORTS_SH_CMT
 
 endchoice
 
@@ -567,27 +558,6 @@ source "arch/sh/boards/Kconfig"
 
 menu "Timer and clock configuration"
 
-config SH_TIMER_TMU
-       bool "TMU timer driver"
-       depends on SYS_SUPPORTS_TMU
-       default y
-       help
-         This enables the build of the TMU timer driver.
-
-config SH_TIMER_CMT
-       bool "CMT timer driver"
-       depends on SYS_SUPPORTS_CMT
-       default y
-       help
-         This enables build of the CMT timer driver.
-
-config SH_TIMER_MTU2
-       bool "MTU2 timer driver"
-       depends on SYS_SUPPORTS_MTU2
-       default y
-       help
-         This enables build of the MTU2 timer driver.
-
 config SH_PCLK_FREQ
        int "Peripheral clock frequency (in Hz)"
        depends on SH_CLK_CPG_LEGACY
index da85a8e..b91abfd 100644 (file)
@@ -699,7 +699,7 @@ static int hpet_cpuhp_notify(struct notifier_block *n,
                /* FIXME: add schedule_work_on() */
                schedule_delayed_work_on(cpu, &work.work, 0);
                wait_for_completion(&work.complete);
-               destroy_timer_on_stack(&work.work.timer);
+               destroy_delayed_work_on_stack(&work.work);
                break;
        case CPU_DEAD:
                if (hdev) {
index cd6950f..52e9329 100644 (file)
@@ -140,3 +140,51 @@ config VF_PIT_TIMER
        bool
        help
          Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
+
+config SYS_SUPPORTS_SH_CMT
+        bool
+
+config SYS_SUPPORTS_SH_MTU2
+        bool
+
+config SYS_SUPPORTS_SH_TMU
+        bool
+
+config SYS_SUPPORTS_EM_STI
+        bool
+
+config SH_TIMER_CMT
+       bool "Renesas CMT timer driver" if COMPILE_TEST
+       depends on GENERIC_CLOCKEVENTS
+       default SYS_SUPPORTS_SH_CMT
+       help
+         This enables build of a clocksource and clockevent driver for
+         the Compare Match Timer (CMT) hardware available in 16/32/48-bit
+         variants on a wide range of Mobile and Automotive SoCs from Renesas.
+
+config SH_TIMER_MTU2
+       bool "Renesas MTU2 timer driver" if COMPILE_TEST
+       depends on GENERIC_CLOCKEVENTS
+       default SYS_SUPPORTS_SH_MTU2
+       help
+         This enables build of a clockevent driver for the Multi-Function
+         Timer Pulse Unit 2 (TMU2) hardware available on SoCs from Renesas.
+         This hardware comes with 16 bit-timer registers.
+
+config SH_TIMER_TMU
+       bool "Renesas TMU timer driver" if COMPILE_TEST
+       depends on GENERIC_CLOCKEVENTS
+       default SYS_SUPPORTS_SH_TMU
+       help
+         This enables build of a clocksource and clockevent driver for
+         the 32-bit Timer Unit (TMU) hardware available on a wide range
+         SoCs from Renesas.
+
+config EM_TIMER_STI
+       bool "Renesas STI timer driver" if COMPILE_TEST
+       depends on GENERIC_CLOCKEVENTS
+       default SYS_SUPPORTS_EM_STI
+       help
+         This enables build of a clocksource and clockevent driver for
+         the 48-bit System Timer (STI) hardware available on a SoCs
+         such as EMEV2 from former NEC Electronics.
index c7ca50a..aed3488 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_ARCH_MARCO)      += timer-marco.o
 obj-$(CONFIG_ARCH_MOXART)      += moxart_timer.o
 obj-$(CONFIG_ARCH_MXS)         += mxs_timer.o
 obj-$(CONFIG_ARCH_PRIMA2)      += timer-prima2.o
+obj-$(CONFIG_ARCH_U300)                += timer-u300.o
 obj-$(CONFIG_SUN4I_TIMER)      += sun4i_timer.o
 obj-$(CONFIG_SUN5I_HSTIMER)    += timer-sun5i.o
 obj-$(CONFIG_ARCH_TEGRA)       += tegra20_timer.o
@@ -37,3 +38,4 @@ obj-$(CONFIG_ARM_ARCH_TIMER)          += arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)         += arm_global_timer.o
 obj-$(CONFIG_CLKSRC_METAG_GENERIC)     += metag_generic.o
 obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST)  += dummy_timer.o
+obj-$(CONFIG_ARCH_KEYSTONE)            += timer-keystone.o
index 95fb944..57e823c 100644 (file)
@@ -277,6 +277,7 @@ static void __arch_timer_setup(unsigned type,
                        clk->set_next_event = arch_timer_set_next_event_phys;
                }
        } else {
+               clk->features |= CLOCK_EVT_FEAT_DYNIRQ;
                clk->name = "arch_mem_timer";
                clk->rating = 400;
                clk->cpumask = cpu_all_mask;
index 63f176d..49fbe28 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/interrupt.h>
 #include <linux/clockchips.h>
 #include <linux/of_address.h>
@@ -52,6 +53,8 @@
 #define TTC_CNT_CNTRL_DISABLE_MASK     0x1
 
 #define TTC_CLK_CNTRL_CSRC_MASK                (1 << 5)        /* clock source */
+#define TTC_CLK_CNTRL_PSV_MASK         0x1e
+#define TTC_CLK_CNTRL_PSV_SHIFT                1
 
 /*
  * Setup the timers to use pre-scaling, using a fixed value for now that will
@@ -63,6 +66,8 @@
 #define CLK_CNTRL_PRESCALE_EN  1
 #define CNT_CNTRL_RESET                (1 << 4)
 
+#define MAX_F_ERR 50
+
 /**
  * struct ttc_timer - This definition defines local timer structure
  *
@@ -82,6 +87,8 @@ struct ttc_timer {
                container_of(x, struct ttc_timer, clk_rate_change_nb)
 
 struct ttc_timer_clocksource {
+       u32                     scale_clk_ctrl_reg_old;
+       u32                     scale_clk_ctrl_reg_new;
        struct ttc_timer        ttc;
        struct clocksource      cs;
 };
@@ -229,32 +236,89 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb,
                        struct ttc_timer_clocksource, ttc);
 
        switch (event) {
-       case POST_RATE_CHANGE:
+       case PRE_RATE_CHANGE:
+       {
+               u32 psv;
+               unsigned long factor, rate_low, rate_high;
+
+               if (ndata->new_rate > ndata->old_rate) {
+                       factor = DIV_ROUND_CLOSEST(ndata->new_rate,
+                                       ndata->old_rate);
+                       rate_low = ndata->old_rate;
+                       rate_high = ndata->new_rate;
+               } else {
+                       factor = DIV_ROUND_CLOSEST(ndata->old_rate,
+                                       ndata->new_rate);
+                       rate_low = ndata->new_rate;
+                       rate_high = ndata->old_rate;
+               }
+
+               if (!is_power_of_2(factor))
+                               return NOTIFY_BAD;
+
+               if (abs(rate_high - (factor * rate_low)) > MAX_F_ERR)
+                       return NOTIFY_BAD;
+
+               factor = __ilog2_u32(factor);
+
                /*
-                * Do whatever is necessary to maintain a proper time base
-                *
-                * I cannot find a way to adjust the currently used clocksource
-                * to the new frequency. __clocksource_updatefreq_hz() sounds
-                * good, but does not work. Not sure what's that missing.
-                *
-                * This approach works, but triggers two clocksource switches.
-                * The first after unregister to clocksource jiffies. And
-                * another one after the register to the newly registered timer.
-                *
-                * Alternatively we could 'waste' another HW timer to ping pong
-                * between clock sources. That would also use one register and
-                * one unregister call, but only trigger one clocksource switch
-                * for the cost of another HW timer used by the OS.
+                * store timer clock ctrl register so we can restore it in case
+                * of an abort.
                 */
-               clocksource_unregister(&ttccs->cs);
-               clocksource_register_hz(&ttccs->cs,
-                               ndata->new_rate / PRESCALE);
-               /* fall through */
-       case PRE_RATE_CHANGE:
+               ttccs->scale_clk_ctrl_reg_old =
+                       __raw_readl(ttccs->ttc.base_addr +
+                                       TTC_CLK_CNTRL_OFFSET);
+
+               psv = (ttccs->scale_clk_ctrl_reg_old &
+                               TTC_CLK_CNTRL_PSV_MASK) >>
+                               TTC_CLK_CNTRL_PSV_SHIFT;
+               if (ndata->new_rate < ndata->old_rate)
+                       psv -= factor;
+               else
+                       psv += factor;
+
+               /* prescaler within legal range? */
+               if (psv & ~(TTC_CLK_CNTRL_PSV_MASK >> TTC_CLK_CNTRL_PSV_SHIFT))
+                       return NOTIFY_BAD;
+
+               ttccs->scale_clk_ctrl_reg_new = ttccs->scale_clk_ctrl_reg_old &
+                       ~TTC_CLK_CNTRL_PSV_MASK;
+               ttccs->scale_clk_ctrl_reg_new |= psv << TTC_CLK_CNTRL_PSV_SHIFT;
+
+
+               /* scale down: adjust divider in post-change notification */
+               if (ndata->new_rate < ndata->old_rate)
+                       return NOTIFY_DONE;
+
+               /* scale up: adjust divider now - before frequency change */
+               __raw_writel(ttccs->scale_clk_ctrl_reg_new,
+                               ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+               break;
+       }
+       case POST_RATE_CHANGE:
+               /* scale up: pre-change notification did the adjustment */
+               if (ndata->new_rate > ndata->old_rate)
+                       return NOTIFY_OK;
+
+               /* scale down: adjust divider now - after frequency change */
+               __raw_writel(ttccs->scale_clk_ctrl_reg_new,
+                               ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+               break;
+
        case ABORT_RATE_CHANGE:
+               /* we have to undo the adjustment in case we scale up */
+               if (ndata->new_rate < ndata->old_rate)
+                       return NOTIFY_OK;
+
+               /* restore original register value */
+               __raw_writel(ttccs->scale_clk_ctrl_reg_old,
+                               ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+               /* fall through */
        default:
                return NOTIFY_DONE;
        }
+
+       return NOTIFY_DONE;
 }
 
 static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
@@ -321,25 +385,12 @@ static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
 
        switch (event) {
        case POST_RATE_CHANGE:
-       {
-               unsigned long flags;
-
-               /*
-                * clockevents_update_freq should be called with IRQ disabled on
-                * the CPU the timer provides events for. The timer we use is
-                * common to both CPUs, not sure if we need to run on both
-                * cores.
-                */
-               local_irq_save(flags);
-               clockevents_update_freq(&ttcce->ce,
-                               ndata->new_rate / PRESCALE);
-               local_irq_restore(flags);
-
                /* update cached frequency */
                ttc->freq = ndata->new_rate;
 
+               clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE);
+
                /* fall through */
-       }
        case PRE_RATE_CHANGE:
        case ABORT_RATE_CHANGE:
        default:
index 48f76bc..c2e390e 100644 (file)
@@ -410,7 +410,7 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt)
        mevt = container_of(evt, struct mct_clock_event_device, evt);
 
        mevt->base = EXYNOS4_MCT_L_BASE(cpu);
-       sprintf(mevt->name, "mct_tick%d", cpu);
+       snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu);
 
        evt->name = mevt->name;
        evt->cpumask = cpumask_of(cpu);
index bf497af..efb17c3 100644 (file)
@@ -196,5 +196,5 @@ static void __init sun4i_timer_init(struct device_node *node)
        clockevents_config_and_register(&sun4i_clockevent, rate,
                                        TIMER_SYNC_TICKS, 0xffffffff);
 }
-CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer",
+CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer",
                       sun4i_timer_init);
index ee8691b..0451e62 100644 (file)
@@ -85,12 +85,6 @@ static u32 ticks_per_jiffy;
 
 static struct clock_event_device __percpu *armada_370_xp_evt;
 
-static void timer_ctrl_clrset(u32 clr, u32 set)
-{
-       writel((readl(timer_base + TIMER_CTRL_OFF) & ~clr) | set,
-               timer_base + TIMER_CTRL_OFF);
-}
-
 static void local_timer_ctrl_clrset(u32 clr, u32 set)
 {
        writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set,
@@ -245,7 +239,7 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
                clr = TIMER0_25MHZ;
                enable_mask = TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT);
        }
-       timer_ctrl_clrset(clr, set);
+       atomic_io_modify(timer_base + TIMER_CTRL_OFF, clr | set, set);
        local_timer_ctrl_clrset(clr, set);
 
        /*
@@ -263,7 +257,9 @@ static void __init armada_370_xp_timer_common_init(struct device_node *np)
        writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
        writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
 
-       timer_ctrl_clrset(0, TIMER0_RELOAD_EN | enable_mask);
+       atomic_io_modify(timer_base + TIMER_CTRL_OFF,
+               TIMER0_RELOAD_EN | enable_mask,
+               TIMER0_RELOAD_EN | enable_mask);
 
        /*
         * Set scale and timer for sched_clock.
index 2006622..0b3ce03 100644 (file)
 #define ORION_ONESHOT_MAX      0xfffffffe
 
 static void __iomem *timer_base;
-static DEFINE_SPINLOCK(timer_ctrl_lock);
-
-/*
- * Thread-safe access to TIMER_CTRL register
- * (shared with watchdog timer)
- */
-void orion_timer_ctrl_clrset(u32 clr, u32 set)
-{
-       spin_lock(&timer_ctrl_lock);
-       writel((readl(timer_base + TIMER_CTRL) & ~clr) | set,
-               timer_base + TIMER_CTRL);
-       spin_unlock(&timer_ctrl_lock);
-}
-EXPORT_SYMBOL(orion_timer_ctrl_clrset);
 
 /*
  * Free-running clocksource handling.
@@ -68,7 +54,8 @@ static int orion_clkevt_next_event(unsigned long delta,
 {
        /* setup and enable one-shot timer */
        writel(delta, timer_base + TIMER1_VAL);
-       orion_timer_ctrl_clrset(TIMER1_RELOAD_EN, TIMER1_EN);
+       atomic_io_modify(timer_base + TIMER_CTRL,
+               TIMER1_RELOAD_EN | TIMER1_EN, TIMER1_EN);
 
        return 0;
 }
@@ -80,10 +67,13 @@ static void orion_clkevt_mode(enum clock_event_mode mode,
                /* setup and enable periodic timer at 1/HZ intervals */
                writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD);
                writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL);
-               orion_timer_ctrl_clrset(0, TIMER1_RELOAD_EN | TIMER1_EN);
+               atomic_io_modify(timer_base + TIMER_CTRL,
+                       TIMER1_RELOAD_EN | TIMER1_EN,
+                       TIMER1_RELOAD_EN | TIMER1_EN);
        } else {
                /* disable timer */
-               orion_timer_ctrl_clrset(TIMER1_RELOAD_EN | TIMER1_EN, 0);
+               atomic_io_modify(timer_base + TIMER_CTRL,
+                       TIMER1_RELOAD_EN | TIMER1_EN, 0);
        }
 }
 
@@ -131,7 +121,9 @@ static void __init orion_timer_init(struct device_node *np)
        /* setup timer0 as free-running clocksource */
        writel(~0, timer_base + TIMER0_VAL);
        writel(~0, timer_base + TIMER0_RELOAD);
-       orion_timer_ctrl_clrset(0, TIMER0_RELOAD_EN | TIMER0_EN);
+       atomic_io_modify(timer_base + TIMER_CTRL,
+               TIMER0_RELOAD_EN | TIMER0_EN,
+               TIMER0_RELOAD_EN | TIMER0_EN);
        clocksource_mmio_init(timer_base + TIMER0_VAL, "orion_clocksource",
                              clk_get_rate(clk), 300, 32,
                              clocksource_mmio_readl_down);
diff --git a/drivers/clocksource/timer-keystone.c b/drivers/clocksource/timer-keystone.c
new file mode 100644 (file)
index 0000000..0250354
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Keystone broadcast clock-event
+ *
+ * Copyright 2013 Texas Instruments, Inc.
+ *
+ * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
+ *
+ * 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/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define TIMER_NAME                     "timer-keystone"
+
+/* Timer register offsets */
+#define TIM12                          0x10
+#define TIM34                          0x14
+#define PRD12                          0x18
+#define PRD34                          0x1c
+#define TCR                            0x20
+#define TGCR                           0x24
+#define INTCTLSTAT                     0x44
+
+/* Timer register bitfields */
+#define TCR_ENAMODE_MASK               0xC0
+#define TCR_ENAMODE_ONESHOT_MASK       0x40
+#define TCR_ENAMODE_PERIODIC_MASK      0x80
+
+#define TGCR_TIM_UNRESET_MASK          0x03
+#define INTCTLSTAT_ENINT_MASK          0x01
+
+/**
+ * struct keystone_timer: holds timer's data
+ * @base: timer memory base address
+ * @hz_period: cycles per HZ period
+ * @event_dev: event device based on timer
+ */
+static struct keystone_timer {
+       void __iomem *base;
+       unsigned long hz_period;
+       struct clock_event_device event_dev;
+} timer;
+
+static inline u32 keystone_timer_readl(unsigned long rg)
+{
+       return readl_relaxed(timer.base + rg);
+}
+
+static inline void keystone_timer_writel(u32 val, unsigned long rg)
+{
+       writel_relaxed(val, timer.base + rg);
+}
+
+/**
+ * keystone_timer_barrier: write memory barrier
+ * use explicit barrier to avoid using readl/writel non relaxed function
+ * variants, because in our case non relaxed variants hide the true places
+ * where barrier is needed.
+ */
+static inline void keystone_timer_barrier(void)
+{
+       __iowmb();
+}
+
+/**
+ * keystone_timer_config: configures timer to work in oneshot/periodic modes.
+ * @ mode: mode to configure
+ * @ period: cycles number to configure for
+ */
+static int keystone_timer_config(u64 period, enum clock_event_mode mode)
+{
+       u32 tcr;
+       u32 off;
+
+       tcr = keystone_timer_readl(TCR);
+       off = tcr & ~(TCR_ENAMODE_MASK);
+
+       /* set enable mode */
+       switch (mode) {
+       case CLOCK_EVT_MODE_ONESHOT:
+               tcr |= TCR_ENAMODE_ONESHOT_MASK;
+               break;
+       case CLOCK_EVT_MODE_PERIODIC:
+               tcr |= TCR_ENAMODE_PERIODIC_MASK;
+               break;
+       default:
+               return -1;
+       }
+
+       /* disable timer */
+       keystone_timer_writel(off, TCR);
+       /* here we have to be sure the timer has been disabled */
+       keystone_timer_barrier();
+
+       /* reset counter to zero, set new period */
+       keystone_timer_writel(0, TIM12);
+       keystone_timer_writel(0, TIM34);
+       keystone_timer_writel(period & 0xffffffff, PRD12);
+       keystone_timer_writel(period >> 32, PRD34);
+
+       /*
+        * enable timer
+        * here we have to be sure that CNTLO, CNTHI, PRDLO, PRDHI registers
+        * have been written.
+        */
+       keystone_timer_barrier();
+       keystone_timer_writel(tcr, TCR);
+       return 0;
+}
+
+static void keystone_timer_disable(void)
+{
+       u32 tcr;
+
+       tcr = keystone_timer_readl(TCR);
+
+       /* disable timer */
+       tcr &= ~(TCR_ENAMODE_MASK);
+       keystone_timer_writel(tcr, TCR);
+}
+
+static irqreturn_t keystone_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = dev_id;
+
+       evt->event_handler(evt);
+       return IRQ_HANDLED;
+}
+
+static int keystone_set_next_event(unsigned long cycles,
+                                 struct clock_event_device *evt)
+{
+       return keystone_timer_config(cycles, evt->mode);
+}
+
+static void keystone_set_mode(enum clock_event_mode mode,
+                            struct clock_event_device *evt)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               keystone_timer_config(timer.hz_period, CLOCK_EVT_MODE_PERIODIC);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_ONESHOT:
+               keystone_timer_disable();
+               break;
+       default:
+               break;
+       }
+}
+
+static void __init keystone_timer_init(struct device_node *np)
+{
+       struct clock_event_device *event_dev = &timer.event_dev;
+       unsigned long rate;
+       struct clk *clk;
+       int irq, error;
+
+       irq  = irq_of_parse_and_map(np, 0);
+       if (irq == NO_IRQ) {
+               pr_err("%s: failed to map interrupts\n", __func__);
+               return;
+       }
+
+       timer.base = of_iomap(np, 0);
+       if (!timer.base) {
+               pr_err("%s: failed to map registers\n", __func__);
+               return;
+       }
+
+       clk = of_clk_get(np, 0);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to get clock\n", __func__);
+               iounmap(timer.base);
+               return;
+       }
+
+       error = clk_prepare_enable(clk);
+       if (error) {
+               pr_err("%s: failed to enable clock\n", __func__);
+               goto err;
+       }
+
+       rate = clk_get_rate(clk);
+
+       /* disable, use internal clock source */
+       keystone_timer_writel(0, TCR);
+       /* here we have to be sure the timer has been disabled */
+       keystone_timer_barrier();
+
+       /* reset timer as 64-bit, no pre-scaler, plus features are disabled */
+       keystone_timer_writel(0, TGCR);
+
+       /* unreset timer */
+       keystone_timer_writel(TGCR_TIM_UNRESET_MASK, TGCR);
+
+       /* init counter to zero */
+       keystone_timer_writel(0, TIM12);
+       keystone_timer_writel(0, TIM34);
+
+       timer.hz_period = DIV_ROUND_UP(rate, HZ);
+
+       /* enable timer interrupts */
+       keystone_timer_writel(INTCTLSTAT_ENINT_MASK, INTCTLSTAT);
+
+       error = request_irq(irq, keystone_timer_interrupt, IRQF_TIMER,
+                           TIMER_NAME, event_dev);
+       if (error) {
+               pr_err("%s: failed to setup irq\n", __func__);
+               goto err;
+       }
+
+       /* setup clockevent */
+       event_dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+       event_dev->set_next_event = keystone_set_next_event;
+       event_dev->set_mode = keystone_set_mode;
+       event_dev->cpumask = cpu_all_mask;
+       event_dev->owner = THIS_MODULE;
+       event_dev->name = TIMER_NAME;
+       event_dev->irq = irq;
+
+       clockevents_config_and_register(event_dev, rate, 1, ULONG_MAX);
+
+       pr_info("keystone timer clock @%lu Hz\n", rate);
+       return;
+err:
+       clk_put(clk);
+       iounmap(timer.base);
+}
+
+CLOCKSOURCE_OF_DECLARE(keystone_timer, "ti,keystone-timer",
+                                       keystone_timer_init);
diff --git a/drivers/clocksource/timer-u300.c b/drivers/clocksource/timer-u300.c
new file mode 100644 (file)
index 0000000..e63d469
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Timer COH 901 328, runs the OS timer interrupt.
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+/* Generic stuff */
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+/*
+ * APP side special timer registers
+ * This timer contains four timers which can fire an interrupt each.
+ * OS (operating system) timer @ 32768 Hz
+ * DD (device driver) timer @ 1 kHz
+ * GP1 (general purpose 1) timer @ 1MHz
+ * GP2 (general purpose 2) timer @ 1MHz
+ */
+
+/* Reset OS Timer 32bit (-/W) */
+#define U300_TIMER_APP_ROST                                    (0x0000)
+#define U300_TIMER_APP_ROST_TIMER_RESET                                (0x00000000)
+/* Enable OS Timer 32bit (-/W) */
+#define U300_TIMER_APP_EOST                                    (0x0004)
+#define U300_TIMER_APP_EOST_TIMER_ENABLE                       (0x00000000)
+/* Disable OS Timer 32bit (-/W) */
+#define U300_TIMER_APP_DOST                                    (0x0008)
+#define U300_TIMER_APP_DOST_TIMER_DISABLE                      (0x00000000)
+/* OS Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SOSTM                                   (0x000c)
+#define U300_TIMER_APP_SOSTM_MODE_CONTINUOUS                   (0x00000000)
+#define U300_TIMER_APP_SOSTM_MODE_ONE_SHOT                     (0x00000001)
+/* OS Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_OSTS                                    (0x0010)
+#define U300_TIMER_APP_OSTS_TIMER_STATE_MASK                   (0x0000000F)
+#define U300_TIMER_APP_OSTS_TIMER_STATE_IDLE                   (0x00000001)
+#define U300_TIMER_APP_OSTS_TIMER_STATE_ACTIVE                 (0x00000002)
+#define U300_TIMER_APP_OSTS_ENABLE_IND                         (0x00000010)
+#define U300_TIMER_APP_OSTS_MODE_MASK                          (0x00000020)
+#define U300_TIMER_APP_OSTS_MODE_CONTINUOUS                    (0x00000000)
+#define U300_TIMER_APP_OSTS_MODE_ONE_SHOT                      (0x00000020)
+#define U300_TIMER_APP_OSTS_IRQ_ENABLED_IND                    (0x00000040)
+#define U300_TIMER_APP_OSTS_IRQ_PENDING_IND                    (0x00000080)
+/* OS Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_OSTCC                                   (0x0014)
+/* OS Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_OSTTC                                   (0x0018)
+/* OS Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_OSTIE                                   (0x001c)
+#define U300_TIMER_APP_OSTIE_IRQ_DISABLE                       (0x00000000)
+#define U300_TIMER_APP_OSTIE_IRQ_ENABLE                                (0x00000001)
+/* OS Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_OSTIA                                   (0x0020)
+#define U300_TIMER_APP_OSTIA_IRQ_ACK                           (0x00000080)
+
+/* Reset DD Timer 32bit (-/W) */
+#define U300_TIMER_APP_RDDT                                    (0x0040)
+#define U300_TIMER_APP_RDDT_TIMER_RESET                                (0x00000000)
+/* Enable DD Timer 32bit (-/W) */
+#define U300_TIMER_APP_EDDT                                    (0x0044)
+#define U300_TIMER_APP_EDDT_TIMER_ENABLE                       (0x00000000)
+/* Disable DD Timer 32bit (-/W) */
+#define U300_TIMER_APP_DDDT                                    (0x0048)
+#define U300_TIMER_APP_DDDT_TIMER_DISABLE                      (0x00000000)
+/* DD Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SDDTM                                   (0x004c)
+#define U300_TIMER_APP_SDDTM_MODE_CONTINUOUS                   (0x00000000)
+#define U300_TIMER_APP_SDDTM_MODE_ONE_SHOT                     (0x00000001)
+/* DD Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_DDTS                                    (0x0050)
+#define U300_TIMER_APP_DDTS_TIMER_STATE_MASK                   (0x0000000F)
+#define U300_TIMER_APP_DDTS_TIMER_STATE_IDLE                   (0x00000001)
+#define U300_TIMER_APP_DDTS_TIMER_STATE_ACTIVE                 (0x00000002)
+#define U300_TIMER_APP_DDTS_ENABLE_IND                         (0x00000010)
+#define U300_TIMER_APP_DDTS_MODE_MASK                          (0x00000020)
+#define U300_TIMER_APP_DDTS_MODE_CONTINUOUS                    (0x00000000)
+#define U300_TIMER_APP_DDTS_MODE_ONE_SHOT                      (0x00000020)
+#define U300_TIMER_APP_DDTS_IRQ_ENABLED_IND                    (0x00000040)
+#define U300_TIMER_APP_DDTS_IRQ_PENDING_IND                    (0x00000080)
+/* DD Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_DDTCC                                   (0x0054)
+/* DD Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_DDTTC                                   (0x0058)
+/* DD Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_DDTIE                                   (0x005c)
+#define U300_TIMER_APP_DDTIE_IRQ_DISABLE                       (0x00000000)
+#define U300_TIMER_APP_DDTIE_IRQ_ENABLE                                (0x00000001)
+/* DD Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_DDTIA                                   (0x0060)
+#define U300_TIMER_APP_DDTIA_IRQ_ACK                           (0x00000080)
+
+/* Reset GP1 Timer 32bit (-/W) */
+#define U300_TIMER_APP_RGPT1                                   (0x0080)
+#define U300_TIMER_APP_RGPT1_TIMER_RESET                       (0x00000000)
+/* Enable GP1 Timer 32bit (-/W) */
+#define U300_TIMER_APP_EGPT1                                   (0x0084)
+#define U300_TIMER_APP_EGPT1_TIMER_ENABLE                      (0x00000000)
+/* Disable GP1 Timer 32bit (-/W) */
+#define U300_TIMER_APP_DGPT1                                   (0x0088)
+#define U300_TIMER_APP_DGPT1_TIMER_DISABLE                     (0x00000000)
+/* GP1 Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SGPT1M                                  (0x008c)
+#define U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS                  (0x00000000)
+#define U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT                    (0x00000001)
+/* GP1 Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT1S                                   (0x0090)
+#define U300_TIMER_APP_GPT1S_TIMER_STATE_MASK                  (0x0000000F)
+#define U300_TIMER_APP_GPT1S_TIMER_STATE_IDLE                  (0x00000001)
+#define U300_TIMER_APP_GPT1S_TIMER_STATE_ACTIVE                        (0x00000002)
+#define U300_TIMER_APP_GPT1S_ENABLE_IND                                (0x00000010)
+#define U300_TIMER_APP_GPT1S_MODE_MASK                         (0x00000020)
+#define U300_TIMER_APP_GPT1S_MODE_CONTINUOUS                   (0x00000000)
+#define U300_TIMER_APP_GPT1S_MODE_ONE_SHOT                     (0x00000020)
+#define U300_TIMER_APP_GPT1S_IRQ_ENABLED_IND                   (0x00000040)
+#define U300_TIMER_APP_GPT1S_IRQ_PENDING_IND                   (0x00000080)
+/* GP1 Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT1CC                                  (0x0094)
+/* GP1 Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_GPT1TC                                  (0x0098)
+/* GP1 Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT1IE                                  (0x009c)
+#define U300_TIMER_APP_GPT1IE_IRQ_DISABLE                      (0x00000000)
+#define U300_TIMER_APP_GPT1IE_IRQ_ENABLE                       (0x00000001)
+/* GP1 Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT1IA                                  (0x00a0)
+#define U300_TIMER_APP_GPT1IA_IRQ_ACK                          (0x00000080)
+
+/* Reset GP2 Timer 32bit (-/W) */
+#define U300_TIMER_APP_RGPT2                                   (0x00c0)
+#define U300_TIMER_APP_RGPT2_TIMER_RESET                       (0x00000000)
+/* Enable GP2 Timer 32bit (-/W) */
+#define U300_TIMER_APP_EGPT2                                   (0x00c4)
+#define U300_TIMER_APP_EGPT2_TIMER_ENABLE                      (0x00000000)
+/* Disable GP2 Timer 32bit (-/W) */
+#define U300_TIMER_APP_DGPT2                                   (0x00c8)
+#define U300_TIMER_APP_DGPT2_TIMER_DISABLE                     (0x00000000)
+/* GP2 Timer Mode Register 32bit (-/W) */
+#define U300_TIMER_APP_SGPT2M                                  (0x00cc)
+#define U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS                  (0x00000000)
+#define U300_TIMER_APP_SGPT2M_MODE_ONE_SHOT                    (0x00000001)
+/* GP2 Timer Status Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT2S                                   (0x00d0)
+#define U300_TIMER_APP_GPT2S_TIMER_STATE_MASK                  (0x0000000F)
+#define U300_TIMER_APP_GPT2S_TIMER_STATE_IDLE                  (0x00000001)
+#define U300_TIMER_APP_GPT2S_TIMER_STATE_ACTIVE                        (0x00000002)
+#define U300_TIMER_APP_GPT2S_ENABLE_IND                                (0x00000010)
+#define U300_TIMER_APP_GPT2S_MODE_MASK                         (0x00000020)
+#define U300_TIMER_APP_GPT2S_MODE_CONTINUOUS                   (0x00000000)
+#define U300_TIMER_APP_GPT2S_MODE_ONE_SHOT                     (0x00000020)
+#define U300_TIMER_APP_GPT2S_IRQ_ENABLED_IND                   (0x00000040)
+#define U300_TIMER_APP_GPT2S_IRQ_PENDING_IND                   (0x00000080)
+/* GP2 Timer Current Count Register 32bit (R/-) */
+#define U300_TIMER_APP_GPT2CC                                  (0x00d4)
+/* GP2 Timer Terminal Count Register 32bit (R/W) */
+#define U300_TIMER_APP_GPT2TC                                  (0x00d8)
+/* GP2 Timer Interrupt Enable Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT2IE                                  (0x00dc)
+#define U300_TIMER_APP_GPT2IE_IRQ_DISABLE                      (0x00000000)
+#define U300_TIMER_APP_GPT2IE_IRQ_ENABLE                       (0x00000001)
+/* GP2 Timer Interrupt Acknowledge Register 32bit (-/W) */
+#define U300_TIMER_APP_GPT2IA                                  (0x00e0)
+#define U300_TIMER_APP_GPT2IA_IRQ_ACK                          (0x00000080)
+
+/* Clock request control register - all four timers */
+#define U300_TIMER_APP_CRC                                     (0x100)
+#define U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE                        (0x00000001)
+
+static void __iomem *u300_timer_base;
+
+struct u300_clockevent_data {
+       struct clock_event_device cevd;
+       unsigned ticks_per_jiffy;
+};
+
+/*
+ * The u300_set_mode() function is always called first, if we
+ * have oneshot timer active, the oneshot scheduling function
+ * u300_set_next_event() is called immediately after.
+ */
+static void u300_set_mode(enum clock_event_mode mode,
+                         struct clock_event_device *evt)
+{
+       struct u300_clockevent_data *cevdata =
+               container_of(evt, struct u300_clockevent_data, cevd);
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               /* Disable interrupts on GPT1 */
+               writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+                      u300_timer_base + U300_TIMER_APP_GPT1IE);
+               /* Disable GP1 while we're reprogramming it. */
+               writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+                      u300_timer_base + U300_TIMER_APP_DGPT1);
+               /*
+                * Set the periodic mode to a certain number of ticks per
+                * jiffy.
+                */
+               writel(cevdata->ticks_per_jiffy,
+                      u300_timer_base + U300_TIMER_APP_GPT1TC);
+               /*
+                * Set continuous mode, so the timer keeps triggering
+                * interrupts.
+                */
+               writel(U300_TIMER_APP_SGPT1M_MODE_CONTINUOUS,
+                      u300_timer_base + U300_TIMER_APP_SGPT1M);
+               /* Enable timer interrupts */
+               writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
+                      u300_timer_base + U300_TIMER_APP_GPT1IE);
+               /* Then enable the OS timer again */
+               writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
+                      u300_timer_base + U300_TIMER_APP_EGPT1);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               /* Just break; here? */
+               /*
+                * The actual event will be programmed by the next event hook,
+                * so we just set a dummy value somewhere at the end of the
+                * universe here.
+                */
+               /* Disable interrupts on GPT1 */
+               writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+                      u300_timer_base + U300_TIMER_APP_GPT1IE);
+               /* Disable GP1 while we're reprogramming it. */
+               writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+                      u300_timer_base + U300_TIMER_APP_DGPT1);
+               /*
+                * Expire far in the future, u300_set_next_event() will be
+                * called soon...
+                */
+               writel(0xFFFFFFFF, u300_timer_base + U300_TIMER_APP_GPT1TC);
+               /* We run one shot per tick here! */
+               writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
+                      u300_timer_base + U300_TIMER_APP_SGPT1M);
+               /* Enable interrupts for this timer */
+               writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
+                      u300_timer_base + U300_TIMER_APP_GPT1IE);
+               /* Enable timer */
+               writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
+                      u300_timer_base + U300_TIMER_APP_EGPT1);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               /* Disable interrupts on GP1 */
+               writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+                      u300_timer_base + U300_TIMER_APP_GPT1IE);
+               /* Disable GP1 */
+               writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+                      u300_timer_base + U300_TIMER_APP_DGPT1);
+               break;
+       case CLOCK_EVT_MODE_RESUME:
+               /* Ignore this call */
+               break;
+       }
+}
+
+/*
+ * The app timer in one shot mode obviously has to be reprogrammed
+ * in EXACTLY this sequence to work properly. Do NOT try to e.g. replace
+ * the interrupt disable + timer disable commands with a reset command,
+ * it will fail miserably. Apparently (and I found this the hard way)
+ * the timer is very sensitive to the instruction order, though you don't
+ * get that impression from the data sheet.
+ */
+static int u300_set_next_event(unsigned long cycles,
+                              struct clock_event_device *evt)
+
+{
+       /* Disable interrupts on GPT1 */
+       writel(U300_TIMER_APP_GPT1IE_IRQ_DISABLE,
+              u300_timer_base + U300_TIMER_APP_GPT1IE);
+       /* Disable GP1 while we're reprogramming it. */
+       writel(U300_TIMER_APP_DGPT1_TIMER_DISABLE,
+              u300_timer_base + U300_TIMER_APP_DGPT1);
+       /* Reset the General Purpose timer 1. */
+       writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
+              u300_timer_base + U300_TIMER_APP_RGPT1);
+       /* IRQ in n * cycles */
+       writel(cycles, u300_timer_base + U300_TIMER_APP_GPT1TC);
+       /*
+        * We run one shot per tick here! (This is necessary to reconfigure,
+        * the timer will tilt if you don't!)
+        */
+       writel(U300_TIMER_APP_SGPT1M_MODE_ONE_SHOT,
+              u300_timer_base + U300_TIMER_APP_SGPT1M);
+       /* Enable timer interrupts */
+       writel(U300_TIMER_APP_GPT1IE_IRQ_ENABLE,
+              u300_timer_base + U300_TIMER_APP_GPT1IE);
+       /* Then enable the OS timer again */
+       writel(U300_TIMER_APP_EGPT1_TIMER_ENABLE,
+              u300_timer_base + U300_TIMER_APP_EGPT1);
+       return 0;
+}
+
+static struct u300_clockevent_data u300_clockevent_data = {
+       /* Use general purpose timer 1 as clock event */
+       .cevd = {
+               .name           = "GPT1",
+               /* Reasonably fast and accurate clock event */
+               .rating         = 300,
+               .features       = CLOCK_EVT_FEAT_PERIODIC |
+                       CLOCK_EVT_FEAT_ONESHOT,
+               .set_next_event = u300_set_next_event,
+               .set_mode       = u300_set_mode,
+       },
+};
+
+/* Clock event timer interrupt handler */
+static irqreturn_t u300_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *evt = &u300_clockevent_data.cevd;
+       /* ACK/Clear timer IRQ for the APP GPT1 Timer */
+
+       writel(U300_TIMER_APP_GPT1IA_IRQ_ACK,
+               u300_timer_base + U300_TIMER_APP_GPT1IA);
+       evt->event_handler(evt);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction u300_timer_irq = {
+       .name           = "U300 Timer Tick",
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+       .handler        = u300_timer_interrupt,
+};
+
+/*
+ * Override the global weak sched_clock symbol with this
+ * local implementation which uses the clocksource to get some
+ * better resolution when scheduling the kernel. We accept that
+ * this wraps around for now, since it is just a relative time
+ * stamp. (Inspired by OMAP implementation.)
+ */
+
+static u64 notrace u300_read_sched_clock(void)
+{
+       return readl(u300_timer_base + U300_TIMER_APP_GPT2CC);
+}
+
+static unsigned long u300_read_current_timer(void)
+{
+       return readl(u300_timer_base + U300_TIMER_APP_GPT2CC);
+}
+
+static struct delay_timer u300_delay_timer;
+
+/*
+ * This sets up the system timers, clock source and clock event.
+ */
+static void __init u300_timer_init_of(struct device_node *np)
+{
+       unsigned int irq;
+       struct clk *clk;
+       unsigned long rate;
+
+       u300_timer_base = of_iomap(np, 0);
+       if (!u300_timer_base)
+               panic("could not ioremap system timer\n");
+
+       /* Get the IRQ for the GP1 timer */
+       irq = irq_of_parse_and_map(np, 2);
+       if (!irq)
+               panic("no IRQ for system timer\n");
+
+       pr_info("U300 GP1 timer @ base: %p, IRQ: %u\n", u300_timer_base, irq);
+
+       /* Clock the interrupt controller */
+       clk = of_clk_get(np, 0);
+       BUG_ON(IS_ERR(clk));
+       clk_prepare_enable(clk);
+       rate = clk_get_rate(clk);
+
+       u300_clockevent_data.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
+
+       sched_clock_register(u300_read_sched_clock, 32, rate);
+
+       u300_delay_timer.read_current_timer = &u300_read_current_timer;
+       u300_delay_timer.freq = rate;
+       register_current_timer_delay(&u300_delay_timer);
+
+       /*
+        * Disable the "OS" and "DD" timers - these are designed for Symbian!
+        * Example usage in cnh1601578 cpu subsystem pd_timer_app.c
+        */
+       writel(U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE,
+               u300_timer_base + U300_TIMER_APP_CRC);
+       writel(U300_TIMER_APP_ROST_TIMER_RESET,
+               u300_timer_base + U300_TIMER_APP_ROST);
+       writel(U300_TIMER_APP_DOST_TIMER_DISABLE,
+               u300_timer_base + U300_TIMER_APP_DOST);
+       writel(U300_TIMER_APP_RDDT_TIMER_RESET,
+               u300_timer_base + U300_TIMER_APP_RDDT);
+       writel(U300_TIMER_APP_DDDT_TIMER_DISABLE,
+               u300_timer_base + U300_TIMER_APP_DDDT);
+
+       /* Reset the General Purpose timer 1. */
+       writel(U300_TIMER_APP_RGPT1_TIMER_RESET,
+               u300_timer_base + U300_TIMER_APP_RGPT1);
+
+       /* Set up the IRQ handler */
+       setup_irq(irq, &u300_timer_irq);
+
+       /* Reset the General Purpose timer 2 */
+       writel(U300_TIMER_APP_RGPT2_TIMER_RESET,
+               u300_timer_base + U300_TIMER_APP_RGPT2);
+       /* Set this timer to run around forever */
+       writel(0xFFFFFFFFU, u300_timer_base + U300_TIMER_APP_GPT2TC);
+       /* Set continuous mode so it wraps around */
+       writel(U300_TIMER_APP_SGPT2M_MODE_CONTINUOUS,
+              u300_timer_base + U300_TIMER_APP_SGPT2M);
+       /* Disable timer interrupts */
+       writel(U300_TIMER_APP_GPT2IE_IRQ_DISABLE,
+               u300_timer_base + U300_TIMER_APP_GPT2IE);
+       /* Then enable the GP2 timer to use as a free running us counter */
+       writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
+               u300_timer_base + U300_TIMER_APP_EGPT2);
+
+       /* Use general purpose timer 2 as clock source */
+       if (clocksource_mmio_init(u300_timer_base + U300_TIMER_APP_GPT2CC,
+                       "GPT2", rate, 300, 32, clocksource_mmio_readl_up))
+               pr_err("timer: failed to initialize U300 clock source\n");
+
+       /* Configure and register the clockevent */
+       clockevents_config_and_register(&u300_clockevent_data.cevd, rate,
+                                       1, 0xffffffff);
+
+       /*
+        * TODO: init and register the rest of the timers too, they can be
+        * used by hrtimers!
+        */
+}
+
+CLOCKSOURCE_OF_DECLARE(u300_timer, "stericsson,u300-apptimer",
+                      u300_timer_init_of);
index a55e68f..09d05ab 100644 (file)
@@ -140,12 +140,14 @@ int cpuidle_idle_call(void)
                return 0;
        }
 
-       trace_cpu_idle_rcuidle(next_state, dev->cpu);
-
        broadcast = !!(drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP);
 
-       if (broadcast)
-               clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+       if (broadcast &&
+           clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu))
+               return -EBUSY;
+
+
+       trace_cpu_idle_rcuidle(next_state, dev->cpu);
 
        if (cpuidle_state_is_coupled(dev, drv, next_state))
                entered_state = cpuidle_enter_state_coupled(dev, drv,
@@ -153,11 +155,11 @@ int cpuidle_idle_call(void)
        else
                entered_state = cpuidle_enter_state(dev, drv, next_state);
 
+       trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
+
        if (broadcast)
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
-       trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
-
        /* give the governor an opportunity to reflect on the outcome */
        if (cpuidle_curr_governor->reflect)
                cpuidle_curr_governor->reflect(dev, entered_state);
index 9293121..0013142 100644 (file)
@@ -317,6 +317,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
            (clockid != CLOCK_MONOTONIC &&
             clockid != CLOCK_REALTIME &&
             clockid != CLOCK_REALTIME_ALARM &&
+            clockid != CLOCK_BOOTTIME &&
             clockid != CLOCK_BOOTTIME_ALARM))
                return -EINVAL;
 
index 493aa02..2e4cb67 100644 (file)
@@ -62,6 +62,11 @@ enum clock_event_mode {
 #define CLOCK_EVT_FEAT_DYNIRQ          0x000020
 #define CLOCK_EVT_FEAT_PERCPU          0x000040
 
+/*
+ * Clockevent device is based on a hrtimer for broadcast
+ */
+#define CLOCK_EVT_FEAT_HRTIMER         0x000080
+
 /**
  * struct clock_event_device - clock event device descriptor
  * @event_handler:     Assigned by the framework to be called by the low
@@ -83,6 +88,7 @@ enum clock_event_mode {
  * @name:              ptr to clock event name
  * @rating:            variable to rate clock event devices
  * @irq:               IRQ number (only for non CPU local devices)
+ * @bound_on:          Bound on CPU
  * @cpumask:           cpumask to indicate for which CPUs this device works
  * @list:              list head for the management code
  * @owner:             module reference
@@ -113,6 +119,7 @@ struct clock_event_device {
        const char              *name;
        int                     rating;
        int                     irq;
+       int                     bound_on;
        const struct cpumask    *cpumask;
        struct list_head        list;
        struct module           *owner;
@@ -180,15 +187,17 @@ extern int tick_receive_broadcast(void);
 #endif
 
 #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT)
+extern void tick_setup_hrtimer_broadcast(void);
 extern int tick_check_broadcast_expired(void);
 #else
 static inline int tick_check_broadcast_expired(void) { return 0; }
+static inline void tick_setup_hrtimer_broadcast(void) {};
 #endif
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
-extern void clockevents_notify(unsigned long reason, void *arg);
+extern int clockevents_notify(unsigned long reason, void *arg);
 #else
-static inline void clockevents_notify(unsigned long reason, void *arg) {}
+static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 #endif
 
 #else /* CONFIG_GENERIC_CLOCKEVENTS_BUILD */
@@ -196,8 +205,9 @@ static inline void clockevents_notify(unsigned long reason, void *arg) {}
 static inline void clockevents_suspend(void) {}
 static inline void clockevents_resume(void) {}
 
-static inline void clockevents_notify(unsigned long reason, void *arg) {}
+static inline int clockevents_notify(unsigned long reason, void *arg) { return 0; }
 static inline int tick_check_broadcast_expired(void) { return 0; }
+static inline void tick_setup_hrtimer_broadcast(void) {};
 
 #endif
 
index d19a5c2..e7a8d3f 100644 (file)
@@ -96,12 +96,12 @@ enum hrtimer_restart {
  * @function:  timer expiry callback function
  * @base:      pointer to the timer base (per cpu and per clock)
  * @state:     state information (See bit values above)
+ * @start_pid: timer statistics field to store the pid of the task which
+ *             started the timer
  * @start_site:        timer statistics field to store the site where the timer
  *             was started
  * @start_comm: timer statistics field to store the name of the process which
  *             started the timer
- * @start_pid: timer statistics field to store the pid of the task which
- *             started the timer
  *
  * The hrtimer structure must be initialized by hrtimer_init()
  */
index c399ed8..7cb07fd 100644 (file)
@@ -294,10 +294,14 @@ extern int runqueue_is_locked(int cpu);
 #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
 extern void nohz_balance_enter_idle(int cpu);
 extern void set_cpu_sd_state_idle(void);
-extern int get_nohz_timer_target(void);
+extern int get_nohz_timer_target(int pinned);
 #else
 static inline void nohz_balance_enter_idle(int cpu) { }
 static inline void set_cpu_sd_state_idle(void) { }
+static inline int get_nohz_timer_target(int pinned)
+{
+       return smp_processor_id();
+}
 #endif
 
 /*
index 5329946..1b22c42 100644 (file)
@@ -180,6 +180,7 @@ struct execute_work {
 #ifdef CONFIG_DEBUG_OBJECTS_WORK
 extern void __init_work(struct work_struct *work, int onstack);
 extern void destroy_work_on_stack(struct work_struct *work);
+extern void destroy_delayed_work_on_stack(struct delayed_work *work);
 static inline unsigned int work_static(struct work_struct *work)
 {
        return *work_data_bits(work) & WORK_STRUCT_STATIC;
@@ -187,6 +188,7 @@ static inline unsigned int work_static(struct work_struct *work)
 #else
 static inline void __init_work(struct work_struct *work, int onstack) { }
 static inline void destroy_work_on_stack(struct work_struct *work) { }
+static inline void destroy_delayed_work_on_stack(struct delayed_work *work) { }
 static inline unsigned int work_static(struct work_struct *work) { return 0; }
 #endif
 
index 0909436..d55092c 100644 (file)
@@ -168,19 +168,6 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
        }
 }
 
-
-/*
- * Get the preferred target CPU for NOHZ
- */
-static int hrtimer_get_target(int this_cpu, int pinned)
-{
-#ifdef CONFIG_NO_HZ_COMMON
-       if (!pinned && get_sysctl_timer_migration() && idle_cpu(this_cpu))
-               return get_nohz_timer_target();
-#endif
-       return this_cpu;
-}
-
 /*
  * With HIGHRES=y we do not migrate the timer when it is expiring
  * before the next event on the target cpu because we cannot reprogram
@@ -214,7 +201,7 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
        struct hrtimer_clock_base *new_base;
        struct hrtimer_cpu_base *new_cpu_base;
        int this_cpu = smp_processor_id();
-       int cpu = hrtimer_get_target(this_cpu, pinned);
+       int cpu = get_nohz_timer_target(pinned);
        int basenum = base->index;
 
 again:
index d11a176..3c4d096 100644 (file)
@@ -555,12 +555,15 @@ void resched_cpu(int cpu)
  * selecting an idle cpu will add more delays to the timers than intended
  * (as that cpu's timer base may not be uptodate wrt jiffies etc).
  */
-int get_nohz_timer_target(void)
+int get_nohz_timer_target(int pinned)
 {
        int cpu = smp_processor_id();
        int i;
        struct sched_domain *sd;
 
+       if (pinned || !get_sysctl_timer_migration() || !idle_cpu(cpu))
+               return cpu;
+
        rcu_read_lock();
        for_each_domain(cpu, sd) {
                for_each_cpu(i, sched_domain_span(sd)) {
index 3ce6e8c..f448513 100644 (file)
@@ -124,7 +124,7 @@ config NO_HZ_FULL
 endchoice
 
 config NO_HZ_FULL_ALL
-       bool "Full dynticks system on all CPUs by default"
+       bool "Full dynticks system on all CPUs by default (except CPU 0)"
        depends on NO_HZ_FULL
        help
          If the user doesn't pass the nohz_full boot option to
index 9250130..57a413f 100644 (file)
@@ -3,7 +3,10 @@ obj-y += timeconv.o posix-clock.o alarmtimer.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)                += clockevents.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)              += tick-common.o
-obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += tick-broadcast.o
+ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
+ obj-y                                         += tick-broadcast.o
+ obj-$(CONFIG_TICK_ONESHOT)                    += tick-broadcast-hrtimer.o
+endif
 obj-$(CONFIG_GENERIC_SCHED_CLOCK)              += sched_clock.o
 obj-$(CONFIG_TICK_ONESHOT)                     += tick-oneshot.o
 obj-$(CONFIG_TICK_ONESHOT)                     += tick-sched.o
index 086ad60..ad362c2 100644 (file)
@@ -439,6 +439,19 @@ void clockevents_config_and_register(struct clock_event_device *dev,
 }
 EXPORT_SYMBOL_GPL(clockevents_config_and_register);
 
+int __clockevents_update_freq(struct clock_event_device *dev, u32 freq)
+{
+       clockevents_config(dev, freq);
+
+       if (dev->mode == CLOCK_EVT_MODE_ONESHOT)
+               return clockevents_program_event(dev, dev->next_event, false);
+
+       if (dev->mode == CLOCK_EVT_MODE_PERIODIC)
+               dev->set_mode(CLOCK_EVT_MODE_PERIODIC, dev);
+
+       return 0;
+}
+
 /**
  * clockevents_update_freq - Update frequency and reprogram a clock event device.
  * @dev:       device to modify
@@ -446,17 +459,22 @@ EXPORT_SYMBOL_GPL(clockevents_config_and_register);
  *
  * Reconfigure and reprogram a clock event device in oneshot
  * mode. Must be called on the cpu for which the device delivers per
- * cpu timer events with interrupts disabled!  Returns 0 on success,
- * -ETIME when the event is in the past.
+ * cpu timer events. If called for the broadcast device the core takes
+ * care of serialization.
+ *
+ * Returns 0 on success, -ETIME when the event is in the past.
  */
 int clockevents_update_freq(struct clock_event_device *dev, u32 freq)
 {
-       clockevents_config(dev, freq);
-
-       if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
-               return 0;
+       unsigned long flags;
+       int ret;
 
-       return clockevents_program_event(dev, dev->next_event, false);
+       local_irq_save(flags);
+       ret = tick_broadcast_update_freq(dev, freq);
+       if (ret == -ENODEV)
+               ret = __clockevents_update_freq(dev, freq);
+       local_irq_restore(flags);
+       return ret;
 }
 
 /*
@@ -524,12 +542,13 @@ void clockevents_resume(void)
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
 /**
  * clockevents_notify - notification about relevant events
+ * Returns 0 on success, any other value on error
  */
-void clockevents_notify(unsigned long reason, void *arg)
+int clockevents_notify(unsigned long reason, void *arg)
 {
        struct clock_event_device *dev, *tmp;
        unsigned long flags;
-       int cpu;
+       int cpu, ret = 0;
 
        raw_spin_lock_irqsave(&clockevents_lock, flags);
 
@@ -542,7 +561,7 @@ void clockevents_notify(unsigned long reason, void *arg)
 
        case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
        case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
-               tick_broadcast_oneshot_control(reason);
+               ret = tick_broadcast_oneshot_control(reason);
                break;
 
        case CLOCK_EVT_NOTIFY_CPU_DYING:
@@ -585,6 +604,7 @@ void clockevents_notify(unsigned long reason, void *arg)
                break;
        }
        raw_spin_unlock_irqrestore(&clockevents_lock, flags);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(clockevents_notify);
 
index af8d1d4..419a52c 100644 (file)
@@ -514,12 +514,13 @@ static void sync_cmos_clock(struct work_struct *work)
                next.tv_sec++;
                next.tv_nsec -= NSEC_PER_SEC;
        }
-       schedule_delayed_work(&sync_cmos_work, timespec_to_jiffies(&next));
+       queue_delayed_work(system_power_efficient_wq,
+                          &sync_cmos_work, timespec_to_jiffies(&next));
 }
 
 void ntp_notify_cmos_timer(void)
 {
-       schedule_delayed_work(&sync_cmos_work, 0);
+       queue_delayed_work(system_power_efficient_wq, &sync_cmos_work, 0);
 }
 
 #else
diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c
new file mode 100644 (file)
index 0000000..eb682d5
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * linux/kernel/time/tick-broadcast-hrtimer.c
+ * This file emulates a local clock event device
+ * via a pseudo clock device.
+ */
+#include <linux/cpu.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/profile.h>
+#include <linux/clockchips.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/module.h>
+
+#include "tick-internal.h"
+
+static struct hrtimer bctimer;
+
+static void bc_set_mode(enum clock_event_mode mode,
+                       struct clock_event_device *bc)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               /*
+                * Note, we cannot cancel the timer here as we might
+                * run into the following live lock scenario:
+                *
+                * cpu 0                cpu1
+                * lock(broadcast_lock);
+                *                      hrtimer_interrupt()
+                *                      bc_handler()
+                *                         tick_handle_oneshot_broadcast();
+                *                          lock(broadcast_lock);
+                * hrtimer_cancel()
+                *  wait_for_callback()
+                */
+               hrtimer_try_to_cancel(&bctimer);
+               break;
+       default:
+               break;
+       }
+}
+
+/*
+ * This is called from the guts of the broadcast code when the cpu
+ * which is about to enter idle has the earliest broadcast timer event.
+ */
+static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
+{
+       /*
+        * We try to cancel the timer first. If the callback is on
+        * flight on some other cpu then we let it handle it. If we
+        * were able to cancel the timer nothing can rearm it as we
+        * own broadcast_lock.
+        *
+        * However we can also be called from the event handler of
+        * ce_broadcast_hrtimer itself when it expires. We cannot
+        * restart the timer because we are in the callback, but we
+        * can set the expiry time and let the callback return
+        * HRTIMER_RESTART.
+        */
+       if (hrtimer_try_to_cancel(&bctimer) >= 0) {
+               hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED);
+               /* Bind the "device" to the cpu */
+               bc->bound_on = smp_processor_id();
+       } else if (bc->bound_on == smp_processor_id()) {
+               hrtimer_set_expires(&bctimer, expires);
+       }
+       return 0;
+}
+
+static struct clock_event_device ce_broadcast_hrtimer = {
+       .set_mode               = bc_set_mode,
+       .set_next_ktime         = bc_set_next,
+       .features               = CLOCK_EVT_FEAT_ONESHOT |
+                                 CLOCK_EVT_FEAT_KTIME |
+                                 CLOCK_EVT_FEAT_HRTIMER,
+       .rating                 = 0,
+       .bound_on               = -1,
+       .min_delta_ns           = 1,
+       .max_delta_ns           = KTIME_MAX,
+       .min_delta_ticks        = 1,
+       .max_delta_ticks        = ULONG_MAX,
+       .mult                   = 1,
+       .shift                  = 0,
+       .cpumask                = cpu_all_mask,
+};
+
+static enum hrtimer_restart bc_handler(struct hrtimer *t)
+{
+       ce_broadcast_hrtimer.event_handler(&ce_broadcast_hrtimer);
+
+       if (ce_broadcast_hrtimer.next_event.tv64 == KTIME_MAX)
+               return HRTIMER_NORESTART;
+
+       return HRTIMER_RESTART;
+}
+
+void tick_setup_hrtimer_broadcast(void)
+{
+       hrtimer_init(&bctimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       bctimer.function = bc_handler;
+       clockevents_register_device(&ce_broadcast_hrtimer);
+}
index 98977a5..64c5990 100644 (file)
@@ -120,6 +120,19 @@ int tick_is_broadcast_device(struct clock_event_device *dev)
        return (dev && tick_broadcast_device.evtdev == dev);
 }
 
+int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq)
+{
+       int ret = -ENODEV;
+
+       if (tick_is_broadcast_device(dev)) {
+               raw_spin_lock(&tick_broadcast_lock);
+               ret = __clockevents_update_freq(dev, freq);
+               raw_spin_unlock(&tick_broadcast_lock);
+       }
+       return ret;
+}
+
+
 static void err_broadcast(const struct cpumask *mask)
 {
        pr_crit_once("Failed to broadcast timer tick. Some CPUs may be unresponsive.\n");
@@ -272,12 +285,8 @@ static void tick_do_broadcast(struct cpumask *mask)
  */
 static void tick_do_periodic_broadcast(void)
 {
-       raw_spin_lock(&tick_broadcast_lock);
-
        cpumask_and(tmpmask, cpu_online_mask, tick_broadcast_mask);
        tick_do_broadcast(tmpmask);
-
-       raw_spin_unlock(&tick_broadcast_lock);
 }
 
 /*
@@ -287,13 +296,15 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
 {
        ktime_t next;
 
+       raw_spin_lock(&tick_broadcast_lock);
+
        tick_do_periodic_broadcast();
 
        /*
         * The device is in periodic mode. No reprogramming necessary:
         */
        if (dev->mode == CLOCK_EVT_MODE_PERIODIC)
-               return;
+               goto unlock;
 
        /*
         * Setup the next period for devices, which do not have
@@ -306,9 +317,11 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
                next = ktime_add(next, tick_period);
 
                if (!clockevents_program_event(dev, next, false))
-                       return;
+                       goto unlock;
                tick_do_periodic_broadcast();
        }
+unlock:
+       raw_spin_unlock(&tick_broadcast_lock);
 }
 
 /*
@@ -630,24 +643,61 @@ again:
        raw_spin_unlock(&tick_broadcast_lock);
 }
 
+static int broadcast_needs_cpu(struct clock_event_device *bc, int cpu)
+{
+       if (!(bc->features & CLOCK_EVT_FEAT_HRTIMER))
+               return 0;
+       if (bc->next_event.tv64 == KTIME_MAX)
+               return 0;
+       return bc->bound_on == cpu ? -EBUSY : 0;
+}
+
+static void broadcast_shutdown_local(struct clock_event_device *bc,
+                                    struct clock_event_device *dev)
+{
+       /*
+        * For hrtimer based broadcasting we cannot shutdown the cpu
+        * local device if our own event is the first one to expire or
+        * if we own the broadcast timer.
+        */
+       if (bc->features & CLOCK_EVT_FEAT_HRTIMER) {
+               if (broadcast_needs_cpu(bc, smp_processor_id()))
+                       return;
+               if (dev->next_event.tv64 < bc->next_event.tv64)
+                       return;
+       }
+       clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
+}
+
+static void broadcast_move_bc(int deadcpu)
+{
+       struct clock_event_device *bc = tick_broadcast_device.evtdev;
+
+       if (!bc || !broadcast_needs_cpu(bc, deadcpu))
+               return;
+       /* This moves the broadcast assignment to this cpu */
+       clockevents_program_event(bc, bc->next_event, 1);
+}
+
 /*
  * Powerstate information: The system enters/leaves a state, where
  * affected devices might stop
+ * Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups.
  */
-void tick_broadcast_oneshot_control(unsigned long reason)
+int tick_broadcast_oneshot_control(unsigned long reason)
 {
        struct clock_event_device *bc, *dev;
        struct tick_device *td;
        unsigned long flags;
        ktime_t now;
-       int cpu;
+       int cpu, ret = 0;
 
        /*
         * Periodic mode does not care about the enter/exit of power
         * states
         */
        if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
-               return;
+               return 0;
 
        /*
         * We are called with preemtion disabled from the depth of the
@@ -658,7 +708,7 @@ void tick_broadcast_oneshot_control(unsigned long reason)
        dev = td->evtdev;
 
        if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
-               return;
+               return 0;
 
        bc = tick_broadcast_device.evtdev;
 
@@ -666,7 +716,7 @@ void tick_broadcast_oneshot_control(unsigned long reason)
        if (reason == CLOCK_EVT_NOTIFY_BROADCAST_ENTER) {
                if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) {
                        WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask));
-                       clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
+                       broadcast_shutdown_local(bc, dev);
                        /*
                         * We only reprogram the broadcast timer if we
                         * did not mark ourself in the force mask and
@@ -679,6 +729,16 @@ void tick_broadcast_oneshot_control(unsigned long reason)
                            dev->next_event.tv64 < bc->next_event.tv64)
                                tick_broadcast_set_event(bc, cpu, dev->next_event, 1);
                }
+               /*
+                * If the current CPU owns the hrtimer broadcast
+                * mechanism, it cannot go deep idle and we remove the
+                * CPU from the broadcast mask. We don't have to go
+                * through the EXIT path as the local timer is not
+                * shutdown.
+                */
+               ret = broadcast_needs_cpu(bc, cpu);
+               if (ret)
+                       cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask);
        } else {
                if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_oneshot_mask)) {
                        clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
@@ -746,6 +806,7 @@ void tick_broadcast_oneshot_control(unsigned long reason)
        }
 out:
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
+       return ret;
 }
 
 /*
@@ -852,6 +913,8 @@ void tick_shutdown_broadcast_oneshot(unsigned int *cpup)
        cpumask_clear_cpu(cpu, tick_broadcast_pending_mask);
        cpumask_clear_cpu(cpu, tick_broadcast_force_mask);
 
+       broadcast_move_bc(cpu);
+
        raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
 }
 
index 20b2fe3..0156612 100644 (file)
@@ -98,18 +98,19 @@ static void tick_periodic(int cpu)
 void tick_handle_periodic(struct clock_event_device *dev)
 {
        int cpu = smp_processor_id();
-       ktime_t next;
+       ktime_t next = dev->next_event;
 
        tick_periodic(cpu);
 
        if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
                return;
-       /*
-        * Setup the next period for devices, which do not have
-        * periodic mode:
-        */
-       next = ktime_add(dev->next_event, tick_period);
        for (;;) {
+               /*
+                * Setup the next period for devices, which do not have
+                * periodic mode:
+                */
+               next = ktime_add(next, tick_period);
+
                if (!clockevents_program_event(dev, next, false))
                        return;
                /*
@@ -118,12 +119,11 @@ void tick_handle_periodic(struct clock_event_device *dev)
                 * to be sure we're using a real hardware clocksource.
                 * Otherwise we could get trapped in an infinite
                 * loop, as the tick_periodic() increments jiffies,
-                * when then will increment time, posibly causing
+                * which then will increment time, possibly causing
                 * the loop to trigger again and again.
                 */
                if (timekeeping_valid_for_hres())
                        tick_periodic(cpu);
-               next = ktime_add(next, tick_period);
        }
 }
 
index 8329669..7ab92b1 100644 (file)
@@ -46,7 +46,7 @@ extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *));
 extern void tick_resume_oneshot(void);
 # ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 extern void tick_broadcast_setup_oneshot(struct clock_event_device *bc);
-extern void tick_broadcast_oneshot_control(unsigned long reason);
+extern int tick_broadcast_oneshot_control(unsigned long reason);
 extern void tick_broadcast_switch_to_oneshot(void);
 extern void tick_shutdown_broadcast_oneshot(unsigned int *cpup);
 extern int tick_resume_broadcast_oneshot(struct clock_event_device *bc);
@@ -58,7 +58,7 @@ static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
        BUG();
 }
-static inline void tick_broadcast_oneshot_control(unsigned long reason) { }
+static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
 static inline void tick_broadcast_switch_to_oneshot(void) { }
 static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
 static inline int tick_broadcast_oneshot_active(void) { return 0; }
@@ -87,7 +87,7 @@ static inline void tick_broadcast_setup_oneshot(struct clock_event_device *bc)
 {
        BUG();
 }
-static inline void tick_broadcast_oneshot_control(unsigned long reason) { }
+static inline int tick_broadcast_oneshot_control(unsigned long reason) { return 0; }
 static inline void tick_shutdown_broadcast_oneshot(unsigned int *cpup) { }
 static inline int tick_resume_broadcast_oneshot(struct clock_event_device *bc)
 {
@@ -111,6 +111,7 @@ extern int tick_resume_broadcast(void);
 extern void tick_broadcast_init(void);
 extern void
 tick_set_periodic_handler(struct clock_event_device *dev, int broadcast);
+int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq);
 
 #else /* !BROADCAST */
 
@@ -133,6 +134,8 @@ static inline void tick_shutdown_broadcast(unsigned int *cpup) { }
 static inline void tick_suspend_broadcast(void) { }
 static inline int tick_resume_broadcast(void) { return 0; }
 static inline void tick_broadcast_init(void) { }
+static inline int tick_broadcast_update_freq(struct clock_event_device *dev,
+                                            u32 freq) { return -ENODEV; }
 
 /*
  * Set the periodic handler in non broadcast mode
@@ -152,6 +155,8 @@ static inline int tick_device_is_functional(struct clock_event_device *dev)
        return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
 }
 
+int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
+
 #endif
 
 extern void do_timer(unsigned long ticks);
index 802433a..4d54f97 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/seq_file.h>
 #include <linux/time.h>
 
+#include "timekeeping_internal.h"
+
 static unsigned int sleep_time_bin[32] = {0};
 
 static int tk_debug_show_sleep_time(struct seq_file *s, void *data)
index d78de04..87bd529 100644 (file)
@@ -81,6 +81,7 @@ struct tvec_base {
        unsigned long timer_jiffies;
        unsigned long next_timer;
        unsigned long active_timers;
+       unsigned long all_timers;
        struct tvec_root tv1;
        struct tvec tv2;
        struct tvec tv3;
@@ -337,6 +338,20 @@ void set_timer_slack(struct timer_list *timer, int slack_hz)
 }
 EXPORT_SYMBOL_GPL(set_timer_slack);
 
+/*
+ * If the list is empty, catch up ->timer_jiffies to the current time.
+ * The caller must hold the tvec_base lock.  Returns true if the list
+ * was empty and therefore ->timer_jiffies was updated.
+ */
+static bool catchup_timer_jiffies(struct tvec_base *base)
+{
+       if (!base->all_timers) {
+               base->timer_jiffies = jiffies;
+               return true;
+       }
+       return false;
+}
+
 static void
 __internal_add_timer(struct tvec_base *base, struct timer_list *timer)
 {
@@ -383,15 +398,17 @@ __internal_add_timer(struct tvec_base *base, struct timer_list *timer)
 
 static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
 {
+       (void)catchup_timer_jiffies(base);
        __internal_add_timer(base, timer);
        /*
         * Update base->active_timers and base->next_timer
         */
        if (!tbase_get_deferrable(timer->base)) {
-               if (time_before(timer->expires, base->next_timer))
+               if (!base->active_timers++ ||
+                   time_before(timer->expires, base->next_timer))
                        base->next_timer = timer->expires;
-               base->active_timers++;
        }
+       base->all_timers++;
 }
 
 #ifdef CONFIG_TIMER_STATS
@@ -671,6 +688,8 @@ detach_expired_timer(struct timer_list *timer, struct tvec_base *base)
        detach_timer(timer, true);
        if (!tbase_get_deferrable(timer->base))
                base->active_timers--;
+       base->all_timers--;
+       (void)catchup_timer_jiffies(base);
 }
 
 static int detach_if_pending(struct timer_list *timer, struct tvec_base *base,
@@ -685,6 +704,8 @@ static int detach_if_pending(struct timer_list *timer, struct tvec_base *base,
                if (timer->expires == base->next_timer)
                        base->next_timer = base->timer_jiffies;
        }
+       base->all_timers--;
+       (void)catchup_timer_jiffies(base);
        return 1;
 }
 
@@ -739,12 +760,7 @@ __mod_timer(struct timer_list *timer, unsigned long expires,
 
        debug_activate(timer, expires);
 
-       cpu = smp_processor_id();
-
-#if defined(CONFIG_NO_HZ_COMMON) && defined(CONFIG_SMP)
-       if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu))
-               cpu = get_nohz_timer_target();
-#endif
+       cpu = get_nohz_timer_target(pinned);
        new_base = per_cpu(tvec_bases, cpu);
 
        if (base != new_base) {
@@ -939,8 +955,15 @@ void add_timer_on(struct timer_list *timer, int cpu)
         * with the timer by holding the timer base lock. This also
         * makes sure that a CPU on the way to stop its tick can not
         * evaluate the timer wheel.
+        *
+        * Spare the IPI for deferrable timers on idle targets though.
+        * The next busy ticks will take care of it. Except full dynticks
+        * require special care against races with idle_cpu(), lets deal
+        * with that later.
         */
-       wake_up_nohz_cpu(cpu);
+       if (!tbase_get_deferrable(timer->base) || tick_nohz_full_cpu(cpu))
+               wake_up_nohz_cpu(cpu);
+
        spin_unlock_irqrestore(&base->lock, flags);
 }
 EXPORT_SYMBOL_GPL(add_timer_on);
@@ -1146,6 +1169,10 @@ static inline void __run_timers(struct tvec_base *base)
        struct timer_list *timer;
 
        spin_lock_irq(&base->lock);
+       if (catchup_timer_jiffies(base)) {
+               spin_unlock_irq(&base->lock);
+               return;
+       }
        while (time_after_eq(jiffies, base->timer_jiffies)) {
                struct list_head work_list;
                struct list_head *head = &work_list;
@@ -1160,7 +1187,7 @@ static inline void __run_timers(struct tvec_base *base)
                                        !cascade(base, &base->tv4, INDEX(2)))
                        cascade(base, &base->tv5, INDEX(3));
                ++base->timer_jiffies;
-               list_replace_init(base->tv1.vec + index, &work_list);
+               list_replace_init(base->tv1.vec + index, head);
                while (!list_empty(head)) {
                        void (*fn)(unsigned long);
                        unsigned long data;
@@ -1523,9 +1550,8 @@ static int init_timers_cpu(int cpu)
                        if (!base)
                                return -ENOMEM;
 
-                       /* Make sure that tvec_base is 2 byte aligned */
-                       if (tbase_get_deferrable(base)) {
-                               WARN_ON(1);
+                       /* Make sure tvec_base has TIMER_FLAG_MASK bits free */
+                       if (WARN_ON(base != tbase_get_base(base))) {
                                kfree(base);
                                return -ENOMEM;
                        }
@@ -1559,6 +1585,7 @@ static int init_timers_cpu(int cpu)
        base->timer_jiffies = jiffies;
        base->next_timer = base->timer_jiffies;
        base->active_timers = 0;
+       base->all_timers = 0;
        return 0;
 }
 
@@ -1648,9 +1675,9 @@ void __init init_timers(void)
 
        err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
                               (void *)(long)smp_processor_id());
-       init_timer_stats();
-
        BUG_ON(err != NOTIFY_OK);
+
+       init_timer_stats();
        register_cpu_notifier(&timers_nb);
        open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
 }
index 3fa5b8f..0ee63af 100644 (file)
@@ -516,6 +516,13 @@ void destroy_work_on_stack(struct work_struct *work)
 }
 EXPORT_SYMBOL_GPL(destroy_work_on_stack);
 
+void destroy_delayed_work_on_stack(struct delayed_work *work)
+{
+       destroy_timer_on_stack(&work->timer);
+       debug_object_free(&work->work, &work_debug_descr);
+}
+EXPORT_SYMBOL_GPL(destroy_delayed_work_on_stack);
+
 #else
 static inline void debug_work_activate(struct work_struct *work) { }
 static inline void debug_work_deactivate(struct work_struct *work) { }