Make SMP timers standalone
Subsystems (8)
cover Make SMP timers standalone
The LOCAL_TIMERS infrastructure has a few limitations:
- It only allows one implementation to be compiled in, hence preventing a single kernel image to be booted hardware with different requirements (Tegra and MSM, for example).
- It is only supported on SMP, which is a problem on platforms where the local timer can be used on UP platforms (Cortex A15 being one).
The proposal is to convert local timer drivers to be "standalone" (not relying on the local timer infrastructure) and to use a CPU notifier to have the timer brought up or down on non-boot CPUs.
The SMP support code can then be simplified to only manage the boadcast timer, which is always installed, and leave the generic kernel code to pick the highest priority timer. CONFIG_LOCAL_TIMERS disappears in the process.
This patch series is based on my earlier series ("Consolidating GIC per-cpu interrupts"). Tested on EB11MP, VE A15, OMAP4 and Tegra.
Marc Zyngier (12):
ARM: local timers: allow smp_twd to be used standalone
ARM: local timers: switch realview to standalone smp_twd
ARM: local timers: switch vexpress to standalone smp_twd
ARM: local timers: remove localtimer.c from plat-versatile
ARM: local timers: switch tegra to standalone smp_twd
ARM: local timers: switch omap4 to standalone smp_twd
ARM: local timers: switch shmobile to standalone smp_twd
ARM: local timers: switch ux500 to standalone smp_twd
ARM: smp_twd: remove support for non-standalone version
ARM: local timers: make MSM timers standalone
ARM: local timers: make MCT timer standalone
ARM: local timers: Remove CONFIG_LOCAL_TIMERS support
arch/arm/Kconfig | 15 +---- arch/arm/include/asm/localtimer.h | 56 ----------------- arch/arm/include/asm/smp_twd.h | 14 +++-- arch/arm/kernel/smp.c | 56 +++++------------- arch/arm/kernel/smp_twd.c | 82 ++++++++++++++++++++++++-- arch/arm/mach-exynos4/mct.c | 75 ++++++++++++++++++------ arch/arm/mach-msm/timer.c | 64 +++++++++++++++----- arch/arm/mach-omap2/Kconfig | 2 +- arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/timer-mpu.c | 39 ------------ arch/arm/mach-omap2/timer.c | 38 ++++++++++-- arch/arm/mach-realview/Kconfig | 3 + arch/arm/mach-realview/realview_eb.c | 33 +++++++++- arch/arm/mach-realview/realview_pb11mp.c | 31 +++++++++- arch/arm/mach-realview/realview_pbx.c | 30 +++++++++- arch/arm/mach-shmobile/Kconfig | 1 + arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/include/mach/common.h | 3 + arch/arm/mach-shmobile/localtimer.c | 26 -------- arch/arm/mach-shmobile/platsmp.c | 1 - arch/arm/mach-shmobile/smp-sh73a0.c | 32 +++++++++- arch/arm/mach-shmobile/timer.c | 10 +++ arch/arm/mach-tegra/Kconfig | 1 + arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/localtimer.c | 26 -------- arch/arm/mach-tegra/timer.c | 34 +++++++++-- arch/arm/mach-ux500/Kconfig | 1 + arch/arm/mach-ux500/Makefile | 1 - arch/arm/mach-ux500/cpu.c | 40 ++++++++++-- arch/arm/mach-ux500/localtimer.c | 29 --------- arch/arm/mach-vexpress/Kconfig | 1 + arch/arm/mach-vexpress/ct-ca9x4.c | 29 ++++++++- arch/arm/plat-versatile/Makefile | 1 - arch/arm/plat-versatile/localtimer.c | 27 --------- 34 files changed, 462 insertions(+), 343 deletions(-) delete mode 100644 arch/arm/include/asm/localtimer.h delete mode 100644 arch/arm/mach-omap2/timer-mpu.c delete mode 100644 arch/arm/mach-shmobile/localtimer.c delete mode 100644 arch/arm/mach-tegra/localtimer.c delete mode 100644 arch/arm/mach-ux500/localtimer.c delete mode 100644 arch/arm/plat-versatile/localtimer.c
RFC PATCH 1/12 ARM: local timers: allow smp_twd to be used standalone
Allow smp_twd to be built in a "standalone" version, without relying on the CONFIG_LOCAL_TIMER infrastructure. It mainly relies on a CPU notifier block to stop or start the timer on the right CPU.
The CONFIG_ARM_SMP_TWD option selects the new behaviour.
--- arch/arm/Kconfig | 6 +++- arch/arm/include/asm/smp_twd.h | 9 +++++ arch/arm/kernel/smp_twd.c | 76 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 89 insertions(+), 2 deletions(-)
arch/arm/Kconfig +5 -1
@@ -1394,6 +1394,10 @@ config HAVE_ARM_TWD help This options enables support for the ARM timer and watchdog unit +config ARM_SMP_TWD + bool + select HAVE_ARM_TWD if SMP + choice prompt "Memory split" default VMSPLIT_3G
@@ -1432,7 +1436,7 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP + depends on SMP && !ARM_SMP_TWD default y select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT) help
arch/arm/include/asm/smp_twd.h +9 -0
@@ -19,10 +19,19 @@#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)struct clock_event_device ; +struct resource ;extern void __iomem *twd_base;void twd_timer_setup (struct clock_event_device *);void twd_timer_stop (struct clock_event_device *); +#ifdef CONFIG_HAVE_ARM_TWD +int twd_timer_register (struct resource *res,int res_nr); +#else +static inline int twd_timer_register (struct resource *res,int res_nr) +{ +return 0 ; +} +#endif #endif
arch/arm/kernel/smp_twd.c +75 -1
91 lines not on this page · raw message
Signature · 1 line
1.7.0.4
RFC PATCH 2/12 ARM: local timers: switch realview to standalone smp_twd
In reply to Marc ZyngierConvert the SMP RealView platforms to the standalone version of smp_twd.c. Since the timer calibration code requires another timer to be up and running, the actual initialisation is left to the late_timer_init hook.
Tested on EB-11MP.
--- arch/arm/mach-realview/Kconfig | 3 ++ arch/arm/mach-realview/realview_eb.c | 33 ++++++++++++++++++++++++++--- arch/arm/mach-realview/realview_pb11mp.c | 31 ++++++++++++++++++++++++--- arch/arm/mach-realview/realview_pbx.c | 30 ++++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 11 deletions(-)
arch/arm/mach-realview/Kconfig +3 -0
@@ -4,6 +4,7 @@ menu "RealView platform type" config MACH_REALVIEW_EB bool "Support RealView(R) Emulation Baseboard" select ARM_GIC + select ARM_SMP_TWD if SMP help Include support for the ARM(R) RealView(R) Emulation Baseboard platform.
@@ -40,6 +41,7 @@ config MACH_REALVIEW_PB11MP select ARM_GIC select HAVE_PATA_PLATFORM select ARCH_HAS_BARRIERS if SMP + select ARM_SMP_TWD if SMP help Include support for the ARM(R) RealView(R) Platform Baseboard for the ARM11MPCore. This platform has an on-board ARM11MPCore and has
@@ -80,6 +82,7 @@ config MACH_REALVIEW_PBX select HAVE_PATA_PLATFORM select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET select ZONE_DMA if SPARSEMEM + select ARM_SMP_TWD if SMP help Include support for the ARM(R) RealView(R) Platform Baseboard Explore.
arch/arm/mach-realview/realview_eb.c +29 -4
@@ -36,7 +36,7 @@#include <asm/pgtable.h> #include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <asm/mach/arch.h> #include <asm/mach/map.h>
@@ -391,6 +391,33 @@ static void realview_eb11mp_fixup(void) realview_eb_isp1761_resources[1 ].end =IRQ_EB11MP_USB ; } +#ifdef CONFIG_ARM_SMP_TWD +static struct resource twd_resources[]__initdata = { + { + .start =REALVIEW_EB11MP_TWD_BASE , + .end =REALVIEW_EB11MP_TWD_BASE +0xff , + .flags =IORESOURCE_MEM , + }, + { + .start =IRQ_LOCALTIMER , + .end =IRQ_LOCALTIMER , + .flags =IORESOURCE_IRQ , + }, +}; + +static void __init realview_eb_twd_init (void ) +{ +if (core_tile_eb11mp () ||core_tile_a9mp ()) { +int err =twd_timer_register (twd_resources, +ARRAY_SIZE (twd_resources)); +if (err) +pr_err ("twd_timer_register failed %d\n" , err); + } +} +#else +#define realview_eb_twd_init NULL +#endif +static void __init realview_eb_timer_init (void ) {unsigned int timer_irq;
@@ -401,9 +428,7 @@ static void __init realview_eb_timer_init(void) timer3_va_base =__io_address (REALVIEW_EB_TIMER2_3_BASE ) +0x20 ;if (core_tile_eb11mp () ||core_tile_a9mp ()) { -#ifdef CONFIG_LOCAL_TIMERS - twd_base =__io_address (REALVIEW_EB11MP_TWD_BASE ); -#endif + late_time_init = realview_eb_twd_init; timer_irq =IRQ_EB11MP_TIMER0_1 ; }else timer_irq =IRQ_EB_TIMER0_1 ;
arch/arm/mach-realview/realview_pb11mp.c +27 -4
@@ -36,7 +36,7 @@#include <asm/pgtable.h> #include <asm/hardware/gic.h> #include <asm/hardware/cache-l2x0.h> -#include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <asm/mach/arch.h> #include <asm/mach/flash.h>
@@ -298,6 +298,31 @@ static void __init gic_init_irq(void)gic_cascade_irq (1 ,IRQ_TC11MP_PB_IRQ1 ); } +#ifdef CONFIG_ARM_SMP_TWD +static struct resource realview_pb11mp_twd_resources[]__initdata = { + { + .start =REALVIEW_TC11MP_TWD_BASE , + .end =REALVIEW_TC11MP_TWD_BASE +0x10 , + .flags =IORESOURCE_MEM , + }, + { + .start =IRQ_LOCALTIMER , + .end =IRQ_LOCALTIMER , + .flags =IORESOURCE_IRQ , + }, +}; + +static void __init realview_pb11mp_twd_init (void ) +{ +int err =twd_timer_register (realview_pb11mp_twd_resources, +ARRAY_SIZE (realview_pb11mp_twd_resources)); +if (err) +pr_err ("twd_timer_register failed %d\n" , err); +} +#else +#define realview_pb11mp_twd_init NULL +#endif +static void __init realview_pb11mp_timer_init (void ) { timer0_va_base =__io_address (REALVIEW_PB11MP_TIMER0_1_BASE );
@@ -305,10 +330,8 @@ static void __init realview_pb11mp_timer_init(void) timer2_va_base =__io_address (REALVIEW_PB11MP_TIMER2_3_BASE ); timer3_va_base =__io_address (REALVIEW_PB11MP_TIMER2_3_BASE ) +0x20 ; -#ifdef CONFIG_LOCAL_TIMERS - twd_base =__io_address (REALVIEW_TC11MP_TWD_BASE ); -#endif realview_timer_init (IRQ_TC11MP_TIMER0_1 ); + late_time_init = realview_pb11mp_twd_init; }static struct sys_timer realview_pb11mp_timer = {
arch/arm/mach-realview/realview_pbx.c +27 -3
@@ -301,6 +301,31 @@ static void __init gic_init_irq(void) } } +#ifdef CONFIG_ARM_SMP_TWD +static struct resource realview_pbx_twd_resources[]__initdata = { + { + .start =REALVIEW_PBX_TILE_TWD_BASE , + .end =REALVIEW_PBX_TILE_TWD_BASE +0x10 , + .flags =IORESOURCE_MEM , + }, + { + .start =IRQ_LOCALTIMER , + .end =IRQ_LOCALTIMER , + .flags =IORESOURCE_IRQ , + }, +}; + +static void __init realview_pbx_twd_init (void ) +{ +int err =twd_timer_register (realview_pbx_twd_resources, +ARRAY_SIZE (realview_pbx_twd_resources)); +if (err) +pr_err ("twd_timer_register failed %d\n" , err); +} +#else +#define realview_pbx_twd_init NULL +#endif +static void __init realview_pbx_timer_init (void ) { timer0_va_base =__io_address (REALVIEW_PBX_TIMER0_1_BASE );
@@ -308,10 +333,9 @@ static void __init realview_pbx_timer_init(void) timer2_va_base =__io_address (REALVIEW_PBX_TIMER2_3_BASE ); timer3_va_base =__io_address (REALVIEW_PBX_TIMER2_3_BASE ) +0x20 ; -#ifdef CONFIG_LOCAL_TIMERS if (core_tile_pbx11mp () ||core_tile_pbxa9mp ()) - twd_base =__io_address (REALVIEW_PBX_TILE_TWD_BASE ); -#endif + late_time_init = realview_pbx_twd_init; +realview_timer_init (IRQ_PBX_TIMER0_1 ); }
Signature · 1 line
1.7.0.4
RFC PATCH 3/12 ARM: local timers: switch vexpress to standalone smp_twd
In reply to Marc ZyngierConvert the Versatile Express platform to the standalone version of smp_twd.c. Since the timer calibration code requires another timer to be up and running, the actual initialisation is left to the late_timer_init hook.
--- arch/arm/mach-vexpress/Kconfig | 1 + arch/arm/mach-vexpress/ct-ca9x4.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-)
arch/arm/mach-vexpress/Kconfig +1 -0
@@ -5,6 +5,7 @@ config ARCH_VEXPRESS_CA9X4 bool "Versatile Express Cortex-A9x4 tile" select CPU_V7 select ARM_GIC + select ARM_SMP_TWD select ARM_ERRATA_720789 select ARM_ERRATA_751472 select ARM_ERRATA_753970
arch/arm/mach-vexpress/ct-ca9x4.c +26 -3
@@ -53,9 +53,6 @@ static struct map_desc ct_ca9x4_io_desc[] __initdata = {static void __init ct_ca9x4_map_io (void ) { -#ifdef CONFIG_LOCAL_TIMERS - twd_base =MMIO_P2V (A9_MPCORE_TWD ); -#endif iotable_init (ct_ca9x4_io_desc,ARRAY_SIZE (ct_ca9x4_io_desc)); }
@@ -191,9 +188,35 @@ static struct platform_device pmu_device = { .resource = pmu_resources, }; +#ifdef CONFIG_ARM_SMP_TWD +static struct resource ca9x4_twd_resources[]__initdata = { + { + .start =A9_MPCORE_TWD , + .end =A9_MPCORE_TWD +0x10 , + .flags =IORESOURCE_MEM , + }, + { + .start =IRQ_LOCALTIMER , + .end =IRQ_LOCALTIMER , + .flags =IORESOURCE_IRQ , + }, +}; + +static void __init ca9x4_twd_init (void ) +{ +int err =twd_timer_register (ca9x4_twd_resources, +ARRAY_SIZE (ca9x4_twd_resources)); +if (err) +pr_err ("twd_timer_register failed %d\n" , err); +} +#else +#define ca9x4_twd_init NULL +#endif +static void __init ct_ca9x4_init_early (void ) {clkdev_add_table (lookups,ARRAY_SIZE (lookups)); + late_time_init = ca9x4_twd_init; }static void __init ct_ca9x4_init (void )
Signature · 1 line
1.7.0.4
RFC PATCH 4/12 ARM: local timers: remove localtimer.c from plat-versatile
In reply to Marc ZyngierAs the localtimer infrastructure is not use anymore by any of the Versatile platforms, remove localtimer.c.
--- arch/arm/plat-versatile/Makefile | 1 - arch/arm/plat-versatile/localtimer.c | 27 --------------------------- 2 files changed, 0 insertions(+), 28 deletions(-) delete mode 100644 arch/arm/plat-versatile/localtimer.c
arch/arm/plat-versatile/Makefile +0 -1
@@ -1,5 +1,4 @@ obj-y := clock.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
arch/arm/plat-versatile/localtimer.c deleted +0 -27
@@ -1,27 +0,0 @@ -/* -* linux/arch/arm/plat-versatile/localtimer.c -* -* Copyright (C) 2002 ARM Ltd. -* All Rights Reserved -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -*/ -#include <linux/init.h> -#include <linux/smp.h> -#include <linux/clockchips.h> - -#include <asm/smp_twd.h> -#include <asm/localtimer.h> -#include <mach/irqs.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ - evt->irq =IRQ_LOCALTIMER ; -twd_timer_setup (evt); -return 0 ; -}
Signature · 1 line
1.7.0.4
RFC PATCH 5/12 ARM: local timers: switch tegra to standalone smp_twd
In reply to Marc ZyngierConvert the Tegra-2 platforms to the standalone version of smp_twd.c. Since the timer calibration code requires another timer to be up and running, the actual initialisation is left to the late_timer_init hook.
Tested on Harmony.
--- arch/arm/mach-tegra/Kconfig | 1 + arch/arm/mach-tegra/Makefile | 2 +- arch/arm/mach-tegra/localtimer.c | 26 -------------------------- arch/arm/mach-tegra/timer.c | 34 +++++++++++++++++++++++++++++----- 4 files changed, 31 insertions(+), 32 deletions(-) delete mode 100644 arch/arm/mach-tegra/localtimer.c
arch/arm/mach-tegra/Kconfig +1 -0
@@ -9,6 +9,7 @@ config ARCH_TEGRA_2x_SOC bool "Tegra 2 family" select CPU_V7 select ARM_GIC + select ARM_SMP_TWD select ARCH_REQUIRE_GPIOLIB select USB_ARCH_HAS_EHCI if USB_SUPPORT select USB_ULPI if USB_SUPPORT
arch/arm/mach-tegra/Makefile +1 -1
@@ -11,7 +11,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o -obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
arch/arm/mach-tegra/localtimer.c deleted +0 -26
@@ -1,26 +0,0 @@ -/* -* arch/arm/mach-tegra/localtimer.c -* -* Copyright (C) 2002 ARM Ltd. -* All Rights Reserved -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -*/ -#include <linux/init.h> -#include <linux/smp.h> -#include <linux/clockchips.h> -#include <asm/irq.h> -#include <asm/smp_twd.h> -#include <asm/localtimer.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ - evt->irq =IRQ_LOCALTIMER ; -twd_timer_setup (evt); -return 0 ; -}
arch/arm/mach-tegra/timer.c +29 -5
@@ -27,9 +27,10 @@#include <linux/clocksource.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/ioport.h> #include <asm/mach/time.h> -#include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <asm/sched_clock.h> #include <mach/iomap.h>
@@ -179,6 +180,31 @@ static struct irqaction tegra_timer_irq = { .irq = INT_TMR3, }; +#ifdef CONFIG_ARM_SMP_TWD +static struct resource tegra_twd_resources[]__initdata = { + { + .start =TEGRA_ARM_PERIF_BASE +0x600 , + .end =TEGRA_ARM_PERIF_BASE +0x610 , + .flags =IORESOURCE_MEM , + }, + { + .start =IRQ_LOCALTIMER , + .end =IRQ_LOCALTIMER , + .flags =IORESOURCE_IRQ , + }, +}; + +static void __init tegra_twd_init (void ) +{ +int err =twd_timer_register (tegra_twd_resources, +ARRAY_SIZE (tegra_twd_resources)); +if (err) +pr_err ("twd_timer_register failed %d\n" , err); +} +#else +#define tegra_twd_init NULL +#endif +static void __init tegra_init_timer (void ) {struct clk *clk;
@@ -197,10 +223,6 @@ static void __init tegra_init_timer(void)BUG_ON (IS_ERR (clk));clk_enable (clk); -#ifdef CONFIG_HAVE_ARM_TWD - twd_base =IO_ADDRESS (TEGRA_ARM_PERIF_BASE +0x600 ); -#endif -switch (rate) {case 12000000 :timer_writel (0x000b ,TIMERUS_USEC_CFG );
@@ -241,6 +263,8 @@ static void __init tegra_init_timer(void) tegra_clockevent.cpumask = cpu_all_mask; tegra_clockevent.irq = tegra_timer_irq.irq;clockevents_register_device (&tegra_clockevent); + + late_time_init = tegra_twd_init; }struct sys_timer tegra_timer = {
Signature · 1 line
1.7.0.4
RFC PATCH 6/12 ARM: local timers: switch omap4 to standalone smp_twd
In reply to Marc ZyngierConvert the OMAP4 platforms to the standalone version of smp_twd.c. Since the timer calibration code requires another timer to be up and running, the actual initialisation is left to the late_timer_init hook.
Tested on a Pandaboard.
--- arch/arm/mach-omap2/Kconfig | 2 +- arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/timer-mpu.c | 39 --------------------------------------- arch/arm/mach-omap2/timer.c | 38 +++++++++++++++++++++++++++++++++----- 4 files changed, 34 insertions(+), 46 deletions(-) delete mode 100644 arch/arm/mach-omap2/timer-mpu.c
arch/arm/mach-omap2/Kconfig +1 -1
@@ -44,7 +44,7 @@ config ARCH_OMAP4 depends on ARCH_OMAP2PLUS select CPU_V7 select ARM_GIC - select LOCAL_TIMERS if SMP + select ARM_SMP_TWD select PL310_ERRATA_588369 select PL310_ERRATA_727915 select ARM_ERRATA_720789
arch/arm/mach-omap2/Makefile +0 -1
@@ -22,7 +22,6 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o # SMP support ONLY available for OMAP4 obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o -obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o obj-$(CONFIG_ARCH_OMAP4) += omap44xx-smc.o omap4-common.o
arch/arm/mach-omap2/timer-mpu.c deleted +0 -39
@@ -1,39 +0,0 @@ -/* -* The MPU local timer source file. In OMAP4, both cortex-a9 cores have -* own timer in it's MPU domain. These timers will be driving the -* linux kernel SMP tick framework when active. These timers are not -* part of the wake up domain. -* -* Copyright (C) 2009 Texas Instruments, Inc. -* -* Author: -* Santosh Shilimkar <[email protected]> -* -* This file is based on arm realview smp platform file. -* Copyright (C) 2002 ARM Ltd. -* -* 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/init.h> -#include <linux/smp.h> -#include <linux/clockchips.h> -#include <asm/irq.h> -#include <asm/smp_twd.h> -#include <asm/localtimer.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ -/* Local timers are not supprted on OMAP4430 ES1.0 */ -if (omap_rev () ==OMAP4430_REV_ES1_0 ) -return -ENXIO ; - - evt->irq =OMAP44XX_IRQ_LOCALTIMER ; -twd_timer_setup (evt); -return 0 ; -} -
arch/arm/mach-omap2/timer.c +33 -5
@@ -38,7 +38,7 @@#include <asm/mach/time.h> #include <plat/dmtimer.h> -#include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <asm/sched_clock.h> #include <plat/common.h> #include <plat/omap_hwmod.h>
@@ -328,15 +328,43 @@ OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE, OMAP_SYS_TIMER(3_secure)#endif +#ifdef CONFIG_ARM_SMP_TWD +static struct resource omap4_twd_resources[]__initdata = { + { + .start =OMAP44XX_LOCAL_TWD_BASE , + .end =OMAP44XX_LOCAL_TWD_BASE +0x10 , + .flags =IORESOURCE_MEM , + }, + { + .start =OMAP44XX_IRQ_LOCALTIMER , + .end =OMAP44XX_IRQ_LOCALTIMER , + .flags =IORESOURCE_IRQ , + }, +}; + +static void __init omap4_twd_init (void ) +{ +int err; + +/* Local timers are not supprted on OMAP4430 ES1.0 */ +if (omap_rev () ==OMAP4430_REV_ES1_0 ) +return ; + + err =twd_timer_register (omap4_twd_resources, +ARRAY_SIZE (omap4_twd_resources)); +if (err) +pr_err ("twd_timer_register failed %d\n" , err); +} +#else +#define omap4_twd_init NULL +#endif +#ifdef CONFIG_ARCH_OMAP4 static void __init omap4_timer_init (void ) { -#ifdef CONFIG_LOCAL_TIMERS - twd_base =ioremap (OMAP44XX_LOCAL_TWD_BASE ,SZ_256 ); -BUG_ON (!twd_base); -#endif omap2_gp_clockevent_init (1 ,OMAP4_CLKEV_SOURCE );omap2_gp_clocksource_init (2 ,OMAP4_MPU_SOURCE ); + late_time_init = omap4_twd_init; } OMAP_SYS_TIMER(4)#endif
Signature · 1 line
1.7.0.4
RFC PATCH 7/12 ARM: local timers: switch shmobile to standalone smp_twd
In reply to Marc ZyngierConvert the SMP shmobile platforms to the standalone version of smp_twd.c. As shmobile is already using the late_time_init hook, a private hook is added to initialise the TWD driver once the platform timer is up and running.
--- arch/arm/mach-shmobile/Kconfig | 1 + arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/include/mach/common.h | 3 ++ arch/arm/mach-shmobile/localtimer.c | 26 --------------------- arch/arm/mach-shmobile/platsmp.c | 1 - arch/arm/mach-shmobile/smp-sh73a0.c | 32 +++++++++++++++++++++++-- arch/arm/mach-shmobile/timer.c | 10 ++++++++ 7 files changed, 43 insertions(+), 31 deletions(-) delete mode 100644 arch/arm/mach-shmobile/localtimer.c
arch/arm/mach-shmobile/Kconfig +1 -0
@@ -23,6 +23,7 @@ config ARCH_SH7372 config ARCH_SH73A0 bool "SH-Mobile AG5 (R8A73A00)" select CPU_V7 + select ARM_SMP_TWD select SH_CLK_CPG select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_GIC
arch/arm/mach-shmobile/Makefile +0 -1
@@ -14,7 +14,6 @@ obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o # SMP objects smp-y := platsmp.o headsmp.o smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o -smp-$(CONFIG_LOCAL_TIMERS) += localtimer.o smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o # Pinmux setup
arch/arm/mach-shmobile/include/mach/common.h +3 -0
@@ -53,4 +53,7 @@ extern void sh73a0_secondary_init(unsigned int cpu);extern int sh73a0_boot_secondary (unsigned int cpu);extern void sh73a0_smp_prepare_cpus (void ); +struct resource ; +extern void shmobile_local_timer_register (void (*)(void )); +#endif /* __ARCH_MACH_COMMON_H */
arch/arm/mach-shmobile/localtimer.c deleted +0 -26
@@ -1,26 +0,0 @@ -/* -* SMP support for R-Mobile / SH-Mobile - local timer portion -* -* Copyright (C) 2010 Magnus Damm -* -* Based on vexpress, Copyright (C) 2002 ARM Ltd, All Rights Reserved -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -*/ -#include <linux/init.h> -#include <linux/smp.h> -#include <linux/clockchips.h> -#include <asm/smp_twd.h> -#include <asm/localtimer.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ - evt->irq =29 ; -twd_timer_setup (evt); -return 0 ; -}
arch/arm/mach-shmobile/platsmp.c +0 -1
@@ -17,7 +17,6 @@#include <linux/smp.h> #include <linux/io.h> #include <asm/hardware/gic.h> -#include <asm/localtimer.h> #include <asm/mach-types.h> #include <mach/common.h>
arch/arm/mach-shmobile/smp-sh73a0.c +29 -3
@@ -22,6 +22,7 @@#include <linux/smp.h> #include <linux/spinlock.h> #include <linux/io.h> +#include <linux/ioport.h> #include <mach/common.h> #include <asm/smp_scu.h> #include <asm/smp_twd.h>
@@ -41,6 +42,31 @@ static void __iomem *scu_base_addr(void)static DEFINE_SPINLOCK (scu_lock);static unsigned long tmp; +#ifdef CONFIG_ARM_SMP_TWD +static struct resource sh73a0_twd_resources[]__initdata = { + { + .start =0xf0000600 , + .end =0xf0000600 +0x10 , + .flags =IORESOURCE_MEM , + }, + { + .start =29 , + .end =29 , + .flags =IORESOURCE_IRQ , + }, +}; + +static void __init sh73a0_twd_init (void ) +{ +int err =twd_timer_register (sh73a0_twd_resources, +ARRAY_SIZE (sh73a0_twd_resources)); +if (err) +pr_err ("twd_timer_register failed %d\n" , err); +} +#else +#define sh73a0_twd_init NULL +#endif +static void modify_scu_cpu_psr (unsigned long set,unsigned long clr) {void __iomem *scu_base =scu_base_addr ();
@@ -59,9 +85,9 @@ unsigned int __init sh73a0_get_core_count(void) {void __iomem *scu_base =scu_base_addr (); -#ifdef CONFIG_HAVE_ARM_TWD -/* twd_base needs to be initialized before percpu_timer_setup() */ - twd_base = (void __iomem *)0xf0000600 ; + +#ifdef CONFIG_ARM_SMP_TWD +shmobile_local_timer_register (sh73a0_twd_init);#endif return scu_get_core_count (scu_base);
arch/arm/mach-shmobile/timer.c +10 -0
@@ -19,8 +19,11 @@* */ #include <linux/platform_device.h> +#include <mach/common.h> #include <asm/mach/time.h> +static void (*local_timer_hook)(void )__initdata ; +static void __init shmobile_late_time_init (void ) {/*
@@ -34,6 +37,8 @@ static void __init shmobile_late_time_init(void)*/ early_platform_driver_register_all ("earlytimer" );early_platform_driver_probe ("earlytimer" ,2 ,0 ); +if (local_timer_hook) +local_timer_hook (); }static void __init shmobile_timer_init (void )
@@ -41,6 +46,11 @@ static void __init shmobile_timer_init(void) late_time_init = shmobile_late_time_init; } +void __init shmobile_local_timer_register (void (*hook)(void )) +{ + local_timer_hook = hook; +} +struct sys_timer shmobile_timer = { .init = shmobile_timer_init, };
Signature · 1 line
1.7.0.4
RFC PATCH 8/12 ARM: local timers: switch ux500 to standalone smp_twd
In reply to Marc ZyngierConvert the ux500 platforms to the standalone version of smp_twd.c. Since the timer calibration code requires another timer to be up and running, the actual initialisation is left to the late_timer_init hook.
--- arch/arm/mach-ux500/Kconfig | 1 + arch/arm/mach-ux500/Makefile | 1 - arch/arm/mach-ux500/cpu.c | 40 +++++++++++++++++++++++++++++++------ arch/arm/mach-ux500/localtimer.c | 29 --------------------------- 4 files changed, 34 insertions(+), 37 deletions(-) delete mode 100644 arch/arm/mach-ux500/localtimer.c
arch/arm/mach-ux500/Kconfig +1 -0
@@ -4,6 +4,7 @@ config UX500_SOC_COMMON bool default y select ARM_GIC + select ARM_SMP_TWD select HAS_MTU select ARM_ERRATA_753970
arch/arm/mach-ux500/Makefile +0 -1
@@ -14,7 +14,6 @@ obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o
arch/arm/mach-ux500/cpu.c +33 -7
@@ -15,7 +15,7 @@#include <asm/hardware/cache-l2x0.h> #include <asm/hardware/gic.h> #include <asm/mach/map.h> -#include <asm/localtimer.h> +#include <asm/smp_twd.h> #include <plat/mtu.h> #include <mach/hardware.h>
@@ -120,15 +120,40 @@ static int ux500_l2x0_init(void)early_initcall (ux500_l2x0_init);#endif +#ifdef CONFIG_ARM_SMP_TWD +static struct resource ux500_twd_resources[]__initdata = { + { + .flags =IORESOURCE_MEM , + }, + { + .start =IRQ_LOCALTIMER , + .end =IRQ_LOCALTIMER , + .flags =IORESOURCE_IRQ , + }, +}; + +static void __init ux500_twd_init (void ) +{ +int err =twd_timer_register (ux500_twd_resources, +ARRAY_SIZE (ux500_twd_resources)); +if (err) +pr_err ("twd_timer_register failed %d\n" , err); +} +#else +#define ux500_twd_init NULL +#endif +static void __init ux500_timer_init (void ) { -#ifdef CONFIG_LOCAL_TIMERS +#ifdef CONFIG_ARM_SMP_TWD /* Setup the local timer base */ -if (cpu_is_u5500 ()) - twd_base =__io_address (U5500_TWD_BASE ); -else if (cpu_is_u8500 ()) - twd_base =__io_address (U8500_TWD_BASE ); -else +if (cpu_is_u5500 ()) { + ux500_twd_resources[0 ].start =U5500_TWD_BASE ; + ux500_twd_resources[0]end = U5500_TWD_BASE + 0x10; + }else if (cpu_is_u8500 ()) { + ux500_twd_resources[0 ].start =U8500_TWD_BASE ; + ux500_twd_resources[0]end = U8500_TWD_BASE + 0x10; + }else ux500_unknown_soc ();#endif if (cpu_is_u5500 ())
@@ -141,6 +166,7 @@ static void __init ux500_timer_init(void)ux500_unknown_soc ();nmdk_timer_init (); + late_time_init = ux500_twd_init; }struct sys_timer ux500_timer = {
arch/arm/mach-ux500/localtimer.c deleted +0 -29
@@ -1,29 +0,0 @@ -/* -* Copyright (C) 2008-2009 ST-Ericsson -* Srinidhi Kasagar <[email protected]> -* -* This file is heavily based on relaview platform, almost a copy. -* -* Copyright (C) 2002 ARM Ltd. -* -* 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/init.h> -#include <linux/smp.h> -#include <linux/clockchips.h> - -#include <asm/irq.h> -#include <asm/smp_twd.h> -#include <asm/localtimer.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ - evt->irq =IRQ_LOCALTIMER ; -twd_timer_setup (evt); -return 0 ; -}
Signature · 1 line
1.7.0.4
RFC PATCH 8/12 ARM: local timers: switch ux500 to standalone smp_twd
Quoted 8 lines · Marc Zyngier
Convert the ux500 platforms to the standalone version of
smp_twd.c. Since the timer calibration code requires another timer to be up and running, the actual initialisation is left to thelate_timer_inithook.Cc Linus Walleij<[email protected]>Signed-off-by Marc Zyngier<[email protected]>
So it switch to ioremap():ing the TWD too.
Seems like a pretty good idea.
Yours,
Linus Walleij
RFC PATCH 9/12 ARM: smp_twd: remove support for non-standalone version
In reply to Marc ZyngierThere is no in-tree platform using both CONFIG_LOCAL_TIMERS and CONFIG_HAVE_ARM_TWD. As such, some code can be removed and some exported function of smp_twd.c can be made static.
--- arch/arm/Kconfig | 1 - arch/arm/include/asm/localtimer.h | 10 ---------- arch/arm/include/asm/smp_twd.h | 5 ----- arch/arm/kernel/smp_twd.c | 10 +++------- 4 files changed, 3 insertions(+), 23 deletions(-)
arch/arm/Kconfig +0 -1
@@ -1438,7 +1438,6 @@ config LOCAL_TIMERS bool "Use local timer interrupts" depends on SMP && !ARM_SMP_TWD default y - select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT) help Enable support for local timers on SMP platforms, rather then the legacy IPI broadcast method. Local timers allows the system
arch/arm/include/asm/localtimer.h +0 -10
@@ -21,21 +21,11 @@ void percpu_timer_setup(void);#ifdef CONFIG_LOCAL_TIMERS -#ifdef CONFIG_HAVE_ARM_TWD - -#include "smp_twd.h" - -#define local_timer_stop (c) twd_timer_stop((c)) - -#else -/* * Stop the local timer */ void local_timer_stop (struct clock_event_device *); -#endif -/* * Setup a local timer interrupt for a CPU. */
arch/arm/include/asm/smp_twd.h +0 -5
@@ -18,13 +18,8 @@#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) -struct clock_event_device ;struct resource ; -extern void __iomem *twd_base; - -void twd_timer_setup (struct clock_event_device *); -void twd_timer_stop (struct clock_event_device *);#ifdef CONFIG_HAVE_ARM_TWD int twd_timer_register (struct resource *res,int res_nr);#else
arch/arm/kernel/smp_twd.c +3 -7
@@ -20,11 +20,9 @@#include <linux/io.h> #include <asm/smp_twd.h> -#include <asm/localtimer.h> #include <asm/hardware/gic.h> -/* set up by the platform code */ -void __iomem *twd_base; +static void __iomem *twd_base;static unsigned long twd_timer_rate;
@@ -79,7 +77,7 @@ static irqreturn_t twd_timer_handler(int irq, void *dev_id)return IRQ_NONE ; } -void twd_timer_stop (struct clock_event_device *clk) +static void twd_timer_stop (struct clock_event_device *clk) {twd_set_mode (CLOCK_EVT_MODE_UNUSED , clk);gic_free_ppi (clk->irq, clk);
@@ -127,7 +125,7 @@ static void __cpuinit twd_calibrate_rate(void)/* * Setup the local clock events for a CPU. */ -void __cpuinit twd_timer_setup (struct clock_event_device *clk) +static void __cpuinit twd_timer_setup (struct clock_event_device *clk) {int err;
@@ -152,7 +150,6 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) clk->name, clk->irq, smp_processor_id(), err); } -#ifdef CONFIG_ARM_SMP_TWD static struct clock_event_device __percpu *twd_evt;static int twd_ppi;
@@ -223,4 +220,3 @@ int twd_timer_register(struct resource *res, int res_nr)return 0 ; } -#endif
Signature · 1 line
1.7.0.4
RFC PATCH 10/12 ARM: local timers: make MSM timers standalone
In reply to Marc ZyngierFollowing the same pattern used for smp_twd, allow the MSM timers to be built in standalone, without relying on the CONFIG_LOCAL_TIMER infrastructure and use a CPU notifier block to stop or start the timer on the secondary CPU.
--- arch/arm/Kconfig | 2 +- arch/arm/mach-msm/timer.c | 64 +++++++++++++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 18 deletions(-)
arch/arm/Kconfig +1 -1
@@ -1436,7 +1436,7 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && !ARM_SMP_TWD + depends on SMP && !ARM_SMP_TWD && !ARCH_MSM default y help Enable support for local timers on SMP platforms, rather then the
arch/arm/mach-msm/timer.c +47 -17
116 lines not on this page · raw message
Signature · 1 line
1.7.0.4
RFC PATCH 11/12 ARM: local timers: make MCT timer standalone
In reply to Marc ZyngierFollowing the same pattern used for smp_twd, allow the MCT timers to be built in standalone, without relying on the CONFIG_LOCAL_TIMER infrastructure and use a CPU notifier block to stop or start the timer on the right CPU.
--- arch/arm/Kconfig | 2 +- arch/arm/mach-exynos4/mct.c | 75 ++++++++++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 19 deletions(-)
arch/arm/Kconfig +1 -1
@@ -1436,7 +1436,7 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && !ARM_SMP_TWD && !ARCH_MSM + depends on SMP && !ARM_SMP_TWD && !ARCH_MSM && !EXYNOS4_MCT default y help Enable support for local timers on SMP platforms, rather then the
arch/arm/mach-exynos4/mct.c +57 -18
151 lines not on this page · raw message
Signature · 1 line
1.7.0.4
RFC PATCH 12/12 ARM: local timers: Remove CONFIG_LOCAL_TIMERS support
In reply to Marc ZyngierLocal timer support in arch/arm is now completely unused, as all in-tree platforms are using standalone timers.
It allows us to simplify the code, only preserving the broadcast timer. The broadcast timer is always installed, and we leave it up to the kernel to pick the more suitable timer (usually the one with the highest priority).
--- arch/arm/Kconfig | 10 ------ arch/arm/include/asm/localtimer.h | 46 ------------------------------ arch/arm/kernel/smp.c | 56 +++++++++--------------------------- 3 files changed, 14 insertions(+), 98 deletions(-) delete mode 100644 arch/arm/include/asm/localtimer.h
arch/arm/Kconfig +0 -10
@@ -1434,16 +1434,6 @@ config HOTPLUG_CPU Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. -config LOCAL_TIMERS - bool "Use local timer interrupts" - depends on SMP && !ARM_SMP_TWD && !ARCH_MSM && !EXYNOS4_MCT - default y - help - Enable support for local timers on SMP platforms, rather then the - legacy IPI broadcast method. Local timers allows the system - accounting to be spread across the timer interval, preventing a - "thundering herd" at every timer tick. - source kernel/Kconfig.preempt config HZ
arch/arm/include/asm/localtimer.h deleted +0 -46
46 lines not on this page · raw message
arch/arm/kernel/smp.c +14 -42
117 lines not on this page · raw message
Signature · 1 line
1.7.0.4