1*27d5dc18SMarcel Moolenaar /* 2*27d5dc18SMarcel Moolenaar * Copyright (c) 2003 Marcel Moolenaar 3*27d5dc18SMarcel Moolenaar * All rights reserved. 4*27d5dc18SMarcel Moolenaar * 5*27d5dc18SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 6*27d5dc18SMarcel Moolenaar * modification, are permitted provided that the following conditions 7*27d5dc18SMarcel Moolenaar * are met: 8*27d5dc18SMarcel Moolenaar * 9*27d5dc18SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 10*27d5dc18SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 11*27d5dc18SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 12*27d5dc18SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 13*27d5dc18SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 14*27d5dc18SMarcel Moolenaar * 15*27d5dc18SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*27d5dc18SMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*27d5dc18SMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*27d5dc18SMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*27d5dc18SMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*27d5dc18SMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*27d5dc18SMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*27d5dc18SMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*27d5dc18SMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*27d5dc18SMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*27d5dc18SMarcel Moolenaar */ 26*27d5dc18SMarcel Moolenaar 27*27d5dc18SMarcel Moolenaar #include <sys/cdefs.h> 28*27d5dc18SMarcel Moolenaar __FBSDID("$FreeBSD$"); 29*27d5dc18SMarcel Moolenaar 30*27d5dc18SMarcel Moolenaar #include <sys/param.h> 31*27d5dc18SMarcel Moolenaar #include <sys/systm.h> 32*27d5dc18SMarcel Moolenaar #include <sys/bus.h> 33*27d5dc18SMarcel Moolenaar #include <sys/conf.h> 34*27d5dc18SMarcel Moolenaar #include <machine/bus.h> 35*27d5dc18SMarcel Moolenaar 36*27d5dc18SMarcel Moolenaar #include <dev/uart/uart.h> 37*27d5dc18SMarcel Moolenaar #include <dev/uart/uart_cpu.h> 38*27d5dc18SMarcel Moolenaar #include <dev/uart/uart_bus.h> 39*27d5dc18SMarcel Moolenaar #include <dev/uart/uart_dev_z8530.h> 40*27d5dc18SMarcel Moolenaar 41*27d5dc18SMarcel Moolenaar #include "uart_if.h" 42*27d5dc18SMarcel Moolenaar 43*27d5dc18SMarcel Moolenaar #define DEFAULT_RCLK 307200 44*27d5dc18SMarcel Moolenaar 45*27d5dc18SMarcel Moolenaar #define IS_CHANNEL_A(bas) (((bas)->bsh & 7) != 0) 46*27d5dc18SMarcel Moolenaar #define IS_CHANNEL_B(bas) (((bas)->bsh & 7) == 0) 47*27d5dc18SMarcel Moolenaar 48*27d5dc18SMarcel Moolenaar /* Multiplexed I/O. */ 49*27d5dc18SMarcel Moolenaar static __inline void 50*27d5dc18SMarcel Moolenaar uart_setmreg(struct uart_bas *bas, int reg, int val) 51*27d5dc18SMarcel Moolenaar { 52*27d5dc18SMarcel Moolenaar 53*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_CTRL, reg); 54*27d5dc18SMarcel Moolenaar uart_barrier(bas); 55*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_CTRL, val); 56*27d5dc18SMarcel Moolenaar } 57*27d5dc18SMarcel Moolenaar 58*27d5dc18SMarcel Moolenaar static __inline uint8_t 59*27d5dc18SMarcel Moolenaar uart_getmreg(struct uart_bas *bas, int reg) 60*27d5dc18SMarcel Moolenaar { 61*27d5dc18SMarcel Moolenaar 62*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_CTRL, reg); 63*27d5dc18SMarcel Moolenaar uart_barrier(bas); 64*27d5dc18SMarcel Moolenaar return (uart_getreg(bas, REG_CTRL)); 65*27d5dc18SMarcel Moolenaar } 66*27d5dc18SMarcel Moolenaar 67*27d5dc18SMarcel Moolenaar static int 68*27d5dc18SMarcel Moolenaar z8530_divisor(int rclk, int baudrate) 69*27d5dc18SMarcel Moolenaar { 70*27d5dc18SMarcel Moolenaar int act_baud, divisor, error; 71*27d5dc18SMarcel Moolenaar 72*27d5dc18SMarcel Moolenaar if (baudrate == 0) 73*27d5dc18SMarcel Moolenaar return (0); 74*27d5dc18SMarcel Moolenaar 75*27d5dc18SMarcel Moolenaar divisor = (rclk + baudrate) / (baudrate << 1) - 2; 76*27d5dc18SMarcel Moolenaar if (divisor >= 65536) 77*27d5dc18SMarcel Moolenaar return (0); 78*27d5dc18SMarcel Moolenaar act_baud = rclk / 2 / (divisor + 2); 79*27d5dc18SMarcel Moolenaar 80*27d5dc18SMarcel Moolenaar /* 10 times error in percent: */ 81*27d5dc18SMarcel Moolenaar error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1; 82*27d5dc18SMarcel Moolenaar 83*27d5dc18SMarcel Moolenaar /* 3.0% maximum error tolerance: */ 84*27d5dc18SMarcel Moolenaar if (error < -30 || error > 30) 85*27d5dc18SMarcel Moolenaar return (0); 86*27d5dc18SMarcel Moolenaar 87*27d5dc18SMarcel Moolenaar return (divisor); 88*27d5dc18SMarcel Moolenaar } 89*27d5dc18SMarcel Moolenaar 90*27d5dc18SMarcel Moolenaar static int 91*27d5dc18SMarcel Moolenaar z8530_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, 92*27d5dc18SMarcel Moolenaar int parity, uint8_t *tpcp) 93*27d5dc18SMarcel Moolenaar { 94*27d5dc18SMarcel Moolenaar int divisor; 95*27d5dc18SMarcel Moolenaar uint8_t mpm, rpc, tpc; 96*27d5dc18SMarcel Moolenaar 97*27d5dc18SMarcel Moolenaar rpc = RPC_RXE; 98*27d5dc18SMarcel Moolenaar mpm = MPM_CM16; 99*27d5dc18SMarcel Moolenaar tpc = TPC_TXE | (*tpcp & (TPC_DTR | TPC_RTS)); 100*27d5dc18SMarcel Moolenaar 101*27d5dc18SMarcel Moolenaar if (databits >= 8) { 102*27d5dc18SMarcel Moolenaar rpc |= RPC_RB8; 103*27d5dc18SMarcel Moolenaar tpc |= TPC_TB8; 104*27d5dc18SMarcel Moolenaar } else if (databits == 7) { 105*27d5dc18SMarcel Moolenaar rpc |= RPC_RB7; 106*27d5dc18SMarcel Moolenaar tpc |= TPC_TB7; 107*27d5dc18SMarcel Moolenaar } else if (databits == 6) { 108*27d5dc18SMarcel Moolenaar rpc |= RPC_RB6; 109*27d5dc18SMarcel Moolenaar tpc |= TPC_TB6; 110*27d5dc18SMarcel Moolenaar } else { 111*27d5dc18SMarcel Moolenaar rpc |= RPC_RB5; 112*27d5dc18SMarcel Moolenaar tpc |= TPC_TB5; 113*27d5dc18SMarcel Moolenaar } 114*27d5dc18SMarcel Moolenaar mpm |= (stopbits > 1) ? MPM_SB2 : MPM_SB1; 115*27d5dc18SMarcel Moolenaar switch (parity) { 116*27d5dc18SMarcel Moolenaar case UART_PARITY_EVEN: mpm |= MPM_PE | MPM_EVEN; break; 117*27d5dc18SMarcel Moolenaar case UART_PARITY_NONE: break; 118*27d5dc18SMarcel Moolenaar case UART_PARITY_ODD: mpm |= MPM_PE; break; 119*27d5dc18SMarcel Moolenaar default: return (EINVAL); 120*27d5dc18SMarcel Moolenaar } 121*27d5dc18SMarcel Moolenaar 122*27d5dc18SMarcel Moolenaar /* Set baudrate. */ 123*27d5dc18SMarcel Moolenaar if (baudrate > 0) { 124*27d5dc18SMarcel Moolenaar divisor = z8530_divisor(bas->rclk, baudrate); 125*27d5dc18SMarcel Moolenaar if (divisor == 0) 126*27d5dc18SMarcel Moolenaar return (EINVAL); 127*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_TCL, divisor & 0xff); 128*27d5dc18SMarcel Moolenaar uart_barrier(bas); 129*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_TCH, (divisor >> 8) & 0xff); 130*27d5dc18SMarcel Moolenaar uart_barrier(bas); 131*27d5dc18SMarcel Moolenaar } 132*27d5dc18SMarcel Moolenaar 133*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_RPC, rpc); 134*27d5dc18SMarcel Moolenaar uart_barrier(bas); 135*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_MPM, mpm); 136*27d5dc18SMarcel Moolenaar uart_barrier(bas); 137*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_TPC, tpc); 138*27d5dc18SMarcel Moolenaar uart_barrier(bas); 139*27d5dc18SMarcel Moolenaar *tpcp = tpc; 140*27d5dc18SMarcel Moolenaar return (0); 141*27d5dc18SMarcel Moolenaar } 142*27d5dc18SMarcel Moolenaar 143*27d5dc18SMarcel Moolenaar static int 144*27d5dc18SMarcel Moolenaar z8530_setup(struct uart_bas *bas, int baudrate, int databits, int stopbits, 145*27d5dc18SMarcel Moolenaar int parity) 146*27d5dc18SMarcel Moolenaar { 147*27d5dc18SMarcel Moolenaar uint8_t tpc; 148*27d5dc18SMarcel Moolenaar 149*27d5dc18SMarcel Moolenaar if (bas->rclk == 0) 150*27d5dc18SMarcel Moolenaar bas->rclk = DEFAULT_RCLK; 151*27d5dc18SMarcel Moolenaar 152*27d5dc18SMarcel Moolenaar /* Assume we don't need to perform a full hardware reset. */ 153*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_MIC, ((IS_CHANNEL_A(bas)) ? MIC_CRA : MIC_CRB) | 154*27d5dc18SMarcel Moolenaar MIC_MIE | MIC_NV); 155*27d5dc18SMarcel Moolenaar uart_barrier(bas); 156*27d5dc18SMarcel Moolenaar /* Set clock sources and enable BRG. */ 157*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_CMC, CMC_RC_BRG | CMC_TC_BRG); 158*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_MCB2, MCB2_PCLK | MCB2_BRGE); 159*27d5dc18SMarcel Moolenaar uart_barrier(bas); 160*27d5dc18SMarcel Moolenaar /* Set data encoding. */ 161*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_MCB1, MCB1_NRZ); 162*27d5dc18SMarcel Moolenaar uart_barrier(bas); 163*27d5dc18SMarcel Moolenaar 164*27d5dc18SMarcel Moolenaar tpc = TPC_DTR | TPC_RTS; 165*27d5dc18SMarcel Moolenaar z8530_param(bas, baudrate, databits, stopbits, parity, &tpc); 166*27d5dc18SMarcel Moolenaar return (int)tpc; 167*27d5dc18SMarcel Moolenaar } 168*27d5dc18SMarcel Moolenaar 169*27d5dc18SMarcel Moolenaar /* 170*27d5dc18SMarcel Moolenaar * Low-level UART interface. 171*27d5dc18SMarcel Moolenaar */ 172*27d5dc18SMarcel Moolenaar static int z8530_probe(struct uart_bas *bas); 173*27d5dc18SMarcel Moolenaar static void z8530_init(struct uart_bas *bas, int, int, int, int); 174*27d5dc18SMarcel Moolenaar static void z8530_term(struct uart_bas *bas); 175*27d5dc18SMarcel Moolenaar static void z8530_putc(struct uart_bas *bas, int); 176*27d5dc18SMarcel Moolenaar static int z8530_poll(struct uart_bas *bas); 177*27d5dc18SMarcel Moolenaar static int z8530_getc(struct uart_bas *bas); 178*27d5dc18SMarcel Moolenaar 179*27d5dc18SMarcel Moolenaar struct uart_ops uart_z8530_ops = { 180*27d5dc18SMarcel Moolenaar .probe = z8530_probe, 181*27d5dc18SMarcel Moolenaar .init = z8530_init, 182*27d5dc18SMarcel Moolenaar .term = z8530_term, 183*27d5dc18SMarcel Moolenaar .putc = z8530_putc, 184*27d5dc18SMarcel Moolenaar .poll = z8530_poll, 185*27d5dc18SMarcel Moolenaar .getc = z8530_getc, 186*27d5dc18SMarcel Moolenaar }; 187*27d5dc18SMarcel Moolenaar 188*27d5dc18SMarcel Moolenaar static int 189*27d5dc18SMarcel Moolenaar z8530_probe(struct uart_bas *bas) 190*27d5dc18SMarcel Moolenaar { 191*27d5dc18SMarcel Moolenaar 192*27d5dc18SMarcel Moolenaar return (0); 193*27d5dc18SMarcel Moolenaar } 194*27d5dc18SMarcel Moolenaar 195*27d5dc18SMarcel Moolenaar static void 196*27d5dc18SMarcel Moolenaar z8530_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, 197*27d5dc18SMarcel Moolenaar int parity) 198*27d5dc18SMarcel Moolenaar { 199*27d5dc18SMarcel Moolenaar 200*27d5dc18SMarcel Moolenaar z8530_setup(bas, baudrate, databits, stopbits, parity); 201*27d5dc18SMarcel Moolenaar } 202*27d5dc18SMarcel Moolenaar 203*27d5dc18SMarcel Moolenaar static void 204*27d5dc18SMarcel Moolenaar z8530_term(struct uart_bas *bas) 205*27d5dc18SMarcel Moolenaar { 206*27d5dc18SMarcel Moolenaar } 207*27d5dc18SMarcel Moolenaar 208*27d5dc18SMarcel Moolenaar static void 209*27d5dc18SMarcel Moolenaar z8530_putc(struct uart_bas *bas, int c) 210*27d5dc18SMarcel Moolenaar { 211*27d5dc18SMarcel Moolenaar 212*27d5dc18SMarcel Moolenaar while (!(uart_getmreg(bas, RR_BES) & BES_TXE)) 213*27d5dc18SMarcel Moolenaar ; 214*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_DATA, c); 215*27d5dc18SMarcel Moolenaar uart_barrier(bas); 216*27d5dc18SMarcel Moolenaar } 217*27d5dc18SMarcel Moolenaar 218*27d5dc18SMarcel Moolenaar static int 219*27d5dc18SMarcel Moolenaar z8530_poll(struct uart_bas *bas) 220*27d5dc18SMarcel Moolenaar { 221*27d5dc18SMarcel Moolenaar 222*27d5dc18SMarcel Moolenaar if (!(uart_getmreg(bas, RR_BES) & BES_RXA)) 223*27d5dc18SMarcel Moolenaar return (-1); 224*27d5dc18SMarcel Moolenaar return (uart_getreg(bas, REG_DATA)); 225*27d5dc18SMarcel Moolenaar } 226*27d5dc18SMarcel Moolenaar 227*27d5dc18SMarcel Moolenaar static int 228*27d5dc18SMarcel Moolenaar z8530_getc(struct uart_bas *bas) 229*27d5dc18SMarcel Moolenaar { 230*27d5dc18SMarcel Moolenaar 231*27d5dc18SMarcel Moolenaar while (!(uart_getmreg(bas, RR_BES) & BES_RXA)) 232*27d5dc18SMarcel Moolenaar ; 233*27d5dc18SMarcel Moolenaar return (uart_getreg(bas, REG_DATA)); 234*27d5dc18SMarcel Moolenaar } 235*27d5dc18SMarcel Moolenaar 236*27d5dc18SMarcel Moolenaar /* 237*27d5dc18SMarcel Moolenaar * High-level UART interface. 238*27d5dc18SMarcel Moolenaar */ 239*27d5dc18SMarcel Moolenaar struct z8530_softc { 240*27d5dc18SMarcel Moolenaar struct uart_softc base; 241*27d5dc18SMarcel Moolenaar uint8_t tpc; 242*27d5dc18SMarcel Moolenaar }; 243*27d5dc18SMarcel Moolenaar 244*27d5dc18SMarcel Moolenaar static int z8530_bus_attach(struct uart_softc *); 245*27d5dc18SMarcel Moolenaar static int z8530_bus_detach(struct uart_softc *); 246*27d5dc18SMarcel Moolenaar static int z8530_bus_flush(struct uart_softc *, int); 247*27d5dc18SMarcel Moolenaar static int z8530_bus_getsig(struct uart_softc *); 248*27d5dc18SMarcel Moolenaar static int z8530_bus_ioctl(struct uart_softc *, int, intptr_t); 249*27d5dc18SMarcel Moolenaar static int z8530_bus_ipend(struct uart_softc *); 250*27d5dc18SMarcel Moolenaar static int z8530_bus_param(struct uart_softc *, int, int, int, int); 251*27d5dc18SMarcel Moolenaar static int z8530_bus_probe(struct uart_softc *); 252*27d5dc18SMarcel Moolenaar static int z8530_bus_receive(struct uart_softc *); 253*27d5dc18SMarcel Moolenaar static int z8530_bus_setsig(struct uart_softc *, int); 254*27d5dc18SMarcel Moolenaar static int z8530_bus_transmit(struct uart_softc *); 255*27d5dc18SMarcel Moolenaar 256*27d5dc18SMarcel Moolenaar static kobj_method_t z8530_methods[] = { 257*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_attach, z8530_bus_attach), 258*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_detach, z8530_bus_detach), 259*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_flush, z8530_bus_flush), 260*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_getsig, z8530_bus_getsig), 261*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_ioctl, z8530_bus_ioctl), 262*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_ipend, z8530_bus_ipend), 263*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_param, z8530_bus_param), 264*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_probe, z8530_bus_probe), 265*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_receive, z8530_bus_receive), 266*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_setsig, z8530_bus_setsig), 267*27d5dc18SMarcel Moolenaar KOBJMETHOD(uart_transmit, z8530_bus_transmit), 268*27d5dc18SMarcel Moolenaar { 0, 0 } 269*27d5dc18SMarcel Moolenaar }; 270*27d5dc18SMarcel Moolenaar 271*27d5dc18SMarcel Moolenaar struct uart_class uart_z8530_class = { 272*27d5dc18SMarcel Moolenaar "z8530 class", 273*27d5dc18SMarcel Moolenaar z8530_methods, 274*27d5dc18SMarcel Moolenaar sizeof(struct z8530_softc), 275*27d5dc18SMarcel Moolenaar .uc_range = 2, 276*27d5dc18SMarcel Moolenaar .uc_rclk = DEFAULT_RCLK 277*27d5dc18SMarcel Moolenaar }; 278*27d5dc18SMarcel Moolenaar 279*27d5dc18SMarcel Moolenaar #define SIGCHG(c, i, s, d) \ 280*27d5dc18SMarcel Moolenaar if (c) { \ 281*27d5dc18SMarcel Moolenaar i |= (i & s) ? s : s | d; \ 282*27d5dc18SMarcel Moolenaar } else { \ 283*27d5dc18SMarcel Moolenaar i = (i & s) ? (i & ~s) | d : i; \ 284*27d5dc18SMarcel Moolenaar } 285*27d5dc18SMarcel Moolenaar 286*27d5dc18SMarcel Moolenaar static int 287*27d5dc18SMarcel Moolenaar z8530_bus_attach(struct uart_softc *sc) 288*27d5dc18SMarcel Moolenaar { 289*27d5dc18SMarcel Moolenaar struct z8530_softc *z8530 = (struct z8530_softc*)sc; 290*27d5dc18SMarcel Moolenaar struct uart_bas *bas; 291*27d5dc18SMarcel Moolenaar struct uart_devinfo *di; 292*27d5dc18SMarcel Moolenaar 293*27d5dc18SMarcel Moolenaar bas = &sc->sc_bas; 294*27d5dc18SMarcel Moolenaar if (sc->sc_sysdev != NULL) { 295*27d5dc18SMarcel Moolenaar di = sc->sc_sysdev; 296*27d5dc18SMarcel Moolenaar z8530->tpc = TPC_DTR|TPC_RTS; 297*27d5dc18SMarcel Moolenaar z8530_param(bas, di->baudrate, di->databits, di->stopbits, 298*27d5dc18SMarcel Moolenaar di->parity, &z8530->tpc); 299*27d5dc18SMarcel Moolenaar } else { 300*27d5dc18SMarcel Moolenaar z8530->tpc = z8530_setup(bas, 9600, 8, 1, UART_PARITY_NONE); 301*27d5dc18SMarcel Moolenaar z8530->tpc &= ~(TPC_DTR|TPC_RTS); 302*27d5dc18SMarcel Moolenaar } 303*27d5dc18SMarcel Moolenaar 304*27d5dc18SMarcel Moolenaar sc->sc_rxfifosz = 3; 305*27d5dc18SMarcel Moolenaar sc->sc_txfifosz = 1; 306*27d5dc18SMarcel Moolenaar 307*27d5dc18SMarcel Moolenaar (void)z8530_bus_getsig(sc); 308*27d5dc18SMarcel Moolenaar 309*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_IC, IC_BRK | IC_CTS | IC_DCD); 310*27d5dc18SMarcel Moolenaar uart_barrier(bas); 311*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_IDT, IDT_TIE | IDT_RIA); 312*27d5dc18SMarcel Moolenaar uart_barrier(bas); 313*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_IV, 0); 314*27d5dc18SMarcel Moolenaar uart_barrier(bas); 315*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_TPC, z8530->tpc); 316*27d5dc18SMarcel Moolenaar uart_barrier(bas); 317*27d5dc18SMarcel Moolenaar return (0); 318*27d5dc18SMarcel Moolenaar } 319*27d5dc18SMarcel Moolenaar 320*27d5dc18SMarcel Moolenaar static int 321*27d5dc18SMarcel Moolenaar z8530_bus_detach(struct uart_softc *sc) 322*27d5dc18SMarcel Moolenaar { 323*27d5dc18SMarcel Moolenaar 324*27d5dc18SMarcel Moolenaar return (0); 325*27d5dc18SMarcel Moolenaar } 326*27d5dc18SMarcel Moolenaar 327*27d5dc18SMarcel Moolenaar static int 328*27d5dc18SMarcel Moolenaar z8530_bus_flush(struct uart_softc *sc, int what) 329*27d5dc18SMarcel Moolenaar { 330*27d5dc18SMarcel Moolenaar 331*27d5dc18SMarcel Moolenaar return (0); 332*27d5dc18SMarcel Moolenaar } 333*27d5dc18SMarcel Moolenaar 334*27d5dc18SMarcel Moolenaar static int 335*27d5dc18SMarcel Moolenaar z8530_bus_getsig(struct uart_softc *sc) 336*27d5dc18SMarcel Moolenaar { 337*27d5dc18SMarcel Moolenaar struct uart_bas *bas; 338*27d5dc18SMarcel Moolenaar uint32_t new, old, sig; 339*27d5dc18SMarcel Moolenaar uint8_t bes; 340*27d5dc18SMarcel Moolenaar 341*27d5dc18SMarcel Moolenaar bas = &sc->sc_bas; 342*27d5dc18SMarcel Moolenaar do { 343*27d5dc18SMarcel Moolenaar old = sc->sc_hwsig; 344*27d5dc18SMarcel Moolenaar sig = old; 345*27d5dc18SMarcel Moolenaar bes = uart_getmreg(bas, RR_BES); 346*27d5dc18SMarcel Moolenaar SIGCHG(bes & BES_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS); 347*27d5dc18SMarcel Moolenaar SIGCHG(bes & BES_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD); 348*27d5dc18SMarcel Moolenaar new = sig & ~UART_SIGMASK_DELTA; 349*27d5dc18SMarcel Moolenaar } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 350*27d5dc18SMarcel Moolenaar return (sig); 351*27d5dc18SMarcel Moolenaar } 352*27d5dc18SMarcel Moolenaar 353*27d5dc18SMarcel Moolenaar static int 354*27d5dc18SMarcel Moolenaar z8530_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 355*27d5dc18SMarcel Moolenaar { 356*27d5dc18SMarcel Moolenaar struct z8530_softc *z8530 = (struct z8530_softc*)sc; 357*27d5dc18SMarcel Moolenaar struct uart_bas *bas; 358*27d5dc18SMarcel Moolenaar 359*27d5dc18SMarcel Moolenaar bas = &sc->sc_bas; 360*27d5dc18SMarcel Moolenaar switch (request) { 361*27d5dc18SMarcel Moolenaar case UART_IOCTL_BREAK: 362*27d5dc18SMarcel Moolenaar if (data) 363*27d5dc18SMarcel Moolenaar z8530->tpc |= TPC_BRK; 364*27d5dc18SMarcel Moolenaar else 365*27d5dc18SMarcel Moolenaar z8530->tpc &= ~TPC_BRK; 366*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_TPC, z8530->tpc); 367*27d5dc18SMarcel Moolenaar uart_barrier(bas); 368*27d5dc18SMarcel Moolenaar break; 369*27d5dc18SMarcel Moolenaar default: 370*27d5dc18SMarcel Moolenaar return (EINVAL); 371*27d5dc18SMarcel Moolenaar } 372*27d5dc18SMarcel Moolenaar return (0); 373*27d5dc18SMarcel Moolenaar } 374*27d5dc18SMarcel Moolenaar 375*27d5dc18SMarcel Moolenaar static int 376*27d5dc18SMarcel Moolenaar z8530_bus_ipend(struct uart_softc *sc) 377*27d5dc18SMarcel Moolenaar { 378*27d5dc18SMarcel Moolenaar struct uart_bas *bas; 379*27d5dc18SMarcel Moolenaar int ipend; 380*27d5dc18SMarcel Moolenaar uint32_t sig; 381*27d5dc18SMarcel Moolenaar uint8_t bes, src; 382*27d5dc18SMarcel Moolenaar 383*27d5dc18SMarcel Moolenaar bas = &sc->sc_bas; 384*27d5dc18SMarcel Moolenaar ipend = 0; 385*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_CTRL, CR_RSTIUS); 386*27d5dc18SMarcel Moolenaar uart_barrier(bas); 387*27d5dc18SMarcel Moolenaar bes = uart_getmreg(bas, RR_BES); 388*27d5dc18SMarcel Moolenaar if (bes & BES_BRK) { 389*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_CTRL, CR_RSTXSI); 390*27d5dc18SMarcel Moolenaar ipend |= UART_IPEND_BREAK; 391*27d5dc18SMarcel Moolenaar } 392*27d5dc18SMarcel Moolenaar if (bes & BES_TXE) { 393*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_CTRL, CR_RSTTXI); 394*27d5dc18SMarcel Moolenaar ipend |= UART_IPEND_TXIDLE; 395*27d5dc18SMarcel Moolenaar } 396*27d5dc18SMarcel Moolenaar if (bes & BES_RXA) 397*27d5dc18SMarcel Moolenaar ipend |= UART_IPEND_RXREADY; 398*27d5dc18SMarcel Moolenaar sig = sc->sc_hwsig; 399*27d5dc18SMarcel Moolenaar SIGCHG(bes & BES_CTS, sig, UART_SIG_CTS, UART_SIG_DCTS); 400*27d5dc18SMarcel Moolenaar SIGCHG(bes & BES_DCD, sig, UART_SIG_DCD, UART_SIG_DDCD); 401*27d5dc18SMarcel Moolenaar if (sig & UART_SIGMASK_DELTA) 402*27d5dc18SMarcel Moolenaar ipend |= UART_IPEND_SIGCHG; 403*27d5dc18SMarcel Moolenaar src = uart_getmreg(bas, RR_SRC); 404*27d5dc18SMarcel Moolenaar if (src & SRC_OVR) { 405*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_CTRL, CR_RSTERR); 406*27d5dc18SMarcel Moolenaar ipend |= UART_IPEND_OVERRUN; 407*27d5dc18SMarcel Moolenaar } 408*27d5dc18SMarcel Moolenaar return (ipend); 409*27d5dc18SMarcel Moolenaar } 410*27d5dc18SMarcel Moolenaar 411*27d5dc18SMarcel Moolenaar static int 412*27d5dc18SMarcel Moolenaar z8530_bus_param(struct uart_softc *sc, int baudrate, int databits, 413*27d5dc18SMarcel Moolenaar int stopbits, int parity) 414*27d5dc18SMarcel Moolenaar { 415*27d5dc18SMarcel Moolenaar struct z8530_softc *z8530 = (struct z8530_softc*)sc; 416*27d5dc18SMarcel Moolenaar int error; 417*27d5dc18SMarcel Moolenaar 418*27d5dc18SMarcel Moolenaar error = z8530_param(&sc->sc_bas, baudrate, databits, stopbits, parity, 419*27d5dc18SMarcel Moolenaar &z8530->tpc); 420*27d5dc18SMarcel Moolenaar return (error); 421*27d5dc18SMarcel Moolenaar } 422*27d5dc18SMarcel Moolenaar 423*27d5dc18SMarcel Moolenaar static int 424*27d5dc18SMarcel Moolenaar z8530_bus_probe(struct uart_softc *sc) 425*27d5dc18SMarcel Moolenaar { 426*27d5dc18SMarcel Moolenaar char buf[80]; 427*27d5dc18SMarcel Moolenaar const char *ch; 428*27d5dc18SMarcel Moolenaar int error; 429*27d5dc18SMarcel Moolenaar 430*27d5dc18SMarcel Moolenaar error = z8530_probe(&sc->sc_bas); 431*27d5dc18SMarcel Moolenaar if (error) 432*27d5dc18SMarcel Moolenaar return (error); 433*27d5dc18SMarcel Moolenaar 434*27d5dc18SMarcel Moolenaar /* Assume the address range is naturally aligned. */ 435*27d5dc18SMarcel Moolenaar ch = IS_CHANNEL_A(&sc->sc_bas) ? "A" : "B"; 436*27d5dc18SMarcel Moolenaar 437*27d5dc18SMarcel Moolenaar snprintf(buf, sizeof(buf), "z8530, channel %s", ch); 438*27d5dc18SMarcel Moolenaar device_set_desc_copy(sc->sc_dev, buf); 439*27d5dc18SMarcel Moolenaar return (0); 440*27d5dc18SMarcel Moolenaar } 441*27d5dc18SMarcel Moolenaar 442*27d5dc18SMarcel Moolenaar static int 443*27d5dc18SMarcel Moolenaar z8530_bus_receive(struct uart_softc *sc) 444*27d5dc18SMarcel Moolenaar { 445*27d5dc18SMarcel Moolenaar struct uart_bas *bas; 446*27d5dc18SMarcel Moolenaar int xc; 447*27d5dc18SMarcel Moolenaar uint8_t bes, src; 448*27d5dc18SMarcel Moolenaar 449*27d5dc18SMarcel Moolenaar bas = &sc->sc_bas; 450*27d5dc18SMarcel Moolenaar bes = uart_getmreg(bas, RR_BES); 451*27d5dc18SMarcel Moolenaar while ((bes & BES_RXA) && !uart_rx_full(sc)) { 452*27d5dc18SMarcel Moolenaar src = uart_getmreg(bas, RR_SRC); 453*27d5dc18SMarcel Moolenaar xc = uart_getreg(bas, REG_DATA); 454*27d5dc18SMarcel Moolenaar if (src & SRC_FE) 455*27d5dc18SMarcel Moolenaar xc |= UART_STAT_FRAMERR; 456*27d5dc18SMarcel Moolenaar if (src & SRC_PE) 457*27d5dc18SMarcel Moolenaar xc |= UART_STAT_PARERR; 458*27d5dc18SMarcel Moolenaar uart_rx_put(sc, xc); 459*27d5dc18SMarcel Moolenaar if (src & (SRC_FE | SRC_PE)) 460*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_CTRL, CR_RSTERR); 461*27d5dc18SMarcel Moolenaar bes = uart_getmreg(bas, RR_BES); 462*27d5dc18SMarcel Moolenaar } 463*27d5dc18SMarcel Moolenaar return (0); 464*27d5dc18SMarcel Moolenaar } 465*27d5dc18SMarcel Moolenaar 466*27d5dc18SMarcel Moolenaar static int 467*27d5dc18SMarcel Moolenaar z8530_bus_setsig(struct uart_softc *sc, int sig) 468*27d5dc18SMarcel Moolenaar { 469*27d5dc18SMarcel Moolenaar struct z8530_softc *z8530 = (struct z8530_softc*)sc; 470*27d5dc18SMarcel Moolenaar struct uart_bas *bas; 471*27d5dc18SMarcel Moolenaar uint32_t new, old; 472*27d5dc18SMarcel Moolenaar 473*27d5dc18SMarcel Moolenaar bas = &sc->sc_bas; 474*27d5dc18SMarcel Moolenaar do { 475*27d5dc18SMarcel Moolenaar old = sc->sc_hwsig; 476*27d5dc18SMarcel Moolenaar new = old; 477*27d5dc18SMarcel Moolenaar if (sig & UART_SIG_DDTR) { 478*27d5dc18SMarcel Moolenaar SIGCHG(sig & UART_SIG_DTR, new, UART_SIG_DTR, 479*27d5dc18SMarcel Moolenaar UART_SIG_DDTR); 480*27d5dc18SMarcel Moolenaar } 481*27d5dc18SMarcel Moolenaar if (sig & UART_SIG_DRTS) { 482*27d5dc18SMarcel Moolenaar SIGCHG(sig & UART_SIG_RTS, new, UART_SIG_RTS, 483*27d5dc18SMarcel Moolenaar UART_SIG_DRTS); 484*27d5dc18SMarcel Moolenaar } 485*27d5dc18SMarcel Moolenaar } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 486*27d5dc18SMarcel Moolenaar 487*27d5dc18SMarcel Moolenaar if (new & UART_SIG_DTR) 488*27d5dc18SMarcel Moolenaar z8530->tpc |= TPC_DTR; 489*27d5dc18SMarcel Moolenaar else 490*27d5dc18SMarcel Moolenaar z8530->tpc &= ~TPC_DTR; 491*27d5dc18SMarcel Moolenaar if (new & UART_SIG_RTS) 492*27d5dc18SMarcel Moolenaar z8530->tpc |= TPC_RTS; 493*27d5dc18SMarcel Moolenaar else 494*27d5dc18SMarcel Moolenaar z8530->tpc &= ~TPC_RTS; 495*27d5dc18SMarcel Moolenaar uart_setmreg(bas, WR_TPC, z8530->tpc); 496*27d5dc18SMarcel Moolenaar uart_barrier(bas); 497*27d5dc18SMarcel Moolenaar return (0); 498*27d5dc18SMarcel Moolenaar } 499*27d5dc18SMarcel Moolenaar 500*27d5dc18SMarcel Moolenaar static int 501*27d5dc18SMarcel Moolenaar z8530_bus_transmit(struct uart_softc *sc) 502*27d5dc18SMarcel Moolenaar { 503*27d5dc18SMarcel Moolenaar struct uart_bas *bas; 504*27d5dc18SMarcel Moolenaar 505*27d5dc18SMarcel Moolenaar bas = &sc->sc_bas; 506*27d5dc18SMarcel Moolenaar while (!(uart_getmreg(bas, RR_BES) & BES_TXE)) 507*27d5dc18SMarcel Moolenaar ; 508*27d5dc18SMarcel Moolenaar uart_setreg(bas, REG_DATA, sc->sc_txbuf[0]); 509*27d5dc18SMarcel Moolenaar uart_barrier(bas); 510*27d5dc18SMarcel Moolenaar sc->sc_txbusy = 1; 511*27d5dc18SMarcel Moolenaar return (0); 512*27d5dc18SMarcel Moolenaar } 513