[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.10.4.1

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

CVSweb <webmaster@jp.NetBSD.org>