Merge tag 'remove-local-timers' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorOlof Johansson <olof@lixom.net>
Tue, 23 Jul 2013 21:51:34 +0000 (14:51 -0700)
committerOlof Johansson <olof@lixom.net>
Tue, 23 Jul 2013 23:54:15 +0000 (16:54 -0700)
From Stephen Boyd:

Now that we have a generic arch hook for broadcast we can remove the
local timer API entirely. Doing so will reduce code in ARM core, reduce
the architecture dependencies of our timer drivers, and simplify the code
because we no longer go through an architecture layer that is essentially
a hotplug notifier.

* tag 'remove-local-timers' of git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm:
  ARM: smp: Remove local timer API
  clocksource: time-armada-370-xp: Divorce from local timer API
  clocksource: time-armada-370-xp: Fix sparse warning
  ARM: msm: Divorce msm_timer from local timer API
  ARM: PRIMA2: Divorce timer-marco from local timer API
  ARM: EXYNOS4: Divorce mct from local timer API
  ARM: OMAP2+: Divorce from local timer API
  ARM: smp_twd: Divorce smp_twd from local timer API
  ARM: smp: Remove duplicate dummy timer implementation

Resolved a large number of conflicts due to __cpuinit cleanups, etc.

Signed-off-by: Olof Johansson <olof@lixom.net>
13 files changed:
1  2 
arch/arm/Kconfig
arch/arm/kernel/smp.c
arch/arm/kernel/smp_twd.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-msm/timer.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/timer.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-ux500/Kconfig
arch/arm/mach-vexpress/Kconfig
drivers/clocksource/exynos_mct.c
drivers/clocksource/time-armada-370-xp.c
drivers/clocksource/timer-marco.c

diff --combined arch/arm/Kconfig
index ba412e02ec0c492abed190202cab324d976d0eec,46fa880916317091cfc48cd68aa468abfb31ea42..baf43de26a54e19e40f34f4dff9b416ab7e998fb
@@@ -9,7 -9,7 +9,7 @@@ config AR
        select BUILDTIME_EXTABLE_SORT if MMU
        select CPU_PM if (SUSPEND || CPU_IDLE)
        select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN && MMU
 -      select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
 +      select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI)
        select GENERIC_CLOCKEVENTS_BROADCAST if SMP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
@@@ -41,7 -41,6 +41,7 @@@
        select HAVE_IDE if PCI || ISA || PCMCIA
        select HAVE_IRQ_TIME_ACCOUNTING
        select HAVE_KERNEL_GZIP
 +      select HAVE_KERNEL_LZ4
        select HAVE_KERNEL_LZMA
        select HAVE_KERNEL_LZO
        select HAVE_KERNEL_XZ
@@@ -177,9 -176,6 +177,9 @@@ config ARCH_HAS_CPUFRE
          and that the relevant menu configurations are displayed for
          it.
  
 +config ARCH_HAS_BANDGAP
 +      bool
 +
  config GENERIC_HWEIGHT
        bool
        default y
@@@ -371,12 -367,11 +371,12 @@@ config ARCH_CLPS711
        select ARCH_REQUIRE_GPIOLIB
        select AUTO_ZRELADDR
        select CLKDEV_LOOKUP
 +      select CLKSRC_MMIO
        select COMMON_CLK
        select CPU_ARM720T
        select GENERIC_CLOCKEVENTS
 +      select MFD_SYSCON
        select MULTI_IRQ_HANDLER
 -      select NEED_MACH_MEMORY_H
        select SPARSE_IRQ
        help
          Support for Cirrus Logic 711x/721x/731x based boards.
@@@ -508,7 -503,6 +508,7 @@@ config ARCH_DOV
  
  config ARCH_KIRKWOOD
        bool "Marvell Kirkwood"
 +      select ARCH_HAS_CPUFREQ
        select ARCH_REQUIRE_GPIOLIB
        select CPU_FEROCEON
        select GENERIC_CLOCKEVENTS
@@@ -630,8 -624,8 +630,8 @@@ config ARCH_MS
        bool "Qualcomm MSM"
        select ARCH_REQUIRE_GPIOLIB
        select CLKDEV_LOOKUP
 +      select COMMON_CLK
        select GENERIC_CLOCKEVENTS
 -      select HAVE_CLK
        help
          Support for Qualcomm MSM/QSD based systems.  This runs on the
          apps processor of the MSM/QSD and depends on a shared memory
  
  config ARCH_SHMOBILE
        bool "Renesas SH-Mobile / R-Mobile"
 +      select ARM_PATCH_PHYS_VIRT
        select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_CLK
        select HAVE_MACH_CLKDEV
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
        select MULTI_IRQ_HANDLER
 -      select NEED_MACH_MEMORY_H
        select NO_IOPORT
 -      select PINCTRL if ARCH_WANT_OPTIONAL_GPIOLIB
 +      select PINCTRL
        select PM_GENERIC_DOMAINS if PM
        select SPARSE_IRQ
        help
@@@ -702,7 -696,6 +702,7 @@@ config ARCH_S3C24X
        select CLKDEV_LOOKUP
        select CLKSRC_MMIO
        select GENERIC_CLOCKEVENTS
 +      select GPIO_SAMSUNG
        select HAVE_CLK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select MULTI_IRQ_HANDLER
        select NEED_MACH_GPIO_H
        select NEED_MACH_IO_H
 +      select SAMSUNG_ATAGS
        help
          Samsung S3C2410, S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443
          and S3C2450 SoCs based systems, such as the Simtec Electronics BAST
@@@ -726,7 -718,6 +726,7 @@@ config ARCH_S3C64X
        select CLKSRC_MMIO
        select CPU_V6
        select GENERIC_CLOCKEVENTS
 +      select GPIO_SAMSUNG
        select HAVE_CLK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select PLAT_SAMSUNG
        select S3C_DEV_NAND
        select S3C_GPIO_TRACK
 +      select SAMSUNG_ATAGS
        select SAMSUNG_CLKSRC
        select SAMSUNG_GPIOLIB_4BIT
        select SAMSUNG_IRQ_VIC_TIMER
 +      select SAMSUNG_WDT_RESET
        select USB_ARCH_HAS_OHCI
        help
          Samsung S3C64XX series based systems
@@@ -751,14 -740,11 +751,14 @@@ config ARCH_S5P64X
        select CLKSRC_MMIO
        select CPU_V6
        select GENERIC_CLOCKEVENTS
 +      select GPIO_SAMSUNG
        select HAVE_CLK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select HAVE_S3C_RTC if RTC_CLASS
        select NEED_MACH_GPIO_H
 +      select SAMSUNG_WDT_RESET
 +      select SAMSUNG_ATAGS
        help
          Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
          SMDK6450.
@@@ -770,14 -756,11 +770,14 @@@ config ARCH_S5PC10
        select CLKSRC_MMIO
        select CPU_V7
        select GENERIC_CLOCKEVENTS
 +      select GPIO_SAMSUNG
        select HAVE_CLK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select HAVE_S3C_RTC if RTC_CLASS
        select NEED_MACH_GPIO_H
 +      select SAMSUNG_WDT_RESET
 +      select SAMSUNG_ATAGS
        help
          Samsung S5PC100 series based systems
  
@@@ -790,14 -773,12 +790,14 @@@ config ARCH_S5PV21
        select CLKSRC_MMIO
        select CPU_V7
        select GENERIC_CLOCKEVENTS
 +      select GPIO_SAMSUNG
        select HAVE_CLK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select HAVE_S3C_RTC if RTC_CLASS
        select NEED_MACH_GPIO_H
        select NEED_MACH_MEMORY_H
 +      select SAMSUNG_ATAGS
        help
          Samsung S5PV210/S5PC110 series based systems
  
@@@ -805,9 -786,7 +805,9 @@@ config ARCH_EXYNO
        bool "Samsung EXYNOS"
        select ARCH_HAS_CPUFREQ
        select ARCH_HAS_HOLES_MEMORYMODEL
 +      select ARCH_REQUIRE_GPIOLIB
        select ARCH_SPARSEMEM_ENABLE
 +      select ARM_GIC
        select CLKDEV_LOOKUP
        select COMMON_CLK
        select CPU_V7
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select HAVE_S3C_RTC if RTC_CLASS
 -      select NEED_MACH_GPIO_H
        select NEED_MACH_MEMORY_H
 +      select SPARSE_IRQ
 +      select USE_OF
        help
          Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
  
@@@ -836,6 -814,23 +836,6 @@@ config ARCH_SHAR
          Support for the StrongARM based Digital DNARD machine, also known
          as "Shark" (<http://www.shark-linux.de/shark.html>).
  
 -config ARCH_U300
 -      bool "ST-Ericsson U300 Series"
 -      depends on MMU
 -      select ARCH_REQUIRE_GPIOLIB
 -      select ARM_AMBA
 -      select ARM_PATCH_PHYS_VIRT
 -      select ARM_VIC
 -      select CLKDEV_LOOKUP
 -      select CLKSRC_MMIO
 -      select COMMON_CLK
 -      select CPU_ARM926T
 -      select GENERIC_CLOCKEVENTS
 -      select HAVE_TCM
 -      select SPARSE_IRQ
 -      help
 -        Support for ST-Ericsson U300 series mobile platforms.
 -
  config ARCH_DAVINCI
        bool "TI DaVinci"
        select ARCH_HAS_HOLES_MEMORYMODEL
        select GENERIC_IRQ_CHIP
        select HAVE_IDE
        select NEED_MACH_GPIO_H
 +      select TI_PRIV_EDMA
        select USE_OF
        select ZONE_DMA
        help
@@@ -878,21 -872,20 +878,21 @@@ menu "Multiple platform selection
  
  comment "CPU Core family selection"
  
 -config ARCH_MULTI_V4
 -      bool "ARMv4 based platforms (FA526, StrongARM)"
 -      depends on !ARCH_MULTI_V6_V7
 -      select ARCH_MULTI_V4_V5
 -
  config ARCH_MULTI_V4T
        bool "ARMv4T based platforms (ARM720T, ARM920T, ...)"
        depends on !ARCH_MULTI_V6_V7
        select ARCH_MULTI_V4_V5
 +      select CPU_ARM920T if !(CPU_ARM7TDMI || CPU_ARM720T || \
 +              CPU_ARM740T || CPU_ARM9TDMI || CPU_ARM922T || \
 +              CPU_ARM925T || CPU_ARM940T)
  
  config ARCH_MULTI_V5
        bool "ARMv5 based platforms (ARM926T, XSCALE, PJ1, ...)"
        depends on !ARCH_MULTI_V6_V7
        select ARCH_MULTI_V4_V5
 +      select CPU_ARM926T if (!CPU_ARM946E || CPU_ARM1020 || \
 +              CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || \
 +              CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_FEROCEON)
  
  config ARCH_MULTI_V4_V5
        bool
@@@ -956,8 -949,6 +956,8 @@@ source "arch/arm/mach-iop13xx/Kconfig
  
  source "arch/arm/mach-ixp4xx/Kconfig"
  
 +source "arch/arm/mach-keystone/Kconfig"
 +
  source "arch/arm/mach-kirkwood/Kconfig"
  
  source "arch/arm/mach-ks8695/Kconfig"
@@@ -974,8 -965,6 +974,8 @@@ source "arch/arm/mach-netx/Kconfig
  
  source "arch/arm/mach-nomadik/Kconfig"
  
 +source "arch/arm/mach-nspire/Kconfig"
 +
  source "arch/arm/plat-omap/Kconfig"
  
  source "arch/arm/mach-omap1/Kconfig"
@@@ -993,8 -982,6 +993,8 @@@ source "arch/arm/mach-mmp/Kconfig
  
  source "arch/arm/mach-realview/Kconfig"
  
 +source "arch/arm/mach-rockchip/Kconfig"
 +
  source "arch/arm/mach-sa1100/Kconfig"
  
  source "arch/arm/plat-samsung/Kconfig"
@@@ -1003,8 -990,6 +1003,8 @@@ source "arch/arm/mach-socfpga/Kconfig
  
  source "arch/arm/mach-spear/Kconfig"
  
 +source "arch/arm/mach-sti/Kconfig"
 +
  source "arch/arm/mach-s3c24xx/Kconfig"
  
  if ARCH_S3C64XX
@@@ -1103,20 -1088,6 +1103,20 @@@ if !MM
  source "arch/arm/Kconfig-nommu"
  endif
  
 +config PJ4B_ERRATA_4742
 +      bool "PJ4B Errata 4742: IDLE Wake Up Commands can Cause the CPU Core to Cease Operation"
 +      depends on CPU_PJ4B && MACH_ARMADA_370
 +      default y
 +      help
 +        When coming out of either a Wait for Interrupt (WFI) or a Wait for
 +        Event (WFE) IDLE states, a specific timing sensitivity exists between
 +        the retiring WFI/WFE instructions and the newly issued subsequent
 +        instructions.  This sensitivity can result in a CPU hang scenario.
 +        Workaround:
 +        The software must insert either a Data Synchronization Barrier (DSB)
 +        or Data Memory Barrier (DMB) command immediately after the WFI/WFE
 +        instruction
 +
  config ARM_ERRATA_326103
        bool "ARM errata: FSR write bit incorrect on a SWP to read-only memory"
        depends on CPU_V6
@@@ -1219,16 -1190,6 +1219,16 @@@ config PL310_ERRATA_58836
           is not correctly implemented in PL310 as clean lines are not
           invalidated as a result of these operations.
  
 +config ARM_ERRATA_643719
 +      bool "ARM errata: LoUIS bit field in CLIDR register is incorrect"
 +      depends on CPU_V7 && SMP
 +      help
 +        This option enables the workaround for the 643719 Cortex-A9 (prior to
 +        r1p0) erratum. On affected cores the LoUIS bit field of the CLIDR
 +        register returns zero when it should return one. The workaround
 +        corrects this value, ensuring cache maintenance operations which use
 +        it behave as intended and avoiding data corruption.
 +
  config ARM_ERRATA_720789
        bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID"
        depends on CPU_V7
@@@ -1316,7 -1277,7 +1316,7 @@@ config ARM_ERRATA_75432
  
  config ARM_ERRATA_364296
        bool "ARM errata: Possible cache data corruption with hit-under-miss enabled"
 -      depends on CPU_V6 && !SMP
 +      depends on CPU_V6
        help
          This options enables the workaround for the 364296 ARM1136
          r0p2 erratum (possible cache data corruption with
@@@ -1433,7 -1394,6 +1433,7 @@@ config PCI_HOST_ITE815
        select DMABOUNCE
  
  source "drivers/pci/Kconfig"
 +source "drivers/pci/pcie/Kconfig"
  
  source "drivers/pcmcia/Kconfig"
  
@@@ -1455,7 -1415,7 +1455,7 @@@ config SM
        depends on CPU_V6K || CPU_V7
        depends on GENERIC_CLOCKEVENTS
        depends on HAVE_SMP
 -      depends on MMU
 +      depends on MMU || ARM_MPU
        select USE_GENERIC_SMP_HELPERS
        help
          This enables support for systems with more than one CPU. If you have
  
  config SMP_ON_UP
        bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
 -      depends on SMP && !XIP_KERNEL
 +      depends on SMP && !XIP_KERNEL && MMU
        default y
        help
          SMP kernels contain instructions which fail on non-SMP processors.
@@@ -1569,7 -1529,7 +1569,7 @@@ config NR_CPU
  
  config HOTPLUG_CPU
        bool "Support for hot-pluggable CPUs"
 -      depends on SMP && HOTPLUG
 +      depends on SMP
        help
          Say Y here to experiment with turning CPUs off and on.  CPUs
          can be controlled through /sys/devices/system/cpu.
@@@ -1584,16 -1544,6 +1584,6 @@@ config ARM_PSC
          0022A ("Power State Coordination Interface System Software on
          ARM processors").
  
- config LOCAL_TIMERS
-       bool "Use local timer interrupts"
-       depends on SMP
-       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.
  # The GPIO number here must be sorted by descending number. In case of
  # a multiplatform kernel, we just want the highest value required by the
  # selected platforms.
@@@ -1601,7 -1551,6 +1591,7 @@@ config ARCH_NR_GPI
        int
        default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
        default 512 if SOC_OMAP5
 +      default 512 if ARCH_KEYSTONE
        default 392 if ARCH_U8500
        default 352 if ARCH_VT8500
        default 288 if ARCH_SUNXI
@@@ -1627,7 -1576,7 +1617,7 @@@ config SCHED_HRTIC
  
  config THUMB2_KERNEL
        bool "Compile the kernel in Thumb-2 mode" if !CPU_THUMBONLY
 -      depends on CPU_V7 && !CPU_V6 && !CPU_V6K
 +      depends on (CPU_V7 || CPU_V7M) && !CPU_V6 && !CPU_V6K
        default y if CPU_THUMBONLY
        select AEABI
        select ARM_ASM_UNIFIED
@@@ -1749,14 -1698,6 +1739,14 @@@ config HW_PERF_EVENT
          Enable hardware performance counter support for perf events. If
          disabled, perf events will use software events only.
  
 +config SYS_SUPPORTS_HUGETLBFS
 +       def_bool y
 +       depends on ARM_LPAE
 +
 +config HAVE_ARCH_TRANSPARENT_HUGEPAGE
 +       def_bool y
 +       depends on ARM_LPAE
 +
  source "mm/Kconfig"
  
  config FORCE_MAX_ZONEORDER
@@@ -2056,7 -1997,7 +2046,7 @@@ config XIP_PHYS_ADD
  
  config KEXEC
        bool "Kexec system call (EXPERIMENTAL)"
 -      depends on (!SMP || HOTPLUG_CPU)
 +      depends on (!SMP || PM_SLEEP_SMP)
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
@@@ -2090,7 -2031,7 +2080,7 @@@ config CRASH_DUM
  
  config AUTO_ZRELADDR
        bool "Auto calculation of the decompressed kernel image address"
 -      depends on !ZBOOT_ROM && !ARCH_U300
 +      depends on !ZBOOT_ROM
        help
          ZRELADDR is the physical address where the decompressed kernel
          image will be placed. If AUTO_ZRELADDR is selected, the address
@@@ -2104,6 -2045,53 +2094,6 @@@ menu "CPU Power Management
  
  if ARCH_HAS_CPUFREQ
  source "drivers/cpufreq/Kconfig"
 -
 -config CPU_FREQ_S3C
 -      bool
 -      help
 -        Internal configuration node for common cpufreq on Samsung SoC
 -
 -config CPU_FREQ_S3C24XX
 -      bool "CPUfreq driver for Samsung S3C24XX series CPUs (EXPERIMENTAL)"
 -      depends on ARCH_S3C24XX && CPU_FREQ
 -      select CPU_FREQ_S3C
 -      help
 -        This enables the CPUfreq driver for the Samsung S3C24XX family
 -        of CPUs.
 -
 -        For details, take a look at <file:Documentation/cpu-freq>.
 -
 -        If in doubt, say N.
 -
 -config CPU_FREQ_S3C24XX_PLL
 -      bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)"
 -      depends on CPU_FREQ_S3C24XX
 -      help
 -        Compile in support for changing the PLL frequency from the
 -        S3C24XX series CPUfreq driver. The PLL takes time to settle
 -        after a frequency change, so by default it is not enabled.
 -
 -        This also means that the PLL tables for the selected CPU(s) will
 -        be built which may increase the size of the kernel image.
 -
 -config CPU_FREQ_S3C24XX_DEBUG
 -      bool "Debug CPUfreq Samsung driver core"
 -      depends on CPU_FREQ_S3C24XX
 -      help
 -        Enable s3c_freq_dbg for the Samsung S3C CPUfreq core
 -
 -config CPU_FREQ_S3C24XX_IODEBUG
 -      bool "Debug CPUfreq Samsung driver IO timing"
 -      depends on CPU_FREQ_S3C24XX
 -      help
 -        Enable s3c_freq_iodbg for the Samsung S3C CPUfreq core
 -
 -config CPU_FREQ_S3C24XX_DEBUGFS
 -      bool "Export debugfs for CPUFreq"
 -      depends on CPU_FREQ_S3C24XX && DEBUG_FS
 -      help
 -        Export status information via debugfs.
 -
  endif
  
  source "drivers/cpuidle/Kconfig"
diff --combined arch/arm/kernel/smp.c
index c2b4f8f0be9a31b20126cc76ba69b14f2d22b585,54aa994c4b20a1ac79d734666b4945113d3e13ff..3a98192a311814a7bd9f460dafe5f0927600f6fe
  #include <asm/sections.h>
  #include <asm/tlbflush.h>
  #include <asm/ptrace.h>
- #include <asm/localtimer.h>
  #include <asm/smp_plat.h>
  #include <asm/virt.h>
  #include <asm/mach/arch.h>
 +#include <asm/mpu.h>
  
  /*
   * as from 2.5, kernels no longer have an init_tasks structure
@@@ -58,7 -56,7 +57,7 @@@ struct secondary_data secondary_data
   * control for which core is the next to come out of the secondary
   * boot "holding pen"
   */
 -volatile int __cpuinitdata pen_release = -1;
 +volatile int pen_release = -1;
  
  enum ipi_msg_type {
        IPI_WAKEUP,
@@@ -79,14 -77,7 +78,14 @@@ void __init smp_set_ops(struct smp_oper
                smp_ops = *ops;
  };
  
 -int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
 +static unsigned long get_arch_pgd(pgd_t *pgd)
 +{
 +      phys_addr_t pgdir = virt_to_phys(pgd);
 +      BUG_ON(pgdir & ARCH_PGD_MASK);
 +      return pgdir >> ARCH_PGD_SHIFT;
 +}
 +
 +int __cpu_up(unsigned int cpu, struct task_struct *idle)
  {
        int ret;
  
         * its stack and the page tables.
         */
        secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
 -      secondary_data.pgdir = virt_to_phys(idmap_pgd);
 -      secondary_data.swapper_pg_dir = virt_to_phys(swapper_pg_dir);
 +#ifdef CONFIG_ARM_MPU
 +      secondary_data.mpu_rgn_szr = mpu_rgn_info.rgns[MPU_RAM_REGION].drsr;
 +#endif
 +
 +#ifdef CONFIG_MMU
 +      secondary_data.pgdir = get_arch_pgd(idmap_pgd);
 +      secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
 +#endif
        __cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data));
        outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1));
  
                pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
        }
  
 -      secondary_data.stack = NULL;
 -      secondary_data.pgdir = 0;
  
 +      memset(&secondary_data, 0, sizeof(secondary_data));
        return ret;
  }
  
@@@ -138,7 -124,7 +137,7 @@@ void __init smp_init_cpus(void
                smp_ops.smp_init_cpus();
  }
  
 -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 +int boot_secondary(unsigned int cpu, struct task_struct *idle)
  {
        if (smp_ops.smp_boot_secondary)
                return smp_ops.smp_boot_secondary(cpu, idle);
  }
  
  #ifdef CONFIG_HOTPLUG_CPU
- static void percpu_timer_stop(void);
  static int platform_cpu_kill(unsigned int cpu)
  {
        if (smp_ops.cpu_kill)
@@@ -170,7 -154,7 +167,7 @@@ static int platform_cpu_disable(unsigne
  /*
   * __cpu_disable runs on the processor to be shutdown.
   */
 -int __cpuinit __cpu_disable(void)
 +int __cpu_disable(void)
  {
        unsigned int cpu = smp_processor_id();
        int ret;
         */
        migrate_irqs();
  
-       /*
-        * Stop the local timer for this CPU.
-        */
-       percpu_timer_stop();
        /*
         * Flush user cache and TLB mappings, and then remove this CPU
         * from the vm mask set of all processes.
@@@ -216,7 -195,7 +208,7 @@@ static DECLARE_COMPLETION(cpu_died)
   * called on the thread which is asking for a CPU to be shutdown -
   * waits until shutdown has completed, or it is timed out.
   */
 -void __cpuinit __cpu_die(unsigned int cpu)
 +void __cpu_die(unsigned int cpu)
  {
        if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
                pr_err("CPU%u: cpu didn't die\n", cpu);
@@@ -264,7 -243,7 +256,7 @@@ void __ref cpu_die(void
         * this returns, power and/or clocks can be removed at any point
         * from this CPU and its cache by platform_cpu_kill().
         */
 -      RCU_NONIDLE(complete(&cpu_died));
 +      complete(&cpu_died);
  
        /*
         * Ensure that the cache lines associated with that completion are
   * Called by both boot and secondaries to move global data into
   * per-processor storage.
   */
 -static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
 +static void smp_store_cpu_info(unsigned int cpuid)
  {
        struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
  
        store_cpu_topology(cpuid);
  }
  
- static void percpu_timer_setup(void);
  /*
   * This is the secondary CPU boot entry.  We're using this CPUs
   * idle thread stack, but a set of temporary page tables.
   */
 -asmlinkage void __cpuinit secondary_start_kernel(void)
 +asmlinkage void secondary_start_kernel(void)
  {
        struct mm_struct *mm = &init_mm;
        unsigned int cpu;
        set_cpu_online(cpu, true);
        complete(&cpu_running);
  
-       /*
-        * Setup the percpu timer for this CPU.
-        */
-       percpu_timer_setup();
        local_irq_enable();
        local_fiq_enable();
  
@@@ -422,12 -394,6 +407,6 @@@ void __init smp_prepare_cpus(unsigned i
        if (max_cpus > ncores)
                max_cpus = ncores;
        if (ncores > 1 && max_cpus) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
                /*
                 * Initialise the present map, which describes the set of CPUs
                 * actually populated at the present time. A platform should
@@@ -504,11 -470,6 +483,6 @@@ u64 smp_irq_stat_cpu(unsigned int cpu
        return sum;
  }
  
- /*
-  * Timer (local or broadcast) support
-  */
- static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
  #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
  void tick_broadcast(const struct cpumask *mask)
  {
  }
  #endif
  
- static void broadcast_timer_set_mode(enum clock_event_mode mode,
-       struct clock_event_device *evt)
- {
- }
- static void broadcast_timer_setup(struct clock_event_device *evt)
- {
-       evt->name       = "dummy_timer";
-       evt->features   = CLOCK_EVT_FEAT_ONESHOT |
-                         CLOCK_EVT_FEAT_PERIODIC |
-                         CLOCK_EVT_FEAT_DUMMY;
-       evt->rating     = 100;
-       evt->mult       = 1;
-       evt->set_mode   = broadcast_timer_set_mode;
-       clockevents_register_device(evt);
- }
- static struct local_timer_ops *lt_ops;
- #ifdef CONFIG_LOCAL_TIMERS
- int local_timer_register(struct local_timer_ops *ops)
- {
-       if (!is_smp() || !setup_max_cpus)
-               return -ENXIO;
-       if (lt_ops)
-               return -EBUSY;
-       lt_ops = ops;
-       return 0;
- }
- #endif
- static void percpu_timer_setup(void)
- {
-       unsigned int cpu = smp_processor_id();
-       struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
-       evt->cpumask = cpumask_of(cpu);
-       if (!lt_ops || lt_ops->setup(evt))
-               broadcast_timer_setup(evt);
- }
- #ifdef CONFIG_HOTPLUG_CPU
- /*
-  * The generic clock events code purposely does not stop the local timer
-  * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
-  * manually here.
-  */
- static void percpu_timer_stop(void)
- {
-       unsigned int cpu = smp_processor_id();
-       struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
-       if (lt_ops)
-               lt_ops->stop(evt);
- }
- #endif
  static DEFINE_RAW_SPINLOCK(stop_lock);
  
  /*
@@@ -664,6 -564,17 +577,6 @@@ void smp_send_reschedule(int cpu
        smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
  }
  
 -#ifdef CONFIG_HOTPLUG_CPU
 -static void smp_kill_cpus(cpumask_t *mask)
 -{
 -      unsigned int cpu;
 -      for_each_cpu(cpu, mask)
 -              platform_cpu_kill(cpu);
 -}
 -#else
 -static void smp_kill_cpus(cpumask_t *mask) { }
 -#endif
 -
  void smp_send_stop(void)
  {
        unsigned long timeout;
  
        if (num_online_cpus() > 1)
                pr_warning("SMP: failed to stop secondary CPUs\n");
 -
 -      smp_kill_cpus(&mask);
  }
  
  /*
index 25956204ef23ee19b4aeb1b3e290342e484252d9,aac1495b44dec142de71dff6c58509c63ce2570d..2985c9f0905d0e8667210e7bcdc0b51765781524
@@@ -11,6 -11,7 +11,7 @@@
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/clk.h>
+ #include <linux/cpu.h>
  #include <linux/delay.h>
  #include <linux/device.h>
  #include <linux/err.h>
@@@ -24,7 -25,6 +25,6 @@@
  
  #include <asm/smp_plat.h>
  #include <asm/smp_twd.h>
- #include <asm/localtimer.h>
  
  /* set up by the platform code */
  static void __iomem *twd_base;
@@@ -33,7 -33,7 +33,7 @@@ static struct clk *twd_clk
  static unsigned long twd_timer_rate;
  static DEFINE_PER_CPU(bool, percpu_setup_called);
  
- static struct clock_event_device __percpu **twd_evt;
+ static struct clock_event_device __percpu *twd_evt;
  static int twd_ppi;
  
  static void twd_set_mode(enum clock_event_mode mode,
@@@ -90,8 -90,10 +90,10 @@@ static int twd_timer_ack(void
        return 0;
  }
  
- static void twd_timer_stop(struct clock_event_device *clk)
+ static void twd_timer_stop(void)
  {
+       struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
        twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
        disable_percpu_irq(clk->irq);
  }
@@@ -106,7 -108,7 +108,7 @@@ static void twd_update_frequency(void *
  {
        twd_timer_rate = *((unsigned long *) new_rate);
  
-       clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate);
+       clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
  }
  
  static int twd_rate_change(struct notifier_block *nb,
         * changing cpu.
         */
        if (flags == POST_RATE_CHANGE)
 -              smp_call_function(twd_update_frequency,
 +              on_each_cpu(twd_update_frequency,
                                  (void *)&cnd->new_rate, 1);
  
        return NOTIFY_OK;
@@@ -132,7 -134,7 +134,7 @@@ static struct notifier_block twd_clk_n
  
  static int twd_clk_init(void)
  {
-       if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+       if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
                return clk_notifier_register(twd_clk, &twd_clk_nb);
  
        return 0;
@@@ -151,7 -153,7 +153,7 @@@ static void twd_update_frequency(void *
  {
        twd_timer_rate = clk_get_rate(twd_clk);
  
-       clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate);
+       clockevents_update_freq(__this_cpu_ptr(twd_evt), twd_timer_rate);
  }
  
  static int twd_cpufreq_transition(struct notifier_block *nb,
@@@ -177,7 -179,7 +179,7 @@@ static struct notifier_block twd_cpufre
  
  static int twd_cpufreq_init(void)
  {
-       if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+       if (twd_evt && __this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
                return cpufreq_register_notifier(&twd_cpufreq_nb,
                        CPUFREQ_TRANSITION_NOTIFIER);
  
@@@ -187,7 -189,7 +189,7 @@@ core_initcall(twd_cpufreq_init)
  
  #endif
  
 -static void __cpuinit twd_calibrate_rate(void)
 +static void twd_calibrate_rate(void)
  {
        unsigned long count;
        u64 waitjiffies;
  
  static irqreturn_t twd_handler(int irq, void *dev_id)
  {
-       struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+       struct clock_event_device *evt = dev_id;
  
        if (twd_timer_ack()) {
                evt->event_handler(evt);
@@@ -265,9 -267,9 +267,9 @@@ static void twd_get_clock(struct device
  /*
   * Setup the local clock events for a CPU.
   */
- static int twd_timer_setup(struct clock_event_device *clk)
 -static void __cpuinit twd_timer_setup(void)
++static void twd_timer_setup(void)
  {
-       struct clock_event_device **this_cpu_clk;
+       struct clock_event_device *clk = __this_cpu_ptr(twd_evt);
        int cpu = smp_processor_id();
  
        /*
         */
        if (per_cpu(percpu_setup_called, cpu)) {
                __raw_writel(0, twd_base + TWD_TIMER_CONTROL);
-               clockevents_register_device(*__this_cpu_ptr(twd_evt));
+               clockevents_register_device(clk);
                enable_percpu_irq(clk->irq, 0);
-               return 0;
+               return;
        }
        per_cpu(percpu_setup_called, cpu) = true;
  
        clk->set_mode = twd_set_mode;
        clk->set_next_event = twd_set_next_event;
        clk->irq = twd_ppi;
-       this_cpu_clk = __this_cpu_ptr(twd_evt);
-       *this_cpu_clk = clk;
+       clk->cpumask = cpumask_of(cpu);
  
        clockevents_config_and_register(clk, twd_timer_rate,
                                        0xf, 0xffffffff);
        enable_percpu_irq(clk->irq, 0);
+ }
  
-       return 0;
 -static int __cpuinit twd_timer_cpu_notify(struct notifier_block *self,
 -                                         unsigned long action, void *hcpu)
++static int twd_timer_cpu_notify(struct notifier_block *self,
++                              unsigned long action, void *hcpu)
+ {
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_STARTING:
+               twd_timer_setup();
+               break;
+       case CPU_DYING:
+               twd_timer_stop();
+               break;
+       }
+       return NOTIFY_OK;
  }
  
- static struct local_timer_ops twd_lt_ops = {
-       .setup  = twd_timer_setup,
-       .stop   = twd_timer_stop,
 -static struct notifier_block twd_timer_cpu_nb __cpuinitdata = {
++static struct notifier_block twd_timer_cpu_nb = {
+       .notifier_call = twd_timer_cpu_notify,
  };
  
  static int __init twd_local_timer_common_register(struct device_node *np)
  {
        int err;
  
-       twd_evt = alloc_percpu(struct clock_event_device *);
+       twd_evt = alloc_percpu(struct clock_event_device);
        if (!twd_evt) {
                err = -ENOMEM;
                goto out_free;
                goto out_free;
        }
  
-       err = local_timer_register(&twd_lt_ops);
+       err = register_cpu_notifier(&twd_timer_cpu_nb);
        if (err)
                goto out_irq;
  
        twd_get_clock(np);
  
+       /*
+        * Immediately configure the timer on the boot CPU, unless we need
+        * jiffies to be incrementing to calibrate the rate in which case
+        * setup the timer in late_time_init.
+        */
+       if (twd_timer_rate)
+               twd_timer_setup();
+       else
+               late_time_init = twd_timer_setup;
        return 0;
  
  out_irq:
index f54656091a9d67dfe896e00ad909ad73d0674570,c8adc79028b8fead4594e41b7ae17aca7e53ad85..21fa9fa3d54ec5f10e80496e0c980dd5581eb9a6
@@@ -56,6 -56,9 +56,6 @@@ config MXC_USE_EPI
          uses the same clocks as the GPT. Anyway, on some systems the GPT
          may be in use for other purposes.
  
 -config MXC_ULPI
 -      bool
 -
  config ARCH_HAS_RNGA
        bool
  
@@@ -108,6 -111,7 +108,6 @@@ config SOC_IMX2
        select ARCH_MXC_IOMUX_V3
        select COMMON_CLK
        select CPU_ARM926T
 -      select HAVE_CAN_FLEXCAN if CAN
        select MXC_AVIC
  
  config SOC_IMX27
@@@ -133,6 -137,7 +133,6 @@@ config SOC_IMX3
        select ARCH_MXC_IOMUX_V3
        select COMMON_CLK
        select CPU_V6K
 -      select HAVE_CAN_FLEXCAN if CAN
        select HAVE_EPIT
        select MXC_AVIC
        select SMP_ON_UP if SMP
@@@ -171,7 -176,6 +171,7 @@@ config ARCH_MX1AD
  config MACH_SCB9328
        bool "Synertronixx scb9328"
        select IMX_HAVE_PLATFORM_IMX_UART
 +      select SOC_IMX1
        help
          Say Y here if you are using a Synertronixx scb9328 board
  
@@@ -229,7 -233,7 +229,7 @@@ config MACH_EUKREA_CPUIMX25S
        select IMX_HAVE_PLATFORM_MXC_EHCI
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX25
  
  choice
@@@ -280,7 -284,7 +280,7 @@@ config MACH_PCM03
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_MXC_W1
        select IMX_HAVE_PLATFORM_SPI_IMX
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX27
        help
          Include support for phyCORE-i.MX27 (aka pcm038) platform. This
@@@ -310,7 -314,7 +310,7 @@@ config MACH_CPUIMX2
        select IMX_HAVE_PLATFORM_MXC_EHCI
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_MXC_W1
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX27
        help
          Include support for Eukrea CPUIMX27 platform. This includes
@@@ -365,7 -369,7 +365,7 @@@ config MACH_MX27_3D
        select IMX_HAVE_PLATFORM_MXC_MMC
        select IMX_HAVE_PLATFORM_SPI_IMX
        select MXC_DEBUG_BOARD
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX27
        help
          Include support for MX27PDK platform. This includes specific
@@@ -410,7 -414,7 +410,7 @@@ config MACH_PCA10
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_MXC_W1
        select IMX_HAVE_PLATFORM_SPI_IMX
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX27
        help
          Include support for phyCARD-s (aka pca100) platform. This
@@@ -477,7 -481,7 +477,7 @@@ config MACH_MX31LILL
        select IMX_HAVE_PLATFORM_MXC_EHCI
        select IMX_HAVE_PLATFORM_MXC_MMC
        select IMX_HAVE_PLATFORM_SPI_IMX
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX31
        help
          Include support for mx31 based LILLY1131 modules. This includes
@@@ -493,7 -497,7 +493,7 @@@ config MACH_MX31LIT
        select IMX_HAVE_PLATFORM_MXC_RTC
        select IMX_HAVE_PLATFORM_SPI_IMX
        select LEDS_GPIO_REGISTER
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX31
        help
          Include support for MX31 LITEKIT platform. This includes specific
@@@ -510,7 -514,7 +510,7 @@@ config MACH_PCM03
        select IMX_HAVE_PLATFORM_MXC_MMC
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_MXC_W1
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX31
        help
          Include support for Phytec pcm037 platform. This includes
@@@ -540,7 -544,7 +540,7 @@@ config MACH_MX31_3D
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_SPI_IMX
        select MXC_DEBUG_BOARD
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX31
        help
          Include support for MX31PDK (3DS) platform. This includes specific
@@@ -567,7 -571,7 +567,7 @@@ config MACH_MX31MOBOAR
        select IMX_HAVE_PLATFORM_MXC_MMC
        select IMX_HAVE_PLATFORM_SPI_IMX
        select LEDS_GPIO_REGISTER
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX31
        help
          Include support for mx31moboard platform. This includes specific
@@@ -591,7 -595,7 +591,7 @@@ config MACH_ARMADILLO5X
        select IMX_HAVE_PLATFORM_MXC_EHCI
        select IMX_HAVE_PLATFORM_MXC_MMC
        select IMX_HAVE_PLATFORM_MXC_NAND
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX31
        help
          Include support for Atmark Armadillo-500 platform. This includes
@@@ -635,7 -639,7 +635,7 @@@ config MACH_PCM04
        select IMX_HAVE_PLATFORM_MXC_EHCI
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX35
        help
          Include support for Phytec pcm043 platform. This includes
@@@ -669,7 -673,7 +669,7 @@@ config MACH_EUKREA_CPUIMX35S
        select IMX_HAVE_PLATFORM_MXC_EHCI
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 -      select MXC_ULPI if USB_ULPI
 +      select USB_ULPI_VIEWPORT if USB_ULPI
        select SOC_IMX35
        help
          Include support for Eukrea CPUIMX35 platform. This includes
@@@ -772,6 -776,7 +772,6 @@@ comment "Device tree only
  
  config        SOC_IMX53
        bool "i.MX53 support"
 -      select HAVE_CAN_FLEXCAN if CAN
        select HAVE_IMX_SRC
        select IMX_HAVE_PLATFORM_IMX2_WDT
        select PINCTRL
@@@ -793,7 -798,8 +793,8 @@@ config SOC_IMX6
        select COMMON_CLK
        select CPU_V7
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
+       select HAVE_CAN_FLEXCAN if CAN
        select HAVE_IMX_ANATOP
        select HAVE_IMX_GPC
        select HAVE_IMX_MMDC
        help
          This enables support for Freescale i.MX6 Quad processor.
  
 +config SOC_IMX6SL
 +      bool "i.MX6 SoloLite support"
 +      select ARM_ERRATA_754322
 +      select ARM_ERRATA_775420
 +      select ARM_GIC
 +      select CPU_V7
 +      select HAVE_IMX_ANATOP
 +      select HAVE_IMX_GPC
 +      select HAVE_IMX_MMDC
 +      select HAVE_IMX_SRC
 +      select MFD_SYSCON
 +      select PINCTRL
 +      select PINCTRL_IMX6SL
 +      select PL310_ERRATA_588369 if CACHE_PL310
 +      select PL310_ERRATA_727915 if CACHE_PL310
 +      select PL310_ERRATA_769419 if CACHE_PL310
 +
 +      help
 +        This enables support for Freescale i.MX6 SoloLite processor.
 +
 +config SOC_VF610
 +      bool "Vybrid Family VF610 support"
 +      select CPU_V7
 +      select ARM_GIC
 +      select CLKSRC_OF
 +      select PINCTRL
 +      select PINCTRL_VF610
 +      select VF_PIT_TIMER
 +      select PL310_ERRATA_588369 if CACHE_PL310
 +      select PL310_ERRATA_727915 if CACHE_PL310
 +      select PL310_ERRATA_769419 if CACHE_PL310
 +
 +      help
 +        This enable support for Freescale Vybrid VF610 processor.
 +
  endif
  
  source "arch/arm/mach-imx/devices/Kconfig"
index 8697cfc0d0b6a74538a59eaf92bd3266a10bab9f,dacdcfdbc3424d57a99e91ebc1385f94323633ed..a7afbacae61a13715a61c790056fbfe58519d2ba
@@@ -16,6 -16,7 +16,7 @@@
  
  #include <linux/clocksource.h>
  #include <linux/clockchips.h>
+ #include <linux/cpu.h>
  #include <linux/init.h>
  #include <linux/interrupt.h>
  #include <linux/irq.h>
@@@ -26,7 -27,6 +27,6 @@@
  #include <linux/sched_clock.h>
  
  #include <asm/mach/time.h>
- #include <asm/localtimer.h>
  
  #include "common.h"
  
@@@ -49,7 -49,7 +49,7 @@@ static void __iomem *sts_base
  
  static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
  {
-       struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+       struct clock_event_device *evt = dev_id;
        /* Stop the timer tick */
        if (evt->mode == CLOCK_EVT_MODE_ONESHOT) {
                u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
@@@ -101,18 -101,7 +101,7 @@@ static void msm_timer_set_mode(enum clo
        writel_relaxed(ctrl, event_base + TIMER_ENABLE);
  }
  
- static struct clock_event_device msm_clockevent = {
-       .name           = "gp_timer",
-       .features       = CLOCK_EVT_FEAT_ONESHOT,
-       .rating         = 200,
-       .set_next_event = msm_timer_set_next_event,
-       .set_mode       = msm_timer_set_mode,
- };
- static union {
-       struct clock_event_device *evt;
-       struct clock_event_device * __percpu *percpu_evt;
- } msm_evt;
+ static struct clock_event_device __percpu *msm_evt;
  
  static void __iomem *source_base;
  
@@@ -138,37 -127,65 +127,65 @@@ static struct clocksource msm_clocksour
        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
  };
  
- #ifdef CONFIG_LOCAL_TIMERS
+ static int msm_timer_irq;
+ static int msm_timer_has_ppi;
 -static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt)
 +static int msm_local_timer_setup(struct clock_event_device *evt)
  {
-       /* Use existing clock_event for cpu 0 */
-       if (!smp_processor_id())
-               return 0;
-       evt->irq = msm_clockevent.irq;
-       evt->name = "local_timer";
-       evt->features = msm_clockevent.features;
-       evt->rating = msm_clockevent.rating;
+       int cpu = smp_processor_id();
+       int err;
+       evt->irq = msm_timer_irq;
+       evt->name = "msm_timer";
+       evt->features = CLOCK_EVT_FEAT_ONESHOT;
+       evt->rating = 200;
        evt->set_mode = msm_timer_set_mode;
        evt->set_next_event = msm_timer_set_next_event;
+       evt->cpumask = cpumask_of(cpu);
+       clockevents_config_and_register(evt, GPT_HZ, 4, 0xffffffff);
+       if (msm_timer_has_ppi) {
+               enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
+       } else {
+               err = request_irq(evt->irq, msm_timer_interrupt,
+                               IRQF_TIMER | IRQF_NOBALANCING |
+                               IRQF_TRIGGER_RISING, "gp_timer", evt);
+               if (err)
+                       pr_err("request_irq failed\n");
+       }
  
-       *__this_cpu_ptr(msm_evt.percpu_evt) = evt;
-       clockevents_config_and_register(evt, GPT_HZ, 4, 0xf0000000);
-       enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
        return 0;
  }
  
 -static void __cpuinit msm_local_timer_stop(struct clock_event_device *evt)
 +static void msm_local_timer_stop(struct clock_event_device *evt)
  {
        evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
        disable_percpu_irq(evt->irq);
  }
  
- static struct local_timer_ops msm_local_timer_ops = {
-       .setup  = msm_local_timer_setup,
-       .stop   = msm_local_timer_stop,
 -static int __cpuinit msm_timer_cpu_notify(struct notifier_block *self,
++static int msm_timer_cpu_notify(struct notifier_block *self,
+                                          unsigned long action, void *hcpu)
+ {
+       /*
+        * Grab cpu pointer in each case to avoid spurious
+        * preemptible warnings
+        */
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_STARTING:
+               msm_local_timer_setup(this_cpu_ptr(msm_evt));
+               break;
+       case CPU_DYING:
+               msm_local_timer_stop(this_cpu_ptr(msm_evt));
+               break;
+       }
+       return NOTIFY_OK;
+ }
 -static struct notifier_block msm_timer_cpu_nb __cpuinitdata = {
++static struct notifier_block msm_timer_cpu_nb = {
+       .notifier_call = msm_timer_cpu_notify,
  };
- #endif /* CONFIG_LOCAL_TIMERS */
  
  static notrace u32 msm_sched_clock_read(void)
  {
  static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
                                  bool percpu)
  {
-       struct clock_event_device *ce = &msm_clockevent;
        struct clocksource *cs = &msm_clocksource;
-       int res;
+       int res = 0;
+       msm_timer_irq = irq;
+       msm_timer_has_ppi = percpu;
+       msm_evt = alloc_percpu(struct clock_event_device);
+       if (!msm_evt) {
+               pr_err("memory allocation failed for clockevents\n");
+               goto err;
+       }
  
-       ce->cpumask = cpumask_of(0);
-       ce->irq = irq;
+       if (percpu)
+               res = request_percpu_irq(irq, msm_timer_interrupt,
+                                        "gp_timer", msm_evt);
  
-       clockevents_config_and_register(ce, GPT_HZ, 4, 0xffffffff);
-       if (percpu) {
-               msm_evt.percpu_evt = alloc_percpu(struct clock_event_device *);
-               if (!msm_evt.percpu_evt) {
-                       pr_err("memory allocation failed for %s\n", ce->name);
+       if (res) {
+               pr_err("request_percpu_irq failed\n");
+       } else {
+               res = register_cpu_notifier(&msm_timer_cpu_nb);
+               if (res) {
+                       free_percpu_irq(irq, msm_evt);
                        goto err;
                }
-               *__this_cpu_ptr(msm_evt.percpu_evt) = ce;
-               res = request_percpu_irq(ce->irq, msm_timer_interrupt,
-                                        ce->name, msm_evt.percpu_evt);
-               if (!res) {
-                       enable_percpu_irq(ce->irq, IRQ_TYPE_EDGE_RISING);
- #ifdef CONFIG_LOCAL_TIMERS
-                       local_timer_register(&msm_local_timer_ops);
- #endif
-               }
-       } else {
-               msm_evt.evt = ce;
-               res = request_irq(ce->irq, msm_timer_interrupt,
-                                 IRQF_TIMER | IRQF_NOBALANCING |
-                                 IRQF_TRIGGER_RISING, ce->name, &msm_evt.evt);
+               /* Immediately configure the timer on the boot CPU */
+               msm_local_timer_setup(__this_cpu_ptr(msm_evt));
        }
  
-       if (res)
-               pr_err("request_irq failed for %s\n", ce->name);
  err:
        writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE);
        res = clocksource_register_hz(cs, dgt_hz);
index 627fa7e41fbabbeccf38c1703dc26ed2a98d66db,4e0049a6060690bb14032ee1e775e3613727d796..3d6ee149d3d79753bc039f087acaa8a4cce61a19
@@@ -1,10 -1,61 +1,10 @@@
  config ARCH_OMAP
        bool
  
 -config ARCH_OMAP2PLUS
 -      bool "TI OMAP2/3/4/5 SoCs with device tree support" if (ARCH_MULTI_V6 || ARCH_MULTI_V7)
 -      select ARCH_HAS_CPUFREQ
 -      select ARCH_HAS_HOLES_MEMORYMODEL
 -      select ARCH_OMAP
 -      select ARCH_REQUIRE_GPIOLIB
 -      select CLKDEV_LOOKUP
 -      select CLKSRC_MMIO
 -      select GENERIC_CLOCKEVENTS
 -      select GENERIC_IRQ_CHIP
 -      select HAVE_CLK
 -      select OMAP_DM_TIMER
 -      select PINCTRL
 -      select PROC_DEVICETREE if PROC_FS
 -      select SOC_BUS
 -      select SPARSE_IRQ
 -      select USE_OF
 -      help
 -        Systems based on OMAP2, OMAP3, OMAP4 or OMAP5
 -
 -
 -if ARCH_OMAP2PLUS
 -
 -menu "TI OMAP2/3/4 Specific Features"
 -
 -config ARCH_OMAP2PLUS_TYPICAL
 -      bool "Typical OMAP configuration"
 -      default y
 -      select AEABI
 -      select HIGHMEM
 -      select I2C
 -      select I2C_OMAP
 -      select MENELAUS if ARCH_OMAP2
 -      select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5
 -      select PM_RUNTIME
 -      select REGULATOR
 -      select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
 -      select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
 -      select VFP
 -      help
 -        Compile a kernel suitable for booting most boards
 -
 -config SOC_HAS_OMAP2_SDRC
 -      bool "OMAP2 SDRAM Controller support"
 -
 -config SOC_HAS_REALTIME_COUNTER
 -      bool "Real time free running counter"
 -      depends on SOC_OMAP5
 -      default y
 -
  config ARCH_OMAP2
        bool "TI OMAP2"
 -      depends on ARCH_OMAP2PLUS
        depends on ARCH_MULTI_V6
 -      default y
 +      select ARCH_OMAP2PLUS
        select CPU_V6
        select MULTI_IRQ_HANDLER
        select SOC_HAS_OMAP2_SDRC
@@@ -12,8 -63,9 +12,8 @@@
  
  config ARCH_OMAP3
        bool "TI OMAP3"
 -      depends on ARCH_OMAP2PLUS
        depends on ARCH_MULTI_V7
 -      default y
 +      select ARCH_OMAP2PLUS
        select ARCH_HAS_OPP
        select ARM_CPU_SUSPEND if PM
        select CPU_V7
@@@ -27,8 -79,9 +27,8 @@@
  
  config ARCH_OMAP4
        bool "TI OMAP4"
 -      default y
 -      depends on ARCH_OMAP2PLUS
        depends on ARCH_MULTI_V7
 +      select ARCH_OMAP2PLUS
        select ARCH_HAS_OPP
        select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
        select ARM_CPU_SUSPEND if PM
@@@ -37,9 -90,8 +37,8 @@@
        select CACHE_L2X0
        select CPU_V7
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
-       select LOCAL_TIMERS if SMP
        select OMAP_INTERCONNECT
        select PL310_ERRATA_588369
        select PL310_ERRATA_727915
  config SOC_OMAP5
        bool "TI OMAP5"
        depends on ARCH_MULTI_V7
 +      select ARCH_OMAP2PLUS
        select ARM_CPU_SUSPEND if PM
        select ARM_GIC
        select CPU_V7
 +      select HAVE_ARM_SCU if SMP
 +      select HAVE_ARM_TWD if LOCAL_TIMERS
        select HAVE_SMP
        select COMMON_CLK
        select HAVE_ARM_ARCH_TIMER
 +      select ARM_ERRATA_798181
 +
 +config SOC_AM33XX
 +      bool "AM33XX support"
 +      depends on ARCH_MULTI_V7
 +      select ARCH_OMAP2PLUS
 +      select ARM_CPU_SUSPEND if PM
 +      select CPU_V7
 +      select MULTI_IRQ_HANDLER
 +      select COMMON_CLK
 +
 +config SOC_AM43XX
 +      bool "TI AM43x"
 +      depends on ARCH_MULTI_V7
 +      select CPU_V7
 +      select ARCH_OMAP2PLUS
 +      select MULTI_IRQ_HANDLER
 +      select ARM_GIC
 +      select COMMON_CLK
 +      select MACH_OMAP_GENERIC
 +
 +config ARCH_OMAP2PLUS
 +      bool
 +      select ARCH_HAS_BANDGAP
 +      select ARCH_HAS_CPUFREQ
 +      select ARCH_HAS_HOLES_MEMORYMODEL
 +      select ARCH_OMAP
 +      select ARCH_REQUIRE_GPIOLIB
 +      select CLKDEV_LOOKUP
 +      select CLKSRC_MMIO
 +      select GENERIC_CLOCKEVENTS
 +      select GENERIC_IRQ_CHIP
 +      select HAVE_CLK
 +      select OMAP_DM_TIMER
 +      select PINCTRL
 +      select PROC_DEVICETREE if PROC_FS
 +      select SOC_BUS
 +      select SPARSE_IRQ
 +      select TI_PRIV_EDMA
 +      select USE_OF
 +      help
 +        Systems based on OMAP2, OMAP3, OMAP4 or OMAP5
 +
 +
 +if ARCH_OMAP2PLUS
 +
 +menu "TI OMAP2/3/4 Specific Features"
 +
 +config ARCH_OMAP2PLUS_TYPICAL
 +      bool "Typical OMAP configuration"
 +      default y
 +      select AEABI
 +      select HIGHMEM
 +      select I2C
 +      select I2C_OMAP
 +      select MENELAUS if ARCH_OMAP2
 +      select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5
 +      select PM_RUNTIME
 +      select REGULATOR
 +      select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
 +      select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
 +      select VFP
 +      help
 +        Compile a kernel suitable for booting most boards
 +
 +config SOC_HAS_OMAP2_SDRC
 +      bool "OMAP2 SDRAM Controller support"
 +
 +config SOC_HAS_REALTIME_COUNTER
 +      bool "Real time free running counter"
 +      depends on SOC_OMAP5
 +      default y
  
  comment "OMAP Core Type"
        depends on ARCH_OMAP2
@@@ -162,6 -139,15 +161,6 @@@ config SOC_TI81X
        depends on ARCH_OMAP3
        default y
  
 -config SOC_AM33XX
 -      bool "AM33XX support"
 -      depends on ARCH_MULTI_V7
 -      default y
 -      select ARM_CPU_SUSPEND if PM
 -      select CPU_V7
 -      select MULTI_IRQ_HANDLER
 -      select COMMON_CLK
 -
  config OMAP_PACKAGE_ZAF
         bool
  
@@@ -180,6 -166,12 +179,6 @@@ config OMAP_PACKAGE_CU
  config OMAP_PACKAGE_CBP
         bool
  
 -config OMAP_PACKAGE_CBL
 -       bool
 -
 -config OMAP_PACKAGE_CBS
 -       bool
 -
  comment "OMAP Board Type"
        depends on ARCH_OMAP2PLUS
  
@@@ -385,6 -377,22 +384,6 @@@ config MACH_TI8148EV
        depends on SOC_TI81XX
        default y
  
 -config MACH_OMAP_4430SDP
 -      bool "OMAP 4430 SDP board"
 -      default y
 -      depends on ARCH_OMAP4
 -      select OMAP_PACKAGE_CBL
 -      select OMAP_PACKAGE_CBS
 -      select REGULATOR_FIXED_VOLTAGE if REGULATOR
 -
 -config MACH_OMAP4_PANDA
 -      bool "OMAP4 Panda Board"
 -      default y
 -      depends on ARCH_OMAP4
 -      select OMAP_PACKAGE_CBL
 -      select OMAP_PACKAGE_CBS
 -      select REGULATOR_FIXED_VOLTAGE if REGULATOR
 -
  config OMAP3_EMU
        bool "OMAP3 debugging peripherals"
        depends on ARCH_OMAP3
index b37e1fcbad56340a4e07a8a06e25504db2a7f457,3b7cabacbcf5c268d5d4dd902966204811779c83..8e99ca368e079747c59433d74570ee52f5b89fa0
@@@ -220,7 -220,7 +220,7 @@@ static int __init omap_dm_timer_init_on
                                         int posted)
  {
        char name[10]; /* 10 = sizeof("gptXX_Xck0") */
 -      const char *oh_name;
 +      const char *oh_name = NULL;
        struct device_node *np;
        struct omap_hwmod *oh;
        struct resource irq, mem;
@@@ -582,7 -582,7 +582,7 @@@ OMAP_SYS_32K_TIMER_INIT(2, 1, "timer_32
                        2, "timer_sys_ck", NULL);
  #endif /* CONFIG_ARCH_OMAP2 */
  
 -#ifdef CONFIG_ARCH_OMAP3
 +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM43XX)
  OMAP_SYS_32K_TIMER_INIT(3, 1, "timer_32k_ck", "ti,timer-alwon",
                        2, "timer_sys_ck", NULL);
  OMAP_SYS_32K_TIMER_INIT(3_secure, 12, "secure_32k_fck", "ti,timer-secure",
@@@ -600,7 -600,6 +600,6 @@@ static OMAP_SYS_32K_TIMER_INIT(4, 1, "t
  #endif
  
  #ifdef CONFIG_ARCH_OMAP4
- #ifdef CONFIG_LOCAL_TIMERS
  static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
  void __init omap4_local_timer_init(void)
  {
                        pr_err("twd_local_timer_register failed %d\n", err);
        }
  }
- #else /* CONFIG_LOCAL_TIMERS */
- void __init omap4_local_timer_init(void)
- {
-       omap4_sync32k_timer_init();
- }
- #endif /* CONFIG_LOCAL_TIMERS */
  #endif /* CONFIG_ARCH_OMAP4 */
  
  #ifdef CONFIG_SOC_OMAP5
index ef3a8da49b2d223616514c364e554f14add271d1,1f3ea1f6cedf5e0b9b3b48fdc4db428e43e8d980..59925cc896fb324e0340b0a836a65b8383e011d8
@@@ -8,7 -8,7 +8,7 @@@ config ARCH_TEGR
        select COMMON_CLK
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_CLK
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
@@@ -28,6 -28,7 +28,6 @@@ config ARCH_TEGRA_2x_SO
        select ARM_ERRATA_754327 if SMP
        select ARM_ERRATA_764369 if SMP
        select ARM_GIC
 -      select CPU_FREQ_TABLE if CPU_FREQ
        select CPU_V7
        select PINCTRL
        select PINCTRL_TEGRA20
@@@ -45,6 -46,7 +45,6 @@@ config ARCH_TEGRA_3x_SO
        select ARM_ERRATA_754322
        select ARM_ERRATA_764369 if SMP
        select ARM_GIC
 -      select CPU_FREQ_TABLE if CPU_FREQ
        select CPU_V7
        select PINCTRL
        select PINCTRL_TEGRA30
  
  config ARCH_TEGRA_114_SOC
        bool "Enable support for Tegra114 family"
 -      select ARM_ARCH_TIMER
 +      select HAVE_ARM_ARCH_TIMER
        select ARM_GIC
        select ARM_L1_CACHE_SHIFT_6
 -      select CPU_FREQ_TABLE if CPU_FREQ
        select CPU_V7
        select PINCTRL
        select PINCTRL_TEGRA114
index b19b07204aafbeb53ced9f4226164ecd9c036cff,0614ee2b052394c19954cb887e7110ff4f669e4e..99a28d62829742d9103764c47abcb5ff24894fbf
@@@ -8,7 -8,7 +8,7 @@@ config ARCH_U850
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
        help
@@@ -51,7 -51,6 +51,7 @@@ config MACH_MOP50
        bool "U8500 Development platform, MOP500 versions"
        select I2C
        select I2C_NOMADIK
 +      select REGULATOR
        select REGULATOR_FIXED_VOLTAGE
        select SOC_BUS
        select UX500_SOC_DB8500
index b8bbabec6310b1a1090a23b60dd84d4009275b0c,5bfdd73dea19de00decfb7dddeab1c9d43d39d8c..83c8677bb1817894dd394287dbeb1da5c3b60969
@@@ -10,7 -10,7 +10,7 @@@ config ARCH_VEXPRES
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if LOCAL_TIMERS
+       select HAVE_ARM_TWD if SMP
        select HAVE_CLK
        select HAVE_PATA_PLATFORM
        select HAVE_SMP
@@@ -57,13 -57,4 +57,13 @@@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRAT
  config ARCH_VEXPRESS_CA9X4
        bool "Versatile Express Cortex-A9x4 tile"
  
 +config ARCH_VEXPRESS_DCSCB
 +      bool "Dual Cluster System Control Block (DCSCB) support"
 +      depends on MCPM
 +      select ARM_CCI
 +      help
 +        Support for the Dual Cluster System Configuration Block (DCSCB).
 +        This is needed to provide CPU and cluster power management
 +        on RTSM implementing big.LITTLE.
 +
  endmenu
index b2bbc415f12055886a53288d1cca2d11a91a304c,1c3f5a652044192b8d38da2ac76286751990e8f9..5b34768f4d7c79f68253966acc8e8268e53f318e
@@@ -16,6 -16,7 +16,7 @@@
  #include <linux/err.h>
  #include <linux/clk.h>
  #include <linux/clockchips.h>
+ #include <linux/cpu.h>
  #include <linux/platform_device.h>
  #include <linux/delay.h>
  #include <linux/percpu.h>
@@@ -24,7 -25,6 +25,6 @@@
  #include <linux/of_address.h>
  #include <linux/clocksource.h>
  
- #include <asm/localtimer.h>
  #include <asm/mach/time.h>
  
  #define EXYNOS4_MCTREG(x)             (x)
@@@ -80,7 -80,7 +80,7 @@@ static unsigned int mct_int_type
  static int mct_irqs[MCT_NR_IRQS];
  
  struct mct_clock_event_device {
-       struct clock_event_device *evt;
+       struct clock_event_device evt;
        unsigned long base;
        char name[10];
  };
@@@ -295,8 -295,6 +295,6 @@@ static void exynos4_clockevent_init(voi
        setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq);
  }
  
- #ifdef CONFIG_LOCAL_TIMERS
  static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick);
  
  /* Clock event handling */
@@@ -369,7 -367,7 +367,7 @@@ static inline void exynos4_tick_set_mod
  
  static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
  {
-       struct clock_event_device *evt = mevt->evt;
+       struct clock_event_device *evt = &mevt->evt;
  
        /*
         * This is for supporting oneshot mode.
  static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
  {
        struct mct_clock_event_device *mevt = dev_id;
-       struct clock_event_device *evt = mevt->evt;
+       struct clock_event_device *evt = &mevt->evt;
  
        exynos4_mct_tick_clear(mevt);
  
        return IRQ_HANDLED;
  }
  
 -static struct irqaction mct_tick0_event_irq = {
 -      .name           = "mct_tick0_irq",
 -      .flags          = IRQF_TIMER | IRQF_NOBALANCING,
 -      .handler        = exynos4_mct_tick_isr,
 -};
 -
 -static struct irqaction mct_tick1_event_irq = {
 -      .name           = "mct_tick1_irq",
 -      .flags          = IRQF_TIMER | IRQF_NOBALANCING,
 -      .handler        = exynos4_mct_tick_isr,
 -};
 -
 -static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
 +static int exynos4_local_timer_setup(struct clock_event_device *evt)
  {
        struct mct_clock_event_device *mevt;
        unsigned int cpu = smp_processor_id();
  
-       mevt = this_cpu_ptr(&percpu_mct_tick);
-       mevt->evt = evt;
+       mevt = container_of(evt, struct mct_clock_event_device, evt);
  
        mevt->base = EXYNOS4_MCT_L_BASE(cpu);
        sprintf(mevt->name, "mct_tick%d", cpu);
        exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET);
  
        if (mct_int_type == MCT_INT_SPI) {
 -              if (cpu == 0) {
 -                      mct_tick0_event_irq.dev_id = mevt;
 -                      evt->irq = mct_irqs[MCT_L0_IRQ];
 -                      setup_irq(evt->irq, &mct_tick0_event_irq);
 -              } else {
 -                      mct_tick1_event_irq.dev_id = mevt;
 -                      evt->irq = mct_irqs[MCT_L1_IRQ];
 -                      setup_irq(evt->irq, &mct_tick1_event_irq);
 -                      irq_set_affinity(evt->irq, cpumask_of(1));
 +              evt->irq = mct_irqs[MCT_L0_IRQ + cpu];
 +              if (request_irq(evt->irq, exynos4_mct_tick_isr,
 +                              IRQF_TIMER | IRQF_NOBALANCING,
 +                              evt->name, mevt)) {
 +                      pr_err("exynos-mct: cannot register IRQ %d\n",
 +                              evt->irq);
 +                      return -EIO;
                }
 +              irq_set_affinity(evt->irq, cpumask_of(cpu));
        } else {
                enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
        }
        return 0;
  }
  
 -static void __cpuinit exynos4_local_timer_stop(struct clock_event_device *evt)
 +static void exynos4_local_timer_stop(struct clock_event_device *evt)
  {
 -      unsigned int cpu = smp_processor_id();
        evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
        if (mct_int_type == MCT_INT_SPI)
 -              if (cpu == 0)
 -                      remove_irq(evt->irq, &mct_tick0_event_irq);
 -              else
 -                      remove_irq(evt->irq, &mct_tick1_event_irq);
 +              free_irq(evt->irq, this_cpu_ptr(&percpu_mct_tick));
        else
                disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
  }
  
- static struct local_timer_ops exynos4_mct_tick_ops = {
-       .setup  = exynos4_local_timer_setup,
-       .stop   = exynos4_local_timer_stop,
 -static int __cpuinit exynos4_mct_cpu_notify(struct notifier_block *self,
++static int exynos4_mct_cpu_notify(struct notifier_block *self,
+                                          unsigned long action, void *hcpu)
+ {
+       struct mct_clock_event_device *mevt;
+       /*
+        * Grab cpu pointer in each case to avoid spurious
+        * preemptible warnings
+        */
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_STARTING:
+               mevt = this_cpu_ptr(&percpu_mct_tick);
+               exynos4_local_timer_setup(&mevt->evt);
+               break;
+       case CPU_DYING:
+               mevt = this_cpu_ptr(&percpu_mct_tick);
+               exynos4_local_timer_stop(&mevt->evt);
+               break;
+       }
+       return NOTIFY_OK;
+ }
 -static struct notifier_block exynos4_mct_cpu_nb __cpuinitdata = {
++static struct notifier_block exynos4_mct_cpu_nb = {
+       .notifier_call = exynos4_mct_cpu_notify,
  };
- #endif /* CONFIG_LOCAL_TIMERS */
  
  static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base)
  {
+       int err;
+       struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick);
        struct clk *mct_clk, *tick_clk;
  
        tick_clk = np ? of_clk_get_by_name(np, "fin_pll") :
        if (!reg_base)
                panic("%s: unable to ioremap mct address space\n", __func__);
  
- #ifdef CONFIG_LOCAL_TIMERS
        if (mct_int_type == MCT_INT_PPI) {
-               int err;
  
                err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
                                         exynos4_mct_tick_isr, "MCT",
                     mct_irqs[MCT_L0_IRQ], err);
        }
  
-       local_timer_register(&exynos4_mct_tick_ops);
- #endif /* CONFIG_LOCAL_TIMERS */
+       err = register_cpu_notifier(&exynos4_mct_cpu_nb);
+       if (err)
+               goto out_irq;
+       /* Immediately configure the timer on the boot CPU */
+       exynos4_local_timer_setup(&mevt->evt);
+       return;
+ out_irq:
+       free_percpu_irq(mct_irqs[MCT_L0_IRQ], &percpu_mct_tick);
  }
  
  void __init mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1)
index 1b04b7e1d39b91c223c993baa88b44d408c3609e,f86542002ee1f21c5cace8559f619fa9ecb6b307..847cab6f6e31009f9a97560642ee4685497ead18
@@@ -19,6 -19,7 +19,7 @@@
  #include <linux/platform_device.h>
  #include <linux/kernel.h>
  #include <linux/clk.h>
+ #include <linux/cpu.h>
  #include <linux/timer.h>
  #include <linux/clockchips.h>
  #include <linux/interrupt.h>
@@@ -28,9 -29,9 +29,9 @@@
  #include <linux/irq.h>
  #include <linux/module.h>
  #include <linux/sched_clock.h>
- #include <asm/localtimer.h>
  #include <linux/percpu.h>
+ #include <linux/time-armada-370-xp.h>
  /*
   * Timer block registers.
   */
@@@ -69,7 -70,7 +70,7 @@@ static bool timer25Mhz = true
   */
  static u32 ticks_per_jiffy;
  
- static struct clock_event_device __percpu **percpu_armada_370_xp_evt;
+ static struct clock_event_device __percpu *armada_370_xp_evt;
  
  static u32 notrace armada_370_xp_read_sched_clock(void)
  {
@@@ -142,21 -143,14 +143,14 @@@ armada_370_xp_clkevt_mode(enum clock_ev
        }
  }
  
- static struct clock_event_device armada_370_xp_clkevt = {
-       .name           = "armada_370_xp_per_cpu_tick",
-       .features       = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
-       .shift          = 32,
-       .rating         = 300,
-       .set_next_event = armada_370_xp_clkevt_next_event,
-       .set_mode       = armada_370_xp_clkevt_mode,
- };
+ static int armada_370_xp_clkevt_irq;
  
  static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id)
  {
        /*
         * ACK timer interrupt and call event handler.
         */
-       struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+       struct clock_event_device *evt = dev_id;
  
        writel(TIMER0_CLR_MASK, local_base + LCL_TIMER_EVENTS_STATUS);
        evt->event_handler(evt);
  /*
   * Setup the local clock events for a CPU.
   */
 -static int __cpuinit armada_370_xp_timer_setup(struct clock_event_device *evt)
 +static int armada_370_xp_timer_setup(struct clock_event_device *evt)
  {
        u32 u;
        int cpu = smp_processor_id();
  
-       /* Use existing clock_event for cpu 0 */
-       if (!smp_processor_id())
-               return 0;
        u = readl(local_base + TIMER_CTRL_OFF);
        if (timer25Mhz)
                writel(u | TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
        else
                writel(u & ~TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
  
-       evt->name               = armada_370_xp_clkevt.name;
-       evt->irq                = armada_370_xp_clkevt.irq;
-       evt->features           = armada_370_xp_clkevt.features;
-       evt->shift              = armada_370_xp_clkevt.shift;
-       evt->rating             = armada_370_xp_clkevt.rating,
+       evt->name               = "armada_370_xp_per_cpu_tick",
+       evt->features           = CLOCK_EVT_FEAT_ONESHOT |
+                                 CLOCK_EVT_FEAT_PERIODIC;
+       evt->shift              = 32,
+       evt->rating             = 300,
        evt->set_next_event     = armada_370_xp_clkevt_next_event,
        evt->set_mode           = armada_370_xp_clkevt_mode,
+       evt->irq                = armada_370_xp_clkevt_irq;
        evt->cpumask            = cpumask_of(cpu);
  
-       *__this_cpu_ptr(percpu_armada_370_xp_evt) = evt;
        clockevents_config_and_register(evt, timer_clk, 1, 0xfffffffe);
        enable_percpu_irq(evt->irq, 0);
  
        return 0;
  }
  
- static void  armada_370_xp_timer_stop(struct clock_event_device *evt)
 -static void __cpuinit armada_370_xp_timer_stop(struct clock_event_device *evt)
++static void armada_370_xp_timer_stop(struct clock_event_device *evt)
  {
        evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
        disable_percpu_irq(evt->irq);
  }
  
- static struct local_timer_ops armada_370_xp_local_timer_ops = {
-       .setup  = armada_370_xp_timer_setup,
-       .stop   =  armada_370_xp_timer_stop,
 -static int __cpuinit armada_370_xp_timer_cpu_notify(struct notifier_block *self,
++static int armada_370_xp_timer_cpu_notify(struct notifier_block *self,
+                                          unsigned long action, void *hcpu)
+ {
+       /*
+        * Grab cpu pointer in each case to avoid spurious
+        * preemptible warnings
+        */
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_STARTING:
+               armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
+               break;
+       case CPU_DYING:
+               armada_370_xp_timer_stop(this_cpu_ptr(armada_370_xp_evt));
+               break;
+       }
+       return NOTIFY_OK;
+ }
 -static struct notifier_block armada_370_xp_timer_cpu_nb __cpuinitdata = {
++static struct notifier_block armada_370_xp_timer_cpu_nb = {
+       .notifier_call = armada_370_xp_timer_cpu_notify,
  };
  
  void __init armada_370_xp_timer_init(void)
  
        if (of_find_property(np, "marvell,timer-25Mhz", NULL)) {
                /* The fixed 25MHz timer is available so let's use it */
-               u = readl(local_base + TIMER_CTRL_OFF);
-               writel(u | TIMER0_25MHZ,
-                      local_base + TIMER_CTRL_OFF);
                u = readl(timer_base + TIMER_CTRL_OFF);
                writel(u | TIMER0_25MHZ,
                       timer_base + TIMER_CTRL_OFF);
                struct clk *clk = of_clk_get(np, 0);
                WARN_ON(IS_ERR(clk));
                rate =  clk_get_rate(clk);
-               u = readl(local_base + TIMER_CTRL_OFF);
-               writel(u & ~(TIMER0_25MHZ),
-                      local_base + TIMER_CTRL_OFF);
  
                u = readl(timer_base + TIMER_CTRL_OFF);
                writel(u & ~(TIMER0_25MHZ),
         * We use timer 0 as clocksource, and private(local) timer 0
         * for clockevents
         */
-       armada_370_xp_clkevt.irq = irq_of_parse_and_map(np, 4);
+       armada_370_xp_clkevt_irq = irq_of_parse_and_map(np, 4);
  
        ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
  
                              "armada_370_xp_clocksource",
                              timer_clk, 300, 32, clocksource_mmio_readl_down);
  
-       /* Register the clockevent on the private timer of CPU 0 */
-       armada_370_xp_clkevt.cpumask = cpumask_of(0);
-       clockevents_config_and_register(&armada_370_xp_clkevt,
-                                       timer_clk, 1, 0xfffffffe);
+       register_cpu_notifier(&armada_370_xp_timer_cpu_nb);
  
-       percpu_armada_370_xp_evt = alloc_percpu(struct clock_event_device *);
+       armada_370_xp_evt = alloc_percpu(struct clock_event_device);
  
  
        /*
         * Setup clockevent timer (interrupt-driven).
         */
-       *__this_cpu_ptr(percpu_armada_370_xp_evt) = &armada_370_xp_clkevt;
-       res = request_percpu_irq(armada_370_xp_clkevt.irq,
+       res = request_percpu_irq(armada_370_xp_clkevt_irq,
                                armada_370_xp_timer_interrupt,
-                               armada_370_xp_clkevt.name,
-                               percpu_armada_370_xp_evt);
-       if (!res) {
-               enable_percpu_irq(armada_370_xp_clkevt.irq, 0);
- #ifdef CONFIG_LOCAL_TIMERS
-               local_timer_register(&armada_370_xp_local_timer_ops);
- #endif
-       }
+                               "armada_370_xp_per_cpu_tick",
+                               armada_370_xp_evt);
+       /* Immediately configure the timer on the boot CPU */
+       if (!res)
+               armada_370_xp_timer_setup(this_cpu_ptr(armada_370_xp_evt));
  }
index 62876baa3ab9c2f69c680e316a4801b11e89777f,01b9683557b2e92f1e11e183eeb736517126efa3..09a17d9a6594c80e38c64bd18d6827db427df18b
@@@ -10,6 -10,7 +10,7 @@@
  #include <linux/interrupt.h>
  #include <linux/clockchips.h>
  #include <linux/clocksource.h>
+ #include <linux/cpu.h>
  #include <linux/bitops.h>
  #include <linux/irq.h>
  #include <linux/clk.h>
@@@ -18,7 -19,6 +19,6 @@@
  #include <linux/of_irq.h>
  #include <linux/of_address.h>
  #include <linux/sched_clock.h>
- #include <asm/localtimer.h>
  #include <asm/mach/time.h>
  
  #define SIRFSOC_TIMER_32COUNTER_0_CTRL                        0x0000
@@@ -151,13 -151,7 +151,7 @@@ static void sirfsoc_clocksource_resume(
                BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
  }
  
- static struct clock_event_device sirfsoc_clockevent = {
-       .name = "sirfsoc_clockevent",
-       .rating = 200,
-       .features = CLOCK_EVT_FEAT_ONESHOT,
-       .set_mode = sirfsoc_timer_set_mode,
-       .set_next_event = sirfsoc_timer_set_next_event,
- };
+ static struct clock_event_device __percpu *sirfsoc_clockevent;
  
  static struct clocksource sirfsoc_clocksource = {
        .name = "sirfsoc_clocksource",
@@@ -173,69 -167,87 +167,87 @@@ static struct irqaction sirfsoc_timer_i
        .name = "sirfsoc_timer0",
        .flags = IRQF_TIMER | IRQF_NOBALANCING,
        .handler = sirfsoc_timer_interrupt,
-       .dev_id = &sirfsoc_clockevent,
  };
  
- #ifdef CONFIG_LOCAL_TIMERS
  static struct irqaction sirfsoc_timer1_irq = {
        .name = "sirfsoc_timer1",
        .flags = IRQF_TIMER | IRQF_NOBALANCING,
        .handler = sirfsoc_timer_interrupt,
  };
  
 -static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce)
 +static int sirfsoc_local_timer_setup(struct clock_event_device *ce)
  {
-       /* Use existing clock_event for cpu 0 */
-       if (!smp_processor_id())
-               return 0;
+       int cpu = smp_processor_id();
+       struct irqaction *action;
+       if (cpu == 0)
+               action = &sirfsoc_timer_irq;
+       else
+               action = &sirfsoc_timer1_irq;
  
-       ce->irq = sirfsoc_timer1_irq.irq;
+       ce->irq = action->irq;
        ce->name = "local_timer";
-       ce->features = sirfsoc_clockevent.features;
-       ce->rating = sirfsoc_clockevent.rating;
+       ce->features = CLOCK_EVT_FEAT_ONESHOT;
+       ce->rating = 200;
        ce->set_mode = sirfsoc_timer_set_mode;
        ce->set_next_event = sirfsoc_timer_set_next_event;
-       ce->shift = sirfsoc_clockevent.shift;
-       ce->mult = sirfsoc_clockevent.mult;
-       ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
-       ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
+       clockevents_calc_mult_shift(ce, CLOCK_TICK_RATE, 60);
+       ce->max_delta_ns = clockevent_delta2ns(-2, ce);
+       ce->min_delta_ns = clockevent_delta2ns(2, ce);
+       ce->cpumask = cpumask_of(cpu);
  
-       sirfsoc_timer1_irq.dev_id = ce;
-       BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
-       irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
+       action->dev_id = ce;
+       BUG_ON(setup_irq(ce->irq, action));
+       irq_set_affinity(action->irq, cpumask_of(cpu));
  
        clockevents_register_device(ce);
        return 0;
  }
  
 -static void __cpuinit sirfsoc_local_timer_stop(struct clock_event_device *ce)
 +static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
  {
+       int cpu = smp_processor_id();
        sirfsoc_timer_count_disable(1);
  
-       remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
+       if (cpu == 0)
+               remove_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq);
+       else
+               remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
  }
  
- static struct local_timer_ops sirfsoc_local_timer_ops = {
-       .setup  = sirfsoc_local_timer_setup,
-       .stop   = sirfsoc_local_timer_stop,
 -static int __cpuinit sirfsoc_cpu_notify(struct notifier_block *self,
 -                                         unsigned long action, void *hcpu)
++static int sirfsoc_cpu_notify(struct notifier_block *self,
++                            unsigned long action, void *hcpu)
+ {
+       /*
+        * Grab cpu pointer in each case to avoid spurious
+        * preemptible warnings
+        */
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_STARTING:
+               sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent));
+               break;
+       case CPU_DYING:
+               sirfsoc_local_timer_stop(this_cpu_ptr(sirfsoc_clockevent));
+               break;
+       }
+       return NOTIFY_OK;
+ }
 -static struct notifier_block sirfsoc_cpu_nb __cpuinitdata = {
++static struct notifier_block sirfsoc_cpu_nb = {
+       .notifier_call = sirfsoc_cpu_notify,
  };
- #endif /* CONFIG_LOCAL_TIMERS */
  
  static void __init sirfsoc_clockevent_init(void)
  {
-       clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
-       sirfsoc_clockevent.max_delta_ns =
-               clockevent_delta2ns(-2, &sirfsoc_clockevent);
-       sirfsoc_clockevent.min_delta_ns =
-               clockevent_delta2ns(2, &sirfsoc_clockevent);
-       sirfsoc_clockevent.cpumask = cpumask_of(0);
-       clockevents_register_device(&sirfsoc_clockevent);
- #ifdef CONFIG_LOCAL_TIMERS
-       local_timer_register(&sirfsoc_local_timer_ops);
- #endif
+       sirfsoc_clockevent = alloc_percpu(struct clock_event_device);
+       BUG_ON(!sirfsoc_clockevent);
+       BUG_ON(register_cpu_notifier(&sirfsoc_cpu_nb));
+       /* Immediately configure the timer on the boot CPU */
+       sirfsoc_local_timer_setup(this_cpu_ptr(sirfsoc_clockevent));
  }
  
  /* initialize the kernel jiffy timer source */
@@@ -273,8 -285,6 +285,6 @@@ static void __init sirfsoc_marco_timer_
  
        BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
  
-       BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
        sirfsoc_clockevent_init();
  }
  
@@@ -288,11 -298,9 +298,9 @@@ static void __init sirfsoc_of_timer_ini
        if (!sirfsoc_timer_irq.irq)
                panic("No irq passed for timer0 via DT\n");
  
- #ifdef CONFIG_LOCAL_TIMERS
        sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
        if (!sirfsoc_timer1_irq.irq)
                panic("No irq passed for timer1 via DT\n");
- #endif
  
        sirfsoc_marco_timer_init();
  }