Make SMP timers standalone
Subsystems (11)
v2 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 on 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.
Tested on EB11MP, OMAP4 and Tegra. Based on next-20111222.
Quoted 1 line
From v1:
- Various bug fixes
- DT support for smp_twd
- Added support for highbank and imx6q
Marc Zyngier (15):
ARM: local timers: allow smp_twd to be used standalone
ARM: smp_twd: add device tree support
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: local timers: switch highbank to standalone smp_twd
ARM: local timers: switch imx6q to standalone smp_twd
ARM: smp_twd: remove support for non-standalone version
ARM: local timers: make MCT timer standalone
ARM: local timers: make MSM timers standalone
ARM: local timers: Remove CONFIG_LOCAL_TIMERS support
Documentation/devicetree/bindings/arm/twd.txt | 29 +++++ arch/arm/Kconfig | 15 +-- arch/arm/include/asm/localtimer.h | 57 --------- arch/arm/include/asm/smp_twd.h | 19 +++- arch/arm/kernel/smp.c | 54 ++------- arch/arm/kernel/smp_twd.c | 155 +++++++++++++++++++------ arch/arm/mach-exynos/mct.c | 85 ++++++++++---- arch/arm/mach-highbank/Makefile | 1 - arch/arm/mach-highbank/highbank.c | 13 ++ arch/arm/mach-highbank/localtimer.c | 40 ------- arch/arm/mach-imx/Makefile | 1 - arch/arm/mach-imx/localtimer.c | 35 ------ arch/arm/mach-imx/mach-imx6q.c | 12 ++ arch/arm/mach-msm/timer.c | 92 +++++++++++---- 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/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/localtimer.c | 29 ----- arch/arm/mach-ux500/timer.c | 41 ++++++- 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 ----- 40 files changed, 591 insertions(+), 460 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/twd.txt delete mode 100644 arch/arm/include/asm/localtimer.h delete mode 100644 arch/arm/mach-highbank/localtimer.c delete mode 100644 arch/arm/mach-imx/localtimer.c 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
Signature · 1 line
1.7.7.1
PATCH v2 1/15 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 | 79 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 2 deletions(-)
arch/arm/Kconfig +5 -1
@@ -1522,6 +1522,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
@@ -1560,7 +1564,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 +78 -1
99 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v2 1/15 ARM: local timers: allow smp_twd to be used standalone
arch/arm/kernel/smp_twd.c void __cpuinit twd_timer_setup(struct clock_event_device *clk) · line 260
Quoted 11 lines · Marc Zyngier
arch/arm/kernel/smp_twd.c +11
-0+ twd_clock_event = alloc_percpu(struct clock_event_device); +if (!twd_base || !twd_clock_event) { +iounmap (twd_base); + twd_base =NULL ; +free_percpu (twd_clock_event); +return -ENOMEM ; + } + +/* Immediately configure the timer on the boot CPU */ + clk =per_cpu_ptr (twd_clock_event,smp_processor_id ()); +twd_setup (clk);
This is insufficient. A proper local timer has this:
evt->cpumask = cpumask_of(cpu); evt->broadcast = smp_timer_broadcast;
as well as all the rest of the normal clock event stuff. The broadcast callback is used when the timer core wants to broadcast the timer tick to other CPUs - see tick_do_broadcast() in kernel/time/tick-broadcast.c. The selection of which clock event device to use is rather 'optimized' for current conditions, and registering local timers without this is likely to oops the kernel at some point.
I don't think you can register separate clock event devices for use as the broadcast device vs the local timer device.
So, either you _have_ to use the SMP supplied version, or we make the broadcast function public and have everyone conditionally set that up, or something else... either way this is getting exceedingly messy.
That's why I believe it's far simpler to just say no to using twd as a global timer, and just keep it for SMP local timer purposes.
PATCH v2 2/15 ARM: smp_twd: add device tree support
In reply to Marc ZyngierAdd bindings to support DT discovery of the ARM Timer Watchdog (aka TWD). Only the timer side is converted by this patch.
--- Documentation/devicetree/bindings/arm/twd.txt | 29 +++++++++++ arch/arm/include/asm/smp_twd.h | 7 +++ arch/arm/kernel/smp_twd.c | 67 +++++++++++++++++++----- 3 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/twd.txt
Documentation/devicetree/bindings/arm/twd.txt new file +29 -0
@@ -0,0 +1,29 @@ +* ARM Timer Watchdog + +ARM 11MP, Cortex-A5 and Cortex-A9 are often associated with a per-core +Timer-Watchdog (aka TWD), which provides both a per-cpu local timer +and watchdog. + +The TWD is usually attached to a GIC to deliver its two per-processor +interrupts. + +Main node required properties: + +- compatible : Should be one of: + "arm,cortex-a9-twd" + "arm,cortex-a5-twd" + "arm,arm11mp-twd" + "arm,smp-twd" + +- interrupts : Two interrupts to each core, the first one for the + timer, the second one for the watchdog. + +- reg : Specify the base address and the size of the TWD. + +Example: + + twd at 2c000600 { + compatible = "arm,arm11mp-twd", "arm,smp-twd"; + reg = <0x2c000600 0x100>; + interrupts = <1 13 0xf01 1 14 0xf01>; + };
arch/arm/include/asm/smp_twd.h +7 -0
@@ -20,6 +20,7 @@struct clock_event_device ;struct resource ; +struct of_device_id ;extern void __iomem *twd_base;
@@ -27,11 +28,17 @@ 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); +int twd_timer_of_init (const struct of_device_id *twd_of_match);#else static inline int twd_timer_register (struct resource *res,int res_nr) {return 0 ; } + +static inline int twd_timer_of_init (const struct of_device_id *twd_of_match) +{ +return 0 ; +}#endif #endif
arch/arm/kernel/smp_twd.c +53 -14
92 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v2 3/15 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.7.1
PATCH v2 4/15 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.7.1
PATCH v2 5/15 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.7.1
PATCH v2 6/15 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
@@ -6,6 +6,7 @@ config ARCH_TEGRA_2x_SOC bool "Enable support for Tegra20 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
@@ -13,7 +13,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-tegra20-tables.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pinmux-tegra30-tables.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.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;
@@ -205,10 +231,6 @@ static void __init tegra_init_timer(void)else 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 );
@@ -249,6 +271,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.7.1
PATCH v2 6/15 ARM: local timers: switch tegra to standalone smp_twd
Quoted 5 lines · Marc Zyngier
Convert 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 thelate_timer_inithook.
Quoted 7 lines
Tested on Harmony.
Cc Colin Cross <[email protected]>Cc Erik Gilling <[email protected]>Cc Olof Johansson <[email protected]>Cc Stephen Warren <[email protected]>Signed-off-by Marc Zyngier <[email protected]>
PATCH v2 7/15 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
@@ -45,7 +45,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
@@ -23,7 +23,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) += omap4-common.o omap-wakeupgen.o \ sleep44xx.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
@@ -39,7 +39,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 "common.h" #include <plat/omap_hwmod.h>
@@ -335,15 +335,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.7.1
PATCH v2 7/15 ARM: local timers: switch omap4 to standalone smp_twd
Marc,
Quoted 9 lines · Marc Zyngier
Convert 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 thelate_timer_inithook.Tested on a Pandaboard.
Cc Tony Lindgren <[email protected]>Signed-off-by Marc Zyngier <[email protected]>
IIRC, have reviewed this earlier. Looking at the patch the changes are almost same. So for OMAP changes
PATCH v2 8/15 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/smp-sh73a0.c | 32 +++++++++++++++++++++++-- arch/arm/mach-shmobile/timer.c | 10 ++++++++ 6 files changed, 43 insertions(+), 30 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
@@ -52,4 +52,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/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.7.1
PATCH v2 9/15 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/localtimer.c | 29 -------------------------- arch/arm/mach-ux500/timer.c | 41 +++++++++++++++++++++++++++++++------ 4 files changed, 35 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 select ARM_ERRATA_754322
arch/arm/mach-ux500/Makefile +0 -1
@@ -15,7 +15,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/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 ; -}
arch/arm/mach-ux500/timer.c +34 -7
67 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v2 10/15 ARM: local timers: switch highbank to standalone smp_twd
In reply to Marc ZyngierConvert the highbank 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-highbank/Makefile | 1 - arch/arm/mach-highbank/highbank.c | 13 +++++++++++ arch/arm/mach-highbank/localtimer.c | 40 ----------------------------------- 3 files changed, 13 insertions(+), 41 deletions(-) delete mode 100644 arch/arm/mach-highbank/localtimer.c
arch/arm/mach-highbank/Makefile +0 -1
@@ -1,6 +1,5 @@ obj-y := clock.o highbank.o system.o obj-$(CONFIG_DEBUG_HIGHBANK_UART) += lluart.o obj-$(CONFIG_SMP) += platsmp.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_PM_SLEEP) += pm.o
arch/arm/mach-highbank/highbank.c +13 -0
@@ -27,6 +27,7 @@#include <asm/cacheflush.h> #include <asm/unified.h> #include <asm/smp_scu.h> +#include <asm/smp_twd.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/timer-sp.h> #include <asm/hardware/gic.h>
@@ -93,6 +94,16 @@ static void __init highbank_init_irq(void)l2x0_of_init (0 , ~0UL ); } +const static struct of_device_id twd_match[]__initconst = { + { .compatible ="arm,smp-twd" , }, + {} +}; + +static void __init highbank_twd_init (void ) +{ +twd_timer_of_init (twd_match); +} +static void __init highbank_timer_init (void ) {int irq;
@@ -113,6 +124,8 @@ static void __init highbank_timer_init(void)sp804_clocksource_init (timer_base +0x20 ,"timer1" );sp804_clockevents_init (timer_base, irq,"timer0" ); + + late_time_init = highbank_twd_init; }static struct sys_timer highbank_timer = {
arch/arm/mach-highbank/localtimer.c deleted +0 -40
@@ -1,40 +0,0 @@ -/* -* Copyright 2010-2011 Calxeda, Inc. -* Based on localtimer.c, Copyright (C) 2002 ARM Ltd. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program. If not, see <http://www.gnu.org/licenses/>. -*/ -#include <linux/init.h> -#include <linux/clockchips.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> - -#include <asm/smp_twd.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ -struct device_node *np; - - np =of_find_compatible_node (NULL ,NULL ,"arm,smp-twd" ); -if (!twd_base) { - twd_base =of_iomap (np,0 ); -WARN_ON (!twd_base); - } - evt->irq =irq_of_parse_and_map (np,0 ); -twd_timer_setup (evt); -return 0 ; -}
Signature · 1 line
1.7.7.1
PATCH v2 11/15 ARM: local timers: switch imx6q to standalone smp_twd
In reply to Marc ZyngierConvert the imx6q 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-imx/Makefile | 1 - arch/arm/mach-imx/localtimer.c | 35 ----------------------------------- arch/arm/mach-imx/mach-imx6q.c | 12 ++++++++++++ 3 files changed, 12 insertions(+), 36 deletions(-) delete mode 100644 arch/arm/mach-imx/localtimer.c
arch/arm/mach-imx/Makefile +0 -1
@@ -71,7 +71,6 @@ obj-$(CONFIG_CPU_V7) += head-v7.o AFLAGS_head-v7.o :=-Wa,-march=armv7-a obj-$(CONFIG_SMP) += platsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o # i.MX5 based machines
arch/arm/mach-imx/localtimer.c deleted +0 -35
@@ -1,35 +0,0 @@ -/* -* Copyright 2011 Freescale Semiconductor, Inc. -* Copyright 2011 Linaro Ltd. -* -* The code contained herein is licensed under the GNU General Public -* License. You may obtain a copy of the GNU General Public License -* Version 2 or later at the following locations: -* -* http://www.opensource.org/licenses/gpl-license.html -* http://www.gnu.org/copyleft/gpl.html -*/ - -#include <linux/init.h> -#include <linux/clockchips.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <asm/smp_twd.h> - -/* -* Setup the local clock events for a CPU. -*/ -int __cpuinit local_timer_setup (struct clock_event_device *evt) -{ -struct device_node *np; - - np =of_find_compatible_node (NULL ,NULL ,"arm,smp-twd" ); -if (!twd_base) { - twd_base =of_iomap (np,0 ); -WARN_ON (!twd_base); - } - evt->irq =irq_of_parse_and_map (np,0 ); -twd_timer_setup (evt); - -return 0 ; -}
arch/arm/mach-imx/mach-imx6q.c +12 -0
@@ -21,6 +21,7 @@#include <linux/of_platform.h> #include <linux/phy.h> #include <linux/micrel_phy.h> +#include <asm/smp_twd.h> #include <asm/hardware/cache-l2x0.h> #include <asm/hardware/gic.h> #include <asm/mach/arch.h>
@@ -116,9 +117,20 @@ static void __init imx6q_init_irq(void)of_irq_init (imx6q_irq_match); } +const static struct of_device_id imx6q_twd_match[]__initconst = { + { .compatible ="arm,smp-twd" , }, + {} +}; + +static void __init imx6q_twd_init (void ) +{ +twd_timer_of_init (imx6q_twd_match); +} +static void __init imx6q_timer_init (void ) {mx6q_clocks_init (); + late_time_init = imx6q_twd_init; }static struct sys_timer imx6q_timer = {
Signature · 1 line
1.7.7.1
PATCH v2 11/15 ARM: local timers: switch imx6q to standalone smp_twd
Hi Marc,
Quoted 5 lines · Marc Zyngier
Convert the imx6q 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.
Quoted 9 lines
Cc Shawn Guo <[email protected]>Signed-off-by Marc Zyngier <[email protected]>--- arch/arm/mach-imx/Makefile | 1 - arch/arm/mach-imx/localtimer.c | 35 ----------------------------------- arch/arm/mach-imx/mach-imx6q.c | 12 ++++++++++++ 3 files changed, 12 insertions(+), 36 deletions(-) delete mode 100644 arch/arm/mach-imx/localtimer.c
Are we missing 'select ARM_SMP_TWD' for 'config SOC_IMX6Q' in arch/arm/mach-imx/Kconfig?
With that added,
Signature · 2 lines
Regards, Shawn
PATCH v2 12/15 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 functions 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 | 65 ++++++++++-------------------------- 4 files changed, 18 insertions(+), 63 deletions(-)
arch/arm/Kconfig +0 -1
@@ -1566,7 +1566,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
@@ -22,21 +22,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,14 +18,9 @@#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) -struct clock_event_device ;struct resource ;struct of_device_id ; -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);int twd_timer_of_init (const struct of_device_id *twd_of_match);
arch/arm/kernel/smp_twd.c +18 -47
127 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v2 13/15 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-exynos/mct.c | 85 ++++++++++++++++++++++++++++++------------- 2 files changed, 60 insertions(+), 27 deletions(-)
arch/arm/Kconfig +1 -1
@@ -1564,7 +1564,7 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && !ARM_SMP_TWD + depends on SMP && !ARM_SMP_TWD && !EXYNOS4_MCT default y help Enable support for local timers on SMP platforms, rather then the
arch/arm/mach-exynos/mct.c +59 -26
172 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v2 14/15 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 | 92 +++++++++++++++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 24 deletions(-)
arch/arm/Kconfig +1 -1
@@ -1564,7 +1564,7 @@ config HOTPLUG_CPU config LOCAL_TIMERS bool "Use local timer interrupts" - depends on SMP && !ARM_SMP_TWD && !EXYNOS4_MCT + depends on SMP && !ARM_SMP_TWD && !EXYNOS4_MCT && !MSM default y help Enable support for local timers on SMP platforms, rather then the
arch/arm/mach-msm/timer.c +69 -23
160 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH v2 15/15 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 | 47 -------------------------------- arch/arm/kernel/smp.c | 54 +++++++++---------------------------- 3 files changed, 13 insertions(+), 98 deletions(-) delete mode 100644 arch/arm/include/asm/localtimer.h
arch/arm/Kconfig +0 -10
@@ -1562,16 +1562,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 && !EXYNOS4_MCT && !MSM - 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 -47
47 lines not on this page · raw message
arch/arm/kernel/smp.c +13 -41
114 lines not on this page · raw message
Signature · 1 line
1.7.7.1
v2 cover Make SMP timers standalone
In reply to Marc ZyngierQuoted 3 lines · Marc Zyngier
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.
You do realise that it's pointless having local timers on non-SMP hardware. On such hardware, you have a single timer instead.
You're also aware I assume that local timers are different from the global timer itself, and require to have additional callbacks for broadcasting the global timer tick?
There is a reason why local timers _use_ the common local timer clock event stuff.
v2 cover Make SMP timers standalone
On 22/12/11 19:32, Russell King - ARM Linux wrote:
Hi Russell,
Quoted 7 lines · Marc Zyngier
Quoted 3 lines
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.
You do realise that it's pointless having local timers on non-SMP hardware. On such hardware, you have a single timer instead.
I do. But on some non-SMP platforms, the local timer and the global timer can actually be the same (MSM is one example of this, and the UP version of the Cortex A15 is another).
Quoted 3 lines
You're also aware I assume that local timers are different from the global timer itself, and require to have additional callbacks for broadcasting the global timer tick?
I was under the impression that we either have the global timer together with broadcasting or the local timers. Completely removing the broadcast callback doesn't seem to generate any ill effect as long as the local timers are used instead of the global timer (which of course requires broadcast in the SMP configuration).
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
v2 cover Make SMP timers standalone
Quoted 10 lines · Marc Zyngier
Quoted 3 lines · Russell King - ARM Linux
You're also aware I assume that local timers are different from the global timer itself, and require to have additional callbacks for broadcasting the global timer tick?
I was under the impression that we either have the global timer together with broadcasting or the local timers. Completely removing the broadcast callback doesn't seem to generate any ill effect as long as the local timers are used instead of the global timer (which of course requires broadcast in the SMP configuration).
I believe even if you have local timers, there are situations where the these will be disabled and the kernel will switch to broadcasting from a global timer tick. I think such a scenario would be like that encountered with OMAP, where suspending a CPU stops its TWD - meaning that the TWD can't be used to wake the CPU from one of the deeper idle states.
v2 cover Make SMP timers standalone
Quoted 12 lines · Russell King - ARM Linux
Quoted 10 lines · Marc Zyngier
Quoted 3 lines · Russell King - ARM Linux
You're also aware I assume that local timers are different from the global timer itself, and require to have additional callbacks for broadcasting the global timer tick?
I was under the impression that we either have the global timer together with broadcasting or the local timers. Completely removing the broadcast callback doesn't seem to generate any ill effect as long as the local timers are used instead of the global timer (which of course requires broadcast in the SMP configuration).
Quoted 5 lines
I believe even if you have local timers, there are situations where the these will be disabled and the kernel will switch to broadcasting from a global timer tick. ?I think such a scenario would be like that encountered with OMAP, where suspending a CPU stops its TWD - meaning that the TWD can't be used to wake the CPU from one of the deeper idle states.
This is true also for the Ux500.
The situation occurs as soon as you want to gate off or power down the CPU clock/power domain, in which the TWD is sythesized.
However IIRC this situation does not occur in the ARM reference designs, notably Versatile Express since it simply isn't designed to be power-agressive in this way and does not gate the clock or power down the CPU power domain, it's always on, always clocked (albeit with shifting frequency).
The Vexpress seem to register a clockevent for its SP804 timer, and even though I've never used this machine I guess it would tick a few ticks during boot and then as TWD is registered it switches to that (due to higher .rate) and no IRQ is ever fired on the SP804 again.
Does this correspond to what is seen in /proc/interrupts on the Vexpress?
And does the system really work if you simply delete the code registering the SP804 clockevent from mach-vexpress/ct-ca9x4.c?
Yours,
Linus Walleij
v2 cover Make SMP timers standalone
Quoted 6 lines · Linus Walleij
However IIRC this situation does not occur in the ARM reference designs, notably Versatile Express since it simply isn't designed to be power-agressive in this way and does not gate the clock or power down the CPU power domain, it's always on, always clocked (albeit with shifting frequency).
Quoted 8 lines
The Vexpress seem to register a clockevent for its SP804 timer, and even though I've never used this machine I guess it would tick a few ticks during boot and then as TWD is registered it switches to that (due to higher .rate) and no IRQ is ever fired on the SP804 again.
Does this correspond to what is seen in
/proc/interruptson the Vexpress?
Yes. You get about 8 ticks worth of SP804, and then switch to TWD for good.
Quoted 3 lines
And does the system really work if you simply delete the code registering the SP804 clockevent from
mach-vexpress/ct-ca9x4.c?
No, because you need the global timer to calibrate the TWD on this platform. But on the VE with a Cortex-A15 tile, the system works perfectly with the architected timers being the only one in the system (the SP804 is left unconfigured).
But now that your cpufreq-aware patches are in -next, I can boot a Panda without a single tick of the global timer (OMAP4 provides the "smp-twd" clock).
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
v2 cover Make SMP timers standalone
Quoted 22 lines · Marc Zyngier
Quoted 6 lines · Linus Walleij
However IIRC this situation does not occur in the ARM reference designs, notably Versatile Express since it simply isn't designed to be power-agressive in this way and does not gate the clock or power down the CPU power domain, it's always on, always clocked (albeit with shifting frequency).
Quoted 8 lines
The Vexpress seem to register a clockevent for its SP804 timer, and even though I've never used this machine I guess it would tick a few ticks during boot and then as TWD is registered it switches to that (due to higher .rate) and no IRQ is ever fired on the SP804 again.
Does this correspond to what is seen in
/proc/interruptson the Vexpress?Yes. You get about 8 ticks worth of SP804, and then switch to TWD for good.
Quoted 3 lines
And does the system really work if you simply delete the code registering the SP804 clockevent from
mach-vexpress/ct-ca9x4.c?
Quoted 9 lines
No, because you need the global timer to calibrate the TWD on this platform. But on the VE with a Cortex-A15 tile, the system works perfectly with the architected timers being the only one in the system (the SP804 is left unconfigured).
But now that your cpufreq-aware patches are in -next, I can boot a Panda without a single tick of the global timer (OMAP4 provides the "smp-twd" clock).
That's only because CPUIDLE low power states are not enabled. You do that and without global timer, system will just die
v2 cover Make SMP timers standalone
Quoted 28 lines · Santosh
Quoted 27 lines · Marc Zyngier
Quoted 6 lines · Linus Walleij
However IIRC this situation does not occur in the ARM reference designs, notably Versatile Express since it simply isn't designed to be power-agressive in this way and does not gate the clock or power down the CPU power domain, it's always on, always clocked (albeit with shifting frequency).
Quoted 8 lines
The Vexpress seem to register a clockevent for its SP804 timer, and even though I've never used this machine I guess it would tick a few ticks during boot and then as TWD is registered it switches to that (due to higher .rate) and no IRQ is ever fired on the SP804 again.
Does this correspond to what is seen in
/proc/interruptson the Vexpress?Yes. You get about 8 ticks worth of SP804, and then switch to TWD for good.
Quoted 3 lines
And does the system really work if you simply delete the code registering the SP804 clockevent from
mach-vexpress/ct-ca9x4.c?No, because you need the global timer to calibrate the TWD on this platform. But on the VE with a Cortex-A15 tile, the system works perfectly with the architected timers being the only one in the system (the SP804 is left unconfigured).
Quoted 6 lines
Quoted 4 lines
But now that your cpufreq-aware patches are in -next, I can boot a Panda without a single tick of the global timer (OMAP4 provides the "smp-twd" clock).
That's only because CPUIDLE low power states are not enabled. You do that and without global timer, system will just die
Global timer is still present, configured and enabled. The kernel just happens to select TWD as a better timer. Should TWD be turned off, gp_timer will be selected again.
This is also what happens with the current implementation, and my patches don't change that.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
v2 cover Make SMP timers standalone
Quoted 3 lines · Marc Zyngier
Global timer is still present, configured and enabled. The kernel just happens to select TWD as a better timer. Should TWD be turned off,
gp_timerwill be selected again.
And at that point, the core time keeping code will find a local timer clock event structure and expect it's broadcast method to be implemented and working, as I described in my initial reply.
Quoted 2 lines
This is also what happens with the current implementation, and my patches don't change that.
Yes they do, because they omit the broadcast method.
Look, local timers *are* special. They're not the same as global timers. They're treated differently. Ripping out the local timer setup stuff from the SMP code is not the right solution, especially when we've already got a separation of the local timer core from the hardware implementation.
v2 cover Make SMP timers standalone
Quoted 5 lines · Russell King - ARM Linux
Quoted 3 lines · Marc Zyngier
Global timer is still present, configured and enabled. The kernel just happens to select TWD as a better timer. Should TWD be turned off,
gp_timerwill be selected again.
Quoted 8 lines
And at that point, the core time keeping code will find a local timer clock event structure and expect it's broadcast method to be implemented and working, as I described in my initial reply.
Quoted 2 lines
This is also what happens with the current implementation, and my patches don't change that.
Yes they do, because they omit the broadcast method.
I forgot to mention I restored this functionality after you pointed that out (I made smp_timer_broadcast a global symbol).
Quoted 5 lines
Look, local timers *are* special. They're not the same as global timers. They're treated differently. Ripping out the local timer setup stuff from the SMP code is not the right solution, especially when we've already got a separation of the local timer core from the hardware implementation.
OK. I'll try to work out something different.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
v2 cover Make SMP timers standalone
Quoted 8 lines · Marc Zyngier
Quoted 5 lines · Russell King - ARM Linux
Look, local timers *are* special. They're not the same as global timers. They're treated differently. Ripping out the local timer setup stuff from the SMP code is not the right solution, especially when we've already got a separation of the local timer core from the hardware implementation.
OK. I'll try to work out something different.
Why? What's wrong with the existing structure?
If you want to use the TWD as a global timer, that's easy to do:
static struct clock_event_device twd_global_ce = {
.irq = whatever_irq,
.cpumask = cpu_mask_all,
};
static int __init twd_global_timer(void)
{
twd_base = ioremap(twd_phys, SZ_4K);
if (!twd_base)
return -ENOMEM;
twd_timer_setup(&twd_global_ce);
return 0;
}And no need to mess around with the local timer structure in arch/arm/kernel/smp.c.
v2 cover Make SMP timers standalone
Quoted 11 lines · Russell King - ARM Linux
Quoted 8 lines · Marc Zyngier
Quoted 5 lines · Russell King - ARM Linux
Look, local timers *are* special. They're not the same as global timers. They're treated differently. Ripping out the local timer setup stuff from the SMP code is not the right solution, especially when we've already got a separation of the local timer core from the hardware implementation.
OK. I'll try to work out something different.
Why? What's wrong with the existing structure?
My main goal here is not to use a local timer as a global timer, but rather to be able to support multiple local timer implementations in the same kernel (TWD, MCT...). The "local timer on UP" is merely a consequence.
I could come up with another registration interface that fits into the existing structure, but I thought something could be done with what we currently have.
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
v2 cover Make SMP timers standalone
Quoted 13 lines · Marc Zyngier
Quoted 11 lines · Russell King - ARM Linux
Quoted 8 lines · Marc Zyngier
Quoted 5 lines · Russell King - ARM Linux
Look, local timers *are* special. They're not the same as global timers. They're treated differently. Ripping out the local timer setup stuff from the SMP code is not the right solution, especially when we've already got a separation of the local timer core from the hardware implementation.
OK. I'll try to work out something different.
Why? What's wrong with the existing structure?
Quoted 7 lines
My main goal here is not to use a local timer as a global timer, but rather to be able to support multiple local timer implementations in the same kernel (TWD, MCT...). The "local timer on UP" is merely a consequence.
I could come up with another registration interface that fits into the existing structure, but I thought something could be done with what we currently have.
That's easy - but the solution depends on exactly how you're trying to solve it.
In local_timer.h:
struct local_timer {
int (*setup)(struct clock_event_device *);
void (*stop)(struct clock_event_device *);
};int local_timer_register(struct local_timer *);
In arch/arm/kernel/smp.c:
static struct local_timer *local_timer;
int local_timer_register(struct local_timer *lt)
{
if (local_timer)
return -EBUSY;
local_timer = lt;
return 0;
}static int local_timer_setup(struct clock_event_device *ce)
{
return local_timer ? local_timer->setup(ce) : -ENXIO;
}static void local_timer_stop(struct clock_event_device *ce)
{
if (local_timer)
local_timer->stop(ce);
}And, for twd:
struct local_timer twd_local_timer = {
.setup = twd_timer_setup,
.stop = twd_timer_stop,
};
But... it's not quite that simple because platforms need to intercept the local_timer_setup() call to do platform specific things - such as finding the twd base, and setting the twd IRQ. That can be solved by moving that out of platform code (why is it there in the first place?) into smp_twd.c, and providing twd_local_timer_dt.
v2 cover Make SMP timers standalone
Quoted 5 lines · Russell King - ARM Linux
But... it's not quite that simple because platforms need to intercept the
local_timer_setup()call to do platform specific things - such as finding the twd base, and setting the twd IRQ. That can be solved by moving that out of platform code (why is it there in the first place?) intosmp_twd.c, and providingtwd_local_timer_dt.
And that's something we really should do anyway - we already have two implementations which are virtually identical to each other for no real reason other than people like to mess around in their own platform stuff rather than solving problems at higher levels.
So, I'll queue this patch after the next merge window.
Note: there's no need for that WARN_ON and subsequent oops in each of these setup functions - it can return an error, in which case we'll fall back to a broadcasted tick for the CPU.
8<---------
From: Russell King <[email protected]>
ARM: TWD: Move DT code into smp_twd.c
Rather than have each platform implement their own DT veneer to discover the base address and IRQ for their TWD, move this code into the TWD driver itself.
--- arch/arm/include/asm/smp_twd.h | 1 + arch/arm/kernel/smp_twd.c | 21 +++++++++++++++++++++ arch/arm/mach-highbank/localtimer.c | 14 +------------- arch/arm/mach-imx/localtimer.c | 14 +------------- 4 files changed, 24 insertions(+), 26 deletions(-)
arch/arm/include/asm/smp_twd.h +1 -0
@@ -23,6 +23,7 @@ struct clock_event_device;extern void __iomem *twd_base;void twd_timer_setup (struct clock_event_device *); +int twd_timer_setup_dt (struct clock_event_device *);void twd_timer_stop (struct clock_event_device *);#endif
arch/arm/kernel/smp_twd.c +21 -0
@@ -20,6 +20,9 @@#include <linux/clockchips.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <asm/smp_twd.h> #include <asm/localtimer.h>
@@ -266,3 +269,21 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) 0xf, 0xffffffff);enable_percpu_irq (clk->irq,0 ); } + +int __cpuinit twd_timer_setup_dt (struct clock_event_device *clk) +{ +struct device_node *np; + + np =of_find_compatible_node (NULL ,NULL ,"arm,smp-twd" ); +if (np) { +if (!twd_base) { + twd_base =of_iomap (np,0 ); +if (!twd_base) +return -ENOMEM ; + } + evt->irq =irq_of_parse_and_map (np,0 ); + } +twd_timer_setup (evt); + +return 0 ; +}
arch/arm/mach-highbank/localtimer.c +1 -13
@@ -16,9 +16,6 @@*/ #include <linux/init.h> #include <linux/clockchips.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> #include <asm/smp_twd.h>
@@ -27,14 +24,5 @@*/ int __cpuinit local_timer_setup (struct clock_event_device *evt) { -struct device_node *np; - - np =of_find_compatible_node (NULL ,NULL ,"arm,smp-twd" ); -if (!twd_base) { - twd_base =of_iomap (np,0 ); -WARN_ON (!twd_base); - } - evt->irq =irq_of_parse_and_map (np,0 ); -twd_timer_setup (evt); -return 0 ; +return twd_timer_setup_dt (evt); }
arch/arm/mach-imx/localtimer.c +1 -13
@@ -12,8 +12,6 @@#include <linux/init.h> #include <linux/clockchips.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> #include <asm/smp_twd.h> /*
@@ -21,15 +19,5 @@*/ int __cpuinit local_timer_setup (struct clock_event_device *evt) { -struct device_node *np; - - np =of_find_compatible_node (NULL ,NULL ,"arm,smp-twd" ); -if (!twd_base) { - twd_base =of_iomap (np,0 ); -WARN_ON (!twd_base); - } - evt->irq =irq_of_parse_and_map (np,0 ); -twd_timer_setup (evt); - -return 0 ; +return twd_timer_setup_dt (evt); }
v2 cover Make SMP timers standalone
In reply to Marc ZyngierQuoted 36 lines · Marc Zyngier
Quoted 28 lines · Santosh
Quoted 27 lines · Marc Zyngier
Quoted 6 lines · Linus Walleij
However IIRC this situation does not occur in the ARM reference designs, notably Versatile Express since it simply isn't designed to be power-agressive in this way and does not gate the clock or power down the CPU power domain, it's always on, always clocked (albeit with shifting frequency).
Quoted 8 lines
The Vexpress seem to register a clockevent for its SP804 timer, and even though I've never used this machine I guess it would tick a few ticks during boot and then as TWD is registered it switches to that (due to higher .rate) and no IRQ is ever fired on the SP804 again.
Does this correspond to what is seen in
/proc/interruptson the Vexpress?Yes. You get about 8 ticks worth of SP804, and then switch to TWD for good.
Quoted 3 lines
And does the system really work if you simply delete the code registering the SP804 clockevent from
mach-vexpress/ct-ca9x4.c?No, because you need the global timer to calibrate the TWD on this platform. But on the VE with a Cortex-A15 tile, the system works perfectly with the architected timers being the only one in the system (the SP804 is left unconfigured).
Quoted 6 lines
Quoted 4 lines
But now that your cpufreq-aware patches are in -next, I can boot a Panda without a single tick of the global timer (OMAP4 provides the "smp-twd" clock).
That's only because CPUIDLE low power states are not enabled. You do that and without global timer, system will just die
Quoted 7 lines
Global timer is still present, configured and enabled. The kernel just happens to select TWD as a better timer. Should TWD be turned off,
gp_timerwill be selected again.This is also what happens with the current implementation, and my patches don't change that.
Great. Thanks for clarifying Marc.
Regards
Santosh
v2 cover Make SMP timers standalone
In reply to Russell King - ARM LinuxQuoted 12 lines · Russell King - ARM Linux
Quoted 10 lines · Marc Zyngier
Quoted 3 lines · Russell King - ARM Linux
You're also aware I assume that local timers are different from the global timer itself, and require to have additional callbacks for broadcasting the global timer tick?
I was under the impression that we either have the global timer together with broadcasting or the local timers. Completely removing the broadcast callback doesn't seem to generate any ill effect as long as the local timers are used instead of the global timer (which of course requires broadcast in the SMP configuration).
Quoted 5 lines
I believe even if you have local timers, there are situations where the these will be disabled and the kernel will switch to broadcasting from a global timer tick. I think such a scenario would be like that encountered with OMAP, where suspending a CPU stops its TWD - meaning that the TWD can't be used to wake the CPU from one of the deeper idle states.
Yes, being able to wake up is definitely a good reason to keep a global timer around, not to mention other artifacts (TWD calibration being one, though on its way out thanks to LinusW patch series).
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
v2 cover Make SMP timers standalone
Quoted 19 lines · Marc Zyngier
Quoted 12 lines · Russell King - ARM Linux
Quoted 10 lines · Marc Zyngier
Quoted 3 lines · Russell King - ARM Linux
You're also aware I assume that local timers are different from the global timer itself, and require to have additional callbacks for broadcasting the global timer tick?
I was under the impression that we either have the global timer together with broadcasting or the local timers. Completely removing the broadcast callback doesn't seem to generate any ill effect as long as the local timers are used instead of the global timer (which of course requires broadcast in the SMP configuration).
Quoted 5 lines
I believe even if you have local timers, there are situations where the these will be disabled and the kernel will switch to broadcasting from a global timer tick. ?I think such a scenario would be like that encountered with OMAP, where suspending a CPU stops its TWD - meaning that the TWD can't be used to wake the CPU from one of the deeper idle states.
Quoted 4 lines
Yes, being able to wake up is definitely a good reason to keep a global timer around, not to mention other artifacts (TWD calibration being one, though on its way out thanks to LinusW patch series).
Catching up bit late on this tread.
I just want to echo the fact that we always need the wakeup capable clock-event till the local timers themselves can wakup the CPU from low power states.
Regards
Santosh
v2 cover Make SMP timers standalone
In reply to Marc ZyngierQuoted 9 lines · Marc Zyngier
On 22/12/11 19:32, Russell King - ARM Linux wrote:
Hi Russell,
Quoted 5 lines · Marc Zyngier
Quoted 3 lines
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.
Quoted 6 lines
Quoted 2 lines
You do realise that it's pointless having local timers on non-SMP hardware. On such hardware, you have a single timer instead.
I do. But on some non-SMP platforms, the local timer and the global timer can actually be the same (MSM is one example of this, and the UP version of the Cortex A15 is another).
On SMP MSM, we use the CPU0 local timer as the global timer. They are the same on non-SMP as well, I guess, but as Russell says, I'm not sure what the concept of a local timer would mean on non-SMP.
David
Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
v2 cover Make SMP timers standalone
Quoted 7 lines · David Brown
Quoted 3 lines · Marc Zyngier
I do. But on some non-SMP platforms, the local timer and the global timer can actually be the same (MSM is one example of this, and the UP version of the Cortex A15 is another).
On SMP MSM, we use the CPU0 local timer as the global timer. ?They are the same on non-SMP as well,
Does this mean your CPU0 local timer is always on, always clocked? And do you use ARMs SMP TWD IP block for that?
Quoted 2 lines
I guess, but as Russell says, I'm not
sure what the concept of a local timer would mean on non-SMP.
I think this looks like one big misunderstanding. I understood it as the SMP TWD block is synthesized also on UP silicon, i.e. same hardware, and so it will need to use the driver from arch/arm/kernel/smp_twd.c, however there is nothing local about that apart from being in close locality of the CPU.
Let us talk about the SMP TWD timer block for A8/A9 systems if that is what it's all about (is it? maybe I'm confused too...) and architectured timers for A15.
Linus Walleij
v2 cover Make SMP timers standalone
Quoted 5 lines · Linus Walleij
I think this looks like one big misunderstanding. I understood it as the SMP TWD block is synthesized also on UP silicon, i.e. same hardware, and so it will need to use the driver from
arch/arm/kernel/smp_twd.c, however there is nothing local about that apart from being in close locality of the CPU.
Yes indeed. The TWD code is architected to plug into the local timer code via a set of well defined hooks.
It's entirely possible to call the TWD setup function with a non-local timer clock event structure if you have a TWD which is a global timer. The percpu stuff for storage will just work on UP systems, so that's not a concern. What could be is the percpu IRQ stuff, which presumably wouldn't be available on non-SMP systems.
Apart from that, I think the current architecture is right - it separates the hardware timer code from the local-timer specifics, and allows the hardware timer driver to be re-used if needed.
Trying to make local timers as a general rule work as global timers is, I think, a big mistake. I've no problem with making a local timer hardware _implementation_ work as a global timer though.
v2 cover Make SMP timers standalone
In reply to Linus WalleijQuoted 10 lines · Linus Walleij
Quoted 6 lines · David Brown
Quoted 3 lines · Marc Zyngier
I do. But on some non-SMP platforms, the local timer and the global timer can actually be the same (MSM is one example of this, and the UP version of the Cortex A15 is another).
On SMP MSM, we use the CPU0 local timer as the global timer. They are the same on non-SMP as well,
Does this mean your CPU0 local timer is always on, always clocked? And do you use ARMs SMP TWD IP block for that?
Yes, CPU0's local timer is always on. We use it as a global clocksource, as well
as for udelay on both cores. It is not ARM's SMP TWD block, it is our own. The
timer blocks can each be read from both CPUs, but can only generate IRQs to one
or the other.
Jeff