uart_dev_cdnc.c revision 283327
1233294Sstas/*-
2233294Sstas * Copyright (c) 2005 M. Warner Losh
3233294Sstas * Copyright (c) 2005 Olivier Houchard
472445Sassar * Copyright (c) 2012 Thomas Skibo
5233294Sstas * All rights reserved.
6233294Sstas *
7233294Sstas * Redistribution and use in source and binary forms, with or without
8120945Snectar * modification, are permitted provided that the following conditions
9233294Sstas * are met:
10233294Sstas *
11120945Snectar * 1. Redistributions of source code must retain the above copyright
12233294Sstas *    notice, this list of conditions and the following disclaimer.
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15120945Snectar *    documentation and/or other materials provided with the distribution.
16233294Sstas *
17233294Sstas * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19120945Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27233294Sstas * SUCH DAMAGE.
28233294Sstas */
29233294Sstas
30233294Sstas/* A driver for the Cadence AMBA UART as used by the Xilinx Zynq-7000.
31120945Snectar *
32233294Sstas * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
33233294Sstas * (v1.4) November 16, 2012.  Xilinx doc UG585.  UART is covered in Ch. 19
34102644Snectar * and register definitions are in appendix B.33.
3572445Sassar */
3672445Sassar
3772445Sassar
3872445Sassar#include <sys/cdefs.h>
3976371Sassar__FBSDID("$FreeBSD: stable/10/sys/arm/xilinx/uart_dev_cdnc.c 283327 2015-05-23 20:54:25Z ian $");
4072445Sassar
4172445Sassar#include "opt_global.h"
42233294Sstas
43233294Sstas#include <sys/param.h>
44233294Sstas#include <sys/systm.h>
4572445Sassar#include <sys/bus.h>
46233294Sstas#include <sys/conf.h>
4772445Sassar#include <sys/cons.h>
48233294Sstas#include <sys/tty.h>
4972445Sassar#include <machine/bus.h>
5072445Sassar
5172445Sassar#include <dev/uart/uart.h>
5272445Sassar#include <dev/uart/uart_cpu.h>
5372445Sassar#include <dev/uart/uart_cpu_fdt.h>
5472445Sassar#include <dev/uart/uart_bus.h>
5572445Sassar
56#include "uart_if.h"
57
58#define	UART_FIFO_SIZE	64
59
60#define	RD4(bas, reg)		\
61	bus_space_read_4((bas)->bst, (bas)->bsh, uart_regofs((bas), (reg)))
62#define	WR4(bas, reg, value)	\
63	bus_space_write_4((bas)->bst, (bas)->bsh, uart_regofs((bas), (reg)), \
64			  (value))
65
66/* Register definitions for Cadence UART Controller.
67 */
68#define CDNC_UART_CTRL_REG	0x00		/* Control Register. */
69#define CDNC_UART_CTRL_REG_STOPBRK	(1<<8)
70#define CDNC_UART_CTRL_REG_STARTBRK	(1<<7)
71#define CDNC_UART_CTRL_REG_TORST	(1<<6)
72#define CDNC_UART_CTRL_REG_TX_DIS	(1<<5)
73#define CDNC_UART_CTRL_REG_TX_EN	(1<<4)
74#define CDNC_UART_CTRL_REG_RX_DIS	(1<<3)
75#define CDNC_UART_CTRL_REG_RX_EN	(1<<2)
76#define CDNC_UART_CTRL_REG_TXRST	(1<<1)
77#define CDNC_UART_CTRL_REG_RXRST	(1<<0)
78
79#define CDNC_UART_MODE_REG	0x04		/* Mode Register. */
80#define CDNC_UART_MODE_REG_CHMOD_R_LOOP	(3<<8)	/* [9:8] - channel mode */
81#define CDNC_UART_MODE_REG_CHMOD_L_LOOP	(2<<8)
82#define CDNC_UART_MODE_REG_CHMOD_AUTECHO (1<<8)
83#define CDNC_UART_MODE_REG_STOP2	(2<<6)	/* [7:6] - stop bits */
84#define CDNC_UART_MODE_REG_PAR_NONE	(4<<3)	/* [5:3] - parity type */
85#define CDNC_UART_MODE_REG_PAR_MARK	(3<<3)
86#define CDNC_UART_MODE_REG_PAR_SPACE	(2<<3)
87#define CDNC_UART_MODE_REG_PAR_ODD	(1<<3)
88#define CDNC_UART_MODE_REG_PAR_EVEN	(0<<3)
89#define CDNC_UART_MODE_REG_6BIT		(3<<1)	/* [2:1] - character len */
90#define CDNC_UART_MODE_REG_7BIT		(2<<1)
91#define CDNC_UART_MODE_REG_8BIT		(0<<1)
92#define CDNC_UART_MODE_REG_CLKSEL	(1<<0)
93
94#define CDNC_UART_IEN_REG	0x08		/* Interrupt registers. */
95#define CDNC_UART_IDIS_REG	0x0C
96#define CDNC_UART_IMASK_REG	0x10
97#define CDNC_UART_ISTAT_REG	0x14
98#define CDNC_UART_INT_TXOVR		(1<<12)
99#define CDNC_UART_INT_TXNRLYFUL		(1<<11)	/* tx "nearly" full */
100#define CDNC_UART_INT_TXTRIG		(1<<10)
101#define CDNC_UART_INT_DMSI		(1<<9)	/* delta modem status */
102#define CDNC_UART_INT_RXTMOUT		(1<<8)
103#define CDNC_UART_INT_PARITY		(1<<7)
104#define CDNC_UART_INT_FRAMING		(1<<6)
105#define CDNC_UART_INT_RXOVR		(1<<5)
106#define CDNC_UART_INT_TXFULL		(1<<4)
107#define CDNC_UART_INT_TXEMPTY		(1<<3)
108#define CDNC_UART_INT_RXFULL		(1<<2)
109#define CDNC_UART_INT_RXEMPTY		(1<<1)
110#define CDNC_UART_INT_RXTRIG		(1<<0)
111#define CDNC_UART_INT_ALL		0x1FFF
112
113#define CDNC_UART_BAUDGEN_REG	0x18
114#define CDNC_UART_RX_TIMEO_REG	0x1C
115#define CDNC_UART_RX_WATER_REG	0x20
116
117#define CDNC_UART_MODEM_CTRL_REG 0x24
118#define CDNC_UART_MODEM_CTRL_REG_FCM	(1<<5)	/* automatic flow control */
119#define CDNC_UART_MODEM_CTRL_REG_RTS	(1<<1)
120#define CDNC_UART_MODEM_CTRL_REG_DTR	(1<<0)
121
122#define CDNC_UART_MODEM_STAT_REG 0x28
123#define CDNC_UART_MODEM_STAT_REG_FCMS	(1<<8)	/* flow control mode (rw) */
124#define CDNC_UART_MODEM_STAT_REG_DCD	(1<<7)
125#define CDNC_UART_MODEM_STAT_REG_RI	(1<<6)
126#define CDNC_UART_MODEM_STAT_REG_DSR	(1<<5)
127#define CDNC_UART_MODEM_STAT_REG_CTS	(1<<4)
128#define CDNC_UART_MODEM_STAT_REG_DDCD	(1<<3)	/* change in DCD (w1tc) */
129#define CDNC_UART_MODEM_STAT_REG_TERI	(1<<2)	/* trail edge ring (w1tc) */
130#define CDNC_UART_MODEM_STAT_REG_DDSR	(1<<1)	/* change in DSR (w1tc) */
131#define CDNC_UART_MODEM_STAT_REG_DCTS	(1<<0)	/* change in CTS (w1tc) */
132
133#define CDNC_UART_CHAN_STAT_REG	0x2C		/* Channel status register. */
134#define CDNC_UART_CHAN_STAT_REG_TXNRLYFUL (1<<14) /* tx "nearly" full */
135#define CDNC_UART_CHAN_STAT_REG_TXTRIG	(1<<13)
136#define CDNC_UART_CHAN_STAT_REG_FDELT	(1<<12)
137#define CDNC_UART_CHAN_STAT_REG_TXACTIVE (1<<11)
138#define CDNC_UART_CHAN_STAT_REG_RXACTIVE (1<<10)
139#define CDNC_UART_CHAN_STAT_REG_TXFULL	(1<<4)
140#define CDNC_UART_CHAN_STAT_REG_TXEMPTY	(1<<3)
141#define CDNC_UART_CHAN_STAT_REG_RXEMPTY	(1<<1)
142#define CDNC_UART_CHAN_STAT_REG_RXTRIG	(1<<0)
143
144#define CDNC_UART_FIFO		0x30		/* Data FIFO (tx and rx) */
145#define CDNC_UART_BAUDDIV_REG	0x34
146#define CDNC_UART_FLOWDEL_REG	0x38
147#define CDNC_UART_TX_WATER_REG	0x44
148
149
150/*
151 * Low-level UART interface.
152 */
153static int cdnc_uart_probe(struct uart_bas *bas);
154static void cdnc_uart_init(struct uart_bas *bas, int, int, int, int);
155static void cdnc_uart_term(struct uart_bas *bas);
156static void cdnc_uart_putc(struct uart_bas *bas, int);
157static int cdnc_uart_rxready(struct uart_bas *bas);
158static int cdnc_uart_getc(struct uart_bas *bas, struct mtx *mtx);
159
160extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
161
162static struct uart_ops cdnc_uart_ops = {
163	.probe = cdnc_uart_probe,
164	.init = cdnc_uart_init,
165	.term = cdnc_uart_term,
166	.putc = cdnc_uart_putc,
167	.rxready = cdnc_uart_rxready,
168	.getc = cdnc_uart_getc,
169};
170
171#define	SIGCHG(c, i, s, d)				\
172	if (c) {					\
173		i |= (i & s) ? s : s | d;		\
174	} else {					\
175		i = (i & s) ? (i & ~s) | d : i;		\
176	}
177
178static int
179cdnc_uart_probe(struct uart_bas *bas)
180{
181
182	return (0);
183}
184
185static int
186cdnc_uart_set_baud(struct uart_bas *bas, int baudrate)
187{
188	uint32_t baudgen, bauddiv;
189	uint32_t best_bauddiv, best_baudgen, best_error;
190	uint32_t baud_out, err;
191
192	best_bauddiv = 0;
193	best_baudgen = 0;
194	best_error = ~0;
195
196	/* Try all possible bauddiv values and pick best match. */
197	for (bauddiv = 4; bauddiv <= 255; bauddiv++) {
198		baudgen = (bas->rclk + (baudrate * (bauddiv + 1)) / 2) /
199			(baudrate * (bauddiv + 1));
200		if (baudgen < 1 || baudgen > 0xffff)
201			continue;
202
203		baud_out = bas->rclk / (baudgen * (bauddiv + 1));
204		err = baud_out > baudrate ?
205			baud_out - baudrate : baudrate - baud_out;
206
207		if (err < best_error) {
208			best_error = err;
209			best_bauddiv = bauddiv;
210			best_baudgen = baudgen;
211		}
212	}
213
214	if (best_bauddiv > 0) {
215		WR4(bas, CDNC_UART_BAUDDIV_REG, best_bauddiv);
216		WR4(bas, CDNC_UART_BAUDGEN_REG, best_baudgen);
217		return (0);
218	} else
219		return (-1); /* out of range */
220}
221
222static int
223cdnc_uart_set_params(struct uart_bas *bas, int baudrate, int databits,
224		      int stopbits, int parity)
225{
226	uint32_t mode_reg_value = 0;
227
228	switch (databits) {
229	case 6:
230		mode_reg_value |= CDNC_UART_MODE_REG_6BIT;
231		break;
232	case 7:
233		mode_reg_value |= CDNC_UART_MODE_REG_7BIT;
234		break;
235	case 8:
236	default:
237		mode_reg_value |= CDNC_UART_MODE_REG_8BIT;
238		break;
239	}
240
241	if (stopbits == 2)
242		mode_reg_value |= CDNC_UART_MODE_REG_STOP2;
243
244	switch (parity) {
245	case UART_PARITY_MARK:
246		mode_reg_value |= CDNC_UART_MODE_REG_PAR_MARK;
247		break;
248	case UART_PARITY_SPACE:
249		mode_reg_value |= CDNC_UART_MODE_REG_PAR_SPACE;
250		break;
251	case UART_PARITY_ODD:
252		mode_reg_value |= CDNC_UART_MODE_REG_PAR_ODD;
253		break;
254	case UART_PARITY_EVEN:
255		mode_reg_value |= CDNC_UART_MODE_REG_PAR_EVEN;
256		break;
257	case UART_PARITY_NONE:
258	default:
259		mode_reg_value |= CDNC_UART_MODE_REG_PAR_NONE;
260		break;
261	}
262
263	WR4(bas, CDNC_UART_MODE_REG, mode_reg_value);
264
265	if (baudrate > 0 && cdnc_uart_set_baud(bas, baudrate) < 0)
266		return (EINVAL);
267
268	return(0);
269}
270
271static void
272cdnc_uart_hw_init(struct uart_bas *bas)
273{
274
275	/* Reset RX and TX. */
276	WR4(bas, CDNC_UART_CTRL_REG,
277	    CDNC_UART_CTRL_REG_RXRST | CDNC_UART_CTRL_REG_TXRST);
278
279	/* Interrupts all off. */
280	WR4(bas, CDNC_UART_IDIS_REG, CDNC_UART_INT_ALL);
281	WR4(bas, CDNC_UART_ISTAT_REG, CDNC_UART_INT_ALL);
282
283	/* Clear delta bits. */
284	WR4(bas, CDNC_UART_MODEM_STAT_REG,
285	    CDNC_UART_MODEM_STAT_REG_DDCD | CDNC_UART_MODEM_STAT_REG_TERI |
286	    CDNC_UART_MODEM_STAT_REG_DDSR | CDNC_UART_MODEM_STAT_REG_DCTS);
287
288	/* RX FIFO water level, stale timeout */
289	WR4(bas, CDNC_UART_RX_WATER_REG, UART_FIFO_SIZE/2);
290	WR4(bas, CDNC_UART_RX_TIMEO_REG, 10);
291
292	/* TX FIFO water level (not used.) */
293	WR4(bas, CDNC_UART_TX_WATER_REG, UART_FIFO_SIZE/2);
294
295	/* Bring RX and TX online. */
296	WR4(bas, CDNC_UART_CTRL_REG,
297	    CDNC_UART_CTRL_REG_RX_EN | CDNC_UART_CTRL_REG_TX_EN |
298	    CDNC_UART_CTRL_REG_TORST | CDNC_UART_CTRL_REG_STOPBRK);
299
300	/* Set DTR and RTS. */
301	WR4(bas, CDNC_UART_MODEM_CTRL_REG, CDNC_UART_MODEM_CTRL_REG_DTR |
302	    CDNC_UART_MODEM_CTRL_REG_RTS);
303}
304
305/*
306 * Initialize this device for use as a console.
307 */
308static void
309cdnc_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
310	      int parity)
311{
312
313	/* Initialize hardware. */
314	cdnc_uart_hw_init(bas);
315
316	/* Set baudrate, parameters. */
317	(void)cdnc_uart_set_params(bas, baudrate, databits, stopbits, parity);
318}
319
320/*
321 * Free resources now that we're no longer the console.  This appears to
322 * be never called, and I'm unsure quite what to do if I am called.
323 */
324static void
325cdnc_uart_term(struct uart_bas *bas)
326{
327
328	/* XXX */
329}
330
331/*
332 * Put a character of console output (so we do it here polling rather than
333 * interrutp driven).
334 */
335static void
336cdnc_uart_putc(struct uart_bas *bas, int c)
337{
338
339	/* Wait for room. */
340	while ((RD4(bas,CDNC_UART_CHAN_STAT_REG) &
341		CDNC_UART_CHAN_STAT_REG_TXFULL) != 0)
342		;
343
344	WR4(bas, CDNC_UART_FIFO, c);
345
346	while ((RD4(bas,CDNC_UART_CHAN_STAT_REG) &
347		CDNC_UART_CHAN_STAT_REG_TXEMPTY) == 0)
348		;
349}
350
351/*
352 * Check for a character available.
353 */
354static int
355cdnc_uart_rxready(struct uart_bas *bas)
356{
357
358	return ((RD4(bas, CDNC_UART_CHAN_STAT_REG) &
359		 CDNC_UART_CHAN_STAT_REG_RXEMPTY) == 0);
360}
361
362/*
363 * Block waiting for a character.
364 */
365static int
366cdnc_uart_getc(struct uart_bas *bas, struct mtx *mtx)
367{
368	int c;
369
370	uart_lock(mtx);
371
372	while ((RD4(bas, CDNC_UART_CHAN_STAT_REG) &
373		CDNC_UART_CHAN_STAT_REG_RXEMPTY) != 0) {
374		uart_unlock(mtx);
375		DELAY(4);
376		uart_lock(mtx);
377	}
378
379	c = RD4(bas, CDNC_UART_FIFO);
380
381	uart_unlock(mtx);
382
383	c &= 0xff;
384	return (c);
385}
386
387/*****************************************************************************/
388/*
389 * High-level UART interface.
390 */
391
392static int cdnc_uart_bus_probe(struct uart_softc *sc);
393static int cdnc_uart_bus_attach(struct uart_softc *sc);
394static int cdnc_uart_bus_flush(struct uart_softc *, int);
395static int cdnc_uart_bus_getsig(struct uart_softc *);
396static int cdnc_uart_bus_ioctl(struct uart_softc *, int, intptr_t);
397static int cdnc_uart_bus_ipend(struct uart_softc *);
398static int cdnc_uart_bus_param(struct uart_softc *, int, int, int, int);
399static int cdnc_uart_bus_receive(struct uart_softc *);
400static int cdnc_uart_bus_setsig(struct uart_softc *, int);
401static int cdnc_uart_bus_transmit(struct uart_softc *);
402static void cdnc_uart_bus_grab(struct uart_softc *);
403static void cdnc_uart_bus_ungrab(struct uart_softc *);
404
405static kobj_method_t cdnc_uart_bus_methods[] = {
406	KOBJMETHOD(uart_probe,		cdnc_uart_bus_probe),
407	KOBJMETHOD(uart_attach, 	cdnc_uart_bus_attach),
408	KOBJMETHOD(uart_flush,		cdnc_uart_bus_flush),
409	KOBJMETHOD(uart_getsig,		cdnc_uart_bus_getsig),
410	KOBJMETHOD(uart_ioctl,		cdnc_uart_bus_ioctl),
411	KOBJMETHOD(uart_ipend,		cdnc_uart_bus_ipend),
412	KOBJMETHOD(uart_param,		cdnc_uart_bus_param),
413	KOBJMETHOD(uart_receive,	cdnc_uart_bus_receive),
414	KOBJMETHOD(uart_setsig,		cdnc_uart_bus_setsig),
415	KOBJMETHOD(uart_transmit,	cdnc_uart_bus_transmit),
416	KOBJMETHOD(uart_grab,		cdnc_uart_bus_grab),
417	KOBJMETHOD(uart_ungrab,		cdnc_uart_bus_ungrab),
418
419	KOBJMETHOD_END
420};
421
422int
423cdnc_uart_bus_probe(struct uart_softc *sc)
424{
425
426	sc->sc_txfifosz = UART_FIFO_SIZE;
427	sc->sc_rxfifosz = UART_FIFO_SIZE;
428	sc->sc_hwiflow = 0;
429	sc->sc_hwoflow = 0;
430
431	device_set_desc(sc->sc_dev, "Cadence UART");
432
433	return (0);
434}
435
436static int
437cdnc_uart_bus_attach(struct uart_softc *sc)
438{
439	struct uart_bas *bas = &sc->sc_bas;
440	struct uart_devinfo *di;
441
442	if (sc->sc_sysdev != NULL) {
443		di = sc->sc_sysdev;
444		(void)cdnc_uart_set_params(bas, di->baudrate, di->databits,
445					   di->stopbits, di->parity);
446	} else
447		cdnc_uart_hw_init(bas);
448
449	(void)cdnc_uart_bus_getsig(sc);
450
451	/* Enable interrupts. */
452	WR4(bas, CDNC_UART_IEN_REG,
453	    CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT |
454	    CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR |
455	    CDNC_UART_INT_DMSI);
456
457	return (0);
458}
459
460static int
461cdnc_uart_bus_transmit(struct uart_softc *sc)
462{
463	int i;
464	struct uart_bas *bas = &sc->sc_bas;
465
466	uart_lock(sc->sc_hwmtx);
467
468	/* Clear sticky TXEMPTY status bit. */
469	WR4(bas, CDNC_UART_ISTAT_REG, CDNC_UART_INT_TXEMPTY);
470
471	for (i = 0; i < sc->sc_txdatasz; i++)
472		WR4(bas, CDNC_UART_FIFO, sc->sc_txbuf[i]);
473
474	/* Enable TX empty interrupt. */
475	WR4(bas, CDNC_UART_IEN_REG, CDNC_UART_INT_TXEMPTY);
476	sc->sc_txbusy = 1;
477
478	uart_unlock(sc->sc_hwmtx);
479
480	return (0);
481}
482
483static int
484cdnc_uart_bus_setsig(struct uart_softc *sc, int sig)
485{
486	struct uart_bas *bas = &sc->sc_bas;
487	uint32_t new, old, modem_ctrl;
488
489	do {
490		old = sc->sc_hwsig;
491		new = old;
492		if (sig & SER_DDTR) {
493			SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR);
494		}
495		if (sig & SER_DRTS) {
496			SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS);
497		}
498	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
499	uart_lock(sc->sc_hwmtx);
500	modem_ctrl = RD4(bas, CDNC_UART_MODEM_CTRL_REG) &
501		~(CDNC_UART_MODEM_CTRL_REG_DTR | CDNC_UART_MODEM_CTRL_REG_RTS);
502	if ((new & SER_DTR) != 0)
503		modem_ctrl |= CDNC_UART_MODEM_CTRL_REG_DTR;
504	if ((new & SER_RTS) != 0)
505		modem_ctrl |= CDNC_UART_MODEM_CTRL_REG_RTS;
506	WR4(bas, CDNC_UART_MODEM_CTRL_REG, modem_ctrl);
507
508	uart_unlock(sc->sc_hwmtx);
509	return (0);
510}
511
512static int
513cdnc_uart_bus_receive(struct uart_softc *sc)
514{
515	struct uart_bas *bas = &sc->sc_bas;
516	uint32_t status;
517	int c, c_status = 0;
518
519	uart_lock(sc->sc_hwmtx);
520
521	/* Check for parity or framing errors and clear the status bits. */
522	status = RD4(bas, CDNC_UART_ISTAT_REG);
523	if ((status & (CDNC_UART_INT_FRAMING | CDNC_UART_INT_PARITY)) != 0) {
524		WR4(bas, CDNC_UART_ISTAT_REG,
525		    status & (CDNC_UART_INT_FRAMING | CDNC_UART_INT_PARITY));
526		if ((status & CDNC_UART_INT_PARITY) != 0)
527			c_status |= UART_STAT_PARERR;
528		if ((status & CDNC_UART_INT_FRAMING) != 0)
529			c_status |= UART_STAT_FRAMERR;
530	}
531
532	while ((RD4(bas, CDNC_UART_CHAN_STAT_REG) &
533		CDNC_UART_CHAN_STAT_REG_RXEMPTY) == 0) {
534		c = RD4(bas, CDNC_UART_FIFO) & 0xff;
535#ifdef KDB
536		/* Detect break and drop into debugger. */
537		if (c == 0 && (c_status & UART_STAT_FRAMERR) != 0 &&
538		    sc->sc_sysdev != NULL &&
539		    sc->sc_sysdev->type == UART_DEV_CONSOLE) {
540			kdb_break();
541			WR4(bas, CDNC_UART_ISTAT_REG, CDNC_UART_INT_FRAMING);
542		}
543#endif
544		uart_rx_put(sc, c | c_status);
545	}
546
547	uart_unlock(sc->sc_hwmtx);
548
549	return (0);
550}
551
552static int
553cdnc_uart_bus_param(struct uart_softc *sc, int baudrate, int databits,
554		   int stopbits, int parity)
555{
556
557	return (cdnc_uart_set_params(&sc->sc_bas, baudrate,
558				    databits, stopbits, parity));
559}
560
561static int
562cdnc_uart_bus_ipend(struct uart_softc *sc)
563{
564	int ipend = 0;
565	struct uart_bas *bas = &sc->sc_bas;
566	uint32_t istatus;
567
568	uart_lock(sc->sc_hwmtx);
569
570	istatus = RD4(bas, CDNC_UART_ISTAT_REG);
571
572	/* Clear interrupt bits. */
573	WR4(bas, CDNC_UART_ISTAT_REG, istatus &
574	    (CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT |
575	     CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR |
576	     CDNC_UART_INT_TXEMPTY | CDNC_UART_INT_DMSI));
577
578	/* Receive data. */
579	if ((istatus & (CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT)) != 0)
580		ipend |= SER_INT_RXREADY;
581
582	/* Transmit fifo empty. */
583	if (sc->sc_txbusy && (istatus & CDNC_UART_INT_TXEMPTY) != 0) {
584		/* disable txempty interrupt. */
585		WR4(bas, CDNC_UART_IDIS_REG, CDNC_UART_INT_TXEMPTY);
586		ipend |= SER_INT_TXIDLE;
587	}
588
589	/* TX Overflow. */
590	if ((istatus & CDNC_UART_INT_TXOVR) != 0)
591		ipend |= SER_INT_OVERRUN;
592
593	/* RX Overflow. */
594	if ((istatus & CDNC_UART_INT_RXOVR) != 0)
595		ipend |= SER_INT_OVERRUN;
596
597	/* Modem signal change. */
598	if ((istatus & CDNC_UART_INT_DMSI) != 0) {
599		WR4(bas, CDNC_UART_MODEM_STAT_REG,
600		    CDNC_UART_MODEM_STAT_REG_DDCD |
601		    CDNC_UART_MODEM_STAT_REG_TERI |
602		    CDNC_UART_MODEM_STAT_REG_DDSR |
603		    CDNC_UART_MODEM_STAT_REG_DCTS);
604		ipend |= SER_INT_SIGCHG;
605	}
606
607	uart_unlock(sc->sc_hwmtx);
608	return (ipend);
609}
610
611static int
612cdnc_uart_bus_flush(struct uart_softc *sc, int what)
613{
614
615	return (0);
616}
617
618static int
619cdnc_uart_bus_getsig(struct uart_softc *sc)
620{
621	struct uart_bas *bas = &sc->sc_bas;
622	uint32_t new, old, sig;
623	uint8_t modem_status;
624
625	do {
626		old = sc->sc_hwsig;
627		sig = old;
628		uart_lock(sc->sc_hwmtx);
629		modem_status = RD4(bas, CDNC_UART_MODEM_STAT_REG);
630		uart_unlock(sc->sc_hwmtx);
631		SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_DSR,
632		       sig, SER_DSR, SER_DDSR);
633		SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_CTS,
634		       sig, SER_CTS, SER_DCTS);
635		SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_DCD,
636		       sig, SER_DCD, SER_DDCD);
637		SIGCHG(modem_status & CDNC_UART_MODEM_STAT_REG_RI,
638		       sig, SER_RI,  SER_DRI);
639		new = sig & ~SER_MASK_DELTA;
640	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
641	return (sig);
642}
643
644static int
645cdnc_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
646{
647	struct uart_bas *bas = &sc->sc_bas;
648	uint32_t uart_ctrl, modem_ctrl;
649	int error = 0;
650
651	uart_lock(sc->sc_hwmtx);
652
653	switch (request) {
654	case UART_IOCTL_BREAK:
655		uart_ctrl = RD4(bas, CDNC_UART_CTRL_REG);
656		if (data) {
657			uart_ctrl |= CDNC_UART_CTRL_REG_STARTBRK;
658			uart_ctrl &= ~CDNC_UART_CTRL_REG_STOPBRK;
659		} else {
660			uart_ctrl |= CDNC_UART_CTRL_REG_STOPBRK;
661			uart_ctrl &= ~CDNC_UART_CTRL_REG_STARTBRK;
662		}
663		WR4(bas, CDNC_UART_CTRL_REG, uart_ctrl);
664		break;
665	case UART_IOCTL_IFLOW:
666		modem_ctrl = RD4(bas, CDNC_UART_MODEM_CTRL_REG);
667		if (data)
668			modem_ctrl |= CDNC_UART_MODEM_CTRL_REG_RTS;
669		else
670			modem_ctrl &= ~CDNC_UART_MODEM_CTRL_REG_RTS;
671		WR4(bas, CDNC_UART_MODEM_CTRL_REG, modem_ctrl);
672		break;
673	default:
674		error = EINVAL;
675		break;
676	}
677
678	uart_unlock(sc->sc_hwmtx);
679
680	return (error);
681}
682
683static void
684cdnc_uart_bus_grab(struct uart_softc *sc)
685{
686
687	/* Enable interrupts. */
688	WR4(&sc->sc_bas, CDNC_UART_IEN_REG,
689	    CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR |
690	    CDNC_UART_INT_DMSI);
691}
692
693static void
694cdnc_uart_bus_ungrab(struct uart_softc *sc)
695{
696
697	/* Enable interrupts. */
698	WR4(&sc->sc_bas, CDNC_UART_IEN_REG,
699	    CDNC_UART_INT_RXTRIG | CDNC_UART_INT_RXTMOUT |
700	    CDNC_UART_INT_TXOVR | CDNC_UART_INT_RXOVR |
701	    CDNC_UART_INT_DMSI);
702}
703
704static struct uart_class uart_cdnc_class = {
705	"cdnc_uart",
706	cdnc_uart_bus_methods,
707	sizeof(struct uart_softc),
708	.uc_ops = &cdnc_uart_ops,
709	.uc_range = 8
710};
711
712static struct ofw_compat_data compat_data[] = {
713	{"cadence,uart",	(uintptr_t)&uart_cdnc_class},
714	{NULL,			(uintptr_t)NULL},
715};
716UART_FDT_CLASS_AND_DEVICE(compat_data);
717