1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2018 Nuvoton Technology corporation. 3 // Copyright 2018 Google, Inc. 4 5 #define pr_fmt(fmt) "nuvoton,npcm7xx-smp: " fmt 6 7 #include <linux/delay.h> 8 #include <linux/device.h> 9 #include <linux/smp.h> 10 #include <linux/io.h> 11 #include <linux/of.h> 12 #include <linux/of_device.h> 13 #include <linux/of_platform.h> 14 #include <linux/of_address.h> 15 #include <asm/cacheflush.h> 16 #include <asm/smp.h> 17 #include <asm/smp_plat.h> 18 #include <asm/smp_scu.h> 19 20 #define NPCM7XX_SCRPAD_REG 0x13c 21 22 extern void npcm7xx_secondary_startup(void); 23 24 static int npcm7xx_smp_boot_secondary(unsigned int cpu, 25 struct task_struct *idle) 26 { 27 struct device_node *gcr_np; 28 void __iomem *gcr_base; 29 int ret = 0; 30 31 gcr_np = of_find_compatible_node(NULL, NULL, "nuvoton,npcm750-gcr"); 32 if (!gcr_np) { 33 pr_err("no gcr device node\n"); 34 ret = -ENODEV; 35 goto out; 36 } 37 gcr_base = of_iomap(gcr_np, 0); 38 if (!gcr_base) { 39 pr_err("could not iomap gcr"); 40 ret = -ENOMEM; 41 goto out; 42 } 43 44 /* give boot ROM kernel start address. */ 45 iowrite32(__pa_symbol(npcm7xx_secondary_startup), gcr_base + 46 NPCM7XX_SCRPAD_REG); 47 /* make sure the previous write is seen by all observers. */ 48 dsb_sev(); 49 50 iounmap(gcr_base); 51 out: 52 return ret; 53 } 54 55 static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus) 56 { 57 struct device_node *scu_np; 58 void __iomem *scu_base; 59 60 scu_np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); 61 if (!scu_np) { 62 pr_err("no scu device node\n"); 63 return; 64 } 65 scu_base = of_iomap(scu_np, 0); 66 if (!scu_base) { 67 pr_err("could not iomap scu"); 68 return; 69 } 70 71 scu_enable(scu_base); 72 73 iounmap(scu_base); 74 } 75 76 static struct smp_operations npcm7xx_smp_ops __initdata = { 77 .smp_prepare_cpus = npcm7xx_smp_prepare_cpus, 78 .smp_boot_secondary = npcm7xx_smp_boot_secondary, 79 }; 80 81 CPU_METHOD_OF_DECLARE(npcm7xx_smp, "nuvoton,npcm750-smp", &npcm7xx_smp_ops); 82