Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
59ac59f6
Commit
59ac59f6
authored
Feb 11, 2010
by
Russell King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ARM: Add Versatile Express SMP support
Signed-off-by:
Russell King
<
rmk+kernel@arm.linux.org.uk
>
parent
fef88f10
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
281 additions
and
2 deletions
+281
-2
arch/arm/Kconfig
arch/arm/Kconfig
+3
-2
arch/arm/mach-vexpress/Makefile
arch/arm/mach-vexpress/Makefile
+2
-0
arch/arm/mach-vexpress/headsmp.S
arch/arm/mach-vexpress/headsmp.S
+39
-0
arch/arm/mach-vexpress/include/mach/smp.h
arch/arm/mach-vexpress/include/mach/smp.h
+21
-0
arch/arm/mach-vexpress/localtimer.c
arch/arm/mach-vexpress/localtimer.c
+26
-0
arch/arm/mach-vexpress/platsmp.c
arch/arm/mach-vexpress/platsmp.c
+190
-0
No files found.
arch/arm/Kconfig
View file @
59ac59f6
...
...
@@ -1121,10 +1121,11 @@ source "kernel/time/Kconfig"
config SMP
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || ARCH_U8500)
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
depends on GENERIC_CLOCKEVENTS
select USE_GENERIC_SMP_HELPERS
select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500)
select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500
|| ARCH_VEXPRESS_CA9X4
)
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
...
...
arch/arm/mach-vexpress/Makefile
View file @
59ac59f6
...
...
@@ -4,3 +4,5 @@
obj-y
:=
v2m.o
obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)
+=
ct-ca9x4.o
obj-$(CONFIG_SMP)
+=
platsmp.o headsmp.o
obj-$(CONFIG_LOCAL_TIMERS)
+=
localtimer.o
arch/arm/mach-vexpress/headsmp.S
0 → 100644
View file @
59ac59f6
/*
*
linux
/
arch
/
arm
/
mach
-
vexpress
/
headsmp
.
S
*
*
Copyright
(
c
)
2003
ARM
Limited
*
All
Rights
Reserved
*
*
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
/*
*
Versatile
Express
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
(
vexpress_secondary_startup
)
mrc
p15
,
0
,
r0
,
c0
,
c0
,
5
and
r0
,
r0
,
#
15
adr
r4
,
1
f
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
1
:
.
long
.
.
long
pen_release
arch/arm/mach-vexpress/include/mach/smp.h
0 → 100644
View file @
59ac59f6
#ifndef __MACH_SMP_H
#define __MACH_SMP_H
#include <asm/hardware/gic.h>
#define hard_smp_processor_id() \
({ \
unsigned int cpunum; \
__asm__("mrc p15, 0, %0, c0, c0, 5" \
: "=r" (cpunum)); \
cpunum &= 0x0F; \
})
/*
* We use IRQ1 as the IPI
*/
static
inline
void
smp_cross_call
(
const
struct
cpumask
*
mask
)
{
gic_raise_softirq
(
mask
,
1
);
}
#endif
arch/arm/mach-vexpress/localtimer.c
0 → 100644
View file @
59ac59f6
/*
* linux/arch/arm/mach-vexpress/localtimer.c
*
* Copyright (C) 2002 ARM Ltd.
* All Rights Reserved
*
* 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/smp_twd.h>
#include <asm/localtimer.h>
#include <mach/irqs.h>
/*
* Setup the local clock events for a CPU.
*/
void
__cpuinit
local_timer_setup
(
struct
clock_event_device
*
evt
)
{
evt
->
irq
=
IRQ_LOCALTIMER
;
twd_timer_setup
(
evt
);
}
arch/arm/mach-vexpress/platsmp.c
0 → 100644
View file @
59ac59f6
/*
* linux/arch/arm/mach-vexpress/platsmp.c
*
* Copyright (C) 2002 ARM Ltd.
* All Rights Reserved
*
* 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/errno.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/jiffies.h>
#include <linux/smp.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
#include <asm/localtimer.h>
#include <asm/smp_scu.h>
#include <asm/unified.h>
#include <mach/ct-ca9x4.h>
#include <mach/motherboard.h>
#define V2M_PA_CS7 0x10000000
#include "core.h"
extern
void
vexpress_secondary_startup
(
void
);
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
volatile
int
__cpuinitdata
pen_release
=
-
1
;
static
void
__iomem
*
scu_base_addr
(
void
)
{
return
MMIO_P2V
(
A9_MPCORE_SCU
);
}
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
,
gic_cpu_base_addr
);
/*
* 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
);
/*
* This is really belt and braces; we hold unintended secondary
* CPUs in the holding pen until we're ready for them. However,
* since we haven't sent them a soft interrupt, they shouldn't
* be there.
*/
pen_release
=
cpu
;
__cpuc_flush_dcache_area
((
void
*
)
&
pen_release
,
sizeof
(
pen_release
));
outer_clean_range
(
__pa
(
&
pen_release
),
__pa
(
&
pen_release
+
1
));
/*
* Send the secondary CPU a soft interrupt, thereby causing
* the boot monitor to read the system wide flags register,
* and branch to the address found there.
*/
smp_cross_call
(
cpumask_of
(
cpu
));
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
)
{
void
__iomem
*
scu_base
=
scu_base_addr
();
unsigned
int
i
,
ncores
;
ncores
=
scu_base
?
scu_get_core_count
(
scu_base
)
:
1
;
/* sanity check */
if
(
ncores
==
0
)
{
printk
(
KERN_ERR
"vexpress: strange CM count of 0? Default to 1
\n
"
);
ncores
=
1
;
}
if
(
ncores
>
NR_CPUS
)
{
printk
(
KERN_WARNING
"vexpress: no. of cores (%d) greater than configured "
"maximum of %d - clipping
\n
"
,
ncores
,
NR_CPUS
);
ncores
=
NR_CPUS
;
}
for
(
i
=
0
;
i
<
ncores
;
i
++
)
set_cpu_possible
(
i
,
true
);
}
void
__init
smp_prepare_cpus
(
unsigned
int
max_cpus
)
{
unsigned
int
ncores
=
num_possible_cpus
();
unsigned
int
cpu
=
smp_processor_id
();
int
i
;
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
);
/*
* Initialise the SCU if there are more than one CPU and let
* them know where to start.
*/
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
();
scu_enable
(
scu_base_addr
());
/*
* Write the address of secondary startup into the
* system-wide flags register. The boot monitor waits
* until it receives a soft interrupt, and then the
* secondary CPU branches to this address.
*/
writel
(
~
0
,
MMIO_P2V
(
V2M_SYS_FLAGSCLR
));
writel
(
BSYM
(
virt_to_phys
(
vexpress_secondary_startup
)),
MMIO_P2V
(
V2M_SYS_FLAGSSET
));
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment