svn commit: r189021 - in projects/cambria/sys: arm/conf
arm/xscale/ixp425 dev/uart
Sam Leffler
sam at FreeBSD.org
Tue Feb 24 16:58:09 PST 2009
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>
More information about the svn-src-projects
mailing list