aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/netlogic/xlp/wakeup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/netlogic/xlp/wakeup.c')
-rw-r--r--arch/mips/netlogic/xlp/wakeup.c92
1 files changed, 70 insertions, 22 deletions
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c
index 682d5638dc01..9a92617a2af5 100644
--- a/arch/mips/netlogic/xlp/wakeup.c
+++ b/arch/mips/netlogic/xlp/wakeup.c
@@ -32,7 +32,6 @@
32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */ 33 */
34 34
35#include <linux/init.h>
36#include <linux/kernel.h> 35#include <linux/kernel.h>
37#include <linux/threads.h> 36#include <linux/threads.h>
38 37
@@ -47,14 +46,14 @@
47#include <asm/netlogic/mips-extns.h> 46#include <asm/netlogic/mips-extns.h>
48 47
49#include <asm/netlogic/xlp-hal/iomap.h> 48#include <asm/netlogic/xlp-hal/iomap.h>
50#include <asm/netlogic/xlp-hal/pic.h>
51#include <asm/netlogic/xlp-hal/xlp.h> 49#include <asm/netlogic/xlp-hal/xlp.h>
50#include <asm/netlogic/xlp-hal/pic.h>
52#include <asm/netlogic/xlp-hal/sys.h> 51#include <asm/netlogic/xlp-hal/sys.h>
53 52
54static int xlp_wakeup_core(uint64_t sysbase, int node, int core) 53static int xlp_wakeup_core(uint64_t sysbase, int node, int core)
55{ 54{
56 uint32_t coremask, value; 55 uint32_t coremask, value;
57 int count; 56 int count, resetreg;
58 57
59 coremask = (1 << core); 58 coremask = (1 << core);
60 59
@@ -65,12 +64,24 @@ static int xlp_wakeup_core(uint64_t sysbase, int node, int core)
65 nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value); 64 nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value);
66 } 65 }
67 66
67 /* On 9XX, mark coherent first */
68 if (cpu_is_xlp9xx()) {
69 value = nlm_read_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE);
70 value &= ~coremask;
71 nlm_write_sys_reg(sysbase, SYS_9XX_CPU_NONCOHERENT_MODE, value);
72 }
73
68 /* Remove CPU Reset */ 74 /* Remove CPU Reset */
69 value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET); 75 resetreg = cpu_is_xlp9xx() ? SYS_9XX_CPU_RESET : SYS_CPU_RESET;
76 value = nlm_read_sys_reg(sysbase, resetreg);
70 value &= ~coremask; 77 value &= ~coremask;
71 nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value); 78 nlm_write_sys_reg(sysbase, resetreg, value);
79
80 /* We are done on 9XX */
81 if (cpu_is_xlp9xx())
82 return 1;
72 83
73 /* Poll for CPU to mark itself coherent */ 84 /* Poll for CPU to mark itself coherent on other type of XLP */
74 count = 100000; 85 count = 100000;
75 do { 86 do {
76 value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE); 87 value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
@@ -84,7 +95,7 @@ static int wait_for_cpus(int cpu, int bootcpu)
84 volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY); 95 volatile uint32_t *cpu_ready = nlm_get_boot_data(BOOT_CPU_READY);
85 int i, count, notready; 96 int i, count, notready;
86 97
87 count = 0x20000000; 98 count = 0x800000;
88 do { 99 do {
89 notready = nlm_threads_per_core; 100 notready = nlm_threads_per_core;
90 for (i = 0; i < nlm_threads_per_core; i++) 101 for (i = 0; i < nlm_threads_per_core; i++)
@@ -98,27 +109,62 @@ static int wait_for_cpus(int cpu, int bootcpu)
98static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) 109static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
99{ 110{
100 struct nlm_soc_info *nodep; 111 struct nlm_soc_info *nodep;
101 uint64_t syspcibase; 112 uint64_t syspcibase, fusebase;
102 uint32_t syscoremask; 113 uint32_t syscoremask, mask, fusemask;
103 int core, n, cpu; 114 int core, n, cpu;
104 115
105 for (n = 0; n < NLM_NR_NODES; n++) { 116 for (n = 0; n < NLM_NR_NODES; n++) {
106 syspcibase = nlm_get_sys_pcibase(n); 117 if (n != 0) {
107 if (nlm_read_reg(syspcibase, 0) == 0xffffffff) 118 /* check if node exists and is online */
108 break; 119 if (cpu_is_xlp9xx()) {
120 int b = xlp9xx_get_socbus(n);
121 pr_info("Node %d SoC PCI bus %d.\n", n, b);
122 if (b == 0)
123 break;
124 } else {
125 syspcibase = nlm_get_sys_pcibase(n);
126 if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
127 break;
128 }
129 nlm_node_init(n);
130 }
109 131
110 /* read cores in reset from SYS */ 132 /* read cores in reset from SYS */
111 if (n != 0)
112 nlm_node_init(n);
113 nodep = nlm_get_node(n); 133 nodep = nlm_get_node(n);
114 syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET); 134
135 if (cpu_is_xlp9xx()) {
136 fusebase = nlm_get_fuse_regbase(n);
137 fusemask = nlm_read_reg(fusebase, FUSE_9XX_DEVCFG6);
138 mask = 0xfffff;
139 } else {
140 fusemask = nlm_read_sys_reg(nodep->sysbase,
141 SYS_EFUSE_DEVICE_CFG_STATUS0);
142 switch (read_c0_prid() & 0xff00) {
143 case PRID_IMP_NETLOGIC_XLP3XX:
144 mask = 0xf;
145 break;
146 case PRID_IMP_NETLOGIC_XLP2XX:
147 mask = 0x3;
148 break;
149 case PRID_IMP_NETLOGIC_XLP8XX:
150 default:
151 mask = 0xff;
152 break;
153 }
154 }
155
156 /*
157 * Fused out cores are set in the fusemask, and the remaining
158 * cores are renumbered to range 0 .. nactive-1
159 */
160 syscoremask = (1 << hweight32(~fusemask & mask)) - 1;
161
115 /* The boot cpu */ 162 /* The boot cpu */
116 if (n == 0) { 163 if (n == 0)
117 syscoremask |= 1;
118 nodep->coremask = 1; 164 nodep->coremask = 1;
119 }
120 165
121 for (core = 0; core < NLM_CORES_PER_NODE; core++) { 166 pr_info("Node %d - SYS/FUSE coremask %x\n", n, syscoremask);
167 for (core = 0; core < nlm_cores_per_node(); core++) {
122 /* we will be on node 0 core 0 */ 168 /* we will be on node 0 core 0 */
123 if (n == 0 && core == 0) 169 if (n == 0 && core == 0)
124 continue; 170 continue;
@@ -128,7 +174,7 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
128 continue; 174 continue;
129 175
130 /* see if at least the first hw thread is enabled */ 176 /* see if at least the first hw thread is enabled */
131 cpu = (n * NLM_CORES_PER_NODE + core) 177 cpu = (n * nlm_cores_per_node() + core)
132 * NLM_THREADS_PER_CORE; 178 * NLM_THREADS_PER_CORE;
133 if (!cpumask_test_cpu(cpu, wakeup_mask)) 179 if (!cpumask_test_cpu(cpu, wakeup_mask))
134 continue; 180 continue;
@@ -141,7 +187,8 @@ static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask)
141 nodep->coremask |= 1u << core; 187 nodep->coremask |= 1u << core;
142 188
143 /* spin until the hw threads sets their ready */ 189 /* spin until the hw threads sets their ready */
144 wait_for_cpus(cpu, 0); 190 if (!wait_for_cpus(cpu, 0))
191 pr_err("Node %d : timeout core %d\n", n, core);
145 } 192 }
146 } 193 }
147} 194}
@@ -153,7 +200,8 @@ void xlp_wakeup_secondary_cpus()
153 * first wakeup core 0 threads 200 * first wakeup core 0 threads
154 */ 201 */
155 xlp_boot_core0_siblings(); 202 xlp_boot_core0_siblings();
156 wait_for_cpus(0, 0); 203 if (!wait_for_cpus(0, 0))
204 pr_err("Node 0 : timeout core 0\n");
157 205
158 /* now get other cores out of reset */ 206 /* now get other cores out of reset */
159 xlp_enable_secondary_cores(&nlm_cpumask); 207 xlp_enable_secondary_cores(&nlm_cpumask);