xref: /optee_os/core/drivers/sprd_uart.c (revision 59cfa779ae5675bc94196d2526ec3e9df4cf3059)
11537d62eSAijun Sun /*
21537d62eSAijun Sun  * Copyright (c) 2016, Spreadtrum Communications Inc.
3*59cfa779SJerome Forissier  * Copyright (c) 2017, Linaro Limited
41537d62eSAijun Sun  * All rights reserved.
51537d62eSAijun Sun  *
61537d62eSAijun Sun  * Redistribution and use in source and binary forms, with or without
71537d62eSAijun Sun  * modification, are permitted provided that the following conditions are met:
81537d62eSAijun Sun  *
91537d62eSAijun Sun  * 1. Redistributions of source code must retain the above copyright notice,
101537d62eSAijun Sun  * this list of conditions and the following disclaimer.
111537d62eSAijun Sun  *
121537d62eSAijun Sun  * 2. Redistributions in binary form must reproduce the above copyright notice,
131537d62eSAijun Sun  * this list of conditions and the following disclaimer in the documentation
141537d62eSAijun Sun  * and/or other materials provided with the distribution.
151537d62eSAijun Sun  *
161537d62eSAijun Sun  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
171537d62eSAijun Sun  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181537d62eSAijun Sun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191537d62eSAijun Sun  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
201537d62eSAijun Sun  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211537d62eSAijun Sun  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221537d62eSAijun Sun  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231537d62eSAijun Sun  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241537d62eSAijun Sun  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251537d62eSAijun Sun  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261537d62eSAijun Sun  * POSSIBILITY OF SUCH DAMAGE.
271537d62eSAijun Sun  */
281537d62eSAijun Sun #include <drivers/sprd_uart.h>
29*59cfa779SJerome Forissier #include <io.h>
30*59cfa779SJerome Forissier #include <util.h>
311537d62eSAijun Sun 
321537d62eSAijun Sun /* Register definitions */
331537d62eSAijun Sun #define UART_TXD		0x0000
341537d62eSAijun Sun #define UART_RXD		0x0004
351537d62eSAijun Sun #define UART_STS1		0x000C /* data number in TX and RX fifo */
361537d62eSAijun Sun 
371537d62eSAijun Sun /* Register Bit Fields*/
381537d62eSAijun Sun #define STS1_RXF_CNT_MASK	0x00ff  /* Rx FIFO data counter mask */
391537d62eSAijun Sun #define STS1_TXF_CNT_MASK	0xff00 /* Tx FIFO data counter mask */
401537d62eSAijun Sun 
41*59cfa779SJerome Forissier static vaddr_t chip_to_base(struct serial_chip *chip)
421537d62eSAijun Sun {
43*59cfa779SJerome Forissier 	struct sprd_uart_data *pd =
44*59cfa779SJerome Forissier 		container_of(chip, struct sprd_uart_data, chip);
45*59cfa779SJerome Forissier 
46*59cfa779SJerome Forissier 	return io_pa_or_va(&pd->base);
471537d62eSAijun Sun }
481537d62eSAijun Sun 
49*59cfa779SJerome Forissier static void sprd_uart_flush(struct serial_chip *chip)
501537d62eSAijun Sun {
51*59cfa779SJerome Forissier 	vaddr_t base = chip_to_base(chip);
521537d62eSAijun Sun 
53*59cfa779SJerome Forissier 	while (read32(base + UART_STS1) & STS1_TXF_CNT_MASK)
541537d62eSAijun Sun 		;
551537d62eSAijun Sun }
561537d62eSAijun Sun 
57*59cfa779SJerome Forissier static bool sprd_uart_have_rx_data(struct serial_chip *chip)
581537d62eSAijun Sun {
59*59cfa779SJerome Forissier 	vaddr_t base = chip_to_base(chip);
60*59cfa779SJerome Forissier 
61*59cfa779SJerome Forissier 	return !!(read32(base + UART_STS1) & STS1_RXF_CNT_MASK);
62*59cfa779SJerome Forissier }
63*59cfa779SJerome Forissier 
64*59cfa779SJerome Forissier static void sprd_uart_putc(struct serial_chip *chip, int ch)
65*59cfa779SJerome Forissier {
66*59cfa779SJerome Forissier 	vaddr_t base = chip_to_base(chip);
67*59cfa779SJerome Forissier 
68*59cfa779SJerome Forissier 	sprd_uart_flush(chip);
69*59cfa779SJerome Forissier 	write32(base + UART_TXD, ch);
70*59cfa779SJerome Forissier }
71*59cfa779SJerome Forissier 
72*59cfa779SJerome Forissier static int sprd_uart_getchar(struct serial_chip *chip)
73*59cfa779SJerome Forissier {
74*59cfa779SJerome Forissier 	vaddr_t base = chip_to_base(chip);
75*59cfa779SJerome Forissier 
76*59cfa779SJerome Forissier 	while (!sprd_uart_have_rx_data(chip))
771537d62eSAijun Sun 		;
78*59cfa779SJerome Forissier 
79*59cfa779SJerome Forissier 	return read32(base + UART_RXD) & 0xff;
801537d62eSAijun Sun }
811537d62eSAijun Sun 
82*59cfa779SJerome Forissier static const struct serial_ops sprd_uart_ops = {
83*59cfa779SJerome Forissier 	.flush = sprd_uart_flush,
84*59cfa779SJerome Forissier 	.getchar = sprd_uart_getchar,
85*59cfa779SJerome Forissier 	.have_rx_data = sprd_uart_have_rx_data,
86*59cfa779SJerome Forissier 	.putc = sprd_uart_putc,
87*59cfa779SJerome Forissier };
88*59cfa779SJerome Forissier 
89*59cfa779SJerome Forissier void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base)
901537d62eSAijun Sun {
91*59cfa779SJerome Forissier 	pd->base.pa = base;
92*59cfa779SJerome Forissier 	pd->chip.ops = &sprd_uart_ops;
931537d62eSAijun Sun }
94