1use core::ptr::NonNull;
2
3use crate::Register;
4use rdif_serial::{Serial, TransferError};
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_no_clock(base: NonNull<u8>) -> Serial<Self> {
155 let clock_freq = Self::detect_clock_frequency(base.as_ptr() as usize);
157 Self::new(base, clock_freq)
158 }
159
160 pub fn new(base: NonNull<u8>, clock_freq: u32) -> Serial<Self> {
161 Serial::new(Self {
162 base: base.cast(),
163 clock_freq,
164 })
165 }
166
167 fn registers(&self) -> &Pl011Registers {
168 unsafe { self.base.as_ref() }
169 }
170
171 fn detect_clock_frequency(base: usize) -> u32 {
173 let registers = unsafe { &*(base as *const Pl011Registers) };
175
176 use tock_registers::interfaces::Readable;
177 let ibrd = registers.uartibrd.read(UARTIBRD::BAUD_DIVINT);
178
179 if ibrd > 0 && ibrd <= 0xFFFF {
181 let estimated_clock = 16 * ibrd * 115200;
184
185 if (1_000_000..=100_000_000).contains(&estimated_clock) {
187 return estimated_clock;
188 }
189 }
190
191 24_000_000
193 }
194
195 fn set_baudrate_internal(&self, baudrate: u32) -> Result<(), ConfigError> {
197 let bauddiv = self.clock_freq / (16 * baudrate);
203 let remainder = self.clock_freq % (16 * baudrate);
204 let fbrd = (remainder * 64 + (16 * baudrate / 2)) / (16 * baudrate);
205
206 if bauddiv == 0 || bauddiv > 0xFFFF {
207 return Err(ConfigError::InvalidBaudrate);
208 }
209
210 self.registers()
211 .uartibrd
212 .write(UARTIBRD::BAUD_DIVINT.val(bauddiv));
213 self.registers()
214 .uartfbrd
215 .write(UARTFBRD::BAUD_DIVFRAC.val(fbrd));
216
217 Ok(())
218 }
219
220 fn set_data_bits_internal(&self, bits: DataBits) -> Result<(), ConfigError> {
221 let wlen = match bits {
222 DataBits::Five => UARTLCR_H::WLEN::FiveBit,
223 DataBits::Six => UARTLCR_H::WLEN::SixBit,
224 DataBits::Seven => UARTLCR_H::WLEN::SevenBit,
225 DataBits::Eight => UARTLCR_H::WLEN::EightBit,
226 };
227
228 self.registers().uartlcr_h.modify(wlen);
229 Ok(())
230 }
231
232 fn set_stop_bits_internal(&self, bits: StopBits) -> Result<(), ConfigError> {
233 match bits {
234 StopBits::One => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::CLEAR),
235 StopBits::Two => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::SET),
236 }
237
238 Ok(())
239 }
240
241 fn set_parity_internal(&self, parity: Parity) -> Result<(), ConfigError> {
242 match parity {
243 Parity::None => {
244 self.registers().uartlcr_h.modify(UARTLCR_H::PEN::CLEAR);
246 }
247 Parity::Odd => {
248 self.registers()
250 .uartlcr_h
251 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::CLEAR);
252 }
253 Parity::Even => {
254 self.registers()
256 .uartlcr_h
257 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::CLEAR);
258 }
259 Parity::Mark => {
260 self.registers()
262 .uartlcr_h
263 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::SET);
264 }
265 Parity::Space => {
266 self.registers()
268 .uartlcr_h
269 .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::SET);
270 }
271 }
272
273 Ok(())
274 }
275
276 fn init(&self) {
278 self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
280
281 while self.registers().uartfr.is_set(UARTFR::BUSY) {
283 core::hint::spin_loop();
284 }
285
286 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
288
289 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
291
292 #[cfg(debug_assertions)]
294 {
295 let ifls = self.registers().uartifls.get();
296 let lcr_h = self.registers().uartlcr_h.get();
297 log::debug!("UART IFLS: 0x{:02x}, LCR_H: 0x{:02x}", ifls, lcr_h);
298 log::debug!(" FIFO enabled: {}", lcr_h & (1 << 4) != 0);
299 log::debug!(" RX trigger level: 1/8");
300 log::debug!(" TX trigger level: 1/2");
301 }
302 self.registers().uartimsc.set(0); self.registers()
305 .uartcr
306 .modify(UARTCR::UARTEN::SET + UARTCR::TXE::SET + UARTCR::RXE::SET);
307 }
308}
309
310impl Register for Pl011 {
311 fn write_byte(&mut self, byte: u8) {
312 self.registers().uartdr.write(UARTDR::DATA.val(byte as u32));
313 }
314
315 fn read_byte(&mut self) -> Result<u8, TransferError> {
316 let dr = self.registers().uartdr.extract();
317 let data = dr.read(UARTDR::DATA) as u8;
318
319 if dr.is_set(UARTDR::FE) {
320 return Err(TransferError::Framing);
321 }
322
323 if dr.is_set(UARTDR::PE) {
324 return Err(TransferError::Parity);
325 }
326
327 if dr.is_set(UARTDR::OE) {
328 return Err(TransferError::Overrun(data));
329 }
330
331 if dr.is_set(UARTDR::BE) {
332 return Err(TransferError::Break);
333 }
334
335 Ok(data)
336 }
337
338 fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
339 use tock_registers::interfaces::Readable;
340
341 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) {
348 core::hint::spin_loop();
349 }
350
351 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
353
354 if let Some(baudrate) = config.baudrate {
356 self.set_baudrate_internal(baudrate)?;
357 }
358 if let Some(data_bits) = config.data_bits {
359 self.set_data_bits_internal(data_bits)?;
360 }
361 if let Some(stop_bits) = config.stop_bits {
362 self.set_stop_bits_internal(stop_bits)?;
363 }
364 if let Some(parity) = config.parity {
365 self.set_parity_internal(parity)?;
366 }
367
368 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
370
371 if original_enable {
373 self.registers().uartcr.modify(UARTCR::UARTEN::SET); }
375
376 Ok(())
377 }
378
379 fn baudrate(&self) -> u32 {
380 let ibrd = self.registers().uartibrd.read(UARTIBRD::BAUD_DIVINT);
381 let fbrd = self.registers().uartfbrd.read(UARTFBRD::BAUD_DIVFRAC);
382
383 let divisor = ibrd * 64 + fbrd;
386 if divisor == 0 {
387 return 0;
388 }
389
390 self.clock_freq * 64 / (16 * divisor)
391 }
392
393 fn data_bits(&self) -> DataBits {
394 let wlen = self.registers().uartlcr_h.read(UARTLCR_H::WLEN);
395
396 match wlen {
397 0 => DataBits::Five,
398 1 => DataBits::Six,
399 2 => DataBits::Seven,
400 3 => DataBits::Eight,
401 _ => DataBits::Eight, }
403 }
404
405 fn stop_bits(&self) -> StopBits {
406 if self.registers().uartlcr_h.is_set(UARTLCR_H::STP2) {
407 StopBits::Two
408 } else {
409 StopBits::One
410 }
411 }
412
413 fn parity(&self) -> Parity {
414 if !self.registers().uartlcr_h.is_set(UARTLCR_H::PEN) {
415 Parity::None
416 } else if self.registers().uartlcr_h.is_set(UARTLCR_H::SPS) {
417 if self.registers().uartlcr_h.is_set(UARTLCR_H::EPS) {
419 Parity::Space
420 } else {
421 Parity::Mark
422 }
423 } else {
424 if self.registers().uartlcr_h.is_set(UARTLCR_H::EPS) {
426 Parity::Even
427 } else {
428 Parity::Odd
429 }
430 }
431 }
432
433 fn open(&mut self) {
434 self.init()
435 }
436
437 fn close(&mut self) {
438 self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
440 }
441
442 fn clean_interrupt_status(&mut self) -> InterruptMask {
443 let mis = self.registers().uartmis.extract();
444 let mut mask = InterruptMask::empty();
445
446 if mis.is_set(UARTIS::RX) {
447 mask |= InterruptMask::RX_AVAILABLE;
448 }
449 if mis.is_set(UARTIS::TX) {
450 mask |= InterruptMask::TX_EMPTY;
451 }
452
453 self.registers().uarticr.set(mis.get());
454
455 mask
456 }
457
458 fn line_status(&mut self) -> LineStatus {
459 let mut status = LineStatus::empty();
460
461 let fr = self.registers().uartfr.extract();
462
463 if !fr.is_set(UARTFR::RXFE) {
464 status |= LineStatus::DATA_READY;
465 }
466
467 if !fr.is_set(UARTFR::TXFF) {
468 status |= LineStatus::TX_HOLDING_EMPTY;
469 }
470
471 status
472 }
473
474 fn read_reg(&self, offset: usize) -> u32 {
475 let addr = unsafe { self.base.cast::<u8>().add(offset) };
476 unsafe { addr.cast().read_volatile() }
477 }
478
479 fn write_reg(&mut self, offset: usize, value: u32) {
480 let addr = unsafe { self.base.cast::<u8>().add(offset) };
481 unsafe { addr.cast().write_volatile(value) };
482 }
483
484 fn get_base(&self) -> usize {
485 self.base.as_ptr() as usize
486 }
487
488 fn set_base(&mut self, base: usize) {
489 self.base = NonNull::new(base as *mut Pl011Registers).unwrap();
490 }
491
492 fn clock_freq(&self) -> u32 {
493 self.clock_freq
494 }
495
496 fn enable_loopback(&mut self) {
497 self.registers().uartcr.modify(UARTCR::LBE::SET);
498 }
499
500 fn disable_loopback(&mut self) {
501 self.registers().uartcr.modify(UARTCR::LBE::CLEAR);
502 }
503
504 fn is_loopback_enabled(&self) -> bool {
505 self.registers().uartcr.is_set(UARTCR::LBE)
506 }
507
508 fn set_irq_mask(&mut self, mask: InterruptMask) {
509 let mut imsc = 0;
510 if mask.contains(InterruptMask::RX_AVAILABLE) {
511 imsc += UARTIS::RX::SET.value;
512 }
513 if mask.contains(InterruptMask::TX_EMPTY) {
514 imsc += UARTIS::TX::SET.value;
515 }
516
517 self.registers().uartimsc.set(imsc);
518 }
519
520 fn get_irq_mask(&self) -> InterruptMask {
521 let imsc = self.registers().uartimsc.extract();
522 let mut mask = InterruptMask::empty();
523
524 if imsc.is_set(UARTIS::RX) {
525 mask |= InterruptMask::RX_AVAILABLE;
526 }
527 if imsc.is_set(UARTIS::TX) {
528 mask |= InterruptMask::TX_EMPTY;
529 }
530
531 mask
532 }
533}
534
535impl Pl011 {
537 pub fn enable_fifo(&self, enable: bool) {
539 if enable {
540 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
541 } else {
542 self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
543 }
544 }
545
546 pub fn set_fifo_trigger_level(&self, rx_level: u8, tx_level: u8) {
548 let rx_iflsel = match rx_level {
556 0..=2 => 0b000, 3..=4 => 0b001, 5..=8 => 0b010, 9..=12 => 0b011, _ => 0b100, };
562
563 let tx_iflsel = match tx_level {
564 0..=2 => 0b000, 3..=4 => 0b001, 5..=8 => 0b010, 9..=12 => 0b011, _ => 0b100, };
570
571 self.registers()
572 .uartifls
573 .write(UARTIFLS::RXIFLSEL.val(rx_iflsel) + UARTIFLS::TXIFLSEL.val(tx_iflsel));
574 }
575}
576
577