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