blob: cc4a6ffcbe480b3a2c929618558d42b5a222581f [file] [log] [blame]
Samuel Holland74703702018-10-21 12:24:16 -05001/*
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
41static DEFINE_BAKERY_LOCK(mhu_secure_message_lock);
42
43static 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
50static 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
57void 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
68void 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
73uint32_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
89void 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}