From 3f9d9eff330bfc542381edcae7b63d912ce7962b Mon Sep 17 00:00:00 2001 From: Marco Visaya Date: Wed, 18 Dec 2024 12:31:14 -0800 Subject: [PATCH 1/5] Add HIL interfaces for DMA and Caliptra Mailbox Define HIL interfaces for Caliptra Mailbox and DMA. This is based on the mailbox functionality defined in : https://github.com/chipsalliance/caliptra-rtl/blob/main/docs/CaliptraIntegrationSpecification.md#mailbox and the DMA operation in: https://github.com/chipsalliance/caliptra-ss/blob/main/docs/Caliptra%202.0%20Subsystem%20Specification%201.pdf --- runtime/dma/Cargo.toml | 16 +++++ runtime/dma/src/hil.rs | 94 +++++++++++++++++++++++++++++ runtime/dma/src/lib.rs | 6 ++ runtime/mailbox/Cargo.toml | 16 +++++ runtime/mailbox/src/hil.rs | 117 +++++++++++++++++++++++++++++++++++++ runtime/mailbox/src/lib.rs | 6 ++ 6 files changed, 255 insertions(+) create mode 100644 runtime/dma/Cargo.toml create mode 100644 runtime/dma/src/hil.rs create mode 100644 runtime/dma/src/lib.rs create mode 100644 runtime/mailbox/Cargo.toml create mode 100644 runtime/mailbox/src/hil.rs create mode 100644 runtime/mailbox/src/lib.rs diff --git a/runtime/dma/Cargo.toml b/runtime/dma/Cargo.toml new file mode 100644 index 0000000..59cb570 --- /dev/null +++ b/runtime/dma/Cargo.toml @@ -0,0 +1,16 @@ +# Licensed under the Apache-2.0 license. + +[package] +name = "dma-driver" +version.workspace = true +authors.workspace = true +edition.workspace = true + +[dependencies] +kernel = { git = "https://github.com/tock/tock.git", rev = "b128ae817b86706c8c4e39d27fae5c54b98659f1" } + +[target.'cfg(target_arch = "riscv32")'.dependencies] +capsules-core = { git = "https://github.com/tock/tock.git", rev = "b128ae817b86706c8c4e39d27fae5c54b98659f1" } +registers-generated.workspace = true +romtime.workspace = true +tock-registers.workspace = true diff --git a/runtime/dma/src/hil.rs b/runtime/dma/src/hil.rs new file mode 100644 index 0000000..3211320 --- /dev/null +++ b/runtime/dma/src/hil.rs @@ -0,0 +1,94 @@ +// Licensed under the Apache-2.0 license. + +//! HIL Interface for Caliptra DMA Engine +use kernel::ErrorCode; + +/// This trait provides the interfaces for managing DMA transfers. +/// The full description of the DMA interface can be found in the Caliptra Subsystem Specification: +/// https://github.com/chipsalliance/caliptra-ss/blob/main/docs/Caliptra%202.0%20Subsystem%20Specification%201.pdf +pub trait DMA { + /// Configure the DMA transfer with 64-bit source and destination addresses. + /// + /// # Arguments: + /// - `byte_count`: Total bytes to transfer (must be aligned to AXI data width). + /// - `block_size`: Size of individual blocks for transfer. + /// - `src_addr`: Optional 64-bit source address for the transfer. + /// - `dest_addr`: Optional 64-bit destination address for the transfer. + /// + /// Returns: + /// - `Ok(())` if configuration is successful. + /// - `Err(ErrorCode)` if parameters are invalid. + fn configure_transfer( + &self, + byte_count: usize, + block_size: usize, + src_addr: Option, + dest_addr: Option, + ) -> Result<(), ErrorCode>; + + /// Start the configured DMA transfer. + fn start_transfer(&self, read_route: DmaRoute, write_route: DmaRoute, fixed_addr: bool) -> Result<(), ErrorCode>; + + /// Poll the DMA status for transfer progress or completion. + fn poll_status(&self) -> Result; + + /// Push data into the WR FIFO for AHB -> AXI WR transfers. + /// + /// # Arguments: + /// - `data`: Slice of data to be written (as bytes). + fn write_fifo(&self, data: &[u8]) -> Result<(), DMAError>; + + /// Pop data from the RD FIFO for AXI RD -> AHB transfers. + /// + /// # Arguments: + /// - `buffer`: Mutable slice to store the read data (as bytes). + /// + /// Returns: + /// - `Ok(bytes_read)` indicating the number of bytes read. + fn read_fifo(&self, buffer: &mut [u8]) -> Result; + + /// Set a client for receiving DMA transfer events asynchronously. + fn set_client(&self, client: &'static dyn DMAClient); +} + +/// DMA Route configuration for Read/Write routes. +#[derive(Debug, Copy, Clone)] +pub enum DmaRoute { + Disabled, + AxiToMailbox, + AxiToAHB, + AxiToAxi, + AHBToAxi, +} + +/// Represents the current status of the DMA transfer. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum DMAStatus { + TxnDone, // Transaction complete + RdFifoNotEmpty, // Read FIFO has data + RdFifoFull, // Read FIFO is full + WrFifoNotFull, // Write FIFO has room for more data + WrFifoEmpty, // Write FIFO is empty +} + +/// Represents possible DMA errors. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum DMAError { + CommandError, // General command error + AxiReadError, // AXI Read error + AxiWriteError, // AXI Write error + MailboxNotLocked, // Mailbox lock not acquired + RdFifoOverflow, // Data overflow in Read FIFO + RdFifoUnderflow, // Data underflow in Read FIFO + WrFifoOverflow, // Data overflow in Write FIFO + WrFifoUnderflow, // Data underflow in Write FIFO +} + +/// A client trait for handling asynchronous DMA transfer events. +pub trait DMAClient { + /// Called when a DMA transfer completes successfully. + fn transfer_complete(&self, status: DMAStatus); + + /// Called when a DMA transfer encounters an error. + fn transfer_error(&self, error: DMAError); +} diff --git a/runtime/dma/src/lib.rs b/runtime/dma/src/lib.rs new file mode 100644 index 0000000..b24ca82 --- /dev/null +++ b/runtime/dma/src/lib.rs @@ -0,0 +1,6 @@ +// Licensed under the Apache-2.0 license. + +#![cfg_attr(target_arch = "riscv32", no_std)] + +#[cfg(target_arch = "riscv32")] +pub mod hil; diff --git a/runtime/mailbox/Cargo.toml b/runtime/mailbox/Cargo.toml new file mode 100644 index 0000000..5579352 --- /dev/null +++ b/runtime/mailbox/Cargo.toml @@ -0,0 +1,16 @@ +# Licensed under the Apache-2.0 license. + +[package] +name = "mailbox-driver" +version.workspace = true +authors.workspace = true +edition.workspace = true + +[dependencies] +kernel = { git = "https://github.com/tock/tock.git", rev = "b128ae817b86706c8c4e39d27fae5c54b98659f1" } + +[target.'cfg(target_arch = "riscv32")'.dependencies] +capsules-core = { git = "https://github.com/tock/tock.git", rev = "b128ae817b86706c8c4e39d27fae5c54b98659f1" } +registers-generated.workspace = true +romtime.workspace = true +tock-registers.workspace = true diff --git a/runtime/mailbox/src/hil.rs b/runtime/mailbox/src/hil.rs new file mode 100644 index 0000000..6cf6c03 --- /dev/null +++ b/runtime/mailbox/src/hil.rs @@ -0,0 +1,117 @@ +// Licensed under the Apache-2.0 license + +//! HIL Interface for Caliptra Mailbox Communication + +use core::result::Result; +use kernel::ErrorCode; + +/// This trait supports both sending and receiving data, handling locks, and managing mailbox state transitions. +/// The full description of the mailbox interface can be found in the Caliptra Integration Specification: +/// https://github.com/chipsalliance/caliptra-rtl/blob/main/docs/CaliptraIntegrationSpecification.md#mailbox +pub trait Mailbox { + /// Check if the mailbox lock is available. + /// + /// Returns: + /// - `Ok(true)` if the mailbox is available and lock was acquired. + /// - `Ok(false)` if the mailbox is currently locked by another device. + /// - `Err(ErrorCode)` for any other error. + fn acquire_lock(&self) -> Result; + + /// Release the mailbox lock. + /// + /// Returns: + /// - `Ok(())` if the lock was successfully released. + /// - `Err(ErrorCode)` if there was an issue releasing the lock. + fn release_lock(&self) -> Result<(), ErrorCode>; + + /// Write a command and data to the mailbox. + /// + /// # Arguments: + /// - `command`: The command ID to write to the mailbox. + /// - `data`: The data payload to send. + /// + /// Returns: + /// - `Ok(())` if the data was successfully written. + /// - `Err(ErrorCode)` if there was an issue with the operation. + fn send_command(&self, command: u32, data: &[u8]) -> Result<(), ErrorCode>; + + /// Read data from the mailbox after the command execution. + /// + /// # Arguments: + /// - `buffer`: A mutable buffer to store the response data. + /// + /// Returns: + /// - `Ok(response_length)` where `response_length` is the number of bytes read. + /// - `Err(ErrorCode)` if there was an issue reading the response. + fn read_response(&self, buffer: &mut [u8]) -> Result; + + /// Check the status of the mailbox after a command execution. + /// + /// Returns: + /// - `Ok(status_code)` where `status_code` represents the current mailbox status. + /// - `Err(ErrorCode)` if there was an issue checking the status. + fn check_status(&self) -> Result; + + /// Handle incoming data when the mailbox data availability signal is asserted. + /// + /// # Arguments: + /// - `buffer`: A mutable buffer to store the received data. + /// + /// Returns: + /// - `Ok(length)` where `length` is the size of the received data. + /// - `Err(ErrorCode)` if there was an issue processing the data. + fn handle_incoming_data(&self, buffer: &mut [u8]) -> Result; + + /// Populate the mailbox with a response if required. + /// + /// # Arguments: + /// - `response_data`: The response data to populate in the mailbox. + /// + /// Returns: + /// - `Ok(())` if the response was successfully populated. + /// - `Err(ErrorCode)` if there was an issue writing the response. + fn send_response(&self, response_data: &[u8]) -> Result<(), ErrorCode>; + + /// Set a client to receive callbacks on mailbox events. + /// + /// # Arguments: + /// - `client`: A reference to an object implementing the `MailboxClient` trait. + fn set_client(&self, client: &'static dyn MailboxClient); +} + +/// Represents the current status of the mailbox. +#[derive(Debug, Copy, Clone)] +pub enum MailboxStatus { + /// Command is still being processed. + Busy, + /// Data is ready to be read. + DataReady, + /// Command completed successfully. + Complete, + /// Command failed. + Failure, +} + +/// A client trait for handling mailbox callbacks. +/// +/// This trait enables asynchronous notifications of mailbox events. +pub trait MailboxClient { + /// Callback when the mailbox data is available for the receiver. + /// + /// # Arguments: + /// - `command`: The command ID of the incoming mailbox data. + /// - `length`: The size of the incoming data. + fn data_available(&self, command: u32, length: usize); + + /// Callback when the sender's command completes. + /// + /// # Arguments: + /// - `status`: The status of the command execution. + fn command_complete(&self, status: MailboxStatus); + + /// Callback when an error occurs during mailbox operations. + /// + /// # Arguments: + /// - `error`: An error code describing the failure. + fn mailbox_error(&self, error: ErrorCode); +} diff --git a/runtime/mailbox/src/lib.rs b/runtime/mailbox/src/lib.rs new file mode 100644 index 0000000..b24ca82 --- /dev/null +++ b/runtime/mailbox/src/lib.rs @@ -0,0 +1,6 @@ +// Licensed under the Apache-2.0 license. + +#![cfg_attr(target_arch = "riscv32", no_std)] + +#[cfg(target_arch = "riscv32")] +pub mod hil; From 2ea6c7278a4089213fe6d3fa230bfe654993d62e Mon Sep 17 00:00:00 2001 From: Marco Visaya Date: Wed, 18 Dec 2024 13:28:35 -0800 Subject: [PATCH 2/5] Addressed feedback Change return of mailbox.check_status from status_code to MailboxStatus --- runtime/mailbox/src/hil.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/mailbox/src/hil.rs b/runtime/mailbox/src/hil.rs index 6cf6c03..f850ade 100644 --- a/runtime/mailbox/src/hil.rs +++ b/runtime/mailbox/src/hil.rs @@ -48,7 +48,7 @@ pub trait Mailbox { /// Check the status of the mailbox after a command execution. /// /// Returns: - /// - `Ok(status_code)` where `status_code` represents the current mailbox status. + /// - `Ok(MailboxStatus)` where `MailboxStatus` represents the current mailbox status. /// - `Err(ErrorCode)` if there was an issue checking the status. fn check_status(&self) -> Result; From 172bdbd01b86d611bf106809d0724410c7932910 Mon Sep 17 00:00:00 2001 From: mlvisaya <38512415+mlvisaya@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:35:42 -0800 Subject: [PATCH 3/5] Update runtime/dma/Cargo.toml Co-authored-by: Christopher Swenson --- runtime/dma/Cargo.toml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/runtime/dma/Cargo.toml b/runtime/dma/Cargo.toml index 59cb570..b17de28 100644 --- a/runtime/dma/Cargo.toml +++ b/runtime/dma/Cargo.toml @@ -9,8 +9,3 @@ edition.workspace = true [dependencies] kernel = { git = "https://github.com/tock/tock.git", rev = "b128ae817b86706c8c4e39d27fae5c54b98659f1" } -[target.'cfg(target_arch = "riscv32")'.dependencies] -capsules-core = { git = "https://github.com/tock/tock.git", rev = "b128ae817b86706c8c4e39d27fae5c54b98659f1" } -registers-generated.workspace = true -romtime.workspace = true -tock-registers.workspace = true From 6637582685182819ec30d9ca32d0e4ba80be13fa Mon Sep 17 00:00:00 2001 From: mlvisaya <38512415+mlvisaya@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:36:06 -0800 Subject: [PATCH 4/5] Update runtime/dma/src/lib.rs Co-authored-by: Christopher Swenson --- runtime/dma/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/dma/src/lib.rs b/runtime/dma/src/lib.rs index b24ca82..9f4e68b 100644 --- a/runtime/dma/src/lib.rs +++ b/runtime/dma/src/lib.rs @@ -2,5 +2,4 @@ #![cfg_attr(target_arch = "riscv32", no_std)] -#[cfg(target_arch = "riscv32")] pub mod hil; From 6d220424a290e7380da5e3bb6bb0cd9a722efd41 Mon Sep 17 00:00:00 2001 From: Marco Visaya Date: Wed, 18 Dec 2024 16:43:05 -0800 Subject: [PATCH 5/5] Remove unnecessary RISC-V config --- runtime/mailbox/Cargo.toml | 5 ----- runtime/mailbox/src/lib.rs | 1 - 2 files changed, 6 deletions(-) diff --git a/runtime/mailbox/Cargo.toml b/runtime/mailbox/Cargo.toml index 5579352..d08dc30 100644 --- a/runtime/mailbox/Cargo.toml +++ b/runtime/mailbox/Cargo.toml @@ -9,8 +9,3 @@ edition.workspace = true [dependencies] kernel = { git = "https://github.com/tock/tock.git", rev = "b128ae817b86706c8c4e39d27fae5c54b98659f1" } -[target.'cfg(target_arch = "riscv32")'.dependencies] -capsules-core = { git = "https://github.com/tock/tock.git", rev = "b128ae817b86706c8c4e39d27fae5c54b98659f1" } -registers-generated.workspace = true -romtime.workspace = true -tock-registers.workspace = true diff --git a/runtime/mailbox/src/lib.rs b/runtime/mailbox/src/lib.rs index b24ca82..9f4e68b 100644 --- a/runtime/mailbox/src/lib.rs +++ b/runtime/mailbox/src/lib.rs @@ -2,5 +2,4 @@ #![cfg_attr(target_arch = "riscv32", no_std)] -#[cfg(target_arch = "riscv32")] pub mod hil;