xref: /rk3399_ARM-atf/drivers/allwinner/sunxi_msgbox.c (revision fbe228b1c1df062b8a2fd2bcd15476421e4209de)
1*50cabf6dSSamuel Holland /*
2*50cabf6dSSamuel Holland  * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
3*50cabf6dSSamuel Holland  *
4*50cabf6dSSamuel Holland  * SPDX-License-Identifier: BSD-3-Clause
5*50cabf6dSSamuel Holland  */
6*50cabf6dSSamuel Holland 
7*50cabf6dSSamuel Holland #include <assert.h>
8*50cabf6dSSamuel Holland #include <stdbool.h>
9*50cabf6dSSamuel Holland 
10*50cabf6dSSamuel Holland #include <drivers/delay_timer.h>
11*50cabf6dSSamuel Holland #include <lib/bakery_lock.h>
12*50cabf6dSSamuel Holland #include <lib/mmio.h>
13*50cabf6dSSamuel Holland #include <lib/utils_def.h>
14*50cabf6dSSamuel Holland 
15*50cabf6dSSamuel Holland #include <sunxi_mmap.h>
16*50cabf6dSSamuel Holland 
17*50cabf6dSSamuel Holland #define REMOTE_IRQ_EN_REG	0x0040
18*50cabf6dSSamuel Holland #define REMOTE_IRQ_STAT_REG	0x0050
19*50cabf6dSSamuel Holland #define LOCAL_IRQ_EN_REG	0x0060
20*50cabf6dSSamuel Holland #define LOCAL_IRQ_STAT_REG	0x0070
21*50cabf6dSSamuel Holland 
22*50cabf6dSSamuel Holland #define RX_IRQ(n)		BIT(0 + 2 * (n))
23*50cabf6dSSamuel Holland #define TX_IRQ(n)		BIT(1 + 2 * (n))
24*50cabf6dSSamuel Holland 
25*50cabf6dSSamuel Holland #define FIFO_STAT_REG(n)	(0x0100 + 0x4 * (n))
26*50cabf6dSSamuel Holland #define FIFO_STAT_MASK		GENMASK(0, 0)
27*50cabf6dSSamuel Holland 
28*50cabf6dSSamuel Holland #define MSG_STAT_REG(n)		(0x0140 + 0x4 * (n))
29*50cabf6dSSamuel Holland #define MSG_STAT_MASK		GENMASK(2, 0)
30*50cabf6dSSamuel Holland 
31*50cabf6dSSamuel Holland #define MSG_DATA_REG(n)		(0x0180 + 0x4 * (n))
32*50cabf6dSSamuel Holland 
33*50cabf6dSSamuel Holland #define RX_CHAN			1
34*50cabf6dSSamuel Holland #define TX_CHAN			0
35*50cabf6dSSamuel Holland 
36*50cabf6dSSamuel Holland #define MHU_MAX_SLOT_ID		31
37*50cabf6dSSamuel Holland 
38*50cabf6dSSamuel Holland #define MHU_TIMEOUT_DELAY	10
39*50cabf6dSSamuel Holland #define MHU_TIMEOUT_ITERS	10000
40*50cabf6dSSamuel Holland 
41*50cabf6dSSamuel Holland static DEFINE_BAKERY_LOCK(mhu_secure_message_lock);
42*50cabf6dSSamuel Holland 
sunxi_msgbox_last_tx_done(unsigned int chan)43*50cabf6dSSamuel Holland static bool sunxi_msgbox_last_tx_done(unsigned int chan)
44*50cabf6dSSamuel Holland {
45*50cabf6dSSamuel Holland 	uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + REMOTE_IRQ_STAT_REG);
46*50cabf6dSSamuel Holland 
47*50cabf6dSSamuel Holland 	return (stat & RX_IRQ(chan)) == 0U;
48*50cabf6dSSamuel Holland }
49*50cabf6dSSamuel Holland 
sunxi_msgbox_peek_data(unsigned int chan)50*50cabf6dSSamuel Holland static bool sunxi_msgbox_peek_data(unsigned int chan)
51*50cabf6dSSamuel Holland {
52*50cabf6dSSamuel Holland 	uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_STAT_REG(chan));
53*50cabf6dSSamuel Holland 
54*50cabf6dSSamuel Holland 	return (stat & MSG_STAT_MASK) != 0U;
55*50cabf6dSSamuel Holland }
56*50cabf6dSSamuel Holland 
mhu_secure_message_start(unsigned int slot_id __unused)57*50cabf6dSSamuel Holland void mhu_secure_message_start(unsigned int slot_id __unused)
58*50cabf6dSSamuel Holland {
59*50cabf6dSSamuel Holland 	uint32_t timeout = MHU_TIMEOUT_ITERS;
60*50cabf6dSSamuel Holland 
61*50cabf6dSSamuel Holland 	bakery_lock_get(&mhu_secure_message_lock);
62*50cabf6dSSamuel Holland 
63*50cabf6dSSamuel Holland 	/* Wait for all previous messages to be acknowledged. */
64*50cabf6dSSamuel Holland 	while (!sunxi_msgbox_last_tx_done(TX_CHAN) && --timeout)
65*50cabf6dSSamuel Holland 		udelay(MHU_TIMEOUT_DELAY);
66*50cabf6dSSamuel Holland }
67*50cabf6dSSamuel Holland 
mhu_secure_message_send(unsigned int slot_id)68*50cabf6dSSamuel Holland void mhu_secure_message_send(unsigned int slot_id)
69*50cabf6dSSamuel Holland {
70*50cabf6dSSamuel Holland 	mmio_write_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(TX_CHAN), BIT(slot_id));
71*50cabf6dSSamuel Holland }
72*50cabf6dSSamuel Holland 
mhu_secure_message_wait(void)73*50cabf6dSSamuel Holland uint32_t mhu_secure_message_wait(void)
74*50cabf6dSSamuel Holland {
75*50cabf6dSSamuel Holland 	uint32_t timeout = MHU_TIMEOUT_ITERS;
76*50cabf6dSSamuel Holland 	uint32_t msg = 0;
77*50cabf6dSSamuel Holland 
78*50cabf6dSSamuel Holland 	/* Wait for a message from the SCP. */
79*50cabf6dSSamuel Holland 	while (!sunxi_msgbox_peek_data(RX_CHAN) && --timeout)
80*50cabf6dSSamuel Holland 		udelay(MHU_TIMEOUT_DELAY);
81*50cabf6dSSamuel Holland 
82*50cabf6dSSamuel Holland 	/* Return the most recent message in the FIFO. */
83*50cabf6dSSamuel Holland 	while (sunxi_msgbox_peek_data(RX_CHAN))
84*50cabf6dSSamuel Holland 		msg = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(RX_CHAN));
85*50cabf6dSSamuel Holland 
86*50cabf6dSSamuel Holland 	return msg;
87*50cabf6dSSamuel Holland }
88*50cabf6dSSamuel Holland 
mhu_secure_message_end(unsigned int slot_id)89*50cabf6dSSamuel Holland void mhu_secure_message_end(unsigned int slot_id)
90*50cabf6dSSamuel Holland {
91*50cabf6dSSamuel Holland 	/* Acknowledge a response by clearing the IRQ status. */
92*50cabf6dSSamuel Holland 	mmio_write_32(SUNXI_MSGBOX_BASE + LOCAL_IRQ_STAT_REG, RX_IRQ(RX_CHAN));
93*50cabf6dSSamuel Holland 
94*50cabf6dSSamuel Holland 	bakery_lock_release(&mhu_secure_message_lock);
95*50cabf6dSSamuel Holland }
96