1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018 Anup Patel <anup@brainfault.org>
4  */
5 
6 #include <clk.h>
7 #include <common.h>
8 #include <debug_uart.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <fdtdec.h>
12 #include <watchdog.h>
13 #include <asm/io.h>
14 #include <linux/compiler.h>
15 #include <serial.h>
16 
17 DECLARE_GLOBAL_DATA_PTR;
18 
19 #define UART_TXFIFO_FULL	0x80000000
20 #define UART_RXFIFO_EMPTY	0x80000000
21 #define UART_RXFIFO_DATA	0x000000ff
22 #define UART_TXCTRL_TXEN	0x1
23 #define UART_RXCTRL_RXEN	0x1
24 
25 struct uart_sifive {
26 	u32 txfifo;
27 	u32 rxfifo;
28 	u32 txctrl;
29 	u32 rxctrl;
30 	u32 ie;
31 	u32 ip;
32 	u32 div;
33 };
34 
35 struct sifive_uart_platdata {
36 	unsigned int clock;
37 	int saved_input_char;
38 	struct uart_sifive *regs;
39 };
40 
41 /* Set up the baud rate in gd struct */
42 static void _sifive_serial_setbrg(struct uart_sifive *regs,
43 				  unsigned long clock, unsigned long baud)
44 {
45 	writel((u32)((clock / baud) - 1), &regs->div);
46 }
47 
48 static void _sifive_serial_init(struct uart_sifive *regs)
49 {
50 	writel(UART_TXCTRL_TXEN, &regs->txctrl);
51 	writel(UART_RXCTRL_RXEN, &regs->rxctrl);
52 	writel(0, &regs->ie);
53 }
54 
55 static int _sifive_serial_putc(struct uart_sifive *regs, const char c)
56 {
57 	if (readl(&regs->txfifo) & UART_TXFIFO_FULL)
58 		return -EAGAIN;
59 
60 	writel(c, &regs->txfifo);
61 
62 	return 0;
63 }
64 
65 static int _sifive_serial_getc(struct uart_sifive *regs)
66 {
67 	int ch = readl(&regs->rxfifo);
68 
69 	if (ch & UART_RXFIFO_EMPTY)
70 		return -EAGAIN;
71 	ch &= UART_RXFIFO_DATA;
72 
73 	return (!ch) ? -EAGAIN : ch;
74 }
75 
76 static int sifive_serial_setbrg(struct udevice *dev, int baudrate)
77 {
78 	int err;
79 	struct clk clk;
80 	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
81 
82 	err = clk_get_by_index(dev, 0, &clk);
83 	if (!err) {
84 		err = clk_get_rate(&clk);
85 		if (!IS_ERR_VALUE(err))
86 			platdata->clock = err;
87 	} else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
88 		debug("SiFive UART failed to get clock\n");
89 		return err;
90 	}
91 
92 	if (!platdata->clock)
93 		platdata->clock = dev_read_u32_default(dev, "clock-frequency", 0);
94 	if (!platdata->clock) {
95 		debug("SiFive UART clock not defined\n");
96 		return -EINVAL;
97 	}
98 
99 	_sifive_serial_setbrg(platdata->regs, platdata->clock, baudrate);
100 
101 	return 0;
102 }
103 
104 static int sifive_serial_probe(struct udevice *dev)
105 {
106 	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
107 
108 	/* No need to reinitialize the UART after relocation */
109 	if (gd->flags & GD_FLG_RELOC)
110 		return 0;
111 
112 	platdata->saved_input_char = 0;
113 	_sifive_serial_init(platdata->regs);
114 
115 	return 0;
116 }
117 
118 static int sifive_serial_getc(struct udevice *dev)
119 {
120 	int c;
121 	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
122 	struct uart_sifive *regs = platdata->regs;
123 
124 	if (platdata->saved_input_char > 0) {
125 		c = platdata->saved_input_char;
126 		platdata->saved_input_char = 0;
127 		return c;
128 	}
129 
130 	while ((c = _sifive_serial_getc(regs)) == -EAGAIN) ;
131 
132 	return c;
133 }
134 
135 static int sifive_serial_putc(struct udevice *dev, const char ch)
136 {
137 	int rc;
138 	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
139 
140 	while ((rc = _sifive_serial_putc(platdata->regs, ch)) == -EAGAIN) ;
141 
142 	return rc;
143 }
144 
145 static int sifive_serial_pending(struct udevice *dev, bool input)
146 {
147 	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
148 	struct uart_sifive *regs = platdata->regs;
149 
150 	if (input) {
151 		if (platdata->saved_input_char > 0)
152 			return 1;
153 		platdata->saved_input_char = _sifive_serial_getc(regs);
154 		return (platdata->saved_input_char > 0) ? 1 : 0;
155 	} else {
156 		return !!(readl(&regs->txfifo) & UART_TXFIFO_FULL);
157 	}
158 }
159 
160 static int sifive_serial_ofdata_to_platdata(struct udevice *dev)
161 {
162 	struct sifive_uart_platdata *platdata = dev_get_platdata(dev);
163 
164 	platdata->regs = (struct uart_sifive *)dev_read_addr(dev);
165 	if (IS_ERR(platdata->regs))
166 		return PTR_ERR(platdata->regs);
167 
168 	return 0;
169 }
170 
171 static const struct dm_serial_ops sifive_serial_ops = {
172 	.putc = sifive_serial_putc,
173 	.getc = sifive_serial_getc,
174 	.pending = sifive_serial_pending,
175 	.setbrg = sifive_serial_setbrg,
176 };
177 
178 static const struct udevice_id sifive_serial_ids[] = {
179 	{ .compatible = "sifive,uart0" },
180 	{ }
181 };
182 
183 U_BOOT_DRIVER(serial_sifive) = {
184 	.name	= "serial_sifive",
185 	.id	= UCLASS_SERIAL,
186 	.of_match = sifive_serial_ids,
187 	.ofdata_to_platdata = sifive_serial_ofdata_to_platdata,
188 	.platdata_auto_alloc_size = sizeof(struct sifive_uart_platdata),
189 	.probe = sifive_serial_probe,
190 	.ops	= &sifive_serial_ops,
191 };
192 
193 #ifdef CONFIG_DEBUG_UART_SIFIVE
194 static inline void _debug_uart_init(void)
195 {
196 	struct uart_sifive *regs =
197 			(struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
198 
199 	_sifive_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK,
200 			      CONFIG_BAUDRATE);
201 	_sifive_serial_init(regs);
202 }
203 
204 static inline void _debug_uart_putc(int ch)
205 {
206 	struct uart_sifive *regs =
207 			(struct uart_sifive *)CONFIG_DEBUG_UART_BASE;
208 
209 	while (_sifive_serial_putc(regs, ch) == -EAGAIN)
210 		WATCHDOG_RESET();
211 }
212 
213 DEBUG_UART_FUNCS
214 
215 #endif
216