^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2013 Linaro Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2013 Hisilicon Limited.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Based on arch/arm/mach-vexpress/platsmp.c, Copyright (C) 2002 ARM Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/smp_plat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/smp_scu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/mach/map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define HIX5HD2_BOOT_ADDRESS 0xffff0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static void __iomem *ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) void hi3xxx_set_cpu_jump(int cpu, void *jump_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) cpu = cpu_logical_map(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (!cpu || !ctrl_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) writel_relaxed(__pa_symbol(jump_addr), ctrl_base + ((cpu - 1) << 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int hi3xxx_get_cpu_jump(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) cpu = cpu_logical_map(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!cpu || !ctrl_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return readl_relaxed(ctrl_base + ((cpu - 1) << 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void __init hisi_enable_scu_a9(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) unsigned long base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) void __iomem *scu_base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (scu_a9_has_base()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) base = scu_a9_get_base();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) scu_base = ioremap(base, SZ_4K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (!scu_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) pr_err("ioremap(scu_base) failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) scu_enable(scu_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) iounmap(scu_base);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct device_node *np = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u32 offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) hisi_enable_scu_a9();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (!ctrl_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) pr_err("failed to find hisilicon,sysctrl node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ctrl_base = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!ctrl_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) pr_err("failed to map address\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (of_property_read_u32(np, "smp-offset", &offset) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) pr_err("failed to find smp-offset property\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ctrl_base += offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int hi3xxx_boot_secondary(unsigned int cpu, struct task_struct *idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) hi3xxx_set_cpu(cpu, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) hi3xxx_set_cpu_jump(cpu, secondary_startup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) arch_send_wakeup_ipi_mask(cpumask_of(cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static const struct smp_operations hi3xxx_smp_ops __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .smp_prepare_cpus = hi3xxx_smp_prepare_cpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .smp_boot_secondary = hi3xxx_boot_secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .cpu_die = hi3xxx_cpu_die,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .cpu_kill = hi3xxx_cpu_kill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static void __init hisi_common_smp_prepare_cpus(unsigned int max_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) hisi_enable_scu_a9();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void hix5hd2_set_scu_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) void __iomem *virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) virt = ioremap(start_addr, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) writel_relaxed(0xe51ff004, virt); /* ldr pc, [pc, #-4] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) writel_relaxed(jump_addr, virt + 4); /* pc jump phy address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) iounmap(virt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) phys_addr_t jumpaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) jumpaddr = __pa_symbol(secondary_startup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) hix5hd2_set_cpu(cpu, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) arch_send_wakeup_ipi_mask(cpumask_of(cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static const struct smp_operations hix5hd2_smp_ops __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .smp_prepare_cpus = hisi_common_smp_prepare_cpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .smp_boot_secondary = hix5hd2_boot_secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .cpu_die = hix5hd2_cpu_die,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define SC_SCTL_REMAP_CLR 0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define HIP01_BOOT_ADDRESS 0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define REG_SC_CTRL 0x000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static void hip01_set_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) void __iomem *virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) virt = phys_to_virt(start_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) writel_relaxed(0xe51ff004, virt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) writel_relaxed(jump_addr, virt + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int hip01_boot_secondary(unsigned int cpu, struct task_struct *idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) phys_addr_t jumpaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) unsigned int remap_reg_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct device_node *node;
^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) jumpaddr = __pa_symbol(secondary_startup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) hip01_set_boot_addr(HIP01_BOOT_ADDRESS, jumpaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) node = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (WARN_ON(!node))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ctrl_base = of_iomap(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* set the secondary core boot from DDR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) remap_reg_value |= SC_SCTL_REMAP_CLR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) writel_relaxed(remap_reg_value, ctrl_base + REG_SC_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) hip01_set_cpu(cpu, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static const struct smp_operations hip01_smp_ops __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .smp_prepare_cpus = hisi_common_smp_prepare_cpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .smp_boot_secondary = hip01_boot_secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops);