xref: /linux/drivers/net/wwan/iosm/iosm_ipc_pm.h (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
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 up to 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