c7d7b3be75709aba19113173dfea7db8cc9792dd
[openwrt/staging/florian.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 }