From owner-svn-src-head@freebsd.org Mon Feb 12 19:36:28 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E3284F15B48; Mon, 12 Feb 2018 19:36:27 +0000 (UTC) (envelope-from landonf@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 912BD69406; Mon, 12 Feb 2018 19:36:27 +0000 (UTC) (envelope-from landonf@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 8BC6C16488; Mon, 12 Feb 2018 19:36:27 +0000 (UTC) (envelope-from landonf@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w1CJaRRp033046; Mon, 12 Feb 2018 19:36:27 GMT (envelope-from landonf@FreeBSD.org) Received: (from landonf@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w1CJaRlq033041; Mon, 12 Feb 2018 19:36:27 GMT (envelope-from landonf@FreeBSD.org) Message-Id: <201802121936.w1CJaRlq033041@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: landonf set sender to landonf@FreeBSD.org using -f From: "Landon J. Fuller" Date: Mon, 12 Feb 2018 19:36:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r329180 - head/sys/dev/bhnd/siba X-SVN-Group: head X-SVN-Commit-Author: landonf X-SVN-Commit-Paths: head/sys/dev/bhnd/siba X-SVN-Commit-Revision: 329180 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 Feb 2018 19:36:28 -0000 Author: landonf Date: Mon Feb 12 19:36:26 2018 New Revision: 329180 URL: https://svnweb.freebsd.org/changeset/base/329180 Log: 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. Added: head/sys/dev/bhnd/siba/siba_eromvar.h (contents, props changed) Modified: head/sys/dev/bhnd/siba/siba.c head/sys/dev/bhnd/siba/siba_erom.c head/sys/dev/bhnd/siba/siba_subr.c head/sys/dev/bhnd/siba/sibavar.h Modified: head/sys/dev/bhnd/siba/siba.c ============================================================================== --- head/sys/dev/bhnd/siba/siba.c Mon Feb 12 19:08:17 2018 (r329179) +++ head/sys/dev/bhnd/siba/siba.c Mon Feb 12 19:36:26 2018 (r329180) @@ -47,9 +47,14 @@ __FBSDID("$FreeBSD$"); #include #include +#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 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,121 +1166,14 @@ siba_get_intr_ivec(device_t dev, device_t child, u_int dinfo = device_get_ivars(child); - KASSERT(dinfo->intr_en, ("core does not have an interrupt assigned")); - *ivec = dinfo->intr.flag; - return (0); -} + KASSERT(dinfo->core_id.intr_en, + ("core does not have an interrupt assigned")); -/** - * 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); - } - + *ivec = dinfo->core_id.intr_flag; 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); - - return (0); -} - -/** * Map per-core configuration blocks for @p dinfo. * * @param dev The siba bus device. @@ -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,40 +1315,14 @@ 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); if (child == NULL) { @@ -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 @@ failed: 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); } Modified: head/sys/dev/bhnd/siba/siba_erom.c ============================================================================== --- head/sys/dev/bhnd/siba/siba_erom.c Mon Feb 12 19:08:17 2018 (r329179) +++ head/sys/dev/bhnd/siba/siba_erom.c Mon Feb 12 19:36:26 2018 (r329180) @@ -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_er * 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,19 +231,154 @@ siba_eio_read_4(struct siba_erom_io *io, u_int core_id * @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); +} + +/** * Read and parse the chip identification register from the ChipCommon core. * * @param io EROM I/O context. @@ -252,9 +391,12 @@ siba_eio_read_chipid(struct siba_erom_io *io, bus_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 { 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 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 /* 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 st 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 st 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 st /* 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 st 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 bhn { 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 bhn 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); } } Added: head/sys/dev/bhnd/siba/siba_eromvar.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/bhnd/siba/siba_eromvar.h Mon Feb 12 19:36:26 2018 (r329180) @@ -0,0 +1,46 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2018 Landon Fuller + * 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 +#include + +#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_ */ Modified: head/sys/dev/bhnd/siba/siba_subr.c ============================================================================== --- head/sys/dev/bhnd/siba/siba_subr.c Mon Feb 12 19:08:17 2018 (r329179) +++ head/sys/dev/bhnd/siba/siba_subr.c Mon Feb 12 19:36:26 2018 (r329180) @@ -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. @@ -68,48 +74,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. * * @param bus The requesting bus device. @@ -138,8 +102,12 @@ 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,14 +124,81 @@ 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); +} + +/** * Map an addrspace index to its corresponding bhnd(4) BHND_PORT_DEVICE port * number. * @@ -238,7 +274,7 @@ siba_port_count(struct siba_core_id *core_id, bhnd_por 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, b 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, b * 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_p * 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, bhn 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_p * @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 s } /* 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; + 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); - /* 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); Modified: head/sys/dev/bhnd/siba/sibavar.h ============================================================================== --- head/sys/dev/bhnd/siba/sibavar.h Mon Feb 12 19:08:17 2018 (r329179) +++ head/sys/dev/bhnd/siba/sibavar.h Mon Feb 12 19:36:26 2018 (r329180) @@ -37,6 +37,7 @@ #define _SIBA_SIBAVAR_H_ #include +#include #include #include #include @@ -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 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***