Broadcom SDK and wireless driver: another attempt to update to ver. 5.10.147.0
[tomato.git] / release / src-rt / shared / hndpmu.c
blob8ff232cfac0828f41397ccdbe17620d1f8c029d2
1 /*
2 * Misc utility routines for accessing PMU corerev specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * Copyright (C) 2009, 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.
13 * $Id: hndpmu.c,v 1.121.2.37 2009/10/13 02:32:49 Exp $
16 #include <typedefs.h>
17 #include <bcmdefs.h>
18 #include <osl.h>
19 #include <bcmutils.h>
20 #include <siutils.h>
21 #include <bcmdevs.h>
22 #include <hndsoc.h>
23 #include <sbchipc.h>
24 #include <hndpmu.h>
26 #define PMU_ERROR(args)
28 #define PMU_MSG(args)
30 /* To check in verbose debugging messages not intended
31 * to be on except on private builds.
33 #define PMU_NONE(args)
35 /* PLL controls/clocks */
36 static void si_pmu0_pllinit0(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal);
37 static void si_pmu1_pllinit0(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal);
38 static uint32 si_pmu0_alpclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
39 static uint32 si_pmu0_cpuclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
40 static uint32 si_pmu1_cpuclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
41 static uint32 si_pmu1_alpclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
43 /* PMU resources */
44 static bool si_pmu_res_depfltr_bb(si_t *sih);
45 static bool si_pmu_res_depfltr_nbb(si_t *sih);
46 static bool si_pmu_res_depfltr_ncb(si_t *sih);
47 static bool si_pmu_res_depfltr_paldo(si_t *sih);
48 static bool si_pmu_res_depfltr_npaldo(si_t *sih);
49 static uint32 si_pmu_res_deps(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 rsrcs, bool all);
50 static uint si_pmu_res_uptime(si_t *sih, osl_t *osh, chipcregs_t *cc, uint8 rsrc);
52 static void si_pmu_res_masks(si_t *sih, uint32 *pmin, uint32 *pmax);
54 /* Read/write a chipcontrol reg */
55 void
56 si_pmu_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
58 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr), ~0, reg);
59 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_data), mask, val);
62 /* FVCO frequency */
63 #define FVCO_880 880000 /* 880MHz */
64 #define FVCO_1760 1760000 /* 1760MHz */
65 #define FVCO_1440 1440000 /* 1440MHz */
67 /* PMU PLL update */
68 void
69 si_pmu_pllupd(si_t *sih)
71 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmucontrol),
72 PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
74 /* Read/write a pllcontrol reg */
75 void
76 si_pmu_pllcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
78 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pllcontrol_addr), ~0, reg);
79 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pllcontrol_data), mask, val);
81 /* Setup switcher voltage */
82 void
83 BCMINITFN(si_pmu_set_switcher_voltage)(si_t *sih, osl_t *osh,
84 uint8 bb_voltage, uint8 rf_voltage)
86 chipcregs_t *cc;
87 uint origidx;
89 ASSERT(sih->cccaps & CC_CAP_PMU);
91 /* Remember original core before switch to chipc */
92 origidx = si_coreidx(sih);
93 cc = si_setcoreidx(sih, SI_CC_IDX);
94 ASSERT(cc != NULL);
96 W_REG(osh, &cc->regcontrol_addr, 0x01);
97 W_REG(osh, &cc->regcontrol_data, (uint32)(bb_voltage & 0x1f) << 22);
99 W_REG(osh, &cc->regcontrol_addr, 0x00);
100 W_REG(osh, &cc->regcontrol_data, (uint32)(rf_voltage & 0x1f) << 14);
102 /* Return to original core */
103 si_setcoreidx(sih, origidx);
106 void
107 BCMINITFN(si_pmu_set_ldo_voltage)(si_t *sih, osl_t *osh, uint8 ldo, uint8 voltage)
109 uint8 sr_cntl_shift = 0, rc_shift = 0, shift = 0, mask = 0;
110 uint8 addr = 0;
112 ASSERT(sih->cccaps & CC_CAP_PMU);
114 switch (CHIPID(sih->chip)) {
115 case BCM4328_CHIP_ID:
116 case BCM5354_CHIP_ID:
117 switch (ldo) {
118 case SET_LDO_VOLTAGE_LDO1:
119 addr = 2;
120 sr_cntl_shift = 8;
121 rc_shift = 17;
122 mask = 0xf;
123 break;
124 case SET_LDO_VOLTAGE_LDO2:
125 addr = 3;
126 rc_shift = 1;
127 mask = 0xf;
128 break;
129 case SET_LDO_VOLTAGE_LDO3:
130 addr = 3;
131 rc_shift = 9;
132 mask = 0xf;
133 break;
134 case SET_LDO_VOLTAGE_PAREF:
135 addr = 3;
136 rc_shift = 17;
137 mask = 0x3f;
138 break;
139 default:
140 ASSERT(FALSE);
141 return;
143 break;
144 case BCM4312_CHIP_ID:
145 switch (ldo) {
146 case SET_LDO_VOLTAGE_PAREF:
147 addr = 0;
148 rc_shift = 21;
149 mask = 0x3f;
150 break;
151 default:
152 ASSERT(FALSE);
153 return;
155 break;
156 case BCM4325_CHIP_ID:
157 switch (ldo) {
158 case SET_LDO_VOLTAGE_CLDO_PWM:
159 addr = 5;
160 rc_shift = 9;
161 mask = 0xf;
162 break;
163 case SET_LDO_VOLTAGE_CBUCK_PWM:
164 addr = 3;
165 rc_shift = 20;
166 mask = 0x1f;
167 /* Bit 116 & 119 are inverted in CLB for opt 2b */
168 if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
169 CST4325_PMUTOP_2B_SHIFT) == 1)
170 voltage ^= 0x9;
171 break;
172 default:
173 ASSERT(FALSE);
174 return;
176 break;
177 default:
178 ASSERT(FALSE);
179 return;
182 shift = sr_cntl_shift + rc_shift;
184 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_addr),
185 ~0, addr);
186 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_data),
187 mask << shift, (voltage & mask) << shift);
190 void
191 si_pmu_paref_ldo_enable(si_t *sih, osl_t *osh, bool enable)
193 uint ldo = 0;
195 ASSERT(sih->cccaps & CC_CAP_PMU);
197 switch (CHIPID(sih->chip)) {
198 case BCM4328_CHIP_ID:
199 ldo = RES4328_PA_REF_LDO;
200 break;
201 case BCM5354_CHIP_ID:
202 ldo = RES5354_PA_REF_LDO;
203 break;
204 case BCM4312_CHIP_ID:
205 ldo = RES4312_PA_REF_LDO;
206 break;
207 default:
208 return;
211 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask),
212 PMURES_BIT(ldo), enable ? PMURES_BIT(ldo) : 0);
215 /* d11 slow to fast clock transition time in slow clock cycles */
216 #define D11SCC_SLOW2FAST_TRANSITION 2
218 uint16
219 BCMINITFN(si_pmu_fast_pwrup_delay)(si_t *sih, osl_t *osh)
221 uint delay = PMU_MAX_TRANSITION_DLY;
222 chipcregs_t *cc;
223 uint origidx;
225 ASSERT(sih->cccaps & CC_CAP_PMU);
227 /* Remember original core before switch to chipc */
228 origidx = si_coreidx(sih);
229 cc = si_setcoreidx(sih, SI_CC_IDX);
230 ASSERT(cc != NULL);
232 switch (CHIPID(sih->chip)) {
233 case BCM4328_CHIP_ID:
234 delay = 7000;
235 break;
236 case BCM4325_CHIP_ID:
237 if (ISSIM_ENAB(sih))
238 delay = 70;
239 else {
240 uint32 ilp = si_ilp_clock(sih);
241 delay = (si_pmu_res_uptime(sih, osh, cc, RES4325_HT_AVAIL) +
242 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
244 break;
245 case BCM4312_CHIP_ID:
246 case BCM4322_CHIP_ID:
247 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
248 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
249 case BCM43224_CHIP_ID:
250 case BCM43225_CHIP_ID:
251 case BCM43421_CHIP_ID:
252 case BCM4342_CHIP_ID:
253 delay = 7000;
254 break;
256 case BCM4319_CHIP_ID:
257 delay = ISSIM_ENAB(sih) ? 70 : 3700;
258 break;
260 default:
261 break;
264 PMU_MSG(("si_pmu_fast_pwrup_delay: chip %s rev %d delay %d\n",
265 bcm_chipname(sih->chip, chn, 8), sih->chiprev, delay));
267 /* Return to original core */
268 si_setcoreidx(sih, origidx);
270 return (uint16)delay;
273 uint32
274 BCMINITFN(si_pmu_force_ilp)(si_t *sih, osl_t *osh, bool force)
276 chipcregs_t *cc;
277 uint origidx;
278 uint32 oldpmucontrol;
280 ASSERT(sih->cccaps & CC_CAP_PMU);
282 /* Remember original core before switch to chipc */
283 origidx = si_coreidx(sih);
284 cc = si_setcoreidx(sih, SI_CC_IDX);
285 ASSERT(cc != NULL);
287 oldpmucontrol = R_REG(osh, &cc->pmucontrol);
288 if (force)
289 W_REG(osh, &cc->pmucontrol, oldpmucontrol &
290 ~(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
291 else
292 W_REG(osh, &cc->pmucontrol, oldpmucontrol |
293 (PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
295 /* Return to original core */
296 si_setcoreidx(sih, origidx);
298 return oldpmucontrol;
301 /* Setup resource up/down timers */
302 typedef struct {
303 uint8 resnum;
304 uint16 updown;
305 } pmu_res_updown_t;
307 /* Change resource dependancies masks */
308 typedef struct {
309 uint32 res_mask; /* resources (chip specific) */
310 int8 action; /* action */
311 uint32 depend_mask; /* changes to the dependancies mask */
312 bool (*filter)(si_t *sih); /* action is taken when filter is NULL or return TRUE */
313 } pmu_res_depend_t;
315 /* Resource dependancies mask change action */
316 #define RES_DEPEND_SET 0 /* Override the dependancies mask */
317 #define RES_DEPEND_ADD 1 /* Add to the dependancies mask */
318 #define RES_DEPEND_REMOVE -1 /* Remove from the dependancies mask */
320 static const pmu_res_updown_t BCMINITDATA(bcm4328a0_res_updown)[] = {
321 { RES4328_EXT_SWITCHER_PWM, 0x0101 },
322 { RES4328_BB_SWITCHER_PWM, 0x1f01 },
323 { RES4328_BB_SWITCHER_BURST, 0x010f },
324 { RES4328_BB_EXT_SWITCHER_BURST, 0x0101 },
325 { RES4328_ILP_REQUEST, 0x0202 },
326 { RES4328_RADIO_SWITCHER_PWM, 0x0f01 },
327 { RES4328_RADIO_SWITCHER_BURST, 0x0f01 },
328 { RES4328_ROM_SWITCH, 0x0101 },
329 { RES4328_PA_REF_LDO, 0x0f01 },
330 { RES4328_RADIO_LDO, 0x0f01 },
331 { RES4328_AFE_LDO, 0x0f01 },
332 { RES4328_PLL_LDO, 0x0f01 },
333 { RES4328_BG_FILTBYP, 0x0101 },
334 { RES4328_TX_FILTBYP, 0x0101 },
335 { RES4328_RX_FILTBYP, 0x0101 },
336 { RES4328_XTAL_PU, 0x0101 },
337 { RES4328_XTAL_EN, 0xa001 },
338 { RES4328_BB_PLL_FILTBYP, 0x0101 },
339 { RES4328_RF_PLL_FILTBYP, 0x0101 },
340 { RES4328_BB_PLL_PU, 0x0701 }
343 static const pmu_res_depend_t BCMINITDATA(bcm4328a0_res_depend)[] = {
344 /* Adjust ILP request resource not to force ext/BB switchers into burst mode */
346 PMURES_BIT(RES4328_ILP_REQUEST),
347 RES_DEPEND_SET,
348 PMURES_BIT(RES4328_EXT_SWITCHER_PWM) | PMURES_BIT(RES4328_BB_SWITCHER_PWM),
349 NULL
353 static const pmu_res_updown_t BCMINITDATA(bcm4325a0_res_updown_qt)[] = {
354 { RES4325_HT_AVAIL, 0x0300 },
355 { RES4325_BBPLL_PWRSW_PU, 0x0101 },
356 { RES4325_RFPLL_PWRSW_PU, 0x0101 },
357 { RES4325_ALP_AVAIL, 0x0100 },
358 { RES4325_XTAL_PU, 0x1000 },
359 { RES4325_LNLDO1_PU, 0x0800 },
360 { RES4325_CLDO_CBUCK_PWM, 0x0101 },
361 { RES4325_CBUCK_PWM, 0x0803 }
364 static const pmu_res_updown_t BCMINITDATA(bcm4325a0_res_updown)[] = {
365 { RES4325_XTAL_PU, 0x1501 }
368 static const pmu_res_depend_t BCMINITDATA(bcm4325a0_res_depend)[] = {
369 /* Adjust LNLDO2 PU resource dependencies - remove BB BURST if power topology
370 * does not use BB to provide LNLDO2 voltage.
373 PMURES_BIT(RES4325_LNLDO2_PU),
374 RES_DEPEND_REMOVE,
375 PMURES_BIT(RES4325_BUCK_BOOST_BURST),
376 si_pmu_res_depfltr_nbb
378 /* Adjust ALP/HT Avail resource dependencies - bring up BB along if it is used. */
380 PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_HT_AVAIL),
381 RES_DEPEND_ADD,
382 PMURES_BIT(RES4325_BUCK_BOOST_BURST) | PMURES_BIT(RES4325_BUCK_BOOST_PWM),
383 si_pmu_res_depfltr_bb
385 /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
387 PMURES_BIT(RES4325_HT_AVAIL),
388 RES_DEPEND_ADD,
389 PMURES_BIT(RES4325_RX_PWRSW_PU) | PMURES_BIT(RES4325_TX_PWRSW_PU) |
390 PMURES_BIT(RES4325_LOGEN_PWRSW_PU) | PMURES_BIT(RES4325_AFE_PWRSW_PU),
391 NULL
393 /* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
395 PMURES_BIT(RES4325_ILP_REQUEST) | PMURES_BIT(RES4325_ABUCK_BURST) |
396 PMURES_BIT(RES4325_ABUCK_PWM) | PMURES_BIT(RES4325_LNLDO1_PU) |
397 PMURES_BIT(RES4325_LNLDO4_PU) | PMURES_BIT(RES4325_XTAL_PU) |
398 PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_RX_PWRSW_PU) |
399 PMURES_BIT(RES4325_TX_PWRSW_PU) | PMURES_BIT(RES4325_RFPLL_PWRSW_PU) |
400 PMURES_BIT(RES4325_LOGEN_PWRSW_PU) | PMURES_BIT(RES4325_AFE_PWRSW_PU) |
401 PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL),
402 RES_DEPEND_REMOVE,
403 PMURES_BIT(RES4325B0_CBUCK_LPOM) | PMURES_BIT(RES4325B0_CBUCK_BURST) |
404 PMURES_BIT(RES4325B0_CBUCK_PWM),
405 si_pmu_res_depfltr_ncb
410 static const pmu_res_updown_t BCMINITDATA(bcm4319a0_res_updown_qt)[] = {
411 { RES4319_HT_AVAIL, 0x0101 },
412 { RES4319_XTAL_PU, 0x0100 },
413 { RES4319_LNLDO1_PU, 0x0100 },
414 { RES4319_PALDO_PU, 0x0100 },
415 { RES4319_CLDO_PU, 0x0100 },
416 { RES4319_CBUCK_PWM, 0x0100 },
417 { RES4319_CBUCK_BURST, 0x0100 },
418 { RES4319_CBUCK_LPOM, 0x0100 }
421 static const pmu_res_updown_t BCMINITDATA(bcm4319a0_res_updown)[] = {
422 { RES4319_XTAL_PU, 0x3f01 }
425 static const pmu_res_depend_t BCMINITDATA(bcm4319a0_res_depend)[] = {
426 /* Adjust OTP PU resource dependencies - not need PALDO unless write */
428 PMURES_BIT(RES4319_OTP_PU),
429 RES_DEPEND_REMOVE,
430 PMURES_BIT(RES4319_PALDO_PU),
431 si_pmu_res_depfltr_npaldo
433 /* Adjust HT Avail resource dependencies - bring up PALDO along if it is used. */
435 PMURES_BIT(RES4319_HT_AVAIL),
436 RES_DEPEND_ADD,
437 PMURES_BIT(RES4319_PALDO_PU),
438 si_pmu_res_depfltr_paldo
440 /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
442 PMURES_BIT(RES4319_HT_AVAIL),
443 RES_DEPEND_ADD,
444 PMURES_BIT(RES4319_RX_PWRSW_PU) | PMURES_BIT(RES4319_TX_PWRSW_PU) |
445 PMURES_BIT(RES4319_RFPLL_PWRSW_PU) |
446 PMURES_BIT(RES4319_LOGEN_PWRSW_PU) | PMURES_BIT(RES4319_AFE_PWRSW_PU),
447 NULL
451 /* TRUE if the power topology uses the buck boost to provide 3.3V to VDDIO_RF and WLAN PA */
452 static bool
453 BCMINITFN(si_pmu_res_depfltr_bb)(si_t *sih)
455 return (sih->boardflags & BFL_BUCKBOOST) != 0;
458 /* TRUE if the power topology doesn't use the buck boost */
459 static bool
460 BCMINITFN(si_pmu_res_depfltr_nbb)(si_t *sih)
462 return (sih->boardflags & BFL_BUCKBOOST) == 0;
465 /* TRUE if the power topology doesn't use the cbuck. Key on chiprev also if the chip is BCM4325. */
466 static bool
467 BCMINITFN(si_pmu_res_depfltr_ncb)(si_t *sih)
469 if (CHIPID(sih->chip) == BCM4325_CHIP_ID)
470 return (sih->chiprev >= 2) && ((sih->boardflags & BFL_NOCBUCK) != 0);
471 return ((sih->boardflags & BFL_NOCBUCK) != 0);
475 /* TRUE if the power topology uses the PALDO */
476 static bool
477 BCMINITFN(si_pmu_res_depfltr_paldo)(si_t *sih)
479 return (sih->boardflags & BFL_PALDO) != 0;
482 /* TRUE if the power topology doesn't use the PALDO */
483 static bool
484 BCMINITFN(si_pmu_res_depfltr_npaldo)(si_t *sih)
486 return (sih->boardflags & BFL_PALDO) == 0;
490 #define BCM94325_BBVDDIOSD_BOARDS(sih) (sih->boardtype == BCM94325DEVBU_BOARD || \
491 sih->boardtype == BCM94325BGABU_BOARD)
493 /* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
494 static void
495 si_pmu_res_masks(si_t *sih, uint32 *pmin, uint32 *pmax)
497 uint32 min_mask = 0, max_mask = 0;
498 uint rsrcs;
499 char *val;
501 /* # resources */
502 rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
504 /* determine min/max rsrc masks */
505 switch (CHIPID(sih->chip)) {
506 case BCM4328_CHIP_ID:
507 /* Down to ILP request */
508 min_mask = PMURES_BIT(RES4328_EXT_SWITCHER_PWM) |
509 PMURES_BIT(RES4328_BB_SWITCHER_PWM) |
510 PMURES_BIT(RES4328_XTAL_EN);
511 /* Allow (but don't require) PLL to turn on */
512 max_mask = 0xfffff;
513 break;
514 case BCM5354_CHIP_ID:
515 /* Allow (but don't require) PLL to turn on */
516 max_mask = 0xfffff;
517 break;
518 case BCM4325_CHIP_ID:
519 /* Leave OTP powered up and power it down later when there is no one needs it */
520 if (sih->chiprev < 2) {
521 min_mask = PMURES_BIT(RES4325_CBUCK_BURST) |
522 PMURES_BIT(RES4325_LNLDO2_PU);
523 if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
524 CST4325_PMUTOP_2B_SHIFT) == 1)
525 min_mask |= PMURES_BIT(RES4325_CLDO_CBUCK_BURST);
527 /* Power down the OTP as well and everything we need from it are cacehed */
528 else {
529 if (!(sih->boardflags & BFL_NOCBUCK))
530 min_mask = PMURES_BIT(RES4325B0_CBUCK_LPOM);
531 if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
532 CST4325_PMUTOP_2B_SHIFT) == 1)
533 min_mask |= PMURES_BIT(RES4325B0_CLDO_PU);
535 /* Leave buck boost on in burst mode for certain boards */
536 if ((sih->boardflags & BFL_BUCKBOOST) && (BCM94325_BBVDDIOSD_BOARDS(sih)))
537 min_mask |= PMURES_BIT(RES4325_BUCK_BOOST_BURST);
538 /* Allow all resources to be turned on upon requests */
539 max_mask = ~(~0 << rsrcs);
540 break;
541 case BCM4312_CHIP_ID:
542 /* default min_mask = 0x80000cbb is wrong */
543 min_mask = 0xcbb;
545 * max_mask = 0x7fff;
546 * pmu_res_updown_table_sz = 0;
547 * pmu_res_depend_table_sz = 0;
549 break;
550 case BCM4322_CHIP_ID:
551 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
552 case BCM4342_CHIP_ID:
553 if (sih->chiprev < 2) {
554 /* request ALP(can skip for A1) */
555 min_mask = PMURES_BIT(RES4322_RF_LDO) |
556 PMURES_BIT(RES4322_XTAL_PU) |
557 PMURES_BIT(RES4322_ALP_AVAIL);
558 #ifdef USB4322
559 min_mask += PMURES_BIT(RES4322_SI_PLL_ON) |
560 PMURES_BIT(RES4322_HT_SI_AVAIL) |
561 PMURES_BIT(RES4322_PHY_PLL_ON) |
562 PMURES_BIT(RES4322_OTP_PU) |
563 PMURES_BIT(RES4322_HT_PHY_AVAIL);
564 #endif
565 max_mask = 0x1ff;
567 break;
568 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
569 case BCM43224_CHIP_ID:
570 case BCM43225_CHIP_ID:
571 case BCM43421_CHIP_ID:
572 /* ??? */
573 break;
575 case BCM4319_CHIP_ID:
576 #ifdef CONFIG_XIP
577 /* Initialize to ResInitMode2 for bootloader */
578 min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
579 PMURES_BIT(RES4319_CBUCK_BURST) |
580 PMURES_BIT(RES4319_CBUCK_PWM) |
581 PMURES_BIT(RES4319_CLDO_PU) |
582 PMURES_BIT(RES4319_PALDO_PU) |
583 PMURES_BIT(RES4319_LNLDO1_PU) |
584 PMURES_BIT(RES4319_OTP_PU) |
585 PMURES_BIT(RES4319_XTAL_PU) |
586 PMURES_BIT(RES4319_ALP_AVAIL) |
587 PMURES_BIT(RES4319_RFPLL_PWRSW_PU);
588 #else
589 /* We only need a few resources to be kept on all the time */
590 min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
591 PMURES_BIT(RES4319_CLDO_PU);
592 #endif /* CONFIG_XIP */
593 /* Allow everything else to be turned on upon requests */
594 max_mask = ~(~0 << rsrcs);
595 break;
597 default:
598 break;
601 /* Apply nvram override to min mask */
602 if ((val = getvar(NULL, "rmin")) != NULL) {
603 PMU_MSG(("Applying rmin=%s to min_mask\n", val));
604 min_mask = (uint32)bcm_strtoul(val, NULL, 0);
606 /* Apply nvram override to max mask */
607 if ((val = getvar(NULL, "rmax")) != NULL) {
608 PMU_MSG(("Applying rmax=%s to max_mask\n", val));
609 max_mask = (uint32)bcm_strtoul(val, NULL, 0);
612 *pmin = min_mask;
613 *pmax = max_mask;
616 /* initialize PMU resources */
617 void
618 BCMINITFN(si_pmu_res_init)(si_t *sih, osl_t *osh)
620 chipcregs_t *cc;
621 uint origidx;
622 const pmu_res_updown_t *pmu_res_updown_table = NULL;
623 uint pmu_res_updown_table_sz = 0;
624 const pmu_res_depend_t *pmu_res_depend_table = NULL;
625 uint pmu_res_depend_table_sz = 0;
626 uint32 min_mask = 0, max_mask = 0;
627 char name[8], *val;
628 uint i, rsrcs;
630 ASSERT(sih->cccaps & CC_CAP_PMU);
632 /* Remember original core before switch to chipc */
633 origidx = si_coreidx(sih);
634 cc = si_setcoreidx(sih, SI_CC_IDX);
635 ASSERT(cc != NULL);
637 switch (CHIPID(sih->chip)) {
638 case BCM4328_CHIP_ID:
639 pmu_res_updown_table = bcm4328a0_res_updown;
640 pmu_res_updown_table_sz = ARRAYSIZE(bcm4328a0_res_updown);
641 pmu_res_depend_table = bcm4328a0_res_depend;
642 pmu_res_depend_table_sz = ARRAYSIZE(bcm4328a0_res_depend);
643 break;
644 case BCM4325_CHIP_ID:
645 /* Optimize resources up/down timers */
646 if (ISSIM_ENAB(sih)) {
647 pmu_res_updown_table = bcm4325a0_res_updown_qt;
648 pmu_res_updown_table_sz = ARRAYSIZE(bcm4325a0_res_updown_qt);
649 } else {
650 pmu_res_updown_table = bcm4325a0_res_updown;
651 pmu_res_updown_table_sz = ARRAYSIZE(bcm4325a0_res_updown);
653 /* Optimize resources dependancies */
654 pmu_res_depend_table = bcm4325a0_res_depend;
655 pmu_res_depend_table_sz = ARRAYSIZE(bcm4325a0_res_depend);
656 break;
657 case BCM4319_CHIP_ID:
658 /* Optimize resources up/down timers */
659 if (ISSIM_ENAB(sih)) {
660 pmu_res_updown_table = bcm4319a0_res_updown_qt;
661 pmu_res_updown_table_sz = ARRAYSIZE(bcm4319a0_res_updown_qt);
663 else {
664 pmu_res_updown_table = bcm4319a0_res_updown;
665 pmu_res_updown_table_sz = ARRAYSIZE(bcm4319a0_res_updown);
667 /* Optimize resources dependancies masks */
668 pmu_res_depend_table = bcm4319a0_res_depend;
669 pmu_res_depend_table_sz = ARRAYSIZE(bcm4319a0_res_depend);
670 break;
672 default:
673 break;
676 /* # resources */
677 rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
679 /* Program up/down timers */
680 while (pmu_res_updown_table_sz--) {
681 ASSERT(pmu_res_updown_table != NULL);
682 PMU_MSG(("Changing rsrc %d res_updn_timer to 0x%x\n",
683 pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
684 pmu_res_updown_table[pmu_res_updown_table_sz].updown));
685 W_REG(osh, &cc->res_table_sel,
686 pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
687 W_REG(osh, &cc->res_updn_timer,
688 pmu_res_updown_table[pmu_res_updown_table_sz].updown);
690 /* Apply nvram overrides to up/down timers */
691 for (i = 0; i < rsrcs; i ++) {
692 snprintf(name, sizeof(name), "r%dt", i);
693 if ((val = getvar(NULL, name)) == NULL)
694 continue;
695 PMU_MSG(("Applying %s=%s to rsrc %d res_updn_timer\n", name, val, i));
696 W_REG(osh, &cc->res_table_sel, (uint32)i);
697 W_REG(osh, &cc->res_updn_timer, (uint32)bcm_strtoul(val, NULL, 0));
700 /* Program resource dependencies table */
701 while (pmu_res_depend_table_sz--) {
702 ASSERT(pmu_res_depend_table != NULL);
703 if (pmu_res_depend_table[pmu_res_depend_table_sz].filter != NULL &&
704 !(pmu_res_depend_table[pmu_res_depend_table_sz].filter)(sih))
705 continue;
706 for (i = 0; i < rsrcs; i ++) {
707 if ((pmu_res_depend_table[pmu_res_depend_table_sz].res_mask &
708 PMURES_BIT(i)) == 0)
709 continue;
710 W_REG(osh, &cc->res_table_sel, i);
711 switch (pmu_res_depend_table[pmu_res_depend_table_sz].action) {
712 case RES_DEPEND_SET:
713 PMU_MSG(("Changing rsrc %d res_dep_mask to 0x%x\n", i,
714 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask));
715 W_REG(osh, &cc->res_dep_mask,
716 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
717 break;
718 case RES_DEPEND_ADD:
719 PMU_MSG(("Adding 0x%x to rsrc %d res_dep_mask\n",
720 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
721 OR_REG(osh, &cc->res_dep_mask,
722 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
723 break;
724 case RES_DEPEND_REMOVE:
725 PMU_MSG(("Removing 0x%x from rsrc %d res_dep_mask\n",
726 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
727 AND_REG(osh, &cc->res_dep_mask,
728 ~pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
729 break;
730 default:
731 ASSERT(0);
732 break;
736 /* Apply nvram overrides to dependancies masks */
737 for (i = 0; i < rsrcs; i ++) {
738 snprintf(name, sizeof(name), "r%dd", i);
739 if ((val = getvar(NULL, name)) == NULL)
740 continue;
741 PMU_MSG(("Applying %s=%s to rsrc %d res_dep_mask\n", name, val, i));
742 W_REG(osh, &cc->res_table_sel, (uint32)i);
743 W_REG(osh, &cc->res_dep_mask, (uint32)bcm_strtoul(val, NULL, 0));
746 /* Determine min/max rsrc masks */
747 si_pmu_res_masks(sih, &min_mask, &max_mask);
749 /* Program min resource mask */
750 if (min_mask) {
751 PMU_MSG(("Changing min_res_mask to 0x%x\n", min_mask));
752 W_REG(osh, &cc->min_res_mask, min_mask);
754 /* Program max resource mask */
755 if (max_mask) {
756 PMU_MSG(("Changing max_res_mask to 0x%x\n", max_mask));
757 W_REG(osh, &cc->max_res_mask, max_mask);
760 /* Return to original core */
761 si_setcoreidx(sih, origidx);
764 /* setup pll and query clock speed */
765 typedef struct {
766 uint16 freq;
767 uint8 xf;
768 uint8 wbint;
769 uint32 wbfrac;
770 } pmu0_xtaltab0_t;
772 /* the following table is based on 880Mhz fvco */
773 static const pmu0_xtaltab0_t BCMINITDATA(pmu0_xtaltab0)[] = {
774 { 12000, 1, 73, 349525 },
775 { 13000, 2, 67, 725937 },
776 { 14400, 3, 61, 116508 },
777 { 15360, 4, 57, 305834 },
778 { 16200, 5, 54, 336579 },
779 { 16800, 6, 52, 399457 },
780 { 19200, 7, 45, 873813 },
781 { 19800, 8, 44, 466033 },
782 { 20000, 9, 44, 0 },
783 { 25000, 10, 70, 419430 },
784 { 26000, 11, 67, 725937 },
785 { 30000, 12, 58, 699050 },
786 { 38400, 13, 45, 873813 },
787 { 40000, 14, 45, 0 },
788 { 0, 0, 0, 0 }
791 #ifdef BCMUSBDEV
792 #define PMU0_XTAL0_DEFAULT 11
793 #else
794 #define PMU0_XTAL0_DEFAULT 8
795 #endif
797 #ifdef BCMUSBDEV
799 * Set new backplane PLL clock frequency
801 static void
802 BCMINITFN(si_pmu0_sbclk4328)(si_t *sih, int freq)
804 uint32 tmp, oldmax, oldmin, origidx;
805 chipcregs_t *cc;
807 /* Remember original core before switch to chipc */
808 origidx = si_coreidx(sih);
809 cc = si_setcoreidx(sih, SI_CC_IDX);
810 ASSERT(cc);
812 /* Set new backplane PLL clock */
813 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
814 tmp = R_REG(osh, &cc->pllcontrol_data);
815 tmp &= ~(PMU0_PLL0_PC0_DIV_ARM_MASK);
816 tmp |= freq << PMU0_PLL0_PC0_DIV_ARM_SHIFT;
817 W_REG(osh, &cc->pllcontrol_data, tmp);
819 /* Power cycle BB_PLL_PU by disabling/enabling it to take on new freq */
820 /* Disable PLL */
821 oldmin = R_REG(osh, &cc->min_res_mask);
822 oldmax = R_REG(osh, &cc->max_res_mask);
823 W_REG(osh, &cc->min_res_mask, oldmin & ~PMURES_BIT(RES4328_BB_PLL_PU));
824 W_REG(osh, &cc->max_res_mask, oldmax & ~PMURES_BIT(RES4328_BB_PLL_PU));
826 /* It takes over several hundred usec to re-enable the PLL since the
827 * sequencer state machines run on ILP clock. Set delay at 450us to be safe.
829 * Be sure PLL is powered down first before re-enabling it.
832 OSL_DELAY(PLL_DELAY);
833 SPINWAIT((R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)), PLL_DELAY*3);
834 if (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)) {
835 /* If BB_PLL not powered down yet, new backplane PLL clock
836 * may not take effect.
838 * Still early during bootup so no serial output here.
840 PMU_ERROR(("Fatal: BB_PLL not power down yet!\n"));
841 ASSERT(!(R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)));
844 /* Enable PLL */
845 W_REG(osh, &cc->max_res_mask, oldmax);
847 /* Return to original core */
848 si_setcoreidx(sih, origidx);
850 #endif /* BCMUSBDEV */
852 /* Set up PLL registers in the PMU as per the crystal speed.
853 * Uses xtalfreq variable, or passed-in default.
855 static void
856 BCMINITFN(si_pmu0_pllinit0)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal)
858 uint32 tmp;
859 const pmu0_xtaltab0_t *xt;
861 /* Find the frequency in the table */
862 for (xt = pmu0_xtaltab0; xt->freq; xt ++)
863 if (xt->freq == xtal)
864 break;
865 if (xt->freq == 0)
866 xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
868 PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
870 /* Check current PLL state */
871 tmp = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
872 PCTL_XTALFREQ_SHIFT;
873 if (tmp == xt->xf) {
874 PMU_MSG(("PLL already programmed for %d.%d MHz\n",
875 xt->freq / 1000, xt->freq % 1000));
876 #ifdef BCMUSBDEV
877 if (CHIPID(sih->chip) == BCM4328_CHIP_ID)
878 si_pmu0_sbclk4328(sih, PMU0_PLL0_PC0_DIV_ARM_88MHZ);
879 #endif /* BCMUSBDEV */
880 return;
883 if (tmp) {
884 PMU_MSG(("Reprogramming PLL for %d.%d MHz (was %d.%dMHz)\n",
885 xt->freq / 1000, xt->freq % 1000,
886 pmu0_xtaltab0[tmp-1].freq / 1000, pmu0_xtaltab0[tmp-1].freq % 1000));
887 } else {
888 PMU_MSG(("Programming PLL for %d.%d MHz\n",
889 xt->freq / 1000, xt->freq % 1000));
892 /* Make sure the PLL is off */
893 switch (CHIPID(sih->chip)) {
894 case BCM4328_CHIP_ID:
895 AND_REG(osh, &cc->min_res_mask, ~PMURES_BIT(RES4328_BB_PLL_PU));
896 AND_REG(osh, &cc->max_res_mask, ~PMURES_BIT(RES4328_BB_PLL_PU));
897 break;
898 case BCM5354_CHIP_ID:
899 AND_REG(osh, &cc->min_res_mask, ~PMURES_BIT(RES5354_BB_PLL_PU));
900 AND_REG(osh, &cc->max_res_mask, ~PMURES_BIT(RES5354_BB_PLL_PU));
901 break;
902 default:
903 ASSERT(0);
905 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS0_HTAVAIL, PMU_MAX_TRANSITION_DLY);
906 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS0_HTAVAIL));
908 PMU_MSG(("Done masking\n"));
910 /* Write PDIV in pllcontrol[0] */
911 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
912 tmp = R_REG(osh, &cc->pllcontrol_data);
913 if (xt->freq >= PMU0_PLL0_PC0_PDIV_FREQ)
914 tmp |= PMU0_PLL0_PC0_PDIV_MASK;
915 else
916 tmp &= ~PMU0_PLL0_PC0_PDIV_MASK;
917 W_REG(osh, &cc->pllcontrol_data, tmp);
919 /* Write WILD in pllcontrol[1] */
920 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
921 tmp = R_REG(osh, &cc->pllcontrol_data);
922 tmp = ((tmp & ~(PMU0_PLL0_PC1_WILD_INT_MASK | PMU0_PLL0_PC1_WILD_FRAC_MASK)) |
923 (((xt->wbint << PMU0_PLL0_PC1_WILD_INT_SHIFT) &
924 PMU0_PLL0_PC1_WILD_INT_MASK) |
925 ((xt->wbfrac << PMU0_PLL0_PC1_WILD_FRAC_SHIFT) &
926 PMU0_PLL0_PC1_WILD_FRAC_MASK)));
927 if (xt->wbfrac == 0)
928 tmp |= PMU0_PLL0_PC1_STOP_MOD;
929 else
930 tmp &= ~PMU0_PLL0_PC1_STOP_MOD;
931 W_REG(osh, &cc->pllcontrol_data, tmp);
933 /* Write WILD in pllcontrol[2] */
934 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
935 tmp = R_REG(osh, &cc->pllcontrol_data);
936 tmp = ((tmp & ~PMU0_PLL0_PC2_WILD_INT_MASK) |
937 ((xt->wbint >> PMU0_PLL0_PC2_WILD_INT_SHIFT) &
938 PMU0_PLL0_PC2_WILD_INT_MASK));
939 W_REG(osh, &cc->pllcontrol_data, tmp);
941 PMU_MSG(("Done pll\n"));
943 /* Write XtalFreq. Set the divisor also. */
944 tmp = R_REG(osh, &cc->pmucontrol);
945 tmp = ((tmp & ~PCTL_ILP_DIV_MASK) |
946 (((((xt->freq + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) & PCTL_ILP_DIV_MASK));
947 tmp = ((tmp & ~PCTL_XTALFREQ_MASK) |
948 ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK));
949 W_REG(osh, &cc->pmucontrol, tmp);
952 /* query alp/xtal clock frequency */
953 static uint32
954 BCMINITFN(si_pmu0_alpclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
956 const pmu0_xtaltab0_t *xt;
957 uint32 xf;
959 /* Find the frequency in the table */
960 xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
961 PCTL_XTALFREQ_SHIFT;
962 for (xt = pmu0_xtaltab0; xt->freq; xt++)
963 if (xt->xf == xf)
964 break;
965 /* PLL must be configured before */
966 ASSERT(xt->freq);
968 return xt->freq * 1000;
971 /* query CPU clock frequency */
972 static uint32
973 BCMINITFN(si_pmu0_cpuclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
975 uint32 tmp, divarm;
976 uint32 FVCO = FVCO_880;
978 /* Read divarm from pllcontrol[0] */
979 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
980 tmp = R_REG(osh, &cc->pllcontrol_data);
981 divarm = (tmp & PMU0_PLL0_PC0_DIV_ARM_MASK) >> PMU0_PLL0_PC0_DIV_ARM_SHIFT;
984 /* Return ARM/SB clock */
985 return FVCO / (divarm + PMU0_PLL0_PC0_DIV_ARM_BASE) * 1000;
988 /* setup pll and query clock speed */
989 typedef struct {
990 uint16 fref;
991 uint8 xf;
992 uint8 p1div;
993 uint8 p2div;
994 uint8 ndiv_int;
995 uint32 ndiv_frac;
996 } pmu1_xtaltab0_t;
998 /* the following table is based on 880Mhz fvco */
999 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880)[] = {
1000 {12000, 1, 3, 22, 0x9, 0xFFFFEF},
1001 {13000, 2, 1, 6, 0xb, 0x483483},
1002 {14400, 3, 1, 10, 0xa, 0x1C71C7},
1003 {15360, 4, 1, 5, 0xb, 0x755555},
1004 {16200, 5, 1, 10, 0x5, 0x6E9E06},
1005 {16800, 6, 1, 10, 0x5, 0x3Cf3Cf},
1006 {19200, 7, 1, 9, 0x5, 0x17B425},
1007 {19800, 8, 1, 11, 0x4, 0xA57EB},
1008 {20000, 9, 1, 11, 0x4, 0x0},
1009 {24000, 10, 3, 11, 0xa, 0x0},
1010 {25000, 11, 5, 16, 0xb, 0x0},
1011 {26000, 12, 1, 2, 0x10, 0xEC4EC4},
1012 {30000, 13, 3, 8, 0xb, 0x0},
1013 {38400, 14, 1, 2, 0xb, 0x755555},
1014 {40000, 15, 1, 2, 0xb, 0},
1015 {0, 0, 0, 0, 0, 0}
1018 #define PMU1_XTALTAB0_880_12000K 0
1019 #define PMU1_XTALTAB0_880_13000K 1
1020 #define PMU1_XTALTAB0_880_14400K 2
1021 #define PMU1_XTALTAB0_880_15360K 3
1022 #define PMU1_XTALTAB0_880_16200K 4
1023 #define PMU1_XTALTAB0_880_16800K 5
1024 #define PMU1_XTALTAB0_880_19200K 6
1025 #define PMU1_XTALTAB0_880_19800K 7
1026 #define PMU1_XTALTAB0_880_20000K 8
1027 #define PMU1_XTALTAB0_880_24000K 9
1028 #define PMU1_XTALTAB0_880_25000K 10
1029 #define PMU1_XTALTAB0_880_26000K 11
1030 #define PMU1_XTALTAB0_880_30000K 12
1031 #define PMU1_XTALTAB0_880_38400K 13
1032 #define PMU1_XTALTAB0_880_40000K 14
1034 /* the following table is based on 1760Mhz fvco */
1035 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1760)[] = {
1036 {12000, 1, 3, 44, 0x9, 0xFFFFEF},
1037 {13000, 2, 1, 12, 0xb, 0x483483},
1038 {14400, 3, 1, 20, 0xa, 0x1C71C7},
1039 {15360, 4, 1, 10, 0xb, 0x755555},
1040 {16200, 5, 1, 20, 0x5, 0x6E9E06},
1041 {16800, 6, 1, 20, 0x5, 0x3Cf3Cf},
1042 {19200, 7, 1, 18, 0x5, 0x17B425},
1043 {19800, 8, 1, 22, 0x4, 0xA57EB},
1044 {20000, 9, 1, 22, 0x4, 0x0},
1045 {24000, 10, 3, 22, 0xa, 0x0},
1046 {25000, 11, 5, 32, 0xb, 0x0},
1047 {26000, 12, 1, 4, 0x10, 0xEC4EC4},
1048 {30000, 13, 3, 16, 0xb, 0x0},
1049 {38400, 14, 1, 10, 0x4, 0x955555},
1050 {40000, 15, 1, 4, 0xb, 0},
1051 {0, 0, 0, 0, 0, 0}
1054 /* table index */
1055 #define PMU1_XTALTAB0_1760_12000K 0
1056 #define PMU1_XTALTAB0_1760_13000K 1
1057 #define PMU1_XTALTAB0_1760_14400K 2
1058 #define PMU1_XTALTAB0_1760_15360K 3
1059 #define PMU1_XTALTAB0_1760_16200K 4
1060 #define PMU1_XTALTAB0_1760_16800K 5
1061 #define PMU1_XTALTAB0_1760_19200K 6
1062 #define PMU1_XTALTAB0_1760_19800K 7
1063 #define PMU1_XTALTAB0_1760_20000K 8
1064 #define PMU1_XTALTAB0_1760_24000K 9
1065 #define PMU1_XTALTAB0_1760_25000K 10
1066 #define PMU1_XTALTAB0_1760_26000K 11
1067 #define PMU1_XTALTAB0_1760_30000K 12
1068 #define PMU1_XTALTAB0_1760_38400K 13
1069 #define PMU1_XTALTAB0_1760_40000K 14
1071 /* the following table is based on 1440Mhz fvco */
1072 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1440)[] = {
1073 {12000, 1, 3, 44, 0x9, 0xFFFFEF},
1074 {13000, 2, 1, 12, 0xb, 0x483483},
1075 {14400, 3, 1, 20, 0xa, 0x1C71C7},
1076 {15360, 4, 1, 10, 0xb, 0x755555},
1077 {16200, 5, 1, 20, 0x5, 0x6E9E06},
1078 {16800, 6, 1, 20, 0x5, 0x3Cf3Cf},
1079 {19200, 7, 1, 18, 0x5, 0x17B425},
1080 {19800, 8, 1, 22, 0x4, 0xA57EB},
1081 {20000, 9, 1, 22, 0x4, 0x0},
1082 {24000, 10, 1, 1, 0x3c, 0x0},
1083 {25000, 11, 5, 32, 0xb, 0x0},
1084 {26000, 12, 1, 4, 0x10, 0xEC4EC4},
1085 {30000, 13, 1, 1, 0x30, 0x0},
1086 {38400, 14, 1, 10, 0x4, 0x955555},
1087 {40000, 15, 1, 4, 0xb, 0},
1088 {48000, 16, 2, 1, 0x3c, 0x0},
1089 {0, 0, 0, 0, 0, 0}
1092 /* table index */
1093 #define PMU1_XTALTAB0_1440_12000K 0
1094 #define PMU1_XTALTAB0_1440_13000K 1
1095 #define PMU1_XTALTAB0_1440_14400K 2
1096 #define PMU1_XTALTAB0_1440_15360K 3
1097 #define PMU1_XTALTAB0_1440_16200K 4
1098 #define PMU1_XTALTAB0_1440_16800K 5
1099 #define PMU1_XTALTAB0_1440_19200K 6
1100 #define PMU1_XTALTAB0_1440_19800K 7
1101 #define PMU1_XTALTAB0_1440_20000K 8
1102 #define PMU1_XTALTAB0_1440_24000K 9
1103 #define PMU1_XTALTAB0_1440_25000K 10
1104 #define PMU1_XTALTAB0_1440_26000K 11
1105 #define PMU1_XTALTAB0_1440_30000K 12
1106 #define PMU1_XTALTAB0_1440_38400K 13
1107 #define PMU1_XTALTAB0_1440_40000K 14
1109 #define XTAL_FREQ_24000MHZ 24000
1110 #define XTAL_FREQ_30000MHZ 30000
1111 #define XTAL_FREQ_48000MHZ 48000
1113 /* select xtal table for each chip */
1114 static const pmu1_xtaltab0_t *
1115 BCMINITFN(si_pmu1_xtaltab0)(si_t *sih)
1118 switch (CHIPID(sih->chip)) {
1119 case BCM4325_CHIP_ID:
1120 return pmu1_xtaltab0_880;
1121 case BCM4319_CHIP_ID:
1122 return pmu1_xtaltab0_1440;
1123 default:
1124 PMU_MSG(("si_pmu1_xtaltab0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1125 break;
1127 ASSERT(0);
1128 return NULL;
1131 /* select default xtal frequency for each chip */
1132 static const pmu1_xtaltab0_t *
1133 BCMINITFN(si_pmu1_xtaldef0)(si_t *sih)
1136 switch (CHIPID(sih->chip)) {
1137 case BCM4325_CHIP_ID:
1138 /* Default to 26000Khz */
1139 return &pmu1_xtaltab0_880[PMU1_XTALTAB0_880_26000K];
1140 case BCM4319_CHIP_ID:
1141 /* Default to 30000Khz */
1142 return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_30000K];
1143 default:
1144 PMU_MSG(("si_pmu1_xtaldef0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1145 break;
1147 ASSERT(0);
1148 return NULL;
1151 /* select default pll fvco for each chip */
1152 static uint32
1153 BCMINITFN(si_pmu1_pllfvco0)(si_t *sih)
1156 switch (CHIPID(sih->chip)) {
1157 case BCM4325_CHIP_ID:
1158 return FVCO_880;
1159 case BCM4319_CHIP_ID:
1160 return FVCO_1440;
1161 default:
1162 PMU_MSG(("si_pmu1_pllfvco0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1163 break;
1165 ASSERT(0);
1166 return 0;
1169 /* query alp/xtal clock frequency */
1170 static uint32
1171 BCMINITFN(si_pmu1_alpclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1173 const pmu1_xtaltab0_t *xt;
1174 uint32 xf;
1176 /* Find the frequency in the table */
1177 xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1178 PCTL_XTALFREQ_SHIFT;
1179 for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
1180 if (xt->xf == xf)
1181 break;
1182 /* Could not find it so assign a default value */
1183 if (xt == NULL || xt->fref == 0)
1184 xt = si_pmu1_xtaldef0(sih);
1185 ASSERT(xt != NULL && xt->fref != 0);
1187 return xt->fref * 1000;
1190 /* Set up PLL registers in the PMU as per the crystal speed.
1191 * XtalFreq field in pmucontrol register being 0 indicates the PLL
1192 * is not programmed and the h/w default is assumed to work, in which
1193 * case the xtal frequency is unknown to the s/w so we need to call
1194 * si_pmu1_xtaldef0() wherever it is needed to return a default value.
1196 static void
1197 BCMINITFN(si_pmu1_pllinit0)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal)
1199 const pmu1_xtaltab0_t *xt;
1200 uint32 tmp;
1201 uint32 buf_strength = 0;
1202 uint8 ndiv_mode = 1;
1204 /* Use h/w default PLL config */
1205 if (xtal == 0) {
1206 PMU_MSG(("Unspecified xtal frequency, skip PLL configuration\n"));
1207 return;
1210 /* Find the frequency in the table */
1211 for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
1212 if (xt->fref == xtal)
1213 break;
1215 /* Check current PLL state, bail out if it has been programmed or
1216 * we don't know how to program it.
1218 if (xt == NULL || xt->fref == 0) {
1219 PMU_MSG(("Unsupported xtal frequency %d.%d MHz, skip PLL configuration\n",
1220 xtal / 1000, xtal % 1000));
1221 return;
1223 if (((R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1224 PCTL_XTALFREQ_SHIFT) == xt->xf) {
1225 PMU_MSG(("PLL already programmed for %d.%d MHz\n",
1226 xt->fref / 1000, xt->fref % 1000));
1227 return;
1230 PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
1231 PMU_MSG(("Programming PLL for %d.%d MHz\n", xt->fref / 1000, xt->fref % 1000));
1233 switch (CHIPID(sih->chip)) {
1234 case BCM4325_CHIP_ID:
1235 /* Change the BBPLL drive strength to 2 for all channels */
1236 buf_strength = 0x222222;
1237 if (sih->pmurev >= 2)
1238 break;
1239 /* Make sure the PLL is off */
1240 AND_REG(osh, &cc->min_res_mask,
1241 ~(PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL)));
1242 AND_REG(osh, &cc->max_res_mask,
1243 ~(PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL)));
1244 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1245 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1246 break;
1247 case BCM4319_CHIP_ID:
1248 /* Change the BBPLL drive strength to 2 for all channels */
1249 buf_strength = 0x222222;
1250 /* Make sure the PLL is off */
1251 /* WAR65104: Disable the HT_AVAIL resource first and then
1252 * after a delay (more than downtime for HT_AVAIL) remove the
1253 * BBPLL resource; backplane clock moves to ALP from HT.
1255 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4319_HT_AVAIL)));
1256 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4319_HT_AVAIL)));
1258 OSL_DELAY(100);
1259 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
1260 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
1262 OSL_DELAY(100);
1263 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1264 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1265 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
1266 tmp = 0x200005c0;
1267 W_REG(osh, &cc->pllcontrol_data, tmp);
1268 break;
1269 default:
1270 ASSERT(0);
1273 PMU_MSG(("Done masking\n"));
1275 /* Write p1div and p2div to pllcontrol[0] */
1276 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
1277 tmp = R_REG(osh, &cc->pllcontrol_data) &
1278 ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
1279 tmp |= ((xt->p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) |
1280 ((xt->p2div << PMU1_PLL0_PC0_P2DIV_SHIFT) & PMU1_PLL0_PC0_P2DIV_MASK);
1281 W_REG(osh, &cc->pllcontrol_data, tmp);
1283 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID))
1284 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
1285 /* Write ndiv_int and ndiv_mode to pllcontrol[2] */
1286 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
1287 tmp = R_REG(osh, &cc->pllcontrol_data) &
1288 ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
1289 tmp |= ((xt->ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) & PMU1_PLL0_PC2_NDIV_INT_MASK) |
1290 ((ndiv_mode << PMU1_PLL0_PC2_NDIV_MODE_SHIFT) & PMU1_PLL0_PC2_NDIV_MODE_MASK);
1291 W_REG(osh, &cc->pllcontrol_data, tmp);
1293 /* Write ndiv_frac to pllcontrol[3] */
1294 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
1295 tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
1296 tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
1297 PMU1_PLL0_PC3_NDIV_FRAC_MASK);
1298 W_REG(osh, &cc->pllcontrol_data, tmp);
1300 /* Write clock driving strength to pllcontrol[5] */
1301 if (buf_strength) {
1302 PMU_MSG(("Adjusting PLL buffer drive strength: %x\n", buf_strength));
1304 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
1305 tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
1306 tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
1307 W_REG(osh, &cc->pllcontrol_data, tmp);
1310 PMU_MSG(("Done pll\n"));
1312 /* to operate the 4319 usb in 24MHz/48MHz; chipcontrol[2][84:83] needs
1313 * to be updated.
1315 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && (xt->fref != XTAL_FREQ_30000MHZ)) {
1316 W_REG(osh, &cc->chipcontrol_addr, PMU1_PLL0_CHIPCTL2);
1317 tmp = R_REG(osh, &cc->chipcontrol_data) & ~CCTL_4319USB_XTAL_SEL_MASK;
1318 if (xt->fref == XTAL_FREQ_24000MHZ) {
1319 tmp |= (CCTL_4319USB_24MHZ_PLL_SEL << CCTL_4319USB_XTAL_SEL_SHIFT);
1320 } else if (xt->fref == XTAL_FREQ_48000MHZ) {
1321 tmp |= (CCTL_4319USB_48MHZ_PLL_SEL << CCTL_4319USB_XTAL_SEL_SHIFT);
1323 W_REG(osh, &cc->chipcontrol_data, tmp);
1326 /* Flush deferred pll control registers writes */
1327 if (sih->pmurev >= 2)
1328 OR_REG(osh, &cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
1330 /* Write XtalFreq. Set the divisor also. */
1331 tmp = R_REG(osh, &cc->pmucontrol) &
1332 ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
1333 tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
1334 PCTL_ILP_DIV_MASK) |
1335 ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
1338 W_REG(osh, &cc->pmucontrol, tmp);
1341 /* query the CPU clock frequency */
1342 static uint32
1343 BCMINITFN(si_pmu1_cpuclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1345 uint32 tmp, m1div;
1346 uint32 FVCO = si_pmu1_pllfvco0(sih);
1348 /* Read m1div from pllcontrol[1] */
1349 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
1350 tmp = R_REG(osh, &cc->pllcontrol_data);
1351 m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT;
1354 /* Return ARM/SB clock */
1355 return FVCO / m1div * 1000;
1358 /* initialize PLL */
1359 void
1360 BCMINITFN(si_pmu_pll_init)(si_t *sih, osl_t *osh, uint xtalfreq)
1362 chipcregs_t *cc;
1363 uint origidx;
1365 ASSERT(sih->cccaps & CC_CAP_PMU);
1367 /* Remember original core before switch to chipc */
1368 origidx = si_coreidx(sih);
1369 cc = si_setcoreidx(sih, SI_CC_IDX);
1370 ASSERT(cc != NULL);
1372 switch (CHIPID(sih->chip)) {
1373 case BCM4328_CHIP_ID:
1374 si_pmu0_pllinit0(sih, osh, cc, xtalfreq);
1375 break;
1376 case BCM5354_CHIP_ID:
1377 if (xtalfreq == 0)
1378 xtalfreq = 25000;
1379 si_pmu0_pllinit0(sih, osh, cc, xtalfreq);
1380 break;
1381 case BCM4325_CHIP_ID:
1382 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
1383 break;
1384 case BCM4312_CHIP_ID:
1385 /* assume default works */
1386 break;
1387 case BCM4322_CHIP_ID:
1388 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
1389 case BCM4342_CHIP_ID:
1391 if (sih->chiprev == 0) {
1392 uint32 minmask, maxmask;
1394 minmask = R_REG(osh, &cc->min_res_mask);
1395 maxmask = R_REG(osh, &cc->max_res_mask);
1397 /* Make sure the PLL is off: clear bit 4 & 5 of min/max_res_mask */
1398 /* Have to remove HT Avail request before powering off PLL */
1399 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
1400 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
1401 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1402 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
1403 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
1404 OSL_DELAY(1000);
1405 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1408 W_REG(osh, &cc->pllcontrol_addr, PMU2_SI_PLL_PLLCTL);
1409 W_REG(osh, &cc->pllcontrol_data, 0x380005c0);
1412 OSL_DELAY(100);
1413 W_REG(osh, &cc->max_res_mask, maxmask);
1414 OSL_DELAY(100);
1415 W_REG(osh, &cc->min_res_mask, minmask);
1416 OSL_DELAY(100);
1419 break;
1421 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
1422 case BCM43224_CHIP_ID:
1423 case BCM43225_CHIP_ID:
1424 case BCM43421_CHIP_ID:
1425 /* ??? */
1426 break;
1428 case BCM4319_CHIP_ID:
1429 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
1430 break;
1432 default:
1433 PMU_MSG(("No PLL init done for chip %s rev %d pmurev %d\n",
1434 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
1435 break;
1438 /* Return to original core */
1439 si_setcoreidx(sih, origidx);
1442 /* query alp/xtal clock frequency */
1443 uint32
1444 BCMINITFN(si_pmu_alp_clock)(si_t *sih, osl_t *osh)
1446 chipcregs_t *cc;
1447 uint origidx;
1448 uint32 clock = ALP_CLOCK;
1450 ASSERT(sih->cccaps & CC_CAP_PMU);
1452 /* Remember original core before switch to chipc */
1453 origidx = si_coreidx(sih);
1454 cc = si_setcoreidx(sih, SI_CC_IDX);
1455 ASSERT(cc != NULL);
1457 switch (CHIPID(sih->chip)) {
1458 case BCM4328_CHIP_ID:
1459 clock = si_pmu0_alpclk0(sih, osh, cc);
1460 break;
1461 case BCM5354_CHIP_ID:
1462 clock = si_pmu0_alpclk0(sih, osh, cc);
1463 break;
1464 case BCM4325_CHIP_ID:
1465 clock = si_pmu1_alpclk0(sih, osh, cc);
1466 break;
1467 case BCM4312_CHIP_ID:
1468 case BCM4322_CHIP_ID:
1469 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
1470 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
1471 case BCM43224_CHIP_ID:
1472 case BCM43225_CHIP_ID:
1473 case BCM43421_CHIP_ID:
1474 case BCM4342_CHIP_ID:
1475 case BCM4716_CHIP_ID:
1476 case BCM4748_CHIP_ID:
1477 case BCM47162_CHIP_ID:
1478 /* always 20Mhz */
1479 clock = 20000 * 1000;
1480 break;
1482 case BCM4319_CHIP_ID:
1483 clock = si_pmu1_alpclk0(sih, osh, cc);
1484 break;
1485 default:
1486 PMU_MSG(("No ALP clock specified "
1487 "for chip %s rev %d pmurev %d, using default %d Hz\n",
1488 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev, clock));
1489 break;
1492 /* Return to original core */
1493 si_setcoreidx(sih, origidx);
1494 return clock;
1497 /* Find the output of the "m" pll divider given pll controls that start with
1498 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
1500 static uint32
1501 BCMINITFN(si_pmu5_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, uint m)
1503 uint32 tmp, div, ndiv, p1, p2, fc;
1505 if ((pll0 & 3) || (pll0 > PMU4716_MAINPLL_PLL0)) {
1506 PMU_ERROR(("%s: Bad pll0: %d\n", __FUNCTION__, pll0));
1507 return 0;
1510 /* Strictly there is an m5 divider, but I'm not sure we use it */
1511 if ((m == 0) || (m > 4)) {
1512 PMU_ERROR(("%s: Bad m divider: %d\n", __FUNCTION__, m));
1513 return 0;
1516 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_P1P2_OFF);
1517 (void)R_REG(osh, &cc->pllcontrol_addr);
1518 tmp = R_REG(osh, &cc->pllcontrol_data);
1519 p1 = (tmp & PMU5_PLL_P1_MASK) >> PMU5_PLL_P1_SHIFT;
1520 p2 = (tmp & PMU5_PLL_P2_MASK) >> PMU5_PLL_P2_SHIFT;
1522 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_M14_OFF);
1523 (void)R_REG(osh, &cc->pllcontrol_addr);
1524 tmp = R_REG(osh, &cc->pllcontrol_data);
1525 div = (tmp >> ((m - 1) * PMU5_PLL_MDIV_WIDTH)) & PMU5_PLL_MDIV_MASK;
1527 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_NM5_OFF);
1528 (void)R_REG(osh, &cc->pllcontrol_addr);
1529 tmp = R_REG(osh, &cc->pllcontrol_data);
1530 ndiv = (tmp & PMU5_PLL_NDIV_MASK) >> PMU5_PLL_NDIV_SHIFT;
1532 /* Do calculation in Mhz */
1533 fc = si_pmu_alp_clock(sih, osh) / 1000000;
1534 fc = (p1 * ndiv * fc) / p2;
1536 PMU_NONE(("%s: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, clock=%d\n",
1537 __FUNCTION__, p1, p2, ndiv, ndiv, m, div, fc, fc / div));
1539 /* Return clock in Hertz */
1540 return ((fc / div) * 1000000);
1543 /* query backplane clock frequency */
1544 /* For designs that feed the same clock to both backplane
1545 * and CPU just return the CPU clock speed.
1547 uint32
1548 BCMINITFN(si_pmu_si_clock)(si_t *sih, osl_t *osh)
1550 chipcregs_t *cc;
1551 uint origidx;
1552 uint32 clock = HT_CLOCK;
1554 ASSERT(sih->cccaps & CC_CAP_PMU);
1556 /* Remember original core before switch to chipc */
1557 origidx = si_coreidx(sih);
1558 cc = si_setcoreidx(sih, SI_CC_IDX);
1559 ASSERT(cc != NULL);
1561 switch (CHIPID(sih->chip)) {
1562 case BCM4328_CHIP_ID:
1563 clock = si_pmu0_cpuclk0(sih, osh, cc);
1564 break;
1565 case BCM5354_CHIP_ID:
1566 clock = 120000000;
1567 break;
1568 case BCM4325_CHIP_ID:
1569 clock = si_pmu1_cpuclk0(sih, osh, cc);
1570 break;
1571 case BCM4322_CHIP_ID:
1572 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
1573 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
1574 case BCM43224_CHIP_ID:
1575 case BCM43225_CHIP_ID:
1576 case BCM43421_CHIP_ID:
1577 case BCM4342_CHIP_ID:
1578 /* 96MHz backplane clock */
1579 clock = 96000 * 1000;
1580 break;
1581 case BCM4716_CHIP_ID:
1582 case BCM4748_CHIP_ID:
1583 case BCM47162_CHIP_ID:
1584 clock = si_pmu5_clock(sih, osh, cc, PMU4716_MAINPLL_PLL0, PMU5_MAINPLL_SI);
1585 break;
1587 case BCM4319_CHIP_ID:
1588 clock = si_pmu1_cpuclk0(sih, osh, cc);
1589 break;
1591 default:
1592 PMU_MSG(("No backplane clock specified "
1593 "for chip %s rev %d pmurev %d, using default %d Hz\n",
1594 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev, clock));
1595 break;
1598 /* Return to original core */
1599 si_setcoreidx(sih, origidx);
1600 return clock;
1603 /* query CPU clock frequency */
1604 uint32
1605 BCMINITFN(si_pmu_cpu_clock)(si_t *sih, osl_t *osh)
1607 chipcregs_t *cc;
1608 uint origidx;
1609 uint32 clock;
1611 ASSERT(sih->cccaps & CC_CAP_PMU);
1613 /* 5354 chip uses a non programmable PLL of frequency 240MHz */
1614 if (sih->chip == BCM5354_CHIP_ID)
1615 return 240000000;
1617 if (((sih->pmurev == 5) || (sih->pmurev == 6) ||
1618 (sih->pmurev == 7)) && (CHIPID(sih->chip) != BCM4319_CHIP_ID)) {
1619 uint pll = PMU4716_MAINPLL_PLL0;
1621 /* Remember original core before switch to chipc */
1622 origidx = si_coreidx(sih);
1623 cc = si_setcoreidx(sih, SI_CC_IDX);
1624 ASSERT(cc != NULL);
1626 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_CPU);
1628 /* Return to original core */
1629 si_setcoreidx(sih, origidx);
1630 } else
1631 clock = si_pmu_si_clock(sih, osh);
1633 return clock;
1636 /* query Memroy clock frequency */
1637 uint32
1638 BCMINITFN(si_pmu_mem_clock)(si_t *sih, osl_t *osh)
1640 chipcregs_t *cc;
1641 uint origidx;
1642 uint32 clock;
1644 ASSERT(sih->cccaps & CC_CAP_PMU);
1646 if ((sih->pmurev == 5) || (sih->pmurev == 6) ||
1647 (sih->pmurev == 7)) {
1648 uint pll = PMU4716_MAINPLL_PLL0;
1650 /* Remember original core before switch to chipc */
1651 origidx = si_coreidx(sih);
1652 cc = si_setcoreidx(sih, SI_CC_IDX);
1653 ASSERT(cc != NULL);
1655 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_MEM);
1657 /* Return to original core */
1658 si_setcoreidx(sih, origidx);
1659 } else
1660 clock = si_pmu_si_clock(sih, osh);
1662 return clock;
1665 /* query ILP clock frequency */
1666 #define ILP_CALC_DUR 10 /* ms, make sure 1000 can be divided by it. */
1667 uint32
1668 BCMINITFN(si_pmu_ilp_clock)(si_t *sih, osl_t *osh)
1670 static uint32 ilpcycles_per_sec = 0;
1672 if (ISSIM_ENAB(sih))
1673 return ILP_CLOCK;
1675 if (ilpcycles_per_sec == 0) {
1676 uint32 start, end, delta;
1677 uint32 origidx = si_coreidx(sih);
1678 chipcregs_t *cc = si_setcoreidx(sih, SI_CC_IDX);
1679 ASSERT(cc != NULL);
1680 start = R_REG(osh, &cc->pmutimer);
1681 OSL_DELAY(ILP_CALC_DUR * 1000);
1682 end = R_REG(osh, &cc->pmutimer);
1683 delta = end >= start ? end - start : ~0 - start + 1 + end;
1684 ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
1685 si_setcoreidx(sih, origidx);
1688 return ilpcycles_per_sec;
1691 /* SDIO Pad drive strength to select value mappings */
1692 typedef struct {
1693 uint8 strength; /* Pad Drive Strength in mA */
1694 uint8 sel; /* Chip-specific select value */
1695 } sdiod_drive_str_t;
1697 /* SDIO Drive Strength to sel value table for PMU Rev 1 */
1698 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab1)[] = {
1699 {4, 0x2},
1700 {2, 0x3},
1701 {1, 0x0},
1702 {0, 0x0} };
1704 /* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
1705 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab2)[] = {
1706 {12, 0x7},
1707 {10, 0x6},
1708 {8, 0x5},
1709 {6, 0x4},
1710 {4, 0x2},
1711 {2, 0x1},
1712 {0, 0x0} };
1714 #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
1716 void
1717 BCMINITFN(si_sdiod_drive_strength_init)(si_t *sih, osl_t *osh, uint drivestrength)
1719 chipcregs_t *cc;
1720 uint origidx, intr_val;
1721 sdiod_drive_str_t *str_tab = NULL;
1722 uint32 str_mask = 0;
1723 uint32 str_shift = 0;
1725 if (!(sih->cccaps & CC_CAP_PMU)) {
1726 return;
1729 /* Remember original core before switch to chipc */
1730 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
1732 switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) {
1733 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
1734 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1;
1735 str_mask = 0x30000000;
1736 str_shift = 28;
1737 break;
1738 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
1739 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
1740 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2;
1741 str_mask = 0x00003800;
1742 str_shift = 11;
1743 break;
1745 default:
1746 PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
1747 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
1749 break;
1752 if (str_tab != NULL) {
1753 uint32 drivestrength_sel = 0;
1754 uint32 cc_data_temp;
1755 int i;
1757 for (i = 0; str_tab[i].strength != 0; i ++) {
1758 if (drivestrength >= str_tab[i].strength) {
1759 drivestrength_sel = str_tab[i].sel;
1760 break;
1764 W_REG(osh, &cc->chipcontrol_addr, 1);
1765 cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
1766 cc_data_temp &= ~str_mask;
1767 drivestrength_sel <<= str_shift;
1768 cc_data_temp |= drivestrength_sel;
1769 W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
1771 PMU_MSG(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
1772 drivestrength, cc_data_temp));
1775 /* Return to original core */
1776 si_restore_core(sih, origidx, intr_val);
1779 /* initialize PMU */
1780 void
1781 BCMINITFN(si_pmu_init)(si_t *sih, osl_t *osh)
1783 chipcregs_t *cc;
1784 uint origidx;
1786 ASSERT(sih->cccaps & CC_CAP_PMU);
1788 /* Remember original core before switch to chipc */
1789 origidx = si_coreidx(sih);
1790 cc = si_setcoreidx(sih, SI_CC_IDX);
1791 ASSERT(cc != NULL);
1793 if (sih->pmurev == 1)
1794 AND_REG(osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
1795 else if (sih->pmurev >= 2)
1796 OR_REG(osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT);
1798 /* Return to original core */
1799 si_setcoreidx(sih, origidx);
1802 /* Return up time in ILP cycles for the given resource. */
1803 static uint
1804 BCMINITFN(si_pmu_res_uptime)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint8 rsrc)
1806 uint32 deps;
1807 uint up, i, dup, dmax;
1808 uint32 min_mask = 0, max_mask = 0;
1810 /* uptime of resource 'rsrc' */
1811 W_REG(osh, &cc->res_table_sel, rsrc);
1812 up = (R_REG(osh, &cc->res_updn_timer) >> 8) & 0xff;
1814 /* direct dependancies of resource 'rsrc' */
1815 deps = si_pmu_res_deps(sih, osh, cc, PMURES_BIT(rsrc), FALSE);
1816 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
1817 if (!(deps & PMURES_BIT(i)))
1818 continue;
1819 deps &= ~si_pmu_res_deps(sih, osh, cc, PMURES_BIT(i), TRUE);
1821 si_pmu_res_masks(sih, &min_mask, &max_mask);
1822 deps &= ~min_mask;
1824 /* max uptime of direct dependancies */
1825 dmax = 0;
1826 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
1827 if (!(deps & PMURES_BIT(i)))
1828 continue;
1829 dup = si_pmu_res_uptime(sih, osh, cc, (uint8)i);
1830 if (dmax < dup)
1831 dmax = dup;
1834 PMU_MSG(("si_pmu_res_uptime: rsrc %u uptime %u(deps 0x%08x uptime %u)\n",
1835 rsrc, up, deps, dmax));
1837 return up + dmax + PMURES_UP_TRANSITION;
1840 /* Return dependancies (direct or all/indirect) for the given resources */
1841 static uint32
1842 si_pmu_res_deps(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 rsrcs, bool all)
1844 uint32 deps = 0;
1845 uint32 i;
1847 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
1848 if (!(rsrcs & PMURES_BIT(i)))
1849 continue;
1850 W_REG(osh, &cc->res_table_sel, i);
1851 deps |= R_REG(osh, &cc->res_dep_mask);
1854 return !all ? deps : (deps ? (deps | si_pmu_res_deps(sih, osh, cc, deps, TRUE)) : 0);
1857 /* power up/down OTP through PMU resources if PMU has that bit
1858 * 1. update chipc chipstatus reg
1859 * 2. refresh newly updated OTP content
1861 void
1862 si_pmu_otp_power(si_t *sih, osl_t *osh, bool on)
1864 chipcregs_t *cc;
1865 uint origidx;
1866 uint32 rsrcs = 0; /* rsrcs to turn on/off OTP power */
1868 ASSERT(sih->cccaps & CC_CAP_PMU);
1870 #if !defined(WLTEST)
1871 /* Don't do anything if OTP is disabled */
1872 if (si_is_otp_disabled(sih)) {
1873 PMU_MSG(("si_pmu_otp_power: OTP is disabled\n"));
1874 return;
1876 #endif
1878 /* Remember original core before switch to chipc */
1879 origidx = si_coreidx(sih);
1880 cc = si_setcoreidx(sih, SI_CC_IDX);
1881 ASSERT(cc != NULL);
1883 switch (CHIPID(sih->chip)) {
1884 case BCM4322_CHIP_ID:
1885 case BCM43221_CHIP_ID:
1886 case BCM43231_CHIP_ID:
1887 case BCM4342_CHIP_ID:
1888 rsrcs = PMURES_BIT(RES4322_OTP_PU);
1889 break;
1890 case BCM4325_CHIP_ID:
1891 rsrcs = PMURES_BIT(RES4325_LNLDO2_PU);
1892 break;
1893 case BCM4319_CHIP_ID:
1894 rsrcs = PMURES_BIT(RES4319_OTP_PU);
1895 break;
1897 default:
1898 break;
1901 if (rsrcs != 0) {
1902 uint32 otps;
1904 /* Figure out the dependancies (exclude min_res_mask) */
1905 uint32 deps = si_pmu_res_deps(sih, osh, cc, rsrcs, TRUE);
1906 uint32 min_mask = 0, max_mask = 0;
1907 si_pmu_res_masks(sih, &min_mask, &max_mask);
1908 deps &= ~min_mask;
1909 /* Turn on/off the power */
1910 if (on) {
1911 PMU_MSG(("Adding rsrc 0x%x to min_res_mask\n", rsrcs | deps));
1912 OR_REG(osh, &cc->min_res_mask, (rsrcs | deps));
1913 SPINWAIT(!(R_REG(osh, &cc->res_state) & rsrcs), PMU_MAX_TRANSITION_DLY);
1914 ASSERT(R_REG(osh, &cc->res_state) & rsrcs);
1916 else {
1917 PMU_MSG(("Removing rsrc 0x%x from min_res_mask\n", rsrcs | deps));
1918 AND_REG(osh, &cc->min_res_mask, ~(rsrcs | deps));
1921 SPINWAIT((((otps = R_REG(osh, &cc->otpstatus)) & OTPS_READY) !=
1922 (on ? OTPS_READY : 0)), 100);
1923 ASSERT((otps & OTPS_READY) == (on ? OTPS_READY : 0));
1924 if ((otps & OTPS_READY) != (on ? OTPS_READY : 0))
1925 PMU_MSG(("OTP ready bit not %s after wait\n", (on ? "ON" : "OFF")));
1928 /* Return to original core */
1929 si_setcoreidx(sih, origidx);
1932 void
1933 si_pmu_rcal(si_t *sih, osl_t *osh)
1935 chipcregs_t *cc;
1936 uint origidx;
1937 uint rcal_done, BT_out_of_reset;
1939 ASSERT(sih->cccaps & CC_CAP_PMU);
1941 /* Remember original core before switch to chipc */
1942 origidx = si_coreidx(sih);
1943 cc = si_setcoreidx(sih, SI_CC_IDX);
1944 ASSERT(cc != NULL);
1946 switch (CHIPID(sih->chip)) {
1947 case BCM4325_CHIP_ID: {
1948 uint8 rcal_code;
1949 uint32 val;
1951 /* Kick RCal */
1952 W_REG(osh, &cc->chipcontrol_addr, 1);
1954 /* Power Down RCAL Block */
1955 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
1957 /* Check if RCAL is already done by BT */
1958 rcal_done = ((R_REG(osh, &cc->chipstatus)) & 0x8) >> 3;
1960 /* If RCAL already done, note that BT is out of reset */
1961 if (rcal_done == 1) {
1962 BT_out_of_reset = 1;
1963 } else {
1964 BT_out_of_reset = 0;
1967 /* Power Up RCAL block */
1968 OR_REG(osh, &cc->chipcontrol_data, 0x04);
1970 /* Wait for completion */
1971 SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08), 10 * 1000 * 1000);
1972 ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
1974 if (BT_out_of_reset) {
1975 rcal_code = 0x6;
1976 } else {
1977 /* Drop the LSB to convert from 5 bit code to 4 bit code */
1978 rcal_code = (uint8)(R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
1981 PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
1982 R_REG(osh, &cc->chipstatus), rcal_code));
1984 /* Write RCal code into pmu_vreg_ctrl[32:29] */
1985 W_REG(osh, &cc->regcontrol_addr, 0);
1986 val = R_REG(osh, &cc->regcontrol_data) & ~((uint32)0x07 << 29);
1987 val |= (uint32)(rcal_code & 0x07) << 29;
1988 W_REG(osh, &cc->regcontrol_data, val);
1989 W_REG(osh, &cc->regcontrol_addr, 1);
1990 val = R_REG(osh, &cc->regcontrol_data) & ~(uint32)0x01;
1991 val |= (uint32)((rcal_code >> 3) & 0x01);
1992 W_REG(osh, &cc->regcontrol_data, val);
1994 /* Write RCal code into pmu_chip_ctrl[33:30] */
1995 W_REG(osh, &cc->chipcontrol_addr, 0);
1996 val = R_REG(osh, &cc->chipcontrol_data) & ~((uint32)0x03 << 30);
1997 val |= (uint32)(rcal_code & 0x03) << 30;
1998 W_REG(osh, &cc->chipcontrol_data, val);
1999 W_REG(osh, &cc->chipcontrol_addr, 1);
2000 val = R_REG(osh, &cc->chipcontrol_data) & ~(uint32)0x03;
2001 val |= (uint32)((rcal_code >> 2) & 0x03);
2002 W_REG(osh, &cc->chipcontrol_data, val);
2004 /* Set override in pmu_chip_ctrl[29] */
2005 W_REG(osh, &cc->chipcontrol_addr, 0);
2006 OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
2008 /* Power off RCal block */
2009 W_REG(osh, &cc->chipcontrol_addr, 1);
2010 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
2012 break;
2014 default:
2015 break;
2018 /* Return to original core */
2019 si_setcoreidx(sih, origidx);
2022 void
2023 si_pmu_spuravoid(si_t *sih, osl_t *osh, bool spuravoid)
2025 chipcregs_t *cc;
2026 uint origidx, intr_val;
2027 uint32 tmp = 0;
2029 /* Remember original core before switch to chipc */
2030 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
2031 ASSERT(cc != NULL);
2033 switch (CHIPID(sih->chip)) {
2034 case BCM43224_CHIP_ID:
2035 case BCM43225_CHIP_ID:
2036 case BCM43421_CHIP_ID:
2037 if (spuravoid) {
2038 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2039 W_REG(osh, &cc->pllcontrol_data, 0x11500010);
2040 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2041 W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
2042 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2043 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
2044 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2045 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2046 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2047 W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
2048 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2049 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2050 } else {
2051 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2052 W_REG(osh, &cc->pllcontrol_data, 0x11100010);
2053 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2054 W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
2055 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2056 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
2057 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2058 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2059 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2060 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
2061 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2062 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2064 tmp = 1 << 10;
2065 break;
2067 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
2068 if (spuravoid) {
2069 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2070 W_REG(osh, &cc->pllcontrol_data, 0x11500008);
2071 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2072 W_REG(osh, &cc->pllcontrol_data, 0x0C000C06);
2073 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2074 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
2075 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2076 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2077 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2078 W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
2079 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2080 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2081 } else {
2082 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2083 W_REG(osh, &cc->pllcontrol_data, 0x11100008);
2084 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2085 W_REG(osh, &cc->pllcontrol_data, 0x0c000c06);
2086 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2087 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
2088 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2089 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2090 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2091 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
2092 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2093 W_REG(osh, &cc->pllcontrol_data, 0x88888855);
2096 tmp = 1 << 10;
2097 break;
2100 case BCM4716_CHIP_ID:
2101 case BCM4748_CHIP_ID:
2102 case BCM47162_CHIP_ID:
2103 if (spuravoid) {
2104 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2105 W_REG(osh, &cc->pllcontrol_data, 0x11500060);
2106 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2107 W_REG(osh, &cc->pllcontrol_data, 0x080C0C06);
2108 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2109 W_REG(osh, &cc->pllcontrol_data, 0x0F600000);
2110 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2111 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2112 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2113 W_REG(osh, &cc->pllcontrol_data, 0x2001E924);
2114 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2115 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2116 } else {
2117 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2118 W_REG(osh, &cc->pllcontrol_data, 0x11100060);
2119 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2120 W_REG(osh, &cc->pllcontrol_data, 0x080c0c06);
2121 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2122 W_REG(osh, &cc->pllcontrol_data, 0x03000000);
2123 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2124 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2125 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2126 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
2127 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2128 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2131 tmp = 3 << 9;
2132 break;
2134 case BCM4322_CHIP_ID:
2135 case BCM43221_CHIP_ID:
2136 case BCM43231_CHIP_ID:
2137 case BCM4342_CHIP_ID:
2138 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2139 W_REG(osh, &cc->pllcontrol_data, 0x11100070);
2140 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2141 W_REG(osh, &cc->pllcontrol_data, 0x1014140a);
2142 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2143 W_REG(osh, &cc->pllcontrol_data, 0x88888854);
2145 if (spuravoid) { /* spur_avoid ON, enable 41/82/164Mhz clock mode */
2146 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2147 W_REG(osh, &cc->pllcontrol_data, 0x05201828);
2148 } else { /* enable 40/80/160Mhz clock mode */
2149 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2150 W_REG(osh, &cc->pllcontrol_data, 0x05001828);
2153 tmp = 1 << 10;
2154 break;
2155 case BCM4319_CHIP_ID:
2156 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2157 W_REG(osh, &cc->pllcontrol_data, 0x11100070);
2158 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2159 W_REG(osh, &cc->pllcontrol_data, 0x1014140a);
2160 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2161 W_REG(osh, &cc->pllcontrol_data, 0x88888854);
2163 if (spuravoid) { /* spur_avoid ON, enable 41/82/164Mhz clock mode */
2164 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2165 W_REG(osh, &cc->pllcontrol_data, 0x05201828);
2166 } else { /* enable 40/80/160Mhz clock mode */
2167 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2168 W_REG(osh, &cc->pllcontrol_data, 0x05001828);
2171 default:
2172 PMU_ERROR(("%s: unknown spuravoidance settings for chip %s, not changing PLL\n",
2173 __FUNCTION__, bcm_chipname(sih->chip, chn, 8)));
2174 break;
2177 tmp |= R_REG(osh, &cc->pmucontrol);
2178 W_REG(osh, &cc->pmucontrol, tmp);
2180 /* Return to original core */
2181 si_restore_core(sih, origidx, intr_val);
2184 void
2185 si_pmu_gband_spurwar(si_t *sih, osl_t *osh)
2187 chipcregs_t *cc;
2188 uint origidx, intr_val;
2189 uint32 cc_clk_ctl_st;
2190 uint32 minmask, maxmask;
2192 if (CHIPID(sih->chip) == BCM43222_CHIP_ID) {
2193 /* Remember original core before switch to chipc */
2194 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
2195 ASSERT(cc != NULL);
2197 /* Remove force HT and HT Avail Request from chipc core */
2198 cc_clk_ctl_st = R_REG(osh, &cc->clk_ctl_st);
2199 AND_REG(osh, &cc->clk_ctl_st, ~(CCS_FORCEHT | CCS_HTAREQ));
2201 minmask = R_REG(osh, &cc->min_res_mask);
2202 maxmask = R_REG(osh, &cc->max_res_mask);
2204 /* Make sure the PLL is off: clear bit 4 & 5 of min/max_res_mask */
2205 /* Have to remove HT Avail request before powering off PLL */
2206 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
2207 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
2208 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2209 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
2210 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
2211 OSL_DELAY(150);
2212 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2214 /* Change backplane clock speed from 96 MHz to 80 MHz */
2215 W_REG(osh, &cc->pllcontrol_addr, PMU2_PLL_PLLCTL2);
2216 W_REG(osh, &cc->pllcontrol_data, (R_REG(osh, &cc->pllcontrol_data) &
2217 ~(PMU2_PLL_PC2_M6DIV_MASK)) |
2218 (0xc << PMU2_PLL_PC2_M6DIV_SHIFT));
2220 /* Reduce the driver strengths of the phyclk160, adcclk80, and phyck80
2221 * clocks from 0x8 to 0x1
2223 W_REG(osh, &cc->pllcontrol_addr, PMU2_PLL_PLLCTL5);
2224 W_REG(osh, &cc->pllcontrol_data, (R_REG(osh, &cc->pllcontrol_data) &
2225 ~(PMU2_PLL_PC5_CLKDRIVE_CH1_MASK |
2226 PMU2_PLL_PC5_CLKDRIVE_CH2_MASK |
2227 PMU2_PLL_PC5_CLKDRIVE_CH3_MASK |
2228 PMU2_PLL_PC5_CLKDRIVE_CH4_MASK)) |
2229 ((1 << PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT) |
2230 (1 << PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT) |
2231 (1 << PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT) |
2232 (1 << PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT)));
2234 W_REG(osh, &cc->pmucontrol, R_REG(osh, &cc->pmucontrol) | PCTL_PLL_PLLCTL_UPD);
2236 /* Restore min_res_mask and max_res_mask */
2237 OSL_DELAY(100);
2238 W_REG(osh, &cc->max_res_mask, maxmask);
2239 OSL_DELAY(100);
2240 W_REG(osh, &cc->min_res_mask, minmask);
2241 OSL_DELAY(100);
2242 /* Make sure the PLL is on. Spinwait until the HTAvail is True */
2243 SPINWAIT(~(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL), PMU_MAX_TRANSITION_DLY);
2244 ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2246 /* Restore force HT and HT Avail Request on the chipc core */
2247 W_REG(osh, &cc->clk_ctl_st, cc_clk_ctl_st);
2249 /* Return to original core */
2250 si_restore_core(sih, origidx, intr_val);
2254 bool
2255 si_pmu_is_otp_powered(si_t *sih, osl_t *osh)
2257 uint idx;
2258 chipcregs_t *cc;
2259 bool st;
2261 /* Retrieve OTP region info */
2262 idx = si_coreidx(sih);
2263 cc = si_setcoreidx(sih, SI_CC_IDX);
2264 ASSERT(cc != NULL);
2266 switch (CHIPID(sih->chip)) {
2267 case BCM4322_CHIP_ID:
2268 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
2269 case BCM4342_CHIP_ID:
2270 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4322_OTP_PU)) != 0;
2271 break;
2272 case BCM4325_CHIP_ID:
2273 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4325_LNLDO2_PU)) != 0;
2274 break;
2275 case BCM4319_CHIP_ID:
2276 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4319_OTP_PU)) != 0;
2277 break;
2279 /* These chip doesn't use PMU bit to power up/down OTP. OTP always on.
2280 * Use OTP_INIT command to reset/refresh state.
2282 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
2283 case BCM43224_CHIP_ID:
2284 case BCM43225_CHIP_ID:
2285 case BCM43421_CHIP_ID:
2286 default:
2287 st = TRUE;
2288 break;
2291 si_setcoreidx(sih, idx);
2292 return st;
2295 /* initialize PMU chip controls */
2296 void
2297 BCMINITFN(si_pmu_chip_init)(si_t *sih, osl_t *osh)
2299 ASSERT(sih->cccaps & CC_CAP_PMU);
2302 /* initialize PMU switch/regulators */
2303 void
2304 BCMINITFN(si_pmu_swreg_init)(si_t *sih, osl_t *osh)
2306 ASSERT(sih->cccaps & CC_CAP_PMU);
2308 switch (CHIPID(sih->chip)) {
2309 case BCM4325_CHIP_ID:
2310 if ((sih->chiprev >= 3) &&
2311 (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
2312 CST4325_PMUTOP_2B_SHIFT) == 1)) {
2313 /* Bump CLDO PWM output voltage to 1.25V */
2314 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xf);
2315 /* Bump CBUCK PWM output voltage to 1.5V */
2316 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0xb);
2318 break;
2319 default:
2320 break;
2324 /* Wait for a particular clock level to be on the backplane */
2325 uint32
2326 si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, uint32 clk, uint32 delay)
2328 chipcregs_t *cc;
2329 uint origidx;
2331 ASSERT(sih->cccaps & CC_CAP_PMU);
2333 /* Remember original core before switch to chipc */
2334 origidx = si_coreidx(sih);
2335 cc = si_setcoreidx(sih, SI_CC_IDX);
2336 ASSERT(cc != NULL);
2338 if (delay)
2339 SPINWAIT(((R_REG(osh, &cc->pmustatus) & clk) != clk), delay);
2341 /* Return to original core */
2342 si_setcoreidx(sih, origidx);
2344 return (R_REG(osh, &cc->pmustatus) & clk);