diff options
Diffstat (limited to 'arch/mips/netlogic/xlp/wakeup.c')
-rw-r--r-- | arch/mips/netlogic/xlp/wakeup.c | 83 |
1 files changed, 55 insertions, 28 deletions
diff --git a/arch/mips/netlogic/xlp/wakeup.c b/arch/mips/netlogic/xlp/wakeup.c index 44d923ff3846..cb9010642ac3 100644 --- a/arch/mips/netlogic/xlp/wakeup.c +++ b/arch/mips/netlogic/xlp/wakeup.c | |||
@@ -51,45 +51,72 @@ | |||
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 | ||
54 | static void xlp_enable_secondary_cores(void) | 54 | static int xlp_wakeup_core(uint64_t sysbase, int core) |
55 | { | 55 | { |
56 | uint32_t core, value, coremask, syscoremask; | 56 | uint32_t coremask, value; |
57 | int count; | 57 | int count; |
58 | 58 | ||
59 | /* read cores in reset from SYS block */ | 59 | coremask = (1 << core); |
60 | syscoremask = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET); | ||
61 | 60 | ||
62 | /* update user specified */ | 61 | /* Enable CPU clock */ |
63 | nlm_coremask = nlm_coremask & (syscoremask | 1); | 62 | value = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL); |
63 | value &= ~coremask; | ||
64 | nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, value); | ||
64 | 65 | ||
65 | for (core = 1; core < 8; core++) { | 66 | /* Remove CPU Reset */ |
66 | coremask = 1 << core; | 67 | value = nlm_read_sys_reg(sysbase, SYS_CPU_RESET); |
67 | if ((nlm_coremask & coremask) == 0) | 68 | value &= ~coremask; |
68 | continue; | 69 | nlm_write_sys_reg(sysbase, SYS_CPU_RESET, value); |
69 | 70 | ||
70 | /* Enable CPU clock */ | 71 | /* Poll for CPU to mark itself coherent */ |
71 | value = nlm_read_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL); | 72 | count = 100000; |
72 | value &= ~coremask; | 73 | do { |
73 | nlm_write_sys_reg(nlm_sys_base, SYS_CORE_DFS_DIS_CTRL, value); | 74 | value = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE); |
75 | } while ((value & coremask) != 0 && --count > 0); | ||
74 | 76 | ||
75 | /* Remove CPU Reset */ | 77 | return count != 0; |
76 | value = nlm_read_sys_reg(nlm_sys_base, SYS_CPU_RESET); | 78 | } |
77 | value &= ~coremask; | 79 | |
78 | nlm_write_sys_reg(nlm_sys_base, SYS_CPU_RESET, value); | 80 | static void xlp_enable_secondary_cores(const cpumask_t *wakeup_mask) |
81 | { | ||
82 | struct nlm_soc_info *nodep; | ||
83 | uint64_t syspcibase; | ||
84 | uint32_t syscoremask; | ||
85 | int core, n, cpu; | ||
86 | |||
87 | for (n = 0; n < NLM_NR_NODES; n++) { | ||
88 | syspcibase = nlm_get_sys_pcibase(n); | ||
89 | if (nlm_read_reg(syspcibase, 0) == 0xffffffff) | ||
90 | break; | ||
91 | |||
92 | /* read cores in reset from SYS and account for boot cpu */ | ||
93 | nlm_node_init(n); | ||
94 | nodep = nlm_get_node(n); | ||
95 | syscoremask = nlm_read_sys_reg(nodep->sysbase, SYS_CPU_RESET); | ||
96 | if (n == 0) | ||
97 | syscoremask |= 1; | ||
98 | |||
99 | for (core = 0; core < NLM_CORES_PER_NODE; core++) { | ||
100 | /* see if the core exists */ | ||
101 | if ((syscoremask & (1 << core)) == 0) | ||
102 | continue; | ||
79 | 103 | ||
80 | /* Poll for CPU to mark itself coherent */ | 104 | /* see if at least the first thread is enabled */ |
81 | count = 100000; | 105 | cpu = (n * NLM_CORES_PER_NODE + core) |
82 | do { | 106 | * NLM_THREADS_PER_CORE; |
83 | value = nlm_read_sys_reg(nlm_sys_base, | 107 | if (!cpumask_test_cpu(cpu, wakeup_mask)) |
84 | SYS_CPU_NONCOHERENT_MODE); | 108 | continue; |
85 | } while ((value & coremask) != 0 && count-- > 0); | ||
86 | 109 | ||
87 | if (count == 0) | 110 | /* wake up the core */ |
88 | pr_err("Failed to enable core %d\n", 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); | ||
115 | } | ||
89 | } | 116 | } |
90 | } | 117 | } |
91 | 118 | ||
92 | void xlp_wakeup_secondary_cpus(void) | 119 | void xlp_wakeup_secondary_cpus() |
93 | { | 120 | { |
94 | /* | 121 | /* |
95 | * In case of u-boot, the secondaries are in reset | 122 | * In case of u-boot, the secondaries are in reset |
@@ -98,5 +125,5 @@ void xlp_wakeup_secondary_cpus(void) | |||
98 | xlp_boot_core0_siblings(); | 125 | xlp_boot_core0_siblings(); |
99 | 126 | ||
100 | /* now get other cores out of reset */ | 127 | /* now get other cores out of reset */ |
101 | xlp_enable_secondary_cores(); | 128 | xlp_enable_secondary_cores(&nlm_cpumask); |
102 | } | 129 | } |