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