xref: /optee_os/core/drivers/serial8250_uart.c (revision 1bb929836182ecb96d2d9d268daa807c67596396)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <compiler.h>
30 #include <console.h>
31 #include <drivers/serial8250_uart.h>
32 #include <io.h>
33 #include <keep.h>
34 #include <util.h>
35 
36 /* uart register defines */
37 #define UART_RHR	0x0
38 #define UART_THR	0x0
39 #define UART_IER	0x4
40 #define UART_ISR	0x8
41 #define UART_FCR	0x8
42 #define UART_LCR	0xc
43 #define UART_MCR	0x10
44 #define UART_LSR	0x14
45 #define UART_MSR	0x18
46 #define UART_SPR	0x1c
47 
48 /* uart status register bits */
49 #define LSR_TEMT	0x40 /* Transmitter empty */
50 #define LSR_THRE	0x20 /* Transmit-hold-register empty */
51 #define LSR_EMPTY	(LSR_TEMT | LSR_THRE)
52 #define LSR_DR		0x01 /* DATA Ready */
53 
54 static vaddr_t chip_to_base(struct serial_chip *chip)
55 {
56 	struct serial8250_uart_data *pd =
57 		container_of(chip, struct serial8250_uart_data, chip);
58 
59 	return io_pa_or_va(&pd->base);
60 }
61 
62 static void serial8250_uart_flush(struct serial_chip *chip)
63 {
64 	vaddr_t base = chip_to_base(chip);
65 
66 	while (1) {
67 		uint32_t state = read32(base + UART_LSR);
68 
69 		/* Wait until transmit FIFO is empty */
70 		if ((state & LSR_EMPTY) == LSR_EMPTY)
71 			break;
72 	}
73 }
74 
75 static bool serial8250_uart_have_rx_data(struct serial_chip *chip)
76 {
77 	vaddr_t base = chip_to_base(chip);
78 
79 	return (read32(base + UART_LSR) & LSR_DR);
80 }
81 
82 static int serial8250_uart_getchar(struct serial_chip *chip)
83 {
84 	vaddr_t base = chip_to_base(chip);
85 
86 	while (!serial8250_uart_have_rx_data(chip)) {
87 		/* Transmit FIFO is empty, waiting again */
88 		;
89 	}
90 	return read32(base + UART_RHR) & 0xff;
91 }
92 
93 static void serial8250_uart_putc(struct serial_chip *chip, int ch)
94 {
95 	vaddr_t base = chip_to_base(chip);
96 
97 	serial8250_uart_flush(chip);
98 
99 	/* Write out character to transmit FIFO */
100 	write32(ch, base + UART_THR);
101 }
102 
103 static const struct serial_ops serial8250_uart_ops = {
104 	.flush = serial8250_uart_flush,
105 	.getchar = serial8250_uart_getchar,
106 	.have_rx_data = serial8250_uart_have_rx_data,
107 	.putc = serial8250_uart_putc,
108 };
109 KEEP_PAGER(serial8250_uart_ops);
110 
111 void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base,
112 			  uint32_t __unused uart_clk,
113 			  uint32_t __unused baud_rate)
114 
115 {
116 	pd->base.pa = base;
117 	pd->chip.ops = &serial8250_uart_ops;
118 
119 	/*
120 	 * do nothing, debug uart(uart0) share with normal world,
121 	 * everything for uart0 is ready now.
122 	 */
123 }
124