.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * OMAP4+ CPU idle Routines |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2011-2013 Texas Instruments, Inc. |
---|
5 | 6 | * Santosh Shilimkar <santosh.shilimkar@ti.com> |
---|
6 | 7 | * Rajendra Nayak <rnayak@ti.com> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License version 2 as |
---|
10 | | - * published by the Free Software Foundation. |
---|
11 | 8 | */ |
---|
12 | 9 | |
---|
13 | 10 | #include <linux/sched.h> |
---|
.. | .. |
---|
125 | 122 | { |
---|
126 | 123 | struct idle_statedata *cx = state_ptr + index; |
---|
127 | 124 | u32 mpuss_can_lose_context = 0; |
---|
| 125 | + int error; |
---|
128 | 126 | |
---|
129 | 127 | /* |
---|
130 | 128 | * CPU0 has to wait and stay ON until CPU1 is OFF state. |
---|
.. | .. |
---|
153 | 151 | (cx->mpu_logic_state == PWRDM_POWER_OFF); |
---|
154 | 152 | |
---|
155 | 153 | /* Enter broadcast mode for periodic timers */ |
---|
156 | | - tick_broadcast_enable(); |
---|
| 154 | + RCU_NONIDLE(tick_broadcast_enable()); |
---|
157 | 155 | |
---|
158 | 156 | /* Enter broadcast mode for one-shot timers */ |
---|
159 | | - tick_broadcast_enter(); |
---|
| 157 | + RCU_NONIDLE(tick_broadcast_enter()); |
---|
160 | 158 | |
---|
161 | 159 | /* |
---|
162 | 160 | * Call idle CPU PM enter notifier chain so that |
---|
163 | 161 | * VFP and per CPU interrupt context is saved. |
---|
164 | 162 | */ |
---|
165 | | - cpu_pm_enter(); |
---|
| 163 | + error = cpu_pm_enter(); |
---|
| 164 | + if (error) |
---|
| 165 | + goto cpu_pm_out; |
---|
166 | 166 | |
---|
167 | 167 | if (dev->cpu == 0) { |
---|
168 | 168 | pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); |
---|
169 | | - omap_set_pwrdm_state(mpu_pd, cx->mpu_state); |
---|
| 169 | + RCU_NONIDLE(omap_set_pwrdm_state(mpu_pd, cx->mpu_state)); |
---|
170 | 170 | |
---|
171 | 171 | /* |
---|
172 | 172 | * Call idle CPU cluster PM enter notifier chain |
---|
173 | 173 | * to save GIC and wakeupgen context. |
---|
174 | 174 | */ |
---|
175 | | - if (mpuss_can_lose_context) |
---|
176 | | - cpu_cluster_pm_enter(); |
---|
| 175 | + if (mpuss_can_lose_context) { |
---|
| 176 | + error = cpu_cluster_pm_enter(); |
---|
| 177 | + if (error) { |
---|
| 178 | + index = 0; |
---|
| 179 | + cx = state_ptr + index; |
---|
| 180 | + pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state); |
---|
| 181 | + RCU_NONIDLE(omap_set_pwrdm_state(mpu_pd, cx->mpu_state)); |
---|
| 182 | + mpuss_can_lose_context = 0; |
---|
| 183 | + } |
---|
| 184 | + } |
---|
177 | 185 | } |
---|
178 | 186 | |
---|
179 | 187 | omap4_enter_lowpower(dev->cpu, cx->cpu_state); |
---|
.. | .. |
---|
186 | 194 | mpuss_can_lose_context) |
---|
187 | 195 | gic_dist_disable(); |
---|
188 | 196 | |
---|
189 | | - clkdm_deny_idle(cpu_clkdm[1]); |
---|
190 | | - omap_set_pwrdm_state(cpu_pd[1], PWRDM_POWER_ON); |
---|
191 | | - clkdm_allow_idle(cpu_clkdm[1]); |
---|
| 197 | + RCU_NONIDLE(clkdm_deny_idle(cpu_clkdm[1])); |
---|
| 198 | + RCU_NONIDLE(omap_set_pwrdm_state(cpu_pd[1], PWRDM_POWER_ON)); |
---|
| 199 | + RCU_NONIDLE(clkdm_allow_idle(cpu_clkdm[1])); |
---|
192 | 200 | |
---|
193 | 201 | if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD) && |
---|
194 | 202 | mpuss_can_lose_context) { |
---|
.. | .. |
---|
201 | 209 | } |
---|
202 | 210 | |
---|
203 | 211 | /* |
---|
204 | | - * Call idle CPU PM exit notifier chain to restore |
---|
205 | | - * VFP and per CPU IRQ context. |
---|
206 | | - */ |
---|
207 | | - cpu_pm_exit(); |
---|
208 | | - |
---|
209 | | - /* |
---|
210 | 212 | * Call idle CPU cluster PM exit notifier chain |
---|
211 | 213 | * to restore GIC and wakeupgen context. |
---|
212 | 214 | */ |
---|
213 | 215 | if (dev->cpu == 0 && mpuss_can_lose_context) |
---|
214 | 216 | cpu_cluster_pm_exit(); |
---|
215 | 217 | |
---|
216 | | - tick_broadcast_exit(); |
---|
| 218 | + /* |
---|
| 219 | + * Call idle CPU PM exit notifier chain to restore |
---|
| 220 | + * VFP and per CPU IRQ context. |
---|
| 221 | + */ |
---|
| 222 | + cpu_pm_exit(); |
---|
| 223 | + |
---|
| 224 | +cpu_pm_out: |
---|
| 225 | + RCU_NONIDLE(tick_broadcast_exit()); |
---|
217 | 226 | |
---|
218 | 227 | fail: |
---|
219 | 228 | cpuidle_coupled_parallel_barrier(dev, &abort_barrier); |
---|