]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c
SPDX: license IDs for some ISC-related files.
[FreeBSD/FreeBSD.git] / sys / dev / bhnd / cores / chipc / pwrctl / bhnd_pwrctl_subr.c
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
48 static 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  */
54 static uint32_t
55 bhnd_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  */
84 bus_size_t
85 bhnd_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  */
107 uint32_t
108 bhnd_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  */
132 bus_size_t
133 bhnd_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  */
173 uint32_t
174 bhnd_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  */
191 uint32_t
192 bhnd_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  */
301 uint32_t
302 bhnd_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 */
328 static bhnd_clksrc
329 bhnd_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 */
360 static uint32_t
361 bhnd_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  */
414 int
415 bhnd_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 */
464 u_int
465 bhnd_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  */
492 int
493 bhnd_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 }