ove/
spi.rs

1// Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4//
5// This file is part of oveRTOS.
6
7//! SPI bus master driver.
8//!
9//! Provides safe wrappers around the oveRTOS SPI API with software CS
10//! management, thread-safe bus locking, and multi-segment transactions.
11
12use crate::bindings;
13use crate::error::{Error, Result};
14
15/// SPI clock mode (CPOL/CPHA).
16#[repr(u32)]
17#[derive(Debug, Copy, Clone, PartialEq, Eq)]
18pub enum Mode {
19    Mode0 = 0,
20    Mode1 = 1,
21    Mode2 = 2,
22    Mode3 = 3,
23}
24
25/// SPI bit order.
26#[repr(u32)]
27#[derive(Debug, Copy, Clone, PartialEq, Eq)]
28pub enum BitOrder {
29    MsbFirst = 0,
30    LsbFirst = 1,
31}
32
33/// Full-duplex SPI transfer. `tx` or `rx` may be empty for half-duplex.
34pub fn transfer(
35    spi: bindings::ove_spi_t,
36    cs: Option<&bindings::ove_spi_cs>,
37    tx: &[u8],
38    rx: &mut [u8],
39    timeout_ms: u32,
40) -> Result<()> {
41    let len = tx.len().max(rx.len());
42    let cs_ptr = cs.map_or(core::ptr::null(), |c| c as *const _);
43    let tx_ptr = if tx.is_empty() { core::ptr::null() } else { tx.as_ptr().cast() };
44    let rx_ptr = if rx.is_empty() { core::ptr::null_mut() } else { rx.as_mut_ptr().cast() };
45    let rc = unsafe { bindings::ove_spi_transfer(spi, cs_ptr, tx_ptr, rx_ptr, len, timeout_ms) };
46    Error::from_code(rc)
47}
48
49/// Write-only SPI transfer.
50pub fn write(
51    spi: bindings::ove_spi_t,
52    cs: Option<&bindings::ove_spi_cs>,
53    data: &[u8],
54    timeout_ms: u32,
55) -> Result<()> {
56    let cs_ptr = cs.map_or(core::ptr::null(), |c| c as *const _);
57    let rc = unsafe {
58        bindings::ove_spi_write(spi, cs_ptr, data.as_ptr().cast(), data.len(), timeout_ms)
59    };
60    Error::from_code(rc)
61}
62
63/// Read-only SPI transfer (clocks out zeros).
64pub fn read(
65    spi: bindings::ove_spi_t,
66    cs: Option<&bindings::ove_spi_cs>,
67    buf: &mut [u8],
68    timeout_ms: u32,
69) -> Result<()> {
70    let cs_ptr = cs.map_or(core::ptr::null(), |c| c as *const _);
71    let rc = unsafe {
72        bindings::ove_spi_read(spi, cs_ptr, buf.as_mut_ptr().cast(), buf.len(), timeout_ms)
73    };
74    Error::from_code(rc)
75}