Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HIL interfaces for DMA and Caliptra Mailbox #65

Merged
merged 5 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions runtime/dma/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 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" }

94 changes: 94 additions & 0 deletions runtime/dma/src/hil.rs
Original file line number Diff line number Diff line change
@@ -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<u64>,
dest_addr: Option<u64>,
) -> 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<DMAStatus, DMAError>;

/// 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<usize, DMAError>;

/// 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);
}
5 changes: 5 additions & 0 deletions runtime/dma/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Licensed under the Apache-2.0 license.

#![cfg_attr(target_arch = "riscv32", no_std)]

pub mod hil;
11 changes: 11 additions & 0 deletions runtime/mailbox/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 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" }

117 changes: 117 additions & 0 deletions runtime/mailbox/src/hil.rs
Original file line number Diff line number Diff line change
@@ -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<bool, ErrorCode>;

/// 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<usize, ErrorCode>;

/// Check the status of the mailbox after a command execution.
///
/// Returns:
/// - `Ok(MailboxStatus)` where `MailboxStatus` represents the current mailbox status.
/// - `Err(ErrorCode)` if there was an issue checking the status.
fn check_status(&self) -> Result<MailboxStatus, ErrorCode>;

/// 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<usize, ErrorCode>;

/// 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);
}
5 changes: 5 additions & 0 deletions runtime/mailbox/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Licensed under the Apache-2.0 license.

#![cfg_attr(target_arch = "riscv32", no_std)]

pub mod hil;