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