1 /* SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020-21 Intel Corporation.
9 /* Trigger the doorbell interrupt on cp to change the PM sleep/active status */
10 #define ipc_cp_irq_sleep_control(ipc_pcie, data) \
11 ipc_doorbell_fire(ipc_pcie, IPC_DOORBELL_IRQ_SLEEP, data)
13 /* Trigger the doorbell interrupt on CP to do hpda update */
14 #define ipc_cp_irq_hpda_update(ipc_pcie, data) \
15 ipc_doorbell_fire(ipc_pcie, IPC_DOORBELL_IRQ_HPDA, 0xFF & (data))
18 * union ipc_pm_cond - Conditions for D3 and the sleep message to CP.
19 * @raw: raw/combined value for faster check
20 * @irq: IRQ towards CP
22 * @link: Device link state.
35 * enum ipc_mem_host_pm_state - Possible states of the HOST SLEEP finite state
37 * @IPC_MEM_HOST_PM_ACTIVE: Host is active
38 * @IPC_MEM_HOST_PM_ACTIVE_WAIT: Intermediate state before going to
40 * @IPC_MEM_HOST_PM_SLEEP_WAIT_IDLE: Intermediate state to wait for idle
41 * before going into sleep
42 * @IPC_MEM_HOST_PM_SLEEP_WAIT_D3: Intermediate state to wait for D3
43 * before going to sleep
44 * @IPC_MEM_HOST_PM_SLEEP: after this state the interface is not
45 * accessible host is in suspend to RAM
46 * @IPC_MEM_HOST_PM_SLEEP_WAIT_EXIT_SLEEP: Intermediate state before exiting
49 enum ipc_mem_host_pm_state {
50 IPC_MEM_HOST_PM_ACTIVE,
51 IPC_MEM_HOST_PM_ACTIVE_WAIT,
52 IPC_MEM_HOST_PM_SLEEP_WAIT_IDLE,
53 IPC_MEM_HOST_PM_SLEEP_WAIT_D3,
54 IPC_MEM_HOST_PM_SLEEP,
55 IPC_MEM_HOST_PM_SLEEP_WAIT_EXIT_SLEEP,
59 * enum ipc_mem_dev_pm_state - Possible states of the DEVICE SLEEP finite state
61 * @IPC_MEM_DEV_PM_ACTIVE: IPC_MEM_DEV_PM_ACTIVE is the initial
62 * power management state.
63 * IRQ(struct ipc_mem_device_info:
64 * device_sleep_notification)
65 * and DOORBELL-IRQ-HPDA(data) values.
66 * @IPC_MEM_DEV_PM_SLEEP: IPC_MEM_DEV_PM_SLEEP is PM state for
68 * @IPC_MEM_DEV_PM_WAKEUP: DOORBELL-IRQ-DEVICE_WAKE(data).
69 * @IPC_MEM_DEV_PM_HOST_SLEEP: DOORBELL-IRQ-HOST_SLEEP(data).
70 * @IPC_MEM_DEV_PM_ACTIVE_WAIT: Local intermediate states.
71 * @IPC_MEM_DEV_PM_FORCE_SLEEP: DOORBELL-IRQ-FORCE_SLEEP.
72 * @IPC_MEM_DEV_PM_FORCE_ACTIVE: DOORBELL-IRQ-FORCE_ACTIVE.
74 enum ipc_mem_dev_pm_state {
75 IPC_MEM_DEV_PM_ACTIVE,
77 IPC_MEM_DEV_PM_WAKEUP,
78 IPC_MEM_DEV_PM_HOST_SLEEP,
79 IPC_MEM_DEV_PM_ACTIVE_WAIT,
80 IPC_MEM_DEV_PM_FORCE_SLEEP = 7,
81 IPC_MEM_DEV_PM_FORCE_ACTIVE,
85 * struct iosm_pm - Power management instance
86 * @pcie: Pointer to iosm_pcie structure
87 * @dev: Pointer to device structure
88 * @host_pm_state: PM states for host
89 * @host_sleep_pend: Variable to indicate Host Sleep Pending
90 * @host_sleep_complete: Generic wait-for-completion used in
92 * @pm_cond: Conditions for power management
93 * @ap_state: Current power management state, the
94 * initial state is IPC_MEM_DEV_PM_ACTIVE eq. 0.
95 * @cp_state: PM State of CP
96 * @device_sleep_notification: last handled device_sleep_notfication
97 * @pending_hpda_update: is a HPDA update pending?
100 struct iosm_pcie *pcie;
102 enum ipc_mem_host_pm_state host_pm_state;
103 unsigned long host_sleep_pend;
104 struct completion host_sleep_complete;
105 union ipc_pm_cond pm_cond;
106 enum ipc_mem_dev_pm_state ap_state;
107 enum ipc_mem_dev_pm_state cp_state;
108 u32 device_sleep_notification;
109 u8 pending_hpda_update:1;
113 * enum ipc_pm_unit - Power management units.
114 * @IPC_PM_UNIT_IRQ: IRQ towards CP
115 * @IPC_PM_UNIT_HS: Host Sleep for converged protocol
116 * @IPC_PM_UNIT_LINK: Link state controlled by CP.
125 * ipc_pm_init - Allocate power management component
126 * @ipc_protocol: Pointer to iosm_protocol structure
128 void ipc_pm_init(struct iosm_protocol *ipc_protocol);
131 * ipc_pm_deinit - Free power management component, invalidating its pointer.
132 * @ipc_protocol: Pointer to iosm_protocol structure
134 void ipc_pm_deinit(struct iosm_protocol *ipc_protocol);
137 * ipc_pm_dev_slp_notification - Handle a sleep notification message from the
138 * device. This can be called from interrupt state
139 * This function handles Host Sleep requests too
140 * if the Host Sleep protocol is register based.
141 * @ipc_pm: Pointer to power management component
142 * @sleep_notification: Actual notification from device
144 * Returns: true if dev sleep state has to be checked, false otherwise.
146 bool ipc_pm_dev_slp_notification(struct iosm_pm *ipc_pm,
147 u32 sleep_notification);
150 * ipc_pm_set_s2idle_sleep - Set PM variables to sleep/active
151 * @ipc_pm: Pointer to power management component
152 * @sleep: true to enter sleep/false to exit sleep
154 void ipc_pm_set_s2idle_sleep(struct iosm_pm *ipc_pm, bool sleep);
157 * ipc_pm_prepare_host_sleep - Prepare the PM for sleep by entering
158 * IPC_MEM_HOST_PM_SLEEP_WAIT_D3 state.
159 * @ipc_pm: Pointer to power management component
161 * Returns: true on success, false if the host was not active.
163 bool ipc_pm_prepare_host_sleep(struct iosm_pm *ipc_pm);
166 * ipc_pm_prepare_host_active - Prepare the PM for wakeup by entering
167 * IPC_MEM_HOST_PM_ACTIVE_WAIT state.
168 * @ipc_pm: Pointer to power management component
170 * Returns: true on success, false if the host was not sleeping.
172 bool ipc_pm_prepare_host_active(struct iosm_pm *ipc_pm);
175 * ipc_pm_wait_for_device_active - Wait upto IPC_PM_ACTIVE_TIMEOUT_MS ms
176 * for the device to reach active state
177 * @ipc_pm: Pointer to power management component
179 * Returns: true if device is active, false on timeout
181 bool ipc_pm_wait_for_device_active(struct iosm_pm *ipc_pm);
184 * ipc_pm_signal_hpda_doorbell - Wake up the device if it is in low power mode
185 * and trigger a head pointer update interrupt.
186 * @ipc_pm: Pointer to power management component
187 * @identifier: specifies what component triggered hpda update irq
188 * @host_slp_check: if set to true then Host Sleep state machine check will
189 * be performed. If Host Sleep state machine allows HP
190 * update then only doorbell is triggered otherwise pending
191 * flag will be set. If set to false then Host Sleep check
192 * will not be performed. This is helpful for Host Sleep
193 * negotiation through message ring.
195 void ipc_pm_signal_hpda_doorbell(struct iosm_pm *ipc_pm, u32 identifier,
196 bool host_slp_check);
198 * ipc_pm_trigger - Update power manager and wake up the link if needed
199 * @ipc_pm: Pointer to power management component
200 * @unit: Power management units
201 * @active: Device link state
203 * Returns: true if link is unchanged or active, false otherwise
205 bool ipc_pm_trigger(struct iosm_pm *ipc_pm, enum ipc_pm_unit unit, bool active);