Date: Wed, 25 Feb 2009 00:58:08 +0000 (UTC) From: Sam Leffler <sam@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r189021 - in projects/cambria/sys: arm/conf arm/xscale/ixp425 dev/uart Message-ID: <200902250058.n1P0w8bg080802@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sam Date: Wed Feb 25 00:58:08 2009 New Revision: 189021 URL: http://svn.freebsd.org/changeset/base/189021 Log: Checkpoint support for the optional GPS chip: o the Trimble part has a TL16C752B uart through which NMEA data comes; add it to the config+hints (rclk 1843200) o map the i/o region associated with the uart o rewrite the ixp bus memory resource allocation to handle two uarts with different bus tag requirements (need to completely rewrite this stuff to hide the A4 crap and/or overhaul uart to eliminate the need for the A4 hack) o add a rwdelay parameter/hack to uart to handle TL16C752B brain-damage: back-to-back read/writes must have a min 2usec delay between or data will be corrupted (again this would be better hidden behind bus space hacks but uart needs re-architecting); thanks to Chris Lang for the tip o force GPIO pin 3 irq to be output+edge-rising (yet another hack as we need to redesign how bus_setup_intr works so we can handle this stuff in one spot instead of in every driver) o add a ddb "show gpio" command to dump GPIO configuration o add a temporary ddb "show istat" command to dump uart stats+registers The GPS part seems to work but the host is hammered by interrupts on GPIO 3; still trying to figure out why. Sponsored by: Gateworks (2358 board w/ GPS chip) Modified: projects/cambria/sys/arm/conf/CAMBRIA projects/cambria/sys/arm/conf/CAMBRIA.hints projects/cambria/sys/arm/xscale/ixp425/ixp425.c projects/cambria/sys/arm/xscale/ixp425/uart_bus_ixp425.c projects/cambria/sys/dev/uart/uart.h projects/cambria/sys/dev/uart/uart_bus.h projects/cambria/sys/dev/uart/uart_bus_acpi.c projects/cambria/sys/dev/uart/uart_bus_ebus.c projects/cambria/sys/dev/uart/uart_bus_isa.c projects/cambria/sys/dev/uart/uart_bus_mbus.c projects/cambria/sys/dev/uart/uart_bus_ocp.c projects/cambria/sys/dev/uart/uart_bus_pccard.c projects/cambria/sys/dev/uart/uart_bus_pci.c projects/cambria/sys/dev/uart/uart_bus_puc.c projects/cambria/sys/dev/uart/uart_bus_scc.c projects/cambria/sys/dev/uart/uart_core.c projects/cambria/sys/dev/uart/uart_dev_ns8250.c projects/cambria/sys/dev/uart/uart_if.m Modified: projects/cambria/sys/arm/conf/CAMBRIA ============================================================================== --- projects/cambria/sys/arm/conf/CAMBRIA Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/arm/conf/CAMBRIA Wed Feb 25 00:58:08 2009 (r189021) @@ -41,7 +41,7 @@ options KDB options DDB #Enable the kernel debugger options INVARIANTS #Enable calls of extra sanity checking options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS -#options WITNESS #Enable checks to detect deadlocks and cycles +options WITNESS #Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed #options DIAGNOSTIC Modified: projects/cambria/sys/arm/conf/CAMBRIA.hints ============================================================================== --- projects/cambria/sys/arm/conf/CAMBRIA.hints Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/arm/conf/CAMBRIA.hints Wed Feb 25 00:58:08 2009 (r189021) @@ -14,17 +14,19 @@ hint.uart.0.ier_rxbits=0x5d # NB: need U # NB: no UART1 on ixp435 # optional GPS serial port -#hint.uart.1.at="ixp0" +hint.uart.1.at="ixp0" hint.uart.1.addr=0x53fc0000 hint.uart.1.irq=20 hint.uart.1.flags=0x10 hint.uart.1.rclk=1843200 +hint.uart.1.rwdelay=2 # optional RS485 serial port #hint.uart.2.at="ixp0" #hint.uart.2.addr=0x53f80000 #hint.uart.2.irq=21 #hint.uart.2.flags=0x10 #hint.uart.2.rclk=1843200 +#hint.uart.2.rwdelay=2 # NPE Hardware Queue Manager hint.ixpqmgr.0.at="ixp0" Modified: projects/cambria/sys/arm/xscale/ixp425/ixp425.c ============================================================================== --- projects/cambria/sys/arm/xscale/ixp425/ixp425.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/arm/xscale/ixp425/ixp425.c Wed Feb 25 00:58:08 2009 (r189021) @@ -36,6 +36,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_ddb.h" + #define _ARM32_BUS_DMA_PRIVATE #include <sys/param.h> #include <sys/systm.h> @@ -95,20 +97,59 @@ bus_dma_get_range_nb(void) return (0); } -static __inline u_int32_t -ixp425_irq2gpio_bit(int irq) -{ +static const uint8_t int2gpio[32] __attribute__ ((aligned(32))) = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* INT#0 -> INT#5 */ + 0x00, 0x01, /* GPIO#0 -> GPIO#1 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* INT#8 -> INT#13 */ + 0xff, 0xff, 0xff, 0xff, 0xff, /* INT#14 -> INT#18 */ + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* GPIO#2 -> GPIO#7 */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, /* GPIO#8 -> GPIO#12 */ + 0xff, 0xff /* INT#30 -> INT#31 */ +}; + +#ifdef DDB +#include <ddb/ddb.h> - static const uint8_t int2gpio[32] __attribute__ ((aligned(32))) = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* INT#0 -> INT#5 */ - 0x00, 0x01, /* GPIO#0 -> GPIO#1 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* INT#8 -> INT#13 */ - 0xff, 0xff, 0xff, 0xff, 0xff, /* INT#14 -> INT#18 */ - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* GPIO#2 -> GPIO#7 */ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, /* GPIO#8 -> GPIO#12 */ - 0xff, 0xff /* INT#30 -> INT#31 */ +DB_SHOW_COMMAND(gpio, db_show_gpio) +{ + static const char *itype[8] = { + [GPIO_TYPE_ACT_HIGH] = "act-high", + [GPIO_TYPE_ACT_LOW] = "act-low", + [GPIO_TYPE_EDG_RISING] = "edge-rising", + [GPIO_TYPE_EDG_FALLING] = "edge-falling", + [GPIO_TYPE_TRANSITIONAL]= "transitional", + [5] = "type-5", [6] = "type-6", [7] = "type-7" }; + uint32_t gpoutr = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOUTR); + uint32_t gpoer = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPOER); + uint32_t gpinr = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPINR); + uint32_t gpit1r = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPIT1R); + uint32_t gpit2r = GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPIT2R); + int i, j; + + db_printf("GPOUTR %08x GPOER %08x GPINR %08x GPISR %08x\n", + gpoutr, gpoer, gpinr, + GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPISR)); + db_printf("GPIT1R %08x GPIT2R %08x GPCLKR %08x\n", + gpit1r, gpit2r, GPIO_CONF_READ_4(ixp425_softc, IXP425_GPIO_GPCLKR)); + for (i = 0; i < 16; i++) { + db_printf("[%2d] out %u in %u %-3s", i, + (gpoutr>>i)&1, (gpinr>>i)&1, (gpoer>>i)&1 ? "in" : "out"); + for (j = 0; j < 32; j++) + if (int2gpio[j] == i) { + db_printf(" irq %2u %s", j, itype[ + (((i & 8) ? gpit2r : gpit1r) >> (3*(i&7))) + & 7]); + break; + } + db_printf("\n"); + } +} +#endif +static __inline u_int32_t +ixp425_irq2gpio_bit(int irq) +{ return (1U << int2gpio[irq]); } @@ -205,7 +246,6 @@ ixp425_attach(device_t dev) { struct ixp425_softc *sc; -bootverbose = 1; /*XXX*/ device_printf(dev, "%b\n", ixp4xx_read_feature_bits(), EXP_FCTRL_BITS); sc = device_get_softc(dev); @@ -254,6 +294,27 @@ bootverbose = 1; /*XXX*/ if (bus_space_map(sc->sc_iot, IXP425_EXP_HWBASE, IXP425_EXP_SIZE, 0, &sc->sc_exp_ioh)) panic("%s: unable to map Expansion Bus registers", __func__); + if (cpu_is_ixp43x()) { + uint32_t cs3 = EXP_BUS_READ_4(sc, EXP_TIMING_CS3_OFFSET); + /* XXX force slowest possible timings and byte mode */ + EXP_BUS_WRITE_4(sc, EXP_TIMING_CS3_OFFSET, + cs3 | (EXP_T1|EXP_T2|EXP_T3|EXP_T4|EXP_T5) | EXP_BYTE_EN); + if (bootverbose) + device_printf(dev, + "EXP_TIMING_CS3_OFFSET 0x%x => 0x%x\n", + cs3, EXP_BUS_READ_4(sc, EXP_TIMING_CS3_OFFSET)); + + /* XXX force GPIO 3 for GPS uart */ + if (bootverbose) + device_printf(dev, "set gpio 3 edge-rising\n"); + GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER, + GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER) | (1<<3)); + /* set interrupt type */ + GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(3), + (GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(3)) &~ + GPIO_TYPE(3, GPIO_TYPE_MASK)) | + GPIO_TYPE(3, GPIO_TYPE_EDG_RISING)); + } bus_generic_probe(dev); bus_generic_attach(dev); @@ -316,46 +377,83 @@ ixp425_read_ivar(device_t bus, device_t } /* - * NB: This table handles P->V translations for regions mapped - * through bus_alloc_resource. Anything done with bus_space_map - * is handled elsewhere and does not require an entry here. + * NB: This table handles P->V translations for regions setup with + * static mappings in initarm. This is used solely for calls to + * bus_alloc_resource_any; anything done with bus_space_map is + * handled elsewhere and does not require an entry here. * - * XXX getvbase is also used by uart_cpu_getdev (hence public) + * XXX this table is also used by uart_cpu_getdev via getvbase + * (hence the public api) */ -static const struct { +struct hwvtrans { uint32_t hwbase; uint32_t size; uint32_t vbase; -} hwvtrans[] = { - { IXP425_IO_HWBASE, IXP425_IO_SIZE, IXP425_IO_VBASE }, - { IXP425_PCI_HWBASE, IXP425_PCI_SIZE, IXP425_PCI_VBASE }, - { IXP425_PCI_MEM_HWBASE,IXP425_PCI_MEM_SIZE, IXP425_PCI_MEM_VBASE }, - { IXP425_EXP_BUS_CS0_HWBASE, IXP425_EXP_BUS_CS0_SIZE, - IXP425_EXP_BUS_CS0_VBASE }, - /* NB: needed only for uart_cpu_getdev */ - { IXP425_UART0_HWBASE, IXP425_REG_SIZE, IXP425_UART0_VBASE }, - { IXP425_UART1_HWBASE, IXP425_REG_SIZE, IXP425_UART1_VBASE }, - /* NB: need for ixp435 ehci controllers */ - { IXP435_USB1_HWBASE, IXP435_USB1_SIZE, IXP435_USB1_VBASE }, - { IXP435_USB2_HWBASE, IXP435_USB2_SIZE, IXP435_USB2_VBASE }, - /* NB: need for optional GPS on Cambria boards */ - { CAMBRIA_GPS_HWBASE, IXP425_REG_SIZE, CAMBRIA_GPS_VBASE }, - { CAMBRIA_RS485_HWBASE, IXP425_REG_SIZE, CAMBRIA_RS485_VBASE }, + int isa4x; /* XXX needs special bus space tag */ }; -int -getvbase(uint32_t hwbase, uint32_t size, uint32_t *vbase) +static const struct hwvtrans * +gethwvtrans(uint32_t hwbase, uint32_t size) { + static const struct hwvtrans hwvtrans[] = { +#if 0 + { .hwbase = IXP425_IO_HWBASE, + .size = IXP425_IO_SIZE, + .vbase = IXP425_IO_VBASE }, +#endif + /* NB: needed only for uart_cpu_getdev */ + { .hwbase = IXP425_UART0_HWBASE, + .size = IXP425_REG_SIZE, + .vbase = IXP425_UART0_VBASE, + .isa4x = 1 }, + { .hwbase = IXP425_UART1_HWBASE, + .size = IXP425_REG_SIZE, + .vbase = IXP425_UART1_VBASE, + .isa4x = 1 }, + { .hwbase = IXP425_PCI_HWBASE, + .size = IXP425_PCI_SIZE, + .vbase = IXP425_PCI_VBASE }, + { .hwbase = IXP425_PCI_MEM_HWBASE, + .size = IXP425_PCI_MEM_SIZE, + .vbase = IXP425_PCI_MEM_VBASE }, + { .hwbase = IXP425_EXP_BUS_CS0_HWBASE, + .size = IXP425_EXP_BUS_CS0_SIZE, + .vbase = IXP425_EXP_BUS_CS0_VBASE }, + /* NB: needed for ixp435 ehci controllers */ + { .hwbase = IXP435_USB1_HWBASE, + .size = IXP435_USB1_SIZE, + .vbase = IXP435_USB1_VBASE }, + { .hwbase = IXP435_USB2_HWBASE, + .size = IXP435_USB2_SIZE, + .vbase = IXP435_USB2_VBASE }, + { .hwbase = CAMBRIA_GPS_HWBASE, + .size = CAMBRIA_GPS_SIZE, + .vbase = CAMBRIA_GPS_VBASE }, + { .hwbase = CAMBRIA_RS485_HWBASE, + .size = CAMBRIA_RS485_SIZE, + .vbase = CAMBRIA_RS485_VBASE }, + }; int i; for (i = 0; i < sizeof hwvtrans / sizeof *hwvtrans; i++) { if (hwbase >= hwvtrans[i].hwbase && - hwbase + size <= hwvtrans[i].hwbase + hwvtrans[i].size) { - *vbase = hwbase - hwvtrans[i].hwbase + hwvtrans[i].vbase; - return (0); - } + hwbase + size <= hwvtrans[i].hwbase + hwvtrans[i].size) + return &hwvtrans[i]; } - return (ENOENT); + return NULL; +} + +/* XXX for uart_cpu_getdev */ +int +getvbase(uint32_t hwbase, uint32_t size, uint32_t *vbase) +{ + const struct hwvtrans *hw; + + hw = gethwvtrans(hwbase, size); + if (hw == NULL) + return (ENOENT); + *vbase = hwbase - hw->hwbase + hw->vbase; + return (0); } static struct resource * @@ -363,9 +461,10 @@ ixp425_alloc_resource(device_t dev, devi u_long start, u_long end, u_long count, u_int flags) { struct ixp425_softc *sc = device_get_softc(dev); + const struct hwvtrans *vtrans; struct rman *rmanp; struct resource *rv; - uint32_t vbase, addr; + uint32_t addr; int irq; switch (type) { @@ -385,11 +484,27 @@ ixp425_alloc_resource(device_t dev, devi /* override per hints */ if (BUS_READ_IVAR(dev, child, IXP425_IVAR_ADDR, &addr) == 0) { start = addr; - end = start + 0x1000; /* XXX */ - } - if (getvbase(start, end - start, &vbase) != 0) { + /* XXX use nominal window to check for mapping */ + vtrans = gethwvtrans(start, 0x1000); + if (vtrans != NULL) { + /* + * Assign the entire mapped region; this may + * not be correct but without more info from + * the caller we cannot tell. + */ + end = start + vtrans->size - + (start - vtrans->hwbase); + if (bootverbose) + device_printf(child, + "%s: assign 0x%lx:0x%lx%s\n", + __func__, start, end-start, + vtrans->isa4x ? " A4X" : ""); + } + } else + vtrans = gethwvtrans(start, end - start); + if (vtrans == NULL) { /* likely means above table needs to be updated */ - device_printf(dev, "%s: no mapping for 0x%lx:0x%lx\n", + device_printf(child, "%s: no mapping for 0x%lx:0x%lx\n", __func__, start, end-start); return NULL; } @@ -397,12 +512,11 @@ ixp425_alloc_resource(device_t dev, devi flags, child); if (rv != NULL) { rman_set_rid(rv, *rid); - if (strcmp(device_get_name(child), "uart") == 0 -&& device_get_unit(child) == 0) /* XXX */ + if (vtrans->isa4x) rman_set_bustag(rv, &ixp425_a4x_bs_tag); else rman_set_bustag(rv, sc->sc_iot); - rman_set_bushandle(rv, vbase); + rman_set_bushandle(rv, vtrans->vbase); } break; default: Modified: projects/cambria/sys/arm/xscale/ixp425/uart_bus_ixp425.c ============================================================================== --- projects/cambria/sys/arm/xscale/ixp425/uart_bus_ixp425.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/arm/xscale/ixp425/uart_bus_ixp425.c Wed Feb 25 00:58:08 2009 (r189021) @@ -68,13 +68,17 @@ static int uart_ixp425_probe(device_t dev) { struct uart_softc *sc; - u_int rclk; + int unit = device_get_unit(dev); + u_int rclk, rwdelay; sc = device_get_softc(dev); sc->sc_class = &uart_ns8250_class; - if (resource_int_value("uart", device_get_unit(dev), "rclk", &rclk)) + if (resource_int_value("uart", unit, "rclk", &rclk)) rclk = IXP425_UART_FREQ; + if (resource_int_value("uart", unit, "rwdelay", &rwdelay)) + rwdelay = 0; if (bootverbose) - device_printf(dev, "rclk %u\n", rclk); - return uart_bus_probe(dev, 0, rclk, 0, 0); + device_printf(dev, "rclk %u rwdelay %u\n", rclk, rwdelay); + + return uart_bus_probe(dev, 0, rclk, 0, 0, rwdelay); } Modified: projects/cambria/sys/dev/uart/uart.h ============================================================================== --- projects/cambria/sys/dev/uart/uart.h Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart.h Wed Feb 25 00:58:08 2009 (r189021) @@ -41,14 +41,26 @@ struct uart_bas { u_int chan; u_int rclk; u_int regshft; + u_int rw_delay; }; #define uart_regofs(bas, reg) ((reg) << (bas)->regshft) -#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 uint8_t +uart_getreg(struct uart_bas *bas, bus_size_t reg) +{ + if (bas->rw_delay) + DELAY(bas->rw_delay); + return bus_space_read_1(bas->bst, bas->bsh, uart_regofs(bas, reg)); +} + +static __inline void +uart_setreg(struct uart_bas *bas, bus_size_t reg, uint8_t v) +{ + if (bas->rw_delay) + DELAY(bas->rw_delay); + bus_space_write_1(bas->bst, bas->bsh, uart_regofs(bas, reg), v); +} /* * XXX we don't know the length of the bus space address range in use by Modified: projects/cambria/sys/dev/uart/uart_bus.h ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus.h Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus.h Wed Feb 25 00:58:08 2009 (r189021) @@ -138,7 +138,8 @@ int uart_bus_attach(device_t dev); int uart_bus_detach(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 rclk, int rid, int chan, + int rwdelay); int uart_bus_sysdev(device_t dev); int uart_tty_attach(struct uart_softc *); Modified: projects/cambria/sys/dev/uart/uart_bus_acpi.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus_acpi.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus_acpi.c Wed Feb 25 00:58:08 2009 (r189021) @@ -73,7 +73,7 @@ uart_acpi_probe(device_t dev) 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. */ Modified: projects/cambria/sys/dev/uart/uart_bus_ebus.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus_ebus.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus_ebus.c Wed Feb 25 00:58:08 2009 (r189021) @@ -97,7 +97,7 @@ uart_ebus_probe(device_t 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); Modified: projects/cambria/sys/dev/uart/uart_bus_isa.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus_isa.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus_isa.c Wed Feb 25 00:58:08 2009 (r189021) @@ -182,7 +182,7 @@ uart_isa_probe(device_t dev) #else sc->sc_class = &uart_ns8250_class; #endif - 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); Modified: projects/cambria/sys/dev/uart/uart_bus_mbus.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus_mbus.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus_mbus.c Wed Feb 25 00:58:08 2009 (r189021) @@ -73,7 +73,7 @@ uart_mbus_probe(device_t dev) sc = device_get_softc(dev); sc->sc_class = &uart_ns8250_class; - status = uart_bus_probe(dev, 2, get_tclk(), 0, 0); + status = uart_bus_probe(dev, 2, get_tclk(), 0, 0, 0); return(status); } Modified: projects/cambria/sys/dev/uart/uart_bus_ocp.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus_ocp.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus_ocp.c Wed Feb 25 00:58:08 2009 (r189021) @@ -82,7 +82,7 @@ uart_ocp_probe(device_t dev) if (BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_CLOCK, &clock)) clock = 0; - return (uart_bus_probe(dev, 0, clock, 0, 0)); + return (uart_bus_probe(dev, 0, clock, 0, 0, 0)); } DRIVER_MODULE(uart, ocpbus, uart_ocp_driver, uart_devclass, 0, 0); Modified: projects/cambria/sys/dev/uart/uart_bus_pccard.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus_pccard.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus_pccard.c Wed Feb 25 00:58:08 2009 (r189021) @@ -91,7 +91,7 @@ uart_pccard_attach(device_t dev) 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)); Modified: projects/cambria/sys/dev/uart/uart_bus_pci.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus_pci.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus_pci.c Wed Feb 25 00:58:08 2009 (r189021) @@ -154,7 +154,7 @@ uart_pci_probe(device_t dev) match: if (id->desc) device_set_desc(dev, id->desc); - return (uart_bus_probe(dev, 0, id->rclk, id->rid, 0)); + return (uart_bus_probe(dev, 0, id->rclk, id->rid, 0, 0)); } DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, 0, 0); Modified: projects/cambria/sys/dev/uart/uart_bus_puc.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus_puc.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus_puc.c Wed Feb 25 00:58:08 2009 (r189021) @@ -81,7 +81,7 @@ uart_puc_probe(device_t dev) 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, rclk, 0, 0, 0)); } DRIVER_MODULE(uart, puc, uart_puc_driver, uart_devclass, 0, 0); Modified: projects/cambria/sys/dev/uart/uart_bus_scc.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_bus_scc.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_bus_scc.c Wed Feb 25 00:58:08 2009 (r189021) @@ -112,7 +112,7 @@ uart_scc_probe(device_t dev) 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, cl, 0, ch, 0)); } DRIVER_MODULE(uart, scc, uart_scc_driver, uart_devclass, 0, 0); Modified: projects/cambria/sys/dev/uart/uart_core.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_core.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_core.c Wed Feb 25 00:58:08 2009 (r189021) @@ -319,7 +319,8 @@ uart_bus_sysdev(device_t dev) } int -uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan) +uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan, + int rwdelay) { struct uart_softc *sc; struct uart_devinfo *sysdev; @@ -379,6 +380,7 @@ uart_bus_probe(device_t dev, int regshft sc->sc_bas.chan = chan; sc->sc_bas.regshft = regshft; sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk; + sc->sc_bas.rw_delay = rwdelay; SLIST_FOREACH(sysdev, &uart_sysdevs, next) { if (chan == sysdev->bas.chan && Modified: projects/cambria/sys/dev/uart/uart_dev_ns8250.c ============================================================================== --- projects/cambria/sys/dev/uart/uart_dev_ns8250.c Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_dev_ns8250.c Wed Feb 25 00:58:08 2009 (r189021) @@ -385,6 +385,8 @@ struct uart_class uart_ns8250_class = { i = (i & s) ? (i & ~s) | d : i; \ } +static struct uart_softc *ns8250sc[4]; + static int ns8250_bus_attach(struct uart_softc *sc) { @@ -446,6 +448,8 @@ ns8250_bus_attach(struct uart_softc *sc) ns8250->ier |= ns8250->ier_rxbits; uart_setreg(bas, REG_IER, ns8250->ier); uart_barrier(bas); + +ns8250sc[device_get_unit(sc->sc_dev)] = sc; return (0); } @@ -580,17 +584,68 @@ ns8250_bus_ioctl(struct uart_softc *sc, return (error); } +static struct { + int count; + int nopend; + int rxrdy; + int overrun; + int ibreak; + int txidle; + int sigchg; +} istats[4]; + +#include "opt_ddb.h" +#ifdef DDB +#include <ddb/ddb.h> +#include <ddb/db_sym.h> + +DB_SHOW_COMMAND(istats, db_show_istats) +{ + int i; + struct uart_softc *sc; + + for (i = 0; i < 4; i++) { + if (istats[i].count == 0) + continue; + db_printf("[%d] %u nopend %u rxrdy %u overrun %u break %u txidle %u sigchg %u\n", + i, istats[i].count, istats[i].nopend, + istats[i].rxrdy, istats[i].overrun, istats[i].ibreak, + istats[i].txidle, istats[i].sigchg); + db_printf(" "); + sc = ns8250sc[i]; + if (sc != NULL) { + struct uart_bas *bas = &sc->sc_bas; + uart_lock(sc->sc_hwmtx); + db_printf("ier %x iir %x lcr %x mcr %x lsr %x " + "msr %x efr %x\n", + uart_getreg(bas, REG_IER), + uart_getreg(bas, REG_IIR), + uart_getreg(bas, REG_LCR), + uart_getreg(bas, REG_MCR), + uart_getreg(bas, REG_LSR), + uart_getreg(bas, REG_MSR), + uart_getreg(bas, REG_EFR)); + uart_unlock(sc->sc_hwmtx); + } else + db_printf("<no softc>\n"); + } +} +#endif + static int ns8250_bus_ipend(struct uart_softc *sc) { struct uart_bas *bas; int ipend; uint8_t iir, lsr; +int unit = device_get_unit(sc->sc_dev); bas = &sc->sc_bas; uart_lock(sc->sc_hwmtx); +istats[unit].count++; iir = uart_getreg(bas, REG_IIR); if (iir & IIR_NOPEND) { +istats[unit].nopend++; uart_unlock(sc->sc_hwmtx); return (0); } @@ -598,18 +653,27 @@ ns8250_bus_ipend(struct uart_softc *sc) if (iir & IIR_RXRDY) { lsr = uart_getreg(bas, REG_LSR); uart_unlock(sc->sc_hwmtx); - if (lsr & LSR_OE) + if (lsr & LSR_OE) { ipend |= SER_INT_OVERRUN; - if (lsr & LSR_BI) +istats[unit].overrun++; + } + if (lsr & LSR_BI) { ipend |= SER_INT_BREAK; - if (lsr & LSR_RXRDY) +istats[unit].ibreak++; + } + if (lsr & LSR_RXRDY) { ipend |= SER_INT_RXREADY; +istats[unit].rxrdy++; + } } else { uart_unlock(sc->sc_hwmtx); - if (iir & IIR_TXRDY) + if (iir & IIR_TXRDY) { ipend |= SER_INT_TXIDLE; - else +istats[unit].txidle++; + } else { ipend |= SER_INT_SIGCHG; +istats[unit].sigchg++; + } } return ((sc->sc_leaving) ? 0 : ipend); } @@ -646,7 +710,7 @@ ns8250_bus_probe(struct uart_softc *sc) mcr = MCR_IE; if (sc->sc_sysdev == NULL) { /* By using ns8250_init() we also set DTR and RTS. */ - ns8250_init(bas, 115200, 8, 1, UART_PARITY_NONE); + ns8250_init(bas, 4800, 8, 1, UART_PARITY_NONE); } else mcr |= MCR_DTR | MCR_RTS; @@ -778,12 +842,15 @@ ns8250_bus_probe(struct uart_softc *sc) return (0); } +#include <sys/kdb.h> + static int ns8250_bus_receive(struct uart_softc *sc) { struct uart_bas *bas; int xc; uint8_t lsr; +int nfe = 0, npe = 0, nrx = 0; bas = &sc->sc_bas; uart_lock(sc->sc_hwmtx); @@ -794,11 +861,16 @@ ns8250_bus_receive(struct uart_softc *sc break; } xc = uart_getreg(bas, REG_DATA); - if (lsr & LSR_FE) + if (lsr & LSR_FE) { xc |= UART_STAT_FRAMERR; - if (lsr & LSR_PE) + nfe++; + } + if (lsr & LSR_PE) { xc |= UART_STAT_PARERR; + npe++; + } uart_rx_put(sc, xc); + nrx++; lsr = uart_getreg(bas, REG_LSR); } /* Discard everything left in the Rx FIFO. */ @@ -808,6 +880,12 @@ ns8250_bus_receive(struct uart_softc *sc lsr = uart_getreg(bas, REG_LSR); } uart_unlock(sc->sc_hwmtx); +if (nfe || npe) device_printf(sc->sc_dev, "%s: nfe %d npe %d\n", __func__, nfe, npe); +if (nrx) { + device_printf(sc->sc_dev, "%s: nrx %d\n", __func__, nrx); + if (device_get_unit(sc->sc_dev) == 0) + kdb_enter("help", __func__); +} return (0); } Modified: projects/cambria/sys/dev/uart/uart_if.m ============================================================================== --- projects/cambria/sys/dev/uart/uart_if.m Tue Feb 24 23:34:02 2009 (r189020) +++ projects/cambria/sys/dev/uart/uart_if.m Wed Feb 25 00:58:08 2009 (r189021) @@ -29,6 +29,7 @@ #include <sys/lock.h> #include <sys/mutex.h> #include <sys/bus.h> +#include <sys/systm.h> #include <machine/bus.h> #include <dev/uart/uart.h> #include <dev/uart/uart_bus.h>
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902250058.n1P0w8bg080802>