diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 13:21:16 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-06 13:21:16 -0700 |
commit | 8e73e367f7dc50f1d1bc22a63e5764bb4eea9b48 (patch) | |
tree | 9bf593c1fc7612bcdd64b9ba46e41d340f9e94d3 /arch/arm/kernel/smp_twd.c | |
parent | d2f3e9eb7c9e12e89f0ac5f0dbc7a9aed0ea925d (diff) | |
parent | 7323f219533e01cc075ba45a76f3e5b214adb23f (diff) |
Merge tag 'cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC cleanups from Olof Johansson:
"This branch contains code cleanups, moves and removals for 3.12.
There's a large number of various cleanups, and a nice net removal of
13500 lines of code.
Highlights worth mentioning are:
- A series of patches from Stephen Boyd removing the ARM local timer
API.
- Move of Qualcomm MSM IOMMU code to drivers/iommu.
- Samsung PWM driver cleanups from Tomasz Figa, removing legacy PWM
driver and switching over to the drivers/pwm one.
- Removal of some unusued auto-generated headers for OMAP2+ (PRM/CM).
There's also a move of a header file out of include/linux/i2c/ to
platform_data, where it really belongs. It touches mostly ARM
platform code for include changes so we took it through our tree"
* tag 'cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (83 commits)
ARM: OMAP2+: Add back the define for AM33XX_RST_GLOBAL_WARM_SW_MASK
gpio: (gpio-pca953x) move header to linux/platform_data/
arm: zynq: hotplug: Remove unreachable code
ARM: SAMSUNG: Remove unnecessary exynos4_default_sdhci*()
tegra: simplify use of devm_ioremap_resource
ARM: SAMSUNG: Remove plat/regs-timer.h header
ARM: SAMSUNG: Remove remaining uses of plat/regs-timer.h header
ARM: SAMSUNG: Remove pwm-clock infrastructure
ARM: SAMSUNG: Remove old PWM timer platform devices
pwm: Remove superseded pwm-samsung-legacy driver
ARM: SAMSUNG: Modify board files to use new PWM platform device
ARM: SAMSUNG: Rework private data handling in dev-backlight
pwm: Add new pwm-samsung driver
ARM: mach-mvebu: remove redundant DT parsing and validation
ARM: msm: Only compile io.c on platforms that use it
iommu/msm: Move mach includes to iommu directory
ARM: msm: Remove devices-iommu.c
ARM: msm: Move mach/board.h contents to common.h
ARM: msm: Migrate msm_timer to CLOCKSOURCE_OF_DECLARE
ARM: msm: Remove TMR and TMR0 static mappings
...
Diffstat (limited to 'arch/arm/kernel/smp_twd.c')
-rw-r--r-- | arch/arm/kernel/smp_twd.c | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 25956204ef2..2985c9f0905 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -11,6 +11,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/clk.h> +#include <linux/cpu.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> @@ -24,7 +25,6 @@ #include <asm/smp_plat.h> #include <asm/smp_twd.h> -#include <asm/localtimer.h> /* set up by the platform code */ static void __iomem *twd_base; @@ -33,7 +33,7 @@ static struct clk *twd_clk; static unsigned long twd_timer_rate; static DEFINE_PER_CPU(bool, percpu_setup_called); -static struct clock_event_device __percpu **twd_evt; +static struct clock_event_device __percpu *twd_evt; static int twd_ppi; static void twd_set_mode(enum clock_event_mode mode, @@ -90,8 +90,10 @@ static int twd_timer_ack(void) return 0; } -static void twd_timer_stop(struct clock_event_device *clk) +static void twd_timer_stop(void) { + struct clock_event_device *clk = __this_cpu_ptr(twd_evt); + twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); disable_percpu_irq(clk->irq); } @@ -106,7 +108,7 @@ static void twd_update_frequency(void *new_rate) { twd_timer_rate = *((unsigned long *) new_rate); - clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); + clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate); } static int twd_rate_change(struct notifier_block *nb, @@ -132,7 +134,7 @@ static struct notifier_block twd_clk_nb = { static int twd_clk_init(void) { - if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) + if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) return clk_notifier_register(twd_clk, &twd_clk_nb); return 0; @@ -151,7 +153,7 @@ static void twd_update_frequency(void *data) { twd_timer_rate = clk_get_rate(twd_clk); - clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); + clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate); } static int twd_cpufreq_transition(struct notifier_block *nb, @@ -177,7 +179,7 @@ static struct notifier_block twd_cpufreq_nb = { static int twd_cpufreq_init(void) { - if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) + if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) return cpufreq_register_notifier(&twd_cpufreq_nb, CPUFREQ_TRANSITION_NOTIFIER); @@ -228,7 +230,7 @@ static void twd_calibrate_rate(void) static irqreturn_t twd_handler(int irq, void *dev_id) { - struct clock_event_device *evt = *(struct clock_event_device **)dev_id; + struct clock_event_device *evt = dev_id; if (twd_timer_ack()) { evt->event_handler(evt); @@ -265,9 +267,9 @@ static void twd_get_clock(struct device_node *np) /* * Setup the local clock events for a CPU. */ -static int twd_timer_setup(struct clock_event_device *clk) +static void twd_timer_setup(void) { - struct clock_event_device **this_cpu_clk; + struct clock_event_device *clk = __this_cpu_ptr(twd_evt); int cpu = smp_processor_id(); /* @@ -276,9 +278,9 @@ static int twd_timer_setup(struct clock_event_device *clk) */ if (per_cpu(percpu_setup_called, cpu)) { __raw_writel(0, twd_base + TWD_TIMER_CONTROL); - clockevents_register_device(*__this_cpu_ptr(twd_evt)); + clockevents_register_device(clk); enable_percpu_irq(clk->irq, 0); - return 0; + return; } per_cpu(percpu_setup_called, cpu) = true; @@ -297,27 +299,37 @@ static int twd_timer_setup(struct clock_event_device *clk) clk->set_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; clk->irq = twd_ppi; - - this_cpu_clk = __this_cpu_ptr(twd_evt); - *this_cpu_clk = clk; + clk->cpumask = cpumask_of(cpu); clockevents_config_and_register(clk, twd_timer_rate, 0xf, 0xffffffff); enable_percpu_irq(clk->irq, 0); +} - return 0; +static int twd_timer_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_STARTING: + twd_timer_setup(); + break; + case CPU_DYING: + twd_timer_stop(); + break; + } + + return NOTIFY_OK; } -static struct local_timer_ops twd_lt_ops = { - .setup = twd_timer_setup, - .stop = twd_timer_stop, +static struct notifier_block twd_timer_cpu_nb = { + .notifier_call = twd_timer_cpu_notify, }; static int __init twd_local_timer_common_register(struct device_node *np) { int err; - twd_evt = alloc_percpu(struct clock_event_device *); + twd_evt = alloc_percpu(struct clock_event_device); if (!twd_evt) { err = -ENOMEM; goto out_free; @@ -329,12 +341,22 @@ static int __init twd_local_timer_common_register(struct device_node *np) goto out_free; } - err = local_timer_register(&twd_lt_ops); + err = register_cpu_notifier(&twd_timer_cpu_nb); if (err) goto out_irq; twd_get_clock(np); + /* + * Immediately configure the timer on the boot CPU, unless we need + * jiffies to be incrementing to calibrate the rate in which case + * setup the timer in late_time_init. + */ + if (twd_timer_rate) + twd_timer_setup(); + else + late_time_init = twd_timer_setup; + return 0; out_irq: |