2 * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
3 * Copyright (c) 2010, Broadcom Corporation.
6 * This file is derived from the siutils.c source distributed with the
7 * Asus RT-N16 firmware source code release.
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
16 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $
24 #include <sys/cdefs.h>
25 __FBSDID("$FreeBSD$");
27 #include <sys/param.h>
28 #include <sys/kernel.h>
30 #include <sys/limits.h>
31 #include <sys/malloc.h>
32 #include <sys/module.h>
33 #include <sys/systm.h>
35 #include <dev/bhnd/bhnd.h>
36 #include <dev/bhnd/bhndb/bhndb_pcireg.h>
38 #include <dev/bhnd/cores/chipc/chipc.h>
39 #include <dev/bhnd/cores/chipc/chipcreg.h>
41 #include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
42 #include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
44 #include "bhnd_chipc_if.h"
46 #include "bhnd_pwrctl_private.h"
48 static uint32_t bhnd_pwrctl_factor6(uint32_t x);
51 * Return the factor value corresponding to a given N3M clock control magic
52 * field value (CHIPC_F6_*).
55 bhnd_pwrctl_factor6(uint32_t x)
76 * Return the backplane clock's chipc 'M' register offset for a given PLL type,
77 * or 0 if a fixed clock speed should be used.
79 * @param cid Chip identification.
80 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
81 * @param[out] fixed_hz If 0 is returned, will be set to the fixed clock
82 * speed for this device.
85 bhnd_pwrctl_si_clkreg_m(const struct bhnd_chipid *cid,
86 uint8_t pll_type, uint32_t *fixed_hz)
90 return (CHIPC_CLKC_M3);
92 return (CHIPC_CLKC_M2);
94 return (CHIPC_CLKC_SB);
99 * Calculate the backplane clock speed (in Hz) for a given a set of clock
102 * @param cid Chip identification.
103 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
104 * @param n clock control N register value.
105 * @param m clock control M register value.
108 bhnd_pwrctl_si_clock_rate(const struct bhnd_chipid *cid,
109 uint32_t pll_type, uint32_t n, uint32_t m)
113 KASSERT(bhnd_pwrctl_si_clkreg_m(cid, pll_type, NULL) != 0,
114 ("can't compute clock rate on fixed clock"));
116 rate = bhnd_pwrctl_clock_rate(pll_type, n, m);
117 if (pll_type == CHIPC_PLL_TYPE3)
124 * Return the CPU clock's chipc 'M' register offset for a given PLL type,
125 * or 0 if a fixed clock speed should be used.
127 * @param cid Chip identification.
128 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
129 * @param[out] fixed_hz If 0 is returned, will be set to the fixed clock
130 * speed for this device.
133 bhnd_pwrctl_cpu_clkreg_m(const struct bhnd_chipid *cid,
134 uint8_t pll_type, uint32_t *fixed_hz)
137 case CHIPC_PLL_TYPE2:
138 case CHIPC_PLL_TYPE4:
139 case CHIPC_PLL_TYPE6:
140 case CHIPC_PLL_TYPE7:
141 return (CHIPC_CLKC_M3);
143 case CHIPC_PLL_TYPE5:
145 if (fixed_hz != NULL)
146 *fixed_hz = 200 * 1000 * 1000;
149 case CHIPC_PLL_TYPE3:
150 if (cid->chip_id == BHND_CHIPID_BCM5365) {
152 if (fixed_hz != NULL)
153 *fixed_hz = 200 * 1000 * 1000;
157 return (CHIPC_CLKC_M2);
160 return (CHIPC_CLKC_SB);
165 * Calculate the CPU clock speed (in Hz) for a given a set of clock control
168 * @param cid Chip identification.
169 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
170 * @param n clock control N register value.
171 * @param m clock control M register value.
174 bhnd_pwrctl_cpu_clock_rate(const struct bhnd_chipid *cid,
175 uint32_t pll_type, uint32_t n, uint32_t m)
177 KASSERT(bhnd_pwrctl_cpu_clkreg_m(cid, pll_type, NULL) != 0,
178 ("can't compute clock rate on fixed clock"));
180 return (bhnd_pwrctl_clock_rate(pll_type, n, m));
184 * Calculate the clock speed (in Hz) for a given a set of clockcontrol
187 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
188 * @param n clock control N register value.
189 * @param m clock control M register value.
192 bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n, uint32_t m)
195 uint32_t n1, n2, clock, m1, m2, m3, mc;
197 n1 = CHIPC_GET_BITS(n, CHIPC_CN_N1);
198 n2 = CHIPC_GET_BITS(n, CHIPC_CN_N2);
201 case CHIPC_PLL_TYPE1:
202 case CHIPC_PLL_TYPE3:
203 case CHIPC_PLL_TYPE4:
204 case CHIPC_PLL_TYPE7:
205 n1 = bhnd_pwrctl_factor6(n1);
209 case CHIPC_PLL_TYPE2:
212 KASSERT(n1 >= 2 && n1 <= 7, ("invalid n1 value"));
213 KASSERT(n2 >= 5 && n2 <= 23, ("invalid n2 value"));
216 case CHIPC_PLL_TYPE5:
219 case CHIPC_PLL_TYPE6:
220 if (m & CHIPC_T6_MMASK)
221 return (CHIPC_T6_M1);
223 return (CHIPC_T6_M0);
226 printf("unsupported PLL type %u\n", pll_type);
230 /* PLL types 3 and 7 use BASE2 (25Mhz) */
231 if (pll_type == CHIPC_PLL_TYPE3 || pll_type == CHIPC_PLL_TYPE7) {
232 clk_base = CHIPC_CLOCK_BASE2;
234 clk_base = CHIPC_CLOCK_BASE1;
237 clock = clk_base * n1 * n2;
242 m1 = CHIPC_GET_BITS(m, CHIPC_M1);
243 m2 = CHIPC_GET_BITS(m, CHIPC_M2);
244 m3 = CHIPC_GET_BITS(m, CHIPC_M3);
245 mc = CHIPC_GET_BITS(m, CHIPC_MC);
248 case CHIPC_PLL_TYPE1:
249 case CHIPC_PLL_TYPE3:
250 case CHIPC_PLL_TYPE4:
251 case CHIPC_PLL_TYPE7:
252 m1 = bhnd_pwrctl_factor6(m1);
253 if (pll_type == CHIPC_PLL_TYPE1 || pll_type == CHIPC_PLL_TYPE3)
256 m2 = bhnd_pwrctl_factor6(m2);
258 m3 = bhnd_pwrctl_factor6(m3);
261 case CHIPC_MC_BYPASS:
266 return (clock / (m1 * m2));
267 case CHIPC_MC_M1M2M3:
268 return (clock / (m1 * m2 * m3));
270 return (clock / (m1 * m3));
272 printf("unsupported pwrctl mc %#x\n", mc);
275 case CHIPC_PLL_TYPE2:
277 m2 += CHIPC_T2M2_BIAS;
279 KASSERT(m1 >= 2 && m1 <= 7, ("invalid m1 value"));
280 KASSERT(m2 >= 3 && m2 <= 10, ("invalid m2 value"));
281 KASSERT(m3 >= 2 && m3 <= 7, ("invalid m3 value"));
283 if ((mc & CHIPC_T2MC_M1BYP) == 0)
285 if ((mc & CHIPC_T2MC_M2BYP) == 0)
287 if ((mc & CHIPC_T2MC_M3BYP) == 0)
292 panic("unhandled PLL type %u\n", pll_type);
297 * Return the backplane clock speed in Hz.
299 * @param sc driver instance state.
302 bhnd_pwrctl_getclk_speed(struct bhnd_pwrctl_softc *sc)
304 const struct bhnd_chipid *cid;
305 struct chipc_caps *ccaps;
310 PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
312 cid = bhnd_get_chipid(sc->chipc_dev);
313 ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev);
315 n = bhnd_bus_read_4(sc->res, CHIPC_CLKC_N);
317 /* Get M register offset */
318 creg = bhnd_pwrctl_si_clkreg_m(cid, ccaps->pll_type, &rate);
319 if (creg == 0) /* fixed rate */
323 m = bhnd_bus_read_4(sc->res, creg);
324 return (bhnd_pwrctl_si_clock_rate(cid, ccaps->pll_type, n, m));
327 /* return the slow clock source */
329 bhnd_pwrctl_slowclk_src(struct bhnd_pwrctl_softc *sc)
334 /* Fetch clock source */
335 if (PWRCTL_QUIRK(sc, PCICLK_CTL)) {
336 return (bhnd_pwrctl_hostb_get_clksrc(sc->chipc_dev,
338 } else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
339 clkreg = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
340 clksrc = clkreg & CHIPC_SCC_SS_MASK;
343 clksrc = CHIPC_SCC_SS_XTAL;
346 /* Map to bhnd_clksrc */
348 case CHIPC_SCC_SS_PCI:
349 return (BHND_CLKSRC_PCI);
350 case CHIPC_SCC_SS_LPO:
351 return (BHND_CLKSRC_LPO);
352 case CHIPC_SCC_SS_XTAL:
353 return (BHND_CLKSRC_XTAL);
355 return (BHND_CLKSRC_UNKNOWN);
359 /* return the ILP (slowclock) min or max frequency */
361 bhnd_pwrctl_slowclk_freq(struct bhnd_pwrctl_softc *sc, bool max_freq)
367 slowclk = bhnd_pwrctl_slowclk_src(sc);
369 /* Determine clock divisor */
370 if (PWRCTL_QUIRK(sc, PCICLK_CTL)) {
371 if (slowclk == BHND_CLKSRC_PCI)
375 } else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
376 div = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
377 div = CHIPC_GET_BITS(div, CHIPC_SCC_CD);
379 } else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
383 div = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL);
384 div = CHIPC_GET_BITS(div, CHIPC_SYCC_CD);
388 device_printf(sc->dev, "unknown device type\n");
392 /* Determine clock frequency */
394 case BHND_CLKSRC_LPO:
395 hz = max_freq ? CHIPC_LPOMAXFREQ : CHIPC_LPOMINFREQ;
397 case BHND_CLKSRC_XTAL:
398 hz = max_freq ? CHIPC_XTALMAXFREQ : CHIPC_XTALMINFREQ;
400 case BHND_CLKSRC_PCI:
401 hz = max_freq ? CHIPC_PCIMAXFREQ : CHIPC_PCIMINFREQ;
404 device_printf(sc->dev, "unknown slowclk source %#x\n", slowclk);
412 * Initialize power control registers.
415 bhnd_pwrctl_init(struct bhnd_pwrctl_softc *sc)
418 uint32_t pll_delay, slowclk, slowmaxfreq;
419 uint32_t pll_on_delay, fref_sel_delay;
422 pll_delay = CHIPC_PLL_DELAY;
424 /* set all Instaclk chip ILP to 1 MHz */
425 if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
426 clkctl = (CHIPC_ILP_DIV_1MHZ << CHIPC_SYCC_CD_SHIFT);
427 clkctl &= CHIPC_SYCC_CD_MASK;
428 bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, clkctl);
432 * Initialize PLL/FREF delays.
434 * If the slow clock is not sourced by the xtal, include the
435 * delay required to bring it up.
437 slowclk = bhnd_pwrctl_slowclk_src(sc);
438 if (slowclk != CHIPC_SCC_SS_XTAL)
439 pll_delay += CHIPC_XTAL_ON_DELAY;
441 /* Starting with 4318 it is ILP that is used for the delays */
442 if (PWRCTL_QUIRK(sc, INSTACLK_CTL))
443 slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, false);
445 slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, true);
447 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
448 fref_sel_delay = ((slowmaxfreq * CHIPC_FREF_DELAY) + 999999) / 1000000;
450 bhnd_bus_write_4(sc->res, CHIPC_PLL_ON_DELAY, pll_on_delay);
451 bhnd_bus_write_4(sc->res, CHIPC_PLL_FREFSEL_DELAY, fref_sel_delay);
453 /* If required, force HT */
454 if (PWRCTL_QUIRK(sc, FORCE_HT)) {
455 if ((error = bhnd_pwrctl_setclk(sc, BHND_CLOCK_HT)))
462 /* return the value suitable for writing to the dot11 core
463 * FAST_PWRUP_DELAY register */
465 bhnd_pwrctl_fast_pwrup_delay(struct bhnd_pwrctl_softc *sc)
467 u_int pll_on_delay, slowminfreq;
472 slowminfreq = bhnd_pwrctl_slowclk_freq(sc, false);
474 pll_on_delay = bhnd_bus_read_4(sc->res, CHIPC_PLL_ON_DELAY) + 2;
475 pll_on_delay *= 1000000;
476 pll_on_delay += (slowminfreq - 1);
477 fpdelay = pll_on_delay / slowminfreq;
483 * Distribute @p clock on backplane.
485 * @param sc Driver instance state.
486 * @param clock Clock to enable.
489 * @retval ENODEV If @p clock is unsupported, or if the device does not
490 * support dynamic clock control.
493 bhnd_pwrctl_setclk(struct bhnd_pwrctl_softc *sc, bhnd_clock clock)
497 PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
499 /* Is dynamic clock control supported? */
500 if (PWRCTL_QUIRK(sc, FIXED_CLK))
503 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR used below */
504 if (bhnd_get_hwrev(sc->chipc_dev) == 10)
507 if (PWRCTL_QUIRK(sc, SLOWCLK_CTL))
508 scc = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
510 scc = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL);
514 /* fast (pll) clock */
515 if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
516 scc &= ~(CHIPC_SCC_XC | CHIPC_SCC_FS | CHIPC_SCC_IP);
519 /* force xtal back on before clearing SCC_DYN_XTAL.. */
520 bhnd_pwrctl_hostb_ungate_clock(sc->chipc_dev,
522 } else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
523 scc |= CHIPC_SYCC_HR;
528 if (PWRCTL_QUIRK(sc, SLOWCLK_CTL))
529 bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc);
531 bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, scc);
532 DELAY(CHIPC_PLL_DELAY);
537 /* enable dynamic clock control */
538 if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
539 scc &= ~(CHIPC_SCC_FS | CHIPC_SCC_IP | CHIPC_SCC_XC);
540 if ((scc & CHIPC_SCC_SS_MASK) != CHIPC_SCC_SS_XTAL)
543 bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc);
545 /* for dynamic control, we have to release our xtal_pu
547 if (scc & CHIPC_SCC_XC) {
548 bhnd_pwrctl_hostb_gate_clock(sc->chipc_dev,
551 } else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
553 scc &= ~CHIPC_SYCC_HR;
554 bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, scc);