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