0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/io.h>
0009 #include <linux/delay.h>
0010 #include <linux/of.h>
0011 #include <linux/of_address.h>
0012
0013 #include <asm/cacheflush.h>
0014 #include <asm/cp15.h>
0015 #include <asm/memory.h>
0016 #include <asm/smp_plat.h>
0017 #include <asm/smp_scu.h>
0018
0019
0020
0021
0022
0023 #define CPU_RESET_SC 0x00
0024 #define CPU_RESET_NON_SC 0x20
0025
0026 #define RESET_VECT 0x00
0027 #define SW_RESET_ADDR 0x94
0028
0029 extern u32 boot_inst;
0030
0031 static void __iomem *cpu_ctrl;
0032
0033 static inline void berlin_perform_reset_cpu(unsigned int cpu)
0034 {
0035 u32 val;
0036
0037 val = readl(cpu_ctrl + CPU_RESET_NON_SC);
0038 val &= ~BIT(cpu_logical_map(cpu));
0039 writel(val, cpu_ctrl + CPU_RESET_NON_SC);
0040 val |= BIT(cpu_logical_map(cpu));
0041 writel(val, cpu_ctrl + CPU_RESET_NON_SC);
0042 }
0043
0044 static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle)
0045 {
0046 if (!cpu_ctrl)
0047 return -EFAULT;
0048
0049
0050
0051
0052
0053 berlin_perform_reset_cpu(cpu);
0054
0055 return 0;
0056 }
0057
0058 static void __init berlin_smp_prepare_cpus(unsigned int max_cpus)
0059 {
0060 struct device_node *np;
0061 void __iomem *scu_base;
0062 void __iomem *vectors_base;
0063
0064 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
0065 scu_base = of_iomap(np, 0);
0066 of_node_put(np);
0067 if (!scu_base)
0068 return;
0069
0070 np = of_find_compatible_node(NULL, NULL, "marvell,berlin-cpu-ctrl");
0071 cpu_ctrl = of_iomap(np, 0);
0072 of_node_put(np);
0073 if (!cpu_ctrl)
0074 goto unmap_scu;
0075
0076 vectors_base = ioremap(VECTORS_BASE, SZ_32K);
0077 if (!vectors_base)
0078 goto unmap_scu;
0079
0080 scu_enable(scu_base);
0081
0082
0083
0084
0085
0086 writel(boot_inst, vectors_base + RESET_VECT);
0087
0088
0089
0090
0091
0092 writel(__pa_symbol(secondary_startup), vectors_base + SW_RESET_ADDR);
0093
0094 iounmap(vectors_base);
0095 unmap_scu:
0096 iounmap(scu_base);
0097 }
0098
0099 #ifdef CONFIG_HOTPLUG_CPU
0100 static void berlin_cpu_die(unsigned int cpu)
0101 {
0102 v7_exit_coherency_flush(louis);
0103 while (1)
0104 cpu_do_idle();
0105 }
0106
0107 static int berlin_cpu_kill(unsigned int cpu)
0108 {
0109 u32 val;
0110
0111 val = readl(cpu_ctrl + CPU_RESET_NON_SC);
0112 val &= ~BIT(cpu_logical_map(cpu));
0113 writel(val, cpu_ctrl + CPU_RESET_NON_SC);
0114
0115 return 1;
0116 }
0117 #endif
0118
0119 static const struct smp_operations berlin_smp_ops __initconst = {
0120 .smp_prepare_cpus = berlin_smp_prepare_cpus,
0121 .smp_boot_secondary = berlin_boot_secondary,
0122 #ifdef CONFIG_HOTPLUG_CPU
0123 .cpu_die = berlin_cpu_die,
0124 .cpu_kill = berlin_cpu_kill,
0125 #endif
0126 };
0127 CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops);