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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
//! [Auxiliaries][1]
//!
//! [1]: https://datasheets.raspberrypi.com/bcm2711/bcm2711-peripherals.pdf#%5B%7B%22num%22%3A11%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::{ReadOnly, ReadWrite},
};

use crate::Vpa;

/// The base address of [the AUX Mini UART register block](Registers).
pub const BASE: Vpa = Vpa(0x4_7e21_5000);

register_structs! {
    pub Registers {
        (0x00 => pub aux_irq: ReadOnly<u32, AUX_IRQ::Register>),
        (0x04 => pub aux_enables: ReadWrite<u32, AUX_ENABLES::Register>),
        (0x08 => _pad0),
        (0x40 => pub aux_mu: MiniUartRegisters),
        (0x80 => pub aux_spi1: SpiRegisters),
        (0xc0 => pub aux_spi2: SpiRegisters),
        (0x100 => @END),
    },

    pub MiniUartRegisters {
        (0x00 => pub io_reg: ReadWrite<u32, AUX_MU_IO_REG::Register>),
        (0x04 => pub ier_reg: ReadWrite<u32, AUX_MU_IER_REG::Register>),
        (0x08 => pub iir_reg: ReadWrite<u32, AUX_MU_IIR_REG::Register>),
        (0x0c => pub lcr_reg: ReadWrite<u32, AUX_MU_LCR_REG::Register>),
        (0x10 => pub mcr_reg: ReadWrite<u32, AUX_MU_MCR_REG::Register>),
        (0x14 => pub lsr_reg: ReadOnly<u32, AUX_MU_LSR_REG::Register>),
        (0x18 => pub msr_reg: ReadOnly<u32, AUX_MU_MSR_REG::Register>),
        (0x1c => pub scratch: ReadWrite<u32, AUX_MU_SCRATCH::Register>),
        (0x20 => pub cntl_reg: ReadWrite<u32, AUX_MU_CNTL_REG::Register>),
        (0x24 => pub stat_reg: ReadOnly<u32, AUX_MU_STAT_REG::Register>),
        (0x28 => pub baud_reg: ReadWrite<u32, AUX_MU_BAUD_REG::Register>),
        (0x2c => _pad0),
        (0x40 => @END),
    },

    pub SpiRegisters {
        (0x00 => pub cntl0_reg: ReadWrite<u32, AUX_SPI_CNTL0_REG::Register>),
        (0x04 => pub cntl1_reg: ReadWrite<u32, AUX_SPI_CNTL1_REG::Register>),
        (0x08 => pub stat_reg: ReadOnly<u32, AUX_SPI_STAT_REG::Register>),
        (0x0c => pub peek_reg: ReadOnly<u32, AUX_SPI_DATA::Register>),
        (0x10 => _pad0),
        (0x20 => pub io_rega: ReadWrite<u32, AUX_SPI_DATA::Register>),
        (0x24 => pub io_regb: ReadWrite<u32, AUX_SPI_DATA::Register>),
        (0x28 => pub io_regc: ReadWrite<u32, AUX_SPI_DATA::Register>),
        (0x2c => pub io_regd: ReadWrite<u32, AUX_SPI_DATA::Register>),
        (0x30 => pub txhold_rega: ReadWrite<u32, AUX_SPI_DATA::Register>),
        (0x34 => pub txhold_regb: ReadWrite<u32, AUX_SPI_DATA::Register>),
        (0x38 => pub txhold_regc: ReadWrite<u32, AUX_SPI_DATA::Register>),
        (0x3c => pub txhold_regd: ReadWrite<u32, AUX_SPI_DATA::Register>),
        (0x40 => @END),
    }
}

register_bitfields! {u32,
    pub AUX_IRQ [
        /// If set the mini UART has an interrupt pending.
        MINI_UART_IRQ OFFSET(0) NUMBITS(1) [],
        /// If set the SPI1 module has an interrupt pending.
        SPI1_IRQ OFFSET(1) NUMBITS(1) [],
        /// If set the SPI2 module has an interrupt pending.
        SPI2_IRQ OFFSET(2) NUMBITS(1) [],
    ]
}

register_bitfields! {u32,
    pub AUX_ENABLES [
        /// If set the mini UART is enabled.
        MINI_UART_ENABLE OFFSET(0) NUMBITS(1) [],
        /// If set the SPI1 module is enabled.
        SPI1_ENABLE OFFSET(1) NUMBITS(1) [],
        /// If set the SPI2 module is enabled.
        SPI2_ENABLE OFFSET(2) NUMBITS(1) [],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_IO_REG [
        /// Receive data read, `DLAB` = 0
        RX_DATA OFFSET(0) NUMBITS(8) [],
        /// Transmit data write, `DLAB` = 0
        TX_DATA OFFSET(8) NUMBITS(8) [],
        /// LS 8 bits baudrate, `DLAB` = 1
        BAUDRATE_LO OFFSET(16) NUMBITS(8) [],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_IER_REG [
        /// Enable transmit interrupt, `DLAB` = 0
        TX_INT_ENABLE OFFSET(0) NUMBITS(1) [],
        /// Enable receive interrupt, `DLAB` = 0
        RX_INT_ENABLE OFFSET(1) NUMBITS(1) [],
        /// MS 8 bits baudrate, `DLAB` = 1
        BAUDRATE_HI OFFSET(0) NUMBITS(8) [],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_IIR_REG [
        /// Interrupt pending
        INT_PENDING OFFSET(0) NUMBITS(1) [],
        /// TX interrupt ID bit (read), FIFO clear (write)
        TX_INT_PENDING_FIFO_CLEAR OFFSET(1) NUMBITS(1) [],
        /// RX interrupt ID bit (write), FIFO clear (read)
        RX_INT_PENDING_FIFO_CLEAR OFFSET(2) NUMBITS(1) [],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_LCR_REG [
        /// Data size
        DATA_SIZE OFFSET(0) NUMBITS(1) [
            SevenBits = 7,
            EightBits = 8,
        ],
        /// Break
        BREAK OFFSET(6) NUMBITS(1) [],
        /// DLAB access - if set the first two Mini UART registers give access
        /// to the Baudrate register.
        DLAB OFFSET(7) NUMBITS(1) [
            Normal = 0,
            RouteToBaudrateReg = 1,
        ],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_MCR_REG [
        /// RTS signal (if set `UART1_RTS` pin is low)
        RTS OFFSET(1) NUMBITS(1) [
            High = 0,
            Low = 1,
        ],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_LSR_REG [
        /// Data ready
        DATA_READY OFFSET(0) NUMBITS(1) [],
        /// Receiver overrun (RO)
        RX_OVERRUN OFFSET(1) NUMBITS(1) [],
        /// Transmitter empty
        TX_EMPTY OFFSET(5) NUMBITS(1) [],
        /// Transmitter idle
        TX_IDLE OFFSET(6) NUMBITS(1) [],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_MSR_REG [
        /// CTS status (if set `UART1_CTS` pin is low)
        CTS OFFSET(4) NUMBITS(1) [
            High = 0,
            Low = 1,
        ],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_SCRATCH [
        /// Scratch
        SCRATCH OFFSET(0) NUMBITS(8) [],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_CNTL_REG [
        /// Receiver enable
        RX_ENABLE OFFSET(0) NUMBITS(1) [],
        /// Transmitter enable
        TX_ENABLE OFFSET(1) NUMBITS(1) [],
        /// Enable receive auto flow-control using RTS
        RTS_AFC OFFSET(2) NUMBITS(1) [],
        /// Enable transmit auto flow-control using CTS
        CTS_AFC OFFSET(3) NUMBITS(1) [],
        // RTS auto flow level
        RTS_AFC_LEVEL OFFSET(4) NUMBITS(2) [
            Three = 0b00,
            Two = 0b01,
            One = 0b10,
            Four = 0b11,
        ],
        /// RTS assert level
        RTS_AFC_POLARITY OFFSET(6) NUMBITS(1) [],
        /// CTS assert level
        CTS_AFC_POLARITY OFFSET(7) NUMBITS(1) [],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_STAT_REG [
        /// Symbol available
        RX_NOT_EMPTY OFFSET(0)  NUMBITS(1) [],
        /// Space available
        TX_NOT_FULL OFFSET(1) NUMBITS(1) [],
        /// Receiver is idle
        RX_IDLE OFFSET(2) NUMBITS(1) [],
        /// Transmitter is idle
        TX_IDLE OFFSET(3) NUMBITS(1) [],
        /// Receiver overrun
        RX_OVERRUN OFFSET(4) NUMBITS(1) [],
        /// Transmit FIFO is full
        TX_FULL OFFSET(5) NUMBITS(1) [],
        /// RTS status
        RTS OFFSET(6) NUMBITS(1) [],
        /// CTS line
        CTS OFFSET(7) NUMBITS(1) [],
        /// Transmit FIFO is empty
        TX_EMPTY OFFSET(8) NUMBITS(1) [],
        /// Transmitter done
        TX_DONE OFFSET(9) NUMBITS(1) [],
        /// Receive FIFO fill level (`0..=8`)
        RX_FIFO_LEVEL OFFSET(16) NUMBITS(4) [],
        /// Transmit FIFO fill level (`0..=8`)
        TX_FIFO_LEVEL OFFSET(24) NUMBITS(4) [],
    ]
}

register_bitfields! {u32,
    pub AUX_MU_BAUD_REG [
        /// Baudrate
        BAUDRATE OFFSET(0) NUMBITS(16) [],
    ]
}

register_bitfields! {u32,
    pub AUX_SPI_CNTL0_REG [
        /// Shift length
        SHIFT_LEN OFFSET(0) NUMBITS(6) [],
        /// SHift out MS bit first
        SHIFT_OUT_DIR OFFSET(6) NUMBITS(1) [
            LsbFirst = 0,
            MsbFirst = 1,
        ],
        /// Invert SPI CLK
        CLK_POLARITY OFFSET(7) NUMBITS(1) [
            IdleLow = 0,
            IdleHigh = 1,
        ],
        /// Out rising
        OUT_EDGE OFFSET(8) NUMBITS(1) [
            FallingEdge = 0,
            RisingEdge = 1,
        ],
        /// Clear FIFOs
        CLEAR_FIFO OFFSET(9) NUMBITS(1) [],
        /// In rising
        IN_EDGE OFFSET(10) NUMBITS(1) [
            FallingEdge = 0,
            RisingEdge = 1,
        ],
        /// Enable
        ENABLE OFFSET(11) NUMBITS(1) [],
        /// DOUT hold time
        DOUT_HOLD_TIME OFFSET(12) NUMBITS(2) [
            Zero = 0b00,
            One = 0b01,
            Four = 0b10,
            Seven = 0b11,
        ],
        /// Variable width
        VARIABLE_WIDTH OFFSET(14) NUMBITS(1) [],
        /// Variable CS
        VARIABLE_CS OFFSET(15) NUMBITS(1) [],
        /// Post-input mode
        POST_INPUT OFFSET(16) NUMBITS(1) [],
        /// Chip selects
        CS OFFSET(17) NUMBITS(3) [],
        /// Speed: `spi_clk_freq = system_clock_freq / 2 * (speed + 1)`
        SPEED OFFSET(20) NUMBITS(12) [],
    ]
}

register_bitfields! {u32,
    pub AUX_SPI_CNTL1_REG [
        /// Keep input
        KEEP_INPUT OFFSET(0) NUMBITS(1) [],
        /// SHift in MS bit first
        SHIFT_IN_DIR OFFSET(1) NUMBITS(1) [
            LsbFirst = 0,
            MsbFirst = 1,
        ],
        /// Done IRQ
        DONE_IRQ OFFSET(6) NUMBITS(1) [],
        /// TX empty IRQ
        TX_EMPTY_IRQ OFFSET(7) NUMBITS(1) [],
        /// CS high time
        CS_HIGH_TIME OFFSET(8) NUMBITS(3) [],
    ]
}

register_bitfields! {u32,
    pub AUX_SPI_STAT_REG [
        /// Bit count
        BIT_COUNT OFFSET(0) NUMBITS(6) [],
        /// Busy
        BUSY OFFSET(6) NUMBITS(1) [],
        /// RX empty
        RX_EMPTY OFFSET(7) NUMBITS(1) [],
        /// RX full
        RX_FULL OFFSET(8) NUMBITS(1) [],
        /// TX empty
        TX_EMPTY OFFSET(9) NUMBITS(1) [],
        /// TX full
        TX_FULL OFFSET(10) NUMBITS(1) [],
        /// RX fifo level
        RX_FIFO_LEVEL OFFSET(16) NUMBITS(4) [],
        /// TX fifo level
        TX_FIFO_LEVEL OFFSET(24) NUMBITS(4) [],
    ]
}

register_bitfields! {u32,
    pub AUX_SPI_DATA [
        DATA OFFSET(0) NUMBITS(16) [],
    ]
}