From: Linus Torvalds Date: Mon, 16 Sep 2013 20:10:26 +0000 (-0400) Subject: Merge branch 'timers/core' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip X-Git-Tag: drm-fsl-dcu-for-next~6733 X-Git-Url: http://git.agner.ch/gitweb/?p=linux-drm-fsl-dcu.git;a=commitdiff_plain;h=a4ae54f90e0a7063799eb90852aa8648ccfbb791 Merge branch 'timers/core' of git://git./linux/kernel/git/tip/tip Pull timer code update from Thomas Gleixner: - armada SoC clocksource overhaul with a trivial merge conflict - Minor improvements to various SoC clocksource drivers * 'timers/core' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: clocksource: armada-370-xp: Add detailed clock requirements in devicetree binding clocksource: armada-370-xp: Get reference fixed-clock by name clocksource: armada-370-xp: Replace WARN_ON with BUG_ON clocksource: armada-370-xp: Fix device-tree binding clocksource: armada-370-xp: Introduce new compatibles clocksource: armada-370-xp: Use CLOCKSOURCE_OF_DECLARE clocksource: armada-370-xp: Simplify TIMER_CTRL register access clocksource: armada-370-xp: Use BIT() ARM: timer-sp: Set dynamic irq affinity ARM: nomadik: add dynamic irq flag to the timer clocksource: sh_cmt: 32-bit control register support clocksource: em_sti: Convert to devm_* managed helpers --- a4ae54f90e0a7063799eb90852aa8648ccfbb791 diff --cc arch/arm/mach-mvebu/armada-370-xp.c index 829b57306328,4ea03ad41179..e2acff98e750 --- a/arch/arm/mach-mvebu/armada-370-xp.c +++ b/arch/arm/mach-mvebu/armada-370-xp.c @@@ -37,9 -37,41 +37,9 @@@ static void __init armada_370_xp_map_io static void __init armada_370_xp_timer_and_clk_init(void) { of_clk_init(NULL); - armada_370_xp_timer_init(); + clocksource_of_init(); coherency_init(); - armada_370_xp_mbus_init(); + BUG_ON(mvebu_mbus_dt_init()); #ifdef CONFIG_CACHE_L2X0 l2x0_of_init(0, ~0UL); #endif diff --cc drivers/clocksource/time-armada-370-xp.c index 847cab6f6e31,44c4fff2f58c..0198504ef6b0 --- a/drivers/clocksource/time-armada-370-xp.c +++ b/drivers/clocksource/time-armada-370-xp.c @@@ -29,9 -41,9 +42,8 @@@ #include #include #include - -#include #include - #include + /* * Timer block registers. */ @@@ -70,8 -82,20 +82,20 @@@ static bool timer25Mhz = true */ static u32 ticks_per_jiffy; -static struct clock_event_device __percpu **percpu_armada_370_xp_evt; +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, + local_base + TIMER_CTRL_OFF); + } + static u32 notrace armada_370_xp_read_sched_clock(void) { return ~readl(timer_base + TIMER0_VAL_OFF); @@@ -163,25 -184,30 +177,25 @@@ static irqreturn_t armada_370_xp_timer_ */ static int armada_370_xp_timer_setup(struct clock_event_device *evt) { - u32 u; + u32 clr = 0, set = 0; int cpu = smp_processor_id(); - u = readl(local_base + TIMER_CTRL_OFF); - /* Use existing clock_event for cpu 0 */ - if (!smp_processor_id()) - return 0; - if (timer25Mhz) - writel(u | TIMER0_25MHZ, local_base + TIMER_CTRL_OFF); + set = TIMER0_25MHZ; else - writel(u & ~TIMER0_25MHZ, local_base + TIMER_CTRL_OFF); + clr = TIMER0_25MHZ; + local_timer_ctrl_clrset(clr, set); - evt->name = armada_370_xp_clkevt.name; - evt->irq = armada_370_xp_clkevt.irq; - evt->features = armada_370_xp_clkevt.features; - evt->shift = armada_370_xp_clkevt.shift; - evt->rating = armada_370_xp_clkevt.rating, + evt->name = "armada_370_xp_per_cpu_tick", + evt->features = CLOCK_EVT_FEAT_ONESHOT | + CLOCK_EVT_FEAT_PERIODIC; + evt->shift = 32, + evt->rating = 300, evt->set_next_event = armada_370_xp_clkevt_next_event, evt->set_mode = armada_370_xp_clkevt_mode, + evt->irq = armada_370_xp_clkevt_irq; evt->cpumask = cpumask_of(cpu); - *__this_cpu_ptr(percpu_armada_370_xp_evt) = evt; - clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe); enable_percpu_irq(evt->irq, 0); @@@ -194,59 -220,26 +208,44 @@@ static void armada_370_xp_timer_stop(st disable_percpu_irq(evt->irq); } -static struct local_timer_ops armada_370_xp_local_timer_ops = { - .setup = armada_370_xp_timer_setup, - .stop = armada_370_xp_timer_stop, +static int armada_370_xp_timer_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + /* + * Grab cpu pointer in each case to avoid spurious + * preemptible warnings + */ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_STARTING: + armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); + break; + case CPU_DYING: + armada_370_xp_timer_stop(this_cpu_ptr(armada_370_xp_evt)); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block armada_370_xp_timer_cpu_nb = { + .notifier_call = armada_370_xp_timer_cpu_notify, }; - void __init armada_370_xp_timer_init(void) + static void __init armada_370_xp_timer_common_init(struct device_node *np) { - u32 u; - struct device_node *np; + u32 clr = 0, set = 0; int res; - np = of_find_compatible_node(NULL, NULL, "marvell,armada-370-xp-timer"); timer_base = of_iomap(np, 0); WARN_ON(!timer_base); local_base = of_iomap(np, 1); - if (of_find_property(np, "marvell,timer-25Mhz", NULL)) { - /* The fixed 25MHz timer is available so let's use it */ - u = readl(timer_base + TIMER_CTRL_OFF); - writel(u | TIMER0_25MHZ, - timer_base + TIMER_CTRL_OFF); - timer_clk = 25000000; - } else { - unsigned long rate = 0; - struct clk *clk = of_clk_get(np, 0); - WARN_ON(IS_ERR(clk)); - rate = clk_get_rate(clk); - - u = readl(timer_base + TIMER_CTRL_OFF); - writel(u & ~(TIMER0_25MHZ), - timer_base + TIMER_CTRL_OFF); - - timer_clk = rate / TIMER_DIVIDER; - timer25Mhz = false; - } + if (timer25Mhz) - set = TIMER0_25MHZ; ++ set = TIMER0_25MHZ; + else + clr = TIMER0_25MHZ; + timer_ctrl_clrset(clr, set); + local_timer_ctrl_clrset(clr, set); /* * We use timer 0 as clocksource, and private(local) timer 0 @@@ -285,11 -279,41 +282,37 @@@ /* * Setup clockevent timer (interrupt-driven). */ - *__this_cpu_ptr(percpu_armada_370_xp_evt) = &armada_370_xp_clkevt; - res = request_percpu_irq(armada_370_xp_clkevt.irq, + res = request_percpu_irq(armada_370_xp_clkevt_irq, armada_370_xp_timer_interrupt, - armada_370_xp_clkevt.name, - percpu_armada_370_xp_evt); - if (!res) { - enable_percpu_irq(armada_370_xp_clkevt.irq, 0); -#ifdef CONFIG_LOCAL_TIMERS - local_timer_register(&armada_370_xp_local_timer_ops); -#endif - } + "armada_370_xp_per_cpu_tick", + armada_370_xp_evt); + /* Immediately configure the timer on the boot CPU */ + if (!res) + armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt)); } + + static void __init armada_xp_timer_init(struct device_node *np) + { + struct clk *clk = of_clk_get_by_name(np, "fixed"); + + /* The 25Mhz fixed clock is mandatory, and must always be available */ + BUG_ON(IS_ERR(clk)); + timer_clk = clk_get_rate(clk); + + armada_370_xp_timer_common_init(np); + } + CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer", + armada_xp_timer_init); + + static void __init armada_370_timer_init(struct device_node *np) + { + struct clk *clk = of_clk_get(np, 0); + + BUG_ON(IS_ERR(clk)); + timer_clk = clk_get_rate(clk) / TIMER_DIVIDER; + timer25Mhz = false; + + armada_370_xp_timer_common_init(np); + } + CLOCKSOURCE_OF_DECLARE(armada_370, "marvell,armada-370-timer", + armada_370_timer_init);