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