Skip to content

Commit

Permalink
SPEAr13xx: Add source files
Browse files Browse the repository at this point in the history
This patch adds source files for SPEAr13xx Machines.

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Deepak Sikri <deepak.sikri@st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
  • Loading branch information
Viresh Kumar authored and Arnd Bergmann committed May 14, 2012
1 parent b31e237 commit e3978dc
Show file tree
Hide file tree
Showing 10 changed files with 809 additions and 0 deletions.
18 changes: 18 additions & 0 deletions arch/arm/mach-spear13xx/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#
# SPEAr13XX Machine configuration file
#

if ARCH_SPEAR13XX

menu "SPEAr13xx Implementations"
config MACH_SPEAR1310
bool "SPEAr1310 Machine support with Device Tree"
help
Supports ST SPEAr1310 machine configured via the device-tree

config MACH_SPEAR1340
bool "SPEAr1340 Machine support with Device Tree"
help
Supports ST SPEAr1340 machine configured via the device-tree
endmenu
endif #ARCH_SPEAR13XX
10 changes: 10 additions & 0 deletions arch/arm/mach-spear13xx/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#
# Makefile for SPEAr13XX machine series
#

obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o

obj-$(CONFIG_ARCH_SPEAR13XX) += spear13xx.o
obj-$(CONFIG_MACH_SPEAR1310) += spear1310.o
obj-$(CONFIG_MACH_SPEAR1340) += spear1340.o
6 changes: 6 additions & 0 deletions arch/arm/mach-spear13xx/Makefile.boot
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
zreladdr-y += 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x00800000

dtb-$(CONFIG_MACH_SPEAR1310) += spear1310-evb.dtb
dtb-$(CONFIG_MACH_SPEAR1340) += spear1340-evb.dtb
47 changes: 47 additions & 0 deletions arch/arm/mach-spear13xx/headsmp.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* arch/arm/mach-spear13XX/headsmp.S
*
* Picked from realview
* Copyright (c) 2012 ST Microelectronics Limited
* Shiraz Hashim <shiraz.hashim@st.com>
*
* 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>

__INIT

/*
* spear13xx specific entry point for secondary CPUs. This provides
* a "holding pen" into which all secondary cores are held until we're
* ready for them to initialise.
*/
ENTRY(spear13xx_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
adr r4, 1f
ldmia r4, {r5, r6}
sub r4, r4, r5
add r6, r6, r4
pen: ldr r7, [r6]
cmp r7, r0
bne pen

/* re-enable coherency */
mrc p15, 0, r0, c1, c0, 1
orr r0, r0, #(1 << 6) | (1 << 0)
mcr p15, 0, r0, c1, c0, 1
/*
* we've been released from the holding pen: secondary_stack
* should now contain the SVC stack for this core
*/
b secondary_startup

.align
1: .long .
.long pen_release
ENDPROC(spear13xx_secondary_startup)
119 changes: 119 additions & 0 deletions arch/arm/mach-spear13xx/hotplug.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* linux/arch/arm/mach-spear13xx/hotplug.c
*
* Copyright (C) 2012 ST Microelectronics Ltd.
* Deepak Sikri <deepak.sikri@st.com>
*
* based upon linux/arch/arm/mach-realview/hotplug.c
*
* 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/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <asm/cacheflush.h>
#include <asm/cp15.h>
#include <asm/smp_plat.h>

extern volatile int pen_release;

static inline void cpu_enter_lowpower(void)
{
unsigned int v;

flush_cache_all();
asm volatile(
" mcr p15, 0, %1, c7, c5, 0\n"
" dsb\n"
/*
* Turn off coherency
*/
" mrc p15, 0, %0, c1, c0, 1\n"
" bic %0, %0, #0x20\n"
" mcr p15, 0, %0, c1, c0, 1\n"
" mrc p15, 0, %0, c1, c0, 0\n"
" bic %0, %0, %2\n"
" mcr p15, 0, %0, c1, c0, 0\n"
: "=&r" (v)
: "r" (0), "Ir" (CR_C)
: "cc", "memory");
}

static inline void cpu_leave_lowpower(void)
{
unsigned int v;

asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
" orr %0, %0, %1\n"
" mcr p15, 0, %0, c1, c0, 0\n"
" mrc p15, 0, %0, c1, c0, 1\n"
" orr %0, %0, #0x20\n"
" mcr p15, 0, %0, c1, c0, 1\n"
: "=&r" (v)
: "Ir" (CR_C)
: "cc");
}

static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
{
for (;;) {
wfi();

if (pen_release == cpu) {
/*
* OK, proper wakeup, we're done
*/
break;
}

/*
* Getting here, means that we have come out of WFI without
* having been woken up - this shouldn't happen
*
* Just note it happening - when we're woken, we can report
* its occurrence.
*/
(*spurious)++;
}
}

int platform_cpu_kill(unsigned int cpu)
{
return 1;
}

/*
* platform-specific code to shutdown a CPU
*
* Called with IRQs disabled
*/
void __cpuinit platform_cpu_die(unsigned int cpu)
{
int spurious = 0;

/*
* we're ready for shutdown now, so do it
*/
cpu_enter_lowpower();
platform_do_lowpower(cpu, &spurious);

/*
* bring this CPU back into the world of cache
* coherency, and then restore interrupts
*/
cpu_leave_lowpower();

if (spurious)
pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
}

int platform_cpu_disable(unsigned int cpu)
{
/*
* we don't allow CPU 0 to be shutdown (it is still too special
* e.g. clock tick interrupts)
*/
return cpu == 0 ? -EPERM : 0;
}
127 changes: 127 additions & 0 deletions arch/arm/mach-spear13xx/platsmp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* arch/arm/mach-spear13xx/platsmp.c
*
* based upon linux/arch/arm/mach-realview/platsmp.c
*
* Copyright (C) 2012 ST Microelectronics Ltd.
* Shiraz Hashim <shiraz.hashim@st.com>
*
* 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/delay.h>
#include <linux/jiffies.h>
#include <linux/io.h>
#include <linux/smp.h>
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
#include <asm/smp_scu.h>
#include <mach/spear.h>

/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
volatile int __cpuinitdata pen_release = -1;
static DEFINE_SPINLOCK(boot_lock);

static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
extern void spear13xx_secondary_startup(void);

void __cpuinit platform_secondary_init(unsigned int cpu)
{
/*
* 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_secondary_init(0);

/*
* let the primary processor know we're out of the
* pen, then head off into the C entry point
*/
pen_release = -1;
smp_wmb();

/*
* 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);

/*
* The secondary processor is waiting to be released from
* the holding pen - release it, then wait for it to flag
* that it has been released by resetting pen_release.
*
* Note that "pen_release" is the hardware CPU ID, whereas
* "cpu" is Linux's internal ID.
*/
pen_release = cpu;
flush_cache_all();
outer_flush_all();

timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
smp_rmb();
if (pen_release == -1)
break;

udelay(10);
}

/*
* now the secondary core is starting up let it run its
* calibrations, then wait for it to finish
*/
spin_unlock(&boot_lock);

return pen_release != -1 ? -ENOSYS : 0;
}

/*
* 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 = scu_get_core_count(scu_base);

if (ncores > nr_cpu_ids) {
pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
ncores, nr_cpu_ids);
ncores = nr_cpu_ids;
}

for (i = 0; i < ncores; i++)
set_cpu_possible(i, true);

set_smp_cross_call(gic_raise_softirq);
}

void __init platform_smp_prepare_cpus(unsigned int max_cpus)
{

scu_enable(scu_base);

/*
* Write the address of secondary startup into the system-wide location
* (presently it is in SRAM). The BootMonitor waits until it receives a
* soft interrupt, and then the secondary CPU branches to this address.
*/
__raw_writel(virt_to_phys(spear13xx_secondary_startup), SYS_LOCATION);
}
Loading

0 comments on commit e3978dc

Please sign in to comment.