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