mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 12:57:06 +09:00
Merge branch 'tracking-armlt-mcpm' into lsk-3.10-vexpress
This commit is contained in:
@@ -1521,6 +1521,13 @@ config MCPM
|
||||
for (multi-)cluster based systems, such as big.LITTLE based
|
||||
systems.
|
||||
|
||||
config BIG_LITTLE
|
||||
bool "big.LITTLE support (Experimental)"
|
||||
depends on CPU_V7 && SMP
|
||||
select MCPM
|
||||
help
|
||||
This option enables support for the big.LITTLE architecture.
|
||||
|
||||
choice
|
||||
prompt "Memory split"
|
||||
default VMSPLIT_3G
|
||||
|
||||
@@ -16,3 +16,4 @@ obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
|
||||
obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o
|
||||
AFLAGS_mcpm_head.o := -march=armv7-a
|
||||
AFLAGS_vlock.o := -march=armv7-a
|
||||
CFLAGS_REMOVE_mcpm_entry.o = -pg
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct tag;
|
||||
@@ -16,8 +18,10 @@ struct pt_regs;
|
||||
struct smp_operations;
|
||||
#ifdef CONFIG_SMP
|
||||
#define smp_ops(ops) (&(ops))
|
||||
#define smp_init_ops(ops) (&(ops))
|
||||
#else
|
||||
#define smp_ops(ops) (struct smp_operations *)NULL
|
||||
#define smp_init_ops(ops) (bool (*)(void))NULL
|
||||
#endif
|
||||
|
||||
struct machine_desc {
|
||||
@@ -41,6 +45,7 @@ struct machine_desc {
|
||||
unsigned char reserve_lp2 :1; /* never has lp2 */
|
||||
char restart_mode; /* default restart mode */
|
||||
struct smp_operations *smp; /* SMP operations */
|
||||
bool (*smp_init)(void);
|
||||
void (*fixup)(struct tag *, char **,
|
||||
struct meminfo *);
|
||||
void (*reserve)(void);/* reserve mem blocks */
|
||||
|
||||
@@ -32,5 +32,14 @@ struct psci_operations {
|
||||
};
|
||||
|
||||
extern struct psci_operations psci_ops;
|
||||
extern struct smp_operations psci_smp_ops;
|
||||
|
||||
#ifdef CONFIG_ARM_PSCI
|
||||
void psci_init(void);
|
||||
bool psci_smp_available(void);
|
||||
#else
|
||||
static inline void psci_init(void) { }
|
||||
static inline bool psci_smp_available(void) { return false; }
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_ARM_PSCI_H */
|
||||
|
||||
@@ -82,6 +82,9 @@ obj-$(CONFIG_DEBUG_LL) += debug.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o
|
||||
obj-$(CONFIG_ARM_PSCI) += psci.o
|
||||
ifeq ($(CONFIG_ARM_PSCI),y)
|
||||
obj-y += psci.o
|
||||
obj-$(CONFIG_SMP) += psci_smp.o
|
||||
endif
|
||||
|
||||
extra-y := $(head-y) vmlinux.lds
|
||||
|
||||
@@ -158,7 +158,7 @@ static const struct of_device_id psci_of_match[] __initconst = {
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init psci_init(void)
|
||||
void __init psci_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
const char *method;
|
||||
@@ -166,7 +166,7 @@ static int __init psci_init(void)
|
||||
|
||||
np = of_find_matching_node(NULL, psci_of_match);
|
||||
if (!np)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
pr_info("probing function IDs from device-tree\n");
|
||||
|
||||
@@ -206,6 +206,5 @@ static int __init psci_init(void)
|
||||
|
||||
out_put_node:
|
||||
of_node_put(np);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
early_initcall(psci_init);
|
||||
|
||||
84
arch/arm/kernel/psci_smp.c
Normal file
84
arch/arm/kernel/psci_smp.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Copyright (C) 2012 ARM Limited
|
||||
*
|
||||
* Author: Will Deacon <will.deacon@arm.com>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/irqchip/arm-gic.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/psci.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
/*
|
||||
* psci_smp assumes that the following is true about PSCI:
|
||||
*
|
||||
* cpu_suspend Suspend the execution on a CPU
|
||||
* @state we don't currently describe affinity levels, so just pass 0.
|
||||
* @entry_point the first instruction to be executed on return
|
||||
* returns 0 success, < 0 on failure
|
||||
*
|
||||
* cpu_off Power down a CPU
|
||||
* @state we don't currently describe affinity levels, so just pass 0.
|
||||
* no return on successful call
|
||||
*
|
||||
* cpu_on Power up a CPU
|
||||
* @cpuid cpuid of target CPU, as from MPIDR
|
||||
* @entry_point the first instruction to be executed on return
|
||||
* returns 0 success, < 0 on failure
|
||||
*
|
||||
* migrate Migrate the context to a different CPU
|
||||
* @cpuid cpuid of target CPU, as from MPIDR
|
||||
* returns 0 success, < 0 on failure
|
||||
*
|
||||
*/
|
||||
|
||||
extern void secondary_startup(void);
|
||||
|
||||
static int __cpuinit psci_boot_secondary(unsigned int cpu,
|
||||
struct task_struct *idle)
|
||||
{
|
||||
if (psci_ops.cpu_on)
|
||||
return psci_ops.cpu_on(cpu_logical_map(cpu),
|
||||
__pa(secondary_startup));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
void __ref psci_cpu_die(unsigned int cpu)
|
||||
{
|
||||
const struct psci_power_state ps = {
|
||||
.type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
|
||||
};
|
||||
|
||||
if (psci_ops.cpu_off)
|
||||
psci_ops.cpu_off(ps);
|
||||
|
||||
/* We should never return */
|
||||
panic("psci: cpu %d failed to shutdown\n", cpu);
|
||||
}
|
||||
#else
|
||||
#define psci_cpu_die NULL
|
||||
#endif
|
||||
|
||||
bool __init psci_smp_available(void)
|
||||
{
|
||||
/* is cpu_on available at least? */
|
||||
return (psci_ops.cpu_on != NULL);
|
||||
}
|
||||
|
||||
struct smp_operations __initdata psci_smp_ops = {
|
||||
.smp_boot_secondary = psci_boot_secondary,
|
||||
.cpu_die = psci_cpu_die,
|
||||
};
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/procinfo.h>
|
||||
#include <asm/psci.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/smp_plat.h>
|
||||
@@ -796,9 +797,15 @@ void __init setup_arch(char **cmdline_p)
|
||||
unflatten_device_tree();
|
||||
|
||||
arm_dt_init_cpu_maps();
|
||||
psci_init();
|
||||
#ifdef CONFIG_SMP
|
||||
if (is_smp()) {
|
||||
smp_set_ops(mdesc->smp);
|
||||
if (!mdesc->smp_init || !mdesc->smp_init()) {
|
||||
if (psci_smp_available())
|
||||
smp_set_ops(&psci_smp_ops);
|
||||
else if (mdesc->smp)
|
||||
smp_set_ops(mdesc->smp);
|
||||
}
|
||||
smp_init_cpus();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
void vexpress_dt_smp_map_io(void);
|
||||
|
||||
bool vexpress_smp_init_ops(void);
|
||||
|
||||
extern struct smp_operations vexpress_smp_ops;
|
||||
|
||||
extern void vexpress_cpu_die(unsigned int cpu);
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/vexpress.h>
|
||||
|
||||
#include <asm/mcpm.h>
|
||||
#include <asm/smp_scu.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
@@ -203,3 +205,21 @@ struct smp_operations __initdata vexpress_smp_ops = {
|
||||
.cpu_die = vexpress_cpu_die,
|
||||
#endif
|
||||
};
|
||||
|
||||
bool __init vexpress_smp_init_ops(void)
|
||||
{
|
||||
#ifdef CONFIG_MCPM
|
||||
/*
|
||||
* The best way to detect a multi-cluster configuration at the moment
|
||||
* is to look for the presence of a CCI in the system.
|
||||
* Override the default vexpress_smp_ops if so.
|
||||
*/
|
||||
struct device_node *node;
|
||||
node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
|
||||
if (node && of_device_is_available(node)) {
|
||||
mcpm_smp_set_ops();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -484,6 +484,7 @@ static const char * const v2m_dt_match[] __initconst = {
|
||||
DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
|
||||
.dt_compat = v2m_dt_match,
|
||||
.smp = smp_ops(vexpress_smp_ops),
|
||||
.smp_init = smp_init_ops(vexpress_smp_init_ops),
|
||||
.map_io = v2m_dt_map_io,
|
||||
.init_early = v2m_dt_init_early,
|
||||
.init_irq = irqchip_init,
|
||||
|
||||
@@ -3,4 +3,3 @@
|
||||
#
|
||||
|
||||
obj-y := virt.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Dummy Virtual Machine - does what it says on the tin.
|
||||
*
|
||||
* Copyright (C) 2012 ARM Ltd
|
||||
* Author: Will Deacon <will.deacon@arm.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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/psci.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
extern void secondary_startup(void);
|
||||
|
||||
static void __init virt_smp_init_cpus(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void __init virt_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
}
|
||||
|
||||
static int __cpuinit virt_boot_secondary(unsigned int cpu,
|
||||
struct task_struct *idle)
|
||||
{
|
||||
if (psci_ops.cpu_on)
|
||||
return psci_ops.cpu_on(cpu_logical_map(cpu),
|
||||
__pa(secondary_startup));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
struct smp_operations __initdata virt_smp_ops = {
|
||||
.smp_init_cpus = virt_smp_init_cpus,
|
||||
.smp_prepare_cpus = virt_smp_prepare_cpus,
|
||||
.smp_boot_secondary = virt_boot_secondary,
|
||||
};
|
||||
@@ -36,11 +36,8 @@ static const char *virt_dt_match[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
extern struct smp_operations virt_smp_ops;
|
||||
|
||||
DT_MACHINE_START(VIRT, "Dummy Virtual Machine")
|
||||
.init_irq = irqchip_init,
|
||||
.init_machine = virt_init,
|
||||
.smp = smp_ops(virt_smp_ops),
|
||||
.dt_compat = virt_dt_match,
|
||||
MACHINE_END
|
||||
|
||||
Reference in New Issue
Block a user