xref: /openbmc/linux/arch/arm/mach-npcm/platsmp.c (revision 152d11a0)
17bffa14cSBrendan Higgins // SPDX-License-Identifier: GPL-2.0
27bffa14cSBrendan Higgins // Copyright (c) 2018 Nuvoton Technology corporation.
37bffa14cSBrendan Higgins // Copyright 2018 Google, Inc.
47bffa14cSBrendan Higgins 
57bffa14cSBrendan Higgins #define pr_fmt(fmt) "nuvoton,npcm7xx-smp: " fmt
67bffa14cSBrendan Higgins 
77bffa14cSBrendan Higgins #include <linux/delay.h>
87bffa14cSBrendan Higgins #include <linux/smp.h>
97bffa14cSBrendan Higgins #include <linux/io.h>
107bffa14cSBrendan Higgins #include <linux/of.h>
117bffa14cSBrendan Higgins #include <linux/of_address.h>
127bffa14cSBrendan Higgins #include <asm/cacheflush.h>
137bffa14cSBrendan Higgins #include <asm/smp.h>
147bffa14cSBrendan Higgins #include <asm/smp_plat.h>
157bffa14cSBrendan Higgins #include <asm/smp_scu.h>
167bffa14cSBrendan Higgins 
177bffa14cSBrendan Higgins #define NPCM7XX_SCRPAD_REG 0x13c
187bffa14cSBrendan Higgins 
197bffa14cSBrendan Higgins extern void npcm7xx_secondary_startup(void);
207bffa14cSBrendan Higgins 
npcm7xx_smp_boot_secondary(unsigned int cpu,struct task_struct * idle)217bffa14cSBrendan Higgins static int npcm7xx_smp_boot_secondary(unsigned int cpu,
227bffa14cSBrendan Higgins 				      struct task_struct *idle)
237bffa14cSBrendan Higgins {
247bffa14cSBrendan Higgins 	struct device_node *gcr_np;
257bffa14cSBrendan Higgins 	void __iomem *gcr_base;
267bffa14cSBrendan Higgins 	int ret = 0;
277bffa14cSBrendan Higgins 
287bffa14cSBrendan Higgins 	gcr_np = of_find_compatible_node(NULL, NULL, "nuvoton,npcm750-gcr");
297bffa14cSBrendan Higgins 	if (!gcr_np) {
307bffa14cSBrendan Higgins 		pr_err("no gcr device node\n");
317bffa14cSBrendan Higgins 		ret = -ENODEV;
327bffa14cSBrendan Higgins 		goto out;
337bffa14cSBrendan Higgins 	}
347bffa14cSBrendan Higgins 	gcr_base = of_iomap(gcr_np, 0);
357bffa14cSBrendan Higgins 	if (!gcr_base) {
367bffa14cSBrendan Higgins 		pr_err("could not iomap gcr");
377bffa14cSBrendan Higgins 		ret = -ENOMEM;
387bffa14cSBrendan Higgins 		goto out;
397bffa14cSBrendan Higgins 	}
407bffa14cSBrendan Higgins 
417bffa14cSBrendan Higgins 	/* give boot ROM kernel start address. */
427bffa14cSBrendan Higgins 	iowrite32(__pa_symbol(npcm7xx_secondary_startup), gcr_base +
437bffa14cSBrendan Higgins 		  NPCM7XX_SCRPAD_REG);
447bffa14cSBrendan Higgins 	/* make sure the previous write is seen by all observers. */
457bffa14cSBrendan Higgins 	dsb_sev();
467bffa14cSBrendan Higgins 
477bffa14cSBrendan Higgins 	iounmap(gcr_base);
487bffa14cSBrendan Higgins out:
497bffa14cSBrendan Higgins 	return ret;
507bffa14cSBrendan Higgins }
517bffa14cSBrendan Higgins 
npcm7xx_smp_prepare_cpus(unsigned int max_cpus)527bffa14cSBrendan Higgins static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus)
537bffa14cSBrendan Higgins {
547bffa14cSBrendan Higgins 	struct device_node *scu_np;
557bffa14cSBrendan Higgins 	void __iomem *scu_base;
567bffa14cSBrendan Higgins 
577bffa14cSBrendan Higgins 	scu_np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
587bffa14cSBrendan Higgins 	if (!scu_np) {
597bffa14cSBrendan Higgins 		pr_err("no scu device node\n");
607bffa14cSBrendan Higgins 		return;
617bffa14cSBrendan Higgins 	}
627bffa14cSBrendan Higgins 	scu_base = of_iomap(scu_np, 0);
637bffa14cSBrendan Higgins 	if (!scu_base) {
647bffa14cSBrendan Higgins 		pr_err("could not iomap scu");
657bffa14cSBrendan Higgins 		return;
667bffa14cSBrendan Higgins 	}
677bffa14cSBrendan Higgins 
687bffa14cSBrendan Higgins 	scu_enable(scu_base);
697bffa14cSBrendan Higgins 
707bffa14cSBrendan Higgins 	iounmap(scu_base);
717bffa14cSBrendan Higgins }
727bffa14cSBrendan Higgins 
737bffa14cSBrendan Higgins static struct smp_operations npcm7xx_smp_ops __initdata = {
747bffa14cSBrendan Higgins 	.smp_prepare_cpus = npcm7xx_smp_prepare_cpus,
757bffa14cSBrendan Higgins 	.smp_boot_secondary = npcm7xx_smp_boot_secondary,
767bffa14cSBrendan Higgins };
777bffa14cSBrendan Higgins 
787bffa14cSBrendan Higgins CPU_METHOD_OF_DECLARE(npcm7xx_smp, "nuvoton,npcm750-smp", &npcm7xx_smp_ops);
79