| /* |
| * 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)); |
| } |