1 // SPDX-License-Identifier: GPL-2.0-or-later 2 // Copyright (C) ASPEED Technology Inc. 3 // Copyright IBM Corp. 4 5 #include <linux/of_address.h> 6 #include <linux/io.h> 7 #include <linux/of.h> 8 #include <linux/smp.h> 9 10 #define BOOT_ADDR 0x00 11 #define BOOT_SIG 0x04 12 13 static struct device_node *secboot_node; 14 15 static int aspeed_g6_boot_secondary(unsigned int cpu, struct task_struct *idle) 16 { 17 void __iomem *base; 18 19 base = of_iomap(secboot_node, 0); 20 if (!base) { 21 pr_err("could not map the secondary boot base!"); 22 return -ENODEV; 23 } 24 25 writel_relaxed(0, base + BOOT_ADDR); 26 writel_relaxed(__pa_symbol(secondary_startup_arm), base + BOOT_ADDR); 27 writel_relaxed((0xABBAAB00 | (cpu & 0xff)), base + BOOT_SIG); 28 29 dsb_sev(); 30 31 iounmap(base); 32 33 return 0; 34 } 35 36 static void __init aspeed_g6_smp_prepare_cpus(unsigned int max_cpus) 37 { 38 void __iomem *base; 39 40 secboot_node = of_find_compatible_node(NULL, NULL, "aspeed,ast2600-smpmem"); 41 if (!secboot_node) { 42 pr_err("secboot device node found!!\n"); 43 return; 44 } 45 46 base = of_iomap(secboot_node, 0); 47 if (!base) { 48 pr_err("could not map the secondary boot base!"); 49 return; 50 } 51 __raw_writel(0xBADABABA, base + BOOT_SIG); 52 53 iounmap(base); 54 } 55 56 static const struct smp_operations aspeed_smp_ops __initconst = { 57 .smp_prepare_cpus = aspeed_g6_smp_prepare_cpus, 58 .smp_boot_secondary = aspeed_g6_boot_secondary, 59 }; 60 61 CPU_METHOD_OF_DECLARE(aspeed_smp, "aspeed,ast2600-smp", &aspeed_smp_ops); 62