xref: /optee_os/core/drivers/serial8250_uart.c (revision 78b7c7c7653f8bff42fe44d31a79d7f6bbfd4d47)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  * All rights reserved.
5  */
6 
7 #include <compiler.h>
8 #include <console.h>
9 #include <drivers/serial8250_uart.h>
10 #include <io.h>
11 #include <keep.h>
12 #include <util.h>
13 
14 /* uart register defines */
15 #define UART_RHR	0x0
16 #define UART_THR	0x0
17 #define UART_IER	0x4
18 #define UART_ISR	0x8
19 #define UART_FCR	0x8
20 #define UART_LCR	0xc
21 #define UART_MCR	0x10
22 #define UART_LSR	0x14
23 #define UART_MSR	0x18
24 #define UART_SPR	0x1c
25 
26 /* uart status register bits */
27 #define LSR_TEMT	0x40 /* Transmitter empty */
28 #define LSR_THRE	0x20 /* Transmit-hold-register empty */
29 #define LSR_EMPTY	(LSR_TEMT | LSR_THRE)
30 #define LSR_DR		0x01 /* DATA Ready */
31 
32 static vaddr_t chip_to_base(struct serial_chip *chip)
33 {
34 	struct serial8250_uart_data *pd =
35 		container_of(chip, struct serial8250_uart_data, chip);
36 
37 	return io_pa_or_va(&pd->base);
38 }
39 
40 static void serial8250_uart_flush(struct serial_chip *chip)
41 {
42 	vaddr_t base = chip_to_base(chip);
43 
44 	while (1) {
45 		uint32_t state = read32(base + UART_LSR);
46 
47 		/* Wait until transmit FIFO is empty */
48 		if ((state & LSR_EMPTY) == LSR_EMPTY)
49 			break;
50 	}
51 }
52 
53 static bool serial8250_uart_have_rx_data(struct serial_chip *chip)
54 {
55 	vaddr_t base = chip_to_base(chip);
56 
57 	return (read32(base + UART_LSR) & LSR_DR);
58 }
59 
60 static int serial8250_uart_getchar(struct serial_chip *chip)
61 {
62 	vaddr_t base = chip_to_base(chip);
63 
64 	while (!serial8250_uart_have_rx_data(chip)) {
65 		/* Transmit FIFO is empty, waiting again */
66 		;
67 	}
68 	return read32(base + UART_RHR) & 0xff;
69 }
70 
71 static void serial8250_uart_putc(struct serial_chip *chip, int ch)
72 {
73 	vaddr_t base = chip_to_base(chip);
74 
75 	serial8250_uart_flush(chip);
76 
77 	/* Write out character to transmit FIFO */
78 	write32(ch, base + UART_THR);
79 }
80 
81 static const struct serial_ops serial8250_uart_ops = {
82 	.flush = serial8250_uart_flush,
83 	.getchar = serial8250_uart_getchar,
84 	.have_rx_data = serial8250_uart_have_rx_data,
85 	.putc = serial8250_uart_putc,
86 };
87 KEEP_PAGER(serial8250_uart_ops);
88 
89 void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base,
90 			  uint32_t __unused uart_clk,
91 			  uint32_t __unused baud_rate)
92 
93 {
94 	pd->base.pa = base;
95 	pd->chip.ops = &serial8250_uart_ops;
96 
97 	/*
98 	 * do nothing, debug uart(uart0) share with normal world,
99 	 * everything for uart0 is ready now.
100 	 */
101 }
102