1 /* 2 * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stdlib.h> 8 9 #include <lib/bakery_lock.h> 10 11 #include <sci/sci_scfw.h> 12 #include <sci/sci_ipc.h> 13 #include <sci/sci_rpc.h> 14 #include "imx8_mu.h" 15 16 sc_ipc_t ipc_handle; 17 18 DEFINE_BAKERY_LOCK(sc_ipc_bakery_lock); 19 #define sc_ipc_lock_init() bakery_lock_init(&sc_ipc_bakery_lock) 20 #define sc_ipc_lock() bakery_lock_get(&sc_ipc_bakery_lock) 21 #define sc_ipc_unlock() bakery_lock_release(&sc_ipc_bakery_lock) 22 23 void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp) 24 { 25 sc_ipc_lock(); 26 27 sc_ipc_write(ipc, msg); 28 if (!no_resp) 29 sc_ipc_read(ipc, msg); 30 31 sc_ipc_unlock(); 32 } 33 34 sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id) 35 { 36 uint32_t base = id; 37 uint32_t i; 38 39 /* Get MU base associated with IPC channel */ 40 if ((ipc == NULL) || (base == 0)) 41 return SC_ERR_IPC; 42 43 sc_ipc_lock_init(); 44 45 /* Init MU */ 46 MU_Init(base); 47 48 /* Enable all RX interrupts */ 49 for (i = 0; i < MU_RR_COUNT; i++) { 50 MU_EnableRxFullInt(base, i); 51 } 52 53 /* Return MU address as handle */ 54 *ipc = (sc_ipc_t) id; 55 56 return SC_ERR_NONE; 57 } 58 59 void sc_ipc_close(sc_ipc_t ipc) 60 { 61 uint32_t base = ipc; 62 63 if (base != 0) 64 MU_Init(base); 65 } 66 67 void sc_ipc_read(sc_ipc_t ipc, void *data) 68 { 69 uint32_t base = ipc; 70 sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data; 71 uint8_t count = 0; 72 73 /* Check parms */ 74 if ((base == 0) || (msg == NULL)) 75 return; 76 77 /* Read first word */ 78 MU_ReceiveMsg(base, 0, (uint32_t *) msg); 79 count++; 80 81 /* Check size */ 82 if (msg->size > SC_RPC_MAX_MSG) { 83 *((uint32_t *) msg) = 0; 84 return; 85 } 86 87 /* Read remaining words */ 88 while (count < msg->size) { 89 MU_ReceiveMsg(base, count % MU_RR_COUNT, 90 &(msg->DATA.u32[count - 1])); 91 count++; 92 } 93 } 94 95 void sc_ipc_write(sc_ipc_t ipc, void *data) 96 { 97 sc_rpc_msg_t *msg = (sc_rpc_msg_t *) data; 98 uint32_t base = ipc; 99 uint8_t count = 0; 100 101 /* Check parms */ 102 if ((base == 0) || (msg == NULL)) 103 return; 104 105 /* Check size */ 106 if (msg->size > SC_RPC_MAX_MSG) 107 return; 108 109 /* Write first word */ 110 MU_SendMessage(base, 0, *((uint32_t *) msg)); 111 count++; 112 113 /* Write remaining words */ 114 while (count < msg->size) { 115 MU_SendMessage(base, count % MU_TR_COUNT, 116 msg->DATA.u32[count - 1]); 117 count++; 118 } 119 } 120 121