blob: 3bcd256ff6f9f6ee157b67dfcc7846d3bb73c1be [file] [log] [blame]
Jonny Svärd9fc527b2020-11-16 16:18:07 +01001/*
Anton Moberge348f8f2021-03-31 11:08:58 +02002 * Copyright (c) 2020-2021 Arm Limited. All rights reserved.
Jonny Svärd9fc527b2020-11-16 16:18:07 +01003 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
Anton Moberg07cf70b2021-07-07 11:08:17 +020019#include "ethosu_log.h"
20
Jonny Svärd9fc527b2020-11-16 16:18:07 +010021#include <mhu_v2.hpp>
22
23#include <cassert>
24#include <cstddef>
25#include <cstdint>
26#include <cstdio>
27#include <cstring>
28
29namespace Mailbox {
30
31MHUv2::MHUv2(const uint32_t txBaseAddress, const uint32_t rxBaseAddress) :
32 txBaseAddr(reinterpret_cast<volatile uint32_t *>(txBaseAddress)),
33 rxBaseAddr(reinterpret_cast<volatile uint32_t *>(rxBaseAddress)) {
34
35 setCombinedRecvInterrupt(true);
36 enableAccessRequest(); // Set high throughout
37}
38
39void MHUv2::handleMessage() {
40 clearMessage();
41 notify();
42}
43
44MHUv2::~MHUv2() {
45 setCombinedRecvInterrupt(false);
46 disableAccessRequest();
47}
48
49bool MHUv2::verifyHardware() {
50 // Sanity check MHUv2.1 id's (tx/rx)
51 struct aidr_t *a;
52 uint32_t txAIDR = getTxAIDR();
53 uint32_t rxAIDR = getRxAIDR();
54
55 a = reinterpret_cast<struct aidr_t *>(&txAIDR);
56 if (a->ARCH_MAJOR_REV != 1 || a->ARCH_MINOR_REV != 1) {
57 return false;
58 }
59
60 a = reinterpret_cast<struct aidr_t *>(&rxAIDR);
61 if (a->ARCH_MAJOR_REV != 1 || a->ARCH_MINOR_REV != 1) {
62 return false;
63 }
64
65 return true;
66}
67
68uint32_t MHUv2::getTxStatusForChan(uint8_t chan) {
69 assert(chan >= 0);
70 assert(chan < 124);
71 return txRead((chan * MHUv2_SND_CHAN_WINDOW_SIZE) + MHUv2_CH_ST);
72}
73
74uint32_t MHUv2::getRxStatusForChan(uint8_t chan) {
75 assert(chan >= 0);
76 assert(chan < 124);
77 return rxRead((chan * MHUv2_RCV_CHAN_WINDOW_SIZE) + MHUv2_CH_ST);
78}
79
80uint32_t MHUv2::getInterruptStatus() {
81 return txRead(MHUv2_SND_INT_ST_OFFS);
82}
83
84uint32_t MHUv2::getAccessReady() {
85 return txRead(MHUv2_SND_ACCESS_READY_OFFS);
86}
87
88uint32_t MHUv2::getAccessRequest() {
89 return txRead(MHUv2_SND_ACCESS_REQUEST_OFFS);
90}
91
92uint32_t MHUv2::getTxAIDR() {
93 return txRead(MHUv2_SND_AIDR_OFFS);
94}
95
96uint32_t MHUv2::getRxAIDR() {
97 return rxRead(MHUv2_RCV_AIDR_OFFS);
98}
99
100void MHUv2::enableAccessRequest() {
101 txWrite(MHUv2_SND_ACCESS_REQUEST_OFFS, 1);
102}
103
104void MHUv2::disableAccessRequest() {
105 txWrite(MHUv2_SND_ACCESS_REQUEST_OFFS, 0);
106}
107
108/*
109 * MHUv2.1
110 * sender: combined clear interrupt
111 */
112void MHUv2::setCombinedClearInterrupt(bool enable) {
113 uint32_t val = txRead(MHUv2_SND_INT_EN_OFFS);
114 if (enable) {
115 val |= (1 << 2);
116 } else {
117 val &= ~(1 << 2);
118 }
119 txWrite(MHUv2_SND_INT_EN_OFFS, val);
120}
121
122/*
123 * MHUv2.1
124 * receiver: combined recv interrupt
125 */
126void MHUv2::setCombinedRecvInterrupt(bool enable) {
127 uint32_t val = rxRead(MHUv2_RCV_INT_EN_OFFS);
128 if (enable) {
129 val |= (1 << 2);
130 } else {
131 val &= ~(1 << 2);
132 }
133 rxWrite(MHUv2_SND_INT_EN_OFFS, val);
134}
135
136// Enable/disable R2NR/NR2R interrupts
137void MHUv2::setReadyNotReadyInterrupts(bool enable) {
138 uint32_t val = txRead(MHUv2_SND_INT_EN_OFFS);
139 if (enable) {
140 val |= (1 << 0 | 1 << 1);
141 } else {
142 val &= ~(1 << 0 | 1 << 1);
143 }
144 txWrite(MHUv2_SND_INT_EN_OFFS, val);
145}
146
147void MHUv2::enableClearChanInterrupt(uint8_t chan) {
148 assert(chan >= 0);
149 assert(chan < 124);
150 txWrite((chan * MHUv2_SND_CHAN_WINDOW_SIZE) + MHUv2_CH_INT_EN, 1);
151}
152
153void MHUv2::disableClearChanInterrupt(uint8_t chan) {
154 assert(chan >= 0);
155 assert(chan < 124);
156 txWrite((chan * MHUv2_SND_CHAN_WINDOW_SIZE) + MHUv2_CH_INT_EN, 0);
157}
158
159/*
160 * Set channel status byte (with only minor error/state check(s))
161 * Doorbell only, chan 0
162 */
163bool MHUv2::sendMessage() {
164 // Check that the other end is ready to receive
165 if (!getAccessReady()) {
166 return false;
167 }
168 txWrite(MHUv2_CH_SET, 1);
169
170 return true;
171}
172
173void MHUv2::clearMessage() {
174 rxWrite(MHUv2_CH_CLR, 0xFFFFFFFF); // Doorbell uses only chan 0, but clear all 32bits to be safe
175}
176
177void MHUv2::txWrite(uint32_t offset, uint32_t value) {
178 write32(txBaseAddr, offset, value);
179}
180
181void MHUv2::rxWrite(uint32_t offset, uint32_t value) {
182 write32(rxBaseAddr, offset, value);
183}
184
185uint32_t MHUv2::txRead(uint32_t offset) {
186 return read32(txBaseAddr, offset);
187}
188
189uint32_t MHUv2::rxRead(uint32_t offset) {
190 return read32(rxBaseAddr, offset);
191}
192
193void MHUv2::printAIDR(bool tx, bool rx) {
194 struct aidr_t *a;
195 uint32_t aidr;
196
197 if (tx) {
198 aidr = getTxAIDR();
199 a = reinterpret_cast<struct aidr_t *>(&aidr);
Anton Moberg07cf70b2021-07-07 11:08:17 +0200200 LOG_INFO("TX MHUv2 reports: Major rev: %d, Minor rev: %d\n", a->ARCH_MAJOR_REV, a->ARCH_MINOR_REV);
Jonny Svärd9fc527b2020-11-16 16:18:07 +0100201 }
202 if (rx) {
203 aidr = getRxAIDR();
204 a = reinterpret_cast<struct aidr_t *>(&aidr);
Anton Moberg07cf70b2021-07-07 11:08:17 +0200205 LOG_INFO("RX MHUv2 reports: Major rev: %d, Minor rev: %d\n", a->ARCH_MAJOR_REV, a->ARCH_MINOR_REV);
Jonny Svärd9fc527b2020-11-16 16:18:07 +0100206 }
207}
208
209} // namespace Mailbox