GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / net / wwan / iosm / iosm_ipc_pm.h
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  */
24 union 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  */
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,
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  */
74 enum 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  */
99 struct 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  */
118 enum 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  */
128 void 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  */
134 void 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  */
146 bool 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  */
154 void 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  */
163 bool 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  */
172 bool ipc_pm_prepare_host_active(struct iosm_pm *ipc_pm);
173
174 /**
175  * ipc_pm_wait_for_device_active - Wait up to 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  */
181 bool 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  */
195 void 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  */
205 bool ipc_pm_trigger(struct iosm_pm *ipc_pm, enum ipc_pm_unit unit, bool active);
206
207 #endif