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