Blame


1 249aeb61 2024-03-14 continue // uart_a64.cc
2 249aeb61 2024-03-14 continue // Allwinner A64 UART (16550)
3 249aeb61 2024-03-14 continue
4 249aeb61 2024-03-14 continue
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>
8 249aeb61 2024-03-14 continue
9 249aeb61 2024-03-14 continue
10 249aeb61 2024-03-14 continue namespace Board {
11 249aeb61 2024-03-14 continue namespace Uart {
12 249aeb61 2024-03-14 continue
13 249aeb61 2024-03-14 continue
14 249aeb61 2024-03-14 continue namespace {
15 249aeb61 2024-03-14 continue
16 249aeb61 2024-03-14 continue constexpr uintptr_t UART0_BASE = 0x01c28000;
17 249aeb61 2024-03-14 continue
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;
22 249aeb61 2024-03-14 continue
23 bb583ea6 2024-03-14 continue static_assert(CLOCK_DIVISOR == 13, "Should be 13");
24 249aeb61 2024-03-14 continue
25 6ed628b4 2024-03-18 continue template <typename T>
26 6ed628b4 2024-03-18 continue uint8_t read8()
27 6ed628b4 2024-03-18 continue {
28 6ed628b4 2024-03-18 continue return Hw::read8(UART0_BASE + T::OFFSET);
29 6ed628b4 2024-03-18 continue }
30 69da5ffe 2024-03-16 continue
31 69da5ffe 2024-03-16 continue template <typename T>
32 69da5ffe 2024-03-16 continue T read()
33 69da5ffe 2024-03-16 continue {
34 6ed628b4 2024-03-18 continue return T{read8<T>()};
35 69da5ffe 2024-03-16 continue }
36 69da5ffe 2024-03-16 continue
37 69da5ffe 2024-03-16 continue
38 69da5ffe 2024-03-16 continue template <typename T>
39 6ed628b4 2024-03-18 continue void write8(uint8_t nValue)
40 6ed628b4 2024-03-18 continue {
41 6ed628b4 2024-03-18 continue Hw::write8(UART0_BASE + T::OFFSET, nValue);
42 6ed628b4 2024-03-18 continue }
43 6ed628b4 2024-03-18 continue
44 6ed628b4 2024-03-18 continue template <typename T>
45 69da5ffe 2024-03-16 continue void write(T Register)
46 69da5ffe 2024-03-16 continue {
47 6ed628b4 2024-03-18 continue write8<T>(Register.m_u.m_nValue);
48 69da5ffe 2024-03-16 continue }
49 69da5ffe 2024-03-16 continue
50 69da5ffe 2024-03-16 continue
51 249aeb61 2024-03-14 continue } // anonymous namespace
52 249aeb61 2024-03-14 continue
53 249aeb61 2024-03-14 continue
54 249aeb61 2024-03-14 continue void initialize()
55 249aeb61 2024-03-14 continue {
56 bb583ea6 2024-03-14 continue for (; ; )
57 bb583ea6 2024-03-14 continue {
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)
60 bb583ea6 2024-03-14 continue break;
61 bb583ea6 2024-03-14 continue }
62 42dfc04a 2024-03-16 continue
63 69da5ffe 2024-03-16 continue write(Uart16550::InterruptEnableRegister{});
64 42dfc04a 2024-03-16 continue
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);
69 69da5ffe 2024-03-16 continue
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);
75 6ed628b4 2024-03-18 continue
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);
79 6ed628b4 2024-03-18 continue
80 6ed628b4 2024-03-18 continue LineControlRegister.m_u.m_Bits.m_DivisorLatchAccess = 1;
81 6ed628b4 2024-03-18 continue write(LineControlRegister);
82 6ed628b4 2024-03-18 continue
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);
85 6ed628b4 2024-03-18 continue
86 6ed628b4 2024-03-18 continue LineControlRegister.m_u.m_Bits.m_DivisorLatchAccess = 0;
87 6ed628b4 2024-03-18 continue write(LineControlRegister);
88 249aeb61 2024-03-14 continue }
89 249aeb61 2024-03-14 continue
90 249aeb61 2024-03-14 continue
91 249aeb61 2024-03-14 continue void send(uint8_t nValue)
92 249aeb61 2024-03-14 continue {
93 6ed628b4 2024-03-18 continue for (; ; )
94 6ed628b4 2024-03-18 continue {
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)
97 6ed628b4 2024-03-18 continue break;
98 6ed628b4 2024-03-18 continue }
99 6ed628b4 2024-03-18 continue write8<Uart16550::TransmitHoldingRegister>(nValue);
100 249aeb61 2024-03-14 continue }
101 249aeb61 2024-03-14 continue
102 249aeb61 2024-03-14 continue
103 249aeb61 2024-03-14 continue uint8_t recv()
104 249aeb61 2024-03-14 continue {
105 6ed628b4 2024-03-18 continue for (; ; )
106 6ed628b4 2024-03-18 continue {
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)
109 6ed628b4 2024-03-18 continue break;
110 6ed628b4 2024-03-18 continue }
111 6ed628b4 2024-03-18 continue return read8<Uart16550::ReceiveBufferRegister>();
112 249aeb61 2024-03-14 continue }
113 249aeb61 2024-03-14 continue
114 249aeb61 2024-03-14 continue
115 249aeb61 2024-03-14 continue } // namespace Uart
116 249aeb61 2024-03-14 continue } // namespace Board