xref: /optee_os/core/drivers/cdns_uart.c (revision 3481d2f66edff52fab73902a85196207a3e94a75)
1*3481d2f6SSoren Brinkmann /*
2*3481d2f6SSoren Brinkmann  * Copyright (c) 2016, Xilinx Inc.
3*3481d2f6SSoren Brinkmann  * All rights reserved.
4*3481d2f6SSoren Brinkmann  *
5*3481d2f6SSoren Brinkmann  * Redistribution and use in source and binary forms, with or without
6*3481d2f6SSoren Brinkmann  * modification, are permitted provided that the following conditions are met:
7*3481d2f6SSoren Brinkmann  *
8*3481d2f6SSoren Brinkmann  * 1. Redistributions of source code must retain the above copyright notice,
9*3481d2f6SSoren Brinkmann  * this list of conditions and the following disclaimer.
10*3481d2f6SSoren Brinkmann  *
11*3481d2f6SSoren Brinkmann  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*3481d2f6SSoren Brinkmann  * this list of conditions and the following disclaimer in the documentation
13*3481d2f6SSoren Brinkmann  * and/or other materials provided with the distribution.
14*3481d2f6SSoren Brinkmann  *
15*3481d2f6SSoren Brinkmann  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*3481d2f6SSoren Brinkmann  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*3481d2f6SSoren Brinkmann  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*3481d2f6SSoren Brinkmann  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19*3481d2f6SSoren Brinkmann  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*3481d2f6SSoren Brinkmann  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*3481d2f6SSoren Brinkmann  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*3481d2f6SSoren Brinkmann  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*3481d2f6SSoren Brinkmann  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*3481d2f6SSoren Brinkmann  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*3481d2f6SSoren Brinkmann  * POSSIBILITY OF SUCH DAMAGE.
26*3481d2f6SSoren Brinkmann  */
27*3481d2f6SSoren Brinkmann #include <compiler.h>
28*3481d2f6SSoren Brinkmann #include <drivers/cdns_uart.h>
29*3481d2f6SSoren Brinkmann #include <io.h>
30*3481d2f6SSoren Brinkmann #include <util.h>
31*3481d2f6SSoren Brinkmann 
32*3481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL		0
33*3481d2f6SSoren Brinkmann #define CDNS_UART_MODE			4
34*3481d2f6SSoren Brinkmann #define CDNS_UART_IEN			8
35*3481d2f6SSoren Brinkmann #define CDNS_UART_IRQ_STATUS		0x14
36*3481d2f6SSoren Brinkmann #define CDNS_UART_CHANNEL_STATUS	0x2c
37*3481d2f6SSoren Brinkmann #define CDNS_UART_FIFO			0x30
38*3481d2f6SSoren Brinkmann 
39*3481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL_RXRES		BIT(0)
40*3481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL_TXRES		BIT(1)
41*3481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL_RXEN		BIT(2)
42*3481d2f6SSoren Brinkmann #define CDNS_UART_CONTROL_TXEN		BIT(4)
43*3481d2f6SSoren Brinkmann 
44*3481d2f6SSoren Brinkmann #define CDNS_UART_MODE_8BIT		(0 << 1)
45*3481d2f6SSoren Brinkmann #define CDNS_UART_MODE_PARITY_NONE	(0x4 << 3)
46*3481d2f6SSoren Brinkmann #define CDNS_UART_MODE_1STP		(0 << 6)
47*3481d2f6SSoren Brinkmann 
48*3481d2f6SSoren Brinkmann #define CDNS_UART_CHANNEL_STATUS_TFUL	BIT(4)
49*3481d2f6SSoren Brinkmann #define CDNS_UART_CHANNEL_STATUS_TEMPTY	BIT(3)
50*3481d2f6SSoren Brinkmann #define CDNS_UART_CHANNEL_STATUS_REMPTY	BIT(1)
51*3481d2f6SSoren Brinkmann 
52*3481d2f6SSoren Brinkmann #define CDNS_UART_IRQ_RXTRIG		BIT(0)
53*3481d2f6SSoren Brinkmann #define CDNS_UART_IRQ_RXTOUT		BIT(8)
54*3481d2f6SSoren Brinkmann 
55*3481d2f6SSoren Brinkmann void cdns_uart_flush(vaddr_t base)
56*3481d2f6SSoren Brinkmann {
57*3481d2f6SSoren Brinkmann 	while (!(read32(base + CDNS_UART_CHANNEL_STATUS) &
58*3481d2f6SSoren Brinkmann 				CDNS_UART_CHANNEL_STATUS_TEMPTY))
59*3481d2f6SSoren Brinkmann 		;
60*3481d2f6SSoren Brinkmann }
61*3481d2f6SSoren Brinkmann 
62*3481d2f6SSoren Brinkmann /*
63*3481d2f6SSoren Brinkmann  * we rely on the bootloader having set up the HW correctly, we just enable
64*3481d2f6SSoren Brinkmann  * transmitter/receiver here, just in case.
65*3481d2f6SSoren Brinkmann  */
66*3481d2f6SSoren Brinkmann void cdns_uart_init(vaddr_t base, uint32_t uart_clk, uint32_t baud_rate)
67*3481d2f6SSoren Brinkmann {
68*3481d2f6SSoren Brinkmann 	if (!base || !uart_clk || !baud_rate)
69*3481d2f6SSoren Brinkmann 		return;
70*3481d2f6SSoren Brinkmann 
71*3481d2f6SSoren Brinkmann 	/* Enable UART and RX/TX */
72*3481d2f6SSoren Brinkmann 	write32(CDNS_UART_CONTROL_RXEN | CDNS_UART_CONTROL_TXEN,
73*3481d2f6SSoren Brinkmann 		base + CDNS_UART_CONTROL);
74*3481d2f6SSoren Brinkmann 
75*3481d2f6SSoren Brinkmann 	cdns_uart_flush(base);
76*3481d2f6SSoren Brinkmann }
77*3481d2f6SSoren Brinkmann 
78*3481d2f6SSoren Brinkmann void cdns_uart_putc(int ch, vaddr_t base)
79*3481d2f6SSoren Brinkmann {
80*3481d2f6SSoren Brinkmann 	/* Wait until there is space in the FIFO */
81*3481d2f6SSoren Brinkmann 	while (read32(base + CDNS_UART_CHANNEL_STATUS) &
82*3481d2f6SSoren Brinkmann 			CDNS_UART_CHANNEL_STATUS_TFUL)
83*3481d2f6SSoren Brinkmann 		;
84*3481d2f6SSoren Brinkmann 
85*3481d2f6SSoren Brinkmann 	/* Send the character */
86*3481d2f6SSoren Brinkmann 	write32(ch, base + CDNS_UART_FIFO);
87*3481d2f6SSoren Brinkmann }
88*3481d2f6SSoren Brinkmann 
89*3481d2f6SSoren Brinkmann bool cdns_uart_have_rx_data(vaddr_t base)
90*3481d2f6SSoren Brinkmann {
91*3481d2f6SSoren Brinkmann 	return !(read32(base + CDNS_UART_CHANNEL_STATUS) &
92*3481d2f6SSoren Brinkmann 			CDNS_UART_CHANNEL_STATUS_REMPTY);
93*3481d2f6SSoren Brinkmann }
94*3481d2f6SSoren Brinkmann 
95*3481d2f6SSoren Brinkmann int cdns_uart_getchar(vaddr_t base)
96*3481d2f6SSoren Brinkmann {
97*3481d2f6SSoren Brinkmann 	while (!cdns_uart_have_rx_data(base))
98*3481d2f6SSoren Brinkmann 		;
99*3481d2f6SSoren Brinkmann 	return read32(base + CDNS_UART_FIFO) & 0xff;
100*3481d2f6SSoren Brinkmann }
101