ARM: SoC: convert shmobile SMP to SMP operations
Convert shmobile SMP platforms to use struct smp_operations to provide their SMP and CPU hotplug operations. Cc: Paul Mundt <lethal@linux-sh.org> Cc: Magnus Damm <magnus.damm@gmail.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Acked-by: Nicolas Pitre <nico@linaro.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
parent
5ac21a943e
commit
a62580e580
@ -650,6 +650,7 @@ static void __init ag5evm_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(AG5EVM, "ag5evm")
|
MACHINE_START(AG5EVM, "ag5evm")
|
||||||
|
.smp = smp_ops(sh73a0_smp_ops),
|
||||||
.map_io = sh73a0_map_io,
|
.map_io = sh73a0_map_io,
|
||||||
.init_early = sh73a0_add_early_devices,
|
.init_early = sh73a0_add_early_devices,
|
||||||
.nr_irqs = NR_IRQS_LEGACY,
|
.nr_irqs = NR_IRQS_LEGACY,
|
||||||
|
@ -545,6 +545,7 @@ static void __init kota2_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(KOTA2, "kota2")
|
MACHINE_START(KOTA2, "kota2")
|
||||||
|
.smp = smp_ops(sh73a0_smp_ops),
|
||||||
.map_io = sh73a0_map_io,
|
.map_io = sh73a0_map_io,
|
||||||
.init_early = sh73a0_add_early_devices,
|
.init_early = sh73a0_add_early_devices,
|
||||||
.nr_irqs = NR_IRQS_LEGACY,
|
.nr_irqs = NR_IRQS_LEGACY,
|
||||||
|
@ -84,6 +84,7 @@ static const char *kzm9d_boards_compat_dt[] __initdata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DT_MACHINE_START(KZM9D_DT, "kzm9d")
|
DT_MACHINE_START(KZM9D_DT, "kzm9d")
|
||||||
|
.smp = smp_ops(emev2_smp_ops),
|
||||||
.map_io = emev2_map_io,
|
.map_io = emev2_map_io,
|
||||||
.init_early = emev2_add_early_devices,
|
.init_early = emev2_add_early_devices,
|
||||||
.nr_irqs = NR_IRQS_LEGACY,
|
.nr_irqs = NR_IRQS_LEGACY,
|
||||||
|
@ -769,6 +769,7 @@ static const char *kzm9g_boards_compat_dt[] __initdata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DT_MACHINE_START(KZM9G_DT, "kzm9g")
|
DT_MACHINE_START(KZM9G_DT, "kzm9g")
|
||||||
|
.smp = smp_ops(sh73a0_smp_ops),
|
||||||
.map_io = sh73a0_map_io,
|
.map_io = sh73a0_map_io,
|
||||||
.init_early = sh73a0_add_early_devices,
|
.init_early = sh73a0_add_early_devices,
|
||||||
.nr_irqs = NR_IRQS_LEGACY,
|
.nr_irqs = NR_IRQS_LEGACY,
|
||||||
|
@ -102,6 +102,7 @@ static void __init marzen_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(MARZEN, "marzen")
|
MACHINE_START(MARZEN, "marzen")
|
||||||
|
.smp = smp_ops(r8a7779_smp_ops),
|
||||||
.map_io = r8a7779_map_io,
|
.map_io = r8a7779_map_io,
|
||||||
.init_early = r8a7779_add_early_devices,
|
.init_early = r8a7779_add_early_devices,
|
||||||
.nr_irqs = NR_IRQS_LEGACY,
|
.nr_irqs = NR_IRQS_LEGACY,
|
||||||
|
@ -14,30 +14,16 @@
|
|||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/of.h>
|
||||||
#include <mach/common.h>
|
#include <mach/common.h>
|
||||||
|
#include <mach/r8a7779.h>
|
||||||
|
#include <mach/emev2.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
|
||||||
static cpumask_t dead_cpus;
|
static cpumask_t dead_cpus;
|
||||||
|
|
||||||
int platform_cpu_kill(unsigned int cpu)
|
void shmobile_cpu_die(unsigned int cpu)
|
||||||
{
|
|
||||||
int k;
|
|
||||||
|
|
||||||
/* this function is running on another CPU than the offline target,
|
|
||||||
* here we need wait for shutdown code in platform_cpu_die() to
|
|
||||||
* finish before asking SoC-specific code to power off the CPU core.
|
|
||||||
*/
|
|
||||||
for (k = 0; k < 1000; k++) {
|
|
||||||
if (cpumask_test_cpu(cpu, &dead_cpus))
|
|
||||||
return shmobile_platform_cpu_kill(cpu);
|
|
||||||
|
|
||||||
mdelay(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void platform_cpu_die(unsigned int cpu)
|
|
||||||
{
|
{
|
||||||
/* hardware shutdown code running on the CPU that is being offlined */
|
/* hardware shutdown code running on the CPU that is being offlined */
|
||||||
flush_cache_all();
|
flush_cache_all();
|
||||||
@ -60,7 +46,7 @@ void platform_cpu_die(unsigned int cpu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int platform_cpu_disable(unsigned int cpu)
|
int shmobile_cpu_disable(unsigned int cpu)
|
||||||
{
|
{
|
||||||
cpumask_clear_cpu(cpu, &dead_cpus);
|
cpumask_clear_cpu(cpu, &dead_cpus);
|
||||||
/*
|
/*
|
||||||
@ -69,3 +55,8 @@ int platform_cpu_disable(unsigned int cpu)
|
|||||||
*/
|
*/
|
||||||
return cpu == 0 ? -EPERM : 0;
|
return cpu == 0 ? -EPERM : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int shmobile_cpu_is_dead(unsigned int cpu)
|
||||||
|
{
|
||||||
|
return cpumask_test_cpu(cpu, &dead_cpus);
|
||||||
|
}
|
||||||
|
@ -8,7 +8,6 @@ extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
|
|||||||
struct twd_local_timer;
|
struct twd_local_timer;
|
||||||
extern void shmobile_setup_console(void);
|
extern void shmobile_setup_console(void);
|
||||||
extern void shmobile_secondary_vector(void);
|
extern void shmobile_secondary_vector(void);
|
||||||
extern int shmobile_platform_cpu_kill(unsigned int cpu);
|
|
||||||
struct clk;
|
struct clk;
|
||||||
extern int shmobile_clk_init(void);
|
extern int shmobile_clk_init(void);
|
||||||
extern void shmobile_handle_irq_intc(struct pt_regs *);
|
extern void shmobile_handle_irq_intc(struct pt_regs *);
|
||||||
@ -58,11 +57,6 @@ extern struct clk sh73a0_extal2_clk;
|
|||||||
extern struct clk sh73a0_extcki_clk;
|
extern struct clk sh73a0_extcki_clk;
|
||||||
extern struct clk sh73a0_extalr_clk;
|
extern struct clk sh73a0_extalr_clk;
|
||||||
|
|
||||||
extern unsigned int sh73a0_get_core_count(void);
|
|
||||||
extern void sh73a0_secondary_init(unsigned int cpu);
|
|
||||||
extern int sh73a0_boot_secondary(unsigned int cpu);
|
|
||||||
extern void sh73a0_smp_prepare_cpus(void);
|
|
||||||
|
|
||||||
extern void r8a7740_init_irq(void);
|
extern void r8a7740_init_irq(void);
|
||||||
extern void r8a7740_map_io(void);
|
extern void r8a7740_map_io(void);
|
||||||
extern void r8a7740_add_early_devices(void);
|
extern void r8a7740_add_early_devices(void);
|
||||||
@ -79,11 +73,6 @@ extern void r8a7779_pinmux_init(void);
|
|||||||
extern void r8a7779_pm_init(void);
|
extern void r8a7779_pm_init(void);
|
||||||
extern void r8a7740_meram_workaround(void);
|
extern void r8a7740_meram_workaround(void);
|
||||||
|
|
||||||
extern unsigned int r8a7779_get_core_count(void);
|
|
||||||
extern int r8a7779_platform_cpu_kill(unsigned int cpu);
|
|
||||||
extern void r8a7779_secondary_init(unsigned int cpu);
|
|
||||||
extern int r8a7779_boot_secondary(unsigned int cpu);
|
|
||||||
extern void r8a7779_smp_prepare_cpus(void);
|
|
||||||
extern void r8a7779_register_twd(void);
|
extern void r8a7779_register_twd(void);
|
||||||
|
|
||||||
extern void shmobile_init_late(void);
|
extern void shmobile_init_late(void);
|
||||||
@ -100,4 +89,15 @@ int shmobile_cpuidle_init(void);
|
|||||||
static inline int shmobile_cpuidle_init(void) { return 0; }
|
static inline int shmobile_cpuidle_init(void) { return 0; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern void shmobile_cpu_die(unsigned int cpu);
|
||||||
|
extern int shmobile_cpu_disable(unsigned int cpu);
|
||||||
|
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
extern int shmobile_cpu_is_dead(unsigned int cpu);
|
||||||
|
#else
|
||||||
|
static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void shmobile_smp_init_cpus(unsigned int ncores);
|
||||||
|
|
||||||
#endif /* __ARCH_MACH_COMMON_H */
|
#endif /* __ARCH_MACH_COMMON_H */
|
||||||
|
@ -7,13 +7,10 @@ extern void emev2_add_early_devices(void);
|
|||||||
extern void emev2_add_standard_devices(void);
|
extern void emev2_add_standard_devices(void);
|
||||||
extern void emev2_clock_init(void);
|
extern void emev2_clock_init(void);
|
||||||
extern void emev2_set_boot_vector(unsigned long value);
|
extern void emev2_set_boot_vector(unsigned long value);
|
||||||
extern unsigned int emev2_get_core_count(void);
|
|
||||||
extern int emev2_platform_cpu_kill(unsigned int cpu);
|
|
||||||
extern void emev2_secondary_init(unsigned int cpu);
|
|
||||||
extern int emev2_boot_secondary(unsigned int cpu);
|
|
||||||
extern void emev2_smp_prepare_cpus(void);
|
|
||||||
|
|
||||||
#define EMEV2_GPIO_BASE 200
|
#define EMEV2_GPIO_BASE 200
|
||||||
#define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
|
#define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
|
||||||
|
|
||||||
|
extern struct smp_operations emev2_smp_ops;
|
||||||
|
|
||||||
#endif /* __ASM_EMEV2_H__ */
|
#endif /* __ASM_EMEV2_H__ */
|
||||||
|
@ -360,4 +360,6 @@ extern void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd,
|
|||||||
#define r8a7779_add_device_to_domain(pd, pdev) do { } while (0)
|
#define r8a7779_add_device_to_domain(pd, pdev) do { } while (0)
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
extern struct smp_operations r8a7779_smp_ops;
|
||||||
|
|
||||||
#endif /* __ASM_R8A7779_H__ */
|
#endif /* __ASM_R8A7779_H__ */
|
||||||
|
@ -557,4 +557,6 @@ enum {
|
|||||||
#define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
|
#define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
|
||||||
#define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
|
#define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
|
||||||
|
|
||||||
|
extern struct smp_operations sh73a0_smp_ops;
|
||||||
|
|
||||||
#endif /* __ASM_SH73A0_H__ */
|
#endif /* __ASM_SH73A0_H__ */
|
||||||
|
@ -11,100 +11,11 @@
|
|||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/io.h>
|
|
||||||
#include <linux/of.h>
|
|
||||||
#include <asm/hardware/gic.h>
|
#include <asm/hardware/gic.h>
|
||||||
#include <asm/mach-types.h>
|
|
||||||
#include <mach/common.h>
|
|
||||||
#include <mach/emev2.h>
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_SH73A0
|
void __init shmobile_smp_init_cpus(unsigned int ncores)
|
||||||
#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \
|
|
||||||
of_machine_is_compatible("renesas,sh73a0"))
|
|
||||||
#else
|
|
||||||
#define is_sh73a0() (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define is_r8a7779() machine_is_marzen()
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_EMEV2
|
|
||||||
#define is_emev2() of_machine_is_compatible("renesas,emev2")
|
|
||||||
#else
|
|
||||||
#define is_emev2() (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static unsigned int __init shmobile_smp_get_core_count(void)
|
|
||||||
{
|
{
|
||||||
if (is_sh73a0())
|
|
||||||
return sh73a0_get_core_count();
|
|
||||||
|
|
||||||
if (is_r8a7779())
|
|
||||||
return r8a7779_get_core_count();
|
|
||||||
|
|
||||||
if (is_emev2())
|
|
||||||
return emev2_get_core_count();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init shmobile_smp_prepare_cpus(void)
|
|
||||||
{
|
|
||||||
if (is_sh73a0())
|
|
||||||
sh73a0_smp_prepare_cpus();
|
|
||||||
|
|
||||||
if (is_r8a7779())
|
|
||||||
r8a7779_smp_prepare_cpus();
|
|
||||||
|
|
||||||
if (is_emev2())
|
|
||||||
emev2_smp_prepare_cpus();
|
|
||||||
}
|
|
||||||
|
|
||||||
int shmobile_platform_cpu_kill(unsigned int cpu)
|
|
||||||
{
|
|
||||||
if (is_r8a7779())
|
|
||||||
return r8a7779_platform_cpu_kill(cpu);
|
|
||||||
|
|
||||||
if (is_emev2())
|
|
||||||
return emev2_platform_cpu_kill(cpu);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cpuinit platform_secondary_init(unsigned int cpu)
|
|
||||||
{
|
|
||||||
trace_hardirqs_off();
|
|
||||||
|
|
||||||
if (is_sh73a0())
|
|
||||||
sh73a0_secondary_init(cpu);
|
|
||||||
|
|
||||||
if (is_r8a7779())
|
|
||||||
r8a7779_secondary_init(cpu);
|
|
||||||
|
|
||||||
if (is_emev2())
|
|
||||||
emev2_secondary_init(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|
||||||
{
|
|
||||||
if (is_sh73a0())
|
|
||||||
return sh73a0_boot_secondary(cpu);
|
|
||||||
|
|
||||||
if (is_r8a7779())
|
|
||||||
return r8a7779_boot_secondary(cpu);
|
|
||||||
|
|
||||||
if (is_emev2())
|
|
||||||
return emev2_boot_secondary(cpu);
|
|
||||||
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __init smp_init_cpus(void)
|
|
||||||
{
|
|
||||||
unsigned int ncores = shmobile_smp_get_core_count();
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (ncores > nr_cpu_ids) {
|
if (ncores > nr_cpu_ids) {
|
||||||
@ -118,8 +29,3 @@ void __init smp_init_cpus(void)
|
|||||||
|
|
||||||
set_smp_cross_call(gic_raise_softirq);
|
set_smp_cross_call(gic_raise_softirq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init platform_smp_prepare_cpus(unsigned int max_cpus)
|
|
||||||
{
|
|
||||||
shmobile_smp_prepare_cpus();
|
|
||||||
}
|
|
||||||
|
@ -440,6 +440,7 @@ void __init emev2_init_irq_dt(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
|
DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
|
||||||
|
.smp = smp_ops(emev2_smp_ops),
|
||||||
.init_early = emev2_init_delay,
|
.init_early = emev2_init_delay,
|
||||||
.nr_irqs = NR_IRQS_LEGACY,
|
.nr_irqs = NR_IRQS_LEGACY,
|
||||||
.init_irq = emev2_init_irq_dt,
|
.init_irq = emev2_init_irq_dt,
|
||||||
|
@ -50,7 +50,7 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int __init emev2_get_core_count(void)
|
static unsigned int __init emev2_get_core_count(void)
|
||||||
{
|
{
|
||||||
if (!scu_base) {
|
if (!scu_base) {
|
||||||
scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
|
scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
|
||||||
@ -62,17 +62,35 @@ unsigned int __init emev2_get_core_count(void)
|
|||||||
return scu_base ? scu_get_core_count(scu_base) : 1;
|
return scu_base ? scu_get_core_count(scu_base) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int emev2_platform_cpu_kill(unsigned int cpu)
|
static int emev2_platform_cpu_kill(unsigned int cpu)
|
||||||
{
|
{
|
||||||
return 0; /* not supported yet */
|
return 0; /* not supported yet */
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit emev2_secondary_init(unsigned int cpu)
|
static int __maybe_unused emev2_cpu_kill(unsigned int cpu)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
/* this function is running on another CPU than the offline target,
|
||||||
|
* here we need wait for shutdown code in platform_cpu_die() to
|
||||||
|
* finish before asking SoC-specific code to power off the CPU core.
|
||||||
|
*/
|
||||||
|
for (k = 0; k < 1000; k++) {
|
||||||
|
if (shmobile_cpu_is_dead(cpu))
|
||||||
|
return emev2_platform_cpu_kill(cpu);
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void __cpuinit emev2_secondary_init(unsigned int cpu)
|
||||||
{
|
{
|
||||||
gic_secondary_init(0);
|
gic_secondary_init(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __cpuinit emev2_boot_secondary(unsigned int cpu)
|
static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||||
{
|
{
|
||||||
cpu = cpu_logical_map(cpu);
|
cpu = cpu_logical_map(cpu);
|
||||||
|
|
||||||
@ -86,7 +104,7 @@ int __cpuinit emev2_boot_secondary(unsigned int cpu)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init emev2_smp_prepare_cpus(void)
|
static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
|
||||||
{
|
{
|
||||||
int cpu = cpu_logical_map(0);
|
int cpu = cpu_logical_map(0);
|
||||||
|
|
||||||
@ -95,3 +113,22 @@ void __init emev2_smp_prepare_cpus(void)
|
|||||||
/* enable cache coherency on CPU0 */
|
/* enable cache coherency on CPU0 */
|
||||||
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __init emev2_smp_init_cpus(void)
|
||||||
|
{
|
||||||
|
unsigned int ncores = emev2_get_core_count();
|
||||||
|
|
||||||
|
shmobile_smp_init_cpus(ncores);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct smp_operations emev2_smp_ops __initdata = {
|
||||||
|
.smp_init_cpus = emev2_smp_init_cpus,
|
||||||
|
.smp_prepare_cpus = emev2_smp_prepare_cpus,
|
||||||
|
.smp_secondary_init = emev2_secondary_init,
|
||||||
|
.smp_boot_secondary = emev2_boot_secondary,
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
.cpu_kill = emev2_cpu_kill,
|
||||||
|
.cpu_die = shmobile_cpu_die,
|
||||||
|
.cpu_disable = shmobile_cpu_disable,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
@ -87,14 +87,14 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
|||||||
__raw_writel(tmp, scu_base + 8);
|
__raw_writel(tmp, scu_base + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int __init r8a7779_get_core_count(void)
|
static unsigned int __init r8a7779_get_core_count(void)
|
||||||
{
|
{
|
||||||
void __iomem *scu_base = scu_base_addr();
|
void __iomem *scu_base = scu_base_addr();
|
||||||
|
|
||||||
return scu_get_core_count(scu_base);
|
return scu_get_core_count(scu_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
int r8a7779_platform_cpu_kill(unsigned int cpu)
|
static int r8a7779_platform_cpu_kill(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct r8a7779_pm_ch *ch = NULL;
|
struct r8a7779_pm_ch *ch = NULL;
|
||||||
int ret = -EIO;
|
int ret = -EIO;
|
||||||
@ -113,12 +113,31 @@ int r8a7779_platform_cpu_kill(unsigned int cpu)
|
|||||||
return ret ? ret : 1;
|
return ret ? ret : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit r8a7779_secondary_init(unsigned int cpu)
|
static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
/* this function is running on another CPU than the offline target,
|
||||||
|
* here we need wait for shutdown code in platform_cpu_die() to
|
||||||
|
* finish before asking SoC-specific code to power off the CPU core.
|
||||||
|
*/
|
||||||
|
for (k = 0; k < 1000; k++) {
|
||||||
|
if (shmobile_cpu_is_dead(cpu))
|
||||||
|
return r8a7779_platform_cpu_kill(cpu);
|
||||||
|
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void __cpuinit r8a7779_secondary_init(unsigned int cpu)
|
||||||
{
|
{
|
||||||
gic_secondary_init(0);
|
gic_secondary_init(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __cpuinit r8a7779_boot_secondary(unsigned int cpu)
|
static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||||
{
|
{
|
||||||
struct r8a7779_pm_ch *ch = NULL;
|
struct r8a7779_pm_ch *ch = NULL;
|
||||||
int ret = -EIO;
|
int ret = -EIO;
|
||||||
@ -137,7 +156,7 @@ int __cpuinit r8a7779_boot_secondary(unsigned int cpu)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init r8a7779_smp_prepare_cpus(void)
|
static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
|
||||||
{
|
{
|
||||||
int cpu = cpu_logical_map(0);
|
int cpu = cpu_logical_map(0);
|
||||||
|
|
||||||
@ -156,3 +175,22 @@ void __init r8a7779_smp_prepare_cpus(void)
|
|||||||
r8a7779_platform_cpu_kill(2);
|
r8a7779_platform_cpu_kill(2);
|
||||||
r8a7779_platform_cpu_kill(3);
|
r8a7779_platform_cpu_kill(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __init r8a7779_smp_init_cpus(void)
|
||||||
|
{
|
||||||
|
unsigned int ncores = r8a7779_get_core_count();
|
||||||
|
|
||||||
|
shmobile_smp_init_cpus(ncores);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct smp_operations r8a7779_smp_ops __initdata = {
|
||||||
|
.smp_init_cpus = r8a7779_smp_init_cpus,
|
||||||
|
.smp_prepare_cpus = r8a7779_smp_prepare_cpus,
|
||||||
|
.smp_secondary_init = r8a7779_secondary_init,
|
||||||
|
.smp_boot_secondary = r8a7779_boot_secondary,
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
.cpu_kill = r8a7779_cpu_kill,
|
||||||
|
.cpu_die = shmobile_cpu_die,
|
||||||
|
.cpu_disable = shmobile_cpu_disable,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
@ -22,8 +22,10 @@
|
|||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <mach/common.h>
|
#include <mach/common.h>
|
||||||
#include <asm/smp_plat.h>
|
#include <asm/smp_plat.h>
|
||||||
|
#include <mach/sh73a0.h>
|
||||||
#include <asm/smp_scu.h>
|
#include <asm/smp_scu.h>
|
||||||
#include <asm/smp_twd.h>
|
#include <asm/smp_twd.h>
|
||||||
#include <asm/hardware/gic.h>
|
#include <asm/hardware/gic.h>
|
||||||
@ -64,19 +66,19 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
|
|||||||
__raw_writel(tmp, scu_base + 8);
|
__raw_writel(tmp, scu_base + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int __init sh73a0_get_core_count(void)
|
static unsigned int __init sh73a0_get_core_count(void)
|
||||||
{
|
{
|
||||||
void __iomem *scu_base = scu_base_addr();
|
void __iomem *scu_base = scu_base_addr();
|
||||||
|
|
||||||
return scu_get_core_count(scu_base);
|
return scu_get_core_count(scu_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit sh73a0_secondary_init(unsigned int cpu)
|
static void __cpuinit sh73a0_secondary_init(unsigned int cpu)
|
||||||
{
|
{
|
||||||
gic_secondary_init(0);
|
gic_secondary_init(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
|
static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||||
{
|
{
|
||||||
cpu = cpu_logical_map(cpu);
|
cpu = cpu_logical_map(cpu);
|
||||||
|
|
||||||
@ -91,7 +93,7 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init sh73a0_smp_prepare_cpus(void)
|
static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
|
||||||
{
|
{
|
||||||
int cpu = cpu_logical_map(0);
|
int cpu = cpu_logical_map(0);
|
||||||
|
|
||||||
@ -104,3 +106,41 @@ void __init sh73a0_smp_prepare_cpus(void)
|
|||||||
/* enable cache coherency on CPU0 */
|
/* enable cache coherency on CPU0 */
|
||||||
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
modify_scu_cpu_psr(0, 3 << (cpu * 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __init sh73a0_smp_init_cpus(void)
|
||||||
|
{
|
||||||
|
unsigned int ncores = sh73a0_get_core_count();
|
||||||
|
|
||||||
|
shmobile_smp_init_cpus(ncores);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
/* this function is running on another CPU than the offline target,
|
||||||
|
* here we need wait for shutdown code in platform_cpu_die() to
|
||||||
|
* finish before asking SoC-specific code to power off the CPU core.
|
||||||
|
*/
|
||||||
|
for (k = 0; k < 1000; k++) {
|
||||||
|
if (shmobile_cpu_is_dead(cpu))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct smp_operations sh73a0_smp_ops __initdata = {
|
||||||
|
.smp_init_cpus = sh73a0_smp_init_cpus,
|
||||||
|
.smp_prepare_cpus = sh73a0_smp_prepare_cpus,
|
||||||
|
.smp_secondary_init = sh73a0_secondary_init,
|
||||||
|
.smp_boot_secondary = sh73a0_boot_secondary,
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
.cpu_kill = sh73a0_cpu_kill,
|
||||||
|
.cpu_die = shmobile_cpu_die,
|
||||||
|
.cpu_disable = shmobile_cpu_disable,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user