linux/drivers/net/wwan/iosm/iosm_ipc_pm.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only
   2 *
   3 * Copyright (C) 2020-21 Intel Corporation.
   4 */
   5
   6#ifndef IOSM_IPC_PM_H
   7#define IOSM_IPC_PM_H
   8
   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)
  12
  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))
  16
  17/**
  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
  21 * @hs:         Host Sleep
  22 * @link:       Device link state.
  23 */
  24union ipc_pm_cond {
  25        unsigned int raw;
  26
  27        struct {
  28                unsigned int irq:1,
  29                             hs:1,
  30                             link:1;
  31        };
  32};
  33
  34/**
  35 * enum ipc_mem_host_pm_state - Possible states of the HOST SLEEP finite state
  36 *                              machine.
  37 * @IPC_MEM_HOST_PM_ACTIVE:                Host is active
  38 * @IPC_MEM_HOST_PM_ACTIVE_WAIT:           Intermediate state before going to
  39 *                                         active
  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
  47 *                                         sleep
  48 */
  49enum 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,
  56};
  57
  58/**
  59 * enum ipc_mem_dev_pm_state - Possible states of the DEVICE SLEEP finite state
  60 *                             machine.
  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
  67 *                                      sleep.
  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.
  73 */
  74enum ipc_mem_dev_pm_state {
  75        IPC_MEM_DEV_PM_ACTIVE,
  76        IPC_MEM_DEV_PM_SLEEP,
  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,
  82};
  83
  84/**
  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
  91 *                              case of Host Sleep
  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?
  98 */
  99struct iosm_pm {
 100        struct iosm_pcie *pcie;
 101        struct device *dev;
 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;
 110};
 111
 112/**
 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.
 117 */
 118enum ipc_pm_unit {
 119        IPC_PM_UNIT_IRQ,
 120        IPC_PM_UNIT_HS,
 121        IPC_PM_UNIT_LINK,
 122};
 123
 124/**
 125 * ipc_pm_init - Allocate power management component
 126 * @ipc_protocol:       Pointer to iosm_protocol structure
 127 */
 128void ipc_pm_init(struct iosm_protocol *ipc_protocol);
 129
 130/**
 131 * ipc_pm_deinit - Free power management component, invalidating its pointer.
 132 * @ipc_protocol:       Pointer to iosm_protocol structure
 133 */
 134void ipc_pm_deinit(struct iosm_protocol *ipc_protocol);
 135
 136/**
 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
 143 *
 144 * Returns: true if dev sleep state has to be checked, false otherwise.
 145 */
 146bool ipc_pm_dev_slp_notification(struct iosm_pm *ipc_pm,
 147                                 u32 sleep_notification);
 148
 149/**
 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
 153 */
 154void ipc_pm_set_s2idle_sleep(struct iosm_pm *ipc_pm, bool sleep);
 155
 156/**
 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
 160 *
 161 * Returns: true on success, false if the host was not active.
 162 */
 163bool ipc_pm_prepare_host_sleep(struct iosm_pm *ipc_pm);
 164
 165/**
 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
 169 *
 170 * Returns: true on success, false if the host was not sleeping.
 171 */
 172bool ipc_pm_prepare_host_active(struct iosm_pm *ipc_pm);
 173
 174/**
 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
 178 *
 179 * Returns: true if device is active, false on timeout
 180 */
 181bool ipc_pm_wait_for_device_active(struct iosm_pm *ipc_pm);
 182
 183/**
 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.
 194 */
 195void ipc_pm_signal_hpda_doorbell(struct iosm_pm *ipc_pm, u32 identifier,
 196                                 bool host_slp_check);
 197/**
 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
 202 *
 203 * Returns: true if link is unchanged or active, false otherwise
 204 */
 205bool ipc_pm_trigger(struct iosm_pm *ipc_pm, enum ipc_pm_unit unit, bool active);
 206
 207#endif
 208