^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * SMP support for SoCs with APMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014 Renesas Electronics Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2013 Magnus Damm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/cpu_pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/threads.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/cp15.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/proc-fns.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/smp_plat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "rcar-gen2.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) void __iomem *iomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) } apmu_cpus[NR_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define WUPCR_OFFS 0x10 /* Wake Up Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define PSTR_OFFS 0x40 /* Power Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define CPUNCR_OFFS(n) (0x100 + (0x10 * (n)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* CPUn Power Status Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define DBGRCR_OFFS 0x180 /* Debug Resource Reset Control Reg. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* Power Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define CPUNST(r, n) (((r) >> (n * 4)) & 3) /* CPUn Status Bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define CPUST_RUN 0 /* Run Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define CPUST_STANDBY 3 /* CoreStandby Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* Debug Resource Reset Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define DBGCPUREN BIT(24) /* CPU Other Reset Request Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define DBGCPUNREN(n) BIT((n) + 20) /* CPUn Reset Request Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define DBGCPUPREN BIT(19) /* CPU Peripheral Reset Req. Enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static int __maybe_unused apmu_power_on(void __iomem *p, int bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* request power on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) writel_relaxed(BIT(bit), p + WUPCR_OFFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* wait for APMU to finish */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) while (readl_relaxed(p + WUPCR_OFFS) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int __maybe_unused apmu_power_off(void __iomem *p, int bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* request Core Standby for next WFI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) writel_relaxed(3, p + CPUNCR_OFFS(bit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int __maybe_unused apmu_power_off_poll(void __iomem *p, int bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) for (k = 0; k < 1000; k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (CPUNST(readl_relaxed(p + PSTR_OFFS), bit) == CPUST_STANDBY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int __maybe_unused apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) void __iomem *p = apmu_cpus[cpu].iomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_SUSPEND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* nicked from arch/arm/mach-exynos/hotplug.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static inline void cpu_enter_lowpower_a15(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned int v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) " mrc p15, 0, %0, c1, c0, 0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) " bic %0, %0, %1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) " mcr p15, 0, %0, c1, c0, 0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) : "=&r" (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) : "Ir" (CR_C)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) : "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) flush_cache_louis();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) asm volatile(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * Turn off coherency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) " mrc p15, 0, %0, c1, c0, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) " bic %0, %0, %1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) " mcr p15, 0, %0, c1, c0, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) : "=&r" (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) : "Ir" (0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) : "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) isb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) dsb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void shmobile_smp_apmu_cpu_shutdown(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Select next sleep mode using the APMU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) apmu_wrap(cpu, apmu_power_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Do ARM specific CPU shutdown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) cpu_enter_lowpower_a15();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #if defined(CONFIG_HOTPLUG_CPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static void shmobile_smp_apmu_cpu_die(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* For this particular CPU deregister boot vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) shmobile_smp_hook(cpu, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* Shutdown CPU core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) shmobile_smp_apmu_cpu_shutdown(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* jump to shared mach-shmobile sleep / reset code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) shmobile_smp_sleep();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return apmu_wrap(cpu, apmu_power_off_poll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #if defined(CONFIG_SUSPEND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int shmobile_smp_apmu_do_suspend(unsigned long cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) shmobile_smp_hook(cpu, __pa_symbol(cpu_resume), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) shmobile_smp_apmu_cpu_shutdown(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) cpu_do_idle(); /* WFI selects Core Standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static inline void cpu_leave_lowpower(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned int v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) " orr %0, %0, %1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) " mcr p15, 0, %0, c1, c0, 0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) " mrc p15, 0, %0, c1, c0, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) " orr %0, %0, %2\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) " mcr p15, 0, %0, c1, c0, 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) : "=&r" (v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) : "Ir" (CR_C), "Ir" (0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) : "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int shmobile_smp_apmu_enter_suspend(suspend_state_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) cpu_suspend(smp_processor_id(), shmobile_smp_apmu_do_suspend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) cpu_leave_lowpower();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) void __init shmobile_smp_apmu_suspend_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #ifdef CONFIG_SMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static void apmu_init_cpu(struct resource *res, int cpu, int bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) u32 x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if ((cpu >= ARRAY_SIZE(apmu_cpus)) || apmu_cpus[cpu].iomem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) apmu_cpus[cpu].iomem = ioremap(res->start, resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) apmu_cpus[cpu].bit = bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) pr_debug("apmu ioremap %d %d %pr\n", cpu, bit, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* Setup for debug mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) x = readl(apmu_cpus[cpu].iomem + DBGRCR_OFFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) x |= DBGCPUREN | DBGCPUNREN(bit) | DBGCPUPREN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) writel(x, apmu_cpus[cpu].iomem + DBGRCR_OFFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static const struct of_device_id apmu_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) { .compatible = "renesas,apmu" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { /*sentinel*/ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void apmu_parse_dt(void (*fn)(struct resource *res, int cpu, int bit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct device_node *np_apmu, *np_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int bit, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) for_each_matching_node(np_apmu, apmu_ids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* only enable the cluster that includes the boot CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) bool is_allowed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) for (bit = 0; bit < CONFIG_NR_CPUS; bit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) np_cpu = of_parse_phandle(np_apmu, "cpus", bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (np_cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!of_property_read_u32(np_cpu, "reg", &id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (id == cpu_logical_map(0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) is_allowed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) of_node_put(np_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) of_node_put(np_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (!is_allowed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) for (bit = 0; bit < CONFIG_NR_CPUS; bit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) np_cpu = of_parse_phandle(np_apmu, "cpus", bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (np_cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!of_property_read_u32(np_cpu, "reg", &id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) index = get_logical_index(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if ((index >= 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) !of_address_to_resource(np_apmu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 0, &res))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) fn(&res, index, bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) of_node_put(np_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static void __init shmobile_smp_apmu_setup_boot(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /* install boot code shared by all CPUs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) shmobile_boot_fn = __pa_symbol(shmobile_smp_boot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) shmobile_boot_fn_gen2 = shmobile_boot_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct task_struct *idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /* For this particular CPU register boot vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) shmobile_smp_hook(cpu, __pa_symbol(shmobile_boot_apmu), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return apmu_wrap(cpu, apmu_power_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static void __init shmobile_smp_apmu_prepare_cpus_dt(unsigned int max_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) shmobile_smp_apmu_setup_boot();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) apmu_parse_dt(apmu_init_cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) rcar_gen2_pm_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static struct smp_operations apmu_smp_ops __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .smp_prepare_cpus = shmobile_smp_apmu_prepare_cpus_dt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .smp_boot_secondary = shmobile_smp_apmu_boot_secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .cpu_can_disable = shmobile_smp_cpu_can_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .cpu_die = shmobile_smp_apmu_cpu_die,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .cpu_kill = shmobile_smp_apmu_cpu_kill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) CPU_METHOD_OF_DECLARE(shmobile_smp_apmu, "renesas,apmu", &apmu_smp_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) #endif /* CONFIG_SMP */