/* Timeout value in MS for the PM to wait for device to reach active state */ #define IPC_PM_ACTIVE_TIMEOUT_MS (500)
/* Note that here "active" has the value 1, as compared to the enums * ipc_mem_host_pm_state or ipc_mem_dev_pm_state, where "active" is 0
*/ #define IPC_PM_SLEEP (0) #define CONSUME_STATE (0) #define IPC_PM_ACTIVE (1)
/* Trigger the irq towards CP */
ipc_cp_irq_hpda_update(ipc_pm->pcie, identifier);
ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_IRQ, false);
}
/* Wake up the device if it is in low power mode. */ staticbool ipc_pm_link_activate(struct iosm_pm *ipc_pm)
{ if (ipc_pm->cp_state == IPC_MEM_DEV_PM_ACTIVE) returntrue;
if (ipc_pm->cp_state == IPC_MEM_DEV_PM_SLEEP) { if (ipc_pm->ap_state == IPC_MEM_DEV_PM_SLEEP) { /* Wake up the device. */
ipc_cp_irq_sleep_control(ipc_pm->pcie,
IPC_MEM_DEV_PM_WAKEUP);
ipc_pm->ap_state = IPC_MEM_DEV_PM_ACTIVE_WAIT;
goto not_active;
}
if (ipc_pm->ap_state == IPC_MEM_DEV_PM_ACTIVE_WAIT) goto not_active;
returntrue;
}
not_active: /* link is not ready */ returnfalse;
}
/* check the consume state !!! */ if (test_bit(CONSUME_STATE, &ipc_pm->host_sleep_pend))
complete(&ipc_pm->host_sleep_complete);
}
/* Check for pending HPDA update. * Pending HP update could be because of sending message was * put on hold due to Device sleep state or due to TD update * which could be because of Device Sleep and Host Sleep * states.
*/ if (ipc_pm->pending_hpda_update &&
ipc_pm->host_pm_state == IPC_MEM_HOST_PM_ACTIVE)
ipc_pm_signal_hpda_doorbell(ipc_pm, IPC_HP_PM_TRIGGER, true);
}
bool ipc_pm_trigger(struct iosm_pm *ipc_pm, enum ipc_pm_unit unit, bool active)
{ union ipc_pm_cond old_cond; union ipc_pm_cond new_cond; bool link_active;
/* Save the current D3 state. */
new_cond = ipc_pm->pm_cond;
old_cond = ipc_pm->pm_cond;
/* Calculate the power state only in the runtime phase. */ switch (unit) { case IPC_PM_UNIT_IRQ: /* CP irq */
new_cond.irq = active; break;
case IPC_PM_UNIT_LINK: /* Device link state. */
new_cond.link = active; break;
bool ipc_pm_prepare_host_sleep(struct iosm_pm *ipc_pm)
{ /* suspend not allowed if host_pm_state is not IPC_MEM_HOST_PM_ACTIVE */ if (ipc_pm->host_pm_state != IPC_MEM_HOST_PM_ACTIVE) {
dev_err(ipc_pm->dev, "host_pm_state=%d\tExpected to be: %d",
ipc_pm->host_pm_state, IPC_MEM_HOST_PM_ACTIVE); returnfalse;
}
case IPC_MEM_DEV_PM_SLEEP: switch (cp_pm_req) { case IPC_MEM_DEV_PM_ACTIVE: /* Inform the PM that the device link is active. */
ipc_pm_trigger(ipc_pm, IPC_PM_UNIT_LINK, true); break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.