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:
landonf 2017-04-24 18:35:25 +00:00
parent 4c9a24e4c5
commit f20e16ee8c
5 changed files with 243 additions and 0 deletions

View File

@ -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
};

View File

@ -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_ */

View File

@ -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;
};

View File

@ -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
};

View File

@ -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);