0001
0002
0003
0004
0005
0006
0007 #include <linux/smp.h>
0008 #include <linux/io.h>
0009 #include <linux/of_address.h>
0010 #include <linux/delay.h>
0011
0012 #include <asm/cacheflush.h>
0013 #include <asm/smp_plat.h>
0014 #include <asm/smp_scu.h>
0015 #include <asm/mach/map.h>
0016
0017 #include "core.h"
0018
0019 #define HIX5HD2_BOOT_ADDRESS 0xffff0000
0020
0021 static void __iomem *ctrl_base;
0022
0023 void hi3xxx_set_cpu_jump(int cpu, void *jump_addr)
0024 {
0025 cpu = cpu_logical_map(cpu);
0026 if (!cpu || !ctrl_base)
0027 return;
0028 writel_relaxed(__pa_symbol(jump_addr), ctrl_base + ((cpu - 1) << 2));
0029 }
0030
0031 int hi3xxx_get_cpu_jump(int cpu)
0032 {
0033 cpu = cpu_logical_map(cpu);
0034 if (!cpu || !ctrl_base)
0035 return 0;
0036 return readl_relaxed(ctrl_base + ((cpu - 1) << 2));
0037 }
0038
0039 static void __init hisi_enable_scu_a9(void)
0040 {
0041 unsigned long base = 0;
0042 void __iomem *scu_base = NULL;
0043
0044 if (scu_a9_has_base()) {
0045 base = scu_a9_get_base();
0046 scu_base = ioremap(base, SZ_4K);
0047 if (!scu_base) {
0048 pr_err("ioremap(scu_base) failed\n");
0049 return;
0050 }
0051 scu_enable(scu_base);
0052 iounmap(scu_base);
0053 }
0054 }
0055
0056 static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
0057 {
0058 struct device_node *np = NULL;
0059 u32 offset = 0;
0060
0061 hisi_enable_scu_a9();
0062 if (!ctrl_base) {
0063 np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
0064 if (!np) {
0065 pr_err("failed to find hisilicon,sysctrl node\n");
0066 return;
0067 }
0068 ctrl_base = of_iomap(np, 0);
0069 if (!ctrl_base) {
0070 of_node_put(np);
0071 pr_err("failed to map address\n");
0072 return;
0073 }
0074 if (of_property_read_u32(np, "smp-offset", &offset) < 0) {
0075 of_node_put(np);
0076 pr_err("failed to find smp-offset property\n");
0077 return;
0078 }
0079 ctrl_base += offset;
0080 of_node_put(np);
0081 }
0082 }
0083
0084 static int hi3xxx_boot_secondary(unsigned int cpu, struct task_struct *idle)
0085 {
0086 hi3xxx_set_cpu(cpu, true);
0087 hi3xxx_set_cpu_jump(cpu, secondary_startup);
0088 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
0089 return 0;
0090 }
0091
0092 static const struct smp_operations hi3xxx_smp_ops __initconst = {
0093 .smp_prepare_cpus = hi3xxx_smp_prepare_cpus,
0094 .smp_boot_secondary = hi3xxx_boot_secondary,
0095 #ifdef CONFIG_HOTPLUG_CPU
0096 .cpu_die = hi3xxx_cpu_die,
0097 .cpu_kill = hi3xxx_cpu_kill,
0098 #endif
0099 };
0100
0101 static void __init hisi_common_smp_prepare_cpus(unsigned int max_cpus)
0102 {
0103 hisi_enable_scu_a9();
0104 }
0105
0106 static void hix5hd2_set_scu_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
0107 {
0108 void __iomem *virt;
0109
0110 virt = ioremap(start_addr, PAGE_SIZE);
0111
0112 writel_relaxed(0xe51ff004, virt);
0113 writel_relaxed(jump_addr, virt + 4);
0114 iounmap(virt);
0115 }
0116
0117 static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle)
0118 {
0119 phys_addr_t jumpaddr;
0120
0121 jumpaddr = __pa_symbol(secondary_startup);
0122 hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr);
0123 hix5hd2_set_cpu(cpu, true);
0124 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
0125 return 0;
0126 }
0127
0128
0129 static const struct smp_operations hix5hd2_smp_ops __initconst = {
0130 .smp_prepare_cpus = hisi_common_smp_prepare_cpus,
0131 .smp_boot_secondary = hix5hd2_boot_secondary,
0132 #ifdef CONFIG_HOTPLUG_CPU
0133 .cpu_die = hix5hd2_cpu_die,
0134 #endif
0135 };
0136
0137
0138 #define SC_SCTL_REMAP_CLR 0x00000100
0139 #define HIP01_BOOT_ADDRESS 0x80000000
0140 #define REG_SC_CTRL 0x000
0141
0142 static void hip01_set_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr)
0143 {
0144 void __iomem *virt;
0145
0146 virt = phys_to_virt(start_addr);
0147
0148 writel_relaxed(0xe51ff004, virt);
0149 writel_relaxed(jump_addr, virt + 4);
0150 }
0151
0152 static int hip01_boot_secondary(unsigned int cpu, struct task_struct *idle)
0153 {
0154 phys_addr_t jumpaddr;
0155 unsigned int remap_reg_value = 0;
0156 struct device_node *node;
0157
0158
0159 jumpaddr = __pa_symbol(secondary_startup);
0160 hip01_set_boot_addr(HIP01_BOOT_ADDRESS, jumpaddr);
0161
0162 node = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
0163 if (WARN_ON(!node))
0164 return -1;
0165 ctrl_base = of_iomap(node, 0);
0166 of_node_put(node);
0167
0168
0169 remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL);
0170 barrier();
0171 remap_reg_value |= SC_SCTL_REMAP_CLR;
0172 barrier();
0173 writel_relaxed(remap_reg_value, ctrl_base + REG_SC_CTRL);
0174
0175 hip01_set_cpu(cpu, true);
0176
0177 return 0;
0178 }
0179
0180 static const struct smp_operations hip01_smp_ops __initconst = {
0181 .smp_prepare_cpus = hisi_common_smp_prepare_cpus,
0182 .smp_boot_secondary = hip01_boot_secondary,
0183 };
0184
0185 CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops);
0186 CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops);
0187 CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops);