Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107844338
D7552.id19462.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
63 KB
Referenced Files
None
Subscribers
None
D7552.id19462.diff
View Options
Index: sys/dev/bhnd/cores/chipc/chipcreg.h
===================================================================
--- sys/dev/bhnd/cores/chipc/chipcreg.h
+++ sys/dev/bhnd/cores/chipc/chipcreg.h
@@ -31,6 +31,10 @@
required during bus
enumeration */
+/** Evaluates to true if the given ChipCommon core revision supports
+ * the CHIPC_CORECTRL register */
+#define CHIPC_HWREV_HAS_CORECTRL(hwrev) ((hwrev) >= 1)
+
/** Evaluates to true if the given ChipCommon core revision provides
* the core count via the chip identification register. */
#define CHIPC_NCORES_MIN_HWREV(hwrev) ((hwrev) == 4 || (hwrev) >= 6)
@@ -278,14 +282,14 @@
#define CHIPC_CST_SPROM_OTP_SEL_R23_SHIFT 6
/* PLL type */
-#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 */
+#define CHIPC_PLL_NONE 0x0
+#define CHIPC_PLL_TYPE1 0x2 /* 48MHz base, 3 dividers */
+#define CHIPC_PLL_TYPE2 0x4 /* 48MHz, 4 dividers */
+#define CHIPC_PLL_TYPE3 0x6 /* 25MHz, 2 dividers */
+#define CHIPC_PLL_TYPE4 0x8 /* 48MHz, 4 dividers */
+#define CHIPC_PLL_TYPE5 0x3 /* 25MHz, 4 dividers */
+#define CHIPC_PLL_TYPE6 0x5 /* 100/200 or 120/240 only */
+#define CHIPC_PLL_TYPE7 0x7 /* 25MHz, 4 dividers */
/* dynamic clock control defines */
#define CHIPC_LPOMINFREQ 25000 /* low power oscillator min */
Index: sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c
===================================================================
--- sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c
+++ sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c
@@ -46,8 +46,6 @@
#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
@@ -75,14 +73,122 @@
}
/**
+ * Return the backplane clock's chipc 'M' register offset for a given PLL type,
+ * or 0 if a fixed clock speed should be used.
+ *
+ * @param cid Chip identification.
+ * @param pll_type PLL type (CHIPC_PLL_TYPE*)
+ * @param[out] fixed_hz If 0 is returned, will be set to the fixed clock
+ * speed for this device.
+ */
+bus_size_t
+bhnd_pwrctl_si_clkreg_m(const struct bhnd_chipid *cid,
+ uint8_t pll_type, uint32_t *fixed_hz)
+{
+ switch (pll_type) {
+ case CHIPC_PLL_TYPE6:
+ return (CHIPC_CLKC_M3);
+ case CHIPC_PLL_TYPE3:
+ return (CHIPC_CLKC_M2);
+ default:
+ return (CHIPC_CLKC_SB);
+ }
+}
+
+/**
+ * Calculate the backplane clock speed (in Hz) for a given a set of clock
+ * control values.
+ *
+ * @param cid Chip identification.
+ * @param pll_type PLL type (CHIPC_PLL_TYPE*)
+ * @param n clock control N register value.
+ * @param m clock control M register value.
+ */
+uint32_t
+bhnd_pwrctl_si_clock_rate(const struct bhnd_chipid *cid,
+ uint32_t pll_type, uint32_t n, uint32_t m)
+{
+ uint32_t rate;
+
+ KASSERT(bhnd_pwrctl_si_clkreg_m(cid, pll_type, NULL) != 0,
+ ("can't compute clock rate on fixed clock"));
+
+ rate = bhnd_pwrctl_clock_rate(pll_type, n, m);
+ if (pll_type == CHIPC_PLL_TYPE3)
+ rate /= 2;
+
+ return (rate);
+}
+
+/**
+ * Return the CPU clock's chipc 'M' register offset for a given PLL type,
+ * or 0 if a fixed clock speed should be used.
+ *
+ * @param cid Chip identification.
+ * @param pll_type PLL type (CHIPC_PLL_TYPE*)
+ * @param[out] fixed_hz If 0 is returned, will be set to the fixed clock
+ * speed for this device.
+ */
+bus_size_t
+bhnd_pwrctl_cpu_clkreg_m(const struct bhnd_chipid *cid,
+ uint8_t pll_type, uint32_t *fixed_hz)
+{
+ switch (pll_type) {
+ case CHIPC_PLL_TYPE2:
+ case CHIPC_PLL_TYPE4:
+ case CHIPC_PLL_TYPE6:
+ case CHIPC_PLL_TYPE7:
+ return (CHIPC_CLKC_M3);
+
+ case CHIPC_PLL_TYPE5:
+ /* fixed 200MHz */
+ if (fixed_hz != NULL)
+ *fixed_hz = 200 * 1000 * 1000;
+ return (0);
+
+ case CHIPC_PLL_TYPE3:
+ if (cid->chip_id == BHND_CHIPID_BCM5365) {
+ /* fixed 200MHz */
+ if (fixed_hz != NULL)
+ *fixed_hz = 200 * 1000 * 1000;
+ return (0);
+ }
+
+ return (CHIPC_CLKC_M2);
+
+ default:
+ return (CHIPC_CLKC_SB);
+ }
+}
+
+/**
+ * Calculate the CPU clock speed (in Hz) for a given a set of clock control
+ * values.
+ *
+ * @param cid Chip identification.
+ * @param pll_type PLL type (CHIPC_PLL_TYPE*)
+ * @param n clock control N register value.
+ * @param m clock control M register value.
+ */
+uint32_t
+bhnd_pwrctl_cpu_clock_rate(const struct bhnd_chipid *cid,
+ uint32_t pll_type, uint32_t n, uint32_t m)
+{
+ KASSERT(bhnd_pwrctl_cpu_clkreg_m(cid, pll_type, NULL) != 0,
+ ("can't compute clock rate on fixed clock"));
+
+ return (bhnd_pwrctl_clock_rate(pll_type, n, m));
+}
+
+/**
* 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.
+ * @param m clock control M register value.
*/
-static uint32_t
+uint32_t
bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n, uint32_t m)
{
uint32_t clk_base;
@@ -195,38 +301,27 @@
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;
+ const struct bhnd_chipid *cid;
+ struct chipc_caps *ccaps;
+ bus_size_t creg;
+ uint32_t n, m;
+ uint32_t rate;
PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
+ cid = bhnd_get_chipid(sc->chipc_dev);
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);
+ /* Get M register offset */
+ creg = bhnd_pwrctl_si_clkreg_m(cid, ccaps->pll_type, &rate);
+ if (creg == 0) /* fixed rate */
+ return (rate);
/* calculate rate */
- rate = bhnd_pwrctl_clock_rate(ccaps->pll_type, n, m);
-
- if (ccaps->pll_type == CHIPC_PLL_TYPE3)
- rate /= 2;
-
- return (rate);
+ m = bhnd_bus_read_4(sc->res, creg);
+ return (bhnd_pwrctl_si_clock_rate(cid, ccaps->pll_type, n, m));
}
/* return the slow clock source */
Index: sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctlvar.h
===================================================================
--- sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctlvar.h
+++ sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctlvar.h
@@ -36,6 +36,21 @@
#include <sys/bus.h>
#include <sys/queue.h>
+#include <dev/bhnd/bhnd.h>
+
+uint32_t bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n,
+ uint32_t m);
+
+bus_size_t bhnd_pwrctl_si_clkreg_m(const struct bhnd_chipid *cid,
+ uint8_t pll_type, uint32_t *fixed_hz);
+uint32_t bhnd_pwrctl_si_clock_rate(const struct bhnd_chipid *cid,
+ uint32_t pll_type, uint32_t n, uint32_t m);
+
+bus_size_t bhnd_pwrctl_cpu_clkreg_m(const struct bhnd_chipid *cid,
+ uint8_t pll_type, uint32_t *fixed_hz);
+uint32_t bhnd_pwrctl_cpu_clock_rate(const struct bhnd_chipid *cid,
+ uint32_t pll_type, uint32_t n, uint32_t m);
+
/**
* bhnd pwrctl device quirks.
*/
Index: sys/dev/bhnd/cores/pmu/bhnd_pmu.c
===================================================================
--- sys/dev/bhnd/cores/pmu/bhnd_pmu.c
+++ sys/dev/bhnd/cores/pmu/bhnd_pmu.c
@@ -44,6 +44,7 @@
#include <machine/resource.h>
#include <dev/bhnd/bhnd.h>
+#include <dev/bhnd/cores/chipc/chipc.h>
#include "bhnd_nvram_map.h"
@@ -69,6 +70,16 @@
static int bhnd_pmu_sysctl_cpu_freq(SYSCTL_HANDLER_ARGS);
static int bhnd_pmu_sysctl_mem_freq(SYSCTL_HANDLER_ARGS);
+static uint32_t bhnd_pmu_read_4(bus_size_t reg, void *ctx);
+static void bhnd_pmu_write_4(bus_size_t reg, uint32_t val, void *ctx);
+static uint32_t bhnd_pmu_read_chipst(void *ctx);
+
+static const struct bhnd_pmu_io bhnd_pmu_res_io = {
+ .rd4 = bhnd_pmu_read_4,
+ .wr4 = bhnd_pmu_write_4,
+ .rd_chipst = bhnd_pmu_read_chipst
+};
+
#define BPMU_CLKCTL_READ_4(_pinfo) \
bhnd_bus_read_4((_pinfo)->pm_res, (_pinfo)->pm_regs)
@@ -144,6 +155,14 @@
return (ENXIO);
}
+ /* Initialize query state */
+ error = bhnd_pmu_query_init(&sc->query, dev, sc->cid, &bhnd_pmu_res_io,
+ sc);
+ if (error)
+ return (error);
+ sc->io = sc->query.io;
+ sc->io_ctx = sc->query.io_ctx;
+
BPMU_LOCK_INIT(sc);
/* Set quirk flags */
@@ -183,6 +202,7 @@
failed:
BPMU_LOCK_DESTROY(sc);
+ bhnd_pmu_query_fini(&sc->query);
return (error);
}
@@ -197,6 +217,7 @@
sc = device_get_softc(dev);
BPMU_LOCK_DESTROY(sc);
+ bhnd_pmu_query_fini(&sc->query);
return (0);
}
@@ -239,7 +260,7 @@
sc = arg1;
BPMU_LOCK(sc);
- freq = bhnd_pmu_si_clock(sc);
+ freq = bhnd_pmu_si_clock(&sc->query);
BPMU_UNLOCK(sc);
return (sysctl_handle_32(oidp, NULL, freq, req));
@@ -254,7 +275,7 @@
sc = arg1;
BPMU_LOCK(sc);
- freq = bhnd_pmu_cpu_clock(sc);
+ freq = bhnd_pmu_cpu_clock(&sc->query);
BPMU_UNLOCK(sc);
return (sysctl_handle_32(oidp, NULL, freq, req));
@@ -269,7 +290,7 @@
sc = arg1;
BPMU_LOCK(sc);
- freq = bhnd_pmu_mem_clock(sc);
+ freq = bhnd_pmu_mem_clock(&sc->query);
BPMU_UNLOCK(sc);
return (sysctl_handle_32(oidp, NULL, freq, req));
@@ -445,6 +466,27 @@
return (0);
}
+static uint32_t
+bhnd_pmu_read_4(bus_size_t reg, void *ctx)
+{
+ struct bhnd_pmu_softc *sc = ctx;
+ return (bhnd_bus_read_4(sc->res, reg));
+}
+
+static void
+bhnd_pmu_write_4(bus_size_t reg, uint32_t val, void *ctx)
+{
+ struct bhnd_pmu_softc *sc = ctx;
+ return (bhnd_bus_write_4(sc->res, reg, val));
+}
+
+static uint32_t
+bhnd_pmu_read_chipst(void *ctx)
+{
+ struct bhnd_pmu_softc *sc = ctx;
+ return (BHND_CHIPC_READ_CHIPST(sc->chipc_dev));
+}
+
static device_method_t bhnd_pmu_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, bhnd_pmu_probe),
Index: sys/dev/bhnd/cores/pmu/bhnd_pmu_private.h
===================================================================
--- sys/dev/bhnd/cores/pmu/bhnd_pmu_private.h
+++ sys/dev/bhnd/cores/pmu/bhnd_pmu_private.h
@@ -30,15 +30,9 @@
#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_READ_4(_sc, _reg) (_sc)->io->rd4((_reg), (_sc)->io_ctx)
#define BHND_PMU_WRITE_4(_sc, _reg, _val) \
- bhnd_bus_write_4((_sc)->res, (_reg), (_val))
+ (_sc)->io->wr4((_reg), (_val), (_sc)->io_ctx)
#define BHND_PMU_AND_4(_sc, _reg, _val) \
BHND_PMU_WRITE_4((_sc), (_reg), \
@@ -49,10 +43,11 @@
/* 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))
+ bhnd_pmu_ind_read((_sc)->io, (_sc)->io_ctx, \
+ 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_ind_write((_sc)->io, (_sc)->io_ctx, \
+ BHND_PMU_ ## _src ## _ADDR, \
BHND_PMU_ ## _src ## _DATA, (_reg), (_val), (_mask))
/* Chip Control indirect registers */
@@ -96,10 +91,12 @@
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);
+
+uint32_t bhnd_pmu_ind_read(const struct bhnd_pmu_io *io, void *io_ctx,
+ bus_size_t addr, bus_size_t data, uint32_t reg);
+void bhnd_pmu_ind_write(const struct bhnd_pmu_io *io, void *io_ctx,
+ 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,
@@ -112,12 +109,6 @@
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,
Index: sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c
===================================================================
--- sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c
+++ sys/dev/bhnd/cores/pmu/bhnd_pmu_subr.c
@@ -38,33 +38,36 @@
#include "bhnd_pmu_private.h"
-#ifdef BCMDBG
-#define PMU_MSG(args) printf args
-#define PMU_ERROR(args) do { \
- panic args; \
+#define PMU_LOG(_sc, _fmt, ...) do { \
+ if (_sc->dev != NULL) \
+ device_printf(_sc->dev, _fmt, ##__VA_ARGS__); \
+ else \
+ printf(_fmt, ##__VA_ARGS__); \
} while (0)
+
+#ifdef BCMDBG
+#define PMU_DEBUG(_sc, _fmt, ...) PMU_LOG(_sc, _fmt, ##__VA_ARGS__)
#else
-#define PMU_MSG(args)
-#define PMU_ERROR(args) printf args
+#define PMU_DEBUG(_sc, _fmt, ...)
#endif
typedef struct pmu0_xtaltab0 pmu0_xtaltab0_t;
typedef struct pmu1_xtaltab0 pmu1_xtaltab0_t;
/* PLL controls/clocks */
-static const pmu1_xtaltab0_t *bhnd_pmu1_xtaltab0(struct bhnd_pmu_softc *sc);
-static const pmu1_xtaltab0_t *bhnd_pmu1_xtaldef0(struct bhnd_pmu_softc *sc);
+static const pmu1_xtaltab0_t *bhnd_pmu1_xtaltab0(struct bhnd_pmu_query *sc);
+static const pmu1_xtaltab0_t *bhnd_pmu1_xtaldef0(struct bhnd_pmu_query *sc);
static void bhnd_pmu0_pllinit0(struct bhnd_pmu_softc *sc, uint32_t xtal);
-static uint32_t bhnd_pmu0_cpuclk0(struct bhnd_pmu_softc *sc);
-static uint32_t bhnd_pmu0_alpclk0(struct bhnd_pmu_softc *sc);
+static uint32_t bhnd_pmu0_cpuclk0(struct bhnd_pmu_query *sc);
+static uint32_t bhnd_pmu0_alpclk0(struct bhnd_pmu_query *sc);
static void bhnd_pmu1_pllinit0(struct bhnd_pmu_softc *sc, uint32_t xtal);
-static uint32_t bhnd_pmu1_pllfvco0(struct bhnd_pmu_softc *sc);
-static uint32_t bhnd_pmu1_cpuclk0(struct bhnd_pmu_softc *sc);
-static uint32_t bhnd_pmu1_alpclk0(struct bhnd_pmu_softc *sc);
+static uint32_t bhnd_pmu1_pllfvco0(struct bhnd_pmu_query *sc);
+static uint32_t bhnd_pmu1_cpuclk0(struct bhnd_pmu_query *sc);
+static uint32_t bhnd_pmu1_alpclk0(struct bhnd_pmu_query *sc);
-static uint32_t bhnd_pmu5_clock(struct bhnd_pmu_softc *sc, u_int pll0, u_int m);
+static uint32_t bhnd_pmu5_clock(struct bhnd_pmu_query *sc, u_int pll0, u_int m);
/* PMU resources */
static bool bhnd_pmu_res_depfltr_bb(struct bhnd_pmu_softc *sc);
@@ -93,7 +96,45 @@
(1 << (BHND_PMU_ ## _bit))
#define PMU_CST4330_SDIOD_CHIPMODE(_sc) \
- CHIPC_CST4330_CHIPMODE_SDIOD(BHND_CHIPC_READ_CHIPST((_sc)->chipc_dev))
+ CHIPC_CST4330_CHIPMODE_SDIOD((_sc)->io->rd_chipst((_sc)->io_ctx))
+
+/**
+ * Initialize @p query state.
+ *
+ * @param[out] query On success, will be populated with a valid query instance
+ * state.
+ * @param dev The device owning @p query, or NULL.
+ * @param id The bhnd chip identification.
+ * @param io I/O callback functions.
+ * @param ctx I/O callback context.
+ *
+ * @retval 0 success
+ * @retval non-zero if the query state could not be initialized.
+ */
+int
+bhnd_pmu_query_init(struct bhnd_pmu_query *query, device_t dev,
+ struct bhnd_chipid id, const struct bhnd_pmu_io *io, void *ctx)
+{
+ query->dev = dev;
+ query->io = io;
+ query->io_ctx = ctx;
+ query->cid = id;
+ query->caps = BHND_PMU_READ_4(query, BHND_PMU_CAP);
+
+ return (0);
+}
+
+/**
+ * Release any resources held by @p query.
+ *
+ * @param query A query instance previously initialized via
+ * bhnd_pmu_query_init().
+ */
+void
+bhnd_pmu_query_fini(struct bhnd_pmu_query *query)
+{
+ /* nothing to do */
+}
/**
* Perform an indirect register read.
@@ -103,11 +144,11 @@
* @param reg Indirect register to be read.
*/
uint32_t
-bhnd_pmu_ind_read(struct bhnd_pmu_softc *sc, bus_size_t addr, bus_size_t data,
- uint32_t reg)
+bhnd_pmu_ind_read(const struct bhnd_pmu_io *io, void *io_ctx, bus_size_t addr,
+ bus_size_t data, uint32_t reg)
{
- BHND_PMU_WRITE_4(sc, addr, reg);
- return (BHND_PMU_READ_4(sc, data));
+ io->wr4(addr, reg, io_ctx);
+ return (io->rd4(data, io_ctx));
}
/**
@@ -120,21 +161,21 @@
* @param mask Only the bits defined by @p mask will be updated from @p val.
*/
void
-bhnd_pmu_ind_write(struct bhnd_pmu_softc *sc, bus_size_t addr,
+bhnd_pmu_ind_write(const struct bhnd_pmu_io *io, void *io_ctx, bus_size_t addr,
bus_size_t data, uint32_t reg, uint32_t val, uint32_t mask)
{
uint32_t rval;
- BHND_PMU_WRITE_4(sc, addr, reg);
+ io->wr4(addr, reg, io_ctx);
if (mask != UINT32_MAX) {
- rval = BHND_PMU_READ_4(sc, data);
+ rval = io->rd4(data, io_ctx);
rval &= ~mask | (val & mask);
} else {
rval = val;
}
- BHND_PMU_WRITE_4(sc, data, rval);
+ io->wr4(data, rval, io_ctx);
}
/**
@@ -375,7 +416,7 @@
if (error)
return (error);
- ilp = bhnd_pmu_ilp_clock(sc);
+ ilp = bhnd_pmu_ilp_clock(&sc->query);
delay = (uptime + D11SCC_SLOW2FAST_TRANSITION) *
((1000000 + ilp - 1) / ilp);
delay = (11 * delay) / 10;
@@ -387,7 +428,7 @@
if (error)
return (error);
- ilp = bhnd_pmu_ilp_clock(sc);
+ ilp = bhnd_pmu_ilp_clock(&sc->query);
delay = (uptime + D11SCC_SLOW2FAST_TRANSITION) *
((1000000 + ilp - 1) / ilp);
delay = (11 * delay) / 10;
@@ -403,7 +444,7 @@
if (error)
return (error);
- ilp = bhnd_pmu_ilp_clock(sc);
+ ilp = bhnd_pmu_ilp_clock(&sc->query);
delay = (uptime + D11SCC_SLOW2FAST_TRANSITION) *
((1000000 + ilp - 1) / ilp);
delay = (11 * delay) / 10;
@@ -415,7 +456,7 @@
if (error)
return (error);
- ilp = bhnd_pmu_ilp_clock(sc);
+ ilp = bhnd_pmu_ilp_clock(&sc->query);
delay = (uptime + D11SCC_SLOW2FAST_TRANSITION) *
((1000000 + ilp - 1) / ilp);
delay = (11 * delay) / 10;
@@ -882,22 +923,22 @@
/* Apply nvram override to min mask */
error = bhnd_nvram_getvar_uint32(sc->chipc_dev, BHND_NVAR_RMIN, &nval);
if (error && error != ENOENT) {
- device_printf(sc->dev, "NVRAM error reading %s: %d\n",
+ PMU_LOG(sc, "NVRAM error reading %s: %d\n",
BHND_NVAR_RMIN, error);
return (error);
} else if (!error) {
- PMU_MSG(("Applying rmin=%#x to min_mask\n", nval));
+ PMU_DEBUG(sc, "Applying rmin=%#x to min_mask\n", nval);
min_mask = nval;
}
/* Apply nvram override to max mask */
error = bhnd_nvram_getvar_uint32(sc->chipc_dev, BHND_NVAR_RMAX, &nval);
if (error && error != ENOENT) {
- device_printf(sc->dev, "NVRAM error reading %s: %d\n",
+ PMU_LOG(sc, "NVRAM error reading %s: %d\n",
BHND_NVAR_RMAX, error);
return (error);
} else if (!error) {
- PMU_MSG(("Applying rmax=%#x to max_mask\n", nval));
+ PMU_DEBUG(sc, "Applying rmax=%#x to max_mask\n", nval);
min_mask = nval;
}
@@ -1013,8 +1054,8 @@
updt = &pmu_res_updown_table[pmu_res_updown_table_sz - i - 1];
- PMU_MSG(("Changing rsrc %d res_updn_timer to %#x\n",
- updt->resnum, updt->updown));
+ PMU_DEBUG(sc, "Changing rsrc %d res_updn_timer to %#x\n",
+ updt->resnum, updt->updown);
BHND_PMU_WRITE_4(sc, BHND_PMU_RES_TABLE_SEL, updt->resnum);
BHND_PMU_WRITE_4(sc, BHND_PMU_RES_UPDN_TIMER, updt->updown);
@@ -1031,13 +1072,13 @@
if (error == ENOENT) {
continue;
} else if (error) {
- device_printf(sc->dev, "NVRAM error reading %s: %d\n",
+ PMU_LOG(sc, "NVRAM error reading %s: %d\n",
name, error);
return (error);
}
- PMU_MSG(("Applying %s=%s to rsrc %d res_updn_timer\n", name,
- val, i));
+ PMU_DEBUG(sc, "Applying %s=%s to rsrc %d res_updn_timer\n",
+ name, val, i);
BHND_PMU_WRITE_4(sc, BHND_PMU_RES_TABLE_SEL, i);
BHND_PMU_WRITE_4(sc, BHND_PMU_RES_UPDN_TIMER, val);
@@ -1066,21 +1107,21 @@
BHND_PMU_RES_DEP_MASK);
switch (rdep->action) {
case RES_DEPEND_SET:
- PMU_MSG(("Changing rsrc %hhu res_dep_mask to "
- "%#x\n", i, table->depend_mask));
+ PMU_DEBUG(sc, "Changing rsrc %hhu res_dep_mask to "
+ "%#x\n", i, table->depend_mask);
depend_mask = rdep->depend_mask;
break;
case RES_DEPEND_ADD:
- PMU_MSG(("Adding %#x to rsrc %hhu "
- "res_dep_mask\n", table->depend_mask, i));
+ PMU_DEBUG(sc, "Adding %#x to rsrc %hhu "
+ "res_dep_mask\n", table->depend_mask, i);
depend_mask |= rdep->depend_mask;
break;
case RES_DEPEND_REMOVE:
- PMU_MSG(("Removing %#x from rsrc %hhu "
- "res_dep_mask\n", table->depend_mask, i));
+ PMU_DEBUG(sc, "Removing %#x from rsrc %hhu "
+ "res_dep_mask\n", table->depend_mask, i);
depend_mask &= ~(rdep->depend_mask);
break;
@@ -1106,13 +1147,13 @@
if (error == ENOENT) {
continue;
} else if (error) {
- device_printf(sc->dev, "NVRAM error reading %s: %d\n",
- name, error);
+ PMU_LOG(sc, "NVRAM error reading %s: %d\n", name,
+ error);
return (error);
}
- PMU_MSG(("Applying %s=%s to rsrc %d res_dep_mask\n", name, val,
- i));
+ PMU_DEBUG(sc, "Applying %s=%s to rsrc %d res_dep_mask\n", name,
+ val, i);
BHND_PMU_WRITE_4(sc, BHND_PMU_RES_TABLE_SEL, i);
BHND_PMU_WRITE_4(sc, BHND_PMU_RES_DEP_MASK, val);
@@ -1126,14 +1167,14 @@
/* Program max resource mask */
if (max_mask != 0) {
- PMU_MSG(("Changing max_res_mask to 0x%x\n", max_mask));
+ PMU_DEBUG(sc, "Changing max_res_mask to 0x%x\n", max_mask);
BHND_PMU_WRITE_4(sc, BHND_PMU_MAX_RES_MASK, max_mask);
}
/* Program min resource mask */
if (min_mask != 0) {
- PMU_MSG(("Changing min_res_mask to 0x%x\n", min_mask));
+ PMU_DEBUG(sc, "Changing min_res_mask to 0x%x\n", min_mask);
BHND_PMU_WRITE_4(sc, BHND_PMU_MIN_RES_MASK, min_mask);
}
@@ -1367,7 +1408,7 @@
/* select xtal table for each chip */
static const pmu1_xtaltab0_t *
-bhnd_pmu1_xtaltab0(struct bhnd_pmu_softc *sc)
+bhnd_pmu1_xtaltab0(struct bhnd_pmu_query *sc)
{
switch (sc->cid.chip_id) {
case BHND_CHIPID_BCM4315:
@@ -1386,15 +1427,15 @@
else
return (pmu1_xtaltab0_1440);
default:
- PMU_MSG(("bhnd_pmu1_xtaltab0: Unknown chipid %#hx\n",
- sc->cid.chip_id));
+ PMU_DEBUG(sc, "bhnd_pmu1_xtaltab0: Unknown chipid %#hx\n",
+ sc->cid.chip_id);
return (NULL);
}
}
/* select default xtal frequency for each chip */
static const pmu1_xtaltab0_t *
-bhnd_pmu1_xtaldef0(struct bhnd_pmu_softc *sc)
+bhnd_pmu1_xtaldef0(struct bhnd_pmu_query *sc)
{
switch (sc->cid.chip_id) {
case BHND_CHIPID_BCM4315:
@@ -1419,15 +1460,15 @@
else
return (&pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_37400K]);
default:
- PMU_MSG(("bhnd_pmu1_xtaldef0: Unknown chipid %#hx\n",
- sc->cid.chip_id));
+ PMU_DEBUG(sc, "bhnd_pmu1_xtaldef0: Unknown chipid %#hx\n",
+ sc->cid.chip_id);
return (NULL);
}
}
/* select default pll fvco for each chip */
static uint32_t
-bhnd_pmu1_pllfvco0(struct bhnd_pmu_softc *sc)
+bhnd_pmu1_pllfvco0(struct bhnd_pmu_query *sc)
{
switch (sc->cid.chip_id) {
case BHND_CHIPID_BCM4329:
@@ -1442,15 +1483,15 @@
else
return (FVCO_1440);
default:
- PMU_MSG(("bhnd_pmu1_pllfvco0: Unknown chipid %#hx\n",
- sc->cid.chip_id));
+ PMU_DEBUG(sc, "bhnd_pmu1_pllfvco0: Unknown chipid %#hx\n",
+ sc->cid.chip_id);
return (0);
}
}
/* query alp/xtal clock frequency */
static uint32_t
-bhnd_pmu1_alpclk0(struct bhnd_pmu_softc *sc)
+bhnd_pmu1_alpclk0(struct bhnd_pmu_query *sc)
{
const pmu1_xtaltab0_t *xt;
uint32_t xf;
@@ -1469,8 +1510,7 @@
xt = bhnd_pmu1_xtaldef0(sc);
if (xt == NULL || xt->fref == 0) {
- device_printf(sc->dev,
- "no matching ALP/XTAL frequency found\n");
+ PMU_LOG(sc, "no matching ALP/XTAL frequency found\n");
return (0);
}
@@ -1489,8 +1529,8 @@
/* Use h/w default PLL config */
if (xtal == 0) {
- PMU_MSG(("Unspecified xtal frequency, skipping PLL "
- "configuration\n"));
+ PMU_DEBUG(sc, "Unspecified xtal frequency, skipping PLL "
+ "configuration\n");
return;
}
@@ -1503,7 +1543,8 @@
if (xt->freq == 0)
xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
- PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
+ PMU_DEBUG(sc, "XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000,
+ xt->xf);
/* Check current PLL state */
pmu_ctrl = BHND_PMU_READ_4(sc, BHND_PMU_CTRL);
@@ -1517,19 +1558,20 @@
}
#endif /* BCMUSBDEV */
- PMU_MSG(("PLL already programmed for %d.%d MHz\n",
- xt->freq / 1000, xt->freq % 1000));
+ PMU_DEBUG(sc, "PLL already programmed for %d.%d MHz\n",
+ xt->freq / 1000, xt->freq % 1000);
return;
}
if (xf != 0) {
- PMU_MSG(("Reprogramming PLL for %d.%d MHz (was %d.%dMHz)\n",
+ PMU_DEBUG(sc,
+ "Reprogramming PLL for %d.%d MHz (was %d.%dMHz)\n",
xt->freq / 1000, xt->freq % 1000,
pmu0_xtaltab0[tmp-1].freq / 1000,
- pmu0_xtaltab0[tmp-1].freq % 1000));
+ pmu0_xtaltab0[tmp-1].freq % 1000);
} else {
- PMU_MSG(("Programming PLL for %d.%d MHz\n",
- xt->freq / 1000, xt->freq % 1000));
+ PMU_DEBUG(sc, "Programming PLL for %d.%d MHz\n",
+ xt->freq / 1000, xt->freq % 1000);
}
/* Make sure the PLL is off */
@@ -1549,7 +1591,7 @@
/* Wait for HT clock to shutdown. */
PMU_WAIT_CLKST(sc, 0, BHND_CCS_HTAVAIL);
- PMU_MSG(("Done masking\n"));
+ PMU_DEBUG(sc, "Done masking\n");
/* Write PDIV in pllcontrol[0] */
if (xt->freq >= BHND_PMU0_PLL0_PC0_PDIV_FREQ) {
@@ -1582,7 +1624,7 @@
pll_mask = BHND_PMU0_PLL0_PC2_WILD_INT_MASK;
BHND_PMU_PLL_WRITE(sc, BHND_PMU0_PLL0_PLLCTL2, pll_data, pll_mask);
- PMU_MSG(("Done pll\n"));
+ PMU_DEBUG(sc, "Done pll\n");
/* Write XtalFreq. Set the divisor also. */
pmu_ctrl = BHND_PMU_READ_4(sc, BHND_PMU_CTRL);
@@ -1597,7 +1639,7 @@
/* query alp/xtal clock frequency */
static uint32_t
-bhnd_pmu0_alpclk0(struct bhnd_pmu_softc *sc)
+bhnd_pmu0_alpclk0(struct bhnd_pmu_query *sc)
{
const pmu0_xtaltab0_t *xt;
uint32_t xf;
@@ -1618,7 +1660,7 @@
/* query CPU clock frequency */
static uint32_t
-bhnd_pmu0_cpuclk0(struct bhnd_pmu_softc *sc)
+bhnd_pmu0_cpuclk0(struct bhnd_pmu_query *sc)
{
uint32_t tmp, divarm;
uint32_t FVCO;
@@ -1654,8 +1696,8 @@
fvco /= 1000;
fvco *= 1000;
- PMU_MSG(("bhnd_pmu0_cpuclk0: wbint %u wbfrac %u fvco %u\n",
- wbint, wbfrac, fvco));
+ PMU_DEBUG(sc, "bhnd_pmu0_cpuclk0: wbint %u wbfrac %u fvco %u\n",
+ wbint, wbfrac, fvco);
FVCO = fvco;
#endif /* BCMDBG */
@@ -1677,19 +1719,21 @@
uint32_t FVCO;
uint8_t ndiv_mode;
- FVCO = bhnd_pmu1_pllfvco0(sc) / 1000;
+ FVCO = bhnd_pmu1_pllfvco0(&sc->query) / 1000;
buf_strength = 0;
ndiv_mode = 1;
/* Use h/w default PLL config */
if (xtal == 0) {
- PMU_MSG(("Unspecified xtal frequency, skipping PLL "
- "configuration\n"));
+ PMU_DEBUG(sc, "Unspecified xtal frequency, skipping PLL "
+ "configuration\n");
return;
}
/* Find the frequency in the table */
- for (xt = bhnd_pmu1_xtaltab0(sc); xt != NULL && xt->fref != 0; xt++) {
+ for (xt = bhnd_pmu1_xtaltab0(&sc->query); xt != NULL && xt->fref != 0;
+ xt++)
+ {
if (xt->fref == xtal)
break;
}
@@ -1698,8 +1742,8 @@
* we don't know how to program it.
*/
if (xt == NULL || xt->fref == 0) {
- device_printf(sc->dev, "Unsupported XTAL frequency %d.%dMHz, "
- "skipping PLL configuration\n", xtal / 1000, xtal % 1000);
+ PMU_LOG(sc, "Unsupported XTAL frequency %d.%dMHz, skipping PLL "
+ "configuration\n", xtal / 1000, xtal % 1000);
return;
}
@@ -1710,14 +1754,14 @@
sc->cid.chip_id != BHND_CHIPID_BCM4319 &&
sc->cid.chip_id != BHND_CHIPID_BCM4330)
{
- PMU_MSG(("PLL already programmed for %d.%dMHz\n",
- xt->fref / 1000, xt->fref % 1000));
+ PMU_DEBUG(sc, "PLL already programmed for %d.%dMHz\n",
+ xt->fref / 1000, xt->fref % 1000);
return;
}
- PMU_MSG(("XTAL %d.%dMHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
- PMU_MSG(("Programming PLL for %d.%dMHz\n", xt->fref / 1000,
- xt->fref % 1000));
+ PMU_DEBUG(sc, "XTAL %d.%dMHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf);
+ PMU_DEBUG(sc, "Programming PLL for %d.%dMHz\n", xt->fref / 1000,
+ xt->fref % 1000);
switch (sc->cid.chip_id) {
case BHND_CHIPID_BCM4325:
@@ -1840,7 +1884,7 @@
panic("unsupported chipid %#hx\n", sc->cid.chip_id);
}
- PMU_MSG(("Done masking\n"));
+ PMU_DEBUG(sc, "Done masking\n");
/* Write p1div and p2div to pllcontrol[0] */
plldata =
@@ -1916,8 +1960,8 @@
/* Write clock driving strength to pllcontrol[5] */
if (buf_strength) {
- PMU_MSG(("Adjusting PLL buffer drive strength: %x\n",
- buf_strength));
+ PMU_DEBUG(sc, "Adjusting PLL buffer drive strength: %x\n",
+ buf_strength);
plldata = BHND_PMU_SET_BITS(buf_strength,
BHND_PMU1_PLL0_PC5_CLK_DRV);
@@ -1946,7 +1990,7 @@
pllmask);
}
- PMU_MSG(("Done pll\n"));
+ PMU_DEBUG(sc, "Done pll\n");
/* to operate the 4319 usb in 24MHz/48MHz; chipcontrol[2][84:83] needs
* to be updated.
@@ -1995,7 +2039,7 @@
/* query the CPU clock frequency */
static uint32_t
-bhnd_pmu1_cpuclk0(struct bhnd_pmu_softc *sc)
+bhnd_pmu1_cpuclk0(struct bhnd_pmu_query *sc)
{
uint32_t tmp, m1div;
#ifdef BCMDBG
@@ -2032,8 +2076,8 @@
fvco /= 1000;
fvco *= 1000;
- PMU_MSG(("bhnd_pmu1_cpuclk0: ndiv_int %u ndiv_frac %u p2div %u "
- "p1div %u fvco %u\n", ndiv_int, ndiv_frac, p2div, p1div, fvco));
+ PMU_DEBUG(sc, "bhnd_pmu1_cpuclk0: ndiv_int %u ndiv_frac %u p2div %u "
+ "p1div %u fvco %u\n", ndiv_int, ndiv_frac, p2div, p1div, fvco);
FVCO = fvco;
#endif /* BCMDBG */
@@ -2134,15 +2178,19 @@
bhnd_pmu1_pllinit0(sc, xtalfreq);
break;
default:
- PMU_MSG(("No PLL init done for chip %#hx rev %d pmurev %d\n",
- sc->cid.chip_id, sc->cid.chip_rev, BHND_PMU_REV(sc)));
+ PMU_DEBUG("No PLL init done for chip %#hx rev %d pmurev %d\n",
+ sc->cid.chip_id, sc->cid.chip_rev, BHND_PMU_REV(sc));
break;
}
}
-/* query alp/xtal clock frequency */
+/**
+ * Return the ALP/XTAL clock frequency, in Hz.
+ *
+ * @param sc PMU query instance.
+ */
uint32_t
-bhnd_pmu_alp_clock(struct bhnd_pmu_softc *sc)
+bhnd_pmu_alp_clock(struct bhnd_pmu_query *sc)
{
uint32_t clock;
@@ -2201,10 +2249,10 @@
clock = 25000 * 1000;
break;
default:
- PMU_MSG(("No ALP clock specified "
+ PMU_DEBUG("No ALP clock specified "
"for chip %s rev %d pmurev %d, using default %d Hz\n",
bcm_chipname(sih->chip, chn, 8), sih->chiprev,
- sih->pmurev, clock));
+ sih->pmurev, clock);
break;
}
@@ -2215,7 +2263,7 @@
* pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
*/
static uint32_t
-bhnd_pmu5_clock(struct bhnd_pmu_softc *sc, u_int pll0, u_int m)
+bhnd_pmu5_clock(struct bhnd_pmu_query *sc, u_int pll0, u_int m)
{
uint32_t div;
uint32_t fc;
@@ -2224,13 +2272,13 @@
uint32_t tmp;
if ((pll0 & 3) || (pll0 > BHND_PMU4716_MAINPLL_PLL0)) {
- PMU_ERROR(("%s: Bad pll0: %d\n", __func__, pll0));
+ PMU_LOG(sc, "%s: Bad pll0: %d", __func__, pll0);
return (0);
}
/* Strictly there is an m5 divider, but I'm not sure we use it */
if ((m == 0) || (m > 4)) {
- PMU_ERROR(("%s: Bad m divider: %d\n", __func__, m));
+ PMU_LOG(sc, "%s: Bad m divider: %d", __func__, m);
return (0);
}
@@ -2238,7 +2286,7 @@
sc->cid.chip_id == BHND_CHIPID_BCM4749)
{
/* Detect failure in clock setting */
- tmp = BHND_CHIPC_READ_CHIPST(sc->chipc_dev);
+ tmp = sc->io->rd_chipst(sc->io_ctx);
if ((tmp & 0x40000) != 0)
return (133 * 1000000);
}
@@ -2274,19 +2322,23 @@
fc = bhnd_pmu_alp_clock(sc) / 1000000;
fc = (p1 * ndiv * fc) / p2;
- PMU_MSG(("%s: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, clock=%d\n",
- __func__, p1, p2, ndiv, ndiv, m, div, fc, fc / div));
+ PMU_DEBUG(sc, "%s: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, "
+ "clock=%d\n", __func__, p1, p2, ndiv, ndiv, m, div, fc, fc / div);
/* Return clock in Hertz */
return ((fc / div) * 1000000);
}
-/* query backplane clock frequency */
-/* For designs that feed the same clock to both backplane
- * and CPU just return the CPU clock speed.
+/**
+ * Return the backplane clock frequency, in Hz.
+ *
+ * On designs that feed the same clock to both backplane
+ * and CPU, this returns the CPU clock speed.
+ *
+ * @param sc PMU query instance.
*/
uint32_t
-bhnd_pmu_si_clock(struct bhnd_pmu_softc *sc)
+bhnd_pmu_si_clock(struct bhnd_pmu_query *sc)
{
uint32_t chipst;
uint32_t clock;
@@ -2351,14 +2403,14 @@
case BHND_CHIPID_BCM43235:
case BHND_CHIPID_BCM43236:
case BHND_CHIPID_BCM43238:
- chipst = BHND_CHIPC_READ_CHIPST(sc->chipc_dev);
+ chipst = sc->io->rd_chipst(sc->io_ctx);
if (chipst & CHIPC_CST43236_BP_CLK)
clock = 120000 * 1000;
else
clock = 96000 * 1000;
break;
case BHND_CHIPID_BCM43237:
- chipst = BHND_CHIPC_READ_CHIPST(sc->chipc_dev);
+ chipst = sc->io->rd_chipst(sc->io_ctx);
if (chipst & CHIPC_CST43237_BP_CLK)
clock = 96000 * 1000;
else
@@ -2377,8 +2429,8 @@
clock = 75000000;
break;
default:
- device_printf(sc->dev, "No backplane clock specified for chip "
- "%#hx rev %hhd pmurev %hhd, using default %dHz\n",
+ PMU_LOG(sc, "No backplane clock specified for chip %#hx rev "
+ "%hhd pmurev %hhd, using default %dHz\n",
sc->cid.chip_id, sc->cid.chip_rev, BHND_PMU_REV(sc), clock);
break;
}
@@ -2386,18 +2438,19 @@
return (clock);
}
-/* query CPU clock frequency */
+/**
+ * Return the CPU clock frequency, in Hz.
+ *
+ * @param sc PMU query instance.
+ */
uint32_t
-bhnd_pmu_cpu_clock(struct bhnd_pmu_softc *sc)
+bhnd_pmu_cpu_clock(struct bhnd_pmu_query *sc)
{
- uint32_t clock;
+ uint32_t clock;
- if (sc->cid.chip_id == BHND_CHIPID_BCM5354)
- return (240 * 1000 * 1000); /* 240MHz */
-
/* 5354 chip uses a non programmable PLL of frequency 240MHz */
if (sc->cid.chip_id == BHND_CHIPID_BCM5354)
- return (240000000);
+ return (240 * 1000 * 1000); /* 240MHz */
if (sc->cid.chip_id == BHND_CHIPID_BCM53572)
return (300000000);
@@ -2436,9 +2489,13 @@
return (clock);
}
-/* query memory clock frequency */
+/**
+ * Return the memory clock frequency, in Hz.
+ *
+ * @param sc PMU query instance.
+ */
uint32_t
-bhnd_pmu_mem_clock(struct bhnd_pmu_softc *sc)
+bhnd_pmu_mem_clock(struct bhnd_pmu_query *sc)
{
uint32_t clock;
@@ -2479,8 +2536,13 @@
/* Measure ILP clock frequency */
#define ILP_CALC_DUR 10 /* ms, make sure 1000 can be divided by it. */
+/**
+ * Measure and return the ILP clock frequency, in Hz.
+ *
+ * @param sc PMU query instance.
+ */
uint32_t
-bhnd_pmu_ilp_clock(struct bhnd_pmu_softc *sc)
+bhnd_pmu_ilp_clock(struct bhnd_pmu_query *sc)
{
uint32_t start, end, delta;
@@ -2572,9 +2634,9 @@
break;
default:
- device_printf(sc->dev, "No SDIO Drive strength init done for "
- "chip %#x rev %hhd pmurev %hhd\n", sc->cid.chip_id,
- sc->cid.chip_rev, BHND_PMU_REV(sc));
+ PMU_LOG(sc, "No SDIO Drive strength init done for chip %#x "
+ "rev %hhd pmurev %hhd\n", sc->cid.chip_id, sc->cid.chip_rev,
+ BHND_PMU_REV(sc));
break;
}
@@ -2595,8 +2657,8 @@
cc_data_temp |= drivestrength_sel;
BHND_PMU_CCTRL_WRITE(sc, 1, cc_data_temp, ~0);
- PMU_MSG(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
- drivestrength, cc_data_temp));
+ PMU_DEBUG(sc, "SDIO: %dmA drive strength selected, set to "
+ "0x%08x\n", drivestrength, cc_data_temp);
}
}
@@ -2633,10 +2695,8 @@
/* If not available, log any real errors, and then try to measure it */
if (error) {
- if (error != ENOENT) {
- device_printf(sc->dev, "error fetching xtalfreq: %d\n",
- error);
- }
+ if (error != ENOENT)
+ PMU_LOG(sc, "error fetching xtalfreq: %d\n", error);
xtalfreq = bhnd_pmu_measure_alpclk(sc);
}
@@ -2693,8 +2753,8 @@
dmax = dup;
}
- PMU_MSG(("bhnd_pmu_res_uptime: rsrc %hhu uptime %u(deps 0x%08x "
- "uptime %u)\n", rsrc, up, deps, dmax));
+ PMU_DEBUG(sc, "bhnd_pmu_res_uptime: rsrc %hhu uptime %u(deps 0x%08x "
+ "uptime %u)\n", rsrc, up, deps, dmax);
*uptime = (up + dmax + BHND_PMURES_UP_TRANSITION);
return (0);
@@ -2779,8 +2839,8 @@
if (on) {
uint32_t state;
- PMU_MSG(("Adding rsrc 0x%x to min_res_mask\n",
- rsrcs | deps));
+ PMU_DEBUG(sc, "Adding rsrc 0x%x to min_res_mask\n",
+ rsrcs | deps);
BHND_PMU_OR_4(sc, BHND_PMU_MIN_RES_MASK, (rsrcs|deps));
/* Wait for all resources to become available */
@@ -2793,13 +2853,13 @@
}
if ((state & rsrcs) != rsrcs) {
- device_printf(sc->dev, "timeout waiting for OTP "
- "resource enable\n");
+ PMU_LOG(sc, "timeout waiting for OTP resource "
+ "enable\n");
return (ENXIO);
}
} else {
- PMU_MSG(("Removing rsrc 0x%x from min_res_mask\n",
- rsrcs | deps));
+ PMU_DEBUG(sc, "Removing rsrc 0x%x from min_res_mask\n",
+ rsrcs | deps);
BHND_PMU_AND_4(sc, BHND_PMU_MIN_RES_MASK, ~(rsrcs|deps));
}
@@ -2853,8 +2913,8 @@
rcal_code = (uint8_t) (chipst >> 5) & 0x0f;
}
- PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
- R_REG(&cc->chipstatus), rcal_code));
+ PMU_DEBUG("RCal completed, status 0x%x, code 0x%x\n",
+ R_REG(&cc->chipstatus), rcal_code);
/* Write RCal code into pmu_vreg_ctrl[32:29] */
BHND_PMU_WRITE_4(sc, BHND_PMU_REG_CONTROL_ADDR, 0);
@@ -3098,6 +3158,7 @@
break;
case BHND_CHIPID_BCM4319:
+ pmuctrl = 0;
break;
case BHND_CHIPID_BCM4322:
@@ -3136,7 +3197,6 @@
}
BHND_PMU_PLL_WRITE(sc, BHND_PMU1_PLL0_PLLCTL3, tmp, ~0);
-
pmuctrl = BHND_PMU_CTRL_PLL_PLLCTL_UPD;
break;
case BHND_CHIPID_BCM43131:
@@ -3176,12 +3236,14 @@
pmuctrl = BHND_PMU_CTRL_PLL_PLLCTL_UPD;
break;
default:
- PMU_ERROR(("%s: unknown spuravoidance settings for chip %#hx, "
- "not changing PLL\n", __func__, sc->cid.chip_id));
+ PMU_LOG(sc, "%s: unknown spuravoidance settings for chip %#hx, "
+ "not changing PLL", __func__, sc->cid.chip_id);
+ pmuctrl = 0;
break;
}
- BHND_PMU_OR_4(sc, BHND_PMU_CTRL, pmuctrl);
+ if (pmuctrl != 0)
+ BHND_PMU_OR_4(sc, BHND_PMU_CTRL, pmuctrl);
}
bool
@@ -3417,7 +3479,7 @@
static void
bhnd_pmu_set_4330_plldivs(struct bhnd_pmu_softc *sc)
{
- uint32_t FVCO = bhnd_pmu1_pllfvco0(sc) / 1000;
+ uint32_t FVCO = bhnd_pmu1_pllfvco0(&sc->query) / 1000;
uint32_t m1div, m2div, m3div, m4div, m5div, m6div;
uint32_t pllc1, pllc2;
Index: sys/dev/bhnd/cores/pmu/bhnd_pmuvar.h
===================================================================
--- sys/dev/bhnd/cores/pmu/bhnd_pmuvar.h
+++ sys/dev/bhnd/cores/pmu/bhnd_pmuvar.h
@@ -37,15 +37,28 @@
#include "bhnd_pmu.h"
+struct bhnd_pmu_query;
+struct bhnd_pmu_io;
+
DECLARE_CLASS(bhnd_pmu_driver);
extern devclass_t bhnd_pmu_devclass;
-int bhnd_pmu_probe(device_t dev);
+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);
+
+int bhnd_pmu_query_init(struct bhnd_pmu_query *query, device_t dev,
+ struct bhnd_chipid id, const struct bhnd_pmu_io *io,
+ void *ctx);
+void bhnd_pmu_query_fini(struct bhnd_pmu_query *query);
-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);
+uint32_t bhnd_pmu_si_clock(struct bhnd_pmu_query *sc);
+uint32_t bhnd_pmu_cpu_clock(struct bhnd_pmu_query *sc);
+uint32_t bhnd_pmu_mem_clock(struct bhnd_pmu_query *sc);
+uint32_t bhnd_pmu_alp_clock(struct bhnd_pmu_query *sc);
+uint32_t bhnd_pmu_ilp_clock(struct bhnd_pmu_query *sc);
/*
* BHND PMU device quirks / features
@@ -60,25 +73,62 @@
BPMU_QUIRK_CLKCTL_CCS0 = 1
};
+
+/**
+ * PMU read-only query support.
+ *
+ * Provides support for querying PMU information prior to availability of
+ * the bhnd(4) bus.
+ */
+struct bhnd_pmu_query {
+ device_t dev; /**< owning device, or NULL */
+ struct bhnd_chipid cid; /**< chip identification */
+ uint32_t caps; /**< pmu capability flags. */
+
+ const struct bhnd_pmu_io *io; /**< I/O operations */
+ void *io_ctx; /**< I/O callback context */
+
+ uint32_t ilp_cps; /**< measured ILP cycles per second, or 0 */
+};
+
+/**
+ * PMU abstract I/O operations.
+ */
+struct bhnd_pmu_io {
+ /* Read 4 bytes from PMU @p reg */
+ uint32_t (*rd4)(bus_size_t reg, void *ctx);
+
+ /* Read 4 bytes to PMU @p reg */
+ void (*wr4)(bus_size_t reg, uint32_t val, void *ctx);
+
+ /* Read ChipCommon's CHIP_ST register */
+ uint32_t (*rd_chipst)(void *ctx);
+};
+
/**
* bhnd_pmu driver instance state.
*/
struct bhnd_pmu_softc {
- device_t dev;
- uint32_t quirks; /**< device quirk flags */
- uint32_t caps; /**< pmu capability flags. */
+ device_t dev;
+ uint32_t quirks; /**< device quirk flags */
+ uint32_t caps; /**< pmu capability flags. */
+ struct bhnd_chipid cid; /**< chip identification */
+
+ struct bhnd_pmu_query query; /**< query instance */
+
+ struct bhnd_board_info board; /**< board identification */
+ device_t chipc_dev; /**< chipcommon device */
- 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 bhnd_resource *res; /**< pmu register block. */
- int rid; /**< pmu register RID */
+ struct mtx mtx; /**< state mutex */
- struct mtx mtx; /**< state mutex */
+ /* For compatibility with bhnd_pmu_query APIs and the shared
+ * BHND_PMU_(READ|WRITE) macros. */
+ const struct bhnd_pmu_io *io;
+ void *io_ctx;
- uint32_t ilp_cps; /**< measured ILP cycles per
- second, or 0 */
};
#define BPMU_LOCK_INIT(sc) \
Index: sys/mips/broadcom/bcm_machdep.h
===================================================================
--- sys/mips/broadcom/bcm_machdep.h
+++ sys/mips/broadcom/bcm_machdep.h
@@ -36,6 +36,13 @@
#include <machine/cpuregs.h>
#include <dev/bhnd/bhnd.h>
+#include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
+
+extern const struct bhnd_pmu_io bcm_pmu_soc_io;
+
+typedef int (bcm_bus_find_core)(struct bhnd_chipid *chipid,
+ bhnd_devclass_t devclass, int unit, struct bhnd_core_info *info,
+ uintptr_t *addr);
struct bcm_platform {
struct bhnd_chipid id; /**< chip id */
@@ -48,46 +55,53 @@
* the pmu_id and pmu_addr values will be copied from cc_id
* and cc_addr. */
struct bhnd_core_info pmu_id; /**< PMU core info */
- uintptr_t pmu_addr; /**< PMU core phys address. */
+ uintptr_t pmu_addr; /**< PMU core phys address, or
+ 0x0 if no PMU */
+
+ struct bhnd_pmu_query pmu; /**< PMU query instance */
#ifdef CFE
int cfe_console; /**< Console handle, or -1 */
#endif
};
+struct bcm_platform *bcm_get_platform(void);
-typedef int (bcm_bus_find_core)(struct bhnd_chipid *chipid,
- bhnd_devclass_t devclass, int unit, struct bhnd_core_info *info,
- uintptr_t *addr);
+uint64_t bcm_get_cpufreq(struct bcm_platform *bp);
+uint64_t bcm_get_sifreq(struct bcm_platform *bp);
+uint64_t bcm_get_alpfreq(struct bcm_platform *bp);
+uint64_t bcm_get_ilpfreq(struct bcm_platform *bp);
-struct bcm_platform *bcm_get_platform(void);
+u_int bcm_get_uart_rclk(struct bcm_platform *bp);
bcm_bus_find_core bcm_find_core_default;
bcm_bus_find_core bcm_find_core_bcma;
bcm_bus_find_core bcm_find_core_siba;
-#define BCM_SOC_ADDR(_addr, _offset) \
+#define BCM_SOC_ADDR(_addr, _offset) \
MIPS_PHYS_TO_KSEG1((_addr) + (_offset))
-#define BCM_SOC_READ_4(_addr, _offset) \
+#define BCM_SOC_READ_4(_addr, _offset) \
readl(BCM_SOC_ADDR((_addr), (_offset)))
-#define BCM_SOC_WRITE_4(_addr, _reg, _val) \
+#define BCM_SOC_WRITE_4(_addr, _reg, _val) \
writel(BCM_SOC_ADDR((_addr), (_offset)), (_val))
-#define BCM_CORE_ADDR(_name, _reg) \
- BCM_SOC_ADDR(bcm_get_platform()->_name, (_reg))
+#define BCM_CORE_ADDR(_bp, _name, _reg) \
+ BCM_SOC_ADDR(_bp->_name, (_reg))
-#define BCM_CORE_READ_4(_name, _reg) \
- readl(BCM_CORE_ADDR(_name, (_reg)))
-#define BCM_CORE_WRITE_4(_name, _reg, _val) \
- writel(BCM_CORE_ADDR(_name, (_reg)), (_val))
+#define BCM_CORE_READ_4(_bp, _name, _reg) \
+ readl(BCM_CORE_ADDR(_bp, _name, (_reg)))
+#define BCM_CORE_WRITE_4(_bp, _name, _reg, _val) \
+ writel(BCM_CORE_ADDR(_bp, _name, (_reg)), (_val))
-#define BCM_CHIPC_READ_4(_reg) BCM_CORE_READ_4(cc_addr, (_reg))
-#define BCM_CHIPC_WRITE_4(_reg, _val) \
- BCM_CORE_WRITE_4(cc_addr, (_reg), (_val))
+#define BCM_CHIPC_READ_4(_bp, _reg) \
+ BCM_CORE_READ_4(_bp, cc_addr, (_reg))
+#define BCM_CHIPC_WRITE_4(_bp, _reg, _val) \
+ BCM_CORE_WRITE_4(_bp, cc_addr, (_reg), (_val))
-#define BCM_PMU_READ_4(_reg) BCM_CORE_READ_4(pmu_addr, (_reg))
-#define BCM_PMU_WRITE_4(_reg, _val) \
- BCM_CORE_WRITE_4(pmu_addr, (_reg), (_val))
+#define BCM_PMU_READ_4(_bp, _reg) \
+ BCM_CORE_READ_4(_bp, pmu_addr, (_reg))
+#define BCM_PMU_WRITE_4(_bp, _reg, _val) \
+ BCM_CORE_WRITE_4(_bp, pmu_addr, (_reg), (_val))
#endif /* _MIPS_BROADCOM_BCM_MACHDEP_H_ */
Index: sys/mips/broadcom/bcm_machdep.c
===================================================================
--- sys/mips/broadcom/bcm_machdep.c
+++ sys/mips/broadcom/bcm_machdep.c
@@ -85,7 +85,6 @@
#include "bcm_machdep.h"
#include "bcm_mips_exts.h"
-#include "bcm_socinfo.h"
#ifdef CFE
#include <dev/cfe/cfe_api.h>
@@ -238,6 +237,16 @@
memset(&pdata->pmu_id, 0, sizeof(pdata->pmu_id));
}
+ if (pmu) {
+ error = bhnd_pmu_query_init(&pdata->pmu, NULL, pdata->id,
+ &bcm_pmu_soc_io, pdata);
+ if (error) {
+ printf("%s: bhnd_pmu_query_init() failed: %d\n",
+ __FUNCTION__, error);
+ return (error);
+ }
+ }
+
bcm_platform_data_avail = true;
return (0);
}
@@ -318,7 +327,8 @@
void
platform_reset(void)
{
- bool bcm4785war;
+ struct bcm_platform *bp;
+ bool bcm4785war;
printf("bcm::platform_reset()\n");
intr_disable();
@@ -332,9 +342,11 @@
}
#endif
- /* Handle BCM4785-specific behavior */
+ bp = bcm_get_platform();
bcm4785war = false;
- if (bcm_get_platform()->id.chip_id == BHND_CHIPID_BCM4785) {
+
+ /* Handle BCM4785-specific behavior */
+ if (bp->id.chip_id == BHND_CHIPID_BCM4785) {
bcm4785war = true;
/* Switch to async mode */
@@ -342,10 +354,10 @@
}
/* Set watchdog (PMU or ChipCommon) */
- if (bcm_get_platform()->pmu_addr != 0x0) {
- BCM_CHIPC_WRITE_4(BHND_PMU_WATCHDOG, 1);
+ if (bp->pmu_addr != 0x0) {
+ BCM_PMU_WRITE_4(bp, BHND_PMU_WATCHDOG, 1);
} else
- BCM_CHIPC_WRITE_4(CHIPC_WATCHDOG, 1);
+ BCM_CHIPC_WRITE_4(bp, CHIPC_WATCHDOG, 1);
/* BCM4785 */
if (bcm4785war) {
@@ -362,7 +374,6 @@
{
vm_offset_t kernend;
uint64_t platform_counter_freq;
- struct bcm_socinfo *socinfo;
int error;
/* clear the BSS and SBSS segments */
@@ -393,16 +404,16 @@
if ((error = bcm_init_platform_data(&bcm_platform_data)))
panic("bcm_init_platform_data() failed: %d", error);
- socinfo = bcm_get_socinfo();
- platform_counter_freq = socinfo->cpurate * 1000 * 1000; /* BCM4718 is 480MHz */
+ platform_counter_freq = bcm_get_cpufreq(bcm_get_platform());
- mips_timer_early_init(platform_counter_freq);
+ /* CP0 ticks every two cycles */
+ mips_timer_early_init(platform_counter_freq / 2);
cninit();
mips_init();
- mips_timer_init_params(platform_counter_freq, socinfo->double_count);
+ mips_timer_init_params(platform_counter_freq, 1);
}
/*
Index: sys/mips/broadcom/bcm_pmu.c
===================================================================
--- /dev/null
+++ sys/mips/broadcom/bcm_pmu.c
@@ -0,0 +1,298 @@
+/*-
+ * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/bhnd/bhnd.h>
+
+#include <dev/bhnd/cores/chipc/chipcreg.h>
+
+#include <dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctlvar.h>
+
+#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
+#include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
+
+#include "bcm_machdep.h"
+
+static struct bhnd_pmu_query *bcm_get_pmu(struct bcm_platform *bp);
+static bool bcm_has_pmu(struct bcm_platform *bp);
+
+static uint32_t bcm_pmu_read4(bus_size_t reg, void *ctx);
+static void bcm_pmu_write4(bus_size_t reg, uint32_t val,
+ void *ctx);
+static uint32_t bcm_pmu_read_chipst(void *ctx);
+
+const struct bhnd_pmu_io bcm_pmu_soc_io = {
+ .rd4 = bcm_pmu_read4,
+ .wr4 = bcm_pmu_write4,
+ .rd_chipst = bcm_pmu_read_chipst
+};
+
+/**
+ * Supported UART clock sources.
+ */
+typedef enum {
+ BCM_UART_RCLK_PLL_T1 = 0, /**< UART uses PLL m2 (mii/uart/mipsref) with no divisor */
+ BCM_UART_RCLK_ALP = 1, /**< UART uses ALP rclk with no divisor */
+ BCM_UART_RCLK_EXT = 2, /**< UART uses 1.8423 MHz external clock */
+ BCM_UART_RCLK_SI = 3, /**< UART uses backplane clock with divisor of two */
+ BCM_UART_RCLK_FIXED = 4, /**< UART uses fixed 88Mhz backplane clock with a divisor of 48 */
+} bcm_uart_clksrc;
+
+/**
+ * UART clock configuration.
+ */
+struct bcm_uart_clkcfg {
+ bcm_uart_clksrc src; /**< clock source */
+ uint32_t div; /**< clock divisor */
+ uint32_t freq; /**< clock frequency (Hz) */
+};
+
+#define BCM_UART_RCLK_PLL_T1_DIV 1
+#define BCM_UART_RCLK_ALP_DIV 1
+#define BCM_UART_RCLK_EXT_HZ 1842300 /* 1.8423MHz */
+#define BCM_UART_RCLK_EXT_DIV 1
+#define BCM_UART_RCLK_FIXED_HZ 88000000 /* 88MHz */
+#define BCM_UART_RCLK_FIXED_DIV 48
+
+/* Fetch PLL type from ChipCommon capability flags */
+#define BCM_PMU_PLL_TYPE(_bp) \
+ CHIPC_GET_BITS(_bp->cc_caps, CHIPC_CAP_PLL)
+
+/**
+ * Return the PMU instance, or NULL if no PMU.
+ */
+static struct bhnd_pmu_query *
+bcm_get_pmu(struct bcm_platform *bp)
+{
+ if (!bcm_has_pmu(bp))
+ return (NULL);
+ return (&bp->pmu);
+}
+
+/**
+ * Return true if a PMU is available, false otherwise.
+ */
+static bool
+bcm_has_pmu(struct bcm_platform *bp)
+{
+ return (bp->pmu_addr != 0);
+}
+
+/**
+ * Determine the UART clock source for @p bp and return the
+ * corresponding clock configuration, if any.
+ */
+static struct bcm_uart_clkcfg
+bcm_get_uart_clkcfg(struct bcm_platform *bp)
+{
+ struct bcm_uart_clkcfg cfg;
+ struct bhnd_core_info *cc_id;
+
+ cc_id = &bp->cc_id;
+
+ /* These tests are ordered by precedence. */
+
+ /* PLL M2 clock source? */
+ if (!bcm_has_pmu(bp) && BCM_PMU_PLL_TYPE(bp) == CHIPC_PLL_TYPE1) {
+ uint32_t n, m;
+
+ n = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_N);
+ m = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_M2);
+
+ cfg = (struct bcm_uart_clkcfg) {
+ BCM_UART_RCLK_PLL_T1,
+ BCM_UART_RCLK_PLL_T1_DIV,
+ bhnd_pwrctl_clock_rate(BCM_PMU_PLL_TYPE(bp), n, m)
+ };
+
+ return (cfg);
+ }
+
+ /* ALP clock source? */
+ if (cc_id->hwrev != 15 && cc_id->hwrev >= 11) {
+ cfg = (struct bcm_uart_clkcfg) {
+ BCM_UART_RCLK_ALP,
+ BCM_UART_RCLK_ALP_DIV,
+ bcm_get_alpfreq(bp)
+ };
+ return (cfg);
+ }
+
+ /* External clock? */
+ if (CHIPC_HWREV_HAS_CORECTRL(cc_id->hwrev)) {
+ uint32_t corectrl, uclksel;
+ bool uintclk0;
+
+ /* Fetch UART clock support flag */
+ uclksel = CHIPC_GET_BITS(bp->cc_caps, CHIPC_CAP_UCLKSEL);
+
+ /* Is UART using internal clock? */
+ corectrl = BCM_CHIPC_READ_4(bp, CHIPC_CORECTRL);
+ uintclk0 = CHIPC_GET_FLAG(corectrl, CHIPC_UARTCLKO);
+
+ if (uintclk0 && uclksel == CHIPC_CAP_UCLKSEL_UINTCLK) {
+ cfg = (struct bcm_uart_clkcfg) {
+ BCM_UART_RCLK_EXT,
+ BCM_UART_RCLK_EXT_DIV,
+ BCM_UART_RCLK_EXT_HZ
+ };
+ return (cfg);
+ }
+ }
+
+ /* UART uses backplane clock? */
+ if (cc_id->hwrev == 15 || (cc_id->hwrev >= 3 && cc_id->hwrev <= 10)) {
+ cfg = (struct bcm_uart_clkcfg) {
+ BCM_UART_RCLK_SI,
+ BCM_CHIPC_READ_4(bp, CHIPC_CLKDIV) & CHIPC_CLKD_UART,
+ bcm_get_sifreq(bp)
+ };
+
+ return (cfg);
+ }
+
+ /* UART uses fixed clock? */
+ if (cc_id->hwrev <= 2) {
+ cfg = (struct bcm_uart_clkcfg) {
+ BCM_UART_RCLK_FIXED,
+ BCM_UART_RCLK_FIXED_DIV,
+ BCM_UART_RCLK_FIXED_HZ
+ };
+
+ return (cfg);
+ }
+
+ /* All cases must be accounted for above */
+ panic("unreachable - no clock config");
+}
+
+/**
+ * Return the UART reference clock frequency (in Hz).
+ */
+u_int
+bcm_get_uart_rclk(struct bcm_platform *bp)
+{
+ struct bcm_uart_clkcfg cfg;
+
+ cfg = bcm_get_uart_clkcfg(bp);
+ return (cfg.freq / cfg.div);
+}
+
+/** ALP clock frequency (in Hz) */
+uint64_t
+bcm_get_alpfreq(struct bcm_platform *bp) {
+ if (!bcm_has_pmu(bp))
+ panic("%s requires PMU\n", __FUNCTION__);
+
+ return (bhnd_pmu_alp_clock(bcm_get_pmu(bp)));
+}
+
+/** ILP clock frequency (in Hz) */
+uint64_t
+bcm_get_ilpfreq(struct bcm_platform *bp) {
+ if (!bcm_has_pmu(bp))
+ panic("%s requires PMU\n", __FUNCTION__);
+
+ return (bhnd_pmu_ilp_clock(bcm_get_pmu(bp)));
+}
+
+/** CPU clock frequency (in Hz) */
+uint64_t
+bcm_get_cpufreq(struct bcm_platform *bp)
+{
+ uint32_t fixed_hz;
+ uint32_t n, m;
+ bus_size_t mreg;
+ uint8_t pll_type;
+
+ /* PMU support */
+ if (bcm_has_pmu(bp))
+ return (bhnd_pmu_cpu_clock(bcm_get_pmu(bp)));
+
+ /*
+ * PWRCTL support
+ */
+ pll_type = CHIPC_GET_BITS(bp->cc_caps, CHIPC_CAP_PLL);
+ mreg = bhnd_pwrctl_cpu_clkreg_m(&bp->id, pll_type, &fixed_hz);
+ if (mreg == 0)
+ return (fixed_hz);
+
+ n = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_N);
+ m = BCM_CHIPC_READ_4(bp, mreg);
+
+ return (bhnd_pwrctl_cpu_clock_rate(&bp->id, pll_type, n, m));
+
+}
+
+/** Backplane clock frequency (in Hz) */
+uint64_t
+bcm_get_sifreq(struct bcm_platform *bp)
+{
+ uint32_t fixed_hz;
+ uint32_t n, m;
+ bus_size_t mreg;
+ uint8_t pll_type;
+
+ /* PMU support */
+ if (bcm_has_pmu(bp))
+ return (bhnd_pmu_si_clock(bcm_get_pmu(bp)));
+
+ /*
+ * PWRCTL support
+ */
+ pll_type = CHIPC_GET_BITS(bp->cc_caps, CHIPC_CAP_PLL);
+ mreg = bhnd_pwrctl_si_clkreg_m(&bp->id, pll_type, &fixed_hz);
+ if (mreg == 0)
+ return (fixed_hz);
+
+ n = BCM_CHIPC_READ_4(bp, CHIPC_CLKC_N);
+ m = BCM_CHIPC_READ_4(bp, mreg);
+
+ return (bhnd_pwrctl_si_clock_rate(&bp->id, pll_type, n, m));
+}
+
+
+static uint32_t
+bcm_pmu_read4(bus_size_t reg, void *ctx) {
+ struct bcm_platform *bp = ctx;
+ return (readl(BCM_SOC_ADDR(bp->pmu_addr, reg)));
+}
+
+static void
+bcm_pmu_write4(bus_size_t reg, uint32_t val, void *ctx) {
+ struct bcm_platform *bp = ctx;
+ writel(BCM_SOC_ADDR(bp->pmu_addr, reg), val);
+}
+
+static uint32_t
+bcm_pmu_read_chipst(void *ctx)
+{
+ struct bcm_platform *bp = ctx;
+ return (readl(BCM_SOC_ADDR(bp->cc_addr, CHIPC_CHIPST)));
+}
Index: sys/mips/broadcom/bcm_socinfo.h
===================================================================
--- sys/mips/broadcom/bcm_socinfo.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-
- * Copyright (c) 2016 Michael Zhilin <mizhka@gmail.com>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * $FreeBSD$
- */
-
-#ifndef _MIPS_BROADCOM_BCM_SOCINFO_H_
-#define _MIPS_BROADCOM_BCM_SOCINFO_H_
-
-#include <machine/cpuregs.h>
-
-struct bcm_socinfo {
- uint32_t id;
- uint32_t cpurate; /* in MHz */
- uint32_t uartrate; /* in Hz */
- int double_count;
-};
-
-struct bcm_socinfo* bcm_get_socinfo_by_socid(uint32_t key);
-struct bcm_socinfo* bcm_get_socinfo(void);
-
-#endif /* _MIPS_BROADCOM_BCM_SOCINFO_H_ */
Index: sys/mips/broadcom/bcm_socinfo.c
===================================================================
--- sys/mips/broadcom/bcm_socinfo.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*-
- * Copyright (c) 2016 Michael Zhilin <mizhka@gmail.com>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-
-#include <dev/bhnd/cores/chipc/chipcreg.h>
-
-#include "bcm_machdep.h"
-#include "bcm_socinfo.h"
-
-/* found on https://wireless.wiki.kernel.org/en/users/drivers/b43/soc */
-struct bcm_socinfo bcm_socinfos[] = {
- {0x00005300, 600, 25000000, 1}, /* BCM4706 to check */
- {0x0022B83A, 300, 20000000, 1}, /* BCM4716B0 ASUS RT-N12 */
- {0x00914716, 354, 20000000, 1}, /* BCM4717A1 to check */
- {0x00A14716, 480, 20000000, 1}, /* BCM4718A1 ASUS RT-N16 */
- {0x00435356, 300, 25000000, 1}, /* BCM5356A1 (RT-N10, WNR1000v3) */
- {0x00825357, 500, 20000000, 1}, /* BCM5358UB0 ASUS RT-N53A1 */
- {0x00845357, 300, 20000000, 1}, /* BCM5357B0 to check */
- {0x00945357, 500, 20000000, 1}, /* BCM5358 */
- {0x00A45357, 500, 20000000, 1}, /* BCM47186B0 Tenda N60 */
- {0x0085D144, 300, 20000000, 1}, /* BCM5356C0 */
- {0x00B5D144, 300, 20000000, 1}, /* BCM5357C0 */
- {0x00015365, 200, 0, 1}, /* BCM5365 */
- {0,0,0}
-};
-
-/* Most popular BCM SoC info */
-struct bcm_socinfo BCM_DEFAULT_SOCINFO = {0x0, 300, 20000000, 0};
-
-struct bcm_socinfo*
-bcm_get_socinfo_by_socid(uint32_t key)
-{
- struct bcm_socinfo* start;
-
- if(!key)
- return (NULL);
-
- for(start = bcm_socinfos; start->id > 0; start++)
- if(start->id == key)
- return (start);
-
- return (NULL);
-}
-
-struct bcm_socinfo*
-bcm_get_socinfo(void)
-{
- uint32_t socid;
- struct bcm_socinfo *socinfo;
-
- /*
- * We need Chip ID + Revision + Package
- * --------------------------------------------------------------
- * | Mask | Usage |
- * --------------------------------------------------------------
- * | 0x0000FFFF | Chip ID |
- * | 0x000F0000 | Chip Revision |
- * | 0x00F00000 | Package Options |
- * | 0x0F000000 | Number of Cores (ChipCommon Rev. >= 4)|
- * | 0xF0000000 | Chip Type |
- * --------------------------------------------------------------
- */
-
- socid = BCM_CHIPC_READ_4(CHIPC_ID) & 0x00FFFFFF;
- socinfo = bcm_get_socinfo_by_socid(socid);
- return (socinfo != NULL) ? socinfo : &BCM_DEFAULT_SOCINFO;
-}
Index: sys/mips/broadcom/files.broadcom
===================================================================
--- sys/mips/broadcom/files.broadcom
+++ sys/mips/broadcom/files.broadcom
@@ -6,6 +6,7 @@
# which just need to be tweaked for attachment to an BHND system bus.
mips/broadcom/bcm_bcma.c optional bcma_nexus bcma
mips/broadcom/bcm_machdep.c standard
+mips/broadcom/bcm_pmu.c standard
mips/broadcom/bcm_siba.c optional siba_nexus siba
mips/mips/tick.c standard
mips/mips/mips_pic.c standard
@@ -16,7 +17,6 @@
mips/broadcom/uart_cpu_chipc.c optional uart
mips/broadcom/uart_bus_chipc.c optional uart
-mips/broadcom/bcm_socinfo.c standard
mips/broadcom/bcm_mipscore.c standard
# TODO: Replace with BCM47xx/57xx/etc-aware geom_map
Index: sys/mips/broadcom/uart_bus_chipc.c
===================================================================
--- sys/mips/broadcom/uart_bus_chipc.c
+++ sys/mips/broadcom/uart_bus_chipc.c
@@ -48,22 +48,20 @@
#include "uart_if.h"
#include "bhnd_chipc_if.h"
-#include "bcm_socinfo.h"
+#include "bcm_machdep.h"
static int
uart_chipc_probe(device_t dev)
{
struct uart_softc *sc;
- struct bcm_socinfo *socinfo;
+ u_int rclk;
sc = device_get_softc(dev);
sc->sc_class = &uart_ns8250_class;
- /* TODO: UART rate should be calculated from CPU clock speed
- * as fetched from bhnd bus */
- socinfo = bcm_get_socinfo();
- return (uart_bus_probe(dev, 0, socinfo->uartrate, 0, 0));
+ rclk = bcm_get_uart_rclk(bcm_get_platform());
+ return (uart_bus_probe(dev, 0, rclk, 0, 0));
}
static device_method_t uart_chipc_methods[] = {
Index: sys/mips/broadcom/uart_cpu_chipc.c
===================================================================
--- sys/mips/broadcom/uart_cpu_chipc.c
+++ sys/mips/broadcom/uart_cpu_chipc.c
@@ -52,7 +52,6 @@
#endif
#include "bcm_machdep.h"
-#include "bcm_socinfo.h"
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
@@ -70,19 +69,16 @@
static int
uart_cpu_init(struct uart_devinfo *di, u_int uart, int baudrate)
{
- struct bcm_socinfo *socinfo;
-
if (uart >= CHIPC_UART_MAX)
return (EINVAL);
- socinfo = bcm_get_socinfo();
di->ops = uart_getops(chipc_uart_class);
di->bas.chan = 0;
di->bas.bst = uart_bus_space_mem;
- di->bas.bsh = (bus_space_handle_t) BCM_CORE_ADDR(cc_addr,
- CHIPC_UART(uart));
+ di->bas.bsh = (bus_space_handle_t) BCM_CORE_ADDR(bcm_get_platform(),
+ cc_addr, CHIPC_UART(uart));
di->bas.regshft = 0;
- di->bas.rclk = socinfo->uartrate; /* in Hz */
+ di->bas.rclk = bcm_get_uart_rclk(bcm_get_platform());
di->baudrate = baudrate;
di->databits = 8;
di->stopbits = 1;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jan 19, 4:34 PM (17 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15949356
Default Alt Text
D7552.id19462.diff (63 KB)
Attached To
Mode
D7552: [mips/broadcom] Replace static frequency table with generic PMU clock handling.
Attached
Detach File
Event Timeline
Log In to Comment