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)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 sunxi_msgbox_peek_data(unsigned int chan)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 mhu_secure_message_start(unsigned int slot_id __unused)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 mhu_secure_message_send(unsigned int slot_id)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 mhu_secure_message_wait(void)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 mhu_secure_message_end(unsigned int slot_id)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 } 96