mirror of
https://github.com/torvalds/linux.git
synced 2024-12-22 10:56:40 +00:00
Renesas ARM based SoC SMP updates for v3.13
* Add CPU notifier based SCU boot vector code - Use on emev2, r8a7779 and sh73a0 SoCs - Remove now unused shmobile_smp_scu_boot_secondary() * Add shared APMU SMP support code - Use to add SMP support for r8a7790 SoC * Introduce shmobile_boot_size * Expose shmobile_invalidate_start() * Introduce shmobile_smp_cpu_disable() - Use on sh73a0 SoC - Remove now unused shmobile_smp_init_cpus() -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAABAgAGBQJSST7gAAoJENfPZGlqN0++XFoP/0RsM7u+sD0gzoNDQzhK0GHp BKi46te3Wo5A0uuYKW+QxMNXKvIvRFtc/IAmIGEtm+WpNA4W/n6r0WVQWcsl9W1V f83qXVUFkdQ6B+UOy8jass+cNPYG34AjPuUkbEyY8pakvMEu81NfkIrJTdN4Yooz Al9nHRQxGz7G7zjYxPvUalu5fHnPw+gTN4gh5xkSyFup6MBq8LNbJh7xY+YGezuy xr+8EJYIlFXNO7regCp2fhRj8yRgmEjvf1At8iUl9f3HoIfYGNc2gUsPIqYdHTpX 0EppCVtiMUMl2M0ujI9p+yN7m6qMLkT6vGfPvUHwly3A+L5hYGJCKowS6Y9EMgKB 1NMco0azKzcoEnZOmgAHbi1ubJsEzLY7Bpbj3W6J+1khTdP1qOu7u2Db1MwZ08Gx ofwtNvFgE9EmiDaAeqMoyani8qJjvVu/+s/vickcZ1EzhcYY1qPi4IpBjBymlGnI oTioQ20czOvU11WT90mw/jlTTdO9FqNOv9owyTCQveWH5n2PVI+hj26oNgUWLaB8 w6YYMzHiTPwjGfIIub10MZRdMSp1nb3+HtWZW+Wd523CuzQsk5akOgrs9iqYE3rW 4PBrniBwHX+7pJnlC47RQJoh6QI4RhML/xthQfIoze/I3eDZi0x5p2LiG59u7opA kusLdSS609D4iYrBkBxt =Tn0W -----END PGP SIGNATURE----- Merge tag 'renesas-smp-for-v3.13' into soc2-base Renesas ARM based SoC SMP updates for v3.13 * Add CPU notifier based SCU boot vector code - Use on emev2, r8a7779 and sh73a0 SoCs - Remove now unused shmobile_smp_scu_boot_secondary() * Add shared APMU SMP support code - Use to add SMP support for r8a7790 SoC * Introduce shmobile_boot_size * Expose shmobile_invalidate_start() * Introduce shmobile_smp_cpu_disable() - Use on sh73a0 SoC - Remove now unused shmobile_smp_init_cpus()
This commit is contained in:
commit
8843c9d430
@ -36,6 +36,7 @@ endif
|
||||
smp-y := platsmp.o headsmp.o
|
||||
smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o platsmp-scu.o
|
||||
smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o
|
||||
smp-$(CONFIG_ARCH_R8A7790) += smp-r8a7790.o platsmp-apmu.o
|
||||
smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
|
||||
|
||||
# IRQ objects
|
||||
|
@ -57,7 +57,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
|
||||
};
|
||||
|
||||
DT_MACHINE_START(APE6EVM_DT, "ape6evm")
|
||||
.init_early = r8a73a4_init_delay,
|
||||
.init_early = r8a73a4_init_early,
|
||||
.init_machine = ape6evm_add_standard_devices,
|
||||
.dt_compat = ape6evm_boards_compat_dt,
|
||||
MACHINE_END
|
||||
|
@ -240,7 +240,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
|
||||
};
|
||||
|
||||
DT_MACHINE_START(APE6EVM_DT, "ape6evm")
|
||||
.init_early = r8a73a4_init_delay,
|
||||
.init_early = r8a73a4_init_early,
|
||||
.init_machine = ape6evm_add_standard_devices,
|
||||
.dt_compat = ape6evm_boards_compat_dt,
|
||||
MACHINE_END
|
||||
|
@ -38,7 +38,8 @@ static const char *lager_boards_compat_dt[] __initdata = {
|
||||
};
|
||||
|
||||
DT_MACHINE_START(LAGER_DT, "lager")
|
||||
.init_early = r8a7790_init_delay,
|
||||
.smp = smp_ops(r8a7790_smp_ops),
|
||||
.init_early = r8a7790_init_early,
|
||||
.init_machine = lager_add_standard_devices,
|
||||
.init_time = r8a7790_timer_init,
|
||||
.dt_compat = lager_boards_compat_dt,
|
||||
|
@ -161,7 +161,8 @@ static const char *lager_boards_compat_dt[] __initdata = {
|
||||
};
|
||||
|
||||
DT_MACHINE_START(LAGER_DT, "lager")
|
||||
.init_early = r8a7790_init_delay,
|
||||
.smp = smp_ops(r8a7790_smp_ops),
|
||||
.init_early = r8a7790_init_early,
|
||||
.init_time = r8a7790_timer_init,
|
||||
.init_machine = lager_add_standard_devices,
|
||||
.dt_compat = lager_boards_compat_dt,
|
||||
|
@ -40,6 +40,9 @@ shmobile_boot_fn:
|
||||
.globl shmobile_boot_arg
|
||||
shmobile_boot_arg:
|
||||
2: .space 4
|
||||
.globl shmobile_boot_size
|
||||
shmobile_boot_size:
|
||||
.long . - shmobile_boot_vector
|
||||
|
||||
/*
|
||||
* Per-CPU SMP boot function/argument selection code based on MPIDR
|
||||
|
@ -9,16 +9,23 @@ extern void shmobile_setup_console(void);
|
||||
extern void shmobile_boot_vector(void);
|
||||
extern unsigned long shmobile_boot_fn;
|
||||
extern unsigned long shmobile_boot_arg;
|
||||
extern unsigned long shmobile_boot_size;
|
||||
extern void shmobile_smp_boot(void);
|
||||
extern void shmobile_smp_sleep(void);
|
||||
extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
|
||||
unsigned long arg);
|
||||
extern int shmobile_smp_cpu_disable(unsigned int cpu);
|
||||
extern void shmobile_invalidate_start(void);
|
||||
extern void shmobile_boot_scu(void);
|
||||
extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
|
||||
extern int shmobile_smp_scu_boot_secondary(unsigned int cpu,
|
||||
struct task_struct *idle);
|
||||
extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
|
||||
extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
|
||||
extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus);
|
||||
extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
|
||||
struct task_struct *idle);
|
||||
extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
|
||||
extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
|
||||
extern void shmobile_invalidate_start(void);
|
||||
struct clk;
|
||||
extern int shmobile_clk_init(void);
|
||||
extern void shmobile_handle_irq_intc(struct pt_regs *);
|
||||
@ -39,7 +46,6 @@ static inline int shmobile_cpuidle_init(void) { return 0; }
|
||||
#endif
|
||||
|
||||
extern void __iomem *shmobile_scu_base;
|
||||
extern void shmobile_smp_init_cpus(unsigned int ncores);
|
||||
|
||||
static inline void __init shmobile_init_late(void)
|
||||
{
|
||||
|
@ -5,6 +5,6 @@ void r8a73a4_add_standard_devices(void);
|
||||
void r8a73a4_add_dt_devices(void);
|
||||
void r8a73a4_clock_init(void);
|
||||
void r8a73a4_pinmux_init(void);
|
||||
void r8a73a4_init_delay(void);
|
||||
void r8a73a4_init_early(void);
|
||||
|
||||
#endif /* __ASM_R8A73A4_H__ */
|
||||
|
@ -5,8 +5,9 @@ void r8a7790_add_standard_devices(void);
|
||||
void r8a7790_add_dt_devices(void);
|
||||
void r8a7790_clock_init(void);
|
||||
void r8a7790_pinmux_init(void);
|
||||
void r8a7790_init_delay(void);
|
||||
void r8a7790_init_early(void);
|
||||
void r8a7790_timer_init(void);
|
||||
extern struct smp_operations r8a7790_smp_ops;
|
||||
|
||||
#define MD(nr) BIT(nr)
|
||||
u32 r8a7790_read_mode_pins(void);
|
||||
|
195
arch/arm/mach-shmobile/platsmp-apmu.c
Normal file
195
arch/arm/mach-shmobile/platsmp-apmu.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* SMP support for SoCs with APMU
|
||||
*
|
||||
* Copyright (C) 2013 Magnus Damm
|
||||
*
|
||||
* 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/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/smp.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/cp15.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <mach/common.h>
|
||||
|
||||
static struct {
|
||||
void __iomem *iomem;
|
||||
int bit;
|
||||
} apmu_cpus[CONFIG_NR_CPUS];
|
||||
|
||||
#define WUPCR_OFFS 0x10
|
||||
#define PSTR_OFFS 0x40
|
||||
#define CPUNCR_OFFS(n) (0x100 + (0x10 * (n)))
|
||||
|
||||
static int apmu_power_on(void __iomem *p, int bit)
|
||||
{
|
||||
/* request power on */
|
||||
writel_relaxed(BIT(bit), p + WUPCR_OFFS);
|
||||
|
||||
/* wait for APMU to finish */
|
||||
while (readl_relaxed(p + WUPCR_OFFS) != 0)
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apmu_power_off(void __iomem *p, int bit)
|
||||
{
|
||||
/* request Core Standby for next WFI */
|
||||
writel_relaxed(3, p + CPUNCR_OFFS(bit));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apmu_power_off_poll(void __iomem *p, int bit)
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0; k < 1000; k++) {
|
||||
if (((readl_relaxed(p + PSTR_OFFS) >> (bit * 4)) & 0x03) == 3)
|
||||
return 1;
|
||||
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu))
|
||||
{
|
||||
void __iomem *p = apmu_cpus[cpu].iomem;
|
||||
|
||||
return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL;
|
||||
}
|
||||
|
||||
static void apmu_init_cpu(struct resource *res, int cpu, int bit)
|
||||
{
|
||||
if (apmu_cpus[cpu].iomem)
|
||||
return;
|
||||
|
||||
apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res));
|
||||
apmu_cpus[cpu].bit = bit;
|
||||
|
||||
pr_debug("apmu ioremap %d %d 0x%08x 0x%08x\n", cpu, bit,
|
||||
res->start, resource_size(res));
|
||||
}
|
||||
|
||||
static struct {
|
||||
struct resource iomem;
|
||||
int cpus[4];
|
||||
} apmu_config[] = {
|
||||
{
|
||||
.iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
|
||||
.cpus = { 0, 1, 2, 3 },
|
||||
},
|
||||
{
|
||||
.iomem = DEFINE_RES_MEM(0xe6151000, 0x88),
|
||||
.cpus = { 0x100, 0x101, 0x102, 0x103 },
|
||||
}
|
||||
};
|
||||
|
||||
static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit))
|
||||
{
|
||||
u32 id;
|
||||
int k;
|
||||
int bit, index;
|
||||
bool is_allowed;
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(apmu_config); k++) {
|
||||
/* only enable the cluster that includes the boot CPU */
|
||||
is_allowed = false;
|
||||
for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
|
||||
id = apmu_config[k].cpus[bit];
|
||||
if (id >= 0) {
|
||||
if (id == cpu_logical_map(0))
|
||||
is_allowed = true;
|
||||
}
|
||||
}
|
||||
if (!is_allowed)
|
||||
continue;
|
||||
|
||||
for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
|
||||
id = apmu_config[k].cpus[bit];
|
||||
if (id >= 0) {
|
||||
index = get_logical_index(id);
|
||||
if (index >= 0)
|
||||
fn(&apmu_config[k].iomem, index, bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
/* install boot code shared by all CPUs */
|
||||
shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
|
||||
shmobile_boot_arg = MPIDR_HWID_BITMASK;
|
||||
|
||||
/* perform per-cpu setup */
|
||||
apmu_parse_cfg(apmu_init_cpu);
|
||||
}
|
||||
|
||||
int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
/* For this particular CPU register boot vector */
|
||||
shmobile_smp_hook(cpu, virt_to_phys(shmobile_invalidate_start), 0);
|
||||
|
||||
return apmu_wrap(cpu, apmu_power_on);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/* nicked from arch/arm/mach-exynos/hotplug.c */
|
||||
static inline void cpu_enter_lowpower_a15(void)
|
||||
{
|
||||
unsigned int v;
|
||||
|
||||
asm volatile(
|
||||
" mrc p15, 0, %0, c1, c0, 0\n"
|
||||
" bic %0, %0, %1\n"
|
||||
" mcr p15, 0, %0, c1, c0, 0\n"
|
||||
: "=&r" (v)
|
||||
: "Ir" (CR_C)
|
||||
: "cc");
|
||||
|
||||
flush_cache_louis();
|
||||
|
||||
asm volatile(
|
||||
/*
|
||||
* Turn off coherency
|
||||
*/
|
||||
" mrc p15, 0, %0, c1, c0, 1\n"
|
||||
" bic %0, %0, %1\n"
|
||||
" mcr p15, 0, %0, c1, c0, 1\n"
|
||||
: "=&r" (v)
|
||||
: "Ir" (0x40)
|
||||
: "cc");
|
||||
|
||||
isb();
|
||||
dsb();
|
||||
}
|
||||
|
||||
void shmobile_smp_apmu_cpu_die(unsigned int cpu)
|
||||
{
|
||||
/* For this particular CPU deregister boot vector */
|
||||
shmobile_smp_hook(cpu, 0, 0);
|
||||
|
||||
/* Select next sleep mode using the APMU */
|
||||
apmu_wrap(cpu, apmu_power_off);
|
||||
|
||||
/* Do ARM specific CPU shutdown */
|
||||
cpu_enter_lowpower_a15();
|
||||
|
||||
/* jump to shared mach-shmobile sleep / reset code */
|
||||
shmobile_smp_sleep();
|
||||
}
|
||||
|
||||
int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
|
||||
{
|
||||
return apmu_wrap(cpu, apmu_power_off_poll);
|
||||
}
|
||||
#endif
|
@ -7,6 +7,7 @@
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
@ -16,6 +17,26 @@
|
||||
#include <asm/smp_scu.h>
|
||||
#include <mach/common.h>
|
||||
|
||||
static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (long)hcpu;
|
||||
|
||||
switch (action) {
|
||||
case CPU_UP_PREPARE:
|
||||
/* For this particular CPU register SCU SMP boot vector */
|
||||
shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
|
||||
(unsigned long)shmobile_scu_base);
|
||||
break;
|
||||
};
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block shmobile_smp_scu_notifier = {
|
||||
.notifier_call = shmobile_smp_scu_notifier_call,
|
||||
};
|
||||
|
||||
void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
/* install boot code shared by all CPUs */
|
||||
@ -25,14 +46,9 @@ void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
|
||||
/* enable SCU and cache coherency on booting CPU */
|
||||
scu_enable(shmobile_scu_base);
|
||||
scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
|
||||
}
|
||||
|
||||
int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
/* For this particular CPU register SCU boot vector */
|
||||
shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
|
||||
(unsigned long)shmobile_scu_base);
|
||||
return 0;
|
||||
/* Use CPU notifier for reset vector control */
|
||||
register_cpu_notifier(&shmobile_smp_scu_notifier);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
|
@ -11,25 +11,10 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <mach/common.h>
|
||||
|
||||
void __init shmobile_smp_init_cpus(unsigned int ncores)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
extern unsigned long shmobile_smp_fn[];
|
||||
extern unsigned long shmobile_smp_arg[];
|
||||
extern unsigned long shmobile_smp_mpidr[];
|
||||
@ -44,3 +29,10 @@ void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg)
|
||||
shmobile_smp_arg[cpu] = arg;
|
||||
flush_cache_all();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
int shmobile_smp_cpu_disable(unsigned int cpu)
|
||||
{
|
||||
return 0; /* Hotplug of any CPU is supported */
|
||||
}
|
||||
#endif
|
||||
|
@ -207,7 +207,7 @@ void __init r8a73a4_add_standard_devices(void)
|
||||
r8a73a4_register_thermal();
|
||||
}
|
||||
|
||||
void __init r8a73a4_init_delay(void)
|
||||
void __init r8a73a4_init_early(void)
|
||||
{
|
||||
#ifndef CONFIG_ARM_ARCH_TIMER
|
||||
shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */
|
||||
@ -222,7 +222,7 @@ static const char *r8a73a4_boards_compat_dt[] __initdata = {
|
||||
};
|
||||
|
||||
DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
|
||||
.init_early = r8a73a4_init_delay,
|
||||
.init_early = r8a73a4_init_early,
|
||||
.dt_compat = r8a73a4_boards_compat_dt,
|
||||
MACHINE_END
|
||||
#endif /* CONFIG_USE_OF */
|
||||
|
@ -31,17 +31,18 @@
|
||||
#include <mach/r8a7790.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
static struct resource pfc_resources[] __initdata = {
|
||||
static const struct resource pfc_resources[] __initconst = {
|
||||
DEFINE_RES_MEM(0xe6060000, 0x250),
|
||||
};
|
||||
|
||||
#define R8A7790_GPIO(idx) \
|
||||
static struct resource r8a7790_gpio##idx##_resources[] __initdata = { \
|
||||
static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \
|
||||
DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50), \
|
||||
DEFINE_RES_IRQ(gic_spi(4 + (idx))), \
|
||||
}; \
|
||||
\
|
||||
static struct gpio_rcar_config r8a7790_gpio##idx##_platform_data __initdata = { \
|
||||
static const struct gpio_rcar_config \
|
||||
r8a7790_gpio##idx##_platform_data __initconst = { \
|
||||
.gpio_base = 32 * (idx), \
|
||||
.irq_base = 0, \
|
||||
.number_of_pins = 32, \
|
||||
@ -112,7 +113,7 @@ void __init r8a7790_pinmux_init(void)
|
||||
enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1,
|
||||
HSCIF0, HSCIF1 };
|
||||
|
||||
static struct plat_sci_port scif[] __initdata = {
|
||||
static const struct plat_sci_port scif[] __initconst = {
|
||||
SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
|
||||
SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
|
||||
SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
|
||||
@ -131,11 +132,11 @@ static inline void r8a7790_register_scif(int idx)
|
||||
sizeof(struct plat_sci_port));
|
||||
}
|
||||
|
||||
static struct renesas_irqc_config irqc0_data __initdata = {
|
||||
static const struct renesas_irqc_config irqc0_data __initconst = {
|
||||
.irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
|
||||
};
|
||||
|
||||
static struct resource irqc0_resources[] __initdata = {
|
||||
static const struct resource irqc0_resources[] __initconst = {
|
||||
DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
|
||||
DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
|
||||
DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
|
||||
@ -150,7 +151,7 @@ static struct resource irqc0_resources[] __initdata = {
|
||||
&irqc##idx##_data, \
|
||||
sizeof(struct renesas_irqc_config))
|
||||
|
||||
static struct resource thermal_resources[] __initdata = {
|
||||
static const struct resource thermal_resources[] __initconst = {
|
||||
DEFINE_RES_MEM(0xe61f0000, 0x14),
|
||||
DEFINE_RES_MEM(0xe61f0100, 0x38),
|
||||
DEFINE_RES_IRQ(gic_spi(69)),
|
||||
@ -161,13 +162,13 @@ static struct resource thermal_resources[] __initdata = {
|
||||
thermal_resources, \
|
||||
ARRAY_SIZE(thermal_resources))
|
||||
|
||||
static struct sh_timer_config cmt00_platform_data __initdata = {
|
||||
static const struct sh_timer_config cmt00_platform_data __initconst = {
|
||||
.name = "CMT00",
|
||||
.timer_bit = 0,
|
||||
.clockevent_rating = 80,
|
||||
};
|
||||
|
||||
static struct resource cmt00_resources[] __initdata = {
|
||||
static const struct resource cmt00_resources[] __initconst = {
|
||||
DEFINE_RES_MEM(0xffca0510, 0x0c),
|
||||
DEFINE_RES_MEM(0xffca0500, 0x04),
|
||||
DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
|
||||
@ -267,7 +268,7 @@ void __init r8a7790_timer_init(void)
|
||||
clocksource_of_init();
|
||||
}
|
||||
|
||||
void __init r8a7790_init_delay(void)
|
||||
void __init r8a7790_init_early(void)
|
||||
{
|
||||
#ifndef CONFIG_ARM_ARCH_TIMER
|
||||
shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
|
||||
@ -276,13 +277,14 @@ void __init r8a7790_init_delay(void)
|
||||
|
||||
#ifdef CONFIG_USE_OF
|
||||
|
||||
static const char *r8a7790_boards_compat_dt[] __initdata = {
|
||||
static const char * const r8a7790_boards_compat_dt[] __initconst = {
|
||||
"renesas,r8a7790",
|
||||
NULL,
|
||||
};
|
||||
|
||||
DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
|
||||
.init_early = r8a7790_init_delay,
|
||||
.smp = smp_ops(r8a7790_smp_ops),
|
||||
.init_early = r8a7790_init_early,
|
||||
.init_time = r8a7790_timer_init,
|
||||
.dt_compat = r8a7790_boards_compat_dt,
|
||||
MACHINE_END
|
||||
|
@ -34,12 +34,6 @@
|
||||
|
||||
static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = shmobile_smp_scu_boot_secondary(cpu, idle);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
|
||||
return 0;
|
||||
}
|
||||
|
@ -87,10 +87,6 @@ static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
unsigned int lcpu = cpu_logical_map(cpu);
|
||||
int ret;
|
||||
|
||||
ret = shmobile_smp_scu_boot_secondary(cpu, idle);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu))
|
||||
ch = r8a7779_ch_cpu[lcpu];
|
||||
|
||||
|
67
arch/arm/mach-shmobile/smp-r8a7790.c
Normal file
67
arch/arm/mach-shmobile/smp-r8a7790.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* SMP support for r8a7790
|
||||
*
|
||||
* Copyright (C) 2012-2013 Renesas Solutions Corp.
|
||||
* Copyright (C) 2012 Takashi Yoshii <takashi.yoshii.ze@renesas.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/smp_plat.h>
|
||||
#include <mach/common.h>
|
||||
|
||||
#define RST 0xe6160000
|
||||
#define CA15BAR 0x0020
|
||||
#define CA7BAR 0x0030
|
||||
#define CA15RESCNT 0x0040
|
||||
#define CA7RESCNT 0x0044
|
||||
#define MERAM 0xe8080000
|
||||
|
||||
static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
void __iomem *p;
|
||||
u32 bar;
|
||||
|
||||
/* let APMU code install data related to shmobile_boot_vector */
|
||||
shmobile_smp_apmu_prepare_cpus(max_cpus);
|
||||
|
||||
/* MERAM for jump stub, because BAR requires 256KB aligned address */
|
||||
p = ioremap_nocache(MERAM, shmobile_boot_size);
|
||||
memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
|
||||
iounmap(p);
|
||||
|
||||
/* setup reset vectors */
|
||||
p = ioremap_nocache(RST, 0x63);
|
||||
bar = (MERAM >> 8) & 0xfffffc00;
|
||||
writel_relaxed(bar, p + CA15BAR);
|
||||
writel_relaxed(bar, p + CA7BAR);
|
||||
writel_relaxed(bar | 0x10, p + CA15BAR);
|
||||
writel_relaxed(bar | 0x10, p + CA7BAR);
|
||||
|
||||
/* enable clocks to all CPUs */
|
||||
writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
|
||||
p + CA15RESCNT);
|
||||
writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
|
||||
p + CA7RESCNT);
|
||||
iounmap(p);
|
||||
}
|
||||
|
||||
struct smp_operations r8a7790_smp_ops __initdata = {
|
||||
.smp_prepare_cpus = r8a7790_smp_prepare_cpus,
|
||||
.smp_boot_secondary = shmobile_smp_apmu_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_disable = shmobile_smp_cpu_disable,
|
||||
.cpu_die = shmobile_smp_apmu_cpu_die,
|
||||
.cpu_kill = shmobile_smp_apmu_cpu_kill,
|
||||
#endif
|
||||
};
|
@ -46,11 +46,6 @@ void __init sh73a0_register_twd(void)
|
||||
static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
||||
{
|
||||
unsigned int lcpu = cpu_logical_map(cpu);
|
||||
int ret;
|
||||
|
||||
ret = shmobile_smp_scu_boot_secondary(cpu, idle);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
|
||||
__raw_writel(1 << lcpu, WUPCR); /* wake up */
|
||||
@ -71,18 +66,11 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
|
||||
shmobile_smp_scu_prepare_cpus(max_cpus);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static int sh73a0_cpu_disable(unsigned int cpu)
|
||||
{
|
||||
return 0; /* CPU0 and CPU1 supported */
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
struct smp_operations sh73a0_smp_ops __initdata = {
|
||||
.smp_prepare_cpus = sh73a0_smp_prepare_cpus,
|
||||
.smp_boot_secondary = sh73a0_boot_secondary,
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
.cpu_disable = sh73a0_cpu_disable,
|
||||
.cpu_disable = shmobile_smp_cpu_disable,
|
||||
.cpu_die = shmobile_smp_scu_cpu_die,
|
||||
.cpu_kill = shmobile_smp_scu_cpu_kill,
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user