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