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>
9 #include <soc/addressmap.h>
14 uint32_t thr
; /* Transmit holding register. */
15 uint32_t rbr
; /* Receive buffer register. */
16 uint32_t dll
; /* Divisor latch lsb. */
19 uint32_t ier
; /* Interrupt enable register. */
20 uint32_t dlm
; /* Divisor latch msb. */
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. */
29 uint32_t mcr
; /* Modem control register. */
30 uint32_t xn1
; /* XON1 */
33 uint32_t lsr
; /* Line status register. */
34 uint32_t xn2
; /* XON2 */
37 uint32_t msr
; /* Modem status register. */
38 uint32_t xf1
; /* XOFF1 */
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. */
48 /* Peripheral Reset and Power Down registers */
49 struct mtk_peri_globalcon
{
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) {
88 /* Set divisor DLL and DLH */
89 divisor
= uartclk
/ (quot
* baudrate
);
90 remainder
= uartclk
% (quot
* baudrate
);
92 if (remainder
>= (quot
/ 2) * baudrate
)
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())
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
)
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
)
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
;