blob: 5f15111fe2623003e1df8211c8250c2c6e47e9e6 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* 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
*
* http://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.
*/
/*
* Special-purpose mailbox support for soundstream. Assumes a
* companion implementation is running on the security core.
*/
#include "mailbox.h"
#include <fail-simulator-on-error.h>
#include <futex.h>
#include <interrupt.h>
#include <locks.h>
#include <thread.h>
#include <debug.hh>
#include <platform/sencha/platform-mailbox.hh>
#include "hw/top_matcha/sw/autogen/top_matcha.h"
/// Expose debugging features unconditionally for this compartment.
using Debug = ConditionalDebug<false, "Mailbox">;
#include "compat.h"
const uint32_t kMessageGpioPressed = 0xdeadbeef;
const uint32_t kMessageGpioReleased = 0x21524110;
const uint32_t kMessageEnableLed = 0xcafeb0ba;
const uint32_t kMessageDisableLed = 0x35014f45;
typedef uint32_t
mailbox_mmio_t[TOP_MATCHA_TLUL_MAILBOX_SMC_SIZE_BYTES / sizeof(uint32_t)];
static dif_tlul_mailbox_t mailbox;
#define CHECK_INIT() CHECK(mailbox.base_addr.base != 0)
static CountingSemaphoreState startup = { 0, 1 };
void mailbox_init(void) {
CHECK_DIF_OK(
dif_tlul_mailbox_init(mmio_region_from_addr((uintptr_t)MMIO_CAPABILITY(
mailbox_mmio_t, mailbox_smc)),
&mailbox));
semaphore_put(&startup);
}
// NB: could be atomic but not needed for our usage.
volatile bool button_pressed = false;
void mailbox_isr(void) {
Timeout t = {0, UnlimitedTimeout};
semaphore_get(&t, &startup);
Debug::log("mailbox_isr: mailbox {} (Thread {})", mailbox.base_addr.base, thread_id_get());
const uint32_t *mailboxRtFutex =
interrupt_futex_get(STATIC_SEALED_VALUE(mailboxRtInterruptCapability));
uint32_t last = *mailboxRtFutex;
for (;;) {
Debug::Assert(futex_wait(mailboxRtFutex, last) == 0, "futex_wait");
last = *mailboxRtFutex;
Debug::log("mailbox_isr: mailbox {} last {}", mailbox.base_addr.base, last);
interrupt_complete(STATIC_SEALED_VALUE(mailboxRtInterruptCapability));
// NB: this is NOT the TockOS mailbox protocol that exchanges
// variable length packets that are encoded by Rust's postcard
// crate.
uint32_t message;
CHECK_DIF_OK(dif_tlul_mailbox_read_message(&mailbox, &message));
if (message == kMessageGpioPressed) {
button_pressed = true;
} else if (message == kMessageGpioReleased) {
button_pressed = false;
} else {
CHECK(false, "Unknown message");
}
}
}
bool mailbox_button_pressed(void) { return button_pressed; }
// XXX temp until gpio's on the SEC can be used (either in simulation or for real)
void mailbox_set_button_pressed(bool pressed) { button_pressed = pressed; }
// Wait until the record switch is pushed
void mailbox_wait_for_button_pressed(void) {
const uint32_t *mailboxRtFutex =
interrupt_futex_get(STATIC_SEALED_VALUE(mailboxRtInterruptCapability));
uint32_t last = *mailboxRtFutex;
while (!mailbox_button_pressed()) {
Debug::Assert(futex_wait(mailboxRtFutex, last) == 0, "futex_wait");
last = *mailboxRtFutex;
}
}
void mailbox_set_led(bool enabled) {
CHECK_INIT();
// NB: this is not the TockOS mailbox protocol.
uint32_t message_enable_led =
enabled ? kMessageEnableLed : kMessageDisableLed;
CHECK_DIF_OK(dif_tlul_mailbox_send_message(&mailbox, &message_enable_led));
}