rust: pl011: Cut down amount of text quoted from PL011 TRM

Currently the comments in the Rust pl011 register.rs file include
large amounts of text from the PL011 TRM.  This is much more
commentary than we typically quote from a device reference manual,
and much of it is not relevant to QEMU.  Compress and rephrase the
comments so that we are not quoting such a large volume of TRM text.

We add a URL for the TRM; readers who need more detail on the
function of the register bits can find it there, presented in
context with the overall description of the hardware.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Peter Maydell 2025-05-14 14:29:47 +01:00
parent ec7e5a90fe
commit 6414b7709d

View file

@ -5,13 +5,13 @@
//! Device registers exposed as typed structs which are backed by arbitrary //! Device registers exposed as typed structs which are backed by arbitrary
//! integer bitmaps. [`Data`], [`Control`], [`LineControl`], etc. //! integer bitmaps. [`Data`], [`Control`], [`LineControl`], etc.
// For more detail see the PL011 Technical Reference Manual DDI0183:
// https://developer.arm.com/documentation/ddi0183/latest/
use bilge::prelude::*; use bilge::prelude::*;
use qemu_api::impl_vmstate_bitsized; use qemu_api::impl_vmstate_bitsized;
/// Offset of each register from the base memory address of the device. /// Offset of each register from the base memory address of the device.
///
/// # Source
/// ARM DDI 0183G, Table 3-1 p.3-3
#[doc(alias = "offset")] #[doc(alias = "offset")]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[repr(u64)] #[repr(u64)]
@ -87,48 +87,11 @@ pub struct Errors {
_reserved_unpredictable: u4, _reserved_unpredictable: u4,
} }
// TODO: FIFO Mode has different semantics
/// Data Register, `UARTDR` /// Data Register, `UARTDR`
/// ///
/// The `UARTDR` register is the data register. /// The `UARTDR` register is the data register; write for TX and
/// /// read for RX. It is a 12-bit register, where bits 7..0 are the
/// For words to be transmitted: /// character and bits 11..8 are error bits.
///
/// - if the FIFOs are enabled, data written to this location is pushed onto the
/// transmit
/// FIFO
/// - if the FIFOs are not enabled, data is stored in the transmitter holding
/// register (the
/// bottom word of the transmit FIFO).
///
/// The write operation initiates transmission from the UART. The data is
/// prefixed with a start bit, appended with the appropriate parity bit
/// (if parity is enabled), and a stop bit. The resultant word is then
/// transmitted.
///
/// For received words:
///
/// - if the FIFOs are enabled, the data byte and the 4-bit status (break,
/// frame, parity,
/// and overrun) is pushed onto the 12-bit wide receive FIFO
/// - if the FIFOs are not enabled, the data byte and status are stored in the
/// receiving
/// holding register (the bottom word of the receive FIFO).
///
/// The received data byte is read by performing reads from the `UARTDR`
/// register along with the corresponding status information. The status
/// information can also be read by a read of the `UARTRSR/UARTECR`
/// register.
///
/// # Note
///
/// You must disable the UART before any of the control registers are
/// reprogrammed. When the UART is disabled in the middle of
/// transmission or reception, it completes the current character before
/// stopping.
///
/// # Source
/// ARM DDI 0183G 3.3.1 Data Register, UARTDR
#[bitsize(32)] #[bitsize(32)]
#[derive(Clone, Copy, Default, DebugBits, FromBits)] #[derive(Clone, Copy, Default, DebugBits, FromBits)]
#[doc(alias = "UARTDR")] #[doc(alias = "UARTDR")]
@ -144,30 +107,17 @@ impl Data {
pub const BREAK: Self = Self { value: 1 << 10 }; pub const BREAK: Self = Self { value: 1 << 10 };
} }
// TODO: FIFO Mode has different semantics
/// Receive Status Register / Error Clear Register, `UARTRSR/UARTECR` /// Receive Status Register / Error Clear Register, `UARTRSR/UARTECR`
/// ///
/// The UARTRSR/UARTECR register is the receive status register/error clear /// This register provides a different way to read the four receive
/// register. Receive status can also be read from the `UARTRSR` /// status error bits that can be found in bits 11..8 of the UARTDR
/// register. If the status is read from this register, then the status /// on a read. It gets updated when the guest reads UARTDR, and the
/// information for break, framing and parity corresponds to the /// status bits correspond to that character that was just read.
/// data character read from the [Data register](Data), `UARTDR` prior to
/// reading the UARTRSR register. The status information for overrun is
/// set immediately when an overrun condition occurs.
/// ///
/// /// The TRM confusingly describes this offset as UARTRSR for reads
/// # Note /// and UARTECR for writes, but really it's a single error status
/// The received data character must be read first from the [Data /// register where writing anything to the register clears the error
/// Register](Data), `UARTDR` before reading the error status associated /// bits.
/// with that data character from the `UARTRSR` register. This read
/// sequence cannot be reversed, because the `UARTRSR` register is
/// updated only when a read occurs from the `UARTDR` register. However,
/// the status information can also be obtained by reading the `UARTDR`
/// register
///
/// # Source
/// ARM DDI 0183G 3.3.2 Receive Status Register/Error Clear Register,
/// UARTRSR/UARTECR
#[bitsize(32)] #[bitsize(32)]
#[derive(Clone, Copy, DebugBits, FromBits)] #[derive(Clone, Copy, DebugBits, FromBits)]
pub struct ReceiveStatusErrorClear { pub struct ReceiveStatusErrorClear {
@ -196,54 +146,29 @@ impl Default for ReceiveStatusErrorClear {
#[bitsize(32)] #[bitsize(32)]
#[derive(Clone, Copy, DebugBits, FromBits)] #[derive(Clone, Copy, DebugBits, FromBits)]
/// Flag Register, `UARTFR` /// Flag Register, `UARTFR`
///
/// This has the usual inbound RS232 modem-control signals, plus flags
/// for RX and TX FIFO fill levels and a BUSY flag.
#[doc(alias = "UARTFR")] #[doc(alias = "UARTFR")]
pub struct Flags { pub struct Flags {
/// CTS Clear to send. This bit is the complement of the UART clear to /// CTS: Clear to send
/// send, `nUARTCTS`, modem status input. That is, the bit is 1
/// when `nUARTCTS` is LOW.
pub clear_to_send: bool, pub clear_to_send: bool,
/// DSR Data set ready. This bit is the complement of the UART data set /// DSR: Data set ready
/// ready, `nUARTDSR`, modem status input. That is, the bit is 1 when
/// `nUARTDSR` is LOW.
pub data_set_ready: bool, pub data_set_ready: bool,
/// DCD Data carrier detect. This bit is the complement of the UART data /// DCD: Data carrier detect
/// carrier detect, `nUARTDCD`, modem status input. That is, the bit is
/// 1 when `nUARTDCD` is LOW.
pub data_carrier_detect: bool, pub data_carrier_detect: bool,
/// BUSY UART busy. If this bit is set to 1, the UART is busy /// BUSY: UART busy. In real hardware, set while the UART is
/// transmitting data. This bit remains set until the complete /// busy transmitting data. QEMU's implementation never sets BUSY.
/// byte, including all the stop bits, has been sent from the
/// shift register. This bit is set as soon as the transmit FIFO
/// becomes non-empty, regardless of whether the UART is enabled
/// or not.
pub busy: bool, pub busy: bool,
/// RXFE Receive FIFO empty. The meaning of this bit depends on the /// RXFE: Receive FIFO empty
/// state of the FEN bit in the UARTLCR_H register. If the FIFO
/// is disabled, this bit is set when the receive holding
/// register is empty. If the FIFO is enabled, the RXFE bit is
/// set when the receive FIFO is empty.
pub receive_fifo_empty: bool, pub receive_fifo_empty: bool,
/// TXFF Transmit FIFO full. The meaning of this bit depends on the /// TXFF: Transmit FIFO full
/// state of the FEN bit in the UARTLCR_H register. If the FIFO
/// is disabled, this bit is set when the transmit holding
/// register is full. If the FIFO is enabled, the TXFF bit is
/// set when the transmit FIFO is full.
pub transmit_fifo_full: bool, pub transmit_fifo_full: bool,
/// RXFF Receive FIFO full. The meaning of this bit depends on the state /// RXFF: Receive FIFO full
/// of the FEN bit in the UARTLCR_H register. If the FIFO is
/// disabled, this bit is set when the receive holding register
/// is full. If the FIFO is enabled, the RXFF bit is set when
/// the receive FIFO is full.
pub receive_fifo_full: bool, pub receive_fifo_full: bool,
/// Transmit FIFO empty. The meaning of this bit depends on the state of /// TXFE: Transmit FIFO empty
/// the FEN bit in the [Line Control register](LineControl),
/// `UARTLCR_H`. If the FIFO is disabled, this bit is set when the
/// transmit holding register is empty. If the FIFO is enabled,
/// the TXFE bit is set when the transmit FIFO is empty. This
/// bit does not indicate if there is data in the transmit shift
/// register.
pub transmit_fifo_empty: bool, pub transmit_fifo_empty: bool,
/// `RI`, is `true` when `nUARTRI` is `LOW`. /// RI: Ring indicator
pub ring_indicator: bool, pub ring_indicator: bool,
_reserved_zero_no_modify: u23, _reserved_zero_no_modify: u23,
} }
@ -270,54 +195,23 @@ impl Default for Flags {
/// Line Control Register, `UARTLCR_H` /// Line Control Register, `UARTLCR_H`
#[doc(alias = "UARTLCR_H")] #[doc(alias = "UARTLCR_H")]
pub struct LineControl { pub struct LineControl {
/// BRK Send break. /// BRK: Send break
///
/// If this bit is set to `1`, a low-level is continually output on the
/// `UARTTXD` output, after completing transmission of the
/// current character. For the proper execution of the break command,
/// the software must set this bit for at least two complete
/// frames. For normal use, this bit must be cleared to `0`.
pub send_break: bool, pub send_break: bool,
/// 1 PEN Parity enable: /// PEN: Parity enable
///
/// - 0 = parity is disabled and no parity bit added to the data frame
/// - 1 = parity checking and generation is enabled.
///
/// See Table 3-11 on page 3-14 for the parity truth table.
pub parity_enabled: bool, pub parity_enabled: bool,
/// EPS Even parity select. Controls the type of parity the UART uses /// EPS: Even parity select
/// during transmission and reception:
/// - 0 = odd parity. The UART generates or checks for an odd number of 1s
/// in the data and parity bits.
/// - 1 = even parity. The UART generates or checks for an even number of 1s
/// in the data and parity bits.
/// This bit has no effect when the `PEN` bit disables parity checking
/// and generation. See Table 3-11 on page 3-14 for the parity
/// truth table.
pub parity: Parity, pub parity: Parity,
/// 3 STP2 Two stop bits select. If this bit is set to 1, two stop bits /// STP2: Two stop bits select
/// are transmitted at the end of the frame. The receive
/// logic does not check for two stop bits being received.
pub two_stops_bits: bool, pub two_stops_bits: bool,
/// FEN Enable FIFOs: /// FEN: Enable FIFOs
/// 0 = FIFOs are disabled (character mode) that is, the FIFOs become
/// 1-byte-deep holding registers 1 = transmit and receive FIFO
/// buffers are enabled (FIFO mode).
pub fifos_enabled: Mode, pub fifos_enabled: Mode,
/// WLEN Word length. These bits indicate the number of data bits /// WLEN: Word length in bits
/// transmitted or received in a frame as follows: b11 = 8 bits /// b11 = 8 bits
/// b10 = 7 bits /// b10 = 7 bits
/// b01 = 6 bits /// b01 = 6 bits
/// b00 = 5 bits. /// b00 = 5 bits.
pub word_length: WordLength, pub word_length: WordLength,
/// 7 SPS Stick parity select. /// SPS Stick parity select
/// 0 = stick parity is disabled
/// 1 = either:
/// • if the EPS bit is 0 then the parity bit is transmitted and checked
/// as a 1 • if the EPS bit is 1 then the parity bit is
/// transmitted and checked as a 0. This bit has no effect when
/// the PEN bit disables parity checking and generation. See Table 3-11
/// on page 3-14 for the parity truth table.
pub sticky_parity: bool, pub sticky_parity: bool,
/// 31:8 - Reserved, do not modify, read as zero. /// 31:8 - Reserved, do not modify, read as zero.
_reserved_zero_no_modify: u24, _reserved_zero_no_modify: u24,
@ -342,11 +236,7 @@ impl Default for LineControl {
/// `EPS` "Even parity select", field of [Line Control /// `EPS` "Even parity select", field of [Line Control
/// register](LineControl). /// register](LineControl).
pub enum Parity { pub enum Parity {
/// - 0 = odd parity. The UART generates or checks for an odd number of 1s
/// in the data and parity bits.
Odd = 0, Odd = 0,
/// - 1 = even parity. The UART generates or checks for an even number of 1s
/// in the data and parity bits.
Even = 1, Even = 1,
} }
@ -381,88 +271,39 @@ pub enum WordLength {
/// Control Register, `UARTCR` /// Control Register, `UARTCR`
/// ///
/// The `UARTCR` register is the control register. All the bits are cleared /// The `UARTCR` register is the control register. It contains various
/// to `0` on reset except for bits `9` and `8` that are set to `1`. /// enable bits, and the bits to write to set the usual outbound RS232
/// /// modem control signals. All bits reset to 0 except TXE and RXE.
/// # Source
/// ARM DDI 0183G, 3.3.8 Control Register, `UARTCR`, Table 3-12
#[bitsize(32)] #[bitsize(32)]
#[doc(alias = "UARTCR")] #[doc(alias = "UARTCR")]
#[derive(Clone, Copy, DebugBits, FromBits)] #[derive(Clone, Copy, DebugBits, FromBits)]
pub struct Control { pub struct Control {
/// `UARTEN` UART enable: 0 = UART is disabled. If the UART is disabled /// `UARTEN` UART enable: 0 = UART is disabled.
/// in the middle of transmission or reception, it completes the current
/// character before stopping. 1 = the UART is enabled. Data
/// transmission and reception occurs for either UART signals or SIR
/// signals depending on the setting of the SIREN bit.
pub enable_uart: bool, pub enable_uart: bool,
/// `SIREN` `SIR` enable: 0 = IrDA SIR ENDEC is disabled. `nSIROUT` /// `SIREN` `SIR` enable: disable or enable IrDA SIR ENDEC.
/// remains LOW (no light pulse generated), and signal transitions on /// QEMU does not model this.
/// SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is
/// transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH,
/// in the marking state. Signal transitions on UARTRXD or modem status
/// inputs have no effect. This bit has no effect if the UARTEN bit
/// disables the UART.
pub enable_sir: bool, pub enable_sir: bool,
/// `SIRLP` SIR low-power IrDA mode. This bit selects the IrDA encoding /// `SIRLP` SIR low-power IrDA mode. QEMU does not model this.
/// mode. If this bit is cleared to 0, low-level bits are transmitted as
/// an active high pulse with a width of 3/ 16th of the bit period. If
/// this bit is set to 1, low-level bits are transmitted with a pulse
/// width that is 3 times the period of the IrLPBaud16 input signal,
/// regardless of the selected bit rate. Setting this bit uses less
/// power, but might reduce transmission distances.
pub sir_lowpower_irda_mode: u1, pub sir_lowpower_irda_mode: u1,
/// Reserved, do not modify, read as zero. /// Reserved, do not modify, read as zero.
_reserved_zero_no_modify: u4, _reserved_zero_no_modify: u4,
/// `LBE` Loopback enable. If this bit is set to 1 and the SIREN bit is /// `LBE` Loopback enable: feed UART output back to the input
/// set to 1 and the SIRTEST bit in the Test Control register, UARTTCR
/// on page 4-5 is set to 1, then the nSIROUT path is inverted, and fed
/// through to the SIRIN path. The SIRTEST bit in the test register must
/// be set to 1 to override the normal half-duplex SIR operation. This
/// must be the requirement for accessing the test registers during
/// normal operation, and SIRTEST must be cleared to 0 when loopback
/// testing is finished. This feature reduces the amount of external
/// coupling required during system test. If this bit is set to 1, and
/// the SIRTEST bit is set to 0, the UARTTXD path is fed through to the
/// UARTRXD path. In either SIR mode or UART mode, when this bit is set,
/// the modem outputs are also fed through to the modem inputs. This bit
/// is cleared to 0 on reset, to disable loopback.
pub enable_loopback: bool, pub enable_loopback: bool,
/// `TXE` Transmit enable. If this bit is set to 1, the transmit section /// `TXE` Transmit enable
/// of the UART is enabled. Data transmission occurs for either UART
/// signals, or SIR signals depending on the setting of the SIREN bit.
/// When the UART is disabled in the middle of transmission, it
/// completes the current character before stopping.
pub enable_transmit: bool, pub enable_transmit: bool,
/// `RXE` Receive enable. If this bit is set to 1, the receive section /// `RXE` Receive enable
/// of the UART is enabled. Data reception occurs for either UART
/// signals or SIR signals depending on the setting of the SIREN bit.
/// When the UART is disabled in the middle of reception, it completes
/// the current character before stopping.
pub enable_receive: bool, pub enable_receive: bool,
/// `DTR` Data transmit ready. This bit is the complement of the UART /// `DTR` Data transmit ready
/// data transmit ready, `nUARTDTR`, modem status output. That is, when
/// the bit is programmed to a 1 then `nUARTDTR` is LOW.
pub data_transmit_ready: bool, pub data_transmit_ready: bool,
/// `RTS` Request to send. This bit is the complement of the UART /// `RTS` Request to send
/// request to send, `nUARTRTS`, modem status output. That is, when the
/// bit is programmed to a 1 then `nUARTRTS` is LOW.
pub request_to_send: bool, pub request_to_send: bool,
/// `Out1` This bit is the complement of the UART Out1 (`nUARTOut1`) /// `Out1` UART Out1 signal; can be used as DCD
/// modem status output. That is, when the bit is programmed to a 1 the
/// output is 0. For DTE this can be used as Data Carrier Detect (DCD).
pub out_1: bool, pub out_1: bool,
/// `Out2` This bit is the complement of the UART Out2 (`nUARTOut2`) /// `Out2` UART Out2 signal; can be used as RI
/// modem status output. That is, when the bit is programmed to a 1, the
/// output is 0. For DTE this can be used as Ring Indicator (RI).
pub out_2: bool, pub out_2: bool,
/// `RTSEn` RTS hardware flow control enable. If this bit is set to 1, /// `RTSEn` RTS hardware flow control enable
/// RTS hardware flow control is enabled. Data is only requested when
/// there is space in the receive FIFO for it to be received.
pub rts_hardware_flow_control_enable: bool, pub rts_hardware_flow_control_enable: bool,
/// `CTSEn` CTS hardware flow control enable. If this bit is set to 1, /// `CTSEn` CTS hardware flow control enable
/// CTS hardware flow control is enabled. Data is only transmitted when
/// the `nUARTCTS` signal is asserted.
pub cts_hardware_flow_control_enable: bool, pub cts_hardware_flow_control_enable: bool,
/// 31:16 - Reserved, do not modify, read as zero. /// 31:16 - Reserved, do not modify, read as zero.
_reserved_zero_no_modify2: u16, _reserved_zero_no_modify2: u16,