bhnd(4): Initial PMU/PWRCTL power and clock management support.
- Added bhnd_pmu driver implementations for PMU and PWRCTL chipsets, derived from Broadcom's ISC-licensed HND code. - Added bhnd bus-level support for routing per-core clock and resource power requests to the PMU device. - Lift ChipCommon support out into the bhnd module, dropping bhnd_chipc. Reviewed by: mizhka Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D7492
This commit is contained in:
parent
c4676089b0
commit
f90f4b6532
@ -1157,19 +1157,26 @@ dev/bhnd/bcma/bcma_bhndb.c optional bcma bhnd bhndb
|
||||
dev/bhnd/bcma/bcma_erom.c optional bcma bhnd
|
||||
dev/bhnd/bcma/bcma_nexus.c optional bcma_nexus bcma bhnd
|
||||
dev/bhnd/bcma/bcma_subr.c optional bcma bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_chipc_if.m optional bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_sprom_chipc.c optional bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_pmu_chipc.c optional bhnd
|
||||
dev/bhnd/cores/chipc/chipc.c optional bhnd
|
||||
dev/bhnd/cores/chipc/chipc_cfi.c optional bhnd cfi
|
||||
dev/bhnd/cores/chipc/chipc_slicer.c optional bhnd cfi | bhnd spibus
|
||||
dev/bhnd/cores/chipc/chipc_spi.c optional bhnd spibus
|
||||
dev/bhnd/cores/chipc/chipc_subr.c optional bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_chipc_if.m optional bhnd
|
||||
dev/bhnd/cores/chipc/bhnd_sprom_chipc.c optional bhnd
|
||||
dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.c optional bhnd
|
||||
dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c optional bhnd
|
||||
dev/bhnd/cores/pci/bhnd_pci.c optional bhnd pci
|
||||
dev/bhnd/cores/pci/bhnd_pci_hostb.c optional bhndb bhnd pci
|
||||
dev/bhnd/cores/pci/bhnd_pcib.c optional bhnd_pcib bhnd pci
|
||||
dev/bhnd/cores/pcie2/bhnd_pcie2.c optional bhnd pci
|
||||
dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c optional bhndb bhnd pci
|
||||
dev/bhnd/cores/pcie2/bhnd_pcie2b.c optional bhnd_pcie2b bhnd pci
|
||||
dev/bhnd/cores/pmu/bhnd_pmu.c optional bhnd
|
||||
dev/bhnd/cores/pmu/bhnd_pmu_core.c optional bhnd
|
||||
dev/bhnd/cores/pmu/bhnd_pmu_if.m optional bhnd
|
||||
dev/bhnd/cores/pmu/bhnd_pmu_subr.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_nvram.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_nvram_common.c optional bhnd
|
||||
dev/bhnd/nvram/bhnd_nvram_cfe.c optional bhnd siba_nexus cfe | \
|
||||
|
@ -259,6 +259,78 @@ bcma_suspend_core(device_t dev, device_t child)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
bcma_read_config(device_t dev, device_t child, bus_size_t offset, u_int width)
|
||||
{
|
||||
struct bcma_devinfo *dinfo;
|
||||
struct bhnd_resource *r;
|
||||
|
||||
/* Must be a directly attached child core */
|
||||
if (device_get_parent(child) != dev)
|
||||
return (UINT32_MAX);
|
||||
|
||||
/* Fetch the agent registers */
|
||||
dinfo = device_get_ivars(child);
|
||||
if ((r = dinfo->res_agent) == NULL)
|
||||
return (UINT32_MAX);
|
||||
|
||||
/* Verify bounds */
|
||||
if (offset > rman_get_size(r->res))
|
||||
return (UINT32_MAX);
|
||||
|
||||
if (rman_get_size(r->res) - offset < width)
|
||||
return (UINT32_MAX);
|
||||
|
||||
switch (width) {
|
||||
case 1:
|
||||
return (bhnd_bus_read_1(r, offset));
|
||||
case 2:
|
||||
return (bhnd_bus_read_2(r, offset));
|
||||
case 4:
|
||||
return (bhnd_bus_read_4(r, offset));
|
||||
default:
|
||||
return (UINT32_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bcma_write_config(device_t dev, device_t child, bus_size_t offset, uint32_t val,
|
||||
u_int width)
|
||||
{
|
||||
struct bcma_devinfo *dinfo;
|
||||
struct bhnd_resource *r;
|
||||
|
||||
/* Must be a directly attached child core */
|
||||
if (device_get_parent(child) != dev)
|
||||
return;
|
||||
|
||||
/* Fetch the agent registers */
|
||||
dinfo = device_get_ivars(child);
|
||||
if ((r = dinfo->res_agent) == NULL)
|
||||
return;
|
||||
|
||||
/* Verify bounds */
|
||||
if (offset > rman_get_size(r->res))
|
||||
return;
|
||||
|
||||
if (rman_get_size(r->res) - offset < width)
|
||||
return;
|
||||
|
||||
switch (width) {
|
||||
case 1:
|
||||
bhnd_bus_write_1(r, offset, val);
|
||||
break;
|
||||
case 2:
|
||||
bhnd_bus_write_2(r, offset, val);
|
||||
break;
|
||||
case 4:
|
||||
bhnd_bus_write_4(r, offset, val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u_int
|
||||
bcma_get_port_count(device_t dev, device_t child, bhnd_port_type type)
|
||||
{
|
||||
@ -473,6 +545,9 @@ bcma_add_children(device_t bus, struct resource *erom_res, bus_size_t erom_offse
|
||||
* unpopulated, the device shouldn't be used. */
|
||||
if (bhnd_is_hw_disabled(child))
|
||||
device_disable(child);
|
||||
|
||||
/* Issue bus callback for fully initialized child. */
|
||||
BHND_BUS_CHILD_ADDED(bus, child);
|
||||
}
|
||||
|
||||
/* Hit EOF parsing cores? */
|
||||
@ -504,6 +579,8 @@ static device_method_t bcma_methods[] = {
|
||||
DEVMETHOD(bhnd_bus_free_devinfo, bcma_free_bhnd_dinfo),
|
||||
DEVMETHOD(bhnd_bus_reset_core, bcma_reset_core),
|
||||
DEVMETHOD(bhnd_bus_suspend_core, bcma_suspend_core),
|
||||
DEVMETHOD(bhnd_bus_read_config, bcma_read_config),
|
||||
DEVMETHOD(bhnd_bus_write_config, bcma_write_config),
|
||||
DEVMETHOD(bhnd_bus_get_port_count, bcma_get_port_count),
|
||||
DEVMETHOD(bhnd_bus_get_region_count, bcma_get_region_count),
|
||||
DEVMETHOD(bhnd_bus_get_port_rid, bcma_get_port_rid),
|
||||
|
@ -109,6 +109,19 @@
|
||||
#define BCMA_DMP_OOBDINWIDTH 0x364
|
||||
#define BCMA_DMP_OOBDOUTWIDTH 0x368
|
||||
|
||||
/* The exact interpretation of these bits is unverified; these
|
||||
* are our best guesses as to their use */
|
||||
#define BCMA_DMP_OOBSEL_MASK 0xFF /**< OOBSEL config mask */
|
||||
#define BCMA_DMP_OOBSEL_0_MASK BCMA_DMP_OOBSEL_MASK
|
||||
#define BCMA_DMP_OOBSEL_1_MASK BCMA_DMP_OOBSEL_MASK
|
||||
#define BCMA_DMP_OOBSEL_2_MASK BCMA_DMP_OOBSEL_MASK
|
||||
#define BCMA_DMP_OOBSEL_3_MASK BCMA_DMP_OOBSEL_MASK
|
||||
#define BCMA_DMP_OOBSEL_0_SHIFT 0 /**< first OOBSEL config */
|
||||
#define BCMA_DMP_OOBSEL_1_SHIFT 8 /**< second OOBSEL config */
|
||||
#define BCMA_DMP_OOBSEL_2_SHIFT 16 /**< third OOBSEL config */
|
||||
#define BCMA_DMP_OOBSEL_3_SHIFT 24 /**< fouth OOBSEL config */
|
||||
#define BCMA_DMP_OOBSEL_EN (1 << 7) /**< enable bit */
|
||||
|
||||
// This was inherited from Broadcom's aidmp.h header
|
||||
// Is it required for any of our use-cases?
|
||||
#if 0 /* defined(IL_BIGENDIAN) && defined(BCMHND74K) */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Landon Fuller <landon@landonf.org>
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -60,6 +60,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcvar.h>
|
||||
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmu.h>
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
#include "bhnd_nvram_if.h"
|
||||
|
||||
@ -342,7 +345,7 @@ bhnd_finish_attach(struct bhnd_softc *sc)
|
||||
{
|
||||
struct chipc_caps *ccaps;
|
||||
|
||||
GIANT_REQUIRED; /* newbus */
|
||||
GIANT_REQUIRED; /* for newbus */
|
||||
|
||||
KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS,
|
||||
("bhnd_finish_attach() called in pass %d", bus_current_pass));
|
||||
@ -367,10 +370,11 @@ bhnd_finish_attach(struct bhnd_softc *sc)
|
||||
}
|
||||
|
||||
/* Look for a PMU */
|
||||
if (ccaps->pmu) {
|
||||
if (ccaps->pmu || ccaps->pwr_ctrl) {
|
||||
if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) {
|
||||
device_printf(sc->dev,
|
||||
"warning: PMU device not found\n");
|
||||
"attach failed: supported PMU not found\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,8 +482,6 @@ found:
|
||||
static device_t
|
||||
bhnd_find_pmu(struct bhnd_softc *sc)
|
||||
{
|
||||
struct chipc_caps *ccaps;
|
||||
|
||||
/* Make sure we're holding Giant for newbus */
|
||||
GIANT_REQUIRED;
|
||||
|
||||
@ -494,11 +496,6 @@ bhnd_find_pmu(struct bhnd_softc *sc)
|
||||
return (sc->pmu_dev);
|
||||
}
|
||||
|
||||
if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (!ccaps->pmu)
|
||||
return (NULL);
|
||||
|
||||
return (bhnd_find_platform_dev(sc, "bhnd_pmu"));
|
||||
}
|
||||
@ -625,6 +622,244 @@ bhnd_generic_get_probe_order(device_t dev, device_t child)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_ALLOC_PMU().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_alloc_pmu(device_t dev, device_t child)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_resource *br;
|
||||
struct chipc_caps *ccaps;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
struct resource_list *rl;
|
||||
struct resource_list_entry *rle;
|
||||
device_t pmu_dev;
|
||||
bhnd_addr_t r_addr;
|
||||
bhnd_size_t r_size;
|
||||
bus_size_t pmu_regs;
|
||||
int error;
|
||||
|
||||
GIANT_REQUIRED; /* for newbus */
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
pmu_regs = BHND_CLK_CTL_ST;
|
||||
|
||||
if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL) {
|
||||
device_printf(sc->dev, "alloc_pmu failed: chipc "
|
||||
"capabilities unavailable\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if ((pmu_dev = bhnd_find_pmu(sc)) == NULL) {
|
||||
device_printf(sc->dev,
|
||||
"pmu unavailable; cannot allocate request state\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* already allocated? */
|
||||
if (dinfo->pmu_info != NULL) {
|
||||
panic("duplicate PMU allocation for %s",
|
||||
device_get_nameunit(child));
|
||||
}
|
||||
|
||||
/* Determine address+size of the core's PMU register block */
|
||||
error = bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &r_addr,
|
||||
&r_size);
|
||||
if (error) {
|
||||
device_printf(sc->dev, "error fetching register block info for "
|
||||
"%s: %d\n", device_get_nameunit(child), error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (r_size < (pmu_regs + sizeof(uint32_t))) {
|
||||
device_printf(sc->dev, "pmu offset %#jx would overrun %s "
|
||||
"register block\n", (uintmax_t)pmu_regs,
|
||||
device_get_nameunit(child));
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
/* Locate actual resource containing the core's register block */
|
||||
if ((rl = BUS_GET_RESOURCE_LIST(dev, child)) == NULL) {
|
||||
device_printf(dev, "NULL resource list returned for %s\n",
|
||||
device_get_nameunit(child));
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if ((rle = resource_list_find(rl, SYS_RES_MEMORY, 0)) == NULL) {
|
||||
device_printf(dev, "cannot locate core register resource "
|
||||
"for %s\n", device_get_nameunit(child));
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (rle->res == NULL) {
|
||||
device_printf(dev, "core register resource unallocated for "
|
||||
"%s\n", device_get_nameunit(child));
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (r_addr+pmu_regs < rman_get_start(rle->res) ||
|
||||
r_addr+pmu_regs >= rman_get_end(rle->res))
|
||||
{
|
||||
device_printf(dev, "core register resource does not map PMU "
|
||||
"registers at %#jx\n for %s\n", r_addr+pmu_regs,
|
||||
device_get_nameunit(child));
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Adjust PMU register offset relative to the actual start address
|
||||
* of the core's register block allocation.
|
||||
*
|
||||
* XXX: The saved offset will be invalid if bus_adjust_resource is
|
||||
* used to modify the resource's start address.
|
||||
*/
|
||||
if (rman_get_start(rle->res) > r_addr)
|
||||
pmu_regs -= rman_get_start(rle->res) - r_addr;
|
||||
else
|
||||
pmu_regs -= r_addr - rman_get_start(rle->res);
|
||||
|
||||
/* Allocate and initialize PMU info */
|
||||
br = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT);
|
||||
if (br == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
br->res = rle->res;
|
||||
br->direct = ((rman_get_flags(rle->res) & RF_ACTIVE) != 0);
|
||||
|
||||
pm = malloc(sizeof(*dinfo->pmu_info), M_BHND, M_NOWAIT);
|
||||
if (pm == NULL) {
|
||||
free(br, M_BHND);
|
||||
return (ENOMEM);
|
||||
}
|
||||
pm->pm_dev = child;
|
||||
pm->pm_pmu = pmu_dev;
|
||||
pm->pm_res = br;
|
||||
pm->pm_regs = pmu_regs;
|
||||
|
||||
dinfo->pmu_info = pm;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_PMU().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_release_pmu(device_t dev, device_t child)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
device_t pmu;
|
||||
int error;
|
||||
|
||||
GIANT_REQUIRED; /* for newbus */
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pmu = bhnd_find_pmu(sc)) == NULL) {
|
||||
device_printf(sc->dev,
|
||||
"pmu unavailable; cannot release request state\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* dispatch release request */
|
||||
if (dinfo->pmu_info == NULL)
|
||||
panic("pmu over-release for %s", device_get_nameunit(child));
|
||||
|
||||
if ((error = BHND_PMU_CORE_RELEASE(pmu, dinfo->pmu_info)))
|
||||
return (error);
|
||||
|
||||
/* free PMU info */
|
||||
free(dinfo->pmu_info->pm_res, M_BHND);
|
||||
free(dinfo->pmu_info, M_BHND);
|
||||
dinfo->pmu_info = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_CLOCK().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_request_clock(device_t dev, device_t child, bhnd_clock clock)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pm = dinfo->pmu_info) == NULL)
|
||||
panic("no active PMU request state");
|
||||
|
||||
/* dispatch request to PMU */
|
||||
return (BHND_PMU_CORE_REQ_CLOCK(pm->pm_pmu, pm, clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_ENABLE_CLOCKS().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_enable_clocks(device_t dev, device_t child, uint32_t clocks)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pm = dinfo->pmu_info) == NULL)
|
||||
panic("no active PMU request state");
|
||||
|
||||
/* dispatch request to PMU */
|
||||
return (BHND_PMU_CORE_EN_CLOCKS(pm->pm_pmu, pm, clocks));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_EXT_RSRC().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_request_ext_rsrc(device_t dev, device_t child, u_int rsrc)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pm = dinfo->pmu_info) == NULL)
|
||||
panic("no active PMU request state");
|
||||
|
||||
/* dispatch request to PMU */
|
||||
return (BHND_PMU_CORE_REQ_EXT_RSRC(pm->pm_pmu, pm, rsrc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_EXT_RSRC().
|
||||
*/
|
||||
int
|
||||
bhnd_generic_release_ext_rsrc(device_t dev, device_t child, u_int rsrc)
|
||||
{
|
||||
struct bhnd_softc *sc;
|
||||
struct bhnd_devinfo *dinfo;
|
||||
struct bhnd_core_pmu_info *pm;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
dinfo = device_get_ivars(child);
|
||||
|
||||
if ((pm = dinfo->pmu_info) == NULL)
|
||||
panic("no active PMU request state");
|
||||
|
||||
/* dispatch request to PMU */
|
||||
return (BHND_PMU_CORE_RELEASE_EXT_RSRC(pm->pm_pmu, pm, rsrc));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID().
|
||||
*
|
||||
@ -815,12 +1050,20 @@ bhnd_generic_add_child(device_t dev, u_int order, const char *name, int unit)
|
||||
|
||||
device_set_ivars(child, dinfo);
|
||||
|
||||
/* Inform concrete bus driver. */
|
||||
BHND_BUS_CHILD_ADDED(dev, child);
|
||||
|
||||
return (child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BHND_BUS_CHILD_ADDED().
|
||||
*
|
||||
* This implementation manages internal bhnd(4) state, and must be called
|
||||
* by subclassing drivers.
|
||||
*/
|
||||
void
|
||||
bhnd_generic_child_added(device_t dev, device_t child)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED().
|
||||
*
|
||||
@ -836,8 +1079,17 @@ bhnd_generic_child_deleted(device_t dev, device_t child)
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Free device info */
|
||||
if ((dinfo = device_get_ivars(child)) != NULL)
|
||||
if ((dinfo = device_get_ivars(child)) != NULL) {
|
||||
if (dinfo->pmu_info != NULL) {
|
||||
/* Releasing PMU requests automatically would be nice,
|
||||
* but we can't reference per-core PMU register
|
||||
* resource after driver detach */
|
||||
panic("%s leaked device pmu state\n",
|
||||
device_get_nameunit(child));
|
||||
}
|
||||
|
||||
BHND_BUS_FREE_DEVINFO(dev, dinfo);
|
||||
}
|
||||
|
||||
/* Clean up platform device references */
|
||||
if (sc->chipc_dev == child) {
|
||||
@ -998,9 +1250,20 @@ static device_method_t bhnd_methods[] = {
|
||||
|
||||
/* BHND interface */
|
||||
DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid),
|
||||
DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order),
|
||||
DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid),
|
||||
DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled),
|
||||
DEVMETHOD(bhnd_bus_read_board_info, bhnd_bus_generic_read_board_info),
|
||||
|
||||
DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order),
|
||||
|
||||
DEVMETHOD(bhnd_bus_alloc_pmu, bhnd_generic_alloc_pmu),
|
||||
DEVMETHOD(bhnd_bus_release_pmu, bhnd_generic_release_pmu),
|
||||
DEVMETHOD(bhnd_bus_request_clock, bhnd_generic_request_clock),
|
||||
DEVMETHOD(bhnd_bus_enable_clocks, bhnd_generic_enable_clocks),
|
||||
DEVMETHOD(bhnd_bus_request_ext_rsrc, bhnd_generic_request_ext_rsrc),
|
||||
DEVMETHOD(bhnd_bus_release_ext_rsrc, bhnd_generic_release_ext_rsrc),
|
||||
|
||||
DEVMETHOD(bhnd_bus_child_added, bhnd_generic_child_added),
|
||||
DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid),
|
||||
DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var),
|
||||
|
||||
/* BHND interface (bus I/O) */
|
||||
|
@ -416,6 +416,67 @@ bhnd_get_chipid(device_t dev) {
|
||||
return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev));
|
||||
};
|
||||
|
||||
/**
|
||||
* If supported by the chipset, return the clock source for the given clock.
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev A bhnd bus child device.
|
||||
* @param clock The clock for which a clock source will be returned.
|
||||
*
|
||||
* @retval bhnd_clksrc The clock source for @p clock.
|
||||
* @retval BHND_CLKSRC_UNKNOWN If @p clock is unsupported, or its
|
||||
* clock source is not known to the bus.
|
||||
*/
|
||||
static inline bhnd_clksrc
|
||||
bhnd_pwrctl_get_clksrc(device_t dev, bhnd_clock clock)
|
||||
{
|
||||
return (BHND_BUS_PWRCTL_GET_CLKSRC(device_get_parent(dev), dev, clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* If supported by the chipset, gate @p clock
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev A bhnd bus child device.
|
||||
* @param clock The clock to be disabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If bus-level clock source management is not supported.
|
||||
* @retval ENXIO If bus-level management of @p clock is not supported.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_pwrctl_gate_clock(device_t dev, bhnd_clock clock)
|
||||
{
|
||||
return (BHND_BUS_PWRCTL_GATE_CLOCK(device_get_parent(dev), dev, clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* If supported by the chipset, ungate @p clock
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev A bhnd bus child device.
|
||||
* @param clock The clock to be enabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If bus-level clock source management is not supported.
|
||||
* @retval ENXIO If bus-level management of @p clock is not supported.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_pwrctl_ungate_clock(device_t dev, bhnd_clock clock)
|
||||
{
|
||||
return (BHND_BUS_PWRCTL_UNGATE_CLOCK(device_get_parent(dev), dev,
|
||||
clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BHND attachment type of the parent bhnd bus.
|
||||
*
|
||||
@ -453,6 +514,171 @@ bhnd_read_board_info(device_t dev, struct bhnd_board_info *info)
|
||||
return (BHND_BUS_READ_BOARD_INFO(device_get_parent(dev), dev, info));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate and enable per-core PMU request handling for @p child.
|
||||
*
|
||||
* The region containing the core's PMU register block (if any) must be
|
||||
* allocated via bus_alloc_resource(9) (or bhnd_alloc_resource) before
|
||||
* calling bhnd_alloc_pmu(), and must not be released until after
|
||||
* calling bhnd_release_pmu().
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The requesting bhnd device.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero If allocating PMU request state otherwise fails, a
|
||||
* regular unix error code will be returned.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_alloc_pmu(device_t dev)
|
||||
{
|
||||
return (BHND_BUS_ALLOC_PMU(device_get_parent(dev), dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* Release any per-core PMU resources allocated for @p child. Any outstanding
|
||||
* PMU requests are are discarded.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The requesting bhnd device.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero If releasing PMU request state otherwise fails, a
|
||||
* regular unix error code will be returned, and
|
||||
* the core state will be left unmodified.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_release_pmu(device_t dev)
|
||||
{
|
||||
return (BHND_BUS_RELEASE_PMU(device_get_parent(dev), dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that @p clock (or faster) be routed to @p dev.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate clock request state
|
||||
* via bhnd_alloc_pmu() before it can request clock resources.
|
||||
*
|
||||
* Request multiplexing is managed by the bus.
|
||||
*
|
||||
* @param dev The bhnd(4) device to which @p clock should be routed.
|
||||
* @param clock The requested clock source.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_request_clock(device_t dev, bhnd_clock clock)
|
||||
{
|
||||
return (BHND_BUS_REQUEST_CLOCK(device_get_parent(dev), dev, clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that @p clocks be powered on behalf of @p dev.
|
||||
*
|
||||
* This will power any clock sources (e.g. XTAL, PLL, etc) required for
|
||||
* @p clocks and wait until they are ready, discarding any previous
|
||||
* requests by @p dev.
|
||||
*
|
||||
* Request multiplexing is managed by the bus.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate clock request state
|
||||
* via bhnd_alloc_pmu() before it can request clock resources.
|
||||
*
|
||||
* @param dev The requesting bhnd(4) device.
|
||||
* @param clocks The clock(s) to be enabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_enable_clocks(device_t dev, uint32_t clocks)
|
||||
{
|
||||
return (BHND_BUS_ENABLE_CLOCKS(device_get_parent(dev), dev, clocks));
|
||||
}
|
||||
|
||||
/**
|
||||
* Power up an external PMU-managed resource assigned to @p dev.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via bhnd_alloc_pmu() before it can request PMU resources.
|
||||
*
|
||||
* @param dev The requesting bhnd(4) device.
|
||||
* @param rsrc The core-specific external resource identifier.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If the PMU does not support @p rsrc.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_request_ext_rsrc(device_t dev, u_int rsrc)
|
||||
{
|
||||
return (BHND_BUS_REQUEST_EXT_RSRC(device_get_parent(dev), dev, rsrc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Power down an external PMU-managed resource assigned to @p dev.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via bhnd_alloc_pmu() before it can request PMU resources.
|
||||
*
|
||||
* @param dev The requesting bhnd(4) device.
|
||||
* @param rsrc The core-specific external resource identifier.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If the PMU does not support @p rsrc.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
static inline int
|
||||
bhnd_release_ext_rsrc(device_t dev, u_int rsrc)
|
||||
{
|
||||
return (BHND_BUS_RELEASE_EXT_RSRC(device_get_parent(dev), dev, rsrc));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read @p width bytes at @p offset from the bus-specific agent/config
|
||||
* space of @p dev.
|
||||
*
|
||||
* @param dev The bhnd device for which @p offset should be read.
|
||||
* @param offset The offset to be read.
|
||||
* @param width The size of the access. Must be 1, 2 or 4 bytes.
|
||||
*
|
||||
* The exact behavior of this method is bus-specific. In the case of
|
||||
* bcma(4), this method provides access to the first agent port of @p child.
|
||||
*
|
||||
* @note Device drivers should only use this API for functionality
|
||||
* that is not available via another bhnd(4) function.
|
||||
*/
|
||||
static inline uint32_t
|
||||
bhnd_read_config(device_t dev, bus_size_t offset, u_int width)
|
||||
{
|
||||
return (BHND_BUS_READ_CONFIG(device_get_parent(dev), dev, offset,
|
||||
width));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read @p width bytes at @p offset from the bus-specific agent/config
|
||||
* space of @p dev.
|
||||
*
|
||||
* @param dev The bhnd device for which @p offset should be read.
|
||||
* @param offset The offset to be written.
|
||||
* @param width The size of the access. Must be 1, 2 or 4 bytes.
|
||||
*
|
||||
* The exact behavior of this method is bus-specific. In the case of
|
||||
* bcma(4), this method provides access to the first agent port of @p child.
|
||||
*
|
||||
* @note Device drivers should only use this API for functionality
|
||||
* that is not available via another bhnd(4) function.
|
||||
*/
|
||||
static inline void
|
||||
bhnd_write_config(device_t dev, bus_size_t offset, uint32_t val, u_int width)
|
||||
{
|
||||
BHND_BUS_WRITE_CONFIG(device_get_parent(dev), dev, offset, val, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an NVRAM variable, coerced to the requested @p type.
|
||||
*
|
||||
|
@ -61,6 +61,27 @@ CODE {
|
||||
{
|
||||
panic("bhnd_bus_get_attach_type unimplemented");
|
||||
}
|
||||
|
||||
static bhnd_clksrc
|
||||
bhnd_bus_null_pwrctl_get_clksrc(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
return (BHND_CLKSRC_UNKNOWN);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_pwrctl_gate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_pwrctl_ungate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_read_board_info(device_t dev, device_t child,
|
||||
@ -74,6 +95,60 @@ CODE {
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_alloc_pmu(device_t dev, device_t child)
|
||||
{
|
||||
panic("bhnd_bus_alloc_pmu unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_release_pmu(device_t dev, device_t child)
|
||||
{
|
||||
panic("bhnd_bus_release_pmu unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_request_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
panic("bhnd_bus_request_clock unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_enable_clocks(device_t dev, device_t child,
|
||||
uint32_t clocks)
|
||||
{
|
||||
panic("bhnd_bus_enable_clocks unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_request_ext_rsrc(device_t dev, device_t child,
|
||||
u_int rsrc)
|
||||
{
|
||||
panic("bhnd_bus_request_ext_rsrc unimplemented");
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bus_null_release_ext_rsrc(device_t dev, device_t child,
|
||||
u_int rsrc)
|
||||
{
|
||||
panic("bhnd_bus_release_ext_rsrc unimplemented");
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
bhnd_bus_null_read_config(device_t dev, device_t child,
|
||||
bus_size_t offset, u_int width)
|
||||
{
|
||||
panic("bhnd_bus_null_read_config unimplemented");
|
||||
}
|
||||
|
||||
static void
|
||||
bhnd_bus_null_write_config(device_t dev, device_t child,
|
||||
bus_size_t offset, uint32_t val, u_int width)
|
||||
{
|
||||
panic("bhnd_bus_null_write_config unimplemented");
|
||||
}
|
||||
|
||||
static device_t
|
||||
bhnd_bus_null_find_hostb_device(device_t dev)
|
||||
{
|
||||
@ -261,9 +336,8 @@ METHOD void free_devinfo {
|
||||
/**
|
||||
* Notify a bhnd bus that a child was added.
|
||||
*
|
||||
* Called at the end of BUS_ADD_CHILD() to allow the concrete bhnd(4)
|
||||
* driver instance to initialize any additional driver-specific state for the
|
||||
* child.
|
||||
* This method must be called by concrete bhnd(4) driver impementations
|
||||
* after @p child's bus state is fully initialized.
|
||||
*
|
||||
* @param dev The bhnd bus whose child is being added.
|
||||
* @param child The child added to @p dev.
|
||||
@ -303,6 +377,230 @@ METHOD int suspend_core {
|
||||
device_t child;
|
||||
}
|
||||
|
||||
/**
|
||||
* If supported by the chipset, return the clock source for the given clock.
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting a clock source.
|
||||
* @param clock The clock for which a clock source will be returned.
|
||||
*
|
||||
* @retval bhnd_clksrc The clock source for @p clock.
|
||||
* @retval BHND_CLKSRC_UNKNOWN If @p clock is unsupported, or its
|
||||
* clock source is not known to the bus.
|
||||
*/
|
||||
METHOD bhnd_clksrc pwrctl_get_clksrc {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bhnd_clock clock;
|
||||
} DEFAULT bhnd_bus_null_pwrctl_get_clksrc;
|
||||
|
||||
/**
|
||||
* If supported by the chipset, gate the clock source for @p clock
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting clock gating.
|
||||
* @param clock The clock to be disabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If bus-level clock source management is not supported.
|
||||
* @retval ENXIO If bus-level management of @p clock is not supported.
|
||||
*/
|
||||
METHOD int pwrctl_gate_clock {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bhnd_clock clock;
|
||||
} DEFAULT bhnd_bus_null_pwrctl_gate_clock;
|
||||
|
||||
/**
|
||||
* If supported by the chipset, ungate the clock source for @p clock
|
||||
*
|
||||
* This function is only supported on early PWRCTL-equipped chipsets
|
||||
* that expose clock management via their host bridge interface. Currently,
|
||||
* this includes PCI (not PCIe) devices, with ChipCommon core revisions 0-9.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting clock gating.
|
||||
* @param clock The clock to be enabled.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If bus-level clock source management is not supported.
|
||||
* @retval ENXIO If bus-level management of @p clock is not supported.
|
||||
*/
|
||||
METHOD int pwrctl_ungate_clock {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bhnd_clock clock;
|
||||
} DEFAULT bhnd_bus_null_pwrctl_ungate_clock;
|
||||
|
||||
/**
|
||||
* Allocate and enable per-core PMU request handling for @p child.
|
||||
*
|
||||
* The region containing the core's PMU register block (if any) must be
|
||||
* allocated via bus_alloc_resource(9) (or bhnd_alloc_resource) before
|
||||
* calling BHND_BUS_ALLOC_PMU(), and must not be released until after
|
||||
* calling BHND_BUS_RELEASE_PMU().
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The requesting bhnd device.
|
||||
*/
|
||||
METHOD int alloc_pmu {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
} DEFAULT bhnd_bus_null_alloc_pmu;
|
||||
|
||||
/**
|
||||
* Release per-core PMU resources allocated for @p child. Any
|
||||
* outstanding PMU requests are discarded.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The requesting bhnd device.
|
||||
*/
|
||||
METHOD int release_pmu {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
} DEFAULT bhnd_bus_null_release_pmu;
|
||||
|
||||
/**
|
||||
* Request that @p clock (or faster) be routed to @p child.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via BHND_BUS_ALLOC_PMU() before it can request clock resources.
|
||||
*
|
||||
* Request multiplexing is managed by the bus.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting @p clock.
|
||||
* @param clock The requested clock source.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
METHOD int request_clock {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bhnd_clock clock;
|
||||
} DEFAULT bhnd_bus_null_request_clock;
|
||||
|
||||
/**
|
||||
* Request that @p clocks be powered on behalf of @p child.
|
||||
*
|
||||
* This will power on clock sources (e.g. XTAL, PLL, etc) required for
|
||||
* @p clocks and wait until they are ready, discarding any previous
|
||||
* requests by @p child.
|
||||
*
|
||||
* Request multiplexing is managed by the bus.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via BHND_BUS_ALLOC_PMU() before it can request clock resources.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting @p clock.
|
||||
* @param clock The requested clock source.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
METHOD int enable_clocks {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
uint32_t clocks;
|
||||
} DEFAULT bhnd_bus_null_enable_clocks;
|
||||
|
||||
/**
|
||||
* Power up an external PMU-managed resource assigned to @p child.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via BHND_BUS_ALLOC_PMU() before it can request PMU resources.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting @p rsrc.
|
||||
* @param rsrc The core-specific external resource identifier.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If the PMU does not support @p rsrc.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
METHOD int request_ext_rsrc {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
u_int rsrc;
|
||||
} DEFAULT bhnd_bus_null_request_ext_rsrc;
|
||||
|
||||
/**
|
||||
* Power down an external PMU-managed resource assigned to @p child.
|
||||
*
|
||||
* A driver must ask the bhnd bus to allocate PMU request state
|
||||
* via BHND_BUS_ALLOC_PMU() before it can request PMU resources.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device requesting @p rsrc.
|
||||
* @param rsrc The core-specific external resource number.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If the PMU does not support @p rsrc.
|
||||
* @retval ENXIO If the PMU has not been initialized or is otherwise unvailable.
|
||||
*/
|
||||
METHOD int release_ext_rsrc {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
u_int rsrc;
|
||||
} DEFAULT bhnd_bus_null_release_ext_rsrc;
|
||||
|
||||
/**
|
||||
* Read @p width bytes at @p offset from the bus-specific agent/config
|
||||
* space of @p child.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device for which @p offset should be read.
|
||||
* @param offset The offset to be read.
|
||||
* @param width The size of the access. Must be 1, 2 or 4 bytes.
|
||||
*
|
||||
* The exact behavior of this method is bus-specific. In the case of
|
||||
* bcma(4), this method provides access to the first agent port of @p child.
|
||||
*
|
||||
* @note Device drivers should only use this API for functionality
|
||||
* that is not available via another bhnd(4) function.
|
||||
*/
|
||||
METHOD uint32_t read_config {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bus_size_t offset;
|
||||
u_int width;
|
||||
} DEFAULT bhnd_bus_null_read_config;
|
||||
|
||||
/**
|
||||
* Read @p width bytes at @p offset from the bus-specific agent/config
|
||||
* space of @p child.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param child The bhnd device for which @p offset should be read.
|
||||
* @param offset The offset to be written.
|
||||
* @param width The size of the access. Must be 1, 2 or 4 bytes.
|
||||
*
|
||||
* The exact behavior of this method is bus-specific. In the case of
|
||||
* bcma(4), this method provides access to the first agent port of @p child.
|
||||
*
|
||||
* @note Device drivers should only use this API for functionality
|
||||
* that is not available via another bhnd(4) function.
|
||||
*/
|
||||
METHOD void write_config {
|
||||
device_t dev;
|
||||
device_t child;
|
||||
bus_size_t offset;
|
||||
uint32_t val;
|
||||
u_int width;
|
||||
} DEFAULT bhnd_bus_null_write_config;
|
||||
|
||||
/**
|
||||
* Allocate a bhnd resource.
|
||||
*
|
||||
|
@ -46,40 +46,4 @@
|
||||
|
||||
#define BHND_RESET_SF 0x0804
|
||||
|
||||
/*
|
||||
* A register that is common to all cores to
|
||||
* communicate w/PMU regarding clock control.
|
||||
*
|
||||
* TODO: Determine when this register first appeared.
|
||||
*/
|
||||
#define BHND_CLK_CTL_ST 0x1e0 /**< clock control and status */
|
||||
|
||||
/*
|
||||
* BHND_CLK_CTL_ST register
|
||||
*
|
||||
* Clock Mode Name Description
|
||||
* High Throughput (HT) Full bandwidth, low latency. Generally supplied
|
||||
* from PLL.
|
||||
* Active Low Power (ALP) Register access, low speed DMA.
|
||||
* Idle Low Power (ILP) No interconnect activity, or if long latency
|
||||
* is permitted.
|
||||
*/
|
||||
#define BHND_CCS_FORCEALP 0x00000001 /**< force ALP request */
|
||||
#define BHND_CCS_FORCEHT 0x00000002 /**< force HT request */
|
||||
#define BHND_CCS_FORCEILP 0x00000004 /**< force ILP request */
|
||||
#define BHND_CCS_ALPAREQ 0x00000008 /**< ALP Avail Request */
|
||||
#define BHND_CCS_HTAREQ 0x00000010 /**< HT Avail Request */
|
||||
#define BHND_CCS_FORCEHWREQOFF 0x00000020 /**< Force HW Clock Request Off */
|
||||
#define BHND_CCS_ERSRC_REQ_MASK 0x00000700 /**< external resource requests */
|
||||
#define BHND_CCS_ERSRC_REQ_SHIFT 8
|
||||
#define BHND_CCS_ALPAVAIL 0x00010000 /**< ALP is available */
|
||||
#define BHND_CCS_HTAVAIL 0x00020000 /**< HT is available */
|
||||
#define BHND_CCS_BP_ON_APL 0x00040000 /**< RO: Backplane is running on ALP clock */
|
||||
#define BHND_CCS_BP_ON_HT 0x00080000 /**< RO: Backplane is running on HT clock */
|
||||
#define BHND_CCS_ERSRC_STS_MASK 0x07000000 /**< external resource status */
|
||||
#define BHND_CCS_ERSRC_STS_SHIFT 24
|
||||
|
||||
#define BHND_CCS0_HTAVAIL 0x00010000 /**< HT avail in chipc and pcmcia on 4328a0 */
|
||||
#define BHND_CCS0_ALPAVAIL 0x00020000 /**< ALP avail in chipc and pcmcia on 4328a0 */
|
||||
|
||||
#endif /* _BHND_BHND_CORE_H_ */
|
||||
|
@ -698,12 +698,6 @@
|
||||
#define BHND_GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */
|
||||
#define BHND_GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */
|
||||
|
||||
/* Power Control Defines */
|
||||
#define BHND_CHIPC_PLL_DELAY 150 /* us pll on delay */
|
||||
#define BHND_CHIPC_FREF_DELAY 200 /* us fref change delay */
|
||||
#define BHND_CHIPC_MIN_SLOW_CLK 32 /* us Slow clock period */
|
||||
#define BHND_CHIPC_XTAL_ON_DELAY 1000 /* us crystal power-on delay */
|
||||
|
||||
/* Board Types */
|
||||
#define BHND_BOARD_BU4710 0x0400
|
||||
#define BHND_BOARD_VSIM4710 0x0401
|
||||
|
@ -1311,7 +1311,9 @@ bhnd_bus_generic_read_board_info(device_t dev, device_t child,
|
||||
OPT_BHND_GV(info->board_vendor, BOARDVENDOR, 0);
|
||||
OPT_BHND_GV(info->board_type, BOARDTYPE, 0); /* srom >= 2 */
|
||||
REQ_BHND_GV(info->board_rev, BOARDREV);
|
||||
REQ_BHND_GV(info->board_srom_rev,SROMREV);
|
||||
OPT_BHND_GV(info->board_srom_rev,SROMREV, 0); /* missing in
|
||||
some SoC
|
||||
NVRAM */
|
||||
REQ_BHND_GV(info->board_flags, BOARDFLAGS);
|
||||
OPT_BHND_GV(info->board_flags2, BOARDFLAGS2, 0); /* srom >= 4 */
|
||||
OPT_BHND_GV(info->board_flags3, BOARDFLAGS3, 0); /* srom >= 11 */
|
||||
|
@ -85,6 +85,66 @@ typedef enum {
|
||||
* SoC */
|
||||
} bhnd_attach_type;
|
||||
|
||||
/**
|
||||
* bhnd(4) clock types.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* Dynamically select an appropriate clock source based on all
|
||||
* outstanding clock requests.
|
||||
*/
|
||||
BHND_CLOCK_DYN = (1 << 0),
|
||||
|
||||
/**
|
||||
* Idle Low-Power (ILP).
|
||||
*
|
||||
* No register access is required, or long request latency is
|
||||
* acceptable.
|
||||
*/
|
||||
BHND_CLOCK_ILP = (1 << 1),
|
||||
|
||||
/**
|
||||
* Active Low-Power (ALP).
|
||||
*
|
||||
* Low-latency register access and low-rate DMA.
|
||||
*/
|
||||
BHND_CLOCK_ALP = (1 << 2),
|
||||
|
||||
/**
|
||||
* High Throughput (HT).
|
||||
*
|
||||
* High bus throughput and lowest-latency register access.
|
||||
*/
|
||||
BHND_CLOCK_HT = (1 << 3)
|
||||
} bhnd_clock;
|
||||
|
||||
/**
|
||||
* Given two clock types, return the type with the highest precedence.
|
||||
*/
|
||||
static inline bhnd_clock
|
||||
bhnd_clock_max(bhnd_clock a, bhnd_clock b) {
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
/**
|
||||
* bhnd(4) clock sources.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* Clock is provided by the PCI bus clock
|
||||
*/
|
||||
BHND_CLKSRC_PCI = 0,
|
||||
|
||||
/** Clock is provided by a crystal. */
|
||||
BHND_CLKSRC_XTAL = 1,
|
||||
|
||||
/** Clock is provided by a low power oscillator. */
|
||||
BHND_CLKSRC_LPO = 2,
|
||||
|
||||
/** Clock source is unknown */
|
||||
BHND_CLKSRC_UNKNOWN = 3
|
||||
} bhnd_clksrc;
|
||||
|
||||
/** Evaluates to true if @p cls is a device class that can be configured
|
||||
* as a host bridge device. */
|
||||
#define BHND_DEVCLASS_SUPPORTS_HOSTB(cls) \
|
||||
|
@ -66,11 +66,42 @@ bhnd_bhndb_get_attach_type(device_t dev, device_t child)
|
||||
return (BHND_ATTACH_ADAPTER);
|
||||
}
|
||||
|
||||
static bhnd_clksrc
|
||||
bhnd_bhndb_pwrctl_get_clksrc(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
/* Delegate to parent bridge */
|
||||
return (BHND_BUS_PWRCTL_GET_CLKSRC(device_get_parent(dev), child,
|
||||
clock));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bhndb_pwrctl_gate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
/* Delegate to parent bridge */
|
||||
return (BHND_BUS_PWRCTL_GATE_CLOCK(device_get_parent(dev), child,
|
||||
clock));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_bhndb_pwrctl_ungate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
/* Delegate to parent bridge */
|
||||
return (BHND_BUS_PWRCTL_UNGATE_CLOCK(device_get_parent(dev), child,
|
||||
clock));
|
||||
}
|
||||
|
||||
static device_method_t bhnd_bhndb_methods[] = {
|
||||
/* BHND interface */
|
||||
DEVMETHOD(bhnd_bus_get_attach_type, bhnd_bhndb_get_attach_type),
|
||||
DEVMETHOD(bhnd_bus_read_board_info, bhnd_bhndb_read_board_info),
|
||||
|
||||
DEVMETHOD(bhnd_bus_pwrctl_get_clksrc, bhnd_bhndb_pwrctl_get_clksrc),
|
||||
DEVMETHOD(bhnd_bus_pwrctl_gate_clock, bhnd_bhndb_pwrctl_gate_clock),
|
||||
DEVMETHOD(bhnd_bus_pwrctl_ungate_clock, bhnd_bhndb_pwrctl_ungate_clock),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
|
@ -2028,4 +2028,3 @@ DEFINE_CLASS_0(bhndb, bhndb_driver, bhndb_methods, sizeof(struct bhndb_softc));
|
||||
|
||||
MODULE_VERSION(bhndb, 1);
|
||||
MODULE_DEPEND(bhndb, bhnd, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb, bhnd_chipc, 1, 1, 1);
|
||||
|
@ -606,6 +606,64 @@ bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static bhnd_clksrc
|
||||
bhndb_pci_pwrctl_get_clksrc(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhndb_pci_softc *sc;
|
||||
uint32_t gpio_out;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Only supported on PCI devices */
|
||||
if (sc->pci_devclass != BHND_DEVCLASS_PCI)
|
||||
return (ENODEV);
|
||||
|
||||
/* Only ILP is supported */
|
||||
if (clock != BHND_CLOCK_ILP)
|
||||
return (ENXIO);
|
||||
|
||||
gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
|
||||
if (gpio_out & BHNDB_PCI_GPIO_SCS)
|
||||
return (BHND_CLKSRC_PCI);
|
||||
else
|
||||
return (BHND_CLKSRC_XTAL);
|
||||
}
|
||||
|
||||
static int
|
||||
bhndb_pci_pwrctl_gate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhndb_pci_softc *sc = device_get_softc(dev);
|
||||
|
||||
/* Only supported on PCI devices */
|
||||
if (sc->pci_devclass != BHND_DEVCLASS_PCI)
|
||||
return (ENODEV);
|
||||
|
||||
/* Only HT is supported */
|
||||
if (clock != BHND_CLOCK_HT)
|
||||
return (ENXIO);
|
||||
|
||||
return (bhndb_disable_pci_clocks(sc));
|
||||
}
|
||||
|
||||
static int
|
||||
bhndb_pci_pwrctl_ungate_clock(device_t dev, device_t child,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhndb_pci_softc *sc = device_get_softc(dev);
|
||||
|
||||
/* Only supported on PCI devices */
|
||||
if (sc->pci_devclass != BHND_DEVCLASS_PCI)
|
||||
return (ENODEV);
|
||||
|
||||
/* Only HT is supported */
|
||||
if (clock != BHND_CLOCK_HT)
|
||||
return (ENXIO);
|
||||
|
||||
return (bhndb_enable_pci_clocks(sc));
|
||||
}
|
||||
|
||||
static device_method_t bhndb_pci_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhndb_pci_probe),
|
||||
@ -614,6 +672,11 @@ static device_method_t bhndb_pci_methods[] = {
|
||||
DEVMETHOD(device_suspend, bhndb_pci_suspend),
|
||||
DEVMETHOD(device_detach, bhndb_pci_detach),
|
||||
|
||||
/* BHND interface */
|
||||
DEVMETHOD(bhnd_bus_pwrctl_get_clksrc, bhndb_pci_pwrctl_get_clksrc),
|
||||
DEVMETHOD(bhnd_bus_pwrctl_gate_clock, bhndb_pci_pwrctl_gate_clock),
|
||||
DEVMETHOD(bhnd_bus_pwrctl_ungate_clock, bhndb_pci_pwrctl_ungate_clock),
|
||||
|
||||
/* BHNDB interface */
|
||||
DEVMETHOD(bhndb_init_full_config, bhndb_pci_init_full_config),
|
||||
DEVMETHOD(bhndb_set_window_addr, bhndb_pci_set_window_addr),
|
||||
@ -627,7 +690,6 @@ DEFINE_CLASS_1(bhndb, bhndb_pci_driver, bhndb_pci_methods,
|
||||
|
||||
MODULE_VERSION(bhndb_pci, 1);
|
||||
MODULE_DEPEND(bhndb_pci, bhnd_pci_hostb, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb_pci, bhnd_pcie2_hostb, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb_pci, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb_pci, bhndb, 1, 1, 1);
|
||||
MODULE_DEPEND(bhndb_pci, bhnd, 1, 1, 1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Landon Fuller <landon@landonf.org>
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -45,27 +45,7 @@
|
||||
MALLOC_DECLARE(M_BHND);
|
||||
DECLARE_CLASS(bhnd_driver);
|
||||
|
||||
/**
|
||||
* bhnd per-device info. Must be first member of all subclass
|
||||
* devinfo structures.
|
||||
*/
|
||||
struct bhnd_devinfo {
|
||||
};
|
||||
|
||||
/**
|
||||
* bhnd driver instance state. Must be first member of all subclass
|
||||
* softc structures.
|
||||
*/
|
||||
struct bhnd_softc {
|
||||
device_t dev; /**< bus device */
|
||||
|
||||
bool attach_done; /**< true if initialization of all
|
||||
* platform devices has been
|
||||
* completed */
|
||||
device_t chipc_dev; /**< bhnd_chipc device */
|
||||
device_t nvram_dev; /**< bhnd_nvram device, if any */
|
||||
device_t pmu_dev; /**< bhnd_pmu device, if any */
|
||||
};
|
||||
struct bhnd_core_pmu_info;
|
||||
|
||||
int bhnd_generic_attach(device_t dev);
|
||||
int bhnd_generic_detach(device_t dev);
|
||||
@ -76,6 +56,19 @@ int bhnd_generic_suspend(device_t dev);
|
||||
int bhnd_generic_get_probe_order(device_t dev,
|
||||
device_t child);
|
||||
|
||||
int bhnd_generic_alloc_pmu(device_t dev,
|
||||
device_t child);
|
||||
int bhnd_generic_release_pmu(device_t dev,
|
||||
device_t child);
|
||||
int bhnd_generic_request_clock(device_t dev,
|
||||
device_t child, bhnd_clock clock);
|
||||
int bhnd_generic_enable_clocks(device_t dev,
|
||||
device_t child, uint32_t clocks);
|
||||
int bhnd_generic_request_ext_rsrc(device_t dev,
|
||||
device_t child, u_int rsrc);
|
||||
int bhnd_generic_release_ext_rsrc(device_t dev,
|
||||
device_t child, u_int rsrc);
|
||||
|
||||
int bhnd_generic_print_child(device_t dev,
|
||||
device_t child);
|
||||
void bhnd_generic_probe_nomatch(device_t dev,
|
||||
@ -83,6 +76,7 @@ void bhnd_generic_probe_nomatch(device_t dev,
|
||||
|
||||
device_t bhnd_generic_add_child(device_t dev, u_int order,
|
||||
const char *name, int unit);
|
||||
void bhnd_generic_child_added(device_t dev, device_t child);
|
||||
void bhnd_generic_child_deleted(device_t dev,
|
||||
device_t child);
|
||||
int bhnd_generic_suspend_child(device_t dev,
|
||||
@ -94,4 +88,28 @@ int bhnd_generic_get_nvram_var(device_t dev,
|
||||
device_t child, const char *name, void *buf,
|
||||
size_t *size, bhnd_nvram_type type);
|
||||
|
||||
|
||||
/**
|
||||
* bhnd per-device info. Must be first member of all subclass
|
||||
* devinfo structures.
|
||||
*/
|
||||
struct bhnd_devinfo {
|
||||
struct bhnd_core_pmu_info *pmu_info; /**< PMU info, or NULL */
|
||||
};
|
||||
|
||||
/**
|
||||
* bhnd driver instance state. Must be first member of all subclass
|
||||
* softc structures.
|
||||
*/
|
||||
struct bhnd_softc {
|
||||
device_t dev; /**< bus device */
|
||||
|
||||
bool attach_done; /**< true if initialization of
|
||||
* all platform devices has
|
||||
* been completed */
|
||||
device_t chipc_dev; /**< bhnd_chipc device */
|
||||
device_t nvram_dev; /**< bhnd_nvram device, if any */
|
||||
device_t pmu_dev; /**< bhnd_pmu device, if any */
|
||||
};
|
||||
|
||||
#endif /* _BHND_BHNDVAR_H_ */
|
||||
|
@ -48,6 +48,22 @@ CODE {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the current value of the chipstatus register.
|
||||
*
|
||||
* @param dev A bhnd(4) ChipCommon device.
|
||||
*
|
||||
* Drivers should only use function for functionality that is not
|
||||
* available via another bhnd_chipc() function.
|
||||
*
|
||||
* @returns The chipstatus register value, or 0 if undefined by this
|
||||
* hardware (e.g. if @p dev is an EXTIF core).
|
||||
*/
|
||||
METHOD uint32_t read_chipst {
|
||||
device_t dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write @p value with @p mask directly to the chipctrl register.
|
||||
*
|
||||
|
126
sys/dev/bhnd/cores/chipc/bhnd_pmu_chipc.c
Normal file
126
sys/dev/bhnd/cores/chipc/bhnd_pmu_chipc.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landon@landonf.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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* ChipCommon attachment support for the bhnd(4) PMU driver.
|
||||
*
|
||||
* Supports non-AOB ("Always-on Bus") devices that map the PMU register blocks
|
||||
* via the ChipCommon core, rather than vending a distinct PMU core on the
|
||||
* bhnd bus.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
#include "bhnd_pmu_if.h"
|
||||
|
||||
#include "chipcvar.h"
|
||||
|
||||
static int
|
||||
bhnd_pmu_chipc_probe(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
struct chipc_caps *ccaps;
|
||||
struct chipc_softc *chipc_sc;
|
||||
device_t chipc;
|
||||
char desc[34];
|
||||
int error;
|
||||
uint32_t pcaps;
|
||||
uint8_t rev;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Look for chipc parent */
|
||||
chipc = device_get_parent(dev);
|
||||
if (device_get_devclass(chipc) != devclass_find("bhnd_chipc"))
|
||||
return (ENXIO);
|
||||
|
||||
/* Check the chipc PMU capability flag. */
|
||||
ccaps = BHND_CHIPC_GET_CAPS(chipc);
|
||||
if (!ccaps->pmu)
|
||||
return (ENXIO);
|
||||
|
||||
/* Delegate to common driver implementation */
|
||||
if ((error = bhnd_pmu_probe(dev)) > 0)
|
||||
return (error);
|
||||
|
||||
/* Fetch PMU capability flags */
|
||||
chipc_sc = device_get_softc(chipc);
|
||||
pcaps = bhnd_bus_read_4(chipc_sc->core, BHND_PMU_CAP);
|
||||
|
||||
/* Set description */
|
||||
rev = BHND_PMU_GET_BITS(pcaps, BHND_PMU_CAP_REV);
|
||||
snprintf(desc, sizeof(desc), "Broadcom ChipCommon PMU, rev %hhu", rev);
|
||||
device_set_desc_copy(dev, desc);
|
||||
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_chipc_attach(device_t dev)
|
||||
{
|
||||
struct chipc_softc *chipc_sc;
|
||||
struct bhnd_resource *r;
|
||||
|
||||
/* Fetch core registers from ChipCommon parent */
|
||||
chipc_sc = device_get_softc(device_get_parent(dev));
|
||||
r = chipc_sc->core;
|
||||
|
||||
return (bhnd_pmu_attach(dev, r));
|
||||
}
|
||||
|
||||
static device_method_t bhnd_pmu_chipc_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_pmu_chipc_probe),
|
||||
DEVMETHOD(device_attach, bhnd_pmu_chipc_attach),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(bhnd_pmu, bhnd_pmu_chipc_driver, bhnd_pmu_chipc_methods,
|
||||
sizeof(struct bhnd_pmu_softc), bhnd_pmu_driver);
|
||||
EARLY_DRIVER_MODULE(bhnd_pmu_chipc, bhnd_chipc, bhnd_pmu_chipc_driver,
|
||||
bhnd_pmu_devclass, NULL, NULL, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
|
||||
|
||||
MODULE_DEPEND(bhnd_pmu_chipc, bhnd, 1, 1, 1);
|
||||
MODULE_VERSION(bhnd_pmu_chipc, 1);
|
@ -46,10 +46,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/bhnd/nvram/bhnd_nvram.h>
|
||||
#include <dev/bhnd/nvram/bhnd_spromvar.h>
|
||||
|
||||
#include "bhnd_nvram_if.h"
|
||||
#include <dev/bhnd/cores/chipc/chipc.h>
|
||||
|
||||
#include "chipcvar.h"
|
||||
#include "chipc_private.h"
|
||||
#include "bhnd_nvram_if.h"
|
||||
|
||||
#define CHIPC_VALID_SPROM_SRC(_src) \
|
||||
((_src) == BHND_NVRAM_SRC_SPROM || (_src) == BHND_NVRAM_SRC_OTP)
|
||||
|
@ -110,25 +110,27 @@ static struct bhnd_device_quirk chipc_quirks[] = {
|
||||
// FIXME: IRQ shouldn't be hard-coded
|
||||
#define CHIPC_MIPS_IRQ 2
|
||||
|
||||
static int chipc_add_children(struct chipc_softc *sc);
|
||||
static int chipc_add_children(struct chipc_softc *sc);
|
||||
|
||||
static bhnd_nvram_src chipc_find_nvram_src(struct chipc_softc *sc,
|
||||
struct chipc_caps *caps);
|
||||
static int chipc_read_caps(struct chipc_softc *sc,
|
||||
struct chipc_caps *caps);
|
||||
static bhnd_nvram_src chipc_find_nvram_src(struct chipc_softc *sc,
|
||||
struct chipc_caps *caps);
|
||||
static int chipc_read_caps(struct chipc_softc *sc,
|
||||
struct chipc_caps *caps);
|
||||
|
||||
static bool chipc_should_enable_sprom(
|
||||
struct chipc_softc *sc);
|
||||
static bool chipc_should_enable_muxed_sprom(
|
||||
struct chipc_softc *sc);
|
||||
static int chipc_enable_otp_power(struct chipc_softc *sc);
|
||||
static void chipc_disable_otp_power(struct chipc_softc *sc);
|
||||
static int chipc_enable_sprom_pins(struct chipc_softc *sc);
|
||||
static void chipc_disable_sprom_pins(struct chipc_softc *sc);
|
||||
|
||||
static int chipc_try_activate_resource(
|
||||
struct chipc_softc *sc, device_t child,
|
||||
int type, int rid, struct resource *r,
|
||||
bool req_direct);
|
||||
static int chipc_try_activate_resource(struct chipc_softc *sc,
|
||||
device_t child, int type, int rid,
|
||||
struct resource *r, bool req_direct);
|
||||
|
||||
static int chipc_init_rman(struct chipc_softc *sc);
|
||||
static void chipc_free_rman(struct chipc_softc *sc);
|
||||
static struct rman *chipc_get_rman(struct chipc_softc *sc,
|
||||
int type);
|
||||
static int chipc_init_rman(struct chipc_softc *sc);
|
||||
static void chipc_free_rman(struct chipc_softc *sc);
|
||||
static struct rman *chipc_get_rman(struct chipc_softc *sc, int type);
|
||||
|
||||
/* quirk and capability flag convenience macros */
|
||||
#define CHIPC_QUIRK(_sc, _name) \
|
||||
@ -266,40 +268,19 @@ chipc_add_children(struct chipc_softc *sc)
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef notyet
|
||||
/*
|
||||
* PMU/SLOWCLK/INSTACLK
|
||||
* PMU/PWR_CTRL
|
||||
*
|
||||
* On AOB ("Always on Bus") devices, a PMU core (if it exists) is
|
||||
* enumerated directly by the bhnd(4) bus -- not chipc.
|
||||
*
|
||||
* Otherwise, we always add a PMU child device, and let the
|
||||
* chipc bhnd_pmu drivers probe for it. If the core supports an
|
||||
* earlier non-PMU clock/power register interface, one of the instaclk,
|
||||
* powerctl, or null bhnd_pmu drivers will claim the device.
|
||||
* On AOB ("Always on Bus") devices, the PMU core (if it exists) is
|
||||
* attached directly to the bhnd(4) bus -- not chipc.
|
||||
*/
|
||||
if (!sc->caps.aob || (sc->caps.aob && !sc->caps.pmu)) {
|
||||
if (sc->caps.pwr_ctrl || (sc->caps.pmu && !sc->caps.aob)) {
|
||||
child = BUS_ADD_CHILD(sc->dev, 0, "bhnd_pmu", -1);
|
||||
if (child == NULL) {
|
||||
device_printf(sc->dev, "failed to add pmu\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Associate the applicable register block */
|
||||
error = 0;
|
||||
if (sc->caps.pmu) {
|
||||
error = chipc_set_resource(sc, child, SYS_RES_MEMORY, 0,
|
||||
CHIPC_PMU, CHIPC_PMU_SIZE, 0, 0);
|
||||
} else if (sc->caps.power_control) {
|
||||
error = chipc_set_resource(sc, child, SYS_RES_MEMORY, 0,
|
||||
CHIPC_PWRCTL, CHIPC_PWRCTL_SIZE, 0, 0);
|
||||
}
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
}
|
||||
#endif /* notyet */
|
||||
|
||||
/* All remaining devices are SoC-only */
|
||||
if (bhnd_get_attach_type(sc->dev) != BHND_ATTACH_NATIVE)
|
||||
@ -422,7 +403,7 @@ chipc_read_caps(struct chipc_softc *sc, struct chipc_caps *caps)
|
||||
caps->uart_clock = CHIPC_GET_BITS(cap_reg, CHIPC_CAP_UCLKSEL);
|
||||
|
||||
caps->extbus_type = CHIPC_GET_BITS(cap_reg, CHIPC_CAP_EXTBUS);
|
||||
caps->power_control = CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_PWR_CTL);
|
||||
caps->pwr_ctrl = CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_PWR_CTL);
|
||||
caps->jtag_master = CHIPC_GET_FLAG(cap_reg, CHIPC_CAP_JTAGP);
|
||||
|
||||
caps->pll_type = CHIPC_GET_BITS(cap_reg, CHIPC_CAP_PLL);
|
||||
@ -1089,7 +1070,7 @@ chipc_deactivate_resource(device_t dev, device_t child, int type,
|
||||
* @param sc chipc driver state.
|
||||
*/
|
||||
static bool
|
||||
chipc_should_enable_sprom(struct chipc_softc *sc)
|
||||
chipc_should_enable_muxed_sprom(struct chipc_softc *sc)
|
||||
{
|
||||
device_t *devs;
|
||||
device_t hostb;
|
||||
@ -1098,17 +1079,19 @@ chipc_should_enable_sprom(struct chipc_softc *sc)
|
||||
int error;
|
||||
bool result;
|
||||
|
||||
mtx_assert(&Giant, MA_OWNED); /* for newbus */
|
||||
|
||||
/* Nothing to do? */
|
||||
if (!CHIPC_QUIRK(sc, MUX_SPROM))
|
||||
return (true);
|
||||
|
||||
mtx_lock(&Giant); /* for newbus */
|
||||
|
||||
parent = device_get_parent(sc->dev);
|
||||
hostb = bhnd_find_hostb_device(parent);
|
||||
|
||||
if ((error = device_get_children(parent, &devs, &devcount)))
|
||||
if ((error = device_get_children(parent, &devs, &devcount))) {
|
||||
mtx_unlock(&Giant);
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* Reject any active devices other than ChipCommon, or the
|
||||
* host bridge (if any). */
|
||||
@ -1129,42 +1112,112 @@ chipc_should_enable_sprom(struct chipc_softc *sc)
|
||||
}
|
||||
|
||||
free(devs, M_TEMP);
|
||||
mtx_unlock(&Giant);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
chipc_enable_sprom(device_t dev)
|
||||
{
|
||||
struct chipc_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
CHIPC_LOCK(sc);
|
||||
|
||||
/* Already enabled? */
|
||||
if (sc->sprom_refcnt >= 1) {
|
||||
sc->sprom_refcnt++;
|
||||
CHIPC_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
switch (sc->caps.nvram_src) {
|
||||
case BHND_NVRAM_SRC_SPROM:
|
||||
error = chipc_enable_sprom_pins(sc);
|
||||
break;
|
||||
case BHND_NVRAM_SRC_OTP:
|
||||
error = chipc_enable_otp_power(sc);
|
||||
break;
|
||||
default:
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Bump the reference count */
|
||||
if (error == 0)
|
||||
sc->sprom_refcnt++;
|
||||
|
||||
CHIPC_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
chipc_disable_sprom(device_t dev)
|
||||
{
|
||||
struct chipc_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
CHIPC_LOCK(sc);
|
||||
|
||||
/* Check reference count, skip disable if in-use. */
|
||||
KASSERT(sc->sprom_refcnt > 0, ("sprom refcnt overrelease"));
|
||||
sc->sprom_refcnt--;
|
||||
if (sc->sprom_refcnt > 0) {
|
||||
CHIPC_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (sc->caps.nvram_src) {
|
||||
case BHND_NVRAM_SRC_SPROM:
|
||||
chipc_disable_sprom_pins(sc);
|
||||
break;
|
||||
case BHND_NVRAM_SRC_OTP:
|
||||
chipc_disable_otp_power(sc);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
CHIPC_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
chipc_enable_otp_power(struct chipc_softc *sc)
|
||||
{
|
||||
// TODO: Enable OTP resource via PMU, and wait up to 100 usec for
|
||||
// OTPS_READY to be set in `optstatus`.
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
chipc_disable_otp_power(struct chipc_softc *sc)
|
||||
{
|
||||
// TODO: Disable OTP resource via PMU
|
||||
}
|
||||
|
||||
/**
|
||||
* If required by this device, enable access to the SPROM.
|
||||
*
|
||||
* @param sc chipc driver state.
|
||||
*/
|
||||
static int
|
||||
chipc_enable_sprom_pins(device_t dev)
|
||||
chipc_enable_sprom_pins(struct chipc_softc *sc)
|
||||
{
|
||||
struct chipc_softc *sc;
|
||||
uint32_t cctrl;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
CHIPC_LOCK_ASSERT(sc, MA_OWNED);
|
||||
KASSERT(sc->sprom_refcnt == 0, ("sprom pins already enabled"));
|
||||
|
||||
/* Nothing to do? */
|
||||
if (!CHIPC_QUIRK(sc, MUX_SPROM))
|
||||
return (0);
|
||||
|
||||
/* Make sure we're holding Giant for newbus */
|
||||
mtx_lock(&Giant);
|
||||
CHIPC_LOCK(sc);
|
||||
|
||||
/* Already enabled? */
|
||||
if (sc->sprom_refcnt >= 1) {
|
||||
error = 0;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
/* Check whether bus is busy */
|
||||
if (!chipc_should_enable_sprom(sc)) {
|
||||
error = EBUSY;
|
||||
goto finished;
|
||||
}
|
||||
if (!chipc_should_enable_muxed_sprom(sc))
|
||||
return (EBUSY);
|
||||
|
||||
cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL);
|
||||
|
||||
@ -1179,8 +1232,7 @@ chipc_enable_sprom_pins(device_t dev)
|
||||
cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN2;
|
||||
|
||||
bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl);
|
||||
error = 0;
|
||||
goto finished;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* 4360 devices */
|
||||
@ -1190,17 +1242,7 @@ chipc_enable_sprom_pins(device_t dev)
|
||||
|
||||
/* Refuse to proceed on unsupported devices with muxed SPROM pins */
|
||||
device_printf(sc->dev, "muxed sprom lines on unrecognized device\n");
|
||||
error = ENXIO;
|
||||
|
||||
finished:
|
||||
/* Bump the reference count */
|
||||
if (error == 0)
|
||||
sc->sprom_refcnt++;
|
||||
|
||||
CHIPC_UNLOCK(sc);
|
||||
mtx_unlock(&Giant);
|
||||
|
||||
return (error);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1210,24 +1252,17 @@ finished:
|
||||
* @param sc chipc driver state.
|
||||
*/
|
||||
static void
|
||||
chipc_disable_sprom_pins(device_t dev)
|
||||
chipc_disable_sprom_pins(struct chipc_softc *sc)
|
||||
{
|
||||
struct chipc_softc *sc;
|
||||
uint32_t cctrl;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Nothing to do? */
|
||||
if (!CHIPC_QUIRK(sc, MUX_SPROM))
|
||||
return;
|
||||
|
||||
CHIPC_LOCK(sc);
|
||||
|
||||
/* Check reference count, skip disable if in-use. */
|
||||
KASSERT(sc->sprom_refcnt > 0, ("sprom refcnt overrelease"));
|
||||
sc->sprom_refcnt--;
|
||||
if (sc->sprom_refcnt > 0)
|
||||
goto finished;
|
||||
CHIPC_LOCK_ASSERT(sc, MA_OWNED);
|
||||
KASSERT(sc->sprom_refcnt != 0, ("sprom pins already disabled"));
|
||||
KASSERT(sc->sprom_refcnt == 1, ("sprom pins in use"));
|
||||
|
||||
cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL);
|
||||
|
||||
@ -1242,16 +1277,20 @@ chipc_disable_sprom_pins(device_t dev)
|
||||
cctrl |= CHIPC_CCTRL4331_EXTPA_EN2;
|
||||
|
||||
bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl);
|
||||
goto finished;
|
||||
return;
|
||||
}
|
||||
|
||||
/* 4360 devices */
|
||||
if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) {
|
||||
/* Unimplemented */
|
||||
}
|
||||
}
|
||||
|
||||
finished:
|
||||
CHIPC_UNLOCK(sc);
|
||||
static uint32_t
|
||||
chipc_read_chipst(device_t dev)
|
||||
{
|
||||
struct chipc_softc *sc = device_get_softc(dev);
|
||||
return (bhnd_bus_read_4(sc->core, CHIPC_CHIPST));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1317,16 +1356,17 @@ static device_method_t chipc_methods[] = {
|
||||
DEVMETHOD(bhnd_bus_activate_resource, chipc_activate_bhnd_resource),
|
||||
|
||||
/* ChipCommon interface */
|
||||
DEVMETHOD(bhnd_chipc_read_chipst, chipc_read_chipst),
|
||||
DEVMETHOD(bhnd_chipc_write_chipctrl, chipc_write_chipctrl),
|
||||
DEVMETHOD(bhnd_chipc_enable_sprom, chipc_enable_sprom_pins),
|
||||
DEVMETHOD(bhnd_chipc_disable_sprom, chipc_disable_sprom_pins),
|
||||
DEVMETHOD(bhnd_chipc_enable_sprom, chipc_enable_sprom),
|
||||
DEVMETHOD(bhnd_chipc_disable_sprom, chipc_disable_sprom),
|
||||
DEVMETHOD(bhnd_chipc_get_caps, chipc_get_caps),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(bhnd_chipc, chipc_driver, chipc_methods, sizeof(struct chipc_softc));
|
||||
EARLY_DRIVER_MODULE(bhnd_chipc, bhnd, chipc_driver, bhnd_chipc_devclass, 0, 0,
|
||||
DEFINE_CLASS_0(bhnd_chipc, bhnd_chipc_driver, chipc_methods, sizeof(struct chipc_softc));
|
||||
EARLY_DRIVER_MODULE(bhnd_chipc, bhnd, bhnd_chipc_driver, bhnd_chipc_devclass, 0, 0,
|
||||
BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
|
||||
MODULE_DEPEND(bhnd_chipc, bhnd, 1, 1, 1);
|
||||
MODULE_VERSION(bhnd_chipc, 1);
|
||||
|
@ -37,4 +37,60 @@
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
|
||||
/**
|
||||
* Supported ChipCommon flash types.
|
||||
*/
|
||||
typedef enum {
|
||||
CHIPC_FLASH_NONE = 0, /**< No flash, or a type unrecognized
|
||||
by the ChipCommon driver */
|
||||
CHIPC_PFLASH_CFI = 1, /**< CFI-compatible parallel flash */
|
||||
CHIPC_SFLASH_ST = 2, /**< ST serial flash */
|
||||
CHIPC_SFLASH_AT = 3, /**< Atmel serial flash */
|
||||
CHIPC_QSFLASH_ST = 4, /**< ST quad-SPI flash */
|
||||
CHIPC_QSFLASH_AT = 5, /**< Atmel quad-SPI flash */
|
||||
CHIPC_NFLASH = 6, /**< NAND flash */
|
||||
CHIPC_NFLASH_4706 = 7 /**< BCM4706 NAND flash */
|
||||
} chipc_flash;
|
||||
|
||||
/**
|
||||
* ChipCommon capability flags;
|
||||
*/
|
||||
struct chipc_caps {
|
||||
uint8_t num_uarts; /**< Number of attached UARTS (1-3) */
|
||||
bool mipseb; /**< MIPS is big-endian */
|
||||
uint8_t uart_clock; /**< UART clock source (see CHIPC_CAP_UCLKSEL_*) */
|
||||
uint8_t uart_gpio; /**< UARTs own GPIO pins 12-15 */
|
||||
|
||||
uint8_t extbus_type; /**< ExtBus type (CHIPC_CAP_EXTBUS_*) */
|
||||
|
||||
chipc_flash flash_type; /**< flash type */
|
||||
uint8_t cfi_width; /**< CFI bus width, 0 if unknown or CFI
|
||||
not present */
|
||||
|
||||
bhnd_nvram_src nvram_src; /**< identified NVRAM source */
|
||||
bus_size_t sprom_offset; /**< Offset to SPROM data within
|
||||
SPROM/OTP, 0 if unknown or not
|
||||
present */
|
||||
uint8_t otp_size; /**< OTP (row?) size, 0 if not present */
|
||||
|
||||
uint8_t pll_type; /**< PLL type */
|
||||
bool pwr_ctrl; /**< Power/clock control available */
|
||||
bool jtag_master; /**< JTAG Master present */
|
||||
bool boot_rom; /**< Internal boot ROM is active */
|
||||
uint8_t backplane_64; /**< Backplane supports 64-bit addressing.
|
||||
Note that this does not gaurantee
|
||||
the CPU itself supports 64-bit
|
||||
addressing. */
|
||||
bool pmu; /**< PMU is present. */
|
||||
bool eci; /**< ECI (enhanced coexistence inteface) is present. */
|
||||
bool seci; /**< SECI (serial ECI) is present */
|
||||
bool sprom; /**< SPROM is present */
|
||||
bool gsio; /**< GSIO (SPI/I2C) present */
|
||||
bool aob; /**< AOB (always on bus) present.
|
||||
If set, PMU and GCI registers are
|
||||
not accessible via ChipCommon,
|
||||
and are instead accessible via
|
||||
dedicated cores on the bhnd bus */
|
||||
};
|
||||
|
||||
#endif /* _BHND_CORES_CHIPC_CHIPC_H_ */
|
||||
|
@ -248,8 +248,8 @@ chipc_print_caps(device_t dev, struct chipc_caps *caps)
|
||||
CC_TFS(sprom), CC_TFS(otp_size));
|
||||
device_printf(dev, "CFIsz: 0x%02x | OTPsz: 0x%02x\n",
|
||||
caps->cfi_width, caps->otp_size);
|
||||
device_printf(dev, "ExtBus: 0x%02x | PwCtl: %s\n",
|
||||
caps->extbus_type, CC_TFS(power_control));
|
||||
device_printf(dev, "ExtBus: 0x%02x | PwrCtrl: %s\n",
|
||||
caps->extbus_type, CC_TFS(pwr_ctrl));
|
||||
device_printf(dev, "PLL: 0x%02x | JTAGM: %s\n",
|
||||
caps->pll_type, CC_TFS(jtag_master));
|
||||
device_printf(dev, "PMU: %-3s | ECI: %s\n",
|
||||
|
@ -100,24 +100,25 @@
|
||||
#define CHIPC_GPIOTIMERVAL 0x88 /**< gpio-based LED duty cycle (rev >= 16) */
|
||||
#define CHIPC_GPIOTIMEROUTMASK 0x8C
|
||||
|
||||
/* clock control block */
|
||||
/* clock control registers (non-PMU devices) */
|
||||
#define CHIPC_CLKC_N 0x90
|
||||
#define CHIPC_CLKC_SB 0x94 /* m0 (backplane) */
|
||||
#define CHIPC_CLKC_PCI 0x98 /* m1 */
|
||||
#define CHIPC_CLKC_M2 0x9C /* mii/uart/mipsref */
|
||||
#define CHIPC_CLKC_M3 0xA0 /* cpu */
|
||||
#define CHIPC_CLKDIV 0xA4 /* rev >= 3 */
|
||||
|
||||
#define CHIPC_GPIODEBUGSEL 0xA8 /* rev >= 28 */
|
||||
#define CHIPC_CAPABILITIES_EXT 0xAC
|
||||
|
||||
/* pll delay (registers rev >= 4) */
|
||||
#define CHIPC_PLL_ON_DELAY 0xB0
|
||||
#define CHIPC_PLL_FREFSEL_DELAY 0xB4
|
||||
#define CHIPC_PLL_SLOWCLK_CTL 0xB8 /* revs 6-9 */
|
||||
|
||||
/* "instaclock" registers */
|
||||
#define CHIPC_SYS_CLK_CTL 0xC0 /* rev >= 10 */
|
||||
#define CHIPC_SYS_CLKSTATESTRETCH 0xC4 /* rev >= 10 */
|
||||
/* pll/slowclk clock control registers (rev >= 4) */
|
||||
#define CHIPC_PLL_ON_DELAY 0xB0 /* rev >= 4 */
|
||||
#define CHIPC_PLL_FREFSEL_DELAY 0xB4 /* rev >= 4 */
|
||||
#define CHIPC_PLL_SLOWCLK_CTL 0xB8 /* "slowclock" (rev 6-9) */
|
||||
|
||||
/* "instaclock" clock control registers */
|
||||
#define CHIPC_SYS_CLK_CTL 0xC0 /* "instaclock" (rev >= 10) */
|
||||
#define CHIPC_SYS_CLK_ST_STRETCH 0xC4 /* state strech (?) rev >= 10 */
|
||||
|
||||
/* indirect backplane access (rev >= 10) */
|
||||
#define CHIPC_BP_ADDRLOW 0xD0
|
||||
@ -135,7 +136,7 @@
|
||||
|
||||
#define CHIPC_EROMPTR 0xFC /**< 32-bit EROM base address
|
||||
* on BCMA devices */
|
||||
|
||||
|
||||
/* ExtBus control registers (rev >= 3) */
|
||||
#define CHIPC_PCMCIA_CFG 0x100
|
||||
#define CHIPC_PCMCIA_MEMWAIT 0x104
|
||||
@ -188,38 +189,10 @@
|
||||
#define CHIPC_UART_MAX 3 /**< max UART blocks */
|
||||
#define CHIPC_UART(_n) (CHIPC_UART_BASE + (CHIPC_UART_SIZE*_n))
|
||||
|
||||
/* PMU registers (rev >= 20) */
|
||||
/* PMU register block (rev >= 20) */
|
||||
#define CHIPC_PMU_BASE 0x600
|
||||
#define CHIPC_PMU_SIZE 0x70
|
||||
|
||||
#define CHIPC_PMU_CTRL 0x600
|
||||
#define CHIPC_PMU_CAP 0x604
|
||||
#define CHIPC_PMU_ST 0x608
|
||||
#define CHIPC_PMU_RES_STATE 0x60c
|
||||
#define CHIPC_PMU_RES_PENDING 0x610
|
||||
#define CHIPC_PMU_TIMER 0x614
|
||||
#define CHIPC_PMU_MIN_RES_MASK 0x618
|
||||
#define CHIPC_PMU_MAX_RES_MASK 0x61c
|
||||
#define CHIPC_PMU_RES_TABLE_SEL 0x620
|
||||
#define CHIPC_PMU_RES_DEP_MASK 0x624
|
||||
#define CHIPC_PMU_RES_UPDN_TIMER 0x628
|
||||
#define CHIPC_PMU_RES_TIMER 0x62C
|
||||
#define CHIPC_PMU_CLKSTRETCH 0x630
|
||||
#define CHIPC_PMU_WATCHDOG 0x634
|
||||
#define CHIPC_PMU_GPIOSEL 0x638 /* pmu rev >= 1 ? */
|
||||
#define CHIPC_PMU_GPIOEN 0x63C /* pmu rev >= 1 ? */
|
||||
#define CHIPC_PMU_RES_REQ_TIMER_SEL 0x640
|
||||
#define CHIPC_PMU_RES_REQ_TIMER 0x644
|
||||
#define CHIPC_PMU_RES_REQ_MASK 0x648
|
||||
#define CHIPC_CHIPCTL_ADDR 0x650
|
||||
#define CHIPC_CHIPCTL_DATA 0x654
|
||||
#define CHIPC_PMU_REG_CONTROL_ADDR 0x658
|
||||
#define CHIPC_PMU_REG_CONTROL_DATA 0x65C
|
||||
#define CHIPC_PMU_PLL_CONTROL_ADDR 0x660
|
||||
#define CHIPC_PMU_PLL_CONTROL_DATA 0x664
|
||||
#define CHIPC_PMU_STRAPOPT 0x668 /* chipc rev >= 28 */
|
||||
#define CHIPC_PMU_XTALFREQ 0x66C /* pmu rev >= 10 */
|
||||
|
||||
#define CHIPC_SPROM_OTP 0x800 /* SPROM/OTP address space */
|
||||
#define CHIPC_SPROM_OTP_SIZE 0x400
|
||||
|
||||
@ -257,7 +230,7 @@
|
||||
#define CHIPC_CAP_PFLASH 0x7 /* Parallel flash */
|
||||
#define CHIPC_CAP_PLL_MASK 0x00038000 /* Type of PLL */
|
||||
#define CHIPC_CAP_PLL_SHIFT 15
|
||||
#define CHIPC_CAP_PWR_CTL 0x00040000 /* Power control */
|
||||
#define CHIPC_CAP_PWR_CTL 0x00040000 /* Power/clock control */
|
||||
#define CHIPC_CAP_OTP_SIZE_MASK 0x00380000 /* OTP Size (0 = none) */
|
||||
#define CHIPC_CAP_OTP_SIZE_SHIFT 19 /* OTP Size shift */
|
||||
#define CHIPC_CAP_OTP_SIZE_BASE 5 /* OTP Size base */
|
||||
@ -305,23 +278,31 @@ enum {
|
||||
#define CHIPC_CST_SPROM_OTP_SEL_R23_SHIFT 6
|
||||
|
||||
/* PLL type */
|
||||
#define CHIPC_PLL_NONE 0x00000000
|
||||
#define CHIPC_PLL_TYPE1 0x00010000 /* 48MHz base, 3 dividers */
|
||||
#define CHIPC_PLL_TYPE2 0x00020000 /* 48MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE3 0x00030000 /* 25MHz, 2 dividers */
|
||||
#define CHIPC_PLL_TYPE4 0x00008000 /* 48MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE5 0x00018000 /* 25MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE6 0x00028000 /* 100/200 or 120/240 only */
|
||||
#define CHIPC_PLL_TYPE7 0x00038000 /* 25MHz, 4 dividers */
|
||||
#define CHIPC_PLL_NONE 0x00
|
||||
#define CHIPC_PLL_TYPE1 0x10 /* 48MHz base, 3 dividers */
|
||||
#define CHIPC_PLL_TYPE2 0x20 /* 48MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE3 0x30 /* 25MHz, 2 dividers */
|
||||
#define CHIPC_PLL_TYPE4 0x08 /* 48MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE5 0x18 /* 25MHz, 4 dividers */
|
||||
#define CHIPC_PLL_TYPE6 0x28 /* 100/200 or 120/240 only */
|
||||
#define CHIPC_PLL_TYPE7 0x38 /* 25MHz, 4 dividers */
|
||||
|
||||
/* ILP clock */
|
||||
#define CHIPC_ILP_CLOCK 32000
|
||||
/* dynamic clock control defines */
|
||||
#define CHIPC_LPOMINFREQ 25000 /* low power oscillator min */
|
||||
#define CHIPC_LPOMAXFREQ 43000 /* low power oscillator max */
|
||||
#define CHIPC_XTALMINFREQ 19800000 /* 20 MHz - 1% */
|
||||
#define CHIPC_XTALMAXFREQ 20200000 /* 20 MHz + 1% */
|
||||
#define CHIPC_PCIMINFREQ 25000000 /* 25 MHz */
|
||||
#define CHIPC_PCIMAXFREQ 34000000 /* 33 MHz + fudge */
|
||||
|
||||
/* ALP clock on pre-PMU chips */
|
||||
#define CHIPC_ALP_CLOCK 20000000
|
||||
#define CHIPC_ILP_DIV_5MHZ 0 /* ILP = 5 MHz */
|
||||
#define CHIPC_ILP_DIV_1MHZ 4 /* ILP = 1 MHz */
|
||||
|
||||
/* HT clock */
|
||||
#define CHIPC_HT_CLOCK 80000000
|
||||
/* Power Control Defines */
|
||||
#define CHIPC_PLL_DELAY 150 /* us pll on delay */
|
||||
#define CHIPC_FREF_DELAY 200 /* us fref change delay */
|
||||
#define CHIPC_MIN_SLOW_CLK 32 /* us Slow clock period */
|
||||
#define CHIPC_XTAL_ON_DELAY 1000 /* us crystal power-on delay */
|
||||
|
||||
/* corecontrol */
|
||||
#define CHIPC_UARTCLKO 0x00000001 /* Drive UART with internal clock */
|
||||
@ -577,27 +558,12 @@ enum {
|
||||
#define CHIPC_SRC_SIZE_SHIFT 1
|
||||
#define CHIPC_SRC_PRESENT 0x00000001
|
||||
|
||||
/* Fields in pmucontrol */
|
||||
#define CHIPC_PCTL_ILP_DIV_MASK 0xffff0000
|
||||
#define CHIPC_PCTL_ILP_DIV_SHIFT 16
|
||||
#define CHIPC_PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */
|
||||
#define CHIPC_PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */
|
||||
#define CHIPC_PCTL_HT_REQ_EN 0x00000100
|
||||
#define CHIPC_PCTL_ALP_REQ_EN 0x00000080
|
||||
#define CHIPC_PCTL_XTALFREQ_MASK 0x0000007c
|
||||
#define CHIPC_PCTL_XTALFREQ_SHIFT 2
|
||||
#define CHIPC_PCTL_ILP_DIV_EN 0x00000002
|
||||
#define CHIPC_PCTL_LPO_SEL 0x00000001
|
||||
|
||||
/* Fields in clkstretch */
|
||||
#define CHIPC_CSTRETCH_HT 0xffff0000
|
||||
#define CHIPC_CSTRETCH_ALP 0x0000ffff
|
||||
|
||||
/* gpiotimerval */
|
||||
#define CHIPC_GPIO_ONTIME_SHIFT 16
|
||||
|
||||
/* clockcontrol_n */
|
||||
#define CHIPC_CN_N1_MASK 0x3f /* n1 control */
|
||||
#define CHIPC_CN_N1_SHIFT 0
|
||||
#define CHIPC_CN_N2_MASK 0x3f00 /* n2 control */
|
||||
#define CHIPC_CN_N2_SHIFT 8
|
||||
#define CHIPC_CN_PLLC_MASK 0xf0000 /* pll control */
|
||||
@ -605,6 +571,7 @@ enum {
|
||||
|
||||
/* clockcontrol_sb/pci/uart */
|
||||
#define CHIPC_M1_MASK 0x3f /* m1 control */
|
||||
#define CHIPC_M1_SHIFT 0
|
||||
#define CHIPC_M2_MASK 0x3f00 /* m2 control */
|
||||
#define CHIPC_M2_SHIFT 8
|
||||
#define CHIPC_M3_MASK 0x3f0000 /* m3 control */
|
||||
@ -788,345 +755,6 @@ enum {
|
||||
#define CHIPC_UART_IER_ETBEI 2 /* enable transmitter holding register empty interrupt */
|
||||
#define CHIPC_UART_IER_ERBFI 1 /* enable data available interrupt */
|
||||
|
||||
/* pmustatus */
|
||||
#define CHIPC_PST_EXTLPOAVAIL 0x0100
|
||||
#define CHIPC_PST_WDRESET 0x0080
|
||||
#define CHIPC_PST_INTPEND 0x0040
|
||||
#define CHIPC_PST_SBCLKST 0x0030
|
||||
#define CHIPC_PST_SBCLKST_ILP 0x0010
|
||||
#define CHIPC_PST_SBCLKST_ALP 0x0020
|
||||
#define CHIPC_PST_SBCLKST_HT 0x0030
|
||||
#define CHIPC_PST_ALPAVAIL 0x0008
|
||||
#define CHIPC_PST_HTAVAIL 0x0004
|
||||
#define CHIPC_PST_RESINIT 0x0003
|
||||
|
||||
/* pmucapabilities */
|
||||
#define CHIPC_PCAP_REV_MASK 0x000000ff
|
||||
#define CHIPC_PCAP_RC_MASK 0x00001f00
|
||||
#define CHIPC_PCAP_RC_SHIFT 8
|
||||
#define CHIPC_PCAP_TC_MASK 0x0001e000
|
||||
#define CHIPC_PCAP_TC_SHIFT 13
|
||||
#define CHIPC_PCAP_PC_MASK 0x001e0000
|
||||
#define CHIPC_PCAP_PC_SHIFT 17
|
||||
#define CHIPC_PCAP_VC_MASK 0x01e00000
|
||||
#define CHIPC_PCAP_VC_SHIFT 21
|
||||
#define CHIPC_PCAP_CC_MASK 0x1e000000
|
||||
#define CHIPC_PCAP_CC_SHIFT 25
|
||||
#define CHIPC_PCAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */
|
||||
#define CHIPC_PCAP5_PC_SHIFT 17
|
||||
#define CHIPC_PCAP5_VC_MASK 0x07c00000
|
||||
#define CHIPC_PCAP5_VC_SHIFT 22
|
||||
#define CHIPC_PCAP5_CC_MASK 0xf8000000
|
||||
#define CHIPC_PCAP5_CC_SHIFT 27
|
||||
|
||||
/* PMU Resource Request Timer registers */
|
||||
/* This is based on PmuRev0 */
|
||||
#define CHIPC_PRRT_TIME_MASK 0x03ff
|
||||
#define CHIPC_PRRT_INTEN 0x0400
|
||||
#define CHIPC_PRRT_REQ_ACTIVE 0x0800
|
||||
#define CHIPC_PRRT_ALP_REQ 0x1000
|
||||
#define CHIPC_PRRT_HT_REQ 0x2000
|
||||
|
||||
/* PMU resource bit position */
|
||||
#define CHIPC_PMURES_BIT(bit) (1 << (bit))
|
||||
|
||||
/* PMU resource number limit */
|
||||
#define CHIPC_PMURES_MAX_RESNUM 30
|
||||
|
||||
/* PMU chip control0 register */
|
||||
#define CHIPC_PMU_CHIPCTL0 0
|
||||
|
||||
/* PMU chip control1 register */
|
||||
#define CHIPC_PMU_CHIPCTL1 1
|
||||
#define CHIPC_PMU_CC1_RXC_DLL_BYPASS 0x00010000
|
||||
|
||||
#define CHIPC_PMU_CC1_IF_TYPE_MASK 0x00000030
|
||||
#define CHIPC_PMU_CC1_IF_TYPE_RMII 0x00000000
|
||||
#define CHIPC_PMU_CC1_IF_TYPE_MII 0x00000010
|
||||
#define CHIPC_PMU_CC1_IF_TYPE_RGMII 0x00000020
|
||||
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_MASK 0x000000c0
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_EPHY 0x00000000
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_EPHYMII 0x00000040
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_EPHYRMII 0x00000080
|
||||
#define CHIPC_PMU_CC1_SW_TYPE_RGMII 0x000000c0
|
||||
|
||||
/* PMU corerev and chip specific PLL controls.
|
||||
* PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
|
||||
* to differentiate different PLLs controlled by the same PMU rev.
|
||||
*/
|
||||
/* pllcontrol registers */
|
||||
/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */
|
||||
#define CHIPC_PMU0_PLL0_PLLCTL0 0
|
||||
#define CHIPC_PMU0_PLL0_PC0_PDIV_MASK 1
|
||||
#define CHIPC_PMU0_PLL0_PC0_PDIV_FREQ 25000
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_SHIFT 3
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_BASE 8
|
||||
|
||||
/* PC0_DIV_ARM for PLLOUT_ARM */
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_110MHZ 0
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_88MHZ 2
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6
|
||||
#define CHIPC_PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7
|
||||
|
||||
/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */
|
||||
#define CHIPC_PMU0_PLL0_PLLCTL1 1
|
||||
#define CHIPC_PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000
|
||||
#define CHIPC_PMU0_PLL0_PC1_WILD_INT_SHIFT 28
|
||||
#define CHIPC_PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00
|
||||
#define CHIPC_PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8
|
||||
#define CHIPC_PMU0_PLL0_PC1_STOP_MOD 0x00000040
|
||||
|
||||
/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */
|
||||
#define CHIPC_PMU0_PLL0_PLLCTL2 2
|
||||
#define CHIPC_PMU0_PLL0_PC2_WILD_INT_MASK 0xf
|
||||
#define CHIPC_PMU0_PLL0_PC2_WILD_INT_SHIFT 4
|
||||
|
||||
/* pllcontrol registers */
|
||||
/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL0 0
|
||||
#define CHIPC_PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000
|
||||
#define CHIPC_PMU1_PLL0_PC0_P1DIV_SHIFT 20
|
||||
#define CHIPC_PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000
|
||||
#define CHIPC_PMU1_PLL0_PC0_P2DIV_SHIFT 24
|
||||
|
||||
/* m<x>div */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL1 1
|
||||
#define CHIPC_PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU1_PLL0_PC1_M1DIV_SHIFT 0
|
||||
#define CHIPC_PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00
|
||||
#define CHIPC_PMU1_PLL0_PC1_M2DIV_SHIFT 8
|
||||
#define CHIPC_PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000
|
||||
#define CHIPC_PMU1_PLL0_PC1_M3DIV_SHIFT 16
|
||||
#define CHIPC_PMU1_PLL0_PC1_M4DIV_MASK 0xff000000
|
||||
#define CHIPC_PMU1_PLL0_PC1_M4DIV_SHIFT 24
|
||||
|
||||
#define CHIPC_DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8
|
||||
#define CHIPC_DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
|
||||
#define CHIPC_DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
|
||||
|
||||
/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL2 2
|
||||
#define CHIPC_PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU1_PLL0_PC2_M5DIV_SHIFT 0
|
||||
#define CHIPC_PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00
|
||||
#define CHIPC_PMU1_PLL0_PC2_M6DIV_SHIFT 8
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_MODE_MASH 1
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_MODE_MFB 2 /* recommended for 4319 */
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000
|
||||
#define CHIPC_PMU1_PLL0_PC2_NDIV_INT_SHIFT 20
|
||||
|
||||
/* ndiv_frac */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL3 3
|
||||
#define CHIPC_PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff
|
||||
#define CHIPC_PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0
|
||||
|
||||
/* pll_ctrl */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL4 4
|
||||
|
||||
/* pll_ctrl, vco_rng, clkdrive_ch<x> */
|
||||
#define CHIPC_PMU1_PLL0_PLLCTL5 5
|
||||
#define CHIPC_PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00
|
||||
#define CHIPC_PMU1_PLL0_PC5_CLK_DRV_SHIFT 8
|
||||
|
||||
/* PMU rev 2 control words */
|
||||
#define CHIPC_PMU2_PHY_PLL_PLLCTL 4
|
||||
#define CHIPC_PMU2_SI_PLL_PLLCTL 10
|
||||
|
||||
/* PMU rev 2 */
|
||||
/* pllcontrol registers */
|
||||
/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL0 0
|
||||
#define CHIPC_PMU2_PLL_PC0_P1DIV_MASK 0x00f00000
|
||||
#define CHIPC_PMU2_PLL_PC0_P1DIV_SHIFT 20
|
||||
#define CHIPC_PMU2_PLL_PC0_P2DIV_MASK 0x0f000000
|
||||
#define CHIPC_PMU2_PLL_PC0_P2DIV_SHIFT 24
|
||||
|
||||
/* m<x>div */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL1 1
|
||||
#define CHIPC_PMU2_PLL_PC1_M1DIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU2_PLL_PC1_M1DIV_SHIFT 0
|
||||
#define CHIPC_PMU2_PLL_PC1_M2DIV_MASK 0x0000ff00
|
||||
#define CHIPC_PMU2_PLL_PC1_M2DIV_SHIFT 8
|
||||
#define CHIPC_PMU2_PLL_PC1_M3DIV_MASK 0x00ff0000
|
||||
#define CHIPC_PMU2_PLL_PC1_M3DIV_SHIFT 16
|
||||
#define CHIPC_PMU2_PLL_PC1_M4DIV_MASK 0xff000000
|
||||
#define CHIPC_PMU2_PLL_PC1_M4DIV_SHIFT 24
|
||||
|
||||
/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL2 2
|
||||
#define CHIPC_PMU2_PLL_PC2_M5DIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU2_PLL_PC2_M5DIV_SHIFT 0
|
||||
#define CHIPC_PMU2_PLL_PC2_M6DIV_MASK 0x0000ff00
|
||||
#define CHIPC_PMU2_PLL_PC2_M6DIV_SHIFT 8
|
||||
#define CHIPC_PMU2_PLL_PC2_NDIV_MODE_MASK 0x000e0000
|
||||
#define CHIPC_PMU2_PLL_PC2_NDIV_MODE_SHIFT 17
|
||||
#define CHIPC_PMU2_PLL_PC2_NDIV_INT_MASK 0x1ff00000
|
||||
#define CHIPC_PMU2_PLL_PC2_NDIV_INT_SHIFT 20
|
||||
|
||||
/* ndiv_frac */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL3 3
|
||||
#define CHIPC_PMU2_PLL_PC3_NDIV_FRAC_MASK 0x00ffffff
|
||||
#define CHIPC_PMU2_PLL_PC3_NDIV_FRAC_SHIFT 0
|
||||
|
||||
/* pll_ctrl */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL4 4
|
||||
|
||||
/* pll_ctrl, vco_rng, clkdrive_ch<x> */
|
||||
#define CHIPC_PMU2_PLL_PLLCTL5 5
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH1_MASK 0x00000f00
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT 8
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH2_MASK 0x0000f000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT 12
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH3_MASK 0x000f0000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT 16
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH4_MASK 0x00f00000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT 20
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH5_MASK 0x0f000000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT 24
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH6_MASK 0xf0000000
|
||||
#define CHIPC_PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT 28
|
||||
|
||||
/* PMU rev 5 (& 6) */
|
||||
#define CHIPC_PMU5_PLL_P1P2_OFF 0
|
||||
#define CHIPC_PMU5_PLL_P1_MASK 0x0f000000
|
||||
#define CHIPC_PMU5_PLL_P1_SHIFT 24
|
||||
#define CHIPC_PMU5_PLL_P2_MASK 0x00f00000
|
||||
#define CHIPC_PMU5_PLL_P2_SHIFT 20
|
||||
#define CHIPC_PMU5_PLL_M14_OFF 1
|
||||
#define CHIPC_PMU5_PLL_MDIV_MASK 0x000000ff
|
||||
#define CHIPC_PMU5_PLL_MDIV_WIDTH 8
|
||||
#define CHIPC_PMU5_PLL_NM5_OFF 2
|
||||
#define CHIPC_PMU5_PLL_NDIV_MASK 0xfff00000
|
||||
#define CHIPC_PMU5_PLL_NDIV_SHIFT 20
|
||||
#define CHIPC_PMU5_PLL_NDIV_MODE_MASK 0x000e0000
|
||||
#define CHIPC_PMU5_PLL_NDIV_MODE_SHIFT 17
|
||||
#define CHIPC_PMU5_PLL_FMAB_OFF 3
|
||||
#define CHIPC_PMU5_PLL_MRAT_MASK 0xf0000000
|
||||
#define CHIPC_PMU5_PLL_MRAT_SHIFT 28
|
||||
#define CHIPC_PMU5_PLL_ABRAT_MASK 0x08000000
|
||||
#define CHIPC_PMU5_PLL_ABRAT_SHIFT 27
|
||||
#define CHIPC_PMU5_PLL_FDIV_MASK 0x07ffffff
|
||||
#define CHIPC_PMU5_PLL_PLLCTL_OFF 4
|
||||
#define CHIPC_PMU5_PLL_PCHI_OFF 5
|
||||
#define CHIPC_PMU5_PLL_PCHI_MASK 0x0000003f
|
||||
|
||||
/* pmu XtalFreqRatio */
|
||||
#define CHIPC_PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
|
||||
#define CHIPC_PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000
|
||||
#define CHIPC_PMU_XTALFREQ_REG_MEASURE_SHIFT 31
|
||||
|
||||
/* Divider allocation in 4716/47162/5356/5357 */
|
||||
#define CHIPC_PMU5_MAINPLL_CPU 1
|
||||
#define CHIPC_PMU5_MAINPLL_MEM 2
|
||||
#define CHIPC_PMU5_MAINPLL_SI 3
|
||||
|
||||
#define CHIPC_PMU7_PLL_PLLCTL7 7
|
||||
#define CHIPC_PMU7_PLL_PLLCTL8 8
|
||||
#define CHIPC_PMU7_PLL_PLLCTL11 11
|
||||
|
||||
/* PLL usage in 4716/47162 */
|
||||
#define CHIPC_PMU4716_MAINPLL_PLL0 12
|
||||
|
||||
/* PLL usage in 5356/5357 */
|
||||
#define CHIPC_PMU5356_MAINPLL_PLL0 0
|
||||
#define CHIPC_PMU5357_MAINPLL_PLL0 0
|
||||
|
||||
/* 4716/47162 resources */
|
||||
#define CHIPC_RES4716_PROC_PLL_ON 0x00000040
|
||||
#define CHIPC_RES4716_PROC_HT_AVAIL 0x00000080
|
||||
|
||||
/* 4716/4717/4718 Chip specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared with pflash */
|
||||
|
||||
/* 5354 resources */
|
||||
#define CHIPC_RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */
|
||||
#define CHIPC_RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */
|
||||
#define CHIPC_RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */
|
||||
#define CHIPC_RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */
|
||||
#define CHIPC_RES5354_ILP_REQUEST 4 /* 0x00010 */
|
||||
#define CHIPC_RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */
|
||||
#define CHIPC_RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */
|
||||
#define CHIPC_RES5354_ROM_SWITCH 7 /* 0x00080 */
|
||||
#define CHIPC_RES5354_PA_REF_LDO 8 /* 0x00100 */
|
||||
#define CHIPC_RES5354_RADIO_LDO 9 /* 0x00200 */
|
||||
#define CHIPC_RES5354_AFE_LDO 10 /* 0x00400 */
|
||||
#define CHIPC_RES5354_PLL_LDO 11 /* 0x00800 */
|
||||
#define CHIPC_RES5354_BG_FILTBYP 12 /* 0x01000 */
|
||||
#define CHIPC_RES5354_TX_FILTBYP 13 /* 0x02000 */
|
||||
#define CHIPC_RES5354_RX_FILTBYP 14 /* 0x04000 */
|
||||
#define CHIPC_RES5354_XTAL_PU 15 /* 0x08000 */
|
||||
#define CHIPC_RES5354_XTAL_EN 16 /* 0x10000 */
|
||||
#define CHIPC_RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */
|
||||
#define CHIPC_RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */
|
||||
#define CHIPC_RES5354_BB_PLL_PU 19 /* 0x80000 */
|
||||
|
||||
/* 5357 Chip specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */
|
||||
#define CHIPC_CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */
|
||||
|
||||
/* 4328 resources */
|
||||
#define CHIPC_RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */
|
||||
#define CHIPC_RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */
|
||||
#define CHIPC_RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */
|
||||
#define CHIPC_RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */
|
||||
#define CHIPC_RES4328_ILP_REQUEST 4 /* 0x00010 */
|
||||
#define CHIPC_RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */
|
||||
#define CHIPC_RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */
|
||||
#define CHIPC_RES4328_ROM_SWITCH 7 /* 0x00080 */
|
||||
#define CHIPC_RES4328_PA_REF_LDO 8 /* 0x00100 */
|
||||
#define CHIPC_RES4328_RADIO_LDO 9 /* 0x00200 */
|
||||
#define CHIPC_RES4328_AFE_LDO 10 /* 0x00400 */
|
||||
#define CHIPC_RES4328_PLL_LDO 11 /* 0x00800 */
|
||||
#define CHIPC_RES4328_BG_FILTBYP 12 /* 0x01000 */
|
||||
#define CHIPC_RES4328_TX_FILTBYP 13 /* 0x02000 */
|
||||
#define CHIPC_RES4328_RX_FILTBYP 14 /* 0x04000 */
|
||||
#define CHIPC_RES4328_XTAL_PU 15 /* 0x08000 */
|
||||
#define CHIPC_RES4328_XTAL_EN 16 /* 0x10000 */
|
||||
#define CHIPC_RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */
|
||||
#define CHIPC_RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */
|
||||
#define CHIPC_RES4328_BB_PLL_PU 19 /* 0x80000 */
|
||||
|
||||
/* 4325 A0/A1 resources */
|
||||
#define CHIPC_RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */
|
||||
#define CHIPC_RES4325_CBUCK_BURST 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4325_CBUCK_PWM 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4325_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4325_ABUCK_BURST 7 /* 0x00000080 */
|
||||
#define CHIPC_RES4325_ABUCK_PWM 8 /* 0x00000100 */
|
||||
#define CHIPC_RES4325_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4325_OTP_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4325_LNLDO3_PU 11 /* 0x00000800 */
|
||||
#define CHIPC_RES4325_LNLDO4_PU 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4325_XTAL_PU 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4325_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define CHIPC_RES4325_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define CHIPC_RES4325_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define CHIPC_RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define CHIPC_RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define CHIPC_RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define CHIPC_RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define CHIPC_RES4325_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4325 B0/C0 resources */
|
||||
#define CHIPC_RES4325B0_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4325B0_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4325B0_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4325B0_CLDO_PU 4 /* 0x00000010 */
|
||||
|
||||
/* 4325 C1 resources */
|
||||
#define CHIPC_RES4325C1_LNLDO2_PU 12 /* 0x00001000 */
|
||||
|
||||
/* 4325 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4325_SPROM_OTP_SEL_MASK CHIPC_CST_SPROM_OTP_SEL_R22_MASK
|
||||
#define CHIPC_CST4325_SPROM_OTP_SEL_SHIFT CHIPC_CST_SPROM_OTP_SEL_R22_SHIFT
|
||||
@ -1139,29 +767,6 @@ enum {
|
||||
#define CHIPC_CST4325_PMUTOP_2B_MASK 0x00000200 /* 1 for 2b, 0 for to 2a */
|
||||
#define CHIPC_CST4325_PMUTOP_2B_SHIFT 9
|
||||
|
||||
#define CHIPC_RES4329_RESERVED0 0 /* 0x00000001 */
|
||||
#define CHIPC_RES4329_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4329_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4329_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4329_CLDO_PU 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4329_PALDO_PU 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4329_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4329_RESERVED7 7 /* 0x00000080 */
|
||||
#define CHIPC_RES4329_RESERVED8 8 /* 0x00000100 */
|
||||
#define CHIPC_RES4329_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4329_OTP_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4329_RESERVED11 11 /* 0x00000800 */
|
||||
#define CHIPC_RES4329_LNLDO2_PU 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4329_XTAL_PU 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4329_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define CHIPC_RES4329_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define CHIPC_RES4329_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define CHIPC_RES4329_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define CHIPC_RES4329_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define CHIPC_RES4329_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define CHIPC_RES4329_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define CHIPC_RES4329_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4329 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4329_SPROM_OTP_SEL_MASK CHIPC_CST_SPROM_OTP_SEL_R22_MASK
|
||||
#define CHIPC_CST4329_SPROM_OTP_SEL_SHIFT CHIPC_CST_SPROM_OTP_SEL_R22_SHIFT
|
||||
@ -1172,33 +777,6 @@ enum {
|
||||
#define CHIPC_CST4312_SPROM_OTP_SEL_MASK CHIPC_CST_SPROM_OTP_SEL_R22_MASK
|
||||
#define CHIPC_CST4312_SPROM_OTP_SEL_SHIFT CHIPC_CST_SPROM_OTP_SEL_R22_SHIFT
|
||||
|
||||
/* 4312 resources (all PMU chips with little memory constraint) */
|
||||
#define CHIPC_RES4312_SWITCHER_BURST 0 /* 0x00000001 */
|
||||
#define CHIPC_RES4312_SWITCHER_PWM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4312_PA_REF_LDO 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4312_CORE_LDO_BURST 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4312_CORE_LDO_PWM 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4312_RADIO_LDO 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4312_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4312_BG_FILTBYP 7 /* 0x00000080 */
|
||||
#define CHIPC_RES4312_TX_FILTBYP 8 /* 0x00000100 */
|
||||
#define CHIPC_RES4312_RX_FILTBYP 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4312_XTAL_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4312_ALP_AVAIL 11 /* 0x00000800 */
|
||||
#define CHIPC_RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4312_HT_AVAIL 14 /* 0x00004000 */
|
||||
|
||||
/* 4322 resources */
|
||||
#define CHIPC_RES4322_RF_LDO 0
|
||||
#define CHIPC_RES4322_ILP_REQUEST 1
|
||||
#define CHIPC_RES4322_XTAL_PU 2
|
||||
#define CHIPC_RES4322_ALP_AVAIL 3
|
||||
#define CHIPC_RES4322_SI_PLL_ON 4
|
||||
#define CHIPC_RES4322_HT_SI_AVAIL 5
|
||||
#define CHIPC_RES4322_PHY_PLL_ON 6
|
||||
#define CHIPC_RES4322_HT_PHY_AVAIL 7
|
||||
#define CHIPC_RES4322_OTP_PU 8
|
||||
|
||||
/* 4322 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4322_XTAL_FREQ_20_40MHZ 0x00000020
|
||||
@ -1227,26 +805,6 @@ enum {
|
||||
#define CHIPC_CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000
|
||||
#define CHIPC_CST4322_PCI_CARDBUS_MODE 0x00040000
|
||||
|
||||
/* 43224 chip-specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL43224_GPIO_TOGGLE 0x8000
|
||||
#define CHIPC_CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */
|
||||
#define CHIPC_CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */
|
||||
|
||||
/* 43236 resources */
|
||||
#define CHIPC_RES43236_REGULATOR 0
|
||||
#define CHIPC_RES43236_ILP_REQUEST 1
|
||||
#define CHIPC_RES43236_XTAL_PU 2
|
||||
#define CHIPC_RES43236_ALP_AVAIL 3
|
||||
#define CHIPC_RES43236_SI_PLL_ON 4
|
||||
#define CHIPC_RES43236_HT_SI_AVAIL 5
|
||||
|
||||
/* 43236 chip-specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL43236_BT_COEXIST (1<<0) /* 0 disable */
|
||||
#define CHIPC_CCTRL43236_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
|
||||
#define CHIPC_CCTRL43236_EXT_LNA (1<<2) /* 0 disable */
|
||||
#define CHIPC_CCTRL43236_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */
|
||||
#define CHIPC_CCTRL43236_GSIO (1<<4) /* 0 disable */
|
||||
|
||||
/* 43236 Chip specific ChipStatus register bits */
|
||||
#define CHIPC_CST43236_SFLASH_MASK 0x00000040
|
||||
#define CHIPC_CST43236_OTP_SEL_MASK 0x00000080
|
||||
@ -1260,15 +818,17 @@ enum {
|
||||
#define CHIPC_CST43236_BOOT_FROM_FLASH 2 /* boot from FLASH */
|
||||
#define CHIPC_CST43236_BOOT_FROM_INVALID 3
|
||||
|
||||
/* 4331 resources */
|
||||
#define CHIPC_RES4331_REGULATOR 0
|
||||
#define CHIPC_RES4331_ILP_REQUEST 1
|
||||
#define CHIPC_RES4331_XTAL_PU 2
|
||||
#define CHIPC_RES4331_ALP_AVAIL 3
|
||||
#define CHIPC_RES4331_SI_PLL_ON 4
|
||||
#define CHIPC_RES4331_HT_SI_AVAIL 5
|
||||
/* 43237 Chip specific ChipStatus register bits */
|
||||
#define CHIPC_CST43237_BP_CLK 0x00000200 /* 96/80Mbps */
|
||||
|
||||
/* 4331 chip-specific ChipControl register bits */
|
||||
/* 4331 Chip specific ChipStatus register bits */
|
||||
#define CHIPC_CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */
|
||||
#define CHIPC_CST4331_SPROM_PRESENT 0x00000002
|
||||
#define CHIPC_CST4331_OTP_PRESENT 0x00000004
|
||||
#define CHIPC_CST4331_LDO_RF 0x00000008
|
||||
#define CHIPC_CST4331_LDO_PAR 0x00000010
|
||||
|
||||
/* 4331 chip-specific CHIPCTRL register bits */
|
||||
#define CHIPC_CCTRL4331_BT_COEXIST (1<<0) /* 0 disable */
|
||||
#define CHIPC_CCTRL4331_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
|
||||
#define CHIPC_CCTRL4331_EXT_LNA (1<<2) /* 0 disable */
|
||||
@ -1285,33 +845,6 @@ enum {
|
||||
#define CHIPC_CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */
|
||||
#define CHIPC_CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */
|
||||
|
||||
/* 4331 Chip specific ChipStatus register bits */
|
||||
#define CHIPC_CST4331_XTAL_FREQ 0x00000001 /* crystal frequency 20/40Mhz */
|
||||
#define CHIPC_CST4331_SPROM_PRESENT 0x00000002
|
||||
#define CHIPC_CST4331_OTP_PRESENT 0x00000004
|
||||
#define CHIPC_CST4331_LDO_RF 0x00000008
|
||||
#define CHIPC_CST4331_LDO_PAR 0x00000010
|
||||
|
||||
/* 4315 resources */
|
||||
#define CHIPC_RES4315_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4315_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4315_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4315_CLDO_PU 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4315_PALDO_PU 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4315_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4315_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4315_OTP_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4315_LNLDO2_PU 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4315_XTAL_PU 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4315_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define CHIPC_RES4315_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define CHIPC_RES4315_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define CHIPC_RES4315_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define CHIPC_RES4315_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define CHIPC_RES4315_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define CHIPC_RES4315_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define CHIPC_RES4315_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4315 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4315_SPROM_OTP_SEL_MASK CHIPC_CST_SPROM_OTP_SEL_R22_MASK
|
||||
#define CHIPC_CST4315_SPROM_OTP_SEL_SHIFT CHIPC_CST_SPROM_OTP_SEL_R22_SHIFT
|
||||
@ -1324,26 +857,6 @@ enum {
|
||||
#define CHIPC_CST4315_CBUCK_MODE_BURST 0x00000400
|
||||
#define CHIPC_CST4315_CBUCK_MODE_LPBURST 0x00000c00
|
||||
|
||||
/* 4319 resources */
|
||||
#define CHIPC_RES4319_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define CHIPC_RES4319_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define CHIPC_RES4319_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define CHIPC_RES4319_CLDO_PU 4 /* 0x00000010 */
|
||||
#define CHIPC_RES4319_PALDO_PU 5 /* 0x00000020 */
|
||||
#define CHIPC_RES4319_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define CHIPC_RES4319_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define CHIPC_RES4319_OTP_PU 10 /* 0x00000400 */
|
||||
#define CHIPC_RES4319_LNLDO2_PU 12 /* 0x00001000 */
|
||||
#define CHIPC_RES4319_XTAL_PU 13 /* 0x00002000 */
|
||||
#define CHIPC_RES4319_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define CHIPC_RES4319_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define CHIPC_RES4319_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define CHIPC_RES4319_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define CHIPC_RES4319_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define CHIPC_RES4319_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define CHIPC_RES4319_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define CHIPC_RES4319_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4319 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4319_SPI_CPULESSUSB 0x00000001
|
||||
#define CHIPC_CST4319_SPI_CLK_POL 0x00000002
|
||||
@ -1364,42 +877,6 @@ enum {
|
||||
#define CHIPC_CST4319_RCAL_VALUE_MASK 0x3e000000
|
||||
#define CHIPC_CST4319_RCAL_VALUE_SHIFT 25
|
||||
|
||||
#define CHIPC_PMU1_PLL0_CHIPCTL0 0
|
||||
#define CHIPC_PMU1_PLL0_CHIPCTL1 1
|
||||
#define CHIPC_PMU1_PLL0_CHIPCTL2 2
|
||||
#define CHIPC_CCTL_4319USB_XTAL_SEL_MASK 0x00180000
|
||||
#define CHIPC_CCTL_4319USB_XTAL_SEL_SHIFT 19
|
||||
#define CHIPC_CCTL_4319USB_48MHZ_PLL_SEL 1
|
||||
#define CHIPC_CCTL_4319USB_24MHZ_PLL_SEL 2
|
||||
|
||||
/* PMU resources for 4336 */
|
||||
#define CHIPC_RES4336_CBUCK_LPOM 0
|
||||
#define CHIPC_RES4336_CBUCK_BURST 1
|
||||
#define CHIPC_RES4336_CBUCK_LP_PWM 2
|
||||
#define CHIPC_RES4336_CBUCK_PWM 3
|
||||
#define CHIPC_RES4336_CLDO_PU 4
|
||||
#define CHIPC_RES4336_DIS_INT_RESET_PD 5
|
||||
#define CHIPC_RES4336_ILP_REQUEST 6
|
||||
#define CHIPC_RES4336_LNLDO_PU 7
|
||||
#define CHIPC_RES4336_LDO3P3_PU 8
|
||||
#define CHIPC_RES4336_OTP_PU 9
|
||||
#define CHIPC_RES4336_XTAL_PU 10
|
||||
#define CHIPC_RES4336_ALP_AVAIL 11
|
||||
#define CHIPC_RES4336_RADIO_PU 12
|
||||
#define CHIPC_RES4336_BG_PU 13
|
||||
#define CHIPC_RES4336_VREG1p4_PU_PU 14
|
||||
#define CHIPC_RES4336_AFE_PWRSW_PU 15
|
||||
#define CHIPC_RES4336_RX_PWRSW_PU 16
|
||||
#define CHIPC_RES4336_TX_PWRSW_PU 17
|
||||
#define CHIPC_RES4336_BB_PWRSW_PU 18
|
||||
#define CHIPC_RES4336_SYNTH_PWRSW_PU 19
|
||||
#define CHIPC_RES4336_MISC_PWRSW_PU 20
|
||||
#define CHIPC_RES4336_LOGEN_PWRSW_PU 21
|
||||
#define CHIPC_RES4336_BBPLL_PWRSW_PU 22
|
||||
#define CHIPC_RES4336_MACPHY_CLKAVAIL 23
|
||||
#define CHIPC_RES4336_HT_AVAIL 24
|
||||
#define CHIPC_RES4336_RSVD 25
|
||||
|
||||
/* 4336 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4336_SPI_MODE_MASK 0x00000001
|
||||
#define CHIPC_CST4336_SPROM_PRESENT 0x00000002
|
||||
@ -1416,36 +893,6 @@ enum {
|
||||
#define CHIPC_CST4336_CBUCK_MODE_MASK 0x00000600
|
||||
#define CHIPC_CST4336_CBUCK_MODE_SHIFT 9
|
||||
|
||||
/* 4330 resources */
|
||||
#define CHIPC_RES4330_CBUCK_LPOM 0
|
||||
#define CHIPC_RES4330_CBUCK_BURST 1
|
||||
#define CHIPC_RES4330_CBUCK_LP_PWM 2
|
||||
#define CHIPC_RES4330_CBUCK_PWM 3
|
||||
#define CHIPC_RES4330_CLDO_PU 4
|
||||
#define CHIPC_RES4330_DIS_INT_RESET_PD 5
|
||||
#define CHIPC_RES4330_ILP_REQUEST 6
|
||||
#define CHIPC_RES4330_LNLDO_PU 7
|
||||
#define CHIPC_RES4330_LDO3P3_PU 8
|
||||
#define CHIPC_RES4330_OTP_PU 9
|
||||
#define CHIPC_RES4330_XTAL_PU 10
|
||||
#define CHIPC_RES4330_ALP_AVAIL 11
|
||||
#define CHIPC_RES4330_RADIO_PU 12
|
||||
#define CHIPC_RES4330_BG_PU 13
|
||||
#define CHIPC_RES4330_VREG1p4_PU_PU 14
|
||||
#define CHIPC_RES4330_AFE_PWRSW_PU 15
|
||||
#define CHIPC_RES4330_RX_PWRSW_PU 16
|
||||
#define CHIPC_RES4330_TX_PWRSW_PU 17
|
||||
#define CHIPC_RES4330_BB_PWRSW_PU 18
|
||||
#define CHIPC_RES4330_SYNTH_PWRSW_PU 19
|
||||
#define CHIPC_RES4330_MISC_PWRSW_PU 20
|
||||
#define CHIPC_RES4330_LOGEN_PWRSW_PU 21
|
||||
#define CHIPC_RES4330_BBPLL_PWRSW_PU 22
|
||||
#define CHIPC_RES4330_MACPHY_CLKAVAIL 23
|
||||
#define CHIPC_RES4330_HT_AVAIL 24
|
||||
#define CHIPC_RES4330_5gRX_PWRSW_PU 25
|
||||
#define CHIPC_RES4330_5gTX_PWRSW_PU 26
|
||||
#define CHIPC_RES4330_5g_LOGEN_PWRSW_PU 27
|
||||
|
||||
/* 4330 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /* SDIO || gSPI */
|
||||
#define CHIPC_CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /* USB || USBDA */
|
||||
@ -1468,41 +915,12 @@ enum {
|
||||
#define CHIPC_SOCDEVRAM_4330_BP_ADDR 0x1E000000
|
||||
#define CHIPC_SOCDEVRAM_4330_ARM_ADDR 0x00800000
|
||||
|
||||
/* 4313 resources */
|
||||
#define CHIPC_RES4313_BB_PU_RSRC 0
|
||||
#define CHIPC_RES4313_ILP_REQ_RSRC 1
|
||||
#define CHIPC_RES4313_XTAL_PU_RSRC 2
|
||||
#define CHIPC_RES4313_ALP_AVAIL_RSRC 3
|
||||
#define CHIPC_RES4313_RADIO_PU_RSRC 4
|
||||
#define CHIPC_RES4313_BG_PU_RSRC 5
|
||||
#define CHIPC_RES4313_VREG1P4_PU_RSRC 6
|
||||
#define CHIPC_RES4313_AFE_PWRSW_RSRC 7
|
||||
#define CHIPC_RES4313_RX_PWRSW_RSRC 8
|
||||
#define CHIPC_RES4313_TX_PWRSW_RSRC 9
|
||||
#define CHIPC_RES4313_BB_PWRSW_RSRC 10
|
||||
#define CHIPC_RES4313_SYNTH_PWRSW_RSRC 11
|
||||
#define CHIPC_RES4313_MISC_PWRSW_RSRC 12
|
||||
#define CHIPC_RES4313_BB_PLL_PWRSW_RSRC 13
|
||||
#define CHIPC_RES4313_HT_AVAIL_RSRC 14
|
||||
#define CHIPC_RES4313_MACPHY_CLK_AVAIL_RSRC 15
|
||||
|
||||
/* 4313 chip-specific ChipStatus register bits */
|
||||
#define CHIPC_CST4313_SPROM_PRESENT 1
|
||||
#define CHIPC_CST4313_OTP_PRESENT 2
|
||||
#define CHIPC_CST4313_SPROM_OTP_SEL_MASK 0x00000002
|
||||
#define CHIPC_CST4313_SPROM_OTP_SEL_SHIFT 0
|
||||
|
||||
/* 4313 Chip specific ChipControl register bits */
|
||||
#define CHIPC_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
|
||||
|
||||
/* 43228 resources */
|
||||
#define CHIPC_RES43228_NOT_USED 0
|
||||
#define CHIPC_RES43228_ILP_REQUEST 1
|
||||
#define CHIPC_RES43228_XTAL_PU 2
|
||||
#define CHIPC_RES43228_ALP_AVAIL 3
|
||||
#define CHIPC_RES43228_PLL_EN 4
|
||||
#define CHIPC_RES43228_HT_PHY_AVAIL 5
|
||||
|
||||
/* 43228 chipstatus reg bits */
|
||||
#define CHIPC_CST43228_ILP_DIV_EN 0x1
|
||||
#define CHIPC_CST43228_OTP_PRESENT 0x2
|
||||
@ -1512,15 +930,6 @@ enum {
|
||||
#define CHIPC_CST43228_SDIO_OTP_PRESENT 0x10
|
||||
#define CHIPC_CST43228_SDIO_RESET 0x20
|
||||
|
||||
/*
|
||||
* Maximum delay for the PMU state transition in us.
|
||||
* This is an upper bound intended for spinwaits etc.
|
||||
*/
|
||||
#define CHIPC_PMU_MAX_TRANSITION_DLY 15000
|
||||
|
||||
/* PMU resource up transition time in ILP cycles */
|
||||
#define CHIPC_PMURES_UP_TRANSITION 2
|
||||
|
||||
/*
|
||||
* Register eci_inputlo bitfield values.
|
||||
* - BT packet type information bits [7:0]
|
||||
|
@ -39,71 +39,15 @@
|
||||
|
||||
#include "chipc.h"
|
||||
|
||||
DECLARE_CLASS(bhnd_chipc);
|
||||
DECLARE_CLASS(bhnd_chipc_driver);
|
||||
extern devclass_t bhnd_chipc_devclass;
|
||||
|
||||
struct chipc_region;
|
||||
|
||||
/**
|
||||
* Supported ChipCommon flash types.
|
||||
*/
|
||||
typedef enum {
|
||||
CHIPC_FLASH_NONE = 0, /**< No flash, or a type unrecognized
|
||||
by the ChipCommon driver */
|
||||
CHIPC_PFLASH_CFI = 1, /**< CFI-compatible parallel flash */
|
||||
CHIPC_SFLASH_ST = 2, /**< ST serial flash */
|
||||
CHIPC_SFLASH_AT = 3, /**< Atmel serial flash */
|
||||
CHIPC_QSFLASH_ST = 4, /**< ST quad-SPI flash */
|
||||
CHIPC_QSFLASH_AT = 5, /**< Atmel quad-SPI flash */
|
||||
CHIPC_NFLASH = 6, /**< NAND flash */
|
||||
CHIPC_NFLASH_4706 = 7 /**< BCM4706 NAND flash */
|
||||
} chipc_flash;
|
||||
|
||||
const char *chipc_flash_name(chipc_flash type);
|
||||
const char *chipc_flash_bus_name(chipc_flash type);
|
||||
const char *chipc_sflash_device_name(chipc_flash type);
|
||||
|
||||
/**
|
||||
* ChipCommon capability flags;
|
||||
*/
|
||||
struct chipc_caps {
|
||||
uint8_t num_uarts; /**< Number of attached UARTS (1-3) */
|
||||
bool mipseb; /**< MIPS is big-endian */
|
||||
uint8_t uart_clock; /**< UART clock source (see CHIPC_CAP_UCLKSEL_*) */
|
||||
uint8_t uart_gpio; /**< UARTs own GPIO pins 12-15 */
|
||||
|
||||
uint8_t extbus_type; /**< ExtBus type (CHIPC_CAP_EXTBUS_*) */
|
||||
|
||||
chipc_flash flash_type; /**< flash type */
|
||||
uint8_t cfi_width; /**< CFI bus width, 0 if unknown or CFI
|
||||
not present */
|
||||
|
||||
bhnd_nvram_src nvram_src; /**< identified NVRAM source */
|
||||
bus_size_t sprom_offset; /**< Offset to SPROM data within
|
||||
SPROM/OTP, 0 if unknown or not
|
||||
present */
|
||||
uint8_t otp_size; /**< OTP (row?) size, 0 if not present */
|
||||
|
||||
uint8_t pll_type; /**< PLL type */
|
||||
bool power_control; /**< Power control available */
|
||||
bool jtag_master; /**< JTAG Master present */
|
||||
bool boot_rom; /**< Internal boot ROM is active */
|
||||
uint8_t backplane_64; /**< Backplane supports 64-bit addressing.
|
||||
Note that this does not gaurantee
|
||||
the CPU itself supports 64-bit
|
||||
addressing. */
|
||||
bool pmu; /**< PMU is present. */
|
||||
bool eci; /**< ECI (enhanced coexistence inteface) is present. */
|
||||
bool seci; /**< SECI (serial ECI) is present */
|
||||
bool sprom; /**< SPROM is present */
|
||||
bool gsio; /**< GSIO (SPI/I2C) present */
|
||||
bool aob; /**< AOB (always on bus) present.
|
||||
If set, PMU and GCI registers are
|
||||
not accessible via ChipCommon,
|
||||
and are instead accessible via
|
||||
dedicated cores on the bhnd bus */
|
||||
};
|
||||
|
||||
/*
|
||||
* ChipCommon device quirks / features
|
||||
*/
|
||||
|
479
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.c
Normal file
479
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.c
Normal file
@ -0,0 +1,479 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* Copyright (c) 2010, Broadcom Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is derived from the siutils.c source distributed with the
|
||||
* Asus RT-N16 firmware source code release.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
#include <dev/bhnd/cores/chipc/chipcvar.h>
|
||||
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
|
||||
#include "bhnd_pwrctl_private.h"
|
||||
|
||||
/*
|
||||
* ChipCommon Power Control.
|
||||
*
|
||||
* Provides a bhnd_pmu_if-compatible interface to device clocking and
|
||||
* power management on non-PMU chipsets.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
BHND_PWRCTL_WAR_UP, /**< apply attach/resume workarounds */
|
||||
BHND_PWRCTL_WAR_RUN, /**< apply running workarounds */
|
||||
BHND_PWRCTL_WAR_DOWN, /**< apply detach/suspend workarounds */
|
||||
} bhnd_pwrctl_wars;
|
||||
|
||||
static int bhnd_pwrctl_updateclk(struct bhnd_pwrctl_softc *sc,
|
||||
bhnd_pwrctl_wars wars);
|
||||
|
||||
static struct bhnd_device_quirk pwrctl_quirks[];
|
||||
|
||||
|
||||
/* Supported parent core device identifiers */
|
||||
static const struct bhnd_device pwrctl_devices[] = {
|
||||
BHND_DEVICE(BCM, CC, "ChipCommon Power Control", pwrctl_quirks),
|
||||
BHND_DEVICE_END
|
||||
};
|
||||
|
||||
/* Device quirks table */
|
||||
static struct bhnd_device_quirk pwrctl_quirks[] = {
|
||||
BHND_CORE_QUIRK (HWREV_LTE(5), PWRCTL_QUIRK_PCICLK_CTL),
|
||||
BHND_CORE_QUIRK (HWREV_RANGE(6, 9), PWRCTL_QUIRK_SLOWCLK_CTL),
|
||||
BHND_CORE_QUIRK (HWREV_RANGE(10, 19), PWRCTL_QUIRK_INSTACLK_CTL),
|
||||
|
||||
BHND_DEVICE_QUIRK_END
|
||||
};
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_probe(device_t dev)
|
||||
{
|
||||
const struct bhnd_device *id;
|
||||
struct chipc_caps *ccaps;
|
||||
device_t chipc;
|
||||
|
||||
/* Look for compatible chipc parent */
|
||||
chipc = device_get_parent(dev);
|
||||
if (device_get_devclass(chipc) != devclass_find("bhnd_chipc"))
|
||||
return (ENXIO);
|
||||
|
||||
if (device_get_driver(chipc) != &bhnd_chipc_driver)
|
||||
return (ENXIO);
|
||||
|
||||
/* Verify chipc capability flags */
|
||||
ccaps = BHND_CHIPC_GET_CAPS(chipc);
|
||||
if (ccaps->pmu || !ccaps->pwr_ctrl)
|
||||
return (ENXIO);
|
||||
|
||||
/* Check for chipc device match */
|
||||
id = bhnd_device_lookup(chipc, pwrctl_devices,
|
||||
sizeof(pwrctl_devices[0]));
|
||||
if (id == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, id->desc);
|
||||
return (BUS_PROBE_NOWILDCARD);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_attach(device_t dev)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
const struct bhnd_chipid *cid;
|
||||
struct chipc_softc *chipc_sc;
|
||||
bhnd_devclass_t hostb_class;
|
||||
device_t hostb_dev;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* TODO: Need further testing on actual PWRCTL hardware */
|
||||
device_printf(dev, "WARNING: Using untested PWRCTL support\n");
|
||||
|
||||
sc->dev = dev;
|
||||
sc->chipc_dev = device_get_parent(dev);
|
||||
sc->quirks = bhnd_device_quirks(sc->chipc_dev, pwrctl_devices,
|
||||
sizeof(pwrctl_devices[0]));
|
||||
|
||||
/* On devices that lack a slow clock source, HT must always be
|
||||
* enabled. */
|
||||
hostb_class = BHND_DEVCLASS_INVALID;
|
||||
hostb_dev = bhnd_find_hostb_device(device_get_parent(sc->chipc_dev));
|
||||
if (hostb_dev != NULL)
|
||||
hostb_class = bhnd_get_class(hostb_dev);
|
||||
|
||||
cid = bhnd_get_chipid(sc->chipc_dev);
|
||||
switch (cid->chip_id) {
|
||||
case BHND_CHIPID_BCM4311:
|
||||
if (cid->chip_rev <= 1 && hostb_class == BHND_DEVCLASS_PCI)
|
||||
sc->quirks |= PWRCTL_QUIRK_FORCE_HT;
|
||||
break;
|
||||
|
||||
case BHND_CHIPID_BCM4321:
|
||||
if (hostb_class == BHND_DEVCLASS_PCIE ||
|
||||
hostb_class == BHND_DEVCLASS_PCI)
|
||||
sc->quirks |= PWRCTL_QUIRK_FORCE_HT;
|
||||
break;
|
||||
|
||||
case BHND_CHIPID_BCM4716:
|
||||
if (hostb_class == BHND_DEVCLASS_PCIE)
|
||||
sc->quirks |= PWRCTL_QUIRK_FORCE_HT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fetch core register block from ChipCommon parent */
|
||||
chipc_sc = device_get_softc(sc->chipc_dev);
|
||||
sc->res = chipc_sc->core;
|
||||
|
||||
PWRCTL_LOCK_INIT(sc);
|
||||
STAILQ_INIT(&sc->clkres_list);
|
||||
|
||||
/* Initialize power control */
|
||||
PWRCTL_LOCK(sc);
|
||||
|
||||
if ((error = bhnd_pwrctl_init(sc))) {
|
||||
PWRCTL_UNLOCK(sc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Apply default clock transitions */
|
||||
if ((error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_UP))) {
|
||||
PWRCTL_UNLOCK(sc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
PWRCTL_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
|
||||
cleanup:
|
||||
PWRCTL_LOCK_DESTROY(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_detach(device_t dev)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
struct bhnd_pwrctl_clkres *clkres, *crnext;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if ((error = bhnd_pwrctl_setclk(sc, BHND_CLOCK_DYN)))
|
||||
return (error);
|
||||
|
||||
STAILQ_FOREACH_SAFE(clkres, &sc->clkres_list, cr_link, crnext)
|
||||
free(clkres, M_DEVBUF);
|
||||
|
||||
PWRCTL_LOCK_DESTROY(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_suspend(device_t dev)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Update clock state */
|
||||
PWRCTL_LOCK(sc);
|
||||
error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_DOWN);
|
||||
PWRCTL_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_resume(device_t dev)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
PWRCTL_LOCK(sc);
|
||||
|
||||
/* Re-initialize power control registers */
|
||||
if ((error = bhnd_pwrctl_init(sc))) {
|
||||
device_printf(sc->dev, "PWRCTL init failed: %d\n", error);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Restore clock state */
|
||||
if ((error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_UP))) {
|
||||
device_printf(sc->dev, "clock state restore failed: %d\n",
|
||||
error);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the clock reservation associated with @p pinfo, if any.
|
||||
*
|
||||
* @param sc Driver instance state.
|
||||
* @param pinfo PMU info for device.
|
||||
*/
|
||||
static struct bhnd_pwrctl_clkres *
|
||||
bhnd_pwrctl_find_res(struct bhnd_pwrctl_softc *sc,
|
||||
struct bhnd_core_pmu_info *pinfo)
|
||||
{
|
||||
struct bhnd_pwrctl_clkres *clkres;
|
||||
|
||||
PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
STAILQ_FOREACH(clkres, &sc->clkres_list, cr_link) {
|
||||
if (clkres->owner == pinfo->pm_dev)
|
||||
return (clkres);
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerate all active clock requests, compute the minimum required clock,
|
||||
* and issue any required clock transition.
|
||||
*
|
||||
* @param sc Driver instance state.
|
||||
* @param wars Work-around state.
|
||||
*/
|
||||
static int
|
||||
bhnd_pwrctl_updateclk(struct bhnd_pwrctl_softc *sc, bhnd_pwrctl_wars wars)
|
||||
{
|
||||
struct bhnd_pwrctl_clkres *clkres;
|
||||
bhnd_clock clock;
|
||||
|
||||
PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
/* Default clock target */
|
||||
clock = BHND_CLOCK_DYN;
|
||||
|
||||
/* Apply quirk-specific overrides to the clock target */
|
||||
switch (wars) {
|
||||
case BHND_PWRCTL_WAR_UP:
|
||||
/* Force HT clock */
|
||||
if (PWRCTL_QUIRK(sc, FORCE_HT))
|
||||
clock = BHND_CLOCK_HT;
|
||||
break;
|
||||
|
||||
case BHND_PWRCTL_WAR_RUN:
|
||||
/* Cannot transition clock if FORCE_HT */
|
||||
if (PWRCTL_QUIRK(sc, FORCE_HT))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case BHND_PWRCTL_WAR_DOWN:
|
||||
/* Leave default clock unmodified to permit
|
||||
* transition back to BHND_CLOCK_DYN on FORCE_HT devices. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Determine required clock */
|
||||
STAILQ_FOREACH(clkres, &sc->clkres_list, cr_link)
|
||||
clock = bhnd_clock_max(clock, clkres->clock);
|
||||
|
||||
/* Map to supported clock setting */
|
||||
switch (clock) {
|
||||
case BHND_CLOCK_DYN:
|
||||
case BHND_CLOCK_ILP:
|
||||
clock = BHND_CLOCK_DYN;
|
||||
break;
|
||||
case BHND_CLOCK_ALP:
|
||||
/* In theory FORCE_ALP is supported by the hardware, but
|
||||
* there are currently no known use-cases for it; mapping
|
||||
* to HT is still valid, and allows us to punt on determing
|
||||
* where FORCE_ALP is supported and functional */
|
||||
clock = BHND_CLOCK_HT;
|
||||
break;
|
||||
case BHND_CLOCK_HT:
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->dev, "unknown clock: %#x\n", clock);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
/* Issue transition */
|
||||
return (bhnd_pwrctl_setclk(sc, clock));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_req_clock(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhnd_pwrctl_softc *sc;
|
||||
struct bhnd_pwrctl_clkres *clkres;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
error = 0;
|
||||
|
||||
PWRCTL_LOCK(sc);
|
||||
|
||||
clkres = bhnd_pwrctl_find_res(sc, pinfo);
|
||||
|
||||
/* BHND_CLOCK_DYN discards the clock reservation entirely */
|
||||
if (clock == BHND_CLOCK_DYN) {
|
||||
/* nothing to clean up? */
|
||||
if (clkres == NULL) {
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* drop reservation and apply clock transition */
|
||||
STAILQ_REMOVE(&sc->clkres_list, clkres,
|
||||
bhnd_pwrctl_clkres, cr_link);
|
||||
|
||||
if ((error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_RUN))) {
|
||||
device_printf(dev, "clock transition failed: %d\n",
|
||||
error);
|
||||
|
||||
/* restore reservation */
|
||||
STAILQ_INSERT_TAIL(&sc->clkres_list, clkres, cr_link);
|
||||
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* deallocate orphaned reservation */
|
||||
free(clkres, M_DEVBUF);
|
||||
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* create (or update) reservation */
|
||||
if (clkres == NULL) {
|
||||
clkres = malloc(sizeof(struct bhnd_pwrctl_clkres), M_DEVBUF,
|
||||
M_NOWAIT);
|
||||
if (clkres == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
clkres->owner = pinfo->pm_dev;
|
||||
clkres->clock = clock;
|
||||
|
||||
STAILQ_INSERT_TAIL(&sc->clkres_list, clkres, cr_link);
|
||||
} else {
|
||||
KASSERT(clkres->owner == pinfo->pm_dev, ("invalid owner"));
|
||||
clkres->clock = clock;
|
||||
}
|
||||
|
||||
/* apply clock transition */
|
||||
error = bhnd_pwrctl_updateclk(sc, BHND_PWRCTL_WAR_RUN);
|
||||
if (error) {
|
||||
STAILQ_REMOVE(&sc->clkres_list, clkres, bhnd_pwrctl_clkres,
|
||||
cr_link);
|
||||
free(clkres, M_DEVBUF);
|
||||
}
|
||||
|
||||
PWRCTL_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_req_ext_rsrc(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
u_int rsrc)
|
||||
{
|
||||
/* HW does not support per-core external resources */
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_release_ext_rsrc(device_t dev,
|
||||
struct bhnd_core_pmu_info *pinfo, u_int rsrc)
|
||||
{
|
||||
/* HW does not support per-core external resources */
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_en_clocks(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
uint32_t clocks)
|
||||
{
|
||||
/* All supported clocks are already enabled by default (?) */
|
||||
clocks &= ~(BHND_CLOCK_DYN |
|
||||
BHND_CLOCK_ILP |
|
||||
BHND_CLOCK_ALP |
|
||||
BHND_CLOCK_HT);
|
||||
|
||||
if (clocks != 0) {
|
||||
device_printf(dev, "%s requested unknown clocks: %#x\n",
|
||||
device_get_nameunit(pinfo->pm_dev), clocks);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pwrctl_core_release(device_t dev, struct bhnd_core_pmu_info *pinfo)
|
||||
{
|
||||
/* Requesting BHND_CLOCK_DYN releases any outstanding clock
|
||||
* reservations */
|
||||
return (bhnd_pwrctl_core_req_clock(dev, pinfo, BHND_CLOCK_DYN));
|
||||
}
|
||||
|
||||
static device_method_t bhnd_pwrctl_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_pwrctl_probe),
|
||||
DEVMETHOD(device_attach, bhnd_pwrctl_attach),
|
||||
DEVMETHOD(device_detach, bhnd_pwrctl_detach),
|
||||
DEVMETHOD(device_suspend, bhnd_pwrctl_suspend),
|
||||
DEVMETHOD(device_resume, bhnd_pwrctl_resume),
|
||||
|
||||
/* BHND PMU interface */
|
||||
DEVMETHOD(bhnd_pmu_core_req_clock, bhnd_pwrctl_core_req_clock),
|
||||
DEVMETHOD(bhnd_pmu_core_en_clocks, bhnd_pwrctl_core_en_clocks),
|
||||
DEVMETHOD(bhnd_pmu_core_req_ext_rsrc, bhnd_pwrctl_core_req_ext_rsrc),
|
||||
DEVMETHOD(bhnd_pmu_core_release_ext_rsrc, bhnd_pwrctl_core_release_ext_rsrc),
|
||||
DEVMETHOD(bhnd_pmu_core_release, bhnd_pwrctl_core_release),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(bhnd_pmu, bhnd_pwrctl_driver, bhnd_pwrctl_methods,
|
||||
sizeof(struct bhnd_pwrctl_softc));
|
||||
EARLY_DRIVER_MODULE(bhnd_pwrctl, bhnd_chipc, bhnd_pwrctl_driver,
|
||||
bhnd_pmu_devclass, NULL, NULL, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
|
||||
|
||||
MODULE_DEPEND(bhnd_pwrctl, bhnd, 1, 1, 1);
|
||||
MODULE_VERSION(bhnd_pwrctl, 1);
|
43
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_private.h
Normal file
43
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_private.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_PWRCTL_BHND_PWRCTL_PRIVATE_H_
|
||||
#define _BHND_PWRCTL_BHND_PWRCTL_PRIVATE_H_
|
||||
|
||||
#include "bhnd_pwrctlvar.h"
|
||||
|
||||
int bhnd_pwrctl_init(struct bhnd_pwrctl_softc *sc);
|
||||
int bhnd_pwrctl_setclk(struct bhnd_pwrctl_softc *sc,
|
||||
bhnd_clock clock);
|
||||
uint32_t bhnd_pwrctl_getclk_speed(struct bhnd_pwrctl_softc *sc);
|
||||
uint16_t bhnd_pwrctl_fast_pwrup_delay(struct bhnd_pwrctl_softc *sc);
|
||||
|
||||
#endif /* _BHND_PWRCTL_BHND_PWRCTL_PRIVATE_H_ */
|
463
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c
Normal file
463
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c
Normal file
@ -0,0 +1,463 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* Copyright (c) 2010, Broadcom Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is derived from the siutils.c source distributed with the
|
||||
* Asus RT-N16 firmware source code release.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
#include <dev/bhnd/bhndb/bhndb_pcireg.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipc.h>
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
|
||||
|
||||
#include "bhnd_chipc_if.h"
|
||||
|
||||
#include "bhnd_pwrctl_private.h"
|
||||
|
||||
static uint32_t bhnd_pwrctl_factor6(uint32_t x);
|
||||
static uint32_t bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n,
|
||||
uint32_t m);
|
||||
|
||||
/**
|
||||
* Return the factor value corresponding to a given N3M clock control magic
|
||||
* field value (CHIPC_F6_*).
|
||||
*/
|
||||
static uint32_t
|
||||
bhnd_pwrctl_factor6(uint32_t x)
|
||||
{
|
||||
switch (x) {
|
||||
case CHIPC_F6_2:
|
||||
return (2);
|
||||
case CHIPC_F6_3:
|
||||
return (3);
|
||||
case CHIPC_F6_4:
|
||||
return (4);
|
||||
case CHIPC_F6_5:
|
||||
return (5);
|
||||
case CHIPC_F6_6:
|
||||
return (6);
|
||||
case CHIPC_F6_7:
|
||||
return (7);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the clock speed (in Hz) for a given a set of clockcontrol
|
||||
* values.
|
||||
*
|
||||
* @param pll_type PLL type (CHIPC_PLL_TYPE*)
|
||||
* @param n clock control N register value.
|
||||
* @param m clock control N register value.
|
||||
*/
|
||||
static uint32_t
|
||||
bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n, uint32_t m)
|
||||
{
|
||||
uint32_t clk_base;
|
||||
uint32_t n1, n2, clock, m1, m2, m3, mc;
|
||||
|
||||
n1 = CHIPC_GET_BITS(n, CHIPC_CN_N1);
|
||||
n2 = CHIPC_GET_BITS(n, CHIPC_CN_N2);
|
||||
|
||||
switch (pll_type) {
|
||||
case CHIPC_PLL_TYPE1:
|
||||
case CHIPC_PLL_TYPE3:
|
||||
case CHIPC_PLL_TYPE4:
|
||||
case CHIPC_PLL_TYPE7:
|
||||
n1 = bhnd_pwrctl_factor6(n1);
|
||||
n2 += CHIPC_F5_BIAS;
|
||||
break;
|
||||
|
||||
case CHIPC_PLL_TYPE2:
|
||||
n1 += CHIPC_T2_BIAS;
|
||||
n2 += CHIPC_T2_BIAS;
|
||||
KASSERT(n1 >= 2 && n1 <= 7, ("invalid n1 value"));
|
||||
KASSERT(n2 >= 5 && n2 <= 23, ("invalid n2 value"));
|
||||
break;
|
||||
|
||||
case CHIPC_PLL_TYPE5:
|
||||
return (100000000);
|
||||
|
||||
case CHIPC_PLL_TYPE6:
|
||||
if (m & CHIPC_T6_MMASK)
|
||||
return (CHIPC_T6_M1);
|
||||
else
|
||||
return (CHIPC_T6_M0);
|
||||
|
||||
default:
|
||||
printf("unsupported PLL type %u\n", pll_type);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* PLL types 3 and 7 use BASE2 (25Mhz) */
|
||||
if (pll_type == CHIPC_PLL_TYPE3 || pll_type == CHIPC_PLL_TYPE7) {
|
||||
clk_base = CHIPC_CLOCK_BASE2;
|
||||
} else {
|
||||
clk_base = CHIPC_CLOCK_BASE1;
|
||||
}
|
||||
|
||||
clock = clk_base * n1 * n2;
|
||||
|
||||
if (clock == 0)
|
||||
return (0);
|
||||
|
||||
m1 = CHIPC_GET_BITS(m, CHIPC_M1);
|
||||
m2 = CHIPC_GET_BITS(m, CHIPC_M2);
|
||||
m3 = CHIPC_GET_BITS(m, CHIPC_M3);
|
||||
mc = CHIPC_GET_BITS(m, CHIPC_MC);
|
||||
|
||||
switch (pll_type) {
|
||||
case CHIPC_PLL_TYPE1:
|
||||
case CHIPC_PLL_TYPE3:
|
||||
case CHIPC_PLL_TYPE4:
|
||||
case CHIPC_PLL_TYPE7:
|
||||
m1 = bhnd_pwrctl_factor6(m1);
|
||||
if (pll_type == CHIPC_PLL_TYPE1 || pll_type == CHIPC_PLL_TYPE3)
|
||||
m2 += CHIPC_F5_BIAS;
|
||||
else
|
||||
m2 = bhnd_pwrctl_factor6(m2);
|
||||
|
||||
m3 = bhnd_pwrctl_factor6(m3);
|
||||
|
||||
switch (mc) {
|
||||
case CHIPC_MC_BYPASS:
|
||||
return (clock);
|
||||
case CHIPC_MC_M1:
|
||||
return (clock / m1);
|
||||
case CHIPC_MC_M1M2:
|
||||
return (clock / (m1 * m2));
|
||||
case CHIPC_MC_M1M2M3:
|
||||
return (clock / (m1 * m2 * m3));
|
||||
case CHIPC_MC_M1M3:
|
||||
return (clock / (m1 * m3));
|
||||
default:
|
||||
printf("unsupported pwrctl mc %#x\n", mc);
|
||||
return (0);
|
||||
}
|
||||
case CHIPC_PLL_TYPE2:
|
||||
m1 += CHIPC_T2_BIAS;
|
||||
m2 += CHIPC_T2M2_BIAS;
|
||||
m3 += CHIPC_T2_BIAS;
|
||||
KASSERT(m1 >= 2 && m1 <= 7, ("invalid m1 value"));
|
||||
KASSERT(m2 >= 3 && m2 <= 10, ("invalid m2 value"));
|
||||
KASSERT(m3 >= 2 && m3 <= 7, ("invalid m3 value"));
|
||||
|
||||
if ((mc & CHIPC_T2MC_M1BYP) == 0)
|
||||
clock /= m1;
|
||||
if ((mc & CHIPC_T2MC_M2BYP) == 0)
|
||||
clock /= m2;
|
||||
if ((mc & CHIPC_T2MC_M3BYP) == 0)
|
||||
clock /= m3;
|
||||
|
||||
return (clock);
|
||||
default:
|
||||
panic("unhandled PLL type %u\n", pll_type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the backplane clock speed in Hz.
|
||||
*
|
||||
* @param sc driver instance state.
|
||||
*/
|
||||
uint32_t
|
||||
bhnd_pwrctl_getclk_speed(struct bhnd_pwrctl_softc *sc)
|
||||
{
|
||||
struct chipc_caps *ccaps;
|
||||
bus_size_t creg;
|
||||
uint32_t n, m;
|
||||
uint32_t rate;
|
||||
|
||||
PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev);
|
||||
|
||||
n = bhnd_bus_read_4(sc->res, CHIPC_CLKC_N);
|
||||
|
||||
switch (ccaps->pll_type) {
|
||||
case CHIPC_PLL_TYPE6:
|
||||
creg = CHIPC_CLKC_M3; /* non-extif regster */
|
||||
break;
|
||||
case CHIPC_PLL_TYPE3:
|
||||
creg = CHIPC_CLKC_M2;
|
||||
break;
|
||||
default:
|
||||
creg = CHIPC_CLKC_SB;
|
||||
break;
|
||||
}
|
||||
|
||||
m = bhnd_bus_read_4(sc->res, creg);
|
||||
|
||||
/* calculate rate */
|
||||
rate = bhnd_pwrctl_clock_rate(ccaps->pll_type, n, m);
|
||||
|
||||
if (ccaps->pll_type == CHIPC_PLL_TYPE3)
|
||||
rate /= 2;
|
||||
|
||||
return (rate);
|
||||
}
|
||||
|
||||
/* return the slow clock source */
|
||||
static bhnd_clksrc
|
||||
bhnd_pwrctl_slowclk_src(struct bhnd_pwrctl_softc *sc)
|
||||
{
|
||||
uint32_t clkreg;
|
||||
uint32_t clksrc;
|
||||
|
||||
/* Fetch clock source */
|
||||
if (PWRCTL_QUIRK(sc, PCICLK_CTL)) {
|
||||
return (bhnd_pwrctl_get_clksrc(sc->chipc_dev, BHND_CLOCK_ILP));
|
||||
} else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
|
||||
clkreg = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
|
||||
clksrc = clkreg & CHIPC_SCC_SS_MASK;
|
||||
} else {
|
||||
/* Instaclock */
|
||||
clksrc = CHIPC_SCC_SS_XTAL;
|
||||
}
|
||||
|
||||
/* Map to bhnd_clksrc */
|
||||
switch (clksrc) {
|
||||
case CHIPC_SCC_SS_PCI:
|
||||
return (BHND_CLKSRC_PCI);
|
||||
case CHIPC_SCC_SS_LPO:
|
||||
return (BHND_CLKSRC_LPO);
|
||||
case CHIPC_SCC_SS_XTAL:
|
||||
return (BHND_CLKSRC_XTAL);
|
||||
default:
|
||||
return (BHND_CLKSRC_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
/* return the ILP (slowclock) min or max frequency */
|
||||
static uint32_t
|
||||
bhnd_pwrctl_slowclk_freq(struct bhnd_pwrctl_softc *sc, bool max_freq)
|
||||
{
|
||||
bhnd_clksrc slowclk;
|
||||
uint32_t div;
|
||||
uint32_t hz;
|
||||
|
||||
slowclk = bhnd_pwrctl_slowclk_src(sc);
|
||||
|
||||
/* Determine clock divisor */
|
||||
if (PWRCTL_QUIRK(sc, PCICLK_CTL)) {
|
||||
if (slowclk == BHND_CLKSRC_PCI)
|
||||
div = 64;
|
||||
else
|
||||
div = 32;
|
||||
} else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
|
||||
div = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
|
||||
div = CHIPC_GET_BITS(div, CHIPC_SCC_CD);
|
||||
div *= 4;
|
||||
} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
|
||||
if (max_freq) {
|
||||
div = 1;
|
||||
} else {
|
||||
div = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL);
|
||||
div = CHIPC_GET_BITS(div, CHIPC_SYCC_CD);
|
||||
div = 4 * (div + 1);
|
||||
}
|
||||
} else {
|
||||
device_printf(sc->dev, "unknown device type\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Determine clock frequency */
|
||||
switch (slowclk) {
|
||||
case BHND_CLKSRC_LPO:
|
||||
hz = max_freq ? CHIPC_LPOMAXFREQ : CHIPC_LPOMINFREQ;
|
||||
break;
|
||||
case BHND_CLKSRC_XTAL:
|
||||
hz = max_freq ? CHIPC_XTALMAXFREQ : CHIPC_XTALMINFREQ;
|
||||
break;
|
||||
case BHND_CLKSRC_PCI:
|
||||
hz = max_freq ? CHIPC_PCIMAXFREQ : CHIPC_PCIMINFREQ;
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->dev, "unknown slowclk source %#x\n", slowclk);
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (hz / div);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize power control registers.
|
||||
*/
|
||||
int
|
||||
bhnd_pwrctl_init(struct bhnd_pwrctl_softc *sc)
|
||||
{
|
||||
uint32_t clkctl;
|
||||
uint32_t pll_delay, slowclk, slowmaxfreq;
|
||||
uint32_t pll_on_delay, fref_sel_delay;
|
||||
int error;
|
||||
|
||||
pll_delay = CHIPC_PLL_DELAY;
|
||||
|
||||
/* set all Instaclk chip ILP to 1 MHz */
|
||||
if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
|
||||
clkctl = (CHIPC_ILP_DIV_1MHZ << CHIPC_SYCC_CD_SHIFT);
|
||||
clkctl &= CHIPC_SYCC_CD_MASK;
|
||||
bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, clkctl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize PLL/FREF delays.
|
||||
*
|
||||
* If the slow clock is not sourced by the xtal, include the
|
||||
* delay required to bring it up.
|
||||
*/
|
||||
slowclk = bhnd_pwrctl_slowclk_src(sc);
|
||||
if (slowclk != CHIPC_SCC_SS_XTAL)
|
||||
pll_delay += CHIPC_XTAL_ON_DELAY;
|
||||
|
||||
/* Starting with 4318 it is ILP that is used for the delays */
|
||||
if (PWRCTL_QUIRK(sc, INSTACLK_CTL))
|
||||
slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, false);
|
||||
else
|
||||
slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, true);
|
||||
|
||||
pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
|
||||
fref_sel_delay = ((slowmaxfreq * CHIPC_FREF_DELAY) + 999999) / 1000000;
|
||||
|
||||
bhnd_bus_write_4(sc->res, CHIPC_PLL_ON_DELAY, pll_on_delay);
|
||||
bhnd_bus_write_4(sc->res, CHIPC_PLL_FREFSEL_DELAY, fref_sel_delay);
|
||||
|
||||
/* If required, force HT */
|
||||
if (PWRCTL_QUIRK(sc, FORCE_HT)) {
|
||||
if ((error = bhnd_pwrctl_setclk(sc, BHND_CLOCK_HT)))
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* return the value suitable for writing to the dot11 core
|
||||
* FAST_PWRUP_DELAY register */
|
||||
uint16_t
|
||||
bhnd_pwrctl_fast_pwrup_delay(struct bhnd_pwrctl_softc *sc)
|
||||
{
|
||||
uint32_t pll_on_delay, slowminfreq;
|
||||
uint16_t fpdelay;
|
||||
|
||||
fpdelay = 0;
|
||||
|
||||
slowminfreq = bhnd_pwrctl_slowclk_freq(sc, false);
|
||||
|
||||
pll_on_delay = bhnd_bus_read_4(sc->res, CHIPC_PLL_ON_DELAY) + 2;
|
||||
pll_on_delay *= 1000000;
|
||||
pll_on_delay += (slowminfreq - 1);
|
||||
fpdelay = pll_on_delay / slowminfreq;
|
||||
|
||||
return (fpdelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Distribute @p clock on backplane.
|
||||
*
|
||||
* @param sc Driver instance state.
|
||||
* @param clock Clock to enable.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If @p clock is unsupported, or if the device does not
|
||||
* support dynamic clock control.
|
||||
*/
|
||||
int
|
||||
bhnd_pwrctl_setclk(struct bhnd_pwrctl_softc *sc, bhnd_clock clock)
|
||||
{
|
||||
uint32_t scc;
|
||||
|
||||
PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
/* Is dynamic clock control supported? */
|
||||
if (PWRCTL_QUIRK(sc, FIXED_CLK))
|
||||
return (ENODEV);
|
||||
|
||||
/* Chips with ccrev 10 are EOL and they don't have SYCC_HR used below */
|
||||
if (bhnd_get_hwrev(sc->chipc_dev) == 10)
|
||||
return (ENODEV);
|
||||
|
||||
scc = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
|
||||
|
||||
switch (clock) {
|
||||
case BHND_CLOCK_HT:
|
||||
/* fast (pll) clock */
|
||||
if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
|
||||
scc &= ~(CHIPC_SCC_XC | CHIPC_SCC_FS | CHIPC_SCC_IP);
|
||||
scc |= CHIPC_SCC_IP;
|
||||
|
||||
/* force xtal back on before clearing SCC_DYN_XTAL.. */
|
||||
bhnd_pwrctl_ungate_clock(sc->chipc_dev, BHND_CLOCK_HT);
|
||||
} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
|
||||
scc |= CHIPC_SYCC_HR;
|
||||
} else {
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc);
|
||||
DELAY(CHIPC_PLL_DELAY);
|
||||
|
||||
break;
|
||||
|
||||
case BHND_CLOCK_DYN:
|
||||
/* enable dynamic clock control */
|
||||
if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
|
||||
scc &= ~(CHIPC_SCC_FS | CHIPC_SCC_IP | CHIPC_SCC_XC);
|
||||
if ((scc & CHIPC_SCC_SS_MASK) != CHIPC_SCC_SS_XTAL)
|
||||
scc |= CHIPC_SCC_XC;
|
||||
|
||||
bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc);
|
||||
|
||||
/* for dynamic control, we have to release our xtal_pu
|
||||
* "force on" */
|
||||
if (scc & CHIPC_SCC_XC) {
|
||||
bhnd_pwrctl_gate_clock(sc->chipc_dev,
|
||||
BHND_CLOCK_HT);
|
||||
}
|
||||
} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
|
||||
/* Instaclock */
|
||||
scc &= ~CHIPC_SYCC_HR;
|
||||
bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, scc);
|
||||
} else {
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
120
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctlvar.h
Normal file
120
sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctlvar.h
Normal file
@ -0,0 +1,120 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_PWRCTL_BHND_PWRCTLVAR_H_
|
||||
#define _BHND_PWRCTL_BHND_PWRCTLVAR_H_
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
/**
|
||||
* bhnd pwrctl device quirks.
|
||||
*/
|
||||
enum {
|
||||
/** No quirks */
|
||||
PWRCTL_QUIRK_NONE = 0,
|
||||
|
||||
/**
|
||||
* Early ChipCommon revisions do not support dynamic clock control
|
||||
*/
|
||||
PWRCTL_QUIRK_FIXED_CLK = (1 << 0),
|
||||
|
||||
/**
|
||||
* On PCI (not PCIe) devices, early ChipCommon revisions
|
||||
* (rev <= 5) vend xtal/pll and clock config registers via the PCI
|
||||
* config space.
|
||||
*
|
||||
* Dynamic clock control is not supported on these devices.
|
||||
*/
|
||||
PWRCTL_QUIRK_PCICLK_CTL = (1 << 1) | PWRCTL_QUIRK_FIXED_CLK,
|
||||
|
||||
|
||||
/**
|
||||
* On earliy BCM4311, BCM4321, and BCM4716 PCI(e) devices, no ALP
|
||||
* clock is available, and the HT clock must be enabled.
|
||||
*/
|
||||
PWRCTL_QUIRK_FORCE_HT = (1 << 2),
|
||||
|
||||
/**
|
||||
* ChipCommon revisions 6-9 use the slowclk register layout.
|
||||
*/
|
||||
PWRCTL_QUIRK_SLOWCLK_CTL = (1 << 3),
|
||||
|
||||
/**
|
||||
* ChipCommon revisions 10-19 support the instaclk register layout.
|
||||
*/
|
||||
PWRCTL_QUIRK_INSTACLK_CTL = (1 << 4),
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* device clock reservation.
|
||||
*/
|
||||
struct bhnd_pwrctl_clkres {
|
||||
device_t owner; /**< bhnd(4) device holding this reservation */
|
||||
bhnd_clock clock; /**< requested clock */
|
||||
STAILQ_ENTRY(bhnd_pwrctl_clkres) cr_link;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* bhnd pwrctl driver instance state.
|
||||
*/
|
||||
struct bhnd_pwrctl_softc {
|
||||
device_t dev;
|
||||
uint32_t quirks;
|
||||
|
||||
device_t chipc_dev; /**< core device */
|
||||
struct bhnd_resource *res; /**< core register block. */
|
||||
|
||||
struct mtx mtx; /**< state mutex */
|
||||
|
||||
/** active clock reservations */
|
||||
STAILQ_HEAD(, bhnd_pwrctl_clkres) clkres_list;
|
||||
};
|
||||
|
||||
#define PWRCTL_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
|
||||
"bhnd pwrctl driver lock", MTX_DEF)
|
||||
#define PWRCTL_LOCK(sc) mtx_lock(&(sc)->mtx)
|
||||
#define PWRCTL_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
|
||||
#define PWRCTL_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what)
|
||||
#define PWRCTL_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx)
|
||||
|
||||
/* quirk convenience macro */
|
||||
#define PWRCTL_QUIRK(_sc, _name) \
|
||||
((_sc)->quirks & PWRCTL_QUIRK_ ## _name)
|
||||
|
||||
#define PWRCTL_ASSERT_QUIRK(_sc, name) \
|
||||
KASSERT(PWRCTL_QUIRK((_sc), name), ("quirk " __STRING(_name) " not set"))
|
||||
|
||||
#endif /* _BHND_PWRCTL_BHND_PWRCTLVAR_H_ */
|
466
sys/dev/bhnd/cores/pmu/bhnd_pmu.c
Normal file
466
sys/dev/bhnd/cores/pmu/bhnd_pmu.c
Normal file
@ -0,0 +1,466 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include "bhnd_nvram_map.h"
|
||||
|
||||
#include "bhnd_pmureg.h"
|
||||
#include "bhnd_pmuvar.h"
|
||||
|
||||
#include "bhnd_pmu_private.h"
|
||||
|
||||
/*
|
||||
* Broadcom PMU driver.
|
||||
*
|
||||
* On modern BHND chipsets, the PMU, GCI, and SRENG (Save/Restore Engine?)
|
||||
* register blocks are found within a dedicated PMU core (attached via
|
||||
* the AHB 'always on bus').
|
||||
*
|
||||
* On earlier chipsets, these register blocks are found at the same
|
||||
* offsets within the ChipCommon core.
|
||||
*/
|
||||
|
||||
devclass_t bhnd_pmu_devclass; /**< bhnd(4) PMU device class */
|
||||
|
||||
static int bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS);
|
||||
static int bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS);
|
||||
static int bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
#define BPMU_CLKCTL_READ_4(_pinfo) \
|
||||
bhnd_bus_read_4((_pinfo)->pm_res, (_pinfo)->pm_regs)
|
||||
|
||||
#define BPMU_CLKCTL_WRITE_4(_pinfo, _val) \
|
||||
bhnd_bus_write_4((_pinfo)->pm_res, (_pinfo)->pm_regs, (_val))
|
||||
|
||||
#define BPMU_CLKCTL_SET_4(_pinfo, _val, _mask) \
|
||||
BPMU_CLKCTL_WRITE_4((_pinfo), \
|
||||
((_val) & (_mask)) | (BPMU_CLKCTL_READ_4(_pinfo) & ~(_mask)))
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_PROBE().
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_probe(device_t dev)
|
||||
{
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_ATTACH().
|
||||
*
|
||||
* @param dev PMU device.
|
||||
* @param res The PMU device registers. The driver will maintain a borrowed
|
||||
* reference to this resource for the lifetime of the device.
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_attach(device_t dev, struct bhnd_resource *res)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
struct sysctl_ctx_list *ctx;
|
||||
struct sysctl_oid *tree;
|
||||
devclass_t bhnd_class;
|
||||
device_t core, bus;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
sc->quirks = 0;
|
||||
sc->res = res;
|
||||
|
||||
/* Fetch capability flags */
|
||||
sc->caps = bhnd_bus_read_4(sc->res, BHND_PMU_CAP);
|
||||
|
||||
/* Find the bus-attached core */
|
||||
bhnd_class = devclass_find("bhnd");
|
||||
core = sc->dev;
|
||||
while ((bus = device_get_parent(core)) != NULL) {
|
||||
if (device_get_devclass(bus) == bhnd_class)
|
||||
break;
|
||||
|
||||
core = bus;
|
||||
}
|
||||
|
||||
if (core == NULL) {
|
||||
device_printf(sc->dev, "bhnd bus not found\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Fetch chip and board info */
|
||||
sc->cid = *bhnd_get_chipid(core);
|
||||
|
||||
if ((error = bhnd_read_board_info(core, &sc->board))) {
|
||||
device_printf(sc->dev, "error fetching board info: %d\n",
|
||||
error);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Locate ChipCommon device */
|
||||
sc->chipc_dev = bhnd_find_child(bus, BHND_DEVCLASS_CC, 0);
|
||||
if (sc->chipc_dev == NULL) {
|
||||
device_printf(sc->dev, "chipcommon device not found\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
BPMU_LOCK_INIT(sc);
|
||||
|
||||
/* Set quirk flags */
|
||||
switch (sc->cid.chip_id) {
|
||||
case BHND_CHIPID_BCM4328:
|
||||
case BHND_CHIPID_BCM5354:
|
||||
/* HTAVAIL/ALPAVAIL are bitswapped in CLKCTL */
|
||||
sc->quirks |= BPMU_QUIRK_CLKCTL_CCS0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Initialize PMU */
|
||||
if ((error = bhnd_pmu_init(sc))) {
|
||||
device_printf(sc->dev, "PMU init failed: %d\n", error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* Set up sysctl nodes */
|
||||
ctx = device_get_sysctl_ctx(dev);
|
||||
tree = device_get_sysctl_tree(dev);
|
||||
|
||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
||||
"bus_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
|
||||
bhnd_pmu_sysctl_bus_freq, "IU", "Bus clock frequency");
|
||||
|
||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
||||
"cpu_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
|
||||
bhnd_pmu_sysctl_cpu_freq, "IU", "CPU clock frequency");
|
||||
|
||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
||||
"mem_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
|
||||
bhnd_pmu_sysctl_mem_freq, "IU", "Memory clock frequency");
|
||||
|
||||
return (0);
|
||||
|
||||
failed:
|
||||
BPMU_LOCK_DESTROY(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_DETACH().
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_detach(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
BPMU_LOCK_DESTROY(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_SUSPEND().
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_suspend(device_t dev)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default bhnd_pmu driver implementation of DEVICE_RESUME().
|
||||
*/
|
||||
int
|
||||
bhnd_pmu_resume(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Re-initialize PMU */
|
||||
if ((error = bhnd_pmu_init(sc))) {
|
||||
device_printf(sc->dev, "PMU init failed: %d\n", error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_sysctl_bus_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t freq;
|
||||
|
||||
sc = arg1;
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
freq = bhnd_pmu_si_clock(sc);
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (sysctl_handle_32(oidp, NULL, freq, req));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t freq;
|
||||
|
||||
sc = arg1;
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
freq = bhnd_pmu_cpu_clock(sc);
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (sysctl_handle_32(oidp, NULL, freq, req));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t freq;
|
||||
|
||||
sc = arg1;
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
freq = bhnd_pmu_mem_clock(sc);
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (sysctl_handle_32(oidp, NULL, freq, req));
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_req_clock(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
bhnd_clock clock)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t avail;
|
||||
uint32_t req;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
avail = 0x0;
|
||||
req = 0x0;
|
||||
|
||||
switch (clock) {
|
||||
case BHND_CLOCK_DYN:
|
||||
break;
|
||||
case BHND_CLOCK_ILP:
|
||||
req |= BHND_CCS_FORCEILP;
|
||||
break;
|
||||
case BHND_CLOCK_ALP:
|
||||
req |= BHND_CCS_FORCEALP;
|
||||
avail |= BHND_CCS_ALPAVAIL;
|
||||
break;
|
||||
case BHND_CLOCK_HT:
|
||||
req |= BHND_CCS_FORCEHT;
|
||||
avail |= BHND_CCS_HTAVAIL;
|
||||
break;
|
||||
default:
|
||||
device_printf(dev, "%s requested unknown clock: %#x\n",
|
||||
device_get_nameunit(pinfo->pm_dev), clock);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
|
||||
/* Issue request */
|
||||
BPMU_CLKCTL_SET_4(pinfo, req, BHND_CCS_FORCE_MASK);
|
||||
|
||||
/* Wait for clock availability */
|
||||
bhnd_pmu_wait_clkst(sc, pinfo->pm_dev, pinfo->pm_res, pinfo->pm_regs,
|
||||
avail, avail);
|
||||
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_en_clocks(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
uint32_t clocks)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t avail;
|
||||
uint32_t req;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
avail = 0x0;
|
||||
req = 0x0;
|
||||
|
||||
/* Build clock request flags */
|
||||
if (clocks & BHND_CLOCK_DYN) /* nothing to enable */
|
||||
clocks &= ~BHND_CLOCK_DYN;
|
||||
|
||||
if (clocks & BHND_CLOCK_ILP) /* nothing to enable */
|
||||
clocks &= ~BHND_CLOCK_ILP;
|
||||
|
||||
if (clocks & BHND_CLOCK_ALP) {
|
||||
req |= BHND_CCS_ALPAREQ;
|
||||
avail |= BHND_CCS_ALPAVAIL;
|
||||
clocks &= ~BHND_CLOCK_ALP;
|
||||
}
|
||||
|
||||
if (clocks & BHND_CLOCK_HT) {
|
||||
req |= BHND_CCS_HTAREQ;
|
||||
avail |= BHND_CCS_HTAVAIL;
|
||||
clocks &= ~BHND_CLOCK_HT;
|
||||
}
|
||||
|
||||
/* Check for unknown clock values */
|
||||
if (clocks != 0x0) {
|
||||
device_printf(dev, "%s requested unknown clocks: %#x\n",
|
||||
device_get_nameunit(pinfo->pm_dev), clocks);
|
||||
return (ENODEV);
|
||||
}
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
|
||||
/* Issue request */
|
||||
BPMU_CLKCTL_SET_4(pinfo, req, BHND_CCS_AREQ_MASK);
|
||||
|
||||
/* Wait for clock availability */
|
||||
bhnd_pmu_wait_clkst(sc, pinfo->pm_dev, pinfo->pm_res, pinfo->pm_regs,
|
||||
avail, avail);
|
||||
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_req_ext_rsrc(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
u_int rsrc)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t req;
|
||||
uint32_t avail;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (rsrc > BHND_CCS_ERSRC_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
req = BHND_PMU_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
|
||||
avail = BHND_PMU_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_STS);
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
|
||||
/* Write request */
|
||||
BPMU_CLKCTL_SET_4(pinfo, req, req);
|
||||
|
||||
/* Wait for resource availability */
|
||||
bhnd_pmu_wait_clkst(sc, pinfo->pm_dev, pinfo->pm_res, pinfo->pm_regs,
|
||||
avail, avail);
|
||||
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_release_ext_rsrc(device_t dev, struct bhnd_core_pmu_info *pinfo,
|
||||
u_int rsrc)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
uint32_t mask;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (rsrc > BHND_CCS_ERSRC_MAX)
|
||||
return (EINVAL);
|
||||
|
||||
mask = BHND_PMU_SET_BITS((1<<rsrc), BHND_CCS_ERSRC_REQ);
|
||||
|
||||
/* Clear request */
|
||||
BPMU_LOCK(sc);
|
||||
BPMU_CLKCTL_SET_4(pinfo, 0x0, mask);
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_release(device_t dev, struct bhnd_core_pmu_info *pinfo)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
BPMU_LOCK(sc);
|
||||
|
||||
/* Clear all FORCE, AREQ, and ERSRC flags */
|
||||
BPMU_CLKCTL_SET_4(pinfo, 0x0,
|
||||
BHND_CCS_FORCE_MASK | BHND_CCS_AREQ_MASK | BHND_CCS_ERSRC_REQ_MASK);
|
||||
|
||||
BPMU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t bhnd_pmu_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_pmu_probe),
|
||||
DEVMETHOD(device_detach, bhnd_pmu_detach),
|
||||
DEVMETHOD(device_suspend, bhnd_pmu_suspend),
|
||||
DEVMETHOD(device_resume, bhnd_pmu_resume),
|
||||
|
||||
/* BHND PMU interface */
|
||||
DEVMETHOD(bhnd_pmu_core_req_clock, bhnd_pmu_core_req_clock),
|
||||
DEVMETHOD(bhnd_pmu_core_en_clocks, bhnd_pmu_core_en_clocks),
|
||||
DEVMETHOD(bhnd_pmu_core_req_ext_rsrc, bhnd_pmu_core_req_ext_rsrc),
|
||||
DEVMETHOD(bhnd_pmu_core_release_ext_rsrc, bhnd_pmu_core_release_ext_rsrc),
|
||||
DEVMETHOD(bhnd_pmu_core_release, bhnd_pmu_core_release),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(bhnd_pmu, bhnd_pmu_driver, bhnd_pmu_methods, sizeof(struct bhnd_pmu_softc));
|
||||
MODULE_VERSION(bhnd_pmu, 1);
|
52
sys/dev/bhnd/cores/pmu/bhnd_pmu.h
Normal file
52
sys/dev/bhnd/cores/pmu/bhnd_pmu.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_CORES_PMU_BHND_PMU_H_
|
||||
#define _BHND_CORES_PMU_BHND_PMU_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "bhnd_pmu_if.h"
|
||||
|
||||
/**
|
||||
* Per-core PMU register information.
|
||||
*/
|
||||
struct bhnd_core_pmu_info {
|
||||
device_t pm_dev; /**< core device */
|
||||
device_t pm_pmu; /**< PMU device */
|
||||
struct bhnd_resource *pm_res; /**< Resource containing PMU
|
||||
register block for this
|
||||
device (if any). */
|
||||
bus_size_t pm_regs; /**< Offset to PMU register
|
||||
* block in @p pm_res */
|
||||
};
|
||||
|
||||
#endif /* _BHND_CORES_PMU_BHND_PMU_H_ */
|
138
sys/dev/bhnd/cores/pmu/bhnd_pmu_core.c
Normal file
138
sys/dev/bhnd/cores/pmu/bhnd_pmu_core.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
#include "bhnd_pmureg.h"
|
||||
#include "bhnd_pmuvar.h"
|
||||
|
||||
/*
|
||||
* PMU core driver.
|
||||
*/
|
||||
|
||||
/* Supported device identifiers */
|
||||
static const struct bhnd_device bhnd_pmucore_devices[] = {
|
||||
BHND_DEVICE(BCM, PMU, NULL, NULL),
|
||||
|
||||
BHND_DEVICE_END
|
||||
};
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_probe(device_t dev)
|
||||
{
|
||||
const struct bhnd_device *id;
|
||||
int error;
|
||||
|
||||
id = bhnd_device_lookup(dev, bhnd_pmucore_devices,
|
||||
sizeof(bhnd_pmucore_devices[0]));
|
||||
if (id == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
/* Delegate to common driver implementation */
|
||||
if ((error = bhnd_pmu_probe(dev)) > 0)
|
||||
return (error);
|
||||
|
||||
bhnd_set_default_core_desc(dev);
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_attach(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
struct bhnd_resource *res;
|
||||
int error;
|
||||
int rid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Allocate register block */
|
||||
rid = 0;
|
||||
res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
|
||||
if (res == NULL) {
|
||||
device_printf(dev, "failed to allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Delegate to common driver implementation */
|
||||
if ((error = bhnd_pmu_attach(dev, res))) {
|
||||
bhnd_release_resource(dev, SYS_RES_MEMORY, rid, res);
|
||||
return (error);
|
||||
}
|
||||
|
||||
sc->rid = rid;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
bhnd_pmu_core_detach(device_t dev)
|
||||
{
|
||||
struct bhnd_pmu_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* Delegate to common driver implementation */
|
||||
if ((error = bhnd_pmu_detach(dev)))
|
||||
return (error);
|
||||
|
||||
bhnd_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t bhnd_pmucore_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, bhnd_pmu_core_probe),
|
||||
DEVMETHOD(device_attach, bhnd_pmu_core_attach),
|
||||
DEVMETHOD(device_detach, bhnd_pmu_core_detach),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(bhnd_pmu, bhnd_pmucore_driver, bhnd_pmucore_methods,
|
||||
sizeof(struct bhnd_pmu_softc), bhnd_pmu_driver);
|
||||
EARLY_DRIVER_MODULE(bhnd_pmu, bhnd, bhnd_pmucore_driver, bhnd_pmu_devclass,
|
||||
NULL, NULL, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
|
||||
|
||||
MODULE_DEPEND(bhnd_pmu_core, bhnd_pmu, 1, 1, 1);
|
||||
MODULE_VERSION(bhnd_pmu_core, 1);
|
130
sys/dev/bhnd/cores/pmu/bhnd_pmu_if.m
Normal file
130
sys/dev/bhnd/cores/pmu/bhnd_pmu_if.m
Normal file
@ -0,0 +1,130 @@
|
||||
#-
|
||||
# Copyright (c) 2016 Landon Fuller <landon@landonf.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 ``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$
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/bhnd/bhnd.h>
|
||||
|
||||
INTERFACE bhnd_pmu;
|
||||
|
||||
#
|
||||
# bhnd(4) PMU interface.
|
||||
#
|
||||
# Provides a common PMU and clock control interface.
|
||||
#
|
||||
|
||||
HEADER {
|
||||
struct bhnd_core_pmu_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enabling routing of @p clock (or faster) to a requesting core.
|
||||
*
|
||||
* @param dev PMU device.
|
||||
* @param pinfo PMU info for requesting core.
|
||||
* @param clock Clock requested.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
*/
|
||||
METHOD int core_req_clock {
|
||||
device_t dev;
|
||||
struct bhnd_core_pmu_info *pinfo;
|
||||
bhnd_clock clock;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Request that @p clocks be powered on behalf of a requesting core.
|
||||
*
|
||||
* This will power any clock sources (XTAL, PLL, etc,) required by
|
||||
* @p clocks and wait until they are ready, discarding any previous
|
||||
* requests from the @p pinfo device.
|
||||
*
|
||||
* Requests from multiple devices are aggregated by the PMU.
|
||||
*
|
||||
* @param dev PMU device.
|
||||
* @param pinfo PMU info for requesting core.
|
||||
* @param clocks Clocks requested.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If an unsupported clock was requested.
|
||||
*/
|
||||
METHOD int core_en_clocks {
|
||||
device_t dev;
|
||||
struct bhnd_core_pmu_info *pinfo;
|
||||
uint32_t clocks;
|
||||
};
|
||||
|
||||
/**
|
||||
* Power up a core-specific external resource.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param pinfo PMU info for requesting core.
|
||||
* @param rsrc The core-specific external resource identifier.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If @p rsrc is not supported by this PMU driver.
|
||||
*/
|
||||
METHOD int core_req_ext_rsrc {
|
||||
device_t dev;
|
||||
struct bhnd_core_pmu_info *pinfo;
|
||||
u_int rsrc;
|
||||
};
|
||||
|
||||
/**
|
||||
* Power down a core-specific external resource.
|
||||
*
|
||||
* @param dev The parent of @p child.
|
||||
* @param pinfo PMU info for requesting core.
|
||||
* @param rsrc The core-specific external resource identifier.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval ENODEV If @p rsrc is not supported by this PMU driver.
|
||||
*/
|
||||
METHOD int core_release_ext_rsrc {
|
||||
device_t dev;
|
||||
struct bhnd_core_pmu_info *pinfo;
|
||||
u_int rsrc;
|
||||
};
|
||||
|
||||
/**
|
||||
* Release all outstanding requests (clocks, resources, etc) associated with
|
||||
* @p pinfo.
|
||||
*
|
||||
* @param dev PMU device.
|
||||
* @param pinfo PMU info for requesting core.
|
||||
*
|
||||
* @retval 0 success
|
||||
* @retval non-zero If releasing PMU request state fails, a
|
||||
* regular unix error code will be returned, and
|
||||
* the request state will be left unmodified.
|
||||
*/
|
||||
METHOD int core_release {
|
||||
device_t dev;
|
||||
struct bhnd_core_pmu_info *pinfo;
|
||||
};
|
147
sys/dev/bhnd/cores/pmu/bhnd_pmu_private.h
Normal file
147
sys/dev/bhnd/cores/pmu/bhnd_pmu_private.h
Normal file
@ -0,0 +1,147 @@
|
||||
/*-
|
||||
* Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
|
||||
* Copyright (C) 2010, Broadcom Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is derived from the hndpmu.h header contributed by Broadcom
|
||||
* to to the Linux staging repository, as well as later revisions of hndpmu.h
|
||||
* distributed with the Asus RT-N16 firmware source code release.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_CORES_PMU_BHND_PMU_PRIVATE_H_
|
||||
#define _BHND_CORES_PMU_BHND_PMU_PRIVATE_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "bhnd_pmuvar.h"
|
||||
|
||||
/* Register I/O */
|
||||
#define BHND_PMU_READ_1(_sc, _reg) bhnd_bus_read_1((_sc)->res, (_reg))
|
||||
#define BHND_PMU_READ_2(_sc, _reg) bhnd_bus_read_2((_sc)->res, (_reg))
|
||||
#define BHND_PMU_READ_4(_sc, _reg) bhnd_bus_read_4((_sc)->res, (_reg))
|
||||
#define BHND_PMU_WRITE_1(_sc, _reg, _val) \
|
||||
bhnd_bus_write_1((_sc)->res, (_reg), (_val))
|
||||
#define BHND_PMU_WRITE_2(_sc, _reg, _val) \
|
||||
bhnd_bus_write_2((_sc)->res, (_reg), (_val))
|
||||
#define BHND_PMU_WRITE_4(_sc, _reg, _val) \
|
||||
bhnd_bus_write_4((_sc)->res, (_reg), (_val))
|
||||
|
||||
#define BHND_PMU_AND_4(_sc, _reg, _val) \
|
||||
BHND_PMU_WRITE_4((_sc), (_reg), \
|
||||
BHND_PMU_READ_4((_sc), (_reg)) & (_val))
|
||||
#define BHND_PMU_OR_4(_sc, _reg, _val) \
|
||||
BHND_PMU_WRITE_4((_sc), (_reg), \
|
||||
BHND_PMU_READ_4((_sc), (_reg)) | (_val))
|
||||
|
||||
/* Indirect register support */
|
||||
#define BHND_PMU_IND_READ(_sc, _src, _reg) \
|
||||
bhnd_pmu_ind_read((_sc), BHND_PMU_ ## _src ## _ADDR, \
|
||||
BHND_PMU_ ## _src ## _DATA, (_reg))
|
||||
#define BHND_PMU_IND_WRITE(_sc, _src, _reg, _val, _mask) \
|
||||
bhnd_pmu_ind_write(sc, BHND_PMU_ ## _src ## _ADDR, \
|
||||
BHND_PMU_ ## _src ## _DATA, (_reg), (_val), (_mask))
|
||||
|
||||
/* Chip Control indirect registers */
|
||||
#define BHND_PMU_CCTRL_READ(_sc, _reg) \
|
||||
BHND_PMU_IND_READ((_sc), CHIPCTL, (_reg))
|
||||
#define BHND_PMU_CCTRL_WRITE(_sc, _reg, _val, _mask) \
|
||||
BHND_PMU_IND_WRITE((_sc), CHIPCTL, (_reg), (_val), (_mask))
|
||||
|
||||
/* Register Control indirect registers */
|
||||
#define BHND_PMU_REGCTRL_READ(_sc, _reg) \
|
||||
BHND_PMU_IND_READ((_sc), REG_CONTROL, (_reg))
|
||||
#define BHND_PMU_REGCTRL_WRITE(_sc, _reg, _val, _mask) \
|
||||
BHND_PMU_IND_WRITE((_sc), REG_CONTROL, (_reg), (_val), (_mask))
|
||||
|
||||
/* PLL Control indirect registers */
|
||||
#define BHND_PMU_PLL_READ(_sc, _reg) \
|
||||
BHND_PMU_IND_READ((_sc), PLL_CONTROL, (_reg))
|
||||
#define BHND_PMU_PLL_WRITE(_sc, _reg, _val, _mask) \
|
||||
BHND_PMU_IND_WRITE((_sc), PLL_CONTROL, (_reg), (_val), (_mask))
|
||||
|
||||
|
||||
/** FVCO frequencies, in Hz */
|
||||
enum {
|
||||
FVCO_880 = 880 * 1000, /**< 880MHz */
|
||||
FVCO_1760 = 1760 * 1000, /**< 1760MHz */
|
||||
FVCO_1440 = 1440 * 1000, /**< 1440MHz */
|
||||
FVCO_960 = 960 * 1000, /**< 960MHz */
|
||||
};
|
||||
|
||||
/** LDO voltage tunables */
|
||||
enum {
|
||||
SET_LDO_VOLTAGE_LDO1 = 1,
|
||||
SET_LDO_VOLTAGE_LDO2 = 2,
|
||||
SET_LDO_VOLTAGE_LDO3 = 3,
|
||||
SET_LDO_VOLTAGE_PAREF = 4,
|
||||
SET_LDO_VOLTAGE_CLDO_PWM = 5,
|
||||
SET_LDO_VOLTAGE_CLDO_BURST = 6,
|
||||
SET_LDO_VOLTAGE_CBUCK_PWM = 7,
|
||||
SET_LDO_VOLTAGE_CBUCK_BURST = 8,
|
||||
SET_LDO_VOLTAGE_LNLDO1 = 9,
|
||||
SET_LDO_VOLTAGE_LNLDO2_SEL = 10,
|
||||
};
|
||||
|
||||
uint32_t bhnd_pmu_ind_read(struct bhnd_pmu_softc *sc, bus_size_t addr,
|
||||
bus_size_t data, uint32_t reg);
|
||||
void bhnd_pmu_ind_write(struct bhnd_pmu_softc *sc, bus_size_t addr,
|
||||
bus_size_t data, uint32_t reg, uint32_t val, uint32_t mask);
|
||||
|
||||
bool bhnd_pmu_wait_clkst(struct bhnd_pmu_softc *sc, device_t dev,
|
||||
struct bhnd_resource *r, bus_size_t clkst_reg,
|
||||
uint32_t value, uint32_t mask);
|
||||
|
||||
int bhnd_pmu_init(struct bhnd_pmu_softc *sc);
|
||||
void bhnd_pmu_pll_init(struct bhnd_pmu_softc *sc, uint32_t xtalfreq);
|
||||
int bhnd_pmu_res_init(struct bhnd_pmu_softc *sc);
|
||||
void bhnd_pmu_swreg_init(struct bhnd_pmu_softc *sc);
|
||||
|
||||
uint32_t bhnd_pmu_force_ilp(struct bhnd_pmu_softc *sc, bool force);
|
||||
|
||||
uint32_t bhnd_pmu_si_clock(struct bhnd_pmu_softc *sc);
|
||||
uint32_t bhnd_pmu_cpu_clock(struct bhnd_pmu_softc *sc);
|
||||
uint32_t bhnd_pmu_mem_clock(struct bhnd_pmu_softc *sc);
|
||||
uint32_t bhnd_pmu_alp_clock(struct bhnd_pmu_softc *sc);
|
||||
uint32_t bhnd_pmu_ilp_clock(struct bhnd_pmu_softc *sc);
|
||||
|
||||
void bhnd_pmu_set_switcher_voltage(struct bhnd_pmu_softc *sc,
|
||||
uint8_t bb_voltage, uint8_t rf_voltage);
|
||||
void bhnd_pmu_set_ldo_voltage(struct bhnd_pmu_softc *sc,
|
||||
uint8_t ldo, uint8_t voltage);
|
||||
int bhnd_pmu_fast_pwrup_delay(struct bhnd_pmu_softc *sc,
|
||||
uint16_t *pwrup_delay);
|
||||
void bhnd_pmu_rcal(struct bhnd_pmu_softc *sc);
|
||||
void bhnd_pmu_spuravoid(struct bhnd_pmu_softc *sc,
|
||||
uint8_t spuravoid);
|
||||
|
||||
bool bhnd_pmu_is_otp_powered(struct bhnd_pmu_softc *sc);
|
||||
uint32_t bhnd_pmu_measure_alpclk(struct bhnd_pmu_softc *sc);
|
||||
|
||||
void bhnd_pmu_radio_enable(struct bhnd_pmu_softc *sc,
|
||||
device_t d11core, bool enable);
|
||||
|
||||
uint32_t bhnd_pmu_waitforclk_on_backplane(struct bhnd_pmu_softc *sc,
|
||||
uint32_t clk, uint32_t delay);
|
||||
|
||||
int bhnd_pmu_otp_power(struct bhnd_pmu_softc *sc, bool on);
|
||||
void bhnd_pmu_sdiod_drive_strength_init(struct bhnd_pmu_softc *sc,
|
||||
uint32_t drivestrength);
|
||||
|
||||
void bhnd_pmu_paref_ldo_enable(struct bhnd_pmu_softc *sc,
|
||||
bool enable);
|
||||
|
||||
#endif /* _BHND_CORES_PMU_BHND_PMU_PRIVATE_H_ */
|
3446
sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c
Normal file
3446
sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c
Normal file
File diff suppressed because it is too large
Load Diff
712
sys/dev/bhnd/cores/pmu/bhnd_pmureg.h
Normal file
712
sys/dev/bhnd/cores/pmu/bhnd_pmureg.h
Normal file
@ -0,0 +1,712 @@
|
||||
/*-
|
||||
* Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
|
||||
* Copyright (c) 2010 Broadcom Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* This file is derived from the sbchipc.h header contributed by Broadcom
|
||||
* to to the Linux staging repository, as well as later revisions of sbchipc.h
|
||||
* distributed with the Asus RT-N16 firmware source code release.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_CORES_PMU_BHND_PMUREG_H_
|
||||
#define _BHND_CORES_PMU_BHND_PMUREG_H_
|
||||
|
||||
#define BHND_PMU_GET_FLAG(_value, _flag) \
|
||||
(((_value) & _flag) != 0)
|
||||
#define BHND_PMU_GET_BITS(_value, _field) \
|
||||
(((_value) & _field ## _MASK) >> _field ## _SHIFT)
|
||||
#define BHND_PMU_SET_BITS(_value, _field) \
|
||||
(((_value) & _field ## _MASK) >> _field ## _SHIFT)
|
||||
|
||||
#define BHND_PMU_ILP_CLOCK 32000 /**< default ILP freq */
|
||||
#define BHND_PMU_ALP_CLOCK 20000000 /**< default ALP freq */
|
||||
#define BHND_PMU_HT_CLOCK 80000000 /**< default HT freq */
|
||||
|
||||
/**
|
||||
* Common per-core clock control/status register available on PMU-equipped
|
||||
* devices.
|
||||
*/
|
||||
#define BHND_CLK_CTL_ST 0x1e0 /**< clock control and status */
|
||||
|
||||
/*
|
||||
* BHND_CLK_CTL_ST register
|
||||
*
|
||||
* Clock Mode Name Description
|
||||
* High Throughput (HT) Full bandwidth, low latency. Generally supplied
|
||||
* from PLL.
|
||||
* Active Low Power (ALP) Register access, low speed DMA.
|
||||
* Idle Low Power (ILP) No interconnect activity, or if long latency
|
||||
* is permitted.
|
||||
*/
|
||||
#define BHND_CCS_FORCEALP 0x00000001 /**< force ALP request */
|
||||
#define BHND_CCS_FORCEHT 0x00000002 /**< force HT request */
|
||||
#define BHND_CCS_FORCEILP 0x00000004 /**< force ILP request */
|
||||
#define BHND_CCS_FORCE_MASK 0x0000000F
|
||||
|
||||
#define BHND_CCS_ALPAREQ 0x00000008 /**< ALP Avail Request */
|
||||
#define BHND_CCS_HTAREQ 0x00000010 /**< HT Avail Request */
|
||||
#define BHND_CCS_AREQ_MASK 0x00000018
|
||||
|
||||
#define BHND_CCS_FORCEHWREQOFF 0x00000020 /**< Force HW Clock Request Off */
|
||||
|
||||
#define BHND_CCS_ERSRC_REQ_MASK 0x00000700 /**< external resource requests */
|
||||
#define BHND_CCS_ERSRC_REQ_SHIFT 8
|
||||
#define BHND_CCS_ERSRC_MAX 2 /**< maximum ERSRC value (corresponding to bits 0-2) */
|
||||
|
||||
#define BHND_CCS_ALPAVAIL 0x00010000 /**< ALP is available */
|
||||
#define BHND_CCS_HTAVAIL 0x00020000 /**< HT is available */
|
||||
#define BHND_CCS_AVAIL_MASK 0x00030000
|
||||
|
||||
#define BHND_CCS_BP_ON_APL 0x00040000 /**< RO: Backplane is running on ALP clock */
|
||||
#define BHND_CCS_BP_ON_HT 0x00080000 /**< RO: Backplane is running on HT clock */
|
||||
#define BHND_CCS_ERSRC_STS_MASK 0x07000000 /**< external resource status */
|
||||
#define BHND_CCS_ERSRC_STS_SHIFT 24
|
||||
|
||||
#define BHND_CCS0_HTAVAIL 0x00010000 /**< HT avail in chipc and pcmcia on 4328a0 */
|
||||
#define BHND_CCS0_ALPAVAIL 0x00020000 /**< ALP avail in chipc and pcmcia on 4328a0 */
|
||||
|
||||
/* PMU registers */
|
||||
#define BHND_PMU_CTRL 0x600
|
||||
#define BHND_PMU_CTRL_ILP_DIV_MASK 0xffff0000
|
||||
#define BHND_PMU_CTRL_ILP_DIV_SHIFT 16
|
||||
#define BHND_PMU_CTRL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */
|
||||
#define BHND_PMU_CTRL_NOILP_ON_WAIT 0x00000200 /* rev 1 */
|
||||
#define BHND_PMU_CTRL_HT_REQ_EN 0x00000100
|
||||
#define BHND_PMU_CTRL_ALP_REQ_EN 0x00000080
|
||||
#define BHND_PMU_CTRL_XTALFREQ_MASK 0x0000007c
|
||||
#define BHND_PMU_CTRL_XTALFREQ_SHIFT 2
|
||||
#define BHND_PMU_CTRL_ILP_DIV_EN 0x00000002
|
||||
#define BHND_PMU_CTRL_LPO_SEL 0x00000001
|
||||
#define BHND_PMU_CAP 0x604
|
||||
#define BHND_PMU_CAP_REV_MASK 0x000000ff
|
||||
#define BHND_PMU_CAP_REV_SHIFT 0
|
||||
#define BHND_PMU_CAP_RC_MASK 0x00001f00
|
||||
#define BHND_PMU_CAP_RC_SHIFT 8
|
||||
#define BHND_PMU_CAP_RC_MAX \
|
||||
(BHND_PMU_CAP_RC_MASK >> BHND_PMU_CAP_RC_SHIFT)
|
||||
#define BHND_PMU_CAP_TC_MASK 0x0001e000
|
||||
#define BHND_PMU_CAP_TC_SHIFT 13
|
||||
#define BHND_PMU_CAP_PC_MASK 0x001e0000
|
||||
#define BHND_PMU_CAP_PC_SHIFT 17
|
||||
#define BHND_PMU_CAP_VC_MASK 0x01e00000
|
||||
#define BHND_PMU_CAP_VC_SHIFT 21
|
||||
#define BHND_PMU_CAP_CC_MASK 0x1e000000
|
||||
#define BHND_PMU_CAP_CC_SHIFT 25
|
||||
#define BHND_PMU_CAP5_PC_MASK 0x003e0000 /* PMU corerev >= 5 */
|
||||
#define BHND_PMU_CAP5_PC_SHIFT 17
|
||||
#define BHND_PMU_CAP5_VC_MASK 0x07c00000
|
||||
#define BHND_PMU_CAP5_VC_SHIFT 22
|
||||
#define BHND_PMU_CAP5_CC_MASK 0xf8000000
|
||||
#define BHND_PMU_CAP5_CC_SHIFT 27
|
||||
#define BHND_PMU_ST 0x608
|
||||
#define BHND_PMU_ST_EXTLPOAVAIL 0x0100
|
||||
#define BHND_PMU_ST_WDRESET 0x0080
|
||||
#define BHND_PMU_ST_INTPEND 0x0040
|
||||
#define BHND_PMU_ST_SBCLKST 0x0030
|
||||
#define BHND_PMU_ST_SBCLKST_ILP 0x0010
|
||||
#define BHND_PMU_ST_SBCLKST_ALP 0x0020
|
||||
#define BHND_PMU_ST_SBCLKST_HT 0x0030
|
||||
#define BHND_PMU_ST_ALPAVAIL 0x0008
|
||||
#define BHND_PMU_ST_HTAVAIL 0x0004
|
||||
#define BHND_PMU_ST_RESINIT 0x0003
|
||||
#define BHND_PMU_RES_STATE 0x60c
|
||||
#define BHND_PMU_RES_PENDING 0x610
|
||||
#define BHND_PMU_TIMER 0x614
|
||||
#define BHND_PMU_MIN_RES_MASK 0x618
|
||||
#define BHND_PMU_MAX_RES_MASK 0x61c
|
||||
#define BHND_PMU_RES_TABLE_SEL 0x620
|
||||
#define BHND_PMU_RES_DEP_MASK 0x624
|
||||
#define BHND_PMU_RES_UPDN_TIMER 0x628
|
||||
#define BHND_PMU_RES_UPDN_UPTME_MASK 0xFF
|
||||
#define BHND_PMU_RES_UPDN_UPTME_SHIFT 8
|
||||
#define BHND_PMU_RES_TIMER 0x62C
|
||||
#define BHND_PMU_CLKSTRETCH 0x630
|
||||
#define BHND_PMU_CSTRETCH_HT 0xffff0000
|
||||
#define BHND_PMU_CSTRETCH_ALP 0x0000ffff
|
||||
#define BHND_PMU_WATCHDOG 0x634
|
||||
#define BHND_PMU_GPIOSEL 0x638 /* pmu rev >= 1 ? */
|
||||
#define BHND_PMU_GPIOEN 0x63C /* pmu rev >= 1 ? */
|
||||
#define BHND_PMU_RES_REQ_TIMER_SEL 0x640
|
||||
#define BHND_PMU_RES_REQ_TIMER 0x644
|
||||
#define BHND_PMU_RRQT_TIME_MASK 0x03ff
|
||||
#define BHND_PMU_RRQT_INTEN 0x0400
|
||||
#define BHND_PMU_RRQT_REQ_ACTIVE 0x0800
|
||||
#define BHND_PMU_RRQT_ALP_REQ 0x1000
|
||||
#define BHND_PMU_RRQT_HT_REQ 0x2000
|
||||
#define BHND_PMU_RES_REQ_MASK 0x648
|
||||
#define BHND_PMU_CHIPCTL_ADDR 0x650
|
||||
#define BHND_PMU_CHIPCTL_DATA 0x654
|
||||
#define BHND_PMU_REG_CONTROL_ADDR 0x658
|
||||
#define BHND_PMU_REG_CONTROL_DATA 0x65C
|
||||
#define BHND_PMU_PLL_CONTROL_ADDR 0x660
|
||||
#define BHND_PMU_PLL_CONTROL_DATA 0x664
|
||||
#define BHND_PMU_STRAPOPT 0x668 /* chipc rev >= 28 */
|
||||
#define BHND_PMU_XTALFREQ 0x66C /* pmu rev >= 10 */
|
||||
|
||||
/* PMU resource bit position */
|
||||
#define BHND_PMURES_BIT(bit) (1 << (bit))
|
||||
|
||||
/* PMU resource number limit */
|
||||
#define BHND_PMU_RESNUM_MAX 30
|
||||
|
||||
/* PMU chip control0 register */
|
||||
#define BHND_PMU_CHIPCTL0 0
|
||||
|
||||
/* PMU chip control1 register */
|
||||
#define BHND_PMU_CHIPCTL1 1
|
||||
#define BHND_PMU_CC1_RXC_DLL_BYPASS 0x00010000
|
||||
|
||||
#define BHND_PMU_CC1_IF_TYPE_MASK 0x00000030
|
||||
#define BHND_PMU_CC1_IF_TYPE_RMII 0x00000000
|
||||
#define BHND_PMU_CC1_IF_TYPE_MII 0x00000010
|
||||
#define BHND_PMU_CC1_IF_TYPE_RGMII 0x00000020
|
||||
|
||||
#define BHND_PMU_CC1_SW_TYPE_MASK 0x000000c0
|
||||
#define BHND_PMU_CC1_SW_TYPE_EPHY 0x00000000
|
||||
#define BHND_PMU_CC1_SW_TYPE_EPHYMII 0x00000040
|
||||
#define BHND_PMU_CC1_SW_TYPE_EPHYRMII 0x00000080
|
||||
#define BHND_PMU_CC1_SW_TYPE_RGMII 0x000000c0
|
||||
|
||||
/* PMU corerev and chip specific PLL controls.
|
||||
* PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
|
||||
* to differentiate different PLLs controlled by the same PMU rev.
|
||||
*/
|
||||
|
||||
/* pllcontrol registers */
|
||||
/* PDIV, div_phy, div_arm, div_adc, dith_sel, ioff, kpd_scale, lsb_sel, mash_sel, lf_c & lf_r */
|
||||
#define BHND_PMU0_PLL0_PLLCTL0 0
|
||||
#define BHND_PMU0_PLL0_PC0_PDIV_MASK 1
|
||||
#define BHND_PMU0_PLL0_PC0_PDIV_FREQ 25000
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_SHIFT 3
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_BASE 8
|
||||
|
||||
/* PC0_DIV_ARM for PLLOUT_ARM */
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_110MHZ 0
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_88MHZ 2
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 /* Default */
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6
|
||||
#define BHND_PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7
|
||||
|
||||
/* Wildcard base, stop_mod, en_lf_tp, en_cal & lf_r2 */
|
||||
#define BHND_PMU0_PLL0_PLLCTL1 1
|
||||
#define BHND_PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000
|
||||
#define BHND_PMU0_PLL0_PC1_WILD_INT_SHIFT 28
|
||||
#define BHND_PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00
|
||||
#define BHND_PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8
|
||||
#define BHND_PMU0_PLL0_PC1_STOP_MOD 0x00000040
|
||||
|
||||
/* Wildcard base, vco_calvar, vco_swc, vco_var_selref, vso_ical & vco_sel_avdd */
|
||||
#define BHND_PMU0_PLL0_PLLCTL2 2
|
||||
#define BHND_PMU0_PLL0_PC2_WILD_INT_MASK 0xf
|
||||
#define BHND_PMU0_PLL0_PC2_WILD_INT_SHIFT 4
|
||||
|
||||
/* pllcontrol registers */
|
||||
/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
|
||||
#define BHND_PMU1_PLL0_PLLCTL0 0
|
||||
#define BHND_PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000
|
||||
#define BHND_PMU1_PLL0_PC0_P1DIV_SHIFT 20
|
||||
#define BHND_PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000
|
||||
#define BHND_PMU1_PLL0_PC0_P2DIV_SHIFT 24
|
||||
#define BHND_PMU1_PLL0_PC0_BYPASS_SDMOD_MASK 0x10000000
|
||||
#define BHND_PMU1_PLL0_PC0_BYPASS_SDMOD_SHIFT 28
|
||||
|
||||
/* m<x>div */
|
||||
#define BHND_PMU1_PLL0_PLLCTL1 1
|
||||
#define BHND_PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff
|
||||
#define BHND_PMU1_PLL0_PC1_M1DIV_SHIFT 0
|
||||
#define BHND_PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00
|
||||
#define BHND_PMU1_PLL0_PC1_M2DIV_SHIFT 8
|
||||
#define BHND_PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000
|
||||
#define BHND_PMU1_PLL0_PC1_M3DIV_SHIFT 16
|
||||
#define BHND_PMU1_PLL0_PC1_M4DIV_MASK 0xff000000
|
||||
#define BHND_PMU1_PLL0_PC1_M4DIV_SHIFT 24
|
||||
|
||||
#define BHND_PMU_DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8
|
||||
#define BHND_PMU_DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << BHND_PMU_DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
|
||||
#define BHND_PMU_DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << BHND_PMU_DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT)
|
||||
|
||||
/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
|
||||
#define BHND_PMU1_PLL0_PLLCTL2 2
|
||||
#define BHND_PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff
|
||||
#define BHND_PMU1_PLL0_PC2_M5DIV_SHIFT 0
|
||||
#define BHND_PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00
|
||||
#define BHND_PMU1_PLL0_PC2_M6DIV_SHIFT 8
|
||||
#define BHND_PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000
|
||||
#define BHND_PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17
|
||||
#define BHND_PMU1_PLL0_PC2_NDIV_MODE_INT 0
|
||||
#define BHND_PMU1_PLL0_PC2_NDIV_MODE_MASH 1
|
||||
#define BHND_PMU1_PLL0_PC2_NDIV_MODE_MFB 2 /* recommended for 4319 */
|
||||
#define BHND_PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000
|
||||
#define BHND_PMU1_PLL0_PC2_NDIV_INT_SHIFT 20
|
||||
|
||||
/* ndiv_frac */
|
||||
#define BHND_PMU1_PLL0_PLLCTL3 3
|
||||
#define BHND_PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff
|
||||
#define BHND_PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0
|
||||
|
||||
/* pll_ctrl */
|
||||
#define BHND_PMU1_PLL0_PLLCTL4 4
|
||||
#define BHND_PMU1_PLL0_PC4_KVCO_XS_MASK 0x38000000
|
||||
#define BHND_PMU1_PLL0_PC4_KVCO_XS_SHIFT 27
|
||||
|
||||
/* pll_ctrl, vco_rng, clkdrive_ch<x> */
|
||||
#define BHND_PMU1_PLL0_PLLCTL5 5
|
||||
#define BHND_PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00
|
||||
#define BHND_PMU1_PLL0_PC5_CLK_DRV_SHIFT 8
|
||||
#define BHND_PMU1_PLL0_PC5_PLL_CTRL_37_32_MASK 0x0000003f
|
||||
#define BHND_PMU1_PLL0_PC5_PLL_CTRL_37_32_SHIFT 0
|
||||
#define BHND_PMU1_PLL0_PC5_VCO_RNG_MASK 0x000000C0
|
||||
#define BHND_PMU1_PLL0_PC5_VCO_RNG_SHIFT 6
|
||||
|
||||
/* PMU rev 2 control words */
|
||||
#define BHND_PMU2_PHY_PLL_PLLCTL 4
|
||||
#define BHND_PMU2_SI_PLL_PLLCTL 10
|
||||
|
||||
/* PMU rev 2 */
|
||||
/* pllcontrol registers */
|
||||
/* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
|
||||
#define BHND_PMU2_PLL_PLLCTL0 0
|
||||
#define BHND_PMU2_PLL_PC0_P1DIV_MASK 0x00f00000
|
||||
#define BHND_PMU2_PLL_PC0_P1DIV_SHIFT 20
|
||||
#define BHND_PMU2_PLL_PC0_P2DIV_MASK 0x0f000000
|
||||
#define BHND_PMU2_PLL_PC0_P2DIV_SHIFT 24
|
||||
|
||||
/* m<x>div */
|
||||
#define BHND_PMU2_PLL_PLLCTL1 1
|
||||
#define BHND_PMU2_PLL_PC1_M1DIV_MASK 0x000000ff
|
||||
#define BHND_PMU2_PLL_PC1_M1DIV_SHIFT 0
|
||||
#define BHND_PMU2_PLL_PC1_M2DIV_MASK 0x0000ff00
|
||||
#define BHND_PMU2_PLL_PC1_M2DIV_SHIFT 8
|
||||
#define BHND_PMU2_PLL_PC1_M3DIV_MASK 0x00ff0000
|
||||
#define BHND_PMU2_PLL_PC1_M3DIV_SHIFT 16
|
||||
#define BHND_PMU2_PLL_PC1_M4DIV_MASK 0xff000000
|
||||
#define BHND_PMU2_PLL_PC1_M4DIV_SHIFT 24
|
||||
|
||||
/* m<x>div, ndiv_dither_mfb, ndiv_mode, ndiv_int */
|
||||
#define BHND_PMU2_PLL_PLLCTL2 2
|
||||
#define BHND_PMU2_PLL_PC2_M5DIV_MASK 0x000000ff
|
||||
#define BHND_PMU2_PLL_PC2_M5DIV_SHIFT 0
|
||||
#define BHND_PMU2_PLL_PC2_M6DIV_MASK 0x0000ff00
|
||||
#define BHND_PMU2_PLL_PC2_M6DIV_SHIFT 8
|
||||
#define BHND_PMU2_PLL_PC2_NDIV_MODE_MASK 0x000e0000
|
||||
#define BHND_PMU2_PLL_PC2_NDIV_MODE_SHIFT 17
|
||||
#define BHND_PMU2_PLL_PC2_NDIV_INT_MASK 0x1ff00000
|
||||
#define BHND_PMU2_PLL_PC2_NDIV_INT_SHIFT 20
|
||||
|
||||
/* ndiv_frac */
|
||||
#define BHND_PMU2_PLL_PLLCTL3 3
|
||||
#define BHND_PMU2_PLL_PC3_NDIV_FRAC_MASK 0x00ffffff
|
||||
#define BHND_PMU2_PLL_PC3_NDIV_FRAC_SHIFT 0
|
||||
|
||||
/* pll_ctrl */
|
||||
#define BHND_PMU2_PLL_PLLCTL4 4
|
||||
|
||||
/* pll_ctrl, vco_rng, clkdrive_ch<x> */
|
||||
#define BHND_PMU2_PLL_PLLCTL5 5
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH1_MASK 0x00000f00
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT 8
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH2_MASK 0x0000f000
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT 12
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH3_MASK 0x000f0000
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT 16
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH4_MASK 0x00f00000
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT 20
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH5_MASK 0x0f000000
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH5_SHIFT 24
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH6_MASK 0xf0000000
|
||||
#define BHND_PMU2_PLL_PC5_CLKDRIVE_CH6_SHIFT 28
|
||||
|
||||
/* PMU rev 5 (& 6) */
|
||||
#define BHND_PMU5_PLL_P1P2_OFF 0
|
||||
#define BHND_PMU5_PLL_P1_MASK 0x0f000000
|
||||
#define BHND_PMU5_PLL_P1_SHIFT 24
|
||||
#define BHND_PMU5_PLL_P2_MASK 0x00f00000
|
||||
#define BHND_PMU5_PLL_P2_SHIFT 20
|
||||
#define BHND_PMU5_PLL_M14_OFF 1
|
||||
#define BHND_PMU5_PLL_MDIV_MASK 0x000000ff
|
||||
#define BHND_PMU5_PLL_MDIV_WIDTH 8
|
||||
#define BHND_PMU5_PLL_NM5_OFF 2
|
||||
#define BHND_PMU5_PLL_NDIV_MASK 0xfff00000
|
||||
#define BHND_PMU5_PLL_NDIV_SHIFT 20
|
||||
#define BHND_PMU5_PLL_NDIV_MODE_MASK 0x000e0000
|
||||
#define BHND_PMU5_PLL_NDIV_MODE_SHIFT 17
|
||||
#define BHND_PMU5_PLL_FMAB_OFF 3
|
||||
#define BHND_PMU5_PLL_MRAT_MASK 0xf0000000
|
||||
#define BHND_PMU5_PLL_MRAT_SHIFT 28
|
||||
#define BHND_PMU5_PLL_ABRAT_MASK 0x08000000
|
||||
#define BHND_PMU5_PLL_ABRAT_SHIFT 27
|
||||
#define BHND_PMU5_PLL_FDIV_MASK 0x07ffffff
|
||||
#define BHND_PMU5_PLL_PLLCTL_OFF 4
|
||||
#define BHND_PMU5_PLL_PCHI_OFF 5
|
||||
#define BHND_PMU5_PLL_PCHI_MASK 0x0000003f
|
||||
|
||||
/* pmu XtalFreqRatio */
|
||||
#define BHND_PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
|
||||
#define BHND_PMU_XTALFREQ_REG_ILPCTR_SHIFT 0
|
||||
#define BHND_PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000
|
||||
#define BHND_PMU_XTALFREQ_REG_MEASURE_SHIFT 31
|
||||
|
||||
|
||||
/* Divider allocation in 4716/47162/5356/5357 */
|
||||
#define BHND_PMU5_MAINPLL_CPU 1
|
||||
#define BHND_PMU5_MAINPLL_MEM 2
|
||||
#define BHND_PMU5_MAINPLL_SI 3
|
||||
|
||||
#define BHND_PMU7_PLL_PLLCTL7 7
|
||||
#define BHND_PMU7_PLL_PLLCTL8 8
|
||||
#define BHND_PMU7_PLL_PLLCTL11 11
|
||||
|
||||
|
||||
/* PLL usage in 4716/47162 */
|
||||
#define BHND_PMU4716_MAINPLL_PLL0 12
|
||||
|
||||
|
||||
/* PLL usage in 5356/5357 */
|
||||
#define BHND_PMU5356_MAINPLL_PLL0 0
|
||||
#define BHND_PMU5357_MAINPLL_PLL0 0
|
||||
|
||||
|
||||
/* 4716/47162 PMU resources */
|
||||
#define BHND_PMU_RES4716_PROC_PLL_ON 0x00000040
|
||||
#define BHND_PMU_RES4716_PROC_HT_AVAIL 0x00000080
|
||||
|
||||
/* 4716/4717/4718 chip-specific CHIPCTRL PMU register bits */
|
||||
#define BHND_PMU_CCTRL471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared with pflash */
|
||||
|
||||
|
||||
/* 5354 PMU resources */
|
||||
#define BHND_PMU_RES5354_EXT_SWITCHER_PWM 0 /* 0x00001 */
|
||||
#define BHND_PMU_RES5354_BB_SWITCHER_PWM 1 /* 0x00002 */
|
||||
#define BHND_PMU_RES5354_BB_SWITCHER_BURST 2 /* 0x00004 */
|
||||
#define BHND_PMU_RES5354_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */
|
||||
#define BHND_PMU_RES5354_ILP_REQUEST 4 /* 0x00010 */
|
||||
#define BHND_PMU_RES5354_RADIO_SWITCHER_PWM 5 /* 0x00020 */
|
||||
#define BHND_PMU_RES5354_RADIO_SWITCHER_BURST 6 /* 0x00040 */
|
||||
#define BHND_PMU_RES5354_ROM_SWITCH 7 /* 0x00080 */
|
||||
#define BHND_PMU_RES5354_PA_REF_LDO 8 /* 0x00100 */
|
||||
#define BHND_PMU_RES5354_RADIO_LDO 9 /* 0x00200 */
|
||||
#define BHND_PMU_RES5354_AFE_LDO 10 /* 0x00400 */
|
||||
#define BHND_PMU_RES5354_PLL_LDO 11 /* 0x00800 */
|
||||
#define BHND_PMU_RES5354_BG_FILTBYP 12 /* 0x01000 */
|
||||
#define BHND_PMU_RES5354_TX_FILTBYP 13 /* 0x02000 */
|
||||
#define BHND_PMU_RES5354_RX_FILTBYP 14 /* 0x04000 */
|
||||
#define BHND_PMU_RES5354_XTAL_PU 15 /* 0x08000 */
|
||||
#define BHND_PMU_RES5354_XTAL_EN 16 /* 0x10000 */
|
||||
#define BHND_PMU_RES5354_BB_PLL_FILTBYP 17 /* 0x20000 */
|
||||
#define BHND_PMU_RES5354_RF_PLL_FILTBYP 18 /* 0x40000 */
|
||||
#define BHND_PMU_RES5354_BB_PLL_PU 19 /* 0x80000 */
|
||||
|
||||
|
||||
/* 5357 chip-specific CHIPCTRL register bits */
|
||||
#define BHND_PMU_CCTRL5357_EXTPA (1<<14) /* extPA in CHIPCTL1, bit 14 */
|
||||
#define BHND_PMU_CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in CHIPCTL1, bit 15 */
|
||||
|
||||
|
||||
/* 4328 PMU resources */
|
||||
#define BHND_PMU_RES4328_EXT_SWITCHER_PWM 0 /* 0x00001 */
|
||||
#define BHND_PMU_RES4328_BB_SWITCHER_PWM 1 /* 0x00002 */
|
||||
#define BHND_PMU_RES4328_BB_SWITCHER_BURST 2 /* 0x00004 */
|
||||
#define BHND_PMU_RES4328_BB_EXT_SWITCHER_BURST 3 /* 0x00008 */
|
||||
#define BHND_PMU_RES4328_ILP_REQUEST 4 /* 0x00010 */
|
||||
#define BHND_PMU_RES4328_RADIO_SWITCHER_PWM 5 /* 0x00020 */
|
||||
#define BHND_PMU_RES4328_RADIO_SWITCHER_BURST 6 /* 0x00040 */
|
||||
#define BHND_PMU_RES4328_ROM_SWITCH 7 /* 0x00080 */
|
||||
#define BHND_PMU_RES4328_PA_REF_LDO 8 /* 0x00100 */
|
||||
#define BHND_PMU_RES4328_RADIO_LDO 9 /* 0x00200 */
|
||||
#define BHND_PMU_RES4328_AFE_LDO 10 /* 0x00400 */
|
||||
#define BHND_PMU_RES4328_PLL_LDO 11 /* 0x00800 */
|
||||
#define BHND_PMU_RES4328_BG_FILTBYP 12 /* 0x01000 */
|
||||
#define BHND_PMU_RES4328_TX_FILTBYP 13 /* 0x02000 */
|
||||
#define BHND_PMU_RES4328_RX_FILTBYP 14 /* 0x04000 */
|
||||
#define BHND_PMU_RES4328_XTAL_PU 15 /* 0x08000 */
|
||||
#define BHND_PMU_RES4328_XTAL_EN 16 /* 0x10000 */
|
||||
#define BHND_PMU_RES4328_BB_PLL_FILTBYP 17 /* 0x20000 */
|
||||
#define BHND_PMU_RES4328_RF_PLL_FILTBYP 18 /* 0x40000 */
|
||||
#define BHND_PMU_RES4328_BB_PLL_PU 19 /* 0x80000 */
|
||||
|
||||
|
||||
/* 4325 A0/A1 PMU resources */
|
||||
#define BHND_PMU_RES4325_BUCK_BOOST_BURST 0 /* 0x00000001 */
|
||||
#define BHND_PMU_RES4325_CBUCK_BURST 1 /* 0x00000002 */
|
||||
#define BHND_PMU_RES4325_CBUCK_PWM 2 /* 0x00000004 */
|
||||
#define BHND_PMU_RES4325_CLDO_CBUCK_BURST 3 /* 0x00000008 */
|
||||
#define BHND_PMU_RES4325_CLDO_CBUCK_PWM 4 /* 0x00000010 */
|
||||
#define BHND_PMU_RES4325_BUCK_BOOST_PWM 5 /* 0x00000020 */
|
||||
#define BHND_PMU_RES4325_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define BHND_PMU_RES4325_ABUCK_BURST 7 /* 0x00000080 */
|
||||
#define BHND_PMU_RES4325_ABUCK_PWM 8 /* 0x00000100 */
|
||||
#define BHND_PMU_RES4325_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define BHND_PMU_RES4325_OTP_PU 10 /* 0x00000400 */
|
||||
#define BHND_PMU_RES4325_LNLDO3_PU 11 /* 0x00000800 */
|
||||
#define BHND_PMU_RES4325_LNLDO4_PU 12 /* 0x00001000 */
|
||||
#define BHND_PMU_RES4325_XTAL_PU 13 /* 0x00002000 */
|
||||
#define BHND_PMU_RES4325_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define BHND_PMU_RES4325_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define BHND_PMU_RES4325_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define BHND_PMU_RES4325_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define BHND_PMU_RES4325_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define BHND_PMU_RES4325_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define BHND_PMU_RES4325_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define BHND_PMU_RES4325_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
|
||||
/* 4325 B0/C0 PMU resources */
|
||||
#define BHND_PMU_RES4325B0_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define BHND_PMU_RES4325B0_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define BHND_PMU_RES4325B0_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define BHND_PMU_RES4325B0_CLDO_PU 4 /* 0x00000010 */
|
||||
|
||||
|
||||
/* 4325 C1 PMU resources */
|
||||
#define BHND_PMU_RES4325C1_LNLDO2_PU 12 /* 0x00001000 */
|
||||
|
||||
|
||||
/* 4325 PMU resources */
|
||||
#define BHND_PMU_RES4329_RESERVED0 0 /* 0x00000001 */
|
||||
#define BHND_PMU_RES4329_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define BHND_PMU_RES4329_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define BHND_PMU_RES4329_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define BHND_PMU_RES4329_CLDO_PU 4 /* 0x00000010 */
|
||||
#define BHND_PMU_RES4329_PALDO_PU 5 /* 0x00000020 */
|
||||
#define BHND_PMU_RES4329_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define BHND_PMU_RES4329_RESERVED7 7 /* 0x00000080 */
|
||||
#define BHND_PMU_RES4329_RESERVED8 8 /* 0x00000100 */
|
||||
#define BHND_PMU_RES4329_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define BHND_PMU_RES4329_OTP_PU 10 /* 0x00000400 */
|
||||
#define BHND_PMU_RES4329_RESERVED11 11 /* 0x00000800 */
|
||||
#define BHND_PMU_RES4329_LNLDO2_PU 12 /* 0x00001000 */
|
||||
#define BHND_PMU_RES4329_XTAL_PU 13 /* 0x00002000 */
|
||||
#define BHND_PMU_RES4329_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define BHND_PMU_RES4329_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define BHND_PMU_RES4329_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define BHND_PMU_RES4329_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define BHND_PMU_RES4329_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define BHND_PMU_RES4329_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define BHND_PMU_RES4329_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define BHND_PMU_RES4329_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
|
||||
/* 4312 PMU resources (all PMU chips with little memory constraint) */
|
||||
#define BHND_PMU_RES4312_SWITCHER_BURST 0 /* 0x00000001 */
|
||||
#define BHND_PMU_RES4312_SWITCHER_PWM 1 /* 0x00000002 */
|
||||
#define BHND_PMU_RES4312_PA_REF_LDO 2 /* 0x00000004 */
|
||||
#define BHND_PMU_RES4312_CORE_LDO_BURST 3 /* 0x00000008 */
|
||||
#define BHND_PMU_RES4312_CORE_LDO_PWM 4 /* 0x00000010 */
|
||||
#define BHND_PMU_RES4312_RADIO_LDO 5 /* 0x00000020 */
|
||||
#define BHND_PMU_RES4312_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define BHND_PMU_RES4312_BG_FILTBYP 7 /* 0x00000080 */
|
||||
#define BHND_PMU_RES4312_TX_FILTBYP 8 /* 0x00000100 */
|
||||
#define BHND_PMU_RES4312_RX_FILTBYP 9 /* 0x00000200 */
|
||||
#define BHND_PMU_RES4312_XTAL_PU 10 /* 0x00000400 */
|
||||
#define BHND_PMU_RES4312_ALP_AVAIL 11 /* 0x00000800 */
|
||||
#define BHND_PMU_RES4312_BB_PLL_FILTBYP 12 /* 0x00001000 */
|
||||
#define BHND_PMU_RES4312_RF_PLL_FILTBYP 13 /* 0x00002000 */
|
||||
#define BHND_PMU_RES4312_HT_AVAIL 14 /* 0x00004000 */
|
||||
|
||||
|
||||
/* 4322 PMU resources */
|
||||
#define BHND_PMU_RES4322_RF_LDO 0
|
||||
#define BHND_PMU_RES4322_ILP_REQUEST 1
|
||||
#define BHND_PMU_RES4322_XTAL_PU 2
|
||||
#define BHND_PMU_RES4322_ALP_AVAIL 3
|
||||
#define BHND_PMU_RES4322_SI_PLL_ON 4
|
||||
#define BHND_PMU_RES4322_HT_SI_AVAIL 5
|
||||
#define BHND_PMU_RES4322_PHY_PLL_ON 6
|
||||
#define BHND_PMU_RES4322_HT_PHY_AVAIL 7
|
||||
#define BHND_PMU_RES4322_OTP_PU 8
|
||||
|
||||
|
||||
/* 43224 chip-specific CHIPCTRL register bits */
|
||||
#define BHND_PMU_CCTRL_43224_GPIO_TOGGLE 0x8000
|
||||
#define BHND_PMU_CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */
|
||||
#define BHND_PMU_CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */
|
||||
|
||||
|
||||
/* 43236 PMU resources */
|
||||
#define BHND_PMU_RES43236_REGULATOR 0
|
||||
#define BHND_PMU_RES43236_ILP_REQUEST 1
|
||||
#define BHND_PMU_RES43236_XTAL_PU 2
|
||||
#define BHND_PMU_RES43236_ALP_AVAIL 3
|
||||
#define BHND_PMU_RES43236_SI_PLL_ON 4
|
||||
#define BHND_PMU_RES43236_HT_SI_AVAIL 5
|
||||
|
||||
/* 43236 chip-specific CHIPCTRL register bits */
|
||||
#define BHND_PMU_CCTRL43236_BT_COEXIST (1<<0) /* 0 disable */
|
||||
#define BHND_PMU_CCTRL43236_SECI (1<<1) /* 0 SECI is disabled (JATG functional) */
|
||||
#define BHND_PMU_CCTRL43236_EXT_LNA (1<<2) /* 0 disable */
|
||||
#define BHND_PMU_CCTRL43236_ANT_MUX_2o3 (1<<3) /* 2o3 mux, chipcontrol bit 3 */
|
||||
#define BHND_PMU_CCTRL43236_GSIO (1<<4) /* 0 disable */
|
||||
|
||||
|
||||
/* 4331 PMU resources */
|
||||
#define BHND_PMU_RES4331_REGULATOR 0
|
||||
#define BHND_PMU_RES4331_ILP_REQUEST 1
|
||||
#define BHND_PMU_RES4331_XTAL_PU 2
|
||||
#define BHND_PMU_RES4331_ALP_AVAIL 3
|
||||
#define BHND_PMU_RES4331_SI_PLL_ON 4
|
||||
#define BHND_PMU_RES4331_HT_SI_AVAIL 5
|
||||
|
||||
/* 4315 PMU resources */
|
||||
#define BHND_PMU_RES4315_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define BHND_PMU_RES4315_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define BHND_PMU_RES4315_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define BHND_PMU_RES4315_CLDO_PU 4 /* 0x00000010 */
|
||||
#define BHND_PMU_RES4315_PALDO_PU 5 /* 0x00000020 */
|
||||
#define BHND_PMU_RES4315_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define BHND_PMU_RES4315_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define BHND_PMU_RES4315_OTP_PU 10 /* 0x00000400 */
|
||||
#define BHND_PMU_RES4315_LNLDO2_PU 12 /* 0x00001000 */
|
||||
#define BHND_PMU_RES4315_XTAL_PU 13 /* 0x00002000 */
|
||||
#define BHND_PMU_RES4315_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define BHND_PMU_RES4315_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define BHND_PMU_RES4315_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define BHND_PMU_RES4315_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define BHND_PMU_RES4315_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define BHND_PMU_RES4315_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define BHND_PMU_RES4315_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define BHND_PMU_RES4315_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4319 PMU resources */
|
||||
#define BHND_PMU_RES4319_CBUCK_LPOM 1 /* 0x00000002 */
|
||||
#define BHND_PMU_RES4319_CBUCK_BURST 2 /* 0x00000004 */
|
||||
#define BHND_PMU_RES4319_CBUCK_PWM 3 /* 0x00000008 */
|
||||
#define BHND_PMU_RES4319_CLDO_PU 4 /* 0x00000010 */
|
||||
#define BHND_PMU_RES4319_PALDO_PU 5 /* 0x00000020 */
|
||||
#define BHND_PMU_RES4319_ILP_REQUEST 6 /* 0x00000040 */
|
||||
#define BHND_PMU_RES4319_LNLDO1_PU 9 /* 0x00000200 */
|
||||
#define BHND_PMU_RES4319_OTP_PU 10 /* 0x00000400 */
|
||||
#define BHND_PMU_RES4319_LNLDO2_PU 12 /* 0x00001000 */
|
||||
#define BHND_PMU_RES4319_XTAL_PU 13 /* 0x00002000 */
|
||||
#define BHND_PMU_RES4319_ALP_AVAIL 14 /* 0x00004000 */
|
||||
#define BHND_PMU_RES4319_RX_PWRSW_PU 15 /* 0x00008000 */
|
||||
#define BHND_PMU_RES4319_TX_PWRSW_PU 16 /* 0x00010000 */
|
||||
#define BHND_PMU_RES4319_RFPLL_PWRSW_PU 17 /* 0x00020000 */
|
||||
#define BHND_PMU_RES4319_LOGEN_PWRSW_PU 18 /* 0x00040000 */
|
||||
#define BHND_PMU_RES4319_AFE_PWRSW_PU 19 /* 0x00080000 */
|
||||
#define BHND_PMU_RES4319_BBPLL_PWRSW_PU 20 /* 0x00100000 */
|
||||
#define BHND_PMU_RES4319_HT_AVAIL 21 /* 0x00200000 */
|
||||
|
||||
/* 4319 chip-specific CHIPCTL register bits */
|
||||
#define BHND_PMU1_PLL0_CHIPCTL0 0
|
||||
#define BHND_PMU1_PLL0_CHIPCTL1 1
|
||||
#define BHND_PMU1_PLL0_CHIPCTL2 2
|
||||
#define BHND_PMU_CCTL_4319USB_XTAL_SEL_MASK 0x00180000
|
||||
#define BHND_PMU_CCTL_4319USB_XTAL_SEL_SHIFT 19
|
||||
#define BHND_PMU_CCTL_4319USB_48MHZ_PLL_SEL 1
|
||||
#define BHND_PMU_CCTL_4319USB_24MHZ_PLL_SEL 2
|
||||
|
||||
/* 4336 PMU resources */
|
||||
#define BHND_PMU_RES4336_CBUCK_LPOM 0
|
||||
#define BHND_PMU_RES4336_CBUCK_BURST 1
|
||||
#define BHND_PMU_RES4336_CBUCK_LP_PWM 2
|
||||
#define BHND_PMU_RES4336_CBUCK_PWM 3
|
||||
#define BHND_PMU_RES4336_CLDO_PU 4
|
||||
#define BHND_PMU_RES4336_DIS_INT_RESET_PD 5
|
||||
#define BHND_PMU_RES4336_ILP_REQUEST 6
|
||||
#define BHND_PMU_RES4336_LNLDO_PU 7
|
||||
#define BHND_PMU_RES4336_LDO3P3_PU 8
|
||||
#define BHND_PMU_RES4336_OTP_PU 9
|
||||
#define BHND_PMU_RES4336_XTAL_PU 10
|
||||
#define BHND_PMU_RES4336_ALP_AVAIL 11
|
||||
#define BHND_PMU_RES4336_RADIO_PU 12
|
||||
#define BHND_PMU_RES4336_BG_PU 13
|
||||
#define BHND_PMU_RES4336_VREG1p4_PU_PU 14
|
||||
#define BHND_PMU_RES4336_AFE_PWRSW_PU 15
|
||||
#define BHND_PMU_RES4336_RX_PWRSW_PU 16
|
||||
#define BHND_PMU_RES4336_TX_PWRSW_PU 17
|
||||
#define BHND_PMU_RES4336_BB_PWRSW_PU 18
|
||||
#define BHND_PMU_RES4336_SYNTH_PWRSW_PU 19
|
||||
#define BHND_PMU_RES4336_MISC_PWRSW_PU 20
|
||||
#define BHND_PMU_RES4336_LOGEN_PWRSW_PU 21
|
||||
#define BHND_PMU_RES4336_BBPLL_PWRSW_PU 22
|
||||
#define BHND_PMU_RES4336_MACPHY_CLKAVAIL 23
|
||||
#define BHND_PMU_RES4336_HT_AVAIL 24
|
||||
#define BHND_PMU_RES4336_RSVD 25
|
||||
|
||||
/* 4330 resources */
|
||||
#define BHND_PMU_RES4330_CBUCK_LPOM 0
|
||||
#define BHND_PMU_RES4330_CBUCK_BURST 1
|
||||
#define BHND_PMU_RES4330_CBUCK_LP_PWM 2
|
||||
#define BHND_PMU_RES4330_CBUCK_PWM 3
|
||||
#define BHND_PMU_RES4330_CLDO_PU 4
|
||||
#define BHND_PMU_RES4330_DIS_INT_RESET_PD 5
|
||||
#define BHND_PMU_RES4330_ILP_REQUEST 6
|
||||
#define BHND_PMU_RES4330_LNLDO_PU 7
|
||||
#define BHND_PMU_RES4330_LDO3P3_PU 8
|
||||
#define BHND_PMU_RES4330_OTP_PU 9
|
||||
#define BHND_PMU_RES4330_XTAL_PU 10
|
||||
#define BHND_PMU_RES4330_ALP_AVAIL 11
|
||||
#define BHND_PMU_RES4330_RADIO_PU 12
|
||||
#define BHND_PMU_RES4330_BG_PU 13
|
||||
#define BHND_PMU_RES4330_VREG1p4_PU_PU 14
|
||||
#define BHND_PMU_RES4330_AFE_PWRSW_PU 15
|
||||
#define BHND_PMU_RES4330_RX_PWRSW_PU 16
|
||||
#define BHND_PMU_RES4330_TX_PWRSW_PU 17
|
||||
#define BHND_PMU_RES4330_BB_PWRSW_PU 18
|
||||
#define BHND_PMU_RES4330_SYNTH_PWRSW_PU 19
|
||||
#define BHND_PMU_RES4330_MISC_PWRSW_PU 20
|
||||
#define BHND_PMU_RES4330_LOGEN_PWRSW_PU 21
|
||||
#define BHND_PMU_RES4330_BBPLL_PWRSW_PU 22
|
||||
#define BHND_PMU_RES4330_MACPHY_CLKAVAIL 23
|
||||
#define BHND_PMU_RES4330_HT_AVAIL 24
|
||||
#define BHND_PMU_RES4330_5gRX_PWRSW_PU 25
|
||||
#define BHND_PMU_RES4330_5gTX_PWRSW_PU 26
|
||||
#define BHND_PMU_RES4330_5g_LOGEN_PWRSW_PU 27
|
||||
|
||||
/* 4313 resources */
|
||||
#define BHND_PMU_RES4313_BB_PU_RSRC 0
|
||||
#define BHND_PMU_RES4313_ILP_REQ_RSRC 1
|
||||
#define BHND_PMU_RES4313_XTAL_PU_RSRC 2
|
||||
#define BHND_PMU_RES4313_ALP_AVAIL_RSRC 3
|
||||
#define BHND_PMU_RES4313_RADIO_PU_RSRC 4
|
||||
#define BHND_PMU_RES4313_BG_PU_RSRC 5
|
||||
#define BHND_PMU_RES4313_VREG1P4_PU_RSRC 6
|
||||
#define BHND_PMU_RES4313_AFE_PWRSW_RSRC 7
|
||||
#define BHND_PMU_RES4313_RX_PWRSW_RSRC 8
|
||||
#define BHND_PMU_RES4313_TX_PWRSW_RSRC 9
|
||||
#define BHND_PMU_RES4313_BB_PWRSW_RSRC 10
|
||||
#define BHND_PMU_RES4313_SYNTH_PWRSW_RSRC 11
|
||||
#define BHND_PMU_RES4313_MISC_PWRSW_RSRC 12
|
||||
#define BHND_PMU_RES4313_BB_PLL_PWRSW_RSRC 13
|
||||
#define BHND_PMU_RES4313_HT_AVAIL_RSRC 14
|
||||
#define BHND_PMU_RES4313_MACPHY_CLK_AVAIL_RSRC 15
|
||||
|
||||
/* 4313 chip-specific CHIPCTRL register bits */
|
||||
#define BHND_PMU_CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */
|
||||
|
||||
/* 43228 resources */
|
||||
#define BHND_PMU_RES43228_NOT_USED 0
|
||||
#define BHND_PMU_RES43228_ILP_REQUEST 1
|
||||
#define BHND_PMU_RES43228_XTAL_PU 2
|
||||
#define BHND_PMU_RES43228_ALP_AVAIL 3
|
||||
#define BHND_PMU_RES43228_PLL_EN 4
|
||||
#define BHND_PMU_RES43228_HT_PHY_AVAIL 5
|
||||
|
||||
/*
|
||||
* Maximum delay for the PMU state transition in us.
|
||||
* This is an upper bound intended for spinwaits etc.
|
||||
*/
|
||||
#define BHND_PMU_MAX_TRANSITION_DLY 15000
|
||||
|
||||
/* PMU resource up transition time in ILP cycles */
|
||||
#define BHND_PMURES_UP_TRANSITION 2
|
||||
|
||||
#endif /* _BHND_CORES_PMU_BHND_PMUREG_H_ */
|
92
sys/dev/bhnd/cores/pmu/bhnd_pmuvar.h
Normal file
92
sys/dev/bhnd/cores/pmu/bhnd_pmuvar.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Landon Fuller <landon@landonf.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,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _BHND_CORES_PMU_BHND_PMUVAR_H_
|
||||
#define _BHND_CORES_PMU_BHND_PMUVAR_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include "bhnd_pmu.h"
|
||||
|
||||
DECLARE_CLASS(bhnd_pmu_driver);
|
||||
extern devclass_t bhnd_pmu_devclass;
|
||||
|
||||
int bhnd_pmu_probe(device_t dev);
|
||||
|
||||
int bhnd_pmu_attach(device_t dev, struct bhnd_resource *res);
|
||||
int bhnd_pmu_detach(device_t dev);
|
||||
int bhnd_pmu_suspend(device_t dev);
|
||||
int bhnd_pmu_resume(device_t dev);
|
||||
|
||||
/*
|
||||
* BHND PMU device quirks / features
|
||||
*/
|
||||
enum {
|
||||
/** No quirks */
|
||||
BPMU_QUIRK_NONE = 0,
|
||||
|
||||
/** On BCM4328-derived chipsets, the CLK_CTL_ST register CCS_HTAVAIL
|
||||
* and CCS_ALPAVAIL bits are swapped; the BHND_CCS0_* constants should
|
||||
* be used. */
|
||||
BPMU_QUIRK_CLKCTL_CCS0 = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* bhnd_pmu driver instance state.
|
||||
*/
|
||||
struct bhnd_pmu_softc {
|
||||
device_t dev;
|
||||
uint32_t quirks; /**< device quirk flags */
|
||||
uint32_t caps; /**< pmu capability flags. */
|
||||
|
||||
struct bhnd_chipid cid; /**< chip identification */
|
||||
struct bhnd_board_info board; /**< board identification */
|
||||
device_t chipc_dev; /**< chipcommon device */
|
||||
|
||||
struct bhnd_resource *res; /**< pmu register block. */
|
||||
int rid; /**< pmu register RID */
|
||||
|
||||
struct mtx mtx; /**< state mutex */
|
||||
|
||||
uint32_t ilp_cps; /**< measured ILP cycles per
|
||||
second, or 0 */
|
||||
};
|
||||
|
||||
#define BPMU_LOCK_INIT(sc) \
|
||||
mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
|
||||
"BHND chipc driver lock", MTX_DEF)
|
||||
#define BPMU_LOCK(sc) mtx_lock(&(sc)->mtx)
|
||||
#define BPMU_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
|
||||
#define BPMU_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what)
|
||||
#define BPMU_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx)
|
||||
|
||||
#endif /* _BHND_CORES_PMU_BHND_PMUVAR_H_ */
|
@ -84,6 +84,21 @@ u8 sromrev {
|
||||
srom 11 0x1D2
|
||||
}
|
||||
|
||||
|
||||
# PMU Info
|
||||
#
|
||||
|
||||
# PMU min resource mask (embedded-only).
|
||||
u32 rmin {
|
||||
sfmt decimal
|
||||
}
|
||||
|
||||
# PMU min resource max (embedded-only).
|
||||
u32 rmax {
|
||||
sfmt decimal
|
||||
}
|
||||
|
||||
|
||||
# Antennas available
|
||||
u8 aa2g {
|
||||
srom 1-3 0x5C (&0x30, >>4)
|
||||
|
@ -260,6 +260,20 @@ siba_suspend_core(device_t dev, device_t child)
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
siba_read_config(device_t dev, device_t child, bus_size_t offset, u_int width)
|
||||
{
|
||||
/* Unsuported */
|
||||
return (UINT32_MAX);
|
||||
}
|
||||
|
||||
static void
|
||||
siba_write_config(device_t dev, device_t child, bus_size_t offset, uint32_t val,
|
||||
u_int width)
|
||||
{
|
||||
/* Unsuported */
|
||||
return;
|
||||
}
|
||||
|
||||
static u_int
|
||||
siba_get_port_count(device_t dev, device_t child, bhnd_port_type type)
|
||||
@ -603,6 +617,9 @@ siba_add_children(device_t dev, const struct bhnd_chipid *chipid)
|
||||
/* Release our resource */
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
|
||||
r = NULL;
|
||||
|
||||
/* Issue bus callback for fully initialized child. */
|
||||
BHND_BUS_CHILD_ADDED(dev, child);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
@ -634,6 +651,8 @@ static device_method_t siba_methods[] = {
|
||||
DEVMETHOD(bhnd_bus_free_devinfo, siba_free_bhnd_dinfo),
|
||||
DEVMETHOD(bhnd_bus_reset_core, siba_reset_core),
|
||||
DEVMETHOD(bhnd_bus_suspend_core, siba_suspend_core),
|
||||
DEVMETHOD(bhnd_bus_read_config, siba_read_config),
|
||||
DEVMETHOD(bhnd_bus_write_config, siba_write_config),
|
||||
DEVMETHOD(bhnd_bus_get_port_count, siba_get_port_count),
|
||||
DEVMETHOD(bhnd_bus_get_region_count, siba_get_region_count),
|
||||
DEVMETHOD(bhnd_bus_get_port_rid, siba_get_port_rid),
|
||||
|
@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/bhnd/siba/sibavar.h>
|
||||
|
||||
#include <dev/bhnd/cores/chipc/chipcreg.h>
|
||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
|
||||
|
||||
#include "bcm_machdep.h"
|
||||
#include "bcm_mips_exts.h"
|
||||
@ -342,7 +343,7 @@ platform_reset(void)
|
||||
|
||||
/* Set watchdog (PMU or ChipCommon) */
|
||||
if (bcm_get_platform()->pmu_addr != 0x0) {
|
||||
BCM_CHIPC_WRITE_4(CHIPC_PMU_WATCHDOG, 1);
|
||||
BCM_CHIPC_WRITE_4(BHND_PMU_WATCHDOG, 1);
|
||||
} else
|
||||
BCM_CHIPC_WRITE_4(CHIPC_WATCHDOG, 1);
|
||||
|
||||
|
@ -1,22 +1,36 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../dev/bhnd
|
||||
.PATH: ${.CURDIR}/../../dev/bhnd/cores/chipc
|
||||
.PATH: ${.CURDIR}/../../dev/bhnd/cores/chipc/pwrctl
|
||||
.PATH: ${.CURDIR}/../../dev/bhnd/cores/pmu
|
||||
.PATH: ${.CURDIR}/../../dev/bhnd/nvram
|
||||
|
||||
KMOD= bhnd
|
||||
SRCS= bhnd.c \
|
||||
bhnd_subr.c
|
||||
SRCS= bhnd.c bhnd_subr.c
|
||||
SRCS+= bhnd_bus_if.c bhnd_bus_if.h
|
||||
|
||||
# ChipCommon
|
||||
SRCS+= chipc.c chipc_subr.c
|
||||
SRCS+= bhnd_sprom_chipc.c \
|
||||
bhnd_pmu_chipc.c \
|
||||
bhnd_pwrctl.c bhnd_pwrctl_subr.c
|
||||
SRCS+= bhnd_chipc_if.c bhnd_chipc_if.h
|
||||
|
||||
# PMU
|
||||
SRCS+= bhnd_pmu.c \
|
||||
bhnd_pmu_core.c \
|
||||
bhnd_pmu_subr.c
|
||||
SRCS+= bhnd_pmu_if.c bhnd_pmu_if.h
|
||||
|
||||
# NVRAM/SPROM
|
||||
SRCS+= bhnd_nvram.c \
|
||||
bhnd_nvram_parser.c \
|
||||
bhnd_sprom.c \
|
||||
bhnd_sprom_parser.c
|
||||
SRCS+= bhnd_nvram_common.c
|
||||
SRCS+= bhnd_nvram_map.h bhnd_nvram_map_data.h
|
||||
|
||||
SRCS+= bhnd_bus_if.c bhnd_bus_if.h \
|
||||
bhnd_chipc_if.c bhnd_chipc_if.h \
|
||||
bhnd_nvram_if.c bhnd_nvram_if.h
|
||||
SRCS+= bhnd_nvram_if.c bhnd_nvram_if.h
|
||||
|
||||
SRCS+= device_if.h bus_if.h
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR= bhnd_chipc \
|
||||
bhnd_pci \
|
||||
SUBDIR= bhnd_pci \
|
||||
bhnd_pci_hostb \
|
||||
bhnd_pcib
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../dev/bhnd/cores/chipc
|
||||
|
||||
KMOD= bhnd_chipc
|
||||
SRCS= chipc.c chipc_subr.c \
|
||||
bhnd_sprom_chipc.c
|
||||
SRCS+= device_if.h bus_if.h bhnd_bus_if.h \
|
||||
bhnd_chipc_if.h bhnd_nvram_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
Loading…
x
Reference in New Issue
Block a user