Skip to content

Commit

Permalink
ARM: PRIMA2: add new SiRFmarco SMP SoC infrastructures
Browse files Browse the repository at this point in the history
this patch adds tick timer, smp entries and generic DT machine
for SiRFmarco dual-core SMP chips.

with the added marco, we change the defconfig, using the same
defconfig, we get a zImage which can work on both prima2 and
marco.

Signed-off-by: Barry Song <Baohua.Song@csr.com>
Cc: Mark Rutland <mark.rutland@arm.com>
  • Loading branch information
Barry Song authored and Barry Song committed Jan 22, 2013
1 parent f2a9419 commit 4898de3
Show file tree
Hide file tree
Showing 10 changed files with 666 additions and 1 deletion.
1 change: 1 addition & 0 deletions arch/arm/boot/dts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
kirkwood-ts219-6281.dtb \
kirkwood-ts219-6282.dtb \
kirkwood-openblocks_a6.dtb
dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
msm8960-cdp.dtb
dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/configs/prima2_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_BSD_DISKLABEL=y
CONFIG_SOLARIS_X86_PARTITION=y
CONFIG_ARCH_SIRF=y
# CONFIG_SWP_EMULATE is not set
CONFIG_SMP=y
CONFIG_SCHED_MC=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_KEXEC=y
Expand Down
10 changes: 10 additions & 0 deletions arch/arm/mach-prima2/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ config ARCH_PRIMA2
help
Support for CSR SiRFSoC ARM Cortex A9 Platform

config ARCH_MARCO
bool "CSR SiRFSoC MARCO ARM Cortex A9 Platform"
default y
select ARM_GIC
select CPU_V7
select HAVE_SMP
select SMP_ON_UP
help
Support for CSR SiRFSoC ARM Cortex A9 Platform

endmenu

config SIRF_IRQ
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/mach-prima2/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ obj-$(CONFIG_DEBUG_LL) += lluart.o
obj-$(CONFIG_CACHE_L2X0) += l2x0.o
obj-$(CONFIG_SUSPEND) += pm.o sleep.o
obj-$(CONFIG_SIRF_IRQ) += irq.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
obj-$(CONFIG_ARCH_MARCO) += timer-marco.o
40 changes: 39 additions & 1 deletion arch/arm/mach-prima2/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/of_irq.h>
#include <asm/sizes.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include "common.h"
Expand All @@ -30,6 +32,12 @@ void __init sirfsoc_init_late(void)
sirfsoc_pm_init();
}

static __init void sirfsoc_map_io(void)
{
sirfsoc_map_lluart();
sirfsoc_map_scu();
}

#ifdef CONFIG_ARCH_PRIMA2
static const char *prima2_dt_match[] __initdata = {
"sirf,prima2",
Expand All @@ -38,7 +46,7 @@ static const char *prima2_dt_match[] __initdata = {

DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
/* Maintainer: Barry Song <baohua.song@csr.com> */
.map_io = sirfsoc_map_lluart,
.map_io = sirfsoc_map_io,
.init_irq = sirfsoc_of_irq_init,
.init_time = sirfsoc_prima2_timer_init,
#ifdef CONFIG_MULTI_IRQ_HANDLER
Expand All @@ -51,3 +59,33 @@ DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
.restart = sirfsoc_restart,
MACHINE_END
#endif

#ifdef CONFIG_ARCH_MARCO
static const struct of_device_id marco_irq_match[] __initconst = {
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
{ /* sentinel */ }
};

static void __init marco_init_irq(void)
{
of_irq_init(marco_irq_match);
}

static const char *marco_dt_match[] __initdata = {
"sirf,marco",
NULL
};

DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)")
/* Maintainer: Barry Song <baohua.song@csr.com> */
.smp = smp_ops(sirfsoc_smp_ops),
.map_io = sirfsoc_map_io,
.init_irq = marco_init_irq,
.init_time = sirfsoc_marco_timer_init,
.handle_irq = gic_handle_irq,
.init_machine = sirfsoc_mach_init,
.init_late = sirfsoc_init_late,
.dt_compat = marco_dt_match,
.restart = sirfsoc_restart,
MACHINE_END
#endif
11 changes: 11 additions & 0 deletions arch/arm/mach-prima2/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
#include <asm/exception.h>

extern void sirfsoc_prima2_timer_init(void);
extern void sirfsoc_marco_timer_init(void);

extern struct smp_operations sirfsoc_smp_ops;
extern void sirfsoc_secondary_startup(void);
extern void sirfsoc_cpu_die(unsigned int cpu);

extern void __init sirfsoc_of_irq_init(void);
extern void __init sirfsoc_of_clk_init(void);
Expand All @@ -26,6 +31,12 @@ static inline void sirfsoc_map_lluart(void) {}
extern void __init sirfsoc_map_lluart(void);
#endif

#ifndef CONFIG_SMP
static inline void sirfsoc_map_scu(void) {}
#else
extern void sirfsoc_map_scu(void);
#endif

#ifdef CONFIG_SUSPEND
extern int sirfsoc_pm_init(void);
#else
Expand Down
79 changes: 79 additions & 0 deletions arch/arm/mach-prima2/headsmp.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Entry of the second core for CSR Marco dual-core SMP SoCs
*
* Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
*
* Licensed under GPLv2 or later.
*/

#include <linux/linkage.h>
#include <linux/init.h>

__INIT
/*
* Cold boot and hardware reset show different behaviour,
* system will be always panic if we warm-reset the board
* Here we invalidate L1 of CPU1 to make sure there isn't
* uninitialized data written into memory later
*/
ENTRY(v7_invalidate_l1)
mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
mcr p15, 2, r0, c0, c0, 0
mrc p15, 1, r0, c0, c0, 0

ldr r1, =0x7fff
and r2, r1, r0, lsr #13

ldr r1, =0x3ff

and r3, r1, r0, lsr #3 @ NumWays - 1
add r2, r2, #1 @ NumSets

and r0, r0, #0x7
add r0, r0, #4 @ SetShift

clz r1, r3 @ WayShift
add r4, r3, #1 @ NumWays
1: sub r2, r2, #1 @ NumSets--
mov r3, r4 @ Temp = NumWays
2: subs r3, r3, #1 @ Temp--
mov r5, r3, lsl r1
mov r6, r2, lsl r0
orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
mcr p15, 0, r5, c7, c6, 2
bgt 2b
cmp r2, #0
bgt 1b
dsb
isb
mov pc, lr
ENDPROC(v7_invalidate_l1)

/*
* SIRFSOC 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(sirfsoc_secondary_startup)
bl v7_invalidate_l1
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

/*
* we've been released from the holding pen: secondary_stack
* should now contain the SVC stack for this core
*/
b secondary_startup
ENDPROC(sirfsoc_secondary_startup)

.align
1: .long .
.long pen_release
41 changes: 41 additions & 0 deletions arch/arm/mach-prima2/hotplug.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* CPU hotplug support for CSR Marco dual-core SMP SoCs
*
* Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
*
* Licensed under GPLv2 or later.
*/

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/smp.h>

#include <asm/cacheflush.h>
#include <asm/smp_plat.h>

static inline void platform_do_lowpower(unsigned int cpu)
{
flush_cache_all();

/* we put the platform to just WFI */
for (;;) {
__asm__ __volatile__("dsb\n\t" "wfi\n\t"
: : : "memory");
if (pen_release == cpu_logical_map(cpu)) {
/*
* OK, proper wakeup, we're done
*/
break;
}
}
}

/*
* platform-specific code to shutdown a CPU
*
* Called with IRQs disabled
*/
void sirfsoc_cpu_die(unsigned int cpu)
{
platform_do_lowpower(cpu);
}
Loading

0 comments on commit 4898de3

Please sign in to comment.