/* SPDX-License-Identifier: GPL-2.0-only
*
* Copyright ( C ) 2020 - 21 Intel Corporation .
*/
#ifndef IOSM_IPC_PM_H
#define IOSM_IPC_PM_H
/* Trigger the doorbell interrupt on cp to change the PM sleep/active status */
#define ipc_cp_irq_sleep_control(ipc_pcie, data) \
ipc_doorbell_fire(ipc_pcie, IPC_DOORBELL_IRQ_SLEEP, data)
/* Trigger the doorbell interrupt on CP to do hpda update */
#define ipc_cp_irq_hpda_update(ipc_pcie, data) \
ipc_doorbell_fire(ipc_pcie, IPC_DOORBELL_IRQ_HPDA, 0 xFF & (data))
/**
* union ipc_pm_cond - Conditions for D3 and the sleep message to CP .
* @ raw : raw / combined value for faster check
* @ irq : IRQ towards CP
* @ hs : Host Sleep
* @ link : Device link state .
*/
union ipc_pm_cond {
unsigned int raw;
struct {
unsigned int irq:1 ,
hs:1 ,
link:1 ;
};
};
/**
* enum ipc_mem_host_pm_state - Possible states of the HOST SLEEP finite state
* machine .
* @ IPC_MEM_HOST_PM_ACTIVE : Host is active
* @ IPC_MEM_HOST_PM_ACTIVE_WAIT : Intermediate state before going to
* active
* @ IPC_MEM_HOST_PM_SLEEP_WAIT_IDLE : Intermediate state to wait for idle
* before going into sleep
* @ IPC_MEM_HOST_PM_SLEEP_WAIT_D3 : Intermediate state to wait for D3
* before going to sleep
* @ IPC_MEM_HOST_PM_SLEEP : after this state the interface is not
* accessible host is in suspend to RAM
* @ IPC_MEM_HOST_PM_SLEEP_WAIT_EXIT_SLEEP : Intermediate state before exiting
* sleep
*/
enum ipc_mem_host_pm_state {
IPC_MEM_HOST_PM_ACTIVE,
IPC_MEM_HOST_PM_ACTIVE_WAIT,
IPC_MEM_HOST_PM_SLEEP_WAIT_IDLE,
IPC_MEM_HOST_PM_SLEEP_WAIT_D3,
IPC_MEM_HOST_PM_SLEEP,
IPC_MEM_HOST_PM_SLEEP_WAIT_EXIT_SLEEP,
};
/**
* enum ipc_mem_dev_pm_state - Possible states of the DEVICE SLEEP finite state
* machine .
* @ IPC_MEM_DEV_PM_ACTIVE : IPC_MEM_DEV_PM_ACTIVE is the initial
* power management state .
* IRQ ( struct ipc_mem_device_info :
* device_sleep_notification )
* and DOORBELL - IRQ - HPDA ( data ) values .
* @ IPC_MEM_DEV_PM_SLEEP : IPC_MEM_DEV_PM_SLEEP is PM state for
* sleep .
* @ IPC_MEM_DEV_PM_WAKEUP : DOORBELL - IRQ - DEVICE_WAKE ( data ) .
* @ IPC_MEM_DEV_PM_HOST_SLEEP : DOORBELL - IRQ - HOST_SLEEP ( data ) .
* @ IPC_MEM_DEV_PM_ACTIVE_WAIT : Local intermediate states .
* @ IPC_MEM_DEV_PM_FORCE_SLEEP : DOORBELL - IRQ - FORCE_SLEEP .
* @ IPC_MEM_DEV_PM_FORCE_ACTIVE : DOORBELL - IRQ - FORCE_ACTIVE .
*/
enum ipc_mem_dev_pm_state {
IPC_MEM_DEV_PM_ACTIVE,
IPC_MEM_DEV_PM_SLEEP,
IPC_MEM_DEV_PM_WAKEUP,
IPC_MEM_DEV_PM_HOST_SLEEP,
IPC_MEM_DEV_PM_ACTIVE_WAIT,
IPC_MEM_DEV_PM_FORCE_SLEEP = 7 ,
IPC_MEM_DEV_PM_FORCE_ACTIVE,
};
/**
* struct iosm_pm - Power management instance
* @ pcie : Pointer to iosm_pcie structure
* @ dev : Pointer to device structure
* @ host_pm_state : PM states for host
* @ host_sleep_pend : Variable to indicate Host Sleep Pending
* @ host_sleep_complete : Generic wait - for - completion used in
* case of Host Sleep
* @ pm_cond : Conditions for power management
* @ ap_state : Current power management state , the
* initial state is IPC_MEM_DEV_PM_ACTIVE eq . 0 .
* @ cp_state : PM State of CP
* @ device_sleep_notification : last handled device_sleep_notfication
* @ pending_hpda_update : is a HPDA update pending ?
*/
struct iosm_pm {
struct iosm_pcie *pcie;
struct device *dev;
enum ipc_mem_host_pm_state host_pm_state;
unsigned long host_sleep_pend;
struct completion host_sleep_complete;
union ipc_pm_cond pm_cond;
enum ipc_mem_dev_pm_state ap_state;
enum ipc_mem_dev_pm_state cp_state;
u32 device_sleep_notification;
u8 pending_hpda_update:1 ;
};
/**
* enum ipc_pm_unit - Power management units .
* @ IPC_PM_UNIT_IRQ : IRQ towards CP
* @ IPC_PM_UNIT_HS : Host Sleep for converged protocol
* @ IPC_PM_UNIT_LINK : Link state controlled by CP .
*/
enum ipc_pm_unit {
IPC_PM_UNIT_IRQ,
IPC_PM_UNIT_HS,
IPC_PM_UNIT_LINK,
};
/**
* ipc_pm_init - Allocate power management component
* @ ipc_protocol : Pointer to iosm_protocol structure
*/
void ipc_pm_init(struct iosm_protocol *ipc_protocol);
/**
* ipc_pm_deinit - Free power management component , invalidating its pointer .
* @ ipc_protocol : Pointer to iosm_protocol structure
*/
void ipc_pm_deinit(struct iosm_protocol *ipc_protocol);
/**
* ipc_pm_dev_slp_notification - Handle a sleep notification message from the
* device . This can be called from interrupt state
* This function handles Host Sleep requests too
* if the Host Sleep protocol is register based .
* @ ipc_pm : Pointer to power management component
* @ sleep_notification : Actual notification from device
*
* Returns : true if dev sleep state has to be checked , false otherwise .
*/
bool ipc_pm_dev_slp_notification(struct iosm_pm *ipc_pm,
u32 sleep_notification);
/**
* ipc_pm_set_s2idle_sleep - Set PM variables to sleep / active
* @ ipc_pm : Pointer to power management component
* @ sleep : true to enter sleep / false to exit sleep
*/
void ipc_pm_set_s2idle_sleep(struct iosm_pm *ipc_pm, bool sleep);
/**
* ipc_pm_prepare_host_sleep - Prepare the PM for sleep by entering
* IPC_MEM_HOST_PM_SLEEP_WAIT_D3 state .
* @ ipc_pm : Pointer to power management component
*
* Returns : true on success , false if the host was not active .
*/
bool ipc_pm_prepare_host_sleep(struct iosm_pm *ipc_pm);
/**
* ipc_pm_prepare_host_active - Prepare the PM for wakeup by entering
* IPC_MEM_HOST_PM_ACTIVE_WAIT state .
* @ ipc_pm : Pointer to power management component
*
* Returns : true on success , false if the host was not sleeping .
*/
bool ipc_pm_prepare_host_active(struct iosm_pm *ipc_pm);
/**
* ipc_pm_wait_for_device_active - Wait up to IPC_PM_ACTIVE_TIMEOUT_MS ms
* for the device to reach active state
* @ ipc_pm : Pointer to power management component
*
* Returns : true if device is active , false on timeout
*/
bool ipc_pm_wait_for_device_active(struct iosm_pm *ipc_pm);
/**
* ipc_pm_signal_hpda_doorbell - Wake up the device if it is in low power mode
* and trigger a head pointer update interrupt .
* @ ipc_pm : Pointer to power management component
* @ identifier : specifies what component triggered hpda update irq
* @ host_slp_check : if set to true then Host Sleep state machine check will
* be performed . If Host Sleep state machine allows HP
* update then only doorbell is triggered otherwise pending
* flag will be set . If set to false then Host Sleep check
* will not be performed . This is helpful for Host Sleep
* negotiation through message ring .
*/
void ipc_pm_signal_hpda_doorbell(struct iosm_pm *ipc_pm, u32 identifier,
bool host_slp_check);
/**
* ipc_pm_trigger - Update power manager and wake up the link if needed
* @ ipc_pm : Pointer to power management component
* @ unit : Power management units
* @ active : Device link state
*
* Returns : true if link is unchanged or active , false otherwise
*/
bool ipc_pm_trigger(struct iosm_pm *ipc_pm, enum ipc_pm_unit unit, bool active);
#endif
Messung V0.5 in Prozent C=95 H=94 G=94
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-10-11)
¤
*© Formatika GbR, Deutschland