1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
|
/* SPDX-License-Identifier: GPL-2.0-only
*
* Copyright (C) 2020-21 Intel Corporation.
*/
#ifndef IOSM_IPC_PROTOCOL_H
#define IOSM_IPC_PROTOCOL_H
#include "iosm_ipc_imem.h"
#include "iosm_ipc_pm.h"
#include "iosm_ipc_protocol_ops.h"
/* Trigger the doorbell interrupt on CP. */
#define IPC_DOORBELL_IRQ_HPDA 0
#define IPC_DOORBELL_IRQ_IPC 1
#define IPC_DOORBELL_IRQ_SLEEP 2
/* IRQ vector number. */
#define IPC_DEVICE_IRQ_VECTOR 0
#define IPC_MSG_IRQ_VECTOR 0
#define IPC_UL_PIPE_IRQ_VECTOR 0
#define IPC_DL_PIPE_IRQ_VECTOR 0
#define IPC_MEM_MSG_ENTRIES 128
/* Default time out for sending IPC messages like open pipe, close pipe etc.
* during run mode.
*
* If the message interface lock to CP times out, the link to CP is broken.
* mode : run mode (IPC_MEM_EXEC_STAGE_RUN)
* unit : milliseconds
*/
#define IPC_MSG_COMPLETE_RUN_DEFAULT_TIMEOUT 500 /* 0.5 seconds */
/* Default time out for sending IPC messages like open pipe, close pipe etc.
* during boot mode.
*
* If the message interface lock to CP times out, the link to CP is broken.
* mode : boot mode
* (IPC_MEM_EXEC_STAGE_BOOT | IPC_MEM_EXEC_STAGE_PSI | IPC_MEM_EXEC_STAGE_EBL)
* unit : milliseconds
*/
#define IPC_MSG_COMPLETE_BOOT_DEFAULT_TIMEOUT 500 /* 0.5 seconds */
/**
* struct ipc_protocol_context_info - Structure of the context info
* @device_info_addr: 64 bit address to device info
* @head_array: 64 bit address to head pointer arr for the pipes
* @tail_array: 64 bit address to tail pointer arr for the pipes
* @msg_head: 64 bit address to message head pointer
* @msg_tail: 64 bit address to message tail pointer
* @msg_ring_addr: 64 bit pointer to the message ring buffer
* @msg_ring_entries: This field provides the number of entries which
* the MR can hold
* @msg_irq_vector: This field provides the IRQ which shall be
* generated by the EP device when generating
* completion for Messages.
* @device_info_irq_vector: This field provides the IRQ which shall be
* generated by the EP dev after updating Dev. Info
*/
struct ipc_protocol_context_info {
phys_addr_t device_info_addr;
phys_addr_t head_array;
phys_addr_t tail_array;
phys_addr_t msg_head;
phys_addr_t msg_tail;
phys_addr_t msg_ring_addr;
__le16 msg_ring_entries;
u8 msg_irq_vector;
u8 device_info_irq_vector;
};
/**
* struct ipc_protocol_device_info - Structure for the device information
* @execution_stage: CP execution stage
* @ipc_status: IPC states
* @device_sleep_notification: Requested device pm states
*/
struct ipc_protocol_device_info {
__le32 execution_stage;
__le32 ipc_status;
__le32 device_sleep_notification;
};
/**
* struct ipc_protocol_ap_shm - Protocol Shared Memory Structure
* @ci: Context information struct
* @device_info: Device information struct
* @msg_head: Point to msg head
* @head_array: Array of head pointer
* @msg_tail: Point to msg tail
* @tail_array: Array of tail pointer
* @msg_ring: Circular buffers for the read/tail and write/head
* indeces.
*/
struct ipc_protocol_ap_shm {
struct ipc_protocol_context_info ci;
struct ipc_protocol_device_info device_info;
__le32 msg_head;
__le32 head_array[IPC_MEM_MAX_PIPES];
__le32 msg_tail;
__le32 tail_array[IPC_MEM_MAX_PIPES];
union ipc_mem_msg_entry msg_ring[IPC_MEM_MSG_ENTRIES];
};
/**
* struct iosm_protocol - Structure for IPC protocol.
* @p_ap_shm: Pointer to Protocol Shared Memory Structure
* @pm: Instance to struct iosm_pm
* @pcie: Pointer to struct iosm_pcie
* @imem: Pointer to struct iosm_imem
* @rsp_ring: Array of OS completion objects to be triggered once CP
* acknowledges a request in the message ring
* @dev: Pointer to device structure
* @phy_ap_shm: Physical/Mapped representation of the shared memory info
* @old_msg_tail: Old msg tail ptr, until AP has handled ACK's from CP
*/
struct iosm_protocol {
struct ipc_protocol_ap_shm *p_ap_shm;
struct iosm_pm pm;
struct iosm_pcie *pcie;
struct iosm_imem *imem;
struct ipc_rsp *rsp_ring[IPC_MEM_MSG_ENTRIES];
struct device *dev;
dma_addr_t phy_ap_shm;
u32 old_msg_tail;
};
/**
* struct ipc_call_msg_send_args - Structure for message argument for
* tasklet function.
* @prep_args: Arguments for message preparation function
* @response: Can be NULL if result can be ignored
* @msg_type: Message Type
*/
struct ipc_call_msg_send_args {
union ipc_msg_prep_args *prep_args;
struct ipc_rsp *response;
enum ipc_msg_prep_type msg_type;
};
/**
* ipc_protocol_tq_msg_send - prepare the msg and send to CP
* @ipc_protocol: Pointer to ipc_protocol instance
* @msg_type: Message type
* @prep_args: Message arguments
* @response: Pointer to a response object which has a
* completion object and return code.
*
* Returns: 0 on success and failure value on error
*/
int ipc_protocol_tq_msg_send(struct iosm_protocol *ipc_protocol,
enum ipc_msg_prep_type msg_type,
union ipc_msg_prep_args *prep_args,
struct ipc_rsp *response);
/**
* ipc_protocol_msg_send - Send ipc control message to CP and wait for response
* @ipc_protocol: Pointer to ipc_protocol instance
* @prep: Message type
* @prep_args: Message arguments
*
* Returns: 0 on success and failure value on error
*/
int ipc_protocol_msg_send(struct iosm_protocol *ipc_protocol,
enum ipc_msg_prep_type prep,
union ipc_msg_prep_args *prep_args);
/**
* ipc_protocol_suspend - Signal to CP that host wants to go to sleep (suspend).
* @ipc_protocol: Pointer to ipc_protocol instance
*
* Returns: true if host can suspend, false if suspend must be aborted.
*/
bool ipc_protocol_suspend(struct iosm_protocol *ipc_protocol);
/**
* ipc_protocol_s2idle_sleep - Call PM function to set PM variables in s2idle
* sleep/active case
* @ipc_protocol: Pointer to ipc_protocol instance
* @sleep: True for sleep/False for active
*/
void ipc_protocol_s2idle_sleep(struct iosm_protocol *ipc_protocol, bool sleep);
/**
* ipc_protocol_resume - Signal to CP that host wants to resume operation.
* @ipc_protocol: Pointer to ipc_protocol instance
*
* Returns: true if host can resume, false if there is a problem.
*/
bool ipc_protocol_resume(struct iosm_protocol *ipc_protocol);
/**
* ipc_protocol_pm_dev_sleep_handle - Handles the Device Sleep state change
* notification.
* @ipc_protocol: Pointer to ipc_protocol instance.
*
* Returns: true if sleep notification handled, false otherwise.
*/
bool ipc_protocol_pm_dev_sleep_handle(struct iosm_protocol *ipc_protocol);
/**
* ipc_protocol_doorbell_trigger - Wrapper for PM function which wake up the
* device if it is in low power mode
* and trigger a head pointer update interrupt.
* @ipc_protocol: Pointer to ipc_protocol instance.
* @identifier: Specifies what component triggered hpda
* update irq
*/
void ipc_protocol_doorbell_trigger(struct iosm_protocol *ipc_protocol,
u32 identifier);
/**
* ipc_protocol_sleep_notification_string - Returns last Sleep Notification as
* string.
* @ipc_protocol: Instance pointer of Protocol module.
*
* Returns: Pointer to string.
*/
const char *
ipc_protocol_sleep_notification_string(struct iosm_protocol *ipc_protocol);
/**
* ipc_protocol_init - Allocates IPC protocol instance
* @ipc_imem: Pointer to iosm_imem structure
*
* Returns: Address of IPC protocol instance on success & NULL on failure.
*/
struct iosm_protocol *ipc_protocol_init(struct iosm_imem *ipc_imem);
/**
* ipc_protocol_deinit - Deallocates IPC protocol instance
* @ipc_protocol: pointer to the IPC protocol instance
*/
void ipc_protocol_deinit(struct iosm_protocol *ipc_protocol);
#endif
|