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];