1 249aeb61 2024-03-14 continue // uart_a64.cc
2 249aeb61 2024-03-14 continue // Allwinner A64 UART (16550)
5 249aeb61 2024-03-14 continue #include <hw.h>
6 249aeb61 2024-03-14 continue #include <uart.h>
7 bb583ea6 2024-03-14 continue #include <uart16550.h>
10 249aeb61 2024-03-14 continue namespace Board {
11 249aeb61 2024-03-14 continue namespace Uart {
14 249aeb61 2024-03-14 continue namespace {
16 249aeb61 2024-03-14 continue constexpr uintptr_t UART0_BASE = 0x01c28000;
18 bb583ea6 2024-03-14 continue constexpr auto SERIAL_CLOCK = 24000000;
19 249aeb61 2024-03-14 continue constexpr auto BAUDRATE = 115200;
20 bb583ea6 2024-03-14 continue constexpr auto BAUDRATE_DIVISOR = (BAUDRATE * 16);
21 bb583ea6 2024-03-14 continue constexpr auto CLOCK_DIVISOR = (SERIAL_CLOCK + (BAUDRATE_DIVISOR / 2)) / BAUDRATE_DIVISOR;
23 bb583ea6 2024-03-14 continue static_assert(CLOCK_DIVISOR == 13, "Should be 13");
25 6ed628b4 2024-03-18 continue template <typename T>
26 6ed628b4 2024-03-18 continue uint8_t read8()
28 6ed628b4 2024-03-18 continue return Hw::read8(UART0_BASE + T::OFFSET);
31 69da5ffe 2024-03-16 continue template <typename T>
32 69da5ffe 2024-03-16 continue T read()
34 6ed628b4 2024-03-18 continue return T{read8<T>()};
38 69da5ffe 2024-03-16 continue template <typename T>
39 6ed628b4 2024-03-18 continue void write8(uint8_t nValue)
41 6ed628b4 2024-03-18 continue Hw::write8(UART0_BASE + T::OFFSET, nValue);
44 6ed628b4 2024-03-18 continue template <typename T>
45 69da5ffe 2024-03-16 continue void write(T Register)
47 6ed628b4 2024-03-18 continue write8<T>(Register.m_u.m_nValue);
51 249aeb61 2024-03-14 continue } // anonymous namespace
54 249aeb61 2024-03-14 continue void initialize()
56 bb583ea6 2024-03-14 continue for (; ; )
58 69da5ffe 2024-03-16 continue const auto LineStatusRegister{read<Uart16550::LineStatusRegister>()};
59 bb583ea6 2024-03-14 continue if (LineStatusRegister.m_u.m_Bits.m_TransmitterEmpty)
63 69da5ffe 2024-03-16 continue write(Uart16550::InterruptEnableRegister{});
65 42dfc04a 2024-03-16 continue Uart16550::ModemControlRegister ModemControlRegister;
66 42dfc04a 2024-03-16 continue ModemControlRegister.m_u.m_Bits.m_DataTerminalReady = 1;
67 42dfc04a 2024-03-16 continue ModemControlRegister.m_u.m_Bits.m_RequestToSend = 1;
68 69da5ffe 2024-03-16 continue write(ModemControlRegister);
70 69da5ffe 2024-03-16 continue Uart16550::FifoControlRegister FifoControlRegister;
71 69da5ffe 2024-03-16 continue FifoControlRegister.m_u.m_Bits.m_EnableFifos = 1;
72 69da5ffe 2024-03-16 continue FifoControlRegister.m_u.m_Bits.m_RcvrFifoReset = 1;
73 69da5ffe 2024-03-16 continue FifoControlRegister.m_u.m_Bits.m_XmitFifoReset = 1;
74 69da5ffe 2024-03-16 continue write(FifoControlRegister);
76 6ed628b4 2024-03-18 continue Uart16550::LineControlRegister LineControlRegister;
77 6ed628b4 2024-03-18 continue LineControlRegister.m_u.m_Bits.m_DataLengthSelect = Uart16550::LineControlRegister::BITS_8;
78 6ed628b4 2024-03-18 continue write(LineControlRegister);
80 6ed628b4 2024-03-18 continue LineControlRegister.m_u.m_Bits.m_DivisorLatchAccess = 1;
81 6ed628b4 2024-03-18 continue write(LineControlRegister);
83 6ed628b4 2024-03-18 continue write8<Uart16550::DivisorLatchLowRegister>(CLOCK_DIVISOR & 0xff);
84 6ed628b4 2024-03-18 continue write8<Uart16550::DivisorLatchHighRegister>((CLOCK_DIVISOR >> 8) & 0xff);
86 6ed628b4 2024-03-18 continue LineControlRegister.m_u.m_Bits.m_DivisorLatchAccess = 0;
87 6ed628b4 2024-03-18 continue write(LineControlRegister);
91 249aeb61 2024-03-14 continue void send(uint8_t nValue)
93 6ed628b4 2024-03-18 continue for (; ; )
95 6ed628b4 2024-03-18 continue const auto LineStatusRegister{read<Uart16550::LineStatusRegister>()};
96 6ed628b4 2024-03-18 continue if (LineStatusRegister.m_u.m_Bits.m_TxHoldingRegisterEmpty)
99 6ed628b4 2024-03-18 continue write8<Uart16550::TransmitHoldingRegister>(nValue);
103 249aeb61 2024-03-14 continue uint8_t recv()
105 6ed628b4 2024-03-18 continue for (; ; )
107 6ed628b4 2024-03-18 continue const auto LineStatusRegister{read<Uart16550::LineStatusRegister>()};
108 6ed628b4 2024-03-18 continue if (LineStatusRegister.m_u.m_Bits.m_DataReady)
111 6ed628b4 2024-03-18 continue return read8<Uart16550::ReceiveBufferRegister>();
115 249aeb61 2024-03-14 continue } // namespace Uart
116 249aeb61 2024-03-14 continue } // namespace Board