Commit cba3b643039b9d38284a5fd5143558622b9b64d9

Authored by Jayachandran C
Committed by John Crispin
1 parent 37a7059bc4

MIPS: Netlogic: Fix for quad-XLP boot

On multi-chip boards, the first core on slave SoCs may take much
more time to wakeup. Add code to wait for the core to come up before
proceeding with the rest of the boot up.

Update xlp_wakeup_core to also skip the boot node and the boot CPU
initialization which is already complete.

Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Patchwork: http://patchwork.linux-mips.org/patch/4783/
Signed-off-by: John Crispin <blogic@openwrt.org>

Showing 1 changed file with 25 additions and 10 deletions Side-by-side Diff

arch/mips/netlogic/xlp/wakeup.c
... ... @@ -51,7 +51,7 @@
51 51 #include <asm/netlogic/xlp-hal/xlp.h>
52 52 #include <asm/netlogic/xlp-hal/sys.h>
53 53  
54   -static int xlp_wakeup_core(uint64_t sysbase, int core)
  54 +static int xlp_wakeup_core(uint64_t sysbase, int node, int core)
55 55 {
56 56 uint32_t coremask, value;
57 57 int count;
58 58  
59 59  
60 60  
61 61  
62 62  
63 63  
... ... @@ -82,36 +82,51 @@
82 82 struct nlm_soc_info *nodep;
83 83 uint64_t syspcibase;
84 84 uint32_t syscoremask;
85   - int core, n, cpu;
  85 + int core, n, cpu, count, val;
86 86  
87 87 for (n = 0; n < NLM_NR_NODES; n++) {
88 88 syspcibase = nlm_get_sys_pcibase(n);
89 89 if (nlm_read_reg(syspcibase, 0) == 0xffffffff)
90 90 break;
91 91  
92   - /* read cores in reset from SYS and account for boot cpu */
93   - nlm_node_init(n);
  92 + /* read cores in reset from SYS */
  93 + if (n != 0)
  94 + nlm_node_init(n);
94 95 nodep = nlm_get_node(n);
95 96 syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET);
96   - if (n == 0)
  97 + /* The boot cpu */
  98 + if (n == 0) {
97 99 syscoremask |= 1;
  100 + nodep->coremask = 1;
  101 + }
98 102  
99 103 for (core = 0; core < NLM_CORES_PER_NODE; core++) {
  104 + /* we will be on node 0 core 0 */
  105 + if (n == 0 && core == 0)
  106 + continue;
  107 +
100 108 /* see if the core exists */
101 109 if ((syscoremask & (1 << core)) == 0)
102 110 continue;
103 111  
104   - /* see if at least the first thread is enabled */
  112 + /* see if at least the first hw thread is enabled */
105 113 cpu = (n * NLM_CORES_PER_NODE + core)
106 114 * NLM_THREADS_PER_CORE;
107 115 if (!cpumask_test_cpu(cpu, wakeup_mask))
108 116 continue;
109 117  
110 118 /* wake up the core */
111   - if (xlp_wakeup_core(nodep->sysbase, core))
112   - nodep->coremask |= 1u << core;
113   - else
114   - pr_err("Failed to enable core %d\n", core);
  119 + if (!xlp_wakeup_core(nodep->sysbase, n, core))
  120 + continue;
  121 +
  122 + /* core is up */
  123 + nodep->coremask |= 1u << core;
  124 +
  125 + /* spin until the first hw thread sets its ready */
  126 + count = 0x20000000;
  127 + do {
  128 + val = *(volatile int *)&nlm_cpu_ready[cpu];
  129 + } while (val == 0 && --count > 0);
115 130 }
116 131 }
117 132 }