0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/delay.h>
0012 #include <linux/jiffies.h>
0013 #include <linux/io.h>
0014 #include <linux/smp.h>
0015 #include <asm/cacheflush.h>
0016 #include <asm/smp_scu.h>
0017 #include "spear.h"
0018 #include "generic.h"
0019
0020
0021 volatile int spear_pen_release = -1;
0022
0023
0024
0025
0026
0027
0028
0029
0030 static void spear_write_pen_release(int val)
0031 {
0032 spear_pen_release = val;
0033 smp_wmb();
0034 sync_cache_w(&spear_pen_release);
0035 }
0036
0037 static DEFINE_SPINLOCK(boot_lock);
0038
0039 static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
0040
0041 static void spear13xx_secondary_init(unsigned int cpu)
0042 {
0043
0044
0045
0046
0047 spear_write_pen_release(-1);
0048
0049
0050
0051
0052 spin_lock(&boot_lock);
0053 spin_unlock(&boot_lock);
0054 }
0055
0056 static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)
0057 {
0058 unsigned long timeout;
0059
0060
0061
0062
0063
0064 spin_lock(&boot_lock);
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 spear_write_pen_release(cpu);
0075
0076 timeout = jiffies + (1 * HZ);
0077 while (time_before(jiffies, timeout)) {
0078 smp_rmb();
0079 if (spear_pen_release == -1)
0080 break;
0081
0082 udelay(10);
0083 }
0084
0085
0086
0087
0088
0089 spin_unlock(&boot_lock);
0090
0091 return spear_pen_release != -1 ? -ENOSYS : 0;
0092 }
0093
0094
0095
0096
0097
0098 static void __init spear13xx_smp_init_cpus(void)
0099 {
0100 unsigned int i, ncores = scu_get_core_count(scu_base);
0101
0102 if (ncores > nr_cpu_ids) {
0103 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
0104 ncores, nr_cpu_ids);
0105 ncores = nr_cpu_ids;
0106 }
0107
0108 for (i = 0; i < ncores; i++)
0109 set_cpu_possible(i, true);
0110 }
0111
0112 static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus)
0113 {
0114
0115 scu_enable(scu_base);
0116
0117
0118
0119
0120
0121
0122 __raw_writel(__pa_symbol(spear13xx_secondary_startup), SYS_LOCATION);
0123 }
0124
0125 const struct smp_operations spear13xx_smp_ops __initconst = {
0126 .smp_init_cpus = spear13xx_smp_init_cpus,
0127 .smp_prepare_cpus = spear13xx_smp_prepare_cpus,
0128 .smp_secondary_init = spear13xx_secondary_init,
0129 .smp_boot_secondary = spear13xx_boot_secondary,
0130 #ifdef CONFIG_HOTPLUG_CPU
0131 .cpu_die = spear13xx_cpu_die,
0132 #endif
0133 };