progress on the adi pronghorn metro board

John Hay jhay at meraka.org.za
Mon Mar 26 07:08:07 UTC 2007


Ok, here is my second try. It use ivars to get the values. Probably not
perfect yet, but I would appreciate feedback on things that should be
done differently or moved somewhere else.

I still need to build a driver for the iic max6652 temperature/voltage
device which is found on the Pronghorn Metro. I must just first have
a look at what Warner did. What I would also like to have is a mechanism
to disable a iic device so that it isn't even probed. Something like the
hints disabled variable. Preferably the board detect function should be
setting the iic devices on and off according to which board it detects.

During my traversals in ixp425.c in ixp425_setup_intr() I saw the piece
inside "if (flags & INTR_TYPE_TTY)". Is that still needed? I deleted it
and did not see any bad side effects. I also stuffed a printf in there
and the uart interrupts was already setup by the time it gets there.
The code looks like this:

#########################
        if (flags & INTR_TYPE_TTY) {
                /* XXX: wrong. */
                if (device_get_unit(dev) == 0)
                        rman_set_start(ires, IXP425_INT_UART0);
                else
                        rman_set_start(ires, IXP425_INT_UART1);
                rman_set_end(ires, rman_get_start(ires));
        }
#########################

John
-- 
John Hay -- John.Hay at meraka.csir.co.za / jhay at FreeBSD.org


Index: avila_ata.c
===================================================================
RCS file: /home/ncvs/src/sys/arm/xscale/ixp425/avila_ata.c,v
retrieving revision 1.3
diff -u -r1.3 avila_ata.c
--- avila_ata.c	14 Mar 2007 18:05:04 -0000	1.3
+++ avila_ata.c	25 Mar 2007 08:32:02 -0000
@@ -104,14 +104,19 @@
 static int
 ata_avila_probe(device_t dev)
 {
-	struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
 
 	/* XXX any way to check? */
-	if (EXP_BUS_READ_4(sa, EXP_TIMING_CS2_OFFSET) != 0)
+	switch (ixp425_get_ivar(dev, IXP425_IVAR_BOARD_TYPE)) {
+	case BOARD_AVILA:
 		device_set_desc_copy(dev, "Gateworks Avila IDE/CF Controller");
-	else
+		break;
+	case BOARD_PRONGHORN:
 		device_set_desc_copy(dev,
 		    "ADI Pronghorn Metro IDE/CF Controller");
+		break;
+	default:
+		return ENXIO;
+	}
 	return 0;
 }
 
@@ -120,43 +125,25 @@
 {
 	struct ata_avila_softc *sc = device_get_softc(dev);
 	struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
-	u_int32_t alt_t_off, board_type, ide_gpin, ide_irq;
+	u_int32_t alt_t_off, ide_gpin, ide_irq;
 
-	board_type = 0;
 	sc->sc_dev = dev;
 	/* NB: borrow from parent */
 	sc->sc_iot = sa->sc_iot;
 	sc->sc_exp_ioh = sa->sc_exp_ioh;
-	if (EXP_BUS_READ_4(sc, EXP_TIMING_CS2_OFFSET) != 0)
-		board_type = 1;		/* Avila board */
 
-	if (board_type == 1) {
-		if (bus_space_map(sc->sc_iot, IXP425_EXP_BUS_CS1_HWBASE,
-		    IXP425_EXP_BUS_CS1_SIZE, 0, &sc->sc_ioh))
-			panic("%s: unable to map Expansion Bus CS1 window",
-			    __func__);
-		if (bus_space_map(sc->sc_iot, IXP425_EXP_BUS_CS2_HWBASE,
-		    IXP425_EXP_BUS_CS2_SIZE, 0, &sc->sc_alt_ioh))
-			panic("%s: unable to map Expansion Bus CS2 window",
-			    __func__);
-		ide_gpin = AVILA_IDE_GPIN;
-		ide_irq = AVILA_IDE_IRQ;
-		sc->sc_16bit_off = EXP_TIMING_CS1_OFFSET;
-		alt_t_off = EXP_TIMING_CS2_OFFSET;
-	} else {
-		if (bus_space_map(sc->sc_iot, IXP425_EXP_BUS_CS3_HWBASE,
-		    IXP425_EXP_BUS_CS3_SIZE, 0, &sc->sc_ioh))
-			panic("%s: unable to map Expansion Bus CS3 window",
-			    __func__);
-		if (bus_space_map(sc->sc_iot, IXP425_EXP_BUS_CS4_HWBASE,
-		    IXP425_EXP_BUS_CS4_SIZE, 0, &sc->sc_alt_ioh))
-			panic("%s: unable to map Expansion Bus CS4 window",
-			    __func__);
-		ide_gpin = PRONGHORN_IDE_GPIN;
-		ide_irq = PRONGHORN_IDE_IRQ;
-		sc->sc_16bit_off = EXP_TIMING_CS3_OFFSET;
-		alt_t_off = EXP_TIMING_CS4_OFFSET;
-	}
+	if (bus_space_map(sc->sc_iot, ixp425_get_ivar(dev, IXP425_IVAR_ATA_CS0),
+	    ixp425_get_ivar(dev, IXP425_IVAR_ATA_SIZE), 0, &sc->sc_ioh))
+		panic("%s: unable to map ATA CS0 window",
+		    __func__);
+	if (bus_space_map(sc->sc_iot, ixp425_get_ivar(dev, IXP425_IVAR_ATA_CS1),
+	    ixp425_get_ivar(dev, IXP425_IVAR_ATA_SIZE), 0, &sc->sc_alt_ioh))
+		panic("%s: unable to map ATA CS1 window",
+		    __func__);
+	ide_gpin = ixp425_get_ivar(dev, IXP425_IVAR_ATA_INT_PIN);
+	ide_irq = ixp425_get_ivar(dev, IXP425_IVAR_ATA_INT);
+	sc->sc_16bit_off = ixp425_get_ivar(dev, IXP425_IVAR_ATA_CS0_REG);
+	alt_t_off = ixp425_get_ivar(dev, IXP425_IVAR_ATA_CS1_REG);
 
 	/*
 	 * Craft special resource for ATA bus space ops
Index: avila_led.c
===================================================================
RCS file: /home/ncvs/src/sys/arm/xscale/ixp425/avila_led.c,v
retrieving revision 1.1
diff -u -r1.1 avila_led.c
--- avila_led.c	22 Nov 2006 12:57:17 -0000	1.1
+++ avila_led.c	25 Mar 2007 07:19:39 -0000
@@ -66,6 +66,8 @@
 static int
 led_avila_probe(device_t dev)
 {
+	if (ixp425_get_ivar(dev, IXP425_IVAR_BOARD_TYPE) != BOARD_AVILA)
+		return ENXIO;
 	device_set_desc(dev, "Gateworks Avila GPIO connected LED");
 	return (0);
 }
Index: ixdp425_pci.c
===================================================================
RCS file: /home/ncvs/src/sys/arm/xscale/ixp425/ixdp425_pci.c,v
retrieving revision 1.1
diff -u -r1.1 ixdp425_pci.c
--- ixdp425_pci.c	19 Nov 2006 23:55:23 -0000	1.1
+++ ixdp425_pci.c	25 Mar 2007 18:45:21 -0000
@@ -56,59 +56,71 @@
 {
 	struct ixp425_softc *sc = device_get_softc(device_get_parent(dev));
 	struct ixppcib_softc *pci_sc = device_get_softc(dev);
-	uint32_t reg;
+	uint32_t inta, intb, intc, intd, reg;
 
 	
 	/* PCI Reset Assert */
 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
-	reg &= ~(1U << GPIO_PCI_RESET);
-	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg & ~(1U << GPIO_PCI_RESET));
+	reg &= ~(1U << ixp425_get_ivar(dev, IXP425_IVAR_PCI_RESET));
+	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
 
 	/* PCI Clock Disable */
 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
 	reg &= ~GPCLKR_MUX14;
 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg & ~GPCLKR_MUX14);
 
+	/* The ixp425 do not support 66MHz pci clock. */
+	if (ixp425_get_ivar(dev, IXP425_IVAR_PCI_CLK66_EN) != -1) {
+        	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
+		reg &= ~(1U << ixp425_get_ivar(dev, IXP425_IVAR_PCI_CLK66_EN));
+		GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
+	}
+
 	/*
 	 * set GPIO Direction
-	 *	Output: PCI_CLK, PCI_RESET
+	 *	Output: (PCI_CLK66_EN), PCI_CLK, PCI_RESET
 	 *	Input:  PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD
 	 */
 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOER);
-	reg &= ~(1U << GPIO_PCI_CLK);
-	reg &= ~(1U << GPIO_PCI_RESET);
-	reg |= ((1U << GPIO_PCI_INTA) | (1U << GPIO_PCI_INTB) |
-		(1U << GPIO_PCI_INTC) | (1U << GPIO_PCI_INTD));
+	if (ixp425_get_ivar(dev, IXP425_IVAR_PCI_CLK66_EN) != -1)
+		 reg &= ~(1U << ixp425_get_ivar(dev, IXP425_IVAR_PCI_CLK66_EN));
+	reg &= ~(1U << ixp425_get_ivar(dev, IXP425_IVAR_PCI_CLK));
+	reg &= ~(1U << ixp425_get_ivar(dev, IXP425_IVAR_PCI_RESET));
+
+	inta = ixp425_get_ivar(dev, IXP425_IVAR_PCI_INTA);
+	intb = ixp425_get_ivar(dev, IXP425_IVAR_PCI_INTB);
+	intc = ixp425_get_ivar(dev, IXP425_IVAR_PCI_INTC);
+	intd = ixp425_get_ivar(dev, IXP425_IVAR_PCI_INTD);
+	reg |= ((1U << inta) | (1U << intb) | (1U << intc) | (1U << intd));
 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOER, reg);
 
 	/*
 	 * Set GPIO interrupt type
 	 * 	PCI_INT_A, PCI_INTB, PCI_INT_C, PCI_INT_D: Active Low
 	 */
-	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA));
-	reg &= ~GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_MASK);
-	reg |= GPIO_TYPE(GPIO_PCI_INTA, GPIO_TYPE_ACT_LOW);
-	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTA), reg);
-
-	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB));
-	reg &= ~GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_MASK);
-	reg |= GPIO_TYPE(GPIO_PCI_INTB, GPIO_TYPE_ACT_LOW);
-	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTB), reg);
-
-	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC));
-	reg &= ~GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_MASK);
-	reg |= GPIO_TYPE(GPIO_PCI_INTC, GPIO_TYPE_ACT_LOW);
-	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTC), reg);
-
-	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTD));
-	reg &= ~GPIO_TYPE(GPIO_PCI_INTD, GPIO_TYPE_MASK);
-	reg |= GPIO_TYPE(GPIO_PCI_INTD, GPIO_TYPE_ACT_LOW);
-	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(GPIO_PCI_INTD), reg);
+	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(inta));
+	reg &= ~GPIO_TYPE(inta, GPIO_TYPE_MASK);
+	reg |= GPIO_TYPE(inta, GPIO_TYPE_ACT_LOW);
+	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(inta), reg);
+
+	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(intb));
+	reg &= ~GPIO_TYPE(intb, GPIO_TYPE_MASK);
+	reg |= GPIO_TYPE(intb, GPIO_TYPE_ACT_LOW);
+	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(intb), reg);
+
+	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(intc));
+	reg &= ~GPIO_TYPE(intc, GPIO_TYPE_MASK);
+	reg |= GPIO_TYPE(intc, GPIO_TYPE_ACT_LOW);
+	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(intc), reg);
+
+	reg = GPIO_CONF_READ_4(sc, GPIO_TYPE_REG(intd));
+	reg &= ~GPIO_TYPE(intd, GPIO_TYPE_MASK);
+	reg |= GPIO_TYPE(intd, GPIO_TYPE_ACT_LOW);
+	GPIO_CONF_WRITE_4(sc, GPIO_TYPE_REG(intd), reg);
 
 	/* clear ISR */
 	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPISR,
-			  (1U << GPIO_PCI_INTA) | (1U << GPIO_PCI_INTB) |
-			  (1U << GPIO_PCI_INTC) | (1U << GPIO_PCI_INTD));
+	    (1U << inta) | (1U << intb) | (1U << intc) | (1U << intd));
 
 	/* wait 1ms to satisfy "minimum reset assertion time" of the PCI spec */
 	DELAY(1000);
@@ -119,7 +131,7 @@
 	/* PCI Clock Enable */
 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPCLKR);
 	reg |= GPCLKR_MUX14;
-	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg | GPCLKR_MUX14);
+	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPCLKR, reg);
 
 	/*
 	 * wait 100us to satisfy "minimum reset assertion time from clock stable
@@ -128,14 +140,21 @@
 	DELAY(100);
         /* PCI Reset deassert */
 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPOUTR);
-	reg |= 1U << GPIO_PCI_RESET;
-	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg | (1U << GPIO_PCI_RESET));
+	reg |= 1U << ixp425_get_ivar(dev, IXP425_IVAR_PCI_RESET);
+	GPIO_CONF_WRITE_4(sc, IXP425_GPIO_GPOUTR, reg);
 	pci_sc->sc_irq_rman.rm_type = RMAN_ARRAY;
 	pci_sc->sc_irq_rman.rm_descr = "IXP425 PCI IRQs";
-	CTASSERT(PCI_INT_D < PCI_INT_A);
-	/* XXX this overlaps the irq's setup in ixp425_attach */
+	/*
+	 * XXX this overlaps the irq's setup in ixp425_attach
+	 *
+	 * PCI irq's on the Pronghorn are not consecutive, so do
+	 * them one at a time.
+	 */
 	if (rman_init(&pci_sc->sc_irq_rman) != 0 ||
-	    rman_manage_region(&pci_sc->sc_irq_rman, PCI_INT_D, PCI_INT_A) != 0)
+	    rman_manage_region(&pci_sc->sc_irq_rman, inta, inta) != 0 ||
+	    rman_manage_region(&pci_sc->sc_irq_rman, intb, intb) != 0 ||
+	    rman_manage_region(&pci_sc->sc_irq_rman, intc, intc) != 0 ||
+	    rman_manage_region(&pci_sc->sc_irq_rman, intd, intd) != 0)
 		panic("ixp425_md_attach: failed to set up IRQ rman");
 }
 
@@ -145,23 +164,38 @@
 int
 ixp425_md_route_interrupt(device_t bridge, device_t device, int pin)
 {
-	static int ixp425_pci_table[IXP425_MAX_DEV][IXP425_MAX_LINE] =
-	{
-		{PCI_INT_A, PCI_INT_B, PCI_INT_C, PCI_INT_D},
-		{PCI_INT_B, PCI_INT_C, PCI_INT_D, PCI_INT_A},
-		{PCI_INT_C, PCI_INT_D, PCI_INT_A, PCI_INT_B},
-		{PCI_INT_D, PCI_INT_A, PCI_INT_B, PCI_INT_C},
-	};
-	int dev;
-	
+	static int ixp425_pci_table[IXP425_MAX_DEV][IXP425_MAX_LINE];
+	static int table_filled = 0;
+	int di, dev, li;
+
+	if (table_filled == 0) {
+		ixp425_pci_table[0][0] =
+		    ixp425_get_ivar(bridge, IXP425_IVAR_PCI_INTA);
+		ixp425_pci_table[0][1] =
+		    ixp425_get_ivar(bridge, IXP425_IVAR_PCI_INTB);
+		ixp425_pci_table[0][2] =
+		    ixp425_get_ivar(bridge, IXP425_IVAR_PCI_INTC);
+		ixp425_pci_table[0][3] =
+		    ixp425_get_ivar(bridge, IXP425_IVAR_PCI_INTD);
+		if (bootverbose)
+			device_printf(bridge, "irq list a %d, b %d, c %d, d %d\n",
+			    ixp425_pci_table[0][0], ixp425_pci_table[0][1],
+			    ixp425_pci_table[0][2], ixp425_pci_table[0][3]);
+		for (di = 1; di < IXP425_MAX_DEV; di++)
+			for (li = 0; li < IXP425_MAX_LINE; li++)
+				ixp425_pci_table[di][li] =
+				    ixp425_pci_table[0][(di + li) %
+				    IXP425_MAX_LINE];
+		table_filled = 1;
+	}
 	dev = pci_get_slot(device);
 	if (bootverbose)
 		device_printf(bridge, "routing pin %d for %s\n", pin,
 		    device_get_nameunit(device));
 	if (pin >= 1 && pin <= IXP425_MAX_LINE &&
-	    dev >= 1 && dev <= IXP425_MAX_DEV) {
+	    dev >= 1 && dev <= IXP425_MAX_DEV)
 		return (ixp425_pci_table[dev - 1][pin - 1]);
-	} else
+	else
 		printf("ixppcib: no mapping for %d/%d/%d\n",
 			pci_get_bus(device), dev, pci_get_function(device));
 
Index: ixp425.c
===================================================================
RCS file: /home/ncvs/src/sys/arm/xscale/ixp425/ixp425.c,v
retrieving revision 1.5
diff -u -r1.5 ixp425.c
--- ixp425.c	14 Mar 2007 19:03:07 -0000	1.5
+++ ixp425.c	25 Mar 2007 18:45:39 -0000
@@ -63,6 +63,8 @@
 static int	ixp425_probe(device_t);
 static void	ixp425_identify(driver_t *, device_t);
 static int	ixp425_attach(device_t);
+static void	*ixp425_get_board_type(void);
+static int	ixp425_read_ivar(device_t, device_t, int, uintptr_t *);
 
 static struct {
 	uint32_t	hwbase;
@@ -236,6 +238,8 @@
 	    rman_manage_region(&sc->sc_mem_rman, 0, ~0) != 0)
 		panic("ixp425_attach: failed to set up IRQ rman");
 
+	device_set_ivars(dev, ixp425_get_board_type());
+
 	device_add_child(dev, "pcib", 0);
 	device_add_child(dev, "ixpclk", 0);
 	device_add_child(dev, "ixpwdog", 0);
@@ -277,10 +281,10 @@
 	case SYS_RES_IRQ:
 		rmanp = &sc->sc_irq_rman;
 		if (isuart) {
-			if (device_get_unit(dev) == 0) 
-				start = IXP425_INT_UART0;
+			if (device_get_unit(dev) == 0)
+				start = ixp425_get_ivar(child, IXP425_IVAR_UARTCN_INT);
 			else
-				start = IXP425_INT_UART1;
+				start = ixp425_get_ivar(child, IXP425_IVAR_UARTALT_INT);
 			end = start;
 		}
 		break;
@@ -288,10 +292,10 @@
 	case SYS_RES_MEMORY:
 		rmanp = &sc->sc_mem_rman;
 		if (isuart) {
-			if (device_get_unit(dev) == 0) 
-				start = IXP425_UART0_HWBASE;
+			if (device_get_unit(dev) == 0)
+				start = ixp425_get_ivar(child, IXP425_IVAR_UARTCN_HWBASE);
 			else
-				start = IXP425_UART1_HWBASE;
+				start = ixp425_get_ivar(child, IXP425_IVAR_UARTALT_HWBASE);
 			end = start + 0x1000;
 		}
 		if (getvbase(start, end - start, &vbase))
@@ -323,14 +327,6 @@
 	uint32_t mask;
 	int i;
 
-	if (flags & INTR_TYPE_TTY) {
-		/* XXX: wrong. */
-		if (device_get_unit(dev) == 0)
-			rman_set_start(ires, IXP425_INT_UART0);
-		else
-			rman_set_start(ires, IXP425_INT_UART1);
-		rman_set_end(ires, rman_get_start(ires));
-	}
 	BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt, intr,
 	     arg, cookiep);
 
@@ -359,6 +355,197 @@
 	return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
 }
 
+struct ixp425_board {
+	int ib_board_type;
+	int ib_pci_int_a;
+	int ib_pci_int_b;
+	int ib_pci_int_c;
+	int ib_pci_int_d;
+	int ib_pci_clk66_en;
+	int ib_pci_clk;
+	int ib_pci_reset;
+	int ib_pci_slot_top;
+	int ib_ata_cs0;
+	int ib_ata_cs0_reg;
+	int ib_ata_cs1;
+	int ib_ata_cs1_reg;
+	int ib_ata_cs_size;
+	int ib_ata_int_pin;
+	int ib_ata_int;
+	int ib_iic_scl;
+	int ib_iic_sda;
+	int ib_uartcn_vbase;
+	int ib_uartcn_hwbase;
+	int ib_uartcn_int;
+	int ib_uartalt_vbase;
+	int ib_uartalt_hwbase;
+	int ib_uartalt_int;
+	int ib_watchdog;
+} ixp425_boards [] = {
+	{
+	.ib_board_type = BOARD_AVILA,
+	.ib_pci_int_a = IXP425_INT_GPIO_11,
+	.ib_pci_int_b = IXP425_INT_GPIO_10,
+	.ib_pci_int_c = IXP425_INT_GPIO_9,
+	.ib_pci_int_d = IXP425_INT_GPIO_8,
+	.ib_pci_clk66_en = -1,
+	.ib_pci_clk = 14 /* GPIO_PCI_CLK */,
+	.ib_pci_reset = 13 /* GPIO_PCI_RESET */,
+	.ib_pci_slot_top = 32,
+	.ib_ata_cs0 = IXP425_EXP_BUS_CS1_HWBASE,
+	.ib_ata_cs0_reg = EXP_TIMING_CS1_OFFSET,
+	.ib_ata_cs1 = IXP425_EXP_BUS_CS2_HWBASE,
+	.ib_ata_cs1_reg = EXP_TIMING_CS2_OFFSET,
+	.ib_ata_cs_size = IXP425_EXP_BUS_CS2_SIZE,
+	.ib_ata_int_pin = 12,
+	.ib_ata_int = IXP425_INT_GPIO_12,
+	.ib_iic_scl = 6 /* GPIO_I2C_SCL */,
+	.ib_iic_sda = 7 /* GPIO_I2C_SDA */,
+	.ib_uartcn_vbase = IXP425_UART0_VBASE,
+	.ib_uartcn_hwbase = IXP425_UART0_HWBASE,
+	.ib_uartcn_int = IXP425_INT_UART0,
+	.ib_uartalt_vbase = IXP425_UART1_VBASE,
+	.ib_uartalt_hwbase = IXP425_UART1_HWBASE,
+	.ib_uartalt_int = IXP425_INT_UART1,
+	.ib_watchdog = -1
+	},
+	{
+	.ib_board_type = BOARD_PRONGHORN,
+	.ib_pci_int_a = IXP425_INT_GPIO_4,
+	.ib_pci_int_b = IXP425_INT_GPIO_6,
+	.ib_pci_int_c = IXP425_INT_GPIO_11,
+	.ib_pci_int_d = IXP425_INT_GPIO_1,
+	.ib_pci_clk66_en = 3,
+	.ib_pci_clk = 14 /* GPIO_PCI_CLK */,
+	.ib_pci_reset = 12,
+	.ib_pci_slot_top = 20,
+	.ib_ata_cs0 = IXP425_EXP_BUS_CS3_HWBASE,
+	.ib_ata_cs0_reg = EXP_TIMING_CS3_OFFSET,
+	.ib_ata_cs1 = IXP425_EXP_BUS_CS4_HWBASE,
+	.ib_ata_cs1_reg = EXP_TIMING_CS4_OFFSET,
+	.ib_ata_cs_size = IXP425_EXP_BUS_CS4_SIZE,
+	.ib_ata_int_pin = 0,
+	.ib_ata_int = IXP425_INT_GPIO_0,
+	.ib_iic_scl = 10,
+	.ib_iic_sda = 9,
+	.ib_uartcn_vbase = IXP425_UART1_VBASE,
+	.ib_uartcn_hwbase = IXP425_UART1_HWBASE,
+	.ib_uartcn_int = IXP425_INT_UART1,
+	.ib_uartalt_vbase = IXP425_UART0_VBASE,
+	.ib_uartalt_hwbase = IXP425_UART0_HWBASE,
+	.ib_uartalt_int = IXP425_INT_UART0,
+	.ib_watchdog = 13,
+	}
+};
+
+static void *
+ixp425_get_board_type(void)
+{
+	struct ixp425_board *ixp425_board;
+
+	if (bus_space_read_4(&ixp425_bs_tag, IXP425_EXP_VBASE,
+	    EXP_TIMING_CS2_OFFSET) != 0)
+		ixp425_board = &ixp425_boards[BOARD_AVILA];
+	else
+		ixp425_board = &ixp425_boards[BOARD_PRONGHORN];
+
+	return (ixp425_board);
+}
+
+int
+ixp425_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
+{
+	struct ixp425_board *bt;
+
+	bt = device_get_ivars(dev);
+	KASSERT(bt != NULL, ("%s %d", __func__, __LINE__));
+
+	if (result == NULL)
+		return (EINVAL);
+
+	switch (index) {
+	case IXP425_IVAR_BOARD_TYPE:
+		*result = bt->ib_board_type;
+		break;
+	case IXP425_IVAR_PCI_INTA:
+		*result = bt->ib_pci_int_a;
+		break;
+	case IXP425_IVAR_PCI_INTB:
+		*result = bt->ib_pci_int_b;
+		break;
+	case IXP425_IVAR_PCI_INTC:
+		*result = bt->ib_pci_int_c;
+		break;
+	case IXP425_IVAR_PCI_INTD:
+		*result = bt->ib_pci_int_d;
+		break;
+	case IXP425_IVAR_PCI_CLK66_EN:
+		*result = bt->ib_pci_clk66_en;
+		break;
+	case IXP425_IVAR_PCI_CLK:
+		*result = bt->ib_pci_clk;
+		break;
+	case IXP425_IVAR_PCI_RESET:
+		*result = bt->ib_pci_reset;
+		break;
+	case IXP425_IVAR_PCI_SLOT_TOP:
+		*result = bt->ib_pci_slot_top;
+		break;
+	case IXP425_IVAR_ATA_CS0:
+		*result = bt->ib_ata_cs0;
+		break;
+	case IXP425_IVAR_ATA_CS0_REG:
+		*result = bt->ib_ata_cs0_reg;
+		break;
+	case IXP425_IVAR_ATA_CS1:
+		*result = bt->ib_ata_cs1;
+		break;
+	case IXP425_IVAR_ATA_CS1_REG:
+		*result = bt->ib_ata_cs1_reg;
+		break;
+	case IXP425_IVAR_ATA_SIZE:
+		*result = bt->ib_ata_cs_size;
+		break;
+	case IXP425_IVAR_ATA_INT_PIN:
+		*result = bt->ib_ata_int_pin;
+		break;
+	case IXP425_IVAR_ATA_INT:
+		*result = bt->ib_ata_int;
+		break;
+	case IXP425_IVAR_IIC_SCL:
+		*result = bt->ib_iic_scl;
+		break;
+	case IXP425_IVAR_IIC_SDA:
+		*result = bt->ib_iic_sda;
+		break;
+	case IXP425_IVAR_UARTCN_VBASE:
+		*result = bt->ib_uartcn_vbase;
+		break;
+	case IXP425_IVAR_UARTCN_HWBASE:
+		*result = bt->ib_uartcn_hwbase;
+		break;
+	case IXP425_IVAR_UARTCN_INT:
+		*result = bt->ib_uartcn_int;
+		break;
+	case IXP425_IVAR_UARTALT_VBASE:
+		*result = bt->ib_uartalt_vbase;
+		break;
+	case IXP425_IVAR_UARTALT_HWBASE:
+		*result = bt->ib_uartalt_hwbase;
+		break;
+	case IXP425_IVAR_UARTALT_INT:
+		*result = bt->ib_uartalt_int;
+		break;
+	case IXP425_IVAR_WATCHDOG:
+		*result = bt->ib_watchdog;
+		break;
+	default:
+		return (ENOENT);
+	}
+
+	return 0;
+}
+
 static device_method_t ixp425_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe, ixp425_probe),
@@ -367,6 +554,7 @@
 
 	/* Bus interface */
 	DEVMETHOD(bus_alloc_resource, ixp425_alloc_resource),
+	DEVMETHOD(bus_read_ivar, ixp425_read_ivar),
 	DEVMETHOD(bus_setup_intr, ixp425_setup_intr),
 	DEVMETHOD(bus_teardown_intr, ixp425_teardown_intr),
 
Index: ixp425_iic.c
===================================================================
RCS file: /home/ncvs/src/sys/arm/xscale/ixp425/ixp425_iic.c,v
retrieving revision 1.1
diff -u -r1.1 ixp425_iic.c
--- ixp425_iic.c	19 Nov 2006 23:55:23 -0000	1.1
+++ ixp425_iic.c	25 Mar 2007 07:17:51 -0000
@@ -61,6 +61,8 @@
 	device_t		sc_dev;
 	bus_space_tag_t		sc_iot;
 	bus_space_handle_t	sc_gpio_ioh;
+	uint32_t		sc_scl_bit;
+	uint32_t		sc_sda_bit;
 
 	device_t		iicbb;
 };
@@ -85,11 +87,13 @@
 	sc->sc_dev = dev;
 	sc->sc_iot = sa->sc_iot;
 	sc->sc_gpio_ioh = sa->sc_gpio_ioh;
+	sc->sc_scl_bit = 1U << ixp425_get_ivar(dev, IXP425_IVAR_IIC_SCL);
+	sc->sc_sda_bit = 1U << ixp425_get_ivar(dev, IXP425_IVAR_IIC_SDA);
 
 	GPIO_CONF_SET(sc, IXP425_GPIO_GPOER,
-		GPIO_I2C_SCL_BIT | GPIO_I2C_SDA_BIT);
+		sc->sc_scl_bit | sc->sc_sda_bit);
 	GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR,
-		GPIO_I2C_SCL_BIT | GPIO_I2C_SDA_BIT);
+		sc->sc_scl_bit | sc->sc_sda_bit);
 
 	/* add generic bit-banging code */	
 	if ((sc->iicbb = device_add_child(dev, "iicbb", -1)) == NULL)
@@ -113,10 +117,10 @@
 	struct ixpiic_softc *sc = ixpiic_sc;
 	uint32_t reg;
 
-	GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
+	GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, sc->sc_scl_bit);
 
 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR);
-	return (reg & GPIO_I2C_SCL_BIT);
+	return (reg & sc->sc_scl_bit);
 }
 
 static int 
@@ -125,10 +129,10 @@
 	struct ixpiic_softc *sc = ixpiic_sc;
 	uint32_t reg;
 
-	GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
+	GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, sc->sc_sda_bit);
 
 	reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR);
-	return (reg & GPIO_I2C_SDA_BIT);
+	return (reg & sc->sc_sda_bit);
 }
 
 static void 
@@ -136,11 +140,11 @@
 {
 	struct ixpiic_softc *sc = ixpiic_sc;
 
-	GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT);
+	GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, sc->sc_sda_bit);
 	if (val)
-		GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
+		GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, sc->sc_sda_bit);
 	else
-		GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
+		GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, sc->sc_sda_bit);
 	DELAY(I2C_DELAY);
 }
 
@@ -149,11 +153,11 @@
 {
 	struct ixpiic_softc *sc = ixpiic_sc;
 
-	GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT);
+	GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, sc->sc_scl_bit);
 	if (val)
-		GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
+		GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, sc->sc_scl_bit);
 	else
-		GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
+		GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, sc->sc_scl_bit);
 	DELAY(I2C_DELAY);
 }
 
Index: ixp425_pci.c
===================================================================
RCS file: /home/ncvs/src/sys/arm/xscale/ixp425/ixp425_pci.c,v
retrieving revision 1.4
diff -u -r1.4 ixp425_pci.c
--- ixp425_pci.c	6 Mar 2007 10:58:22 -0000	1.4
+++ ixp425_pci.c	25 Mar 2007 06:32:23 -0000
@@ -213,6 +213,8 @@
 	IXPPCIB_WRITE_CONF(sc, PCIR_COMMAND,
 	    PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
 	
+	sc->sc_slot_top = ixp425_get_ivar(dev, IXP425_IVAR_PCI_SLOT_TOP);
+
 	/*
 	 * Wait some more to ensure PCI devices have stabilised.
 	 */
@@ -355,8 +357,9 @@
 			slot &= 0x1f;
 			func &= 0x07;
 			/* configuration type 0 */
-			PCI_CSR_WRITE_4(sc, PCI_NP_AD, (1U << (32 - slot)) |
-				(func << 8) | (reg & ~3));
+			PCI_CSR_WRITE_4(sc, PCI_NP_AD,
+			    (1U << (sc->sc_slot_top - slot)) |
+			    (func << 8) | (reg & ~3));
 		}
 	} else {
 			/* configuration type 1 */
Index: ixp425var.h
===================================================================
RCS file: /home/ncvs/src/sys/arm/xscale/ixp425/ixp425var.h,v
retrieving revision 1.2
diff -u -r1.2 ixp425var.h
--- ixp425var.h	17 Jan 2007 00:58:25 -0000	1.2
+++ ixp425var.h	25 Mar 2007 08:23:00 -0000
@@ -75,6 +75,8 @@
 	struct bus_space        sc_pci_memt;
 	struct bus_space        sc_pci_iot;
 	bus_dma_tag_t 		sc_dmat;
+
+	u_int			sc_slot_top;	/* Where to start the search for slots. */
 };
 
 #define EXP_BUS_WRITE_4(sc, reg, data) \
@@ -98,4 +100,51 @@
 int	ixp425_md_route_interrupt(device_t, device_t, int);
 void	ixp425_md_attach(device_t);
 
+enum {
+	IXP425_IVAR_BOARD_TYPE,
+	IXP425_IVAR_PCI_INTA,
+	IXP425_IVAR_PCI_INTB,
+	IXP425_IVAR_PCI_INTC,
+	IXP425_IVAR_PCI_INTD,
+	IXP425_IVAR_PCI_CLK66_EN,
+	IXP425_IVAR_PCI_CLK,
+	IXP425_IVAR_PCI_RESET,
+	IXP425_IVAR_PCI_SLOT_TOP,
+	IXP425_IVAR_ATA_CS0,
+	IXP425_IVAR_ATA_CS0_REG,
+	IXP425_IVAR_ATA_CS1,
+	IXP425_IVAR_ATA_CS1_REG,
+	IXP425_IVAR_ATA_SIZE,
+	IXP425_IVAR_ATA_INT_PIN,
+	IXP425_IVAR_ATA_INT,
+	IXP425_IVAR_IIC_SCL,
+	IXP425_IVAR_IIC_SDA,
+	IXP425_IVAR_UARTCN_VBASE,
+	IXP425_IVAR_UARTCN_HWBASE,
+	IXP425_IVAR_UARTCN_INT,
+	IXP425_IVAR_UARTALT_VBASE,
+	IXP425_IVAR_UARTALT_HWBASE,
+	IXP425_IVAR_UARTALT_INT,
+	IXP425_IVAR_WATCHDOG,
+};
+
+#define	BOARD_AVILA		0
+#define	BOARD_PRONGHORN		1
+
+/* XXX
+ * Only the files that have sys/bus.h included will get this. The other
+ * option is to force everyone to include sys/bus.h or create another
+ * file.
+ */
+#ifdef __BUS_ACCESSOR
+__inline static uint32_t
+ixp425_get_ivar(device_t dev, int index)
+{
+	uintptr_t val;
+
+	BUS_READ_IVAR(device_get_parent(dev), dev, index, &val);
+	return (uint32_t)val;
+}
+#endif /* __BUS_ACCESSOR */
+
 #endif /* _IXP425VAR_H_ */
Index: uart_bus_ixp425.c
===================================================================
RCS file: /home/ncvs/src/sys/arm/xscale/ixp425/uart_bus_ixp425.c,v
retrieving revision 1.1
diff -u -r1.1 uart_bus_ixp425.c
--- uart_bus_ixp425.c	19 Nov 2006 23:55:23 -0000	1.1
+++ uart_bus_ixp425.c	25 Mar 2007 09:18:57 -0000
@@ -68,6 +68,7 @@
 uart_ixp425_probe(device_t dev)
 {
 	struct uart_softc *sc;
+	uint32_t vbase;
 
 	sc = device_get_softc(dev);
 	sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
@@ -81,9 +82,12 @@
 	 * uart_ns8250 carefully avoids touching these bits so we can
 	 * just set them here and proceed.  But this is fragile...
 	 */
-	bus_space_write_4(&ixp425_a4x_bs_tag,
-	    device_get_unit(dev) == 0 ? IXP425_UART0_VBASE : IXP425_UART1_VBASE,
-	    IXP425_UART_IER, IXP425_UART_IER_UUE | IXP425_UART_IER_RTOIE);
+	if (device_get_unit(dev) == 0)
+		vbase = ixp425_get_ivar(dev, IXP425_IVAR_UARTCN_VBASE);
+	else
+		vbase = ixp425_get_ivar(dev, IXP425_IVAR_UARTALT_VBASE);
+	bus_space_write_4(&ixp425_a4x_bs_tag, vbase, IXP425_UART_IER,
+	    IXP425_UART_IER_UUE | IXP425_UART_IER_RTOIE);
 	return(uart_bus_probe(dev, 0, IXP425_UART_FREQ, 0, 0));
 }
 
Index: uart_cpu_ixp425.c
===================================================================
RCS file: /home/ncvs/src/sys/arm/xscale/ixp425/uart_cpu_ixp425.c,v
retrieving revision 1.1
diff -u -r1.1 uart_cpu_ixp425.c
--- uart_cpu_ixp425.c	19 Nov 2006 23:55:23 -0000	1.1
+++ uart_cpu_ixp425.c	24 Mar 2007 17:47:58 -0000
@@ -62,6 +62,12 @@
 	di->parity = UART_PARITY_NONE;
 	uart_bus_space_io = &ixp425_a4x_bs_tag;
 	uart_bus_space_mem = NULL;
-	di->bas.bsh = IXP425_UART0_VBASE;
+
+	/* Crude support for both Avila and Pronghorn Metro boards. */
+	if (bus_space_read_4(&ixp425_bs_tag, IXP425_EXP_VBASE,
+	    EXP_TIMING_CS2_OFFSET) != 0)
+		di->bas.bsh = IXP425_UART0_VBASE;
+	else
+		di->bas.bsh = IXP425_UART1_VBASE;
 	return (0);
 }


More information about the freebsd-arm mailing list