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