Skip to main content

phytium_mci/
lib.rs

1#![no_std]
2#![deny(warnings, missing_docs)]
3
4//! # phytium-mci
5//!
6//! A `no_std` SD/MMC host controller driver for Phytium E2000 series SoCs.
7//!
8//! ## Overview
9//!
10//! This crate provides a comprehensive driver for SD/MMC cards on Phytium platforms,
11//! supporting both SD and eMMC cards with DMA and PIO transfer modes.
12//!
13//! ## Features
14//!
15//! - **Full SD Specification Support**: SDSC, SDHC, SDXC (versions 1.0-3.0)
16//! - **eMMC Support**: MMC protocol implementation
17//! - **Flexible Transfer Modes**: DMA (high-performance) and PIO (simple)
18//! - **Voltage Support**: 3.3V (default) and 1.8V (UHS-I modes)
19//! - **Bus Widths**: 1-bit, 4-bit, and 8-bit (eMMC) data bus
20//! - **High-Speed Modes**: SDR12, SDR25, SDR50, SDR104, DDR50
21//! - **Clock Speed**: From 400 KHz to 208 MHz
22//! - **Card Detection**: GPIO-based and host-based
23//! - **Interrupt Support**: Command, data, and card detection interrupts
24//!
25//! ## Architecture
26//!
27//! The driver is organized into distinct layers:
28//!
29//! ```text
30//! Application Layer    (SdCard, MCIHost - High-level API)
31//!        ↓
32//! Protocol Layer       (Command/Data transfer, Card initialization)
33//!        ↓
34//! Hardware Abstraction (Register access, DMA/PIO control)
35//!        ↓
36//! Hardware Support     (IoPad pin configuration, OSA memory/timing)
37//! ```
38//!
39//! ## Modules
40//!
41//! - [`iopad`] - I/O pad configuration for pin multiplexing
42//! - [`mci`] - Hardware controller driver (register access, DMA/PIO, interrupts)
43//! - [`mci_host`] - Host controller protocol layer (SD/MMC protocol)
44//! - [`osa`] - OS abstraction layer (memory management, event flags)
45//!
46//! ## Platform Integration
47//!
48//! To use this driver, you must implement the [`Kernel`] trait to provide
49//! platform-specific functionality:
50//!
51//! ```rust
52//! use phytium_mci::{Kernel, set_impl};
53//! use core::{ptr::NonNull, time::Duration};
54//!
55//! struct MyPlatform;
56//!
57//! impl Kernel for MyPlatform {
58//!     fn sleep(duration: Duration) {
59//!         // Platform-specific delay implementation
60//!     }
61//!
62//!     #[cfg(feature = "dma")]
63//!     fn mmap(virt_addr: NonNull<u8>) -> u64 {
64//!         // Virtual to physical address translation
65//!     }
66//!
67//!     fn flush(addr: NonNull<u8>, size: usize) {
68//!         // Cache clean for DMA
69//!     }
70//!
71//!     fn invalidate(addr: NonNull<u8>, size: usize) {
72//!         // Cache invalidate for DMA
73//!     }
74//! }
75//!
76//! // Register your implementation
77//! set_impl!(MyPlatform);
78//! ```
79//!
80//! ## Hardware Configuration
81//!
82//! Target Hardware:
83//! - **SoC**: Phytium E2000 series (ARMv8-A)
84//! - **Board**: Phytium Pi development board
85//! - **Controller**: Phytium SDIF (Synopsys DesignWare-based)
86//! - **MCI0 Base**: 0x2800_1000
87//! - **MCI1 Base**: 0x2800_2000
88//! - **IOPAD Base**: 0x2800_0000
89//!
90//! ## Example
91//!
92//! ```rust,ignore
93//! use phytium_mci::{sd::SdCard, IoPad};
94//! use core::ptr::NonNull;
95//!
96//! // Initialize IOPAD
97//! let iopad = unsafe { IoPad::new(NonNull::new_unchecked(0x2800_0000 as *mut u8)) };
98//!
99//! // Create SD card instance
100//! let mut sdcard = unsafe {
101//!     SdCard::new(
102//!         NonNull::new_unchecked(0x2800_1000 as *mut u8),
103//!         iopad
104//!     )
105//! };
106//!
107//! // Initialize the card
108//! sdcard.init(NonNull::new_unchecked(0x2800_1000 as *mut u8))?;
109//!
110//! // Read blocks
111//! let mut buffer = Vec::new();
112//! sdcard.read_blocks(&mut buffer, 0, 1)?;
113//! ```
114
115extern crate alloc;
116
117use core::{ptr::NonNull, time::Duration};
118
119#[macro_use]
120mod regs;
121mod aarch;
122pub mod iopad;
123pub mod mci;
124pub mod mci_host;
125pub mod osa;
126mod tools;
127
128pub use iopad::*;
129pub use mci_host::*;
130
131/// Platform abstraction trait for phytium-mci driver.
132///
133/// This trait must be implemented by the platform to provide platform-specific
134/// functionality required by the driver, including delay operations, memory
135/// management, and cache operations.
136///
137/// # Example
138///
139/// ```rust
140/// use phytium_mci::Kernel;
141/// use core::{ptr::NonNull, time::Duration};
142///
143/// struct MyPlatform;
144///
145/// impl Kernel for MyPlatform {
146///     fn sleep(duration: Duration) {
147///         // Implement platform-specific delay
148///         // e.g., using a timer or busy-waiting
149///     }
150///
151///     #[cfg(feature = "dma")]
152///     fn mmap(virt_addr: NonNull<u8>) -> u64 {
153///         // Convert virtual address to physical address
154///         // Required for DMA operations
155///     }
156///
157///     fn flush(addr: NonNull<u8>, size: usize) {
158///         // Clean data cache to ensure data is written to memory
159///         // Required before DMA write operations
160///     }
161///
162///     fn invalidate(addr: NonNull<u8>, size: usize) {
163///         // Invalidate data cache to ensure fresh data is read
164///         // Required after DMA read operations
165///     }
166/// }
167/// ```
168pub trait Kernel {
169    /// Delay execution for the specified duration.
170    ///
171    /// This is used for timing delays during card initialization and
172    /// command processing.
173    ///
174    /// # Arguments
175    ///
176    /// * `duration` - The duration to sleep
177    fn sleep(duration: Duration);
178
179    /// Convert virtual address to physical address.
180    ///
181    /// This is required for DMA operations to provide the physical
182    /// address of DMA buffers to the hardware.
183    ///
184    /// # Arguments
185    ///
186    /// * `virt_addr` - Virtual address to translate
187    ///
188    /// # Returns
189    ///
190    /// Physical address corresponding to the virtual address
191    #[cfg(feature = "dma")]
192    fn mmap(virt_addr: NonNull<u8>) -> u64;
193
194    /// Clean data cache for the specified memory range.
195    ///
196    /// Ensures that data in the cache is written back to memory.
197    /// This must be called before DMA write operations to ensure
198    /// the hardware sees the correct data.
199    ///
200    /// # Arguments
201    ///
202    /// * `addr` - Start address of the memory range
203    /// * `size` - Size of the memory range in bytes
204    fn flush(addr: NonNull<u8>, size: usize);
205
206    /// Invalidate data cache for the specified memory range.
207    ///
208    /// Discards cached data so that subsequent reads fetch fresh
209    /// data from memory. This must be called after DMA read
210    /// operations to ensure the CPU sees the data written by the hardware.
211    ///
212    /// # Arguments
213    ///
214    /// * `addr` - Start address of the memory range
215    /// * `size` - Size of the memory range in bytes
216    fn invalidate(addr: core::ptr::NonNull<u8>, size: usize);
217}
218
219pub(crate) fn sleep(duration: Duration) {
220    unsafe extern "Rust" {
221        fn _phytium_mci_sleep(duration: Duration);
222    }
223
224    unsafe {
225        _phytium_mci_sleep(duration);
226    }
227}
228
229#[cfg(feature = "dma")]
230pub(crate) fn mmap(virt_addr: NonNull<u8>) -> u64 {
231    unsafe extern "Rust" {
232        fn _phytium_mci_map(virt_addr: NonNull<u8>) -> u64;
233    }
234
235    unsafe { _phytium_mci_map(virt_addr) }
236}
237
238pub(crate) fn flush(addr: NonNull<u8>, size: usize) {
239    unsafe extern "Rust" {
240        fn _phytium_mci_flush(addr: NonNull<u8>, size: usize);
241    }
242
243    unsafe {
244        _phytium_mci_flush(addr, size);
245    }
246}
247
248pub(crate) fn invalidate(addr: core::ptr::NonNull<u8>, size: usize) {
249    unsafe extern "Rust" {
250        fn _phytium_mci_invalidate(addr: core::ptr::NonNull<u8>, size: usize);
251    }
252
253    unsafe {
254        _phytium_mci_invalidate(addr, size);
255    }
256}
257
258/// Register a platform-specific implementation of the [`Kernel`] trait.
259///
260/// This macro generates the external interface functions that the phytium-mci
261/// driver uses to call platform-specific operations. It should be called once
262/// with your platform type that implements the [`Kernel`] trait.
263///
264/// # Example
265///
266/// ```rust
267/// use phytium_mci::{Kernel, set_impl};
268/// use core::{ptr::NonNull, time::Duration};
269///
270/// struct MyPlatform;
271///
272/// impl Kernel for MyPlatform {
273///     fn sleep(duration: Duration) {
274///         // Your implementation
275///     }
276///
277///     #[cfg(feature = "dma")]
278///     fn mmap(virt_addr: NonNull<u8>) -> u64 {
279///         // Your implementation
280///     }
281///
282///     fn flush(addr: NonNull<u8>, size: usize) {
283///         // Your implementation
284///     }
285///
286///     fn invalidate(addr: NonNull<u8>, size: usize) {
287///         // Your implementation
288///     }
289/// }
290///
291/// // Register the implementation
292/// set_impl!(MyPlatform);
293/// ```
294///
295/// # Generated Functions
296///
297/// This macro generates the following `no_mangle` functions:
298/// - `_phytium_mci_sleep` - Sleep/delay functionality
299/// - `_phytium_mci_map` - Virtual to physical address translation (DMA only)
300/// - `_phytium_mci_flush` - Cache clean operation
301/// - `_phytium_mci_invalidate` - Cache invalidate operation
302#[macro_export]
303macro_rules! set_impl {
304    ($t: ty) => {
305        #[unsafe(no_mangle)]
306        unsafe fn _phytium_mci_sleep(duration: core::time::Duration) {
307            <$t as $crate::Kernel>::sleep(duration)
308        }
309        #[cfg(feature = "dma")]
310        #[unsafe(no_mangle)]
311        fn _phytium_mci_map(addr: core::ptr::NonNull<u8>) -> u64 {
312            <$t as $crate::Kernel>::mmap(addr)
313        }
314        #[unsafe(no_mangle)]
315        fn _phytium_mci_flush(addr: core::ptr::NonNull<u8>, size: usize) {
316            <$t as $crate::Kernel>::flush(addr, size)
317        }
318        #[unsafe(no_mangle)]
319        fn _phytium_mci_invalidate(addr: core::ptr::NonNull<u8>, size: usize) {
320            <$t as $crate::Kernel>::invalidate(addr, size)
321        }
322    };
323}