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 AVECR IOMEM(0xfe700040) 24 #define R8A7779_SCU_BASE 0xf0000000 25 26 static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle) 27 { 28 int ret = -EIO; 29 30 cpu = cpu_logical_map(cpu); 31 if (cpu) 32 ret = rcar_sysc_power_up_cpu(cpu); 33 34 return ret; 35 } 36 37 static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus) 38 { 39 /* Map the reset vector (in headsmp-scu.S, headsmp.S) */ 40 __raw_writel(__pa(shmobile_boot_vector), AVECR); 41 42 /* setup r8a7779 specific SCU bits */ 43 shmobile_smp_scu_prepare_cpus(R8A7779_SCU_BASE, max_cpus); 44 } 45 46 #ifdef CONFIG_HOTPLUG_CPU 47 static int r8a7779_platform_cpu_kill(unsigned int cpu) 48 { 49 int ret = -EIO; 50 51 cpu = cpu_logical_map(cpu); 52 if (cpu) 53 ret = rcar_sysc_power_down_cpu(cpu); 54 55 return ret ? ret : 1; 56 } 57 58 static int r8a7779_cpu_kill(unsigned int cpu) 59 { 60 if (shmobile_smp_scu_cpu_kill(cpu)) 61 return r8a7779_platform_cpu_kill(cpu); 62 63 return 0; 64 } 65 #endif /* CONFIG_HOTPLUG_CPU */ 66 67 const struct smp_operations r8a7779_smp_ops __initconst = { 68 .smp_prepare_cpus = r8a7779_smp_prepare_cpus, 69 .smp_boot_secondary = r8a7779_boot_secondary, 70 #ifdef CONFIG_HOTPLUG_CPU 71 .cpu_die = shmobile_smp_scu_cpu_die, 72 .cpu_kill = r8a7779_cpu_kill, 73 #endif 74 }; 75