xref: /freebsd/sys/riscv/sifive/sifive_uart.c (revision ec4deee4e4f2aef1b97d9424f25d04e91fd7dc10)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2019 Axiado Corporation
5  * All rights reserved.
6  *
7  * This software was developed in part by Kristof Provost under contract for
8  * Axiado Corporation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bus.h>
38 #include <sys/kernel.h>
39 #include <sys/lock.h>
40 #include <sys/module.h>
41 #include <sys/mutex.h>
42 #include <sys/rman.h>
43 
44 #include <machine/bus.h>
45 #include <machine/cpu.h>
46 
47 #include <dev/extres/clk/clk.h>
48 
49 #include <dev/ofw/ofw_bus.h>
50 #include <dev/ofw/ofw_bus_subr.h>
51 #include <dev/ofw/openfirm.h>
52 
53 #include <dev/uart/uart.h>
54 #include <dev/uart/uart_bus.h>
55 #include <dev/uart/uart_cpu.h>
56 #include <dev/uart/uart_cpu_fdt.h>
57 
58 #include "uart_if.h"
59 
60 #define	SFUART_TXDATA			0x00
61 #define		SFUART_TXDATA_FULL	(1 << 31)
62 #define	SFUART_RXDATA			0x04
63 #define		SFUART_RXDATA_EMPTY	(1 << 31)
64 #define	SFUART_TXCTRL			0x08
65 #define		SFUART_TXCTRL_ENABLE	0x01
66 #define		SFUART_TXCTRL_NSTOP	0x02
67 #define		SFUART_TXCTRL_TXCNT	0x70000
68 #define		SFUART_TXCTRL_TXCNT_SHIFT	16
69 #define	SFUART_RXCTRL			0x0c
70 #define		SFUART_RXCTRL_ENABLE	0x01
71 #define		SFUART_RXCTRL_RXCNT	0x70000
72 #define		SFUART_RXCTRL_RXCNT_SHIFT	16
73 #define	SFUART_IRQ_ENABLE		0x10
74 #define		SFUART_IRQ_ENABLE_TXWM	0x01
75 #define		SFUART_IRQ_ENABLE_RXWM	0x02
76 #define	SFUART_IRQ_PENDING		0x14
77 #define		SFUART_IRQ_PENDING_TXWM	0x01
78 #define		SFUART_IRQ_PENDING_RXQM	0x02
79 #define	SFUART_DIV			0x18
80 #define	SFUART_REGS_SIZE		0x1c
81 
82 #define	SFUART_RX_FIFO_DEPTH		8
83 #define	SFUART_TX_FIFO_DEPTH		8
84 
85 struct sfuart_softc {
86 	struct uart_softc	uart_softc;
87 	clk_t			clk;
88 };
89 
90 static int
91 sfuart_probe(struct uart_bas *bas)
92 {
93 
94 	bas->regiowidth = 4;
95 
96 	return (0);
97 }
98 
99 static void
100 sfuart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
101     int parity)
102 {
103 	uint32_t reg;
104 
105 	uart_setreg(bas, SFUART_IRQ_ENABLE, 0);
106 
107 	/* Enable RX and configure the watermark so that we get an interrupt
108 	 * when a single character arrives (if interrupts are enabled). */
109 	reg = SFUART_RXCTRL_ENABLE;
110 	reg |= (0 << SFUART_RXCTRL_RXCNT_SHIFT);
111 	uart_setreg(bas, SFUART_RXCTRL, reg);
112 
113 	/* Enable TX and configure the watermark so that we get an interrupt
114 	 * when there's room for one more character in the TX fifo (if
115 	 * interrupts are enabled). */
116 	reg = SFUART_TXCTRL_ENABLE;
117 	reg |= (1 << SFUART_TXCTRL_TXCNT_SHIFT);
118 	if (stopbits == 2)
119 		reg |= SFUART_TXCTRL_NSTOP;
120 	uart_setreg(bas, SFUART_TXCTRL, reg);
121 
122 	/* Don't touch DIV. Assume that's set correctly until we can
123 	 * reconfigure. */
124 }
125 
126 static void
127 sfuart_putc(struct uart_bas *bas, int c)
128 {
129 
130 	while ((uart_getreg(bas, SFUART_TXDATA) & SFUART_TXDATA_FULL)
131 	    != 0)
132 		cpu_spinwait();
133 
134 	uart_setreg(bas, SFUART_TXDATA, c);
135 }
136 
137 static int
138 sfuart_rxready(struct uart_bas *bas)
139 {
140 
141 	return ((uart_getreg(bas, SFUART_RXDATA) &
142 	    SFUART_RXDATA_EMPTY) == 0);
143 }
144 
145 static int
146 sfuart_getc(struct uart_bas *bas, struct mtx *hwmtx)
147 {
148 	int c;
149 
150 	uart_lock(hwmtx);
151 
152 	while (((c = uart_getreg(bas, SFUART_RXDATA)) &
153 	    SFUART_RXDATA_EMPTY) != 0) {
154 		uart_unlock(hwmtx);
155 		DELAY(4);
156 		uart_lock(hwmtx);
157 	}
158 
159 	uart_unlock(hwmtx);
160 
161 	return (c & 0xff);
162 }
163 
164 static int
165 sfuart_bus_probe(struct uart_softc *sc)
166 {
167 	int error;
168 
169 	error = sfuart_probe(&sc->sc_bas);
170 	if (error)
171 		return (error);
172 
173 	sc->sc_rxfifosz = SFUART_RX_FIFO_DEPTH;
174 	sc->sc_txfifosz = SFUART_TX_FIFO_DEPTH;
175 	sc->sc_hwiflow = 0;
176 	sc->sc_hwoflow = 0;
177 
178 	device_set_desc(sc->sc_dev, "SiFive UART");
179 
180 	return (0);
181 }
182 
183 static int
184 sfuart_bus_attach(struct uart_softc *sc)
185 {
186 	struct uart_bas *bas;
187 	struct sfuart_softc *sfsc;
188 	uint64_t freq;
189 	uint32_t reg;
190 	int error;
191 
192 	sfsc = (struct sfuart_softc *)sc;
193 	bas = &sc->sc_bas;
194 
195 	error = clk_get_by_ofw_index(sc->sc_dev, 0, 0, &sfsc->clk);
196 	if (error) {
197 		device_printf(sc->sc_dev, "couldn't allocate clock\n");
198 		return (ENXIO);
199 	}
200 
201 	error = clk_enable(sfsc->clk);
202 	if (error) {
203 		device_printf(sc->sc_dev, "couldn't enable clock\n");
204 		return (ENXIO);
205 	}
206 
207 	error = clk_get_freq(sfsc->clk, &freq);
208 	if (error || freq == 0) {
209 		clk_disable(sfsc->clk);
210 		device_printf(sc->sc_dev, "couldn't get clock frequency\n");
211 		return (ENXIO);
212 	}
213 
214 	bas->rclk = freq;
215 
216 	/* Enable RX/RX */
217 	reg = SFUART_RXCTRL_ENABLE;
218 	reg |= (0 << SFUART_RXCTRL_RXCNT_SHIFT);
219 	uart_setreg(bas, SFUART_RXCTRL, reg);
220 
221 	reg = SFUART_TXCTRL_ENABLE;
222 	reg |= (1 << SFUART_TXCTRL_TXCNT_SHIFT);
223 	uart_setreg(bas, SFUART_TXCTRL, reg);
224 
225 	/* Enable RX interrupt */
226 	uart_setreg(bas, SFUART_IRQ_ENABLE, SFUART_IRQ_ENABLE_RXWM);
227 
228 	return (0);
229 }
230 
231 static int
232 sfuart_bus_detach(struct uart_softc *sc)
233 {
234 	struct sfuart_softc *sfsc;
235 	struct uart_bas *bas;
236 
237 	sfsc = (struct sfuart_softc *)sc;
238 	bas = &sc->sc_bas;
239 
240 	/* Disable RX/TX */
241 	uart_setreg(bas, SFUART_RXCTRL, 0);
242 	uart_setreg(bas, SFUART_TXCTRL, 0);
243 
244 	/* Disable interrupts */
245 	uart_setreg(bas, SFUART_IRQ_ENABLE, 0);
246 
247 	clk_disable(sfsc->clk);
248 
249 	return (0);
250 }
251 
252 static int
253 sfuart_bus_flush(struct uart_softc *sc, int what)
254 {
255 	struct uart_bas *bas;
256 	uint32_t reg;
257 
258 	bas = &sc->sc_bas;
259 	uart_lock(sc->sc_hwmtx);
260 
261 	if (what & UART_FLUSH_TRANSMITTER) {
262 		do {
263 			reg = uart_getreg(bas, SFUART_TXDATA);
264 		} while ((reg & SFUART_TXDATA_FULL) != 0);
265 	}
266 
267 	if (what & UART_FLUSH_RECEIVER) {
268 		do {
269 			reg = uart_getreg(bas, SFUART_RXDATA);
270 		} while ((reg & SFUART_RXDATA_EMPTY) == 0);
271 	}
272 	uart_unlock(sc->sc_hwmtx);
273 
274 	return (0);
275 }
276 
277 #define	SIGCHG(c, i, s, d)						\
278 	do {								\
279 		if (c)							\
280 			i |= ((i) & (s)) ? (s) : (s) | (d);		\
281 		else		 					\
282 			i = ((i) & (s)) ? (i) & ~(s) | (d) : (i);	\
283 	} while (0)
284 
285 static int
286 sfuart_bus_getsig(struct uart_softc *sc)
287 {
288 	uint32_t new, old, sig;
289 
290 	do {
291 		old = sc->sc_hwsig;
292 		sig = old;
293 		SIGCHG(1, sig, SER_DSR, SER_DDSR);
294 		SIGCHG(1, sig, SER_DCD, SER_DDCD);
295 		SIGCHG(1, sig, SER_CTS, SER_DCTS);
296 		new = sig & ~SER_MASK_DELTA;
297 	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
298 
299 	return (sig);
300 }
301 
302 static int
303 sfuart_bus_setsig(struct uart_softc *sc, int sig)
304 {
305 	uint32_t new, old;
306 
307 	do {
308 		old = sc->sc_hwsig;
309 		new = old;
310 		if (sig & SER_DDTR) {
311 			SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR);
312 		}
313 		if (sig & SER_DRTS) {
314 			SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS);
315 		}
316 	 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
317 
318 	return (0);
319 }
320 
321 static int
322 sfuart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
323 {
324 	struct uart_bas *bas;
325 	uint32_t reg;
326 	int error;
327 
328 	bas = &sc->sc_bas;
329 
330 	uart_lock(sc->sc_hwmtx);
331 
332 	switch (request) {
333 	case UART_IOCTL_BAUD:
334 		reg = uart_getreg(bas, SFUART_DIV);
335 		if (reg == 0) {
336 			/* Possible if the divisor hasn't been set up yet. */
337 			error = ENXIO;
338 			break;
339 		}
340 		*(int*)data = bas->rclk / (reg + 1);
341 		error = 0;
342 		break;
343 	default:
344 		error = EINVAL;
345 		break;
346 	}
347 
348 	uart_unlock(sc->sc_hwmtx);
349 
350 	return (error);
351 }
352 
353 static int
354 sfuart_bus_ipend(struct uart_softc *sc)
355 {
356 	struct uart_bas *bas;
357 	int ipend;
358 	uint32_t reg, ie;
359 
360 	bas = &sc->sc_bas;
361 	uart_lock(sc->sc_hwmtx);
362 
363 	ipend = 0;
364 	reg = uart_getreg(bas, SFUART_IRQ_PENDING);
365 	ie = uart_getreg(bas, SFUART_IRQ_ENABLE);
366 
367 	if ((reg & SFUART_IRQ_PENDING_TXWM) != 0 &&
368 	    (ie & SFUART_IRQ_ENABLE_TXWM) != 0) {
369 		ipend |= SER_INT_TXIDLE;
370 
371 		/* Disable TX interrupt */
372 		ie &= ~(SFUART_IRQ_ENABLE_TXWM);
373 		uart_setreg(bas, SFUART_IRQ_ENABLE, ie);
374 	}
375 
376 	if ((reg & SFUART_IRQ_PENDING_RXQM) != 0)
377 		ipend |= SER_INT_RXREADY;
378 
379 	uart_unlock(sc->sc_hwmtx);
380 
381 	return (ipend);
382 }
383 
384 static int
385 sfuart_bus_param(struct uart_softc *sc, int baudrate, int databits,
386     int stopbits, int parity)
387 {
388 	struct uart_bas *bas;
389 	uint32_t reg;
390 
391 	bas = &sc->sc_bas;
392 
393 	if (databits != 8)
394 		return (EINVAL);
395 
396 	if (parity != UART_PARITY_NONE)
397 		return (EINVAL);
398 
399 	uart_lock(sc->sc_hwmtx);
400 
401 	reg = uart_getreg(bas, SFUART_TXCTRL);
402 	if (stopbits == 2) {
403 		reg |= SFUART_TXCTRL_NSTOP;
404 	} else if (stopbits == 1) {
405 		reg &= ~SFUART_TXCTRL_NSTOP;
406 	} else {
407 		uart_unlock(sc->sc_hwmtx);
408 		return (EINVAL);
409 	}
410 
411 	if (baudrate > 0 && bas->rclk != 0) {
412 		reg = (bas->rclk / baudrate) - 1;
413 		uart_setreg(bas, SFUART_DIV, reg);
414 	}
415 
416 	uart_unlock(sc->sc_hwmtx);
417 	return (0);
418 }
419 
420 static int
421 sfuart_bus_receive(struct uart_softc *sc)
422 {
423 	struct uart_bas *bas;
424 	uint32_t reg;
425 
426 	bas = &sc->sc_bas;
427 	uart_lock(sc->sc_hwmtx);
428 
429 	reg = uart_getreg(bas, SFUART_RXDATA);
430 	while ((reg & SFUART_RXDATA_EMPTY) == 0) {
431 		if (uart_rx_full(sc)) {
432 			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
433 			break;
434 		}
435 
436 		uart_rx_put(sc, reg & 0xff);
437 
438 		reg = uart_getreg(bas, SFUART_RXDATA);
439 	}
440 
441 	uart_unlock(sc->sc_hwmtx);
442 
443 	return (0);
444 }
445 
446 static int
447 sfuart_bus_transmit(struct uart_softc *sc)
448 {
449 	struct uart_bas *bas;
450 	int i;
451 	uint32_t reg;
452 
453 	bas = &sc->sc_bas;
454 	uart_lock(sc->sc_hwmtx);
455 
456 	reg = uart_getreg(bas, SFUART_IRQ_ENABLE);
457 	reg |= SFUART_IRQ_ENABLE_TXWM;
458 	uart_setreg(bas, SFUART_IRQ_ENABLE, reg);
459 
460 	for (i = 0; i < sc->sc_txdatasz; i++)
461 		sfuart_putc(bas, sc->sc_txbuf[i]);
462 
463 	sc->sc_txbusy = 1;
464 
465 	uart_unlock(sc->sc_hwmtx);
466 
467 	return (0);
468 }
469 
470 static void
471 sfuart_bus_grab(struct uart_softc *sc)
472 {
473 	struct uart_bas *bas;
474 	uint32_t reg;
475 
476 	bas = &sc->sc_bas;
477 	uart_lock(sc->sc_hwmtx);
478 
479 	reg = uart_getreg(bas, SFUART_IRQ_ENABLE);
480 	reg &= ~(SFUART_IRQ_ENABLE_TXWM | SFUART_IRQ_PENDING_RXQM);
481 	uart_setreg(bas, SFUART_IRQ_ENABLE, reg);
482 
483 	uart_unlock(sc->sc_hwmtx);
484 }
485 
486 static void
487 sfuart_bus_ungrab(struct uart_softc *sc)
488 {
489 	struct uart_bas *bas;
490 	uint32_t reg;
491 
492 	bas = &sc->sc_bas;
493 	uart_lock(sc->sc_hwmtx);
494 
495 	reg = uart_getreg(bas, SFUART_IRQ_ENABLE);
496 	reg |= SFUART_IRQ_ENABLE_TXWM | SFUART_IRQ_PENDING_RXQM;
497 	uart_setreg(bas, SFUART_IRQ_ENABLE, reg);
498 
499 	uart_unlock(sc->sc_hwmtx);
500 }
501 
502 static kobj_method_t sfuart_methods[] = {
503 	KOBJMETHOD(uart_probe,		sfuart_bus_probe),
504 	KOBJMETHOD(uart_attach,		sfuart_bus_attach),
505 	KOBJMETHOD(uart_detach,		sfuart_bus_detach),
506 	KOBJMETHOD(uart_flush,		sfuart_bus_flush),
507 	KOBJMETHOD(uart_getsig,		sfuart_bus_getsig),
508 	KOBJMETHOD(uart_setsig,		sfuart_bus_setsig),
509 	KOBJMETHOD(uart_ioctl,		sfuart_bus_ioctl),
510 	KOBJMETHOD(uart_ipend,		sfuart_bus_ipend),
511 	KOBJMETHOD(uart_param,		sfuart_bus_param),
512 	KOBJMETHOD(uart_receive,	sfuart_bus_receive),
513 	KOBJMETHOD(uart_transmit,	sfuart_bus_transmit),
514 	KOBJMETHOD(uart_grab,		sfuart_bus_grab),
515 	KOBJMETHOD(uart_ungrab,		sfuart_bus_ungrab),
516 	KOBJMETHOD_END
517 };
518 
519 static struct uart_ops sfuart_ops = {
520 	.probe = sfuart_probe,
521 	.init = sfuart_init,
522 	.term = NULL,
523 	.putc = sfuart_putc,
524 	.rxready = sfuart_rxready,
525 	.getc = sfuart_getc,
526 };
527 
528 struct uart_class sfuart_class = {
529 	"sifiveuart",
530 	sfuart_methods,
531 	sizeof(struct sfuart_softc),
532 	.uc_ops = &sfuart_ops,
533 	.uc_range = SFUART_REGS_SIZE,
534 	.uc_rclk = 0,
535 	.uc_rshift = 0
536 };
537 
538 static struct ofw_compat_data compat_data[] = {
539 	{ "sifive,uart0",	(uintptr_t)&sfuart_class },
540 	{ NULL,			(uintptr_t)NULL }
541 };
542 
543 UART_FDT_CLASS_AND_DEVICE(compat_data);
544