0001
0002
0003
0004
0005 #include <linux/of_address.h>
0006 #include <linux/io.h>
0007 #include <linux/of.h>
0008 #include <linux/smp.h>
0009
0010 #define BOOT_ADDR 0x00
0011 #define BOOT_SIG 0x04
0012
0013 static struct device_node *secboot_node;
0014
0015 static int aspeed_g6_boot_secondary(unsigned int cpu, struct task_struct *idle)
0016 {
0017 void __iomem *base;
0018
0019 base = of_iomap(secboot_node, 0);
0020 if (!base) {
0021 pr_err("could not map the secondary boot base!");
0022 return -ENODEV;
0023 }
0024
0025 writel_relaxed(0, base + BOOT_ADDR);
0026 writel_relaxed(__pa_symbol(secondary_startup_arm), base + BOOT_ADDR);
0027 writel_relaxed((0xABBAAB00 | (cpu & 0xff)), base + BOOT_SIG);
0028
0029 dsb_sev();
0030
0031 iounmap(base);
0032
0033 return 0;
0034 }
0035
0036 static void __init aspeed_g6_smp_prepare_cpus(unsigned int max_cpus)
0037 {
0038 void __iomem *base;
0039
0040 secboot_node = of_find_compatible_node(NULL, NULL, "aspeed,ast2600-smpmem");
0041 if (!secboot_node) {
0042 pr_err("secboot device node found!!\n");
0043 return;
0044 }
0045
0046 base = of_iomap(secboot_node, 0);
0047 if (!base) {
0048 pr_err("could not map the secondary boot base!");
0049 return;
0050 }
0051 __raw_writel(0xBADABABA, base + BOOT_SIG);
0052
0053 iounmap(base);
0054 }
0055
0056 static const struct smp_operations aspeed_smp_ops __initconst = {
0057 .smp_prepare_cpus = aspeed_g6_smp_prepare_cpus,
0058 .smp_boot_secondary = aspeed_g6_boot_secondary,
0059 };
0060
0061 CPU_METHOD_OF_DECLARE(aspeed_smp, "aspeed,ast2600-smp", &aspeed_smp_ops);