1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! [BCM2711 SPI][1]
//!
//! [1]: https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf#%5B%7B%22num%22%3A136%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C115%2C841.89%2Cnull%5D
use tock_registers::{register_bitfields, register_structs, registers::ReadWrite};

use crate::Vpa;

/// The base address of the SPI0 instance of [the SPI register block](Registers).
pub const BASE_SPI0: Vpa = Vpa(0x4_7e20_4000);
/// The base address of the SPI3 instance of [the SPI register block](Registers).
pub const BASE_SPI3: Vpa = Vpa(0x4_7e20_4600);
/// The base address of the SPI4 instance of [the SPI register block](Registers).
pub const BASE_SPI4: Vpa = Vpa(0x4_7e20_4800);
/// The base address of the SPI5 instance of [the SPI register block](Registers).
pub const BASE_SPI5: Vpa = Vpa(0x4_7e20_4a00);
/// The base address of the SPI6 instance of [the SPI register block](Registers).
pub const BASE_SPI6: Vpa = Vpa(0x4_7e20_4c00);

register_structs! {
    pub Registers {
        /// SPI master control and status
        (0x00 => pub cs: ReadWrite<u32, CS::Register>),
        /// SPI master TX and RX FIFOs
        (0x04 => pub fifo: ReadWrite<u32, FIFO::Register>),
        /// SPI master clock divider
        (0x08 => pub clk: ReadWrite<u32, CLK::Register>),
        /// SPI master data length
        (0x0c => pub dlen: ReadWrite<u32, DLEN::Register>),
        /// SPI LoSSI mode TOH
        (0x10 => pub ltoh: ReadWrite<u32, LTOH::Register>),
        /// SPI DMA DREQ controls
        (0x14 => pub dc: ReadWrite<u32, DC::Register>),
        (0x18 => @END),
    }
}

register_bitfields! {u32,
    pub CS [
        /// Chip select
        CS OFFSET(0) NUMBITS(2) [
            ChipSelect0 = 0b00,
            ChipSelect1 = 0b01,
            ChipSelect2 = 0b10,
        ],
        /// Clock phase
        CPHA OFFSET(2) NUMBITS(1) [
            FirstSclkTransitionAtMiddleOfDataBit = 0,
            FirstSclkTransitionAtBeginningOFDataBit = 1,
        ],
        /// Clock polarity
        CPOL OFFSET(3) NUMBITS(1) [
            RestStateIsLow = 0,
            RestStateIsHigh = 1,
        ],
        /// TX FIFO clear
        CLEAR_TX OFFSET(4) NUMBITS(1) [],
        /// RX FIFO clear
        CLEAR_RX OFFSET(5) NUMBITS(1) [],
        /// Chip select polarity
        CSPOL OFFSET(6) NUMBITS(1) [
            ActiveLow = 0,
            ActiveHigh = 1,
        ],
        /// Transfer active
        TA OFFSET(7) NUMBITS(1) [],
        /// DMA enable
        DMAEN OFFSET(8) NUMBITS(1) [],
        /// Interrupt on done
        INTD OFFSET(9) NUMBITS(1) [],
        /// Interrupt on RXR
        INTR OFFSET(10) NUMBITS(1) [],
        /// Automatically de-assert chip select
        ADCS OFFSET(11) NUMBITS(1) [],
        /// Read enable
        REN OFFSET(12) NUMBITS(1) [],
        /// LoSSI enable
        LEN OFFSET(13) NUMBITS(1) [
            Spi = 0,
            Lossi = 1,
        ],
        /// Unused
        LMONO OFFSET(14) NUMBITS(1) [],
        /// Unused
        TE_EN OFFSET(15) NUMBITS(1) [],
        /// Transfer done
        DONE OFFSET(16) NUMBITS(1) [],
        /// RX FIFO contains data
        RXD OFFSET(17) NUMBITS(1) [],
        /// TX FIFO can accept data
        TXD OFFSET(18) NUMBITS(1) [],
        /// RX FIFO needs reading
        RXR OFFSET(19) NUMBITS(1) [],
        /// RX FIFO full
        RXF OFFSET(20) NUMBITS(1) [],
        /// Chip select 0 polarity
        CSPOL0 OFFSET(21) NUMBITS(1) [
            ActiveLow = 0,
            ActiveHigh = 1,
        ],
        /// Chip select 1 polarity
        CSPOL1 OFFSET(22) NUMBITS(1) [
            ActiveLow = 0,
            ActiveHigh = 1,
        ],
        /// Chip select 2 polarity
        CSPOL2 OFFSET(23) NUMBITS(1) [
            ActiveLow = 0,
            ActiveHigh = 1,
        ],
        /// Enable DMA mode in LoSSI mode
        DMA_LEN OFFSET(24) NUMBITS(1) [],
        /// Enable long data word in LoSSI mode if `DMA_LEN` is set
        LEN_LONG OFFSET(25) NUMBITS(1) [],
    ]
}

register_bitfields! {u32,
    pub FIFO [
        /// Read from RX FIFO or write to TX FIFO
        ///
        /// *DMA Mode (`DMAEN` set):* If `TA` is clear, the first 32-bit write
        /// to this register will control `SPIDLEN` and `SPICS`. Subsequent
        /// reads and writes will be taken as four-byte data words to be read
        /// or written to the FIFOs.
        ///
        /// *Poll/Interrupt Mode (`DMAEN` clear, `TA` set):* Writes to the
        /// register write bytes to the TX FIFO. Reads from the register read
        /// bytes from the RX FIFO.
        DATA OFFSET(0) NUMBITS(32) [],
    ]
}

register_bitfields! {u32,
    pub CLK [
        /// Clock divider
        CDIV OFFSET(0) NUMBITS(16) [],
    ]
}

register_bitfields! {u32,
    pub DLEN [
        /// Data length: The number of bytes to transfer.
        LEN OFFSET(0) NUMBITS(16) [],
    ]
}

register_bitfields! {u32,
    pub LTOH [
        /// This sets the Output Hold delay in APB clocks. A value of `0` causes
        /// a one-clock delay.
        TOH OFFSET(0) NUMBITS(4) [],
    ]
}

register_bitfields! {u32,
    pub DC [
        /// DMA write request threshold
        TDREQ OFFSET(0) NUMBITS(8) [],
        /// DMA write panic threshold
        TPANIC OFFSET(8) NUMBITS(8) [],
        /// DMA read request threshold
        RDREQ OFFSET(16) NUMBITS(8) [],
        /// DMA read panic threshold
        RPANIC OFFSET(24) NUMBITS(8) [],
    ]
}