mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 04:43:53 +00:00
bhnd(4): include a subset of the ChipCommon capability flags in bhnd_chipid;
this provides early access to device capability flags required by bhnd(4) bus and bhndb(4) bridge drivers.
This commit is contained in:
parent
19f74c09b1
commit
f3524ec8ed
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=331744
|
@ -28,7 +28,7 @@
|
|||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 19, 2018
|
||||
.Dd March 26, 2018
|
||||
.Dt BHND 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -1130,6 +1130,10 @@ chip, each of which may require driver workarounds for hardware errata,
|
|||
unpopulated components, etc.
|
||||
.It Fa chip_type
|
||||
The interconnect architecture used by this chip.
|
||||
.It Fa chip_caps
|
||||
The
|
||||
.Nm
|
||||
capability flags supported by this chip.
|
||||
.It Fa enum_addr
|
||||
The backplane enumeration address.
|
||||
On SSB devices, this will be the base address of the first SSB core.
|
||||
|
@ -1156,6 +1160,16 @@ UBUS is not currently supported by
|
|||
.Xr bhnd 4 .
|
||||
.El
|
||||
.Pp
|
||||
The following
|
||||
.Fa chip_caps
|
||||
flags are supported:
|
||||
.Bl -tag -width ".Dv BHND_CAP_BP64" -offset indent -compact
|
||||
.It Dv BHND_CAP_BP64
|
||||
The backplane supports 64-bit addressing.
|
||||
.It Dv BHND_CAP_PMU
|
||||
PMU is present.
|
||||
.El
|
||||
.Pp
|
||||
Additional symbolic constants for known
|
||||
.Fa chip_id ,
|
||||
.Fa chip_pkg ,
|
||||
|
|
|
@ -45,7 +45,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
#include <dev/bhnd/bhnd_eromvar.h>
|
||||
|
||||
#include "bcma_eromreg.h"
|
||||
#include "bcma_eromvar.h"
|
||||
|
@ -168,23 +168,16 @@ static int
|
|||
bcma_erom_probe(bhnd_erom_class_t *cls, struct bhnd_erom_io *eio,
|
||||
const struct bhnd_chipid *hint, struct bhnd_chipid *cid)
|
||||
{
|
||||
uint32_t idreg, eromptr;
|
||||
int error;
|
||||
|
||||
/* Hints aren't supported; all BCMA devices have a ChipCommon
|
||||
* core */
|
||||
if (hint != NULL)
|
||||
return (EINVAL);
|
||||
|
||||
/* Confirm CHIPC_EROMPTR availability */
|
||||
idreg = bhnd_erom_io_read(eio, CHIPC_ID, 4);
|
||||
if (!BHND_CHIPTYPE_HAS_EROM(CHIPC_GET_BITS(idreg, CHIPC_ID_BUS)))
|
||||
return (ENXIO);
|
||||
|
||||
/* Fetch EROM address */
|
||||
eromptr = bhnd_erom_io_read(eio, CHIPC_EROMPTR, 4);
|
||||
|
||||
/* Parse chip identifier */
|
||||
*cid = bhnd_parse_chipid(idreg, eromptr);
|
||||
/* Read and parse chip identification */
|
||||
if ((error = bhnd_erom_read_chipid(eio, cid)))
|
||||
return (error);
|
||||
|
||||
/* Verify chip type */
|
||||
switch (cid->chip_type) {
|
||||
|
|
|
@ -219,6 +219,7 @@ struct bhnd_chipid {
|
|||
uint8_t chip_rev; /**< chip revision */
|
||||
uint8_t chip_pkg; /**< chip package (BHND_PKGID_*) */
|
||||
uint8_t chip_type; /**< chip type (BHND_CHIPTYPE_*) */
|
||||
uint32_t chip_caps; /**< chip capabilities (BHND_CAP_*) */
|
||||
|
||||
bhnd_addr_t enum_addr; /**< chip_type-specific enumeration
|
||||
* address; either the siba(4) base
|
||||
|
@ -229,6 +230,15 @@ struct bhnd_chipid {
|
|||
* not available. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Chip capabilities
|
||||
*/
|
||||
enum bhnd_cap {
|
||||
BHND_CAP_BP64 = (1<<0), /**< Backplane supports 64-bit
|
||||
* addressing */
|
||||
BHND_CAP_PMU = (1<<1), /**< PMU is present */
|
||||
};
|
||||
|
||||
/**
|
||||
* A bhnd(4) core descriptor.
|
||||
*/
|
||||
|
@ -520,18 +530,6 @@ void bhnd_release_resources(device_t dev,
|
|||
const struct resource_spec *rs,
|
||||
struct bhnd_resource **res);
|
||||
|
||||
struct bhnd_chipid bhnd_parse_chipid(uint32_t idreg,
|
||||
bhnd_addr_t enum_addr);
|
||||
|
||||
int bhnd_chipid_fixed_ncores(
|
||||
const struct bhnd_chipid *cid,
|
||||
uint16_t chipc_hwrev, uint8_t *ncores);
|
||||
|
||||
int bhnd_read_chipid(device_t dev,
|
||||
struct resource_spec *rs,
|
||||
bus_size_t chipc_offset,
|
||||
struct bhnd_chipid *result);
|
||||
|
||||
void bhnd_set_custom_core_desc(device_t dev,
|
||||
const char *name);
|
||||
void bhnd_set_default_core_desc(device_t dev);
|
||||
|
|
|
@ -44,18 +44,26 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/bhndreg.h>
|
||||
#include <dev/bhnd/bhndvar.h>
|
||||
|
||||
#include <dev/bhnd/bhnd_erom.h>
|
||||
#include <dev/bhnd/bhnd_eromvar.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
|
||||
static int bhnd_erom_iores_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
|
||||
bhnd_size_t size);
|
||||
static int bhnd_erom_iores_tell(struct bhnd_erom_io *eio,
|
||||
bhnd_addr_t *addr, bhnd_size_t *size);
|
||||
static uint32_t bhnd_erom_iores_read(struct bhnd_erom_io *eio,
|
||||
bhnd_size_t offset, u_int width);
|
||||
static void bhnd_erom_iores_fini(struct bhnd_erom_io *eio);
|
||||
|
||||
static int bhnd_erom_iobus_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
|
||||
bhnd_size_t size);
|
||||
static int bhnd_erom_iobus_tell(struct bhnd_erom_io *eio,
|
||||
bhnd_addr_t *addr, bhnd_size_t *size);
|
||||
static uint32_t bhnd_erom_iobus_read(struct bhnd_erom_io *eio,
|
||||
bhnd_size_t offset, u_int width);
|
||||
|
||||
|
@ -248,6 +256,62 @@ bhnd_erom_free(bhnd_erom_t *erom)
|
|||
kobj_delete((kobj_t)erom, M_BHND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the chip identification registers mapped by @p eio, popuating @p cid
|
||||
* with the parsed result
|
||||
*
|
||||
* @param eio A bus I/O instance, configured with a mapping
|
||||
* of the ChipCommon core.
|
||||
* @param[out] cid On success, the parsed chip identification.
|
||||
*
|
||||
* @warning
|
||||
* On early siba(4) devices, the ChipCommon core does not provide
|
||||
* a valid CHIPC_ID_NUMCORE field. On these ChipCommon revisions
|
||||
* (see CHIPC_NCORES_MIN_HWREV()), this function will parse and return
|
||||
* an invalid `ncores` value.
|
||||
*/
|
||||
int
|
||||
bhnd_erom_read_chipid(struct bhnd_erom_io *eio, struct bhnd_chipid *cid)
|
||||
{
|
||||
bhnd_addr_t cc_addr;
|
||||
bhnd_size_t cc_size;
|
||||
uint32_t idreg, cc_caps;
|
||||
int error;
|
||||
|
||||
/* Fetch ChipCommon address */
|
||||
if ((error = bhnd_erom_io_tell(eio, &cc_addr, &cc_size)))
|
||||
return (error);
|
||||
|
||||
/* Read chip identifier */
|
||||
idreg = bhnd_erom_io_read(eio, CHIPC_ID, 4);
|
||||
|
||||
/* Extract the basic chip info */
|
||||
cid->chip_id = CHIPC_GET_BITS(idreg, CHIPC_ID_CHIP);
|
||||
cid->chip_pkg = CHIPC_GET_BITS(idreg, CHIPC_ID_PKG);
|
||||
cid->chip_rev = CHIPC_GET_BITS(idreg, CHIPC_ID_REV);
|
||||
cid->chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS);
|
||||
cid->ncores = CHIPC_GET_BITS(idreg, CHIPC_ID_NUMCORE);
|
||||
|
||||
/* Populate EROM address */
|
||||
if (BHND_CHIPTYPE_HAS_EROM(cid->chip_type)) {
|
||||
cid->enum_addr = bhnd_erom_io_read(eio, CHIPC_EROMPTR, 4);
|
||||
} else {
|
||||
cid->enum_addr = cc_addr;
|
||||
}
|
||||
|
||||
/* Populate capability flags */
|
||||
cc_caps = bhnd_erom_io_read(eio, CHIPC_CAPABILITIES, 4);
|
||||
cid->chip_caps = 0x0;
|
||||
|
||||
if (cc_caps & CHIPC_CAP_BKPLN64)
|
||||
cid->chip_caps |= BHND_CAP_BP64;
|
||||
|
||||
if (cc_caps & CHIPC_CAP_PMU)
|
||||
cid->chip_caps |= BHND_CAP_PMU;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempt to map @p size bytes at @p addr, replacing any existing
|
||||
|
@ -267,6 +331,23 @@ bhnd_erom_io_map(struct bhnd_erom_io *eio, bhnd_addr_t addr, bhnd_size_t size)
|
|||
return (eio->map(eio, addr, size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the address range mapped by @p eio, if any.
|
||||
*
|
||||
* @param eio I/O instance state.
|
||||
* @param[out] addr The address mapped by @p eio.
|
||||
* @param[out] size The number of bytes mapped at @p addr.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENXIO if @p eio has no mapping.
|
||||
*/
|
||||
int
|
||||
bhnd_erom_io_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr,
|
||||
bhnd_size_t *size)
|
||||
{
|
||||
return (eio->tell(eio, addr, size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a 1, 2, or 4 byte data item from @p eio, at the given @p offset
|
||||
* relative to @p eio's current mapping.
|
||||
|
@ -306,6 +387,7 @@ bhnd_erom_iores_new(device_t dev, int rid)
|
|||
|
||||
iores = malloc(sizeof(*iores), M_BHND, M_WAITOK | M_ZERO);
|
||||
iores->eio.map = bhnd_erom_iores_map;
|
||||
iores->eio.tell = bhnd_erom_iores_tell;
|
||||
iores->eio.read = bhnd_erom_iores_read;
|
||||
iores->eio.fini = bhnd_erom_iores_fini;
|
||||
|
||||
|
@ -361,6 +443,21 @@ bhnd_erom_iores_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_erom_iores_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr,
|
||||
bhnd_size_t *size)
|
||||
{
|
||||
struct bhnd_erom_iores *iores = (struct bhnd_erom_iores *)eio;
|
||||
|
||||
if (iores->mapped == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
*addr = rman_get_start(iores->mapped->res);
|
||||
*size = rman_get_size(iores->mapped->res);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
bhnd_erom_iores_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width)
|
||||
{
|
||||
|
@ -416,6 +513,7 @@ bhnd_erom_iobus_init(struct bhnd_erom_iobus *iobus, bhnd_addr_t addr,
|
|||
bhnd_size_t size, bus_space_tag_t bst, bus_space_handle_t bsh)
|
||||
{
|
||||
iobus->eio.map = bhnd_erom_iobus_map;
|
||||
iobus->eio.tell = bhnd_erom_iobus_tell;
|
||||
iobus->eio.read = bhnd_erom_iobus_read;
|
||||
iobus->eio.fini = NULL;
|
||||
|
||||
|
@ -463,6 +561,21 @@ bhnd_erom_iobus_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_erom_iobus_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr,
|
||||
bhnd_size_t *size)
|
||||
{
|
||||
struct bhnd_erom_iobus *iobus = (struct bhnd_erom_iobus *)eio;
|
||||
|
||||
if (!iobus->mapped)
|
||||
return (ENXIO);
|
||||
|
||||
*addr = iobus->addr + iobus->offset;
|
||||
*size = iobus->limit;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
bhnd_erom_iobus_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width)
|
||||
{
|
||||
|
|
|
@ -76,6 +76,8 @@ int bhnd_erom_iobus_init(struct bhnd_erom_iobus *iobus,
|
|||
|
||||
int bhnd_erom_io_map(struct bhnd_erom_io *eio,
|
||||
bhnd_addr_t addr, bhnd_size_t size);
|
||||
int bhnd_erom_io_tell(struct bhnd_erom_io *eio,
|
||||
bhnd_addr_t *addr, bhnd_size_t *size);
|
||||
uint32_t bhnd_erom_io_read(struct bhnd_erom_io *eio,
|
||||
bhnd_size_t offset, u_int width);
|
||||
void bhnd_erom_io_fini(struct bhnd_erom_io *eio);
|
||||
|
|
|
@ -48,6 +48,10 @@ struct bhnd_erom_iobus;
|
|||
typedef int (bhnd_erom_io_map_t)(struct bhnd_erom_io *eio,
|
||||
bhnd_addr_t addr, bhnd_size_t size);
|
||||
|
||||
/** @see bhnd_erom_io_tell() */
|
||||
typedef int (bhnd_erom_io_tell_t)(struct bhnd_erom_io *eio,
|
||||
bhnd_addr_t *addr, bhnd_size_t *size);
|
||||
|
||||
/** @see bhnd_erom_io_read() */
|
||||
typedef uint32_t (bhnd_erom_io_read_t)(struct bhnd_erom_io *eio,
|
||||
bhnd_size_t offset, u_int width);
|
||||
|
@ -55,11 +59,17 @@ typedef uint32_t (bhnd_erom_io_read_t)(struct bhnd_erom_io *eio,
|
|||
/** @see bhnd_erom_io_fini() */
|
||||
typedef void (bhnd_erom_io_fini_t)(struct bhnd_erom_io *eio);
|
||||
|
||||
|
||||
int bhnd_erom_read_chipid(struct bhnd_erom_io *eio,
|
||||
struct bhnd_chipid *cid);
|
||||
|
||||
|
||||
/**
|
||||
* Abstract EROM bus I/O support.
|
||||
*/
|
||||
struct bhnd_erom_io {
|
||||
bhnd_erom_io_map_t *map; /**< @see bhnd_erom_io_map() */
|
||||
bhnd_erom_io_tell_t *tell; /**< @see bhnd_erom_io_tell() */
|
||||
bhnd_erom_io_read_t *read; /**< @see bhnd_erom_io_read() */
|
||||
bhnd_erom_io_fini_t *fini; /**< @see bhnd_erom_io_fini(). May be NULL */
|
||||
};
|
||||
|
|
|
@ -1056,174 +1056,6 @@ bhnd_release_resources(device_t dev, const struct resource_spec *rs,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the CHIPC_ID_* fields from the ChipCommon CHIPC_ID
|
||||
* register, returning its bhnd_chipid representation.
|
||||
*
|
||||
* @param idreg The CHIPC_ID register value.
|
||||
* @param enum_addr The enumeration address to include in the result.
|
||||
*
|
||||
* @warning
|
||||
* On early siba(4) devices, the ChipCommon core does not provide
|
||||
* a valid CHIPC_ID_NUMCORE field. On these ChipCommon revisions
|
||||
* (see CHIPC_NCORES_MIN_HWREV()), this function will parse and return
|
||||
* an invalid `ncores` value.
|
||||
*/
|
||||
struct bhnd_chipid
|
||||
bhnd_parse_chipid(uint32_t idreg, bhnd_addr_t enum_addr)
|
||||
{
|
||||
struct bhnd_chipid result;
|
||||
|
||||
/* Fetch the basic chip info */
|
||||
result.chip_id = CHIPC_GET_BITS(idreg, CHIPC_ID_CHIP);
|
||||
result.chip_pkg = CHIPC_GET_BITS(idreg, CHIPC_ID_PKG);
|
||||
result.chip_rev = CHIPC_GET_BITS(idreg, CHIPC_ID_REV);
|
||||
result.chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS);
|
||||
result.ncores = CHIPC_GET_BITS(idreg, CHIPC_ID_NUMCORE);
|
||||
|
||||
result.enum_addr = enum_addr;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the correct core count for a chip identification value that
|
||||
* may contain an invalid core count.
|
||||
*
|
||||
* On some early siba(4) devices (see CHIPC_NCORES_MIN_HWREV()), the ChipCommon
|
||||
* core does not provide a valid CHIPC_ID_NUMCORE field.
|
||||
*
|
||||
* @param cid The chip identification to be queried.
|
||||
* @param chipc_hwrev The hardware revision of the ChipCommon core from which
|
||||
* @p cid was parsed.
|
||||
* @param[out] ncores On success, will be set to the correct core count.
|
||||
*
|
||||
* @retval 0 If the core count is already correct, or was mapped to a
|
||||
* a correct value.
|
||||
* @retval EINVAL If the core count is incorrect, but the chip was not
|
||||
* recognized.
|
||||
*/
|
||||
int
|
||||
bhnd_chipid_fixed_ncores(const struct bhnd_chipid *cid, uint16_t chipc_hwrev,
|
||||
uint8_t *ncores)
|
||||
{
|
||||
/* bcma(4), and most siba(4) devices */
|
||||
if (CHIPC_NCORES_MIN_HWREV(chipc_hwrev)) {
|
||||
*ncores = cid->ncores;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* broken siba(4) chipsets */
|
||||
switch (cid->chip_id) {
|
||||
case BHND_CHIPID_BCM4306:
|
||||
*ncores = 6;
|
||||
break;
|
||||
case BHND_CHIPID_BCM4704:
|
||||
*ncores = 9;
|
||||
break;
|
||||
case BHND_CHIPID_BCM5365:
|
||||
/*
|
||||
* BCM5365 does support ID_NUMCORE in at least
|
||||
* some of its revisions, but for unknown
|
||||
* reasons, Broadcom's drivers always exclude
|
||||
* the ChipCommon revision (0x5) used by BCM5365
|
||||
* from the set of revisions supporting
|
||||
* ID_NUMCORE, and instead supply a fixed value.
|
||||
*
|
||||
* Presumably, at least some of these devices
|
||||
* shipped with a broken ID_NUMCORE value.
|
||||
*/
|
||||
*ncores = 7;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the resource defined by @p rs via @p dev, use it
|
||||
* to read the ChipCommon ID register relative to @p chipc_offset,
|
||||
* then release the resource.
|
||||
*
|
||||
* @param dev The device owning @p rs.
|
||||
* @param rs A resource spec that encompasses the ChipCommon register block.
|
||||
* @param chipc_offset The offset of the ChipCommon registers within @p rs.
|
||||
* @param[out] result The chip identification data.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero if the ChipCommon identification data could not be read.
|
||||
*/
|
||||
int
|
||||
bhnd_read_chipid(device_t dev, struct resource_spec *rs,
|
||||
bus_size_t chipc_offset, struct bhnd_chipid *result)
|
||||
{
|
||||
struct resource *res;
|
||||
bhnd_addr_t enum_addr;
|
||||
uint32_t reg;
|
||||
uint8_t chip_type;
|
||||
int error, rid, rtype;
|
||||
|
||||
rid = rs->rid;
|
||||
rtype = rs->type;
|
||||
error = 0;
|
||||
|
||||
/* Allocate the ChipCommon window resource and fetch the chipid data */
|
||||
res = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE);
|
||||
if (res == NULL) {
|
||||
device_printf(dev,
|
||||
"failed to allocate bhnd chipc resource\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Fetch the basic chip info */
|
||||
reg = bus_read_4(res, chipc_offset + CHIPC_ID);
|
||||
chip_type = CHIPC_GET_BITS(reg, CHIPC_ID_BUS);
|
||||
|
||||
/* Fetch the EROMPTR */
|
||||
if (BHND_CHIPTYPE_HAS_EROM(chip_type)) {
|
||||
enum_addr = bus_read_4(res, chipc_offset + CHIPC_EROMPTR);
|
||||
} else if (chip_type == BHND_CHIPTYPE_SIBA) {
|
||||
/* siba(4) uses the ChipCommon base address as the enumeration
|
||||
* address */
|
||||
enum_addr = BHND_DEFAULT_CHIPC_ADDR;
|
||||
} else {
|
||||
device_printf(dev, "unknown chip type %hhu\n", chip_type);
|
||||
error = ENODEV;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*result = bhnd_parse_chipid(reg, enum_addr);
|
||||
|
||||
/* Fix the core count on early siba(4) devices */
|
||||
if (chip_type == BHND_CHIPTYPE_SIBA) {
|
||||
uint32_t idh;
|
||||
uint16_t chipc_hwrev;
|
||||
|
||||
/*
|
||||
* We need the ChipCommon revision to determine whether
|
||||
* the ncore field is valid.
|
||||
*
|
||||
* We can safely assume the siba IDHIGH register is mapped
|
||||
* within the chipc register block.
|
||||
*/
|
||||
idh = bus_read_4(res, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
|
||||
chipc_hwrev = SIBA_IDH_CORE_REV(idh);
|
||||
|
||||
error = bhnd_chipid_fixed_ncores(result, chipc_hwrev,
|
||||
&result->ncores);
|
||||
if (error)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* Clean up */
|
||||
bus_release_resource(dev, rtype, rid, res);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and return a new per-core PMU clock control/status (clkctl)
|
||||
* instance for @p dev.
|
||||
|
|
|
@ -125,6 +125,8 @@ static void bhndb_pci_eio_init(struct bhndb_pci_eio *eio,
|
|||
struct bhndb_pci_probe *probe);
|
||||
static int bhndb_pci_eio_map(struct bhnd_erom_io *eio,
|
||||
bhnd_addr_t addr, bhnd_size_t size);
|
||||
static int bhndb_pci_eio_tell(struct bhnd_erom_io *eio,
|
||||
bhnd_addr_t *addr, bhnd_size_t *size);
|
||||
static uint32_t bhndb_pci_eio_read(struct bhnd_erom_io *eio,
|
||||
bhnd_size_t offset, u_int width);
|
||||
|
||||
|
@ -144,6 +146,7 @@ static struct bhndb_pci_core bhndb_pci_cores[] = {
|
|||
/* bhndb_pci erom I/O instance state */
|
||||
struct bhndb_pci_eio {
|
||||
struct bhnd_erom_io eio;
|
||||
bool mapped; /**< true if a valid mapping exists */
|
||||
bhnd_addr_t addr; /**< mapped address */
|
||||
bhnd_size_t size; /**< mapped size */
|
||||
struct bhndb_pci_probe *probe; /**< borrowed probe reference */
|
||||
|
@ -1667,9 +1670,11 @@ bhndb_pci_eio_init(struct bhndb_pci_eio *pio, struct bhndb_pci_probe *probe)
|
|||
memset(pio, 0, sizeof(*pio));
|
||||
|
||||
pio->eio.map = bhndb_pci_eio_map;
|
||||
pio->eio.tell = bhndb_pci_eio_tell;
|
||||
pio->eio.read = bhndb_pci_eio_read;
|
||||
pio->eio.fini = NULL;
|
||||
|
||||
pio->mapped = false;
|
||||
pio->addr = 0;
|
||||
pio->size = 0;
|
||||
pio->probe = probe;
|
||||
|
@ -1687,6 +1692,23 @@ bhndb_pci_eio_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
|
|||
|
||||
pio->addr = addr;
|
||||
pio->size = size;
|
||||
pio->mapped = true;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* bhnd_erom_io_tell() implementation */
|
||||
static int
|
||||
bhndb_pci_eio_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr,
|
||||
bhnd_size_t *size)
|
||||
{
|
||||
struct bhndb_pci_eio *pio = (struct bhndb_pci_eio *)eio;
|
||||
|
||||
if (!pio->mapped)
|
||||
return (ENXIO);
|
||||
|
||||
*addr = pio->addr;
|
||||
*size = pio->size;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -1697,12 +1719,16 @@ bhndb_pci_eio_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width)
|
|||
{
|
||||
struct bhndb_pci_eio *pio = (struct bhndb_pci_eio *)eio;
|
||||
|
||||
/* Must have a valid mapping */
|
||||
if (!pio->mapped)
|
||||
panic("no active mapping");
|
||||
|
||||
/* The requested subrange must fall within the existing mapped range */
|
||||
if (offset > pio->size ||
|
||||
width > pio->size ||
|
||||
pio->size - offset < width)
|
||||
{
|
||||
return (ENXIO);
|
||||
panic("invalid offset %#jx", offset);
|
||||
}
|
||||
|
||||
return (bhndb_pci_probe_read(pio->probe, pio->addr, offset, width));
|
||||
|
|
|
@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$");
|
|||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/bhnd/bhnd_erom.h>
|
||||
#include <dev/bhnd/bhnd_eromvar.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
|
||||
|
@ -390,7 +390,6 @@ siba_eio_read_chipid(struct siba_erom_io *io, bus_addr_t enum_addr,
|
|||
struct bhnd_chipid *cid)
|
||||
{
|
||||
struct siba_core_id ccid;
|
||||
uint32_t idreg;
|
||||
int error;
|
||||
|
||||
/* Identify the chipcommon core */
|
||||
|
@ -409,12 +408,39 @@ siba_eio_read_chipid(struct siba_erom_io *io, bus_addr_t enum_addr,
|
|||
}
|
||||
|
||||
/* Identify the chipset */
|
||||
idreg = siba_eio_read_4(io, 0, CHIPC_ID);
|
||||
*cid = bhnd_parse_chipid(idreg, enum_addr);
|
||||
if ((error = bhnd_erom_read_chipid(io->eio, cid)))
|
||||
return (error);
|
||||
|
||||
/* Fix up the core count in-place */
|
||||
return (bhnd_chipid_fixed_ncores(cid, ccid.core_info.hwrev,
|
||||
&cid->ncores));
|
||||
/* Do we need to fix up the core count? */
|
||||
if (CHIPC_NCORES_MIN_HWREV(ccid.core_info.hwrev))
|
||||
return (0);
|
||||
|
||||
switch (cid->chip_id) {
|
||||
case BHND_CHIPID_BCM4306:
|
||||
cid->ncores = 6;
|
||||
break;
|
||||
case BHND_CHIPID_BCM4704:
|
||||
cid->ncores = 9;
|
||||
break;
|
||||
case BHND_CHIPID_BCM5365:
|
||||
/*
|
||||
* BCM5365 does support ID_NUMCORE in at least
|
||||
* some of its revisions, but for unknown
|
||||
* reasons, Broadcom's drivers always exclude
|
||||
* the ChipCommon revision (0x5) used by BCM5365
|
||||
* from the set of revisions supporting
|
||||
* ID_NUMCORE, and instead supply a fixed value.
|
||||
*
|
||||
* Presumably, at least some of these devices
|
||||
* shipped with a broken ID_NUMCORE value.
|
||||
*/
|
||||
cid->ncores = 7;
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
Loading…
Reference in a new issue