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