mss_pm_ipc.c 2.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
/*
 * Copyright (C) 2018 Marvell International Ltd.
 *
 * SPDX-License-Identifier:     BSD-3-Clause
 * https://spdx.org/licenses
 */

#include <string.h>

10
11
12
13
#include <common/debug.h>
#include <lib/psci/psci.h>
#include <lib/mmio.h>

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <mss_pm_ipc.h>

/*
 * SISR is 32 bit interrupt register representing 32 interrupts
 *
 * +======+=============+=============+
 * + Bits + 31          + 30 - 00     +
 * +======+=============+=============+
 * + Desc + MSS Msg Int + Reserved    +
 * +======+=============+=============+
 */
#define MSS_SISR		(MVEBU_REGS_BASE + 0x5800D0)
#define MSS_SISTR		(MVEBU_REGS_BASE + 0x5800D8)

#define MSS_MSG_INT_MASK	(0x80000000)
#define MSS_TIMER_BASE		(MVEBU_REGS_BASE_MASK + 0x580110)
30
#define MSS_TRIGGER_TIMEOUT	(2000)
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

/*****************************************************************************
 * mss_pm_ipc_msg_send
 *
 * DESCRIPTION: create and transmit IPC message
 *****************************************************************************
 */
int mss_pm_ipc_msg_send(unsigned int channel_id, unsigned int msg_id,
			const psci_power_state_t *target_state)
{
	/* Transmit IPC message */
#ifndef DISABLE_CLUSTER_LEVEL
	mv_pm_ipc_msg_tx(channel_id, msg_id,
			 (unsigned int)target_state->pwr_domain_state[
					MPIDR_AFFLVL1]);
#else
	mv_pm_ipc_msg_tx(channel_id, msg_id, 0);
#endif

	return 0;
}

/*****************************************************************************
 * mss_pm_ipc_msg_trigger
 *
 * DESCRIPTION: Trigger IPC message interrupt to MSS
 *****************************************************************************
 */
int mss_pm_ipc_msg_trigger(void)
{
	unsigned int timeout;
	unsigned int t_end;
	unsigned int t_start = mmio_read_32(MSS_TIMER_BASE);

	mmio_write_32(MSS_SISR, MSS_MSG_INT_MASK);

	do {
		/* wait while SCP process incoming interrupt */
		if (mmio_read_32(MSS_SISTR) != MSS_MSG_INT_MASK)
			break;

		/* check timeout */
		t_end = mmio_read_32(MSS_TIMER_BASE);

		timeout = ((t_start > t_end) ?
			   (t_start - t_end) : (t_end - t_start));
		if (timeout > MSS_TRIGGER_TIMEOUT) {
			ERROR("PM MSG Trigger Timeout\n");
			break;
		}

	} while (1);

	return 0;
}