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