From e9cdc6374dc730dc61d2a8a81beabe563ad7fe88 Mon Sep 17 00:00:00 2001 From: Yulia Garbovich Date: Tue, 23 Nov 2021 20:00:04 +0200 Subject: Add mpu driver and remove interface library from drivers Add mpu driver for upstreaming After removing of interface library,targets and applications will list explicitly which libraries to link Change-Id: Icfa449a2981093161f283e45b4d52ca6199371b8 --- drivers/mhu_v2/src/mhu_v2.cpp | 209 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 drivers/mhu_v2/src/mhu_v2.cpp (limited to 'drivers/mhu_v2/src') diff --git a/drivers/mhu_v2/src/mhu_v2.cpp b/drivers/mhu_v2/src/mhu_v2.cpp new file mode 100644 index 0000000..1144a0f --- /dev/null +++ b/drivers/mhu_v2/src/mhu_v2.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2020-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ethosu_log.h" + +#include + +#include +#include +#include +#include +#include + +namespace Mailbox { + +MHUv2::MHUv2(const uint32_t txBaseAddress, const uint32_t rxBaseAddress) : + txBaseAddr(reinterpret_cast(txBaseAddress)), + rxBaseAddr(reinterpret_cast(rxBaseAddress)) { + + setCombinedRecvInterrupt(true); + enableAccessRequest(); // Set high throughout +} + +void MHUv2::handleMessage() { + clearMessage(); + notify(); +} + +MHUv2::~MHUv2() { + setCombinedRecvInterrupt(false); + disableAccessRequest(); +} + +bool MHUv2::verifyHardware() { + // Sanity check MHUv2.1 id's (tx/rx) + struct aidr_t *a; + uint32_t txAIDR = getTxAIDR(); + uint32_t rxAIDR = getRxAIDR(); + + a = reinterpret_cast(&txAIDR); + if (a->ARCH_MAJOR_REV != 1 || a->ARCH_MINOR_REV != 1) { + return false; + } + + a = reinterpret_cast(&rxAIDR); + if (a->ARCH_MAJOR_REV != 1 || a->ARCH_MINOR_REV != 1) { + return false; + } + + return true; +} + +uint32_t MHUv2::getTxStatusForChan(uint8_t chan) { + assert(chan >= 0); + assert(chan < 124); + return txRead((chan * MHUv2_SND_CHAN_WINDOW_SIZE) + MHUv2_CH_ST); +} + +uint32_t MHUv2::getRxStatusForChan(uint8_t chan) { + assert(chan >= 0); + assert(chan < 124); + return rxRead((chan * MHUv2_RCV_CHAN_WINDOW_SIZE) + MHUv2_CH_ST); +} + +uint32_t MHUv2::getInterruptStatus() { + return txRead(MHUv2_SND_INT_ST_OFFS); +} + +uint32_t MHUv2::getAccessReady() { + return txRead(MHUv2_SND_ACCESS_READY_OFFS); +} + +uint32_t MHUv2::getAccessRequest() { + return txRead(MHUv2_SND_ACCESS_REQUEST_OFFS); +} + +uint32_t MHUv2::getTxAIDR() { + return txRead(MHUv2_SND_AIDR_OFFS); +} + +uint32_t MHUv2::getRxAIDR() { + return rxRead(MHUv2_RCV_AIDR_OFFS); +} + +void MHUv2::enableAccessRequest() { + txWrite(MHUv2_SND_ACCESS_REQUEST_OFFS, 1); +} + +void MHUv2::disableAccessRequest() { + txWrite(MHUv2_SND_ACCESS_REQUEST_OFFS, 0); +} + +/* + * MHUv2.1 + * sender: combined clear interrupt + */ +void MHUv2::setCombinedClearInterrupt(bool enable) { + uint32_t val = txRead(MHUv2_SND_INT_EN_OFFS); + if (enable) { + val |= (1 << 2); + } else { + val &= ~(1 << 2); + } + txWrite(MHUv2_SND_INT_EN_OFFS, val); +} + +/* + * MHUv2.1 + * receiver: combined recv interrupt + */ +void MHUv2::setCombinedRecvInterrupt(bool enable) { + uint32_t val = rxRead(MHUv2_RCV_INT_EN_OFFS); + if (enable) { + val |= (1 << 2); + } else { + val &= ~(1 << 2); + } + rxWrite(MHUv2_SND_INT_EN_OFFS, val); +} + +// Enable/disable R2NR/NR2R interrupts +void MHUv2::setReadyNotReadyInterrupts(bool enable) { + uint32_t val = txRead(MHUv2_SND_INT_EN_OFFS); + if (enable) { + val |= (1 << 0 | 1 << 1); + } else { + val &= ~(1 << 0 | 1 << 1); + } + txWrite(MHUv2_SND_INT_EN_OFFS, val); +} + +void MHUv2::enableClearChanInterrupt(uint8_t chan) { + assert(chan >= 0); + assert(chan < 124); + txWrite((chan * MHUv2_SND_CHAN_WINDOW_SIZE) + MHUv2_CH_INT_EN, 1); +} + +void MHUv2::disableClearChanInterrupt(uint8_t chan) { + assert(chan >= 0); + assert(chan < 124); + txWrite((chan * MHUv2_SND_CHAN_WINDOW_SIZE) + MHUv2_CH_INT_EN, 0); +} + +/* + * Set channel status byte (with only minor error/state check(s)) + * Doorbell only, chan 0 + */ +bool MHUv2::sendMessage() { + // Check that the other end is ready to receive + if (!getAccessReady()) { + return false; + } + txWrite(MHUv2_CH_SET, 1); + + return true; +} + +void MHUv2::clearMessage() { + rxWrite(MHUv2_CH_CLR, 0xFFFFFFFF); // Doorbell uses only chan 0, but clear all 32bits to be safe +} + +void MHUv2::txWrite(uint32_t offset, uint32_t value) { + write32(txBaseAddr, offset, value); +} + +void MHUv2::rxWrite(uint32_t offset, uint32_t value) { + write32(rxBaseAddr, offset, value); +} + +uint32_t MHUv2::txRead(uint32_t offset) { + return read32(txBaseAddr, offset); +} + +uint32_t MHUv2::rxRead(uint32_t offset) { + return read32(rxBaseAddr, offset); +} + +void MHUv2::printAIDR(bool tx, bool rx) { + struct aidr_t *a; + uint32_t aidr; + + if (tx) { + aidr = getTxAIDR(); + a = reinterpret_cast(&aidr); + LOG_INFO("TX MHUv2 reports: Major rev: %d, Minor rev: %d", a->ARCH_MAJOR_REV, a->ARCH_MINOR_REV); + } + if (rx) { + aidr = getRxAIDR(); + a = reinterpret_cast(&aidr); + LOG_INFO("RX MHUv2 reports: Major rev: %d, Minor rev: %d", a->ARCH_MAJOR_REV, a->ARCH_MINOR_REV); + } +} + +} // namespace Mailbox -- cgit v1.2.1