svn commit: r265969 - in stable/10/sys: conf dev/fdt dev/ofw powerpc/include powerpc/mpc85xx powerpc/ofw powerpc/powerpc powerpc/pseries

Ian Lepore ian at FreeBSD.org
Tue May 13 18:06:29 UTC 2014


Author: ian
Date: Tue May 13 18:06:26 2014
New Revision: 265969
URL: http://svnweb.freebsd.org/changeset/base/265969

Log:
  MFC r256994, r257016, r257055, r257059, r257060, r257075
  
    Add two new interfaces to ofw_bus:
    - ofw_bus_map_intr()
      Maps an (iparent, IRQ) tuple to a system-global interrupt number in some
      platform dependent way. This is meant to be implemented as a replacement
      for [FDT_]MAP_IRQ() that is an MI interface that knows about the bus
      hierarchy.
    - ofw_bus_config_intr()
      Configures an interrupt (previously mapped) based on firmware sense flags.
      This replaces manual interpretation of the sense field in bus drivers and
      will, in a follow-up, allow that interpretation to be redirected to the PIC
      drivers where it belongs. This will eventually replace the tables in
      /sys/dev/fdt/fdt_ARCH.c
  
    The PowerPC/AIM code has been converted to use these globally, with an
    implementation in terms of MAP_IRQ() and powerpc_config_intr(), assuming
    OpenPIC, at the bus root in nexus(4). The ofw_bus_config_intr() will shortly
    be integrated into pic_if.m and bounced through nexus into the PIC tree.
  
    Factor out MI portions of the PowerPC nexus device into /sys/dev/ofw. The
    sparc64 driver will be modified to use this shortly.
  
    Allow PIC drivers to translate firmware sense codes for themselves. This
    is designed to replace the tables in dev/fdt/fdt_ARCH.c, but will not
    happen quite yet.
  
    Do not map IRQs twice. This fixes PowerPC/FDT systems with multiple PICs,
    which would try to treat the previously-mapped interrupts from
    fdt_decode_intr() as interrupt line numbers on the same parent PIC.
  
    Remove some of the code required for supporting ssm(4) on SPARC in favor
    of a more PowerPC/FDT-focused design. Whenever SPARC64 is integrated
    into this rework, this should be (trivially) revisited.

Added:
  stable/10/sys/dev/ofw/ofw_nexus.c
     - copied, changed from r257016, head/sys/dev/ofw/ofw_nexus.c
  stable/10/sys/dev/ofw/ofw_nexus.h
     - copied unchanged from r257016, head/sys/dev/ofw/ofw_nexus.h
Modified:
  stable/10/sys/conf/files.powerpc
  stable/10/sys/dev/fdt/fdt_common.c
  stable/10/sys/dev/ofw/ofw_bus.h
  stable/10/sys/dev/ofw/ofw_bus_if.m
  stable/10/sys/powerpc/include/intr_machdep.h
  stable/10/sys/powerpc/mpc85xx/atpic.c
  stable/10/sys/powerpc/ofw/ofw_pci.c
  stable/10/sys/powerpc/ofw/ofw_pcib_pci.c
  stable/10/sys/powerpc/ofw/ofw_pcibus.c
  stable/10/sys/powerpc/ofw/openpic_ofw.c
  stable/10/sys/powerpc/powerpc/intr_machdep.c
  stable/10/sys/powerpc/powerpc/nexus.c
  stable/10/sys/powerpc/powerpc/pic_if.m
  stable/10/sys/powerpc/pseries/vdevice.c

Modified: stable/10/sys/conf/files.powerpc
==============================================================================
--- stable/10/sys/conf/files.powerpc	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/conf/files.powerpc	Tue May 13 18:06:26 2014	(r265969)
@@ -48,6 +48,7 @@ dev/ofw/ofw_bus_subr.c		optional	aim
 dev/ofw/ofw_console.c		optional	aim
 dev/ofw/ofw_disk.c		optional	ofwd aim
 dev/ofw/ofw_iicbus.c		optional	iicbus aim
+dev/ofw/ofw_nexus.c		optional	aim | fdt
 dev/ofw/ofw_standard.c		optional	aim powerpc
 dev/powermac_nvram/powermac_nvram.c optional	powermac_nvram powermac
 dev/quicc/quicc_bfe_fdt.c	optional	quicc mpc85xx

Modified: stable/10/sys/dev/fdt/fdt_common.c
==============================================================================
--- stable/10/sys/dev/fdt/fdt_common.c	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/dev/fdt/fdt_common.c	Tue May 13 18:06:26 2014	(r265969)
@@ -514,7 +514,7 @@ fdt_intr_to_rl(phandle_t node, struct re
 	pcell_t *intr;
 	pcell_t intr_cells;
 	int interrupt, trig, pol;
-	int i, intr_num, irq, rv;
+	int i, intr_num, rv;
 
 	if (OF_getproplen(node, "interrupts") <= 0)
 		/* Node does not have 'interrupts' property. */
@@ -566,8 +566,7 @@ fdt_intr_to_rl(phandle_t node, struct re
 		intr_sl[i].trig = trig;
 		intr_sl[i].pol = pol;
 
-		irq = FDT_MAP_IRQ(iph, interrupt);
-		resource_list_add(rl, SYS_RES_IRQ, i, irq, irq, 1);
+		resource_list_add(rl, SYS_RES_IRQ, i, interrupt, interrupt, 1);
 	}
 
 out:

Modified: stable/10/sys/dev/ofw/ofw_bus.h
==============================================================================
--- stable/10/sys/dev/ofw/ofw_bus.h	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/dev/ofw/ofw_bus.h	Tue May 13 18:06:26 2014	(r265969)
@@ -70,4 +70,16 @@ ofw_bus_get_type(device_t dev)
 	return (OFW_BUS_GET_TYPE(device_get_parent(dev), dev));
 }
 
+static __inline int
+ofw_bus_map_intr(device_t dev, phandle_t iparent, int irq)
+{
+	return (OFW_BUS_MAP_INTR(dev, dev, iparent, irq));
+}
+
+static __inline int
+ofw_bus_config_intr(device_t dev, int irq, int sense)
+{
+	return (OFW_BUS_CONFIG_INTR(dev, dev, irq, sense));
+}
+
 #endif /* !_DEV_OFW_OFW_BUS_H_ */

Modified: stable/10/sys/dev/ofw/ofw_bus_if.m
==============================================================================
--- stable/10/sys/dev/ofw/ofw_bus_if.m	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/dev/ofw/ofw_bus_if.m	Tue May 13 18:06:26 2014	(r265969)
@@ -56,6 +56,8 @@ CODE {
 	static ofw_bus_get_name_t ofw_bus_default_get_name;
 	static ofw_bus_get_node_t ofw_bus_default_get_node;
 	static ofw_bus_get_type_t ofw_bus_default_get_type;
+	static ofw_bus_map_intr_t ofw_bus_default_map_intr;
+	static ofw_bus_config_intr_t ofw_bus_default_config_intr;
 
 	static const struct ofw_bus_devinfo *
 	ofw_bus_default_get_devinfo(device_t bus, device_t dev)
@@ -98,6 +100,31 @@ CODE {
 
 		return (NULL);
 	}
+
+	int
+	ofw_bus_default_map_intr(device_t bus, device_t dev, phandle_t iparent,
+	    int irq)
+	{
+		/* Propagate up the bus hierarchy until someone handles it. */	
+		if (device_get_parent(bus) != NULL)
+			return OFW_BUS_MAP_INTR(device_get_parent(bus), dev,
+			    iparent, irq);
+
+		/* If that fails, then assume a one-domain system */
+		return (irq);
+	}
+
+	int
+	ofw_bus_default_config_intr(device_t bus, device_t dev, int irq,
+	    int sense)
+	{
+		/* Propagate up the bus hierarchy until someone handles it. */	
+		if (device_get_parent(bus) != NULL)
+			return OFW_BUS_CONFIG_INTR(device_get_parent(bus), dev,
+			    irq, sense);
+
+		return (ENXIO);
+	}
 };
 
 # Get the ofw_bus_devinfo struct for the device dev on the bus. Used for bus
@@ -143,3 +170,22 @@ METHOD const char * get_type {
 	device_t bus;
 	device_t dev;
 } DEFAULT ofw_bus_default_get_type;
+
+# Map an (interrupt parent, IRQ) pair to a unique system-wide interrupt number.
+METHOD int map_intr {
+	device_t bus;
+	device_t dev;
+	phandle_t iparent;
+	int irq;
+} DEFAULT ofw_bus_default_map_intr;
+
+# Configure an interrupt using the device-tree encoded sense key (the second
+# value in the interrupts property if interrupt-cells is 2). IRQ should be
+# encoded as from ofw_bus_map_intr().
+METHOD int config_intr {
+	device_t bus;
+	device_t dev;
+	int irq;
+	int sense;
+} DEFAULT ofw_bus_default_config_intr;
+

Copied and modified: stable/10/sys/dev/ofw/ofw_nexus.c (from r257016, head/sys/dev/ofw/ofw_nexus.c)
==============================================================================
--- head/sys/dev/ofw/ofw_nexus.c	Wed Oct 23 20:00:14 2013	(r257016, copy source)
+++ stable/10/sys/dev/ofw/ofw_nexus.c	Tue May 13 18:06:26 2014	(r265969)
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/openfirm.h>
 
 #include <machine/bus.h>
-#include <machine/intr_machdep.h>
 #include <machine/resource.h>
 
 /*
@@ -188,21 +187,17 @@ nexus_attach(device_t dev)
 
 	sc = device_get_softc(dev);
 
-	if (strcmp(device_get_name(device_get_parent(dev)), "root") == 0) {
-		node = OF_peer(0);
+	node = OF_peer(0);
 
-		sc->sc_intr_rman.rm_type = RMAN_ARRAY;
-		sc->sc_intr_rman.rm_descr = "Interrupts";
-		sc->sc_mem_rman.rm_type = RMAN_ARRAY;
-		sc->sc_mem_rman.rm_descr = "Device Memory";
-		if (rman_init(&sc->sc_intr_rman) != 0 ||
-		    rman_init(&sc->sc_mem_rman) != 0 ||
-		    rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0 ||
-		    rman_manage_region(&sc->sc_mem_rman, 0, BUS_SPACE_MAXADDR)
-		     != 0)
-			panic("%s: failed to set up rmans.", __func__);
-	} else
-		node = ofw_bus_get_node(dev);
+	sc->sc_intr_rman.rm_type = RMAN_ARRAY;
+	sc->sc_intr_rman.rm_descr = "Interrupts";
+	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+	sc->sc_mem_rman.rm_descr = "Device Memory";
+	if (rman_init(&sc->sc_intr_rman) != 0 ||
+	    rman_init(&sc->sc_mem_rman) != 0 ||
+	    rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0 ||
+	    rman_manage_region(&sc->sc_mem_rman, 0, BUS_SPACE_MAXADDR) != 0)
+		panic("%s: failed to set up rmans.", __func__);
 
 	/*
 	 * Allow devices to identify.
@@ -296,15 +291,11 @@ nexus_alloc_resource(device_t bus, devic
 	struct rman *rm;
 	struct resource *rv;
 	struct resource_list_entry *rle;
-	device_t nexus;
 	int isdefault, passthrough;
 
 	isdefault = (start == 0UL && end == ~0UL);
 	passthrough = (device_get_parent(child) != bus);
-	nexus = bus;
-	while (strcmp(device_get_name(device_get_parent(nexus)), "root") != 0)
-		nexus = device_get_parent(nexus);
-	sc = device_get_softc(nexus);
+	sc = device_get_softc(bus);
 	rle = NULL;
 
 	if (!passthrough && isdefault) {
@@ -471,9 +462,9 @@ nexus_setup_dinfo(device_t dev, phandle_
 	    (void **)&intr);
 	if (nintr > 0) {
 		iparent = 0;
-		OF_searchprop(node, "interrupt-parent", &iparent,
+		OF_searchencprop(node, "interrupt-parent", &iparent,
 		    sizeof(iparent));
-		OF_searchprop(iparent, "#interrupt-cells", &icells,
+		OF_searchencprop(iparent, "#interrupt-cells", &icells,
 		    sizeof(icells));
 		for (i = 0; i < nintr; i+= icells) {
 			intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]);

Copied: stable/10/sys/dev/ofw/ofw_nexus.h (from r257016, head/sys/dev/ofw/ofw_nexus.h)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/10/sys/dev/ofw/ofw_nexus.h	Tue May 13 18:06:26 2014	(r265969, copy of r257016, head/sys/dev/ofw/ofw_nexus.h)
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2010 Marius Strobl <marius at FreeBSD.org>
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _OFW_NEXUS_H_
+#define	_OFW_NEXUS_H_
+
+struct ofw_nexus_softc {
+	uint32_t	acells, scells;
+	struct rman	sc_intr_rman;
+	struct rman	sc_mem_rman;
+};
+
+DECLARE_CLASS(ofw_nexus_driver);
+
+#endif /* _OFW_NEXUS_H_ */

Modified: stable/10/sys/powerpc/include/intr_machdep.h
==============================================================================
--- stable/10/sys/powerpc/include/intr_machdep.h	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/powerpc/include/intr_machdep.h	Tue May 13 18:06:26 2014	(r265969)
@@ -56,5 +56,6 @@ int	powerpc_setup_intr(const char *, u_i
 int	powerpc_teardown_intr(void *);
 int	powerpc_bind_intr(u_int irq, u_char cpu);
 int	powerpc_config_intr(int, enum intr_trigger, enum intr_polarity);
+int	powerpc_fw_config_intr(int irq, int sense_code);
 
 #endif /* _MACHINE_INTR_MACHDEP_H_ */

Modified: stable/10/sys/powerpc/mpc85xx/atpic.c
==============================================================================
--- stable/10/sys/powerpc/mpc85xx/atpic.c	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/powerpc/mpc85xx/atpic.c	Tue May 13 18:06:26 2014	(r265969)
@@ -79,6 +79,9 @@ static void atpic_ipi(device_t, u_int);
 static void atpic_mask(device_t, u_int);
 static void atpic_unmask(device_t, u_int);
 
+static void atpic_ofw_translate_code(device_t, u_int irq, int code,
+    enum intr_trigger *trig, enum intr_polarity *pol);
+
 static device_method_t atpic_isa_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_identify, 	atpic_isa_identify),
@@ -94,6 +97,8 @@ static device_method_t atpic_isa_methods
 	DEVMETHOD(pic_mask,		atpic_mask),
 	DEVMETHOD(pic_unmask,		atpic_unmask),
 
+	DEVMETHOD(pic_translate_code,	atpic_ofw_translate_code),
+
 	{ 0, 0 },
 };
 
@@ -325,3 +330,35 @@ atpic_unmask(device_t dev, u_int irq)
 		atpic_write(sc, ATPIC_MASTER, 1, sc->sc_mask[ATPIC_MASTER]);
 	}
 }
+
+static void
+atpic_ofw_translate_code(device_t dev, u_int irq, int code,
+    enum intr_trigger *trig, enum intr_polarity *pol)
+{
+	switch (code) {
+	case 0:
+		/* Active L level */
+		*trig = INTR_TRIGGER_LEVEL;
+		*pol = INTR_POLARITY_LOW;
+		break;
+	case 1:
+		/* Active H level */
+		*trig = INTR_TRIGGER_LEVEL;
+		*pol = INTR_POLARITY_HIGH;
+		break;
+	case 2:
+		/* H to L edge */
+		*trig = INTR_TRIGGER_EDGE;
+		*pol = INTR_POLARITY_LOW;
+		break;
+	case 3:
+		/* L to H edge */
+		*trig = INTR_TRIGGER_EDGE;
+		*pol = INTR_POLARITY_HIGH;
+		break;
+	default:
+		*trig = INTR_TRIGGER_CONFORM;
+		*pol = INTR_POLARITY_CONFORM;
+	}
+}
+

Modified: stable/10/sys/powerpc/ofw/ofw_pci.c
==============================================================================
--- stable/10/sys/powerpc/ofw/ofw_pci.c	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/powerpc/ofw/ofw_pci.c	Tue May 13 18:06:26 2014	(r265969)
@@ -272,7 +272,7 @@ ofw_pci_route_interrupt(device_t bus, de
 	if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
 	    sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
 	    &iparent, maskbuf))
-		return (MAP_IRQ(iparent, mintr));
+		return (ofw_bus_map_intr(dev, iparent, mintr));
 
 	/* Maybe it's a real interrupt, not an intpin */
 	if (pin > 4)

Modified: stable/10/sys/powerpc/ofw/ofw_pcib_pci.c
==============================================================================
--- stable/10/sys/powerpc/ofw/ofw_pcib_pci.c	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/powerpc/ofw/ofw_pcib_pci.c	Tue May 13 18:06:26 2014	(r265969)
@@ -157,7 +157,7 @@ ofw_pcib_pci_route_interrupt(device_t br
 			 * it again on higher levels - that causes problems
 			 * in some cases, and never seems to be required.
 			 */
-			return (MAP_IRQ(iparent, mintr));
+			return (ofw_bus_map_intr(dev, iparent, mintr));
 		}
 	} else if (intpin >= 1 && intpin <= 4) {
 		/*

Modified: stable/10/sys/powerpc/ofw/ofw_pcibus.c
==============================================================================
--- stable/10/sys/powerpc/ofw/ofw_pcibus.c	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/powerpc/ofw/ofw_pcibus.c	Tue May 13 18:06:26 2014	(r265969)
@@ -215,15 +215,13 @@ ofw_pcibus_enum_devtree(device_t dev, u_
 					OF_getprop(OF_xref_phandle(iparent),
 					    "#interrupt-cells", &icells,
 					    sizeof(icells));
-					intr[0] = MAP_IRQ(iparent, intr[0]);
+					intr[0] = ofw_bus_map_intr(dev, iparent,
+					    intr[0]);
 				}
 
-				if (iparent != 0 && icells > 1) {
-					powerpc_config_intr(intr[0],
-					    (intr[1] & 1) ? INTR_TRIGGER_LEVEL :
-					    INTR_TRIGGER_EDGE,
-					    INTR_POLARITY_LOW);
-				}
+				if (iparent != 0 && icells > 1)
+					ofw_bus_config_intr(dev, intr[0],
+					    intr[1]);
 
 				resource_list_add(&dinfo->opd_dinfo.resources,
 				    SYS_RES_IRQ, 0, intr[0], intr[0], 1);
@@ -341,12 +339,13 @@ ofw_pcibus_assign_interrupt(device_t dev
 
 	isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr));
 	if (isz == sizeof(intr))
-		return ((iparent == -1) ? intr : MAP_IRQ(iparent, intr));
+		return ((iparent == -1) ? intr : ofw_bus_map_intr(dev, iparent,
+		    intr));
 
 	isz = OF_getprop(node, "interrupts", &intr, sizeof(intr));
 	if (isz == sizeof(intr)) {
 		if (iparent != -1)
-			intr = MAP_IRQ(iparent, intr);
+			intr = ofw_bus_map_intr(dev, iparent, intr);
 	} else {
 		/* No property: our best guess is the intpin. */
 		intr = pci_get_intpin(child);

Modified: stable/10/sys/powerpc/ofw/openpic_ofw.c
==============================================================================
--- stable/10/sys/powerpc/ofw/openpic_ofw.c	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/powerpc/ofw/openpic_ofw.c	Tue May 13 18:06:26 2014	(r265969)
@@ -61,6 +61,9 @@ __FBSDID("$FreeBSD$");
 static int	openpic_ofw_probe(device_t);
 static int	openpic_ofw_attach(device_t);
 
+static void	openpic_ofw_translate_code(device_t, u_int irq, int code,
+		    enum intr_trigger *trig, enum intr_polarity *pol);
+
 static device_method_t  openpic_ofw_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		openpic_ofw_probe),
@@ -76,6 +79,8 @@ static device_method_t  openpic_ofw_meth
 	DEVMETHOD(pic_mask,		openpic_mask),
 	DEVMETHOD(pic_unmask,		openpic_unmask),
 
+	DEVMETHOD(pic_translate_code,	openpic_ofw_translate_code),
+
 	DEVMETHOD_END
 };
 
@@ -127,3 +132,34 @@ openpic_ofw_attach(device_t dev)
 	return (openpic_common_attach(dev, xref));
 }
 
+static void
+openpic_ofw_translate_code(device_t dev, u_int irq, int code,
+    enum intr_trigger *trig, enum intr_polarity *pol)
+{
+	switch (code) {
+	case 0:
+		/* L to H edge */
+		*trig = INTR_TRIGGER_EDGE;
+		*pol = INTR_POLARITY_HIGH;
+		break;
+	case 1:
+		/* Active L level */
+		*trig = INTR_TRIGGER_LEVEL;
+		*pol = INTR_POLARITY_LOW;
+		break;
+	case 2:
+		/* Active H level */
+		*trig = INTR_TRIGGER_LEVEL;
+		*pol = INTR_POLARITY_HIGH;
+		break;
+	case 3:
+		/* H to L edge */
+		*trig = INTR_TRIGGER_EDGE;
+		*pol = INTR_POLARITY_LOW;
+		break;
+	default:
+		*trig = INTR_TRIGGER_CONFORM;
+		*pol = INTR_POLARITY_CONFORM;
+	}
+}
+

Modified: stable/10/sys/powerpc/powerpc/intr_machdep.c
==============================================================================
--- stable/10/sys/powerpc/powerpc/intr_machdep.c	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/powerpc/powerpc/intr_machdep.c	Tue May 13 18:06:26 2014	(r265969)
@@ -102,6 +102,7 @@ struct powerpc_intr {
 	cpuset_t cpu;
 	enum intr_trigger trig;
 	enum intr_polarity pol;
+	int	fwcode;
 };
 
 struct pic {
@@ -427,6 +428,9 @@ powerpc_enable_intr(void)
 		if (error)
 			continue;
 
+		if (i->trig == -1)
+			PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode,
+			    &i->trig, &i->pol);
 		if (i->trig != INTR_TRIGGER_CONFORM ||
 		    i->pol != INTR_POLARITY_CONFORM)
 			PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
@@ -469,15 +473,21 @@ powerpc_setup_intr(const char *name, u_i
 	if (!cold) {
 		error = powerpc_map_irq(i);
 
-		if (!error && (i->trig != INTR_TRIGGER_CONFORM ||
-		    i->pol != INTR_POLARITY_CONFORM))
-			PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
+		if (!error) {
+			if (i->trig == -1)
+				PIC_TRANSLATE_CODE(i->pic, i->intline,
+				    i->fwcode, &i->trig, &i->pol);
+	
+			if (i->trig != INTR_TRIGGER_CONFORM ||
+			    i->pol != INTR_POLARITY_CONFORM)
+				PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
 
-		if (!error && i->pic == root_pic)
-			PIC_BIND(i->pic, i->intline, i->cpu);
+			if (i->pic == root_pic)
+				PIC_BIND(i->pic, i->intline, i->cpu);
 
-		if (!error && enable)
-			PIC_ENABLE(i->pic, i->intline, i->vector);
+			if (enable)
+				PIC_ENABLE(i->pic, i->intline, i->vector);
+		}
 	}
 	return (error);
 }
@@ -504,6 +514,28 @@ powerpc_bind_intr(u_int irq, u_char cpu)
 #endif
 
 int
+powerpc_fw_config_intr(int irq, int sense_code)
+{
+	struct powerpc_intr *i;
+
+	i = intr_lookup(irq);
+	if (i == NULL)
+		return (ENOMEM);
+
+	i->trig = -1;
+	i->pol = INTR_POLARITY_CONFORM;
+	i->fwcode = sense_code;
+
+	if (!cold && i->pic != NULL) {
+		PIC_TRANSLATE_CODE(i->pic, i->intline, i->fwcode, &i->trig,
+		    &i->pol);
+		PIC_CONFIG(i->pic, i->intline, i->trig, i->pol);
+	}
+
+	return (0);
+}
+
+int
 powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol)
 {
 	struct powerpc_intr *i;

Modified: stable/10/sys/powerpc/powerpc/nexus.c
==============================================================================
--- stable/10/sys/powerpc/powerpc/nexus.c	Tue May 13 18:00:41 2014	(r265968)
+++ stable/10/sys/powerpc/powerpc/nexus.c	Tue May 13 18:06:26 2014	(r265969)
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_nexus.h>
 #include <dev/ofw/openfirm.h>
 
 #include <machine/bus.h>
@@ -63,260 +64,45 @@ __FBSDID("$FreeBSD$");
  *
  * Additionally, interrupt setup/teardown and some resource management are
  * done at this level.
- *
- * Maybe this code should get into dev/ofw to some extent, as some of it should
- * work for all Open Firmware based machines...
  */
 
-struct nexus_devinfo {
-	struct ofw_bus_devinfo	ndi_obdinfo;
-	struct resource_list	ndi_rl;
-};
-
-struct nexus_softc {
-	uint32_t	acells, scells;
-	struct rman	sc_intr_rman;
-	struct rman	sc_mem_rman;
-};
-
-static device_probe_t nexus_probe;
-static device_attach_t nexus_attach;
-static bus_print_child_t nexus_print_child;
-static bus_add_child_t nexus_add_child;
-static bus_probe_nomatch_t nexus_probe_nomatch;
 static bus_setup_intr_t nexus_setup_intr;
 static bus_teardown_intr_t nexus_teardown_intr;
-static bus_alloc_resource_t nexus_alloc_resource;
 static bus_activate_resource_t nexus_activate_resource;
 static bus_deactivate_resource_t nexus_deactivate_resource;
-static bus_adjust_resource_t nexus_adjust_resource;
-static bus_release_resource_t nexus_release_resource;
-static bus_get_resource_list_t nexus_get_resource_list;
 #ifdef SMP
 static bus_bind_intr_t nexus_bind_intr;
 #endif
 static bus_config_intr_t nexus_config_intr;
-static ofw_bus_get_devinfo_t nexus_get_devinfo;
-
-static int nexus_inlist(const char *, const char *const *);
-static struct nexus_devinfo * nexus_setup_dinfo(device_t, phandle_t);
-static void nexus_destroy_dinfo(struct nexus_devinfo *);
-static int nexus_print_res(struct nexus_devinfo *);
+static ofw_bus_map_intr_t nexus_ofw_map_intr;
+static ofw_bus_config_intr_t nexus_ofw_config_intr;
 
 static device_method_t nexus_methods[] = {
-	/* Device interface */
-	DEVMETHOD(device_probe,		nexus_probe),
-	DEVMETHOD(device_attach,	nexus_attach),
-	DEVMETHOD(device_detach,	bus_generic_detach),
-	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
-	DEVMETHOD(device_suspend,	bus_generic_suspend),
-	DEVMETHOD(device_resume,	bus_generic_resume),
-
 	/* Bus interface */
-	DEVMETHOD(bus_print_child,	nexus_print_child),
-	DEVMETHOD(bus_probe_nomatch,	nexus_probe_nomatch),
-	DEVMETHOD(bus_read_ivar,	bus_generic_read_ivar),
-	DEVMETHOD(bus_write_ivar,	bus_generic_write_ivar),
-	DEVMETHOD(bus_add_child,	nexus_add_child),
-	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
-	DEVMETHOD(bus_alloc_resource,	nexus_alloc_resource),
 	DEVMETHOD(bus_activate_resource,	nexus_activate_resource),
 	DEVMETHOD(bus_deactivate_resource,	nexus_deactivate_resource),
-	DEVMETHOD(bus_adjust_resource,	nexus_adjust_resource),
-	DEVMETHOD(bus_release_resource,	nexus_release_resource),
 	DEVMETHOD(bus_setup_intr,	nexus_setup_intr),
 	DEVMETHOD(bus_teardown_intr,	nexus_teardown_intr),
-	DEVMETHOD(bus_set_resource,	bus_generic_rl_set_resource),
-	DEVMETHOD(bus_get_resource,	bus_generic_rl_get_resource),
-	DEVMETHOD(bus_get_resource_list, nexus_get_resource_list),
 #ifdef SMP
 	DEVMETHOD(bus_bind_intr,	nexus_bind_intr),
 #endif
 	DEVMETHOD(bus_config_intr,	nexus_config_intr),
 
 	/* ofw_bus interface */
-	DEVMETHOD(ofw_bus_get_devinfo,	nexus_get_devinfo),
-	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
-	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
-	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
-	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
-	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
+	DEVMETHOD(ofw_bus_map_intr,	nexus_ofw_map_intr),
+	DEVMETHOD(ofw_bus_config_intr,	nexus_ofw_config_intr),
 
 	DEVMETHOD_END
 };
 
 static devclass_t nexus_devclass;
 
-DEFINE_CLASS_0(nexus, nexus_driver, nexus_methods, sizeof(struct nexus_softc));
+DEFINE_CLASS_1(nexus, nexus_driver, nexus_methods,
+    sizeof(struct ofw_nexus_softc), ofw_nexus_driver);
 EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0,
     BUS_PASS_BUS);
 MODULE_VERSION(nexus, 1);
 
-static const char *const nexus_excl_name[] = {
-	"FJSV,system",
-	"aliases",
-	"associations",
-	"chosen",
-	"cmp",
-	"counter-timer",	/* No separate device; handled by psycho/sbus */
-	"failsafe",
-	"memory",
-	"openprom",
-	"options",
-	"packages",
-	"physical-memory",
-	"rsc",
-	"sgcn",
-	"todsg",
-	"virtual-memory",
-	NULL
-};
-
-static const char *const nexus_excl_type[] = {
-	"core",
-	"cpu",
-	NULL
-};
-
-extern struct bus_space_tag nexus_bustag;
-extern struct bus_dma_tag nexus_dmatag;
-
-static int
-nexus_inlist(const char *name, const char *const *list)
-{
-	int i;
-
-	if (name == NULL)
-		return (0);
-	for (i = 0; list[i] != NULL; i++)
-		if (strcmp(name, list[i]) == 0)
-			return (1);
-	return (0);
-}
-
-#define	NEXUS_EXCLUDED(name, type)					\
-	(nexus_inlist((name), nexus_excl_name) ||			\
-	((type) != NULL && nexus_inlist((type), nexus_excl_type)))
-
-static int
-nexus_probe(device_t dev)
-{
-
-	/* Nexus does always match. */
-	device_set_desc(dev, "Open Firmware Nexus device");
-	return (0);
-}
-
-static int
-nexus_attach(device_t dev)
-{
-	struct nexus_devinfo *ndi;
-	struct nexus_softc *sc;
-	device_t cdev;
-	phandle_t node;
-
-	sc = device_get_softc(dev);
-
-	if (strcmp(device_get_name(device_get_parent(dev)), "root") == 0) {
-		node = OF_peer(0);
-
-		sc->sc_intr_rman.rm_type = RMAN_ARRAY;
-		sc->sc_intr_rman.rm_descr = "Interrupts";
-		sc->sc_mem_rman.rm_type = RMAN_ARRAY;
-		sc->sc_mem_rman.rm_descr = "Device Memory";
-		if (rman_init(&sc->sc_intr_rman) != 0 ||
-		    rman_init(&sc->sc_mem_rman) != 0 ||
-		    rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0 ||
-		    rman_manage_region(&sc->sc_mem_rman, 0, BUS_SPACE_MAXADDR)
-		     != 0)
-			panic("%s: failed to set up rmans.", __func__);
-	} else
-		node = ofw_bus_get_node(dev);
-
-	/*
-	 * Allow devices to identify.
-	 */
-	bus_generic_probe(dev);
-
-	/*
-	 * If no Open Firmware, bail early
-	 */
-	if (node == -1)
-		return (bus_generic_attach(dev));
-
-	/*
-	 * Some important numbers
-	 */
-	sc->acells = 2;
-	OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
-	sc->scells = 1;
-	OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));
-
-	/*
-	 * Now walk the OFW tree and attach top-level devices.
-	 */
-	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
-		if ((ndi = nexus_setup_dinfo(dev, node)) == NULL)
-			continue;
-		cdev = device_add_child(dev, NULL, -1);
-		if (cdev == NULL) {
-			device_printf(dev, "<%s>: device_add_child failed\n",
-			    ndi->ndi_obdinfo.obd_name);
-			nexus_destroy_dinfo(ndi);
-			continue;
-		}
-		device_set_ivars(cdev, ndi);
-	}
-	return (bus_generic_attach(dev));
-}
-
-static device_t
-nexus_add_child(device_t dev, u_int order, const char *name, int unit)
-{
-	device_t cdev;
-	struct nexus_devinfo *ndi;
-
-	cdev = device_add_child_ordered(dev, order, name, unit);
-	if (cdev == NULL)
-		return (NULL);
-
-	ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
-	ndi->ndi_obdinfo.obd_node = -1;
-	resource_list_init(&ndi->ndi_rl);
-	device_set_ivars(cdev, ndi);
-
-	return (cdev);
-}
-
-static int
-nexus_print_child(device_t bus, device_t child)
-{
-	int rv;
-
-	rv = bus_print_child_header(bus, child);
-	rv += nexus_print_res(device_get_ivars(child));
-	rv += bus_print_child_footer(bus, child);
-	return (rv);
-}
-
-static void
-nexus_probe_nomatch(device_t bus, device_t child)
-{
-	const char *name, *type;
-
-	if (!bootverbose)
-		return;
-
-	name = ofw_bus_get_name(child);
-	type = ofw_bus_get_type(child);
-
-	device_printf(bus, "<%s>",
-	    name != NULL ? name : "unknown");
-	nexus_print_res(device_get_ivars(child));
-	printf(" type %s (no driver attached)\n",
-	    type != NULL ? type : "unknown");
-}
-
 static int
 nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r,
     int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
@@ -370,71 +156,20 @@ nexus_config_intr(device_t dev, int irq,
 	return (powerpc_config_intr(irq, trig, pol));
 } 
 
-static struct resource *
-nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
-    u_long start, u_long end, u_long count, u_int flags)
+static int
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq)
 {
-	struct nexus_softc *sc;
-	struct rman *rm;
-	struct resource *rv;
-	struct resource_list_entry *rle;
-	device_t nexus;
-	int isdefault, passthrough;
-
-	isdefault = (start == 0UL && end == ~0UL);
-	passthrough = (device_get_parent(child) != bus);
-	nexus = bus;
-	while (strcmp(device_get_name(device_get_parent(nexus)), "root") != 0)
-		nexus = device_get_parent(nexus);
-	sc = device_get_softc(nexus);
-	rle = NULL;
-
-	if (!passthrough && isdefault) {
-		rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child),
-		    type, *rid);
-		if (rle == NULL)
-			return (NULL);
-		if (rle->res != NULL)
-			panic("%s: resource entry is busy", __func__);
-		start = rle->start;
-		count = ulmax(count, rle->count);
-		end = ulmax(rle->end, start + count - 1);
-	}
-
-	switch (type) {
-	case SYS_RES_IRQ:
-		rm = &sc->sc_intr_rman;
-		break;
-	case SYS_RES_MEMORY:
-		rm = &sc->sc_mem_rman;
-		break;
-	default:
-		return (NULL);
-	}
-
-	rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
-	    child);
-	if (rv == NULL)
-		return (NULL);
-	rman_set_rid(rv, *rid);
-
-	if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type,
-	    *rid, rv) != 0) {
-		rman_release_resource(rv);
-		return (NULL);
-	}
-
-	if (!passthrough && rle != NULL) {
-		rle->res = rv;
-		rle->start = rman_get_start(rv);
-		rle->end = rman_get_end(rv);
-		rle->count = rle->end - rle->start + 1;
-	}
-
-	return (rv);
+	return (MAP_IRQ(iparent, irq));
 }
 
 static int
+nexus_ofw_config_intr(device_t dev, device_t child, int irq, int sense)
+{
+ 
+	return (powerpc_fw_config_intr(irq, sense));
+} 
+
+static int
 nexus_activate_resource(device_t bus __unused, device_t child __unused,
     int type, int rid __unused, struct resource *r)
 {
@@ -476,164 +211,3 @@ nexus_deactivate_resource(device_t bus _
 	return (rman_deactivate_resource(r));
 }
 
-static int
-nexus_adjust_resource(device_t bus, device_t child __unused, int type,
-    struct resource *r, u_long start, u_long end)
-{
-	struct nexus_softc *sc;
-	struct rman *rm;
-	device_t nexus;
-
-	nexus = bus;
-	while (strcmp(device_get_name(device_get_parent(nexus)), "root") != 0)
-		nexus = device_get_parent(nexus);
-	sc = device_get_softc(nexus);
-	switch (type) {
-	case SYS_RES_IRQ:
-		rm = &sc->sc_intr_rman;
-		break;
-	case SYS_RES_MEMORY:
-		rm = &sc->sc_mem_rman;
-		break;
-	default:
-		return (EINVAL);
-	}
-	if (rm == NULL)
-		return (ENXIO);
-	if (rman_is_region_manager(r, rm) == 0)
-		return (EINVAL);
-	return (rman_adjust_resource(r, start, end));
-}
-
-static int
-nexus_release_resource(device_t bus __unused, device_t child, int type,
-    int rid, struct resource *r)
-{
-	int error;
-
-	if ((rman_get_flags(r) & RF_ACTIVE) != 0) {
-		error = bus_deactivate_resource(child, type, rid, r);
-		if (error)
-			return (error);
-	}
-	return (rman_release_resource(r));
-}
-
-static struct resource_list *
-nexus_get_resource_list(device_t bus __unused, device_t child)
-{
-	struct nexus_devinfo *ndi;
-
-	ndi = device_get_ivars(child);
-	return (&ndi->ndi_rl);
-}
-
-static const struct ofw_bus_devinfo *
-nexus_get_devinfo(device_t bus __unused, device_t child)
-{
-	struct nexus_devinfo *ndi;
-
-	ndi = device_get_ivars(child);
-	return (&ndi->ndi_obdinfo);
-}
-
-static struct nexus_devinfo *
-nexus_setup_dinfo(device_t dev, phandle_t node)
-{
-	struct nexus_softc *sc;
-	struct nexus_devinfo *ndi;
-	uint32_t *reg, *intr, icells;
-	uint64_t phys, size;
-	phandle_t iparent;
-	int i, j;
-	int nintr;
-	int nreg;
-
-	sc = device_get_softc(dev);
-
-	ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
-	if (ofw_bus_gen_setup_devinfo(&ndi->ndi_obdinfo, node) != 0) {
-		free(ndi, M_DEVBUF);
-		return (NULL);
-	}
-	if (NEXUS_EXCLUDED(ndi->ndi_obdinfo.obd_name,
-	    ndi->ndi_obdinfo.obd_type)) {
-		ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
-		free(ndi, M_DEVBUF);
-		return (NULL);
-	}
-
-	resource_list_init(&ndi->ndi_rl);
-	nreg = OF_getencprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
-	if (nreg == -1)
-		nreg = 0;
-	if (nreg % (sc->acells + sc->scells) != 0) {
-		if (bootverbose)
-			device_printf(dev, "Malformed reg property on <%s>\n",
-			    ndi->ndi_obdinfo.obd_name);
-		nreg = 0;
-	}
-
-	for (i = 0; i < nreg; i += sc->acells + sc->scells) {
-		phys = size = 0;
-		for (j = 0; j < sc->acells; j++) {
-			phys <<= 32;
-			phys |= reg[i + j];
-		}
-		for (j = 0; j < sc->scells; j++) {
-			size <<= 32;
-			size |= reg[i + sc->acells + j];
-		}
-		/* Skip the dummy reg property of glue devices like ssm(4). */
-		if (size != 0)
-			resource_list_add(&ndi->ndi_rl, SYS_RES_MEMORY, i,
-			    phys, phys + size - 1, size);
-	}
-	free(reg, M_OFWPROP);
-
-	nintr = OF_getencprop_alloc(node, "interrupts",  sizeof(*intr),
-	    (void **)&intr);
-	if (nintr > 0) {
-		iparent = 0;
-		OF_searchprop(node, "interrupt-parent", &iparent,
-		    sizeof(iparent));
-		OF_searchprop(iparent, "#interrupt-cells", &icells,
-		    sizeof(icells));
-		for (i = 0; i < nintr; i+= icells) {
-			intr[i] = MAP_IRQ(iparent, intr[i]);
-			resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
-			    intr[i], 1);
-			if (icells > 1) {
-				powerpc_config_intr(intr[i], (intr[i+1] & 1) ?
-				    INTR_TRIGGER_LEVEL : INTR_TRIGGER_EDGE,
-				    INTR_POLARITY_LOW);
-			}
-		}
-		free(intr, M_OFWPROP);
-	}
-
-	return (ndi);
-}
-
-static void
-nexus_destroy_dinfo(struct nexus_devinfo *ndi)
-{
-
-	resource_list_free(&ndi->ndi_rl);
-	ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
-	free(ndi, M_DEVBUF);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list