| /* |
| * Copyright 2017 NXP |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following disclaimer. |
| * |
| * Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * Neither the name of NXP nor the names of its contributors may be used |
| * to endorse or promote products derived from this software without specific |
| * prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <sci/scfw.h> |
| #include <sci/ipc.h> |
| #include <sci/rpc.h> |
| #include <stdlib.h> |
| |
| #include "mx8_mu.h" |
| |
| #include <bakery_lock.h> |
| DEFINE_BAKERY_LOCK(sc_ipc_bakery_lock); |
| #define sc_ipc_lock_init() bakery_lock_init(&sc_ipc_bakery_lock) |
| #define sc_ipc_lock() bakery_lock_get(&sc_ipc_bakery_lock) |
| #define sc_ipc_unlock() bakery_lock_release(&sc_ipc_bakery_lock) |
| |
| void sc_call_rpc(sc_ipc_t ipc, sc_rpc_msg_t *msg, bool no_resp) |
| { |
| sc_ipc_lock(); |
| |
| sc_ipc_write(ipc, msg); |
| if (!no_resp) |
| sc_ipc_read(ipc, msg); |
| |
| sc_ipc_unlock(); |
| } |
| |
| sc_err_t sc_ipc_open(sc_ipc_t *ipc, sc_ipc_id_t id) |
| { |
| uint32_t base = id; |
| uint32_t i; |
| |
| /* Get MU base associated with IPC channel */ |
| if ((ipc == NULL) || (base == 0)) |
| return SC_ERR_IPC; |
| |
| sc_ipc_lock_init(); |
| |
| /* Init MU */ |
| MU_Init(base); |
| |
| /* Enable all RX interrupts */ |
| for (i = 0; i < MU_RR_COUNT; i++) { |
| MU_EnableRxFullInt(base, i); |
| } |
| |
| /* Return MU address as handle */ |
| *ipc = (sc_ipc_t) id; |
| |
| return SC_ERR_NONE; |
| } |
| |
| void sc_ipc_close(sc_ipc_t ipc) |
| { |
| uint32_t base = ipc; |
| |
| if (base != 0) |
| MU_Init(base); |
| } |
| |
| void sc_ipc_read(sc_ipc_t ipc, void *data) |
| { |
| uint32_t base = ipc; |
| sc_rpc_msg_t *msg = (sc_rpc_msg_t*) data; |
| uint8_t count = 0; |
| |
| /* Check parms */ |
| if ((base == 0) || (msg == NULL)) |
| return; |
| |
| /* Read first word */ |
| MU_ReceiveMsg(base, 0, (uint32_t*) msg); |
| count++; |
| |
| /* Check size */ |
| if (msg->size > SC_RPC_MAX_MSG) { |
| *((uint32_t*) msg) = 0; |
| return; |
| } |
| |
| /* Read remaining words */ |
| while (count < msg->size) { |
| MU_ReceiveMsg(base, count % MU_RR_COUNT, |
| &(msg->DATA.u32[count - 1])); |
| count++; |
| } |
| } |
| |
| void sc_ipc_write(sc_ipc_t ipc, void *data) |
| { |
| sc_rpc_msg_t *msg = (sc_rpc_msg_t*) data; |
| uint32_t base = ipc; |
| uint8_t count = 0; |
| |
| /* Check parms */ |
| if ((base == 0) || (msg == NULL)) |
| return; |
| |
| /* Check size */ |
| if (msg->size > SC_RPC_MAX_MSG) |
| return; |
| |
| /* Write first word */ |
| MU_SendMessage(base, 0, *((uint32_t*) msg)); |
| count++; |
| |
| /* Write remaining words */ |
| while (count < msg->size) { |
| MU_SendMessage(base, count % MU_TR_COUNT, |
| msg->DATA.u32[count - 1]); |
| count++; |
| } |
| } |
| |