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