1 /*
2 * Copyright (c) 2023 Intel Corporation
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "sedi_driver_core.h"
8 #include <sedi_driver_common.h>
9 #include <sedi_ipc_regs.h>
10 #include <sedi_driver_ipc.h>
11
12 #define SEDI_IPC_API_VERSION 0
13 /* driver version */
14 #define SEDI_IPC_DRIVER_VERSION SEDI_DRIVER_VERSION_MAJOR_MINOR(0, 1)
15
16 #define IPC_REG_SB_LOCAL2PMC_DRBL 0x1804
17 #define IPC_REG_SB_LOCAL2PMC_MSG 0x1808
18 #define IPC_REG_SB_PMC2LOCAL_DRBL_MIRROR 0x1888
19 #define IPC_REG_SB_PMC2LOCAL_DRBL_MIRROR 0x1888
20
21 #define IPC_REG_SB_LOCAL2CSE_CSR 0x3c
22 #define IPC_REG_SB_LOCAL2CSE_DRBL 0x0
23 #define IPC_REG_SB_LOCAL2CSE_MSG 0x40
24 #define IPC_REG_SB_CSE2LOCAL_DRBL_MIRROR 0x4
25
26 #define IPC_REG_SB_LOCAL2CNVI_CSR 0x698
27 #define IPC_REG_SB_LOCAL2CNVI_DRBL 0x690
28 #define IPC_REG_SB_LOCAL2CNVI_MSG 0x7600
29 #define IPC_REG_SB_CNVI2LOCAL_DRBL_MIRROR 0x694
30
31 #define IPC_REG_SB_LOCAL2BT_CSR 0x698
32 #define IPC_REG_SB_LOCAL2BT_DRBL 0x690
33 #define IPC_REG_SB_LOCAL2BT_MSG 0x7600
34 #define IPC_REG_SB_BT2LOCAL_DRBL_MIRROR 0x694
35
36 #ifdef SEDI_SB_SUPPORT
37 #define SEDI_SIDEBAND_PMC SEDI_SIDEBAND_0
38 #define SEDI_SIDEBAND_CSE SEDI_SIDEBAND_0
39 #endif
40
41 /*driver version*/
42 static const sedi_driver_version_t driver_version = { SEDI_IPC_API_VERSION,
43 SEDI_IPC_DRIVER_VERSION };
44 /* sideband params for non-host interfaces */
45 #ifdef SEDI_SB_SUPPORT
46 typedef struct {
47 sedi_sideband_t dev;
48 sb_port_t port;
49 uint32_t csr_peer_addr;
50 uint32_t drbl_peer_addr;
51 uint32_t msg_peer_addr;
52 uint32_t drbl_mirror_peer_addr;
53 } sideband_param_t;
54 #else
55 typedef struct {
56 } sideband_param_t;
57 #endif
58
59 /* ipc resource information */
60 typedef struct {
61 sedi_ipc_regs_t *reg_base_addr;
62 vnn_id_t read_vnn;
63 vnn_id_t write_vnn;
64 sideband_param_t *sb;
65 } ipc_resource_t;
66
67 /*ipc runtime context information */
68 typedef struct {
69 bool initialized;
70 uint32_t csr_saved;
71 sedi_ipc_event_cb_t cb_event; /*event callback*/
72 uint32_t in_msg_count; /* for debug usage*/
73 uint32_t out_msg_count; /* for debug usage*/
74 /* user parameters for event callback other private runtime data*/
75 void *usr_params;
76 } ipc_context_t;
77
78 static sedi_ipc_capabilities_t driver_capabilities[SEDI_IPC_NUM] = { 0 };
79
80 #ifdef SEDI_SB_SUPPORT
81 static sideband_param_t pmc_sb = { .dev = SEDI_SIDEBAND_PMC,
82 .port = SB_PMC,
83 .csr_peer_addr = IPC_REG_SB_LOCAL2PMC_CSR,
84 .drbl_peer_addr = IPC_REG_SB_LOCAL2PMC_DRBL,
85 .msg_peer_addr = IPC_REG_SB_LOCAL2PMC_MSG,
86 .drbl_mirror_peer_addr = IPC_REG_SB_PMC2LOCAL_DRBL_MIRROR };
87 static sideband_param_t cse_sb = { .dev = SEDI_SIDEBAND_CSE,
88 .port = SB_CSME,
89 .csr_peer_addr = IPC_REG_SB_LOCAL2CSE_CSR,
90 .drbl_peer_addr = IPC_REG_SB_LOCAL2CSE_DRBL,
91 .msg_peer_addr = IPC_REG_SB_LOCAL2CSE_MSG,
92 .drbl_mirror_peer_addr = IPC_REG_SB_CSE2LOCAL_DRBL_MIRROR };
93 #endif
94
95 static const ipc_resource_t ipc_resource[SEDI_IPC_NUM] = {
96 #ifdef SEDI_SB_SUPPORT
97 { .reg_base_addr = (sedi_ipc_regs_t *)SEDI_REG_BASE(IPC_HOST),
98 .read_vnn = VNN_ID_IPC_HOST_R,
99 .write_vnn = VNN_ID_IPC_HOST_W,
100 .sb = NULL },
101 { .reg_base_addr = (sedi_ipc_regs_t *)SEDI_REG_BASE(IPC_CSME),
102 .read_vnn = VNN_ID_IPC_CSE_R,
103 .write_vnn = VNN_ID_IPC_CSE_W,
104 .sb = &cse_sb },
105 { .reg_base_addr = (sedi_ipc_regs_t *)SEDI_REG_BASE(IPC_PMC),
106 .read_vnn = VNN_ID_IPC_PMC_R,
107 .write_vnn = VNN_ID_IPC_PMC_W,
108 .sb = &pmc_sb },
109 #else
110 { .reg_base_addr = (sedi_ipc_regs_t *)SEDI_REG_BASE(IPC_HOST),
111 .read_vnn = VNN_ID_IPC_HOST_R,
112 .write_vnn = VNN_ID_IPC_HOST_W },
113 { .reg_base_addr = (sedi_ipc_regs_t *)SEDI_REG_BASE(IPC_CSME),
114 .read_vnn = VNN_ID_IPC_CSE_R,
115 .write_vnn = VNN_ID_IPC_CSE_W },
116 { .reg_base_addr = (sedi_ipc_regs_t *)SEDI_REG_BASE(IPC_PMC),
117 .read_vnn = VNN_ID_IPC_PMC_R,
118 .write_vnn = VNN_ID_IPC_PMC_W },
119 #endif
120 };
121
122 /*driver contexts */
123 static ipc_context_t ipc_contexts[SEDI_IPC_NUM] = { 0 };
124
check_ipc_available(IN sedi_ipc_t ipc_device)125 static int32_t check_ipc_available(IN sedi_ipc_t ipc_device)
126 {
127 DBG_CHECK(ipc_device < SEDI_IPC_NUM, SEDI_DRIVER_ERROR_PARAMETER);
128 if (!ipc_contexts[ipc_device].initialized) {
129 return SEDI_DRIVER_ERROR;
130 }
131 return SEDI_DRIVER_OK;
132 }
133
134 /********** IPC driver API implementation ***********/
135
sedi_ipc_get_version(void)136 sedi_driver_version_t sedi_ipc_get_version(void)
137 {
138 return driver_version;
139 }
140
sedi_ipc_get_capabilities(IN sedi_ipc_t ipc_device,INOUT sedi_ipc_capabilities_t * cap)141 int32_t sedi_ipc_get_capabilities(IN sedi_ipc_t ipc_device, INOUT sedi_ipc_capabilities_t *cap)
142 {
143 DBG_CHECK(ipc_device < SEDI_IPC_NUM, SEDI_DRIVER_ERROR_PARAMETER);
144
145 /* IPC is always available */
146 driver_capabilities[ipc_device].is_available = 1;
147 *cap = driver_capabilities[ipc_device];
148 return SEDI_DRIVER_OK;
149 }
150
sedi_ipc_init(IN sedi_ipc_t ipc_device,IN sedi_ipc_event_cb_t cb,INOUT void * param)151 int32_t sedi_ipc_init(IN sedi_ipc_t ipc_device, IN sedi_ipc_event_cb_t cb, INOUT void *param)
152 {
153 DBG_CHECK(ipc_device < SEDI_IPC_NUM, SEDI_DRIVER_ERROR_PARAMETER);
154 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
155 vnn_id_t write_vnn = ipc_resource[ipc_device].write_vnn;
156
157 ipc_contexts[ipc_device].initialized = false;
158 ipc_contexts[ipc_device].csr_saved = 0;
159 ipc_contexts[ipc_device].cb_event = cb;
160 ipc_contexts[ipc_device].usr_params = param;
161 ipc_contexts[ipc_device].in_msg_count = 0;
162 ipc_contexts[ipc_device].out_msg_count = 0;
163
164 #ifdef SEDI_SB_SUPPORT
165 sideband_param_t *sb = ipc_resource[ipc_device].sb;
166
167 if (sb) {
168 sedi_sideband_init(sb->dev);
169 }
170 #endif
171 if (SEDI_PREG_RBFV_IS_SET(IPC, ISH2AGENT_DOORBELL_AGENT, BUSY, 1,
172 ®s->ish2agent_doorbell_agent)) {
173 PM_VNN_DRIVER_REQ(write_vnn);
174 SEDI_PREG_RBFV_SET(IPC, ISH2AGENT_DOORBELL_AGENT, BUSY, 0,
175 ®s->ish2agent_doorbell_agent);
176 PM_VNN_DRIVER_DEREQ(write_vnn);
177 }
178 ipc_contexts[ipc_device].initialized = true;
179
180 if (SEDI_PREG_RBFV_IS_SET(IPC, ISH_IPC_BUSY_CLEAR_AGENT,
181 ISH2AGENT_BUSY_CLEAR, 1,
182 ®s->ish_ipc_busy_clear_agent)) {
183 /*set 1 to clear this interrupt*/
184 SEDI_PREG_RBFV_SET(IPC, ISH_IPC_BUSY_CLEAR_AGENT,
185 ISH2AGENT_BUSY_CLEAR, 1, ®s->ish_ipc_busy_clear_agent);
186 }
187 /* Enable Msg in, busyClean and out Interrupt */
188 SEDI_PREG_RBFV_SET(IPC, PIMR_AGENT2ISH, AGENT2ISH_DB, 1, ®s->pimr_agent2ish);
189 SEDI_PREG_RBFV_SET(IPC, PIMR_AGENT2ISH, ISH2AGENT_BC, 1, ®s->pimr_agent2ish);
190 SEDI_PREG_RBFV_SET(IPC, PIMR_ISH2AGENT, ISH2AGENT_DB, 1, ®s->pimr_ish2agent);
191 SEDI_PREG_RBFV_SET(IPC, CIM_AGENT, CH_INTR_MASK, 0, ®s->cim_agent);
192
193 return SEDI_DRIVER_OK;
194 }
195
sedi_ipc_uninit(IN sedi_ipc_t ipc_device)196 int32_t sedi_ipc_uninit(IN sedi_ipc_t ipc_device)
197 {
198 DBG_CHECK(ipc_device < SEDI_IPC_NUM, SEDI_DRIVER_ERROR_PARAMETER);
199 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
200
201 /* disable Msg in, busyClean and out Interrupt */
202 SEDI_PREG_RBFV_SET(IPC, PIMR_AGENT2ISH, AGENT2ISH_DB, 0, ®s->pimr_agent2ish);
203 SEDI_PREG_RBFV_SET(IPC, PIMR_AGENT2ISH, ISH2AGENT_BC, 0, ®s->pimr_agent2ish);
204
205 ipc_contexts[ipc_device].cb_event = NULL;
206 ipc_contexts[ipc_device].initialized = false;
207 #ifdef SEDI_SB_SUPPORT
208 sideband_param_t *sb = ipc_resource[ipc_device].sb;
209
210 if (sb) {
211 sedi_sideband_uninit(sb->dev);
212 }
213 #endif
214 return SEDI_DRIVER_OK;
215 }
216
217 /*
218 * IPC is an always-on IP, no power operation available for IPC,
219 * keep API for future
220 */
sedi_ipc_set_power(IN sedi_ipc_t ipc_device,IN sedi_power_state_t state)221 int32_t sedi_ipc_set_power(IN sedi_ipc_t ipc_device, IN sedi_power_state_t state)
222 {
223 int ret;
224
225 ret = check_ipc_available(ipc_device);
226 if (ret != SEDI_DRIVER_OK) {
227 return ret;
228 }
229
230 PARAM_UNUSED(state);
231
232 return SEDI_DRIVER_OK;
233 }
234
sedi_ipc_write_msg(IN sedi_ipc_t ipc_device,IN uint8_t * msg,IN int32_t size)235 int32_t sedi_ipc_write_msg(IN sedi_ipc_t ipc_device, IN uint8_t *msg, IN int32_t size)
236 {
237 int ret, i;
238 uint32_t tail = 0;
239
240 ret = check_ipc_available(ipc_device);
241 if (ret != SEDI_DRIVER_OK) {
242 return ret;
243 }
244
245 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
246 sideband_param_t *sb = ipc_resource[ipc_device].sb;
247
248 DBG_CHECK((size <= IPC_DATA_LEN_MAX) && (size >= 0), SEDI_DRIVER_ERROR_PARAMETER);
249 DBG_CHECK(msg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
250
251 if (sb) {
252 #ifdef SEDI_SB_SUPPORT
253 /* for CSE and PMC, use sideband */
254 for (i = 0; i < size; i = i + 4) {
255 sedi_sideband_send(sb->dev, sb->port, SEDI_SIDEBAND_ACTION_WRITE,
256 sb->msg_peer_addr + i, *((uint32_t *)(msg + i)));
257 }
258 #endif
259 } else {
260 /* write data in 32-bit*/
261 for (i = 0; i < (size >> 2); i++) {
262 regs->ish2agent_msg_agent[i] = *((uint32_t *)msg + i);
263 }
264 /* write data in 8-bit for the rest*/
265 if (size % sizeof(uint32_t)) {
266 for (i = ((size >> 2) << 2); i < size; i++) {
267 tail += msg[i] << ((i % 4) << 3);
268 }
269 regs->ish2agent_msg_agent[size >> 2] = tail;
270 }
271 }
272 return SEDI_DRIVER_OK;
273 }
274
sedi_ipc_write_dbl(IN sedi_ipc_t ipc_device,IN uint32_t doorbell)275 int32_t sedi_ipc_write_dbl(IN sedi_ipc_t ipc_device, IN uint32_t doorbell)
276 {
277 int ret;
278
279 ret = check_ipc_available(ipc_device);
280 if (ret != SEDI_DRIVER_OK) {
281 return ret;
282 }
283
284 vnn_id_t write_vnn = ipc_resource[ipc_device].write_vnn;
285 sideband_param_t *sb = ipc_resource[ipc_device].sb;
286 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
287
288 if (sb) {
289 regs->ish2agent_doorbell_agent = doorbell;
290 #ifdef SEDI_SB_SUPPORT
291 sedi_sideband_send(sb->dev, sb->port, SEDI_SIDEBAND_ACTION_WRITE,
292 sb->drbl_peer_addr, doorbell);
293 #endif
294 } else {
295 /* IPC to HOST */
296 PM_VNN_DRIVER_REQ(write_vnn);
297 regs->ish2agent_doorbell_agent = doorbell;
298 if (SEDI_PREG_RBFV_IS_SET(IPC, ISH2AGENT_DOORBELL_AGENT, BUSY, 0,
299 (uint32_t *)&doorbell)) {
300 PM_VNN_DRIVER_DEREQ(write_vnn);
301 }
302 }
303
304 return SEDI_DRIVER_OK;
305 }
306
sedi_ipc_write_csr(IN sedi_ipc_t ipc_device,IN uint32_t csr)307 int32_t sedi_ipc_write_csr(IN sedi_ipc_t ipc_device, IN uint32_t csr)
308 {
309 int ret;
310
311 ret = check_ipc_available(ipc_device);
312 if (ret != SEDI_DRIVER_OK) {
313 return ret;
314 }
315
316 sideband_param_t *sb = ipc_resource[ipc_device].sb;
317
318 if (sb) {
319 #ifdef SEDI_SB_SUPPORT
320 sedi_sideband_send(sb->dev, sb->port, SEDI_SIDEBAND_ACTION_WRITE, sb->csr_peer_addr,
321 csr);
322 #endif
323 }
324
325 return SEDI_DRIVER_OK;
326 }
327
sedi_ipc_read_csr(IN sedi_ipc_t ipc_device,OUT uint32_t * csr)328 int32_t sedi_ipc_read_csr(IN sedi_ipc_t ipc_device, OUT uint32_t *csr)
329 {
330 int ret;
331
332 ret = check_ipc_available(ipc_device);
333 if (ret != SEDI_DRIVER_OK) {
334 return ret;
335 }
336
337 if (csr) {
338 *csr = ipc_contexts[ipc_device].csr_saved;
339 } else {
340 return SEDI_DRIVER_ERROR_PARAMETER;
341 }
342
343 return SEDI_DRIVER_OK;
344 }
345
sedi_ipc_read_msg(IN sedi_ipc_t ipc_device,OUT uint8_t * msg,IN int32_t size)346 int32_t sedi_ipc_read_msg(IN sedi_ipc_t ipc_device, OUT uint8_t *msg, IN int32_t size)
347 {
348 int ret, i;
349 uint32_t tail = 0;
350
351 ret = check_ipc_available(ipc_device);
352 if (ret != SEDI_DRIVER_OK) {
353 return ret;
354 }
355
356 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
357
358 DBG_CHECK((size <= IPC_DATA_LEN_MAX) && (size >= 0), SEDI_DRIVER_ERROR_PARAMETER);
359 DBG_CHECK(msg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
360
361 /* read data in 32-bit*/
362 for (i = 0; i < (size >> 2); i++) {
363 *((uint32_t *)msg + i) = regs->agent2ish_msg_agent[i];
364 }
365
366 /* read data in 8-bit for the rest*/
367 if (size % sizeof(uint32_t)) {
368 tail = regs->agent2ish_msg_agent[size >> 2];
369 }
370 for (i = ((size >> 2) << 2); i < size; i++) {
371 msg[i] = *((uint8_t *)&tail + i % sizeof(uint32_t));
372 }
373 return SEDI_DRIVER_OK;
374 }
375
sedi_ipc_read_dbl(IN sedi_ipc_t ipc_device,OUT uint32_t * doorbell)376 int32_t sedi_ipc_read_dbl(IN sedi_ipc_t ipc_device, OUT uint32_t *doorbell)
377 {
378 int ret;
379
380 ret = check_ipc_available(ipc_device);
381 if (ret != SEDI_DRIVER_OK) {
382 return ret;
383 }
384
385 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
386 *doorbell = regs->agent2ish_doorbell_agent;
387 return SEDI_DRIVER_OK;
388 }
389
sedi_ipc_send_ack_drbl(IN sedi_ipc_t ipc_device,IN uint32_t ack)390 int32_t sedi_ipc_send_ack_drbl(IN sedi_ipc_t ipc_device, IN uint32_t ack)
391 {
392 int ret;
393
394 ret = check_ipc_available(ipc_device);
395 if (ret != SEDI_DRIVER_OK) {
396 return ret;
397 }
398
399 sideband_param_t *sb = ipc_resource[ipc_device].sb;
400
401 if (SEDI_PREG_RBFV_IS_SET(IPC, ISH2AGENT_DOORBELL_AGENT, BUSY, 1, (uint32_t *)&ack)) {
402 return SEDI_DRIVER_ERROR_PARAMETER;
403 }
404
405 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
406 vnn_id_t read_vnn = ipc_resource[ipc_device].read_vnn;
407
408 regs->agent2ish_doorbell_agent = ack;
409 if (sb) {
410 #ifdef SEDI_SB_SUPPORT
411 /* the peer is PMC or CSE */
412 sedi_sideband_send(sb->dev, sb->port, SEDI_SIDEBAND_ACTION_WRITE,
413 sb->drbl_mirror_peer_addr, ack);
414 #endif
415 } else {
416 /* the peer is host */
417 PM_VNN_DRIVER_DEREQ(read_vnn);
418 }
419 SEDI_PREG_RBFV_SET(IPC, PIMR_AGENT2ISH, AGENT2ISH_DB, 1, ®s->pimr_agent2ish);
420 return SEDI_DRIVER_OK;
421 }
422
sedi_ipc_read_ack_drbl(IN sedi_ipc_t ipc_device,OUT uint32_t * ack)423 int32_t sedi_ipc_read_ack_drbl(IN sedi_ipc_t ipc_device, OUT uint32_t *ack)
424 {
425 int ret;
426
427 ret = check_ipc_available(ipc_device);
428 if (ret != SEDI_DRIVER_OK) {
429 return ret;
430 }
431
432 DBG_CHECK(ack != NULL, ret);
433 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
434
435 *ack = regs->ish2agent_doorbell_agent;
436
437 return SEDI_DRIVER_OK;
438 }
439
sedi_ipc_send_ack_msg(IN sedi_ipc_t ipc_device,IN uint8_t * msg,IN int32_t size)440 int32_t sedi_ipc_send_ack_msg(IN sedi_ipc_t ipc_device, IN uint8_t *msg, IN int32_t size)
441 {
442 int ret, i;
443 uint32_t tail = 0;
444
445 ret = check_ipc_available(ipc_device);
446 if (ret != SEDI_DRIVER_OK) {
447 return ret;
448 }
449
450 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
451
452 DBG_CHECK((size <= IPC_DATA_LEN_MAX) && (size >= 0), SEDI_DRIVER_ERROR_PARAMETER);
453 DBG_CHECK(msg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
454
455 /* write data in 32-bit*/
456 for (i = 0; i < (size >> 2); i++) {
457 regs->agent2ish_msg_agent[i] = *((uint32_t *)msg + i);
458 }
459 /* write data in 8-bit for the rest*/
460 if (size % sizeof(uint32_t)) {
461 for (i = ((size >> 2) << 2); i < size; i++) {
462 tail += msg[i] << ((i % 4) << 3);
463 }
464 regs->agent2ish_msg_agent[size >> 2] = tail;
465 }
466 return SEDI_DRIVER_OK;
467 }
468
sedi_ipc_read_ack_msg(IN sedi_ipc_t ipc_device,OUT uint8_t * msg,IN int32_t size)469 int32_t sedi_ipc_read_ack_msg(IN sedi_ipc_t ipc_device, OUT uint8_t *msg, IN int32_t size)
470 {
471 int ret, i;
472 uint32_t tail;
473
474 ret = check_ipc_available(ipc_device);
475 if (ret != SEDI_DRIVER_OK) {
476 return ret;
477 }
478
479 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
480
481 DBG_CHECK((size <= IPC_DATA_LEN_MAX) && (size >= 0), SEDI_DRIVER_ERROR_PARAMETER);
482 DBG_CHECK(msg != NULL, SEDI_DRIVER_ERROR_PARAMETER);
483
484 if (ipc_device == SEDI_IPC_HOST) {
485 /* read data in 32-bit*/
486 for (i = 0; i < (size >> 2); i++) {
487 *((uint32_t *)msg + i) = regs->ish2agent_msg_agent[i];
488 }
489 /* read data in 8-bit for the rest*/
490 if (size % sizeof(uint32_t)) {
491 tail = regs->ish2agent_msg_agent[size >> 2];
492 }
493 for (i = ((size >> 2) << 2); i < size; i++) {
494 msg[i] = *((uint8_t *)&tail + i % sizeof(uint32_t));
495 }
496 } else {
497 #ifdef SEDI_SB_SUPPORT
498 sideband_param_t *sb = ipc_resource[ipc_device].sb;
499
500 for (i = 0; i < size; i = i + 4) {
501 sedi_sideband_send(sb->dev, sb->port, SEDI_SIDEBAND_ACTION_READ,
502 sb->msg_peer_addr + i, 0);
503 sedi_sideband_wait_ack(sb->dev, sb->port, SEDI_SIDEBAND_ACTION_READ,
504 (uint32_t *)(msg + i));
505 }
506 #endif
507 }
508
509 return SEDI_DRIVER_OK;
510 }
511 /* IPC ISR process function */
512
sedi_ipc_isr(IN sedi_ipc_t ipc_device)513 void sedi_ipc_isr(IN sedi_ipc_t ipc_device)
514 {
515 int ret;
516 volatile sedi_ipc_regs_t *regs = ipc_resource[ipc_device].reg_base_addr;
517
518 ret = check_ipc_available(ipc_device);
519 if (ret != SEDI_DRIVER_OK) {
520 return;
521 }
522
523 /* check whether it is an inbound interrupt*/
524 if (SEDI_PREG_RBFV_IS_SET(IPC, PISR_AGENT2ISH, AGENT2ISH_DB, 1, ®s->pisr_agent2ish) &&
525 SEDI_PREG_RBFV_IS_SET(IPC, PIMR_AGENT2ISH, AGENT2ISH_DB, 1,
526 ®s->pimr_agent2ish)) {
527 /* mask interrupts before ack */
528 SEDI_PREG_RBFV_SET(IPC, PIMR_AGENT2ISH, AGENT2ISH_DB, 0, ®s->pimr_agent2ish);
529 if (ipc_device == SEDI_IPC_HOST) {
530 PM_VNN_DRIVER_REQ(ipc_resource[ipc_device].read_vnn);
531 }
532 if (ipc_contexts[ipc_device].cb_event) {
533 ipc_contexts[ipc_device].in_msg_count++;
534 ipc_contexts[ipc_device].cb_event(ipc_device, SEDI_IPC_EVENT_MSG_IN,
535 ipc_contexts[ipc_device].usr_params);
536 }
537 }
538
539 /* check whether it is an outbound interrupt*/
540 if (SEDI_PREG_RBFV_IS_SET(IPC, ISH_IPC_BUSY_CLEAR_AGENT, ISH2AGENT_BUSY_CLEAR, 1,
541 ®s->ish_ipc_busy_clear_agent)) {
542 /*set 1 to clear this interrupt*/
543 SEDI_PREG_RBFV_SET(IPC, ISH_IPC_BUSY_CLEAR_AGENT, ISH2AGENT_BUSY_CLEAR, 1,
544 ®s->ish_ipc_busy_clear_agent);
545 if ((ipc_contexts[ipc_device].initialized == true) &&
546 (ipc_contexts[ipc_device].cb_event)) {
547 ipc_contexts[ipc_device].out_msg_count++;
548 ipc_contexts[ipc_device].cb_event(ipc_device, SEDI_IPC_EVENT_MSG_PEER_ACKED,
549 ipc_contexts[ipc_device].usr_params);
550 }
551 if (ipc_device == SEDI_IPC_HOST) {
552 PM_VNN_DRIVER_DEREQ(ipc_resource[ipc_device].write_vnn);
553 }
554 }
555
556 /* check whether it is a csr interrupt */
557 if ((ipc_device != SEDI_IPC_HOST) && (regs->agent2ish_csr_agent != 0)) {
558 ipc_contexts[ipc_device].csr_saved = regs->agent2ish_csr_agent;
559 /* write back to clear the interrupt */
560 regs->agent2ish_csr_agent = ipc_contexts[ipc_device].csr_saved;
561 if ((ipc_contexts[ipc_device].initialized == true) &&
562 (ipc_contexts[ipc_device].cb_event)) {
563 ipc_contexts[ipc_device].cb_event(ipc_device, SEDI_IPC_EVENT_CSR_ACK,
564 ipc_contexts[ipc_device].usr_params);
565 }
566 }
567 }
568