Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Mar 2012 15:39:56 +0000 (UTC)
From:      "Jayachandran C." <jchandra@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233563 - in head/sys/mips/nlm: . hal
Message-ID:  <201203271539.q2RFduw6092794@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jchandra
Date: Tue Mar 27 15:39:55 2012
New Revision: 233563
URL: http://svn.freebsd.org/changeset/base/233563

Log:
  Update memory and resource allocation code for SoC devices
  
  The XLP on-chip devices have PCI configuration headers, but some of the
  devices need custom resource allocation code.
  - devices with no MEM/IO BARs with registers in PCIe extended reg
    space have to be handled in memory resource allocation
  - devices without INTPIN/INTLINE in PCI header can be supported
    by having these faked with a shadow register.
  - Some devices does not allow 8/16 bit access to the register space,
    he default bus space cannot be used for these.
  
  Subclass pci and override attach and resource allocation methods to
  take care of this.
  
  Remove earlier code which did this partially.

Deleted:
  head/sys/mips/nlm/intern_dev.c
Modified:
  head/sys/mips/nlm/files.xlp
  head/sys/mips/nlm/hal/nlm_hal.c
  head/sys/mips/nlm/hal/pcibus.h
  head/sys/mips/nlm/hal/pic.h
  head/sys/mips/nlm/intr_machdep.c
  head/sys/mips/nlm/xlp.h
  head/sys/mips/nlm/xlp_machdep.c
  head/sys/mips/nlm/xlp_pci.c

Modified: head/sys/mips/nlm/files.xlp
==============================================================================
--- head/sys/mips/nlm/files.xlp	Tue Mar 27 15:33:38 2012	(r233562)
+++ head/sys/mips/nlm/files.xlp	Tue Mar 27 15:39:55 2012	(r233563)
@@ -12,7 +12,6 @@ mips/nlm/mpreset.S				standard
 mips/nlm/board_eeprom.c				standard
 mips/nlm/board_cpld.c				standard
 mips/nlm/xlp_pci.c				optional pci
-mips/nlm/intern_dev.c				optional pci
 mips/nlm/uart_cpu_xlp.c				optional uart
 mips/nlm/usb_init.c				optional usb
 #

Modified: head/sys/mips/nlm/hal/nlm_hal.c
==============================================================================
--- head/sys/mips/nlm/hal/nlm_hal.c	Tue Mar 27 15:33:38 2012	(r233562)
+++ head/sys/mips/nlm/hal/nlm_hal.c	Tue Mar 27 15:39:55 2012	(r233563)
@@ -37,23 +37,8 @@ __FBSDID("$FreeBSD$");
 #include <mips/nlm/hal/haldefs.h>
 #include <mips/nlm/hal/iomap.h>
 #include <mips/nlm/hal/sys.h>
-#include <mips/nlm/hal/pic.h>
 #include <mips/nlm/xlp.h>
 
-#include <mips/nlm/hal/uart.h>
-#include <mips/nlm/hal/mmu.h>
-#include <mips/nlm/hal/pcibus.h>
-#include <mips/nlm/hal/usb.h>
-
-int pic_irt_ehci0;
-int pic_irt_ehci1;
-int pic_irt_uart0;
-int pic_irt_uart1;
-int pic_irt_pcie_lnk0;
-int pic_irt_pcie_lnk1;
-int pic_irt_pcie_lnk2;
-int pic_irt_pcie_lnk3;
-
 uint32_t
 xlp_get_cpu_frequency(int node, int core)
 {
@@ -66,9 +51,9 @@ xlp_get_cpu_frequency(int node, int core
 	pll_divf = ((rstval >> 10) & 0x7f) + 1;
 	pll_divr = ((rstval >> 8)  & 0x3) + 1;
 	if (!nlm_is_xlp8xx_ax())
-		ext_div  = ((rstval >> 30) & 0x3) + 1;
+		ext_div = ((rstval >> 30) & 0x3) + 1;
 	else
-		ext_div  = 1;
+		ext_div = 1;
 	dfs_div  = ((dfsval >> (core << 2)) & 0xf) + 1;
 
 	return ((800000000ULL * pll_divf)/(3 * pll_divr * ext_div * dfs_div));
@@ -122,98 +107,3 @@ nlm_set_device_frequency(int node, int d
 	}
 	return (nlm_get_device_frequency(sysbase, devtype));
 }
-
-void
-nlm_pic_irt_init(int node)
-{
-	pic_irt_ehci0 = nlm_irtstart(nlm_get_usb_pcibase(node, 0));
-	pic_irt_ehci1 = nlm_irtstart(nlm_get_usb_pcibase(node, 3));
-	pic_irt_uart0 = nlm_irtstart(nlm_get_uart_pcibase(node, 0));
-	pic_irt_uart1 = nlm_irtstart(nlm_get_uart_pcibase(node, 1));
-
-	/* Hardcoding the PCIE IRT information as PIC doesn't 
-	   understand any value other than 78,79,80,81 for PCIE0/1/2/3 */
-	pic_irt_pcie_lnk0 = 78;
-	pic_irt_pcie_lnk1 = 79;
-	pic_irt_pcie_lnk2 = 80;
-	pic_irt_pcie_lnk3 = 81;
-}
-/*
- * Find the IRQ for the link, each link has a different interrupt 
- * at the XLP pic
- */
-int xlp_pcie_link_irt(int link)
-{
-
-	if( (link < 0) || (link > 3))
-		return (-1);
-
-	return (pic_irt_pcie_lnk0 + link);
-}
-
-int
-xlp_irt_to_irq(int irt)
-{
-	if (irt == pic_irt_ehci0)
-		return PIC_EHCI_0_IRQ;
-	else if (irt == pic_irt_ehci1)
-		return PIC_EHCI_1_IRQ;
-	else if (irt == pic_irt_uart0)
-		return PIC_UART_0_IRQ;
-	else if (irt == pic_irt_uart1)
-		return PIC_UART_1_IRQ;
-	else if (irt == pic_irt_pcie_lnk0)
-		return PIC_PCIE_0_IRQ;
-	else if (irt == pic_irt_pcie_lnk1)
-		return PIC_PCIE_1_IRQ;
-	else if (irt == pic_irt_pcie_lnk2)
-		return PIC_PCIE_2_IRQ;
-	else if (irt == pic_irt_pcie_lnk3)
-		return PIC_PCIE_3_IRQ;
-	else {
-		if (bootverbose)
-			printf("Cannot find irq for IRT %d\n", irt);
-		return 0;
-	 }
-}
-
-int
-xlp_irq_to_irt(int irq)
-{
-	switch (irq) {
- 		case PIC_EHCI_0_IRQ :
- 			return pic_irt_ehci0;
- 		case PIC_EHCI_1_IRQ :
- 			return pic_irt_ehci1;
-		case PIC_UART_0_IRQ :
-			return pic_irt_uart0;
-		case PIC_UART_1_IRQ :
-			return pic_irt_uart1;
-		case PIC_PCIE_0_IRQ :
-			return pic_irt_pcie_lnk0;
-		case PIC_PCIE_1_IRQ :
-			return pic_irt_pcie_lnk1;
-		case PIC_PCIE_2_IRQ :
-			return pic_irt_pcie_lnk2;
-		case PIC_PCIE_3_IRQ :
-			return pic_irt_pcie_lnk3;
-		default: panic("Bad IRQ %d\n", irq);
-	}
-}
-
-int
-xlp_irq_is_picintr(int irq)
-{
-	switch (irq) {
- 		case PIC_EHCI_0_IRQ :
- 		case PIC_EHCI_1_IRQ :
-		case PIC_UART_0_IRQ :
-		case PIC_UART_1_IRQ :
-		case PIC_PCIE_0_IRQ :
-		case PIC_PCIE_1_IRQ :
-		case PIC_PCIE_2_IRQ :
-		case PIC_PCIE_3_IRQ :
-			return (1);
-		default: return (0);
-	}
-}

Modified: head/sys/mips/nlm/hal/pcibus.h
==============================================================================
--- head/sys/mips/nlm/hal/pcibus.h	Tue Mar 27 15:33:38 2012	(r233562)
+++ head/sys/mips/nlm/hal/pcibus.h	Tue Mar 27 15:39:55 2012	(r233563)
@@ -84,6 +84,9 @@
 /* PCIE_INT_EN0 */
 #define	PCIE_MSI_INT_EN			(1 << 9)
 
+/* XXXJC: Ax workaround */
+#define	PCIE_LINK0_IRT			78
+
 #if !defined(LOCORE) && !defined(__ASSEMBLY__)
 
 #define	nlm_read_pcie_reg(b, r)		nlm_read_reg(b, r)
@@ -93,6 +96,15 @@
 #define	nlm_get_pcie_regbase(node, inst)	\
 				(nlm_get_pcie_base(node, inst) + XLP_IO_PCI_HDRSZ)
 
+static __inline int
+xlp_pcie_link_irt(int link)
+{
+	if ((link < 0) || (link > 3))
+		return (-1);
+
+	return (PCIE_LINK0_IRT + link);
+}
+
 /*
  * Build Intel MSI message and data values from a source.  AMD64 systems
  * seem to be compatible, so we use the same function for both.
@@ -106,8 +118,4 @@
 	 MSI_MIPS_DATA_ASSERT | (irq))
 
 #endif
-
-#ifndef LOCORE
-int xlp_pcie_link_irt(int link);
-#endif
 #endif /* __XLP_PCIBUS_H__ */

Modified: head/sys/mips/nlm/hal/pic.h
==============================================================================
--- head/sys/mips/nlm/hal/pic.h	Tue Mar 27 15:33:38 2012	(r233562)
+++ head/sys/mips/nlm/hal/pic.h	Tue Mar 27 15:39:55 2012	(r233563)
@@ -174,7 +174,7 @@
 
 #define	PIC_IRT_FIRST_IRQ		(PIC_IRQ_BASE)
 #define	PIC_IRT_LAST_IRQ		63
-#define	PIC_IRQ_IS_IRT(irq)		((irq) >= PIC_IRT_FIRST_IRQ)
+#define	XLP_IRQ_IS_PICINTR(irq)		((irq) >= PIC_IRT_FIRST_IRQ)
 
 /*
  *   Misc

Modified: head/sys/mips/nlm/intr_machdep.c
==============================================================================
--- head/sys/mips/nlm/intr_machdep.c	Tue Mar 27 15:33:38 2012	(r233562)
+++ head/sys/mips/nlm/intr_machdep.c	Tue Mar 27 15:39:55 2012	(r233563)
@@ -141,13 +141,13 @@ xlp_establish_intr(const char *name, dri
 		 * PIC based interrupts need ack in PIC, and some SoC
 		 * components need additional acks (e.g. PCI)
 		 */
-		if (xlp_irq_is_picintr(irq))
+		if (XLP_IRQ_IS_PICINTR(irq))
 			errcode = intr_event_create(&ie, src, 0, irq,
 			    xlp_pre_ithread, xlp_post_ithread, xlp_post_filter,
 			    NULL, "hard intr%d:", irq);
 		else {
 			if (filt == NULL)
-				panic("Not supported - non filter percpu intr");
+				panic("Unsupported non filter percpu intr %d", irq);
 			errcode = intr_event_create(&ie, src, 0, irq,
 			    NULL, NULL, NULL, NULL, "hard intr%d:", irq);
 		}

Modified: head/sys/mips/nlm/xlp.h
==============================================================================
--- head/sys/mips/nlm/xlp.h	Tue Mar 27 15:33:38 2012	(r233562)
+++ head/sys/mips/nlm/xlp.h	Tue Mar 27 15:39:55 2012	(r233563)
@@ -35,17 +35,15 @@
 #include <mips/nlm/hal/iomap.h>
 
 #define	PIC_UART_0_IRQ	9
-#define	PIC_UART_1_IRQ	10
 
 #define	PIC_PCIE_0_IRQ	11
 #define	PIC_PCIE_1_IRQ	12
 #define	PIC_PCIE_2_IRQ	13
 #define	PIC_PCIE_3_IRQ	14
 
-#define	PIC_EHCI_0_IRQ	39 
+#define	PIC_EHCI_0_IRQ	16 
+#define	PIC_MMC_IRQ	21
 /* 41 used by IRQ_SMP */
-#define	PIC_EHCI_1_IRQ	42 
-#define	PIC_MMC_IRQ	43
 
 
 /* XLP 8xx/4xx A0, A1, A2 CPU COP0 PRIDs */
@@ -75,10 +73,8 @@ extern void xlp_enable_threads(int code)
 #endif
 uint32_t xlp_get_cpu_frequency(int node, int core);
 int nlm_set_device_frequency(int node, int devtype, int frequency);
-void nlm_pic_irt_init(int node);
 int xlp_irt_to_irq(int irt);
 int xlp_irq_to_irt(int irq);
-int xlp_irq_is_picintr(int irq);
 
 static __inline int nlm_processor_id(void)
 {

Modified: head/sys/mips/nlm/xlp_machdep.c
==============================================================================
--- head/sys/mips/nlm/xlp_machdep.c	Tue Mar 27 15:33:38 2012	(r233562)
+++ head/sys/mips/nlm/xlp_machdep.c	Tue Mar 27 15:39:55 2012	(r233563)
@@ -98,7 +98,7 @@ __FBSDID("$FreeBSD$");
 char boot1_env[4096];
 
 uint64_t xlp_cpu_frequency;
-uint64_t xlp_io_base = MIPS_PHYS_TO_KSEG1(XLP_DEFAULT_IO_BASE);
+uint64_t xlp_io_base = MIPS_PHYS_TO_DIRECT_UNCACHED(XLP_DEFAULT_IO_BASE);
 
 int xlp_ncores;
 int xlp_threads_per_core;
@@ -521,7 +521,6 @@ platform_start(__register_t a0 __unused,
 	/* initialize console so that we have printf */
 	boothowto |= (RB_SERIAL | RB_MULTIPLE);	/* Use multiple consoles */
 
-	nlm_pic_irt_init(0); /* complete before interrupts or console init */
 	init_static_kenv(boot1_env, sizeof(boot1_env));
 	xlp_bootargs_init(a0);
 

Modified: head/sys/mips/nlm/xlp_pci.c
==============================================================================
--- head/sys/mips/nlm/xlp_pci.c	Tue Mar 27 15:33:38 2012	(r233562)
+++ head/sys/mips/nlm/xlp_pci.c	Tue Mar 27 15:39:55 2012	(r233563)
@@ -1,32 +1,31 @@
 /*-
- * Copyright (c) 2003-2009 RMI Corporation
- * All rights reserved.
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of RMI Corporation, nor the names of its contributors,
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * NETLOGIC_BSD */
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
@@ -39,14 +38,16 @@ __FBSDID("$FreeBSD$");
 #include <sys/bus.h>
 #include <sys/endian.h>
 #include <sys/rman.h>
+#include <sys/pciio.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 
-#include <sys/pciio.h>
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
+#include <dev/pci/pci_private.h>
+
 #include <dev/uart/uart.h>
 #include <dev/uart/uart_bus.h>
 #include <dev/uart/uart_cpu.h>
@@ -68,16 +69,260 @@ __FBSDID("$FreeBSD$");
 #include <mips/nlm/xlp.h>
 
 #include "pcib_if.h"
+#include "pci_if.h"
+
+#define	EMUL_MEM_START	0x16000000UL
+#define	EMUL_MEM_END	0x18ffffffUL
 
-struct xlp_pcib_softc {
-	bus_dma_tag_t	sc_pci_dmat;	/* PCI DMA tag pointer */
+/* SoC device qurik handling */
+static int irt_irq_map[4 * 256];
+static int irq_irt_map[64];
+
+static void
+xlp_add_irq(int node, int irt, int irq)
+{
+	int nodeirt = node * 256 + irt;
+
+	irt_irq_map[nodeirt] = irq;
+	irq_irt_map[irq] = nodeirt;
+}
+
+int
+xlp_irq_to_irt(int irq)
+{
+	return irq_irt_map[irq];
+}
+
+int
+xlp_irt_to_irq(int nodeirt)
+{
+	return irt_irq_map[nodeirt];
+}
+
+/* Override PCI a bit for SoC devices */
+
+enum {
+	INTERNAL_DEV	= 0x1,	/* internal device, skip on enumeration */
+	MEM_RES_EMUL	= 0x2,	/* no MEM or IO bar, custom res alloc */
+	SHARED_IRQ	= 0x4,
+	DEV_MMIO32	= 0x8,	/* byte access not allowed to mmio */
+};
+
+struct soc_dev_desc {
+	u_int	devid;		/* device ID */
+	int	irqbase;	/* start IRQ */
+	u_int	flags;		/* flags */
+	int	ndevs;		/* to keep track of number of devices */
+};
+
+struct soc_dev_desc xlp_dev_desc[] = {
+	{ PCI_DEVICE_ID_NLM_ICI,               0, INTERNAL_DEV },
+	{ PCI_DEVICE_ID_NLM_PIC,               0, INTERNAL_DEV },
+	{ PCI_DEVICE_ID_NLM_FMN,               0, INTERNAL_DEV },
+	{ PCI_DEVICE_ID_NLM_UART, PIC_UART_0_IRQ, MEM_RES_EMUL | DEV_MMIO32},
+	{ PCI_DEVICE_ID_NLM_I2C,               0, MEM_RES_EMUL | DEV_MMIO32 },
+	{ PCI_DEVICE_ID_NLM_NOR,               0, MEM_RES_EMUL },
+	{ PCI_DEVICE_ID_NLM_MMC,     PIC_MMC_IRQ, MEM_RES_EMUL },
+	{ PCI_DEVICE_ID_NLM_EHCI, PIC_EHCI_0_IRQ, 0 }
+};
+
+struct  xlp_devinfo {
+	struct pci_devinfo pcidev;
+	int	irq;
+	int	flags;
+	u_long	mem_res_start;
 };
 
+static __inline struct soc_dev_desc *
+xlp_find_soc_desc(int devid)
+{
+	struct soc_dev_desc *p;
+	int i, n;
+
+	n = sizeof(xlp_dev_desc) / sizeof(xlp_dev_desc[0]);
+	for (i = 0, p = xlp_dev_desc; i < n; i++, p++)
+		if (p->devid == devid)
+			return (p);
+	return (NULL);
+}
+
+static struct resource *
+xlp_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+    u_long start, u_long end, u_long count, u_int flags)
+{
+	struct resource *r;
+	struct xlp_devinfo *xlp_devinfo;
+	int busno;
+
+	/*
+	 * Do custom allocation for MEMORY resource for SoC device if 
+	 * MEM_RES_EMUL flag is set
+	 */
+	busno = pci_get_bus(child);
+	if ((type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) && busno == 0) {
+		xlp_devinfo = (struct xlp_devinfo *)device_get_ivars(child);
+		if ((xlp_devinfo->flags & MEM_RES_EMUL) != 0) {
+			/* no emulation for IO ports */
+			if (type == SYS_RES_IOPORT)
+				return (NULL);
+			start = xlp_devinfo->mem_res_start;
+			count = XLP_PCIE_CFG_SIZE - XLP_IO_PCI_HDRSZ;
+			end = start + count - 1;
+			r = BUS_ALLOC_RESOURCE(device_get_parent(bus), child,
+			    type, rid, start, end, count, flags);
+			if (r == NULL)
+				return (NULL);
+			if ((xlp_devinfo->flags & DEV_MMIO32) != 0)
+				rman_set_bustag(r, rmi_uart_bus_space);
+			return (r);
+		}
+	}
+
+	/* Not custom alloc, use PCI code */
+	return (pci_alloc_resource(bus, child, type, rid, start, end, count,
+	    flags));
+}
+
+static int
+xlp_pci_release_resource(device_t bus, device_t child, int type, int rid,
+    struct resource *r)
+{
+	u_long start;
+
+	/* If custom alloc, handle that */
+	start = rman_get_start(r);
+	if (type == SYS_RES_MEMORY && pci_get_bus(child) == 0 &&
+	    start >= EMUL_MEM_START && start <= EMUL_MEM_END)
+		return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child,
+		    type, rid, r));
+
+	/* use default PCI function */
+	return (bus_generic_rl_release_resource(bus, child, type, rid, r));
+}
+
+static void
+xlp_add_soc_child(device_t pcib, device_t dev, int b, int s, int f)
+{
+	struct pci_devinfo *dinfo;
+	struct xlp_devinfo *xlp_dinfo;
+	struct soc_dev_desc *si;
+	uint64_t pcibase;
+	int domain, node, irt, irq, flags, devoffset, num;
+	uint16_t devid;
+
+	domain = pcib_get_domain(dev);
+	node = s / 8;
+	devoffset = XLP_HDR_OFFSET(node, 0, s % 8, f);
+	if (!nlm_dev_exists(devoffset))
+		return;
+
+	/* Find if there is a desc for the SoC device */
+	devid = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVICE, 2);
+	si = xlp_find_soc_desc(devid);
+
+	/* update flags and irq from desc if available */
+	irq = 0;
+	flags = 0;
+	if (si != NULL) {
+		if (si->irqbase != 0)
+			irq = si->irqbase + si->ndevs;
+		flags = si->flags;
+		si->ndevs++;
+	}
+
+	/* skip internal devices */
+	if ((flags & INTERNAL_DEV) != 0)
+		return;
+
+	/* PCIe interfaces are special, bug in Ax */
+	if (devid == PCI_DEVICE_ID_NLM_PCIE) {
+		xlp_add_irq(node, xlp_pcie_link_irt(f), PIC_PCIE_0_IRQ + f);
+	} else {
+		/* Stash intline and pin in shadow reg for devices */
+		pcibase = nlm_pcicfg_base(devoffset);
+		irt = nlm_irtstart(pcibase);
+		num = nlm_irtnum(pcibase);
+		if (irq != 0 && num > 0) {
+			xlp_add_irq(node, irt, irq);
+			nlm_write_reg(pcibase, XLP_PCI_DEVSCRATCH_REG0,
+			    (1 << 8) | irq);
+		}
+	}
+	dinfo = pci_read_device(pcib, domain, b, s, f, sizeof(*xlp_dinfo));
+	if (dinfo == NULL)
+		return;
+	xlp_dinfo = (struct xlp_devinfo *)dinfo;
+	xlp_dinfo->irq = irq;
+	xlp_dinfo->flags = flags;
+	if ((flags & MEM_RES_EMUL) != 0)
+		xlp_dinfo->mem_res_start = XLP_DEFAULT_IO_BASE + devoffset +
+		    XLP_IO_PCI_HDRSZ;
+	pci_add_child(dev, dinfo);
+}
+
+static int
+xlp_pci_attach(device_t dev)
+{
+	device_t pcib = device_get_parent(dev);
+	int maxslots, s, f, pcifunchigh;
+	int busno;
+	uint8_t hdrtype;
+
+	/*
+	 * The on-chip devices are on a bus that is almost, but not
+	 * quite, completely like PCI. Add those things by hand.
+	 */
+	busno = pcib_get_bus(dev);
+	maxslots = PCIB_MAXSLOTS(pcib);
+	for (s = 0; s <= maxslots; s++) {
+		pcifunchigh = 0;
+		f = 0;
+		hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1);
+		if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
+			continue;
+		if (hdrtype & PCIM_MFDEV)
+			pcifunchigh = PCI_FUNCMAX;
+		for (f = 0; f <= pcifunchigh; f++)
+			xlp_add_soc_child(pcib, dev, busno, s, f);
+	}
+	return (bus_generic_attach(dev));
+}
+
+static int
+xlp_pci_probe(device_t dev)
+{
+	device_t pcib;
+
+	pcib = device_get_parent(dev);
+	/*
+	 * Only the top level bus has SoC devices, leave the rest to
+	 * Generic PCI code
+	 */
+	if (strcmp(device_get_nameunit(pcib), "pcib0") != 0)
+		return (ENXIO);
+	device_set_desc(dev, "XLP SoCbus");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static devclass_t pci_devclass;
+static device_method_t xlp_pci_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		xlp_pci_probe),
+	DEVMETHOD(device_attach,	xlp_pci_attach),
+	DEVMETHOD(bus_alloc_resource,	xlp_pci_alloc_resource),
+	DEVMETHOD(bus_release_resource, xlp_pci_release_resource),
+
+	DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(pci, xlp_pci_driver, xlp_pci_methods, 0, pci_driver);
+DRIVER_MODULE(xlp_pci, pcib, xlp_pci_driver, pci_devclass, 0, 0);
+
 static devclass_t pcib_devclass;
 static struct rman irq_rman, port_rman, mem_rman, emul_rman;
 
 static void
-xlp_pci_init_resources(void)
+xlp_pcib_init_resources(void)
 {
 	irq_rman.rm_start = 0;
 	irq_rman.rm_end = 255;
@@ -112,7 +357,7 @@ xlp_pci_init_resources(void)
 	emul_rman.rm_type = RMAN_ARRAY;
 	emul_rman.rm_descr = "Emulated MEMIO";
 	if (rman_init(&emul_rman)
-	    || rman_manage_region(&emul_rman, 0x16000000UL, 0x18ffffffUL))
+	    || rman_manage_region(&emul_rman, EMUL_MEM_START, EMUL_MEM_END))
 		panic("pci_init_resources emul_rman");
 }
 
@@ -121,7 +366,7 @@ xlp_pcib_probe(device_t dev)
 {
 
 	device_set_desc(dev, "XLP PCI bus");
-	xlp_pci_init_resources();
+	xlp_pcib_init_resources();
 	return (0);
 }
 
@@ -173,20 +418,15 @@ xlp_pcib_read_config(device_t dev, u_int
 	else if ((width == 4) && (reg & 3))
 		return 0xFFFFFFFF;
 
-	data = nlm_read_pci_reg(cfgaddr, regindex);
-
 	/* 
-	 * Fix up read data in some SoC devices 
-	 * to emulate complete PCIe header
+	 * The intline and int pin of SoC devices are DOA, except
+	 * for bridges (slot %8 == 1).
+	 * use the values we stashed in a writable PCI scratch reg.
 	 */
-	if (b == 0) {
-		int dev = s % 8;
+	if (b == 0 && regindex == 0xf && s % 8 > 1)
+		regindex = XLP_PCI_DEVSCRATCH_REG0;
 
-		/* Fake intpin on config read for UART/I2C, USB, SD/Flash */
-		if (regindex == 0xf && 
-		    (dev == 6 || dev == 2 || dev == 7))
-			data |= 0x1 << 8;	/* Fake int pin */
-	}
+	data = nlm_read_pci_reg(cfgaddr, regindex);
 	if (width == 1)
 		return ((data >> ((reg & 3) << 3)) & 0xff);
 	else if (width == 2)
@@ -221,8 +461,12 @@ xlp_pcib_write_config(device_t dev, u_in
 		data = val;
 	}
 
+	/*
+	 * use shadow reg for intpin/intline which are dead
+	 */
+	if (b == 0 && regindex == 0xf && s % 8 > 1)
+		regindex = XLP_PCI_DEVSCRATCH_REG0;
 	nlm_write_pci_reg(cfgaddr, regindex, data);
-	return;
 }
 
 /*
@@ -230,7 +474,7 @@ xlp_pcib_write_config(device_t dev, u_in
  * from the link's IO and MEM address ranges.
  */
 static void
-xlp_pci_hardware_swap_enable(int node, int link)
+xlp_pcib_hardware_swap_enable(int node, int link)
 {
 	uint64_t bbase, linkpcibase;
 	uint32_t bar;
@@ -263,7 +507,7 @@ xlp_pcib_attach(device_t dev)
 	/* enable hardware swap on all nodes/links */
 	for (node = 0; node < XLP_MAX_NODES; node++)
 		for (link = 0; link < 4; link++)
-			xlp_pci_hardware_swap_enable(node, link);
+			xlp_pcib_hardware_swap_enable(node, link);
 
 	device_add_child(dev, "pci", 0);
 	bus_generic_attach(dev);
@@ -384,7 +628,7 @@ bridge_pcie_ack(int irq)
 }
 
 static int
-mips_platform_pci_setup_intr(device_t dev, device_t child,
+mips_platform_pcib_setup_intr(device_t dev, device_t child,
     struct resource *irq, int flags, driver_filter_t *filt,
     driver_intr_t *intr, void *arg, void **cookiep)
 {
@@ -401,11 +645,11 @@ mips_platform_pci_setup_intr(device_t de
 		return (EINVAL);
 	}
 	xlpirq = rman_get_start(irq);
+	if (xlpirq == 0)
+		return (0);
 
-	if (strcmp(device_get_name(dev), "pcib") != 0) {
-		device_printf(dev, "ret 0 on dev\n");
+	if (strcmp(device_get_name(dev), "pcib") != 0)
 		return (0);
-	}
 
 	/* 
 	 * temporary hack for MSI, we support just one device per
@@ -465,7 +709,7 @@ mips_platform_pci_setup_intr(device_t de
 }
 
 static int
-mips_platform_pci_teardown_intr(device_t dev, device_t child,
+mips_platform_pcib_teardown_intr(device_t dev, device_t child,
     struct resource *irq, void *cookie)
 {
 	if (strcmp(device_get_name(child), "pci") == 0) {
@@ -475,146 +719,65 @@ mips_platform_pci_teardown_intr(device_t
 	return (bus_generic_teardown_intr(dev, child, irq, cookie));
 }
 
-static void
-assign_soc_resource(device_t child, int type, u_long *startp, u_long *endp,
-    u_long *countp, struct rman **rm, bus_space_tag_t *bst, vm_offset_t *va)
-{
-	int devid, inst, node, unit;
-	uint32_t val;
-
-	devid = pci_get_device(child);
-	inst = pci_get_function(child);
-	node = pci_get_slot(child) / 8;
-	unit = device_get_unit(child);
-
-	*rm = NULL;
-	*va = 0;
-	*bst = 0;
-	if (type == SYS_RES_MEMORY) { 
-		switch (devid) {
-		case PCI_DEVICE_ID_NLM_UART:
-			*va = nlm_get_uart_regbase(node, inst);
-			*startp = MIPS_KSEG1_TO_PHYS(*va);
-			*countp = 0x100;
-			*rm = &emul_rman;
-			*bst = uart_bus_space_mem;
-			break;
-
-		case PCI_DEVICE_ID_NLM_I2C:
-			*va = nlm_pcicfg_base(XLP_IO_I2C_OFFSET(node, unit)) +
-			    XLP_IO_PCI_HDRSZ;
-			*startp = MIPS_KSEG1_TO_PHYS(*va);
-			*countp = 0x100;
-			*rm = &emul_rman;
-			*bst = uart_bus_space_mem;
-			break;
-		case PCI_DEVICE_ID_NLM_NOR:
-			/* XXXJC: support multiple chip selects */
-			val = nlm_read_pci_reg(nlm_get_gbu_regbase(node), 0);
-			*startp = val << 8;
-			*va = MIPS_PHYS_TO_KSEG1(*startp);
-			/* XXXJC: count is not correct */
-			*countp = 0x100;
-			*rm = &emul_rman;
-			break;
-		}
-		/* calculate end if allocated */
-		if (*rm)
-			*endp = *startp + *countp - 1;
-	} else if (type != SYS_RES_IRQ) {
-		/*
-		 * IRQ allocation is done by route_interrupt,
-		 * for any other request print warning.
-		 */
-		printf("Unknown type %d in req for [%x%x]\n",
-			type, devid, inst);
-	}
-}
-
 static struct resource *
-xlp_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+xlp_pcib_alloc_resource(device_t bus, device_t child, int type, int *rid,
     u_long start, u_long end, u_long count, u_int flags)
 {
 	struct rman *rm = NULL;
 	struct resource *rv;
-	vm_offset_t va = 0;
+	void *va;
 	int needactivate = flags & RF_ACTIVE;
-	bus_space_tag_t bst = 0;
 
-	/*
-	 * For SoC PCI devices, we have to assign resources correctly
-	 * since the IRQ and MEM resources depend on the block.
-	 * If the address is not from BAR0, then we use emul_rman
-	 */
-	if (pci_get_bus(child) == 0 &&
-	    pci_get_vendor(child) == PCI_VENDOR_NETLOGIC)
-      		assign_soc_resource(child, type, &start, &end,
-		    &count, &rm, &bst, &va);
-	if (rm == NULL) {
-		switch (type) {
-		case SYS_RES_IRQ:
-			rm = &irq_rman;
-			break;
+	switch (type) {
+	case SYS_RES_IRQ:
+		rm = &irq_rman;
+		break;
 	
-		case SYS_RES_IOPORT:
-			rm = &port_rman;
-			break;
-
-		case SYS_RES_MEMORY:
+	case SYS_RES_IOPORT:
+		rm = &port_rman;
+		break;
+
+	case SYS_RES_MEMORY:
+		if (start >= EMUL_MEM_START && start <= EMUL_MEM_END)
+			rm = &emul_rman;
+		else
 			rm = &mem_rman;
 			break;
 
-		default:
-			return (0);
-		}
+	default:
+		return (0);
 	}
 
 	rv = rman_reserve_resource(rm, start, end, count, flags, child);
-	if (rv == 0)
-		return (0);
+	if (rv == NULL)
+		return (NULL);
 
 	rman_set_rid(rv, *rid);
 
 	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
-		if (va == 0)
-			va = (vm_offset_t)pmap_mapdev(start, count);
-		if (bst == 0)
-			bst = rmi_bus_space;
-
-		rman_set_bushandle(rv, va);
-		rman_set_virtual(rv, (void *)va);
-		rman_set_bustag(rv, bst);
+		va = pmap_mapdev(start, count);
+		rman_set_bushandle(rv, (bus_space_handle_t)va);
+		rman_set_bustag(rv, rmi_bus_space);
 	}
-
 	if (needactivate) {
 		if (bus_activate_resource(child, type, *rid, rv)) {
 			rman_release_resource(rv);
 			return (NULL);
 		}
 	}
-
 	return (rv);
 }
 
 static int
-xlp_pci_release_resource(device_t bus, device_t child, int type, int rid,
+xlp_pcib_release_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
 
 	return (rman_release_resource(r));
 }
 
-static bus_dma_tag_t
-xlp_pci_get_dma_tag(device_t bus, device_t child)
-{
-	struct xlp_pcib_softc *sc;
-
-	sc = device_get_softc(bus);
-	return (sc->sc_pci_dmat);
-}
-
 static int
-xlp_pci_activate_resource(device_t bus, device_t child, int type, int rid,
+xlp_pcib_activate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
 
@@ -622,7 +785,7 @@ xlp_pci_activate_resource(device_t bus, 
 }
 
 static int
-xlp_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
+xlp_pcib_deactivate_resource(device_t bus, device_t child, int type, int rid,
     struct resource *r)
 {
 
@@ -630,7 +793,7 @@ xlp_pci_deactivate_resource(device_t bus
 }
 
 static int
-mips_pci_route_interrupt(device_t bus, device_t dev, int pin)
+mips_pcib_route_interrupt(device_t bus, device_t dev, int pin)
 {
 	int irt, link;
 
@@ -685,19 +848,18 @@ static device_method_t xlp_pcib_methods[
 	/* Bus interface */
 	DEVMETHOD(bus_read_ivar, xlp_pcib_read_ivar),
 	DEVMETHOD(bus_write_ivar, xlp_pcib_write_ivar),
-	DEVMETHOD(bus_alloc_resource, xlp_pci_alloc_resource),
-	DEVMETHOD(bus_release_resource, xlp_pci_release_resource),
-	DEVMETHOD(bus_get_dma_tag, xlp_pci_get_dma_tag),
-	DEVMETHOD(bus_activate_resource, xlp_pci_activate_resource),
-	DEVMETHOD(bus_deactivate_resource, xlp_pci_deactivate_resource),
-	DEVMETHOD(bus_setup_intr, mips_platform_pci_setup_intr),
-	DEVMETHOD(bus_teardown_intr, mips_platform_pci_teardown_intr),
+	DEVMETHOD(bus_alloc_resource, xlp_pcib_alloc_resource),
+	DEVMETHOD(bus_release_resource, xlp_pcib_release_resource),
+	DEVMETHOD(bus_activate_resource, xlp_pcib_activate_resource),
+	DEVMETHOD(bus_deactivate_resource, xlp_pcib_deactivate_resource),
+	DEVMETHOD(bus_setup_intr, mips_platform_pcib_setup_intr),
+	DEVMETHOD(bus_teardown_intr, mips_platform_pcib_teardown_intr),
 
 	/* pcib interface */
 	DEVMETHOD(pcib_maxslots, xlp_pcib_maxslots),
 	DEVMETHOD(pcib_read_config, xlp_pcib_read_config),
 	DEVMETHOD(pcib_write_config, xlp_pcib_write_config),
-	DEVMETHOD(pcib_route_interrupt, mips_pci_route_interrupt),
+	DEVMETHOD(pcib_route_interrupt, mips_pcib_route_interrupt),
 
 	DEVMETHOD(pcib_alloc_msi, xlp_alloc_msi),
 	DEVMETHOD(pcib_release_msi, xlp_release_msi),
@@ -709,7 +871,7 @@ static device_method_t xlp_pcib_methods[
 static driver_t xlp_pcib_driver = {
 	"pcib",
 	xlp_pcib_methods,
-	sizeof(struct xlp_pcib_softc),
+	1, /* no softc */
 };
 
 DRIVER_MODULE(pcib, nexus, xlp_pcib_driver, pcib_devclass, 0, 0);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203271539.q2RFduw6092794>