siba(4): Ignore disabled per-core address match entries.
Previously, the address regions described by disabled admatch entries would be treated as being mapped to the given core; while incorrect, this was essentially harmless given that the entries describe unused address space on the few affected devices. We now perform parsing of per-core admatch registers and interrupt flags in siba_erom, correctly skip any disabled admatch entries, and use the siba_erom API in siba_add_children() to perform enumeration of attached cores.
This commit is contained in:
parent
21b8a7a6ca
commit
7c7c726bca
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=329180
@ -47,9 +47,14 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/bhnd/cores/chipc/chipc.h>
|
||||
#include <dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.h>
|
||||
|
||||
#include "siba_eromvar.h"
|
||||
|
||||
#include "sibareg.h"
|
||||
#include "sibavar.h"
|
||||
|
||||
/* RID used when allocating EROM resources */
|
||||
#define SIBA_EROM_RID 0
|
||||
|
||||
static bhnd_erom_class_t *
|
||||
siba_get_erom_class(driver_t *driver)
|
||||
{
|
||||
@ -1057,7 +1062,7 @@ siba_decode_port_rid(device_t dev, device_t child, int type, int rid,
|
||||
return (EINVAL);
|
||||
|
||||
/* Look for a matching addrspace entry */
|
||||
for (u_int i = 0; i < dinfo->core_id.num_addrspace; i++) {
|
||||
for (u_int i = 0; i < dinfo->core_id.num_admatch; i++) {
|
||||
if (dinfo->addrspace[i].sa_rid != rid)
|
||||
continue;
|
||||
|
||||
@ -1131,7 +1136,7 @@ siba_get_intr_count(device_t dev, device_t child)
|
||||
return (BHND_BUS_GET_INTR_COUNT(device_get_parent(dev), child));
|
||||
|
||||
dinfo = device_get_ivars(child);
|
||||
if (!dinfo->intr_en) {
|
||||
if (!dinfo->core_id.intr_en) {
|
||||
/* No interrupts */
|
||||
return (0);
|
||||
} else {
|
||||
@ -1161,117 +1166,10 @@ siba_get_intr_ivec(device_t dev, device_t child, u_int intr, u_int *ivec)
|
||||
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
KASSERT(dinfo->intr_en, ("core does not have an interrupt assigned"));
|
||||
*ivec = dinfo->intr.flag;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all address space mappings for @p di.
|
||||
*
|
||||
* @param dev The siba bus device.
|
||||
* @param di The device info instance on which to register all address
|
||||
* space entries.
|
||||
* @param r A resource mapping the enumeration table block for @p di.
|
||||
*/
|
||||
static int
|
||||
siba_register_addrspaces(device_t dev, struct siba_devinfo *di,
|
||||
struct bhnd_resource *r)
|
||||
{
|
||||
struct siba_core_id *cid;
|
||||
uint32_t addr;
|
||||
uint32_t size;
|
||||
int error;
|
||||
|
||||
cid = &di->core_id;
|
||||
|
||||
|
||||
/* Register the device address space entries */
|
||||
for (uint8_t i = 0; i < di->core_id.num_addrspace; i++) {
|
||||
uint32_t adm;
|
||||
u_int adm_offset;
|
||||
uint32_t bus_reserved;
|
||||
|
||||
/* Determine the register offset */
|
||||
adm_offset = siba_admatch_offset(i);
|
||||
if (adm_offset == 0) {
|
||||
device_printf(dev, "addrspace %hhu is unsupported", i);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
/* Fetch the address match register value */
|
||||
adm = bhnd_bus_read_4(r, adm_offset);
|
||||
|
||||
/* Parse the value */
|
||||
if ((error = siba_parse_admatch(adm, &addr, &size))) {
|
||||
device_printf(dev, "failed to decode address "
|
||||
" match register value 0x%x\n", adm);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* If this is the device's core/enumeration addrespace,
|
||||
* reserve the Sonics configuration register blocks for the
|
||||
* use of our bus. */
|
||||
bus_reserved = 0;
|
||||
if (i == SIBA_CORE_ADDRSPACE)
|
||||
bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE;
|
||||
|
||||
/* Append the region info */
|
||||
error = siba_append_dinfo_region(di, i, addr, size,
|
||||
bus_reserved);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register all interrupt descriptors for @p dinfo. Must be called after
|
||||
* configuration blocks have been mapped.
|
||||
*
|
||||
* @param dev The siba bus device.
|
||||
* @param child The siba child device.
|
||||
* @param dinfo The device info instance on which to register all interrupt
|
||||
* descriptor entries.
|
||||
* @param r A resource mapping the enumeration table block for @p di.
|
||||
*/
|
||||
static int
|
||||
siba_register_interrupts(device_t dev, device_t child,
|
||||
struct siba_devinfo *dinfo, struct bhnd_resource *r)
|
||||
{
|
||||
uint32_t tpsflag;
|
||||
int error;
|
||||
|
||||
/* Is backplane interrupt distribution enabled for this core? */
|
||||
tpsflag = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_TPSFLAG));
|
||||
if ((tpsflag & SIBA_TPS_F0EN0) == 0) {
|
||||
dinfo->intr_en = false;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Have one interrupt */
|
||||
dinfo->intr_en = true;
|
||||
dinfo->intr.flag = SIBA_REG_GET(tpsflag, TPS_NUM0);
|
||||
dinfo->intr.mapped = false;
|
||||
dinfo->intr.irq = 0;
|
||||
dinfo->intr.rid = -1;
|
||||
|
||||
/* Map the interrupt */
|
||||
error = BHND_BUS_MAP_INTR(dev, child, 0 /* single intr is always 0 */,
|
||||
&dinfo->intr.irq);
|
||||
if (error) {
|
||||
device_printf(dev, "failed mapping interrupt line for core %u: "
|
||||
"%d\n", dinfo->core_id.core_info.core_idx, error);
|
||||
return (error);
|
||||
}
|
||||
dinfo->intr.mapped = true;
|
||||
|
||||
/* Update the resource list */
|
||||
dinfo->intr.rid = resource_list_add_next(&dinfo->resources, SYS_RES_IRQ,
|
||||
dinfo->intr.irq, dinfo->intr.irq, 1);
|
||||
KASSERT(dinfo->core_id.intr_en,
|
||||
("core does not have an interrupt assigned"));
|
||||
|
||||
*ivec = dinfo->core_id.intr_flag;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1386,21 +1284,27 @@ siba_child_deleted(device_t dev, device_t child)
|
||||
int
|
||||
siba_add_children(device_t dev)
|
||||
{
|
||||
const struct bhnd_chipid *chipid;
|
||||
bhnd_erom_t *erom;
|
||||
struct siba_erom *siba_erom;
|
||||
struct bhnd_erom_io *eio;
|
||||
const struct bhnd_chipid *cid;
|
||||
struct siba_core_id *cores;
|
||||
struct bhnd_resource *r;
|
||||
device_t *children;
|
||||
int rid;
|
||||
int error;
|
||||
|
||||
cores = NULL;
|
||||
r = NULL;
|
||||
cid = BHND_BUS_GET_CHIPID(dev, dev);
|
||||
|
||||
chipid = BHND_BUS_GET_CHIPID(dev, dev);
|
||||
/* Allocate our EROM parser */
|
||||
eio = bhnd_erom_iores_new(dev, SIBA_EROM_RID);
|
||||
erom = bhnd_erom_alloc(&siba_erom_parser, cid, eio);
|
||||
if (erom == NULL) {
|
||||
bhnd_erom_io_fini(eio);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
/* Allocate our temporary core and device table */
|
||||
cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_WAITOK);
|
||||
children = malloc(sizeof(*children) * chipid->ncores, M_BHND,
|
||||
cores = malloc(sizeof(*cores) * cid->ncores, M_BHND, M_WAITOK);
|
||||
children = malloc(sizeof(*children) * cid->ncores, M_BHND,
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
/*
|
||||
@ -1411,39 +1315,13 @@ siba_add_children(device_t dev)
|
||||
* defer mapping of the per-core siba(4) config blocks until all cores
|
||||
* have been enumerated and otherwise configured.
|
||||
*/
|
||||
for (u_int i = 0; i < chipid->ncores; i++) {
|
||||
siba_erom = (struct siba_erom *)erom;
|
||||
for (u_int i = 0; i < cid->ncores; i++) {
|
||||
struct siba_devinfo *dinfo;
|
||||
device_t child;
|
||||
uint32_t idhigh, idlow;
|
||||
rman_res_t r_count, r_end, r_start;
|
||||
|
||||
/* Map the core's register block */
|
||||
rid = 0;
|
||||
r_start = SIBA_CORE_ADDR(i);
|
||||
r_count = SIBA_CORE_SIZE;
|
||||
r_end = r_start + SIBA_CORE_SIZE - 1;
|
||||
r = bhnd_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start,
|
||||
r_end, r_count, RF_ACTIVE);
|
||||
if (r == NULL) {
|
||||
error = ENXIO;
|
||||
if ((error = siba_erom_get_core_id(siba_erom, i, &cores[i])))
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Read the core info */
|
||||
idhigh = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
|
||||
idlow = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW));
|
||||
|
||||
cores[i] = siba_parse_core_id(idhigh, idlow, i, 0);
|
||||
|
||||
/* Determine and set unit number */
|
||||
for (u_int j = 0; j < i; j++) {
|
||||
struct bhnd_core_info *cur = &cores[i].core_info;
|
||||
struct bhnd_core_info *prev = &cores[j].core_info;
|
||||
|
||||
if (prev->vendor == cur->vendor &&
|
||||
prev->device == cur->device)
|
||||
cur->unit++;
|
||||
}
|
||||
|
||||
/* Add the child device */
|
||||
child = BUS_ADD_CHILD(dev, 0, NULL, -1);
|
||||
@ -1460,30 +1338,22 @@ siba_add_children(device_t dev)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if ((error = siba_init_dinfo(dev, dinfo, &cores[i])))
|
||||
if ((error = siba_init_dinfo(dev, child, dinfo, &cores[i])))
|
||||
goto failed;
|
||||
|
||||
/* Register the core's address space(s). */
|
||||
if ((error = siba_register_addrspaces(dev, dinfo, r)))
|
||||
goto failed;
|
||||
|
||||
/* Register the core's interrupts */
|
||||
if ((error = siba_register_interrupts(dev, child, dinfo, r)))
|
||||
goto failed;
|
||||
|
||||
/* Unmap the core's register block */
|
||||
bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r);
|
||||
r = NULL;
|
||||
|
||||
/* If pins are floating or the hardware is otherwise
|
||||
* unpopulated, the device shouldn't be used. */
|
||||
if (bhnd_is_hw_disabled(child))
|
||||
device_disable(child);
|
||||
}
|
||||
|
||||
/* Free EROM (and any bridge register windows it might hold) */
|
||||
bhnd_erom_free(erom);
|
||||
erom = NULL;
|
||||
|
||||
/* Map all valid core's config register blocks and perform interrupt
|
||||
* assignment */
|
||||
for (u_int i = 0; i < chipid->ncores; i++) {
|
||||
for (u_int i = 0; i < cid->ncores; i++) {
|
||||
struct siba_devinfo *dinfo;
|
||||
device_t child;
|
||||
|
||||
@ -1509,7 +1379,7 @@ siba_add_children(device_t dev)
|
||||
return (0);
|
||||
|
||||
failed:
|
||||
for (u_int i = 0; i < chipid->ncores; i++) {
|
||||
for (u_int i = 0; i < cid->ncores; i++) {
|
||||
if (children[i] == NULL)
|
||||
continue;
|
||||
|
||||
@ -1518,9 +1388,8 @@ siba_add_children(device_t dev)
|
||||
|
||||
free(cores, M_BHND);
|
||||
free(children, M_BHND);
|
||||
|
||||
if (r != NULL)
|
||||
bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r);
|
||||
if (erom != NULL)
|
||||
bhnd_erom_free(erom);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include "sibareg.h"
|
||||
#include "sibavar.h"
|
||||
|
||||
#include "siba_eromvar.h"
|
||||
|
||||
struct siba_erom;
|
||||
struct siba_erom_io;
|
||||
|
||||
@ -59,8 +61,9 @@ static int siba_eio_init(struct siba_erom_io *io,
|
||||
static uint32_t siba_eio_read_4(struct siba_erom_io *io,
|
||||
u_int core_idx, bus_size_t offset);
|
||||
|
||||
static struct siba_core_id siba_eio_read_core_id(struct siba_erom_io *io,
|
||||
u_int core_idx, int unit);
|
||||
static int siba_eio_read_core_id(struct siba_erom_io *io,
|
||||
u_int core_idx, int unit,
|
||||
struct siba_core_id *sid);
|
||||
|
||||
static int siba_eio_read_chipid(struct siba_erom_io *io,
|
||||
bus_addr_t enum_addr,
|
||||
@ -118,7 +121,8 @@ siba_erom_probe(bhnd_erom_class_t *cls, struct bhnd_erom_io *eio,
|
||||
* BCM4710, it's a SDRAM core (0x803).
|
||||
*/
|
||||
|
||||
sid = siba_eio_read_core_id(&io, 0, 0);
|
||||
if ((error = siba_eio_read_core_id(&io, 0, 0, &sid)))
|
||||
return (error);
|
||||
|
||||
if (sid.core_info.vendor != BHND_MFGID_BCM)
|
||||
return (ENXIO);
|
||||
@ -227,16 +231,151 @@ siba_eio_read_4(struct siba_erom_io *io, u_int core_idx, bus_size_t offset)
|
||||
* @param core_idx The core index.
|
||||
* @param unit The caller-specified unit number to be included in the return
|
||||
* value.
|
||||
* @param[out] sid On success, the parsed siba core id.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero if reading or parsing the identification registers
|
||||
* otherwise fails, a regular unix error code will be
|
||||
* returned.
|
||||
*/
|
||||
static struct siba_core_id
|
||||
siba_eio_read_core_id(struct siba_erom_io *io, u_int core_idx, int unit)
|
||||
static int
|
||||
siba_eio_read_core_id(struct siba_erom_io *io, u_int core_idx, int unit,
|
||||
struct siba_core_id *sid)
|
||||
{
|
||||
uint32_t idhigh, idlow;
|
||||
struct siba_admatch admatch[SIBA_MAX_ADDRSPACE];
|
||||
uint32_t idhigh, idlow;
|
||||
uint32_t tpsflag;
|
||||
uint16_t ocp_vendor;
|
||||
uint8_t sonics_rev;
|
||||
uint8_t num_admatch;
|
||||
uint8_t num_admatch_en;
|
||||
uint8_t num_cfg;
|
||||
bool intr_en;
|
||||
u_int intr_flag;
|
||||
int error;
|
||||
|
||||
idhigh = siba_eio_read_4(io, core_idx, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
|
||||
idlow = siba_eio_read_4(io, core_idx, SB0_REG_ABS(SIBA_CFG0_IDLOW));
|
||||
tpsflag = siba_eio_read_4(io, core_idx, SB0_REG_ABS(SIBA_CFG0_TPSFLAG));
|
||||
|
||||
return (siba_parse_core_id(idhigh, idlow, core_idx, unit));
|
||||
ocp_vendor = SIBA_REG_GET(idhigh, IDH_VENDOR);
|
||||
sonics_rev = SIBA_REG_GET(idlow, IDL_SBREV);
|
||||
num_admatch = SIBA_REG_GET(idlow, IDL_NRADDR) + 1 /* + enum block */;
|
||||
if (num_admatch > nitems(admatch)) {
|
||||
printf("core%u: invalid admatch count %hhu\n", core_idx,
|
||||
num_admatch);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* Determine backplane interrupt distribution configuration */
|
||||
intr_en = ((tpsflag & SIBA_TPS_F0EN0) != 0);
|
||||
intr_flag = SIBA_REG_GET(tpsflag, TPS_NUM0);
|
||||
|
||||
/* Determine the number of sonics config register blocks */
|
||||
num_cfg = SIBA_CFG_NUM_2_2;
|
||||
if (sonics_rev >= SIBA_IDL_SBREV_2_3)
|
||||
num_cfg = SIBA_CFG_NUM_2_3;
|
||||
|
||||
/* Parse all admatch descriptors */
|
||||
num_admatch_en = 0;
|
||||
for (uint8_t i = 0; i < num_admatch; i++) {
|
||||
uint32_t am_value;
|
||||
u_int am_offset;
|
||||
|
||||
KASSERT(i < nitems(admatch), ("invalid admatch index"));
|
||||
|
||||
/* Determine the register offset */
|
||||
am_offset = siba_admatch_offset(i);
|
||||
if (am_offset == 0) {
|
||||
printf("core%u: addrspace %hhu is unsupported",
|
||||
core_idx, i);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
/* Read and parse the address match register */
|
||||
am_value = siba_eio_read_4(io, core_idx, am_offset);
|
||||
error = siba_parse_admatch(am_value, &admatch[num_admatch_en]);
|
||||
if (error) {
|
||||
printf("core%u: failed to decode admatch[%hhu] "
|
||||
"register value 0x%x\n", core_idx, i, am_value);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Skip disabled entries */
|
||||
if (!admatch[num_admatch_en].am_enabled)
|
||||
continue;
|
||||
|
||||
/* Reject unsupported negative matches. These are not used on
|
||||
* any known devices */
|
||||
if (admatch[num_admatch_en].am_negative) {
|
||||
printf("core%u: unsupported negative admatch[%hhu] "
|
||||
"value 0x%x\n", core_idx, i, am_value);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
num_admatch_en++;
|
||||
}
|
||||
|
||||
/* Populate the result */
|
||||
*sid = (struct siba_core_id) {
|
||||
.core_info = {
|
||||
.vendor = siba_get_bhnd_mfgid(ocp_vendor),
|
||||
.device = SIBA_REG_GET(idhigh, IDH_DEVICE),
|
||||
.hwrev = SIBA_IDH_CORE_REV(idhigh),
|
||||
.core_idx = core_idx,
|
||||
.unit = unit
|
||||
},
|
||||
.sonics_vendor = ocp_vendor,
|
||||
.sonics_rev = sonics_rev,
|
||||
.intr_en = intr_en,
|
||||
.intr_flag = intr_flag,
|
||||
.num_admatch = num_admatch_en,
|
||||
.num_cfg_blocks = num_cfg
|
||||
};
|
||||
memcpy(sid->admatch, admatch, num_admatch_en * sizeof(admatch[0]));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and parse the SSB identification registers for the given @p core_index,
|
||||
* returning the siba(4) core identification in @p sid.
|
||||
*
|
||||
* @param sc A siba EROM instance.
|
||||
* @param core_idx The index of the core to be identified.
|
||||
* @param[out] result On success, the parsed siba core id.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero if reading or parsing the identification registers
|
||||
* otherwise fails, a regular unix error code will be
|
||||
* returned.
|
||||
*/
|
||||
int
|
||||
siba_erom_get_core_id(struct siba_erom *sc, u_int core_idx,
|
||||
struct siba_core_id *result)
|
||||
{
|
||||
struct siba_core_id sid;
|
||||
int error;
|
||||
|
||||
/* Fetch the core info, assuming a unit number of 0 */
|
||||
if ((error = siba_eio_read_core_id(&sc->io, core_idx, 0, &sid)))
|
||||
return (error);
|
||||
|
||||
/* Scan preceding cores to determine the real unit number. */
|
||||
for (u_int i = 0; i < core_idx; i++) {
|
||||
struct siba_core_id prev;
|
||||
|
||||
if ((error = siba_eio_read_core_id(&sc->io, i, 0, &prev)))
|
||||
return (error);
|
||||
|
||||
/* Bump the unit number? */
|
||||
if (sid.core_info.vendor == prev.core_info.vendor &&
|
||||
sid.core_info.device == prev.core_info.device)
|
||||
sid.core_info.unit++;
|
||||
}
|
||||
|
||||
*result = sid;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -252,9 +391,12 @@ siba_eio_read_chipid(struct siba_erom_io *io, bus_addr_t enum_addr,
|
||||
{
|
||||
struct siba_core_id ccid;
|
||||
uint32_t idreg;
|
||||
int error;
|
||||
|
||||
/* Identify the chipcommon core */
|
||||
ccid = siba_eio_read_core_id(io, 0, 0);
|
||||
if ((error = siba_eio_read_core_id(io, 0, 0, &ccid)))
|
||||
return (error);
|
||||
|
||||
if (ccid.core_info.vendor != BHND_MFGID_BCM ||
|
||||
ccid.core_info.device != BHND_COREID_CC)
|
||||
{
|
||||
@ -281,6 +423,7 @@ siba_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc,
|
||||
{
|
||||
struct siba_erom *sc;
|
||||
struct bhnd_core_match imatch;
|
||||
int error;
|
||||
|
||||
sc = (struct siba_erom *)erom;
|
||||
|
||||
@ -294,7 +437,9 @@ siba_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc,
|
||||
struct bhnd_core_info ci;
|
||||
|
||||
/* Read the core info */
|
||||
sid = siba_eio_read_core_id(&sc->io, i, 0);
|
||||
if ((error = siba_eio_read_core_id(&sc->io, i, 0, &sid)))
|
||||
return (error);
|
||||
|
||||
ci = sid.core_info;
|
||||
|
||||
/* Check for initial match */
|
||||
@ -303,7 +448,9 @@ siba_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc,
|
||||
|
||||
/* Re-scan preceding cores to determine the unit number. */
|
||||
for (u_int j = 0; j < i; j++) {
|
||||
sid = siba_eio_read_core_id(&sc->io, j, 0);
|
||||
error = siba_eio_read_core_id(&sc->io, j, 0, &sid);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Bump the unit number? */
|
||||
if (sid.core_info.vendor == ci.vendor &&
|
||||
@ -332,7 +479,8 @@ siba_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc
|
||||
struct siba_erom *sc;
|
||||
struct bhnd_core_info core;
|
||||
struct siba_core_id sid;
|
||||
uint32_t am, am_addr, am_size;
|
||||
struct siba_admatch admatch;
|
||||
uint32_t am;
|
||||
u_int am_offset;
|
||||
u_int addrspace, cfg;
|
||||
|
||||
@ -345,7 +493,9 @@ siba_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc
|
||||
return (error);
|
||||
|
||||
/* Fetch full siba core ident */
|
||||
sid = siba_eio_read_core_id(&sc->io, core.core_idx, core.unit);
|
||||
error = siba_eio_read_core_id(&sc->io, core.core_idx, core.unit, &sid);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Is port valid? */
|
||||
if (!siba_is_port_valid(&sid, type, port))
|
||||
@ -419,7 +569,7 @@ siba_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc
|
||||
/* Read and parse the address match register */
|
||||
am = siba_eio_read_4(&sc->io, core.core_idx, am_offset);
|
||||
|
||||
if ((error = siba_parse_admatch(am, &am_addr, &am_size))) {
|
||||
if ((error = siba_parse_admatch(am, &admatch))) {
|
||||
printf("failed to decode address match register value 0x%x\n",
|
||||
am);
|
||||
return (error);
|
||||
@ -428,8 +578,8 @@ siba_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc
|
||||
if (info != NULL)
|
||||
*info = core;
|
||||
|
||||
*addr = am_addr;
|
||||
*size = am_size;
|
||||
*addr = admatch.am_base;
|
||||
*size = admatch.am_size;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -441,6 +591,7 @@ siba_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores,
|
||||
{
|
||||
struct siba_erom *sc;
|
||||
struct bhnd_core_info *out;
|
||||
int error;
|
||||
|
||||
sc = (struct siba_erom *)erom;
|
||||
|
||||
@ -457,7 +608,9 @@ siba_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores,
|
||||
struct siba_core_id sid;
|
||||
|
||||
/* Read the core info */
|
||||
sid = siba_eio_read_core_id(&sc->io, i, 0);
|
||||
if ((error = siba_eio_read_core_id(&sc->io, i, 0, &sid)))
|
||||
return (error);
|
||||
|
||||
out[i] = sid.core_info;
|
||||
|
||||
/* Determine unit number */
|
||||
@ -508,8 +661,9 @@ siba_erom_dump(bhnd_erom_t *erom)
|
||||
printf("\tnraddr\t0x%04x\n", nraddr);
|
||||
|
||||
for (size_t addrspace = 0; addrspace < nraddr; addrspace++) {
|
||||
uint32_t am, am_addr, am_size;
|
||||
u_int am_offset;
|
||||
struct siba_admatch admatch;
|
||||
uint32_t am;
|
||||
u_int am_offset;
|
||||
|
||||
/* Determine the register offset */
|
||||
am_offset = siba_admatch_offset(addrspace);
|
||||
@ -521,16 +675,15 @@ siba_erom_dump(bhnd_erom_t *erom)
|
||||
|
||||
/* Read and parse the address match register */
|
||||
am = siba_eio_read_4(&sc->io, i, am_offset);
|
||||
error = siba_parse_admatch(am, &am_addr, &am_size);
|
||||
if (error) {
|
||||
if ((error = siba_parse_admatch(am, &admatch))) {
|
||||
printf("failed to decode address match "
|
||||
"register value 0x%x\n", am);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("\taddrspace %zu\n", addrspace);
|
||||
printf("\t\taddr: 0x%08x\n", am_addr);
|
||||
printf("\t\tsize: 0x%08x\n", am_size);
|
||||
printf("\t\taddr: 0x%08x\n", admatch.am_base);
|
||||
printf("\t\tsize: 0x%08x\n", admatch.am_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
46
sys/dev/bhnd/siba/siba_eromvar.h
Normal file
46
sys/dev/bhnd/siba/siba_eromvar.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2018 Landon Fuller <landonf@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 _SIBA_SIBA_EROMVAR_H_
|
||||
#define _SIBA_SIBA_EROMVAR_H_
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
#include <dev/bhnd/bhnd_erom.h>
|
||||
|
||||
#include "sibavar.h"
|
||||
|
||||
struct siba_erom;
|
||||
|
||||
#define SIBA_EROM_
|
||||
|
||||
int siba_erom_get_core_id(struct siba_erom *sc, u_int core_idx,
|
||||
struct siba_core_id *result);
|
||||
|
||||
#endif /* _SIBA_SIBA_EROMVAR_H_ */
|
@ -48,6 +48,12 @@ __FBSDID("$FreeBSD$");
|
||||
#include "sibareg.h"
|
||||
#include "sibavar.h"
|
||||
|
||||
static int siba_register_interrupts(device_t dev, device_t child,
|
||||
struct siba_devinfo *dinfo);
|
||||
static int siba_append_dinfo_region(struct siba_devinfo *dinfo,
|
||||
uint8_t addridx, uint32_t base, uint32_t size,
|
||||
uint32_t bus_reserved);
|
||||
|
||||
/**
|
||||
* Map a siba(4) OCP vendor code to its corresponding JEDEC JEP-106 vendor
|
||||
* code.
|
||||
@ -67,48 +73,6 @@ siba_get_bhnd_mfgid(uint16_t ocp_vendor)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the SIBA_IDH_* fields from the per-core identification
|
||||
* registers, returning a siba_core_id representation.
|
||||
*
|
||||
* @param idhigh The SIBA_R0_IDHIGH register.
|
||||
* @param idlow The SIBA_R0_IDLOW register.
|
||||
* @param core_id The core id (index) to include in the result.
|
||||
* @param unit The unit number to include in the result.
|
||||
*/
|
||||
struct siba_core_id
|
||||
siba_parse_core_id(uint32_t idhigh, uint32_t idlow, u_int core_idx, int unit)
|
||||
{
|
||||
|
||||
uint16_t ocp_vendor;
|
||||
uint8_t sonics_rev;
|
||||
uint8_t num_addrspace;
|
||||
uint8_t num_cfg;
|
||||
|
||||
ocp_vendor = SIBA_REG_GET(idhigh, IDH_VENDOR);
|
||||
sonics_rev = SIBA_REG_GET(idlow, IDL_SBREV);
|
||||
num_addrspace = SIBA_REG_GET(idlow, IDL_NRADDR) + 1 /* + enum block */;
|
||||
|
||||
/* Determine the number of sonics config register blocks */
|
||||
num_cfg = SIBA_CFG_NUM_2_2;
|
||||
if (sonics_rev >= SIBA_IDL_SBREV_2_3)
|
||||
num_cfg = SIBA_CFG_NUM_2_3;
|
||||
|
||||
return (struct siba_core_id) {
|
||||
.core_info = {
|
||||
.vendor = siba_get_bhnd_mfgid(ocp_vendor),
|
||||
.device = SIBA_REG_GET(idhigh, IDH_DEVICE),
|
||||
.hwrev = SIBA_IDH_CORE_REV(idhigh),
|
||||
.core_idx = core_idx,
|
||||
.unit = unit
|
||||
},
|
||||
.sonics_vendor = ocp_vendor,
|
||||
.sonics_rev = sonics_rev,
|
||||
.num_addrspace = num_addrspace,
|
||||
.num_cfg_blocks = num_cfg
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and return a new empty device info structure.
|
||||
*
|
||||
@ -138,7 +102,11 @@ siba_alloc_dinfo(device_t bus)
|
||||
resource_list_init(&dinfo->resources);
|
||||
|
||||
dinfo->pmu_state = SIBA_PMU_NONE;
|
||||
dinfo->intr_en = false;
|
||||
|
||||
dinfo->intr = (struct siba_intr) {
|
||||
.mapped = false,
|
||||
.rid = -1
|
||||
};
|
||||
|
||||
return dinfo;
|
||||
}
|
||||
@ -148,6 +116,7 @@ siba_alloc_dinfo(device_t bus)
|
||||
* siba_alloc_dinfo, copying the provided core id.
|
||||
*
|
||||
* @param dev The requesting bus device.
|
||||
* @param child The siba child device.
|
||||
* @param dinfo The device info instance.
|
||||
* @param core Device core info.
|
||||
*
|
||||
@ -155,10 +124,77 @@ siba_alloc_dinfo(device_t bus)
|
||||
* @retval non-zero initialization failed.
|
||||
*/
|
||||
int
|
||||
siba_init_dinfo(device_t dev, struct siba_devinfo *dinfo,
|
||||
siba_init_dinfo(device_t dev, device_t child, struct siba_devinfo *dinfo,
|
||||
const struct siba_core_id *core_id)
|
||||
{
|
||||
int error;
|
||||
|
||||
dinfo->core_id = *core_id;
|
||||
|
||||
/* Register all address space mappings */
|
||||
for (uint8_t i = 0; i < core_id->num_admatch; i++) {
|
||||
uint32_t bus_reserved;
|
||||
|
||||
/* If this is the device's core/enumeration addrespace,
|
||||
* reserve the Sonics configuration register blocks for the
|
||||
* use of our bus. */
|
||||
bus_reserved = 0;
|
||||
if (i == SIBA_CORE_ADDRSPACE)
|
||||
bus_reserved = core_id->num_cfg_blocks * SIBA_CFG_SIZE;
|
||||
|
||||
/* Append the region info */
|
||||
error = siba_append_dinfo_region(dinfo, i,
|
||||
core_id->admatch[i].am_base, core_id->admatch[i].am_size,
|
||||
bus_reserved);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Register all interrupt(s) */
|
||||
if ((error = siba_register_interrupts(dev, child, dinfo)))
|
||||
return (error);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register and map all interrupts for @p dinfo.
|
||||
*
|
||||
* @param dev The siba bus device.
|
||||
* @param child The siba child device.
|
||||
* @param dinfo The device info instance on which to register all interrupt
|
||||
* entries.
|
||||
*/
|
||||
static int
|
||||
siba_register_interrupts(device_t dev, device_t child,
|
||||
struct siba_devinfo *dinfo)
|
||||
{
|
||||
int error;
|
||||
|
||||
/* Is backplane interrupt distribution enabled for this core? */
|
||||
if (!dinfo->core_id.intr_en)
|
||||
return (0);
|
||||
|
||||
/* Have one interrupt */
|
||||
dinfo->intr.mapped = false;
|
||||
dinfo->intr.irq = 0;
|
||||
dinfo->intr.rid = -1;
|
||||
|
||||
/* Map the interrupt */
|
||||
error = BHND_BUS_MAP_INTR(dev, child, 0 /* single intr is always 0 */,
|
||||
&dinfo->intr.irq);
|
||||
if (error) {
|
||||
device_printf(dev, "failed mapping interrupt line for core %u: "
|
||||
"%d\n", dinfo->core_id.core_info.core_idx, error);
|
||||
return (error);
|
||||
}
|
||||
dinfo->intr.mapped = true;
|
||||
|
||||
/* Update the resource list */
|
||||
dinfo->intr.rid = resource_list_add_next(&dinfo->resources, SYS_RES_IRQ,
|
||||
dinfo->intr.irq, dinfo->intr.irq, 1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -238,7 +274,7 @@ siba_port_count(struct siba_core_id *core_id, bhnd_port_type port_type)
|
||||
switch (port_type) {
|
||||
case BHND_PORT_DEVICE:
|
||||
/* 0, 1, or 2 ports */
|
||||
return (min(core_id->num_addrspace, 2));
|
||||
return (min(core_id->num_admatch, 2));
|
||||
|
||||
case BHND_PORT_AGENT:
|
||||
/* One agent port maps all configuration blocks */
|
||||
@ -292,11 +328,11 @@ siba_port_region_count(struct siba_core_id *core_id, bhnd_port_type port_type,
|
||||
case BHND_PORT_DEVICE:
|
||||
/* The first address space, if any, is mapped to device0.0 */
|
||||
if (port == 0)
|
||||
return (min(core_id->num_addrspace, 1));
|
||||
return (min(core_id->num_admatch, 1));
|
||||
|
||||
/* All remaining address spaces are mapped to device0.(n - 1) */
|
||||
if (port == 1 && core_id->num_addrspace >= 2)
|
||||
return (core_id->num_addrspace - 1);
|
||||
if (port == 1 && core_id->num_admatch >= 2)
|
||||
return (core_id->num_admatch - 1);
|
||||
|
||||
break;
|
||||
|
||||
@ -327,7 +363,6 @@ siba_port_region_count(struct siba_core_id *core_id, bhnd_port_type port_type,
|
||||
* agent0.0 0
|
||||
* agent0.1 1
|
||||
*
|
||||
* @param num_addrspace The number of available siba address spaces.
|
||||
* @param port_type The bhnd(4) port type.
|
||||
* @param port The bhnd(4) port number.
|
||||
* @param region The bhnd(4) port region.
|
||||
@ -394,7 +429,7 @@ siba_find_cfg_block(struct siba_devinfo *dinfo, bhnd_port_type type, u_int port,
|
||||
* For compatibility with bcma(4), we map address spaces to port/region
|
||||
* identifiers as follows:
|
||||
*
|
||||
* [port] [addrspace]
|
||||
* [port.region] [admatch index]
|
||||
* device0.0 0
|
||||
* device1.0 1
|
||||
* device1.1 2
|
||||
@ -431,7 +466,7 @@ siba_addrspace_index(struct siba_core_id *core_id, bhnd_port_type port_type,
|
||||
else
|
||||
return (ENOENT);
|
||||
|
||||
if (idx >= core_id->num_addrspace)
|
||||
if (idx >= core_id->num_admatch)
|
||||
return (ENOENT);
|
||||
|
||||
/* Found */
|
||||
@ -484,7 +519,7 @@ siba_find_addrspace(struct siba_devinfo *dinfo, bhnd_port_type type, u_int port,
|
||||
* @retval 0 success
|
||||
* @retval non-zero An error occurred appending the entry.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
siba_append_dinfo_region(struct siba_devinfo *dinfo, uint8_t addridx,
|
||||
uint32_t base, uint32_t size, uint32_t bus_reserved)
|
||||
{
|
||||
@ -546,7 +581,7 @@ siba_free_dinfo(device_t dev, device_t child, struct siba_devinfo *dinfo)
|
||||
}
|
||||
|
||||
/* Unmap the core's interrupt */
|
||||
if (dinfo->intr_en && dinfo->intr.mapped) {
|
||||
if (dinfo->core_id.intr_en && dinfo->intr.mapped) {
|
||||
BHND_BUS_UNMAP_INTR(dev, child, dinfo->intr.irq);
|
||||
dinfo->intr.mapped = false;
|
||||
}
|
||||
@ -585,36 +620,38 @@ siba_admatch_offset(uint8_t addrspace)
|
||||
*
|
||||
* @param addrspace The address space index.
|
||||
* @param am The address match register value to be parsed.
|
||||
* @param[out] addr The parsed address.
|
||||
* @param[out] size The parsed size.
|
||||
* @param[out] admatch The parsed address match descriptor
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero a parse error occurred.
|
||||
*/
|
||||
int
|
||||
siba_parse_admatch(uint32_t am, uint32_t *addr, uint32_t *size)
|
||||
siba_parse_admatch(uint32_t am, struct siba_admatch *admatch)
|
||||
{
|
||||
u_int am_type;
|
||||
|
||||
/* Negative encoding is not supported. This is not used on any
|
||||
* currently known devices*/
|
||||
if (am & SIBA_AM_ADNEG)
|
||||
return (EINVAL);
|
||||
u_int am_type;
|
||||
|
||||
/* Extract the base address and size */
|
||||
am_type = SIBA_REG_GET(am, AM_TYPE);
|
||||
switch (am_type) {
|
||||
case 0:
|
||||
*addr = am & SIBA_AM_BASE0_MASK;
|
||||
*size = 1 << (SIBA_REG_GET(am, AM_ADINT0) + 1);
|
||||
/* Type 0 entries are always enabled, and do not support
|
||||
* negative matching */
|
||||
admatch->am_base = am & SIBA_AM_BASE0_MASK;
|
||||
admatch->am_size = 1 << (SIBA_REG_GET(am, AM_ADINT0) + 1);
|
||||
admatch->am_enabled = true;
|
||||
admatch->am_negative = false;
|
||||
break;
|
||||
case 1:
|
||||
*addr = am & SIBA_AM_BASE1_MASK;
|
||||
*size = 1 << (SIBA_REG_GET(am, AM_ADINT1) + 1);
|
||||
admatch->am_base = am & SIBA_AM_BASE1_MASK;
|
||||
admatch->am_size = 1 << (SIBA_REG_GET(am, AM_ADINT1) + 1);
|
||||
admatch->am_enabled = ((am & SIBA_AM_ADEN) != 0);
|
||||
admatch->am_negative = ((am & SIBA_AM_ADNEG) != 0);
|
||||
break;
|
||||
case 2:
|
||||
*addr = am & SIBA_AM_BASE2_MASK;
|
||||
*size = 1 << (SIBA_REG_GET(am, AM_ADINT2) + 1);
|
||||
admatch->am_base = am & SIBA_AM_BASE2_MASK;
|
||||
admatch->am_size = 1 << (SIBA_REG_GET(am, AM_ADINT2) + 1);
|
||||
admatch->am_enabled = ((am & SIBA_AM_ADEN) != 0);
|
||||
admatch->am_negative = ((am & SIBA_AM_ADNEG) != 0);
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define _SIBA_SIBAVAR_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bitstring.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/lock.h>
|
||||
@ -52,6 +53,7 @@
|
||||
*/
|
||||
|
||||
struct siba_addrspace;
|
||||
struct siba_admatch;
|
||||
struct siba_cfg_block;
|
||||
struct siba_devinfo;
|
||||
struct siba_core_id;
|
||||
@ -68,13 +70,10 @@ int siba_get_intr_ivec(device_t dev, device_t child,
|
||||
|
||||
uint16_t siba_get_bhnd_mfgid(uint16_t ocp_vendor);
|
||||
|
||||
struct siba_core_id siba_parse_core_id(uint32_t idhigh, uint32_t idlow,
|
||||
u_int core_idx, int unit);
|
||||
|
||||
int siba_add_children(device_t bus);
|
||||
|
||||
struct siba_devinfo *siba_alloc_dinfo(device_t dev);
|
||||
int siba_init_dinfo(device_t dev,
|
||||
int siba_init_dinfo(device_t dev, device_t child,
|
||||
struct siba_devinfo *dinfo,
|
||||
const struct siba_core_id *core_id);
|
||||
void siba_free_dinfo(device_t dev, device_t child,
|
||||
@ -109,13 +108,9 @@ struct siba_addrspace *siba_find_addrspace(struct siba_devinfo *dinfo,
|
||||
struct siba_cfg_block *siba_find_cfg_block(struct siba_devinfo *dinfo,
|
||||
bhnd_port_type type, u_int port, u_int region);
|
||||
|
||||
int siba_append_dinfo_region(struct siba_devinfo *dinfo,
|
||||
uint8_t sid, uint32_t base, uint32_t size,
|
||||
uint32_t bus_reserved);
|
||||
|
||||
u_int siba_admatch_offset(uint8_t addrspace);
|
||||
int siba_parse_admatch(uint32_t am, uint32_t *addr,
|
||||
uint32_t *size);
|
||||
int siba_parse_admatch(uint32_t am,
|
||||
struct siba_admatch *admatch);
|
||||
|
||||
void siba_write_target_state(device_t dev,
|
||||
struct siba_devinfo *dinfo, bus_size_t reg,
|
||||
@ -148,6 +143,14 @@ int siba_wait_target_state(device_t dev,
|
||||
#define SIBA_MAX_PORT 2 /**< maximum number of advertised
|
||||
* bhnd(4) ports */
|
||||
|
||||
/** siba(4) address match descriptor */
|
||||
struct siba_admatch {
|
||||
uint32_t am_base; /**< base address. */
|
||||
uint32_t am_size; /**< size. */
|
||||
bool am_negative; /**< if true, negative matching is performed. */
|
||||
bool am_enabled; /**< if true, matching on this entry is enabled. */
|
||||
};
|
||||
|
||||
/** siba(4) address space descriptor */
|
||||
struct siba_addrspace {
|
||||
uint32_t sa_base; /**< base address */
|
||||
@ -166,7 +169,6 @@ struct siba_cfg_block {
|
||||
|
||||
/** siba(4) backplane interrupt flag descriptor */
|
||||
struct siba_intr {
|
||||
u_int flag; /**< backplane flag # */
|
||||
bool mapped; /**< if an irq has been mapped */
|
||||
int rid; /**< bus resource id, or -1 if unassigned */
|
||||
rman_res_t irq; /**< the mapped bus irq, if any */
|
||||
@ -176,15 +178,17 @@ struct siba_intr {
|
||||
* siba(4) per-core identification info.
|
||||
*/
|
||||
struct siba_core_id {
|
||||
struct bhnd_core_info core_info; /**< standard bhnd(4) core info */
|
||||
uint16_t sonics_vendor; /**< OCP vendor identifier used to generate
|
||||
* the JEDEC-106 bhnd(4) vendor identifier. */
|
||||
uint8_t sonics_rev; /**< sonics backplane revision code */
|
||||
uint8_t num_addrspace; /**< number of address ranges mapped to
|
||||
this core. */
|
||||
uint8_t num_cfg_blocks; /**< number of Sonics configuration register
|
||||
blocks mapped to the core's enumeration
|
||||
space */
|
||||
struct bhnd_core_info core_info; /**< standard bhnd(4) core info */
|
||||
uint16_t sonics_vendor; /**< OCP vendor identifier used to generate
|
||||
* the JEDEC-106 bhnd(4) vendor identifier. */
|
||||
uint8_t sonics_rev; /**< sonics backplane revision code */
|
||||
bool intr_en; /**< if backplane interrupt distribution is enabled for this core */
|
||||
u_int intr_flag; /**< backplane interrupt flag # */
|
||||
struct siba_admatch admatch[SIBA_MAX_ADDRSPACE]; /**< active address match descriptors defined by this core. */
|
||||
uint8_t num_admatch; /**< number of address match descriptors. */
|
||||
uint8_t num_cfg_blocks; /**< number of Sonics configuration register
|
||||
blocks mapped to the core's enumeration
|
||||
space */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -205,8 +209,7 @@ struct siba_devinfo {
|
||||
struct siba_core_id core_id; /**< core identification info */
|
||||
struct siba_addrspace addrspace[SIBA_MAX_ADDRSPACE]; /**< memory map descriptors */
|
||||
struct siba_cfg_block cfg[SIBA_MAX_CFG]; /**< config block descriptors */
|
||||
struct siba_intr intr; /**< interrupt flag descriptor, if any */
|
||||
bool intr_en; /**< if true, core has an assigned interrupt flag */
|
||||
struct siba_intr intr; /**< interrupt flag mapping, if any */
|
||||
|
||||
struct bhnd_resource *cfg_res[SIBA_MAX_CFG]; /**< bus-mapped config block registers */
|
||||
int cfg_rid[SIBA_MAX_CFG]; /**< bus-mapped config block resource IDs */
|
||||
|
Loading…
Reference in New Issue
Block a user