Fix several MIPS/BCM-blocking bugs in bhnd(4) chipc
- Correct IRQ lines for UART (to fix IRQ lookup in future) - Check device unit in resource assignment during chipc_add_child - If chipc hint->size is RM_MAX_END, resource end should be same as window end - Clear reference from resource list entry to resource in case of resource release - Add CHIPC_GET_CAPS implementation - Correct chipc flash constants (to be unshifted) - Default implementation of get_attach_type should iterate over device tree - Add default implementation for BHND_CHIPC_GET_CAPS usable by chipc grandchildren Submitted by: Michael Zhilin <mizhka@gmail.com> Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D6584
This commit is contained in:
parent
09864b3ba8
commit
05a96f9151
@ -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);
|
||||
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user