Index: head/sys/arm/at91/uart_bus_at91usart.c =================================================================== --- head/sys/arm/at91/uart_bus_at91usart.c (revision 314361) +++ head/sys/arm/at91/uart_bus_at91usart.c (revision 314362) @@ -1,111 +1,111 @@ /*- * Copyright (c) 2005 Olivier Houchard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" extern struct uart_class at91_usart_class; static int usart_at91_probe(device_t dev); static device_method_t usart_at91_methods[] = { /* Device interface */ DEVMETHOD(device_probe, usart_at91_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t usart_at91_driver = { uart_driver_name, usart_at91_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int usart_at91_probe(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); switch (device_get_unit(dev)) { case 0: device_set_desc(dev, "DBGU"); /* * Setting sc_sysdev makes this device a 'system device' and * indirectly makes it the system console. */ sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); break; case 1: device_set_desc(dev, "USART0"); break; case 2: device_set_desc(dev, "USART1"); break; case 3: device_set_desc(dev, "USART2"); break; case 4: device_set_desc(dev, "USART3"); break; case 5: device_set_desc(dev, "USART4"); break; case 6: device_set_desc(dev, "USART5"); break; } sc->sc_class = &at91_usart_class; if (sc->sc_class->uc_rclk == 0) sc->sc_class->uc_rclk = at91_master_clock; - return (uart_bus_probe(dev, 0, 0, 0, device_get_unit(dev))); + return (uart_bus_probe(dev, 0, 0, 0, 0, device_get_unit(dev))); } DRIVER_MODULE(uart, atmelarm, usart_at91_driver, uart_devclass, 0, 0); Index: head/sys/arm/cavium/cns11xx/uart_bus_ec.c =================================================================== --- head/sys/arm/cavium/cns11xx/uart_bus_ec.c (revision 314361) +++ head/sys/arm/cavium/cns11xx/uart_bus_ec.c (revision 314362) @@ -1,76 +1,76 @@ /*- * Copyright (C) 2009 Yohanes Nugroho * All rights reserved. * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include static int uart_ec_probe(device_t dev); static device_method_t uart_ec_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_ec_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_ec_driver = { uart_driver_name, uart_ec_methods, sizeof(struct uart_softc), }; static int uart_ec_probe(device_t dev) { struct uart_softc *sc; int status; sc = device_get_softc(dev); sc->sc_class = &uart_ns8250_class; - status = uart_bus_probe(dev, EC_UART_REGSHIFT, EC_UART_CLOCK, 0, 0); + status = uart_bus_probe(dev, EC_UART_REGSHIFT, 0, EC_UART_CLOCK, 0, 0); return (status); } DRIVER_MODULE(uart, econaarm, uart_ec_driver, uart_devclass, 0, 0); Index: head/sys/arm/nvidia/tegra_uart.c =================================================================== --- head/sys/arm/nvidia/tegra_uart.c (revision 314361) +++ head/sys/arm/nvidia/tegra_uart.c (revision 314362) @@ -1,250 +1,250 @@ /*- * Copyright (c) 2016 Michal Meloun * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * UART driver for Tegra SoCs. */ #include "opt_platform.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" /* * High-level UART interface. */ struct tegra_softc { struct ns8250_softc ns8250_base; clk_t clk; hwreset_t reset; }; /* * UART class interface. */ static int tegra_uart_attach(struct uart_softc *sc) { int rv; struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; struct uart_bas *bas = &sc->sc_bas; rv = ns8250_bus_attach(sc); if (rv != 0) return (rv); ns8250->ier_rxbits = 0x1d; ns8250->ier_mask = 0xc0; ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; ns8250->ier |= ns8250->ier_rxbits; uart_setreg(bas, REG_IER, ns8250->ier); uart_barrier(bas); return (0); } static void tegra_uart_grab(struct uart_softc *sc) { struct uart_bas *bas = &sc->sc_bas; struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; u_char ier; /* * turn off all interrupts to enter polling mode. Leave the * saved mask alone. We'll restore whatever it was in ungrab. * All pending interrupt signals are reset when IER is set to 0. */ uart_lock(sc->sc_hwmtx); ier = uart_getreg(bas, REG_IER); uart_setreg(bas, REG_IER, ier & ns8250->ier_mask); uart_setreg(bas, REG_FCR, 0); uart_barrier(bas); uart_unlock(sc->sc_hwmtx); } static void tegra_uart_ungrab(struct uart_softc *sc) { struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc; struct uart_bas *bas = &sc->sc_bas; /* * Restore previous interrupt mask */ uart_lock(sc->sc_hwmtx); uart_setreg(bas, REG_FCR, ns8250->fcr); uart_setreg(bas, REG_IER, ns8250->ier); uart_barrier(bas); uart_unlock(sc->sc_hwmtx); } static kobj_method_t tegra_methods[] = { KOBJMETHOD(uart_probe, ns8250_bus_probe), KOBJMETHOD(uart_attach, tegra_uart_attach), KOBJMETHOD(uart_detach, ns8250_bus_detach), KOBJMETHOD(uart_flush, ns8250_bus_flush), KOBJMETHOD(uart_getsig, ns8250_bus_getsig), KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl), KOBJMETHOD(uart_ipend, ns8250_bus_ipend), KOBJMETHOD(uart_param, ns8250_bus_param), KOBJMETHOD(uart_receive, ns8250_bus_receive), KOBJMETHOD(uart_setsig, ns8250_bus_setsig), KOBJMETHOD(uart_transmit, ns8250_bus_transmit), KOBJMETHOD(uart_grab, tegra_uart_grab), KOBJMETHOD(uart_ungrab, tegra_uart_ungrab), KOBJMETHOD_END }; static struct uart_class tegra_uart_class = { "tegra class", tegra_methods, sizeof(struct tegra_softc), .uc_ops = &uart_ns8250_ops, .uc_range = 8, .uc_rclk = 0, }; /* Compatible devices. */ static struct ofw_compat_data compat_data[] = { {"nvidia,tegra124-uart", (uintptr_t)&tegra_uart_class}, {NULL, (uintptr_t)NULL}, }; UART_FDT_CLASS(compat_data); /* * UART Driver interface. */ static int uart_fdt_get_shift1(phandle_t node) { pcell_t shift; if ((OF_getencprop(node, "reg-shift", &shift, sizeof(shift))) <= 0) shift = 2; return ((int)shift); } static int tegra_uart_probe(device_t dev) { struct tegra_softc *sc; phandle_t node; uint64_t freq; int shift; int rv; const struct ofw_compat_data *cd; sc = device_get_softc(dev); if (!ofw_bus_status_okay(dev)) return (ENXIO); cd = ofw_bus_search_compatible(dev, compat_data); if (cd->ocd_data == 0) return (ENXIO); sc->ns8250_base.base.sc_class = (struct uart_class *)cd->ocd_data; rv = hwreset_get_by_ofw_name(dev, 0, "serial", &sc->reset); if (rv != 0) { device_printf(dev, "Cannot get 'serial' reset\n"); return (ENXIO); } rv = hwreset_deassert(sc->reset); if (rv != 0) { device_printf(dev, "Cannot unreset 'serial' reset\n"); return (ENXIO); } node = ofw_bus_get_node(dev); shift = uart_fdt_get_shift1(node); rv = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); if (rv != 0) { device_printf(dev, "Cannot get UART clock: %d\n", rv); return (ENXIO); } rv = clk_enable(sc->clk); if (rv != 0) { device_printf(dev, "Cannot enable UART clock: %d\n", rv); return (ENXIO); } rv = clk_get_freq(sc->clk, &freq); if (rv != 0) { device_printf(dev, "Cannot enable UART clock: %d\n", rv); return (ENXIO); } - return (uart_bus_probe(dev, shift, (int)freq, 0, 0)); + return (uart_bus_probe(dev, shift, 0, (int)freq, 0, 0)); } static int tegra_uart_detach(device_t dev) { struct tegra_softc *sc; sc = device_get_softc(dev); if (sc->clk != NULL) { clk_release(sc->clk); } return (uart_bus_detach(dev)); } static device_method_t tegra_uart_bus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, tegra_uart_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, tegra_uart_detach), { 0, 0 } }; static driver_t tegra_uart_driver = { uart_driver_name, tegra_uart_bus_methods, sizeof(struct tegra_softc), }; DRIVER_MODULE(tegra_uart, simplebus, tegra_uart_driver, uart_devclass, 0, 0); Index: head/sys/arm/xscale/i8134x/uart_bus_i81342.c =================================================================== --- head/sys/arm/xscale/i8134x/uart_bus_i81342.c (revision 314361) +++ head/sys/arm/xscale/i8134x/uart_bus_i81342.c (revision 314362) @@ -1,92 +1,92 @@ /*- * Copyright (c) 2004 Olivier Houchard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" static int uart_i81342_probe(device_t dev); static device_method_t uart_i81342_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_i81342_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_i81342_driver = { uart_driver_name, uart_i81342_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_i81342_probe(device_t dev) { struct uart_softc *sc; int err; sc = device_get_softc(dev); sc->sc_class = &uart_ns8250_class; if (device_get_unit(dev) == 0) { sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); } sc->sc_rres = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &sc->sc_rrid, uart_getrange(sc->sc_class), RF_ACTIVE); sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh, REG_IER << 2, 0x40 | 0x10); bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); - err = uart_bus_probe(dev, 2, 33334000, 0, device_get_unit(dev)); + err = uart_bus_probe(dev, 2, 0, 33334000, 0, device_get_unit(dev)); sc->sc_rxfifosz = sc->sc_txfifosz = 1; return (err); } DRIVER_MODULE(uart, obio, uart_i81342_driver, uart_devclass, 0, 0); Index: head/sys/arm/xscale/ixp425/uart_bus_ixp425.c =================================================================== --- head/sys/arm/xscale/ixp425/uart_bus_ixp425.c (revision 314361) +++ head/sys/arm/xscale/ixp425/uart_bus_ixp425.c (revision 314362) @@ -1,82 +1,82 @@ /*- * Copyright (c) 2006 Kevin Lo. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" static int uart_ixp425_probe(device_t dev); static device_method_t uart_ixp425_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_ixp425_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_ixp425_driver = { uart_driver_name, uart_ixp425_methods, sizeof(struct uart_softc), }; DRIVER_MODULE(uart, ixp, uart_ixp425_driver, uart_devclass, 0, 0); static int uart_ixp425_probe(device_t dev) { struct uart_softc *sc; int unit = device_get_unit(dev); u_int rclk; sc = device_get_softc(dev); sc->sc_class = &uart_ns8250_class; if (resource_int_value("uart", unit, "rclk", &rclk)) rclk = IXP425_UART_FREQ; if (bootverbose) device_printf(dev, "rclk %u\n", rclk); - return uart_bus_probe(dev, 0, rclk, 0, 0); + return uart_bus_probe(dev, 0, 0, rclk, 0, 0); } Index: head/sys/arm/xscale/pxa/uart_bus_pxa.c =================================================================== --- head/sys/arm/xscale/pxa/uart_bus_pxa.c (revision 314361) +++ head/sys/arm/xscale/pxa/uart_bus_pxa.c (revision 314362) @@ -1,103 +1,103 @@ /*- * Copyright (c) 2006 Benno Rice. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" #define PXA_UART_UUE 0x40 /* UART Unit Enable */ static int uart_pxa_probe(device_t dev); static device_method_t uart_pxa_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_pxa_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_pxa_driver = { uart_driver_name, uart_pxa_methods, sizeof(struct uart_softc), }; static int uart_pxa_probe(device_t dev) { bus_space_handle_t base; struct uart_softc *sc; base = (bus_space_handle_t)pxa_get_base(dev); #ifdef QEMU_WORKAROUNDS /* * QEMU really exposes only the first uart unless * you specify several of them in the configuration. * Otherwise all the rest of UARTs stay unconnected, * which causes problems in the ns16550 attach routine. * Unfortunately, even if you provide qemu with 4 uarts * on the command line, it has a bug where it segfaults * trying to enable bluetooth on the HWUART. So we just * allow the FFUART to be attached. * Also, don't check the UUE (UART Unit Enable) bit, as * the gumstix bootloader doesn't set it. */ if (base != PXA2X0_FFUART_BASE) return (ENXIO); #else /* Check to see if the enable bit's on. */ if ((bus_space_read_4(obio_tag, base, (REG_IER << 2)) & PXA_UART_UUE) == 0) return (ENXIO); #endif sc = device_get_softc(dev); sc->sc_class = &uart_ns8250_class; - return(uart_bus_probe(dev, 2, PXA2X0_COM_FREQ, 0, 0)); + return(uart_bus_probe(dev, 2, 0, PXA2X0_COM_FREQ, 0, 0)); } DRIVER_MODULE(uart, pxa, uart_pxa_driver, uart_devclass, 0, 0); Index: head/sys/dev/uart/uart.h =================================================================== --- head/sys/dev/uart/uart.h (revision 314361) +++ head/sys/dev/uart/uart.h (revision 314362) @@ -1,93 +1,127 @@ /*- * Copyright (c) 2003 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DEV_UART_H_ #define _DEV_UART_H_ /* * Bus access structure. This structure holds the minimum information needed * to access the UART. The rclk field, although not important to actually * access the UART, is important for baudrate programming, delay loops and * other timing related computations. */ struct uart_bas { bus_space_tag_t bst; bus_space_handle_t bsh; u_int chan; u_int rclk; u_int regshft; + u_int regiowidth; }; #define uart_regofs(bas, reg) ((reg) << (bas)->regshft) +#define uart_regiowidth(bas) ((bas)->regiowidth) -#define uart_getreg(bas, reg) \ - bus_space_read_1((bas)->bst, (bas)->bsh, uart_regofs(bas, reg)) -#define uart_setreg(bas, reg, value) \ - bus_space_write_1((bas)->bst, (bas)->bsh, uart_regofs(bas, reg), value) +static inline uint32_t +uart_getreg(struct uart_bas *bas, int reg) +{ + uint32_t ret; + + switch (uart_regiowidth(bas)) { + case 4: + ret = bus_space_read_4(bas->bst, bas->bsh, uart_regofs(bas, reg)); + break; + case 2: + ret = bus_space_read_2(bas->bst, bas->bsh, uart_regofs(bas, reg)); + break; + default: + ret = bus_space_read_1(bas->bst, bas->bsh, uart_regofs(bas, reg)); + break; + } + + return (ret); +} + +static inline void +uart_setreg(struct uart_bas *bas, int reg, int value) +{ + + switch (uart_regiowidth(bas)) { + case 4: + bus_space_write_4(bas->bst, bas->bsh, uart_regofs(bas, reg), value); + break; + case 2: + bus_space_write_2(bas->bst, bas->bsh, uart_regofs(bas, reg), value); + break; + default: + bus_space_write_1(bas->bst, bas->bsh, uart_regofs(bas, reg), value); + break; + } +} /* * XXX we don't know the length of the bus space address range in use by * the UART. Since barriers don't use the length field currently, we put * a zero there for now. */ #define uart_barrier(bas) \ bus_space_barrier((bas)->bst, (bas)->bsh, 0, 0, \ BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE) /* * UART device classes. */ struct uart_class; extern struct uart_class uart_ns8250_class __attribute__((weak)); extern struct uart_class uart_quicc_class __attribute__((weak)); extern struct uart_class uart_s3c2410_class __attribute__((weak)); extern struct uart_class uart_sab82532_class __attribute__((weak)); extern struct uart_class uart_sbbc_class __attribute__((weak)); extern struct uart_class uart_z8530_class __attribute__((weak)); /* * Device flags. */ #define UART_FLAGS_CONSOLE(f) ((f) & 0x10) #define UART_FLAGS_DBGPORT(f) ((f) & 0x80) #define UART_FLAGS_FCR_RX_LOW(f) ((f) & 0x100) #define UART_FLAGS_FCR_RX_MEDL(f) ((f) & 0x200) #define UART_FLAGS_FCR_RX_MEDH(f) ((f) & 0x400) #define UART_FLAGS_FCR_RX_HIGH(f) ((f) & 0x800) /* * Data parity values (magical numbers related to ns8250). */ #define UART_PARITY_NONE 0 #define UART_PARITY_ODD 1 #define UART_PARITY_EVEN 3 #define UART_PARITY_MARK 5 #define UART_PARITY_SPACE 7 #endif /* _DEV_UART_H_ */ Index: head/sys/dev/uart/uart_bus.h =================================================================== --- head/sys/dev/uart/uart_bus.h (revision 314361) +++ head/sys/dev/uart/uart_bus.h (revision 314362) @@ -1,216 +1,217 @@ /*- * Copyright (c) 2003 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DEV_UART_BUS_H_ #define _DEV_UART_BUS_H_ #ifndef KLD_MODULE #include "opt_uart.h" #endif #include #include /* Drain and flush targets. */ #define UART_DRAIN_RECEIVER 0x0001 #define UART_DRAIN_TRANSMITTER 0x0002 #define UART_FLUSH_RECEIVER UART_DRAIN_RECEIVER #define UART_FLUSH_TRANSMITTER UART_DRAIN_TRANSMITTER /* Received character status bits. */ #define UART_STAT_BREAK 0x0100 #define UART_STAT_FRAMERR 0x0200 #define UART_STAT_OVERRUN 0x0400 #define UART_STAT_PARERR 0x0800 /* UART_IOCTL() requests */ #define UART_IOCTL_BREAK 1 #define UART_IOCTL_IFLOW 2 #define UART_IOCTL_OFLOW 3 #define UART_IOCTL_BAUD 4 /* * UART class & instance (=softc) */ struct uart_class { KOBJ_CLASS_FIELDS; struct uart_ops *uc_ops; /* Low-level console operations. */ u_int uc_range; /* Bus space address range. */ u_int uc_rclk; /* Default rclk for this device. */ u_int uc_rshift; /* Default regshift for this device. */ + u_int uc_riowidth; /* Default reg io width for this device. */ }; struct uart_softc { KOBJ_FIELDS; struct uart_class *sc_class; struct uart_bas sc_bas; device_t sc_dev; struct mtx sc_hwmtx_s; /* Spinlock protecting hardware. */ struct mtx *sc_hwmtx; struct resource *sc_rres; /* Register resource. */ int sc_rrid; int sc_rtype; /* SYS_RES_{IOPORT|MEMORY}. */ struct resource *sc_ires; /* Interrupt resource. */ void *sc_icookie; int sc_irid; struct callout sc_timer; int sc_callout:1; /* This UART is opened for callout. */ int sc_fastintr:1; /* This UART uses fast interrupts. */ int sc_hwiflow:1; /* This UART has HW input flow ctl. */ int sc_hwoflow:1; /* This UART has HW output flow ctl. */ int sc_leaving:1; /* This UART is going away. */ int sc_opened:1; /* This UART is open for business. */ int sc_polled:1; /* This UART has no interrupts. */ int sc_txbusy:1; /* This UART is transmitting. */ int sc_isquelch:1; /* This UART has input squelched. */ int sc_testintr:1; /* This UART is under int. testing. */ struct uart_devinfo *sc_sysdev; /* System device (or NULL). */ int sc_altbrk; /* State for alt break sequence. */ uint32_t sc_hwsig; /* Signal state. Used by HW driver. */ /* Receiver data. */ uint16_t *sc_rxbuf; int sc_rxbufsz; int sc_rxput; int sc_rxget; int sc_rxfifosz; /* Size of RX FIFO. */ /* Transmitter data. */ uint8_t *sc_txbuf; int sc_txdatasz; int sc_txfifosz; /* Size of TX FIFO and buffer. */ /* Pulse capturing support (PPS). */ struct pps_state sc_pps; int sc_pps_mode; sbintime_t sc_pps_captime; /* Upper layer data. */ void *sc_softih; uint32_t sc_ttypend; union { /* TTY specific data. */ struct { struct tty *tp; } u_tty; /* Keyboard specific data. */ struct { } u_kbd; } sc_u; }; extern devclass_t uart_devclass; extern const char uart_driver_name[]; int uart_bus_attach(device_t dev); int uart_bus_detach(device_t dev); int uart_bus_resume(device_t dev); serdev_intr_t *uart_bus_ihand(device_t dev, int ipend); int uart_bus_ipend(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 regiowidth, int rclk, int rid, int chan); int uart_bus_sysdev(device_t dev); void uart_sched_softih(struct uart_softc *, uint32_t); int uart_tty_attach(struct uart_softc *); int uart_tty_detach(struct uart_softc *); struct mtx *uart_tty_getlock(struct uart_softc *); void uart_tty_intr(void *arg); /* * Receive buffer operations. */ static __inline int uart_rx_empty(struct uart_softc *sc) { return ((sc->sc_rxget == sc->sc_rxput) ? 1 : 0); } static __inline int uart_rx_full(struct uart_softc *sc) { return ((sc->sc_rxput + 1 < sc->sc_rxbufsz) ? (sc->sc_rxput + 1 == sc->sc_rxget) : (sc->sc_rxget == 0)); } static __inline int uart_rx_get(struct uart_softc *sc) { int ptr, xc; ptr = sc->sc_rxget; if (ptr == sc->sc_rxput) return (-1); xc = sc->sc_rxbuf[ptr++]; sc->sc_rxget = (ptr < sc->sc_rxbufsz) ? ptr : 0; return (xc); } static __inline int uart_rx_next(struct uart_softc *sc) { int ptr; ptr = sc->sc_rxget; if (ptr == sc->sc_rxput) return (-1); ptr += 1; sc->sc_rxget = (ptr < sc->sc_rxbufsz) ? ptr : 0; return (0); } static __inline int uart_rx_peek(struct uart_softc *sc) { int ptr; ptr = sc->sc_rxget; return ((ptr == sc->sc_rxput) ? -1 : sc->sc_rxbuf[ptr]); } static __inline int uart_rx_put(struct uart_softc *sc, int xc) { int ptr; ptr = (sc->sc_rxput + 1 < sc->sc_rxbufsz) ? sc->sc_rxput + 1 : 0; if (ptr == sc->sc_rxget) return (ENOSPC); sc->sc_rxbuf[sc->sc_rxput] = xc; sc->sc_rxput = ptr; return (0); } #endif /* _DEV_UART_BUS_H_ */ Index: head/sys/dev/uart/uart_bus_acpi.c =================================================================== --- head/sys/dev/uart/uart_bus_acpi.c (revision 314361) +++ head/sys/dev/uart/uart_bus_acpi.c (revision 314362) @@ -1,124 +1,124 @@ /*- * Copyright (c) 2001 M. Warner Losh. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __aarch64__ #include #include #include #endif static int uart_acpi_probe(device_t dev); static device_method_t uart_acpi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_acpi_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD(device_resume, uart_bus_resume), { 0, 0 } }; static driver_t uart_acpi_driver = { uart_driver_name, uart_acpi_methods, sizeof(struct uart_softc), }; #if defined(__i386__) || defined(__amd64__) static struct isa_pnp_id acpi_ns8250_ids[] = { {0x0005d041, "Standard PC COM port"}, /* PNP0500 */ {0x0105d041, "16550A-compatible COM port"}, /* PNP0501 */ {0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */ {0x1005d041, "Generic IRDA-compatible device"}, /* PNP0510 */ {0x1105d041, "Generic IRDA-compatible device"}, /* PNP0511 */ {0x04f0235c, "Wacom Tablet PC Screen"}, /* WACF004 */ {0xe502aa1a, "Wacom Tablet at FuS Lifebook T"}, /* FUJ02E5 */ {0} }; #endif #ifdef __aarch64__ static struct uart_class * uart_acpi_find_device(device_t dev) { struct acpi_uart_compat_data **cd; ACPI_HANDLE h; if ((h = acpi_get_handle(dev)) == NULL) return (NULL); SET_FOREACH(cd, uart_acpi_class_and_device_set) { if (acpi_MatchHid(h, (*cd)->hid)) { return ((*cd)->clas); } } return (NULL); } #endif static int uart_acpi_probe(device_t dev) { struct uart_softc *sc; device_t parent; parent = device_get_parent(dev); sc = device_get_softc(dev); #if defined(__i386__) || defined(__amd64__) if (!ISA_PNP_PROBE(parent, dev, acpi_ns8250_ids)) { sc->sc_class = &uart_ns8250_class; - return (uart_bus_probe(dev, 0, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0, 0)); } /* Add checks for non-ns8250 IDs here. */ #elif defined(__aarch64__) if ((sc->sc_class = uart_acpi_find_device(dev)) != NULL) - return (uart_bus_probe(dev, 2, 0, 0, 0)); + return (uart_bus_probe(dev, 2, 0, 0, 0, 0)); #endif return (ENXIO); } DRIVER_MODULE(uart, acpi, uart_acpi_driver, uart_devclass, 0, 0); Index: head/sys/dev/uart/uart_bus_ebus.c =================================================================== --- head/sys/dev/uart/uart_bus_ebus.c (revision 314361) +++ head/sys/dev/uart/uart_bus_ebus.c (revision 314362) @@ -1,106 +1,106 @@ /*- * Copyright (c) 2001 by Thomas Moestl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include static int uart_ebus_probe(device_t dev); static device_method_t uart_ebus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_ebus_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_ebus_driver = { uart_driver_name, uart_ebus_methods, sizeof(struct uart_softc), }; static int uart_ebus_probe(device_t dev) { const char *nm, *cmpt; struct uart_softc *sc; struct uart_devinfo dummy; sc = device_get_softc(dev); sc->sc_class = NULL; nm = ofw_bus_get_name(dev); cmpt = ofw_bus_get_compat(dev); if (cmpt == NULL) cmpt = ""; if (!strcmp(nm, "lom-console") || !strcmp(nm, "su") || !strcmp(nm, "su_pnp") || !strcmp(cmpt, "rsc-console") || !strcmp(cmpt, "rsc-control") || !strcmp(cmpt, "su") || !strcmp(cmpt, "su16550") || !strcmp(cmpt, "su16552")) { /* * On AXi and AXmp boards the NS16550 (used to connect * keyboard/mouse) share their IRQ lines with the i8042. * Any IRQ activity (typically during attach) of the * NS16550 used to connect the keyboard when actually the * PS/2 keyboard is selected in OFW causes interaction * with the OBP i8042 driver resulting in a hang and vice * versa. As RS232 keyboards and mice obviously aren't * meant to be used in parallel with PS/2 ones on these * boards don't attach to the NS16550 in case the RS232 * keyboard isn't selected in order to prevent such hangs. */ if ((!strcmp(sparc64_model, "SUNW,UltraAX-MP") || !strcmp(sparc64_model, "SUNW,UltraSPARC-IIi-Engine")) && uart_cpu_getdev(UART_DEV_KEYBOARD, &dummy)) { device_disable(dev); return (ENXIO); } sc->sc_class = &uart_ns8250_class; - return (uart_bus_probe(dev, 0, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0, 0)); } return (ENXIO); } DRIVER_MODULE(uart, ebus, uart_ebus_driver, uart_devclass, 0, 0); Index: head/sys/dev/uart/uart_bus_fdt.c =================================================================== --- head/sys/dev/uart/uart_bus_fdt.c (revision 314361) +++ head/sys/dev/uart/uart_bus_fdt.c (revision 314362) @@ -1,258 +1,274 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * All rights reserved. * * This software was developed by Semihalf under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_platform.h" #include #include #include #include #include #include #include #include #include #include #include #include #include static int uart_fdt_probe(device_t); static device_method_t uart_fdt_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_fdt_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_fdt_driver = { uart_driver_name, uart_fdt_methods, sizeof(struct uart_softc), }; int uart_fdt_get_clock(phandle_t node, pcell_t *cell) { /* clock-frequency is a FreeBSD-only extension. */ if ((OF_getencprop(node, "clock-frequency", cell, sizeof(*cell))) <= 0) { /* Try to retrieve parent 'bus-frequency' */ /* XXX this should go to simple-bus fixup or so */ if ((OF_getencprop(OF_parent(node), "bus-frequency", cell, sizeof(*cell))) <= 0) *cell = 0; } return (0); } int uart_fdt_get_shift(phandle_t node, pcell_t *cell) { if ((OF_getencprop(node, "reg-shift", cell, sizeof(*cell))) <= 0) return (-1); return (0); } +int +uart_fdt_get_io_width(phandle_t node, pcell_t *cell) +{ + + if ((OF_getencprop(node, "reg-io-width", cell, sizeof(*cell))) <= 0) + return (-1); + return (0); +} + static uintptr_t uart_fdt_find_device(device_t dev) { struct ofw_compat_data **cd; const struct ofw_compat_data *ocd; SET_FOREACH(cd, uart_fdt_class_and_device_set) { ocd = ofw_bus_search_compatible(dev, *cd); if (ocd->ocd_data != 0) return (ocd->ocd_data); } return (0); } static int phandle_chosen_propdev(phandle_t chosen, const char *name, phandle_t *node) { char buf[64]; if (OF_getprop(chosen, name, buf, sizeof(buf)) <= 0) return (ENXIO); if ((*node = OF_finddevice(buf)) == -1) return (ENXIO); return (0); } static const struct ofw_compat_data * uart_fdt_find_compatible(phandle_t node, const struct ofw_compat_data *cd) { const struct ofw_compat_data *ocd; for (ocd = cd; ocd->ocd_str != NULL; ocd++) { if (ofw_bus_node_is_compatible(node, ocd->ocd_str)) return (ocd); } return (NULL); } static uintptr_t uart_fdt_find_by_node(phandle_t node, int class_list) { struct ofw_compat_data **cd; const struct ofw_compat_data *ocd; if (class_list) { SET_FOREACH(cd, uart_fdt_class_set) { ocd = uart_fdt_find_compatible(node, *cd); if ((ocd != NULL) && (ocd->ocd_data != 0)) return (ocd->ocd_data); } } else { SET_FOREACH(cd, uart_fdt_class_and_device_set) { ocd = uart_fdt_find_compatible(node, *cd); if ((ocd != NULL) && (ocd->ocd_data != 0)) return (ocd->ocd_data); } } return (0); } int uart_cpu_fdt_probe(struct uart_class **classp, bus_space_tag_t *bst, - bus_space_handle_t *bsh, int *baud, u_int *rclk, u_int *shiftp) + bus_space_handle_t *bsh, int *baud, u_int *rclk, u_int *shiftp, + u_int *iowidthp) { const char *propnames[] = {"stdout-path", "linux,stdout-path", "stdout", "stdin-path", "stdin", NULL}; const char **name; struct uart_class *class; phandle_t node, chosen; - pcell_t br, clk, shift; + pcell_t br, clk, shift, iowidth; char *cp; int err; /* Has the user forced a specific device node? */ cp = kern_getenv("hw.fdt.console"); if (cp == NULL) { /* * Retrieve /chosen/std{in,out}. */ node = -1; if ((chosen = OF_finddevice("/chosen")) != -1) { for (name = propnames; *name != NULL; name++) { if (phandle_chosen_propdev(chosen, *name, &node) == 0) break; } } if (chosen == -1 || *name == NULL) node = OF_finddevice("serial0"); /* Last ditch */ } else { node = OF_finddevice(cp); } if (node == -1) return (ENXIO); /* * Check old style of UART definition first. Unfortunately, the common * FDT processing is not possible if we have clock, power domains and * pinmux stuff. */ class = (struct uart_class *)uart_fdt_find_by_node(node, 0); if (class != NULL) { if ((err = uart_fdt_get_clock(node, &clk)) != 0) return (err); } else { /* Check class only linker set */ class = (struct uart_class *)uart_fdt_find_by_node(node, 1); if (class == NULL) return (ENXIO); clk = 0; } /* * Retrieve serial attributes. */ if (uart_fdt_get_shift(node, &shift) != 0) shift = uart_getregshift(class); + if (uart_fdt_get_io_width(node, &iowidth) != 0) + iowidth = uart_getregiowidth(class); + if (OF_getencprop(node, "current-speed", &br, sizeof(br)) <= 0) br = 0; err = OF_decode_addr(node, 0, bst, bsh, NULL); if (err != 0) return (err); *classp = class; *baud = br; *rclk = clk; *shiftp = shift; + *iowidthp = iowidth; return (0); } static int uart_fdt_probe(device_t dev) { struct uart_softc *sc; phandle_t node; - pcell_t clock, shift; + pcell_t clock, shift, iowidth; int err; sc = device_get_softc(dev); if (!ofw_bus_status_okay(dev)) return (ENXIO); sc->sc_class = (struct uart_class *)uart_fdt_find_device(dev); if (sc->sc_class == NULL) return (ENXIO); node = ofw_bus_get_node(dev); if ((err = uart_fdt_get_clock(node, &clock)) != 0) return (err); if (uart_fdt_get_shift(node, &shift) != 0) shift = uart_getregshift(sc->sc_class); + if (uart_fdt_get_io_width(node, &iowidth) != 0) + iowidth = uart_getregiowidth(sc->sc_class); - return (uart_bus_probe(dev, (int)shift, (int)clock, 0, 0)); + return (uart_bus_probe(dev, (int)shift, (int)iowidth, (int)clock, 0, 0)); } DRIVER_MODULE(uart, simplebus, uart_fdt_driver, uart_devclass, 0, 0); DRIVER_MODULE(uart, ofwbus, uart_fdt_driver, uart_devclass, 0, 0); Index: head/sys/dev/uart/uart_bus_isa.c =================================================================== --- head/sys/dev/uart/uart_bus_isa.c (revision 314361) +++ head/sys/dev/uart/uart_bus_isa.c (revision 314362) @@ -1,171 +1,171 @@ /*- * Copyright (c) 2008 TAKAHASHI Yoshihiro * Copyright (c) 2008 Marcel Moolenaar * Copyright (c) 2001 M. Warner Losh * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include static int uart_isa_probe(device_t dev); static device_method_t uart_isa_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_isa_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD(device_resume, uart_bus_resume), { 0, 0 } }; static driver_t uart_isa_driver = { uart_driver_name, uart_isa_methods, sizeof(struct uart_softc), }; static struct isa_pnp_id isa_ns8250_ids[] = { {0x0005d041, "Standard PC COM port"}, /* PNP0500 */ {0x0105d041, "16550A-compatible COM port"}, /* PNP0501 */ {0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */ {0x1005d041, "Generic IRDA-compatible device"}, /* PNP0510 */ {0x1105d041, "Generic IRDA-compatible device"}, /* PNP0511 */ /* Devices that do not have a compatid */ {0x12206804, NULL}, /* ACH2012 - 5634BTS 56K Video Ready Modem */ {0x7602a904, NULL}, /* AEI0276 - 56K v.90 Fax Modem (LKT) */ {0x00007905, NULL}, /* AKY0000 - 56K Plug&Play Modem */ {0x21107905, NULL}, /* AKY1021 - 56K Plug&Play Modem */ {0x01405407, NULL}, /* AZT4001 - AZT3000 PnP SOUND DEVICE, MODEM */ {0x56039008, NULL}, /* BDP0356 - Best Data 56x2 */ {0x56159008, NULL}, /* BDP1556 - B.D. Smart One 56SPS,Voice Modem*/ {0x36339008, NULL}, /* BDP3336 - Best Data Prods. 336F */ {0x0014490a, NULL}, /* BRI1400 - Boca 33.6 PnP */ {0x0015490a, NULL}, /* BRI1500 - Internal Fax Data */ {0x0034490a, NULL}, /* BRI3400 - Internal ACF Modem */ {0x0094490a, NULL}, /* BRI9400 - Boca K56Flex PnP */ {0x00b4490a, NULL}, /* BRIB400 - Boca 56k PnP */ {0x0010320d, NULL}, /* CIR1000 - Cirrus Logic V34 */ {0x0030320d, NULL}, /* CIR3000 - Cirrus Logic V43 */ {0x0100440e, NULL}, /* CRD0001 - Cardinal MVP288IV ? */ {0x01308c0e, NULL}, /* CTL3001 - Creative Labs Phoneblaster */ {0x36033610, NULL}, /* DAV0336 - DAVICOM 336PNP MODEM */ {0x01009416, NULL}, /* ETT0001 - E-Tech Bullet 33k6 PnP */ {0x0000aa1a, NULL}, /* FUJ0000 - FUJITSU Modem 33600 PNP/I2 */ {0x1200c31e, NULL}, /* GVC0012 - VF1128HV-R9 (win modem?) */ {0x0303c31e, NULL}, /* GVC0303 - MaxTech 33.6 PnP D/F/V */ {0x0505c31e, NULL}, /* GVC0505 - GVC 56k Faxmodem */ {0x0116c31e, NULL}, /* GVC1601 - Rockwell V.34 Plug & Play Modem */ {0x0050c31e, NULL}, /* GVC5000 - some GVC modem */ {0x3800f91e, NULL}, /* GWY0038 - Telepath with v.90 */ {0x9062f91e, NULL}, /* GWY6290 - Telepath with x2 Technology */ {0x8100e425, NULL}, /* IOD0081 - I-O DATA DEVICE,INC. IFML-560 */ {0x71004d24, NULL}, /* IBM0071 - IBM ThinkPad 240 IrDA controller*/ {0x21002534, NULL}, /* MAE0021 - Jetstream Int V.90 56k Voice Series 2*/ {0x0000f435, NULL}, /* MOT0000 - Motorola ModemSURFR 33.6 Intern */ {0x5015f435, NULL}, /* MOT1550 - Motorola ModemSURFR 56K Modem */ {0xf015f435, NULL}, /* MOT15F0 - Motorola VoiceSURFR 56K Modem */ {0x6045f435, NULL}, /* MOT4560 - Motorola ? */ {0x61e7a338, NULL}, /* NECE761 - 33.6Modem */ {0x0160633a, NULL}, /* NSC6001 - National Semi's IrDA Controller*/ {0x08804f3f, NULL}, /* OZO8008 - Zoom (33.6k Modem) */ {0x0f804f3f, NULL}, /* OZO800f - Zoom 2812 (56k Modem) */ {0x39804f3f, NULL}, /* OZO8039 - Zoom 56k flex */ {0x00914f3f, NULL}, /* OZO9100 - Zoom 2919 (K56 Faxmodem) */ {0x3024a341, NULL}, /* PMC2430 - Pace 56 Voice Internal Modem */ {0x1000eb49, NULL}, /* ROK0010 - Rockwell ? */ {0x1200b23d, NULL}, /* RSS0012 - OMRON ME5614ISA */ {0x5002734a, NULL}, /* RSS0250 - 5614Jx3(G) Internal Modem */ {0x6202734a, NULL}, /* RSS0262 - 5614Jx3[G] V90+K56Flex Modem */ {0x1010104d, NULL}, /* SHP1010 - Rockwell 33600bps Modem */ {0x10f0a34d, NULL}, /* SMCF010 - SMC IrCC*/ {0xc100ad4d, NULL}, /* SMM00C1 - Leopard 56k PnP */ {0x9012b04e, NULL}, /* SUP1290 - Supra ? */ {0x1013b04e, NULL}, /* SUP1310 - SupraExpress 336i PnP */ {0x8013b04e, NULL}, /* SUP1380 - SupraExpress 288i PnP Voice */ {0x8113b04e, NULL}, /* SUP1381 - SupraExpress 336i PnP Voice */ {0x5016b04e, NULL}, /* SUP1650 - Supra 336i Sp Intl */ {0x7016b04e, NULL}, /* SUP1670 - Supra 336i V+ Intl */ {0x7420b04e, NULL}, /* SUP2070 - Supra ? */ {0x8020b04e, NULL}, /* SUP2080 - Supra ? */ {0x8420b04e, NULL}, /* SUP2084 - SupraExpress 56i PnP */ {0x7121b04e, NULL}, /* SUP2171 - SupraExpress 56i Sp? */ {0x8024b04e, NULL}, /* SUP2480 - Supra ? */ {0x01007256, NULL}, /* USR0001 - U.S. Robotics Inc., Sportster W */ {0x02007256, NULL}, /* USR0002 - U.S. Robotics Inc. Sportster 33. */ {0x04007256, NULL}, /* USR0004 - USR Sportster 14.4k */ {0x06007256, NULL}, /* USR0006 - USR Sportster 33.6k */ {0x11007256, NULL}, /* USR0011 - USR ? */ {0x01017256, NULL}, /* USR0101 - USR ? */ {0x30207256, NULL}, /* USR2030 - U.S.Robotics Inc. Sportster 560 */ {0x50207256, NULL}, /* USR2050 - U.S.Robotics Inc. Sportster 33. */ {0x70207256, NULL}, /* USR2070 - U.S.Robotics Inc. Sportster 560 */ {0x30307256, NULL}, /* USR3030 - U.S. Robotics 56K FAX INT */ {0x31307256, NULL}, /* USR3031 - U.S. Robotics 56K FAX INT */ {0x50307256, NULL}, /* USR3050 - U.S. Robotics 56K FAX INT */ {0x70307256, NULL}, /* USR3070 - U.S. Robotics 56K Voice INT */ {0x90307256, NULL}, /* USR3090 - USR ? */ {0x70917256, NULL}, /* USR9170 - U.S. Robotics 56K FAX INT */ {0x90917256, NULL}, /* USR9190 - USR 56k Voice INT */ {0x04f0235c, NULL}, /* WACF004 - Wacom Tablet PC Screen*/ {0x0300695c, NULL}, /* WCI0003 - Fax/Voice/Modem/Speakphone/Asvd */ {0x01a0896a, NULL}, /* ZTIA001 - Zoom Internal V90 Faxmodem */ {0x61f7896a, NULL}, /* ZTIF761 - Zoom ComStar 33.6 */ {0} }; static int uart_isa_probe(device_t dev) { struct uart_softc *sc; device_t parent; parent = device_get_parent(dev); sc = device_get_softc(dev); /* Check PnP IDs */ if (ISA_PNP_PROBE(parent, dev, isa_ns8250_ids) == ENXIO) return (ENXIO); /* Probe PnP _and_ non-PnP ns8250 here. */ sc->sc_class = &uart_ns8250_class; - return (uart_bus_probe(dev, 0, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0, 0)); } DRIVER_MODULE(uart, isa, uart_isa_driver, uart_devclass, 0, 0); Index: head/sys/dev/uart/uart_bus_pccard.c =================================================================== --- head/sys/dev/uart/uart_bus_pccard.c (revision 314361) +++ head/sys/dev/uart/uart_bus_pccard.c (revision 314362) @@ -1,104 +1,104 @@ /*- * Copyright (c) 2001 M. Warner Losh. All rights reserved. * Copyright (c) 2003 Norikatsu Shigemura, Takenori Watanabe All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "pccarddevs.h" static int uart_pccard_probe(device_t dev); static int uart_pccard_attach(device_t dev); static device_method_t uart_pccard_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_pccard_probe), DEVMETHOD(device_attach, uart_pccard_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static uint32_t uart_pccard_function = PCCARD_FUNCTION_SERIAL; static driver_t uart_pccard_driver = { uart_driver_name, uart_pccard_methods, sizeof(struct uart_softc), }; static int uart_pccard_probe(device_t dev) { int error; uint32_t fcn; fcn = PCCARD_FUNCTION_UNSPEC; error = pccard_get_function(dev, &fcn); if (error != 0) return (error); /* * If a serial card, we are likely the right driver. However, * some serial cards are better serviced by other drivers, so * allow other drivers to claim it, if they want. */ if (fcn == uart_pccard_function) return (BUS_PROBE_GENERIC); return (ENXIO); } static int uart_pccard_attach(device_t dev) { struct uart_softc *sc; int error; sc = device_get_softc(dev); sc->sc_class = &uart_ns8250_class; - error = uart_bus_probe(dev, 0, 0, 0, 0); + error = uart_bus_probe(dev, 0, 0, 0, 0, 0); if (error > 0) return (error); return (uart_bus_attach(dev)); } DRIVER_MODULE(uart, pccard, uart_pccard_driver, uart_devclass, 0, 0); MODULE_PNP_INFO("U32:function_type;", pccard, uart, &uart_pccard_function, sizeof(uart_pccard_function), 1); Index: head/sys/dev/uart/uart_bus_pci.c =================================================================== --- head/sys/dev/uart/uart_bus_pci.c (revision 314361) +++ head/sys/dev/uart/uart_bus_pci.c (revision 314362) @@ -1,250 +1,250 @@ /*- * Copyright (c) 2006 Marcel Moolenaar * Copyright (c) 2001 M. Warner Losh * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #define DEFAULT_RCLK 1843200 static int uart_pci_probe(device_t dev); static int uart_pci_attach(device_t dev); static int uart_pci_detach(device_t dev); static device_method_t uart_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_pci_probe), DEVMETHOD(device_attach, uart_pci_attach), DEVMETHOD(device_detach, uart_pci_detach), DEVMETHOD(device_resume, uart_bus_resume), DEVMETHOD_END }; static driver_t uart_pci_driver = { uart_driver_name, uart_pci_methods, sizeof(struct uart_softc), }; struct pci_id { uint16_t vendor; uint16_t device; uint16_t subven; uint16_t subdev; const char *desc; int rid; int rclk; int regshft; }; static const struct pci_id pci_ns8250_ids[] = { { 0x1028, 0x0008, 0xffff, 0, "Dell Remote Access Card III", 0x14, 128 * DEFAULT_RCLK }, { 0x1028, 0x0012, 0xffff, 0, "Dell RAC 4 Daughter Card Virtual UART", 0x14, 128 * DEFAULT_RCLK }, { 0x1033, 0x0074, 0x1033, 0x8014, "NEC RCV56ACF 56k Voice Modem", 0x10 }, { 0x1033, 0x007d, 0x1033, 0x8012, "NEC RS232C", 0x10 }, { 0x103c, 0x1048, 0x103c, 0x1227, "HP Diva Serial [GSP] UART - Powerbar SP2", 0x10 }, { 0x103c, 0x1048, 0x103c, 0x1301, "HP Diva RMP3", 0x14 }, { 0x103c, 0x1290, 0xffff, 0, "HP Auxiliary Diva Serial Port", 0x18 }, { 0x103c, 0x3301, 0xffff, 0, "HP iLO serial port", 0x10 }, { 0x11c1, 0x0480, 0xffff, 0, "Agere Systems Venus Modem (V90, 56KFlex)", 0x14 }, { 0x115d, 0x0103, 0xffff, 0, "Xircom Cardbus Ethernet + 56k Modem", 0x10 }, { 0x1282, 0x6585, 0xffff, 0, "Davicom 56PDV PCI Modem", 0x10 }, { 0x12b9, 0x1008, 0xffff, 0, "3Com 56K FaxModem Model 5610", 0x10 }, { 0x131f, 0x1000, 0xffff, 0, "Siig CyberSerial (1-port) 16550", 0x18 }, { 0x131f, 0x1001, 0xffff, 0, "Siig CyberSerial (1-port) 16650", 0x18 }, { 0x131f, 0x1002, 0xffff, 0, "Siig CyberSerial (1-port) 16850", 0x18 }, { 0x131f, 0x2000, 0xffff, 0, "Siig CyberSerial (1-port) 16550", 0x10 }, { 0x131f, 0x2001, 0xffff, 0, "Siig CyberSerial (1-port) 16650", 0x10 }, { 0x131f, 0x2002, 0xffff, 0, "Siig CyberSerial (1-port) 16850", 0x10 }, { 0x135c, 0x0190, 0xffff, 0, "Quatech SSCLP-100", 0x18 }, { 0x135c, 0x01c0, 0xffff, 0, "Quatech SSCLP-200/300", 0x18 }, { 0x135e, 0x7101, 0xffff, 0, "Sealevel Systems Single Port RS-232/422/485/530", 0x18 }, { 0x1407, 0x0110, 0xffff, 0, "Lava Computer mfg DSerial-PCI Port A", 0x10 }, { 0x1407, 0x0111, 0xffff, 0, "Lava Computer mfg DSerial-PCI Port B", 0x10 }, { 0x1407, 0x0510, 0xffff, 0, "Lava SP Serial 550 PCI", 0x10 }, { 0x1409, 0x7168, 0x1409, 0x4025, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1409, 0x7168, 0x1409, 0x4027, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1409, 0x7168, 0x1409, 0x4028, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1409, 0x7168, 0x1409, 0x5025, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1409, 0x7168, 0x1409, 0x5027, "Timedia Technology Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x1415, 0x950b, 0xffff, 0, "Oxford Semiconductor OXCB950 Cardbus 16950 UART", 0x10, 16384000 }, { 0x1415, 0xc120, 0xffff, 0, "Oxford Semiconductor OXPCIe952 PCIe 16950 UART", 0x10 }, { 0x14e4, 0x160a, 0xffff, 0, "Broadcom TruManage UART", 0x10, 128 * DEFAULT_RCLK, 2}, { 0x14e4, 0x4344, 0xffff, 0, "Sony Ericsson GC89 PC Card", 0x10}, { 0x151f, 0x0000, 0xffff, 0, "TOPIC Semiconductor TP560 56k modem", 0x10 }, { 0x1fd4, 0x1999, 0x1fd4, 0x0001, "Sunix SER5xxxx Serial Port", 0x10, 8 * DEFAULT_RCLK }, { 0x8086, 0x0f0a, 0xffff, 0, "Intel ValleyView LPIO1 HSUART#1", 0x10, 24 * DEFAULT_RCLK, 2 }, { 0x8086, 0x0f0c, 0xffff, 0, "Intel ValleyView LPIO1 HSUART#2", 0x10, 24 * DEFAULT_RCLK, 2 }, { 0x8086, 0x1c3d, 0xffff, 0, "Intel AMT - KT Controller", 0x10 }, { 0x8086, 0x1d3d, 0xffff, 0, "Intel C600/X79 Series Chipset KT Controller", 0x10 }, { 0x8086, 0x1e3d, 0xffff, 0, "Intel Panther Point KT Controller", 0x10 }, { 0x8086, 0x228a, 0xffff, 0, "Intel Cherryview SIO HSUART#1", 0x10, 24 * DEFAULT_RCLK, 2 }, { 0x8086, 0x228c, 0xffff, 0, "Intel Cherryview SIO HSUART#2", 0x10, 24 * DEFAULT_RCLK, 2 }, { 0x8086, 0x2a07, 0xffff, 0, "Intel AMT - PM965/GM965 KT Controller", 0x10 }, { 0x8086, 0x2a47, 0xffff, 0, "Mobile 4 Series Chipset KT Controller", 0x10 }, { 0x8086, 0x2e17, 0xffff, 0, "4 Series Chipset Serial KT Controller", 0x10 }, { 0x8086, 0x3b67, 0xffff, 0, "5 Series/3400 Series Chipset KT Controller", 0x10 }, { 0x8086, 0x8811, 0xffff, 0, "Intel EG20T Serial Port 0", 0x10 }, { 0x8086, 0x8812, 0xffff, 0, "Intel EG20T Serial Port 1", 0x10 }, { 0x8086, 0x8813, 0xffff, 0, "Intel EG20T Serial Port 2", 0x10 }, { 0x8086, 0x8814, 0xffff, 0, "Intel EG20T Serial Port 3", 0x10 }, { 0x8086, 0x8c3d, 0xffff, 0, "Intel Lynx Point KT Controller", 0x10 }, { 0x8086, 0x8cbd, 0xffff, 0, "Intel Wildcat Point KT Controller", 0x10 }, { 0x8086, 0x9c3d, 0xffff, 0, "Intel Lynx Point-LP HECI KT", 0x10 }, { 0x9710, 0x9820, 0x1000, 1, "NetMos NM9820 Serial Port", 0x10 }, { 0x9710, 0x9835, 0x1000, 1, "NetMos NM9835 Serial Port", 0x10 }, { 0x9710, 0x9865, 0xa000, 0x1000, "NetMos NM9865 Serial Port", 0x10 }, { 0x9710, 0x9900, 0xa000, 0x1000, "MosChip MCS9900 PCIe to Peripheral Controller", 0x10 }, { 0x9710, 0x9901, 0xa000, 0x1000, "MosChip MCS9901 PCIe to Peripheral Controller", 0x10 }, { 0x9710, 0x9904, 0xa000, 0x1000, "MosChip MCS9904 PCIe to Peripheral Controller", 0x10 }, { 0x9710, 0x9922, 0xa000, 0x1000, "MosChip MCS9922 PCIe to Peripheral Controller", 0x10 }, { 0xdeaf, 0x9051, 0xffff, 0, "Middle Digital PC Weasel Serial Port", 0x10 }, { 0xffff, 0, 0xffff, 0, NULL, 0, 0} }; const static struct pci_id * uart_pci_match(device_t dev, const struct pci_id *id) { uint16_t device, subdev, subven, vendor; vendor = pci_get_vendor(dev); device = pci_get_device(dev); while (id->vendor != 0xffff && (id->vendor != vendor || id->device != device)) id++; if (id->vendor == 0xffff) return (NULL); if (id->subven == 0xffff) return (id); subven = pci_get_subvendor(dev); subdev = pci_get_subdevice(dev); while (id->vendor == vendor && id->device == device && (id->subven != subven || id->subdev != subdev)) id++; return ((id->vendor == vendor && id->device == device) ? id : NULL); } static int uart_pci_probe(device_t dev) { struct uart_softc *sc; const struct pci_id *id; int result; sc = device_get_softc(dev); id = uart_pci_match(dev, pci_ns8250_ids); if (id != NULL) { sc->sc_class = &uart_ns8250_class; goto match; } /* Add checks for non-ns8250 IDs here. */ return (ENXIO); match: - result = uart_bus_probe(dev, id->regshft, id->rclk, id->rid, 0); + result = uart_bus_probe(dev, id->regshft, 0, id->rclk, id->rid, 0); /* Bail out on error. */ if (result > 0) return (result); /* Set/override the device description. */ if (id->desc) device_set_desc(dev, id->desc); return (result); } static int uart_pci_attach(device_t dev) { struct uart_softc *sc; int count; sc = device_get_softc(dev); /* * Use MSI in preference to legacy IRQ if available. * Whilst some PCIe UARTs support >1 MSI vector, use only the first. */ if (pci_msi_count(dev) > 0) { count = 1; if (pci_alloc_msi(dev, &count) == 0) { sc->sc_irid = 1; device_printf(dev, "Using %d MSI message\n", count); } } return (uart_bus_attach(dev)); } static int uart_pci_detach(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); if (sc->sc_irid != 0) pci_release_msi(dev); return (uart_bus_detach(dev)); } DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, NULL, NULL); Index: head/sys/dev/uart/uart_bus_puc.c =================================================================== --- head/sys/dev/uart/uart_bus_puc.c (revision 314361) +++ head/sys/dev/uart/uart_bus_puc.c (revision 314362) @@ -1,87 +1,87 @@ /*- * Copyright (c) 2006 Marcel Moolenaar. All rights reserved. * Copyright (c) 2002 JF Hay. All rights reserved. * Copyright (c) 2001 M. Warner Losh. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include static int uart_puc_probe(device_t dev); static device_method_t uart_puc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_puc_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), /* Serdev interface */ DEVMETHOD(serdev_ihand, uart_bus_ihand), DEVMETHOD(serdev_ipend, uart_bus_ipend), { 0, 0 } }; static driver_t uart_puc_driver = { uart_driver_name, uart_puc_methods, sizeof(struct uart_softc), }; static int uart_puc_probe(device_t dev) { device_t parent; struct uart_softc *sc; uintptr_t rclk, type; parent = device_get_parent(dev); sc = device_get_softc(dev); if (BUS_READ_IVAR(parent, dev, PUC_IVAR_TYPE, &type)) return (ENXIO); if (type != PUC_TYPE_SERIAL) return (ENXIO); sc->sc_class = &uart_ns8250_class; if (BUS_READ_IVAR(parent, dev, PUC_IVAR_CLOCK, &rclk)) rclk = 0; - return (uart_bus_probe(dev, 0, rclk, 0, 0)); + return (uart_bus_probe(dev, 0, 0, rclk, 0, 0)); } DRIVER_MODULE(uart, puc, uart_puc_driver, uart_devclass, 0, 0); Index: head/sys/dev/uart/uart_bus_scc.c =================================================================== --- head/sys/dev/uart/uart_bus_scc.c (revision 314361) +++ head/sys/dev/uart/uart_bus_scc.c (revision 314362) @@ -1,118 +1,118 @@ /*- * Copyright (c) 2004-2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include static int uart_scc_attach(device_t dev); static int uart_scc_probe(device_t dev); static device_method_t uart_scc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_scc_probe), DEVMETHOD(device_attach, uart_scc_attach), DEVMETHOD(device_detach, uart_bus_detach), /* Serdev interface */ DEVMETHOD(serdev_ihand, uart_bus_ihand), DEVMETHOD(serdev_sysdev, uart_bus_sysdev), { 0, 0 } }; static driver_t uart_scc_driver = { uart_driver_name, uart_scc_methods, sizeof(struct uart_softc), }; static int uart_scc_attach(device_t dev) { device_t parent; struct uart_softc *sc; uintptr_t mtx; parent = device_get_parent(dev); sc = device_get_softc(dev); if (BUS_READ_IVAR(parent, dev, SCC_IVAR_HWMTX, &mtx)) return (ENXIO); sc->sc_hwmtx = (struct mtx *)(void *)mtx; return (uart_bus_attach(dev)); } static int uart_scc_probe(device_t dev) { device_t parent; struct uart_softc *sc; uintptr_t ch, cl, md, rs; parent = device_get_parent(dev); sc = device_get_softc(dev); if (BUS_READ_IVAR(parent, dev, SCC_IVAR_MODE, &md) || BUS_READ_IVAR(parent, dev, SCC_IVAR_CLASS, &cl)) return (ENXIO); if (md != SCC_MODE_ASYNC) return (ENXIO); switch (cl) { case SCC_CLASS_QUICC: sc->sc_class = &uart_quicc_class; break; case SCC_CLASS_SAB82532: sc->sc_class = &uart_sab82532_class; break; case SCC_CLASS_Z8530: sc->sc_class = &uart_z8530_class; break; default: return (ENXIO); } if (BUS_READ_IVAR(parent, dev, SCC_IVAR_CHANNEL, &ch) || BUS_READ_IVAR(parent, dev, SCC_IVAR_CLOCK, &cl) || BUS_READ_IVAR(parent, dev, SCC_IVAR_REGSHFT, &rs)) return (ENXIO); - return (uart_bus_probe(dev, rs, cl, 0, ch)); + return (uart_bus_probe(dev, rs, 0, cl, 0, ch)); } DRIVER_MODULE(uart, scc, uart_scc_driver, uart_devclass, 0, 0); Index: head/sys/dev/uart/uart_core.c =================================================================== --- head/sys/dev/uart/uart_core.c (revision 314361) +++ head/sys/dev/uart/uart_core.c (revision 314362) @@ -1,814 +1,821 @@ /*- * Copyright (c) 2003 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" devclass_t uart_devclass; const char uart_driver_name[] = "uart"; SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs = SLIST_HEAD_INITIALIZER(uart_sysdevs); static MALLOC_DEFINE(M_UART, "UART", "UART driver"); #ifndef UART_POLL_FREQ #define UART_POLL_FREQ 50 #endif static int uart_poll_freq = UART_POLL_FREQ; SYSCTL_INT(_debug, OID_AUTO, uart_poll_freq, CTLFLAG_RDTUN, &uart_poll_freq, 0, "UART poll frequency"); static int uart_force_poll; SYSCTL_INT(_debug, OID_AUTO, uart_force_poll, CTLFLAG_RDTUN, &uart_force_poll, 0, "Force UART polling"); static inline int uart_pps_mode_valid(int pps_mode) { int opt; switch(pps_mode & UART_PPS_SIGNAL_MASK) { case UART_PPS_DISABLED: case UART_PPS_CTS: case UART_PPS_DCD: break; default: return (false); } opt = pps_mode & UART_PPS_OPTION_MASK; if ((opt & ~(UART_PPS_INVERT_PULSE | UART_PPS_NARROW_PULSE)) != 0) return (false); return (true); } static void uart_pps_print_mode(struct uart_softc *sc) { device_printf(sc->sc_dev, "PPS capture mode: "); switch(sc->sc_pps_mode & UART_PPS_SIGNAL_MASK) { case UART_PPS_DISABLED: printf("disabled"); break; case UART_PPS_CTS: printf("CTS"); break; case UART_PPS_DCD: printf("DCD"); break; default: printf("invalid"); break; } if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE) printf("-Inverted"); if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) printf("-NarrowPulse"); printf("\n"); } static int uart_pps_mode_sysctl(SYSCTL_HANDLER_ARGS) { struct uart_softc *sc; int err, tmp; sc = arg1; tmp = sc->sc_pps_mode; err = sysctl_handle_int(oidp, &tmp, 0, req); if (err != 0 || req->newptr == NULL) return (err); if (!uart_pps_mode_valid(tmp)) return (EINVAL); sc->sc_pps_mode = tmp; return(0); } static void uart_pps_process(struct uart_softc *sc, int ser_sig) { sbintime_t now; int is_assert, pps_sig; /* Which signal is configured as PPS? Early out if none. */ switch(sc->sc_pps_mode & UART_PPS_SIGNAL_MASK) { case UART_PPS_CTS: pps_sig = SER_CTS; break; case UART_PPS_DCD: pps_sig = SER_DCD; break; default: return; } /* Early out if there is no change in the signal configured as PPS. */ if ((ser_sig & SER_DELTA(pps_sig)) == 0) return; /* * In narrow-pulse mode we need to synthesize both capture and clear * events from a single "delta occurred" indication from the uart * hardware because the pulse width is too narrow to reliably detect * both edges. However, when the pulse width is close to our interrupt * processing latency we might intermittantly catch both edges. To * guard against generating spurious events when that happens, we use a * separate timer to ensure at least half a second elapses before we * generate another event. */ pps_capture(&sc->sc_pps); if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) { now = getsbinuptime(); if (now > sc->sc_pps_captime + 500 * SBT_1MS) { sc->sc_pps_captime = now; pps_event(&sc->sc_pps, PPS_CAPTUREASSERT); pps_event(&sc->sc_pps, PPS_CAPTURECLEAR); } } else { is_assert = ser_sig & pps_sig; if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE) is_assert = !is_assert; pps_event(&sc->sc_pps, is_assert ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); } } static void uart_pps_init(struct uart_softc *sc) { struct sysctl_ctx_list *ctx; struct sysctl_oid *tree; ctx = device_get_sysctl_ctx(sc->sc_dev); tree = device_get_sysctl_tree(sc->sc_dev); /* * The historical default for pps capture mode is either DCD or CTS, * depending on the UART_PPS_ON_CTS kernel option. Start with that, * then try to fetch the tunable that overrides the mode for all uart * devices, then try to fetch the sysctl-tunable that overrides the mode * for one specific device. */ #ifdef UART_PPS_ON_CTS sc->sc_pps_mode = UART_PPS_CTS; #else sc->sc_pps_mode = UART_PPS_DCD; #endif TUNABLE_INT_FETCH("hw.uart.pps_mode", &sc->sc_pps_mode); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "pps_mode", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0, uart_pps_mode_sysctl, "I", "pulse mode: 0/1/2=disabled/CTS/DCD; " "add 0x10 to invert, 0x20 for narrow pulse"); if (!uart_pps_mode_valid(sc->sc_pps_mode)) { device_printf(sc->sc_dev, "Invalid pps_mode 0x%02x configured; disabling PPS capture\n", sc->sc_pps_mode); sc->sc_pps_mode = UART_PPS_DISABLED; } else if (bootverbose) { uart_pps_print_mode(sc); } sc->sc_pps.ppscap = PPS_CAPTUREBOTH; sc->sc_pps.driver_mtx = uart_tty_getlock(sc); sc->sc_pps.driver_abi = PPS_ABI_VERSION; pps_init_abi(&sc->sc_pps); } void uart_add_sysdev(struct uart_devinfo *di) { SLIST_INSERT_HEAD(&uart_sysdevs, di, next); } const char * uart_getname(struct uart_class *uc) { return ((uc != NULL) ? uc->name : NULL); } struct uart_ops * uart_getops(struct uart_class *uc) { return ((uc != NULL) ? uc->uc_ops : NULL); } int uart_getrange(struct uart_class *uc) { return ((uc != NULL) ? uc->uc_range : 0); } u_int uart_getregshift(struct uart_class *uc) { return ((uc != NULL) ? uc->uc_rshift : 0); } +u_int +uart_getregiowidth(struct uart_class *uc) +{ + return ((uc != NULL) ? uc->uc_riowidth : 0); +} + /* * Schedule a soft interrupt. We do this on the 0 to !0 transition * of the TTY pending interrupt status. */ void uart_sched_softih(struct uart_softc *sc, uint32_t ipend) { uint32_t new, old; do { old = sc->sc_ttypend; new = old | ipend; } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new)); if ((old & SER_INT_MASK) == 0) swi_sched(sc->sc_softih, 0); } /* * A break condition has been detected. We treat the break condition as * a special case that should not happen during normal operation. When * the break condition is to be passed to higher levels in the form of * a NUL character, we really want the break to be in the right place in * the input stream. The overhead to achieve that is not in relation to * the exceptional nature of the break condition, so we permit ourselves * to be sloppy. */ static __inline int uart_intr_break(void *arg) { struct uart_softc *sc = arg; #if defined(KDB) if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { if (kdb_break()) return (0); } #endif if (sc->sc_opened) uart_sched_softih(sc, SER_INT_BREAK); return (0); } /* * Handle a receiver overrun situation. We lost at least 1 byte in the * input stream and it's our job to contain the situation. We grab as * much of the data we can, but otherwise flush the receiver FIFO to * create some breathing room. The net effect is that we avoid the * overrun condition to happen for the next X characters, where X is * related to the FIFO size at the cost of losing data right away. * So, instead of having multiple overrun interrupts in close proximity * to each other and possibly pessimizing UART interrupt latency for * other UARTs in a multiport configuration, we create a longer segment * of missing characters by freeing up the FIFO. * Each overrun condition is marked in the input buffer by a token. The * token represents the loss of at least one, but possible more bytes in * the input stream. */ static __inline int uart_intr_overrun(void *arg) { struct uart_softc *sc = arg; if (sc->sc_opened) { UART_RECEIVE(sc); if (uart_rx_put(sc, UART_STAT_OVERRUN)) sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; uart_sched_softih(sc, SER_INT_RXREADY); } UART_FLUSH(sc, UART_FLUSH_RECEIVER); return (0); } /* * Received data ready. */ static __inline int uart_intr_rxready(void *arg) { struct uart_softc *sc = arg; int rxp; rxp = sc->sc_rxput; UART_RECEIVE(sc); #if defined(KDB) if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) { while (rxp != sc->sc_rxput) { kdb_alt_break(sc->sc_rxbuf[rxp++], &sc->sc_altbrk); if (rxp == sc->sc_rxbufsz) rxp = 0; } } #endif if (sc->sc_opened) uart_sched_softih(sc, SER_INT_RXREADY); else sc->sc_rxput = sc->sc_rxget; /* Ignore received data. */ return (1); } /* * Line or modem status change (OOB signalling). * We pass the signals to the software interrupt handler for further * processing. Note that we merge the delta bits, but set the state * bits. This is to avoid losing state transitions due to having more * than 1 hardware interrupt between software interrupts. */ static __inline int uart_intr_sigchg(void *arg) { struct uart_softc *sc = arg; int new, old, sig; sig = UART_GETSIG(sc); /* * Time pulse counting support, invoked whenever the PPS parameters are * currently set to capture either edge of the signal. */ if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) { uart_pps_process(sc, sig); } /* * Keep track of signal changes, even when the device is not * opened. This allows us to inform upper layers about a * possible loss of DCD and thus the existence of a (possibly) * different connection when we have DCD back, during the time * that the device was closed. */ do { old = sc->sc_ttypend; new = old & ~SER_MASK_STATE; new |= sig & SER_INT_SIGMASK; } while (!atomic_cmpset_32(&sc->sc_ttypend, old, new)); if (sc->sc_opened) uart_sched_softih(sc, SER_INT_SIGCHG); return (1); } /* * The transmitter can accept more data. */ static __inline int uart_intr_txidle(void *arg) { struct uart_softc *sc = arg; if (sc->sc_txbusy) { sc->sc_txbusy = 0; uart_sched_softih(sc, SER_INT_TXIDLE); } return (0); } static int uart_intr(void *arg) { struct uart_softc *sc = arg; int cnt, ipend, testintr; if (sc->sc_leaving) return (FILTER_STRAY); cnt = 0; testintr = sc->sc_testintr; while ((!testintr || cnt < 20) && (ipend = UART_IPEND(sc)) != 0) { cnt++; if (ipend & SER_INT_OVERRUN) uart_intr_overrun(sc); if (ipend & SER_INT_BREAK) uart_intr_break(sc); if (ipend & SER_INT_RXREADY) uart_intr_rxready(sc); if (ipend & SER_INT_SIGCHG) uart_intr_sigchg(sc); if (ipend & SER_INT_TXIDLE) uart_intr_txidle(sc); } if (sc->sc_polled) { callout_reset(&sc->sc_timer, hz / uart_poll_freq, (timeout_t *)uart_intr, sc); } return ((cnt == 0) ? FILTER_STRAY : ((testintr && cnt == 20) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED)); } serdev_intr_t * uart_bus_ihand(device_t dev, int ipend) { switch (ipend) { case SER_INT_BREAK: return (uart_intr_break); case SER_INT_OVERRUN: return (uart_intr_overrun); case SER_INT_RXREADY: return (uart_intr_rxready); case SER_INT_SIGCHG: return (uart_intr_sigchg); case SER_INT_TXIDLE: return (uart_intr_txidle); } return (NULL); } int uart_bus_ipend(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); return (UART_IPEND(sc)); } int uart_bus_sysdev(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); return ((sc->sc_sysdev != NULL) ? 1 : 0); } int -uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan) +uart_bus_probe(device_t dev, int regshft, int regiowidth, int rclk, int rid, int chan) { struct uart_softc *sc; struct uart_devinfo *sysdev; int error; sc = device_get_softc(dev); /* * All uart_class references are weak. Check that the needed * class has been compiled-in. Fail if not. */ if (sc->sc_class == NULL) return (ENXIO); /* * Initialize the instance. Note that the instance (=softc) does * not necessarily match the hardware specific softc. We can't do * anything about it now, because we may not attach to the device. * Hardware drivers cannot use any of the class specific fields * while probing. */ kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class); sc->sc_dev = dev; if (device_get_desc(dev) == NULL) device_set_desc(dev, uart_getname(sc->sc_class)); /* * Allocate the register resource. We assume that all UARTs have * a single register window in either I/O port space or memory * mapped I/O space. Any UART that needs multiple windows will * consequently not be supported by this driver as-is. We try I/O * port space first because that's the common case. */ sc->sc_rrid = rid; sc->sc_rtype = SYS_RES_IOPORT; sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype, &sc->sc_rrid, RF_ACTIVE); if (sc->sc_rres == NULL) { sc->sc_rrid = rid; sc->sc_rtype = SYS_RES_MEMORY; sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype, &sc->sc_rrid, RF_ACTIVE); if (sc->sc_rres == NULL) return (ENXIO); } /* * Fill in the bus access structure and compare this device with * a possible console device and/or a debug port. We set the flags * in the softc so that the hardware dependent probe can adjust * accordingly. In general, you don't want to permanently disrupt * console I/O. */ sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); sc->sc_bas.chan = chan; sc->sc_bas.regshft = regshft; + sc->sc_bas.regiowidth = regiowidth; sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk; SLIST_FOREACH(sysdev, &uart_sysdevs, next) { if (chan == sysdev->bas.chan && uart_cpu_eqres(&sc->sc_bas, &sysdev->bas)) { /* XXX check if ops matches class. */ sc->sc_sysdev = sysdev; sysdev->bas.rclk = sc->sc_bas.rclk; } } error = UART_PROBE(sc); bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); return ((error) ? error : BUS_PROBE_DEFAULT); } int uart_bus_attach(device_t dev) { struct uart_softc *sc, *sc0; const char *sep; int error, filt; /* * The sc_class field defines the type of UART we're going to work * with and thus the size of the softc. Replace the generic softc * with one that matches the UART now that we're certain we handle * the device. */ sc0 = device_get_softc(dev); if (sc0->sc_class->size > device_get_driver(dev)->size) { sc = malloc(sc0->sc_class->size, M_UART, M_WAITOK|M_ZERO); bcopy(sc0, sc, sizeof(*sc)); device_set_softc(dev, sc); } else sc = sc0; /* * Now that we know the softc for this device, connect the back * pointer from the sysdev for this device, if any */ if (sc->sc_sysdev != NULL) sc->sc_sysdev->sc = sc; /* * Protect ourselves against interrupts while we're not completely * finished attaching and initializing. We don't expect interrupts * until after UART_ATTACH(), though. */ sc->sc_leaving = 1; mtx_init(&sc->sc_hwmtx_s, "uart_hwmtx", NULL, MTX_SPIN); if (sc->sc_hwmtx == NULL) sc->sc_hwmtx = &sc->sc_hwmtx_s; /* * Re-allocate. We expect that the softc contains the information * collected by uart_bus_probe() intact. */ sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype, &sc->sc_rrid, RF_ACTIVE); if (sc->sc_rres == NULL) { mtx_destroy(&sc->sc_hwmtx_s); return (ENXIO); } sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); /* * Ensure there is room for at least three full FIFOs of data in the * receive buffer (handles the case of low-level drivers with huge * FIFOs), and also ensure that there is no less than the historical * size of 384 bytes (handles the typical small-FIFO case). */ sc->sc_rxbufsz = MAX(384, sc->sc_rxfifosz * 3); sc->sc_rxbuf = malloc(sc->sc_rxbufsz * sizeof(*sc->sc_rxbuf), M_UART, M_WAITOK); sc->sc_txbuf = malloc(sc->sc_txfifosz * sizeof(*sc->sc_txbuf), M_UART, M_WAITOK); error = UART_ATTACH(sc); if (error) goto fail; if (sc->sc_hwiflow || sc->sc_hwoflow) { sep = ""; device_print_prettyname(dev); if (sc->sc_hwiflow) { printf("%sRTS iflow", sep); sep = ", "; } if (sc->sc_hwoflow) { printf("%sCTS oflow", sep); sep = ", "; } printf("\n"); } if (sc->sc_sysdev != NULL) { if (sc->sc_sysdev->baudrate == 0) { if (UART_IOCTL(sc, UART_IOCTL_BAUD, (intptr_t)&sc->sc_sysdev->baudrate) != 0) sc->sc_sysdev->baudrate = -1; } switch (sc->sc_sysdev->type) { case UART_DEV_CONSOLE: device_printf(dev, "console"); break; case UART_DEV_DBGPORT: device_printf(dev, "debug port"); break; case UART_DEV_KEYBOARD: device_printf(dev, "keyboard"); break; default: device_printf(dev, "unknown system device"); break; } printf(" (%d,%c,%d,%d)\n", sc->sc_sysdev->baudrate, "noems"[sc->sc_sysdev->parity], sc->sc_sysdev->databits, sc->sc_sysdev->stopbits); } sc->sc_leaving = 0; sc->sc_testintr = 1; filt = uart_intr(sc); sc->sc_testintr = 0; /* * Don't use interrupts if we couldn't clear any pending interrupt * conditions. We may have broken H/W and polling is probably the * safest thing to do. */ if (filt != FILTER_SCHEDULE_THREAD && !uart_force_poll) { sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); } if (sc->sc_ires != NULL) { error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY, uart_intr, NULL, sc, &sc->sc_icookie); sc->sc_fastintr = (error == 0) ? 1 : 0; if (!sc->sc_fastintr) error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE, NULL, (driver_intr_t *)uart_intr, sc, &sc->sc_icookie); if (error) { device_printf(dev, "could not activate interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); sc->sc_ires = NULL; } } if (sc->sc_ires == NULL) { /* No interrupt resource. Force polled mode. */ sc->sc_polled = 1; callout_init(&sc->sc_timer, 1); callout_reset(&sc->sc_timer, hz / uart_poll_freq, (timeout_t *)uart_intr, sc); } if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) { sep = ""; device_print_prettyname(dev); if (sc->sc_fastintr) { printf("%sfast interrupt", sep); sep = ", "; } if (sc->sc_polled) { printf("%spolled mode (%dHz)", sep, uart_poll_freq); sep = ", "; } printf("\n"); } if (sc->sc_sysdev != NULL && sc->sc_sysdev->attach != NULL) { if ((error = sc->sc_sysdev->attach(sc)) != 0) goto fail; } else { if ((error = uart_tty_attach(sc)) != 0) goto fail; uart_pps_init(sc); } if (sc->sc_sysdev != NULL) sc->sc_sysdev->hwmtx = sc->sc_hwmtx; return (0); fail: free(sc->sc_txbuf, M_UART); free(sc->sc_rxbuf, M_UART); if (sc->sc_ires != NULL) { bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); } bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); mtx_destroy(&sc->sc_hwmtx_s); return (error); } int uart_bus_detach(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); sc->sc_leaving = 1; if (sc->sc_sysdev != NULL) sc->sc_sysdev->hwmtx = NULL; UART_DETACH(sc); if (sc->sc_sysdev != NULL && sc->sc_sysdev->detach != NULL) (*sc->sc_sysdev->detach)(sc); else uart_tty_detach(sc); free(sc->sc_txbuf, M_UART); free(sc->sc_rxbuf, M_UART); if (sc->sc_ires != NULL) { bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); } bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres); mtx_destroy(&sc->sc_hwmtx_s); if (sc->sc_class->size > device_get_driver(dev)->size) { device_set_softc(dev, NULL); free(sc, M_UART); } return (0); } int uart_bus_resume(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); return (UART_ATTACH(sc)); } void uart_grab(struct uart_devinfo *di) { if (di->sc) UART_GRAB(di->sc); } void uart_ungrab(struct uart_devinfo *di) { if (di->sc) UART_UNGRAB(di->sc); } Index: head/sys/dev/uart/uart_cpu.h =================================================================== --- head/sys/dev/uart/uart_cpu.h (revision 314361) +++ head/sys/dev/uart/uart_cpu.h (revision 314362) @@ -1,176 +1,177 @@ /*- * Copyright (c) 2003, 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DEV_UART_CPU_H_ #define _DEV_UART_CPU_H_ #include #include #include struct uart_softc; /* * Low-level operations for use by console and/or debug port support. */ struct uart_ops { int (*probe)(struct uart_bas *); void (*init)(struct uart_bas *, int, int, int, int); void (*term)(struct uart_bas *); void (*putc)(struct uart_bas *, int); int (*rxready)(struct uart_bas *); int (*getc)(struct uart_bas *, struct mtx *); }; extern bus_space_tag_t uart_bus_space_io; extern bus_space_tag_t uart_bus_space_mem; /* * Console and debug port device info. */ struct uart_devinfo { SLIST_ENTRY(uart_devinfo) next; struct uart_ops *ops; struct uart_bas bas; int baudrate; int databits; int stopbits; int parity; int type; #define UART_DEV_CONSOLE 0 #define UART_DEV_DBGPORT 1 #define UART_DEV_KEYBOARD 2 int (*attach)(struct uart_softc*); int (*detach)(struct uart_softc*); void *cookie; /* Type dependent use. */ struct mtx *hwmtx; struct uart_softc *sc; /* valid only from start of attach */ }; int uart_cpu_eqres(struct uart_bas *, struct uart_bas *); int uart_cpu_getdev(int, struct uart_devinfo *); int uart_getenv(int, struct uart_devinfo *, struct uart_class *); const char *uart_getname(struct uart_class *); struct uart_ops *uart_getops(struct uart_class *); int uart_getrange(struct uart_class *); u_int uart_getregshift(struct uart_class *); +u_int uart_getregiowidth(struct uart_class *); void uart_add_sysdev(struct uart_devinfo *); /* * Operations for low-level access to the UART. Primarily for use * by console and debug port logic. */ static __inline void uart_lock(struct mtx *hwmtx) { if (!kdb_active && hwmtx != NULL) mtx_lock_spin(hwmtx); } static __inline void uart_unlock(struct mtx *hwmtx) { if (!kdb_active && hwmtx != NULL) mtx_unlock_spin(hwmtx); } static __inline int uart_probe(struct uart_devinfo *di) { int res; uart_lock(di->hwmtx); res = di->ops->probe(&di->bas); uart_unlock(di->hwmtx); return (res); } static __inline void uart_init(struct uart_devinfo *di) { uart_lock(di->hwmtx); di->ops->init(&di->bas, di->baudrate, di->databits, di->stopbits, di->parity); uart_unlock(di->hwmtx); } static __inline void uart_term(struct uart_devinfo *di) { uart_lock(di->hwmtx); di->ops->term(&di->bas); uart_unlock(di->hwmtx); } static __inline void uart_putc(struct uart_devinfo *di, int c) { uart_lock(di->hwmtx); di->ops->putc(&di->bas, c); uart_unlock(di->hwmtx); } static __inline int uart_rxready(struct uart_devinfo *di) { int res; uart_lock(di->hwmtx); res = di->ops->rxready(&di->bas); uart_unlock(di->hwmtx); return (res); } static __inline int uart_poll(struct uart_devinfo *di) { int res; uart_lock(di->hwmtx); if (di->ops->rxready(&di->bas)) res = di->ops->getc(&di->bas, NULL); else res = -1; uart_unlock(di->hwmtx); return (res); } static __inline int uart_getc(struct uart_devinfo *di) { return (di->ops->getc(&di->bas, di->hwmtx)); } void uart_grab(struct uart_devinfo *di); void uart_ungrab(struct uart_devinfo *di); #endif /* _DEV_UART_CPU_H_ */ Index: head/sys/dev/uart/uart_cpu_arm64.c =================================================================== --- head/sys/dev/uart/uart_cpu_arm64.c (revision 314361) +++ head/sys/dev/uart/uart_cpu_arm64.c (revision 314362) @@ -1,200 +1,201 @@ /*- * Copyright (c) 2016 The FreeBSD Foundation * All rights reserved. * * This software was developed by Andrew Turner under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "opt_acpi.h" #include "opt_platform.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #ifdef DEV_ACPI #include #include #include #include #endif #ifdef FDT #include #include #include #include #endif /* * UART console routines. */ bus_space_tag_t uart_bus_space_io; bus_space_tag_t uart_bus_space_mem; int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { if (pmap_kextract(b1->bsh) == 0) return (0); if (pmap_kextract(b2->bsh) == 0) return (0); return ((pmap_kextract(b1->bsh) == pmap_kextract(b2->bsh)) ? 1 : 0); } #ifdef DEV_ACPI static struct acpi_uart_compat_data * uart_cpu_acpi_scan(uint8_t interface_type) { struct acpi_uart_compat_data **cd; SET_FOREACH(cd, uart_acpi_class_and_device_set) { if ((*cd)->port_subtype == interface_type) return (*cd); } SET_FOREACH(cd, uart_acpi_class_set) { if ((*cd)->port_subtype == interface_type) return (*cd); } return (NULL); } static int uart_cpu_acpi_probe(struct uart_class **classp, bus_space_tag_t *bst, bus_space_handle_t *bsh, int *baud, u_int *rclk, u_int *shiftp) { struct acpi_uart_compat_data *cd; ACPI_TABLE_SPCR *spcr; vm_paddr_t spcr_physaddr; int err; err = ENXIO; spcr_physaddr = acpi_find_table(ACPI_SIG_SPCR); if (spcr_physaddr == 0) return (ENXIO); spcr = acpi_map_table(spcr_physaddr, ACPI_SIG_SPCR); cd = uart_cpu_acpi_scan(spcr->InterfaceType); if (cd == NULL) goto out; switch(spcr->BaudRate) { case 3: *baud = 9600; break; case 4: *baud = 19200; break; case 6: *baud = 57600; break; case 7: *baud = 115200; break; default: goto out; } err = acpi_map_addr(&spcr->SerialPort, bst, bsh, PAGE_SIZE); if (err != 0) goto out; *classp = cd->clas; *rclk = 0; *shiftp = 2; out: acpi_unmap_table(spcr); return (err); } #endif int uart_cpu_getdev(int devtype, struct uart_devinfo *di) { struct uart_class *class; bus_space_handle_t bsh; bus_space_tag_t bst; - u_int rclk, shift; + u_int rclk, shift, iowidth; int br, err; /* Allow overriding the FDT using the environment. */ class = &uart_ns8250_class; err = uart_getenv(devtype, di, class); if (err == 0) return (0); if (devtype != UART_DEV_CONSOLE) return (ENXIO); err = ENXIO; #ifdef DEV_ACPI err = uart_cpu_acpi_probe(&class, &bst, &bsh, &br, &rclk, &shift); #endif #ifdef FDT if (err != 0) { err = uart_cpu_fdt_probe(&class, &bst, &bsh, &br, &rclk, - &shift); + &shift, &iowidth); } #endif if (err != 0) return (err); /* * Finalize configuration. */ di->bas.chan = 0; di->bas.regshft = shift; + di->bas.regiowidth = iowidth; di->baudrate = br; di->bas.rclk = rclk; di->ops = uart_getops(class); di->databits = 8; di->stopbits = 1; di->parity = UART_PARITY_NONE; di->bas.bst = bst; di->bas.bsh = bsh; uart_bus_space_mem = di->bas.bst; uart_bus_space_io = NULL; return (0); } Index: head/sys/dev/uart/uart_cpu_fdt.c =================================================================== --- head/sys/dev/uart/uart_cpu_fdt.c (revision 314361) +++ head/sys/dev/uart/uart_cpu_fdt.c (revision 314362) @@ -1,113 +1,114 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * All rights reserved. * * This software was developed by Semihalf under sponsorship from * the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_platform.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * UART console routines. */ bus_space_tag_t uart_bus_space_io; bus_space_tag_t uart_bus_space_mem; int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { if (b1->bst != b2->bst) return (0); if (pmap_kextract(b1->bsh) == 0) return (0); if (pmap_kextract(b2->bsh) == 0) return (0); return ((pmap_kextract(b1->bsh) == pmap_kextract(b2->bsh)) ? 1 : 0); } int uart_cpu_getdev(int devtype, struct uart_devinfo *di) { struct uart_class *class; bus_space_tag_t bst; bus_space_handle_t bsh; - u_int shift, rclk; + u_int shift, iowidth, rclk; int br, err; /* Allow overriding the FDT using the environment. */ class = &uart_ns8250_class; err = uart_getenv(devtype, di, class); if (!err) return (0); if (devtype != UART_DEV_CONSOLE) return (ENXIO); - err = uart_cpu_fdt_probe(&class, &bst, &bsh, &br, &rclk, &shift); + err = uart_cpu_fdt_probe(&class, &bst, &bsh, &br, &rclk, &shift, &iowidth); if (err != 0) return (err); /* * Finalize configuration. */ di->bas.chan = 0; di->bas.regshft = shift; + di->bas.regiowidth = iowidth; di->baudrate = br; di->bas.rclk = rclk; di->ops = uart_getops(class); di->databits = 8; di->stopbits = 1; di->parity = UART_PARITY_NONE; di->bas.bst = bst; di->bas.bsh = bsh; uart_bus_space_mem = di->bas.bst; uart_bus_space_io = NULL; return (err); } Index: head/sys/dev/uart/uart_cpu_fdt.h =================================================================== --- head/sys/dev/uart/uart_cpu_fdt.h (revision 314361) +++ head/sys/dev/uart/uart_cpu_fdt.h (revision 314362) @@ -1,58 +1,59 @@ /*- * Copyright 2015 Michal Meloun * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DEV_UART_CPU_FDT_H_ #define _DEV_UART_CPU_FDT_H_ #include #include /* * If your UART driver implements only uart_class and uses uart_cpu_fdt.c * for device instantiation, then use UART_FDT_CLASS_AND_DEVICE for its * declaration */ SET_DECLARE(uart_fdt_class_and_device_set, struct ofw_compat_data ); #define UART_FDT_CLASS_AND_DEVICE(data) \ DATA_SET(uart_fdt_class_and_device_set, data) /* * If your UART driver implements uart_class and custom device layer, * then use UART_FDT_CLASS for its declaration */ SET_DECLARE(uart_fdt_class_set, struct ofw_compat_data ); #define UART_FDT_CLASS(data) \ DATA_SET(uart_fdt_class_set, data) int uart_cpu_fdt_probe(struct uart_class **, bus_space_tag_t *, - bus_space_handle_t *, int *, u_int *, u_int *); + bus_space_handle_t *, int *, u_int *, u_int *, u_int *); int uart_fdt_get_clock(phandle_t node, pcell_t *cell); int uart_fdt_get_shift(phandle_t node, pcell_t *cell); +int uart_fdt_get_io_width(phandle_t node, pcell_t *cell); #endif /* _DEV_UART_CPU_FDT_H_ */ Index: head/sys/dev/uart/uart_dev_snps.c =================================================================== --- head/sys/dev/uart/uart_dev_snps.c (revision 314361) +++ head/sys/dev/uart/uart_dev_snps.c (revision 314362) @@ -1,283 +1,285 @@ /*- * Copyright (c) 2016 Jared McNeill * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #ifdef EXT_RESOURCES #include #include #endif #include "uart_if.h" struct snps_softc { struct ns8250_softc ns8250; #ifdef EXT_RESOURCES clk_t baudclk; clk_t apb_pclk; hwreset_t reset; #endif }; static int snps_uart_attach(struct uart_softc *uart_sc) { struct snps_softc *sc; sc = (struct snps_softc *)uart_sc; /* UART requires to read USR reg when IIR_BUSY */ sc->ns8250.busy_detect = 1; return (ns8250_bus_attach(uart_sc)); } static kobj_method_t snps_methods[] = { KOBJMETHOD(uart_probe, ns8250_bus_probe), KOBJMETHOD(uart_attach, snps_uart_attach), KOBJMETHOD(uart_detach, ns8250_bus_detach), KOBJMETHOD(uart_flush, ns8250_bus_flush), KOBJMETHOD(uart_getsig, ns8250_bus_getsig), KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl), KOBJMETHOD(uart_ipend, ns8250_bus_ipend), KOBJMETHOD(uart_param, ns8250_bus_param), KOBJMETHOD(uart_receive, ns8250_bus_receive), KOBJMETHOD(uart_setsig, ns8250_bus_setsig), KOBJMETHOD(uart_transmit, ns8250_bus_transmit), KOBJMETHOD(uart_grab, ns8250_bus_grab), KOBJMETHOD(uart_ungrab, ns8250_bus_ungrab), KOBJMETHOD_END }; struct uart_class uart_snps_class = { "snps", snps_methods, sizeof(struct snps_softc), .uc_ops = &uart_ns8250_ops, .uc_range = 8, .uc_rclk = 0, }; static struct ofw_compat_data compat_data[] = { { "snps,dw-apb-uart", (uintptr_t)&uart_snps_class }, { NULL, (uintptr_t)NULL } }; UART_FDT_CLASS(compat_data); #ifdef EXT_RESOURCES static int snps_get_clocks(device_t dev, clk_t *baudclk, clk_t *apb_pclk) { struct snps_softc *sc; sc = device_get_softc(dev); *baudclk = NULL; *apb_pclk = NULL; /* Baud clock is either named "baudclk", or there is a single * unnamed clock. */ if (clk_get_by_ofw_name(dev, 0, "baudclk", baudclk) != 0 && clk_get_by_ofw_index(dev, 0, 0, baudclk) != 0) return (ENOENT); /* APB peripheral clock is optional */ (void)clk_get_by_ofw_name(dev, 0, "apb_pclk", apb_pclk); return (0); } #endif static int snps_probe(device_t dev) { struct snps_softc *sc; struct uart_class *uart_class; phandle_t node; - uint32_t shift, clock; + uint32_t shift, iowidth, clock; uint64_t freq; int error; #ifdef EXT_RESOURCES clk_t baudclk, apb_pclk; hwreset_t reset; #endif if (!ofw_bus_status_okay(dev)) return (ENXIO); uart_class = (struct uart_class *)ofw_bus_search_compatible(dev, compat_data)->ocd_data; if (uart_class == NULL) return (ENXIO); freq = 0; sc = device_get_softc(dev); sc->ns8250.base.sc_class = uart_class; node = ofw_bus_get_node(dev); if (OF_getencprop(node, "reg-shift", &shift, sizeof(shift)) <= 0) shift = 0; + if (OF_getencprop(node, "reg-io-width", &iowidth, sizeof(iowidth)) <= 0) + iowidth = 1; if (OF_getencprop(node, "clock-frequency", &clock, sizeof(clock)) <= 0) clock = 0; #ifdef EXT_RESOURCES if (hwreset_get_by_ofw_idx(dev, 0, 0, &reset) == 0) { error = hwreset_deassert(reset); if (error != 0) { device_printf(dev, "cannot de-assert reset\n"); return (error); } } if (snps_get_clocks(dev, &baudclk, &apb_pclk) == 0) { error = clk_enable(baudclk); if (error != 0) { device_printf(dev, "cannot enable baud clock\n"); return (error); } if (apb_pclk != NULL) { error = clk_enable(apb_pclk); if (error != 0) { device_printf(dev, "cannot enable peripheral clock\n"); return (error); } } if (clock == 0) { error = clk_get_freq(baudclk, &freq); if (error != 0) { device_printf(dev, "cannot get frequency\n"); return (error); } clock = (uint32_t)freq; } } #endif if (bootverbose && clock == 0) device_printf(dev, "could not determine frequency\n"); - error = uart_bus_probe(dev, (int)shift, (int)clock, 0, 0); + error = uart_bus_probe(dev, (int)shift, (int)iowidth, (int)clock, 0, 0); if (error != 0) return (error); #ifdef EXT_RESOURCES /* XXX uart_bus_probe has changed the softc, so refresh it */ sc = device_get_softc(dev); /* Store clock and reset handles for detach */ sc->baudclk = baudclk; sc->apb_pclk = apb_pclk; sc->reset = reset; #endif return (0); } static int snps_detach(device_t dev) { #ifdef EXT_RESOURCES struct snps_softc *sc; clk_t baudclk, apb_pclk; hwreset_t reset; #endif int error; #ifdef EXT_RESOURCES sc = device_get_softc(dev); baudclk = sc->baudclk; apb_pclk = sc->apb_pclk; reset = sc->reset; #endif error = uart_bus_detach(dev); if (error != 0) return (error); #ifdef EXT_RESOURCES if (reset != NULL) { error = hwreset_assert(reset); if (error != 0) { device_printf(dev, "cannot assert reset\n"); return (error); } hwreset_release(reset); } if (apb_pclk != NULL) { error = clk_release(apb_pclk); if (error != 0) { device_printf(dev, "cannot release peripheral clock\n"); return (error); } } if (baudclk != NULL) { error = clk_release(baudclk); if (error != 0) { device_printf(dev, "cannot release baud clock\n"); return (error); } } #endif return (0); } static device_method_t snps_bus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, snps_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, snps_detach), DEVMETHOD_END }; static driver_t snps_uart_driver = { uart_driver_name, snps_bus_methods, sizeof(struct snps_softc) }; DRIVER_MODULE(uart_snps, simplebus, snps_uart_driver, uart_devclass, 0, 0); Index: head/sys/mips/adm5120/uart_bus_adm5120.c =================================================================== --- head/sys/mips/adm5120/uart_bus_adm5120.c (revision 314361) +++ head/sys/mips/adm5120/uart_bus_adm5120.c (revision 314362) @@ -1,93 +1,93 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * $Id$ */ /* * Skeleton of this file was based on respective code for ARM * code written by Olivier Houchard. */ /* * XXXMIPS: This file is hacked from arm/... . XXXMIPS here means this file is * experimental and was written for MIPS32 port. */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" static int uart_adm5120_probe(device_t dev); extern struct uart_class uart_adm5120_uart_class; static device_method_t uart_adm5120_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_adm5120_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_adm5120_driver = { uart_driver_name, uart_adm5120_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_adm5120_probe(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); sc->sc_class = &uart_adm5120_uart_class; bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); - return (uart_bus_probe(dev, 0, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0, 0)); } DRIVER_MODULE(uart, obio, uart_adm5120_driver, uart_devclass, 0, 0); Index: head/sys/mips/alchemy/uart_bus_alchemy.c =================================================================== --- head/sys/mips/alchemy/uart_bus_alchemy.c (revision 314361) +++ head/sys/mips/alchemy/uart_bus_alchemy.c (revision 314362) @@ -1,87 +1,87 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * $Id$ */ /* * Skeleton of this file was based on respective code for ARM * code written by Olivier Houchard. */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" static int uart_alchemy_probe(device_t dev); static device_method_t uart_alchemy_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_alchemy_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_alchemy_driver = { uart_driver_name, uart_alchemy_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_alchemy_probe(device_t dev) { struct uart_softc *sc; 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)); + return (uart_bus_probe(dev, 0, 0, 0, 0, 0)); } DRIVER_MODULE(uart, obio, uart_alchemy_driver, uart_devclass, 0, 0); Index: head/sys/mips/atheros/ar531x/uart_bus_ar5315.c =================================================================== --- head/sys/mips/atheros/ar531x/uart_bus_ar5315.c (revision 314361) +++ head/sys/mips/atheros/ar531x/uart_bus_ar5315.c (revision 314362) @@ -1,89 +1,89 @@ /*- * Copyright (c) 2009, Oleksandr Tymoshenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" static int uart_ar5315_probe(device_t dev); extern struct uart_class uart_ar5315_uart_class; static device_method_t uart_ar5315_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_ar5315_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD_END }; static driver_t uart_ar5315_driver = { uart_driver_name, uart_ar5315_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_ar5315_probe(device_t dev) { struct uart_softc *sc; uint64_t freq; freq = ar531x_ahb_freq(); 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)); sc->sc_sysdev->bas.regshft = 2; sc->sc_sysdev->bas.bst = mips_bus_space_generic; sc->sc_sysdev->bas.bsh = ar531x_uart_addr() + 3; sc->sc_bas.regshft = 2; sc->sc_bas.bst = mips_bus_space_generic; sc->sc_bas.bsh = ar531x_uart_addr() + 3; - return (uart_bus_probe(dev, 2, freq, 0, 0)); + return (uart_bus_probe(dev, 2, 0, freq, 0, 0)); } DRIVER_MODULE(uart, apb, uart_ar5315_driver, uart_devclass, 0, 0); Index: head/sys/mips/atheros/uart_bus_ar71xx.c =================================================================== --- head/sys/mips/atheros/uart_bus_ar71xx.c (revision 314361) +++ head/sys/mips/atheros/uart_bus_ar71xx.c (revision 314362) @@ -1,106 +1,106 @@ /*- * Copyright (c) 2009, Oleksandr Tymoshenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" static int uart_ar71xx_probe(device_t dev); extern struct uart_class uart_ar71xx_uart_class; static device_method_t uart_ar71xx_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_ar71xx_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_ar71xx_driver = { uart_driver_name, uart_ar71xx_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_ar71xx_probe(device_t dev) { struct uart_softc *sc; uint64_t freq; freq = ar71xx_uart_freq(); 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)); sc->sc_sysdev->bas.regshft = 2; sc->sc_sysdev->bas.bst = mips_bus_space_generic; sc->sc_sysdev->bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR) + 3; sc->sc_bas.regshft = 2; sc->sc_bas.bst = mips_bus_space_generic; sc->sc_bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR) + 3; - return (uart_bus_probe(dev, 2, freq, 0, 0)); + return (uart_bus_probe(dev, 2, 0, freq, 0, 0)); } #ifdef EARLY_PRINTF static void ar71xx_early_putc(int c) { int i; for (i = 0; i < 1000; i++) { if (ATH_READ_REG(AR71XX_UART_ADDR + AR71XX_UART_LSR) & AR71XX_UART_LSR_THRE) break; } ATH_WRITE_REG(AR71XX_UART_ADDR + AR71XX_UART_THR, (c & 0xff)); } early_putc_t *early_putc = ar71xx_early_putc; #endif DRIVER_MODULE(uart, apb, uart_ar71xx_driver, uart_devclass, 0, 0); Index: head/sys/mips/atheros/uart_bus_ar933x.c =================================================================== --- head/sys/mips/atheros/uart_bus_ar933x.c (revision 314361) +++ head/sys/mips/atheros/uart_bus_ar933x.c (revision 314362) @@ -1,115 +1,115 @@ /*- * Copyright (c) 2012, Adrian Chadd * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef EARLY_PRINTF #include #endif #include "uart_if.h" static int uart_ar933x_probe(device_t dev); extern struct uart_class uart_ar933x_uart_class; static device_method_t uart_ar933x_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_ar933x_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_ar933x_driver = { uart_driver_name, uart_ar933x_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_ar933x_probe(device_t dev) { struct uart_softc *sc; uint64_t freq; freq = ar71xx_uart_freq(); sc = device_get_softc(dev); sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); sc->sc_class = &uart_ar933x_class; bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); sc->sc_sysdev->bas.regshft = 0; sc->sc_sysdev->bas.bst = mips_bus_space_generic; sc->sc_sysdev->bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR); sc->sc_bas.regshft = 0; sc->sc_bas.bst = mips_bus_space_generic; sc->sc_bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR); - return (uart_bus_probe(dev, 2, freq, 0, 0)); + return (uart_bus_probe(dev, 2, 0, freq, 0, 0)); } /* * Assume the UART is setup by the bootloader and just echo that. */ #if defined(EARLY_PRINTF) static void ar933x_early_putc(int c) { int i = 1000; /* Wait until FIFO is clear */ while ((i > 0) && (ATH_READ_REG(AR71XX_UART_ADDR + AR933X_UART_CS_REG) & AR933X_UART_CS_TX_BUSY)) i--; /* Write it out */ ATH_WRITE_REG(AR71XX_UART_ADDR + AR933X_UART_DATA_REG, (c & 0xff)| AR933X_UART_DATA_TX_CSR); } early_putc_t *early_putc = ar933x_early_putc; #endif /* EARLY_PRINTF */ DRIVER_MODULE(uart, apb, uart_ar933x_driver, uart_devclass, 0, 0); Index: head/sys/mips/broadcom/uart_bus_chipc.c =================================================================== --- head/sys/mips/broadcom/uart_bus_chipc.c (revision 314361) +++ head/sys/mips/broadcom/uart_bus_chipc.c (revision 314362) @@ -1,81 +1,81 @@ /*- * Copyright (c) 2016 Michael Zhilin * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_uart.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" #include "bhnd_chipc_if.h" #include "bcm_machdep.h" static int uart_chipc_probe(device_t dev) { struct uart_softc *sc; u_int rclk; sc = device_get_softc(dev); sc->sc_class = &uart_ns8250_class; rclk = bcm_get_uart_rclk(bcm_get_platform()); - return (uart_bus_probe(dev, 0, rclk, 0, 0)); + return (uart_bus_probe(dev, 0, 0, rclk, 0, 0)); } static device_method_t uart_chipc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_chipc_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_chipc_driver = { uart_driver_name, uart_chipc_methods, sizeof(struct uart_softc), }; DRIVER_MODULE(uart, bhnd_chipc, uart_chipc_driver, uart_devclass, 0, 0); Index: head/sys/mips/cavium/uart_bus_octeonusart.c =================================================================== --- head/sys/mips/cavium/uart_bus_octeonusart.c (revision 314361) +++ head/sys/mips/cavium/uart_bus_octeonusart.c (revision 314362) @@ -1,111 +1,111 @@ /*- * Copyright (c) 2006 Wojciech A. Koszek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * $Id$ */ /* * Skeleton of this file was based on respective code for ARM * code written by Olivier Houchard. */ /* * XXXMIPS: This file is hacked from arm/... . XXXMIPS here means this file is * experimental and was written for MIPS32 port. */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" extern struct uart_class uart_oct16550_class; static int uart_octeon_probe(device_t dev); static device_method_t uart_octeon_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_octeon_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), {0, 0} }; static driver_t uart_octeon_driver = { uart_driver_name, uart_octeon_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_octeon_probe(device_t dev) { struct uart_softc *sc; int unit; unit = device_get_unit(dev); sc = device_get_softc(dev); sc->sc_class = &uart_oct16550_class; /* * We inherit the settings from the systme console. Note, the bst * bad bus_space_map are bogus here, but obio doesn't yet support * them, it seems. */ sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); sc->sc_bas.bst = uart_bus_space_mem; /* * XXX * RBR isn't really a great base address. */ if (bus_space_map(sc->sc_bas.bst, CVMX_MIO_UARTX_RBR(0), uart_getrange(sc->sc_class), 0, &sc->sc_bas.bsh) != 0) return (ENXIO); - return (uart_bus_probe(dev, sc->sc_bas.regshft, 0, 0, unit)); + return (uart_bus_probe(dev, sc->sc_bas.regshft, 0, 0, 0, unit)); } DRIVER_MODULE(uart, obio, uart_octeon_driver, uart_devclass, 0, 0); Index: head/sys/mips/idt/uart_bus_rc32434.c =================================================================== --- head/sys/mips/idt/uart_bus_rc32434.c (revision 314361) +++ head/sys/mips/idt/uart_bus_rc32434.c (revision 314362) @@ -1,100 +1,100 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * $Id$ */ /* * Skeleton of this file was based on respective code for ARM * code written by Olivier Houchard. */ /* * XXXMIPS: This file is hacked from arm/... . XXXMIPS here means this file is * experimental and was written for MIPS32 port. */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" static int uart_rc32434_probe(device_t dev); extern struct uart_class uart_rc32434_uart_class; static device_method_t uart_rc32434_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_rc32434_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_rc32434_driver = { uart_driver_name, uart_rc32434_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_rc32434_probe(device_t dev) { struct uart_softc *sc; 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)); sc->sc_sysdev->bas.regshft = 2; sc->sc_sysdev->bas.bst = mips_bus_space_generic; sc->sc_sysdev->bas.bsh = MIPS_PHYS_TO_KSEG1(IDT_BASE_UART0); sc->sc_bas.regshft = 2; sc->sc_bas.bst = mips_bus_space_generic; sc->sc_bas.bsh = MIPS_PHYS_TO_KSEG1(IDT_BASE_UART0); - return (uart_bus_probe(dev, 2, 330000000UL/2, 0, 0)); + return (uart_bus_probe(dev, 2, 0, 330000000UL/2, 0, 0)); } DRIVER_MODULE(uart, obio, uart_rc32434_driver, uart_devclass, 0, 0); Index: head/sys/mips/ingenic/jz4780_uart.c =================================================================== --- head/sys/mips/ingenic/jz4780_uart.c (revision 314361) +++ head/sys/mips/ingenic/jz4780_uart.c (revision 314362) @@ -1,220 +1,220 @@ /*- * Copyright (c) 2013 Ian Lepore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "opt_platform.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" /* * High-level UART interface. */ struct jz4780_uart_softc { struct ns8250_softc ns8250_base; clk_t clk_mod; clk_t clk_baud; }; static int jz4780_bus_attach(struct uart_softc *sc) { struct ns8250_softc *ns8250; struct uart_bas *bas; int rv; ns8250 = (struct ns8250_softc *)sc; bas = &sc->sc_bas; rv = ns8250_bus_attach(sc); if (rv != 0) return (0); /* Configure uart to use extra IER_RXTMOUT bit */ ns8250->ier_rxbits = IER_RXTMOUT | IER_EMSC | IER_ERLS | IER_ERXRDY; ns8250->ier_mask = ~(ns8250->ier_rxbits); ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask; ns8250->ier |= ns8250->ier_rxbits; uart_setreg(bas, REG_IER, ns8250->ier); uart_barrier(bas); return (0); } static kobj_method_t jz4780_uart_methods[] = { KOBJMETHOD(uart_probe, ns8250_bus_probe), KOBJMETHOD(uart_attach, jz4780_bus_attach), KOBJMETHOD(uart_detach, ns8250_bus_detach), KOBJMETHOD(uart_flush, ns8250_bus_flush), KOBJMETHOD(uart_getsig, ns8250_bus_getsig), KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl), KOBJMETHOD(uart_ipend, ns8250_bus_ipend), KOBJMETHOD(uart_param, ns8250_bus_param), KOBJMETHOD(uart_receive, ns8250_bus_receive), KOBJMETHOD(uart_setsig, ns8250_bus_setsig), KOBJMETHOD(uart_transmit, ns8250_bus_transmit), KOBJMETHOD(uart_grab, ns8250_bus_grab), KOBJMETHOD(uart_ungrab, ns8250_bus_ungrab), KOBJMETHOD_END }; static struct uart_class jz4780_uart_class = { "jz4780_uart_class", jz4780_uart_methods, sizeof(struct jz4780_uart_softc), .uc_ops = &uart_ns8250_ops, .uc_range = 8, .uc_rclk = 0, }; /* Compatible devices. */ static struct ofw_compat_data compat_data[] = { {"ingenic,jz4780-uart", (uintptr_t)&jz4780_uart_class}, {NULL, (uintptr_t)NULL}, }; UART_FDT_CLASS(compat_data); /* * UART Driver interface. */ static int jz4780_uart_get_shift(device_t dev) { phandle_t node; pcell_t shift; node = ofw_bus_get_node(dev); if ((OF_getencprop(node, "reg-shift", &shift, sizeof(shift))) <= 0) shift = 2; return ((int)shift); } static int jz4780_uart_probe(device_t dev) { struct jz4780_uart_softc *sc; uint64_t freq; int shift; int rv; const struct ofw_compat_data *cd; sc = device_get_softc(dev); if (!ofw_bus_status_okay(dev)) return (ENXIO); cd = ofw_bus_search_compatible(dev, compat_data); if (cd->ocd_data == 0) return (ENXIO); /* Figure out clock setup */ rv = clk_get_by_ofw_name(dev, 0, "module", &sc->clk_mod); if (rv != 0) { device_printf(dev, "Cannot get UART clock: %d\n", rv); return (ENXIO); } rv = clk_enable(sc->clk_mod); if (rv != 0) { device_printf(dev, "Cannot enable UART clock: %d\n", rv); return (ENXIO); } rv = clk_get_by_ofw_name(dev, 0, "baud", &sc->clk_baud); if (rv != 0) { device_printf(dev, "Cannot get UART clock: %d\n", rv); return (ENXIO); } rv = clk_enable(sc->clk_baud); if (rv != 0) { device_printf(dev, "Cannot enable UART clock: %d\n", rv); return (ENXIO); } rv = clk_get_freq(sc->clk_baud, &freq); if (rv != 0) { device_printf(dev, "Cannot determine UART clock frequency: %d\n", rv); return (ENXIO); } if (bootverbose) device_printf(dev, "got UART clock: %lld\n", freq); sc->ns8250_base.base.sc_class = (struct uart_class *)cd->ocd_data; shift = jz4780_uart_get_shift(dev); - return (uart_bus_probe(dev, shift, (int)freq, 0, 0)); + return (uart_bus_probe(dev, shift, 0, (int)freq, 0, 0)); } static int jz4780_uart_detach(device_t dev) { struct jz4780_uart_softc *sc; int rv; rv = uart_bus_detach(dev); if (rv != 0) return (rv); sc = device_get_softc(dev); if (sc->clk_mod != NULL) { clk_release(sc->clk_mod); } if (sc->clk_baud != NULL) { clk_release(sc->clk_baud); } return (0); } static device_method_t jz4780_uart_bus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, jz4780_uart_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, jz4780_uart_detach), { 0, 0 } }; static driver_t jz4780_uart_driver = { uart_driver_name, jz4780_uart_bus_methods, sizeof(struct jz4780_uart_softc), }; DRIVER_MODULE(jz4780_uart, simplebus, jz4780_uart_driver, uart_devclass, 0, 0); Index: head/sys/mips/malta/uart_bus_maltausart.c =================================================================== --- head/sys/mips/malta/uart_bus_maltausart.c (revision 314361) +++ head/sys/mips/malta/uart_bus_maltausart.c (revision 314362) @@ -1,91 +1,91 @@ /*- * Copyright (c) 2006 Wojciech A. Koszek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * $Id$ */ /* * Skeleton of this file was based on respective code for ARM * code written by Olivier Houchard. */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" static int uart_malta_probe(device_t dev); extern struct uart_class malta_uart_class; static device_method_t uart_malta_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_malta_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_malta_driver = { uart_driver_name, uart_malta_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_malta_probe(device_t dev) { struct uart_softc *sc; 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)); sc->sc_sysdev->bas.bst = mips_bus_space_generic; sc->sc_sysdev->bas.bsh = MIPS_PHYS_TO_KSEG1(MALTA_UART0ADR); sc->sc_bas.bst = mips_bus_space_generic; sc->sc_bas.bsh = MIPS_PHYS_TO_KSEG1(MALTA_UART0ADR); - return(uart_bus_probe(dev, 0, 0, 0, 0)); + return(uart_bus_probe(dev, 0, 0, 0, 0, 0)); } DRIVER_MODULE(uart, obio, uart_malta_driver, uart_devclass, 0, 0); Index: head/sys/mips/rmi/uart_bus_xlr_iodi.c =================================================================== --- head/sys/mips/rmi/uart_bus_xlr_iodi.c (revision 314361) +++ head/sys/mips/rmi/uart_bus_xlr_iodi.c (revision 314362) @@ -1,80 +1,80 @@ /*- * Copyright (c) 2006 Raza Microelectronics * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int uart_iodi_probe(device_t dev); static device_method_t uart_iodi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_iodi_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), {0, 0} }; static driver_t uart_iodi_driver = { uart_driver_name, uart_iodi_methods, sizeof(struct uart_softc), }; extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; static int uart_iodi_probe(device_t dev) { struct uart_softc *sc; 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)); sc->sc_sysdev->bas.bst = rmi_bus_space; sc->sc_sysdev->bas.bsh = MIPS_PHYS_TO_KSEG1(XLR_UART0ADDR); sc->sc_bas.bst = rmi_bus_space; sc->sc_bas.bsh = MIPS_PHYS_TO_KSEG1(XLR_UART0ADDR); /* regshft = 2, rclk = 66000000, rid = 0, chan = 0 */ - return (uart_bus_probe(dev, 2, 66000000, 0, 0)); + return (uart_bus_probe(dev, 2, 0, 66000000, 0, 0)); } DRIVER_MODULE(uart, iodi, uart_iodi_driver, uart_devclass, 0, 0); Index: head/sys/mips/rt305x/uart_bus_rt305x.c =================================================================== --- head/sys/mips/rt305x/uart_bus_rt305x.c (revision 314361) +++ head/sys/mips/rt305x/uart_bus_rt305x.c (revision 314362) @@ -1,94 +1,94 @@ /*- * Copyright (c) 2007 Bruce M. Simpson. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * $Id$ */ /* * Skeleton of this file was based on respective code for ARM * code written by Olivier Houchard. */ /* * XXXMIPS: This file is hacked from arm/... . XXXMIPS here means this file is * experimental and was written for MIPS32 port. */ #include "opt_uart.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uart_if.h" static int uart_rt305x_probe(device_t dev); extern struct uart_class uart_rt305x_uart_class; static device_method_t uart_rt305x_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_rt305x_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_rt305x_driver = { uart_driver_name, uart_rt305x_methods, sizeof(struct uart_softc), }; static int uart_rt305x_probe(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); sc->sc_class = &uart_rt305x_uart_class; sc->sc_bas.regshft = 2; sc->sc_bas.bst = mips_bus_space_generic; sc->sc_bas.bsh = MIPS_PHYS_TO_KSEG1(device_get_unit(dev)?UARTLITE_BASE:UART_BASE); - return (uart_bus_probe(dev, 2, SYSTEM_CLOCK, 0, 0)); + return (uart_bus_probe(dev, 2, 0, SYSTEM_CLOCK, 0, 0)); } DRIVER_MODULE(uart, obio, uart_rt305x_driver, uart_devclass, 0, 0); Index: head/sys/powerpc/psim/uart_iobus.c =================================================================== --- head/sys/powerpc/psim/uart_iobus.c (revision 314361) +++ head/sys/powerpc/psim/uart_iobus.c (revision 314362) @@ -1,87 +1,87 @@ /*- * Copyright 2002 by Peter Grehan. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * PSIM local bus 16550 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int uart_iobus_probe(device_t dev); static device_method_t uart_iobus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, uart_iobus_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), { 0, 0 } }; static driver_t uart_iobus_driver = { uart_driver_name, uart_iobus_methods, sizeof(struct uart_softc), }; static int uart_iobus_probe(device_t dev) { struct uart_softc *sc; char *type; type = iobus_get_name(dev); if (strncmp(type, "com", 3) != 0) return (ENXIO); sc = device_get_softc(dev); sc->sc_class = &uart_ns8250_class; device_set_desc(dev, "PSIM serial port"); - return (uart_bus_probe(dev, 0, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0, 0)); } DRIVER_MODULE(uart, iobus, uart_iobus_driver, uart_devclass, 0, 0); Index: head/sys/sparc64/pci/sbbc.c =================================================================== --- head/sys/sparc64/pci/sbbc.c (revision 314361) +++ head/sys/sparc64/pci/sbbc.c (revision 314362) @@ -1,1111 +1,1111 @@ /* $OpenBSD: sbbc.c,v 1.7 2009/11/09 17:53:39 nicm Exp $ */ /*- * Copyright (c) 2008 Mark Kettenis * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /*- * Copyright (c) 2010 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "clock_if.h" #include "uart_if.h" #define SBBC_PCI_BAR PCIR_BAR(0) #define SBBC_PCI_VENDOR 0x108e #define SBBC_PCI_PRODUCT 0xc416 #define SBBC_REGS_OFFSET 0x800000 #define SBBC_REGS_SIZE 0x6230 #define SBBC_EPLD_OFFSET 0x8e0000 #define SBBC_EPLD_SIZE 0x20 #define SBBC_SRAM_OFFSET 0x900000 #define SBBC_SRAM_SIZE 0x20000 /* 128KB SRAM */ #define SBBC_PCI_INT_STATUS 0x2320 #define SBBC_PCI_INT_ENABLE 0x2330 #define SBBC_PCI_ENABLE_INT_A 0x11 #define SBBC_EPLD_INTERRUPT 0x13 #define SBBC_EPLD_INTERRUPT_ON 0x01 #define SBBC_SRAM_CONS_IN 0x00000001 #define SBBC_SRAM_CONS_OUT 0x00000002 #define SBBC_SRAM_CONS_BRK 0x00000004 #define SBBC_SRAM_CONS_SPACE_IN 0x00000008 #define SBBC_SRAM_CONS_SPACE_OUT 0x00000010 #define SBBC_TAG_KEY_SIZE 8 #define SBBC_TAG_KEY_SCSOLIE "SCSOLIE" /* SC -> OS int. enable */ #define SBBC_TAG_KEY_SCSOLIR "SCSOLIR" /* SC -> OS int. reason */ #define SBBC_TAG_KEY_SOLCONS "SOLCONS" /* OS console buffer */ #define SBBC_TAG_KEY_SOLSCIE "SOLSCIE" /* OS -> SC int. enable */ #define SBBC_TAG_KEY_SOLSCIR "SOLSCIR" /* OS -> SC int. reason */ #define SBBC_TAG_KEY_TODDATA "TODDATA" /* OS TOD struct */ #define SBBC_TAG_OFF(x) offsetof(struct sbbc_sram_tag, x) struct sbbc_sram_tag { char tag_key[SBBC_TAG_KEY_SIZE]; uint32_t tag_size; uint32_t tag_offset; } __packed; #define SBBC_TOC_MAGIC "TOCSRAM" #define SBBC_TOC_MAGIC_SIZE 8 #define SBBC_TOC_TAGS_MAX 32 #define SBBC_TOC_OFF(x) offsetof(struct sbbc_sram_toc, x) struct sbbc_sram_toc { char toc_magic[SBBC_TOC_MAGIC_SIZE]; uint8_t toc_reserved; uint8_t toc_type; uint16_t toc_version; uint32_t toc_ntags; struct sbbc_sram_tag toc_tag[SBBC_TOC_TAGS_MAX]; } __packed; #define SBBC_TOD_MAGIC 0x54443100 /* "TD1" */ #define SBBC_TOD_VERSION 1 #define SBBC_TOD_OFF(x) offsetof(struct sbbc_sram_tod, x) struct sbbc_sram_tod { uint32_t tod_magic; uint32_t tod_version; uint64_t tod_time; uint64_t tod_skew; uint32_t tod_reserved; uint32_t tod_heartbeat; uint32_t tod_timeout; } __packed; #define SBBC_CONS_MAGIC 0x434f4e00 /* "CON" */ #define SBBC_CONS_VERSION 1 #define SBBC_CONS_OFF(x) offsetof(struct sbbc_sram_cons, x) struct sbbc_sram_cons { uint32_t cons_magic; uint32_t cons_version; uint32_t cons_size; uint32_t cons_in_begin; uint32_t cons_in_end; uint32_t cons_in_rdptr; uint32_t cons_in_wrptr; uint32_t cons_out_begin; uint32_t cons_out_end; uint32_t cons_out_rdptr; uint32_t cons_out_wrptr; } __packed; struct sbbc_softc { struct resource *sc_res; }; #define SBBC_READ_N(wdth, offs) \ bus_space_read_ ## wdth((bst), (bsh), (offs)) #define SBBC_WRITE_N(wdth, offs, val) \ bus_space_write_ ## wdth((bst), (bsh), (offs), (val)) #define SBBC_READ_1(offs) \ SBBC_READ_N(1, (offs)) #define SBBC_READ_2(offs) \ bswap16(SBBC_READ_N(2, (offs))) #define SBBC_READ_4(offs) \ bswap32(SBBC_READ_N(4, (offs))) #define SBBC_READ_8(offs) \ bswap64(SBBC_READ_N(8, (offs))) #define SBBC_WRITE_1(offs, val) \ SBBC_WRITE_N(1, (offs), (val)) #define SBBC_WRITE_2(offs, val) \ SBBC_WRITE_N(2, (offs), bswap16(val)) #define SBBC_WRITE_4(offs, val) \ SBBC_WRITE_N(4, (offs), bswap32(val)) #define SBBC_WRITE_8(offs, val) \ SBBC_WRITE_N(8, (offs), bswap64(val)) #define SBBC_REGS_READ_1(offs) \ SBBC_READ_1((offs) + SBBC_REGS_OFFSET) #define SBBC_REGS_READ_2(offs) \ SBBC_READ_2((offs) + SBBC_REGS_OFFSET) #define SBBC_REGS_READ_4(offs) \ SBBC_READ_4((offs) + SBBC_REGS_OFFSET) #define SBBC_REGS_READ_8(offs) \ SBBC_READ_8((offs) + SBBC_REGS_OFFSET) #define SBBC_REGS_WRITE_1(offs, val) \ SBBC_WRITE_1((offs) + SBBC_REGS_OFFSET, (val)) #define SBBC_REGS_WRITE_2(offs, val) \ SBBC_WRITE_2((offs) + SBBC_REGS_OFFSET, (val)) #define SBBC_REGS_WRITE_4(offs, val) \ SBBC_WRITE_4((offs) + SBBC_REGS_OFFSET, (val)) #define SBBC_REGS_WRITE_8(offs, val) \ SBBC_WRITE_8((offs) + SBBC_REGS_OFFSET, (val)) #define SBBC_EPLD_READ_1(offs) \ SBBC_READ_1((offs) + SBBC_EPLD_OFFSET) #define SBBC_EPLD_READ_2(offs) \ SBBC_READ_2((offs) + SBBC_EPLD_OFFSET) #define SBBC_EPLD_READ_4(offs) \ SBBC_READ_4((offs) + SBBC_EPLD_OFFSET) #define SBBC_EPLD_READ_8(offs) \ SBBC_READ_8((offs) + SBBC_EPLD_OFFSET) #define SBBC_EPLD_WRITE_1(offs, val) \ SBBC_WRITE_1((offs) + SBBC_EPLD_OFFSET, (val)) #define SBBC_EPLD_WRITE_2(offs, val) \ SBBC_WRITE_2((offs) + SBBC_EPLD_OFFSET, (val)) #define SBBC_EPLD_WRITE_4(offs, val) \ SBBC_WRITE_4((offs) + SBBC_EPLD_OFFSET, (val)) #define SBBC_EPLD_WRITE_8(offs, val) \ SBBC_WRITE_8((offs) + SBBC_EPLD_OFFSET, (val)) #define SBBC_SRAM_READ_1(offs) \ SBBC_READ_1((offs) + SBBC_SRAM_OFFSET) #define SBBC_SRAM_READ_2(offs) \ SBBC_READ_2((offs) + SBBC_SRAM_OFFSET) #define SBBC_SRAM_READ_4(offs) \ SBBC_READ_4((offs) + SBBC_SRAM_OFFSET) #define SBBC_SRAM_READ_8(offs) \ SBBC_READ_8((offs) + SBBC_SRAM_OFFSET) #define SBBC_SRAM_WRITE_1(offs, val) \ SBBC_WRITE_1((offs) + SBBC_SRAM_OFFSET, (val)) #define SBBC_SRAM_WRITE_2(offs, val) \ SBBC_WRITE_2((offs) + SBBC_SRAM_OFFSET, (val)) #define SBBC_SRAM_WRITE_4(offs, val) \ SBBC_WRITE_4((offs) + SBBC_SRAM_OFFSET, (val)) #define SBBC_SRAM_WRITE_8(offs, val) \ SBBC_WRITE_8((offs) + SBBC_SRAM_OFFSET, (val)) #define SUNW_SETCONSINPUT "SUNW,set-console-input" #define SUNW_SETCONSINPUT_CLNT "CON_CLNT" #define SUNW_SETCONSINPUT_OBP "CON_OBP" static u_int sbbc_console; static uint32_t sbbc_scsolie; static uint32_t sbbc_scsolir; static uint32_t sbbc_solcons; static uint32_t sbbc_solscie; static uint32_t sbbc_solscir; static uint32_t sbbc_toddata; /* * internal helpers */ static int sbbc_parse_toc(bus_space_tag_t bst, bus_space_handle_t bsh); static inline void sbbc_send_intr(bus_space_tag_t bst, bus_space_handle_t bsh); static const char *sbbc_serengeti_set_console_input(char *new); /* * SBBC PCI interface */ static bus_activate_resource_t sbbc_bus_activate_resource; static bus_adjust_resource_t sbbc_bus_adjust_resource; static bus_deactivate_resource_t sbbc_bus_deactivate_resource; static bus_alloc_resource_t sbbc_bus_alloc_resource; static bus_release_resource_t sbbc_bus_release_resource; static bus_get_resource_list_t sbbc_bus_get_resource_list; static bus_setup_intr_t sbbc_bus_setup_intr; static bus_teardown_intr_t sbbc_bus_teardown_intr; static device_attach_t sbbc_pci_attach; static device_probe_t sbbc_pci_probe; static clock_gettime_t sbbc_tod_gettime; static clock_settime_t sbbc_tod_settime; static device_method_t sbbc_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbbc_pci_probe), DEVMETHOD(device_attach, sbbc_pci_attach), DEVMETHOD(bus_alloc_resource, sbbc_bus_alloc_resource), DEVMETHOD(bus_activate_resource,sbbc_bus_activate_resource), DEVMETHOD(bus_deactivate_resource,sbbc_bus_deactivate_resource), DEVMETHOD(bus_adjust_resource, sbbc_bus_adjust_resource), DEVMETHOD(bus_release_resource, sbbc_bus_release_resource), DEVMETHOD(bus_setup_intr, sbbc_bus_setup_intr), DEVMETHOD(bus_teardown_intr, sbbc_bus_teardown_intr), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_get_resource_list, sbbc_bus_get_resource_list), /* clock interface */ DEVMETHOD(clock_gettime, sbbc_tod_gettime), DEVMETHOD(clock_settime, sbbc_tod_settime), DEVMETHOD_END }; static devclass_t sbbc_devclass; DEFINE_CLASS_0(sbbc, sbbc_driver, sbbc_pci_methods, sizeof(struct sbbc_softc)); DRIVER_MODULE(sbbc, pci, sbbc_driver, sbbc_devclass, NULL, NULL); static int sbbc_pci_probe(device_t dev) { if (pci_get_vendor(dev) == SBBC_PCI_VENDOR && pci_get_device(dev) == SBBC_PCI_PRODUCT) { device_set_desc(dev, "Sun BootBus controller"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int sbbc_pci_attach(device_t dev) { struct sbbc_softc *sc; struct timespec ts; device_t child; bus_space_tag_t bst; bus_space_handle_t bsh; phandle_t node; int error, rid; uint32_t val; /* Nothing to to if we're not the chosen one. */ if ((node = OF_finddevice("/chosen")) == -1) { device_printf(dev, "failed to find /chosen\n"); return (ENXIO); } if (OF_getprop(node, "iosram", &node, sizeof(node)) == -1) { device_printf(dev, "failed to get iosram\n"); return (ENXIO); } if (node != ofw_bus_get_node(dev)) return (0); sc = device_get_softc(dev); rid = SBBC_PCI_BAR; sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_res == NULL) { device_printf(dev, "failed to allocate resources\n"); return (ENXIO); } bst = rman_get_bustag(sc->sc_res); bsh = rman_get_bushandle(sc->sc_res); if (sbbc_console != 0) { /* Once again the interrupt pin isn't set. */ if (pci_get_intpin(dev) == 0) pci_set_intpin(dev, 1); child = device_add_child(dev, NULL, -1); if (child == NULL) device_printf(dev, "failed to add UART device\n"); error = bus_generic_attach(dev); if (error != 0) device_printf(dev, "failed to attach UART device\n"); } else { error = sbbc_parse_toc(bst, bsh); if (error != 0) { device_printf(dev, "failed to parse TOC\n"); if (sbbc_console != 0) { bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->sc_res); return (error); } } } if (sbbc_toddata != 0) { if ((val = SBBC_SRAM_READ_4(sbbc_toddata + SBBC_TOD_OFF(tod_magic))) != SBBC_TOD_MAGIC) device_printf(dev, "invalid TOD magic %#x\n", val); else if ((val = SBBC_SRAM_READ_4(sbbc_toddata + SBBC_TOD_OFF(tod_version))) < SBBC_TOD_VERSION) device_printf(dev, "invalid TOD version %#x\n", val); else { clock_register(dev, 1000000); /* 1 sec. resolution */ if (bootverbose) { sbbc_tod_gettime(dev, &ts); device_printf(dev, "current time: %ld.%09ld\n", (long)ts.tv_sec, ts.tv_nsec); } } } return (0); } /* * Note that the bus methods don't pass-through the uart(4) requests but act * as if they would come from sbbc(4) in order to avoid complications with * pci(4) (actually, uart(4) isn't a real child but rather a function of * sbbc(4) anyway). */ static struct resource * sbbc_bus_alloc_resource(device_t dev, device_t child __unused, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) { struct sbbc_softc *sc; sc = device_get_softc(dev); switch (type) { case SYS_RES_IRQ: return (bus_generic_alloc_resource(dev, dev, type, rid, start, end, count, flags)); case SYS_RES_MEMORY: return (sc->sc_res); default: return (NULL); } } static int sbbc_bus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { if (type == SYS_RES_MEMORY) return (0); return (bus_generic_activate_resource(bus, child, type, rid, res)); } static int sbbc_bus_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { if (type == SYS_RES_MEMORY) return (0); return (bus_generic_deactivate_resource(bus, child, type, rid, res)); } static int sbbc_bus_adjust_resource(device_t bus __unused, device_t child __unused, int type __unused, struct resource *res __unused, rman_res_t start __unused, rman_res_t end __unused) { return (ENXIO); } static int sbbc_bus_release_resource(device_t dev, device_t child __unused, int type, int rid, struct resource *res) { if (type == SYS_RES_IRQ) return (bus_generic_release_resource(dev, dev, type, rid, res)); return (0); } static struct resource_list * sbbc_bus_get_resource_list(device_t dev, device_t child __unused) { return (bus_generic_get_resource_list(dev, dev)); } static int sbbc_bus_setup_intr(device_t dev, device_t child __unused, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep) { return (bus_generic_setup_intr(dev, dev, res, flags, filt, intr, arg, cookiep)); } static int sbbc_bus_teardown_intr(device_t dev, device_t child __unused, struct resource *res, void *cookie) { return (bus_generic_teardown_intr(dev, dev, res, cookie)); } /* * internal helpers */ static int sbbc_parse_toc(bus_space_tag_t bst, bus_space_handle_t bsh) { char buf[MAX(SBBC_TAG_KEY_SIZE, SBBC_TOC_MAGIC_SIZE)]; bus_size_t tag; phandle_t node; uint32_t off, sram_toc; u_int i, tags; if ((node = OF_finddevice("/chosen")) == -1) return (ENXIO); /* SRAM TOC offset defaults to 0. */ if (OF_getprop(node, "iosram-toc", &sram_toc, sizeof(sram_toc)) <= 0) sram_toc = 0; bus_space_read_region_1(bst, bsh, SBBC_SRAM_OFFSET + sram_toc + SBBC_TOC_OFF(toc_magic), buf, SBBC_TOC_MAGIC_SIZE); buf[SBBC_TOC_MAGIC_SIZE - 1] = '\0'; if (strcmp(buf, SBBC_TOC_MAGIC) != 0) return (ENXIO); tags = SBBC_SRAM_READ_4(sram_toc + SBBC_TOC_OFF(toc_ntags)); for (i = 0; i < tags; i++) { tag = sram_toc + SBBC_TOC_OFF(toc_tag) + i * sizeof(struct sbbc_sram_tag); bus_space_read_region_1(bst, bsh, SBBC_SRAM_OFFSET + tag + SBBC_TAG_OFF(tag_key), buf, SBBC_TAG_KEY_SIZE); buf[SBBC_TAG_KEY_SIZE - 1] = '\0'; off = SBBC_SRAM_READ_4(tag + SBBC_TAG_OFF(tag_offset)); if (strcmp(buf, SBBC_TAG_KEY_SCSOLIE) == 0) sbbc_scsolie = off; else if (strcmp(buf, SBBC_TAG_KEY_SCSOLIR) == 0) sbbc_scsolir = off; else if (strcmp(buf, SBBC_TAG_KEY_SOLCONS) == 0) sbbc_solcons = off; else if (strcmp(buf, SBBC_TAG_KEY_SOLSCIE) == 0) sbbc_solscie = off; else if (strcmp(buf, SBBC_TAG_KEY_SOLSCIR) == 0) sbbc_solscir = off; else if (strcmp(buf, SBBC_TAG_KEY_TODDATA) == 0) sbbc_toddata = off; } return (0); } static const char * sbbc_serengeti_set_console_input(char *new) { struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t new; cell_t old; } args = { (cell_t)SUNW_SETCONSINPUT, 1, 1, }; args.new = (cell_t)new; if (ofw_entry(&args) == -1) return (NULL); return ((const char *)args.old); } static inline void sbbc_send_intr(bus_space_tag_t bst, bus_space_handle_t bsh) { SBBC_EPLD_WRITE_1(SBBC_EPLD_INTERRUPT, SBBC_EPLD_INTERRUPT_ON); bus_space_barrier(bst, bsh, SBBC_EPLD_OFFSET + SBBC_EPLD_INTERRUPT, 1, BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); } /* * TOD interface */ static int sbbc_tod_gettime(device_t dev, struct timespec *ts) { struct sbbc_softc *sc; bus_space_tag_t bst; bus_space_handle_t bsh; sc = device_get_softc(dev); bst = rman_get_bustag(sc->sc_res); bsh = rman_get_bushandle(sc->sc_res); ts->tv_sec = SBBC_SRAM_READ_8(sbbc_toddata + SBBC_TOD_OFF(tod_time)) + SBBC_SRAM_READ_8(sbbc_toddata + SBBC_TOD_OFF(tod_skew)); ts->tv_nsec = 0; return (0); } static int sbbc_tod_settime(device_t dev, struct timespec *ts) { struct sbbc_softc *sc; bus_space_tag_t bst; bus_space_handle_t bsh; sc = device_get_softc(dev); bst = rman_get_bustag(sc->sc_res); bsh = rman_get_bushandle(sc->sc_res); SBBC_SRAM_WRITE_8(sbbc_toddata + SBBC_TOD_OFF(tod_skew), ts->tv_sec - SBBC_SRAM_READ_8(sbbc_toddata + SBBC_TOD_OFF(tod_time))); return (0); } /* * UART bus front-end */ static device_probe_t sbbc_uart_sbbc_probe; static device_method_t sbbc_uart_sbbc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbbc_uart_sbbc_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD_END }; DEFINE_CLASS_0(uart, sbbc_uart_driver, sbbc_uart_sbbc_methods, sizeof(struct uart_softc)); DRIVER_MODULE(uart, sbbc, sbbc_uart_driver, uart_devclass, NULL, NULL); static int sbbc_uart_sbbc_probe(device_t dev) { struct uart_softc *sc; sc = device_get_softc(dev); sc->sc_class = &uart_sbbc_class; device_set_desc(dev, "Serengeti console"); - return (uart_bus_probe(dev, 0, 0, SBBC_PCI_BAR, 0)); + return (uart_bus_probe(dev, 0, 0, 0, SBBC_PCI_BAR, 0)); } /* * Low-level UART interface */ static int sbbc_uart_probe(struct uart_bas *bas); static void sbbc_uart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity); static void sbbc_uart_term(struct uart_bas *bas); static void sbbc_uart_putc(struct uart_bas *bas, int c); static int sbbc_uart_rxready(struct uart_bas *bas); static int sbbc_uart_getc(struct uart_bas *bas, struct mtx *hwmtx); static struct uart_ops sbbc_uart_ops = { .probe = sbbc_uart_probe, .init = sbbc_uart_init, .term = sbbc_uart_term, .putc = sbbc_uart_putc, .rxready = sbbc_uart_rxready, .getc = sbbc_uart_getc, }; static int sbbc_uart_probe(struct uart_bas *bas) { bus_space_tag_t bst; bus_space_handle_t bsh; int error; sbbc_console = 1; bst = bas->bst; bsh = bas->bsh; error = sbbc_parse_toc(bst, bsh); if (error != 0) return (error); if (sbbc_scsolie == 0 || sbbc_scsolir == 0 || sbbc_solcons == 0 || sbbc_solscie == 0 || sbbc_solscir == 0) return (ENXIO); if (SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_magic)) != SBBC_CONS_MAGIC || SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_version)) < SBBC_CONS_VERSION) return (ENXIO); return (0); } static void sbbc_uart_init(struct uart_bas *bas, int baudrate __unused, int databits __unused, int stopbits __unused, int parity __unused) { bus_space_tag_t bst; bus_space_handle_t bsh; bst = bas->bst; bsh = bas->bsh; /* Enable output to and space in from the SC interrupts. */ SBBC_SRAM_WRITE_4(sbbc_solscie, SBBC_SRAM_READ_4(sbbc_solscie) | SBBC_SRAM_CONS_OUT | SBBC_SRAM_CONS_SPACE_IN); uart_barrier(bas); /* Take over the console input. */ sbbc_serengeti_set_console_input(SUNW_SETCONSINPUT_CLNT); } static void sbbc_uart_term(struct uart_bas *bas __unused) { /* Give back the console input. */ sbbc_serengeti_set_console_input(SUNW_SETCONSINPUT_OBP); } static void sbbc_uart_putc(struct uart_bas *bas, int c) { bus_space_tag_t bst; bus_space_handle_t bsh; uint32_t wrptr; bst = bas->bst; bsh = bas->bsh; wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr)); SBBC_SRAM_WRITE_1(sbbc_solcons + wrptr, c); uart_barrier(bas); if (++wrptr == SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_end))) wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_begin)); SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr), wrptr); uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solscir, SBBC_SRAM_READ_4(sbbc_solscir) | SBBC_SRAM_CONS_OUT); uart_barrier(bas); sbbc_send_intr(bst, bsh); } static int sbbc_uart_rxready(struct uart_bas *bas) { bus_space_tag_t bst; bus_space_handle_t bsh; bst = bas->bst; bsh = bas->bsh; if (SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr)) == SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_wrptr))) return (0); return (1); } static int sbbc_uart_getc(struct uart_bas *bas, struct mtx *hwmtx) { bus_space_tag_t bst; bus_space_handle_t bsh; int c; uint32_t rdptr; bst = bas->bst; bsh = bas->bsh; uart_lock(hwmtx); while (sbbc_uart_rxready(bas) == 0) { uart_unlock(hwmtx); DELAY(4); uart_lock(hwmtx); } rdptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr)); c = SBBC_SRAM_READ_1(sbbc_solcons + rdptr); uart_barrier(bas); if (++rdptr == SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_end))) rdptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_begin)); SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr), rdptr); uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solscir, SBBC_SRAM_READ_4(sbbc_solscir) | SBBC_SRAM_CONS_SPACE_IN); uart_barrier(bas); sbbc_send_intr(bst, bsh); uart_unlock(hwmtx); return (c); } /* * High-level UART interface */ static int sbbc_uart_bus_attach(struct uart_softc *sc); static int sbbc_uart_bus_detach(struct uart_softc *sc); static int sbbc_uart_bus_flush(struct uart_softc *sc, int what); static int sbbc_uart_bus_getsig(struct uart_softc *sc); static int sbbc_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data); static int sbbc_uart_bus_ipend(struct uart_softc *sc); static int sbbc_uart_bus_param(struct uart_softc *sc, int baudrate, int databits, int stopbits, int parity); static int sbbc_uart_bus_probe(struct uart_softc *sc); static int sbbc_uart_bus_receive(struct uart_softc *sc); static int sbbc_uart_bus_setsig(struct uart_softc *sc, int sig); static int sbbc_uart_bus_transmit(struct uart_softc *sc); static kobj_method_t sbbc_uart_methods[] = { KOBJMETHOD(uart_attach, sbbc_uart_bus_attach), KOBJMETHOD(uart_detach, sbbc_uart_bus_detach), KOBJMETHOD(uart_flush, sbbc_uart_bus_flush), KOBJMETHOD(uart_getsig, sbbc_uart_bus_getsig), KOBJMETHOD(uart_ioctl, sbbc_uart_bus_ioctl), KOBJMETHOD(uart_ipend, sbbc_uart_bus_ipend), KOBJMETHOD(uart_param, sbbc_uart_bus_param), KOBJMETHOD(uart_probe, sbbc_uart_bus_probe), KOBJMETHOD(uart_receive, sbbc_uart_bus_receive), KOBJMETHOD(uart_setsig, sbbc_uart_bus_setsig), KOBJMETHOD(uart_transmit, sbbc_uart_bus_transmit), DEVMETHOD_END }; struct uart_class uart_sbbc_class = { "sbbc", sbbc_uart_methods, sizeof(struct uart_softc), .uc_ops = &sbbc_uart_ops, .uc_range = 1, .uc_rclk = 0x5bbc, /* arbitrary */ .uc_rshift = 0 }; #define SIGCHG(c, i, s, d) \ if ((c) != 0) { \ i |= (((i) & (s)) != 0) ? (s) : (s) | (d); \ } else { \ i = (((i) & (s)) != 0) ? ((i) & ~(s)) | (d) : (i); \ } static int sbbc_uart_bus_attach(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; uint32_t wrptr; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; uart_lock(sc->sc_hwmtx); /* * Let the current output drain before enabling interrupts. Not * doing so tends to cause lost output when turning them on. */ wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr)); while (SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_rdptr)) != wrptr); cpu_spinwait(); /* Clear and acknowledge possibly outstanding interrupts. */ SBBC_SRAM_WRITE_4(sbbc_scsolir, 0); uart_barrier(bas); SBBC_REGS_WRITE_4(SBBC_PCI_INT_STATUS, SBBC_SRAM_READ_4(sbbc_scsolir)); uart_barrier(bas); /* Enable PCI interrupts. */ SBBC_REGS_WRITE_4(SBBC_PCI_INT_ENABLE, SBBC_PCI_ENABLE_INT_A); uart_barrier(bas); /* Enable input from and output to SC as well as break interrupts. */ SBBC_SRAM_WRITE_4(sbbc_scsolie, SBBC_SRAM_READ_4(sbbc_scsolie) | SBBC_SRAM_CONS_IN | SBBC_SRAM_CONS_BRK | SBBC_SRAM_CONS_SPACE_OUT); uart_barrier(bas); uart_unlock(sc->sc_hwmtx); return (0); } static int sbbc_uart_bus_detach(struct uart_softc *sc) { /* Give back the console input. */ sbbc_serengeti_set_console_input(SUNW_SETCONSINPUT_OBP); return (0); } static int sbbc_uart_bus_flush(struct uart_softc *sc, int what) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; if ((what & UART_FLUSH_TRANSMITTER) != 0) return (ENODEV); if ((what & UART_FLUSH_RECEIVER) != 0) { SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr), SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_wrptr))); uart_barrier(bas); } return (0); } static int sbbc_uart_bus_getsig(struct uart_softc *sc) { uint32_t dummy, new, old, sig; do { old = sc->sc_hwsig; sig = old; dummy = 0; SIGCHG(dummy, sig, SER_CTS, SER_DCTS); SIGCHG(dummy, sig, SER_DCD, SER_DDCD); SIGCHG(dummy, sig, SER_DSR, SER_DDSR); new = sig & ~SER_MASK_DELTA; } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); return (sig); } static int sbbc_uart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) { int error; error = 0; uart_lock(sc->sc_hwmtx); switch (request) { case UART_IOCTL_BAUD: *(int*)data = 9600; /* arbitrary */ break; default: error = EINVAL; break; } uart_unlock(sc->sc_hwmtx); return (error); } static int sbbc_uart_bus_ipend(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; int ipend; uint32_t reason, status; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; uart_lock(sc->sc_hwmtx); status = SBBC_REGS_READ_4(SBBC_PCI_INT_STATUS); if (status == 0) { uart_unlock(sc->sc_hwmtx); return (0); } /* * Unfortunately, we can't use compare and swap for non-cachable * memory. */ reason = SBBC_SRAM_READ_4(sbbc_scsolir); SBBC_SRAM_WRITE_4(sbbc_scsolir, 0); uart_barrier(bas); /* Acknowledge the interrupt. */ SBBC_REGS_WRITE_4(SBBC_PCI_INT_STATUS, status); uart_barrier(bas); uart_unlock(sc->sc_hwmtx); ipend = 0; if ((reason & SBBC_SRAM_CONS_IN) != 0) ipend |= SER_INT_RXREADY; if ((reason & SBBC_SRAM_CONS_BRK) != 0) ipend |= SER_INT_BREAK; if ((reason & SBBC_SRAM_CONS_SPACE_OUT) != 0 && SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_rdptr)) == SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr))) ipend |= SER_INT_TXIDLE; return (ipend); } static int sbbc_uart_bus_param(struct uart_softc *sc __unused, int baudrate __unused, int databits __unused, int stopbits __unused, int parity __unused) { return (0); } static int sbbc_uart_bus_probe(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; if (sbbc_console != 0) { bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; sc->sc_rxfifosz = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_end)) - SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_begin)) - 1; sc->sc_txfifosz = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_end)) - SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_begin)) - 1; return (0); } return (ENXIO); } static int sbbc_uart_bus_receive(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; int c; uint32_t end, rdptr, wrptr; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; uart_lock(sc->sc_hwmtx); end = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_end)); rdptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr)); wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_wrptr)); while (rdptr != wrptr) { if (uart_rx_full(sc) != 0) { sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; break; } c = SBBC_SRAM_READ_1(sbbc_solcons + rdptr); uart_rx_put(sc, c); if (++rdptr == end) rdptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_begin)); } uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_in_rdptr), rdptr); uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solscir, SBBC_SRAM_READ_4(sbbc_solscir) | SBBC_SRAM_CONS_SPACE_IN); uart_barrier(bas); sbbc_send_intr(bst, bsh); uart_unlock(sc->sc_hwmtx); return (0); } static int sbbc_uart_bus_setsig(struct uart_softc *sc, int sig) { struct uart_bas *bas; uint32_t new, old; bas = &sc->sc_bas; do { old = sc->sc_hwsig; new = old; if ((sig & SER_DDTR) != 0) { SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR); } if ((sig & SER_DRTS) != 0) { SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS); } } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); return (0); } static int sbbc_uart_bus_transmit(struct uart_softc *sc) { struct uart_bas *bas; bus_space_tag_t bst; bus_space_handle_t bsh; int i; uint32_t end, wrptr; bas = &sc->sc_bas; bst = bas->bst; bsh = bas->bsh; uart_lock(sc->sc_hwmtx); end = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_end)); wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr)); for (i = 0; i < sc->sc_txdatasz; i++) { SBBC_SRAM_WRITE_1(sbbc_solcons + wrptr, sc->sc_txbuf[i]); if (++wrptr == end) wrptr = SBBC_SRAM_READ_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_begin)); } uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solcons + SBBC_CONS_OFF(cons_out_wrptr), wrptr); uart_barrier(bas); SBBC_SRAM_WRITE_4(sbbc_solscir, SBBC_SRAM_READ_4(sbbc_solscir) | SBBC_SRAM_CONS_OUT); uart_barrier(bas); sbbc_send_intr(bst, bsh); sc->sc_txbusy = 1; uart_unlock(sc->sc_hwmtx); return (0); }