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"
config SMP
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
select USE_GENERIC_SMP_HELPERS
select HAVE_ARM_SCU if ARCH_REALVIEW
select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4)
help
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
......@@ -917,9 +917,9 @@ config HOTPLUG_CPU
config LOCAL_TIMERS
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
select HAVE_ARM_TWD if ARCH_REALVIEW
select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4)
help
Enable support for local timers on SMP platforms, rather then the
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)
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
obj-$(CONFIG_ARCH_OMAP2420) += sram242x.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 @@
#include <asm/mach/time.h>
#include <mach/dmtimer.h>
#include <asm/localtimer.h>
/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
#define MAX_GPTIMER_ID 12
......@@ -229,6 +230,9 @@ static void __init omap2_gp_clocksource_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();
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 @@
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
.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
.macro irq_prio_table
......
......@@ -427,6 +427,8 @@
#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_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