svn commit: r299241 - in head/sys: conf dev/bhnd dev/bhnd/bhndb dev/bhnd/cores/chipc dev/bhnd/nvram dev/bhnd/tools dev/bwn modules/bhnd modules/bhnd/bhndb modules/bhnd/bhndb_pci modules/bhnd/cores/...

Adrian Chadd adrian at FreeBSD.org
Sun May 8 19:14:07 UTC 2016


Author: adrian
Date: Sun May  8 19:14:05 2016
New Revision: 299241
URL: https://svnweb.freebsd.org/changeset/base/299241

Log:
  [bhnd] Initial bhnd(4) SPROM/NVRAM support.
  
  This adds support for the NVRAM handling and the basic SPROM
  hardware used on siba(4) and bcma(4) devices, including:
  
  * SPROM directly attached to the PCI core, accessible via PCI configuration
    space.
  * SPROM attached to later ChipCommon cores.
  * SPROM variables vended from the parent SoC bus (e.g. via a directly-attached
    flash device).
  
  Additional improvements to the NVRAM/SPROM interface will
  be required, but this changeset stands alone as working
  checkpoint.
  
  Submitted by:	Landon Fuller <landonf at landonf.org>
  Reviewed by:	Michael Zhilin <mizkha at gmail.com> (Broadcom MIPS support)
  Differential Revision:	https://reviews.freebsd.org/D6196

Added:
  head/sys/dev/bhnd/bhndb/bhndb_pci_sprom.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_sprom.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/bhnd_spromreg.h
     - copied, changed from r299234, head/sys/dev/bhnd/bhndb/bhndb_pcivar.h
  head/sys/dev/bhnd/nvram/bhnd_spromvar.h
     - copied, changed from r299234, head/sys/dev/bhnd/bhndb/bhndb_pcivar.h
  head/sys/dev/bhnd/nvram/nvram_map   (contents, props changed)
  head/sys/dev/bhnd/nvram/nvram_subr.c   (contents, props changed)
  head/sys/dev/bhnd/nvram/nvramvar.h   (contents, props changed)
  head/sys/dev/bhnd/tools/nvram_map_gen.awk   (contents, props changed)
  head/sys/dev/bhnd/tools/nvram_map_gen.sh   (contents, props changed)
Deleted:
  head/sys/dev/bhnd/bcmsrom_fmt.h
  head/sys/dev/bhnd/bcmsrom_tbl.h
  head/sys/modules/bhnd/nvram/Makefile
Modified:
  head/sys/conf/files
  head/sys/conf/kmod.mk
  head/sys/dev/bhnd/bhnd.c
  head/sys/dev/bhnd/bhnd.h
  head/sys/dev/bhnd/bhnd_bus_if.m
  head/sys/dev/bhnd/bhnd_ids.h
  head/sys/dev/bhnd/bhndb/bhndb.c
  head/sys/dev/bhnd/bhndb/bhndb_pci.c
  head/sys/dev/bhnd/bhndb/bhndb_pcireg.h
  head/sys/dev/bhnd/bhndb/bhndb_pcivar.h
  head/sys/dev/bhnd/cores/chipc/chipc.c
  head/sys/dev/bhnd/cores/chipc/chipcreg.h
  head/sys/dev/bhnd/cores/chipc/chipcvar.h
  head/sys/dev/bhnd/nvram/bhnd_nvram.h
  head/sys/dev/bhnd/nvram/bhnd_nvram_if.m
  head/sys/dev/bwn/bwn_mac.c
  head/sys/modules/bhnd/Makefile
  head/sys/modules/bhnd/bhndb/Makefile
  head/sys/modules/bhnd/bhndb_pci/Makefile
  head/sys/modules/bhnd/cores/bhnd_chipc/Makefile
  head/sys/modules/bwn_pci/Makefile
Directory Properties:
  head/sys/dev/bhnd/tools/bus_macro.sh   (props changed)

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/conf/files	Sun May  8 19:14:05 2016	(r299241)
@@ -9,6 +9,16 @@ acpi_quirks.h			optional acpi				   \
 	compile-with	"${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \
 	no-obj no-implicit-rule before-depend				   \
 	clean		"acpi_quirks.h"
+bhnd_nvram_map.h		optional bhndbus | bhnd			   \
+	dependency	"$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \
+	compile-with	"$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -h" \
+	no-obj no-implicit-rule before-depend				   \
+	clean		"bhnd_nvram_map.h"
+bhnd_nvram_map_data.h		optional bhndbus | bhnd			   \
+	dependency	"$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \
+	compile-with	"$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -d" \
+	no-obj no-implicit-rule before-depend				   \
+	clean		"bhnd_nvram_map_data.h"
 #
 # The 'fdt_dtb_file' target covers an actual DTB file name, which is derived
 # from the specified source (DTS) file: <platform>.dts -> <platform>.dtb
@@ -1121,6 +1131,7 @@ dev/bhnd/bhndb/bhndb_hwdata.c		optional 
 dev/bhnd/bhndb/bhndb_if.m		optional bhndbus | bhndb
 dev/bhnd/bhndb/bhndb_pci.c		optional bhndbus pci | bhndb pci
 dev/bhnd/bhndb/bhndb_pci_hwdata.c 	optional bhndbus pci | bhndb pci
+dev/bhnd/bhndb/bhndb_pci_sprom.c	optional bhndbus pci | bhndb pci
 dev/bhnd/bhndb/bhndb_subr.c		optional bhndbus pci | bhndb
 dev/bhnd/bcma/bcma.c			optional bhndbus | bcma
 dev/bhnd/bcma/bcma_bhndb.c		optional bhndbus | bcma bhndb
@@ -1132,6 +1143,8 @@ dev/bhnd/cores/pci/bhnd_pci.c		optional 
 dev/bhnd/cores/pci/bhnd_pci_hostb.c	optional bhndbus pci | bhndb pci
 dev/bhnd/cores/pci/bhnd_pcib.c		optional bhnd_pcib bhnd pci
 dev/bhnd/nvram/bhnd_nvram_if.m		optional bhndbus | bhnd
+dev/bhnd/nvram/bhnd_sprom.c		optional bhndbus | bhnd
+dev/bhnd/nvram/nvram_subr.c		optional bhndbus | bhnd
 dev/bhnd/siba/siba.c			optional bhndbus | siba
 dev/bhnd/siba/siba_bhndb.c		optional bhndbus | siba bhndb
 dev/bhnd/siba/siba_nexus.c		optional siba_nexus siba

Modified: head/sys/conf/kmod.mk
==============================================================================
--- head/sys/conf/kmod.mk	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/conf/kmod.mk	Sun May  8 19:14:05 2016	(r299241)
@@ -411,6 +411,26 @@ ${_i}devs.h: ${SYSDIR}/tools/${_i}devs2h
 .endif
 .endfor # _i
 
+.if !empty(SRCS:Mbhnd_nvram_map.h)
+CLEANFILES+=	bhnd_nvram_map.h
+bhnd_nvram_map.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \
+    ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
+    ${SYSDIR}/dev/bhnd/nvram/nvram_map
+bhnd_nvram_map.h:
+	${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
+	    ${SYSDIR}/dev/bhnd/nvram/nvram_map -h
+.endif
+
+.if !empty(SRCS:Mbhnd_nvram_map_data.h)
+CLEANFILES+=	bhnd_nvram_map_data.h
+bhnd_nvram_map_data.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \
+    ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
+    ${SYSDIR}/dev/bhnd/nvram/nvram_map
+bhnd_nvram_map_data.h:
+	${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \
+	    ${SYSDIR}/dev/bhnd/nvram/nvram_map -d
+.endif
+
 .if !empty(SRCS:Musbdevs.h)
 CLEANFILES+=	usbdevs.h
 usbdevs.h: ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs

Modified: head/sys/dev/bhnd/bhnd.c
==============================================================================
--- head/sys/dev/bhnd/bhnd.c	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/dev/bhnd/bhnd.c	Sun May  8 19:14:05 2016	(r299241)
@@ -58,11 +58,14 @@ __FBSDID("$FreeBSD$");
 #include <sys/rman.h>
 #include <machine/resource.h>
 
-#include "bhnd.h"
-#include "bhndvar.h"
+#include "nvram/bhnd_nvram.h"
 
+#include "bhnd_chipc_if.h"
 #include "bhnd_nvram_if.h"
 
+#include "bhnd.h"
+#include "bhndvar.h"
+
 MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures");
 
 /**
@@ -386,23 +389,27 @@ bhnd_generic_is_region_valid(device_t de
 static device_t
 find_nvram_child(device_t dev)
 {
-	device_t chipc, nvram;
+	device_t	chipc, nvram;
 
 	/* Look for a directly-attached NVRAM child */
-	nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass),
-	    -1);
-	if (nvram == NULL)
-		return (NULL);
+	nvram = device_find_child(dev, "bhnd_nvram", 0);
+	if (nvram != NULL)
+		return (nvram);
 
-	/* Further checks require a bhnd(4) bus */
+	/* Remaining checks are only applicable when searching a bhnd(4)
+	 * bus. */
 	if (device_get_devclass(dev) != bhnd_devclass)
 		return (NULL);
 
-	/* Look for a ChipCommon-attached OTP device */
+	/* Look for a ChipCommon device */
 	if ((chipc = bhnd_find_child(dev, BHND_DEVCLASS_CC, -1)) != NULL) {
-		/* Recursively search the ChipCommon device */
-		if ((nvram = find_nvram_child(chipc)) != NULL)
-			return (nvram);
+		bhnd_nvram_src_t src;
+
+		/* Query the NVRAM source and determine whether it's
+		 * accessible via the ChipCommon device */
+		src = BHND_CHIPC_NVRAM_SRC(chipc);
+		if (BHND_NVRAM_SRC_CC(src))
+			return (chipc);
 	}
 
 	/* Not found */
@@ -410,22 +417,26 @@ find_nvram_child(device_t dev)
 }
 
 /**
- * Default bhnd(4) bus driver implementation of BHND_BUS_READ_NVRAM_VAR().
+ * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR().
+ * 
+ * This implementation searches @p dev for a usable NVRAM child device:
+ * - The first child device implementing the bhnd_nvram devclass is
+ *   returned, otherwise
+ * - If @p dev is a bhnd(4) bus, a ChipCommon core that advertises an
+ *   attached NVRAM source.
  * 
- * This implementation searches @p dev for a valid NVRAM device. If no NVRAM
- * child device is found on @p dev, the request is delegated to the
- * BHND_BUS_READ_NVRAM_VAR() method on the parent
- * of @p dev.
+ * If no usable child device is found on @p dev, the request is delegated to
+ * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev.
  */
 static int
-bhnd_generic_read_nvram_var(device_t dev, device_t child, const char *name,
+bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name,
     void *buf, size_t *size)
 {
 	device_t nvram;
 
 	/* Try to find an NVRAM device applicable to @p child */
 	if ((nvram = find_nvram_child(dev)) == NULL)
-		return (BHND_BUS_READ_NVRAM_VAR(device_get_parent(dev), child,
+		return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
 		    name, buf, size));
 
 	return BHND_NVRAM_GETVAR(nvram, name, buf, size);
@@ -682,7 +693,7 @@ static device_method_t bhnd_methods[] = 
 	DEVMETHOD(bhnd_bus_get_probe_order,	bhnd_generic_get_probe_order),
 	DEVMETHOD(bhnd_bus_is_region_valid,	bhnd_generic_is_region_valid),
 	DEVMETHOD(bhnd_bus_is_hw_disabled,	bhnd_bus_generic_is_hw_disabled),
-	DEVMETHOD(bhnd_bus_read_nvram_var,	bhnd_generic_read_nvram_var),
+	DEVMETHOD(bhnd_bus_get_nvram_var,	bhnd_generic_get_nvram_var),
 	DEVMETHOD(bhnd_bus_read_1,		bhnd_read_1),
 	DEVMETHOD(bhnd_bus_read_2,		bhnd_read_2),
 	DEVMETHOD(bhnd_bus_read_4,		bhnd_read_4),

Modified: head/sys/dev/bhnd/bhnd.h
==============================================================================
--- head/sys/dev/bhnd/bhnd.h	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/dev/bhnd/bhnd.h	Sun May  8 19:14:05 2016	(r299241)
@@ -464,6 +464,55 @@ bhnd_get_chipid(device_t dev) {
 	return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev));
 };
 
+/**
+ * Determine an NVRAM variable's expected size.
+ *
+ * @param 	dev	A bhnd bus child device.
+ * @param	name	The variable name.
+ * @param[out]	len	On success, the variable's size, in bytes.
+ *
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+static inline int
+bhnd_nvram_getvarlen(device_t dev, const char *name, size_t *len)
+{
+	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, NULL,
+	    len));
+}
+
+/**
+ * Read an NVRAM variable.
+ *
+ * @param 	dev	A bhnd bus child device.
+ * @param	name	The NVRAM variable name.
+ * @param	buf	A buffer large enough to hold @p len bytes. On success,
+ * 			the requested value will be written to this buffer.
+ * @param	len	The required variable length.
+ *
+ * @retval 0		success
+ * @retval ENOENT	The requested variable was not found.
+ * @retval EINVAL	If @p len does not match the actual variable size.
+ * @retval non-zero	If reading @p name otherwise fails, a regular unix
+ *			error code will be returned.
+ */
+static inline int
+bhnd_nvram_getvar(device_t dev, const char *name, void *buf, size_t len)
+{
+	size_t	var_len;
+	int	error;
+
+	if ((error = bhnd_nvram_getvarlen(dev, name, &var_len)))
+		return (error);
+
+	if (len != var_len)
+		return (EINVAL);
+
+	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, buf,
+	    &len));
+}
 
 /**
  * Allocate a resource from a device's parent bhnd(4) bus.

Modified: head/sys/dev/bhnd/bhnd_bus_if.m
==============================================================================
--- head/sys/dev/bhnd/bhnd_bus_if.m	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/dev/bhnd/bhnd_bus_if.m	Sun May  8 19:14:05 2016	(r299241)
@@ -96,7 +96,7 @@ CODE {
 	}
 	
 	static int
-	bhnd_bus_null_read_nvram_var(device_t dev, device_t child,
+	bhnd_bus_null_get_nvram_var(device_t dev, device_t child,
 	    const char *name, void *buf, size_t *size)
 	{
 		return (ENOENT);
@@ -403,13 +403,13 @@ METHOD int get_region_addr {
  * @retval non-zero	If reading @p name otherwise fails, a regular unix
  *			error code will be returned.
  */
-METHOD int read_nvram_var {
+METHOD int get_nvram_var {
 	device_t	 dev;
 	device_t	 child;
 	const char	*name;
 	void		*buf;
 	size_t		*size;
-} DEFAULT bhnd_bus_null_read_nvram_var;
+} DEFAULT bhnd_bus_null_get_nvram_var;
 
 
 /** An implementation of bus_read_1() compatible with bhnd_resource */

Modified: head/sys/dev/bhnd/bhnd_ids.h
==============================================================================
--- head/sys/dev/bhnd/bhnd_ids.h	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/dev/bhnd/bhnd_ids.h	Sun May  8 19:14:05 2016	(r299241)
@@ -328,6 +328,7 @@
 #define	BHND_CHIPID_BCM43428		43428		/* 43228 chipcommon chipid (OTP, RBBU) */
 #define	BHND_CHIPID_BCM43431		43431		/* 4331  chipcommon chipid (OTP, RBBU) */
 #define	BHND_CHIPID_BCM43460		43460		/* 4360  chipcommon chipid (OTP, RBBU) */
+#define	BHND_CHIPID_BCM43462		0xA9C6		/* 43462 chipcommon chipid */
 #define	BHND_CHIPID_BCM4325		0x4325		/* 4325 chip id */
 #define	BHND_CHIPID_BCM4328		0x4328		/* 4328 chip id */
 #define	BHND_CHIPID_BCM4329		0x4329		/* 4329 chipcommon chipid */
@@ -345,6 +346,7 @@
 #define	BHND_CHIPID_BCM4334		0x4334		/* 4334 chipcommon chipid */
 #define	BHND_CHIPID_BCM4335		0x4335		/* 4335 chipcommon chipid */
 #define	BHND_CHIPID_BCM4360		0x4360          /* 4360 chipcommon chipid */
+#define	BHND_CHIPID_BCM43602		0xaa52          /* 43602 chipcommon chipid */
 #define	BHND_CHIPID_BCM4352		0x4352          /* 4352 chipcommon chipid */
 #define	BHND_CHIPID_BCM43526		0xAA06
 #define	BHND_CHIPID_BCM43341		43341		/* 43341 chipcommon chipid */
@@ -433,7 +435,6 @@
 #define	BHND_PKGID_BCM4335_FCBGAD	(0x3)		/* FCBGA Debug Debug/Dev All if's. */
 #define	BHND_PKGID_PKG_MASK_BCM4335	(0x3)
 
-
 /* Broadcom Core IDs */
 #define	BHND_COREID_INVALID		0x700		/* Invalid coreid */
 #define	BHND_COREID_CC			0x800		/* chipcommon core */

Modified: head/sys/dev/bhnd/bhndb/bhndb.c
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb.c	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/dev/bhnd/bhndb/bhndb.c	Sun May  8 19:14:05 2016	(r299241)
@@ -51,6 +51,10 @@ __FBSDID("$FreeBSD$");
 #include <dev/bhnd/bhndreg.h>
 
 #include <dev/bhnd/cores/chipc/chipcreg.h>
+#include <dev/bhnd/nvram/bhnd_nvram.h>
+
+#include "bhnd_chipc_if.h"
+#include "bhnd_nvram_if.h"
 
 #include "bhndbvar.h"
 #include "bhndb_bus_if.h"
@@ -609,7 +613,7 @@ bhndb_generic_init_full_config(device_t 
 		goto cleanup;
 	}
 
-	if (bootverbose)
+	if (bootverbose || BHNDB_DEBUG(PRIO))
 		device_printf(sc->dev, "%s resource configuration\n", hw->name);
 
 	/* Release existing resource state */
@@ -1298,9 +1302,10 @@ bhndb_retain_dynamic_window(struct bhndb
 	    rman_get_size(r));
 	if (error) {
 		device_printf(sc->dev, "dynamic window initialization "
-			"for 0x%llx-0x%llx failed\n",
+			"for 0x%llx-0x%llx failed: %d\n",
 			(unsigned long long) r_start,
-			(unsigned long long) r_start + r_size - 1);
+			(unsigned long long) r_start + r_size - 1,
+			error);
 		return (NULL);
 	}
 
@@ -1709,6 +1714,26 @@ bhndb_io_resource(struct bhndb_softc *sc
 	return (dwa);
 }
 
+/**
+ * Default bhndb(4) implementation of BHND_BUS_GET_NVRAM_VAR().
+ */
+static int
+bhndb_get_nvram_var(device_t dev, device_t child, const char *name,
+    void *buf, size_t *size)
+{
+	device_t nvram;
+
+	/* Look for a directly-attached NVRAM child */
+	nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass),
+	    0);
+	if (nvram != NULL)
+		return (BHND_NVRAM_GETVAR(nvram, name, buf, size));
+
+	/* Otherwise, delegate to our parent */
+	return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child,
+	    name, buf, size));
+}
+
 /*
  * BHND_BUS_(READ|WRITE_* implementations
  */
@@ -1936,6 +1961,7 @@ static device_method_t bhndb_methods[] =
 	DEVMETHOD(bhnd_bus_get_chipid,		bhndb_get_chipid),
 	DEVMETHOD(bhnd_bus_activate_resource,	bhndb_activate_bhnd_resource),
 	DEVMETHOD(bhnd_bus_deactivate_resource,	bhndb_deactivate_bhnd_resource),
+	DEVMETHOD(bhnd_bus_get_nvram_var,	bhndb_get_nvram_var),
 	DEVMETHOD(bhnd_bus_read_1,		bhndb_bus_read_1),
 	DEVMETHOD(bhnd_bus_read_2,		bhndb_bus_read_2),
 	DEVMETHOD(bhnd_bus_read_4,		bhndb_bus_read_4),

Modified: head/sys/dev/bhnd/bhndb/bhndb_pci.c
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_pci.c	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/dev/bhnd/bhndb/bhndb_pci.c	Sun May  8 19:14:05 2016	(r299241)
@@ -61,15 +61,19 @@ __FBSDID("$FreeBSD$");
 #include "bhndb_pcivar.h"
 #include "bhndb_private.h"
 
-static int	bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc);
-static int	bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc);
+static int		bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc);
+static int		bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc);
 
-static int	bhndb_pci_compat_setregwin(struct bhndb_pci_softc *,
-		    const struct bhndb_regwin *, bhnd_addr_t);
-static int	bhndb_pci_fast_setregwin(struct bhndb_pci_softc *,
-		    const struct bhndb_regwin *, bhnd_addr_t);
+static int		bhndb_pci_compat_setregwin(struct bhndb_pci_softc *,
+			    const struct bhndb_regwin *, bhnd_addr_t);
+static int		bhndb_pci_fast_setregwin(struct bhndb_pci_softc *,
+			    const struct bhndb_regwin *, bhnd_addr_t);
 
-static void	bhndb_init_sromless_pci_config(struct bhndb_pci_softc *sc);
+static void		bhndb_init_sromless_pci_config(
+			    struct bhndb_pci_softc *sc);
+
+static bus_addr_t	bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc);
+static size_t		bhndb_pci_sprom_size(struct bhndb_pci_softc *sc);
 
 /** 
  * Default bhndb_pci implementation of device_probe().
@@ -104,13 +108,14 @@ bhndb_pci_attach(device_t dev)
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
+	sc->parent = device_get_parent(dev);
 
 	/* Enable PCI bus mastering */
-	pci_enable_busmaster(device_get_parent(dev));
+	pci_enable_busmaster(sc->parent);
 
 	/* Determine our bridge device class */
 	sc->pci_devclass = BHND_DEVCLASS_PCI;
-	if (pci_find_cap(device_get_parent(dev), PCIY_EXPRESS, &reg) == 0)
+	if (pci_find_cap(sc->parent, PCIY_EXPRESS, &reg) == 0)
 		sc->pci_devclass = BHND_DEVCLASS_PCIE;
 
 	/* Enable clocks (if supported by this hardware) */
@@ -142,6 +147,8 @@ bhndb_pci_init_full_config(device_t dev,
     const struct bhndb_hw_priority *hw_prio_table)
 {
 	struct bhndb_pci_softc	*sc;
+	device_t		 nv_dev;
+	bus_size_t		 nv_sz;
 	int			 error;
 
 	sc = device_get_softc(dev);
@@ -153,9 +160,126 @@ bhndb_pci_init_full_config(device_t dev,
 	/* Fix-up power on defaults for SROM-less devices. */
 	bhndb_init_sromless_pci_config(sc);
 
+	/* If SPROM is mapped directly into BAR0, add NVRAM device. */
+	nv_sz = bhndb_pci_sprom_size(sc);
+	if (nv_sz > 0) {
+		struct bhndb_devinfo	*dinfo;
+		const char		*dname;
+
+		if (bootverbose) {
+			device_printf(dev, "found SPROM (%zu bytes)\n", nv_sz);
+		}
+
+		/* Add sprom device */
+		dname = "bhnd_nvram";
+		if ((nv_dev = BUS_ADD_CHILD(dev, 0, dname, -1)) == NULL) {
+			device_printf(dev, "failed to add sprom device\n");
+			return (ENXIO);
+		}
+
+		/* Initialize device address space and resource covering the
+		 * BAR0 SPROM shadow. */
+		dinfo = device_get_ivars(nv_dev);
+		dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE;
+		error = bus_set_resource(nv_dev, SYS_RES_MEMORY, 0,
+		    bhndb_pci_sprom_addr(sc), nv_sz);
+
+		if (error) {
+			device_printf(dev,
+			    "failed to register sprom resources\n");
+			return (error);
+		}
+
+		/* Attach the device */
+		if ((error = device_probe_and_attach(nv_dev))) {
+			device_printf(dev, "sprom attach failed\n");
+			return (error);
+		}
+	}
+
 	return (0);
 }
 
+static const struct bhndb_regwin *
+bhndb_pci_sprom_regwin(struct bhndb_pci_softc *sc)
+{
+	struct bhndb_resources		*bres;
+	const struct bhndb_hwcfg	*cfg;
+	const struct bhndb_regwin	*sprom_win;
+
+	bres = sc->bhndb.bus_res;
+	cfg = bres->cfg;
+
+	sprom_win = bhndb_regwin_find_type(cfg->register_windows,
+	    BHNDB_REGWIN_T_SPROM, BHNDB_PCI_V0_BAR0_SPROM_SIZE);
+
+	return (sprom_win);
+}
+
+static bus_addr_t
+bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc)
+{
+	const struct bhndb_regwin	*sprom_win;
+	struct resource			*r;
+
+	/* Fetch the SPROM register window */
+	sprom_win = bhndb_pci_sprom_regwin(sc);
+	KASSERT(sprom_win != NULL, ("requested sprom address on PCI_V2+"));
+
+	/* Fetch the associated resource */
+	r = bhndb_find_regwin_resource(sc->bhndb.bus_res, sprom_win);
+	KASSERT(r != NULL, ("missing resource for sprom window\n"));
+
+	return (rman_get_start(r) + sprom_win->win_offset);
+}
+
+static bus_size_t
+bhndb_pci_sprom_size(struct bhndb_pci_softc *sc)
+{
+	const struct bhndb_regwin	*sprom_win;
+	uint32_t			 sctl;
+	bus_size_t			 sprom_sz;
+
+	sprom_win = bhndb_pci_sprom_regwin(sc);
+
+	/* PCI_V2 and later devices map SPROM/OTP via ChipCommon */
+	if (sprom_win == NULL)
+		return (0);
+
+	/* Determine SPROM size */
+	sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4);
+	if (sctl & BHNDB_PCI_SPROM_BLANK)
+		return (0);
+
+	switch (sctl & BHNDB_PCI_SPROM_SZ_MASK) {
+	case BHNDB_PCI_SPROM_SZ_1KB:
+		sprom_sz = (1 * 1024);
+		break;
+
+	case BHNDB_PCI_SPROM_SZ_4KB:
+		sprom_sz = (4 * 1024);
+		break;
+
+	case BHNDB_PCI_SPROM_SZ_16KB:
+		sprom_sz = (16 * 1024);
+		break;
+
+	case BHNDB_PCI_SPROM_SZ_RESERVED:
+	default:
+		device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl);
+		return (0);
+	}
+
+	if (sprom_sz > sprom_win->win_size) {
+		device_printf(sc->dev,
+		    "PCI sprom size (0x%x) overruns defined register window\n",
+		    sctl);
+		return (0);
+	}
+
+	return (sprom_sz);
+}
+
 /*
  * On devices without a SROM, the PCI(e) cores will be initialized with
  * their Power-on-Reset defaults; this can leave two of the BAR0 PCI windows
@@ -274,7 +398,7 @@ bhndb_pci_detach(device_t dev)
 		return (error);
 
 	/* Disable PCI bus mastering */
-	pci_disable_busmaster(device_get_parent(dev));
+	pci_disable_busmaster(sc->parent);
 
 	return (0);
 }
@@ -301,19 +425,18 @@ static int
 bhndb_pci_compat_setregwin(struct bhndb_pci_softc *sc,
     const struct bhndb_regwin *rw, bhnd_addr_t addr)
 {
-	device_t	parent;
 	int		error;
-
-	parent = sc->bhndb.parent_dev;
+	int		reg;
 
 	if (rw->win_type != BHNDB_REGWIN_T_DYN)
 		return (ENODEV);
 
+	reg = rw->d.dyn.cfg_offset;
 	for (u_int i = 0; i < BHNDB_PCI_BARCTRL_WRITE_RETRY; i++) {
 		if ((error = bhndb_pci_fast_setregwin(sc, rw, addr)))
 			return (error);
 
-		if (pci_read_config(parent, rw->d.dyn.cfg_offset, 4) == addr)
+		if (pci_read_config(sc->parent, reg, 4) == addr)
 			return (0);
 
 		DELAY(10);
@@ -330,8 +453,6 @@ static int
 bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc,
     const struct bhndb_regwin *rw, bhnd_addr_t addr)
 {
-	device_t parent = sc->bhndb.parent_dev;
-
 	/* The PCI bridge core only supports 32-bit addressing, regardless
 	 * of the bus' support for 64-bit addressing */
 	if (addr > UINT32_MAX)
@@ -343,7 +464,7 @@ bhndb_pci_fast_setregwin(struct bhndb_pc
 		if (addr % rw->win_size != 0)
 			return (EINVAL);
 
-		pci_write_config(parent, rw->d.dyn.cfg_offset, addr, 4);
+		pci_write_config(sc->parent, rw->d.dyn.cfg_offset, addr, 4);
 		break;
 	default:
 		return (ENODEV);
@@ -366,7 +487,6 @@ bhndb_pci_fast_setregwin(struct bhndb_pc
 static int
 bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc)
 {
-	device_t		pci_parent;
 	uint32_t		gpio_in, gpio_out, gpio_en;
 	uint32_t		gpio_flags;
 	uint16_t		pci_status;
@@ -375,35 +495,33 @@ bhndb_enable_pci_clocks(struct bhndb_pci
 	if (sc->pci_devclass != BHND_DEVCLASS_PCI)
 		return (0);
 
-	pci_parent = device_get_parent(sc->dev);
-
 	/* Read state of XTAL pin */
-	gpio_in = pci_read_config(pci_parent, BHNDB_PCI_GPIO_IN, 4);
+	gpio_in = pci_read_config(sc->parent, BHNDB_PCI_GPIO_IN, 4);
 	if (gpio_in & BHNDB_PCI_GPIO_XTAL_ON)
 		return (0); /* already enabled */
 
 	/* Fetch current config */
-	gpio_out = pci_read_config(pci_parent, BHNDB_PCI_GPIO_OUT, 4);
-	gpio_en = pci_read_config(pci_parent, BHNDB_PCI_GPIO_OUTEN, 4);
+	gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
+	gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4);
 
 	/* Set PLL_OFF/XTAL_ON pins to HIGH and enable both pins */
 	gpio_flags = (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
 	gpio_out |= gpio_flags;
 	gpio_en |= gpio_flags;
 
-	pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
-	pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
+	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
+	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
 	DELAY(1000);
 
 	/* Reset PLL_OFF */
 	gpio_out &= ~BHNDB_PCI_GPIO_PLL_OFF;
-	pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
+	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
 	DELAY(5000);
 
 	/* Clear any PCI 'sent target-abort' flag. */
-	pci_status = pci_read_config(pci_parent, PCIR_STATUS, 2);
+	pci_status = pci_read_config(sc->parent, PCIR_STATUS, 2);
 	pci_status &= ~PCIM_STATUS_STABORT;
-	pci_write_config(pci_parent, PCIR_STATUS, pci_status, 2);
+	pci_write_config(sc->parent, PCIR_STATUS, pci_status, 2);
 
 	return (0);
 }
@@ -416,31 +534,28 @@ bhndb_enable_pci_clocks(struct bhndb_pci
 static int
 bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc)
 {
-	device_t	parent_dev;
 	uint32_t	gpio_out, gpio_en;
 
 	/* Only supported and required on PCI devices */
 	if (sc->pci_devclass != BHND_DEVCLASS_PCI)
 		return (0);
 
-	parent_dev = device_get_parent(sc->dev);
-
 	// TODO: Check board flags for BFL2_XTALBUFOUTEN?
 	// TODO: Check PCI core revision?
 	// TODO: Switch to 'slow' clock?
 
 	/* Fetch current config */
-	gpio_out = pci_read_config(parent_dev, BHNDB_PCI_GPIO_OUT, 4);
-	gpio_en = pci_read_config(parent_dev, BHNDB_PCI_GPIO_OUTEN, 4);
+	gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
+	gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4);
 
 	/* Set PLL_OFF to HIGH, XTAL_ON to LOW. */
 	gpio_out &= ~BHNDB_PCI_GPIO_XTAL_ON;
 	gpio_out |= BHNDB_PCI_GPIO_PLL_OFF;
-	pci_write_config(parent_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
+	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
 
 	/* Enable both output pins */
 	gpio_en |= (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
-	pci_write_config(parent_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
+	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
 
 	return (0);
 }

Added: head/sys/dev/bhnd/bhndb/bhndb_pci_sprom.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/bhnd/bhndb/bhndb_pci_sprom.c	Sun May  8 19:14:05 2016	(r299241)
@@ -0,0 +1,210 @@
+/*-
+ * Copyright (c) 2015-2016 Landon Fuller <landon at landonf.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,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ *    redistribution must be conditioned upon including a substantially
+ *    similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * BHNDB PCI SPROM driver.
+ * 
+ * Provides support for early PCI bridge cores that vend SPROM CSRs
+ * via PCI configuration space.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/limits.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/bhnd/bhnd.h>
+#include <dev/bhnd/cores/pci/bhnd_pci_hostbvar.h>
+#include <dev/bhnd/nvram/bhnd_spromvar.h>
+
+#include "bhnd_nvram_if.h"
+#include "bhndb_pcireg.h"
+#include "bhndb_pcivar.h"
+
+struct bhndb_pci_sprom_softc {
+	device_t		 dev;
+	struct bhnd_resource	*sprom_res;	/**< SPROM resource */
+	int			 sprom_rid;	/**< SPROM RID */
+	struct bhnd_sprom	 shadow;	/**< SPROM shadow */
+	struct mtx		 mtx;		/**< SPROM shadow mutex */
+};
+
+#define	SPROM_LOCK_INIT(sc) \
+	mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
+	    "BHND PCI SPROM lock", MTX_DEF)
+#define	SPROM_LOCK(sc)			mtx_lock(&(sc)->mtx)
+#define	SPROM_UNLOCK(sc)			mtx_unlock(&(sc)->mtx)
+#define	SPROM_LOCK_ASSERT(sc, what)	mtx_assert(&(sc)->mtx, what)
+#define	SPROM_LOCK_DESTROY(sc)		mtx_destroy(&(sc)->mtx)
+
+static int
+bhndb_pci_sprom_probe(device_t dev)
+{
+	device_t	bridge, bus;
+
+	/* Our parent must be a PCI-BHND bridge with an attached bhnd bus */
+	bridge = device_get_parent(dev);
+	if (device_get_driver(bridge) != &bhndb_pci_driver)
+		return (ENXIO);
+	
+	bus = device_find_child(bridge, devclass_get_name(bhnd_devclass), 0);
+	if (bus == NULL)
+		return (ENXIO);
+
+	/* Found */
+	device_set_desc(dev, "PCI-BHNDB SPROM/OTP");
+	if (!bootverbose)
+		device_quiet(dev);
+
+	/* Refuse wildcard attachments */
+	return (BUS_PROBE_NOWILDCARD);
+}
+
+static int
+bhndb_pci_sprom_attach(device_t dev)
+{
+	struct bhndb_pci_sprom_softc	*sc;
+	int				 error;
+	
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	/* Allocate SPROM resource */
+	sc->sprom_rid = 0;
+	sc->sprom_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY,
+	    &sc->sprom_rid, RF_ACTIVE);
+	if (sc->sprom_res == NULL) {
+		device_printf(dev, "failed to allocate resources\n");
+		return (ENXIO);
+	}
+
+	/* Initialize SPROM shadow */
+	if ((error = bhnd_sprom_init(&sc->shadow, sc->sprom_res, 0))) {
+		device_printf(dev, "unrecognized SPROM format\n");
+		goto failed;
+	}
+
+	/* Initialize mutex */
+	SPROM_LOCK_INIT(sc);
+
+	return (0);
+	
+failed:
+	bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid,
+	    sc->sprom_res);
+	return (error);
+}
+
+static int
+bhndb_pci_sprom_resume(device_t dev)
+{
+	return (0);
+}
+
+static int
+bhndb_pci_sprom_suspend(device_t dev)
+{
+	return (0);
+}
+
+static int
+bhndb_pci_sprom_detach(device_t dev)
+{
+	struct bhndb_pci_sprom_softc	*sc;
+	
+	sc = device_get_softc(dev);
+
+	bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid,
+	    sc->sprom_res);
+	bhnd_sprom_fini(&sc->shadow);
+	SPROM_LOCK_DESTROY(sc);
+
+	return (0);
+}
+
+static int
+bhndb_pci_sprom_getvar(device_t dev, const char *name, void *buf, size_t *len)
+{
+	struct bhndb_pci_sprom_softc	*sc;
+	int				 error;
+
+	sc = device_get_softc(dev);
+
+	SPROM_LOCK(sc);
+	error = bhnd_sprom_getvar(&sc->shadow, name, buf, len);
+	SPROM_UNLOCK(sc);
+
+	return (error);
+}
+
+static int
+bhndb_pci_sprom_setvar(device_t dev, const char *name, const void *buf,
+    size_t len)
+{
+	struct bhndb_pci_sprom_softc	*sc;
+	int				 error;
+
+	sc = device_get_softc(dev);
+
+	SPROM_LOCK(sc);
+	error = bhnd_sprom_setvar(&sc->shadow, name, buf, len);
+	SPROM_UNLOCK(sc);
+
+	return (error);
+}
+
+static device_method_t bhndb_pci_sprom_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,			bhndb_pci_sprom_probe),
+	DEVMETHOD(device_attach,		bhndb_pci_sprom_attach),
+	DEVMETHOD(device_resume,		bhndb_pci_sprom_resume),
+	DEVMETHOD(device_suspend,		bhndb_pci_sprom_suspend),
+	DEVMETHOD(device_detach,		bhndb_pci_sprom_detach),
+
+	/* NVRAM interface */
+	DEVMETHOD(bhnd_nvram_getvar,		bhndb_pci_sprom_getvar),
+	DEVMETHOD(bhnd_nvram_setvar,		bhndb_pci_sprom_setvar),
+
+	DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(bhnd_nvram, bhndb_pci_sprom_driver, bhndb_pci_sprom_methods, sizeof(struct bhndb_pci_sprom_softc));
+
+DRIVER_MODULE(bhndb_pci_sprom, bhndb, bhndb_pci_sprom_driver, bhnd_nvram_devclass, NULL, NULL);
+MODULE_DEPEND(bhndb_pci_sprom, bhnd, 1, 1, 1);
+MODULE_VERSION(bhndb_pci_sprom, 1);

Modified: head/sys/dev/bhnd/bhndb/bhndb_pcireg.h
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_pcireg.h	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/dev/bhnd/bhndb/bhndb_pcireg.h	Sun May  8 19:14:05 2016	(r299241)
@@ -205,13 +205,17 @@
 #define	BHNDB_PCI_SBIM_MASK_SERR	0x4	/* backplane SBErr interrupt mask */
 
 /* BHNDB_PCI_SPROM_CONTROL */
-#define	BHNDB_PCI_SPROM_SZ_MSK		0x02	/* SPROM Size Mask */
-#define	BHNDB_PCI_SPROM_LOCKED		0x08	/* SPROM Locked */
-#define	BHNDB_PCI_SPROM_BLANK		0x04	/* indicating a blank SPROM */
-#define	BHNDB_PCI_SPROM_WRITEEN		0x10	/* SPROM write enable */
-#define	BHNDB_PCI_SPROM_BOOTROM_WE	0x20	/* external bootrom write enable */
-#define	BHNDB_PCI_SPROM_BACKPLANE_EN	0x40	/* Enable indirect backplane access */
-#define	BHNDB_PCI_SPROM_OTPIN_USE	0x80	/* device OTP In use */
+#define	BHNDB_PCI_SPROM_SZ_MASK		0x03	/**< sprom size mask */
+#define	BHNDB_PCI_SPROM_SZ_1KB		0x00	/**< 1KB sprom size */
+#define	BHNDB_PCI_SPROM_SZ_4KB		0x01	/**< 4KB sprom size */
+#define	BHNDB_PCI_SPROM_SZ_16KB		0x02	/**< 16KB sprom size */
+#define	BHNDB_PCI_SPROM_SZ_RESERVED	0x03	/**< unsupported sprom size */
+#define	BHNDB_PCI_SPROM_LOCKED		0x08	/**< sprom locked */
+#define	BHNDB_PCI_SPROM_BLANK		0x04	/**< sprom blank */
+#define	BHNDB_PCI_SPROM_WRITEEN		0x10	/**< sprom write enable */
+#define	BHNDB_PCI_SPROM_BOOTROM_WE	0x20	/**< external bootrom write enable */
+#define	BHNDB_PCI_SPROM_BACKPLANE_EN	0x40	/**< enable indirect backplane access (BHNDB_PCI_BACKPLANE_*) */
+#define	BHNDB_PCI_SPROM_OTPIN_USE	0x80	/**< device OTP in use */
 
 
 /* PCI (non-PCIe) BHNDB_PCI_GPIO_OUTEN  */

Modified: head/sys/dev/bhnd/bhndb/bhndb_pcivar.h
==============================================================================
--- head/sys/dev/bhnd/bhndb/bhndb_pcivar.h	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/dev/bhnd/bhndb/bhndb_pcivar.h	Sun May  8 19:14:05 2016	(r299241)
@@ -51,6 +51,7 @@ typedef int (*bhndb_pci_set_regwin_t)(st
 struct bhndb_pci_softc {
 	struct bhndb_softc	bhndb;		/**< parent softc */
 	device_t		dev;		/**< bridge device */
+	device_t		parent;		/**< parent PCI device */
 	bhnd_devclass_t		pci_devclass;	/**< PCI core's devclass */
 	bhndb_pci_set_regwin_t	set_regwin;	/**< regwin handler */
 };

Modified: head/sys/dev/bhnd/cores/chipc/chipc.c
==============================================================================
--- head/sys/dev/bhnd/cores/chipc/chipc.c	Sun May  8 18:30:08 2016	(r299240)
+++ head/sys/dev/bhnd/cores/chipc/chipc.c	Sun May  8 19:14:05 2016	(r299241)
@@ -52,6 +52,8 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/bhnd/bhnd.h>
 
+#include "bhnd_nvram_if.h"
+
 #include "chipcreg.h"
 #include "chipcvar.h"
 
@@ -73,13 +75,44 @@ static const struct bhnd_device chipc_de
 
 /* Device quirks table */
 static struct bhnd_device_quirk chipc_quirks[] = {
-	{ BHND_HWREV_RANGE	(0,	21),	CHIPC_QUIRK_ALWAYS_HAS_SPROM },
-	{ BHND_HWREV_EQ		(22),		CHIPC_QUIRK_SPROM_CHECK_CST_R22 },
-	{ BHND_HWREV_RANGE	(23,	31),	CHIPC_QUIRK_SPROM_CHECK_CST_R23 },
-	{ BHND_HWREV_GTE	(35),		CHIPC_QUIRK_SUPPORTS_NFLASH },
+	{ BHND_HWREV_GTE	(32),	CHIPC_QUIRK_SUPPORTS_SPROM },
+	{ BHND_HWREV_GTE	(35),	CHIPC_QUIRK_SUPPORTS_NFLASH },
 	BHND_DEVICE_QUIRK_END
 };
 
+/* Chip-specific quirks table */
+static struct bhnd_chip_quirk chipc_chip_quirks[] = {
+	/* 4331 12x9 packages */
+	{{ BHND_CHIP_IP(4331, 4331TN) },
+		CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM
+	},
+	{{ BHND_CHIP_IP(4331, 4331TNA0) },
+		CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM
+	},
+
+	/* 4331 12x12 packages */
+	{{ BHND_CHIP_IPR(4331, 4331TT, HWREV_GTE(1)) },
+		CHIPC_QUIRK_4331_EXTPA2_MUX_SPROM
+	},
+
+	/* 4331 (all packages/revisions) */
+	{{ BHND_CHIP_ID(4331) },
+		CHIPC_QUIRK_4331_EXTPA_MUX_SPROM
+	},
+
+	/* 4360 family (all revs <= 2) */
+	{{ BHND_CHIP_IR(4352, HWREV_LTE(2)) },
+		CHIPC_QUIRK_4360_FEM_MUX_SPROM },
+	{{ BHND_CHIP_IR(43460, HWREV_LTE(2)) },
+		CHIPC_QUIRK_4360_FEM_MUX_SPROM },
+	{{ BHND_CHIP_IR(43462, HWREV_LTE(2)) },
+		CHIPC_QUIRK_4360_FEM_MUX_SPROM },
+	{{ BHND_CHIP_IR(43602, HWREV_LTE(2)) },
+		CHIPC_QUIRK_4360_FEM_MUX_SPROM },
+
+	BHND_CHIP_QUIRK_END
+};
+
 /* quirk and capability flag convenience macros */
 #define	CHIPC_QUIRK(_sc, _name)	\
     ((_sc)->quirks & CHIPC_QUIRK_ ## _name)
@@ -91,7 +124,13 @@ static struct bhnd_device_quirk chipc_qu
     KASSERT(CHIPC_QUIRK((_sc), name), ("quirk " __STRING(_name) " not set"))
 
 #define	CHIPC_ASSERT_CAP(_sc, name)	\
-    KASSERT(CHIPC_CAP((_sc), name), ("capability " __STRING(_name) " not set"))    
+    KASSERT(CHIPC_CAP((_sc), name), ("capability " __STRING(_name) " not set"))
+
+static bhnd_nvram_src_t	chipc_nvram_identify(struct chipc_softc *sc);
+static int		chipc_sprom_init(struct chipc_softc *);
+static int		chipc_enable_sprom_pins(struct chipc_softc *);
+static int		chipc_disable_sprom_pins(struct chipc_softc *);
+
 
 static int
 chipc_probe(device_t dev)
@@ -119,6 +158,9 @@ chipc_attach(device_t dev)
 	sc->dev = dev;
 	sc->quirks = bhnd_device_quirks(dev, chipc_devices,
 	    sizeof(chipc_devices[0]));
+	sc->quirks |= bhnd_chip_quirks(dev, chipc_chip_quirks);
+	
+	CHIPC_LOCK_INIT(sc);
 
 	/* Allocate bus resources */

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


More information about the svn-src-all mailing list