1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2016, Spreadtrum Communications Inc.
4  * Copyright (c) 2017, Linaro Limited
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include <drivers/sprd_uart.h>
30 #include <io.h>
31 #include <keep.h>
32 #include <util.h>
33 
34 /* Register definitions */
35 #define UART_TXD		0x0000
36 #define UART_RXD		0x0004
37 #define UART_STS1		0x000C /* data number in TX and RX fifo */
38 #define UART_SIZE		0x0010
39 
40 /* Register Bit Fields*/
41 #define STS1_RXF_CNT_MASK	0x00ff  /* Rx FIFO data counter mask */
42 #define STS1_TXF_CNT_MASK	0xff00 /* Tx FIFO data counter mask */
43 
chip_to_base(struct serial_chip * chip)44 static vaddr_t chip_to_base(struct serial_chip *chip)
45 {
46 	struct sprd_uart_data *pd =
47 		container_of(chip, struct sprd_uart_data, chip);
48 
49 	return io_pa_or_va(&pd->base, UART_SIZE);
50 }
51 
sprd_uart_flush(struct serial_chip * chip)52 static void sprd_uart_flush(struct serial_chip *chip)
53 {
54 	vaddr_t base = chip_to_base(chip);
55 
56 	while (io_read32(base + UART_STS1) & STS1_TXF_CNT_MASK)
57 		;
58 }
59 
sprd_uart_have_rx_data(struct serial_chip * chip)60 static bool sprd_uart_have_rx_data(struct serial_chip *chip)
61 {
62 	vaddr_t base = chip_to_base(chip);
63 
64 	return !!(io_read32(base + UART_STS1) & STS1_RXF_CNT_MASK);
65 }
66 
sprd_uart_putc(struct serial_chip * chip,int ch)67 static void sprd_uart_putc(struct serial_chip *chip, int ch)
68 {
69 	vaddr_t base = chip_to_base(chip);
70 
71 	sprd_uart_flush(chip);
72 	io_write32(base + UART_TXD, ch);
73 }
74 
sprd_uart_getchar(struct serial_chip * chip)75 static int sprd_uart_getchar(struct serial_chip *chip)
76 {
77 	vaddr_t base = chip_to_base(chip);
78 
79 	while (!sprd_uart_have_rx_data(chip))
80 		;
81 
82 	return io_read32(base + UART_RXD) & 0xff;
83 }
84 
85 static const struct serial_ops sprd_uart_ops = {
86 	.flush = sprd_uart_flush,
87 	.getchar = sprd_uart_getchar,
88 	.have_rx_data = sprd_uart_have_rx_data,
89 	.putc = sprd_uart_putc,
90 };
91 DECLARE_KEEP_PAGER(sprd_uart_ops);
92 
sprd_uart_init(struct sprd_uart_data * pd,paddr_t base)93 void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base)
94 {
95 	pd->base.pa = base;
96 	pd->chip.ops = &sprd_uart_ops;
97 }
98