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