get rid of $Id$ - it has never helped us and it has broken too many patches ;)
[openwrt.git] / target / linux / brcm-2.4 / files / arch / mips / bcm947xx / hndpmu.c
1 /*
2  * Misc utility routines for accessing PMU corerev specific features
3  * of the SiliconBackplane-based Broadcom chips.
4  *
5  * Copyright 2007, Broadcom Corporation
6  * All Rights Reserved.
7  * 
8  * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
9  * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
10  * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
11  * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
12  */
13
14 #include <typedefs.h>
15 #include <bcmdefs.h>
16 #include <osl.h>
17 #include <sbutils.h>
18 #include <bcmdevs.h>
19 #include <sbconfig.h>
20 #include <sbchipc.h>
21 #include <hndpmu.h>
22
23 /* debug/trace */
24 #define PMU_ERROR(args)
25
26 #ifdef BCMDBG
27 #define PMU_MSG(args)   printf args
28 #else
29 #define PMU_MSG(args)
30 #endif /* BCMDBG */
31
32 /* PMU & control */
33 /* PMU rev 0 pll control for BCM4328 and BCM5354 */
34 static void sb_pmu0_pllinit0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc,
35                               uint32 xtal);
36 static uint32 sb_pmu0_alpclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc);
37 static uint32 sb_pmu0_cpuclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc);
38 /* PMU rev 0 pll control for BCM4325 BCM4329 */
39 static void sb_pmu1_pllinit0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc,
40                               uint32 xtal);
41 static uint32 sb_pmu1_cpuclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc);
42 static uint32 sb_pmu1_alpclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc);
43
44 /* Setup switcher voltage */
45 void
46 BCMINITFN (sb_pmu_set_switcher_voltage) (sb_t * sbh, osl_t * osh,
47                                          uint8 bb_voltage, uint8 rf_voltage)
48 {
49   chipcregs_t *cc;
50   uint origidx;
51
52   ASSERT (sbh->cccaps & CC_CAP_PMU);
53
54   /* Remember original core before switch to chipc */
55   origidx = sb_coreidx (sbh);
56   cc = sb_setcore (sbh, SB_CC, 0);
57   ASSERT (cc);
58
59   W_REG (osh, &cc->regcontrol_addr, 0x01);
60   W_REG (osh, &cc->regcontrol_data, (uint32) (bb_voltage & 0x1f) << 22);
61
62   W_REG (osh, &cc->regcontrol_addr, 0x00);
63   W_REG (osh, &cc->regcontrol_data, (uint32) (rf_voltage & 0x1f) << 14);
64
65   /* Return to original core */
66   sb_setcoreidx (sbh, origidx);
67 }
68
69 void
70 sb_pmu_set_ldo_voltage (sb_t * sbh, osl_t * osh, uint8 ldo, uint8 voltage)
71 {
72   uint8 sr_cntl_shift, rc_shift, shift, mask;
73   uint32 addr;
74
75   ASSERT (sbh->cccaps & CC_CAP_PMU);
76
77   switch (sbh->chip)
78     {
79     case BCM4328_CHIP_ID:
80     case BCM5354_CHIP_ID:
81       switch (ldo)
82         {
83         case SET_LDO_VOLTAGE_LDO1:
84           addr = 2;
85           sr_cntl_shift = 8;
86           rc_shift = 17;
87           mask = 0xf;
88           break;
89         case SET_LDO_VOLTAGE_LDO2:
90           addr = 3;
91           sr_cntl_shift = 0;
92           rc_shift = 1;
93           mask = 0xf;
94           break;
95         case SET_LDO_VOLTAGE_LDO3:
96           addr = 3;
97           sr_cntl_shift = 0;
98           rc_shift = 9;
99           mask = 0xf;
100           break;
101         case SET_LDO_VOLTAGE_PAREF:
102           addr = 3;
103           sr_cntl_shift = 0;
104           rc_shift = 17;
105           mask = 0x3f;
106           break;
107         default:
108           ASSERT (FALSE);
109           return;
110         }
111       break;
112     case BCM4312_CHIP_ID:
113       switch (ldo)
114         {
115         case SET_LDO_VOLTAGE_PAREF:
116           addr = 0;
117           sr_cntl_shift = 0;
118           rc_shift = 21;
119           mask = 0x3f;
120           break;
121         default:
122           ASSERT (FALSE);
123           return;
124         }
125       break;
126     default:
127       ASSERT (FALSE);
128       return;
129     }
130
131   shift = sr_cntl_shift + rc_shift;
132
133   sb_corereg (sbh, SB_CC_IDX, OFFSETOF (chipcregs_t, regcontrol_addr),
134               ~0, addr);
135   sb_corereg (sbh, SB_CC_IDX, OFFSETOF (chipcregs_t, regcontrol_data),
136               mask << shift, (voltage & mask) << shift);
137 }
138
139 void
140 sb_pmu_paref_ldo_enable (sb_t * sbh, osl_t * osh, bool enable)
141 {
142   uint ldo = 0;
143
144   ASSERT (sbh->cccaps & CC_CAP_PMU);
145
146   switch (sbh->chip)
147     {
148     case BCM4328_CHIP_ID:
149       ldo = RES4328_PA_REF_LDO;
150       break;
151     case BCM5354_CHIP_ID:
152       ldo = RES5354_PA_REF_LDO;
153       break;
154     case BCM4312_CHIP_ID:
155       ldo = RES4312_PA_REF_LDO;
156       break;
157     default:
158       return;
159     }
160
161   sb_corereg (sbh, SB_CC_IDX, OFFSETOF (chipcregs_t, min_res_mask),
162               PMURES_BIT (ldo), enable ? PMURES_BIT (ldo) : 0);
163 }
164
165 uint16 BCMINITFN (sb_pmu_fast_pwrup_delay) (sb_t * sbh, osl_t * osh)
166 {
167   uint16 delay = PMU_MAX_TRANSITION_DLY;
168
169   ASSERT (sbh->cccaps & CC_CAP_PMU);
170
171   switch (sbh->chip)
172     {
173     case BCM4328_CHIP_ID:
174       delay = 7000;
175       break;
176
177     case BCM4325_CHIP_ID:
178     case BCM4312_CHIP_ID:
179 #ifdef BCMQT
180       delay = 70;
181 #else
182       delay = 2800;
183 #endif
184       break;
185
186     default:
187       PMU_MSG (("No PMU fast power up delay specified "
188                 "for chip %x rev %d, using default %d us\n",
189                 sbh->chip, sbh->chiprev, delay));
190       break;
191     }
192
193   return delay;
194 }
195
196 uint32 BCMINITFN (sb_pmu_force_ilp) (sb_t * sbh, osl_t * osh, bool force)
197 {
198   chipcregs_t *cc;
199   uint origidx;
200   uint32 oldpmucontrol;
201
202   ASSERT (sbh->cccaps & CC_CAP_PMU);
203
204   /* Remember original core before switch to chipc */
205   origidx = sb_coreidx (sbh);
206   cc = sb_setcore (sbh, SB_CC, 0);
207   ASSERT (cc);
208
209   oldpmucontrol = R_REG (osh, &cc->pmucontrol);
210   if (force)
211     W_REG (osh, &cc->pmucontrol, oldpmucontrol &
212            ~(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
213   else
214     W_REG (osh, &cc->pmucontrol, oldpmucontrol |
215            (PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
216
217   /* Return to original core */
218   sb_setcoreidx (sbh, origidx);
219
220   return oldpmucontrol;
221 }
222
223 /* Setup min/max resources and up/down timers */
224 typedef struct
225 {
226   uint8 resnum;
227   uint16 updown;
228 } pmu_res_updown_t;
229
230 typedef struct
231 {
232   uint8 resnum;
233   int8 action;                  /* 0 - set, 1 - add, -1 - remove */
234   uint32 depend_mask;
235 } pmu_res_depend_t;
236
237 static const pmu_res_updown_t
238 BCMINITDATA (bcm4328a0_res_updown)[] =
239 {
240   {
241   RES4328_EXT_SWITCHER_PWM, 0x0101},
242   {
243   RES4328_BB_SWITCHER_PWM, 0x1f01},
244   {
245   RES4328_BB_SWITCHER_BURST, 0x010f},
246   {
247   RES4328_BB_EXT_SWITCHER_BURST, 0x0101},
248   {
249   RES4328_ILP_REQUEST, 0x0202},
250   {
251   RES4328_RADIO_SWITCHER_PWM, 0x0f01},
252   {
253   RES4328_RADIO_SWITCHER_BURST, 0x0f01},
254   {
255   RES4328_ROM_SWITCH, 0x0101},
256   {
257   RES4328_PA_REF_LDO, 0x0f01},
258   {
259   RES4328_RADIO_LDO, 0x0f01},
260   {
261   RES4328_AFE_LDO, 0x0f01},
262   {
263   RES4328_PLL_LDO, 0x0f01},
264   {
265   RES4328_BG_FILTBYP, 0x0101},
266   {
267   RES4328_TX_FILTBYP, 0x0101},
268   {
269   RES4328_RX_FILTBYP, 0x0101},
270   {
271   RES4328_XTAL_PU, 0x0101},
272   {
273   RES4328_XTAL_EN, 0xa001},
274   {
275   RES4328_BB_PLL_FILTBYP, 0x0101},
276   {
277   RES4328_RF_PLL_FILTBYP, 0x0101},
278   {
279   RES4328_BB_PLL_PU, 0x0701}
280 };
281
282 static const pmu_res_depend_t
283 BCMINITDATA (bcm4328a0_res_depend)[] =
284 {
285   /* Adjust ILP request resource not to force ext/BB switchers into burst mode */
286   {
287   RES4328_ILP_REQUEST, 0,
288       PMURES_BIT (RES4328_EXT_SWITCHER_PWM) |
289       PMURES_BIT (RES4328_BB_SWITCHER_PWM)}
290 };
291
292 #ifdef BCMQT                    /* for power save on slow QT/small beacon interval */
293 static const pmu_res_updown_t
294 BCMINITDATA (bcm4325a0_res_updown_qt)[] =
295 {
296   {
297   RES4325_HT_AVAIL, 0x0300},
298   {
299   RES4325_BBPLL_PWRSW_PU, 0x0101},
300   {
301   RES4325_RFPLL_PWRSW_PU, 0x0101},
302   {
303   RES4325_ALP_AVAIL, 0x0100},
304   {
305   RES4325_XTAL_PU, 0x1000},
306   {
307   RES4325_LNLDO1_PU, 0x0800},
308   {
309   RES4325_CLDO_CBUCK_PWM, 0x0101},
310   {
311   RES4325_CBUCK_PWM, 0x0803}
312 };
313 #else
314 static const pmu_res_updown_t
315 BCMINITDATA (bcm4325a0_res_updown)[] =
316 {
317   {
318   RES4325_XTAL_PU, 0x1501}
319 };
320 #endif /* !BCMQT */
321
322 static const pmu_res_depend_t
323 BCMINITDATA (bcm4325a0_res_depend)[] =
324 {
325   /* Adjust HT Avail resource dependencies */
326   {
327   RES4325_HT_AVAIL, 1,
328       PMURES_BIT (RES4325_RX_PWRSW_PU) | PMURES_BIT (RES4325_TX_PWRSW_PU) |
329       PMURES_BIT (RES4325_LOGEN_PWRSW_PU) | PMURES_BIT (RES4325_AFE_PWRSW_PU)}
330 };
331
332 void BCMINITFN (sb_pmu_res_init) (sb_t * sbh, osl_t * osh)
333 {
334   chipcregs_t *cc;
335   uint origidx;
336   const pmu_res_updown_t *pmu_res_updown_table = NULL;
337   int pmu_res_updown_table_sz = 0;
338   const pmu_res_depend_t *pmu_res_depend_table = NULL;
339   int pmu_res_depend_table_sz = 0;
340   uint32 min_mask = 0, max_mask = 0;
341
342   ASSERT (sbh->cccaps & CC_CAP_PMU);
343
344   /* Remember original core before switch to chipc */
345   origidx = sb_coreidx (sbh);
346   cc = sb_setcore (sbh, SB_CC, 0);
347   ASSERT (cc);
348
349   switch (sbh->chip)
350     {
351     case BCM4328_CHIP_ID:
352       /* Down to ILP request excluding ROM */
353       min_mask = PMURES_BIT (RES4328_EXT_SWITCHER_PWM) |
354         PMURES_BIT (RES4328_BB_SWITCHER_PWM) | PMURES_BIT (RES4328_XTAL_EN);
355 #ifdef BCMROMOFFLOAD
356       /* Including ROM */
357       min_mask |= PMURES_BIT (RES4328_ROM_SWITCH);
358 #endif
359       /* Allow (but don't require) PLL to turn on */
360       max_mask = 0xfffff;
361       pmu_res_updown_table = bcm4328a0_res_updown;
362       pmu_res_updown_table_sz = ARRAYSIZE (bcm4328a0_res_updown);
363       pmu_res_depend_table = bcm4328a0_res_depend;
364       pmu_res_depend_table_sz = ARRAYSIZE (bcm4328a0_res_depend);
365       break;
366     case BCM4312_CHIP_ID:
367       /* keep default
368        * min_mask = 0xcbb; max_mask = 0x7ffff;
369        * pmu_res_updown_table_sz = 0;
370        * pmu_res_depend_table_sz = 0;
371        */
372       break;
373     case BCM5354_CHIP_ID:
374       /* Allow (but don't require) PLL to turn on */
375       max_mask = 0xfffff;
376       break;
377
378     case BCM4325_CHIP_ID:
379       /* Leave OTP powered up and power it down later. */
380       min_mask =
381         PMURES_BIT (RES4325_CBUCK_BURST) | PMURES_BIT (RES4325_LNLDO2_PU);
382       if (((sbh->chipst & CST4325_PMUTOP_2B_MASK) >>
383            CST4325_PMUTOP_2B_SHIFT) == 1)
384         min_mask |= PMURES_BIT (RES4325_CLDO_CBUCK_BURST);
385       /* Allow (but don't require) PLL to turn on */
386       max_mask = 0x3fffff;
387 #ifdef BCMQT
388       pmu_res_updown_table = bcm4325a0_res_updown_qt;
389       pmu_res_updown_table_sz = ARRAYSIZE (bcm4325a0_res_updown_qt);
390 #else
391       pmu_res_updown_table = bcm4325a0_res_updown;
392       pmu_res_updown_table_sz = ARRAYSIZE (bcm4325a0_res_updown);
393       pmu_res_depend_table = bcm4325a0_res_depend;
394       pmu_res_depend_table_sz = ARRAYSIZE (bcm4325a0_res_depend);
395 #endif
396       break;
397
398     default:
399       break;
400     }
401
402   /* Program up/down timers */
403   while (pmu_res_updown_table_sz--)
404     {
405       ASSERT (pmu_res_updown_table);
406       W_REG (osh, &cc->res_table_sel,
407              pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
408       W_REG (osh, &cc->res_updn_timer,
409              pmu_res_updown_table[pmu_res_updown_table_sz].updown);
410     }
411
412   /* Program resource dependencies table */
413   while (pmu_res_depend_table_sz--)
414     {
415       ASSERT (pmu_res_depend_table);
416       W_REG (osh, &cc->res_table_sel,
417              pmu_res_depend_table[pmu_res_depend_table_sz].resnum);
418       switch (pmu_res_depend_table[pmu_res_depend_table_sz].action)
419         {
420         case 0:
421           W_REG (osh, &cc->res_dep_mask,
422                  pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
423           break;
424         case 1:
425           OR_REG (osh, &cc->res_dep_mask,
426                   pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
427           break;
428         case -1:
429           AND_REG (osh, &cc->res_dep_mask,
430                    ~pmu_res_depend_table[pmu_res_depend_table_sz].
431                    depend_mask);
432           break;
433         default:
434           ASSERT (0);
435           break;
436         }
437     }
438
439   /* program min resource mask */
440   if (min_mask)
441     {
442       PMU_MSG (("Changing min_res_mask to 0x%x\n", min_mask));
443       W_REG (osh, &cc->min_res_mask, min_mask);
444     }
445   /* program max resource mask */
446   if (max_mask)
447     {
448       PMU_MSG (("Changing max_res_mask to 0x%x\n", max_mask));
449       W_REG (osh, &cc->max_res_mask, max_mask);
450     }
451
452   /* Return to original core */
453   sb_setcoreidx (sbh, origidx);
454 }
455
456 /* setup pll and query clock speed */
457 typedef struct
458 {
459   uint16 freq;
460   uint8 xf;
461   uint8 wbint;
462   uint32 wbfrac;
463 } pmu0_xtaltab0_t;
464
465 /* the following table is based on 880Mhz Fvco */
466 #define PMU0_PLL0_FVCO  880000  /* Fvco 880Mhz */
467 static const pmu0_xtaltab0_t
468 BCMINITDATA (pmu0_xtaltab0)[] =
469 {
470   {
471   12000, 1, 73, 349525},
472   {
473   13000, 2, 67, 725937},
474   {
475   14400, 3, 61, 116508},
476   {
477   15360, 4, 57, 305834},
478   {
479   16200, 5, 54, 336579},
480   {
481   16800, 6, 52, 399457},
482   {
483   19200, 7, 45, 873813},
484   {
485   19800, 8, 44, 466033},
486   {
487   20000, 9, 44, 0},
488   {
489   25000, 10, 70, 419430},
490   {
491   26000, 11, 67, 725937},
492   {
493   30000, 12, 58, 699050},
494   {
495   38400, 13, 45, 873813},
496   {
497   40000, 14, 45, 0},
498   {
499   0, 0, 0, 0}
500 };
501
502 #ifdef BCMUSBDEV
503 #define PMU0_XTAL0_DEFAULT      11
504 #else
505 #define PMU0_XTAL0_DEFAULT      8
506 #endif
507
508 #ifdef BCMUSBDEV
509 /*
510  * Set new backplane PLL clock frequency
511  */
512 static void BCMINITFN (sb_pmu0_sbclk4328) (sb_t * sbh, int freq)
513 {
514   uint32 tmp, oldmax, oldmin, origidx;
515   chipcregs_t *cc;
516
517   /* Remember original core before switch to chipc */
518   origidx = sb_coreidx (sbh);
519   cc = sb_setcore (sbh, SB_CC, 0);
520   ASSERT (cc);
521
522   /* Set new backplane PLL clock */
523   W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
524   tmp = R_REG (osh, &cc->pllcontrol_data);
525   tmp &= ~(PMU0_PLL0_PC0_DIV_ARM_MASK);
526   tmp |= freq << PMU0_PLL0_PC0_DIV_ARM_SHIFT;
527   W_REG (osh, &cc->pllcontrol_data, tmp);
528
529   /* Power cycle BB_PLL_PU by disabling/enabling it to take on new freq */
530   /* Disable PLL */
531   oldmin = R_REG (osh, &cc->min_res_mask);
532   oldmax = R_REG (osh, &cc->max_res_mask);
533   W_REG (osh, &cc->min_res_mask, oldmin & ~PMURES_BIT (RES4328_BB_PLL_PU));
534   W_REG (osh, &cc->max_res_mask, oldmax & ~PMURES_BIT (RES4328_BB_PLL_PU));
535
536   /* It takes over several hundred usec to re-enable the PLL since the
537    * sequencer state machines run on ILP clock. Set delay at 450us to be safe.
538    *
539    * Be sure PLL is powered down first before re-enabling it.
540    */
541
542   OSL_DELAY (PLL_DELAY);
543   SPINWAIT ((R_REG (osh, &cc->res_state) & PMURES_BIT (RES4328_BB_PLL_PU)),
544             PLL_DELAY * 3);
545
546   if (R_REG (osh, &cc->res_state) & PMURES_BIT (RES4328_BB_PLL_PU))
547     {
548       /* If BB_PLL not powered down yet, new backplane PLL clock
549        *  may not take effect.
550        *
551        * Still early during bootup so no serial output here.
552        */
553       PMU_ERROR (("Fatal: BB_PLL not power down yet!\n"));
554       ASSERT (!
555               (R_REG (osh, &cc->res_state) & PMURES_BIT (RES4328_BB_PLL_PU)));
556     }
557
558   /* Enable PLL */
559   W_REG (osh, &cc->max_res_mask, oldmax);
560
561   /* Return to original core */
562   sb_setcoreidx (sbh, origidx);
563 }
564 #endif /* BCMUSBDEV */
565
566 /* Set up PLL registers in the PMU as per the crystal speed.
567  * Uses xtalfreq variable, or passed-in default.
568  */
569 static void
570 BCMINITFN (sb_pmu0_pllinit0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc,
571                               uint32 xtal)
572 {
573   uint32 tmp;
574   const pmu0_xtaltab0_t *xt;
575
576   if ((sb_chip (sbh) == BCM5354_CHIP_ID) && (xtal == 0))
577     {
578       /* 5354 has xtal freq of 25MHz */
579       xtal = 25000;
580     }
581
582   /* Find the frequency in the table */
583   for (xt = pmu0_xtaltab0; xt->freq; xt++)
584     if (xt->freq == xtal)
585       break;
586   if (xt->freq == 0)
587     xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
588
589   PMU_MSG (("XTAL %d (%d)\n", xtal, xt->xf));
590
591   /* Check current PLL state */
592   tmp = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
593     PCTL_XTALFREQ_SHIFT;
594   if (tmp == xt->xf)
595     {
596       PMU_MSG (("PLL already programmed for %d.%d MHz\n",
597                 (xt->freq / 1000), (xt->freq % 1000)));
598
599 #ifdef BCMUSBDEV
600       if (sbh->chip == BCM4328_CHIP_ID)
601         sb_pmu0_sbclk4328 (sbh, PMU0_PLL0_PC0_DIV_ARM_88MHZ);
602 #endif
603       return;
604     }
605
606   if (tmp)
607     {
608       PMU_MSG (("Reprogramming PLL for %d.%d MHz (was %d.%dMHz)\n",
609                 (xt->freq / 1000), (xt->freq % 1000),
610                 (pmu0_xtaltab0[tmp - 1].freq / 1000),
611                 (pmu0_xtaltab0[tmp - 1].freq % 1000)));
612     }
613   else
614     {
615       PMU_MSG (("Programming PLL for %d.%d MHz\n", (xt->freq / 1000),
616                 (xt->freq % 1000)));
617     }
618
619   /* Make sure the PLL is off */
620   switch (sbh->chip)
621     {
622     case BCM4328_CHIP_ID:
623       AND_REG (osh, &cc->min_res_mask, ~PMURES_BIT (RES4328_BB_PLL_PU));
624       AND_REG (osh, &cc->max_res_mask, ~PMURES_BIT (RES4328_BB_PLL_PU));
625       break;
626     case BCM5354_CHIP_ID:
627       AND_REG (osh, &cc->min_res_mask, ~PMURES_BIT (RES5354_BB_PLL_PU));
628       AND_REG (osh, &cc->max_res_mask, ~PMURES_BIT (RES5354_BB_PLL_PU));
629       break;
630     default:
631       ASSERT (0);
632     }
633   SPINWAIT (R_REG (osh, &cc->clk_ctl_st) & CCS0_HTAVAIL,
634             PMU_MAX_TRANSITION_DLY);
635   ASSERT (!(R_REG (osh, &cc->clk_ctl_st) & CCS0_HTAVAIL));
636
637   PMU_MSG (("Done masking\n"));
638
639   /* Write PDIV in pllcontrol[0] */
640   W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
641   tmp = R_REG (osh, &cc->pllcontrol_data);
642   if (xt->freq >= PMU0_PLL0_PC0_PDIV_FREQ)
643     tmp |= PMU0_PLL0_PC0_PDIV_MASK;
644   else
645     tmp &= ~PMU0_PLL0_PC0_PDIV_MASK;
646   W_REG (osh, &cc->pllcontrol_data, tmp);
647
648   /* Write WILD in pllcontrol[1] */
649   W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
650   tmp = R_REG (osh, &cc->pllcontrol_data);
651   tmp =
652     ((tmp & ~(PMU0_PLL0_PC1_WILD_INT_MASK | PMU0_PLL0_PC1_WILD_FRAC_MASK)) |
653      (((xt->
654         wbint << PMU0_PLL0_PC1_WILD_INT_SHIFT) & PMU0_PLL0_PC1_WILD_INT_MASK)
655       | ((xt->wbfrac << PMU0_PLL0_PC1_WILD_FRAC_SHIFT) &
656          PMU0_PLL0_PC1_WILD_FRAC_MASK)));
657   if (xt->wbfrac == 0)
658     tmp |= PMU0_PLL0_PC1_STOP_MOD;
659   else
660     tmp &= ~PMU0_PLL0_PC1_STOP_MOD;
661   W_REG (osh, &cc->pllcontrol_data, tmp);
662
663   /* Write WILD in pllcontrol[2] */
664   W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
665   tmp = R_REG (osh, &cc->pllcontrol_data);
666   tmp = ((tmp & ~PMU0_PLL0_PC2_WILD_INT_MASK) |
667          ((xt->wbint >> PMU0_PLL0_PC2_WILD_INT_SHIFT) &
668           PMU0_PLL0_PC2_WILD_INT_MASK));
669   W_REG (osh, &cc->pllcontrol_data, tmp);
670
671   PMU_MSG (("Done pll\n"));
672
673   /* Write XtalFreq. Set the divisor also. */
674   tmp = R_REG (osh, &cc->pmucontrol);
675   tmp = ((tmp & ~PCTL_ILP_DIV_MASK) |
676          (((((xt->freq + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
677           PCTL_ILP_DIV_MASK));
678   tmp = ((tmp & ~PCTL_XTALFREQ_MASK) |
679          ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK));
680   W_REG (osh, &cc->pmucontrol, tmp);
681 }
682
683 static uint32
684 BCMINITFN (sb_pmu0_alpclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc)
685 {
686   const pmu0_xtaltab0_t *xt;
687   uint32 xf;
688
689   /* Find the frequency in the table */
690   xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
691     PCTL_XTALFREQ_SHIFT;
692   for (xt = pmu0_xtaltab0; xt->freq; xt++)
693     if (xt->xf == xf)
694       break;
695   if (xt->freq == 0)
696     xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
697
698   return xt->freq * 1000;
699 }
700
701 static uint32
702 BCMINITFN (sb_pmu0_cpuclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc)
703 {
704   const pmu0_xtaltab0_t *xt;
705   uint32 xf, tmp, divarm;
706 #ifdef BCMDBG
707   uint32 pdiv, wbint, wbfrac, fvco;
708 #endif
709
710   if (sb_chip (sbh) == BCM5354_CHIP_ID)
711     {
712       /* 5354 gets sb clock of 120MHz from main pll */
713       return 120000000;
714     }
715
716   /* Find the xtal frequency in the table */
717   xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
718     PCTL_XTALFREQ_SHIFT;
719   for (xt = pmu0_xtaltab0; xt->freq; xt++)
720     if (xt->xf == xf)
721       break;
722   if (xt->freq == 0)
723     xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
724
725   /* Read divarm from pllcontrol[0] */
726   W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
727   tmp = R_REG (osh, &cc->pllcontrol_data);
728   divarm = (tmp & PMU0_PLL0_PC0_DIV_ARM_MASK) >> PMU0_PLL0_PC0_DIV_ARM_SHIFT;
729
730 #ifdef BCMDBG
731   /* Calculate Fvco based on xtal freq, pdiv, and wild */
732   pdiv = tmp & PMU0_PLL0_PC0_PDIV_MASK;
733
734   W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
735   tmp = R_REG (osh, &cc->pllcontrol_data);
736   wbfrac =
737     (tmp & PMU0_PLL0_PC1_WILD_FRAC_MASK) >> PMU0_PLL0_PC1_WILD_FRAC_SHIFT;
738   wbint = (tmp & PMU0_PLL0_PC1_WILD_INT_MASK) >> PMU0_PLL0_PC1_WILD_INT_SHIFT;
739
740   W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
741   tmp = R_REG (osh, &cc->pllcontrol_data);
742   wbint +=
743     (tmp & PMU0_PLL0_PC2_WILD_INT_MASK) << PMU0_PLL0_PC2_WILD_INT_SHIFT;
744
745   fvco = (xt->freq * wbint) << 8;
746   fvco += (xt->freq * (wbfrac >> 10)) >> 2;
747   fvco += (xt->freq * (wbfrac & 0x3ff)) >> 10;
748   fvco >>= 8;
749   fvco >>= pdiv;
750   fvco /= 1000;
751   fvco *= 1000;
752
753   PMU_MSG (("sb_pmu0_cpuclk0: wbint %u wbfrac %u fvco %u\n",
754             wbint, wbfrac, fvco));
755   ASSERT (fvco == PMU0_PLL0_FVCO);
756 #endif /* BCMDBG */
757
758   /* Return ARM/SB clock */
759   return PMU0_PLL0_FVCO / (divarm + PMU0_PLL0_PC0_DIV_ARM_BASE) * 1000;
760 }
761
762 /* PMU corerev 1 pll programming for BCM4325 */
763 /* setup pll and query clock speed */
764 typedef struct
765 {
766   uint16 fref;
767   uint8 xf;
768   uint8 p1div;
769   uint8 p2div;
770   uint8 ndiv_int;
771   uint32 ndiv_frac;
772 } pmu1_xtaltab0_t;
773
774 /* the following table is based on 880Mhz Fvco */
775 #define PMU1_PLL0_FVCO  880000  /* Fvco 880Mhz */
776 static const pmu1_xtaltab0_t
777 BCMINITDATA (pmu1_xtaltab0)[] =
778 {
779   {
780   12000, 1, 3, 22, 0x9, 0xFFFFEF},
781   {
782   13000, 2, 1, 6, 0xb, 0x483483},
783   {
784   14400, 3, 1, 10, 0xa, 0x1C71C7},
785   {
786   15360, 4, 1, 5, 0xb, 0x755555},
787   {
788   16200, 5, 1, 10, 0x5, 0x6E9E06},
789   {
790   16800, 6, 1, 10, 0x5, 0x3Cf3Cf},
791   {
792   19200, 7, 1, 9, 0x5, 0x17B425},
793   {
794   19800, 8, 1, 11, 0x4, 0xA57EB},
795   {
796   20000, 9, 1, 11, 0x4, 0x0},
797   {
798   24000, 10, 3, 11, 0xa, 0x0},
799   {
800   25000, 11, 5, 16, 0xb, 0x0},
801   {
802   26000, 12, 1, 2, 0x10, 0xEC4EC4},
803   {
804   30000, 13, 3, 8, 0xb, 0x0},
805   {
806   38400, 14, 1, 5, 0x4, 0x955555},
807   {
808   40000, 15, 1, 2, 0xb, 0},
809   {
810   0, 0, 0, 0, 0, 0}
811 };
812
813 /* Default to 15360Khz crystal */
814 #define PMU1_XTAL0_DEFAULT      3
815
816 static uint32
817 BCMINITFN (sb_pmu1_alpclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc)
818 {
819   const pmu1_xtaltab0_t *xt;
820   uint32 xf;
821
822   /* Find the frequency in the table */
823   xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
824     PCTL_XTALFREQ_SHIFT;
825   for (xt = pmu1_xtaltab0; xt->fref; xt++)
826     if (xt->xf == xf)
827       break;
828   if (xt->fref == 0)
829     xt = &pmu1_xtaltab0[PMU1_XTAL0_DEFAULT];
830
831   return xt->fref * 1000;
832 }
833
834 /* Set up PLL registers in the PMU as per the crystal speed.
835  * Uses xtalfreq variable, or passed-in default.
836  */
837 static void
838 BCMINITFN (sb_pmu1_pllinit0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc,
839                               uint32 xtal)
840 {
841   const pmu1_xtaltab0_t *xt;
842   uint32 tmp;
843   uint32 buf_strength = 0;
844
845   /* 4312: assume default works */
846   if (sbh->chip == BCM4312_CHIP_ID)
847     return;
848
849   /* Find the frequency in the table */
850   for (xt = pmu1_xtaltab0; xt->fref; xt++)
851     if (xt->fref == xtal)
852       break;
853   if (xt->fref == 0)
854     xt = &pmu1_xtaltab0[PMU1_XTAL0_DEFAULT];
855
856   PMU_MSG (("XTAL %d (%d)\n", xtal, xt->xf));
857
858   /* Check current PLL state */
859   if (((R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
860        PCTL_XTALFREQ_SHIFT) == xt->xf)
861     {
862       PMU_MSG (("PLL already programmed for %d.%d MHz\n",
863                 (xt->fref / 1000), (xt->fref % 1000)));
864       return;
865     }
866
867   PMU_MSG (("Programming PLL for %d.%d MHz\n", (xt->fref / 1000),
868             (xt->fref % 1000)));
869
870   /* Make sure the PLL is off */
871   switch (sbh->chip)
872     {
873     case BCM4325_CHIP_ID:
874       AND_REG (osh, &cc->min_res_mask,
875                ~(PMURES_BIT (RES4325_BBPLL_PWRSW_PU) |
876                  PMURES_BIT (RES4325_HT_AVAIL)));
877       AND_REG (osh, &cc->max_res_mask,
878                ~(PMURES_BIT (RES4325_BBPLL_PWRSW_PU) |
879                  PMURES_BIT (RES4325_HT_AVAIL)));
880
881       /* Change the BBPLL drive strength to 2 for all channels */
882       buf_strength = 0x222222;
883       break;
884     default:
885       ASSERT (0);
886     }
887   SPINWAIT (R_REG (osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
888             PMU_MAX_TRANSITION_DLY);
889   ASSERT (!(R_REG (osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
890
891   PMU_MSG (("Done masking\n"));
892
893   /* Write p1div and p2div to pllcontrol[0] */
894   W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
895   tmp = R_REG (osh, &cc->pllcontrol_data) &
896     ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
897   tmp |=
898     ((xt->
899       p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) | ((xt->
900                                                                           p2div
901                                                                           <<
902                                                                           PMU1_PLL0_PC0_P2DIV_SHIFT)
903                                                                          &
904                                                                          PMU1_PLL0_PC0_P2DIV_MASK);
905   W_REG (osh, &cc->pllcontrol_data, tmp);
906
907   /* Write ndiv_int and ndiv_mode to pllcontrol[2] */
908   W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
909   tmp = R_REG (osh, &cc->pllcontrol_data) &
910     ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
911   tmp |=
912     ((xt->
913       ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) & PMU1_PLL0_PC2_NDIV_INT_MASK)
914     | ((1 << PMU1_PLL0_PC2_NDIV_MODE_SHIFT) & PMU1_PLL0_PC2_NDIV_MODE_MASK);
915   W_REG (osh, &cc->pllcontrol_data, tmp);
916
917   /* Write ndiv_frac to pllcontrol[3] */
918   W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
919   tmp = R_REG (osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
920   tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
921           PMU1_PLL0_PC3_NDIV_FRAC_MASK);
922   W_REG (osh, &cc->pllcontrol_data, tmp);
923
924   if (buf_strength)
925     {
926       PMU_MSG (("Adjusting PLL buffer drive strength: %x\n", buf_strength));
927
928       W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
929       tmp = R_REG (osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
930       tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
931       W_REG (osh, &cc->pllcontrol_data, tmp);
932     }
933
934   PMU_MSG (("Done pll\n"));
935
936   /* Write XtalFreq. Set the divisor also. */
937   tmp = R_REG (osh, &cc->pmucontrol) &
938     ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
939   tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
940           PCTL_ILP_DIV_MASK) |
941     ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
942   W_REG (osh, &cc->pmucontrol, tmp);
943 }
944
945
946 static uint32
947 BCMINITFN (sb_pmu1_cpuclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc)
948 {
949   const pmu1_xtaltab0_t *xt;
950   uint32 xf, tmp, m1div;
951 #ifdef BCMDBG
952   uint32 ndiv_int, ndiv_frac, p2div, p1div, fvco;
953 #endif
954
955   /* Find the xtal frequency in the table */
956   xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
957     PCTL_XTALFREQ_SHIFT;
958   for (xt = pmu1_xtaltab0; xt->fref; xt++)
959     if (xt->xf == xf)
960       break;
961   if (xt->fref == 0)
962     xt = &pmu1_xtaltab0[PMU1_XTAL0_DEFAULT];
963
964   /* Read m1div from pllcontrol[1] */
965   W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
966   tmp = R_REG (osh, &cc->pllcontrol_data);
967   m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT;
968
969 #ifdef BCMDBG
970   /* Read p2div/p1div from pllcontrol[0] */
971   W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
972   tmp = R_REG (osh, &cc->pllcontrol_data);
973   p2div = (tmp & PMU1_PLL0_PC0_P2DIV_MASK) >> PMU1_PLL0_PC0_P2DIV_SHIFT;
974   p1div = (tmp & PMU1_PLL0_PC0_P1DIV_MASK) >> PMU1_PLL0_PC0_P1DIV_SHIFT;
975
976   /* Calculate Fvco based on xtal freq and ndiv and pdiv */
977   W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
978   tmp = R_REG (osh, &cc->pllcontrol_data);
979   ndiv_int =
980     (tmp & PMU1_PLL0_PC2_NDIV_INT_MASK) >> PMU1_PLL0_PC2_NDIV_INT_SHIFT;
981
982   W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
983   tmp = R_REG (osh, &cc->pllcontrol_data);
984   ndiv_frac =
985     (tmp & PMU1_PLL0_PC3_NDIV_FRAC_MASK) >> PMU1_PLL0_PC3_NDIV_FRAC_SHIFT;
986
987   fvco = (xt->fref * ndiv_int) << 8;
988   fvco += (xt->fref * (ndiv_frac >> 12)) >> 4;
989   fvco += (xt->fref * (ndiv_frac & 0xfff)) >> 12;
990   fvco >>= 8;
991   fvco *= p2div;
992   fvco /= p1div;
993   fvco /= 1000;
994   fvco *= 1000;
995
996   PMU_MSG (("sb_pmu0_cpuclk0: ndiv_int %u ndiv_frac %u "
997             "p2div %u p1div %u fvco %u\n",
998             ndiv_int, ndiv_frac, p2div, p1div, fvco));
999   ASSERT (fvco == PMU1_PLL0_FVCO);
1000 #endif /* BCMDBG */
1001
1002   /* Return ARM/SB clock */
1003   return PMU1_PLL0_FVCO / m1div * 1000;
1004 }
1005
1006 void BCMINITFN (sb_pmu_pll_init) (sb_t * sbh, osl_t * osh, uint xtalfreq)
1007 {
1008   chipcregs_t *cc;
1009   uint origidx;
1010
1011   ASSERT (sbh->cccaps & CC_CAP_PMU);
1012
1013   /* Remember original core before switch to chipc */
1014   origidx = sb_coreidx (sbh);
1015   cc = sb_setcore (sbh, SB_CC, 0);
1016   ASSERT (cc);
1017
1018   switch (sbh->chip)
1019     {
1020     case BCM4328_CHIP_ID:
1021       sb_pmu0_pllinit0 (sbh, osh, cc, xtalfreq);
1022       break;
1023     case BCM5354_CHIP_ID:
1024       sb_pmu0_pllinit0 (sbh, osh, cc, xtalfreq);
1025       break;
1026     case BCM4325_CHIP_ID:
1027       sb_pmu1_pllinit0 (sbh, osh, cc, xtalfreq);
1028       break;
1029     case BCM4312_CHIP_ID:
1030       sb_pmu1_pllinit0 (sbh, osh, cc, xtalfreq);
1031       break;
1032     default:
1033       PMU_MSG (("No PLL init done for chip %x rev %d pmurev %d\n",
1034                 sbh->chip, sbh->chiprev, sbh->pmurev));
1035       break;
1036     }
1037
1038   /* Return to original core */
1039   sb_setcoreidx (sbh, origidx);
1040 }
1041
1042 uint32 BCMINITFN (sb_pmu_alp_clock) (sb_t * sbh, osl_t * osh)
1043 {
1044   chipcregs_t *cc;
1045   uint origidx;
1046   uint32 clock = ALP_CLOCK;
1047
1048   ASSERT (sbh->cccaps & CC_CAP_PMU);
1049
1050   /* Remember original core before switch to chipc */
1051   origidx = sb_coreidx (sbh);
1052   cc = sb_setcore (sbh, SB_CC, 0);
1053   ASSERT (cc);
1054
1055   switch (sbh->chip)
1056     {
1057     case BCM4328_CHIP_ID:
1058       clock = sb_pmu0_alpclk0 (sbh, osh, cc);
1059       break;
1060     case BCM5354_CHIP_ID:
1061       clock = sb_pmu0_alpclk0 (sbh, osh, cc);
1062       break;
1063     case BCM4325_CHIP_ID:
1064       clock = sb_pmu1_alpclk0 (sbh, osh, cc);
1065       break;
1066     case BCM4312_CHIP_ID:
1067       clock = sb_pmu1_alpclk0 (sbh, osh, cc);
1068       /* always 20Mhz */
1069       clock = 20000 * 1000;
1070       break;
1071     default:
1072       PMU_MSG (("No ALP clock specified "
1073                 "for chip %x rev %d pmurev %d, using default %d Hz\n",
1074                 sbh->chip, sbh->chiprev, sbh->pmurev, clock));
1075       break;
1076     }
1077
1078   /* Return to original core */
1079   sb_setcoreidx (sbh, origidx);
1080   return clock;
1081 }
1082
1083 uint BCMINITFN (sb_pmu_cpu_clock) (sb_t * sbh, osl_t * osh)
1084 {
1085   chipcregs_t *cc;
1086   uint origidx;
1087   uint32 clock = HT_CLOCK;
1088
1089   ASSERT (sbh->cccaps & CC_CAP_PMU);
1090
1091   /* Remember original core before switch to chipc */
1092   origidx = sb_coreidx (sbh);
1093   cc = sb_setcore (sbh, SB_CC, 0);
1094   ASSERT (cc);
1095
1096   switch (sbh->chip)
1097     {
1098     case BCM4328_CHIP_ID:
1099       clock = sb_pmu0_cpuclk0 (sbh, osh, cc);
1100       break;
1101     case BCM5354_CHIP_ID:
1102       clock = sb_pmu0_cpuclk0 (sbh, osh, cc);
1103       break;
1104     case BCM4325_CHIP_ID:
1105       clock = sb_pmu1_cpuclk0 (sbh, osh, cc);
1106       break;
1107     case BCM4312_CHIP_ID:
1108       clock = sb_pmu1_cpuclk0 (sbh, osh, cc);
1109       break;
1110     default:
1111       PMU_MSG (("No CPU clock specified "
1112                 "for chip %x rev %d pmurev %d, using default %d Hz\n",
1113                 sbh->chip, sbh->chiprev, sbh->pmurev, clock));
1114       break;
1115     }
1116
1117   /* Return to original core */
1118   sb_setcoreidx (sbh, origidx);
1119   return clock;
1120 }
1121
1122 void BCMINITFN (sb_pmu_init) (sb_t * sbh, osl_t * osh)
1123 {
1124   chipcregs_t *cc;
1125   uint origidx;
1126
1127   ASSERT (sbh->cccaps & CC_CAP_PMU);
1128
1129   /* Remember original core before switch to chipc */
1130   origidx = sb_coreidx (sbh);
1131   cc = sb_setcore (sbh, SB_CC, 0);
1132   ASSERT (cc);
1133
1134   if (sbh->pmurev >= 1)
1135     {
1136       if (sbh->chip == BCM4325_CHIP_ID && sbh->chiprev <= 1)
1137         AND_REG (osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
1138       else
1139         OR_REG (osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT);
1140     }
1141
1142   /* Return to original core */
1143   sb_setcoreidx (sbh, origidx);
1144 }
1145
1146 void BCMINITFN (sb_pmu_otp_power) (sb_t * sbh, osl_t * osh, bool on)
1147 {
1148   chipcregs_t *cc;
1149   uint origidx;
1150
1151   ASSERT (sbh->cccaps & CC_CAP_PMU);
1152
1153   /* Remember original core before switch to chipc */
1154   origidx = sb_coreidx (sbh);
1155   cc = sb_setcore (sbh, SB_CC, 0);
1156   ASSERT (cc);
1157
1158   switch (sbh->chip)
1159     {
1160     case BCM4325_CHIP_ID:
1161       if (on)
1162         {
1163           OR_REG (osh, &cc->min_res_mask, PMURES_BIT (RES4325_LNLDO2_PU));
1164           if (sbh->boardflags & BFL_BUCKBOOST)
1165             AND_REG (osh, &cc->min_res_mask,
1166                      ~PMURES_BIT (RES4325_BUCK_BOOST_PWM));
1167           OSL_DELAY (500);
1168         }
1169       else
1170         {
1171           if (sbh->boardflags & BFL_BUCKBOOST)
1172             OR_REG (osh, &cc->min_res_mask,
1173                     PMURES_BIT (RES4325_BUCK_BOOST_PWM));
1174           AND_REG (osh, &cc->min_res_mask, ~PMURES_BIT (RES4325_LNLDO2_PU));
1175         }
1176       break;
1177     default:
1178       break;
1179     }
1180
1181   /* Return to original core */
1182   sb_setcoreidx (sbh, origidx);
1183 }
1184
1185 void
1186 sb_pmu_rcal (sb_t * sbh, osl_t * osh)
1187 {
1188   chipcregs_t *cc;
1189   uint origidx;
1190
1191   ASSERT (sbh->cccaps & CC_CAP_PMU);
1192
1193   /* Remember original core before switch to chipc */
1194   origidx = sb_coreidx (sbh);
1195   cc = sb_setcore (sbh, SB_CC, 0);
1196   ASSERT (cc);
1197
1198   switch (sbh->chip)
1199     {
1200     case BCM4325_CHIP_ID:
1201       {
1202         uint8 rcal_code;
1203         uint32 val;
1204
1205         /* Kick RCal */
1206         W_REG (osh, &cc->chipcontrol_addr, 1);
1207         AND_REG (osh, &cc->chipcontrol_data, ~0x04);
1208         OR_REG (osh, &cc->chipcontrol_data, 0x04);
1209
1210         /* Wait for completion */
1211         SPINWAIT (0 == (R_REG (osh, &cc->chipstatus) & 0x08),
1212                   10 * 1000 * 1000);
1213         ASSERT (R_REG (osh, &cc->chipstatus) & 0x08);
1214
1215         /* Drop the LSB to convert from 5 bit code to 4 bit code */
1216         rcal_code = (uint8) (R_REG (osh, &cc->chipstatus) >> 5) & 0x0f;
1217         PMU_MSG (("RCal completed, status 0x%x, code 0x%x\n",
1218                   R_REG (osh, &cc->chipstatus), rcal_code));
1219
1220         /* Write RCal code into pmu_vreg_ctrl[32:29] */
1221         W_REG (osh, &cc->regcontrol_addr, 0);
1222         val = R_REG (osh, &cc->regcontrol_data) & ~((uint32) 0x07 << 29);
1223         val |= (uint32) (rcal_code & 0x07) << 29;
1224         W_REG (osh, &cc->regcontrol_data, val);
1225         W_REG (osh, &cc->regcontrol_addr, 1);
1226         val = R_REG (osh, &cc->regcontrol_data) & ~(uint32) 0x01;
1227         val |= (uint32) ((rcal_code >> 3) & 0x01);
1228         W_REG (osh, &cc->regcontrol_data, val);
1229
1230         /* Write RCal code into pmu_chip_ctrl[33:30] */
1231         W_REG (osh, &cc->chipcontrol_addr, 0);
1232         val = R_REG (osh, &cc->chipcontrol_data) & ~((uint32) 0x03 << 30);
1233         val |= (uint32) (rcal_code & 0x03) << 30;
1234         W_REG (osh, &cc->chipcontrol_data, val);
1235         W_REG (osh, &cc->chipcontrol_addr, 1);
1236         val = R_REG (osh, &cc->chipcontrol_data) & ~(uint32) 0x03;
1237         val |= (uint32) ((rcal_code >> 2) & 0x03);
1238         W_REG (osh, &cc->chipcontrol_data, val);
1239
1240         /* Set override in pmu_chip_ctrl[29] */
1241         W_REG (osh, &cc->chipcontrol_addr, 0);
1242         OR_REG (osh, &cc->chipcontrol_data, (0x01 << 29));
1243
1244         /* Power off RCal block */
1245         W_REG (osh, &cc->chipcontrol_addr, 1);
1246         AND_REG (osh, &cc->chipcontrol_data, ~0x04);
1247
1248         break;
1249       }
1250     default:
1251       break;
1252     }
1253
1254   /* Return to original core */
1255   sb_setcoreidx (sbh, origidx);
1256 }