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