xref: /qemu/rust/hw/char/pl011/src/registers.rs (revision f8a113701dd2d28f3bedb216e59125ddcb77fd05)
1 // Copyright 2024, Linaro Limited
2 // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
3 // SPDX-License-Identifier: GPL-2.0-or-later
4 
5 //! Device registers exposed as typed structs which are backed by arbitrary
6 //! integer bitmaps. [`Data`], [`Control`], [`LineControl`], etc.
7 
8 // For more detail see the PL011 Technical Reference Manual DDI0183:
9 // https://developer.arm.com/documentation/ddi0183/latest/
10 
11 use bilge::prelude::*;
12 use bits::bits;
13 use qemu_api::{impl_vmstate_bitsized, impl_vmstate_forward};
14 
15 /// Offset of each register from the base memory address of the device.
16 #[doc(alias = "offset")]
17 #[allow(non_camel_case_types)]
18 #[repr(u64)]
19 #[derive(Debug, Eq, PartialEq, qemu_api_macros::TryInto)]
20 pub enum RegisterOffset {
21     /// Data Register
22     ///
23     /// A write to this register initiates the actual data transmission
24     #[doc(alias = "UARTDR")]
25     DR = 0x000,
26     /// Receive Status Register or Error Clear Register
27     #[doc(alias = "UARTRSR")]
28     #[doc(alias = "UARTECR")]
29     RSR = 0x004,
30     /// Flag Register
31     ///
32     /// A read of this register shows if transmission is complete
33     #[doc(alias = "UARTFR")]
34     FR = 0x018,
35     /// Fractional Baud Rate Register
36     ///
37     /// responsible for baud rate speed
38     #[doc(alias = "UARTFBRD")]
39     FBRD = 0x028,
40     /// `IrDA` Low-Power Counter Register
41     #[doc(alias = "UARTILPR")]
42     ILPR = 0x020,
43     /// Integer Baud Rate Register
44     ///
45     /// Responsible for baud rate speed
46     #[doc(alias = "UARTIBRD")]
47     IBRD = 0x024,
48     /// line control register (data frame format)
49     #[doc(alias = "UARTLCR_H")]
50     LCR_H = 0x02C,
51     /// Toggle UART, transmission or reception
52     #[doc(alias = "UARTCR")]
53     CR = 0x030,
54     /// Interrupt FIFO Level Select Register
55     #[doc(alias = "UARTIFLS")]
56     FLS = 0x034,
57     /// Interrupt Mask Set/Clear Register
58     #[doc(alias = "UARTIMSC")]
59     IMSC = 0x038,
60     /// Raw Interrupt Status Register
61     #[doc(alias = "UARTRIS")]
62     RIS = 0x03C,
63     /// Masked Interrupt Status Register
64     #[doc(alias = "UARTMIS")]
65     MIS = 0x040,
66     /// Interrupt Clear Register
67     #[doc(alias = "UARTICR")]
68     ICR = 0x044,
69     /// DMA control Register
70     #[doc(alias = "UARTDMACR")]
71     DMACR = 0x048,
72     ///// Reserved, offsets `0x04C` to `0x07C`.
73     //Reserved = 0x04C,
74 }
75 
76 /// Receive Status Register / Data Register common error bits
77 ///
78 /// The `UARTRSR` register is updated only when a read occurs
79 /// from the `UARTDR` register with the same status information
80 /// that can also be obtained by reading the `UARTDR` register
81 #[bitsize(8)]
82 #[derive(Clone, Copy, Default, DebugBits, FromBits)]
83 pub struct Errors {
84     pub framing_error: bool,
85     pub parity_error: bool,
86     pub break_error: bool,
87     pub overrun_error: bool,
88     _reserved_unpredictable: u4,
89 }
90 
91 /// Data Register, `UARTDR`
92 ///
93 /// The `UARTDR` register is the data register; write for TX and
94 /// read for RX. It is a 12-bit register, where bits 7..0 are the
95 /// character and bits 11..8 are error bits.
96 #[bitsize(32)]
97 #[derive(Clone, Copy, Default, DebugBits, FromBits)]
98 #[doc(alias = "UARTDR")]
99 pub struct Data {
100     pub data: u8,
101     pub errors: Errors,
102     _reserved: u16,
103 }
104 impl_vmstate_bitsized!(Data);
105 
106 impl Data {
107     // bilge is not very const-friendly, unfortunately
108     pub const BREAK: Self = Self { value: 1 << 10 };
109 }
110 
111 /// Receive Status Register / Error Clear Register, `UARTRSR/UARTECR`
112 ///
113 /// This register provides a different way to read the four receive
114 /// status error bits that can be found in bits 11..8 of the UARTDR
115 /// on a read. It gets updated when the guest reads UARTDR, and the
116 /// status bits correspond to that character that was just read.
117 ///
118 /// The TRM confusingly describes this offset as UARTRSR for reads
119 /// and UARTECR for writes, but really it's a single error status
120 /// register where writing anything to the register clears the error
121 /// bits.
122 #[bitsize(32)]
123 #[derive(Clone, Copy, DebugBits, FromBits)]
124 pub struct ReceiveStatusErrorClear {
125     pub errors: Errors,
126     _reserved_unpredictable: u24,
127 }
128 impl_vmstate_bitsized!(ReceiveStatusErrorClear);
129 
130 impl ReceiveStatusErrorClear {
set_from_data(&mut self, data: Data)131     pub fn set_from_data(&mut self, data: Data) {
132         self.set_errors(data.errors());
133     }
134 
reset(&mut self)135     pub fn reset(&mut self) {
136         // All the bits are cleared to 0 on reset.
137         *self = Self::default();
138     }
139 }
140 
141 impl Default for ReceiveStatusErrorClear {
default() -> Self142     fn default() -> Self {
143         0.into()
144     }
145 }
146 
147 #[bitsize(32)]
148 #[derive(Clone, Copy, DebugBits, FromBits)]
149 /// Flag Register, `UARTFR`
150 ///
151 /// This has the usual inbound RS232 modem-control signals, plus flags
152 /// for RX and TX FIFO fill levels and a BUSY flag.
153 #[doc(alias = "UARTFR")]
154 pub struct Flags {
155     /// CTS: Clear to send
156     pub clear_to_send: bool,
157     /// DSR: Data set ready
158     pub data_set_ready: bool,
159     /// DCD: Data carrier detect
160     pub data_carrier_detect: bool,
161     /// BUSY: UART busy. In real hardware, set while the UART is
162     /// busy transmitting data. QEMU's implementation never sets BUSY.
163     pub busy: bool,
164     /// RXFE: Receive FIFO empty
165     pub receive_fifo_empty: bool,
166     /// TXFF: Transmit FIFO full
167     pub transmit_fifo_full: bool,
168     /// RXFF: Receive FIFO full
169     pub receive_fifo_full: bool,
170     /// TXFE: Transmit FIFO empty
171     pub transmit_fifo_empty: bool,
172     /// RI: Ring indicator
173     pub ring_indicator: bool,
174     _reserved_zero_no_modify: u23,
175 }
176 impl_vmstate_bitsized!(Flags);
177 
178 impl Flags {
reset(&mut self)179     pub fn reset(&mut self) {
180         *self = Self::default();
181     }
182 }
183 
184 impl Default for Flags {
default() -> Self185     fn default() -> Self {
186         let mut ret: Self = 0.into();
187         // After reset TXFF, RXFF, and BUSY are 0, and TXFE and RXFE are 1
188         ret.set_receive_fifo_empty(true);
189         ret.set_transmit_fifo_empty(true);
190         ret
191     }
192 }
193 
194 #[bitsize(32)]
195 #[derive(Clone, Copy, DebugBits, FromBits)]
196 /// Line Control Register, `UARTLCR_H`
197 #[doc(alias = "UARTLCR_H")]
198 pub struct LineControl {
199     /// BRK: Send break
200     pub send_break: bool,
201     /// PEN: Parity enable
202     pub parity_enabled: bool,
203     /// EPS: Even parity select
204     pub parity: Parity,
205     /// STP2: Two stop bits select
206     pub two_stops_bits: bool,
207     /// FEN: Enable FIFOs
208     pub fifos_enabled: Mode,
209     /// WLEN: Word length in bits
210     /// b11 = 8 bits
211     /// b10 = 7 bits
212     /// b01 = 6 bits
213     /// b00 = 5 bits.
214     pub word_length: WordLength,
215     /// SPS Stick parity select
216     pub sticky_parity: bool,
217     /// 31:8 - Reserved, do not modify, read as zero.
218     _reserved_zero_no_modify: u24,
219 }
220 impl_vmstate_bitsized!(LineControl);
221 
222 impl LineControl {
reset(&mut self)223     pub fn reset(&mut self) {
224         // All the bits are cleared to 0 when reset.
225         *self = 0.into();
226     }
227 }
228 
229 impl Default for LineControl {
default() -> Self230     fn default() -> Self {
231         0.into()
232     }
233 }
234 
235 #[bitsize(1)]
236 #[derive(Clone, Copy, Debug, Eq, FromBits, PartialEq)]
237 /// `EPS` "Even parity select", field of [Line Control
238 /// register](LineControl).
239 pub enum Parity {
240     Odd = 0,
241     Even = 1,
242 }
243 
244 #[bitsize(1)]
245 #[derive(Clone, Copy, Debug, Eq, FromBits, PartialEq)]
246 /// `FEN` "Enable FIFOs" or Device mode, field of [Line Control
247 /// register](LineControl).
248 pub enum Mode {
249     /// 0 = FIFOs are disabled (character mode) that is, the FIFOs become
250     /// 1-byte-deep holding registers
251     Character = 0,
252     /// 1 = transmit and receive FIFO buffers are enabled (FIFO mode).
253     FIFO = 1,
254 }
255 
256 #[bitsize(2)]
257 #[derive(Clone, Copy, Debug, Eq, FromBits, PartialEq)]
258 /// `WLEN` Word length, field of [Line Control register](LineControl).
259 ///
260 /// These bits indicate the number of data bits transmitted or received in a
261 /// frame as follows:
262 pub enum WordLength {
263     /// b11 = 8 bits
264     _8Bits = 0b11,
265     /// b10 = 7 bits
266     _7Bits = 0b10,
267     /// b01 = 6 bits
268     _6Bits = 0b01,
269     /// b00 = 5 bits.
270     _5Bits = 0b00,
271 }
272 
273 /// Control Register, `UARTCR`
274 ///
275 /// The `UARTCR` register is the control register. It contains various
276 /// enable bits, and the bits to write to set the usual outbound RS232
277 /// modem control signals. All bits reset to 0 except TXE and RXE.
278 #[bitsize(32)]
279 #[doc(alias = "UARTCR")]
280 #[derive(Clone, Copy, DebugBits, FromBits)]
281 pub struct Control {
282     /// `UARTEN` UART enable: 0 = UART is disabled.
283     pub enable_uart: bool,
284     /// `SIREN` `SIR` enable: disable or enable IrDA SIR ENDEC.
285     /// QEMU does not model this.
286     pub enable_sir: bool,
287     /// `SIRLP` SIR low-power IrDA mode. QEMU does not model this.
288     pub sir_lowpower_irda_mode: u1,
289     /// Reserved, do not modify, read as zero.
290     _reserved_zero_no_modify: u4,
291     /// `LBE` Loopback enable: feed UART output back to the input
292     pub enable_loopback: bool,
293     /// `TXE` Transmit enable
294     pub enable_transmit: bool,
295     /// `RXE` Receive enable
296     pub enable_receive: bool,
297     /// `DTR` Data transmit ready
298     pub data_transmit_ready: bool,
299     /// `RTS` Request to send
300     pub request_to_send: bool,
301     /// `Out1` UART Out1 signal; can be used as DCD
302     pub out_1: bool,
303     /// `Out2` UART Out2 signal; can be used as RI
304     pub out_2: bool,
305     /// `RTSEn` RTS hardware flow control enable
306     pub rts_hardware_flow_control_enable: bool,
307     /// `CTSEn` CTS hardware flow control enable
308     pub cts_hardware_flow_control_enable: bool,
309     /// 31:16 - Reserved, do not modify, read as zero.
310     _reserved_zero_no_modify2: u16,
311 }
312 impl_vmstate_bitsized!(Control);
313 
314 impl Control {
reset(&mut self)315     pub fn reset(&mut self) {
316         *self = 0.into();
317         self.set_enable_receive(true);
318         self.set_enable_transmit(true);
319     }
320 }
321 
322 impl Default for Control {
default() -> Self323     fn default() -> Self {
324         let mut ret: Self = 0.into();
325         ret.reset();
326         ret
327     }
328 }
329 
330 bits! {
331     /// Interrupt status bits in UARTRIS, UARTMIS, UARTIMSC
332     #[derive(Default)]
333     pub struct Interrupt(u32) {
334         OE = 1 << 10,
335         BE = 1 << 9,
336         PE = 1 << 8,
337         FE = 1 << 7,
338         RT = 1 << 6,
339         TX = 1 << 5,
340         RX = 1 << 4,
341         DSR = 1 << 3,
342         DCD = 1 << 2,
343         CTS = 1 << 1,
344         RI = 1 << 0,
345 
346         E = bits!(Self as u32: OE | BE | PE | FE),
347         MS = bits!(Self as u32: RI | DSR | DCD | CTS),
348     }
349 }
350 impl_vmstate_forward!(Interrupt);
351