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