1 /* 2 * Copyright (C) 2018 Marvell International Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * https://spdx.org/licenses 6 */ 7 8 #include <string.h> 9 10 #include <common/debug.h> 11 #include <lib/mmio.h> 12 13 #include <plat_marvell.h> 14 #include <mss_ipc_drv.h> 15 16 #define IPC_MSG_BASE_MASK MVEBU_REGS_BASE_MASK 17 18 #define IPC_CH_NUM_OF_MSG (16) 19 #define IPC_CH_MSG_IDX (-1) 20 21 unsigned long mv_pm_ipc_msg_base; 22 unsigned int mv_pm_ipc_queue_size; 23 24 unsigned int msg_sync; 25 int msg_index = IPC_CH_MSG_IDX; 26 27 /****************************************************************************** 28 * mss_pm_ipc_init 29 * 30 * DESCRIPTION: Initialize PM IPC infrastructure 31 ****************************************************************************** 32 */ 33 int mv_pm_ipc_init(unsigned long ipc_control_addr) 34 { 35 struct mss_pm_ipc_ctrl *ipc_control = 36 (struct mss_pm_ipc_ctrl *)ipc_control_addr; 37 38 /* Initialize PM IPC control block */ 39 mv_pm_ipc_msg_base = ipc_control->msg_base_address | 40 IPC_MSG_BASE_MASK; 41 mv_pm_ipc_queue_size = ipc_control->queue_size; 42 43 return 0; 44 } 45 46 /****************************************************************************** 47 * mv_pm_ipc_queue_addr_get 48 * 49 * DESCRIPTION: Returns the IPC queue address 50 ****************************************************************************** 51 */ 52 unsigned int mv_pm_ipc_queue_addr_get(void) 53 { 54 unsigned int addr; 55 56 inv_dcache_range((uint64_t)&msg_index, sizeof(msg_index)); 57 msg_index = msg_index + 1; 58 if (msg_index >= IPC_CH_NUM_OF_MSG) 59 msg_index = 0; 60 61 addr = (unsigned int)(mv_pm_ipc_msg_base + 62 (msg_index * mv_pm_ipc_queue_size)); 63 64 flush_dcache_range((uint64_t)&msg_index, sizeof(msg_index)); 65 66 return addr; 67 } 68 69 /****************************************************************************** 70 * mv_pm_ipc_msg_rx 71 * 72 * DESCRIPTION: Retrieve message from IPC channel 73 ****************************************************************************** 74 */ 75 int mv_pm_ipc_msg_rx(unsigned int channel_id, struct mss_pm_ipc_msg *msg) 76 { 77 unsigned int addr = mv_pm_ipc_queue_addr_get(); 78 79 msg->msg_reply = mmio_read_32(addr + IPC_MSG_REPLY_LOC); 80 81 return 0; 82 } 83 84 /****************************************************************************** 85 * mv_pm_ipc_msg_tx 86 * 87 * DESCRIPTION: Send message via IPC channel 88 ****************************************************************************** 89 */ 90 int mv_pm_ipc_msg_tx(unsigned int channel_id, unsigned int msg_id, 91 unsigned int cluster_power_state) 92 { 93 unsigned int addr = mv_pm_ipc_queue_addr_get(); 94 95 /* Validate the entry for message placed by the host is free */ 96 if (mmio_read_32(addr + IPC_MSG_STATE_LOC) == IPC_MSG_FREE) { 97 inv_dcache_range((uint64_t)&msg_sync, sizeof(msg_sync)); 98 msg_sync = msg_sync + 1; 99 flush_dcache_range((uint64_t)&msg_sync, sizeof(msg_sync)); 100 101 mmio_write_32(addr + IPC_MSG_SYNC_ID_LOC, msg_sync); 102 mmio_write_32(addr + IPC_MSG_ID_LOC, msg_id); 103 mmio_write_32(addr + IPC_MSG_CPU_ID_LOC, channel_id); 104 mmio_write_32(addr + IPC_MSG_POWER_STATE_LOC, 105 cluster_power_state); 106 mmio_write_32(addr + IPC_MSG_STATE_LOC, IPC_MSG_OCCUPY); 107 108 } else { 109 ERROR("%s: FAILED\n", __func__); 110 } 111 112 return 0; 113 } 114