0e95f2cfe953869879190ae920292b8f0e4f45f8
[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 */
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 }