From owner-p4-projects@FreeBSD.ORG Mon Feb 21 22:31:00 2005 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 959B316A4D1; Mon, 21 Feb 2005 22:30:59 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 37AB916A4CE for ; Mon, 21 Feb 2005 22:30:59 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8B44A43D4C for ; Mon, 21 Feb 2005 22:30:56 +0000 (GMT) (envelope-from jmg@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j1LMUuUO072579 for ; Mon, 21 Feb 2005 22:30:56 GMT (envelope-from jmg@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j1LMUuxX072576 for perforce@freebsd.org; Mon, 21 Feb 2005 22:30:56 GMT (envelope-from jmg@freebsd.org) Date: Mon, 21 Feb 2005 22:30:56 GMT Message-Id: <200502212230.j1LMUuxX072576@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jmg@freebsd.org using -f From: John-Mark Gurney To: Perforce Change Reviews Subject: PERFORCE change 71502 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Feb 2005 22:31:00 -0000 http://perforce.freebsd.org/chv.cgi?CH=71502 Change 71502 by jmg@jmg_carbon on 2005/02/21 22:30:01 make epuart probe and attach.... teach eparm about resources.. This is still using the virtual map, and we haven't split the busses yet, but now irq's and memory mappings are allocated... teach uart how to handle other irq's than the 0 one so that we don't have to create a stupid shim bus/device just to translate the irq resource request from one of all irq's, down to a specific one.. (This one might be fixed with better/correct/existant hints) use BUSY isntead of TXFE so that the logic is correct, and we really wait till tx is completely done... I think that's all this contains... Affected files ... .. //depot/projects/arm/src/sys/arm/ep93xx/ep93xx.c#5 edit .. //depot/projects/arm/src/sys/arm/ep93xx/ep93xxvar.h#2 edit .. //depot/projects/arm/src/sys/arm/ep93xx/uart_bus_ep93xx.c#2 edit .. //depot/projects/arm/src/sys/arm/ep93xx/uart_cpu_ep93xx.c#2 edit .. //depot/projects/arm/src/sys/dev/uart/uart_bus.h#2 edit .. //depot/projects/arm/src/sys/dev/uart/uart_core.c#2 edit .. //depot/projects/arm/src/sys/dev/uart/uart_dev_epuart.c#3 edit Differences ... ==== //depot/projects/arm/src/sys/arm/ep93xx/ep93xx.c#5 (text+ko) ==== @@ -69,6 +69,11 @@ #include /* XXX */ +struct eparm_softc { + struct rman sc_intr_rman; + struct rman sc_mem_rman; +}; + /* Software copy of the IRQs we have enabled. */ __volatile u_int32_t vic1_intr_enabled; __volatile u_int32_t vic2_intr_enabled; @@ -78,7 +83,6 @@ #define VIC2REG(reg) *((volatile u_int32_t*) (EP93XX_AHB_VBASE + \ EP93XX_AHB_VIC2 + (reg))) - void arm_unmask_irq(int irq) { @@ -130,7 +134,6 @@ vic1_intr_enabled = 0; vic2_intr_enabled = 0; - /* All interrupts should use IRQ not FIQ */ VIC1REG(EP93XX_VIC_IntSelect) = 0; VIC2REG(EP93XX_VIC_IntSelect) = 0; @@ -171,13 +174,42 @@ return (0); } +/* + * XXX - we might want to think about breaking this up into two busses, one + * for APB, and another for AHB. Then we would only manage 0 through BUSHIGH, + * and mappings would be directly relative, i.e. just EP93XX_APB_UART1 instead + * of EP93XX_APB_VBASE + EP93XX_APB_UART1. + */ int ep93xx_attach(device_t dev) { + struct eparm_softc *sc; + device_t chld; + + sc = device_get_softc(dev); + sc->sc_intr_rman.rm_type = RMAN_ARRAY; + sc->sc_intr_rman.rm_descr = "Interrupts"; + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "Register Memory"; + if (rman_init(&sc->sc_intr_rman) != 0 || + rman_init(&sc->sc_mem_rman) != 0 || + rman_manage_region(&sc->sc_intr_rman, 0, NIRQ - 1) != 0 || + rman_manage_region(&sc->sc_mem_rman, EP93XX_AHB_VBASE, + EP93XX_AHB_VBASE + EP93XX_AHB_SIZE - 1) != 0 || + rman_manage_region(&sc->sc_mem_rman, EP93XX_APB_VBASE, + EP93XX_APB_VBASE + EP93XX_APB_SIZE - 1) != 0) + panic("ep93xx_attach(): failed to set up rmans"); ep93xx_intr_init(); - device_add_child(dev, "uart", 0); - device_add_child(dev, "epclk", 0); + + /* XXX - hardcode the device id's? */ + /* XXX - convert to device.hints */ + chld = device_add_child(dev, "uart", -1); + device_set_ivars(chld, (void *)1); + chld = device_add_child(dev, "uart", -1); + device_set_ivars(chld, (void *)2); + + device_add_child(dev, "epclk", -1); /* kick these off */ bus_generic_probe(dev); @@ -214,16 +246,75 @@ } static struct resource * -ep93xx_alloc_resource(device_t dev, device_t child, int type, int *rid, +ep93xx_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - if (type == SYS_RES_IRQ) { - struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK); - res->r_start = start; - res->r_end = end; - return (res); + struct eparm_softc *sc = device_get_softc(bus); + struct resource *rv; + struct rman *rm; + int needactivate = flags & RF_ACTIVE; + + flags &= ~RF_ACTIVE; + + switch (type) { + case SYS_RES_IRQ: + rm = &sc->sc_intr_rman; + break; + case SYS_RES_MEMORY: + rm = &sc->sc_mem_rman; + break; + default: + return (NULL); + } + + /* if non-zero rid, that means it's a specific address */ + if (*rid != 0) + rv = rman_reserve_resource(rm, *rid, *rid + count - 1, count, + flags, child); + else + rv = rman_reserve_resource(rm, start, end, count, flags, child); + + if (rv == NULL) + return (NULL); + if (type == SYS_RES_MEMORY) { + rman_set_bustag(rv, &ep93xx_bs_tag); + rman_set_bushandle(rv, rman_get_start(rv)); + } + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + rman_release_resource(rv); + return (NULL); + } } - return (NULL); + + return (rv); +} + +static int +ep93xx_activate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + /* XXX - enable interrupt? */ + /* not much to do since we use static mappings */ + return rman_activate_resource(r); +} + +static int +ep93xx_deactivate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + /* XXX - disable interrupt? */ + /* not much to do since we use static mappings */ + return rman_deactivate_resource(r); +} + +static int +ep93xx_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + /* not much to do since we use static mappings */ + return rman_release_resource(r); } static int @@ -239,18 +330,21 @@ return (0); } static device_method_t ep93xx_methods[] = { - DEVMETHOD(device_probe, ep93xx_probe), - DEVMETHOD(device_attach, ep93xx_attach), - DEVMETHOD(device_identify, ep93xx_identify), - DEVMETHOD(bus_alloc_resource, ep93xx_alloc_resource), - DEVMETHOD(bus_setup_intr, ep93xx_setup_intr), + DEVMETHOD(device_probe, ep93xx_probe), + DEVMETHOD(device_attach, ep93xx_attach), + DEVMETHOD(device_identify, ep93xx_identify), + DEVMETHOD(bus_alloc_resource, ep93xx_alloc_resource), + DEVMETHOD(bus_activate_resource, ep93xx_activate_resource), + DEVMETHOD(bus_deactivate_resource, ep93xx_deactivate_resource), + DEVMETHOD(bus_release_resource, ep93xx_release_resource), + DEVMETHOD(bus_setup_intr, ep93xx_setup_intr), {0, 0}, }; static driver_t ep93xx_driver = { "eparm", ep93xx_methods, - 1, + sizeof(struct eparm_softc), }; static devclass_t ep93xx_devclass; ==== //depot/projects/arm/src/sys/arm/ep93xx/ep93xxvar.h#2 (text+ko) ==== @@ -45,4 +45,14 @@ extern struct bus_space ep93xx_bs_tag; +#define EPUARTBAS(x) (struct uart_bas) { &ep93xx_bs_tag, \ + EP93XX_APB_VBASE + ((x) == 1 ? EP93XX_APB_UART1 : \ + EP93XX_APB_UART2), (x) == 1 ? 1 : 2, EP93XX_UART_FREQ, 0 } +#if 0 +/* XXX once we get things more properly virtualized */ +#define EPUARTBAS(x) (struct uart_bas) { &ep93xx_bs_tag, \ + ((x) == 1 ? EP93XX_APB_UART1 : EP93XX_APB_UART2), \ + (x) == 1 ? 1 : 2, EP93XX_UART_FREQ, 0 } +#endif + #endif /* _EP93XXVAR_H_ */ ==== //depot/projects/arm/src/sys/arm/ep93xx/uart_bus_ep93xx.c#2 (text+ko) ==== @@ -41,6 +41,9 @@ #include #include +#include +#include + #include "uart_if.h" static int uart_ep93xx_probe(device_t dev); @@ -64,13 +67,17 @@ uart_ep93xx_probe(device_t dev) { struct uart_softc *sc; + int i; + if ((i = (int)device_get_ivars(dev)) < 1 || i > 2) + return ENXIO; + sc = device_get_softc(dev); - sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); - sc->sc_class = &uart_ns8250_class; - bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); - return(uart_bus_probe(dev, 0, 0, 0, 0)); + sc->sc_class = &uart_epuart_class; + sc->sc_bas = EPUARTBAS(i); + sc->sc_irid = i == 1 ? 52 : 54; + return (uart_bus_probe(dev, sc->sc_bas.regshft, sc->sc_bas.rclk, + sc->sc_bas.bsh, sc->sc_bas.chan, sc->sc_irid)); } - DRIVER_MODULE(uart, eparm, uart_ep93xx_driver, uart_devclass, 0, 0); ==== //depot/projects/arm/src/sys/arm/ep93xx/uart_cpu_ep93xx.c#2 (text+ko) ==== @@ -45,6 +45,7 @@ int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { + return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0); } @@ -52,16 +53,12 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) { di->ops = uart_epuart_ops; - di->bas.chan = 0; - di->bas.bst = &ep93xx_bs_tag; - di->bas.regshft = 0; - di->bas.rclk = 0; di->baudrate = 115200; di->databits = 8; di->stopbits = 1; di->parity = UART_PARITY_NONE; uart_bus_space_io = &ep93xx_bs_tag; uart_bus_space_mem = NULL; - di->bas.bsh = EP93XX_APB_VBASE + EP93XX_APB_UART1; + di->bas = EPUARTBAS(1); return (0); } ==== //depot/projects/arm/src/sys/dev/uart/uart_bus.h#2 (text+ko) ==== @@ -94,6 +94,7 @@ extern struct uart_class uart_ns8250_class; extern struct uart_class uart_sab82532_class; extern struct uart_class uart_z8530_class; +extern struct uart_class uart_epuart_class; struct uart_softc { KOBJ_FIELDS; @@ -159,7 +160,8 @@ int uart_bus_attach(device_t dev); int uart_bus_detach(device_t dev); -int uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan); +int uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan, + int irid); int uart_tty_attach(struct uart_softc *); int uart_tty_detach(struct uart_softc *); ==== //depot/projects/arm/src/sys/dev/uart/uart_core.c#2 (text+ko) ==== @@ -219,7 +219,7 @@ } int -uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan) +uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan, int irid) { struct uart_softc *sc; struct uart_devinfo *sysdev; @@ -257,6 +257,7 @@ if (sc->sc_rres == NULL) return (ENXIO); } + sc->sc_irid = irid; /* stash the irq rid */ /* * Fill in the bus access structure and compare this device with @@ -326,7 +327,6 @@ sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); - sc->sc_irid = 0; sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE); if (sc->sc_ires != NULL) { ==== //depot/projects/arm/src/sys/dev/uart/uart_dev_epuart.c#3 (text+ko) ==== @@ -1,6 +1,6 @@ /*- + * Copyright 2005 John-Mark Gurney * Copyright (c) 2003 Marcel Moolenaar - * Copyright 2005 John-Mark Gurney * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,7 +42,6 @@ #include "uart_if.h" -#if 0 /* * Clear pending interrupts. THRE is cleared by reading IIR. Data * that may have been received gets lost here. @@ -50,22 +49,9 @@ static void epuart_clrint(struct uart_bas *bas) { - uint8_t iir; - iir = uart_getreg(bas, REG_IIR); - while ((iir & IIR_NOPEND) == 0) { - iir &= IIR_IMASK; - if (iir == IIR_RLS) - (void)uart_getreg(bas, REG_LSR); - else if (iir == IIR_RXRDY || iir == IIR_RXTOUT) - (void)uart_getreg(bas, REG_DATA); - else if (iir == IIR_MLSC) - (void)uart_getreg(bas, REG_MSR); - uart_barrier(bas); - iir = uart_getreg(bas, REG_IIR); - } + uart_setreg(bas, EP93XX_UART_Ctrl, 0); } -#endif static int epuart_delay(struct uart_bas *bas) @@ -106,7 +92,6 @@ return (divisor); } -#if 0 static int epuart_drain(struct uart_bas *bas, int what) { @@ -121,8 +106,8 @@ * limit high enough to handle large FIFOs. */ limit = 10*1024; - while (uart_getreg(bas, EP93XX_UART_Flag) & EP93XX_UART_F_TXFE - && --limit) + while (uart_getreg(bas, EP93XX_UART_Flag) & + EP93XX_UART_F_BUSY && --limit) DELAY(delay); if (limit == 0) { /* printf("epuart: transmitter appears stuck... "); */ @@ -161,15 +146,14 @@ * We can only flush UARTs with FIFOs. UARTs without FIFOs should be * drained. WARNING: this function clobbers the FIFO setting! */ -static void +static int epuart_flush(struct uart_bas *bas, int what) { - epuart_drain(bas, (what & UART_FLUSH_TRANSMITTER ? + return epuart_drain(bas, (what & UART_FLUSH_TRANSMITTER ? UART_DRAIN_TRANSMITTER : 0) | (what & UART_FLUSH_RECEIVER ? UART_DRAIN_RECEIVER : 0)); } -#endif static int epuart_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, @@ -230,6 +214,8 @@ epuart_probe(struct uart_bas *bas) { + if (bas->chan < 1 || bas->chan > 2) + return (ENXIO); return (0); } @@ -297,15 +283,11 @@ return (uart_getreg(bas, EP93XX_UART_Data)); } -#if 0 /* * High-level UART interface. */ struct epuart_softc { struct uart_softc base; - uint8_t fcr; - uint8_t ier; - uint8_t mcr; }; static int epuart_bus_attach(struct uart_softc *); @@ -339,8 +321,8 @@ "epuart class", epuart_methods, sizeof(struct epuart_softc), - .uc_range = 8, - .uc_rclk = DEFAULT_RCLK + .uc_range = 0x10000, + .uc_rclk = EP93XX_UART_FREQ }; #define SIGCHG(c, i, s, d) \ @@ -353,26 +335,27 @@ static int epuart_bus_attach(struct uart_softc *sc) { - struct epuart_softc *epuart = (struct epuart_softc*)sc; struct uart_bas *bas; + int mdmctrl; + int ctrl; bas = &sc->sc_bas; - epuart->mcr = uart_getreg(bas, REG_MCR); - epuart->fcr = FCR_ENABLE | FCR_RX_MEDH; - uart_setreg(bas, REG_FCR, epuart->fcr); - uart_barrier(bas); epuart_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER); - if (epuart->mcr & MCR_DTR) - sc->sc_hwsig |= SER_DTR; - if (epuart->mcr & MCR_RTS) - sc->sc_hwsig |= SER_RTS; - epuart_bus_getsig(sc); + /* don't futz around with the ctrl reg if it's a console */ + if (bas->chan == 1) { + mdmctrl = uart_getreg(bas, EP93XX_UART_MdmCtrl); + if (mdmctrl & EP93XX_UART_DTR) + sc->sc_hwsig |= SER_DTR; + if (mdmctrl & EP93XX_UART_RTS) + sc->sc_hwsig |= SER_RTS; + epuart_bus_getsig(sc); + } epuart_clrint(bas); - epuart->ier = IER_EMSC | IER_ERLS | IER_ERXRDY; - uart_setreg(bas, REG_IER, epuart->ier); + ctrl = EP93XX_UART_MSIE | EP93XX_UART_RIE | EP93XX_UART_UARTE; + uart_setreg(bas, EP93XX_UART_Ctrl, ctrl); uart_barrier(bas); return (0); } @@ -383,28 +366,20 @@ struct uart_bas *bas; bas = &sc->sc_bas; - uart_setreg(bas, REG_IER, 0); + epuart_clrint(bas); uart_barrier(bas); - epuart_clrint(bas); return (0); } static int epuart_bus_flush(struct uart_softc *sc, int what) { - struct epuart_softc *epuart = (struct epuart_softc*)sc; struct uart_bas *bas; int error; bas = &sc->sc_bas; mtx_lock_spin(&sc->sc_hwmtx); - if (sc->sc_hasfifo) { - epuart_flush(bas, what); - uart_setreg(bas, REG_FCR, epuart->fcr); - uart_barrier(bas); - error = 0; - } else - error = epuart_drain(bas, what); + error = epuart_flush(bas, what); mtx_unlock_spin(&sc->sc_hwmtx); return (error); } @@ -412,21 +387,35 @@ static int epuart_bus_getsig(struct uart_softc *sc) { - uint32_t new, old, sig; - uint8_t msr; + uint32_t new, sig; + uint8_t mdmsts; - do { - old = sc->sc_hwsig; - sig = old; - mtx_lock_spin(&sc->sc_hwmtx); - msr = uart_getreg(&sc->sc_bas, REG_MSR); - mtx_unlock_spin(&sc->sc_hwmtx); - SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR); - SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS); - SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD); - SIGCHG(msr & MSR_RI, sig, SER_RI, SER_DRI); - new = sig & ~UART_SIGMASK_DELTA; - } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); + /* + * We don't spin since we have already destroyed state, should we + * lock the hwsig w/ the spinlock? + */ + mtx_lock_spin(&sc->sc_hwmtx); + mdmsts = uart_getreg(&sc->sc_bas, EP93XX_UART_MdmSts); + sig = 0; + if (mdmsts & EP93XX_UART_MS_DCD) + sig |= SER_DCD; + if (mdmsts & EP93XX_UART_MS_DDCD) + sig |= SER_DDCD; + if (mdmsts & EP93XX_UART_MS_RI) + sig |= SER_RI; + if (mdmsts & EP93XX_UART_MS_TERI) + sig |= SER_DRI; + if (mdmsts & EP93XX_UART_MS_DSR) + sig |= SER_DSR; + if (mdmsts & EP93XX_UART_MS_DDSR) + sig |= SER_DDSR; + if (mdmsts & EP93XX_UART_MS_CTS) + sig |= SER_CTS; + if (mdmsts & EP93XX_UART_MS_DCTS) + sig |= SER_DCTS; + new = sig & ~UART_SIGMASK_DELTA; + sc->sc_hwsig = new; + mtx_unlock_spin(&sc->sc_hwmtx); return (sig); } @@ -435,60 +424,41 @@ { struct uart_bas *bas; int baudrate, divisor, error; - uint8_t efr, lcr; + uint8_t mdmctrl, lctrlh; bas = &sc->sc_bas; error = 0; mtx_lock_spin(&sc->sc_hwmtx); switch (request) { case UART_IOCTL_BREAK: - lcr = uart_getreg(bas, REG_LCR); + lctrlh = uart_getreg(bas, EP93XX_UART_LinCH); if (data) - lcr |= LCR_SBREAK; + lctrlh |= EP93XX_UART_BRK; else - lcr &= ~LCR_SBREAK; - uart_setreg(bas, REG_LCR, lcr); + lctrlh &= ~EP93XX_UART_BRK; + uart_setreg(bas, EP93XX_UART_LinCH, lctrlh); uart_barrier(bas); break; case UART_IOCTL_IFLOW: - lcr = uart_getreg(bas, REG_LCR); - uart_barrier(bas); - uart_setreg(bas, REG_LCR, 0xbf); - uart_barrier(bas); - efr = uart_getreg(bas, REG_EFR); - if (data) - efr |= EFR_RTS; - else - efr &= ~EFR_RTS; - uart_setreg(bas, REG_EFR, efr); - uart_barrier(bas); - uart_setreg(bas, REG_LCR, lcr); - uart_barrier(bas); + if (bas->chan == 1) { + mdmctrl = uart_getreg(bas, EP93XX_UART_MdmCtrl); + if (data) + mdmctrl |= EP93XX_UART_RTS; + else + mdmctrl &= ~EP93XX_UART_RTS; + uart_setreg(bas, EP93XX_UART_MdmCtrl, mdmctrl); + uart_barrier(bas); + } else + error = ENODEV; break; case UART_IOCTL_OFLOW: - lcr = uart_getreg(bas, REG_LCR); - uart_barrier(bas); - uart_setreg(bas, REG_LCR, 0xbf); - uart_barrier(bas); - efr = uart_getreg(bas, REG_EFR); - if (data) - efr |= EFR_CTS; - else - efr &= ~EFR_CTS; - uart_setreg(bas, REG_EFR, efr); - uart_barrier(bas); - uart_setreg(bas, REG_LCR, lcr); - uart_barrier(bas); + /* XXX - hun? I can only read CTS */ break; case UART_IOCTL_BAUD: - lcr = uart_getreg(bas, REG_LCR); - uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); + divisor = uart_getreg(bas, EP93XX_UART_LinCL); + divisor |= uart_getreg(bas, EP93XX_UART_LinCM) << 8; uart_barrier(bas); - divisor = uart_getdreg(bas, REG_DL); - uart_barrier(bas); - uart_setreg(bas, REG_LCR, lcr); - uart_barrier(bas); - baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0; + baudrate = bas->rclk / (16 * (divisor + 1)); if (baudrate > 0) *(int*)data = baudrate; else @@ -507,32 +477,33 @@ { struct uart_bas *bas; int ipend; - uint8_t iir, lsr; + uint8_t iidclr, rxsts; bas = &sc->sc_bas; mtx_lock_spin(&sc->sc_hwmtx); - iir = uart_getreg(bas, REG_IIR); - if (iir & IIR_NOPEND) { + iidclr = uart_getreg(bas, EP93XX_UART_IntIDCLR); + if (!(iidclr & (EP93XX_UART_TIS | EP93XX_UART_RIS | EP93XX_UART_MIS))) { mtx_unlock_spin(&sc->sc_hwmtx); return (0); } ipend = 0; - if (iir & IIR_RXRDY) { - lsr = uart_getreg(bas, REG_LSR); - mtx_unlock_spin(&sc->sc_hwmtx); - if (lsr & LSR_OE) + if (iidclr & EP93XX_UART_RIS) { + rxsts = uart_getreg(bas, EP93XX_UART_RXSts); + uart_setreg(bas, EP93XX_UART_RXSts, 0); /* clear */ + if (rxsts & EP93XX_UART_OE) ipend |= UART_IPEND_OVERRUN; - if (lsr & LSR_BI) + if (rxsts & EP93XX_UART_BE) ipend |= UART_IPEND_BREAK; - if (lsr & LSR_RXRDY) + if (iidclr & EP93XX_UART_RIS) ipend |= UART_IPEND_RXREADY; - } else { - mtx_unlock_spin(&sc->sc_hwmtx); - if (iir & IIR_TXRDY) - ipend |= UART_IPEND_TXIDLE; - else - ipend |= UART_IPEND_SIGCHG; } + if (iidclr & EP93XX_UART_TIS) + ipend |= UART_IPEND_TXIDLE; + if (iidclr & EP93XX_UART_MIS) + ipend |= UART_IPEND_SIGCHG; + + uart_setreg(bas, EP93XX_UART_IntIDCLR, 0); /* clear */ + mtx_unlock_spin(&sc->sc_hwmtx); return ((sc->sc_leaving) ? 0 : ipend); } @@ -554,8 +525,7 @@ epuart_bus_probe(struct uart_softc *sc) { struct uart_bas *bas; - int count, delay, error, limit; - uint8_t lsr, mcr; + int error; bas = &sc->sc_bas; @@ -563,123 +533,28 @@ if (error) return (error); - mcr = MCR_IE; if (sc->sc_sysdev == NULL) { /* By using epuart_init() we also set DTR and RTS. */ epuart_init(bas, 9600, 8, 1, UART_PARITY_NONE); - } else - mcr |= MCR_DTR | MCR_RTS; + } error = epuart_drain(bas, UART_DRAIN_TRANSMITTER); if (error) return (error); /* - * Set loopback mode. This avoids having garbage on the wire and - * also allows us send and receive data. We set DTR and RTS to - * avoid the possibility that automatic flow-control prevents - * any data from being sent. + * XXX - Set loopback mode. I guess we should check operation via + * loopback mode. */ - uart_setreg(bas, REG_MCR, MCR_LOOPBACK | MCR_IE | MCR_DTR | MCR_RTS); - uart_barrier(bas); - /* - * Enable FIFOs. And check that the UART has them. If not, we're - * done. Since this is the first time we enable the FIFOs, we reset - * them. - */ - uart_setreg(bas, REG_FCR, FCR_ENABLE); - uart_barrier(bas); - sc->sc_hasfifo = (uart_getreg(bas, REG_IIR) & IIR_FIFO_MASK) ? 1 : 0; - if (!sc->sc_hasfifo) { - /* - * NS16450 or INS8250. We don't bother to differentiate - * between them. They're too old to be interesting. - */ - uart_setreg(bas, REG_MCR, mcr); - uart_barrier(bas); - device_set_desc(sc->sc_dev, "8250 or 16450 or compatible"); - return (0); - } - - uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST); - uart_barrier(bas); - - count = 0; - delay = epuart_delay(bas); - - /* We have FIFOs. Drain the transmitter and receiver. */ - error = epuart_drain(bas, UART_DRAIN_RECEIVER|UART_DRAIN_TRANSMITTER); - if (error) { - uart_setreg(bas, REG_MCR, mcr); - uart_setreg(bas, REG_FCR, 0); - uart_barrier(bas); - goto describe; - } - - /* - * We should have a sufficiently clean "pipe" to determine the - * size of the FIFOs. We send as much characters as is reasonable - * and wait for the the overflow bit in the LSR register to be - * asserted, counting the characters as we send them. Based on - * that count we know the FIFO size. - */ - do { - uart_setreg(bas, REG_DATA, 0); - uart_barrier(bas); - count++; - - limit = 30; - lsr = 0; - /* - * LSR bits are cleared upon read, so we must accumulate - * them to be able to test LSR_OE below. - */ - while (((lsr |= uart_getreg(bas, REG_LSR)) & LSR_TEMT) == 0 && - --limit) - DELAY(delay); - if (limit == 0) { - uart_setreg(bas, REG_IER, 0); - uart_setreg(bas, REG_MCR, mcr); - uart_setreg(bas, REG_FCR, 0); - uart_barrier(bas); - count = 0; - goto describe; - } - } while ((lsr & LSR_OE) == 0 && count < 130); - count--; - - uart_setreg(bas, REG_MCR, mcr); - - /* Reset FIFOs. */ - epuart_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER); - - describe: - if (count >= 14 && count <= 16) { - sc->sc_rxfifosz = 16; - device_set_desc(sc->sc_dev, "16550 or compatible"); - } else if (count >= 28 && count <= 32) { - sc->sc_rxfifosz = 32; - device_set_desc(sc->sc_dev, "16650 or compatible"); - } else if (count >= 56 && count <= 64) { - sc->sc_rxfifosz = 64; - device_set_desc(sc->sc_dev, "16750 or compatible"); - } else if (count >= 112 && count <= 128) { - sc->sc_rxfifosz = 128; - device_set_desc(sc->sc_dev, "16950 or compatible"); - } else { - sc->sc_rxfifosz = 16; + if (bas->chan == 1) + device_set_desc(sc->sc_dev, + "UART1 with HDLC and Modem Control Signals"); + else device_set_desc(sc->sc_dev, - "Non-standard epuart class UART with FIFOs"); - } + "UART2 with IrDA"); - /* - * Force the Tx FIFO size to 16 bytes for now. We don't program the - * Tx trigger. Also, we assume that all data has been sent when the - * interrupt happens. - */ sc->sc_txfifosz = 16; - #if 0 /* * XXX there are some issues related to hardware flow control and @@ -687,11 +562,6 @@ * investigation, but we avoid using for hardware flow control * until then. */ - /* 16650s or higher have automatic flow control. */ - if (sc->sc_rxfifosz > 16) { - sc->sc_hwiflow = 1; - sc->sc_hwoflow = 1; - } #endif return (0); @@ -702,29 +572,30 @@ { struct uart_bas *bas; int xc; - uint8_t lsr; + uint8_t flag, rxsts; bas = &sc->sc_bas; mtx_lock_spin(&sc->sc_hwmtx); - lsr = uart_getreg(bas, REG_LSR); - while (lsr & LSR_RXRDY) { + flag = uart_getreg(bas, EP93XX_UART_Flag); + while (!(flag & EP93XX_UART_F_RXFE)) { if (uart_rx_full(sc)) { sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; break; } - xc = uart_getreg(bas, REG_DATA); - if (lsr & LSR_FE) + xc = uart_getreg(bas, EP93XX_UART_Data); + rxsts = uart_getreg(bas, EP93XX_UART_Data); + if (rxsts & EP93XX_UART_FE) xc |= UART_STAT_FRAMERR; - if (lsr & LSR_PE) + if (rxsts & EP93XX_UART_PE) xc |= UART_STAT_PARERR; uart_rx_put(sc, xc); - lsr = uart_getreg(bas, REG_LSR); + flag = uart_getreg(bas, EP93XX_UART_Flag); } /* Discard everything left in the Rx FIFO. */ - while (lsr & LSR_RXRDY) { - (void)uart_getreg(bas, REG_DATA); + while (flag & EP93XX_UART_F_RXFE) { + (void)uart_getreg(bas, EP93XX_UART_Data); uart_barrier(bas); - lsr = uart_getreg(bas, REG_LSR); + flag = uart_getreg(bas, EP93XX_UART_Flag); } mtx_unlock_spin(&sc->sc_hwmtx); return (0); @@ -733,9 +604,9 @@ static int epuart_bus_setsig(struct uart_softc *sc, int sig) { - struct epuart_softc *epuart = (struct epuart_softc*)sc; struct uart_bas *bas; uint32_t new, old; + int mdmctrl; bas = &sc->sc_bas; do { @@ -751,12 +622,12 @@ } } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); mtx_lock_spin(&sc->sc_hwmtx); - epuart->mcr &= ~(MCR_DTR|MCR_RTS); + mdmctrl = 0; if (new & SER_DTR) - epuart->mcr |= MCR_DTR; + mdmctrl |= EP93XX_UART_DTR; if (new & SER_RTS) - epuart->mcr |= MCR_RTS; - uart_setreg(bas, REG_MCR, epuart->mcr); + mdmctrl |= EP93XX_UART_RTS; + uart_setreg(bas, EP93XX_UART_MdmCtrl, mdmctrl); uart_barrier(bas); mtx_unlock_spin(&sc->sc_hwmtx); return (0); @@ -765,22 +636,23 @@ static int epuart_bus_transmit(struct uart_softc *sc) { - struct epuart_softc *epuart = (struct epuart_softc*)sc; struct uart_bas *bas; int i; + int ctrl; bas = &sc->sc_bas; mtx_lock_spin(&sc->sc_hwmtx); - while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0) + /* XXX - ugly, this sucks, but that's the way uart forces us to be */ + while ((uart_getreg(bas, EP93XX_UART_Flag) & EP93XX_UART_F_TXFE) == 0) ; - uart_setreg(bas, REG_IER, epuart->ier | IER_ETXRDY); + ctrl = uart_getreg(bas, EP93XX_UART_Ctrl); + uart_setreg(bas, EP93XX_UART_Ctrl, ctrl | EP93XX_UART_TIE); uart_barrier(bas); for (i = 0; i < sc->sc_txdatasz; i++) { - uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]); + uart_setreg(bas, EP93XX_UART_Data, sc->sc_txbuf[i]); uart_barrier(bas); } sc->sc_txbusy = 1; mtx_unlock_spin(&sc->sc_hwmtx); return (0); } -#endif