xref: /openbmc/u-boot/drivers/serial/serial_xuartlite.c (revision d024236e5a31a2b4b82cbcc98b31b8170fc88d28)
1 /*
2  * (C) Copyright 2008 - 2015 Michal Simek <monstr@monstr.eu>
3  * Clean driver and add xilinx constant from header file
4  *
5  * (C) Copyright 2004 Atmark Techno, Inc.
6  * Yasushi SHOJI <yashi@atmark-techno.com>
7  *
8  * SPDX-License-Identifier:	GPL-2.0+
9  */
10 
11 #include <config.h>
12 #include <common.h>
13 #include <dm.h>
14 #include <asm/io.h>
15 #include <linux/compiler.h>
16 #include <serial.h>
17 
18 #define SR_TX_FIFO_FULL		BIT(3) /* transmit FIFO full */
19 #define SR_TX_FIFO_EMPTY	BIT(2) /* transmit FIFO empty */
20 #define SR_RX_FIFO_VALID_DATA	BIT(0) /* data in receive FIFO */
21 #define SR_RX_FIFO_FULL		BIT(1) /* receive FIFO full */
22 
23 #define ULITE_CONTROL_RST_TX	0x01
24 #define ULITE_CONTROL_RST_RX	0x02
25 
26 struct uartlite {
27 	unsigned int rx_fifo;
28 	unsigned int tx_fifo;
29 	unsigned int status;
30 	unsigned int control;
31 };
32 
33 struct uartlite_platdata {
34 	struct uartlite *regs;
35 };
36 
37 static int uartlite_serial_putc(struct udevice *dev, const char ch)
38 {
39 	struct uartlite_platdata *plat = dev_get_platdata(dev);
40 	struct uartlite *regs = plat->regs;
41 
42 	if (in_be32(&regs->status) & SR_TX_FIFO_FULL)
43 		return -EAGAIN;
44 
45 	out_be32(&regs->tx_fifo, ch & 0xff);
46 
47 	return 0;
48 }
49 
50 static int uartlite_serial_getc(struct udevice *dev)
51 {
52 	struct uartlite_platdata *plat = dev_get_platdata(dev);
53 	struct uartlite *regs = plat->regs;
54 
55 	if (!(in_be32(&regs->status) & SR_RX_FIFO_VALID_DATA))
56 		return -EAGAIN;
57 
58 	return in_be32(&regs->rx_fifo) & 0xff;
59 }
60 
61 static int uartlite_serial_pending(struct udevice *dev, bool input)
62 {
63 	struct uartlite_platdata *plat = dev_get_platdata(dev);
64 	struct uartlite *regs = plat->regs;
65 
66 	if (input)
67 		return in_be32(&regs->status) & SR_RX_FIFO_VALID_DATA;
68 
69 	return !(in_be32(&regs->status) & SR_TX_FIFO_EMPTY);
70 }
71 
72 static int uartlite_serial_probe(struct udevice *dev)
73 {
74 	struct uartlite_platdata *plat = dev_get_platdata(dev);
75 	struct uartlite *regs = plat->regs;
76 
77 	out_be32(&regs->control, 0);
78 	out_be32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
79 	in_be32(&regs->control);
80 
81 	return 0;
82 }
83 
84 static int uartlite_serial_ofdata_to_platdata(struct udevice *dev)
85 {
86 	struct uartlite_platdata *plat = dev_get_platdata(dev);
87 
88 	plat->regs = (struct uartlite *)devfdt_get_addr(dev);
89 
90 	return 0;
91 }
92 
93 static const struct dm_serial_ops uartlite_serial_ops = {
94 	.putc = uartlite_serial_putc,
95 	.pending = uartlite_serial_pending,
96 	.getc = uartlite_serial_getc,
97 };
98 
99 static const struct udevice_id uartlite_serial_ids[] = {
100 	{ .compatible = "xlnx,opb-uartlite-1.00.b", },
101 	{ .compatible = "xlnx,xps-uartlite-1.00.a" },
102 	{ }
103 };
104 
105 U_BOOT_DRIVER(serial_uartlite) = {
106 	.name	= "serial_uartlite",
107 	.id	= UCLASS_SERIAL,
108 	.of_match = uartlite_serial_ids,
109 	.ofdata_to_platdata = uartlite_serial_ofdata_to_platdata,
110 	.platdata_auto_alloc_size = sizeof(struct uartlite_platdata),
111 	.probe = uartlite_serial_probe,
112 	.ops	= &uartlite_serial_ops,
113 	.flags = DM_FLAG_PRE_RELOC,
114 };
115 
116 #ifdef CONFIG_DEBUG_UART_UARTLITE
117 
118 #include <debug_uart.h>
119 
120 static inline void _debug_uart_init(void)
121 {
122 	struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE;
123 
124 	out_be32(&regs->control, 0);
125 	out_be32(&regs->control, ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX);
126 	in_be32(&regs->control);
127 }
128 
129 static inline void _debug_uart_putc(int ch)
130 {
131 	struct uartlite *regs = (struct uartlite *)CONFIG_DEBUG_UART_BASE;
132 
133 	while (in_be32(&regs->status) & SR_TX_FIFO_FULL)
134 		;
135 
136 	out_be32(&regs->tx_fifo, ch & 0xff);
137 }
138 
139 DEBUG_UART_FUNCS
140 #endif
141