1/*-
2 * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
3 * Copyright (c) 2010, Broadcom Corporation.
4 * All rights reserved.
5 *
6 * This file is derived from the siutils.c source distributed with the
7 * Asus RT-N16 firmware source code release.
8 *
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.
12 *
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.
20 *
21 * $Id: siutils.c,v 1.821.2.48 2011-02-11 20:59:28 Exp $
22 */
23
24#include <sys/param.h>
25#include <sys/kernel.h>
26#include <sys/bus.h>
27#include <sys/limits.h>
28#include <sys/malloc.h>
29#include <sys/module.h>
30#include <sys/systm.h>
31
32#include <dev/bhnd/bhnd.h>
33#include <dev/bhnd/bhndb/bhndb_pcireg.h>
34
35#include <dev/bhnd/cores/chipc/chipc.h>
36#include <dev/bhnd/cores/chipc/chipcreg.h>
37
38#include <dev/bhnd/cores/pmu/bhnd_pmuvar.h>
39#include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
40
41#include "bhnd_chipc_if.h"
42
43#include "bhnd_pwrctl_private.h"
44
45static uint32_t	bhnd_pwrctl_factor6(uint32_t x);
46
47/**
48 * Return the factor value corresponding to a given N3M clock control magic
49 * field value (CHIPC_F6_*).
50 */
51static uint32_t
52bhnd_pwrctl_factor6(uint32_t x)
53{
54	switch (x) {
55	case CHIPC_F6_2:
56		return (2);
57	case CHIPC_F6_3:
58		return (3);
59	case CHIPC_F6_4:
60		return (4);
61	case CHIPC_F6_5:
62		return (5);
63	case CHIPC_F6_6:
64		return (6);
65	case CHIPC_F6_7:
66		return (7);
67	default:
68		return (0);
69	}
70}
71
72/**
73 * Return the backplane clock's chipc 'M' register offset for a given PLL type,
74 * or 0 if a fixed clock speed should be used.
75 *
76 * @param cid Chip identification.
77 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
78 * @param[out] fixed_hz If 0 is returned, will be set to the fixed clock
79 * speed for this device.
80 */
81bus_size_t
82bhnd_pwrctl_si_clkreg_m(const struct bhnd_chipid *cid,
83    uint8_t pll_type, uint32_t *fixed_hz)
84{
85	switch (pll_type) {
86	case CHIPC_PLL_TYPE6:
87		return (CHIPC_CLKC_M3);
88	case CHIPC_PLL_TYPE3:
89		return (CHIPC_CLKC_M2);
90	default:
91		return (CHIPC_CLKC_SB);
92	}
93}
94
95/**
96 * Calculate the backplane clock speed (in Hz) for a given a set of clock
97 * control values.
98 *
99 * @param cid Chip identification.
100 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
101 * @param n clock control N register value.
102 * @param m clock control M register value.
103 */
104uint32_t
105bhnd_pwrctl_si_clock_rate(const struct bhnd_chipid *cid,
106    uint32_t pll_type, uint32_t n, uint32_t m)
107{
108	uint32_t rate;
109
110	KASSERT(bhnd_pwrctl_si_clkreg_m(cid, pll_type, NULL) != 0,
111	    ("can't compute clock rate on fixed clock"));
112
113	rate = bhnd_pwrctl_clock_rate(pll_type, n, m);
114	if (pll_type == CHIPC_PLL_TYPE3)
115		rate /= 2;
116
117	return (rate);
118}
119
120/**
121 * Return the CPU clock's chipc 'M' register offset for a given PLL type,
122 * or 0 if a fixed clock speed should be used.
123 *
124 * @param cid Chip identification.
125 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
126 * @param[out] fixed_hz If 0 is returned, will be set to the fixed clock
127 * speed for this device.
128 */
129bus_size_t
130bhnd_pwrctl_cpu_clkreg_m(const struct bhnd_chipid *cid,
131    uint8_t pll_type, uint32_t *fixed_hz)
132{
133	switch (pll_type) {
134	case CHIPC_PLL_TYPE2:
135	case CHIPC_PLL_TYPE4:
136	case CHIPC_PLL_TYPE6:
137	case CHIPC_PLL_TYPE7:
138		return (CHIPC_CLKC_M3);
139
140	case CHIPC_PLL_TYPE5:
141		/* fixed 200MHz */
142		if (fixed_hz != NULL)
143			*fixed_hz = 200 * 1000 * 1000;
144		return (0);
145
146	case CHIPC_PLL_TYPE3:
147		if (cid->chip_id == BHND_CHIPID_BCM5365) {
148			/* fixed 200MHz */
149			if (fixed_hz != NULL)
150				*fixed_hz = 200 * 1000 * 1000;
151			return (0);
152		}
153
154		return (CHIPC_CLKC_M2);
155
156	default:
157		return (CHIPC_CLKC_SB);
158	}
159}
160
161/**
162 * Calculate the CPU clock speed (in Hz) for a given a set of clock control
163 * values.
164 *
165 * @param cid Chip identification.
166 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
167 * @param n clock control N register value.
168 * @param m clock control M register value.
169 */
170uint32_t
171bhnd_pwrctl_cpu_clock_rate(const struct bhnd_chipid *cid,
172    uint32_t pll_type, uint32_t n, uint32_t m)
173{
174	KASSERT(bhnd_pwrctl_cpu_clkreg_m(cid, pll_type, NULL) != 0,
175	    ("can't compute clock rate on fixed clock"));
176
177	return (bhnd_pwrctl_clock_rate(pll_type, n, m));
178}
179
180/**
181 * Calculate the clock speed (in Hz) for a given a set of clockcontrol
182 * values.
183 *
184 * @param pll_type PLL type (CHIPC_PLL_TYPE*)
185 * @param n clock control N register value.
186 * @param m clock control M register value.
187 */
188uint32_t
189bhnd_pwrctl_clock_rate(uint32_t pll_type, uint32_t n, uint32_t m)
190{
191	uint32_t clk_base;
192	uint32_t n1, n2, clock, m1, m2, m3, mc;
193
194	n1 = CHIPC_GET_BITS(n, CHIPC_CN_N1);
195	n2 = CHIPC_GET_BITS(n, CHIPC_CN_N2);
196
197	switch (pll_type) {
198	case CHIPC_PLL_TYPE1:
199	case CHIPC_PLL_TYPE3:
200	case CHIPC_PLL_TYPE4:
201	case CHIPC_PLL_TYPE7:
202		n1 = bhnd_pwrctl_factor6(n1);
203		n2 += CHIPC_F5_BIAS;
204		break;
205
206	case CHIPC_PLL_TYPE2:
207		n1 += CHIPC_T2_BIAS;
208		n2 += CHIPC_T2_BIAS;
209		KASSERT(n1 >= 2 && n1 <= 7, ("invalid n1 value"));
210		KASSERT(n2 >= 5 && n2 <= 23, ("invalid n2 value"));
211		break;
212
213	case CHIPC_PLL_TYPE5:
214		return (100000000);
215
216	case CHIPC_PLL_TYPE6:
217		if (m & CHIPC_T6_MMASK)
218			return (CHIPC_T6_M1);
219		else
220			return (CHIPC_T6_M0);
221
222	default:
223		printf("unsupported PLL type %u\n", pll_type);
224		return (0);
225	}
226
227	/* PLL types 3 and 7 use BASE2 (25Mhz) */
228	if (pll_type == CHIPC_PLL_TYPE3 || pll_type == CHIPC_PLL_TYPE7) {
229		clk_base = CHIPC_CLOCK_BASE2;
230	} else {
231		clk_base = CHIPC_CLOCK_BASE1;
232	}
233
234	clock = clk_base * n1 * n2;
235
236	if (clock == 0)
237		return (0);
238
239	m1 = CHIPC_GET_BITS(m, CHIPC_M1);
240	m2 = CHIPC_GET_BITS(m, CHIPC_M2);
241	m3 = CHIPC_GET_BITS(m, CHIPC_M3);
242	mc = CHIPC_GET_BITS(m, CHIPC_MC);
243
244	switch (pll_type) {
245	case CHIPC_PLL_TYPE1:
246	case CHIPC_PLL_TYPE3:
247	case CHIPC_PLL_TYPE4:
248	case CHIPC_PLL_TYPE7:
249		m1 = bhnd_pwrctl_factor6(m1);
250		if (pll_type == CHIPC_PLL_TYPE1 || pll_type == CHIPC_PLL_TYPE3)
251			m2 += CHIPC_F5_BIAS;
252		else
253			m2 = bhnd_pwrctl_factor6(m2);
254
255		m3 = bhnd_pwrctl_factor6(m3);
256
257		switch (mc) {
258		case CHIPC_MC_BYPASS:
259			return (clock);
260		case CHIPC_MC_M1:
261			return (clock / m1);
262		case CHIPC_MC_M1M2:
263			return (clock / (m1 * m2));
264		case CHIPC_MC_M1M2M3:
265			return (clock / (m1 * m2 * m3));
266		case CHIPC_MC_M1M3:
267			return (clock / (m1 * m3));
268		default:
269			printf("unsupported pwrctl mc %#x\n", mc);
270			return (0);
271		}
272	case CHIPC_PLL_TYPE2:
273		m1 += CHIPC_T2_BIAS;
274		m2 += CHIPC_T2M2_BIAS;
275		m3 += CHIPC_T2_BIAS;
276		KASSERT(m1 >= 2 && m1 <= 7, ("invalid m1 value"));
277		KASSERT(m2 >= 3 && m2 <= 10, ("invalid m2 value"));
278		KASSERT(m3 >= 2 && m3 <= 7, ("invalid m3 value"));
279
280		if ((mc & CHIPC_T2MC_M1BYP) == 0)
281			clock /= m1;
282		if ((mc & CHIPC_T2MC_M2BYP) == 0)
283			clock /= m2;
284		if ((mc & CHIPC_T2MC_M3BYP) == 0)
285			clock /= m3;
286
287		return (clock);
288	default:
289		panic("unhandled PLL type %u\n", pll_type);
290	}
291}
292
293/**
294 * Return the backplane clock speed in Hz.
295 *
296 * @param sc driver instance state.
297 */
298uint32_t
299bhnd_pwrctl_getclk_speed(struct bhnd_pwrctl_softc *sc)
300{
301	const struct bhnd_chipid	*cid;
302	struct chipc_caps		*ccaps;
303	bus_size_t			 creg;
304	uint32_t 			 n, m;
305	uint32_t 			 rate;
306
307	PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
308
309	cid = bhnd_get_chipid(sc->chipc_dev);
310	ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev);
311
312	n = bhnd_bus_read_4(sc->res, CHIPC_CLKC_N);
313
314	/* Get M register offset */
315	creg = bhnd_pwrctl_si_clkreg_m(cid, ccaps->pll_type, &rate);
316	if (creg == 0) /* fixed rate */
317		return (rate);
318
319	/* calculate rate */
320	m = bhnd_bus_read_4(sc->res, creg);
321	return (bhnd_pwrctl_si_clock_rate(cid, ccaps->pll_type, n, m));
322}
323
324/* return the slow clock source */
325static bhnd_clksrc
326bhnd_pwrctl_slowclk_src(struct bhnd_pwrctl_softc *sc)
327{
328	uint32_t clkreg;
329	uint32_t clksrc;
330
331	/* Fetch clock source */
332	if (PWRCTL_QUIRK(sc, PCICLK_CTL)) {
333		return (bhnd_pwrctl_hostb_get_clksrc(sc->chipc_dev,
334		    BHND_CLOCK_ILP));
335	} else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
336		clkreg = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
337		clksrc = clkreg & CHIPC_SCC_SS_MASK;
338	} else {
339		/* Instaclock */
340		clksrc = CHIPC_SCC_SS_XTAL;
341	}
342
343	/* Map to bhnd_clksrc */
344	switch (clksrc) {
345	case CHIPC_SCC_SS_PCI:
346		return (BHND_CLKSRC_PCI);
347	case CHIPC_SCC_SS_LPO:
348		return (BHND_CLKSRC_LPO);
349	case CHIPC_SCC_SS_XTAL:
350		return (BHND_CLKSRC_XTAL);
351	default:
352		return (BHND_CLKSRC_UNKNOWN);
353	}
354}
355
356/* return the ILP (slowclock) min or max frequency */
357static uint32_t
358bhnd_pwrctl_slowclk_freq(struct bhnd_pwrctl_softc *sc, bool max_freq)
359{
360	bhnd_clksrc	slowclk;
361	uint32_t	div;
362	uint32_t	hz;
363
364	slowclk = bhnd_pwrctl_slowclk_src(sc);
365
366	/* Determine clock divisor */
367	if (PWRCTL_QUIRK(sc, PCICLK_CTL)) {
368		if (slowclk == BHND_CLKSRC_PCI)
369			div = 64;
370		else
371			div = 32;
372	} else if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
373		div = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
374		div = CHIPC_GET_BITS(div, CHIPC_SCC_CD);
375		div = 4 * (div + 1);
376	} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
377		if (max_freq) {
378			div = 1;
379		} else {
380			div = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL);
381			div = CHIPC_GET_BITS(div, CHIPC_SYCC_CD);
382			div = 4 * (div + 1);
383		}
384	} else {
385		device_printf(sc->dev, "unknown device type\n");
386		return (0);
387	}
388
389	/* Determine clock frequency */
390	switch (slowclk) {
391	case BHND_CLKSRC_LPO:
392		hz = max_freq ? CHIPC_LPOMAXFREQ : CHIPC_LPOMINFREQ;
393		break;
394	case BHND_CLKSRC_XTAL:
395		hz = max_freq ? CHIPC_XTALMAXFREQ : CHIPC_XTALMINFREQ;
396		break;
397	case BHND_CLKSRC_PCI:
398		hz = max_freq ? CHIPC_PCIMAXFREQ : CHIPC_PCIMINFREQ;
399		break;
400	default:
401		device_printf(sc->dev, "unknown slowclk source %#x\n", slowclk);
402		return (0);
403	}
404
405	return (hz / div);
406}
407
408/**
409 * Initialize power control registers.
410 */
411int
412bhnd_pwrctl_init(struct bhnd_pwrctl_softc *sc)
413{
414	uint32_t	clkctl;
415	uint32_t	pll_delay, slowclk, slowmaxfreq;
416	uint32_t 	pll_on_delay, fref_sel_delay;
417	int		error;
418
419	pll_delay = CHIPC_PLL_DELAY;
420
421	/* set all Instaclk chip ILP to 1 MHz */
422	if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
423		clkctl = (CHIPC_ILP_DIV_1MHZ << CHIPC_SYCC_CD_SHIFT);
424		clkctl &= CHIPC_SYCC_CD_MASK;
425		bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, clkctl);
426	}
427
428	/*
429	 * Initialize PLL/FREF delays.
430	 *
431	 * If the slow clock is not sourced by the xtal, include the
432	 * delay required to bring it up.
433	 */
434	slowclk = bhnd_pwrctl_slowclk_src(sc);
435	if (slowclk != CHIPC_SCC_SS_XTAL)
436		pll_delay += CHIPC_XTAL_ON_DELAY;
437
438	/* Starting with 4318 it is ILP that is used for the delays */
439	if (PWRCTL_QUIRK(sc, INSTACLK_CTL))
440		slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, false);
441	else
442		slowmaxfreq = bhnd_pwrctl_slowclk_freq(sc, true);
443
444	pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
445	fref_sel_delay = ((slowmaxfreq * CHIPC_FREF_DELAY) + 999999) / 1000000;
446
447	bhnd_bus_write_4(sc->res, CHIPC_PLL_ON_DELAY, pll_on_delay);
448	bhnd_bus_write_4(sc->res, CHIPC_PLL_FREFSEL_DELAY, fref_sel_delay);
449
450	/* If required, force HT */
451	if (PWRCTL_QUIRK(sc, FORCE_HT)) {
452		if ((error = bhnd_pwrctl_setclk(sc, BHND_CLOCK_HT)))
453			return (error);
454	}
455
456	return (0);
457}
458
459/* return the value suitable for writing to the dot11 core
460 * FAST_PWRUP_DELAY register */
461u_int
462bhnd_pwrctl_fast_pwrup_delay(struct bhnd_pwrctl_softc *sc)
463{
464	u_int pll_on_delay, slowminfreq;
465	u_int fpdelay;
466
467	fpdelay = 0;
468
469	slowminfreq = bhnd_pwrctl_slowclk_freq(sc, false);
470
471	pll_on_delay = bhnd_bus_read_4(sc->res, CHIPC_PLL_ON_DELAY) + 2;
472	pll_on_delay *= 1000000;
473	pll_on_delay += (slowminfreq - 1);
474	fpdelay = pll_on_delay / slowminfreq;
475
476	return (fpdelay);
477}
478
479/**
480 * Distribute @p clock on backplane.
481 *
482 * @param sc Driver instance state.
483 * @param clock Clock to enable.
484 *
485 * @retval 0 success
486 * @retval ENODEV If @p clock is unsupported, or if the device does not
487 * 		  support dynamic clock control.
488 */
489int
490bhnd_pwrctl_setclk(struct bhnd_pwrctl_softc *sc, bhnd_clock clock)
491{
492	uint32_t	scc;
493
494	PWRCTL_LOCK_ASSERT(sc, MA_OWNED);
495
496	/* Is dynamic clock control supported? */
497	if (PWRCTL_QUIRK(sc, FIXED_CLK))
498		return (ENODEV);
499
500	/* Chips with ccrev 10 are EOL and they don't have SYCC_HR used below */
501	if (bhnd_get_hwrev(sc->chipc_dev) == 10)
502		return (ENODEV);
503
504	if (PWRCTL_QUIRK(sc, SLOWCLK_CTL))
505		scc = bhnd_bus_read_4(sc->res, CHIPC_PLL_SLOWCLK_CTL);
506	else
507		scc = bhnd_bus_read_4(sc->res, CHIPC_SYS_CLK_CTL);
508
509	switch (clock) {
510	case BHND_CLOCK_HT:
511		/* fast (pll) clock */
512		if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
513			scc &= ~(CHIPC_SCC_XC | CHIPC_SCC_FS | CHIPC_SCC_IP);
514			scc |= CHIPC_SCC_IP;
515
516			/* force xtal back on before clearing SCC_DYN_XTAL.. */
517			bhnd_pwrctl_hostb_ungate_clock(sc->chipc_dev,
518			    BHND_CLOCK_HT);
519		} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
520			scc |= CHIPC_SYCC_HR;
521		} else {
522			return (ENODEV);
523		}
524
525		if (PWRCTL_QUIRK(sc, SLOWCLK_CTL))
526			bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc);
527		else
528			bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, scc);
529		DELAY(CHIPC_PLL_DELAY);
530
531		break;
532
533	case BHND_CLOCK_DYN:
534		/* enable dynamic clock control */
535		if (PWRCTL_QUIRK(sc, SLOWCLK_CTL)) {
536			scc &= ~(CHIPC_SCC_FS | CHIPC_SCC_IP | CHIPC_SCC_XC);
537			if ((scc & CHIPC_SCC_SS_MASK) != CHIPC_SCC_SS_XTAL)
538				scc |= CHIPC_SCC_XC;
539
540			bhnd_bus_write_4(sc->res, CHIPC_PLL_SLOWCLK_CTL, scc);
541
542			/* for dynamic control, we have to release our xtal_pu
543			 * "force on" */
544			if (scc & CHIPC_SCC_XC) {
545				bhnd_pwrctl_hostb_gate_clock(sc->chipc_dev,
546				    BHND_CLOCK_HT);
547			}
548		} else if (PWRCTL_QUIRK(sc, INSTACLK_CTL)) {
549			/* Instaclock */
550			scc &= ~CHIPC_SYCC_HR;
551			bhnd_bus_write_4(sc->res, CHIPC_SYS_CLK_CTL, scc);
552		} else {
553			return (ENODEV);
554		}
555
556		break;
557
558	default:
559		return (ENODEV);
560	}
561
562	return (0);
563}
564