Add support for dumping bcma/siba EROM tables to the console via a new
BHND_EROM_DUMP() method. Dump the EROM tables to the coneole on mips/broadcom devices if bootverbose is enabled; this functionality is primarily useful when debugging SoC EROM parsing and device matching issues during early boot. Reviewed by: mizhka Approved by: adrian (mentor) Sponsored by: Plausible Labs Differential Revision: https://reviews.freebsd.org/D10122
This commit is contained in:
parent
4c9a24e4c5
commit
f20e16ee8c
@ -1367,6 +1367,157 @@ bcma_erom_next_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
bcma_erom_dump(bhnd_erom_t *erom)
|
||||
{
|
||||
struct bcma_erom *sc;
|
||||
uint32_t entry;
|
||||
int error;
|
||||
|
||||
sc = (struct bcma_erom *)erom;
|
||||
|
||||
bcma_erom_reset(sc);
|
||||
|
||||
while (!(error = bcma_erom_read32(sc, &entry))) {
|
||||
/* Handle EOF */
|
||||
if (entry == BCMA_EROM_TABLE_EOF) {
|
||||
EROM_LOG(sc, "EOF\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Invalid entry */
|
||||
if (!BCMA_EROM_GET_ATTR(entry, ENTRY_ISVALID)) {
|
||||
EROM_LOG(sc, "invalid EROM entry %#x\n", entry);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
switch (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE)) {
|
||||
case BCMA_EROM_ENTRY_TYPE_CORE: {
|
||||
/* CoreDescA */
|
||||
EROM_LOG(sc, "coreA (0x%x)\n", entry);
|
||||
EROM_LOG(sc, "\tdesigner:\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, COREA_DESIGNER));
|
||||
EROM_LOG(sc, "\tid:\t\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, COREA_ID));
|
||||
EROM_LOG(sc, "\tclass:\t\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, COREA_CLASS));
|
||||
|
||||
/* CoreDescB */
|
||||
if ((error = bcma_erom_read32(sc, &entry))) {
|
||||
EROM_LOG(sc, "error reading CoreDescB: %d\n",
|
||||
error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (!BCMA_EROM_ENTRY_IS(entry, CORE)) {
|
||||
EROM_LOG(sc, "invalid core descriptor; found "
|
||||
"unexpected entry %#x (type=%s)\n",
|
||||
entry, bcma_erom_entry_type_name(entry));
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
EROM_LOG(sc, "coreB (0x%x)\n", entry);
|
||||
EROM_LOG(sc, "\trev:\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, COREB_REV));
|
||||
EROM_LOG(sc, "\tnummp:\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, COREB_NUM_MP));
|
||||
EROM_LOG(sc, "\tnumdp:\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, COREB_NUM_DP));
|
||||
EROM_LOG(sc, "\tnumwmp:\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, COREB_NUM_WMP));
|
||||
EROM_LOG(sc, "\tnumwsp:\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, COREB_NUM_WMP));
|
||||
|
||||
break;
|
||||
}
|
||||
case BCMA_EROM_ENTRY_TYPE_MPORT:
|
||||
EROM_LOG(sc, "\tmport 0x%x\n", entry);
|
||||
EROM_LOG(sc, "\t\tport:\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, MPORT_NUM));
|
||||
EROM_LOG(sc, "\t\tid:\t\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, MPORT_ID));
|
||||
break;
|
||||
|
||||
case BCMA_EROM_ENTRY_TYPE_REGION: {
|
||||
bool addr64;
|
||||
uint8_t size_type;
|
||||
|
||||
addr64 = (BCMA_EROM_GET_ATTR(entry, REGION_64BIT) != 0);
|
||||
size_type = BCMA_EROM_GET_ATTR(entry, REGION_SIZE);
|
||||
|
||||
EROM_LOG(sc, "\tregion 0x%x:\n", entry);
|
||||
EROM_LOG(sc, "\t\t%s:\t0x%x\n",
|
||||
addr64 ? "baselo" : "base",
|
||||
BCMA_EROM_GET_ATTR(entry, REGION_BASE));
|
||||
EROM_LOG(sc, "\t\tport:\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, REGION_PORT));
|
||||
EROM_LOG(sc, "\t\ttype:\t0x%x\n",
|
||||
BCMA_EROM_GET_ATTR(entry, REGION_TYPE));
|
||||
EROM_LOG(sc, "\t\tsztype:\t0x%hhx\n", size_type);
|
||||
|
||||
/* Read the base address high bits */
|
||||
if (addr64) {
|
||||
if ((error = bcma_erom_read32(sc, &entry))) {
|
||||
EROM_LOG(sc, "error reading region "
|
||||
"base address high bits %d\n",
|
||||
error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
EROM_LOG(sc, "\t\tbasehi:\t0x%x\n", entry);
|
||||
}
|
||||
|
||||
/* Read extended size descriptor */
|
||||
if (size_type == BCMA_EROM_REGION_SIZE_OTHER) {
|
||||
bool size64;
|
||||
|
||||
if ((error = bcma_erom_read32(sc, &entry))) {
|
||||
EROM_LOG(sc, "error reading region "
|
||||
"size descriptor %d\n",
|
||||
error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (BCMA_EROM_GET_ATTR(entry, RSIZE_64BIT))
|
||||
size64 = true;
|
||||
else
|
||||
size64 = false;
|
||||
|
||||
EROM_LOG(sc, "\t\t%s:\t0x%x\n",
|
||||
size64 ? "sizelo" : "size",
|
||||
BCMA_EROM_GET_ATTR(entry, RSIZE_VAL));
|
||||
|
||||
if (size64) {
|
||||
error = bcma_erom_read32(sc, &entry);
|
||||
if (error) {
|
||||
EROM_LOG(sc, "error reading "
|
||||
"region size high bits: "
|
||||
"%d\n", error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
EROM_LOG(sc, "\t\tsizehi:\t0x%x\n",
|
||||
entry);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
EROM_LOG(sc, "unknown EROM entry 0x%x (type=%s)\n",
|
||||
entry, bcma_erom_entry_type_name(entry));
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (error == ENOENT)
|
||||
EROM_LOG(sc, "BCMA EROM table missing terminating EOF\n");
|
||||
else if (error)
|
||||
EROM_LOG(sc, "EROM read failed: %d\n", error);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static kobj_method_t bcma_erom_methods[] = {
|
||||
KOBJMETHOD(bhnd_erom_probe, bcma_erom_probe),
|
||||
KOBJMETHOD(bhnd_erom_probe_static, bcma_erom_probe_static),
|
||||
@ -1377,6 +1528,7 @@ static kobj_method_t bcma_erom_methods[] = {
|
||||
KOBJMETHOD(bhnd_erom_free_core_table, bcma_erom_free_core_table),
|
||||
KOBJMETHOD(bhnd_erom_lookup_core, bcma_erom_lookup_core),
|
||||
KOBJMETHOD(bhnd_erom_lookup_core_addr, bcma_erom_lookup_core_addr),
|
||||
KOBJMETHOD(bhnd_erom_dump, bcma_erom_dump),
|
||||
|
||||
KOBJMETHOD_END
|
||||
};
|
||||
|
@ -240,4 +240,19 @@ bhnd_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc
|
||||
core, addr, size));
|
||||
};
|
||||
|
||||
/**
|
||||
* Enumerate and print all entries in @p erom.
|
||||
*
|
||||
* @param erom The erom parser to be enumerated.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero If an error occurs parsing the EROM table, a regular
|
||||
* unix error code will be returned.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_erom_dump(bhnd_erom_t *erom)
|
||||
{
|
||||
return (BHND_EROM_DUMP(erom));
|
||||
}
|
||||
|
||||
#endif /* _BHND_EROM_BHND_EROM_H_ */
|
||||
|
@ -241,3 +241,16 @@ METHOD int lookup_core_addr {
|
||||
bhnd_addr_t *addr;
|
||||
bhnd_size_t *size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Enumerate and print all EROM table entries.
|
||||
*
|
||||
* @param erom The erom parser to be enumerated.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero If an error occurs reading the EROM table, a regular
|
||||
* unix error code will be returned.
|
||||
*/
|
||||
METHOD int dump {
|
||||
bhnd_erom_t *erom;
|
||||
};
|
||||
|
@ -519,6 +519,65 @@ siba_erom_free_core_table(bhnd_erom_t *erom, struct bhnd_core_info *cores)
|
||||
free(cores, M_BHND);
|
||||
}
|
||||
|
||||
/* BHND_EROM_DUMP() */
|
||||
static int
|
||||
siba_erom_dump(bhnd_erom_t *erom)
|
||||
{
|
||||
struct siba_erom *sc;
|
||||
int error;
|
||||
|
||||
sc = (struct siba_erom *)erom;
|
||||
|
||||
/* Enumerate all cores. */
|
||||
for (u_int i = 0; i < sc->io.ncores; i++) {
|
||||
uint32_t idhigh, idlow;
|
||||
uint32_t nraddr;
|
||||
|
||||
idhigh = siba_eio_read_4(&sc->io, i,
|
||||
SB0_REG_ABS(SIBA_CFG0_IDHIGH));
|
||||
idlow = siba_eio_read_4(&sc->io, i,
|
||||
SB0_REG_ABS(SIBA_CFG0_IDLOW));
|
||||
|
||||
printf("siba core %u:\n", i);
|
||||
printf("\tvendor:\t0x%04x\n", SIBA_REG_GET(idhigh, IDH_VENDOR));
|
||||
printf("\tdevice:\t0x%04x\n", SIBA_REG_GET(idhigh, IDH_DEVICE));
|
||||
printf("\trev:\t0x%04x\n", SIBA_IDH_CORE_REV(idhigh));
|
||||
printf("\tsbrev:\t0x%02x\n", SIBA_REG_GET(idlow, IDL_SBREV));
|
||||
|
||||
/* Enumerate the address match registers */
|
||||
nraddr = SIBA_REG_GET(idlow, IDL_NRADDR);
|
||||
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;
|
||||
|
||||
/* Determine the register offset */
|
||||
am_offset = siba_admatch_offset(addrspace);
|
||||
if (am_offset == 0) {
|
||||
printf("addrspace %zu unsupported",
|
||||
addrspace);
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static kobj_method_t siba_erom_methods[] = {
|
||||
KOBJMETHOD(bhnd_erom_probe, siba_erom_probe),
|
||||
KOBJMETHOD(bhnd_erom_probe_static, siba_erom_probe_static),
|
||||
@ -529,6 +588,7 @@ static kobj_method_t siba_erom_methods[] = {
|
||||
KOBJMETHOD(bhnd_erom_free_core_table, siba_erom_free_core_table),
|
||||
KOBJMETHOD(bhnd_erom_lookup_core, siba_erom_lookup_core),
|
||||
KOBJMETHOD(bhnd_erom_lookup_core_addr, siba_erom_lookup_core_addr),
|
||||
KOBJMETHOD(bhnd_erom_dump, siba_erom_dump),
|
||||
|
||||
KOBJMETHOD_END
|
||||
};
|
||||
|
@ -343,6 +343,9 @@ bcm_init_platform_data(struct bcm_platform *bp)
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (bootverbose)
|
||||
bhnd_erom_dump(&bp->erom.obj);
|
||||
|
||||
/* Fetch chipcommon core info */
|
||||
error = bcm_find_core(bp, bcm_chipc_cores, nitems(bcm_chipc_cores),
|
||||
&bp->cc_id, &bp->cc_addr);
|
||||
|
Loading…
Reference in New Issue
Block a user