1 /*
2  *  linux/arch/arm/mach-vexpress/platsmp.c
3  *
4  *  Copyright (C) 2002 ARM Ltd.
5  *  All Rights Reserved
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 #include <linux/init.h>
12 #include <linux/errno.h>
13 #include <linux/smp.h>
14 #include <linux/io.h>
15 #include <linux/of_address.h>
16 #include <linux/vexpress.h>
17 
18 #include <asm/mcpm.h>
19 #include <asm/smp_scu.h>
20 #include <asm/mach/map.h>
21 
22 #include <plat/platsmp.h>
23 
24 #include "core.h"
25 
vexpress_smp_init_ops(void)26 bool __init vexpress_smp_init_ops(void)
27 {
28 #ifdef CONFIG_MCPM
29 	/*
30 	 * The best way to detect a multi-cluster configuration at the moment
31 	 * is to look for the presence of a CCI in the system.
32 	 * Override the default vexpress_smp_ops if so.
33 	 */
34 	struct device_node *node;
35 	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
36 	if (node && of_device_is_available(node)) {
37 		mcpm_smp_set_ops();
38 		return true;
39 	}
40 #endif
41 	return false;
42 }
43 
44 static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = {
45 	{ .compatible = "arm,cortex-a5-scu", },
46 	{ .compatible = "arm,cortex-a9-scu", },
47 	{}
48 };
49 
vexpress_smp_dt_prepare_cpus(unsigned int max_cpus)50 static void __init vexpress_smp_dt_prepare_cpus(unsigned int max_cpus)
51 {
52 	struct device_node *scu = of_find_matching_node(NULL,
53 			vexpress_smp_dt_scu_match);
54 
55 	if (scu)
56 		scu_enable(of_iomap(scu, 0));
57 
58 	/*
59 	 * Write the address of secondary startup into the
60 	 * system-wide flags register. The boot monitor waits
61 	 * until it receives a soft interrupt, and then the
62 	 * secondary CPU branches to this address.
63 	 */
64 	vexpress_flags_set(virt_to_phys(versatile_secondary_startup));
65 }
66 
67 struct smp_operations __initdata vexpress_smp_dt_ops = {
68 	.smp_prepare_cpus	= vexpress_smp_dt_prepare_cpus,
69 	.smp_secondary_init	= versatile_secondary_init,
70 	.smp_boot_secondary	= versatile_boot_secondary,
71 #ifdef CONFIG_HOTPLUG_CPU
72 	.cpu_die		= vexpress_cpu_die,
73 #endif
74 };
75