1 /* $Id: at91usart.c,v 1.3 2009/10/23 06:53:13 snj Exp $ */
2 /* $NetBSD: at91usart.c,v 1.2 2008/07/03 01:15:39 matt Exp $ */
5 * Copyright (c) 2007 Embedtronics Oy. All rights reserved.
7 * Copyright (c) 1998, 1999, 2001, 2002, 2004 The NetBSD Foundation, Inc.
10 * This code is derived from software contributed to The NetBSD Foundation
13 * This code is derived from software contributed to The NetBSD Foundation
14 * by Ichiro FUKUHARA and Naoto Shimazaki.
16 * This code is derived from software contributed to The NetBSD Foundation
17 * by IWAMOTO Toshihiro.
19 * This code is derived from software contributed to The NetBSD Foundation
20 * by Charles M. Hannum.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
25 * 1. Redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
31 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
32 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
33 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
35 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGE.
45 * Copyright (c) 1991 The Regents of the University of California.
46 * All rights reserved.
48 * Redistribution and use in source and binary forms, with or without
49 * modification, are permitted provided that the following conditions
51 * 1. Redistributions of source code must retain the above copyright
52 * notice, this list of conditions and the following disclaimer.
53 * 2. Redistributions in binary form must reproduce the above copyright
54 * notice, this list of conditions and the following disclaimer in the
55 * documentation and/or other materials provided with the distribution.
56 * 3. Neither the name of the University nor the names of its contributors
57 * may be used to endorse or promote products derived from this software
58 * without specific prior written permission.
60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * @(#)com.c 7.5 (Berkeley) 5/16/91
76 * TODO: hardware flow control
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: at91usart.c,v 1.2 2008/07/03 01:15:39 matt Exp $");
86 #if NRND > 0 && defined(RND_COM)
92 * Override cnmagic(9) macro before including <sys/systm.h>.
93 * We need to know if cn_check_magic triggered debugger, so set a flag.
94 * Callers of cn_check_magic must declare int cn_trapped = 0;
95 * XXX: this is *ugly*!
101 } while (/* CONSTCOND */ 0)
105 #include <sys/param.h>
106 #include <sys/systm.h>
107 #include <sys/types.h>
108 #include <sys/conf.h>
109 #include <sys/file.h>
110 #include <sys/device.h>
111 #include <sys/kernel.h>
112 #include <sys/malloc.h>
115 #include <sys/vnode.h>
116 #include <sys/kauth.h>
118 #include <machine/intr.h>
119 #include <machine/bus.h>
121 #include <arm/at91/at91reg.h>
122 #include <arm/at91/at91var.h>
123 #include <arm/at91/at91usartreg.h>
124 #include <arm/at91/at91usartvar.h>
126 #include <dev/cons.h>
128 static int at91usart_param(struct tty
*, struct termios
*);
129 static void at91usart_start(struct tty
*);
130 static int at91usart_hwiflow(struct tty
*, int);
133 static u_int
cflag2lcrhi(tcflag_t
);
135 static void at91usart_set(struct at91usart_softc
*);
138 int at91usart_cn_getc(dev_t
);
139 void at91usart_cn_putc(dev_t
, int);
140 void at91usart_cn_pollc(dev_t
, int);
141 void at91usart_cn_probe(struct consdev
*);
142 void at91usart_cn_init(struct consdev
*);
144 static struct at91usart_cons_softc
{
145 bus_space_tag_t sc_iot
;
146 bus_space_handle_t sc_ioh
;
147 bus_addr_t sc_hwbase
;
153 u_int8_t sc_rx_fifo
[64];
156 static struct cnm_state at91usart_cnm_state
;
159 static void at91usart_soft(void* arg
);
160 inline static void at91usart_txsoft(struct at91usart_softc
*, struct tty
*);
161 inline static void at91usart_rxsoft(struct at91usart_softc
*, struct tty
*, unsigned csr
);
163 #define PDC_BLOCK_SIZE 64
165 //CFATTACH_DECL(at91usart, sizeof(struct at91usart_softc),
166 // at91usart_match, at91usart_attach, NULL, NULL);
168 //#define USART_DEBUG 10
171 int usart_debug
= USART_DEBUG
;
172 #define DPRINTFN(n,fmt) if (usart_debug >= (n)) printf fmt
174 #define DPRINTFN(n,fmt)
177 extern struct cfdriver at91usart_cd
;
179 dev_type_open(at91usart_open
);
180 dev_type_close(at91usart_close
);
181 dev_type_read(at91usart_read
);
182 dev_type_write(at91usart_write
);
183 dev_type_ioctl(at91usart_ioctl
);
184 dev_type_stop(at91usart_stop
);
185 dev_type_tty(at91usart_tty
);
186 dev_type_poll(at91usart_poll
);
188 const struct cdevsw at91usart_cdevsw
= {
189 at91usart_open
, at91usart_close
, at91usart_read
, at91usart_write
, at91usart_ioctl
,
190 at91usart_stop
, at91usart_tty
, at91usart_poll
, nommap
, ttykqfilter
, D_TTY
194 struct consdev at91usart_cons
= {
195 at91usart_cn_probe
, NULL
, at91usart_cn_getc
, at91usart_cn_putc
, at91usart_cn_pollc
, NULL
,
196 NULL
, NULL
, NODEV
, CN_REMOTE
200 #ifndef DEFAULT_COMSPEED
201 #define DEFAULT_COMSPEED 115200
204 #define COMUNIT_MASK 0x7ffff
205 #define COMDIALOUT_MASK 0x80000
207 #define COMUNIT(x) (minor(x) & COMUNIT_MASK)
208 #define COMDIALOUT(x) (minor(x) & COMDIALOUT_MASK)
210 #define COM_ISALIVE(sc) ((sc)->enabled != 0 && device_is_active((sc)->sc_dev))
213 at91usart_writereg(struct at91usart_softc
*sc
, int reg
, u_int val
)
215 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, reg
, val
);
219 at91usart_readreg(struct at91usart_softc
*sc
, int reg
)
221 return bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, reg
);
225 at91usart_match(device_t parent
, cfdata_t cf
, void *aux
)
227 if (strcmp(cf
->cf_name
, "at91usart") == 0)
232 static int at91usart_intr(void* arg
);
235 at91usart_attach_subr(struct at91usart_softc
*sc
, struct at91bus_attach_args
*sa
)
242 if (bus_space_map(sa
->sa_iot
, sa
->sa_addr
, sa
->sa_size
, 0, &sc
->sc_ioh
))
243 panic("%s: Cannot map registers", device_xname(sc
->sc_dev
));
245 sc
->sc_iot
= sa
->sa_iot
;
246 sc
->sc_hwbase
= sa
->sa_addr
;
247 sc
->sc_dmat
= sa
->sa_dmat
;
248 sc
->sc_pid
= sa
->sa_pid
;
251 err
= at91pdc_alloc_fifo(sc
->sc_dmat
, &sc
->sc_rx_fifo
, AT91USART_RING_SIZE
, BUS_DMA_READ
| BUS_DMA_STREAMING
);
253 panic("%s: cannot allocate rx fifo", device_xname(sc
->sc_dev
));
255 err
= at91pdc_alloc_fifo(sc
->sc_dmat
, &sc
->sc_tx_fifo
, AT91USART_RING_SIZE
, BUS_DMA_WRITE
| BUS_DMA_STREAMING
);
257 panic("%s: cannot allocate tx fifo", device_xname(sc
->sc_dev
));
259 /* initialize uart */
260 at91_peripheral_clock(sc
->sc_pid
, 1);
262 at91usart_writereg(sc
, US_IDR
, -1);
263 at91usart_writereg(sc
, US_RTOR
, 12); // 12-bit timeout
264 at91usart_writereg(sc
, US_PDC
+ PDC_PTCR
, PDC_PTCR_TXTDIS
| PDC_PTCR_RXTDIS
);
265 at91_intr_establish(sa
->sa_pid
, IPL_TTY
, INTR_HIGH_LEVEL
, at91usart_intr
, sc
);
266 USART_INIT(sc
, 115200U);
269 if (sc
->sc_iot
== usart_cn_sc
.sc_iot
270 && sc
->sc_hwbase
== usart_cn_sc
.sc_hwbase
) {
271 usart_cn_sc
.sc_attached
= 1;
272 /* Make sure the console is always "hardwired". */
273 delay(10000); /* wait for output to finish */
274 SET(sc
->sc_hwflags
, COM_HW_CONSOLE
);
275 SET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
);
276 SET(sc
->sc_ier
, USART_INT_RXRDY
);
277 USARTREG(USART_IER
) = USART_INT_RXRDY
; // @@@@@
282 tp
->t_oproc
= at91usart_start
;
283 tp
->t_param
= at91usart_param
;
284 tp
->t_hwiflow
= at91usart_hwiflow
;
291 if (ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
294 /* locate the major number */
295 maj
= cdevsw_lookup_major(&at91usart_cdevsw
);
297 cn_tab
->cn_dev
= makedev(maj
, device_unit(sc
->sc_dev
));
299 aprint_normal("%s: console (maj %u min %u cn_dev %u)\n",
300 device_xname(sc
->sc_dev
), maj
, device_unit(sc
->sc_dev
),
305 sc
->sc_si
= softint_establish(SOFTINT_SERIAL
, at91usart_soft
, sc
);
307 #if NRND > 0 && defined(RND_COM)
308 rnd_attach_source(&sc
->rnd_source
, device_xname(sc
->sc_dev
),
312 /* if there are no enable/disable functions, assume the device
317 /* XXX configure register */
320 SET(sc
->sc_hwflags
, COM_HW_DEV_OK
);
324 at91usart_param(struct tty
*tp
, struct termios
*t
)
326 struct at91usart_softc
*sc
327 = device_lookup_private(&at91usart_cd
, COMUNIT(tp
->t_dev
));
330 if (COM_ISALIVE(sc
) == 0)
333 if (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
)
337 * For the console, always force CLOCAL and !HUPCL, so that the port
340 if (ISSET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
) ||
341 ISSET(sc
->sc_hwflags
, COM_HW_CONSOLE
)) {
342 SET(t
->c_cflag
, CLOCAL
);
343 CLR(t
->c_cflag
, HUPCL
);
347 * If there were no changes, don't do anything. This avoids dropping
348 * input and improves performance when all we did was frob things like
351 if (tp
->t_ospeed
== t
->c_ospeed
&&
352 tp
->t_cflag
== t
->c_cflag
)
357 sc
->sc_brgr
= (AT91_MSTCLK
/ 16 + t
->c_ospeed
/ 2) / t
->c_ospeed
;
359 /* And copy to tty. */
361 tp
->t_ospeed
= t
->c_ospeed
;
362 tp
->t_cflag
= t
->c_cflag
;
368 * Update the tty layer's idea of the carrier bit.
369 * We tell tty the carrier is always on.
371 (void) (*tp
->t_linesw
->l_modem
)(tp
, 1);
375 comstatus(sc
, "comparam ");
378 /* tell the upper layer about hwflow.. */
380 (*sc
->hwflow
)(sc
, t
->c_cflag
);
386 at91usart_hwiflow(struct tty
*tp
, int block
)
389 /* tty discipline wants to block */
391 /* tty discipline wants to unblock */
397 at91usart_start_tx(struct at91usart_softc
*sc
)
400 at91usart_writereg(sc
, US_PDC
+ PDC_PTCR
, PDC_PTCR_TXTEN
);
406 at91usart_stop_tx(struct at91usart_softc
*sc
)
409 at91usart_writereg(sc
, US_PDC
+ PDC_PTCR
, PDC_PTCR_TXTDIS
);
415 at91usart_rx_started(struct at91usart_softc
*sc
)
418 (*sc
->rx_started
)(sc
);
422 at91usart_rx_stopped(struct at91usart_softc
*sc
)
425 (*sc
->rx_stopped
)(sc
);
429 at91usart_rx_rts_ctl(struct at91usart_softc
*sc
, int enabled
)
432 (*sc
->rx_rts_ctl
)(sc
, enabled
);
436 at91usart_filltx(struct at91usart_softc
*sc
)
438 struct tty
*tp
= sc
->sc_tty
;
442 // post write handler
443 AT91PDC_FIFO_POSTWRITE(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_dmat
, US_PDC
,
446 // copy more data to fifo:
448 && (dst
= AT91PDC_FIFO_WRPTR(&sc
->sc_tx_fifo
, &len
)) != NULL
) {
450 if (len
> sc
->sc_tbc
)
452 memcpy(dst
, sc
->sc_tba
, len
);
454 if ((sc
->sc_tbc
-= len
) <= 0)
455 CLR(tp
->t_state
, TS_BUSY
);
457 AT91PDC_FIFO_WRITTEN(&sc
->sc_tx_fifo
, len
);
458 // tell tty interface we've sent some bytes
459 ndflush(&tp
->t_outq
, len
);
462 // start sending data...
463 if (AT91PDC_FIFO_PREWRITE(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_dmat
,
464 US_PDC
, &sc
->sc_tx_fifo
, PDC_BLOCK_SIZE
)) {
465 at91usart_start_tx(sc
);
466 SET(sc
->sc_ier
, US_CSR_TXEMPTY
| US_CSR_ENDTX
);
468 CLR(sc
->sc_ier
, US_CSR_ENDTX
);
473 at91usart_start(struct tty
*tp
)
475 struct at91usart_softc
*sc
476 = device_lookup_private(&at91usart_cd
, COMUNIT(tp
->t_dev
));
479 if (COM_ISALIVE(sc
) == 0) {
480 DPRINTFN(5, ("%s: %s / COM_ISALIVE == 0\n", device_xname(sc
->sc_dev
), __FUNCTION__
));
485 if (ISSET(tp
->t_state
, TS_BUSY
| TS_TIMEOUT
| TS_TTSTOP
)) {
486 DPRINTFN(5, ("%s: %s: TS_BUSY || TS_TIMEOUT || TS_TTSTOP\n", device_xname(sc
->sc_dev
), __FUNCTION__
));
493 /* Grab the first contiguous region of buffer space. */
498 tba
= tp
->t_outq
.c_cf
;
499 tbc
= ndqb(&tp
->t_outq
, 0);
505 SET(tp
->t_state
, TS_BUSY
);
507 /* Output the first chunk of the contiguous buffer. */
508 at91usart_filltx(sc
);
509 at91usart_writereg(sc
, US_IER
, sc
->sc_ier
);
510 DPRINTFN(5, ("%s: %s, ier=%08x (csr=%08x)\n", device_xname(sc
->sc_dev
), __FUNCTION__
, sc
->sc_ier
, at91usart_readreg(sc
, US_CSR
)));
518 static __inline__
void
519 at91usart_break(struct at91usart_softc
*sc
, int onoff
)
521 at91usart_writereg(sc
, US_CR
, onoff
? US_CR_STTBRK
: US_CR_STPBRK
);
525 at91usart_shutdown(struct at91usart_softc
*sc
)
532 at91usart_writereg(sc
, US_PDC
+ PDC_PTCR
, PDC_PTCR_TXTDIS
| PDC_PTCR_RXTDIS
);
533 at91usart_writereg(sc
, US_PDC
+ PDC_TNCR
, 0);
534 at91usart_writereg(sc
, US_PDC
+ PDC_TCR
, 0);
535 at91usart_writereg(sc
, US_PDC
+ PDC_RNCR
, 0);
536 at91usart_writereg(sc
, US_PDC
+ PDC_RCR
, 0);
538 /* Turn off interrupts. */
539 at91usart_writereg(sc
, US_IDR
, -1);
541 /* Clear any break condition set with TIOCSBRK. */
542 at91usart_break(sc
, 0);
548 panic("at91usart_shutdown: not enabled?");
557 at91usart_open(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
559 struct at91usart_softc
*sc
;
564 sc
= device_lookup_private(&at91usart_cd
, COMUNIT(dev
));
565 if (sc
== NULL
|| !ISSET(sc
->sc_hwflags
, COM_HW_DEV_OK
))
568 if (!device_is_active(sc
->sc_dev
))
573 * If this is the kgdb port, no other use is permitted.
575 if (ISSET(sc
->sc_hwflags
, COM_HW_KGDB
))
581 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
587 * Do the following iff this is a first open.
589 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
595 if ((*sc
->enable
)(sc
)) {
597 printf("%s: device enable failed\n",
598 device_xname(sc
->sc_dev
));
603 /* XXXXXXXXXXXXXXX */
609 AT91PDC_RESET_FIFO(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_dmat
, US_PDC
, &sc
->sc_rx_fifo
, 0);
610 AT91PDC_RESET_FIFO(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_dmat
, US_PDC
, &sc
->sc_tx_fifo
, 1);
613 at91usart_writereg(sc
, US_CR
, US_CR_RSTSTA
| US_CR_STTTO
);
615 /* Turn on interrupts. */
616 sc
->sc_ier
= US_CSR_ENDRX
|US_CSR_RXBUFF
|US_CSR_TIMEOUT
|US_CSR_RXBRK
;
617 at91usart_writereg(sc
, US_IER
, sc
->sc_ier
);
620 at91usart_writereg(sc
, US_PDC
+ PDC_PTCR
, PDC_PTCR_RXTEN
);
623 * Initialize the termios status to the defaults. Add in the
624 * sticky bits from TIOCSFLAGS.
627 /* if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
628 t.c_ospeed = usart_cn_sc.sc_ospeed;
629 t.c_cflag = usart_cn_sc.sc_cflag;
631 t
.c_ospeed
= TTYDEF_SPEED
;
632 t
.c_cflag
= TTYDEF_CFLAG
;
634 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CLOCAL
))
635 SET(t
.c_cflag
, CLOCAL
);
636 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CRTSCTS
))
637 SET(t
.c_cflag
, CRTSCTS
);
638 if (ISSET(sc
->sc_swflags
, TIOCFLAG_MDMBUF
))
639 SET(t
.c_cflag
, MDMBUF
);
641 /* Make sure at91usart_param() will do something. */
643 (void) at91usart_param(tp
, &t
);
644 tp
->t_iflag
= TTYDEF_IFLAG
;
645 tp
->t_oflag
= TTYDEF_OFLAG
;
646 tp
->t_lflag
= TTYDEF_LFLAG
;
651 CLR(sc
->sc_rx_flags
, RX_ANY_BLOCK
);
655 comstatus(sc
, "at91usart_open ");
662 error
= ttyopen(tp
, COMDIALOUT(dev
), ISSET(flag
, O_NONBLOCK
));
666 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
673 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
675 * We failed to open the device, and nobody else had it opened.
676 * Clean up the state as appropriate.
678 at91usart_shutdown(sc
);
685 at91usart_close(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
687 struct at91usart_softc
*sc
= device_lookup_private(&at91usart_cd
, COMUNIT(dev
));
688 struct tty
*tp
= sc
->sc_tty
;
690 /* XXX This is for cons.c. */
691 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
694 (*tp
->t_linesw
->l_close
)(tp
, flag
);
697 if (COM_ISALIVE(sc
) == 0)
700 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
702 * Although we got a last close, the device may still be in
703 * use; e.g. if this was the dialout node, and there are still
704 * processes waiting for carrier on the non-dialout node.
706 at91usart_shutdown(sc
);
713 at91usart_read(dev_t dev
, struct uio
*uio
, int flag
)
715 struct at91usart_softc
*sc
= device_lookup_private(&at91usart_cd
, COMUNIT(dev
));
716 struct tty
*tp
= sc
->sc_tty
;
718 if (COM_ISALIVE(sc
) == 0)
721 return ((*tp
->t_linesw
->l_read
)(tp
, uio
, flag
));
725 at91usart_write(dev_t dev
, struct uio
*uio
, int flag
)
727 struct at91usart_softc
*sc
= device_lookup_private(&at91usart_cd
, COMUNIT(dev
));
728 struct tty
*tp
= sc
->sc_tty
;
730 if (COM_ISALIVE(sc
) == 0)
733 return ((*tp
->t_linesw
->l_write
)(tp
, uio
, flag
));
737 at91usart_poll(dev_t dev
, int events
, struct lwp
*l
)
739 struct at91usart_softc
*sc
= device_lookup_private(&at91usart_cd
, COMUNIT(dev
));
740 struct tty
*tp
= sc
->sc_tty
;
742 if (COM_ISALIVE(sc
) == 0)
745 return ((*tp
->t_linesw
->l_poll
)(tp
, events
, l
));
749 at91usart_tty(dev_t dev
)
751 struct at91usart_softc
*sc
= device_lookup_private(&at91usart_cd
, COMUNIT(dev
));
752 struct tty
*tp
= sc
->sc_tty
;
758 at91usart_ioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
760 struct at91usart_softc
*sc
= device_lookup_private(&at91usart_cd
, COMUNIT(dev
));
761 struct tty
*tp
= sc
->sc_tty
;
765 if (COM_ISALIVE(sc
) == 0)
768 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
769 if (error
!= EPASSTHROUGH
)
772 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
773 if (error
!= EPASSTHROUGH
)
782 at91usart_break(sc
, 1);
786 at91usart_break(sc
, 0);
790 *(int *)data
= sc
->sc_swflags
;
794 error
= kauth_authorize_device_tty(l
->l_cred
,
795 KAUTH_DEVICE_TTY_PRIVSET
, tp
);
798 sc
->sc_swflags
= *(int *)data
;
802 error
= EPASSTHROUGH
;
812 * Stop output on a line.
815 at91usart_stop(struct tty
*tp
, int flag
)
817 struct at91usart_softc
*sc
818 = device_lookup_private(&at91usart_cd
, COMUNIT(tp
->t_dev
));
822 if (ISSET(tp
->t_state
, TS_BUSY
)) {
823 /* Stop transmitting at the next chunk. */
825 if (!ISSET(tp
->t_state
, TS_TTSTOP
))
826 SET(tp
->t_state
, TS_FLUSH
);
833 cflag2lcrhi(tcflag_t cflag
)
837 switch (cflag
& CSIZE
) {
843 mr
|= (cflag
& PARENB
) ? LinCtrlHigh_PEN
: 0;
844 mr
|= (cflag
& PARODD
) ? 0 : LinCtrlHigh_EPS
;
845 mr
|= (cflag
& CSTOPB
) ? LinCtrlHigh_STP2
: 0;
846 mr
|= LinCtrlHigh_FEN
; /* FIFO always enabled */
848 mr
|= USART_MR_PAR_NONE
;
855 at91usart_set(struct at91usart_softc
*sc
)
857 at91usart_writereg(sc
, US_MR
, US_MR_CHRL_8
| US_MR_PAR_NONE
| US_MR_NBSTOP_1
);
858 at91usart_writereg(sc
, US_BRGR
, sc
->sc_brgr
);
859 at91usart_writereg(sc
, US_CR
, US_CR_TXEN
| US_CR_RXEN
); // @@@ just in case
864 at91usart_cn_attach(bus_space_tag_t iot
, bus_addr_t iobase
, bus_space_handle_t ioh
,
865 u_int32_t mstclk
, int ospeed
, tcflag_t cflag
)
867 cn_tab
= &at91usart_cons
;
868 cn_init_magic(&at91usart_cnm_state
);
869 cn_set_magic("\047\001");
871 usart_cn_sc
.sc_iot
= iot
;
872 usart_cn_sc
.sc_ioh
= ioh
;
873 usart_cn_sc
.sc_hwbase
= iobase
;
874 usart_cn_sc
.sc_ospeed
= ospeed
;
875 usart_cn_sc
.sc_cflag
= cflag
;
877 USART_INIT(mstclk
, ospeed
);
883 at91usart_cn_probe(struct consdev
*cp
)
885 cp
->cn_pri
= CN_REMOTE
;
889 at91usart_cn_pollc(dev_t dev
, int on
)
892 // enable polling mode
893 USARTREG(US_IDR
) = USART_INT_RXRDY
;
895 // disable polling mode
896 USARTREG(US_IER
) = USART_INT_RXRDY
;
901 at91usart_cn_putc(dev_t dev
, int c
)
905 bus_space_tag_t iot
= usart_cn_sc
.sc_iot
;
906 bus_space_handle_t ioh
= usart_cn_sc
.sc_ioh
;
914 while((USARTREG(USART_SR
) & USART_SR_TXEMPTY
) == 0)
923 at91usart_cn_getc(dev_t dev
)
928 bus_space_tag_t iot
= usart_cn_sc
.sc_iot
;
929 bus_space_handle_t ioh
= usart_cn_sc
.sc_ioh
;
934 while ((c
= USART_PEEKC()) == -1) {
939 sr
= USARTREG(USART_SR
);
940 if (ISSET(sr
, USART_SR_FRAME
) && c
== 0) {
941 USARTREG(USART_CR
) = USART_CR_RSTSTA
; // reset status bits
945 extern int db_active
;
949 int cn_trapped
= 0; /* unused */
951 cn_check_magic(dev
, c
, at91usart_cnm_state
);
962 at91usart_rxsoft(struct at91usart_softc
*sc
, struct tty
*tp
, unsigned csr
)
964 u_char
*start
, *get
, *end
;
967 AT91PDC_FIFO_POSTREAD(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_dmat
, US_PDC
,
970 if (ISSET(csr
, US_CSR_TIMEOUT
| US_CSR_RXBRK
))
971 at91usart_rx_stopped(sc
);
973 while ((start
= AT91PDC_FIFO_RDPTR(&sc
->sc_rx_fifo
, &cc
)) != NULL
) {
974 int (*rint
)(int, struct tty
*) = tp
->t_linesw
->l_rint
;
977 if (!ISSET(csr
, US_CSR_TIMEOUT
| US_CSR_RXBRK
))
978 at91usart_rx_started(sc
);
980 for (get
= start
, end
= start
+ cc
; get
< end
; get
++) {
982 if ((*rint
)(code
, tp
) == -1) {
984 * The line discipline's buffer is out of space.
986 if (!ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
)) {
988 * We're either not using flow control, or the
989 * line discipline didn't tell us to block for
990 * some reason. Either way, we have no way to
991 * know when there's more space available, so
992 * just drop the rest of the data.
995 printf("%s: receive missing data!\n",
996 device_xname(sc
->sc_dev
));
999 * Don't schedule any more receive processing
1000 * until the line discipline tells us there's
1001 * space available (through comhwiflow()).
1002 * Leave the rest of the data in the input
1005 SET(sc
->sc_rx_flags
, RX_TTY_OVERFLOWED
);
1011 // tell we've read some bytes...
1012 AT91PDC_FIFO_READ(&sc
->sc_rx_fifo
, get
- start
);
1014 if (ISSET(sc
->sc_rx_flags
, RX_TTY_BLOCKED
))
1018 // h/w flow control hook:
1019 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CRTSCTS
))
1020 at91usart_rx_rts_ctl(sc
, (AT91PDC_FIFO_SPACE(&sc
->sc_rx_fifo
) > PDC_BLOCK_SIZE
* 2));
1022 // write next pointer if USART is ready:
1023 if (AT91PDC_FIFO_PREREAD(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_dmat
, US_PDC
,
1024 &sc
->sc_rx_fifo
, PDC_BLOCK_SIZE
)) {
1025 SET(sc
->sc_ier
, US_CSR_ENDRX
| US_CSR_RXBUFF
| US_CSR_TIMEOUT
| US_CSR_RXBRK
);
1027 CLR(sc
->sc_ier
, US_CSR_ENDRX
| US_CSR_RXBUFF
| US_CSR_TIMEOUT
| US_CSR_RXBRK
);
1032 at91usart_txsoft(struct at91usart_softc
*sc
, struct tty
*tp
)
1034 at91usart_filltx(sc
);
1035 if (!ISSET(tp
->t_state
, TS_BUSY
))
1036 (*tp
->t_linesw
->l_start
)(tp
);
1041 at91usart_soft(void* arg
)
1043 struct at91usart_softc
*sc
= arg
;
1047 if (COM_ISALIVE(sc
) == 0)
1053 if ((csr
&= sc
->sc_ier
) == 0)
1056 DPRINTFN(5, ("%s: %s / csr = 0x%08x\n", device_xname(sc
->sc_dev
), __FUNCTION__
, csr
));
1057 if (ISSET(csr
, US_CSR_ENDRX
| US_CSR_RXBUFF
| US_CSR_TIMEOUT
| US_CSR_RXBRK
)) {
1058 /* receive interrupt */
1059 if (ISSET(csr
, US_CSR_RXBRK
)) {
1061 at91usart_writereg(sc
, US_CR
, US_CR_RSTSTA
| US_CR_STTTO
);
1062 } else if (ISSET(csr
, US_CSR_TIMEOUT
)) {
1064 at91usart_writereg(sc
, US_CR
, US_CR_STTTO
);
1066 at91usart_rxsoft(sc
, sc
->sc_tty
, csr
);
1068 if (ISSET(csr
, US_CSR_TXEMPTY
)) {
1069 at91usart_stop_tx(sc
);
1070 CLR(sc
->sc_ier
, US_CSR_TXEMPTY
);
1071 if (AT91PDC_FIFO_EMPTY(&sc
->sc_tx_fifo
)) {
1073 if (ISSET(sc
->sc_tty
->t_state
, TS_FLUSH
))
1074 CLR(sc
->sc_tty
->t_state
, TS_FLUSH
);
1077 if (ISSET(csr
, US_CSR_TXEMPTY
| US_CSR_ENDTX
)) {
1078 /* transmit interrupt! */
1079 at91usart_txsoft(sc
, sc
->sc_tty
);
1082 csr
= at91usart_readreg(sc
, US_CSR
);
1085 at91usart_writereg(sc
, US_IER
, sc
->sc_ier
); // re-enable interrupts
1091 at91usart_intr(void* arg
)
1093 struct at91usart_softc
*sc
= arg
;
1096 // get out if interrupts are not enabled
1097 imr
= at91usart_readreg(sc
, US_IMR
);
1100 // get out if pending interrupt is not enabled
1101 csr
= at91usart_readreg(sc
, US_CSR
);
1102 DPRINTFN(6,("%s: csr=%08X imr=%08X\n", device_xname(sc
->sc_dev
), csr
, imr
));
1103 if (!ISSET(csr
, imr
))
1106 // ok, we DO have some interrupts to serve! let softint do it
1108 at91usart_writereg(sc
, US_IDR
, -1);
1110 /* Wake up the poller. */
1111 softint_schedule(sc
->sc_si
);
1113 /* we're done for now */