[BACK]Return to imxuart.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / arm / imx

Annotation of src/sys/arch/arm/imx/imxuart.c, Revision 1.11.2.2

1.11.2.2! tls         1: /* $NetBSD: imxuart.c,v 1.13 2014/07/25 08:10:32 dholland Exp $ */
1.5       bsh         2:
                      3: /*
                      4:  * Copyright (c) 2009, 2010  Genetec Corporation.  All rights reserved.
                      5:  * Written by Hiroyuki Bessho for Genetec Corporation.
                      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:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
                     17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     18:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     19:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
                     20:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     21:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     22:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     23:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     24:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     25:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  *
                     28:  */
1.2       matt       29:
1.5       bsh        30: /*
                     31:  * derived from sys/dev/ic/com.c
                     32:  */
1.2       matt       33:
1.5       bsh        34: /*-
                     35:  * Copyright (c) 1998, 1999, 2004, 2008 The NetBSD Foundation, Inc.
                     36:  * All rights reserved.
                     37:  *
                     38:  * This code is derived from software contributed to The NetBSD Foundation
                     39:  * by Charles M. Hannum.
                     40:  *
                     41:  * Redistribution and use in source and binary forms, with or without
                     42:  * modification, are permitted provided that the following conditions
                     43:  * are met:
                     44:  * 1. Redistributions of source code must retain the above copyright
                     45:  *    notice, this list of conditions and the following disclaimer.
                     46:  * 2. Redistributions in binary form must reproduce the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer in the
                     48:  *    documentation and/or other materials provided with the distribution.
                     49:  *
                     50:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     51:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     52:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     53:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     54:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     55:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     56:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     57:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     58:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     59:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     60:  * POSSIBILITY OF SUCH DAMAGE.
                     61:  */
1.2       matt       62:
1.5       bsh        63: /*
                     64:  * Copyright (c) 1991 The Regents of the University of California.
                     65:  * All rights reserved.
                     66:  *
                     67:  * Redistribution and use in source and binary forms, with or without
                     68:  * modification, are permitted provided that the following conditions
                     69:  * are met:
                     70:  * 1. Redistributions of source code must retain the above copyright
                     71:  *    notice, this list of conditions and the following disclaimer.
                     72:  * 2. Redistributions in binary form must reproduce the above copyright
                     73:  *    notice, this list of conditions and the following disclaimer in the
                     74:  *    documentation and/or other materials provided with the distribution.
                     75:  * 3. Neither the name of the University nor the names of its contributors
                     76:  *    may be used to endorse or promote products derived from this software
                     77:  *    without specific prior written permission.
                     78:  *
                     79:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     80:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     81:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     82:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     83:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     84:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     85:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     86:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     87:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     88:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     89:  * SUCH DAMAGE.
                     90:  *
                     91:  *     @(#)com.c       7.5 (Berkeley) 5/16/91
                     92:  */
1.2       matt       93:
1.5       bsh        94: /*
                     95:  * driver for UART in i.MX SoC.
                     96:  */
1.2       matt       97:
1.5       bsh        98: #include <sys/cdefs.h>
1.11.2.2! tls        99: __KERNEL_RCSID(0, "$NetBSD: imxuart.c,v 1.13 2014/07/25 08:10:32 dholland Exp $");
1.2       matt      100:
1.5       bsh       101: #include "opt_imxuart.h"
                    102: #include "opt_ddb.h"
                    103: #include "opt_kgdb.h"
                    104: #include "opt_lockdebug.h"
                    105: #include "opt_multiprocessor.h"
                    106: #include "opt_ntp.h"
                    107: #include "opt_imxuart.h"
                    108: #include "opt_imx.h"
                    109:
                    110: #include "rnd.h"
1.9       tls       111: #ifdef RND_COM
1.5       bsh       112: #include <sys/rnd.h>
                    113: #endif
1.2       matt      114:
1.5       bsh       115: #ifndef        IMXUART_TOLERANCE
                    116: #define        IMXUART_TOLERANCE       30      /* baud rate tolerance, in 0.1% units */
                    117: #endif
1.2       matt      118:
1.5       bsh       119: #ifndef        IMXUART_FREQDIV
                    120: #define        IMXUART_FREQDIV         2       /* XXX */
                    121: #endif
1.2       matt      122:
1.5       bsh       123: #ifndef        IMXUART_FREQ
                    124: #define        IMXUART_FREQ    (56900000)
                    125: #endif
1.2       matt      126:
1.5       bsh       127: /*
                    128:  * Override cnmagic(9) macro before including <sys/systm.h>.
                    129:  * We need to know if cn_check_magic triggered debugger, so set a flag.
                    130:  * Callers of cn_check_magic must declare int cn_trapped = 0;
                    131:  * XXX: this is *ugly*!
                    132:  */
                    133: #define        cn_trap()                               \
                    134:        do {                                    \
                    135:                console_debugger();             \
                    136:                cn_trapped = 1;                 \
                    137:        } while (/* CONSTCOND */ 0)
1.2       matt      138:
1.5       bsh       139: #include <sys/param.h>
                    140: #include <sys/systm.h>
                    141: #include <sys/ioctl.h>
                    142: #include <sys/select.h>
                    143: #include <sys/poll.h>
                    144: #include <sys/tty.h>
                    145: #include <sys/proc.h>
                    146: #include <sys/conf.h>
                    147: #include <sys/file.h>
                    148: #include <sys/uio.h>
                    149: #include <sys/kernel.h>
                    150: #include <sys/syslog.h>
                    151: #include <sys/device.h>
                    152: #include <sys/malloc.h>
                    153: #include <sys/timepps.h>
                    154: #include <sys/vnode.h>
                    155: #include <sys/kauth.h>
                    156: #include <sys/intr.h>
1.2       matt      157:
1.5       bsh       158: #include <sys/bus.h>
1.2       matt      159:
1.5       bsh       160: #include <arm/imx/imxuartreg.h>
                    161: #include <arm/imx/imxuartvar.h>
                    162: #include <dev/cons.h>
1.2       matt      163:
1.5       bsh       164: #ifndef        IMXUART_RING_SIZE
                    165: #define        IMXUART_RING_SIZE       2048
1.2       matt      166: #endif
                    167:
1.5       bsh       168: typedef struct imxuart_softc {
                    169:        device_t        sc_dev;
1.2       matt      170:
1.5       bsh       171:        struct imxuart_regs {
                    172:                bus_space_tag_t         ur_iot;
                    173:                bus_space_handle_t      ur_ioh;
                    174:                bus_addr_t              ur_iobase;
                    175: #if 0
                    176:                bus_size_t              ur_nports;
                    177:                bus_size_t              ur_map[16];
                    178: #endif
                    179:        } sc_regs;
1.2       matt      180:
1.5       bsh       181: #define        sc_bt   sc_regs.ur_iot
                    182: #define        sc_bh   sc_regs.ur_ioh
1.2       matt      183:
1.5       bsh       184:        uint32_t                sc_intrspec_enb;
                    185:        uint32_t        sc_ucr2_d;      /* target value for UCR2 */
                    186:        uint32_t        sc_ucr[4];      /* cached value of UCRn */
                    187: #define        sc_ucr1 sc_ucr[0]
                    188: #define        sc_ucr2 sc_ucr[1]
                    189: #define        sc_ucr3 sc_ucr[2]
                    190: #define        sc_ucr4 sc_ucr[3]
                    191:
                    192:        uint                    sc_init_cnt;
                    193:
                    194:        bus_addr_t              sc_addr;
                    195:        bus_size_t              sc_size;
                    196:        int                     sc_intr;
                    197:
                    198:        u_char  sc_hwflags;
                    199: /* Hardware flag masks */
                    200: #define        IMXUART_HW_FLOW         __BIT(0)
                    201: #define        IMXUART_HW_DEV_OK       __BIT(1)
                    202: #define        IMXUART_HW_CONSOLE      __BIT(2)
                    203: #define        IMXUART_HW_KGDB         __BIT(3)
                    204:
                    205:
                    206:        bool    enabled;
                    207:
                    208:        u_char  sc_swflags;
                    209:
                    210:        u_char sc_rx_flags;
                    211: #define        IMXUART_RX_TTY_BLOCKED          __BIT(0)
                    212: #define        IMXUART_RX_TTY_OVERFLOWED       __BIT(1)
                    213: #define        IMXUART_RX_IBUF_BLOCKED         __BIT(2)
                    214: #define        IMXUART_RX_IBUF_OVERFLOWED      __BIT(3)
                    215: #define        IMXUART_RX_ANY_BLOCK                                    \
                    216:        (IMXUART_RX_TTY_BLOCKED|IMXUART_RX_TTY_OVERFLOWED|      \
                    217:            IMXUART_RX_IBUF_BLOCKED|IMXUART_RX_IBUF_OVERFLOWED)
                    218:
                    219:        bool    sc_tx_busy, sc_tx_done, sc_tx_stopped;
                    220:        bool    sc_rx_ready,sc_st_check;
                    221:        u_short sc_txfifo_len, sc_txfifo_thresh;
                    222:
                    223:        uint16_t        *sc_rbuf;
                    224:        u_int           sc_rbuf_size;
                    225:        u_int           sc_rbuf_in;
                    226:        u_int           sc_rbuf_out;
                    227: #define        IMXUART_RBUF_AVAIL(sc)                                  \
                    228:        ((sc->sc_rbuf_out <= sc->sc_rbuf_in) ?                  \
                    229:        (sc->sc_rbuf_in - sc->sc_rbuf_out) :                    \
                    230:        (sc->sc_rbuf_size - (sc->sc_rbuf_out - sc->sc_rbuf_in)))
                    231:
                    232: #define        IMXUART_RBUF_SPACE(sc)  \
                    233:        ((sc->sc_rbuf_in <= sc->sc_rbuf_out ?                       \
                    234:            sc->sc_rbuf_size - (sc->sc_rbuf_out - sc->sc_rbuf_in) : \
                    235:            sc->sc_rbuf_in - sc->sc_rbuf_out) - 1)
                    236: /* increment ringbuffer pointer */
                    237: #define        IMXUART_RBUF_INC(sc,v,i)        (((v) + (i))&((sc->sc_rbuf_size)-1))
                    238:        u_int   sc_r_lowat;
                    239:        u_int   sc_r_hiwat;
                    240:
                    241:        /* output chunk */
                    242:        u_char *sc_tba;
                    243:        u_int sc_tbc;
                    244:        u_int sc_heldtbc;
                    245:        /* pending parameter changes */
                    246:        u_char  sc_pending;
                    247: #define        IMXUART_PEND_PARAM      __BIT(0)
                    248: #define        IMXUART_PEND_SPEED      __BIT(1)
                    249:
                    250:
                    251:        struct callout sc_diag_callout;
                    252:        kmutex_t sc_lock;
                    253:        void *sc_ih;            /* interrupt handler */
                    254:        void *sc_si;            /* soft interrupt */
                    255:        struct tty              *sc_tty;
                    256:
                    257:        /* power management hooks */
                    258:        int (*enable)(struct imxuart_softc *);
                    259:        void (*disable)(struct imxuart_softc *);
                    260:
                    261:        struct {
                    262:                ulong err;
                    263:                ulong brk;
                    264:                ulong prerr;
                    265:                ulong frmerr;
                    266:                ulong ovrrun;
                    267:        }       sc_errors;
                    268:
                    269:        struct imxuart_baudrate_ratio {
                    270:                uint16_t numerator;     /* UBIR */
                    271:                uint16_t modulator;     /* UBMR */
                    272:        } sc_ratio;
                    273:
                    274: } imxuart_softc_t;
                    275:
                    276:
                    277: int    imxuspeed(long, struct imxuart_baudrate_ratio *);
                    278: int    imxuparam(struct tty *, struct termios *);
                    279: void   imxustart(struct tty *);
                    280: int    imxuhwiflow(struct tty *, int);
                    281:
                    282: void   imxuart_shutdown(struct imxuart_softc *);
                    283: void   imxuart_loadchannelregs(struct imxuart_softc *);
                    284: void   imxuart_hwiflow(struct imxuart_softc *);
                    285: void   imxuart_break(struct imxuart_softc *, bool);
                    286: void   imxuart_modem(struct imxuart_softc *, int);
                    287: void   tiocm_to_imxu(struct imxuart_softc *, u_long, int);
                    288: int    imxuart_to_tiocm(struct imxuart_softc *);
                    289: void   imxuart_iflush(struct imxuart_softc *);
                    290: int    imxuintr(void *);
                    291:
                    292: int    imxuart_common_getc(dev_t, struct imxuart_regs *);
                    293: void   imxuart_common_putc(dev_t, struct imxuart_regs *, int);
                    294:
                    295:
                    296: int    imxuart_init(struct imxuart_regs *, int, tcflag_t);
                    297:
                    298: int    imxucngetc(dev_t);
                    299: void   imxucnputc(dev_t, int);
                    300: void   imxucnpollc(dev_t, int);
                    301:
                    302: static void imxuintr_read(struct imxuart_softc *);
                    303: static void imxuintr_send(struct imxuart_softc *);
                    304:
                    305: static void imxuart_enable_debugport(struct imxuart_softc *);
                    306: static void imxuart_disable_all_interrupts(struct imxuart_softc *);
                    307: static void imxuart_control_rxint(struct imxuart_softc *, bool);
                    308: static void imxuart_control_txint(struct imxuart_softc *, bool);
                    309: static u_int imxuart_txfifo_space(struct imxuart_softc *sc);
1.2       matt      310:
1.5       bsh       311: static uint32_t        cflag_to_ucr2(tcflag_t, uint32_t);
1.2       matt      312:
1.5       bsh       313: CFATTACH_DECL_NEW(imxuart, sizeof(struct imxuart_softc),
1.2       matt      314:     imxuart_match, imxuart_attach, NULL, NULL);
                    315:
                    316:
1.5       bsh       317: #define        integrate       static inline
                    318: void   imxusoft(void *);
                    319: integrate void imxuart_rxsoft(struct imxuart_softc *, struct tty *);
                    320: integrate void imxuart_txsoft(struct imxuart_softc *, struct tty *);
                    321: integrate void imxuart_stsoft(struct imxuart_softc *, struct tty *);
                    322: integrate void imxuart_schedrx(struct imxuart_softc *);
                    323: void   imxudiag(void *);
                    324: static void imxuart_load_speed(struct imxuart_softc *);
                    325: static void imxuart_load_params(struct imxuart_softc *);
                    326: integrate void imxuart_load_pendings(struct imxuart_softc *);
                    327:
                    328:
                    329: extern struct cfdriver imxuart_cd;
                    330:
                    331: dev_type_open(imxuopen);
                    332: dev_type_close(imxuclose);
                    333: dev_type_read(imxuread);
                    334: dev_type_write(imxuwrite);
                    335: dev_type_ioctl(imxuioctl);
                    336: dev_type_stop(imxustop);
                    337: dev_type_tty(imxutty);
                    338: dev_type_poll(imxupoll);
                    339:
                    340: const struct cdevsw imxcom_cdevsw = {
1.11      dholland  341:        .d_open = imxuopen,
                    342:        .d_close = imxuclose,
                    343:        .d_read = imxuread,
                    344:        .d_write = imxuwrite,
                    345:        .d_ioctl = imxuioctl,
                    346:        .d_stop = imxustop,
                    347:        .d_tty = imxutty,
                    348:        .d_poll = imxupoll,
                    349:        .d_mmap = nommap,
                    350:        .d_kqfilter = ttykqfilter,
1.11.2.2! tls       351:        .d_discard = nodiscard,
1.11      dholland  352:        .d_flag = D_TTY
1.5       bsh       353: };
                    354:
1.2       matt      355: /*
1.5       bsh       356:  * Make this an option variable one can patch.
                    357:  * But be warned:  this must be a power of 2!
                    358:  */
                    359: u_int imxuart_rbuf_size = IMXUART_RING_SIZE;
                    360:
                    361: /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
                    362: u_int imxuart_rbuf_hiwat = (IMXUART_RING_SIZE * 1) / 4;
                    363: u_int imxuart_rbuf_lowat = (IMXUART_RING_SIZE * 3) / 4;
                    364:
                    365: static struct imxuart_regs imxuconsregs;
                    366: static int imxuconsattached;
                    367: static int imxuconsrate;
                    368: static tcflag_t imxuconscflag;
                    369: static struct cnm_state imxuart_cnm_state;
                    370:
                    371: u_int imxuart_freq = IMXUART_FREQ;
                    372: u_int imxuart_freqdiv = IMXUART_FREQDIV;
                    373:
                    374: #ifdef KGDB
                    375: #include <sys/kgdb.h>
                    376:
                    377: static struct imxuart_regs imxu_kgdb_regs;
                    378: static int imxu_kgdb_attached;
1.2       matt      379:
1.5       bsh       380: int    imxuart_kgdb_getc(void *);
                    381: void   imxuart_kgdb_putc(void *, int);
                    382: #endif /* KGDB */
                    383:
                    384: #define        IMXUART_UNIT_MASK       0x7ffff
                    385: #define        IMXUART_DIALOUT_MASK    0x80000
1.2       matt      386:
1.5       bsh       387: #define        IMXUART_UNIT(x) (minor(x) & IMXUART_UNIT_MASK)
                    388: #define        IMXUART_DIALOUT(x)      (minor(x) & IMXUART_DIALOUT_MASK)
1.2       matt      389:
1.5       bsh       390: #define        IMXUART_ISALIVE(sc)     ((sc)->enabled != 0 && \
                    391:                         device_is_active((sc)->sc_dev))
1.2       matt      392:
1.5       bsh       393: #define        BR      BUS_SPACE_BARRIER_READ
                    394: #define        BW      BUS_SPACE_BARRIER_WRITE
                    395: #define        IMXUART_BARRIER(r, f) \
                    396:        bus_space_barrier((r)->ur_iot, (r)->ur_ioh, 0, IMX_UART_SIZE, (f))
1.2       matt      397:
                    398:
1.5       bsh       399: void
1.6       bsh       400: imxuart_attach_common(device_t parent, device_t self,
1.5       bsh       401:     bus_space_tag_t iot, paddr_t iobase, size_t size, int intr, int flags)
1.2       matt      402: {
1.5       bsh       403:        imxuart_softc_t *sc = device_private(self);
                    404:        struct imxuart_regs *regsp = &sc->sc_regs;
                    405:        struct tty *tp;
                    406:        bus_space_handle_t ioh;
                    407:
                    408:        aprint_naive("\n");
                    409:        aprint_normal("\n");
                    410:
                    411:        sc->sc_dev = self;
                    412:
                    413:        if (size <= 0)
                    414:                size = IMX_UART_SIZE;
                    415:
                    416:        sc->sc_intr = intr;
                    417:        regsp->ur_iot = iot;
                    418:        regsp->ur_iobase = iobase;
                    419:
                    420:        if (bus_space_map(iot, regsp->ur_iobase, size, 0, &ioh)) {
                    421:                return;
                    422:        }
                    423:        regsp->ur_ioh = ioh;
                    424:
                    425:        callout_init(&sc->sc_diag_callout, 0);
                    426:        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
                    427:
                    428:        bus_space_read_region_4(iot, ioh, IMX_UCR1, sc->sc_ucr, 4);
                    429:        sc->sc_ucr2_d = sc->sc_ucr2;
                    430:
                    431:        /* Disable interrupts before configuring the device. */
                    432:        imxuart_disable_all_interrupts(sc);
                    433:
                    434:        if (regsp->ur_iobase == imxuconsregs.ur_iobase) {
                    435:                imxuconsattached = 1;
                    436:
                    437:                /* Make sure the console is always "hardwired". */
                    438: #if 0
                    439:                delay(10000);                   /* wait for output to finish */
                    440: #endif
                    441:                SET(sc->sc_hwflags, IMXUART_HW_CONSOLE);
                    442:                SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
                    443:        }
                    444:
                    445:
1.8       rmind     446:        tp = tty_alloc();
1.5       bsh       447:        tp->t_oproc = imxustart;
                    448:        tp->t_param = imxuparam;
                    449:        tp->t_hwiflow = imxuhwiflow;
                    450:
                    451:        sc->sc_tty = tp;
                    452:        sc->sc_rbuf = malloc(sizeof (*sc->sc_rbuf) * imxuart_rbuf_size,
                    453:            M_DEVBUF, M_NOWAIT);
                    454:        sc->sc_rbuf_size = imxuart_rbuf_size;
                    455:        sc->sc_rbuf_in = sc->sc_rbuf_out = 0;
                    456:        if (sc->sc_rbuf == NULL) {
                    457:                aprint_error_dev(sc->sc_dev,
                    458:                    "unable to allocate ring buffer\n");
                    459:                return;
                    460:        }
                    461:
                    462:        sc->sc_txfifo_len = 32;
                    463:        sc->sc_txfifo_thresh = 16;      /* when USR1.TRDY, fifo has space
                    464:                                         * for this many characters */
                    465:
                    466:        tty_attach(tp);
                    467:
                    468:        if (ISSET(sc->sc_hwflags, IMXUART_HW_CONSOLE)) {
                    469:                int maj;
                    470:
                    471:                /* locate the major number */
                    472:                maj = cdevsw_lookup_major(&imxcom_cdevsw);
                    473:
                    474:                if (maj != NODEVMAJOR) {
                    475:                        tp->t_dev = cn_tab->cn_dev = makedev(maj,
                    476:                            device_unit(sc->sc_dev));
                    477:
                    478:                        aprint_normal_dev(sc->sc_dev, "console\n");
                    479:                }
                    480:        }
                    481:
                    482:        sc->sc_ih = intr_establish(sc->sc_intr, IPL_SERIAL, IST_LEVEL,
                    483:            imxuintr, sc);
                    484:        if (sc->sc_ih == NULL)
                    485:                aprint_error_dev(sc->sc_dev, "intr_establish failed\n");
                    486:
                    487: #ifdef KGDB
                    488:        /*
                    489:         * Allow kgdb to "take over" this port.  If this is
                    490:         * not the console and is the kgdb device, it has
                    491:         * exclusive use.  If it's the console _and_ the
                    492:         * kgdb device, it doesn't.
                    493:         */
                    494:        if (regsp->ur_iobase == imxu_kgdb_regs.ur_iobase) {
                    495:                if (!ISSET(sc->sc_hwflags, IMXUART_HW_CONSOLE)) {
                    496:                        imxu_kgdb_attached = 1;
                    497:
                    498:                        SET(sc->sc_hwflags, IMXUART_HW_KGDB);
                    499:                }
                    500:                aprint_normal_dev(sc->sc_dev, "kgdb\n");
                    501:        }
                    502: #endif
                    503:
                    504:        sc->sc_si = softint_establish(SOFTINT_SERIAL, imxusoft, sc);
1.2       matt      505:
1.9       tls       506: #ifdef RND_COM
1.5       bsh       507:        rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
1.11.2.1  tls       508:                          RND_TYPE_TTY, RND_FLAG_COLLECT_TIME |
                    509:                                        RND_FLAG_ESTIMATE_TIME);
1.5       bsh       510: #endif
                    511:
                    512:        /* if there are no enable/disable functions, assume the device
                    513:           is always enabled */
                    514:        if (!sc->enable)
                    515:                sc->enabled = 1;
                    516:
                    517:        imxuart_enable_debugport(sc);
1.2       matt      518:
1.5       bsh       519:        SET(sc->sc_hwflags, IMXUART_HW_DEV_OK);
1.2       matt      520:
1.5       bsh       521:        //shutdownhook_establish(imxuart_shutdownhook, sc);
1.2       matt      522:
                    523:
1.5       bsh       524: #if 0
                    525:        {
                    526:                uint32_t reg;
                    527:                reg = bus_space_read_4(iot, ioh, IMX_UCR1);
                    528:                reg |= IMX_UCR1_TXDMAEN | IMX_UCR1_RXDMAEN;
                    529:                bus_space_write_4(iot, ioh, IMX_UCR1, reg);
                    530:        }
                    531: #endif
1.2       matt      532: }
                    533:
                    534: /*
1.5       bsh       535:  * baudrate = RefFreq / (16 * (UMBR + 1)/(UBIR + 1))
                    536:  *
                    537:  * (UBIR + 1) / (UBMR + 1) = (16 * BaurdRate) / RefFreq
1.2       matt      538:  */
1.5       bsh       539:
                    540: static long
                    541: gcd(long m, long n)
1.2       matt      542: {
                    543:
1.5       bsh       544:        if (m < n)
                    545:                return gcd(n, m);
                    546:
                    547:        if (n <= 0)
                    548:                return m;
                    549:        return gcd(n, m % n);
1.2       matt      550: }
                    551:
                    552:
                    553: int
1.5       bsh       554: imxuspeed(long speed, struct imxuart_baudrate_ratio *ratio)
1.2       matt      555: {
1.5       bsh       556: #define        divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
                    557:        long b = 16 * speed;
                    558:        long f = imxuart_freq / imxuart_freqdiv;
                    559:        long d;
                    560:        int err = 0;
                    561:
                    562:        /* reduce b/f */
                    563:        while ((f > (1<<16) || b > (1<<16)) && (d = gcd(f, b)) > 1) {
                    564:                f /= d;
                    565:                b /= d;
                    566:        }
                    567:
                    568:
                    569:        while (f > (1<<16) || b > (1<<16)) {
                    570:                f /= 2;
                    571:                b /= 2;
                    572:        }
                    573:        if (f <= 0 || b <= 0)
                    574:                return -1;
                    575:
                    576: #ifdef DIAGNOSTIC
                    577:        err = divrnd(((uint64_t)imxuart_freq) * 1000 / imxuart_freqdiv,
                    578:                     (uint64_t)speed * 16 * f / b) - 1000;
                    579:        if (err < 0)
                    580:                err = -err;
                    581: #endif
                    582:
                    583:        ratio->numerator = b-1;
                    584:        ratio->modulator = f-1;
1.2       matt      585:
1.5       bsh       586:        if (err > IMXUART_TOLERANCE)
                    587:                return -1;
1.2       matt      588:
                    589:        return 0;
1.5       bsh       590: #undef divrnd
1.2       matt      591: }
                    592:
1.5       bsh       593: #ifdef IMXUART_DEBUG
                    594: int    imxuart_debug = 0;
                    595:
                    596: void imxustatus(struct imxuart_softc *, const char *);
                    597: void
                    598: imxustatus(struct imxuart_softc *sc, const char *str)
1.2       matt      599: {
1.5       bsh       600:        struct tty *tp = sc->sc_tty;
1.2       matt      601:
1.5       bsh       602:        aprint_normal_dev(sc->sc_dev,
                    603:            "%s %cclocal  %cdcd %cts_carr_on %cdtr %ctx_stopped\n",
                    604:            str,
                    605:            ISSET(tp->t_cflag, CLOCAL) ? '+' : '-',
                    606:            ISSET(sc->sc_msr, MSR_DCD) ? '+' : '-',
                    607:            ISSET(tp->t_state, TS_CARR_ON) ? '+' : '-',
                    608:            ISSET(sc->sc_mcr, MCR_DTR) ? '+' : '-',
                    609:            sc->sc_tx_stopped ? '+' : '-');
                    610:
                    611:        aprint_normal_dev(sc->sc_dev,
                    612:            "%s %ccrtscts %ccts %cts_ttstop  %crts rx_flags=0x%x\n",
                    613:            str,
                    614:            ISSET(tp->t_cflag, CRTSCTS) ? '+' : '-',
                    615:            ISSET(sc->sc_msr, MSR_CTS) ? '+' : '-',
                    616:            ISSET(tp->t_state, TS_TTSTOP) ? '+' : '-',
                    617:            ISSET(sc->sc_mcr, MCR_RTS) ? '+' : '-',
                    618:            sc->sc_rx_flags);
1.2       matt      619: }
1.5       bsh       620: #endif
1.2       matt      621:
1.5       bsh       622: #if 0
1.2       matt      623: int
1.5       bsh       624: imxuart_detach(device_t self, int flags)
1.2       matt      625: {
1.5       bsh       626:        struct imxuart_softc *sc = device_private(self);
                    627:        int maj, mn;
1.2       matt      628:
1.5       bsh       629:         if (ISSET(sc->sc_hwflags, IMXUART_HW_CONSOLE))
                    630:                return EBUSY;
                    631:
                    632:        /* locate the major number */
                    633:        maj = cdevsw_lookup_major(&imxcom_cdevsw);
                    634:
                    635:        /* Nuke the vnodes for any open instances. */
                    636:        mn = device_unit(self);
                    637:        vdevgone(maj, mn, mn, VCHR);
                    638:
                    639:        mn |= IMXUART_DIALOUT_MASK;
                    640:        vdevgone(maj, mn, mn, VCHR);
                    641:
                    642:        if (sc->sc_rbuf == NULL) {
                    643:                /*
                    644:                 * Ring buffer allocation failed in the imxuart_attach_subr,
                    645:                 * only the tty is allocated, and nothing else.
                    646:                 */
1.8       rmind     647:                tty_free(sc->sc_tty);
1.5       bsh       648:                return 0;
1.2       matt      649:        }
                    650:
1.5       bsh       651:        /* Free the receive buffer. */
                    652:        free(sc->sc_rbuf, M_DEVBUF);
                    653:
                    654:        /* Detach and free the tty. */
                    655:        tty_detach(sc->sc_tty);
1.8       rmind     656:        tty_free(sc->sc_tty);
1.5       bsh       657:
                    658:        /* Unhook the soft interrupt handler. */
                    659:        softint_disestablish(sc->sc_si);
                    660:
1.9       tls       661: #ifdef RND_COM
1.5       bsh       662:        /* Unhook the entropy source. */
                    663:        rnd_detach_source(&sc->rnd_source);
                    664: #endif
                    665:        callout_destroy(&sc->sc_diag_callout);
                    666:
                    667:        /* Destroy the lock. */
                    668:        mutex_destroy(&sc->sc_lock);
1.2       matt      669:
1.5       bsh       670:        return (0);
1.2       matt      671: }
1.5       bsh       672: #endif
1.2       matt      673:
1.5       bsh       674: #ifdef notyet
1.2       matt      675: int
1.5       bsh       676: imxuart_activate(device_t self, enum devact act)
1.2       matt      677: {
1.5       bsh       678:        struct imxuart_softc *sc = device_private(self);
                    679:        int rv = 0;
1.2       matt      680:
1.5       bsh       681:        switch (act) {
                    682:        case DVACT_ACTIVATE:
                    683:                rv = EOPNOTSUPP;
                    684:                break;
                    685:
                    686:        case DVACT_DEACTIVATE:
                    687:                if (sc->sc_hwflags & (IMXUART_HW_CONSOLE|IMXUART_HW_KGDB)) {
                    688:                        rv = EBUSY;
                    689:                        break;
1.2       matt      690:                }
1.5       bsh       691:
                    692:                if (sc->disable != NULL && sc->enabled != 0) {
                    693:                        (*sc->disable)(sc);
                    694:                        sc->enabled = 0;
1.2       matt      695:                }
1.5       bsh       696:                break;
1.2       matt      697:        }
                    698:
1.5       bsh       699:        return (rv);
1.2       matt      700: }
1.5       bsh       701: #endif
1.2       matt      702:
1.5       bsh       703: void
                    704: imxuart_shutdown(struct imxuart_softc *sc)
1.2       matt      705: {
1.5       bsh       706:        struct tty *tp = sc->sc_tty;
                    707:
                    708:        mutex_spin_enter(&sc->sc_lock);
                    709:
                    710:        /* If we were asserting flow control, then deassert it. */
                    711:        SET(sc->sc_rx_flags, IMXUART_RX_IBUF_BLOCKED);
                    712:        imxuart_hwiflow(sc);
                    713:
                    714:        /* Clear any break condition set with TIOCSBRK. */
                    715:        imxuart_break(sc, false);
                    716:
                    717:        /*
                    718:         * Hang up if necessary.  Wait a bit, so the other side has time to
                    719:         * notice even if we immediately open the port again.
                    720:         * Avoid tsleeping above splhigh().
                    721:         */
                    722:        if (ISSET(tp->t_cflag, HUPCL)) {
                    723:                imxuart_modem(sc, 0);
                    724:                mutex_spin_exit(&sc->sc_lock);
                    725:                /* XXX will only timeout */
                    726:                (void) kpause(ttclos, false, hz, NULL);
                    727:                mutex_spin_enter(&sc->sc_lock);
                    728:        }
                    729:
                    730:        /* Turn off interrupts. */
                    731:        imxuart_disable_all_interrupts(sc);
                    732:        /* re-enable recv interrupt for console or kgdb port */
                    733:        imxuart_enable_debugport(sc);
                    734:
                    735:        mutex_spin_exit(&sc->sc_lock);
                    736:
                    737: #ifdef notyet
                    738:        if (sc->disable) {
                    739: #ifdef DIAGNOSTIC
                    740:                if (!sc->enabled)
                    741:                        panic("imxuart_shutdown: not enabled?");
                    742: #endif
                    743:                (*sc->disable)(sc);
                    744:                sc->enabled = 0;
1.2       matt      745:        }
                    746: #endif
                    747: }
                    748:
1.5       bsh       749: int
                    750: imxuopen(dev_t dev, int flag, int mode, struct lwp *l)
1.2       matt      751: {
1.5       bsh       752:        struct imxuart_softc *sc;
                    753:        struct tty *tp;
                    754:        int s;
                    755:        int error;
                    756:
                    757:        sc = device_lookup_private(&imxuart_cd, IMXUART_UNIT(dev));
                    758:        if (sc == NULL || !ISSET(sc->sc_hwflags, IMXUART_HW_DEV_OK) ||
                    759:                sc->sc_rbuf == NULL)
                    760:                return (ENXIO);
                    761:
                    762:        if (!device_is_active(sc->sc_dev))
                    763:                return (ENXIO);
                    764:
                    765: #ifdef KGDB
                    766:        /*
                    767:         * If this is the kgdb port, no other use is permitted.
                    768:         */
                    769:        if (ISSET(sc->sc_hwflags, IMXUART_HW_KGDB))
                    770:                return (EBUSY);
                    771: #endif
                    772:
                    773:        tp = sc->sc_tty;
                    774:
                    775:        if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
                    776:                return (EBUSY);
                    777:
                    778:        s = spltty();
                    779:
                    780:        /*
                    781:         * Do the following iff this is a first open.
                    782:         */
                    783:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
                    784:                struct termios t;
                    785:
                    786:                tp->t_dev = dev;
                    787:
                    788:
                    789: #ifdef notyet
                    790:                if (sc->enable) {
                    791:                        if ((*sc->enable)(sc)) {
                    792:                                splx(s);
                    793:                                aprint_error_dev(sc->sc_dev,
                    794:                                    "device enable failed\n");
                    795:                                return (EIO);
                    796:                        }
                    797:                        sc->enabled = 1;
                    798:                }
                    799: #endif
                    800:
                    801:                mutex_spin_enter(&sc->sc_lock);
                    802:
                    803:                imxuart_disable_all_interrupts(sc);
                    804:
                    805:                /* Fetch the current modem control status, needed later. */
                    806:
                    807: #ifdef IMXUART_PPS
                    808:                /* Clear PPS capture state on first open. */
                    809:                mutex_spin_enter(&timecounter_lock);
                    810:                memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
                    811:                sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
                    812:                pps_init(&sc->sc_pps_state);
                    813:                mutex_spin_exit(&timecounter_lock);
                    814: #endif
                    815:
                    816:                mutex_spin_exit(&sc->sc_lock);
                    817:
                    818:                /*
                    819:                 * Initialize the termios status to the defaults.  Add in the
                    820:                 * sticky bits from TIOCSFLAGS.
                    821:                 */
                    822:                if (ISSET(sc->sc_hwflags, IMXUART_HW_CONSOLE)) {
                    823:                        t.c_ospeed = imxuconsrate;
                    824:                        t.c_cflag = imxuconscflag;
                    825:                } else {
                    826:                        t.c_ospeed = TTYDEF_SPEED;
                    827:                        t.c_cflag = TTYDEF_CFLAG;
                    828:                }
                    829:                t.c_ispeed = t.c_ospeed;
                    830:                if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
                    831:                        SET(t.c_cflag, CLOCAL);
                    832:                if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
                    833:                        SET(t.c_cflag, CRTSCTS);
                    834:                if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
                    835:                        SET(t.c_cflag, MDMBUF);
                    836:                /* Make sure imxuparam() will do something. */
                    837:                tp->t_ospeed = 0;
                    838:                (void) imxuparam(tp, &t);
                    839:                tp->t_iflag = TTYDEF_IFLAG;
                    840:                tp->t_oflag = TTYDEF_OFLAG;
                    841:                tp->t_lflag = TTYDEF_LFLAG;
                    842:                ttychars(tp);
                    843:                ttsetwater(tp);
                    844:
                    845:                mutex_spin_enter(&sc->sc_lock);
                    846:
                    847:                /*
                    848:                 * Turn on DTR.  We must always do this, even if carrier is not
                    849:                 * present, because otherwise we'd have to use TIOCSDTR
                    850:                 * immediately after setting CLOCAL, which applications do not
                    851:                 * expect.  We always assert DTR while the device is open
                    852:                 * unless explicitly requested to deassert it.
                    853:                 */
                    854:                imxuart_modem(sc, 1);
                    855:
                    856:                /* Clear the input ring, and unblock. */
                    857:                sc->sc_rbuf_in = sc->sc_rbuf_out = 0;
                    858:                imxuart_iflush(sc);
                    859:                CLR(sc->sc_rx_flags, IMXUART_RX_ANY_BLOCK);
                    860:                imxuart_hwiflow(sc);
                    861:
                    862:                /* Turn on interrupts. */
                    863:                imxuart_control_rxint(sc, true);
                    864:
                    865: #ifdef IMXUART_DEBUG
                    866:                if (imxuart_debug)
                    867:                        imxustatus(sc, "imxuopen  ");
                    868: #endif
1.2       matt      869:
1.5       bsh       870:                mutex_spin_exit(&sc->sc_lock);
1.2       matt      871:        }
                    872:
1.5       bsh       873:        splx(s);
1.2       matt      874:
                    875: #if 0
1.5       bsh       876:        error = ttyopen(tp, IMXUART_DIALOUT(dev), ISSET(flag, O_NONBLOCK));
                    877: #else
                    878:        error = ttyopen(tp, 1, ISSET(flag, O_NONBLOCK));
1.2       matt      879: #endif
1.5       bsh       880:        if (error)
                    881:                goto bad;
1.2       matt      882:
1.5       bsh       883:        error = (*tp->t_linesw->l_open)(dev, tp);
                    884:        if (error)
                    885:                goto bad;
                    886:
                    887:        return (0);
                    888:
                    889: bad:
                    890:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
                    891:                /*
                    892:                 * We failed to open the device, and nobody else had it opened.
                    893:                 * Clean up the state as appropriate.
                    894:                 */
                    895:                imxuart_shutdown(sc);
                    896:        }
1.2       matt      897:
1.5       bsh       898:        return (error);
                    899: }
1.2       matt      900:
1.5       bsh       901: int
                    902: imxuclose(dev_t dev, int flag, int mode, struct lwp *l)
                    903: {
                    904:        struct imxuart_softc *sc =
                    905:            device_lookup_private(&imxuart_cd, IMXUART_UNIT(dev));
                    906:        struct tty *tp = sc->sc_tty;
                    907:
                    908:        /* XXX This is for cons.c. */
                    909:        if (!ISSET(tp->t_state, TS_ISOPEN))
                    910:                return (0);
                    911:
                    912:        (*tp->t_linesw->l_close)(tp, flag);
                    913:        ttyclose(tp);
                    914:
                    915:        if (IMXUART_ISALIVE(sc) == 0)
                    916:                return (0);
                    917:
                    918:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
                    919:                /*
                    920:                 * Although we got a last close, the device may still be in
                    921:                 * use; e.g. if this was the dialout node, and there are still
                    922:                 * processes waiting for carrier on the non-dialout node.
                    923:                 */
                    924:                imxuart_shutdown(sc);
1.2       matt      925:        }
                    926:
1.5       bsh       927:        return (0);
                    928: }
                    929:
                    930: int
                    931: imxuread(dev_t dev, struct uio *uio, int flag)
                    932: {
                    933:        struct imxuart_softc *sc =
                    934:            device_lookup_private(&imxuart_cd, IMXUART_UNIT(dev));
                    935:        struct tty *tp = sc->sc_tty;
                    936:
                    937:        if (IMXUART_ISALIVE(sc) == 0)
                    938:                return (EIO);
1.2       matt      939:
1.5       bsh       940:        return ((*tp->t_linesw->l_read)(tp, uio, flag));
1.2       matt      941: }
                    942:
1.5       bsh       943: int
                    944: imxuwrite(dev_t dev, struct uio *uio, int flag)
1.2       matt      945: {
1.5       bsh       946:        struct imxuart_softc *sc =
                    947:            device_lookup_private(&imxuart_cd, IMXUART_UNIT(dev));
                    948:        struct tty *tp = sc->sc_tty;
                    949:
                    950:        if (IMXUART_ISALIVE(sc) == 0)
                    951:                return (EIO);
1.2       matt      952:
1.5       bsh       953:        return ((*tp->t_linesw->l_write)(tp, uio, flag));
1.2       matt      954: }
                    955:
1.5       bsh       956: int
                    957: imxupoll(dev_t dev, int events, struct lwp *l)
1.2       matt      958: {
1.5       bsh       959:        struct imxuart_softc *sc =
                    960:            device_lookup_private(&imxuart_cd, IMXUART_UNIT(dev));
                    961:        struct tty *tp = sc->sc_tty;
1.2       matt      962:
1.5       bsh       963:        if (IMXUART_ISALIVE(sc) == 0)
                    964:                return (POLLHUP);
1.2       matt      965:
1.5       bsh       966:        return ((*tp->t_linesw->l_poll)(tp, events, l));
1.2       matt      967: }
                    968:
1.5       bsh       969: struct tty *
                    970: imxutty(dev_t dev)
1.2       matt      971: {
1.5       bsh       972:        struct imxuart_softc *sc =
                    973:            device_lookup_private(&imxuart_cd, IMXUART_UNIT(dev));
                    974:        struct tty *tp = sc->sc_tty;
1.2       matt      975:
1.5       bsh       976:        return (tp);
1.2       matt      977: }
                    978:
1.5       bsh       979: int
                    980: imxuioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.2       matt      981: {
1.5       bsh       982:        struct imxuart_softc *sc;
                    983:        struct tty *tp;
                    984:        int error;
                    985:
                    986:        sc = device_lookup_private(&imxuart_cd, IMXUART_UNIT(dev));
                    987:        if (sc == NULL)
                    988:                return ENXIO;
                    989:        if (IMXUART_ISALIVE(sc) == 0)
                    990:                return (EIO);
                    991:
                    992:        tp = sc->sc_tty;
                    993:
                    994:        error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
                    995:        if (error != EPASSTHROUGH)
                    996:                return (error);
                    997:
                    998:        error = ttioctl(tp, cmd, data, flag, l);
                    999:        if (error != EPASSTHROUGH)
                   1000:                return (error);
                   1001:
                   1002:        error = 0;
                   1003:        switch (cmd) {
                   1004:        case TIOCSFLAGS:
                   1005:                error = kauth_authorize_device_tty(l->l_cred,
                   1006:                    KAUTH_DEVICE_TTY_PRIVSET, tp);
                   1007:                break;
                   1008:        default:
                   1009:                /* nothing */
                   1010:                break;
                   1011:        }
                   1012:        if (error) {
                   1013:                return error;
                   1014:        }
                   1015:
                   1016:        mutex_spin_enter(&sc->sc_lock);
                   1017:
                   1018:        switch (cmd) {
                   1019:        case TIOCSBRK:
                   1020:                imxuart_break(sc, true);
                   1021:                break;
                   1022:
                   1023:        case TIOCCBRK:
                   1024:                imxuart_break(sc, false);
                   1025:                break;
                   1026:
                   1027:        case TIOCSDTR:
                   1028:                imxuart_modem(sc, 1);
                   1029:                break;
                   1030:
                   1031:        case TIOCCDTR:
                   1032:                imxuart_modem(sc, 0);
                   1033:                break;
                   1034:
                   1035:        case TIOCGFLAGS:
                   1036:                *(int *)data = sc->sc_swflags;
                   1037:                break;
                   1038:
                   1039:        case TIOCSFLAGS:
                   1040:                sc->sc_swflags = *(int *)data;
                   1041:                break;
                   1042:
                   1043:        case TIOCMSET:
                   1044:        case TIOCMBIS:
                   1045:        case TIOCMBIC:
                   1046:                tiocm_to_imxu(sc, cmd, *(int *)data);
                   1047:                break;
                   1048:
                   1049:        case TIOCMGET:
                   1050:                *(int *)data = imxuart_to_tiocm(sc);
                   1051:                break;
                   1052:
                   1053: #ifdef notyet
                   1054:        case PPS_IOC_CREATE:
                   1055:        case PPS_IOC_DESTROY:
                   1056:        case PPS_IOC_GETPARAMS:
                   1057:        case PPS_IOC_SETPARAMS:
                   1058:        case PPS_IOC_GETCAP:
                   1059:        case PPS_IOC_FETCH:
                   1060: #ifdef PPS_SYNC
                   1061:        case PPS_IOC_KCBIND:
                   1062: #endif
                   1063:                mutex_spin_enter(&timecounter_lock);
                   1064:                error = pps_ioctl(cmd, data, &sc->sc_pps_state);
                   1065:                mutex_spin_exit(&timecounter_lock);
                   1066:                break;
                   1067:
                   1068:        case TIOCDCDTIMESTAMP:  /* XXX old, overloaded  API used by xntpd v3 */
                   1069:                mutex_spin_enter(&timecounter_lock);
                   1070: #ifndef PPS_TRAILING_EDGE
                   1071:                TIMESPEC_TO_TIMEVAL((struct timeval *)data,
                   1072:                    &sc->sc_pps_state.ppsinfo.assert_timestamp);
                   1073: #else
                   1074:                TIMESPEC_TO_TIMEVAL((struct timeval *)data,
                   1075:                    &sc->sc_pps_state.ppsinfo.clear_timestamp);
                   1076: #endif
                   1077:                mutex_spin_exit(&timecounter_lock);
                   1078:                break;
                   1079: #endif
                   1080:
                   1081:        default:
                   1082:                error = EPASSTHROUGH;
                   1083:                break;
                   1084:        }
                   1085:
                   1086:        mutex_spin_exit(&sc->sc_lock);
                   1087:
                   1088: #ifdef IMXUART_DEBUG
                   1089:        if (imxuart_debug)
                   1090:                imxustatus(sc, "imxuioctl ");
                   1091: #endif
                   1092:
                   1093:        return (error);
1.2       matt     1094: }
                   1095:
1.5       bsh      1096: integrate void
                   1097: imxuart_schedrx(struct imxuart_softc *sc)
1.2       matt     1098: {
1.5       bsh      1099:        sc->sc_rx_ready = 1;
                   1100:
                   1101:        /* Wake up the poller. */
                   1102:        softint_schedule(sc->sc_si);
1.2       matt     1103: }
                   1104:
1.5       bsh      1105: void
                   1106: imxuart_break(struct imxuart_softc *sc, bool onoff)
1.2       matt     1107: {
1.5       bsh      1108:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   1109:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   1110:
                   1111:        if (onoff)
                   1112:                SET(sc->sc_ucr1, IMX_UCR1_SNDBRK);
                   1113:        else
                   1114:                CLR(sc->sc_ucr1, IMX_UCR1_SNDBRK);
                   1115:
                   1116:        bus_space_write_4(iot, ioh, IMX_UCR1, sc->sc_ucr1);
1.2       matt     1117: }
                   1118:
                   1119: void
1.5       bsh      1120: imxuart_modem(struct imxuart_softc *sc, int onoff)
1.2       matt     1121: {
1.5       bsh      1122: #ifdef notyet
                   1123:        if (sc->sc_mcr_dtr == 0)
                   1124:                return;
                   1125:
                   1126:        if (onoff)
                   1127:                SET(sc->sc_mcr, sc->sc_mcr_dtr);
                   1128:        else
                   1129:                CLR(sc->sc_mcr, sc->sc_mcr_dtr);
                   1130:
                   1131:        if (!sc->sc_heldchange) {
                   1132:                if (sc->sc_tx_busy) {
                   1133:                        sc->sc_heldtbc = sc->sc_tbc;
                   1134:                        sc->sc_tbc = 0;
                   1135:                        sc->sc_heldchange = 1;
                   1136:                } else
                   1137:                        imxuart_loadchannelregs(sc);
                   1138:        }
                   1139: #endif
1.2       matt     1140: }
                   1141:
1.5       bsh      1142: /*
                   1143:  * RTS output is controlled by UCR2.CTS bit.
                   1144:  * DTR output is controlled by UCR3.DSR bit.
                   1145:  * (i.MX reference manual uses names in DCE mode)
                   1146:  *
                   1147:  * note: if UCR2.CTSC == 1 for automatic HW flow control, UCR2.CTS is ignored.
                   1148:  */
                   1149: void
                   1150: tiocm_to_imxu(struct imxuart_softc *sc, u_long how, int ttybits)
1.2       matt     1151: {
1.5       bsh      1152:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   1153:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   1154:
                   1155:        uint32_t ucr2 = sc->sc_ucr2_d;
                   1156:        uint32_t ucr3 = sc->sc_ucr3;
                   1157:
                   1158:        uint32_t ucr2_mask = 0;
                   1159:        uint32_t ucr3_mask = 0;
                   1160:
                   1161:
                   1162:        if (ISSET(ttybits, TIOCM_DTR))
                   1163:                ucr3_mask = IMX_UCR3_DSR;
                   1164:        if (ISSET(ttybits, TIOCM_RTS))
                   1165:                ucr2_mask = IMX_UCR2_CTS;
                   1166:
                   1167:        switch (how) {
                   1168:        case TIOCMBIC:
                   1169:                CLR(ucr2, ucr2_mask);
                   1170:                CLR(ucr3, ucr3_mask);
                   1171:                break;
                   1172:
                   1173:        case TIOCMBIS:
                   1174:                SET(ucr2, ucr2_mask);
                   1175:                SET(ucr3, ucr3_mask);
                   1176:                break;
                   1177:
                   1178:        case TIOCMSET:
                   1179:                CLR(ucr2, ucr2_mask);
                   1180:                CLR(ucr3, ucr3_mask);
                   1181:                SET(ucr2, ucr2_mask);
                   1182:                SET(ucr3, ucr3_mask);
                   1183:                break;
                   1184:        }
                   1185:
                   1186:        if (ucr3 != sc->sc_ucr3) {
                   1187:                bus_space_write_4(iot, ioh, IMX_UCR3, ucr3);
                   1188:                sc->sc_ucr3 = ucr3;
                   1189:        }
                   1190:
                   1191:        if (ucr2 == sc->sc_ucr2_d)
                   1192:                return;
                   1193:
                   1194:        sc->sc_ucr2_d = ucr2;
                   1195:        /* update CTS bit only */
                   1196:        ucr2 = (sc->sc_ucr2 & ~IMX_UCR2_CTS) |
                   1197:            (ucr2 & IMX_UCR2_CTS);
1.2       matt     1198:
1.5       bsh      1199:        bus_space_write_4(iot, ioh, IMX_UCR2, ucr2);
                   1200:        sc->sc_ucr2 = ucr2;
1.2       matt     1201: }
                   1202:
1.5       bsh      1203: int
                   1204: imxuart_to_tiocm(struct imxuart_softc *sc)
1.2       matt     1205: {
1.5       bsh      1206:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   1207:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   1208:        int ttybits = 0;
                   1209:        uint32_t usr[2];
                   1210:
                   1211:        if (ISSET(sc->sc_ucr3, IMX_UCR3_DSR))
                   1212:                SET(ttybits, TIOCM_DTR);
                   1213:        if (ISSET(sc->sc_ucr2, IMX_UCR2_CTS))
                   1214:                SET(ttybits, TIOCM_RTS);
                   1215:
                   1216:        bus_space_read_region_4(iot, ioh, IMX_USR1, usr, 2);
                   1217:
                   1218:        if (ISSET(usr[0], IMX_USR1_RTSS))
                   1219:                SET(ttybits, TIOCM_CTS);
                   1220:
                   1221:        if (ISSET(usr[1], IMX_USR2_DCDIN))
                   1222:                SET(ttybits, TIOCM_CD);
                   1223:
                   1224: #if 0
                   1225:        /* XXXbsh: I couldn't find the way to read ipp_uart_dsr_dte_i signal,
                   1226:           although there are bits in UART registers to detect delta of DSR.
                   1227:        */
                   1228:        if (ISSET(imxubits, MSR_DSR))
                   1229:                SET(ttybits, TIOCM_DSR);
                   1230: #endif
                   1231:
                   1232:        if (ISSET(usr[1], IMX_USR2_RIIN))
                   1233:                SET(ttybits, TIOCM_RI);
                   1234:
                   1235:
                   1236: #ifdef notyet
                   1237:        if (ISSET(sc->sc_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC))
                   1238:                SET(ttybits, TIOCM_LE);
                   1239: #endif
                   1240:
                   1241:        return (ttybits);
1.2       matt     1242: }
                   1243:
1.5       bsh      1244: static uint32_t
                   1245: cflag_to_ucr2(tcflag_t cflag, uint32_t oldval)
1.2       matt     1246: {
1.5       bsh      1247:        uint32_t val = oldval;
                   1248:
                   1249:        CLR(val,IMX_UCR2_WS|IMX_UCR2_PREN|IMX_UCR2_PROE|IMX_UCR2_STPB);
                   1250:
                   1251:        switch (cflag & CSIZE) {
                   1252:        case CS5:
                   1253:        case CS6:
                   1254:                /* not suppreted. use 7-bits */
                   1255:        case CS7:
                   1256:                break;
                   1257:        case CS8:
                   1258:                SET(val, IMX_UCR2_WS);
                   1259:                break;
                   1260:        }
                   1261:
                   1262:
                   1263:        if (ISSET(cflag, PARENB)) {
                   1264:                SET(val, IMX_UCR2_PREN);
                   1265:
                   1266:                /* odd parity */
                   1267:                if (!ISSET(cflag, PARODD))
                   1268:                        SET(val, IMX_UCR2_PROE);
                   1269:        }
                   1270:
                   1271:        if (ISSET(cflag, CSTOPB))
                   1272:                SET(val, IMX_UCR2_STPB);
                   1273:
                   1274:        val |= IMX_UCR2_TXEN| IMX_UCR2_RXEN|IMX_UCR2_SRST;
                   1275:
                   1276:        return val;
1.2       matt     1277: }
1.5       bsh      1278:
1.2       matt     1279: int
1.5       bsh      1280: imxuparam(struct tty *tp, struct termios *t)
1.2       matt     1281: {
1.5       bsh      1282:        struct imxuart_softc *sc =
                   1283:            device_lookup_private(&imxuart_cd, IMXUART_UNIT(tp->t_dev));
                   1284:        struct imxuart_baudrate_ratio ratio;
                   1285:        uint32_t ucr2;
                   1286:        bool change_speed = tp->t_ospeed != t->c_ospeed;
                   1287:
                   1288:        if (IMXUART_ISALIVE(sc) == 0)
                   1289:                return (EIO);
                   1290:
                   1291:        /* Check requested parameters. */
                   1292:        if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
                   1293:                return (EINVAL);
                   1294:
                   1295:        /*
                   1296:         * For the console, always force CLOCAL and !HUPCL, so that the port
                   1297:         * is always active.
                   1298:         */
                   1299:        if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
                   1300:            ISSET(sc->sc_hwflags, IMXUART_HW_CONSOLE)) {
                   1301:                SET(t->c_cflag, CLOCAL);
                   1302:                CLR(t->c_cflag, HUPCL);
                   1303:        }
                   1304:
                   1305:        /*
                   1306:         * If there were no changes, don't do anything.  This avoids dropping
                   1307:         * input and improves performance when all we did was frob things like
                   1308:         * VMIN and VTIME.
                   1309:         */
                   1310:        if ( !change_speed && tp->t_cflag == t->c_cflag)
                   1311:                return (0);
                   1312:
                   1313:        if (change_speed) {
                   1314:                /* calculate baudrate modulator value */
                   1315:                if (imxuspeed(t->c_ospeed, &ratio) < 0)
                   1316:                        return (EINVAL);
                   1317:                sc->sc_ratio = ratio;
                   1318:        }
                   1319:
                   1320:        ucr2 = cflag_to_ucr2(t->c_cflag, sc->sc_ucr2_d);
                   1321:
                   1322:        mutex_spin_enter(&sc->sc_lock);
                   1323:
                   1324: #if 0  /* flow control stuff.  not yet */
                   1325:        /*
                   1326:         * If we're not in a mode that assumes a connection is present, then
                   1327:         * ignore carrier changes.
                   1328:         */
                   1329:        if (ISSET(t->c_cflag, CLOCAL | MDMBUF))
                   1330:                sc->sc_msr_dcd = 0;
                   1331:        else
                   1332:                sc->sc_msr_dcd = MSR_DCD;
                   1333:        /*
                   1334:         * Set the flow control pins depending on the current flow control
                   1335:         * mode.
                   1336:         */
                   1337:        if (ISSET(t->c_cflag, CRTSCTS)) {
                   1338:                sc->sc_mcr_dtr = MCR_DTR;
                   1339:                sc->sc_mcr_rts = MCR_RTS;
                   1340:                sc->sc_msr_cts = MSR_CTS;
                   1341:                sc->sc_efr = EFR_AUTORTS | EFR_AUTOCTS;
                   1342:        } else if (ISSET(t->c_cflag, MDMBUF)) {
                   1343:                /*
                   1344:                 * For DTR/DCD flow control, make sure we don't toggle DTR for
                   1345:                 * carrier detection.
                   1346:                 */
                   1347:                sc->sc_mcr_dtr = 0;
                   1348:                sc->sc_mcr_rts = MCR_DTR;
                   1349:                sc->sc_msr_cts = MSR_DCD;
                   1350:                sc->sc_efr = 0;
                   1351:        } else {
                   1352:                /*
                   1353:                 * If no flow control, then always set RTS.  This will make
                   1354:                 * the other side happy if it mistakenly thinks we're doing
                   1355:                 * RTS/CTS flow control.
                   1356:                 */
                   1357:                sc->sc_mcr_dtr = MCR_DTR | MCR_RTS;
                   1358:                sc->sc_mcr_rts = 0;
                   1359:                sc->sc_msr_cts = 0;
                   1360:                sc->sc_efr = 0;
                   1361:                if (ISSET(sc->sc_mcr, MCR_DTR))
                   1362:                        SET(sc->sc_mcr, MCR_RTS);
                   1363:                else
                   1364:                        CLR(sc->sc_mcr, MCR_RTS);
                   1365:        }
                   1366:        sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd;
                   1367: #endif
                   1368:
                   1369:        /* And copy to tty. */
                   1370:        tp->t_ispeed = t->c_ospeed;
                   1371:        tp->t_ospeed = t->c_ospeed;
                   1372:        tp->t_cflag = t->c_cflag;
1.2       matt     1373:
1.5       bsh      1374:        if (!change_speed && ucr2 == sc->sc_ucr2_d) {
                   1375:                /* noop */
                   1376:        }
                   1377:        else if (!sc->sc_pending && !sc->sc_tx_busy) {
                   1378:                if (ucr2 != sc->sc_ucr2_d) {
                   1379:                        sc->sc_ucr2_d = ucr2;
                   1380:                        imxuart_load_params(sc);
                   1381:                }
                   1382:                if (change_speed)
                   1383:                        imxuart_load_speed(sc);
                   1384:        }
                   1385:        else {
                   1386:                if (!sc->sc_pending) {
                   1387:                        sc->sc_heldtbc = sc->sc_tbc;
                   1388:                        sc->sc_tbc = 0;
                   1389:                }
                   1390:                sc->sc_pending |=
                   1391:                    (ucr2 == sc->sc_ucr2_d ? 0 : IMXUART_PEND_PARAM) |
                   1392:                    (change_speed ? 0 : IMXUART_PEND_SPEED);
                   1393:                sc->sc_ucr2_d = ucr2;
                   1394:        }
                   1395:
                   1396:        if (!ISSET(t->c_cflag, CHWFLOW)) {
                   1397:                /* Disable the high water mark. */
                   1398:                sc->sc_r_hiwat = 0;
                   1399:                sc->sc_r_lowat = 0;
                   1400:                if (ISSET(sc->sc_rx_flags, IMXUART_RX_TTY_OVERFLOWED)) {
                   1401:                        CLR(sc->sc_rx_flags, IMXUART_RX_TTY_OVERFLOWED);
                   1402:                        imxuart_schedrx(sc);
                   1403:                }
                   1404:                if (ISSET(sc->sc_rx_flags,
                   1405:                        IMXUART_RX_TTY_BLOCKED|IMXUART_RX_IBUF_BLOCKED)) {
                   1406:                        CLR(sc->sc_rx_flags,
                   1407:                            IMXUART_RX_TTY_BLOCKED|IMXUART_RX_IBUF_BLOCKED);
                   1408:                        imxuart_hwiflow(sc);
                   1409:                }
                   1410:        } else {
                   1411:                sc->sc_r_hiwat = imxuart_rbuf_hiwat;
                   1412:                sc->sc_r_lowat = imxuart_rbuf_lowat;
                   1413:        }
                   1414:
                   1415:        mutex_spin_exit(&sc->sc_lock);
                   1416:
                   1417: #if 0
                   1418:        /*
                   1419:         * Update the tty layer's idea of the carrier bit, in case we changed
                   1420:         * CLOCAL or MDMBUF.  We don't hang up here; we only do that by
                   1421:         * explicit request.
                   1422:         */
                   1423:        (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, MSR_DCD));
                   1424: #else
                   1425:        /* XXX: always report that we have DCD */
                   1426:        (void) (*tp->t_linesw->l_modem)(tp, 1);
                   1427: #endif
                   1428:
                   1429: #ifdef IMXUART_DEBUG
                   1430:        if (imxuart_debug)
                   1431:                imxustatus(sc, "imxuparam ");
                   1432: #endif
                   1433:
                   1434:        if (!ISSET(t->c_cflag, CHWFLOW)) {
                   1435:                if (sc->sc_tx_stopped) {
                   1436:                        sc->sc_tx_stopped = 0;
                   1437:                        imxustart(tp);
                   1438:                }
                   1439:        }
                   1440:
                   1441:        return (0);
                   1442: }
                   1443:
                   1444: void
                   1445: imxuart_iflush(struct imxuart_softc *sc)
                   1446: {
                   1447:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   1448:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   1449: #ifdef DIAGNOSTIC
                   1450:        uint32_t reg = 0xffff;
                   1451: #endif
                   1452:        int timo;
                   1453:
                   1454:        timo = 50000;
                   1455:        /* flush any pending I/O */
                   1456:        while (ISSET(bus_space_read_4(iot, ioh, IMX_USR2), IMX_USR2_RDR)
                   1457:            && --timo)
                   1458: #ifdef DIAGNOSTIC
                   1459:                reg =
                   1460: #else
                   1461:                    (void)
                   1462: #endif
                   1463:                    bus_space_read_4(iot, ioh, IMX_URXD);
                   1464: #ifdef DIAGNOSTIC
                   1465:        if (!timo)
                   1466:                aprint_error_dev(sc->sc_dev, "imxuart_iflush timeout %02x\n", reg);
                   1467: #endif
                   1468: }
                   1469:
                   1470: int
                   1471: imxuhwiflow(struct tty *tp, int block)
                   1472: {
                   1473:        struct imxuart_softc *sc =
                   1474:            device_lookup_private(&imxuart_cd, IMXUART_UNIT(tp->t_dev));
                   1475:
                   1476:        if (IMXUART_ISALIVE(sc) == 0)
                   1477:                return (0);
                   1478:
                   1479: #ifdef notyet
                   1480:        if (sc->sc_mcr_rts == 0)
                   1481:                return (0);
                   1482: #endif
                   1483:
                   1484:        mutex_spin_enter(&sc->sc_lock);
                   1485:
                   1486:        if (block) {
                   1487:                if (!ISSET(sc->sc_rx_flags, IMXUART_RX_TTY_BLOCKED)) {
                   1488:                        SET(sc->sc_rx_flags, IMXUART_RX_TTY_BLOCKED);
                   1489:                        imxuart_hwiflow(sc);
                   1490:                }
                   1491:        } else {
                   1492:                if (ISSET(sc->sc_rx_flags, IMXUART_RX_TTY_OVERFLOWED)) {
                   1493:                        CLR(sc->sc_rx_flags, IMXUART_RX_TTY_OVERFLOWED);
                   1494:                        imxuart_schedrx(sc);
                   1495:                }
                   1496:                if (ISSET(sc->sc_rx_flags, IMXUART_RX_TTY_BLOCKED)) {
                   1497:                        CLR(sc->sc_rx_flags, IMXUART_RX_TTY_BLOCKED);
                   1498:                        imxuart_hwiflow(sc);
                   1499:                }
                   1500:        }
                   1501:
                   1502:        mutex_spin_exit(&sc->sc_lock);
                   1503:        return (1);
                   1504: }
                   1505:
                   1506: /*
                   1507:  * (un)block input via hw flowcontrol
                   1508:  */
                   1509: void
                   1510: imxuart_hwiflow(struct imxuart_softc *sc)
                   1511: {
                   1512: #ifdef notyet
                   1513:        struct imxuart_regs *regsp= &sc->sc_regs;
                   1514:
                   1515:        if (sc->sc_mcr_rts == 0)
                   1516:                return;
                   1517:
                   1518:        if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
                   1519:                CLR(sc->sc_mcr, sc->sc_mcr_rts);
                   1520:                CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
                   1521:        } else {
                   1522:                SET(sc->sc_mcr, sc->sc_mcr_rts);
                   1523:                SET(sc->sc_mcr_active, sc->sc_mcr_rts);
                   1524:        }
                   1525:        UR_WRITE_1(regsp, IMXUART_REG_MCR, sc->sc_mcr_active);
                   1526: #endif
                   1527: }
                   1528:
                   1529:
                   1530: void
                   1531: imxustart(struct tty *tp)
                   1532: {
                   1533:        struct imxuart_softc *sc =
                   1534:            device_lookup_private(&imxuart_cd, IMXUART_UNIT(tp->t_dev));
                   1535:        int s;
                   1536:        u_char *tba;
                   1537:        int tbc;
                   1538:        u_int n;
                   1539:        u_int space;
                   1540:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   1541:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   1542:
                   1543:        if (IMXUART_ISALIVE(sc) == 0)
                   1544:                return;
                   1545:
                   1546:        s = spltty();
                   1547:        if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
                   1548:                goto out;
                   1549:        if (sc->sc_tx_stopped)
                   1550:                goto out;
                   1551:        if (!ttypull(tp))
                   1552:                goto out;
                   1553:
                   1554:        /* Grab the first contiguous region of buffer space. */
                   1555:        tba = tp->t_outq.c_cf;
                   1556:        tbc = ndqb(&tp->t_outq, 0);
                   1557:
                   1558:        mutex_spin_enter(&sc->sc_lock);
                   1559:
                   1560:        sc->sc_tba = tba;
                   1561:        sc->sc_tbc = tbc;
                   1562:
                   1563:        SET(tp->t_state, TS_BUSY);
                   1564:        sc->sc_tx_busy = 1;
                   1565:
                   1566:        space = imxuart_txfifo_space(sc);
                   1567:        n = MIN(sc->sc_tbc, space);
                   1568:
                   1569:        bus_space_write_multi_1(iot, ioh, IMX_UTXD, sc->sc_tba, n);
                   1570:        sc->sc_tbc -= n;
                   1571:        sc->sc_tba += n;
                   1572:
                   1573:        /* Enable transmit completion interrupts */
                   1574:        imxuart_control_txint(sc, true);
                   1575:
                   1576:        mutex_spin_exit(&sc->sc_lock);
                   1577: out:
                   1578:        splx(s);
                   1579:        return;
                   1580: }
                   1581:
                   1582: /*
                   1583:  * Stop output on a line.
                   1584:  */
                   1585: void
                   1586: imxustop(struct tty *tp, int flag)
                   1587: {
                   1588:        struct imxuart_softc *sc =
                   1589:            device_lookup_private(&imxuart_cd, IMXUART_UNIT(tp->t_dev));
                   1590:
                   1591:        mutex_spin_enter(&sc->sc_lock);
                   1592:        if (ISSET(tp->t_state, TS_BUSY)) {
                   1593:                /* Stop transmitting at the next chunk. */
                   1594:                sc->sc_tbc = 0;
                   1595:                sc->sc_heldtbc = 0;
                   1596:                if (!ISSET(tp->t_state, TS_TTSTOP))
                   1597:                        SET(tp->t_state, TS_FLUSH);
                   1598:        }
                   1599:        mutex_spin_exit(&sc->sc_lock);
                   1600: }
                   1601:
                   1602: void
                   1603: imxudiag(void *arg)
                   1604: {
                   1605: #ifdef notyet
                   1606:        struct imxuart_softc *sc = arg;
                   1607:        int overflows, floods;
                   1608:
                   1609:        mutex_spin_enter(&sc->sc_lock);
                   1610:        overflows = sc->sc_overflows;
                   1611:        sc->sc_overflows = 0;
                   1612:        floods = sc->sc_floods;
                   1613:        sc->sc_floods = 0;
                   1614:        sc->sc_errors = 0;
                   1615:        mutex_spin_exit(&sc->sc_lock);
                   1616:
                   1617:        log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n",
                   1618:            device_xname(sc->sc_dev),
                   1619:            overflows, overflows == 1 ? "" : "s",
                   1620:            floods, floods == 1 ? "" : "s");
                   1621: #endif
                   1622: }
                   1623:
                   1624: integrate void
                   1625: imxuart_rxsoft(struct imxuart_softc *sc, struct tty *tp)
                   1626: {
                   1627:        int (*rint)(int, struct tty *) = tp->t_linesw->l_rint;
                   1628:        u_int cc, scc, outp;
                   1629:        uint16_t data;
                   1630:        u_int code;
                   1631:
                   1632:        scc = cc = IMXUART_RBUF_AVAIL(sc);
                   1633:
                   1634: #if 0
                   1635:        if (cc == imxuart_rbuf_size-1) {
                   1636:                sc->sc_floods++;
                   1637:                if (sc->sc_errors++ == 0)
                   1638:                        callout_reset(&sc->sc_diag_callout, 60 * hz,
                   1639:                            imxudiag, sc);
                   1640:        }
                   1641: #endif
                   1642:
                   1643:        /* If not yet open, drop the entire buffer content here */
                   1644:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
                   1645:                sc->sc_rbuf_out = sc->sc_rbuf_in;
                   1646:                cc = 0;
                   1647:        }
                   1648:
                   1649:        outp = sc->sc_rbuf_out;
                   1650:
                   1651: #define        ERRBITS (IMX_URXD_PRERR|IMX_URXD_BRK|IMX_URXD_FRMERR|IMX_URXD_OVRRUN)
                   1652:
                   1653:        while (cc) {
                   1654:                data = sc->sc_rbuf[outp];
                   1655:                code = data & IMX_URXD_RX_DATA;
                   1656:                if (ISSET(data, ERRBITS)) {
                   1657:                        if (sc->sc_errors.err == 0)
                   1658:                                callout_reset(&sc->sc_diag_callout,
                   1659:                                    60 * hz, imxudiag, sc);
                   1660:                        if (ISSET(data, IMX_URXD_OVRRUN))
                   1661:                                sc->sc_errors.ovrrun++;
                   1662:                        if (ISSET(data, IMX_URXD_BRK)) {
                   1663:                                sc->sc_errors.brk++;
                   1664:                                SET(code, TTY_FE);
                   1665:                        }
                   1666:                        if (ISSET(data, IMX_URXD_FRMERR)) {
                   1667:                                sc->sc_errors.frmerr++;
                   1668:                                SET(code, TTY_FE);
                   1669:                        }
                   1670:                        if (ISSET(data, IMX_URXD_PRERR)) {
                   1671:                                sc->sc_errors.prerr++;
                   1672:                                SET(code, TTY_PE);
                   1673:                        }
                   1674:                }
                   1675:                if ((*rint)(code, tp) == -1) {
                   1676:                        /*
                   1677:                         * The line discipline's buffer is out of space.
                   1678:                         */
                   1679:                        if (!ISSET(sc->sc_rx_flags, IMXUART_RX_TTY_BLOCKED)) {
                   1680:                                /*
                   1681:                                 * We're either not using flow control, or the
                   1682:                                 * line discipline didn't tell us to block for
                   1683:                                 * some reason.  Either way, we have no way to
                   1684:                                 * know when there's more space available, so
                   1685:                                 * just drop the rest of the data.
                   1686:                                 */
                   1687:                                sc->sc_rbuf_out = sc->sc_rbuf_in;
                   1688:                                cc = 0;
                   1689:                        } else {
                   1690:                                /*
                   1691:                                 * Don't schedule any more receive processing
                   1692:                                 * until the line discipline tells us there's
                   1693:                                 * space available (through imxuhwiflow()).
                   1694:                                 * Leave the rest of the data in the input
                   1695:                                 * buffer.
                   1696:                                 */
                   1697:                                SET(sc->sc_rx_flags, IMXUART_RX_TTY_OVERFLOWED);
                   1698:                        }
                   1699:                        break;
                   1700:                }
                   1701:                outp = IMXUART_RBUF_INC(sc, outp, 1);
                   1702:                cc--;
                   1703:        }
                   1704:
                   1705:        if (cc != scc) {
                   1706:                sc->sc_rbuf_out = outp;
                   1707:                mutex_spin_enter(&sc->sc_lock);
                   1708:
                   1709:                cc = IMXUART_RBUF_SPACE(sc);
                   1710:
                   1711:                /* Buffers should be ok again, release possible block. */
                   1712:                if (cc >= sc->sc_r_lowat) {
                   1713:                        if (ISSET(sc->sc_rx_flags, IMXUART_RX_IBUF_OVERFLOWED)) {
                   1714:                                CLR(sc->sc_rx_flags, IMXUART_RX_IBUF_OVERFLOWED);
                   1715:                                imxuart_control_rxint(sc, true);
                   1716:                        }
                   1717:                        if (ISSET(sc->sc_rx_flags, IMXUART_RX_IBUF_BLOCKED)) {
                   1718:                                CLR(sc->sc_rx_flags, IMXUART_RX_IBUF_BLOCKED);
                   1719:                                imxuart_hwiflow(sc);
                   1720:                        }
                   1721:                }
                   1722:                mutex_spin_exit(&sc->sc_lock);
                   1723:        }
                   1724: }
                   1725:
                   1726: integrate void
                   1727: imxuart_txsoft(struct imxuart_softc *sc, struct tty *tp)
                   1728: {
                   1729:
                   1730:        CLR(tp->t_state, TS_BUSY);
                   1731:        if (ISSET(tp->t_state, TS_FLUSH))
                   1732:                CLR(tp->t_state, TS_FLUSH);
                   1733:        else
                   1734:                ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
                   1735:        (*tp->t_linesw->l_start)(tp);
                   1736: }
                   1737:
                   1738: integrate void
                   1739: imxuart_stsoft(struct imxuart_softc *sc, struct tty *tp)
                   1740: {
                   1741: #ifdef notyet
                   1742:        u_char msr, delta;
                   1743:
                   1744:        mutex_spin_enter(&sc->sc_lock);
                   1745:        msr = sc->sc_msr;
                   1746:        delta = sc->sc_msr_delta;
                   1747:        sc->sc_msr_delta = 0;
                   1748:        mutex_spin_exit(&sc->sc_lock);
                   1749:
                   1750:        if (ISSET(delta, sc->sc_msr_dcd)) {
                   1751:                /*
                   1752:                 * Inform the tty layer that carrier detect changed.
                   1753:                 */
                   1754:                (void) (*tp->t_linesw->l_modem)(tp, ISSET(msr, MSR_DCD));
                   1755:        }
                   1756:
                   1757:        if (ISSET(delta, sc->sc_msr_cts)) {
                   1758:                /* Block or unblock output according to flow control. */
                   1759:                if (ISSET(msr, sc->sc_msr_cts)) {
                   1760:                        sc->sc_tx_stopped = 0;
                   1761:                        (*tp->t_linesw->l_start)(tp);
                   1762:                } else {
                   1763:                        sc->sc_tx_stopped = 1;
                   1764:                }
                   1765:        }
                   1766:
                   1767: #endif
                   1768: #ifdef IMXUART_DEBUG
                   1769:        if (imxuart_debug)
                   1770:                imxustatus(sc, "imxuart_stsoft");
                   1771: #endif
                   1772: }
                   1773:
                   1774: void
                   1775: imxusoft(void *arg)
                   1776: {
                   1777:        struct imxuart_softc *sc = arg;
                   1778:        struct tty *tp;
                   1779:
                   1780:        if (IMXUART_ISALIVE(sc) == 0)
                   1781:                return;
                   1782:
                   1783:        tp = sc->sc_tty;
                   1784:
                   1785:        if (sc->sc_rx_ready) {
                   1786:                sc->sc_rx_ready = 0;
                   1787:                imxuart_rxsoft(sc, tp);
                   1788:        }
                   1789:
                   1790:        if (sc->sc_st_check) {
                   1791:                sc->sc_st_check = 0;
                   1792:                imxuart_stsoft(sc, tp);
                   1793:        }
                   1794:
                   1795:        if (sc->sc_tx_done) {
                   1796:                sc->sc_tx_done = 0;
                   1797:                imxuart_txsoft(sc, tp);
                   1798:        }
                   1799: }
                   1800:
                   1801: int
                   1802: imxuintr(void *arg)
                   1803: {
                   1804:        struct imxuart_softc *sc = arg;
                   1805:        uint32_t usr1, usr2;
                   1806:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   1807:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   1808:
                   1809:
                   1810:        if (IMXUART_ISALIVE(sc) == 0)
                   1811:                return (0);
                   1812:
                   1813:        mutex_spin_enter(&sc->sc_lock);
                   1814:
                   1815:        usr2 = bus_space_read_4(iot, ioh, IMX_USR2);
                   1816:
                   1817:
                   1818:        do {
                   1819:                bus_space_write_4(iot, ioh, IMX_USR2,
                   1820:                    usr2 & (IMX_USR2_BRCD|IMX_USR2_ORE));
                   1821:                if (usr2 & IMX_USR2_BRCD) {
                   1822:                        /* Break signal detected */
                   1823:                        int cn_trapped = 0;
                   1824:
                   1825:                        cn_check_magic(sc->sc_tty->t_dev,
                   1826:                                       CNC_BREAK, imxuart_cnm_state);
                   1827:                        if (cn_trapped)
                   1828:                                continue;
                   1829: #if defined(KGDB) && !defined(DDB)
                   1830:                        if (ISSET(sc->sc_hwflags, IMXUART_HW_KGDB)) {
                   1831:                                kgdb_connect(1);
                   1832:                                continue;
                   1833:                        }
                   1834: #endif
                   1835:                }
                   1836:
                   1837:                if (usr2 & IMX_USR2_RDR)
                   1838:                        imxuintr_read(sc);
                   1839:
                   1840: #ifdef IMXUART_PPS
                   1841:                {
                   1842:                        u_char  msr, delta;
                   1843:
                   1844:                        msr = CSR_READ_1(regsp, IMXUART_REG_MSR);
                   1845:                        delta = msr ^ sc->sc_msr;
                   1846:                        sc->sc_msr = msr;
                   1847:                        if ((sc->sc_pps_state.ppsparam.mode & PPS_CAPTUREBOTH) &&
                   1848:                            (delta & MSR_DCD)) {
                   1849:                                mutex_spin_enter(&timecounter_lock);
                   1850:                                pps_capture(&sc->sc_pps_state);
                   1851:                                pps_event(&sc->sc_pps_state,
                   1852:                                    (msr & MSR_DCD) ?
                   1853:                                    PPS_CAPTUREASSERT :
                   1854:                                    PPS_CAPTURECLEAR);
                   1855:                                mutex_spin_exit(&timecounter_lock);
                   1856:                        }
                   1857:                }
                   1858: #endif
                   1859:
                   1860: #ifdef notyet
                   1861:                /*
                   1862:                 * Process normal status changes
                   1863:                 */
                   1864:                if (ISSET(delta, sc->sc_msr_mask)) {
                   1865:                        SET(sc->sc_msr_delta, delta);
                   1866:
                   1867:                        /*
                   1868:                         * Stop output immediately if we lose the output
                   1869:                         * flow control signal or carrier detect.
                   1870:                         */
                   1871:                        if (ISSET(~msr, sc->sc_msr_mask)) {
                   1872:                                sc->sc_tbc = 0;
                   1873:                                sc->sc_heldtbc = 0;
                   1874: #ifdef IMXUART_DEBUG
                   1875:                                if (imxuart_debug)
                   1876:                                        imxustatus(sc, "imxuintr  ");
                   1877: #endif
                   1878:                        }
                   1879:
                   1880:                        sc->sc_st_check = 1;
                   1881:                }
                   1882: #endif
                   1883:
                   1884:                usr2 = bus_space_read_4(iot, ioh, IMX_USR2);
                   1885:        } while (usr2 & (IMX_USR2_RDR|IMX_USR2_BRCD));
                   1886:
                   1887:        usr1 = bus_space_read_4(iot, ioh, IMX_USR1);
                   1888:        if (usr1 & IMX_USR1_TRDY)
                   1889:                imxuintr_send(sc);
                   1890:
                   1891:        mutex_spin_exit(&sc->sc_lock);
                   1892:
                   1893:        /* Wake up the poller. */
                   1894:        softint_schedule(sc->sc_si);
                   1895:
1.9       tls      1896: #ifdef RND_COM
1.5       bsh      1897:        rnd_add_uint32(&sc->rnd_source, iir | lsr);
                   1898: #endif
                   1899:
                   1900:        return (1);
                   1901: }
                   1902:
                   1903:
                   1904: /*
                   1905:  * called when there is least one character in rxfifo
                   1906:  *
                   1907:  */
                   1908:
                   1909: static void
                   1910: imxuintr_read(struct imxuart_softc *sc)
                   1911: {
                   1912:        int cc;
                   1913:        uint16_t rd;
                   1914:        uint32_t usr2;
                   1915:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   1916:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   1917:
                   1918:        cc = IMXUART_RBUF_SPACE(sc);
                   1919:
                   1920:        /* clear aging timer interrupt */
                   1921:        bus_space_write_4(iot, ioh, IMX_USR1, IMX_USR1_AGTIM);
                   1922:
                   1923:        while (cc > 0) {
                   1924:                int cn_trapped = 0;
                   1925:
                   1926:
                   1927:                sc->sc_rbuf[sc->sc_rbuf_in] = rd =
                   1928:                    bus_space_read_4(iot, ioh, IMX_URXD);
                   1929:
                   1930:                cn_check_magic(sc->sc_tty->t_dev,
                   1931:                    rd & 0xff, imxuart_cnm_state);
                   1932:
                   1933:                if (!cn_trapped) {
                   1934:                        sc->sc_rbuf_in = IMXUART_RBUF_INC(sc, sc->sc_rbuf_in, 1);
                   1935:                        cc--;
                   1936:                }
                   1937:
                   1938:                usr2 = bus_space_read_4(iot, ioh, IMX_USR2);
                   1939:                if (!(usr2 & IMX_USR2_RDR))
                   1940:                        break;
                   1941:        }
                   1942:
                   1943:        /*
                   1944:         * Current string of incoming characters ended because
                   1945:         * no more data was available or we ran out of space.
                   1946:         * Schedule a receive event if any data was received.
                   1947:         * If we're out of space, turn off receive interrupts.
                   1948:         */
                   1949:        if (!ISSET(sc->sc_rx_flags, IMXUART_RX_TTY_OVERFLOWED))
                   1950:                sc->sc_rx_ready = 1;
                   1951:        /*
                   1952:         * See if we are in danger of overflowing a buffer. If
                   1953:         * so, use hardware flow control to ease the pressure.
                   1954:         */
                   1955:        if (!ISSET(sc->sc_rx_flags, IMXUART_RX_IBUF_BLOCKED) &&
                   1956:            cc < sc->sc_r_hiwat) {
                   1957:                sc->sc_rx_flags |= IMXUART_RX_IBUF_BLOCKED;
                   1958:                imxuart_hwiflow(sc);
                   1959:        }
                   1960:
                   1961:        /*
                   1962:         * If we're out of space, disable receive interrupts
                   1963:         * until the queue has drained a bit.
                   1964:         */
                   1965:        if (!cc) {
                   1966:                sc->sc_rx_flags |= IMXUART_RX_IBUF_OVERFLOWED;
                   1967:                imxuart_control_rxint(sc, false);
                   1968:        }
                   1969: }
                   1970:
                   1971:
                   1972:
                   1973: /*
                   1974:  * find how many chars we can put into tx-fifo
                   1975:  */
                   1976: static u_int
                   1977: imxuart_txfifo_space(struct imxuart_softc *sc)
                   1978: {
                   1979:        uint32_t usr1, usr2;
                   1980:        u_int cc;
                   1981:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   1982:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   1983:
                   1984:        usr2 = bus_space_read_4(iot, ioh, IMX_USR2);
                   1985:        if (usr2 & IMX_USR2_TXFE)
                   1986:                cc = sc->sc_txfifo_len;
                   1987:        else {
                   1988:                usr1 = bus_space_read_4(iot, ioh, IMX_USR1);
                   1989:                if (usr1 & IMX_USR1_TRDY)
                   1990:                        cc = sc->sc_txfifo_thresh;
                   1991:                else
                   1992:                        cc = 0;
                   1993:        }
                   1994:
                   1995:        return cc;
                   1996: }
                   1997:
                   1998: void
                   1999: imxuintr_send(struct imxuart_softc *sc)
                   2000: {
                   2001:        uint32_t usr2;
                   2002:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   2003:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   2004:        int cc = 0;
                   2005:
                   2006:        usr2 = bus_space_read_4(iot, ioh, IMX_USR2);
                   2007:
                   2008:        if (sc->sc_pending) {
                   2009:                if (usr2 & IMX_USR2_TXFE) {
                   2010:                        imxuart_load_pendings(sc);
                   2011:                        sc->sc_tbc = sc->sc_heldtbc;
                   2012:                        sc->sc_heldtbc = 0;
                   2013:                }
                   2014:                else {
                   2015:                        /* wait for TX fifo empty */
                   2016:                        imxuart_control_txint(sc, true);
                   2017:                        return;
                   2018:                }
                   2019:        }
                   2020:
                   2021:        cc = imxuart_txfifo_space(sc);
                   2022:        cc = MIN(cc, sc->sc_tbc);
                   2023:
                   2024:        if (cc > 0) {
                   2025:                bus_space_write_multi_1(iot, ioh, IMX_UTXD, sc->sc_tba, cc);
                   2026:                sc->sc_tbc -= cc;
                   2027:                sc->sc_tba += cc;
                   2028:        }
                   2029:
                   2030:        if (sc->sc_tbc > 0)
                   2031:                imxuart_control_txint(sc, true);
                   2032:        else {
                   2033:                /* no more chars to send.
                   2034:                   we don't need tx interrupt any more. */
                   2035:                imxuart_control_txint(sc, false);
                   2036:                if (sc->sc_tx_busy) {
                   2037:                        sc->sc_tx_busy = 0;
                   2038:                        sc->sc_tx_done = 1;
                   2039:                }
                   2040:        }
                   2041: }
                   2042:
                   2043: static void
                   2044: imxuart_disable_all_interrupts(struct imxuart_softc *sc)
                   2045: {
                   2046:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   2047:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   2048:
                   2049:        sc->sc_ucr1 &= ~IMXUART_INTRS_UCR1;
                   2050:        sc->sc_ucr2 &= ~IMXUART_INTRS_UCR2;
                   2051:        sc->sc_ucr3 &= ~IMXUART_INTRS_UCR3;
                   2052:        sc->sc_ucr4 &= ~IMXUART_INTRS_UCR4;
                   2053:
                   2054:
                   2055:        bus_space_write_region_4(iot, ioh, IMX_UCR1, sc->sc_ucr, 4);
                   2056: }
                   2057:
                   2058: static void
                   2059: imxuart_control_rxint(struct imxuart_softc *sc, bool enable)
                   2060: {
                   2061:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   2062:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   2063:        uint32_t ucr1, ucr2;
                   2064:
                   2065:        ucr1 = sc->sc_ucr1;
                   2066:        ucr2 = sc->sc_ucr2;
                   2067:
                   2068:        if (enable) {
                   2069:                ucr1 |= IMX_UCR1_RRDYEN;
                   2070:                ucr2 |= IMX_UCR2_ATEN;
                   2071:        }
                   2072:        else {
                   2073:                ucr1 &= ~IMX_UCR1_RRDYEN;
                   2074:                ucr2 &= ~IMX_UCR2_ATEN;
                   2075:        }
                   2076:
                   2077:        if (ucr1 != sc->sc_ucr1 || ucr2 != sc->sc_ucr2) {
                   2078:                sc->sc_ucr1 = ucr1;
                   2079:                sc->sc_ucr2 = ucr2;
                   2080:                bus_space_write_region_4(iot, ioh, IMX_UCR1, sc->sc_ucr, 2);
                   2081:        }
                   2082: }
                   2083:
                   2084: static void
                   2085: imxuart_control_txint(struct imxuart_softc *sc, bool enable)
                   2086: {
                   2087:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   2088:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   2089:        uint32_t ucr1;
                   2090:        uint32_t mask;
                   2091:
                   2092:        /* if parameter change is pending, get interrupt when Tx fifo
                   2093:           is completely empty.  otherwise, get interrupt when txfifo
                   2094:           has less characters than threshold */
                   2095:        mask = sc->sc_pending ? IMX_UCR1_TXMPTYEN : IMX_UCR1_TRDYEN;
                   2096:
                   2097:        ucr1 = sc->sc_ucr1;
                   2098:
                   2099:        CLR(ucr1, IMX_UCR1_TXMPTYEN|IMX_UCR1_TRDYEN);
                   2100:        if (enable)
                   2101:                SET(ucr1, mask);
                   2102:
                   2103:        if (ucr1 != sc->sc_ucr1) {
                   2104:                bus_space_write_4(iot, ioh, IMX_UCR1, ucr1);
                   2105:                sc->sc_ucr1 = ucr1;
                   2106:        }
                   2107: }
                   2108:
                   2109:
                   2110: static void
                   2111: imxuart_load_params(struct imxuart_softc *sc)
                   2112: {
                   2113:        uint32_t ucr2;
                   2114:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   2115:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   2116:
                   2117:        ucr2 = (sc->sc_ucr2_d & ~IMX_UCR2_ATEN) |
                   2118:            (sc->sc_ucr2 & IMX_UCR2_ATEN);
                   2119:
                   2120:        bus_space_write_4(iot, ioh, IMX_UCR2, ucr2);
                   2121:        sc->sc_ucr2 = ucr2;
                   2122: }
                   2123:
                   2124: static void
                   2125: imxuart_load_speed(struct imxuart_softc *sc)
                   2126: {
                   2127:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   2128:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   2129:        int n, rfdiv, ufcr;
                   2130:
                   2131: #ifdef notyet
                   2132:        /*
                   2133:         * Set the FIFO threshold based on the receive speed.
                   2134:         *
                   2135:         *  * If it's a low speed, it's probably a mouse or some other
                   2136:         *    interactive device, so set the threshold low.
                   2137:         *  * If it's a high speed, trim the trigger level down to prevent
                   2138:         *    overflows.
                   2139:         *  * Otherwise set it a bit higher.
                   2140:         */
                   2141:        if (t->c_ospeed <= 1200)
                   2142:                sc->sc_fifo = FIFO_ENABLE | FIFO_TRIGGER_1;
                   2143:        else if (t->c_ospeed <= 38400)
                   2144:                sc->sc_fifo = FIFO_ENABLE | FIFO_TRIGGER_8;
                   2145:        else
                   2146:                sc->sc_fifo = FIFO_ENABLE | FIFO_TRIGGER_4;
                   2147: #endif
                   2148:
                   2149:        n = 32 - sc->sc_txfifo_thresh;
                   2150:        n = MAX(2, n);
                   2151:
                   2152:        rfdiv = IMX_UFCR_DIVIDER_TO_RFDIV(imxuart_freqdiv);
                   2153:
                   2154:        ufcr = (n << IMX_UFCR_TXTL_SHIFT) |
                   2155:                (rfdiv << IMX_UFCR_RFDIV_SHIFT) |
                   2156:                (16 << IMX_UFCR_RXTL_SHIFT);
                   2157:
                   2158:        /* keep DCE/DTE bit */
                   2159:        ufcr |= bus_space_read_4(iot, ioh, IMX_UFCR) & IMX_UFCR_DCEDTE;
                   2160:
                   2161:        bus_space_write_4(iot, ioh, IMX_UFCR, ufcr);
                   2162:
                   2163:        /* UBIR must updated before UBMR */
                   2164:        bus_space_write_4(iot, ioh,
                   2165:            IMX_UBIR, sc->sc_ratio.numerator);
                   2166:        bus_space_write_4(iot, ioh,
                   2167:            IMX_UBMR, sc->sc_ratio.modulator);
                   2168:
                   2169:
                   2170: }
                   2171:
                   2172:
                   2173: static void
                   2174: imxuart_load_pendings(struct imxuart_softc *sc)
                   2175: {
                   2176:        if (sc->sc_pending & IMXUART_PEND_PARAM)
                   2177:                imxuart_load_params(sc);
                   2178:        if (sc->sc_pending & IMXUART_PEND_SPEED)
                   2179:                imxuart_load_speed(sc);
                   2180:        sc->sc_pending = 0;
                   2181: }
                   2182:
                   2183: #if defined(IMXUARTCONSOLE) || defined(KGDB)
                   2184:
                   2185: /*
                   2186:  * The following functions are polled getc and putc routines, shared
                   2187:  * by the console and kgdb glue.
                   2188:  *
                   2189:  * The read-ahead code is so that you can detect pending in-band
                   2190:  * cn_magic in polled mode while doing output rather than having to
                   2191:  * wait until the kernel decides it needs input.
                   2192:  */
                   2193:
                   2194: #define        READAHEAD_RING_LEN      16
                   2195: static int imxuart_readahead[READAHEAD_RING_LEN];
                   2196: static int imxuart_readahead_in = 0;
                   2197: static int imxuart_readahead_out = 0;
                   2198: #define        READAHEAD_IS_EMPTY()    (imxuart_readahead_in==imxuart_readahead_out)
                   2199: #define        READAHEAD_IS_FULL()     \
                   2200:        (((imxuart_readahead_in+1) & (READAHEAD_RING_LEN-1)) ==imxuart_readahead_out)
                   2201:
                   2202: int
                   2203: imxuart_common_getc(dev_t dev, struct imxuart_regs *regsp)
                   2204: {
                   2205:        int s = splserial();
                   2206:        u_char c;
                   2207:        bus_space_tag_t iot = regsp->ur_iot;
                   2208:        bus_space_handle_t ioh = regsp->ur_ioh;
                   2209:        uint32_t usr2;
                   2210:
                   2211:        /* got a character from reading things earlier */
                   2212:        if (imxuart_readahead_in != imxuart_readahead_out) {
                   2213:
                   2214:                c = imxuart_readahead[imxuart_readahead_out];
                   2215:                imxuart_readahead_out = (imxuart_readahead_out + 1) &
                   2216:                    (READAHEAD_RING_LEN-1);
                   2217:                splx(s);
                   2218:                return (c);
                   2219:        }
                   2220:
                   2221:        /* block until a character becomes available */
                   2222:        while (!((usr2 = bus_space_read_4(iot, ioh, IMX_USR2)) & IMX_USR2_RDR))
                   2223:                ;
                   2224:
                   2225:        c = 0xff & bus_space_read_4(iot, ioh, IMX_URXD);
                   2226:
                   2227:        {
1.11.2.2! tls      2228:                int __attribute__((__unused__))cn_trapped = 0; /* unused */
1.5       bsh      2229: #ifdef DDB
                   2230:                extern int db_active;
                   2231:                if (!db_active)
                   2232: #endif
                   2233:                        cn_check_magic(dev, c, imxuart_cnm_state);
                   2234:        }
                   2235:        splx(s);
                   2236:        return (c);
                   2237: }
                   2238:
                   2239: void
                   2240: imxuart_common_putc(dev_t dev, struct imxuart_regs *regsp, int c)
                   2241: {
                   2242:        int s = splserial();
                   2243:        int cin, timo;
                   2244:        bus_space_tag_t iot = regsp->ur_iot;
                   2245:        bus_space_handle_t ioh = regsp->ur_ioh;
                   2246:        uint32_t usr2;
                   2247:
                   2248:        if (!READAHEAD_IS_FULL() &&
                   2249:            ((usr2 = bus_space_read_4(iot, ioh, IMX_USR2)) & IMX_USR2_RDR)) {
                   2250:
1.11.2.2! tls      2251:                int __attribute__((__unused__))cn_trapped = 0;
1.5       bsh      2252:                cin = bus_space_read_4(iot, ioh, IMX_URXD);
                   2253:                cn_check_magic(dev, cin & 0xff, imxuart_cnm_state);
                   2254:                imxuart_readahead_in = (imxuart_readahead_in + 1) &
                   2255:                    (READAHEAD_RING_LEN-1);
                   2256:        }
                   2257:
                   2258:        /* wait for any pending transmission to finish */
                   2259:        timo = 150000;
                   2260:        do {
                   2261:                if (bus_space_read_4(iot, ioh, IMX_USR1) & IMX_USR1_TRDY) {
                   2262:                        bus_space_write_4(iot, ioh, IMX_UTXD, c);
                   2263:                        break;
                   2264:                }
                   2265:        } while(--timo > 0);
                   2266:
                   2267:        IMXUART_BARRIER(regsp, BR | BW);
                   2268:
                   2269:        splx(s);
                   2270: }
                   2271:
                   2272: /*
                   2273:  * Initialize UART for use as console or KGDB line.
                   2274:  */
                   2275: int
                   2276: imxuart_init(struct imxuart_regs *regsp, int rate, tcflag_t cflag)
                   2277: {
                   2278:        struct imxuart_baudrate_ratio ratio;
                   2279:        int rfdiv = IMX_UFCR_DIVIDER_TO_RFDIV(imxuart_freqdiv);
                   2280:        uint32_t ufcr;
                   2281:
                   2282:        if (bus_space_map(regsp->ur_iot, regsp->ur_iobase, IMX_UART_SIZE, 0,
                   2283:                &regsp->ur_ioh))
                   2284:                return ENOMEM; /* ??? */
                   2285:
                   2286:        if (imxuspeed(rate, &ratio) < 0)
                   2287:                return EINVAL;
                   2288:
                   2289:        /* UBIR must updated before UBMR */
                   2290:        bus_space_write_4(regsp->ur_iot, regsp->ur_ioh,
                   2291:            IMX_UBIR, ratio.numerator);
                   2292:        bus_space_write_4(regsp->ur_iot, regsp->ur_ioh,
                   2293:            IMX_UBMR, ratio.modulator);
                   2294:
                   2295:
                   2296:        /* XXX: DTREN, DPEC */
                   2297:        bus_space_write_4(regsp->ur_iot, regsp->ur_ioh, IMX_UCR3,
                   2298:            IMX_UCR3_DSR|IMX_UCR3_RXDMUXSEL);
                   2299:
                   2300:        ufcr = (8 << IMX_UFCR_TXTL_SHIFT) | (rfdiv << IMX_UFCR_RFDIV_SHIFT) |
                   2301:                (1 << IMX_UFCR_RXTL_SHIFT);
                   2302:        /* XXX: keep DCE/DTE bit */
                   2303:        ufcr |= bus_space_read_4(regsp->ur_iot, regsp->ur_ioh, IMX_UFCR) &
                   2304:                IMX_UFCR_DCEDTE;
                   2305:
                   2306:        bus_space_write_4(regsp->ur_iot, regsp->ur_ioh, IMX_UFCR, ufcr);
                   2307:
                   2308:        bus_space_write_4(regsp->ur_iot, regsp->ur_ioh, IMX_ONEMS,
                   2309:            imxuart_freq / imxuart_freqdiv / 1000);
                   2310:
                   2311:        bus_space_write_4(regsp->ur_iot, regsp->ur_ioh, IMX_UCR2,
                   2312:                          IMX_UCR2_IRTS|
                   2313:                          IMX_UCR2_CTSC|
                   2314:                          IMX_UCR2_WS|IMX_UCR2_TXEN|
                   2315:                          IMX_UCR2_RXEN|IMX_UCR2_SRST);
                   2316:        /* clear status registers */
                   2317:        bus_space_write_4(regsp->ur_iot, regsp->ur_ioh, IMX_USR1, 0xffff);
                   2318:        bus_space_write_4(regsp->ur_iot, regsp->ur_ioh, IMX_USR2, 0xffff);
                   2319:
                   2320:
                   2321:        bus_space_write_4(regsp->ur_iot, regsp->ur_ioh, IMX_UCR1,
                   2322:            IMX_UCR1_UARTEN);
                   2323:
                   2324:        return (0);
                   2325: }
                   2326:
                   2327:
                   2328: #endif
                   2329:
                   2330:
                   2331: #ifdef IMXUARTCONSOLE
                   2332: /*
                   2333:  * Following are all routines needed for UART to act as console
                   2334:  */
                   2335: struct consdev imxucons = {
                   2336:        NULL, NULL, imxucngetc, imxucnputc, imxucnpollc, NULL, NULL, NULL,
                   2337:        NODEV, CN_NORMAL
                   2338: };
                   2339:
                   2340:
                   2341: int
                   2342: imxuart_cons_attach(bus_space_tag_t iot, paddr_t iobase, u_int rate,
                   2343:                    tcflag_t cflag)
                   2344: {
                   2345:        struct imxuart_regs regs;
                   2346:        int res;
                   2347:
                   2348:        regs.ur_iot = iot;
                   2349:        regs.ur_iobase = iobase;
                   2350:
                   2351:        res = imxuart_init(&regs, rate, cflag);
                   2352:        if (res)
                   2353:                return (res);
                   2354:
                   2355:        cn_tab = &imxucons;
                   2356:        cn_init_magic(&imxuart_cnm_state);
                   2357:        cn_set_magic("\047\001"); /* default magic is BREAK */
                   2358:
                   2359:        imxuconsrate = rate;
                   2360:        imxuconscflag = cflag;
                   2361:
                   2362:        imxuconsregs = regs;
                   2363:
                   2364:        return 0;
                   2365: }
                   2366:
                   2367: int
                   2368: imxucngetc(dev_t dev)
                   2369: {
                   2370:        return (imxuart_common_getc(dev, &imxuconsregs));
                   2371: }
                   2372:
                   2373: /*
                   2374:  * Console kernel output character routine.
                   2375:  */
                   2376: void
                   2377: imxucnputc(dev_t dev, int c)
                   2378: {
                   2379:        imxuart_common_putc(dev, &imxuconsregs, c);
                   2380: }
                   2381:
                   2382: void
                   2383: imxucnpollc(dev_t dev, int on)
                   2384: {
                   2385:
1.10      mlelstv  2386:        imxuart_readahead_in = 0;
                   2387:        imxuart_readahead_out = 0;
1.5       bsh      2388: }
                   2389:
                   2390: #endif /* IMXUARTCONSOLE */
                   2391:
                   2392: #ifdef KGDB
                   2393: int
                   2394: imxuart_kgdb_attach(bus_space_tag_t iot, paddr_t iobase, u_int rate,
                   2395:     tcflag_t cflag)
                   2396: {
                   2397:        int res;
                   2398:
                   2399:        if (iot == imxuconsregs.ur_iot &&
                   2400:            iobase == imxuconsregs.ur_iobase) {
                   2401: #if !defined(DDB)
                   2402:                return (EBUSY); /* cannot share with console */
                   2403: #else
                   2404:                imxu_kgdb_regs.ur_iot = iot;
                   2405:                imxu_kgdb_regs.ur_ioh = imxuconsregs.ur_ioh;
                   2406:                imxu_kgdb_regs.ur_iobase = iobase;
                   2407: #endif
                   2408:        } else {
                   2409:                imxu_kgdb_regs.ur_iot = iot;
                   2410:                imxu_kgdb_regs.ur_iobase = iobase;
                   2411:
                   2412:                res = imxuart_init(&imxu_kgdb_regs, rate, cflag);
                   2413:                if (res)
                   2414:                        return (res);
                   2415:
                   2416:                /*
                   2417:                 * XXXfvdl this shouldn't be needed, but the cn_magic goo
                   2418:                 * expects this to be initialized
                   2419:                 */
                   2420:                cn_init_magic(&imxuart_cnm_state);
                   2421:                cn_set_magic("\047\001");
                   2422:        }
                   2423:
                   2424:        kgdb_attach(imxuart_kgdb_getc, imxuart_kgdb_putc, &imxu_kgdb_regs);
                   2425:        kgdb_dev = 123; /* unneeded, only to satisfy some tests */
                   2426:
                   2427:        return (0);
                   2428: }
                   2429:
                   2430: /* ARGSUSED */
                   2431: int
                   2432: imxuart_kgdb_getc(void *arg)
                   2433: {
                   2434:        struct imxuart_regs *regs = arg;
                   2435:
                   2436:        return (imxuart_common_getc(NODEV, regs));
                   2437: }
                   2438:
                   2439: /* ARGSUSED */
                   2440: void
                   2441: imxuart_kgdb_putc(void *arg, int c)
                   2442: {
                   2443:        struct imxuart_regs *regs = arg;
                   2444:
                   2445:        imxuart_common_putc(NODEV, regs, c);
                   2446: }
                   2447: #endif /* KGDB */
                   2448:
                   2449: /* helper function to identify the imxu ports used by
                   2450:  console or KGDB (and not yet autoconf attached) */
                   2451: int
                   2452: imxuart_is_console(bus_space_tag_t iot, bus_addr_t iobase, bus_space_handle_t *ioh)
                   2453: {
                   2454:        bus_space_handle_t help;
                   2455:
                   2456:        if (!imxuconsattached &&
                   2457:            iot == imxuconsregs.ur_iot && iobase == imxuconsregs.ur_iobase)
                   2458:                help = imxuconsregs.ur_ioh;
                   2459: #ifdef KGDB
                   2460:        else if (!imxu_kgdb_attached &&
                   2461:            iot == imxu_kgdb_regs.ur_iot && iobase == imxu_kgdb_regs.ur_iobase)
                   2462:                help = imxu_kgdb_regs.ur_ioh;
                   2463: #endif
                   2464:        else
                   2465:                return (0);
                   2466:
                   2467:        if (ioh)
                   2468:                *ioh = help;
                   2469:        return (1);
                   2470: }
                   2471:
                   2472: #ifdef notyet
                   2473:
                   2474: bool
                   2475: imxuart_cleanup(device_t self, int how)
                   2476: {
                   2477: /*
                   2478:  * this routine exists to serve as a shutdown hook for systems that
                   2479:  * have firmware which doesn't interact properly with a imxuart device in
                   2480:  * FIFO mode.
                   2481:  */
                   2482:        struct imxuart_softc *sc = device_private(self);
                   2483:
                   2484:        if (ISSET(sc->sc_hwflags, IMXUART_HW_FIFO))
                   2485:                UR_WRITE_1(&sc->sc_regs, IMXUART_REG_FIFO, 0);
                   2486:
                   2487:        return true;
                   2488: }
                   2489: #endif
                   2490:
                   2491: #ifdef notyet
                   2492: bool
                   2493: imxuart_suspend(device_t self PMF_FN_ARGS)
                   2494: {
                   2495:        struct imxuart_softc *sc = device_private(self);
                   2496:
                   2497:        UR_WRITE_1(&sc->sc_regs, IMXUART_REG_IER, 0);
                   2498:        (void)CSR_READ_1(&sc->sc_regs, IMXUART_REG_IIR);
                   2499:
                   2500:        return true;
                   2501: }
                   2502: #endif
                   2503:
                   2504: #ifdef notyet
                   2505: bool
                   2506: imxuart_resume(device_t self PMF_FN_ARGS)
                   2507: {
                   2508:        struct imxuart_softc *sc = device_private(self);
                   2509:
                   2510:        mutex_spin_enter(&sc->sc_lock);
                   2511:        imxuart_loadchannelregs(sc);
                   2512:        mutex_spin_exit(&sc->sc_lock);
                   2513:
                   2514:        return true;
                   2515: }
                   2516: #endif
                   2517:
                   2518: static void
                   2519: imxuart_enable_debugport(struct imxuart_softc *sc)
                   2520: {
                   2521:        bus_space_tag_t iot = sc->sc_regs.ur_iot;
                   2522:        bus_space_handle_t ioh = sc->sc_regs.ur_ioh;
                   2523:
                   2524:        if (sc->sc_hwflags & (IMXUART_HW_CONSOLE|IMXUART_HW_KGDB)) {
                   2525:
                   2526:                /* Turn on line break interrupt, set carrier. */
                   2527:
                   2528:                sc->sc_ucr3 |= IMX_UCR3_DSR;
                   2529:                bus_space_write_4(iot, ioh, IMX_UCR3, sc->sc_ucr3);
                   2530:
                   2531:                sc->sc_ucr4 |= IMX_UCR4_BKEN;
                   2532:                bus_space_write_4(iot, ioh, IMX_UCR4, sc->sc_ucr4);
                   2533:
                   2534:                sc->sc_ucr2 |= IMX_UCR2_TXEN|IMX_UCR2_RXEN|
                   2535:                    IMX_UCR2_CTS;
                   2536:                bus_space_write_4(iot, ioh, IMX_UCR2, sc->sc_ucr2);
                   2537:
                   2538:                sc->sc_ucr1 |= IMX_UCR1_UARTEN;
                   2539:                bus_space_write_4(iot, ioh, IMX_UCR1, sc->sc_ucr1);
                   2540:        }
                   2541: }
                   2542:
                   2543:
                   2544: void
                   2545: imxuart_set_frequency(u_int freq, u_int div)
                   2546: {
                   2547:        imxuart_freq = freq;
                   2548:        imxuart_freqdiv = div;
                   2549: }

CVSweb <webmaster@jp.NetBSD.org>