Commit 1ee73784 authored by Russell King's avatar Russell King Committed by Russell King

Merge branch 'for_rmk' of git://dev.omapzoom.org/pub/scm/santosh/kernel-omap4-base into devel

parents 7698fded b5495610
...@@ -846,10 +846,10 @@ source "kernel/time/Kconfig" ...@@ -846,10 +846,10 @@ source "kernel/time/Kconfig"
config SMP config SMP
bool "Symmetric Multi-Processing (EXPERIMENTAL)" bool "Symmetric Multi-Processing (EXPERIMENTAL)"
depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP) depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP ||ARCH_OMAP4)
depends on GENERIC_CLOCKEVENTS depends on GENERIC_CLOCKEVENTS
select USE_GENERIC_SMP_HELPERS select USE_GENERIC_SMP_HELPERS
select HAVE_ARM_SCU if ARCH_REALVIEW select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4)
help help
This enables support for systems with more than one CPU. If you have This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If a system with only one CPU, like most personal computers, say N. If
...@@ -917,9 +917,9 @@ config HOTPLUG_CPU ...@@ -917,9 +917,9 @@ config HOTPLUG_CPU
config LOCAL_TIMERS config LOCAL_TIMERS
bool "Use local timer interrupts" bool "Use local timer interrupts"
depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || REALVIEW_EB_A9MP) depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || REALVIEW_EB_A9MP || ARCH_OMAP4)
default y default y
select HAVE_ARM_TWD if ARCH_REALVIEW select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4)
help help
Enable support for local timers on SMP platforms, rather then the Enable support for local timers on SMP platforms, rather then the
legacy IPI broadcast method. Local timers allows the system legacy IPI broadcast method. Local timers allows the system
......
This diff is collapsed.
...@@ -14,6 +14,10 @@ obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(clock-common) ...@@ -14,6 +14,10 @@ obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(clock-common)
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
# SMP support ONLY available for OMAP4
obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o
obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o
# Functions loaded to SRAM # Functions loaded to SRAM
obj-$(CONFIG_ARCH_OMAP2420) += sram242x.o obj-$(CONFIG_ARCH_OMAP2420) += sram242x.o
obj-$(CONFIG_ARCH_OMAP2430) += sram243x.o obj-$(CONFIG_ARCH_OMAP2430) += sram243x.o
......
/*
* Secondary CPU startup routine source file.
*
* Copyright (C) 2009 Texas Instruments, Inc.
*
* Author:
* Santosh Shilimkar <santosh.shilimkar@ti.com>
*
* Interface functions needed for the SMP. This file is based on arm
* realview smp platform.
* Copyright (c) 2003 ARM Limited.
*
* 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/linkage.h>
#include <linux/init.h>
/* Physical address needed since MMU not enabled yet on secondary core */
#define OMAP4_AUX_CORE_BOOT1_PA 0x48281804
__INIT
/*
* OMAP4 specific entry point for secondary CPU to jump from ROM
* code. This routine also provides a holding flag into which
* secondary core is held until we're ready for it to initialise.
* The primary core will update the this flag using a hardware
* register AuxCoreBoot1.
*/
ENTRY(omap_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #0x0f
hold: ldr r1, =OMAP4_AUX_CORE_BOOT1_PA @ read from AuxCoreBoot1
ldr r2, [r1]
cmp r2, r0
bne hold
/*
* we've been released from the cpu_release,secondary_stack
* should now contain the SVC stack for this core
*/
b secondary_startup
/*
* OMAP4 SMP source file. It contains platform specific fucntions
* needed for the linux smp kernel.
*
* Copyright (C) 2009 Texas Instruments, Inc.
*
* Author:
* Santosh Shilimkar <santosh.shilimkar@ti.com>
*
* Platform file needed for the OMAP4 SMP. This file is based on arm
* realview smp platform.
* * Copyright (c) 2002 ARM Limited.
*
* 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/device.h>
#include <linux/jiffies.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/localtimer.h>
#include <asm/smp_scu.h>
#include <mach/hardware.h>
/* Registers used for communicating startup information */
#define OMAP4_AUXCOREBOOT_REG0 (OMAP44XX_VA_WKUPGEN_BASE + 0x800)
#define OMAP4_AUXCOREBOOT_REG1 (OMAP44XX_VA_WKUPGEN_BASE + 0x804)
/* SCU base address */
static void __iomem *scu_base = OMAP44XX_VA_SCU_BASE;
/*
* Use SCU config register to count number of cores
*/
static inline unsigned int get_core_count(void)
{
if (scu_base)
return scu_get_core_count(scu_base);
return 1;
}
static DEFINE_SPINLOCK(boot_lock);
void __cpuinit platform_secondary_init(unsigned int cpu)
{
trace_hardirqs_off();
/*
* If any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
gic_cpu_init(0, IO_ADDRESS(OMAP44XX_GIC_CPU_BASE));
/*
* Synchronise with the boot thread.
*/
spin_lock(&boot_lock);
spin_unlock(&boot_lock);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned long timeout;
/*
* Set synchronisation state between this boot processor
* and the secondary one
*/
spin_lock(&boot_lock);
/*
* Update the AuxCoreBoot1 with boot state for secondary core.
* omap_secondary_startup() routine will hold the secondary core till
* the AuxCoreBoot1 register is updated with cpu state
* A barrier is added to ensure that write buffer is drained
*/
__raw_writel(cpu, OMAP4_AUXCOREBOOT_REG1);
smp_wmb();
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout))
;
/*
* Now the secondary core is starting up let it run its
* calibrations, then wait for it to finish
*/
spin_unlock(&boot_lock);
return 0;
}
static void __init wakeup_secondary(void)
{
/*
* Write the address of secondary startup routine into the
* AuxCoreBoot0 where ROM code will jump and start executing
* on secondary core once out of WFE
* A barrier is added to ensure that write buffer is drained
*/
__raw_writel(virt_to_phys(omap_secondary_startup), \
OMAP4_AUXCOREBOOT_REG0);
smp_wmb();
/*
* Send a 'sev' to wake the secondary core from WFE.
*/
set_event();
mb();
}
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system.
*/
void __init smp_init_cpus(void)
{
unsigned int i, ncores = get_core_count();
for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);
}
void __init smp_prepare_cpus(unsigned int max_cpus)
{
unsigned int ncores = get_core_count();
unsigned int cpu = smp_processor_id();
int i;
/* sanity check */
if (ncores == 0) {
printk(KERN_ERR
"OMAP4: strange core count of 0? Default to 1\n");
ncores = 1;
}
if (ncores > NR_CPUS) {
printk(KERN_WARNING
"OMAP4: no. of cores (%d) greater than configured "
"maximum of %d - clipping\n",
ncores, NR_CPUS);
ncores = NR_CPUS;
}
smp_store_cpu_info(cpu);
/*
* are we trying to boot more cores than exist?
*/
if (max_cpus > ncores)
max_cpus = ncores;
/*
* Initialise the present map, which describes the set of CPUs
* actually populated at the present time.
*/
for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true);
if (max_cpus > 1) {
/*
* 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 SCU and wake up the secondary core using
* wakeup_secondary().
*/
scu_enable(scu_base);
wakeup_secondary();
}
}
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <asm/mach/time.h> #include <asm/mach/time.h>
#include <mach/dmtimer.h> #include <mach/dmtimer.h>
#include <asm/localtimer.h>
/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */ /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
#define MAX_GPTIMER_ID 12 #define MAX_GPTIMER_ID 12
...@@ -229,6 +230,9 @@ static void __init omap2_gp_clocksource_init(void) ...@@ -229,6 +230,9 @@ static void __init omap2_gp_clocksource_init(void)
static void __init omap2_gp_timer_init(void) static void __init omap2_gp_timer_init(void)
{ {
#ifdef CONFIG_LOCAL_TIMERS
twd_base = IO_ADDRESS(OMAP44XX_LOCAL_TWD_BASE);
#endif
omap_dm_timer_init(); omap_dm_timer_init();
omap2_gp_clockevent_init(); omap2_gp_clockevent_init();
......
/*
* 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 <santosh.shilimkar@ti.com>
*
* 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.
*/
void __cpuinit local_timer_setup(struct clock_event_device *evt)
{
evt->irq = INT_44XX_LOCALTIMER_IRQ;
twd_timer_setup(evt);
}
...@@ -136,6 +136,34 @@ ...@@ -136,6 +136,34 @@
cmpne \irqnr, \tmp cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr cmpcs \irqnr, \irqnr
.endm .endm
/* We assume that irqstat (the raw value of the IRQ acknowledge
* register) is preserved from the macro above.
* If there is an IPI, we immediately signal end of interrupt
* on the controller, since this requires the original irqstat
* value which we won't easily be able to recreate later.
*/
.macro test_for_ipi, irqnr, irqstat, base, tmp
bic \irqnr, \irqstat, #0x1c00
cmp \irqnr, #16
it cc
strcc \irqstat, [\base, #GIC_CPU_EOI]
it cs
cmpcs \irqnr, \irqnr
.endm
/* As above, this assumes that irqstat and base are preserved */
.macro test_for_ltirq, irqnr, irqstat, base, tmp
bic \irqnr, \irqstat, #0x1c00
mov \tmp, #0
cmp \irqnr, #29
itt eq
moveq \tmp, #1
streq \irqstat, [\base, #GIC_CPU_EOI]
cmp \tmp, #0
.endm
#endif #endif
.macro irq_prio_table .macro irq_prio_table
......
...@@ -427,6 +427,8 @@ ...@@ -427,6 +427,8 @@
#define IRQ_GIC_START 32 #define IRQ_GIC_START 32
#define INT_44XX_LOCALTIMER_IRQ 29
#define INT_44XX_LOCALWDT_IRQ 30
#define INT_44XX_BENCH_MPU_EMUL (3 + IRQ_GIC_START) #define INT_44XX_BENCH_MPU_EMUL (3 + IRQ_GIC_START)
#define INT_44XX_SSM_ABORT_IRQ (6 + IRQ_GIC_START) #define INT_44XX_SSM_ABORT_IRQ (6 + IRQ_GIC_START)
......
/*
* OMAP4 machine specific smp.h
*
* Copyright (C) 2009 Texas Instruments, Inc.
*
* Author:
* Santosh Shilimkar <santosh.shilimkar@ti.com>
*
* Interface functions needed for the SMP. This file is based on arm
* realview smp platform.
* Copyright (c) 2003 ARM Limited.
*
* 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.
*/
#ifndef OMAP_ARCH_SMP_H
#define OMAP_ARCH_SMP_H
#include <asm/hardware/gic.h>
/*
* set_event() is used to wake up secondary core from wfe using sev. ROM
* code puts the second core into wfe(standby).
*
*/
#define set_event() __asm__ __volatile__ ("sev" : : : "memory")
/* Needed for secondary core boot */
extern void omap_secondary_startup(void);
/*
* We use Soft IRQ1 as the IPI
*/
static inline void smp_cross_call(const struct cpumask *mask)
{
gic_raise_softirq(mask, 1);
}
/*
* Read MPIDR: Multiprocessor affinity register
*/
#define hard_smp_processor_id() \
({ \
unsigned int cpunum; \
__asm__("mrc p15, 0, %0, c0, c0, 5" \
: "=r" (cpunum)); \
cpunum &= 0x0F; \
})
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment