From 9fc527b8b01847b16a8aa577dec4c6d9401a2ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonny=20Sv=C3=A4rd?= Date: Mon, 16 Nov 2020 16:18:07 +0100 Subject: Add basic MHU drivers Add MHUv2 doorbell driver implementation Add MHU doorbell driver for Juno board Add a dummy MHU driver Add some comments to the mailbox header file Change-Id: I0950a7ca3afeec88ca691ca2486022dfbb3319b8 --- applications/message_process/CMakeLists.txt | 2 +- drivers/CMakeLists.txt | 11 +- drivers/mailbox/CMakeLists.txt | 7 +- drivers/mailbox/include/mailbox.hpp | 46 ++++++- drivers/mhu_dummy/CMakeLists.txt | 23 ++++ drivers/mhu_dummy/include/mhu_dummy.hpp | 36 +++++ drivers/mhu_dummy/src/mhu_dummy.cc | 33 +++++ drivers/mhu_juno/CMakeLists.txt | 23 ++++ drivers/mhu_juno/include/mhu_juno.hpp | 66 +++++++++ drivers/mhu_juno/src/mhu_juno.cc | 76 ++++++++++ drivers/mhu_v2/CMakeLists.txt | 23 ++++ drivers/mhu_v2/include/mhu_v2.hpp | 169 +++++++++++++++++++++++ drivers/mhu_v2/src/mhu_v2.cc | 207 ++++++++++++++++++++++++++++ 13 files changed, 715 insertions(+), 7 deletions(-) create mode 100644 drivers/mhu_dummy/CMakeLists.txt create mode 100644 drivers/mhu_dummy/include/mhu_dummy.hpp create mode 100644 drivers/mhu_dummy/src/mhu_dummy.cc create mode 100644 drivers/mhu_juno/CMakeLists.txt create mode 100644 drivers/mhu_juno/include/mhu_juno.hpp create mode 100644 drivers/mhu_juno/src/mhu_juno.cc create mode 100644 drivers/mhu_v2/CMakeLists.txt create mode 100644 drivers/mhu_v2/include/mhu_v2.hpp create mode 100644 drivers/mhu_v2/src/mhu_v2.cc diff --git a/applications/message_process/CMakeLists.txt b/applications/message_process/CMakeLists.txt index 9c80672..2f7e5cf 100644 --- a/applications/message_process/CMakeLists.txt +++ b/applications/message_process/CMakeLists.txt @@ -18,4 +18,4 @@ add_library(message_process STATIC src/message_process.cc) target_include_directories(message_process PUBLIC include ${LINUX_DRIVER_STACK_PATH}/kernel) -target_link_libraries(message_process PRIVATE cmsis_core inference_process mailbox) +target_link_libraries(message_process PRIVATE cmsis_core inference_process ethosu_mailbox) diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index cea6325..c130a26 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -20,4 +20,13 @@ add_library(ethosu_drivers INTERFACE) # Mailbox driver add_subdirectory(mailbox) -target_link_libraries(ethosu_drivers INTERFACE mailbox) +target_link_libraries(ethosu_drivers INTERFACE ethosu_mailbox) + +# MHU drivers +add_subdirectory(mhu_v2) +add_subdirectory(mhu_juno) +add_subdirectory(mhu_dummy) +target_link_libraries(ethosu_drivers INTERFACE ethosu_mhu_v2) +target_link_libraries(ethosu_drivers INTERFACE ethosu_mhu_juno) +target_link_libraries(ethosu_drivers INTERFACE ethosu_mhu_dummy) + diff --git a/drivers/mailbox/CMakeLists.txt b/drivers/mailbox/CMakeLists.txt index 6d55407..bd2dae3 100644 --- a/drivers/mailbox/CMakeLists.txt +++ b/drivers/mailbox/CMakeLists.txt @@ -16,7 +16,6 @@ # limitations under the License. # -add_library(mailbox STATIC) -target_include_directories(mailbox PUBLIC include) -target_sources(mailbox PRIVATE src/mailbox.cc) - +add_library(ethosu_mailbox STATIC) +target_include_directories(ethosu_mailbox PUBLIC include) +target_sources(ethosu_mailbox PRIVATE src/mailbox.cc) diff --git a/drivers/mailbox/include/mailbox.hpp b/drivers/mailbox/include/mailbox.hpp index 465503e..f3a2dc4 100644 --- a/drivers/mailbox/include/mailbox.hpp +++ b/drivers/mailbox/include/mailbox.hpp @@ -25,19 +25,63 @@ namespace Mailbox { +/** + * The Mailbox parent class + * + * Intended to be implemented by a driver subclass, see MHU_v2 driver as example. + */ class Mailbox { public: + /** + * Constructor/Destructor + */ Mailbox(); virtual ~Mailbox(); - virtual bool sendMessage() = 0; + + /** + * Intended to trigger an interrupt to an external block + * MUST be implemented by subclass. + */ + virtual bool sendMessage() = 0; + + /** + * Intended to be called when Cortex M has received an + * interrupt/event from mailbox/mhu. If an interrupt needs to be cleared, + * this is a good place to do that. MUST call notify(). + * MUST be implemented by subclass. + */ virtual void handleMessage() = 0; + + /** + * Can be used to verify that hardware versions match expected versions + * CAN be implemented by subclass, optional. Default impl returns true. + */ virtual bool verifyHardware(); + + /** + * Function signature for callbacks + */ typedef void (*CallbackFptr)(void *userArg); + + /** + * Register a callback to be called when a message is received. + */ void registerCallback(CallbackFptr callback, void *userArg); + + /** + * Remove a specific callback from the callback list. + */ void deregisterCallback(CallbackFptr callback, void *userArg); protected: + /** + * Calls every registered callback when a message has been received. + */ void notify(); + + /** + * Helper functions + */ uint32_t read32(volatile uint32_t *baseAddr, const uint32_t offset); void write32(volatile uint32_t *baseAddr, const uint32_t offset, const uint32_t value); diff --git a/drivers/mhu_dummy/CMakeLists.txt b/drivers/mhu_dummy/CMakeLists.txt new file mode 100644 index 0000000..83943d6 --- /dev/null +++ b/drivers/mhu_dummy/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (c) 2020 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. +# + +add_library(ethosu_mhu_dummy STATIC) +target_include_directories(ethosu_mhu_dummy PUBLIC include) + +target_sources(ethosu_mhu_dummy PRIVATE src/mhu_dummy.cc) +target_link_libraries(ethosu_mhu_dummy PRIVATE ethosu_mailbox) diff --git a/drivers/mhu_dummy/include/mhu_dummy.hpp b/drivers/mhu_dummy/include/mhu_dummy.hpp new file mode 100644 index 0000000..365f392 --- /dev/null +++ b/drivers/mhu_dummy/include/mhu_dummy.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef MHU_DUMMY_HPP +#define MHU_DUMMY_HPP + +#include + +namespace Mailbox { + +class MHUDummy : public Mailbox { +public: + MHUDummy(); + virtual ~MHUDummy(); + virtual bool sendMessage() final; + virtual void handleMessage() final; +}; + +} // namespace Mailbox + +#endif /* #ifndef MHU_DUMMY_HPP */ diff --git a/drivers/mhu_dummy/src/mhu_dummy.cc b/drivers/mhu_dummy/src/mhu_dummy.cc new file mode 100644 index 0000000..196fb93 --- /dev/null +++ b/drivers/mhu_dummy/src/mhu_dummy.cc @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 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 + +namespace Mailbox { + +MHUDummy::MHUDummy() {} +MHUDummy::~MHUDummy() {} + +void MHUDummy::handleMessage() { + notify(); +} +bool MHUDummy::sendMessage() { + return true; +} + +} // namespace Mailbox diff --git a/drivers/mhu_juno/CMakeLists.txt b/drivers/mhu_juno/CMakeLists.txt new file mode 100644 index 0000000..1dbb6fd --- /dev/null +++ b/drivers/mhu_juno/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (c) 2020 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. +# + +add_library(ethosu_mhu_juno STATIC) +target_include_directories(ethosu_mhu_juno PUBLIC include) + +target_sources(ethosu_mhu_juno PRIVATE src/mhu_juno.cc) +target_link_libraries(ethosu_mhu_juno PRIVATE ethosu_mailbox) diff --git a/drivers/mhu_juno/include/mhu_juno.hpp b/drivers/mhu_juno/include/mhu_juno.hpp new file mode 100644 index 0000000..f864cd5 --- /dev/null +++ b/drivers/mhu_juno/include/mhu_juno.hpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef MHU_JUNO_HPP +#define MHU_JUNO_HPP + +#include + +#include +#include + +namespace Mailbox { + +// Doorbell implementation only +class MHUJuno : public Mailbox { +public: + MHUJuno(const uint32_t baseAddress); + virtual ~MHUJuno(); + virtual bool sendMessage() final; + virtual void handleMessage() final; + virtual bool verifyHardware() final; + +private: + /* Offsets */ + static constexpr uint32_t CPU0_INTR_STAT = 0x00; + static constexpr uint32_t CPU0_INTR_SET = 0x04; + static constexpr uint32_t CPU0_INTR_CLR = 0x08; + static constexpr uint32_t CPU1_INTR_STAT = 0x10; + static constexpr uint32_t CPU1_INTR_SET = 0x14; + static constexpr uint32_t CPU1_INTR_CLR = 0x18; + static constexpr uint32_t OFFSET = 0x10; + static constexpr uint32_t PIDR0 = 0xfe0; + static constexpr uint32_t PIDR1 = 0xfe4; + static constexpr uint32_t PIDR2 = 0xfe8; + static constexpr uint32_t PIDR3 = 0xfec; + static constexpr uint32_t PIDR4 = 0xfd0; + static constexpr uint32_t CIDR0 = 0xff0; + static constexpr uint32_t CIDR1 = 0xff4; + static constexpr uint32_t CIDR2 = 0xff8; + static constexpr uint32_t CIDR3 = 0xffc; + + volatile uint32_t *baseAddr; + + void clearMessage(); + void write(uint32_t offset, uint32_t val); + uint32_t read(uint32_t offset); +}; + +} // namespace Mailbox + +#endif /* #ifndef MHU_JUNO_HPP */ diff --git a/drivers/mhu_juno/src/mhu_juno.cc b/drivers/mhu_juno/src/mhu_juno.cc new file mode 100644 index 0000000..9a58a80 --- /dev/null +++ b/drivers/mhu_juno/src/mhu_juno.cc @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020 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 + +#include +#include +#include +#include +#include + +namespace Mailbox { + +MHUJuno::MHUJuno(const uint32_t baseAddress) { + baseAddr = reinterpret_cast(baseAddress); +} + +void MHUJuno::handleMessage() { + clearMessage(); + notify(); +} + +MHUJuno::~MHUJuno() {} + +// Doorbell only +bool MHUJuno::sendMessage() { + write(CPU1_INTR_SET, 1); + return true; +} +// Doorbell only +void MHUJuno::clearMessage() { + write(CPU0_INTR_CLR, 0xF); +} + +bool MHUJuno::verifyHardware() { + uint32_t pidr0 = read(PIDR0); + uint32_t pidr1 = read(PIDR1); + uint32_t pidr2 = read(PIDR2); + uint32_t pidr3 = read(PIDR3); + uint32_t pidr4 = read(PIDR4); + uint32_t cidr0 = read(CIDR0); + uint32_t cidr1 = read(CIDR1); + uint32_t cidr2 = read(CIDR2); + uint32_t cidr3 = read(CIDR3); + + if (pidr0 != 0x56 || pidr1 != 0xb8 || pidr2 != 0x0b || pidr3 != 0x00 || pidr4 != 0x04 || cidr0 != 0x0d || + cidr1 != 0xf0 || cidr2 != 0x05 || cidr3 != 0xb1) { + return false; + } + return true; +} + +void MHUJuno::write(const uint32_t offset, const uint32_t value) { + write32(baseAddr, offset, value); +} + +uint32_t MHUJuno::read(const uint32_t offset) { + return read32(baseAddr, offset); +} + +} // namespace Mailbox diff --git a/drivers/mhu_v2/CMakeLists.txt b/drivers/mhu_v2/CMakeLists.txt new file mode 100644 index 0000000..2ecf35a --- /dev/null +++ b/drivers/mhu_v2/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (c) 2020 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. +# + +add_library(ethosu_mhu_v2 STATIC) +target_include_directories(ethosu_mhu_v2 PUBLIC include) + +target_sources(ethosu_mhu_v2 PRIVATE src/mhu_v2.cc) +target_link_libraries(ethosu_mhu_v2 PRIVATE ethosu_mailbox) diff --git a/drivers/mhu_v2/include/mhu_v2.hpp b/drivers/mhu_v2/include/mhu_v2.hpp new file mode 100644 index 0000000..881c0ea --- /dev/null +++ b/drivers/mhu_v2/include/mhu_v2.hpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef MHU_V2_HPP +#define MHU_V2_HPP + +#include + +#include +#include +#include +#include + +namespace Mailbox { +/* + * SENDER OVERVIEW + * ------------------------------------------------------------------------ + * Offset Access Type Register Name Short Name + * ------------------------------------------------------------------------ + * 0x000-0xF7C - Sender Channel Window 0-123 - + * 0xF80 RO Message Handling Unit Configuration MHU_CFG + * 0xF84 RW Response Configuration RESP_CFG + * 0xF88 RW Access Request ACCESS_REQUEST + * 0xF8C RO Access Ready ACCESS_READY + * 0xF90 RO Interrupt Status INT_ST + * 0xF94 WO Interrupt Clear INT_CLR + * 0xF98 RW Interrupt Enable INT_EN + * 0xF9C-0xFC4 RO Reserved - + * 0xFC8 RO Implementer Identification Register IIDR + * 0xFCC RO Architecture Identification Register AIDR + * 0xFD0-0xFFC - IMPL DEF Identification Regs - + */ + +/* + * RECEIVER OVERVIEW + * ------------------------------------------------------------------------ + * Offset Access Type Register Name Short Name + * ------------------------------------------------------------------------ + * 0x000-0xF7C - Receiver Channel Window 0-123 - + * 0xF80 RO Message Handling Unit Configuration MHU_CFG + * 0xF84-0xFC4 RO Reserved - + * 0xFC8 RO Implementer Identification Register IIDR + * 0xFCC RO Architecture Identification Register AIDR + * 0xFD0-0xFFC - IMPL DEF Identification Regs - + */ + +/* + * Sender Channel Window + * ------------------------------------------------------------------------ + * Offset Access Type Register Name Short Name + * ------------------------------------------------------------------------ + * 0x00 RO Channel Status CH_ST + * 0x04 RO Reserved - + * 0x08 RO Reserved - + * 0x0C WO Channel Set CH_SET + * 0x10 RO Reserved - + * 0x14 RO Reserved - + * 0x18 RO Reserved - + * 0x1C RO Reserved - + */ + +/* + * Receiver Channel Window + * ------------------------------------------------------------------------ + * Offset Access Type Register Name Short Name + * ------------------------------------------------------------------------ + * 0x00 RO Channel Status CH_ST + * 0x04 RO Channel Status Masked CH_ST_MSK + * 0x08 WO Channel Clear CH_CLR + * 0x0C RO Reserved - + * 0x10 RO Channel Mask Status CH_MSK_ST + * 0x14 WO Channel Mask Set CH_MSK_SET + * 0x18 WO Channel Mask Clear CH_MSK_CLR + * 0x1C RO Reserved - + */ + +// Doorbell implementation only +// NOTE: MHUv2 is unidirectional. Two MHU's are needed for bidirectional +// messaging. txBase/rxBase refers to the base address of _two_ +// separate MHU blocks. +class MHUv2 : public Mailbox { +public: + MHUv2(const uint32_t txBaseAddress, const uint32_t rxBaseAddress); + virtual ~MHUv2(); + virtual bool sendMessage() final; + virtual void handleMessage() final; + virtual bool verifyHardware() final; + +private: + /* Offsets */ + static constexpr uint32_t MHUv2_CH_ST = 0x00; + static constexpr uint32_t MHUv2_CH_ST_MSK = 0x04; + static constexpr uint32_t MHUv2_CH_CLR = 0x08; + static constexpr uint32_t MHUv2_CH_SET = 0x0C; + static constexpr uint32_t MHUv2_CH_MSK_ST = 0x10; + static constexpr uint32_t MHUv2_CH_MSK_SET = 0x14; + static constexpr uint32_t MHUv2_CH_MSK_CLR = 0x18; + static constexpr uint32_t MHUv2_CH_INT_CLR = 0x14; + static constexpr uint32_t MHUv2_CH_INT_EN = 0x18; + static constexpr uint32_t MHUv2_SND_CHAN_WINDOW_SIZE = 0x20; + static constexpr uint32_t MHUv2_SND_MHU_CFG_OFFS = 0xF80; + static constexpr uint32_t MHUv2_SND_RESP_CFG_OFFS = 0xF84; + static constexpr uint32_t MHUv2_SND_ACCESS_REQUEST_OFFS = 0xF88; + static constexpr uint32_t MHUv2_SND_ACCESS_READY_OFFS = 0xF8C; + static constexpr uint32_t MHUv2_SND_INT_ST_OFFS = 0xF90; + static constexpr uint32_t MHUv2_SND_INT_CLR_OFFS = 0xF94; + static constexpr uint32_t MHUv2_SND_INT_EN_OFFS = 0xF98; + static constexpr uint32_t MHUv2_SND_IIDR_OFFS = 0xFC8; + static constexpr uint32_t MHUv2_SND_AIDR_OFFS = 0xFCC; + static constexpr uint32_t MHUv2_RCV_CHAN_WINDOW_SIZE = 0x20; + static constexpr uint32_t MHUv2_RCV_MHU_CFG_OFFS = 0xF80; + static constexpr uint32_t MHUv2_RCV_IIDR_OFFS = 0xFC8; + static constexpr uint32_t MHUv2_RCV_AIDR_OFFS = 0xFCC; + static constexpr uint32_t MHUv2_RCV_INT_EN_OFFS = 0xF98; + + struct aidr_t { + uint32_t ARCH_MINOR_REV : 4; + uint32_t ARCH_MAJOR_REV : 4; + uint32_t RESERVED : 24; + }; + + volatile uint32_t *txBaseAddr; + volatile uint32_t *rxBaseAddr; + + void clearMessage(); + void printAIDR(bool tx = true, bool rx = true); + + void txWrite(uint32_t offset, uint32_t value); + void rxWrite(uint32_t offset, uint32_t value); + uint32_t txRead(uint32_t offset); + uint32_t rxRead(uint32_t offset); + + // Sender/tx + uint32_t getAccessReady(); + uint32_t getAccessRequest(); + uint32_t getInterruptStatus(); + uint32_t getTxAIDR(); + uint32_t getTxStatusForChan(uint8_t chan); + void enableAccessRequest(); + void disableAccessRequest(); + void setCombinedClearInterrupt(bool enable); + void setReadyNotReadyInterrupts(bool enable); + + // Receiver/rx + uint32_t getRxAIDR(); + uint32_t getRxStatusForChan(uint8_t chan); + void setCombinedRecvInterrupt(bool enable); + void enableClearChanInterrupt(uint8_t chan); + void disableClearChanInterrupt(uint8_t chan); +}; + +} // namespace Mailbox + +#endif /* #ifndef MHU_V2_HPP */ diff --git a/drivers/mhu_v2/src/mhu_v2.cc b/drivers/mhu_v2/src/mhu_v2.cc new file mode 100644 index 0000000..76336ce --- /dev/null +++ b/drivers/mhu_v2/src/mhu_v2.cc @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2020 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 + +#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); + printf("TX MHUv2 reports: Major rev: %d\nMinor rev: %d\n", a->ARCH_MAJOR_REV, a->ARCH_MINOR_REV); + } + if (rx) { + aidr = getRxAIDR(); + a = reinterpret_cast(&aidr); + printf("RX MHUv2 reports: Major rev: %d\nMinor rev: %d\n", a->ARCH_MAJOR_REV, a->ARCH_MINOR_REV); + } +} + +} // namespace Mailbox -- cgit v1.2.1