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