mb/system76/cml-u/dt: Make use of chipset devicetree
[coreboot.git] / src / soc / mediatek / common / uart.c
blob4585fc07cbe87a95fa8ad445eed6ff4ad5192b93
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <device/mmio.h>
4 #include <boot/coreboot_tables.h>
5 #include <console/uart.h>
6 #include <drivers/uart/uart8250reg.h>
7 #include <stdint.h>
9 #include <soc/addressmap.h>
10 #include <soc/pll.h>
12 struct mtk_uart {
13 union {
14 uint32_t thr; /* Transmit holding register. */
15 uint32_t rbr; /* Receive buffer register. */
16 uint32_t dll; /* Divisor latch lsb. */
18 union {
19 uint32_t ier; /* Interrupt enable register. */
20 uint32_t dlm; /* Divisor latch msb. */
22 union {
23 uint32_t iir; /* Interrupt identification register. */
24 uint32_t fcr; /* FIFO control register. */
25 uint32_t efr; /* Enhanced feature register. */
27 uint32_t lcr; /* Line control register. */
28 union {
29 uint32_t mcr; /* Modem control register. */
30 uint32_t xn1; /* XON1 */
32 union {
33 uint32_t lsr; /* Line status register. */
34 uint32_t xn2; /* XON2 */
36 union {
37 uint32_t msr; /* Modem status register. */
38 uint32_t xf1; /* XOFF1 */
40 union {
41 uint32_t scr; /* Scratch register. */
42 uint32_t xf2; /* XOFF2 */
44 uint32_t autobaud_en; /* Enable auto baudrate. */
45 uint32_t highspeed; /* High speed UART. */
46 } __packed;
48 /* Peripheral Reset and Power Down registers */
49 struct mtk_peri_globalcon {
50 uint32_t rst0;
51 uint32_t rst1;
52 uint32_t pdn0_set;
53 uint32_t pdn1_set;
54 uint32_t pdn0_clr;
55 uint32_t pdn1_clr;
56 uint32_t pdn0_sta;
57 uint32_t pdn1_sta;
58 uint32_t pdn_md1_set;
59 uint32_t pdn_md2_set;
60 uint32_t pdn_md1_clr;
61 uint32_t pdn_md2_clr;
62 uint32_t pdn_md1_sta;
63 uint32_t pdn_md2_sta;
64 uint32_t pdn_md_mask;
65 } __packed;
67 static struct mtk_uart *const uart_ptr = (void *)UART0_BASE;
69 static void mtk_uart_tx_flush(void);
70 static int mtk_uart_tst_byte(void);
72 static void mtk_uart_init(void)
74 /* Use a hardcoded divisor for now. */
75 const unsigned int uartclk = UART_HZ;
76 const unsigned int baudrate = get_uart_baudrate();
77 const uint8_t line_config = UART8250_LCR_WLS_8; /* 8n1 */
78 unsigned int highspeed, quot, divisor, remainder;
80 if (baudrate <= 115200) {
81 highspeed = 0;
82 quot = 16;
83 } else {
84 highspeed = 2;
85 quot = 4;
88 /* Set divisor DLL and DLH */
89 divisor = uartclk / (quot * baudrate);
90 remainder = uartclk % (quot * baudrate);
92 if (remainder >= (quot / 2) * baudrate)
93 divisor += 1;
95 mtk_uart_tx_flush();
97 /* Disable interrupts. */
98 write8(&uart_ptr->ier, 0);
99 /* Force DTR and RTS to high. */
100 write8(&uart_ptr->mcr, UART8250_MCR_DTR | UART8250_MCR_RTS);
101 /* Set High speed UART register. */
102 write8(&uart_ptr->highspeed, highspeed);
103 /* Set line configuration, access divisor latches. */
104 write8(&uart_ptr->lcr, UART8250_LCR_DLAB | line_config);
105 /* Set the divisor. */
106 write8(&uart_ptr->dll, divisor & 0xff);
107 write8(&uart_ptr->dlm, (divisor >> 8) & 0xff);
108 /* Hide the divisor latches. */
109 write8(&uart_ptr->lcr, line_config);
110 /* Enable FIFOs, and clear receive and transmit. */
111 write8(&uart_ptr->fcr,
112 UART8250_FCR_FIFO_EN | UART8250_FCR_CLEAR_RCVR |
113 UART8250_FCR_CLEAR_XMIT);
116 static void mtk_uart_tx_byte(unsigned char data)
118 while (!(read8(&uart_ptr->lsr) & UART8250_LSR_THRE))
120 write8(&uart_ptr->thr, data);
123 static void mtk_uart_tx_flush(void)
125 while (!(read8(&uart_ptr->lsr) & UART8250_LSR_TEMT))
129 static unsigned char mtk_uart_rx_byte(void)
131 if (!mtk_uart_tst_byte())
132 return 0;
133 return read8(&uart_ptr->rbr);
136 static int mtk_uart_tst_byte(void)
138 return (read8(&uart_ptr->lsr) & UART8250_LSR_DR) == UART8250_LSR_DR;
141 void uart_init(unsigned int idx)
143 mtk_uart_init();
146 unsigned char uart_rx_byte(unsigned int idx)
148 return mtk_uart_rx_byte();
151 void uart_tx_byte(unsigned int idx, unsigned char data)
153 mtk_uart_tx_byte(data);
156 void uart_tx_flush(unsigned int idx)
158 mtk_uart_tx_flush();
161 enum cb_err fill_lb_serial(struct lb_serial *serial)
163 serial->type = LB_SERIAL_TYPE_MEMORY_MAPPED;
164 serial->baseaddr = UART0_BASE;
165 serial->baud = get_uart_baudrate();
166 serial->regwidth = 4;
167 serial->input_hertz = UART_HZ;
169 return CB_SUCCESS;