aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/netlogic/xlp/wakeup.c
diff options
context:
space:
mode:
authorJayachandran C <jayachandranc@netlogicmicro.com>2011-11-15 19:21:29 -0500
committerRalf Baechle <ralf@linux-mips.org>2011-12-07 17:04:56 -0500
commit66d29985fab8207b1b2c03ac34a2c294c5b47a30 (patch)
treef73145e09c53606716266577eef5e14262129ed9 /arch/mips/netlogic/xlp/wakeup.c
parent8da24631e60438631112e6fdd198ef62416ff14a (diff)
MIPS: Netlogic: Merge some of XLR/XLP wakup code
Create a common NMI and reset handler in smpboot.S and use this for both XLR and XLP. In the earlier code, the woken up CPUs would busy wait until released, switch this to wakeup by NMI. The initial wakeup code or XLR and XLP are differ since they are started from different bootloaders (XLP from u-boot and XLR from netlogic bootloader). But in both platforms the woken up CPUs wait and are released by sending an NMI. Add support for starting XLR and XLP in 1/2/4 threads per core. Signed-off-by: Jayachandran C <jayachandranc@netlogicmicro.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2970/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/netlogic/xlp/wakeup.c')
-rw-r--r--arch/mips/netlogic/xlp/wakeup.c93
1 files changed, 23 insertions, 70 deletions
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index e081a778678e..44d923ff3846 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -51,18 +51,20 @@
51#include <asm/netlogic/xlp-hal/xlp.h> 51#include <asm/netlogic/xlp-hal/xlp.h>
52#include <asm/netlogic/xlp-hal/sys.h> 52#include <asm/netlogic/xlp-hal/sys.h>
53 53
54unsigned long secondary_entry; 54static void xlp_enable_secondary_cores(void)
55uint32_t nlm_coremask;
56unsigned int nlm_threads_per_core;
57unsigned int nlm_threadmode;
58
59static void nlm_enable_secondary_cores(unsigned int cores_bitmap)
60{ 55{
61 uint32_t core, value, coremask; 56 uint32_t core, value, coremask, syscoremask;
57 int count;
58
59 /* read cores in reset from SYS block */
60 syscoremask = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET);
61
62 /* update user specified */
63 nlm_coremask = nlm_coremask & (syscoremask | 1);
62 64
63 for (core = 1; core < 8; core++) { 65 for (core = 1; core < 8; core++) {
64 coremask = 1 << core; 66 coremask = 1 << core;
65 if ((cores_bitmap & coremask) == 0) 67 if ((nlm_coremask & coremask) == 0)
66 continue; 68 continue;
67 69
68 /* Enable CPU clock */ 70 /* Enable CPU clock */
@@ -76,74 +78,25 @@ static void nlm_enable_secondary_cores(unsigned int cores_bitmap)
76 nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value); 78 nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value);
77 79
78 /* Poll for CPU to mark itself coherent */ 80 /* Poll for CPU to mark itself coherent */
81 count = 100000;
79 do { 82 do {
80 value = nlm_read_sys_reg(nlm_sys_base, 83 value = nlm_read_sys_reg(nlm_sys_base,
81 SYS_CPU_NONCOHERENT_MODE); 84 SYS_CPU_NONCOHERENT_MODE);
82 } while ((value & coremask) != 0); 85 } while ((value & coremask) != 0 && count-- > 0);
83 }
84}
85
86
87static void nlm_parse_cpumask(u32 cpu_mask)
88{
89 uint32_t core0_thr_mask, core_thr_mask;
90 int i;
91 86
92 core0_thr_mask = cpu_mask & 0xf; 87 if (count == 0)
93 switch (core0_thr_mask) { 88 pr_err("Failed to enable core %d\n", core);
94 case 1:
95 nlm_threads_per_core = 1;
96 nlm_threadmode = 0;
97 break;
98 case 3:
99 nlm_threads_per_core = 2;
100 nlm_threadmode = 2;
101 break;
102 case 0xf:
103 nlm_threads_per_core = 4;
104 nlm_threadmode = 3;
105 break;
106 default:
107 goto unsupp;
108 } 89 }
109
110 /* Verify other cores CPU masks */
111 nlm_coremask = 1;
112 for (i = 1; i < 8; i++) {
113 core_thr_mask = (cpu_mask >> (i * 4)) & 0xf;
114 if (core_thr_mask) {
115 if (core_thr_mask != core0_thr_mask)
116 goto unsupp;
117 nlm_coremask |= 1 << i;
118 }
119 }
120 return;
121
122unsupp:
123 panic("Unsupported CPU mask %x\n", cpu_mask);
124} 90}
125 91
126int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask) 92void xlp_wakeup_secondary_cpus(void)
127{ 93{
128 unsigned long reset_vec; 94 /*
129 unsigned int *reset_data; 95 * In case of u-boot, the secondaries are in reset
130 96 * first wakeup core 0 threads
131 /* Update reset entry point with CPU init code */ 97 */
132 reset_vec = CKSEG1ADDR(RESET_VEC_PHYS); 98 xlp_boot_core0_siblings();
133 memcpy((void *)reset_vec, (void *)nlm_reset_entry, 99
134 (nlm_reset_entry_end - nlm_reset_entry)); 100 /* now get other cores out of reset */
135 101 xlp_enable_secondary_cores();
136 /* verify the mask and setup core config variables */
137 nlm_parse_cpumask(wakeup_mask);
138
139 /* Setup CPU init parameters */
140 reset_data = (unsigned int *)CKSEG1ADDR(RESET_DATA_PHYS);
141 reset_data[BOOT_THREAD_MODE] = nlm_threadmode;
142
143 /* first wakeup core 0 siblings */
144 nlm_boot_core0_siblings();
145
146 /* enable the reset of the cores */
147 nlm_enable_secondary_cores(nlm_coremask);
148 return 0;
149} 102}