1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020-21 Intel Corporation.
6 #include "iosm_ipc_protocol.h"
8 /* Timeout value in MS for the PM to wait for device to reach active state */
9 #define IPC_PM_ACTIVE_TIMEOUT_MS (500)
11 /* Note that here "active" has the value 1, as compared to the enums
12 * ipc_mem_host_pm_state or ipc_mem_dev_pm_state, where "active" is 0
14 #define IPC_PM_SLEEP (0)
15 #define CONSUME_STATE (0)
16 #define IPC_PM_ACTIVE (1)
18 void ipc_pm_signal_hpda_doorbell(struct iosm_pm *ipc_pm, u32 identifier,
21 if (host_slp_check && ipc_pm->host_pm_state != IPC_MEM_HOST_PM_ACTIVE &&
22 ipc_pm->host_pm_state != IPC_MEM_HOST_PM_ACTIVE_WAIT) {
23 ipc_pm->pending_hpda_update = true;
25 "Pend HPDA update set. Host PM_State: %d identifier:%d",
26 ipc_pm->host_pm_state, identifier);
30 if (!ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_IRQ, true)) {
31 ipc_pm->pending_hpda_update = true;
32 dev_dbg(ipc_pm->dev, "Pending HPDA update set. identifier:%d",
36 ipc_pm->pending_hpda_update = false;
38 /* Trigger the irq towards CP */
39 ipc_cp_irq_hpda_update(ipc_pm->pcie, identifier);
41 ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_IRQ, false);
44 /* Wake up the device if it is in low power mode. */
45 static bool ipc_pm_link_activate(struct iosm_pm *ipc_pm)
47 if (ipc_pm->cp_state == IPC_MEM_DEV_PM_ACTIVE)
50 if (ipc_pm->cp_state == IPC_MEM_DEV_PM_SLEEP) {
51 if (ipc_pm->ap_state == IPC_MEM_DEV_PM_SLEEP) {
52 /* Wake up the device. */
53 ipc_cp_irq_sleep_control(ipc_pm->pcie,
54 IPC_MEM_DEV_PM_WAKEUP);
55 ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE_WAIT;
60 if (ipc_pm->ap_state == IPC_MEM_DEV_PM_ACTIVE_WAIT)
67 /* link is not ready */
71 bool ipc_pm_wait_for_device_active(struct iosm_pm *ipc_pm)
75 if (ipc_pm->ap_state != IPC_MEM_DEV_PM_ACTIVE) {
76 /* Complete all memory stores before setting bit */
77 smp_mb__before_atomic();
79 /* Wait for IPC_PM_ACTIVE_TIMEOUT_MS for Device sleep state
80 * machine to enter ACTIVE state.
82 set_bit(0, &ipc_pm->host_sleep_pend);
84 /* Complete all memory stores after setting bit */
85 smp_mb__after_atomic();
87 if (!wait_for_completion_interruptible_timeout
88 (&ipc_pm->host_sleep_complete,
89 msecs_to_jiffies(IPC_PM_ACTIVE_TIMEOUT_MS))) {
91 "PM timeout. Expected State:%d. Actual: %d",
92 IPC_MEM_DEV_PM_ACTIVE, ipc_pm->ap_state);
99 /* Complete all memory stores before clearing bit */
100 smp_mb__before_atomic();
102 /* Reset the atomic variable in any case as device sleep
103 * state machine change is no longer of interest.
105 clear_bit(0, &ipc_pm->host_sleep_pend);
107 /* Complete all memory stores after clearing bit */
108 smp_mb__after_atomic();
113 static void ipc_pm_on_link_sleep(struct iosm_pm *ipc_pm)
115 /* pending sleep ack and all conditions are cleared
116 * -> signal SLEEP__ACK to CP
118 ipc_pm->cp_state = IPC_MEM_DEV_PM_SLEEP;
119 ipc_pm->ap_state = IPC_MEM_DEV_PM_SLEEP;
121 ipc_cp_irq_sleep_control(ipc_pm->pcie, IPC_MEM_DEV_PM_SLEEP);
124 static void ipc_pm_on_link_wake(struct iosm_pm *ipc_pm, bool ack)
126 ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE;
129 ipc_pm->cp_state = IPC_MEM_DEV_PM_ACTIVE;
131 ipc_cp_irq_sleep_control(ipc_pm->pcie, IPC_MEM_DEV_PM_ACTIVE);
133 /* check the consume state !!! */
134 if (test_bit(CONSUME_STATE, &ipc_pm->host_sleep_pend))
135 complete(&ipc_pm->host_sleep_complete);
138 /* Check for pending HPDA update.
139 * Pending HP update could be because of sending message was
140 * put on hold due to Device sleep state or due to TD update
141 * which could be because of Device Sleep and Host Sleep
144 if (ipc_pm->pending_hpda_update &&
145 ipc_pm->host_pm_state == IPC_MEM_HOST_PM_ACTIVE)
146 ipc_pm_signal_hpda_doorbell(ipc_pm, IPC_HP_PM_TRIGGER, true);
149 bool ipc_pm_trigger(struct iosm_pm *ipc_pm, enum ipc_pm_unit unit, bool active)
151 union ipc_pm_cond old_cond;
152 union ipc_pm_cond new_cond;
155 /* Save the current D3 state. */
156 new_cond = ipc_pm->pm_cond;
157 old_cond = ipc_pm->pm_cond;
159 /* Calculate the power state only in the runtime phase. */
161 case IPC_PM_UNIT_IRQ: /* CP irq */
162 new_cond.irq = active;
165 case IPC_PM_UNIT_LINK: /* Device link state. */
166 new_cond.link = active;
169 case IPC_PM_UNIT_HS: /* Host sleep trigger requires Link. */
170 new_cond.hs = active;
177 /* Something changed ? */
178 if (old_cond.raw == new_cond.raw) {
179 /* Stay in the current PM state. */
180 link_active = old_cond.link == IPC_PM_ACTIVE;
184 ipc_pm->pm_cond = new_cond;
187 ipc_pm_on_link_wake(ipc_pm, unit == IPC_PM_UNIT_LINK);
188 else if (unit == IPC_PM_UNIT_LINK)
189 ipc_pm_on_link_sleep(ipc_pm);
191 if (old_cond.link == IPC_PM_SLEEP && new_cond.raw) {
192 link_active = ipc_pm_link_activate(ipc_pm);
196 link_active = old_cond.link == IPC_PM_ACTIVE;
202 bool ipc_pm_prepare_host_sleep(struct iosm_pm *ipc_pm)
204 /* suspend not allowed if host_pm_state is not IPC_MEM_HOST_PM_ACTIVE */
205 if (ipc_pm->host_pm_state != IPC_MEM_HOST_PM_ACTIVE) {
206 dev_err(ipc_pm->dev, "host_pm_state=%d\tExpected to be: %d",
207 ipc_pm->host_pm_state, IPC_MEM_HOST_PM_ACTIVE);
211 ipc_pm->host_pm_state = IPC_MEM_HOST_PM_SLEEP_WAIT_D3;
216 bool ipc_pm_prepare_host_active(struct iosm_pm *ipc_pm)
218 if (ipc_pm->host_pm_state != IPC_MEM_HOST_PM_SLEEP) {
219 dev_err(ipc_pm->dev, "host_pm_state=%d\tExpected to be: %d",
220 ipc_pm->host_pm_state, IPC_MEM_HOST_PM_SLEEP);
224 /* Sending Sleep Exit message to CP. Update the state */
225 ipc_pm->host_pm_state = IPC_MEM_HOST_PM_ACTIVE_WAIT;
230 void ipc_pm_set_s2idle_sleep(struct iosm_pm *ipc_pm, bool sleep)
233 ipc_pm->ap_state = IPC_MEM_DEV_PM_SLEEP;
234 ipc_pm->cp_state = IPC_MEM_DEV_PM_SLEEP;
235 ipc_pm->device_sleep_notification = IPC_MEM_DEV_PM_SLEEP;
237 ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE;
238 ipc_pm->cp_state = IPC_MEM_DEV_PM_ACTIVE;
239 ipc_pm->device_sleep_notification = IPC_MEM_DEV_PM_ACTIVE;
240 ipc_pm->pm_cond.link = IPC_PM_ACTIVE;
244 bool ipc_pm_dev_slp_notification(struct iosm_pm *ipc_pm, u32 cp_pm_req)
246 if (cp_pm_req == ipc_pm->device_sleep_notification)
249 ipc_pm->device_sleep_notification = cp_pm_req;
251 /* Evaluate the PM request. */
252 switch (ipc_pm->cp_state) {
253 case IPC_MEM_DEV_PM_ACTIVE:
255 case IPC_MEM_DEV_PM_ACTIVE:
258 case IPC_MEM_DEV_PM_SLEEP:
259 /* Inform the PM that the device link can go down. */
260 ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_LINK, false);
265 "loc-pm=%d active: confused req-pm=%d",
266 ipc_pm->cp_state, cp_pm_req);
271 case IPC_MEM_DEV_PM_SLEEP:
273 case IPC_MEM_DEV_PM_ACTIVE:
274 /* Inform the PM that the device link is active. */
275 ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_LINK, true);
278 case IPC_MEM_DEV_PM_SLEEP:
283 "loc-pm=%d sleep: confused req-pm=%d",
284 ipc_pm->cp_state, cp_pm_req);
290 dev_err(ipc_pm->dev, "confused loc-pm=%d, req-pm=%d",
291 ipc_pm->cp_state, cp_pm_req);
298 void ipc_pm_init(struct iosm_protocol *ipc_protocol)
300 struct iosm_imem *ipc_imem = ipc_protocol->imem;
301 struct iosm_pm *ipc_pm = &ipc_protocol->pm;
303 ipc_pm->pcie = ipc_imem->pcie;
304 ipc_pm->dev = ipc_imem->dev;
306 ipc_pm->pm_cond.irq = IPC_PM_SLEEP;
307 ipc_pm->pm_cond.hs = IPC_PM_SLEEP;
308 ipc_pm->pm_cond.link = IPC_PM_ACTIVE;
310 ipc_pm->cp_state = IPC_MEM_DEV_PM_ACTIVE;
311 ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE;
312 ipc_pm->host_pm_state = IPC_MEM_HOST_PM_ACTIVE;
314 /* Create generic wait-for-completion handler for Host Sleep
315 * and device sleep coordination.
317 init_completion(&ipc_pm->host_sleep_complete);
319 /* Complete all memory stores before clearing bit */
320 smp_mb__before_atomic();
322 clear_bit(0, &ipc_pm->host_sleep_pend);
324 /* Complete all memory stores after clearing bit */
325 smp_mb__after_atomic();
328 void ipc_pm_deinit(struct iosm_protocol *proto)
330 struct iosm_pm *ipc_pm = &proto->pm;
332 complete(&ipc_pm->host_sleep_complete);