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