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