1use core::ptr::NonNull;
2
3use crate::Register;
4use rdif_serial::{RegisterTransferError as TransferError, Serial, SerialRaw};
5use tock_registers::{interfaces::*, register_bitfields, register_structs, registers::*};
6
7use crate::{Config, ConfigError, DataBits, InterruptMask, LineStatus, Parity, StopBits};
8
9register_bitfields! [
10 u32,
11
12 UARTDR [
14 DATA OFFSET(0) NUMBITS(8) [],
15 FE OFFSET(8) NUMBITS(1) [],
16 PE OFFSET(9) NUMBITS(1) [],
17 BE OFFSET(10) NUMBITS(1) [],
18 OE OFFSET(11) NUMBITS(1) []
19 ],
20
21 UARTRSR_ECR [
23 FE OFFSET(0) NUMBITS(1) [],
24 PE OFFSET(1) NUMBITS(1) [],
25 BE OFFSET(2) NUMBITS(1) [],
26 OE OFFSET(3) NUMBITS(1) []
27 ],
28
29 UARTFR [
31 CTS OFFSET(0) NUMBITS(1) [],
32 DSR OFFSET(1) NUMBITS(1) [],
33 DCD OFFSET(2) NUMBITS(1) [],
34 BUSY OFFSET(3) NUMBITS(1) [],
35 RXFE OFFSET(4) NUMBITS(1) [],
36 TXFF OFFSET(5) NUMBITS(1) [],
37 RXFF OFFSET(6) NUMBITS(1) [],
38 TXFE OFFSET(7) NUMBITS(1) [],
39 RI OFFSET(8) NUMBITS(1) []
40 ],
41
42 UARTIBRD [
44 BAUD_DIVINT OFFSET(0) NUMBITS(16) []
45 ],
46
47 UARTFBRD [
49 BAUD_DIVFRAC OFFSET(0) NUMBITS(6) []
50 ],
51
52 UARTLCR_H [
54 BRK OFFSET(0) NUMBITS(1) [],
55 PEN OFFSET(1) NUMBITS(1) [],
56 EPS OFFSET(2) NUMBITS(1) [],
57 STP2 OFFSET(3) NUMBITS(1) [],
58 FEN OFFSET(4) NUMBITS(1) [],
59 WLEN OFFSET(5) NUMBITS(2) [
60 FiveBit = 0,
61 SixBit = 1,
62 SevenBit = 2,
63 EightBit = 3
64 ],
65 SPS OFFSET(7) NUMBITS(1) []
66 ],
67
68 UARTCR [
70 UARTEN OFFSET(0) NUMBITS(1) [],
71 SIREN OFFSET(1) NUMBITS(1) [],
72 SIRLP OFFSET(2) NUMBITS(1) [],
73 LBE OFFSET(7) NUMBITS(1) [],
74 TXE OFFSET(8) NUMBITS(1) [],
75 RXE OFFSET(9) NUMBITS(1) [],
76 DTR OFFSET(10) NUMBITS(1) [],
77 RTS OFFSET(11) NUMBITS(1) [],
78 OUT1 OFFSET(12) NUMBITS(1) [],
79 OUT2 OFFSET(13) NUMBITS(1) [],
80 RTSEN OFFSET(14) NUMBITS(1) [],
81 CTSEN OFFSET(15) NUMBITS(1) []
82 ],
83
84 UARTIFLS [
86 TXIFLSEL OFFSET(0) NUMBITS(3) [],
87 RXIFLSEL OFFSET(3) NUMBITS(3) []
88 ],
89
90 UARTIS [
92 RIM OFFSET(0) NUMBITS(1) [],
93 CTSM OFFSET(1) NUMBITS(1) [],
94 DCDM OFFSET(2) NUMBITS(1) [],
95 DSRM OFFSET(3) NUMBITS(1) [],
96 RX OFFSET(4) NUMBITS(1) [],
97 TX OFFSET(5) NUMBITS(1) [],
98 RT OFFSET(6) NUMBITS(1) [],
99 FE OFFSET(7) NUMBITS(1) [],
100 PE OFFSET(8) NUMBITS(1) [],
101 BE OFFSET(9) NUMBITS(1) [],
102 OE OFFSET(10) NUMBITS(1) []
103 ],
104
105 UARTDMACR [
107 RXDMAE OFFSET(0) NUMBITS(1) [],
108 TXDMAE OFFSET(1) NUMBITS(1) [],
109 DMAONERR OFFSET(2) NUMBITS(1) []
110 ]
111];
112
113register_structs! {
114 pub Pl011Registers {
115 (0x000 => uartdr: ReadWrite<u32, UARTDR::Register>), (0x004 => uartrsr_ecr: ReadWrite<u32, UARTRSR_ECR::Register>), (0x008 => _reserved1), (0x018 => uartfr: ReadOnly<u32, UARTFR::Register>), (0x01c => _reserved2), (0x020 => uartilpr: ReadWrite<u32>), (0x024 => uartibrd: ReadWrite<u32, UARTIBRD::Register>), (0x028 => uartfbrd: ReadWrite<u32, UARTFBRD::Register>), (0x02c => uartlcr_h: ReadWrite<u32, UARTLCR_H::Register>), (0x030 => uartcr: ReadWrite<u32, UARTCR::Register>), (0x034 => uartifls: ReadWrite<u32, UARTIFLS::Register>), (0x038 => uartimsc: ReadWrite<u32, UARTIS::Register>), (0x03c => uartris: ReadOnly<u32, UARTIS::Register>), (0x040 => uartmis: ReadOnly<u32, UARTIS::Register>), (0x044 => uarticr: WriteOnly<u32, UARTIS::Register>), (0x048 => uartdmacr: ReadWrite<u32, UARTDMACR::Register>), (0x04c => _reserved3), (0x1000 => @END),
133 }
134}
135
136unsafe impl Sync for Pl011Registers {}
138
139#[derive(Clone)]
141pub struct Pl011 {
142 base: NonNull<Pl011Registers>,
143 clock_freq: u32,
144}
145
146unsafe impl Send for Pl011 {}
147unsafe impl Sync for Pl011 {}
148
149impl Pl011 {
150 pub fn new_raw_no_clock(base: NonNull<u8>) -> SerialRaw<Self> {
155 let clock_freq = Self::detect_clock_frequency(base.as_ptr() as usize);
157 Self::new_raw(base, clock_freq)
158 }
159
160 pub fn new_raw(base: NonNull<u8>, clock_freq: u32) -> SerialRaw<Self> {
166 SerialRaw::new(Self {
167 base: base.cast(),
168 clock_freq,
169 })
170 }
171
172 pub fn new(base: NonNull<u8>, clock_freq: u32) -> Serial<Self> {
173 Serial::new(Self {
174 base: base.cast(),
175 clock_freq,
176 })
177 }
178
179 fn registers(&self) -> &Pl011Registers {
180 unsafe { self.base.as_ref() }
181 }
182
183 fn detect_clock_frequency(base: usize) -> u32 {
185 let registers = unsafe { &*(base as *const Pl011Registers) };
187
188 use tock_registers::interfaces::Readable;
189 let ibrd = registers.uartibrd.read(UARTIBRD::BAUD_DIVINT);
190
191 if ibrd > 0 && ibrd <= 0xFFFF {
193 let estimated_clock = 16 * ibrd * 115200;
196
197 if (1_000_000..=100_000_000).contains(&estimated_clock) {
199 return estimated_clock;
200 }
201 }
202
203 24_000_000
205 }
206
207 fn set_baudrate_internal(&self, baudrate: u32) -> Result<(), ConfigError> {
209 let bauddiv = self.clock_freq / (16 * baudrate);
215 let remainder = self.clock_freq % (16 * baudrate);
216 let fbrd = (remainder * 64 + (16 * baudrate / 2)) / (16 * baudrate);
217
218 if bauddiv == 0 || bauddiv > 0xFFFF {
219 return Err(ConfigError::InvalidBaudrate);
220 }
221
222 self.registers()
223 .uartibrd
224 .write(UARTIBRD::BAUD_DIVINT.val(bauddiv));
225 self.registers()
226 .uartfbrd
227 .write(UARTFBRD::BAUD_DIVFRAC.val(fbrd));
228
229 Ok(())
230 }
231
232 fn set_data_bits_internal(&self, bits: DataBits) -> Result<(), ConfigError> {
233 let wlen = match bits {
234 DataBits::Five => UARTLCR_H::WLEN::FiveBit,
235 DataBits::Six => UARTLCR_H::WLEN::SixBit,
236 DataBits::Seven => UARTLCR_H::WLEN::SevenBit,
237 DataBits::Eight => UARTLCR_H::WLEN::EightBit,
238 };
239
240 self.registers().uartlcr_h.modify(wlen);
241 Ok(())
242 }
243
244 fn set_stop_bits_internal(&self, bits: StopBits) -> Result<(), ConfigError> {
245 match bits {
246 StopBits::One => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::CLEAR),
247 StopBits::Two => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::SET),
248 }
249
250 Ok(())
251 }
252
253 fn set_parity_internal(&self, parity: Parity) -> Result<(), ConfigError> {
254 match parity {
255 Parity::None => {
256 self.registers().uartlcr_h.modify(UARTLCR_H::PEN::CLEAR);
258 }
259 Parity::Odd => {
260 self.registers()
262 .uartlcr_h
263 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::CLEAR);
264 }
265 Parity::Even => {
266 self.registers()
268 .uartlcr_h
269 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::CLEAR);
270 }
271 Parity::Mark => {
272 self.registers()
274 .uartlcr_h
275 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::SET);
276 }
277 Parity::Space => {
278 self.registers()
280 .uartlcr_h
281 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::SET);
282 }
283 }
284
285 Ok(())
286 }
287
288 fn init(&self) {
290 self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
292
293 while self.registers().uartfr.is_set(UARTFR::BUSY) {
295 core::hint::spin_loop();
296 }
297
298 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
300
301 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
303
304 #[cfg(debug_assertions)]
306 {
307 let ifls = self.registers().uartifls.get();
308 let lcr_h = self.registers().uartlcr_h.get();
309 log::debug!("UART IFLS: 0x{:02x}, LCR_H: 0x{:02x}", ifls, lcr_h);
310 log::debug!(" FIFO enabled: {}", lcr_h & (1 << 4) != 0);
311 log::debug!(" RX trigger level: 1/8");
312 log::debug!(" TX trigger level: 1/2");
313 }
314 self.registers().uartimsc.set(0); self.registers()
317 .uartcr
318 .modify(UARTCR::UARTEN::SET + UARTCR::TXE::SET + UARTCR::RXE::SET);
319 }
320}
321
322impl Register for Pl011 {
323 fn write_byte(&mut self, byte: u8) {
324 self.registers().uartdr.write(UARTDR::DATA.val(byte as u32));
325 }
326
327 fn read_byte(&self) -> Result<u8, TransferError> {
328 let dr = self.registers().uartdr.extract();
329 let data = dr.read(UARTDR::DATA) as u8;
330
331 if dr.is_set(UARTDR::FE) {
332 return Err(TransferError::Framing);
333 }
334
335 if dr.is_set(UARTDR::PE) {
336 return Err(TransferError::Parity);
337 }
338
339 if dr.is_set(UARTDR::OE) {
340 return Err(TransferError::Overrun(data));
341 }
342
343 if dr.is_set(UARTDR::BE) {
344 return Err(TransferError::Break);
345 }
346
347 Ok(data)
348 }
349
350 fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
351 use tock_registers::interfaces::Readable;
352
353 let original_enable = self.registers().uartcr.is_set(UARTCR::UARTEN); self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR); while self.registers().uartfr.is_set(UARTFR::BUSY) {
360 core::hint::spin_loop();
361 }
362
363 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
365
366 if let Some(baudrate) = config.baudrate {
368 self.set_baudrate_internal(baudrate)?;
369 }
370 if let Some(data_bits) = config.data_bits {
371 self.set_data_bits_internal(data_bits)?;
372 }
373 if let Some(stop_bits) = config.stop_bits {
374 self.set_stop_bits_internal(stop_bits)?;
375 }
376 if let Some(parity) = config.parity {
377 self.set_parity_internal(parity)?;
378 }
379
380 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
382
383 if original_enable {
385 self.registers().uartcr.modify(UARTCR::UARTEN::SET); }
387
388 Ok(())
389 }
390
391 fn baudrate(&self) -> u32 {
392 let ibrd = self.registers().uartibrd.read(UARTIBRD::BAUD_DIVINT);
393 let fbrd = self.registers().uartfbrd.read(UARTFBRD::BAUD_DIVFRAC);
394
395 let divisor = ibrd * 64 + fbrd;
398 if divisor == 0 {
399 return 0;
400 }
401
402 self.clock_freq * 64 / (16 * divisor)
403 }
404
405 fn data_bits(&self) -> DataBits {
406 let wlen = self.registers().uartlcr_h.read(UARTLCR_H::WLEN);
407
408 match wlen {
409 0 => DataBits::Five,
410 1 => DataBits::Six,
411 2 => DataBits::Seven,
412 3 => DataBits::Eight,
413 _ => DataBits::Eight, }
415 }
416
417 fn stop_bits(&self) -> StopBits {
418 if self.registers().uartlcr_h.is_set(UARTLCR_H::STP2) {
419 StopBits::Two
420 } else {
421 StopBits::One
422 }
423 }
424
425 fn parity(&self) -> Parity {
426 if !self.registers().uartlcr_h.is_set(UARTLCR_H::PEN) {
427 Parity::None
428 } else if self.registers().uartlcr_h.is_set(UARTLCR_H::SPS) {
429 if self.registers().uartlcr_h.is_set(UARTLCR_H::EPS) {
431 Parity::Space
432 } else {
433 Parity::Mark
434 }
435 } else {
436 if self.registers().uartlcr_h.is_set(UARTLCR_H::EPS) {
438 Parity::Even
439 } else {
440 Parity::Odd
441 }
442 }
443 }
444
445 fn open(&mut self) {
446 self.init()
447 }
448
449 fn close(&mut self) {
450 self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
452 }
453
454 fn clean_interrupt_status(&mut self) -> InterruptMask {
455 let mis = self.registers().uartmis.extract();
456 let mut mask = InterruptMask::empty();
457
458 if mis.is_set(UARTIS::RX) {
459 mask |= InterruptMask::RX_AVAILABLE;
460 }
461 if mis.is_set(UARTIS::TX) {
462 mask |= InterruptMask::TX_EMPTY;
463 }
464
465 self.registers().uarticr.set(mis.get());
466
467 mask
468 }
469
470 fn line_status(&self) -> LineStatus {
471 use tock_registers::interfaces::Readable;
472 let mut status = LineStatus::empty();
473
474 let fr = self.registers().uartfr.extract();
475
476 if !fr.is_set(UARTFR::RXFE) {
477 status |= LineStatus::DATA_READY;
478 }
479
480 if !fr.is_set(UARTFR::TXFF) {
481 status |= LineStatus::TX_HOLDING_EMPTY;
482 }
483
484 status
485 }
486
487 fn read_reg(&self, offset: usize) -> u32 {
488 let addr = unsafe { self.base.cast::<u8>().add(offset) };
489 unsafe { addr.cast().read_volatile() }
490 }
491
492 fn write_reg(&mut self, offset: usize, value: u32) {
493 let addr = unsafe { self.base.cast::<u8>().add(offset) };
494 unsafe { addr.cast().write_volatile(value) };
495 }
496
497 fn get_base(&self) -> usize {
498 self.base.as_ptr() as usize
499 }
500
501 fn set_base(&mut self, base: NonNull<u8>) {
502 self.base = base.cast();
503 }
504
505 fn clock_freq(&self) -> u32 {
506 self.clock_freq
507 }
508
509 fn enable_loopback(&mut self) {
510 self.registers().uartcr.modify(UARTCR::LBE::SET);
511 }
512
513 fn disable_loopback(&mut self) {
514 self.registers().uartcr.modify(UARTCR::LBE::CLEAR);
515 }
516
517 fn is_loopback_enabled(&self) -> bool {
518 self.registers().uartcr.is_set(UARTCR::LBE)
519 }
520
521 fn set_irq_mask(&mut self, mask: InterruptMask) {
522 let mut imsc = 0;
523 if mask.contains(InterruptMask::RX_AVAILABLE) {
524 imsc += UARTIS::RX::SET.value;
525 }
526 if mask.contains(InterruptMask::TX_EMPTY) {
527 imsc += UARTIS::TX::SET.value;
528 }
529
530 self.registers().uartimsc.set(imsc);
531 }
532
533 fn get_irq_mask(&self) -> InterruptMask {
534 let imsc = self.registers().uartimsc.extract();
535 let mut mask = InterruptMask::empty();
536
537 if imsc.is_set(UARTIS::RX) {
538 mask |= InterruptMask::RX_AVAILABLE;
539 }
540 if imsc.is_set(UARTIS::TX) {
541 mask |= InterruptMask::TX_EMPTY;
542 }
543
544 mask
545 }
546}
547
548impl Pl011 {
550 pub fn enable_fifo(&self, enable: bool) {
552 if enable {
553 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
554 } else {
555 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
556 }
557 }
558
559 pub fn set_fifo_trigger_level(&self, rx_level: u8, tx_level: u8) {
561 let rx_iflsel = match rx_level {
569 0..=2 => 0b000, 3..=4 => 0b001, 5..=8 => 0b010, 9..=12 => 0b011, _ => 0b100, };
575
576 let tx_iflsel = match tx_level {
577 0..=2 => 0b000, 3..=4 => 0b001, 5..=8 => 0b010, 9..=12 => 0b011, _ => 0b100, };
583
584 self.registers()
585 .uartifls
586 .write(UARTIFLS::RXIFLSEL.val(rx_iflsel) + UARTIFLS::TXIFLSEL.val(tx_iflsel));
587 }
588}
589
590