commit de71629ce95ed08bd9c6d124e22db286fd3be1e6
parent c8b11c0d45fd9d0a3b58e2da319595c2cbef619b
Author: Sylvia Ivory <git@sivory.net>
Date: Fri, 27 Feb 2026 21:14:28 -0800
Add SPI0 types
Diffstat:
| A | pi/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