1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * SMP support for R-Mobile / SH-Mobile - r8a7779 portion 4 * 5 * Copyright (C) 2011 Renesas Solutions Corp. 6 * Copyright (C) 2011 Magnus Damm 7 */ 8 #include <linux/kernel.h> 9 #include <linux/init.h> 10 #include <linux/smp.h> 11 #include <linux/spinlock.h> 12 #include <linux/io.h> 13 #include <linux/delay.h> 14 #include <linux/soc/renesas/rcar-sysc.h> 15 16 #include <asm/cacheflush.h> 17 #include <asm/smp_plat.h> 18 #include <asm/smp_scu.h> 19 20 #include "common.h" 21 #include "r8a7779.h" 22 23 #define HPBREG_BASE 0xfe700000 24 #define AVECR 0x0040 /* ARM Reset Vector Address Register */ 25 26 #define R8A7779_SCU_BASE 0xf0000000 27 28 static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle) 29 { 30 int ret = -EIO; 31 32 cpu = cpu_logical_map(cpu); 33 if (cpu) 34 ret = rcar_sysc_power_up_cpu(cpu); 35 36 return ret; 37 } 38 39 static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus) 40 { 41 void __iomem *base = ioremap(HPBREG_BASE, 0x1000); 42 43 /* Map the reset vector (in headsmp-scu.S, headsmp.S) */ 44 writel(__pa(shmobile_boot_vector), base + AVECR); 45 46 /* setup r8a7779 specific SCU bits */ 47 shmobile_smp_scu_prepare_cpus(R8A7779_SCU_BASE, max_cpus); 48 49 iounmap(base); 50 } 51 52 #ifdef CONFIG_HOTPLUG_CPU 53 static int r8a7779_platform_cpu_kill(unsigned int cpu) 54 { 55 int ret = -EIO; 56 57 cpu = cpu_logical_map(cpu); 58 if (cpu) 59 ret = rcar_sysc_power_down_cpu(cpu); 60 61 return ret ? ret : 1; 62 } 63 64 static int r8a7779_cpu_kill(unsigned int cpu) 65 { 66 if (shmobile_smp_scu_cpu_kill(cpu)) 67 return r8a7779_platform_cpu_kill(cpu); 68 69 return 0; 70 } 71 #endif /* CONFIG_HOTPLUG_CPU */ 72 73 const struct smp_operations r8a7779_smp_ops __initconst = { 74 .smp_prepare_cpus = r8a7779_smp_prepare_cpus, 75 .smp_boot_secondary = r8a7779_boot_secondary, 76 #ifdef CONFIG_HOTPLUG_CPU 77 .cpu_die = shmobile_smp_scu_cpu_die, 78 .cpu_kill = r8a7779_cpu_kill, 79 #endif 80 }; 81