1 /*
2  * Copyright (c) 2023 Intel Corporation
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _SEDI_DRIVER_IPC_H_
8 #define _SEDI_DRIVER_IPC_H_
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #include "sedi_driver_common.h"
15 
16 /*
17  * struct sedi_ipc
18  * define IPC interface ID
19  * \ingroup sedi_driver_ipc
20  */
21 typedef enum {
22 	SEDI_IPC_HOST = 0,
23 	SEDI_IPC_CSME,
24 	SEDI_IPC_PMC,
25 	SEDI_IPC_NUM
26 } sedi_ipc_t;
27 
28 /****** IPC Event *****/
29 
30 /*
31  * SEDI_IPC_EVENT_MSG_IN
32  * Received an incoming ipc message
33  * \ingroup sedi_driver_ipc
34  */
35 #define SEDI_IPC_EVENT_MSG_IN (1UL << 0)
36 
37 /*
38  * SEDI_IPC_EVENT_MSG_PEER_ACKED
39  * An ipc busy bit is cleared by peer
40  * \ingroup sedi_driver_ipc
41  */
42 #define SEDI_IPC_EVENT_MSG_PEER_ACKED (1UL << 1)
43 
44 /*
45  * SEDI_IPC_EVENT_MSG_OUT
46  * An ipc message is received by peer
47  * \ingroup sedi_driver_ipc
48  */
49 #define SEDI_IPC_EVENT_MSG_OUT (1UL << 2)
50 
51 /*
52  * SEDI_IPC_EVENT_CSR_ACK
53  * Receive a CSR ack from peer after writing CSR
54  * \ingroup sedi_driver_ipc
55  */
56 #define SEDI_IPC_EVENT_CSR_ACK (1UL << 3)
57 
58 /****** IPC Capability *****/
59 
60 /*
61  * struct sedi_ipc_capabilities_t
62  * define IPC Driver Capabilities.
63  * \ingroup sedi_driver_ipc
64  */
65 typedef struct {
66 	uint32_t is_available : 1;
67 	uint32_t reserved : 31;
68 } sedi_ipc_capabilities_t;
69 
70 /****** IPC Driver helper definitions *****/
71 
72 #define IPC_PROTOCOL_BOOT 0
73 #define IPC_PROTOCOL_HECI 1
74 #define IPC_PROTOCOL_MCTP 2
75 #define IPC_PROTOCOL_MNG 3
76 
77 #define IPC_DRBL_BUSY_BIT 31
78 #define IPC_DATA_LEN_MAX  128
79 
80 #define IPC_HEADER_LENGTH_MASK (0x03FF)
81 #define IPC_HEADER_PROTOCOL_MASK (0x0F)
82 #define IPC_HEADER_MNG_CMD_MASK (0x0F)
83 
84 #define IPC_HEADER_LENGTH_OFFSET 0
85 #define IPC_HEADER_PROTOCOL_OFFSET 10
86 #define IPC_HEADER_MNG_CMD_OFFSET 16
87 #define IPC_DRBL_BUSY_OFFS 31
88 
89 #define IPC_HEADER_GET_LENGTH(drbl_reg)        \
90 	(((drbl_reg) >> IPC_HEADER_LENGTH_OFFSET) & IPC_HEADER_LENGTH_MASK)
91 #define IPC_HEADER_GET_PROTOCOL(drbl_reg) \
92 	(((drbl_reg) >> IPC_HEADER_PROTOCOL_OFFSET) & IPC_HEADER_PROTOCOL_MASK)
93 #define IPC_HEADER_GET_MNG_CMD(drbl_reg) \
94 	(((drbl_reg) >> IPC_HEADER_MNG_CMD_OFFSET) & IPC_HEADER_MNG_CMD_MASK)
95 #define IPC_IS_BUSY(drbl) ((drbl) & BIT(IPC_DRBL_BUSY_OFFS))
96 #define IPC_SET_BUSY(drbl) ((drbl) | BIT(IPC_DRBL_BUSY_OFFS))
97 
98 #define IPC_BUILD_DRBL(length, protocol)             \
99 	((1 << IPC_DRBL_BUSY_OFFS)                    \
100 	 | ((protocol) << IPC_HEADER_PROTOCOL_OFFSET) \
101 	 | ((length) << IPC_HEADER_LENGTH_OFFSET))
102 
103 #define IPC_BUILD_MNG_DRBL(cmd, length)                              \
104 	(((1) << IPC_DRBL_BUSY_OFFS)                          \
105 	 | ((IPC_PROTOCOL_MNG) << IPC_HEADER_PROTOCOL_OFFSET) \
106 	 | ((cmd) << IPC_HEADER_MNG_CMD_OFFSET)               \
107 	 | ((length) << IPC_HEADER_LENGTH_OFFSET))
108 
109 /* CSR bit definition */
110 #define IPC_CSR_NO_MSG			0
111 #define IPC_CSR_RESET_ENTRY		BIT(0)
112 #define IPC_CSR_RESET_EXIT		BIT(1)
113 #define IPC_CSR_QUERY			BIT(2)
114 #define IPC_CSR_ASSERT_VALID		BIT(3)
115 #define IPC_CSR_ACKED_VALID		BIT(4)
116 #define IPC_CSR_DEASSERT_VALID		BIT(5)
117 #define IPC_CSR_SRAM_CLAIM		BIT(31)
118 
119 /****** IPC Driver API *****/
120 
121 /*
122  * ipc_event_handler IPC Event Handler Callback
123  * typedef sedi_ipc_event_cb_t
124  * Callback function type for signal ipc event.
125  * param[in] event: event type.
126  * return    void
127  */
128 typedef void (*sedi_ipc_event_cb_t)(IN sedi_ipc_t device, IN uint32_t event,
129 				    INOUT void *params);
130 
131 /*
132  * Get the ipc driver's API version.
133  * return the version of current ipc driver's API
134  */
135 sedi_driver_version_t sedi_ipc_get_version(void);
136 
137 /*
138  * Get the device's capabilities.
139  * param[in] ipc_device: ipc device id
140  * param[inout]  the capabilities of specific ipc device
141  * return return status
142  */
143 int32_t sedi_ipc_get_capabilities(IN sedi_ipc_t ipc_device,
144 				  INOUT sedi_ipc_capabilities_t *cap);
145 /*
146  * write CSR message to peer.
147  * param[in] ipc_device: ipc device id
148  * param[in] csr: the csr content to sent
149  * return return status
150  */
151 int32_t sedi_ipc_write_csr(IN sedi_ipc_t ipc_device, IN uint32_t csr);
152 
153 /*
154  * read CSR message from peer.
155  * param[in] ipc_device: ipc device id
156  * param[out] csr: the pointer storing the csr msg
157  * return return status
158  */
159 int32_t sedi_ipc_read_csr(IN sedi_ipc_t ipc_device, OUT uint32_t *csr);
160 
161 /*
162  * Initialize the device
163  * param[in] ipc_device: ipc device id
164  * param[in] cb: the callback function which can receive device's events.
165  * param[in] user_params: user params, will be the last input of callback
166  * return  return_status
167  */
168 int32_t sedi_ipc_init(IN sedi_ipc_t ipc_device, IN sedi_ipc_event_cb_t cb,
169 		      INOUT void *user_params);
170 
171 /*
172  * Uninitialize the device
173  * param[in] ipc_device: ipc device id
174  * return  return_status
175  */
176 int32_t sedi_ipc_uninit(IN sedi_ipc_t ipc_device);
177 
178 /*
179  * Set the device's power
180  * param[in] ipc_device: ipc device id
181  * param[in] state: the power state to be set to the device
182  * return  return_status
183  */
184 int32_t sedi_ipc_set_power(IN sedi_ipc_t ipc_device,
185 			   IN sedi_power_state_t state);
186 
187 /*
188  * Write data to IPC message fifo
189  * param[in] ipc_device: ipc device id
190  * param[in] msg: point to memory area where data is stored
191  * param[in] size: the length of data buffer
192  * return  return_status
193  */
194 int32_t sedi_ipc_write_msg(IN sedi_ipc_t ipc_device, IN uint8_t *msg,
195 			   IN int32_t size);
196 
197 /*
198  * Write IPC doorbell register
199  * param[in] ipc_device: ipc device id
200  * param[in] doorbell: the value of doorbell
201  * return  return_status
202  */
203 int32_t sedi_ipc_write_dbl(IN sedi_ipc_t ipc_device, IN uint32_t doorbell);
204 
205 /*
206  * Read data from IPC message fifo
207  * param[in] ipc_device: ipc device id
208  * param[out] msg: point to memory area where data will be stored
209  * param[in] size: the length of data buffer
210  * return  return_status
211  */
212 int32_t sedi_ipc_read_msg(IN sedi_ipc_t ipc_device, OUT uint8_t *msg,
213 			  IN int32_t size);
214 
215 /*
216  * Read IPC doorbell register
217  * param[in] ipc_device: ipc device id
218  * param[out] doorbel: point to the value of doorbell
219  * return  return_status
220  */
221 int32_t sedi_ipc_read_dbl(IN sedi_ipc_t ipc_device, OUT uint32_t *doorbell);
222 
223 /*
224  * send ack IPC message
225  * param[in] ipc_device: ipc device id
226  * param[in] msg: the ack msg
227  * param[in] size: the length of data buffer
228  * return  return_status
229  */
230 int32_t sedi_ipc_send_ack_msg(IN sedi_ipc_t ipc_device, IN uint8_t *msg,
231 			      IN int32_t size);
232 
233 /*
234  * send ack IPC doorbell register
235  * param[in] ipc_device: ipc device id
236  * param[in] doorbell: the ack doorbell
237  * return  return_status
238  */
239 int32_t sedi_ipc_send_ack_drbl(IN sedi_ipc_t ipc_device, IN uint32_t ack);
240 
241 /*
242  * read peer ack IPC message
243  * param[in] ipc_device: ipc device id
244  * param[out] doorbell: the buffer to store ack msg
245  * param[in] size: the length of data buffer
246  * return  return_status
247  */
248 int32_t sedi_ipc_read_ack_msg(IN sedi_ipc_t ipc_device, OUT uint8_t *msg,
249 			      IN int32_t size);
250 
251 /*
252  * read peer ack IPC doorbell register
253  * param[in] ipc_device: ipc device id
254  * param[out] doorbell: the ack doorbell
255  * return  return_status
256  */
257 int32_t sedi_ipc_read_ack_drbl(IN sedi_ipc_t ipc_device, OUT uint32_t *ack);
258 
259 #ifdef __cplusplus
260 }
261 #endif
262 
263 #endif /* _SEDI_DRIVER_IPC_H_*/
264