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