aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/bhnd/bhnd.h2
-rw-r--r--sys/dev/bhnd/bhnd_bus_if.m8
-rw-r--r--sys/dev/bhnd/bhnd_subr.c19
-rw-r--r--sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m25
-rw-r--r--sys/dev/bhnd/cores/chipc/chipc.c77
-rw-r--r--sys/dev/bhnd/cores/chipc/chipcreg.h10
6 files changed, 115 insertions, 26 deletions
diff --git a/sys/dev/bhnd/bhnd.h b/sys/dev/bhnd/bhnd.h
index 82a1ed8bdb5c..53215cf49648 100644
--- a/sys/dev/bhnd/bhnd.h
+++ b/sys/dev/bhnd/bhnd.h
@@ -356,6 +356,8 @@ int bhnd_bus_generic_activate_resource (device_t dev,
int bhnd_bus_generic_deactivate_resource (device_t dev,
device_t child, int type, int rid,
struct bhnd_resource *r);
+bhnd_attach_type bhnd_bus_generic_get_attach_type(device_t dev,
+ device_t child);
diff --git a/sys/dev/bhnd/bhnd_bus_if.m b/sys/dev/bhnd/bhnd_bus_if.m
index e7a117c9cd3b..e523496f2c0c 100644
--- a/sys/dev/bhnd/bhnd_bus_if.m
+++ b/sys/dev/bhnd/bhnd_bus_if.m
@@ -55,12 +55,6 @@ CODE {
panic("bhnd_bus_get_chipid unimplemented");
}
- static bhnd_attach_type
- bhnd_bus_null_get_attach_type(device_t dev, device_t child)
- {
- panic("bhnd_bus_get_attach_type unimplemented");
- }
-
static int
bhnd_bus_null_read_board_info(device_t dev, device_t child,
struct bhnd_board_info *info)
@@ -203,7 +197,7 @@ METHOD const struct bhnd_chipid * get_chipid {
METHOD bhnd_attach_type get_attach_type {
device_t dev;
device_t child;
-} DEFAULT bhnd_bus_null_get_attach_type;
+} DEFAULT bhnd_bus_generic_get_attach_type;
/**
* Attempt to read the BHND board identification from the parent bus.
diff --git a/sys/dev/bhnd/bhnd_subr.c b/sys/dev/bhnd/bhnd_subr.c
index 087208c7583c..67b11cb5088a 100644
--- a/sys/dev/bhnd/bhnd_subr.c
+++ b/sys/dev/bhnd/bhnd_subr.c
@@ -1158,3 +1158,22 @@ bhnd_bus_generic_deactivate_resource(device_t dev, device_t child,
return (EINVAL);
};
+
+/**
+ * Helper function for implementing BHND_BUS_GET_ATTACH_TYPE().
+ *
+ * This implementation of BHND_BUS_GET_ATTACH_TYPE() simply calls the
+ * BHND_BUS_GET_ATTACH_TYPE() method of the parent of @p dev.
+ */
+bhnd_attach_type
+bhnd_bus_generic_get_attach_type(device_t dev, device_t child)
+{
+ /* iterate from cores via bhnd to bridge or SoC */
+ if (device_get_parent(dev) != NULL)
+ return (BHND_BUS_GET_ATTACH_TYPE(device_get_parent(dev),
+ child));
+
+ panic("bhnd_bus_get_attach_type unimplemented");
+ /* Unreachable */
+ return (BHND_ATTACH_ADAPTER);
+}
diff --git a/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m b/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
index 8a214d682d5a..0098b91f03e7 100644
--- a/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
+++ b/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
@@ -39,6 +39,29 @@ INTERFACE bhnd_chipc;
HEADER {
/* forward declarations */
struct chipc_caps;
+ struct chipc_caps *bhnd_chipc_generic_get_caps(device_t dev);
+}
+
+CODE {
+
+ /**
+ * Helper function for implementing BHND_CHIPC_GET_CAPS().
+ *
+ * This implementation of BHND_CHIPC_GET_CAPS() simply calls the
+ * BHND_CHIPC_GET_CAPS() method of the parent of @p dev.
+ */
+ struct chipc_caps*
+ bhnd_chipc_generic_get_caps(device_t dev)
+ {
+
+ if (device_get_parent(dev) != NULL)
+ return (BHND_CHIPC_GET_CAPS(device_get_parent(dev)));
+
+ panic("bhnd_chipc_generic_get_caps unimplemented");
+ /* Unreachable */
+ return (NULL);
+ }
+
}
/**
@@ -77,7 +100,7 @@ METHOD void write_chipctrl {
*/
METHOD struct chipc_caps * get_caps {
device_t dev;
-}
+} DEFAULT bhnd_chipc_generic_get_caps;
/**
* Enable hardware access to the SPROM.
diff --git a/sys/dev/bhnd/cores/chipc/chipc.c b/sys/dev/bhnd/cores/chipc/chipc.c
index 6fce0dae6359..c4c7df1c8653 100644
--- a/sys/dev/bhnd/cores/chipc/chipc.c
+++ b/sys/dev/bhnd/cores/chipc/chipc.c
@@ -110,12 +110,13 @@ static const struct chipc_hint {
u_int region;
} chipc_hints[] = {
// FIXME: cfg/spi port1.1 mapping on siba(4) SoCs
+ // FIXME: IRQ shouldn't be hardcoded
/* device unit type rid base size port,region */
{ "bhnd_nvram", 0, SYS_RES_MEMORY, 0, CHIPC_SPROM_OTP, CHIPC_SPROM_OTP_SIZE, 0,0 },
{ "uart", 0, SYS_RES_MEMORY, 0, CHIPC_UART0_BASE, CHIPC_UART_SIZE, 0,0 },
- { "uart", 0, SYS_RES_IRQ, 0, 0, RM_MAX_END },
+ { "uart", 0, SYS_RES_IRQ, 0, 2, 1 },
{ "uart", 1, SYS_RES_MEMORY, 0, CHIPC_UART1_BASE, CHIPC_UART_SIZE, 0,0 },
- { "uart", 1, SYS_RES_IRQ, 0, 0, RM_MAX_END },
+ { "uart", 1, SYS_RES_IRQ, 0, 2, 1 },
{ "spi", 0, SYS_RES_MEMORY, 0, 0, RM_MAX_END, 1,1 },
{ "spi", 0, SYS_RES_MEMORY, 1, CHIPC_SFLASH_BASE, CHIPC_SFLASH_SIZE, 0,0 },
{ "cfi", 0, SYS_RES_MEMORY, 0, 0, RM_MAX_END, 1,1},
@@ -480,12 +481,30 @@ chipc_add_child(device_t dev, u_int order, const char *name, int unit)
struct chipc_devinfo *dinfo;
const struct chipc_hint *hint;
device_t child;
+ devclass_t child_dc;
int error;
+ int busrel_unit;
child = device_add_child_ordered(dev, order, name, unit);
if (child == NULL)
return (NULL);
+ /* system-wide device unit */
+ unit = device_get_unit(child);
+ child_dc = device_get_devclass(child);
+
+ busrel_unit = 0;
+ for (int i = 0; i < unit; i++) {
+ device_t tmp;
+
+ tmp = devclass_get_device(child_dc, i);
+ if (tmp != NULL && (device_get_parent(tmp) == dev))
+ busrel_unit++;
+ }
+
+ /* bus-wide device unit (override unit for further hint matching) */
+ unit = busrel_unit;
+
dinfo = malloc(sizeof(struct chipc_devinfo), M_BHND, M_NOWAIT);
if (dinfo == NULL) {
device_delete_child(dev, child);
@@ -504,9 +523,14 @@ chipc_add_child(device_t dev, u_int order, const char *name, int unit)
bhnd_addr_t region_addr;
bhnd_size_t region_size;
+ /* Check device name */
if (strcmp(hint->name, name) != 0)
continue;
+ /* Check device unit */
+ if (hint->unit >= 0 && unit != hint->unit)
+ continue;
+
switch (hint->type) {
case SYS_RES_IRQ:
/* Add child resource */
@@ -535,8 +559,9 @@ chipc_add_child(device_t dev, u_int order, const char *name, int unit)
/* Verify requested range is mappable */
if (hint->base > region_size ||
- hint->size > region_size ||
- region_size - hint->base < hint->size )
+ (hint->size != RM_MAX_END &&
+ (hint->size > region_size ||
+ region_size - hint->base < hint->size )))
{
device_printf(dev,
"%s%u.%u region cannot map requested range "
@@ -546,9 +571,17 @@ chipc_add_child(device_t dev, u_int order, const char *name, int unit)
hint->size);
}
- /* Add child resource */
- error = bus_set_resource(child, hint->type,
- hint->rid, region_addr + hint->base, hint->size);
+ /*
+ * Add child resource. If hint doesn't define the end
+ * of resource window (RX_MAX_END), use end of region.
+ */
+
+ error = bus_set_resource(child,
+ hint->type,
+ hint->rid, region_addr + hint->base,
+ (hint->size == RM_MAX_END) ?
+ region_size - hint->base :
+ hint->size);
if (error) {
device_printf(dev,
"bus_set_resource() failed for %s: %d\n",
@@ -754,8 +787,10 @@ chipc_alloc_resource(device_t dev, device_t child, int type,
if (rle->res != NULL) {
device_printf(dev,
- "resource entry %#x type %d for child %s is busy\n",
- *rid, type, device_get_nameunit(child));
+ "resource entry %#x type %d for child %s is busy "
+ "[%d]\n",
+ *rid, type, device_get_nameunit(child),
+ rman_get_flags(rle->res));
return (NULL);
}
@@ -821,10 +856,11 @@ static int
chipc_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
- struct chipc_softc *sc;
- struct chipc_region *cr;
- struct rman *rm;
- int error;
+ struct chipc_softc *sc;
+ struct chipc_region *cr;
+ struct rman *rm;
+ struct resource_list_entry *rle;
+ int error;
sc = device_get_softc(dev);
@@ -853,6 +889,11 @@ chipc_release_resource(device_t dev, device_t child, int type, int rid,
/* Drop allocation reference */
chipc_release_region(sc, cr, RF_ALLOCATED);
+ /* Clear reference from the resource list entry if exists */
+ rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child), type, rid);
+ if (rle != NULL)
+ rle->res = NULL;
+
return (0);
}
@@ -1238,6 +1279,15 @@ chipc_write_chipctrl(device_t dev, uint32_t value, uint32_t mask)
CHIPC_UNLOCK(sc);
}
+static struct chipc_caps *
+chipc_get_caps(device_t dev)
+{
+ struct chipc_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (&sc->caps);
+}
+
static device_method_t chipc_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, chipc_probe),
@@ -1279,6 +1329,7 @@ static device_method_t chipc_methods[] = {
DEVMETHOD(bhnd_chipc_write_chipctrl, chipc_write_chipctrl),
DEVMETHOD(bhnd_chipc_enable_sprom, chipc_enable_sprom_pins),
DEVMETHOD(bhnd_chipc_disable_sprom, chipc_disable_sprom_pins),
+ DEVMETHOD(bhnd_chipc_get_caps, chipc_get_caps),
DEVMETHOD_END
};
diff --git a/sys/dev/bhnd/cores/chipc/chipcreg.h b/sys/dev/bhnd/cores/chipc/chipcreg.h
index 5b2721d74b1b..26c693ea3fcf 100644
--- a/sys/dev/bhnd/cores/chipc/chipcreg.h
+++ b/sys/dev/bhnd/cores/chipc/chipcreg.h
@@ -240,11 +240,11 @@
#define CHIPC_CAP_EXTBUS_PROG 0x2 /* ExtBus: ProgIf only */
#define CHIPC_CAP_FLASH_MASK 0x00000700 /* Type of flash */
#define CHIPC_CAP_FLASH_SHIFT 8
-#define CHIPC_CAP_FLASH_NONE 0x000 /* No flash */
-#define CHIPC_CAP_SFLASH_ST 0x100 /* ST serial flash */
-#define CHIPC_CAP_SFLASH_AT 0x200 /* Atmel serial flash */
-#define CHIPC_CAP_NFLASH 0x300 /* NAND flash */
-#define CHIPC_CAP_PFLASH 0x700 /* Parallel flash */
+#define CHIPC_CAP_FLASH_NONE 0x0 /* No flash */
+#define CHIPC_CAP_SFLASH_ST 0x1 /* ST serial flash */
+#define CHIPC_CAP_SFLASH_AT 0x2 /* Atmel serial flash */
+#define CHIPC_CAP_NFLASH 0x3 /* NAND flash */
+#define CHIPC_CAP_PFLASH 0x7 /* Parallel flash */
#define CHIPC_CAP_PLL_MASK 0x00038000 /* Type of PLL */
#define CHIPC_CAP_PLL_SHIFT 15
#define CHIPC_CAP_PWR_CTL 0x00040000 /* Power control */