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