sylveos

Toy Operating System
Log | Files | Refs

commit de71629ce95ed08bd9c6d124e22db286fd3be1e6
parent c8b11c0d45fd9d0a3b58e2da319595c2cbef619b
Author: Sylvia Ivory <git@sivory.net>
Date:   Fri, 27 Feb 2026 21:14:28 -0800

Add SPI0 types

Diffstat:
Api/spi.zig | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 116 insertions(+), 0 deletions(-)

diff --git a/pi/spi.zig b/pi/spi.zig @@ -0,0 +1,116 @@ +const std = @import("std"); + +const mem = @import("./mem.zig"); +const register = @import("./register.zig"); + +const BASE_ADDRESS: usize = mem.BASE_ADDRESS + 0x0020_4000; +const CS: register.Register(MasterControlStatus, .ReadModifyWrite) = .init(BASE_ADDRESS + 0x00); +const FIFO: register.Register(FiFo, .ReadModifyWrite) = .init(BASE_ADDRESS + 0x04); +const CLK: register.Register(Clk, .ReadModifyWrite) = .init(BASE_ADDRESS + 0x08); +const DATA_LENGTH: register.Register(DataLength, .ReadModifyWrite) = .init(BASE_ADDRESS + 0x0C); +const LTOH: register.Register(Ltoh, .ReadModifyWrite) = .init(BASE_ADDRESS + 0x10); +const DC: register.Register(Dc, .ReadModifyWrite) = .init(BASE_ADDRESS + 0x14); + +const MasterControlStatus = packed struct(u32) { + pub const ChipSelect = enum(u2) { + @"0" = 0b00, + @"1" = 0b01, + @"2" = 0b10, + }; + + pub const ClockPhase = enum(u1) { + Middle = 0, + Beginning = 1, + }; + + pub const ClockPolarity = enum(u1) { + Low = 0, + High = 1, + }; + + pub const FiFoClear = packed struct(u2) { + clear_tx: bool, + clear_rx: bool, + }; + + pub const ChipSelectPolarity = enum(u1) { + SelectActoveLow = 0, + SelectActiveHigh = 1, + }; + + pub const Ren = enum(u1) { + Write = 0, + Read = 1, + }; + + pub const Len = enum(u1) { + SPIMaster = 0, + LoSSIMasster = 1, + }; + + pub const TransferProgress = enum(u1) { + InProgress = 0, + Complete = 1, + }; + + chip_select: ChipSelect = .@"0", + clock_phase: ClockPhase = .Middle, + clock_polarity: ClockPolarity = .Low, + clear_fifo_clear: FiFoClear = .{ .clear_tx = false, .clear_rx = false }, + chip_select_polarity: ChipSelectPolarity = .SelectActoveLow, + transfer_active: bool = false, + dma_enable: bool = false, + interrupt_on_done: bool = false, + interrupt_on_rx: bool = false, + automatically_deassert_chip_select: bool = false, + ren: Ren = .Write, + len_lossi_enable: Len = .SPIMaster, + _unused_14: u1 = 0, + _unused_15: u1 = 0, + transfer_progress: TransferProgress = .InProgress, + rxd_contains_data: bool = false, + txd_has_space: bool = true, + rxr_is_full: bool = false, + rxf_is_full: bool = false, + chip_select_0: ChipSelectPolarity = .SelectActoveLow, + chip_select_1: ChipSelectPolarity = .SelectActoveLow, + chip_select_2: ChipSelectPolarity = .SelectActoveLow, + dma_enable_lossi: bool = false, + lossi_write_u32: bool = false, + _reserved_31_26: u6, +}; + +const FiFo = packed union { + bytes: [@sizeOf(u32) / @sizeOf(u8)]u8, + long: u32, +}; + +const Clk = packed struct(u32) { + clock_divider: u16 = 0, + _reserved_31_16: u16 = 0, +}; + +const DataLength = packed struct(u32) { + length: u32, + _reserved_31_16: u32, +}; + +const Ltoh = packed struct(u32) { + toh: u4, + _reserved_31_4: u28, +}; + +const Dc = packed struct(u32) { + dma_write_request_threshold: u8, + dma_write_panic_threshold: u8, + dma_read_request_threshold: u8, + dma_read_panic_threshold: u8, +}; + +// Polled: +// 1. Set CS(MasterControlStatus), CPOL(chip_select_polarity), CPHA(clock_phase) +// as required and set TA(transfer_active) = 1 +// 2. Poll TXD(txd_has_space) writing bytes to SPI_FIFO(FiFo), RXD(rxd_contains_data) +// reading bytes from SPI_FIFO(FiFo) until all data is written +// 3. Poll DONE(transfer_progress) until it goes to 1 +// 4. Set TA(transfer_active) = 0