qemu_rv32_virt_chip/
uart.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! QEMU's memory mapped 16550 UART
6
7use core::cell::Cell;
8
9use kernel::hil;
10use kernel::utilities::cells::{OptionalCell, TakeCell};
11use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
12use kernel::utilities::registers::{
13    register_bitfields, Aliased, Field, InMemoryRegister, ReadOnly, ReadWrite,
14};
15use kernel::utilities::StaticRef;
16use kernel::ErrorCode;
17
18pub const UART0_BASE: StaticRef<Uart16550Registers> =
19    unsafe { StaticRef::new(0x1000_0000 as *const Uart16550Registers) };
20
21pub const UART_16550_BAUD_BASE: usize = 399193;
22
23type Uart16550RegshiftInt = u8;
24
25#[repr(C)]
26pub struct Uart16550Registers {
27    /// 0x00:
28    /// - DLAB = 0
29    ///   - Read: receiver buffer (RBR)
30    ///   - Write: transmitter holding (THR)
31    /// - DLAB = 1: divisor latch LSB (DLL)
32    rbr_thr: Aliased<Uart16550RegshiftInt, RBR::Register, THR::Register>,
33
34    /// 0x01:
35    /// - DLAB = 0: interrupt enable (IER)
36    /// - DLAB = 1: divisor latch MSB (DLM)
37    ier: ReadWrite<Uart16550RegshiftInt, IER::Register>,
38
39    /// 0x02:
40    /// - Read: interrupt identification (IIR)
41    /// - Write: FIFO control (FCR)
42    iir_fcr: Aliased<Uart16550RegshiftInt, IIR::Register, FCR::Register>,
43
44    /// 0x03: line control (LCR)
45    lcr: ReadWrite<Uart16550RegshiftInt, LCR::Register>,
46
47    /// 0x04: modem control (MCR)
48    mcr: ReadWrite<Uart16550RegshiftInt, MCR::Register>,
49
50    /// 0x05: line status (LSR)
51    lsr: ReadOnly<Uart16550RegshiftInt, LSR::Register>,
52
53    /// 0x06: modem status (MSR)
54    msr: ReadOnly<Uart16550RegshiftInt, MSR::Register>,
55}
56
57impl Uart16550Registers {
58    /// Access the DLL and DLM (divisor latch LSB and MSB) registers
59    ///
60    /// Setting the 7th bit of the line control register (LCR) changes
61    /// the RBR/THR and IER to be the DLL and DLM register
62    /// respectively.
63    ///
64    /// This function takes care of latching the registers and calling
65    /// a closure in which this virtual register can be
66    /// accessed. Prior to calling the closure, the register is
67    /// latched back and the closure is instead provided with an
68    /// in-memory copy of the register, which is then written back to
69    /// DLL and DLM.
70    ///
71    /// This provides a safe way to access the DLL and DLM
72    /// registers.
73    fn divisor_latch_reg<F, R>(&self, f: F) -> R
74    where
75        F: FnOnce(&InMemoryRegister<u16, DLR::Register>) -> R,
76    {
77        let dlab_field = Field::<Uart16550RegshiftInt, LCR::Register>::new(1, 7);
78
79        // Set DLAB = 1
80        self.lcr.modify(dlab_field.val(1));
81
82        // Read the old values of rbr_thr and ier and combine them
83        // into a u16
84        let old_val = u16::from_be_bytes([self.ier.get(), self.rbr_thr.get()]);
85
86        // Set DLAB = 0 prior to handing back to the caller
87        self.lcr.modify(dlab_field.val(0));
88
89        let dlr = InMemoryRegister::<u16, DLR::Register>::new(old_val);
90        let ret = f(&dlr);
91
92        // Get the bytes from the modified value
93        let [new_ier, new_rbr_thr] = u16::to_be_bytes(dlr.get());
94
95        // Set DLAB = 1
96        self.lcr.modify(dlab_field.val(1));
97
98        // Write the modified value back to the registers
99        self.ier.set(new_ier as Uart16550RegshiftInt);
100        self.rbr_thr.set(new_rbr_thr as Uart16550RegshiftInt);
101
102        // Set DLAB = 0
103        self.lcr.modify(dlab_field.val(0));
104
105        ret
106    }
107}
108
109register_bitfields![u8,
110    RBR [
111        Data OFFSET(0) NUMBITS(8) [],
112    ],
113    THR [
114        Data OFFSET(0) NUMBITS(8) [],
115    ],
116    IER [
117        ModemStatusRegisterChange OFFSET(3) NUMBITS(1) [],
118        ReceiverLineStatusRegisterChange OFFSET(2) NUMBITS(1) [],
119        TransmitterHoldingRegisterEmpty OFFSET(1) NUMBITS(1) [],
120        ReceivedDataAvailable OFFSET(0) NUMBITS(1) [],
121    ],
122    IIR [
123        FIFO OFFSET(6) NUMBITS(2) [
124            NoFIFO = 0,
125            UnusableFIFO = 2,
126            FIFOEnabled = 3,
127        ],
128        Identification OFFSET(1) NUMBITS(3) [
129            ModemStatusChange = 0,
130            TransmitterHoldingRegisterEmpty = 1,
131            ReceiveDataAvailable = 2,
132            LineStatusChange = 3,
133            CharacterTimeout = 6,
134        ],
135        Pending OFFSET(0) NUMBITS(1) [
136            Pending = 0,
137            NotPending = 1,
138        ],
139    ],
140    FCR [
141        ReceiveFIFOInterruptTriggerLevel OFFSET(6) NUMBITS(2) [
142            Bytes1 = 0,
143            Bytes4 = 1,
144            Bytes8 = 2,
145            Bytes14 = 3,
146        ],
147        DMAMode OFFSET(3) NUMBITS(1) [
148            Mode0 = 0,
149            Mode1 = 1,
150        ],
151        ClearTransmitFIFO OFFSET(2) NUMBITS(1) [],
152        ClearReceiveFIFO OFFSET(1) NUMBITS(1) [],
153        Enable OFFSET(0) NUMBITS(1) [],
154    ],
155    LCR [
156        BreakSignal OFFSET(6) NUMBITS(1) [],
157        ParityMode OFFSET(4) NUMBITS(2) [
158            Odd = 0,
159            Even = 1,
160            High = 2,
161            Low = 3,
162        ],
163        Parity OFFSET(3) NUMBITS(1) [],
164        StopBits OFFSET(2) NUMBITS(1) [
165            One = 0,
166            OneHalfTwo = 1,
167        ],
168        DataWordLength OFFSET(0) NUMBITS(2) [
169            Bits5 = 0,
170            Bits6 = 1,
171            Bits7 = 2,
172            Bits8 = 3,
173        ],
174    ],
175    MCR [
176        LoopbackMode OFFSET(4) NUMBITS(1) [],
177        AuxiliaryOutput2 OFFSET(3) NUMBITS(1) [],
178        AuxiliaryOutput1 OFFSET(2) NUMBITS(1) [],
179        RequestToSend OFFSET(1) NUMBITS(1) [],
180        DataTerminalReady OFFSET(0) NUMBITS(1) [],
181    ],
182    LSR [
183        ErronousDataInFIFO OFFSET(7) NUMBITS(1) [],
184        THREmptyLineIdle OFFSET(6) NUMBITS(1) [],
185        THREmpty OFFSET(5) NUMBITS(1) [],
186        BreakSignalReceived OFFSET(4) NUMBITS(1) [],
187        FramingError OFFSET(3) NUMBITS(1) [],
188        ParityError OFFSET(2) NUMBITS(1) [],
189        OverrunError OFFSET(1) NUMBITS(1) [],
190        DataAvailable OFFSET(0) NUMBITS(1) [],
191    ],
192    MSR [
193        CarrierDetect OFFSET(7) NUMBITS(1) [],
194        RingIndicator OFFSET(6) NUMBITS(1) [],
195        DataSetReady OFFSET(5) NUMBITS(1) [],
196        ClearToSend OFFSET(4) NUMBITS(1) [],
197        ChangeInCarrierDetect OFFSET(3) NUMBITS(1) [],
198        TrailingEdgeRingIndicator OFFSET(2) NUMBITS(1) [],
199        ChangeInDataSetReady OFFSET(1) NUMBITS(1) [],
200        ChangeInClearToSend OFFSET(0) NUMBITS(1) [],
201    ],
202];
203
204register_bitfields![u16,
205    DLR [
206        Divisor OFFSET(0) NUMBITS(16) [],
207    ],
208];
209
210pub struct Uart16550<'a> {
211    regs: StaticRef<Uart16550Registers>,
212    tx_client: OptionalCell<&'a dyn hil::uart::TransmitClient>,
213    rx_client: OptionalCell<&'a dyn hil::uart::ReceiveClient>,
214    tx_buffer: TakeCell<'static, [u8]>,
215    tx_len: Cell<usize>,
216    tx_index: Cell<usize>,
217    rx_buffer: TakeCell<'static, [u8]>,
218    rx_len: Cell<usize>,
219    rx_index: Cell<usize>,
220}
221
222impl<'a> Uart16550<'a> {
223    pub fn new(regs: StaticRef<Uart16550Registers>) -> Uart16550<'a> {
224        // Disable all interrupts when constructing the UART
225        regs.ier.set(0xF);
226
227        regs.iir_fcr.write(FCR::Enable::CLEAR);
228
229        Uart16550 {
230            regs,
231            tx_client: OptionalCell::empty(),
232            rx_client: OptionalCell::empty(),
233            tx_buffer: TakeCell::empty(),
234            tx_len: Cell::new(0),
235            tx_index: Cell::new(0),
236            rx_buffer: TakeCell::empty(),
237            rx_len: Cell::new(0),
238            rx_index: Cell::new(0),
239        }
240    }
241}
242
243impl Uart16550<'_> {
244    pub fn handle_interrupt(&self) {
245        // Currently we can only receive a tx interrupt, however we
246        // need to check the interrupt cause nonetheless as this will
247        // clear the TX interrupt bit
248        let iir = self.regs.iir_fcr.extract();
249
250        // Check if the register contained a valid interrupt at all
251        if !iir.matches_all(IIR::Pending::Pending) {
252            panic!("UART 16550: interrupt without interrupt");
253        }
254
255        // Check whether there is space for new data
256        if iir.matches_all(IIR::Identification::TransmitterHoldingRegisterEmpty) {
257            // The respective interrupt has already been cleared by
258            // the extraction of IIR
259
260            // We also check whether the tx_buffer is set, as we
261            // could've generated the interrupt by transmit_sync
262            if self.tx_buffer.is_some() {
263                self.transmit_continue();
264            }
265        }
266        // Check whether we've received some new data.
267        else if iir.matches_all(IIR::Identification::ReceiveDataAvailable) {
268            self.receive();
269        }
270        // We don't care about MSC interrupts, but have to ack the
271        // interrupt by reading MSR
272        else if iir.matches_all(IIR::Identification::ModemStatusChange) {
273            let _ = self.regs.msr.get();
274        }
275        // We don't care about LSC interrupts, but have to ack the
276        // interrupt by reading LSR
277        else if iir.matches_all(IIR::Identification::LineStatusChange) {
278            let _ = self.regs.lsr.get();
279        }
280        // We con't care about character timeout interrupts, but CAN'T
281        // SUPPRESS THEM and have to ack by reading RBR
282        else if iir.matches_all(IIR::Identification::CharacterTimeout) {
283            let _ = self.regs.rbr_thr.get();
284        }
285        // All other interrupt sources are unknown, panic if we see
286        // them
287        else {
288            panic!("UART 16550: unknown interrupt");
289        }
290    }
291
292    /// Blocking transmit
293    ///
294    /// This function will transmit the passed slice in a blocking
295    /// fashing, returning when finished.
296    ///
297    /// The current device configuration is used, and the device must
298    /// be enabled. Otherwise, this function may block indefinitely.
299    pub fn transmit_sync(&self, bytes: &[u8]) {
300        // We don't want to cause excessive interrupts here, so
301        // disable transmit interrupts temporarily
302        let prev_ier = self.regs.ier.extract();
303        if prev_ier.is_set(IER::TransmitterHoldingRegisterEmpty) {
304            self.regs
305                .ier
306                .modify_no_read(prev_ier, IER::TransmitterHoldingRegisterEmpty::CLEAR);
307        }
308
309        for byte in bytes.iter() {
310            while !self.regs.lsr.is_set(LSR::THREmpty) {}
311            self.regs.rbr_thr.write(THR::Data.val(*byte));
312        }
313
314        // Restore the IER register to its original state
315        self.regs.ier.set(prev_ier.get());
316    }
317
318    fn transmit_continue(&self) {
319        // This should only be called as a result of a transmit
320        // interrupt
321
322        // Get the current transmission information
323        let mut index = self.tx_index.get();
324        let tx_data = self.tx_buffer.take().expect("UART 16550: no tx buffer");
325
326        if index < self.tx_len.get() {
327            // Still data to send
328            while index < self.tx_len.get() && self.regs.lsr.is_set(LSR::THREmpty) {
329                self.regs.rbr_thr.write(THR::Data.val(tx_data[index]));
330                index += 1;
331            }
332
333            // Put the updated index and buffer back, wait for an
334            // interrupt
335            self.tx_index.set(index);
336            self.tx_buffer.replace(tx_data);
337        } else {
338            // We are finished, disable tx interrupts
339            self.regs
340                .ier
341                .modify(IER::TransmitterHoldingRegisterEmpty::CLEAR);
342
343            // Callback to the client
344            self.tx_client
345                .map(move |client| client.transmitted_buffer(tx_data, self.tx_len.get(), Ok(())));
346        }
347    }
348
349    fn receive(&self) {
350        // Receive interrupts must only be enabled when we're currently holding
351        // a buffer to receive data into:
352        let rx_buffer = self.rx_buffer.take().expect("UART 16550: no rx buffer");
353        let len = self.rx_len.get();
354        let mut index = self.rx_index.get();
355
356        // Read in a while loop, until no more data in the FIFO
357        while self.regs.lsr.is_set(LSR::DataAvailable) && index < len {
358            rx_buffer[index] = self.regs.rbr_thr.get();
359            index += 1;
360        }
361
362        // Check whether we've read sufficient data:
363        if index == len {
364            // We're done, disable interrupts and return to the client:
365            self.regs.ier.modify(IER::ReceivedDataAvailable::CLEAR);
366
367            self.rx_client.map(move |client| {
368                client.received_buffer(rx_buffer, len, Ok(()), hil::uart::Error::None)
369            });
370        } else {
371            // Store the new index and place the buffer back:
372            self.rx_index.set(index);
373            self.rx_buffer.replace(rx_buffer);
374        }
375    }
376}
377
378impl hil::uart::Configure for Uart16550<'_> {
379    fn configure(&self, params: hil::uart::Parameters) -> Result<(), ErrorCode> {
380        use hil::uart::{Parity, StopBits, Width};
381
382        // 16550 operates at a default frequency of 115200. Dividing
383        // this by the target frequency gives the divisor register
384        // contents.
385        let divisor: u16 = (115_200 / params.baud_rate) as u16;
386        self.regs.divisor_latch_reg(|dlr| {
387            dlr.set(divisor);
388        });
389
390        let mut lcr = self.regs.lcr.extract();
391
392        match params.width {
393            Width::Six => lcr.modify(LCR::DataWordLength::Bits6),
394            Width::Seven => lcr.modify(LCR::DataWordLength::Bits7),
395            Width::Eight => lcr.modify(LCR::DataWordLength::Bits8),
396        }
397
398        match params.stop_bits {
399            StopBits::One => LCR::StopBits::One,
400            // 1.5 stop bits for 5bit works, 2 stop bits for 6-8 bit
401            // words. We only support 6-8 bit words, so this
402            // configures 2 stop bits
403            StopBits::Two => LCR::StopBits::OneHalfTwo,
404        };
405
406        match params.parity {
407            Parity::None => lcr.modify(LCR::Parity.val(0b000)),
408            Parity::Odd => lcr.modify(LCR::Parity.val(0b001)),
409            Parity::Even => lcr.modify(LCR::Parity.val(0b011)),
410        }
411
412        match params.hw_flow_control {
413            true => lcr.modify(LCR::BreakSignal::SET),
414            false => lcr.modify(LCR::BreakSignal::CLEAR),
415        }
416
417        self.regs.lcr.set(lcr.get());
418
419        Ok(())
420    }
421}
422
423impl<'a> hil::uart::Transmit<'a> for Uart16550<'a> {
424    fn set_transmit_client(&self, client: &'a dyn hil::uart::TransmitClient) {
425        self.tx_client.set(client);
426    }
427
428    fn transmit_buffer(
429        &self,
430        tx_data: &'static mut [u8],
431        tx_len: usize,
432    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
433        if tx_len > tx_data.len() {
434            return Err((ErrorCode::INVAL, tx_data));
435        }
436
437        if self.tx_buffer.is_some() {
438            return Err((ErrorCode::BUSY, tx_data));
439        }
440
441        // Enable interrupts for the transmitter holding register
442        // being empty such that we can callback to the client
443        self.regs
444            .ier
445            .modify(IER::TransmitterHoldingRegisterEmpty::SET);
446
447        // Start transmitting the first data word(s) already
448        let mut index = 0;
449        while index < tx_len && self.regs.lsr.is_set(LSR::THREmpty) {
450            self.regs.rbr_thr.write(THR::Data.val(tx_data[index]));
451            index += 1;
452        }
453
454        // Store the required buffer and information for the interrupt
455        // handler
456        self.tx_buffer.replace(tx_data);
457        self.tx_len.set(tx_len);
458        self.tx_index.set(index);
459
460        Ok(())
461    }
462
463    fn transmit_abort(&self) -> Result<(), ErrorCode> {
464        Err(ErrorCode::FAIL)
465    }
466
467    fn transmit_word(&self, _word: u32) -> Result<(), ErrorCode> {
468        Err(ErrorCode::FAIL)
469    }
470}
471
472impl<'a> hil::uart::Receive<'a> for Uart16550<'a> {
473    fn set_receive_client(&self, client: &'a dyn hil::uart::ReceiveClient) {
474        self.rx_client.set(client);
475    }
476
477    fn receive_buffer(
478        &self,
479        rx_buffer: &'static mut [u8],
480        rx_len: usize,
481    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
482        // Ensure the provided buffer holds at least `rx_len` bytes, and
483        // `rx_len` is strictly positive (otherwise we'd need to use deferred
484        // calls):
485        if rx_buffer.len() < rx_len && rx_len > 0 {
486            return Err((ErrorCode::SIZE, rx_buffer));
487        }
488
489        // Store the receive buffer and byte count. We cannot call into the
490        // generic receive routine here, as the client callback needs to be
491        // called from another call stack. Hence simply enable interrupts here.
492        self.rx_buffer.replace(rx_buffer);
493        self.rx_len.set(rx_len);
494        self.rx_index.set(0);
495
496        // Enable receive interrupts:
497        self.regs.ier.modify(IER::ReceivedDataAvailable::SET);
498
499        Ok(())
500    }
501
502    fn receive_abort(&self) -> Result<(), ErrorCode> {
503        // Currently unsupported as we'd like to avoid using deferred
504        // calls. Needs to be migrated to the new UART HIL anyways.
505        Err(ErrorCode::FAIL)
506    }
507
508    fn receive_word(&self) -> Result<(), ErrorCode> {
509        // Currently unsupported.
510        Err(ErrorCode::FAIL)
511    }
512}