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/psci/psci.h> 12 #include <lib/mmio.h> 13 14 #include <mss_pm_ipc.h> 15 16 /* 17 * SISR is 32 bit interrupt register representing 32 interrupts 18 * 19 * +======+=============+=============+ 20 * + Bits + 31 + 30 - 00 + 21 * +======+=============+=============+ 22 * + Desc + MSS Msg Int + Reserved + 23 * +======+=============+=============+ 24 */ 25 #define MSS_SISR (MVEBU_REGS_BASE + 0x5800D0) 26 #define MSS_SISTR (MVEBU_REGS_BASE + 0x5800D8) 27 28 #define MSS_MSG_INT_MASK (0x80000000) 29 #define MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110) 30 #define MSS_TRIGGER_TIMEOUT (2000) 31 32 /***************************************************************************** 33 * mss_pm_ipc_msg_send 34 * 35 * DESCRIPTION: create and transmit IPC message 36 ***************************************************************************** 37 */ mss_pm_ipc_msg_send(unsigned int channel_id,unsigned int msg_id,const psci_power_state_t * target_state)38int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id, 39 const psci_power_state_t *target_state) 40 { 41 /* Transmit IPC message */ 42 #ifndef DISABLE_CLUSTER_LEVEL 43 mv_pm_ipc_msg_tx(channel_id, msg_id, 44 (unsigned int)target_state->pwr_domain_state[ 45 MPIDR_AFFLVL1]); 46 #else 47 mv_pm_ipc_msg_tx(channel_id, msg_id, 0); 48 #endif 49 50 return 0; 51 } 52 53 /***************************************************************************** 54 * mss_pm_ipc_msg_trigger 55 * 56 * DESCRIPTION: Trigger IPC message interrupt to MSS 57 ***************************************************************************** 58 */ mss_pm_ipc_msg_trigger(void)59int mss_pm_ipc_msg_trigger(void) 60 { 61 unsigned int timeout; 62 unsigned int t_end; 63 unsigned int t_start = mmio_read_32(MSS_TIMER_BASE); 64 65 mmio_write_32(MSS_SISR, MSS_MSG_INT_MASK); 66 67 do { 68 /* wait while SCP process incoming interrupt */ 69 if (mmio_read_32(MSS_SISTR) != MSS_MSG_INT_MASK) 70 break; 71 72 /* check timeout */ 73 t_end = mmio_read_32(MSS_TIMER_BASE); 74 75 timeout = ((t_start > t_end) ? 76 (t_start - t_end) : (t_end - t_start)); 77 if (timeout > MSS_TRIGGER_TIMEOUT) { 78 ERROR("PM MSG Trigger Timeout\n"); 79 break; 80 } 81 82 } while (1); 83 84 return 0; 85 } 86