1use core::marker::PhantomData;
2
3pub use crate::shared::{FifoClear, TriggerLevel};
4
5cfg_if::cfg_if! {
6 if #[cfg(feature = "vor1x")] {
7 pub const BASE_ADDR_0: usize = 0x4005_0000;
9 pub const BASE_ADDR_1: usize = 0x4005_1000;
11 pub const BASE_ADDR_2: usize = 0x4005_2000;
13 } else if #[cfg(feature = "vor4x")] {
14 pub const BASE_ADDR_0: usize = 0x4001_5000;
16 pub const BASE_ADDR_1: usize = 0x4001_5400;
18 pub const BASE_ADDR_2: usize = 0x4001_5800;
20 pub const BASE_ADDR_3: usize = 0x4001_5C00;
22 }
23}
24
25#[derive(Debug, PartialEq, Eq, Clone, Copy)]
26#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27pub enum Bank {
28 Spi0 = 0,
29 Spi1 = 1,
30 Spi2 = 2,
31 #[cfg(feature = "vor4x")]
32 Spi3 = 3,
33}
34
35impl Bank {
36 pub unsafe fn steal_regs(&self) -> MmioSpi<'static> {
42 Spi::new_mmio(*self)
43 }
44}
45
46#[bitbybit::bitenum(u4)]
47#[derive(Debug, PartialEq, Eq)]
48#[cfg_attr(feature = "defmt", derive(defmt::Format))]
49pub enum WordSize {
50 OneBit = 0x00,
51 FourBits = 0x03,
52 EightBits = 0x07,
53 SixteenBits = 0x0f,
54}
55
56#[derive(Debug, PartialEq, Eq)]
57#[bitbybit::bitenum(u3, exhaustive = true)]
58#[cfg_attr(feature = "defmt", derive(defmt::Format))]
59pub enum HwChipSelectId {
60 Id0 = 0,
61 Id1 = 1,
62 Id2 = 2,
63 Id3 = 3,
64 Id4 = 4,
65 Id5 = 5,
66 Id6 = 6,
67 Id7 = 7,
68}
69
70#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_fields(feature = "defmt"))]
71pub struct Control0 {
72 #[bits(8..=15, rw)]
73 scrdv: u8,
74 #[bit(7, rw)]
75 sph: bool,
76 #[bit(6, rw)]
77 spo: bool,
78 #[bits(0..=3, rw)]
79 word_size: Option<WordSize>,
80}
81
82#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_bitfields(feature = "defmt"))]
83pub struct Control1 {
84 #[bit(11, rw)]
85 mtxpause: bool,
86 #[bit(10, rw)]
87 mdlycap: bool,
88 #[bit(9, rw)]
89 bm_stall: bool,
90 #[bit(8, rw)]
91 bm_start: bool,
92 #[bit(7, rw)]
93 blockmode: bool,
94 #[bits(4..=6, rw)]
95 ss: HwChipSelectId,
96 #[bit(3, rw)]
97 sod: bool,
98 #[bit(2, rw)]
99 slave_mode: bool,
100 #[bit(1, rw)]
101 enable: bool,
102 #[bit(0, rw)]
103 lbm: bool,
104}
105
106#[bitbybit::bitfield(u32)]
107#[derive(Debug)]
108pub struct Data {
109 #[bit(31, rw)]
113 bm_start_stop: bool,
114 #[bit(30, rw)]
118 bm_skipdata: bool,
119 #[bits(0..=15, rw)]
120 data: u16,
121}
122
123#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
124pub struct Status {
125 #[bit(7, r)]
127 tx_trigger: bool,
128 #[bit(6, r)]
130 rx_trigger: bool,
131 #[bit(5, r)]
132 rx_data_first: bool,
133 #[bit(4, r)]
134 busy: bool,
135 #[bit(3, r)]
136 rx_full: bool,
137 #[bit(2, r)]
138 rx_not_empty: bool,
139 #[bit(1, r)]
140 tx_not_full: bool,
141 #[bit(0, r)]
142 tx_empty: bool,
143}
144
145#[derive(Debug, Copy, Clone, PartialEq, Eq)]
149pub struct ClockPrescaler(arbitrary_int::UInt<u32, 8>);
150
151impl ClockPrescaler {
152 pub const fn new(value: u8) -> Self {
153 ClockPrescaler(arbitrary_int::UInt::<u32, 8>::new(value as u32))
154 }
155 pub const fn value(&self) -> u8 {
156 self.0.value() as u8
157 }
158}
159
160#[bitbybit::bitfield(u32, debug, default = 0x0, defmt_bitfields(feature = "defmt"))]
161pub struct InterruptControl {
162 #[bit(3, rw)]
164 tx: bool,
165 #[bit(2, rw)]
167 rx: bool,
168 #[bit(1, rw)]
172 rx_timeout: bool,
173 #[bit(0, rw)]
174 rx_overrun: bool,
175}
176
177impl InterruptControl {
178 pub const DISABLE_ALL: Self = Self::ZERO;
179 pub const ENABLE_ALL: Self = Self::builder()
180 .with_tx(true)
181 .with_rx(true)
182 .with_rx_timeout(true)
183 .with_rx_overrun(true)
184 .build();
185}
186
187#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
188pub struct InterruptStatus {
189 #[bit(3, r)]
191 tx: bool,
192 #[bit(2, r)]
194 rx: bool,
195 #[bit(1, r)]
199 rx_timeout: bool,
200 #[bit(0, r)]
201 rx_overrun: bool,
202}
203
204#[bitbybit::bitfield(u32, default = 0x0)]
205#[derive(Debug)]
206pub struct InterruptClear {
207 #[bit(1, w)]
209 rx_timeout: bool,
210 #[bit(0, w)]
211 rx_overrun: bool,
212}
213
214impl InterruptClear {
215 pub const ALL: Self = Self::builder()
216 .with_rx_timeout(true)
217 .with_rx_overrun(true)
218 .build();
219}
220
221#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
222pub struct State {
223 #[bits(0..=7, r)]
224 rx_state: u8,
225 #[bits(8..=15, r)]
226 rx_fifo: u8,
227 #[bits(24..=31, r)]
228 tx_fifo: u8,
229}
230
231#[derive(derive_mmio::Mmio)]
232#[mmio(no_ctors)]
233#[repr(C)]
234pub struct Spi {
235 ctrl0: Control0,
236 ctrl1: Control1,
237 data: Data,
238 #[mmio(PureRead)]
239 status: Status,
240 clkprescale: ClockPrescaler,
241 interrupt_control: InterruptControl,
242 #[mmio(PureRead)]
244 interrupt_status_raw: InterruptStatus,
245 #[mmio(PureRead)]
247 interrupt_status: InterruptStatus,
248 #[mmio(Write)]
249 interrupt_clear: InterruptClear,
250 rx_fifo_trigger: TriggerLevel,
251 tx_fifo_trigger: TriggerLevel,
252 #[mmio(Write)]
253 fifo_clear: FifoClear,
254 #[mmio(PureRead)]
255 state: State,
256 #[cfg(feature = "vor1x")]
257 _reserved: [u32; 0x3F2],
258 #[cfg(feature = "vor4x")]
259 _reserved: [u32; 0xF2],
260 #[mmio(PureRead)]
262 perid: u32,
263}
264
265cfg_if::cfg_if! {
266 if #[cfg(feature = "vor1x")] {
267 static_assertions::const_assert_eq!(core::mem::size_of::<Spi>(), 0x1000);
268 } else if #[cfg(feature = "vor4x")] {
269 static_assertions::const_assert_eq!(core::mem::size_of::<Spi>(), 0x400);
270 }
271}
272
273impl Spi {
274 fn new_mmio_at(base: usize) -> MmioSpi<'static> {
275 MmioSpi {
276 ptr: base as *mut _,
277 phantom: PhantomData,
278 }
279 }
280
281 pub fn new_mmio(bank: Bank) -> MmioSpi<'static> {
282 match bank {
283 Bank::Spi0 => Self::new_mmio_at(BASE_ADDR_0),
284 Bank::Spi1 => Self::new_mmio_at(BASE_ADDR_1),
285 Bank::Spi2 => Self::new_mmio_at(BASE_ADDR_2),
286 #[cfg(feature = "vor4x")]
287 Bank::Spi3 => Self::new_mmio_at(BASE_ADDR_2),
288 }
289 }
290}