diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 11:00:07 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 11:00:07 -0700 |
commit | 1ead65812486cda65093683a99b8907a7242fa93 (patch) | |
tree | 094684870815537aae4aedb69c10d669ba29f0af /arch/arm | |
parent | b6d739e9581272f0bbbd6edd15340fb8e108df96 (diff) | |
parent | b97f0291a2504291aef850077f98cab68a5a2f33 (diff) |
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
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
...
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/boot/dts/sun4i-a10.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun5i-a10s.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun5i-a13.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun6i-a31.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/sun7i-a20.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/boot/dts/zynq-7000.dtsi | 6 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/Kconfig | 36 | ||||
-rw-r--r-- | arch/arm/mach-u300/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-u300/timer.c | 451 | ||||
-rw-r--r-- | arch/arm/mach-zynq/Kconfig | 4 | ||||
-rw-r--r-- | arch/arm/mach-zynq/common.c | 3 |
11 files changed, 36 insertions, 476 deletions
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index d4d2763f4794..2ce61228d5f9 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi @@ -403,7 +403,7 @@ }; timer@01c20c00 { - compatible = "allwinner,sun4i-timer"; + compatible = "allwinner,sun4i-a10-timer"; reg = <0x01c20c00 0x90>; interrupts = <22>; clocks = <&osc24M>; diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index 79fd412005b0..29dd32d8e77e 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi @@ -366,7 +366,7 @@ }; timer@01c20c00 { - compatible = "allwinner,sun4i-timer"; + compatible = "allwinner,sun4i-a10-timer"; reg = <0x01c20c00 0x90>; interrupts = <22>; clocks = <&osc24M>; diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index c463fd730c91..e63bb383b43d 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi @@ -329,7 +329,7 @@ }; timer@01c20c00 { - compatible = "allwinner,sun4i-timer"; + compatible = "allwinner,sun4i-a10-timer"; reg = <0x01c20c00 0x90>; interrupts = <22>; clocks = <&osc24M>; diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 5256ad9be52c..996fff54c8a2 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -231,7 +231,7 @@ }; timer@01c20c00 { - compatible = "allwinner,sun4i-timer"; + compatible = "allwinner,sun4i-a10-timer"; reg = <0x01c20c00 0xa0>; interrupts = <0 18 4>, <0 19 4>, diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index 6f25cf559ad0..dddc8ac2d522 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi @@ -435,7 +435,7 @@ }; timer@01c20c00 { - compatible = "allwinner,sun4i-timer"; + compatible = "allwinner,sun4i-a10-timer"; reg = <0x01c20c00 0x90>; interrupts = <0 22 4>, <0 23 4>, diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi index 8b67b19392ec..789d0bacc110 100644 --- a/arch/arm/boot/dts/zynq-7000.dtsi +++ b/arch/arm/boot/dts/zynq-7000.dtsi @@ -24,6 +24,12 @@ device_type = "cpu"; reg = <0>; clocks = <&clkc 3>; + operating-points = < + /* kHz uV */ + 666667 1000000 + 333334 1000000 + 222223 1000000 + >; }; cpu@1 { diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 05fa505df585..f6db7dcae3f4 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -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 diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile index 0f362b64fb87..3ec74ac95bc1 100644 --- a/arch/arm/mach-u300/Makefile +++ b/arch/arm/mach-u300/Makefile @@ -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 index fe08fd34c0ce..000000000000 --- a/arch/arm/mach-u300/timer.c +++ /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); diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index 6b04260aa142..f03e75bd0b2b 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -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 diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 8c09a8393fb6..a39be8e80856 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -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) |