serial_pl011/
spec.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Naming and fields come from specification for PL011 chip.
5//! <https://developer.arm.com/documentation/ddi0183/g/?lang=en>
6
7use bitfield_struct::bitfield;
8use inspect::Inspect;
9use open_enum::open_enum;
10
11/// PL011 has 32-byte FIFOs.
12pub const FIFO_SIZE: usize = 32;
13
14open_enum! {
15    /// MMIO port assignments
16    pub enum Register: u16 {
17        UARTDR         = 0x000, // Data Register. 12 bit (R), 8 bit (W)
18        UARTRSR        = 0x004, // Receive Status Register (R)
19        UARTECR        = 0x004, // Error Clear Register
20        UARTFR         = 0x018, // Flag Register. Read-only
21        UARTILPR       = 0x020, // IrDA Low-Power Counter Register
22        UARTIBRD       = 0x024, // Integer Baud Rate Register
23        UARTFBRD       = 0x028, // Fractional Baud Rate Register
24        UARTLCR_H      = 0x02C, // Line Control Register
25        UARTCR         = 0x030, // Control Register
26        UARTIFLS       = 0x034, // Interrupt FIFO Level Select Register
27        UARTIMSC       = 0x038, // Interrupt Mask Set/Clear Register
28        UARTRIS        = 0x03C, // Raw Interrupt Status Register
29        UARTMIS        = 0x040, // Masked Interrupt Status Register
30        UARTICR        = 0x044, // Interrupt Clear Register
31        UARTDMACR      = 0x048, // DMA Control Register
32
33        // Offsets 0x04C - 0xFDC are reserved
34
35        UARTPERIPHID0  = 0xFE0, // Peripheral Identification Register 0
36        UARTPERIPHID1  = 0xFE4, // Peripheral Identification Register 1
37        UARTPERIPHID2  = 0xFE8, // Peripheral Identification Register 2
38        UARTPERIPHID3  = 0xFEC, // Peripheral Identification Register 3
39        UARTPCELLID0   = 0xFF0, // PrimeCell Identification Register 0
40        UARTPCELLID1   = 0xFF4, // PrimeCell Identification Register 1
41        UARTPCELLID2   = 0xFF8, // PrimeCell Identification Register 2
42        UARTPCELLID3   = 0xFFC, // PrimeCell Identification Register 3
43    }
44}
45
46pub const REGISTERS_SIZE: u64 = 0x1000;
47
48open_enum! {
49    pub enum FifoLevelSelect: u8 {
50        BYTES_4 = 0,
51        BYTES_8 = 1,
52        BYTES_16 = 2,
53        BYTES_24 = 3,
54        BYTES_28 = 4,
55    }
56}
57
58#[derive(Inspect)]
59#[bitfield(u16)]
60pub struct FlagRegister {
61    pub cts: bool,  // UARTFR_CTS   = 0x0001; Clear to send
62    pub dsr: bool,  // UARTFR_DSR   = 0x0002; Data set ready
63    pub dcd: bool,  // UARTFR_DCD   = 0x0004; Data carrier detect
64    pub busy: bool, // UARTFR_BUSY  = 0x0008; UART busy
65    pub rxfe: bool, // UARTFR_RXFE  = 0x0010; Receive FIFO empty
66    pub txff: bool, // UARTFR_TXFF  = 0x0020; Transmit FIFO full
67    pub rxff: bool, // UARTFR_RXFF  = 0x0040; Receive FIFO full
68    pub txfe: bool, // UARTFR_TXFE  = 0x0080; Transmit FIFO empty
69    pub ri: bool,   // UARTFR_RI    = 0x0100; Ring indicator
70    #[bits(7)]
71    reserved: u8,
72}
73
74#[derive(Inspect)]
75#[bitfield(u8)]
76pub struct LineControlRegister {
77    #[bits(4)]
78    unused: u8,
79    pub enable_fifos: bool, // UARTLCR_H_FIFO_ENABLE_MASK = 0x10;
80    #[bits(3)]
81    unused2: u8,
82}
83
84#[derive(Inspect)]
85#[bitfield(u16)]
86pub struct ControlRegister {
87    pub enabled: bool, // UARTCR_UARTEN = 0x0001; UART enable
88    #[bits(2)]
89    unused: u8,
90    #[bits(4)]
91    reserved: u8,
92    pub loopback: bool, // UARTCR_LBE   = 0x0080; Loopback enable
93    pub txe: bool,      // UARTCR_TXE   = 0x0100; Transmit enable
94    pub rxe: bool,      // UARTCR_RXE   = 0x0200; Receive enable
95    pub dtr: bool,      // UARTCR_DTR   = 0x0400; Data transmit ready
96    pub rts: bool,      // UARTCR_RTS   = 0x0800; Request to send
97    #[bits(4)]
98    unused2: u8,
99}
100
101impl ControlRegister {
102    pub fn clear_reserved(&mut self) -> ControlRegister {
103        self.with_reserved(0)
104    }
105}
106
107#[derive(Inspect)]
108#[bitfield(u16)]
109pub struct InterruptRegister {
110    pub ri: bool,  // UARTRI    = 0x0001; RI modem interrupt status
111    pub cts: bool, // UARTCTS   = 0x0002; CTS modem interrupt status
112    pub dcd: bool, // UARTDCD   = 0x0004; DCD modem interrupt status
113    pub dsr: bool, // UARTDSR   = 0x0008; DSR modem interrupt status
114    pub rx: bool,  // RXRIS     = 0x0010; Receive interrupt status
115    pub tx: bool,  // TXRIS     = 0x0020; Transmit interrupt status
116    pub rt: bool,  // RTRIS     = 0x0040; Receive timeout interrupt status
117    pub fe: bool,  // FERIS     = 0x0080; Framing error interrupt status
118    pub pe: bool,  // PERIS     = 0x0100; Parity error interrupt status
119    pub be: bool,  // BERIS     = 0x0200; Break error interrupt status
120    pub oe: bool,  // OERIS     = 0x0400; Overrun error interrupt status
121    #[bits(5)]
122    reserved: u8,
123}
124
125impl InterruptRegister {
126    pub fn clear_reserved(&mut self) -> InterruptRegister {
127        self.with_reserved(0)
128    }
129}
130
131#[derive(Inspect)]
132#[bitfield(u16)]
133pub struct InterruptFifoLevelSelectRegister {
134    #[bits(3)]
135    pub txiflsel: u8,
136    #[bits(3)]
137    pub rxiflsel: u8,
138    #[bits(10)]
139    reserved: u16,
140}
141
142impl InterruptFifoLevelSelectRegister {
143    pub fn clear_reserved(&mut self) -> InterruptFifoLevelSelectRegister {
144        self.with_reserved(0)
145    }
146}
147
148#[derive(Inspect)]
149#[bitfield(u8)]
150pub struct FractionalBaudRateRegister {
151    #[bits(6)]
152    pub baud: u8,
153    #[bits(2)]
154    reserved: u8,
155}
156
157impl FractionalBaudRateRegister {
158    pub fn clear_reserved(&mut self) -> FractionalBaudRateRegister {
159        self.with_reserved(0)
160    }
161}
162
163#[derive(Inspect)]
164#[bitfield(u16)]
165pub struct DmaControlRegister {
166    #[bits(3)]
167    pub valid: u8,
168    #[bits(13)]
169    reserved: u16,
170}
171
172impl DmaControlRegister {
173    pub fn clear_reserved(&mut self) -> DmaControlRegister {
174        self.with_reserved(0)
175    }
176}
177
178// Spec-defined defaults:
179// It's used to read a specific register offset (UARTPERIPHID0..3) that identify the device.
180pub const UARTPERIPH_ID: [u16; 4] = [0x11, 0x10, 0x34, 0x00];
181// It's used to read a specific register offset (UARTPCELLID0..3) that identify the device.
182pub const UARTPCELL_ID: [u16; 4] = [0x0D, 0xF0, 0x05, 0xB1];