Clean and tiddy-up files.
[tomato.git] / release / src-rt / shared / hndpmu.c
blob40cd75e293624f25b2ad6647c9f4e1d5599c0d26
1 /*
2 * Misc utility routines for accessing PMU corerev specific features
3 * of the SiliconBackplane-based Broadcom chips.
5 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * $Id: hndpmu.c,v 1.234.2.35 2011-02-11 21:35:40 Exp $
22 #include <typedefs.h>
23 #include <bcmdefs.h>
24 #include <osl.h>
25 #include <bcmutils.h>
26 #include <siutils.h>
27 #include <bcmdevs.h>
28 #include <hndsoc.h>
29 #include <sbchipc.h>
30 #include <hndpmu.h>
32 #ifdef BCMDBG_ERR
33 #define PMU_ERROR(args) printf args
34 #else
35 #define PMU_ERROR(args)
36 #endif /* BCMDBG_ERR */
38 #ifdef BCMDBG
39 #define PMU_MSG(args) printf args
40 #else
41 #define PMU_MSG(args)
42 #endif /* BCMDBG */
44 /* To check in verbose debugging messages not intended
45 * to be on except on private builds.
47 #define PMU_NONE(args)
49 /* PLL controls/clocks */
50 static void si_pmu0_pllinit0(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal);
51 static uint32 si_pmu0_alpclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
52 #if !defined(_CFE_) || defined(CFG_WL)
53 static uint32 si_pmu0_cpuclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
54 static void si_pmu1_pllinit0(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal);
55 static uint32 si_pmu1_cpuclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
56 static uint32 si_pmu1_alpclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
58 /* PMU resources */
59 static bool si_pmu_res_depfltr_bb(si_t *sih);
60 static bool si_pmu_res_depfltr_ncb(si_t *sih);
61 static bool si_pmu_res_depfltr_paldo(si_t *sih);
62 static bool si_pmu_res_depfltr_npaldo(si_t *sih);
63 static uint32 si_pmu_res_deps(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 rsrcs, bool all);
64 static uint si_pmu_res_uptime(si_t *sih, osl_t *osh, chipcregs_t *cc, uint8 rsrc);
65 static void si_pmu_res_masks(si_t *sih, uint32 *pmin, uint32 *pmax);
66 static void si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, osl_t *osh, uint8 spuravoid);
68 void si_pmu_set_4330_plldivs(si_t *sih, uint8 dacrate);
69 #endif /* !_CFE_ || CFG_WL */
71 /* FVCO frequency */
72 #define FVCO_880 880000 /* 880MHz */
73 #define FVCO_1760 1760000 /* 1760MHz */
74 #define FVCO_1440 1440000 /* 1440MHz */
75 #define FVCO_960 960000 /* 960MHz */
77 /* Read/write a chipcontrol reg */
78 uint32
79 si_pmu_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
81 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr), ~0, reg);
82 return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_data), mask, val);
85 /* Read/write a regcontrol reg */
86 uint32
87 si_pmu_regcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
89 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_addr), ~0, reg);
90 return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_data), mask, val);
93 /* Read/write a pllcontrol reg */
94 uint32
95 si_pmu_pllcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
97 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pllcontrol_addr), ~0, reg);
98 return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pllcontrol_data), mask, val);
101 /* PMU PLL update */
102 void
103 si_pmu_pllupd(si_t *sih)
105 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmucontrol),
106 PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
109 /* PMU PLL reset */
110 void
111 si_pmu_pllreset(si_t *sih)
113 uint32 res_mask = 0;
114 chipcregs_t *cc;
115 uint origidx;
117 /* Remember original core before switch to chipc */
118 origidx = si_coreidx(sih);
119 cc = si_setcoreidx(sih, SI_CC_IDX);
120 ASSERT(cc != NULL);
122 res_mask = PMURES_BIT(RES4330_BBPLL_PWRSW_PU) | PMURES_BIT(RES4330_MACPHY_CLKAVAIL) |
123 PMURES_BIT(RES4330_HT_AVAIL);
125 AND_REG(si_osh(sih), &cc->min_res_mask, ~(res_mask));
126 AND_REG(si_osh(sih), &cc->max_res_mask, ~(res_mask));
127 OR_REG(si_osh(sih), &cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
128 OR_REG(si_osh(sih), &cc->max_res_mask, res_mask);
130 /* Return to original core */
131 si_setcoreidx(sih, origidx);
134 /* Setup switcher voltage */
135 void
136 BCMATTACHFN(si_pmu_set_switcher_voltage)(si_t *sih, osl_t *osh,
137 uint8 bb_voltage, uint8 rf_voltage)
139 chipcregs_t *cc;
140 uint origidx;
142 ASSERT(sih->cccaps & CC_CAP_PMU);
144 /* Remember original core before switch to chipc */
145 origidx = si_coreidx(sih);
146 cc = si_setcoreidx(sih, SI_CC_IDX);
147 ASSERT(cc != NULL);
149 W_REG(osh, &cc->regcontrol_addr, 0x01);
150 W_REG(osh, &cc->regcontrol_data, (uint32)(bb_voltage & 0x1f) << 22);
152 W_REG(osh, &cc->regcontrol_addr, 0x00);
153 W_REG(osh, &cc->regcontrol_data, (uint32)(rf_voltage & 0x1f) << 14);
155 /* Return to original core */
156 si_setcoreidx(sih, origidx);
159 void
160 BCMATTACHFN(si_pmu_set_ldo_voltage)(si_t *sih, osl_t *osh, uint8 ldo, uint8 voltage)
162 uint8 sr_cntl_shift = 0, rc_shift = 0, shift = 0, mask = 0;
163 uint8 addr = 0;
165 ASSERT(sih->cccaps & CC_CAP_PMU);
167 switch (CHIPID(sih->chip)) {
168 case BCM4328_CHIP_ID:
169 case BCM5354_CHIP_ID:
170 switch (ldo) {
171 case SET_LDO_VOLTAGE_LDO1:
172 addr = 2;
173 sr_cntl_shift = 8;
174 rc_shift = 17;
175 mask = 0xf;
176 break;
177 case SET_LDO_VOLTAGE_LDO2:
178 addr = 3;
179 rc_shift = 1;
180 mask = 0xf;
181 break;
182 case SET_LDO_VOLTAGE_LDO3:
183 addr = 3;
184 rc_shift = 9;
185 mask = 0xf;
186 break;
187 case SET_LDO_VOLTAGE_PAREF:
188 addr = 3;
189 rc_shift = 17;
190 mask = 0x3f;
191 break;
192 default:
193 ASSERT(FALSE);
194 return;
196 break;
197 case BCM4312_CHIP_ID:
198 switch (ldo) {
199 case SET_LDO_VOLTAGE_PAREF:
200 addr = 0;
201 rc_shift = 21;
202 mask = 0x3f;
203 break;
204 default:
205 ASSERT(FALSE);
206 return;
208 break;
209 case BCM4325_CHIP_ID:
210 switch (ldo) {
211 case SET_LDO_VOLTAGE_CLDO_PWM:
212 addr = 5;
213 rc_shift = 9;
214 mask = 0xf;
215 break;
216 case SET_LDO_VOLTAGE_CLDO_BURST:
217 addr = 5;
218 rc_shift = 13;
219 mask = 0xf;
220 break;
221 case SET_LDO_VOLTAGE_CBUCK_PWM:
222 addr = 3;
223 rc_shift = 20;
224 mask = 0x1f;
225 /* Bit 116 & 119 are inverted in CLB for opt 2b */
226 if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
227 CST4325_PMUTOP_2B_SHIFT) == 1)
228 voltage ^= 0x9;
229 break;
230 case SET_LDO_VOLTAGE_CBUCK_BURST:
231 addr = 3;
232 rc_shift = 25;
233 mask = 0x1f;
234 /* Bit 121 & 124 are inverted in CLB for opt 2b */
235 if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
236 CST4325_PMUTOP_2B_SHIFT) == 1)
237 voltage ^= 0x9;
238 break;
239 case SET_LDO_VOLTAGE_LNLDO1:
240 addr = 5;
241 rc_shift = 17;
242 mask = 0x1f;
243 break;
244 case SET_LDO_VOLTAGE_LNLDO2_SEL:
245 addr = 6;
246 rc_shift = 0;
247 mask = 0x1;
248 break;
249 default:
250 ASSERT(FALSE);
251 return;
253 break;
254 case BCM4336_CHIP_ID:
255 switch (ldo) {
256 case SET_LDO_VOLTAGE_CLDO_PWM:
257 addr = 4;
258 rc_shift = 1;
259 mask = 0xf;
260 break;
261 case SET_LDO_VOLTAGE_CLDO_BURST:
262 addr = 4;
263 rc_shift = 5;
264 mask = 0xf;
265 break;
266 case SET_LDO_VOLTAGE_LNLDO1:
267 addr = 4;
268 rc_shift = 17;
269 mask = 0xf;
270 break;
271 default:
272 ASSERT(FALSE);
273 return;
275 break;
276 case BCM4330_CHIP_ID:
277 switch (ldo) {
278 case SET_LDO_VOLTAGE_CBUCK_PWM:
279 addr = 3;
280 rc_shift = 0;
281 mask = 0x1f;
282 break;
283 default:
284 ASSERT(FALSE);
285 break;
287 break;
288 case BCM4331_CHIP_ID:
289 switch (ldo) {
290 case SET_LDO_VOLTAGE_PAREF:
291 addr = 1;
292 rc_shift = 0;
293 mask = 0xf;
294 break;
295 default:
296 ASSERT(FALSE);
297 break;
299 break;
300 default:
301 ASSERT(FALSE);
302 return;
305 shift = sr_cntl_shift + rc_shift;
307 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_addr),
308 ~0, addr);
309 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_data),
310 mask << shift, (voltage & mask) << shift);
313 void
314 si_pmu_paref_ldo_enable(si_t *sih, osl_t *osh, bool enable)
316 uint ldo = 0;
318 ASSERT(sih->cccaps & CC_CAP_PMU);
320 switch (CHIPID(sih->chip)) {
321 case BCM4328_CHIP_ID:
322 ldo = RES4328_PA_REF_LDO;
323 break;
324 case BCM5354_CHIP_ID:
325 ldo = RES5354_PA_REF_LDO;
326 break;
327 case BCM4312_CHIP_ID:
328 ldo = RES4312_PA_REF_LDO;
329 break;
330 default:
331 return;
334 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask),
335 PMURES_BIT(ldo), enable ? PMURES_BIT(ldo) : 0);
338 #if !defined(_CFE_) || defined(CFG_WL)
339 /* d11 slow to fast clock transition time in slow clock cycles */
340 #define D11SCC_SLOW2FAST_TRANSITION 2
342 uint16
343 BCMINITFN(si_pmu_fast_pwrup_delay)(si_t *sih, osl_t *osh)
345 uint delay = PMU_MAX_TRANSITION_DLY;
346 chipcregs_t *cc;
347 uint origidx;
348 #ifdef BCMDBG
349 char chn[8];
351 chn[0] = 0; /* to suppress compile error */
352 #endif
354 ASSERT(sih->cccaps & CC_CAP_PMU);
356 /* Remember original core before switch to chipc */
357 origidx = si_coreidx(sih);
358 cc = si_setcoreidx(sih, SI_CC_IDX);
359 ASSERT(cc != NULL);
361 switch (CHIPID(sih->chip)) {
362 case BCM4312_CHIP_ID:
363 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
364 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
365 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43420_CHIP_ID:
366 case BCM43421_CHIP_ID:
367 case BCM43226_CHIP_ID:
368 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
369 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
370 case BCM4331_CHIP_ID:
371 case BCM43431_CHIP_ID:
372 case BCM43227_CHIP_ID:
373 case BCM43228_CHIP_ID:
374 case BCM43428_CHIP_ID:
375 case BCM6362_CHIP_ID:
376 case BCM4342_CHIP_ID:
377 case BCM4313_CHIP_ID:
378 delay = ISSIM_ENAB(sih) ? 70 : 3700;
379 break;
380 case BCM4328_CHIP_ID:
381 delay = 7000;
382 break;
383 case BCM4325_CHIP_ID:
384 if (ISSIM_ENAB(sih))
385 delay = 70;
386 else {
387 uint32 ilp = si_ilp_clock(sih);
388 delay = (si_pmu_res_uptime(sih, osh, cc, RES4325_HT_AVAIL) +
389 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
390 delay = (11 * delay) / 10;
392 break;
393 case BCM4329_CHIP_ID:
394 if (ISSIM_ENAB(sih))
395 delay = 70;
396 else {
397 uint32 ilp = si_ilp_clock(sih);
398 delay = (si_pmu_res_uptime(sih, osh, cc, RES4329_HT_AVAIL) +
399 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
400 delay = (11 * delay) / 10;
402 break;
403 case BCM4315_CHIP_ID:
404 if (ISSIM_ENAB(sih))
405 delay = 70;
406 else {
407 uint32 ilp = si_ilp_clock(sih);
408 delay = (si_pmu_res_uptime(sih, osh, cc, RES4315_HT_AVAIL) +
409 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
410 delay = (11 * delay) / 10;
412 break;
413 case BCM4319_CHIP_ID:
414 if (ISSIM_ENAB(sih))
415 delay = 70;
416 else {
417 #ifdef BCMUSBDEV
418 /* For USB HT is always available, even durring IEEE PS,
419 * so need minimal delay
421 delay = 100;
422 #else /* BCMUSBDEV */
423 /* For SDIO, total delay in getting HT available */
424 /* Adjusted for uptime XTAL=672us, HTAVail=128us */
425 uint32 ilp = si_ilp_clock(sih);
426 delay = si_pmu_res_uptime(sih, osh, cc, RES4319_HT_AVAIL);
427 PMU_MSG(("si_ilp_clock (Hz): %u delay (ilp clks): %u\n", ilp, delay));
428 delay = (delay + D11SCC_SLOW2FAST_TRANSITION) * (1000000 / ilp);
429 PMU_MSG(("delay (us): %u\n", delay));
430 delay = (11 * delay) / 10;
431 PMU_MSG(("delay (us): %u\n", delay));
432 /* VDDIO_RF por delay = 3.4ms */
433 if (delay < 3400) delay = 3400;
434 #endif /* BCMUSBDEV */
436 break;
437 case BCM4336_CHIP_ID:
438 if (ISSIM_ENAB(sih))
439 delay = 70;
440 else {
441 uint32 ilp = si_ilp_clock(sih);
442 delay = (si_pmu_res_uptime(sih, osh, cc, RES4336_HT_AVAIL) +
443 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
444 delay = (11 * delay) / 10;
446 break;
447 case BCM4330_CHIP_ID:
448 if (ISSIM_ENAB(sih))
449 delay = 70;
450 else {
451 uint32 ilp = si_ilp_clock(sih);
452 delay = (si_pmu_res_uptime(sih, osh, cc, RES4330_HT_AVAIL) +
453 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
454 delay = (11 * delay) / 10;
456 break;
457 default:
458 break;
461 /* PMU_MSG(("si_pmu_fast_pwrup_delay: chip %s rev %d delay %d\n",
462 * bcm_chipname(sih->chip, chn, 8), sih->chiprev, delay));
465 /* Return to original core */
466 si_setcoreidx(sih, origidx);
468 return (uint16)delay;
470 #endif /* !_CFE_ || CFG_WL */
472 uint32
473 BCMATTACHFN(si_pmu_force_ilp)(si_t *sih, osl_t *osh, bool force)
475 chipcregs_t *cc;
476 uint origidx;
477 uint32 oldpmucontrol;
479 ASSERT(sih->cccaps & CC_CAP_PMU);
481 /* Remember original core before switch to chipc */
482 origidx = si_coreidx(sih);
483 cc = si_setcoreidx(sih, SI_CC_IDX);
484 ASSERT(cc != NULL);
486 oldpmucontrol = R_REG(osh, &cc->pmucontrol);
487 if (force)
488 W_REG(osh, &cc->pmucontrol, oldpmucontrol &
489 ~(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
490 else
491 W_REG(osh, &cc->pmucontrol, oldpmucontrol |
492 (PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
494 /* Return to original core */
495 si_setcoreidx(sih, origidx);
497 return oldpmucontrol;
500 /* Setup resource up/down timers */
501 typedef struct {
502 uint8 resnum;
503 uint16 updown;
504 } pmu_res_updown_t;
506 /* Change resource dependancies masks */
507 typedef struct {
508 uint32 res_mask; /* resources (chip specific) */
509 int8 action; /* action */
510 uint32 depend_mask; /* changes to the dependancies mask */
511 bool (*filter)(si_t *sih); /* action is taken when filter is NULL or return TRUE */
512 } pmu_res_depend_t;
514 /* Resource dependancies mask change action */
515 #define RES_DEPEND_SET 0 /* Override the dependancies mask */
516 #define RES_DEPEND_ADD 1 /* Add to the dependancies mask */
517 #define RES_DEPEND_REMOVE -1 /* Remove from the dependancies mask */
519 #if !defined(_CFE_) || defined(CFG_WL)
520 static const pmu_res_updown_t BCMATTACHDATA(bcm4328a0_res_updown)[] = {
521 { RES4328_EXT_SWITCHER_PWM, 0x0101 },
522 { RES4328_BB_SWITCHER_PWM, 0x1f01 },
523 { RES4328_BB_SWITCHER_BURST, 0x010f },
524 { RES4328_BB_EXT_SWITCHER_BURST, 0x0101 },
525 { RES4328_ILP_REQUEST, 0x0202 },
526 { RES4328_RADIO_SWITCHER_PWM, 0x0f01 },
527 { RES4328_RADIO_SWITCHER_BURST, 0x0f01 },
528 { RES4328_ROM_SWITCH, 0x0101 },
529 { RES4328_PA_REF_LDO, 0x0f01 },
530 { RES4328_RADIO_LDO, 0x0f01 },
531 { RES4328_AFE_LDO, 0x0f01 },
532 { RES4328_PLL_LDO, 0x0f01 },
533 { RES4328_BG_FILTBYP, 0x0101 },
534 { RES4328_TX_FILTBYP, 0x0101 },
535 { RES4328_RX_FILTBYP, 0x0101 },
536 { RES4328_XTAL_PU, 0x0101 },
537 { RES4328_XTAL_EN, 0xa001 },
538 { RES4328_BB_PLL_FILTBYP, 0x0101 },
539 { RES4328_RF_PLL_FILTBYP, 0x0101 },
540 { RES4328_BB_PLL_PU, 0x0701 }
543 static const pmu_res_depend_t BCMATTACHDATA(bcm4328a0_res_depend)[] = {
544 /* Adjust ILP request resource not to force ext/BB switchers into burst mode */
546 PMURES_BIT(RES4328_ILP_REQUEST),
547 RES_DEPEND_SET,
548 PMURES_BIT(RES4328_EXT_SWITCHER_PWM) | PMURES_BIT(RES4328_BB_SWITCHER_PWM),
549 NULL
553 static const pmu_res_updown_t BCMATTACHDATA(bcm4325a0_res_updown_qt)[] = {
554 { RES4325_HT_AVAIL, 0x0300 },
555 { RES4325_BBPLL_PWRSW_PU, 0x0101 },
556 { RES4325_RFPLL_PWRSW_PU, 0x0101 },
557 { RES4325_ALP_AVAIL, 0x0100 },
558 { RES4325_XTAL_PU, 0x1000 },
559 { RES4325_LNLDO1_PU, 0x0800 },
560 { RES4325_CLDO_CBUCK_PWM, 0x0101 },
561 { RES4325_CBUCK_PWM, 0x0803 }
564 static const pmu_res_updown_t BCMATTACHDATA(bcm4325a0_res_updown)[] = {
565 { RES4325_XTAL_PU, 0x1501 }
568 static const pmu_res_depend_t BCMATTACHDATA(bcm4325a0_res_depend)[] = {
569 /* Adjust OTP PU resource dependencies - remove BB BURST */
571 PMURES_BIT(RES4325_OTP_PU),
572 RES_DEPEND_REMOVE,
573 PMURES_BIT(RES4325_BUCK_BOOST_BURST),
574 NULL
576 /* Adjust ALP/HT Avail resource dependencies - bring up BB along if it is used. */
578 PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_HT_AVAIL),
579 RES_DEPEND_ADD,
580 PMURES_BIT(RES4325_BUCK_BOOST_BURST) | PMURES_BIT(RES4325_BUCK_BOOST_PWM),
581 si_pmu_res_depfltr_bb
583 /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
585 PMURES_BIT(RES4325_HT_AVAIL),
586 RES_DEPEND_ADD,
587 PMURES_BIT(RES4325_RX_PWRSW_PU) | PMURES_BIT(RES4325_TX_PWRSW_PU) |
588 PMURES_BIT(RES4325_LOGEN_PWRSW_PU) | PMURES_BIT(RES4325_AFE_PWRSW_PU),
589 NULL
591 /* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
593 PMURES_BIT(RES4325_ILP_REQUEST) | PMURES_BIT(RES4325_ABUCK_BURST) |
594 PMURES_BIT(RES4325_ABUCK_PWM) | PMURES_BIT(RES4325_LNLDO1_PU) |
595 PMURES_BIT(RES4325C1_LNLDO2_PU) | PMURES_BIT(RES4325_XTAL_PU) |
596 PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_RX_PWRSW_PU) |
597 PMURES_BIT(RES4325_TX_PWRSW_PU) | PMURES_BIT(RES4325_RFPLL_PWRSW_PU) |
598 PMURES_BIT(RES4325_LOGEN_PWRSW_PU) | PMURES_BIT(RES4325_AFE_PWRSW_PU) |
599 PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL),
600 RES_DEPEND_REMOVE,
601 PMURES_BIT(RES4325B0_CBUCK_LPOM) | PMURES_BIT(RES4325B0_CBUCK_BURST) |
602 PMURES_BIT(RES4325B0_CBUCK_PWM),
603 si_pmu_res_depfltr_ncb
607 static const pmu_res_updown_t BCMATTACHDATA(bcm4315a0_res_updown_qt)[] = {
608 { RES4315_HT_AVAIL, 0x0101 },
609 { RES4315_XTAL_PU, 0x0100 },
610 { RES4315_LNLDO1_PU, 0x0100 },
611 { RES4315_PALDO_PU, 0x0100 },
612 { RES4315_CLDO_PU, 0x0100 },
613 { RES4315_CBUCK_PWM, 0x0100 },
614 { RES4315_CBUCK_BURST, 0x0100 },
615 { RES4315_CBUCK_LPOM, 0x0100 }
618 static const pmu_res_updown_t BCMATTACHDATA(bcm4315a0_res_updown)[] = {
619 { RES4315_XTAL_PU, 0x2501 }
622 static const pmu_res_depend_t BCMATTACHDATA(bcm4315a0_res_depend)[] = {
623 /* Adjust OTP PU resource dependencies - not need PALDO unless write */
625 PMURES_BIT(RES4315_OTP_PU),
626 RES_DEPEND_REMOVE,
627 PMURES_BIT(RES4315_PALDO_PU),
628 si_pmu_res_depfltr_npaldo
630 /* Adjust ALP/HT Avail resource dependencies - bring up PALDO along if it is used. */
632 PMURES_BIT(RES4315_ALP_AVAIL) | PMURES_BIT(RES4315_HT_AVAIL),
633 RES_DEPEND_ADD,
634 PMURES_BIT(RES4315_PALDO_PU),
635 si_pmu_res_depfltr_paldo
637 /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
639 PMURES_BIT(RES4315_HT_AVAIL),
640 RES_DEPEND_ADD,
641 PMURES_BIT(RES4315_RX_PWRSW_PU) | PMURES_BIT(RES4315_TX_PWRSW_PU) |
642 PMURES_BIT(RES4315_LOGEN_PWRSW_PU) | PMURES_BIT(RES4315_AFE_PWRSW_PU),
643 NULL
645 /* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
647 PMURES_BIT(RES4315_CLDO_PU) | PMURES_BIT(RES4315_ILP_REQUEST) |
648 PMURES_BIT(RES4315_LNLDO1_PU) | PMURES_BIT(RES4315_OTP_PU) |
649 PMURES_BIT(RES4315_LNLDO2_PU) | PMURES_BIT(RES4315_XTAL_PU) |
650 PMURES_BIT(RES4315_ALP_AVAIL) | PMURES_BIT(RES4315_RX_PWRSW_PU) |
651 PMURES_BIT(RES4315_TX_PWRSW_PU) | PMURES_BIT(RES4315_RFPLL_PWRSW_PU) |
652 PMURES_BIT(RES4315_LOGEN_PWRSW_PU) | PMURES_BIT(RES4315_AFE_PWRSW_PU) |
653 PMURES_BIT(RES4315_BBPLL_PWRSW_PU) | PMURES_BIT(RES4315_HT_AVAIL),
654 RES_DEPEND_REMOVE,
655 PMURES_BIT(RES4315_CBUCK_LPOM) | PMURES_BIT(RES4315_CBUCK_BURST) |
656 PMURES_BIT(RES4315_CBUCK_PWM),
657 si_pmu_res_depfltr_ncb
661 static const pmu_res_updown_t BCMATTACHDATA(bcm4329_res_updown)[] = {
662 { RES4329_XTAL_PU, 0x1501 },
663 { RES4329_PALDO_PU, 0x3501 }
666 static const pmu_res_depend_t BCMATTACHDATA(bcm4329_res_depend)[] = {
667 /* Make lnldo1 independant of CBUCK_PWM and CBUCK_BURST */
669 PMURES_BIT(RES4329_LNLDO1_PU),
670 RES_DEPEND_REMOVE,
671 PMURES_BIT(RES4329_CBUCK_PWM) | PMURES_BIT(RES4329_CBUCK_BURST),
672 NULL
675 PMURES_BIT(RES4329_CBUCK_BURST),
676 RES_DEPEND_ADD,
677 PMURES_BIT(RES4329_CBUCK_LPOM) | PMURES_BIT(RES4329_PALDO_PU),
678 NULL
681 PMURES_BIT(RES4329_BBPLL_PWRSW_PU),
682 RES_DEPEND_ADD,
683 PMURES_BIT(RES4329_RX_PWRSW_PU) | PMURES_BIT(RES4329_TX_PWRSW_PU) |
684 PMURES_BIT(RES4329_LOGEN_PWRSW_PU) | PMURES_BIT(RES4329_AFE_PWRSW_PU),
685 NULL
687 /* Adjust HT Avail resource dependencies */
689 PMURES_BIT(RES4329_HT_AVAIL),
690 RES_DEPEND_ADD,
691 PMURES_BIT(RES4329_PALDO_PU) |
692 PMURES_BIT(RES4329_RX_PWRSW_PU) | PMURES_BIT(RES4329_TX_PWRSW_PU) |
693 PMURES_BIT(RES4329_LOGEN_PWRSW_PU) | PMURES_BIT(RES4329_AFE_PWRSW_PU),
694 NULL
698 static const pmu_res_updown_t BCMATTACHDATA(bcm4319a0_res_updown_qt)[] = {
699 { RES4319_HT_AVAIL, 0x0101 },
700 { RES4319_XTAL_PU, 0x0100 },
701 { RES4319_LNLDO1_PU, 0x0100 },
702 { RES4319_PALDO_PU, 0x0100 },
703 { RES4319_CLDO_PU, 0x0100 },
704 { RES4319_CBUCK_PWM, 0x0100 },
705 { RES4319_CBUCK_BURST, 0x0100 },
706 { RES4319_CBUCK_LPOM, 0x0100 }
709 static const pmu_res_updown_t BCMATTACHDATA(bcm4319a0_res_updown)[] = {
710 { RES4319_XTAL_PU, 0x3f01 }
713 static const pmu_res_depend_t BCMATTACHDATA(bcm4319a0_res_depend)[] = {
714 /* Adjust OTP PU resource dependencies - not need PALDO unless write */
716 PMURES_BIT(RES4319_OTP_PU),
717 RES_DEPEND_REMOVE,
718 PMURES_BIT(RES4319_PALDO_PU),
719 si_pmu_res_depfltr_npaldo
721 /* Adjust HT Avail resource dependencies - bring up PALDO along if it is used. */
723 PMURES_BIT(RES4319_HT_AVAIL),
724 RES_DEPEND_ADD,
725 PMURES_BIT(RES4319_PALDO_PU),
726 si_pmu_res_depfltr_paldo
728 /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
730 PMURES_BIT(RES4319_HT_AVAIL),
731 RES_DEPEND_ADD,
732 PMURES_BIT(RES4319_RX_PWRSW_PU) | PMURES_BIT(RES4319_TX_PWRSW_PU) |
733 PMURES_BIT(RES4319_RFPLL_PWRSW_PU) |
734 PMURES_BIT(RES4319_LOGEN_PWRSW_PU) | PMURES_BIT(RES4319_AFE_PWRSW_PU),
735 NULL
739 static const pmu_res_updown_t BCMATTACHDATA(bcm4336a0_res_updown_qt)[] = {
740 { RES4336_HT_AVAIL, 0x0101 },
741 { RES4336_XTAL_PU, 0x0100 },
742 { RES4336_CLDO_PU, 0x0100 },
743 { RES4336_CBUCK_PWM, 0x0100 },
744 { RES4336_CBUCK_BURST, 0x0100 },
745 { RES4336_CBUCK_LPOM, 0x0100 }
748 static const pmu_res_updown_t BCMATTACHDATA(bcm4336a0_res_updown)[] = {
749 { RES4336_HT_AVAIL, 0x0D01}
752 static const pmu_res_depend_t BCMATTACHDATA(bcm4336a0_res_depend)[] = {
753 /* Just a dummy entry for now */
755 PMURES_BIT(RES4336_RSVD),
756 RES_DEPEND_ADD,
758 NULL
762 static const pmu_res_updown_t BCMATTACHDATA(bcm4330a0_res_updown_qt)[] = {
763 { RES4330_HT_AVAIL, 0x0101 },
764 { RES4330_XTAL_PU, 0x0100 },
765 { RES4330_CLDO_PU, 0x0100 },
766 { RES4330_CBUCK_PWM, 0x0100 },
767 { RES4330_CBUCK_BURST, 0x0100 },
768 { RES4330_CBUCK_LPOM, 0x0100 }
771 static const pmu_res_updown_t BCMATTACHDATA(bcm4330a0_res_updown)[] = {
772 { RES4330_HT_AVAIL, 0x0e02}
775 static const pmu_res_depend_t BCMATTACHDATA(bcm4330a0_res_depend)[] = {
776 /* Just a dummy entry for now */
778 PMURES_BIT(RES4330_HT_AVAIL),
779 RES_DEPEND_ADD,
781 NULL
785 /* TRUE if the power topology uses the buck boost to provide 3.3V to VDDIO_RF and WLAN PA */
786 static bool
787 BCMATTACHFN(si_pmu_res_depfltr_bb)(si_t *sih)
789 return (sih->boardflags & BFL_BUCKBOOST) != 0;
792 /* TRUE if the power topology doesn't use the cbuck. Key on chiprev also if the chip is BCM4325. */
793 static bool
794 BCMATTACHFN(si_pmu_res_depfltr_ncb)(si_t *sih)
796 if (CHIPID(sih->chip) == BCM4325_CHIP_ID)
797 return (CHIPREV(sih->chiprev) >= 2) && ((sih->boardflags & BFL_NOCBUCK) != 0);
798 return ((sih->boardflags & BFL_NOCBUCK) != 0);
801 /* TRUE if the power topology uses the PALDO */
802 static bool
803 BCMATTACHFN(si_pmu_res_depfltr_paldo)(si_t *sih)
805 return (sih->boardflags & BFL_PALDO) != 0;
808 /* TRUE if the power topology doesn't use the PALDO */
809 static bool
810 BCMATTACHFN(si_pmu_res_depfltr_npaldo)(si_t *sih)
812 return (sih->boardflags & BFL_PALDO) == 0;
815 #define BCM94325_BBVDDIOSD_BOARDS(sih) (sih->boardtype == BCM94325DEVBU_BOARD || \
816 sih->boardtype == BCM94325BGABU_BOARD)
818 /* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
819 static void
820 si_pmu_res_masks(si_t *sih, uint32 *pmin, uint32 *pmax)
822 uint32 min_mask = 0, max_mask = 0;
823 uint rsrcs;
824 char *val;
826 /* # resources */
827 rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
829 /* determine min/max rsrc masks */
830 switch (CHIPID(sih->chip)) {
831 case BCM4328_CHIP_ID:
832 /* Down to ILP request */
833 min_mask = PMURES_BIT(RES4328_EXT_SWITCHER_PWM) |
834 PMURES_BIT(RES4328_BB_SWITCHER_PWM) |
835 PMURES_BIT(RES4328_XTAL_EN);
836 /* Allow (but don't require) PLL to turn on */
837 max_mask = 0xfffff;
838 break;
839 case BCM5354_CHIP_ID:
840 /* Allow (but don't require) PLL to turn on */
841 max_mask = 0xfffff;
842 break;
843 case BCM4325_CHIP_ID:
844 ASSERT(CHIPREV(sih->chiprev) >= 2);
845 /* Minimum rsrcs to work in sleep mode */
846 if (!(sih->boardflags & BFL_NOCBUCK))
847 min_mask |= PMURES_BIT(RES4325B0_CBUCK_LPOM);
848 if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
849 CST4325_PMUTOP_2B_SHIFT) == 1)
850 min_mask |= PMURES_BIT(RES4325B0_CLDO_PU);
851 if (!si_is_otp_disabled(sih))
852 min_mask |= PMURES_BIT(RES4325_OTP_PU);
853 /* Leave buck boost on in burst mode for certain boards */
854 if ((sih->boardflags & BFL_BUCKBOOST) && (BCM94325_BBVDDIOSD_BOARDS(sih)))
855 min_mask |= PMURES_BIT(RES4325_BUCK_BOOST_BURST);
856 /* Allow all resources to be turned on upon requests */
857 max_mask = ~(~0 << rsrcs);
858 break;
859 case BCM4312_CHIP_ID:
860 /* default min_mask = 0x80000cbb is wrong */
861 min_mask = 0xcbb;
863 * max_mask = 0x7fff;
864 * pmu_res_updown_table_sz = 0;
865 * pmu_res_depend_table_sz = 0;
867 break;
868 case BCM4322_CHIP_ID:
869 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
870 case BCM4342_CHIP_ID:
871 if (CHIPREV(sih->chiprev) < 2) {
872 /* request ALP(can skip for A1) */
873 min_mask = PMURES_BIT(RES4322_RF_LDO) |
874 PMURES_BIT(RES4322_XTAL_PU) |
875 PMURES_BIT(RES4322_ALP_AVAIL);
876 if (BUSTYPE(sih->bustype) == SI_BUS) {
877 min_mask += PMURES_BIT(RES4322_SI_PLL_ON) |
878 PMURES_BIT(RES4322_HT_SI_AVAIL) |
879 PMURES_BIT(RES4322_PHY_PLL_ON) |
880 PMURES_BIT(RES4322_OTP_PU) |
881 PMURES_BIT(RES4322_HT_PHY_AVAIL);
882 max_mask = 0x1ff;
885 break;
886 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
887 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID:
888 case BCM43226_CHIP_ID: case BCM43420_CHIP_ID:
889 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
890 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
891 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
892 case BCM6362_CHIP_ID:
893 /* use chip default */
894 break;
896 case BCM4329_CHIP_ID:
898 /* Down to save the power. */
899 if (CHIPREV(sih->chiprev) >= 0x2) {
900 min_mask = PMURES_BIT(RES4329_CBUCK_LPOM) |
901 PMURES_BIT(RES4329_LNLDO1_PU) | PMURES_BIT(RES4329_CLDO_PU);
902 } else {
903 min_mask = PMURES_BIT(RES4329_CBUCK_LPOM) | PMURES_BIT(RES4329_CLDO_PU);
905 if (!si_is_otp_disabled(sih))
906 min_mask |= PMURES_BIT(RES4329_OTP_PU);
907 /* Allow (but don't require) PLL to turn on */
908 max_mask = 0x3ff63e;
910 break;
911 case BCM4315_CHIP_ID:
912 /* We only need a few resources to be kept on all the time */
913 if (!(sih->boardflags & BFL_NOCBUCK))
914 min_mask = PMURES_BIT(RES4315_CBUCK_LPOM);
915 min_mask |= PMURES_BIT(RES4315_CLDO_PU);
916 /* Allow everything else to be turned on upon requests */
917 max_mask = ~(~0 << rsrcs);
918 break;
919 case BCM4319_CHIP_ID:
920 #ifdef BCM_BOOTLOADER
921 /* Initialize to ResInitMode3 for bootloader */
922 min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
923 PMURES_BIT(RES4319_CBUCK_BURST) |
924 PMURES_BIT(RES4319_CBUCK_PWM) |
925 PMURES_BIT(RES4319_CLDO_PU) |
926 PMURES_BIT(RES4319_PALDO_PU) |
927 PMURES_BIT(RES4319_LNLDO1_PU) |
928 PMURES_BIT(RES4319_XTAL_PU) |
929 PMURES_BIT(RES4319_ALP_AVAIL) |
930 PMURES_BIT(RES4319_RFPLL_PWRSW_PU) |
931 PMURES_BIT(RES4319_BBPLL_PWRSW_PU) |
932 PMURES_BIT(RES4319_HT_AVAIL);
933 #else
934 /* We only need a few resources to be kept on all the time */
935 #ifdef BCMUSBDEV
936 /* For USB HT is always available, even durring IEEE PS, so RF switches are
937 * made independent of HT Avail and are by default on, but can be made off
938 * during IEEE PS by ucode (and then on)
940 min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
941 PMURES_BIT(RES4319_CLDO_PU) |
942 PMURES_BIT(RES4319_RX_PWRSW_PU) | PMURES_BIT(RES4319_TX_PWRSW_PU) |
943 PMURES_BIT(RES4319_LOGEN_PWRSW_PU) | PMURES_BIT(RES4319_AFE_PWRSW_PU);
944 #else
945 /* For SDIO RF switches are automatically made on off along with HT */
946 min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
947 PMURES_BIT(RES4319_CLDO_PU);
948 #endif
949 #endif /* BCM_BOOTLOADER */
951 /* Allow everything else to be turned on upon requests */
952 max_mask = ~(~0 << rsrcs);
953 break;
954 case BCM4336_CHIP_ID:
955 /* Down to save the power. */
956 min_mask = PMURES_BIT(RES4336_CBUCK_LPOM) | PMURES_BIT(RES4336_CLDO_PU) |
957 PMURES_BIT(RES4336_LDO3P3_PU) | PMURES_BIT(RES4336_OTP_PU) |
958 PMURES_BIT(RES4336_DIS_INT_RESET_PD);
959 /* Allow (but don't require) PLL to turn on */
960 max_mask = 0x1ffffff;
961 break;
963 case BCM4330_CHIP_ID:
964 /* Down to save the power. */
965 min_mask = PMURES_BIT(RES4330_CBUCK_LPOM) | PMURES_BIT(RES4330_CLDO_PU) |
966 PMURES_BIT(RES4330_DIS_INT_RESET_PD) | PMURES_BIT(RES4330_LDO3P3_PU) |
967 PMURES_BIT(RES4330_OTP_PU);
968 /* Allow (but don't require) PLL to turn on */
969 max_mask = 0xfffffff;
970 break;
972 case BCM4313_CHIP_ID:
973 min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) |
974 PMURES_BIT(RES4313_XTAL_PU_RSRC) |
975 PMURES_BIT(RES4313_ALP_AVAIL_RSRC) |
976 PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC);
977 max_mask = 0xffff;
978 break;
979 default:
980 break;
983 /* Apply nvram override to min mask */
984 if ((val = getvar(NULL, "rmin")) != NULL) {
985 PMU_MSG(("Applying rmin=%s to min_mask\n", val));
986 min_mask = (uint32)bcm_strtoul(val, NULL, 0);
988 /* Apply nvram override to max mask */
989 if ((val = getvar(NULL, "rmax")) != NULL) {
990 PMU_MSG(("Applying rmax=%s to max_mask\n", val));
991 max_mask = (uint32)bcm_strtoul(val, NULL, 0);
994 *pmin = min_mask;
995 *pmax = max_mask;
997 #endif /* !_CFE_ || CFG_WL */
999 /* initialize PMU resources */
1000 void
1001 BCMATTACHFN(si_pmu_res_init)(si_t *sih, osl_t *osh)
1003 #if !defined(_CFE_) || defined(CFG_WL)
1004 chipcregs_t *cc;
1005 uint origidx;
1006 const pmu_res_updown_t *pmu_res_updown_table = NULL;
1007 uint pmu_res_updown_table_sz = 0;
1008 const pmu_res_depend_t *pmu_res_depend_table = NULL;
1009 uint pmu_res_depend_table_sz = 0;
1010 uint32 min_mask = 0, max_mask = 0;
1011 char name[8], *val;
1012 uint i, rsrcs;
1014 ASSERT(sih->cccaps & CC_CAP_PMU);
1016 /* Remember original core before switch to chipc */
1017 origidx = si_coreidx(sih);
1018 cc = si_setcoreidx(sih, SI_CC_IDX);
1019 ASSERT(cc != NULL);
1021 switch (CHIPID(sih->chip)) {
1022 case BCM4328_CHIP_ID:
1023 pmu_res_updown_table = bcm4328a0_res_updown;
1024 pmu_res_updown_table_sz = ARRAYSIZE(bcm4328a0_res_updown);
1025 pmu_res_depend_table = bcm4328a0_res_depend;
1026 pmu_res_depend_table_sz = ARRAYSIZE(bcm4328a0_res_depend);
1027 break;
1028 case BCM4325_CHIP_ID:
1029 /* Optimize resources up/down timers */
1030 if (ISSIM_ENAB(sih)) {
1031 pmu_res_updown_table = bcm4325a0_res_updown_qt;
1032 pmu_res_updown_table_sz = ARRAYSIZE(bcm4325a0_res_updown_qt);
1033 } else {
1034 pmu_res_updown_table = bcm4325a0_res_updown;
1035 pmu_res_updown_table_sz = ARRAYSIZE(bcm4325a0_res_updown);
1037 /* Optimize resources dependancies */
1038 pmu_res_depend_table = bcm4325a0_res_depend;
1039 pmu_res_depend_table_sz = ARRAYSIZE(bcm4325a0_res_depend);
1040 break;
1041 case BCM4315_CHIP_ID:
1042 /* Optimize resources up/down timers */
1043 if (ISSIM_ENAB(sih)) {
1044 pmu_res_updown_table = bcm4315a0_res_updown_qt;
1045 pmu_res_updown_table_sz = ARRAYSIZE(bcm4315a0_res_updown_qt);
1047 else {
1048 pmu_res_updown_table = bcm4315a0_res_updown;
1049 pmu_res_updown_table_sz = ARRAYSIZE(bcm4315a0_res_updown);
1051 /* Optimize resources dependancies masks */
1052 pmu_res_depend_table = bcm4315a0_res_depend;
1053 pmu_res_depend_table_sz = ARRAYSIZE(bcm4315a0_res_depend);
1054 break;
1055 case BCM4329_CHIP_ID:
1056 /* Optimize resources up/down timers */
1057 if (ISSIM_ENAB(sih)) {
1058 pmu_res_updown_table = NULL;
1059 pmu_res_updown_table_sz = 0;
1060 } else {
1061 pmu_res_updown_table = bcm4329_res_updown;
1062 pmu_res_updown_table_sz = ARRAYSIZE(bcm4329_res_updown);
1064 /* Optimize resources dependencies */
1065 pmu_res_depend_table = bcm4329_res_depend;
1066 pmu_res_depend_table_sz = ARRAYSIZE(bcm4329_res_depend);
1067 break;
1069 case BCM4319_CHIP_ID:
1070 /* Optimize resources up/down timers */
1071 if (ISSIM_ENAB(sih)) {
1072 pmu_res_updown_table = bcm4319a0_res_updown_qt;
1073 pmu_res_updown_table_sz = ARRAYSIZE(bcm4319a0_res_updown_qt);
1075 else {
1076 pmu_res_updown_table = bcm4319a0_res_updown;
1077 pmu_res_updown_table_sz = ARRAYSIZE(bcm4319a0_res_updown);
1079 /* Optimize resources dependancies masks */
1080 pmu_res_depend_table = bcm4319a0_res_depend;
1081 pmu_res_depend_table_sz = ARRAYSIZE(bcm4319a0_res_depend);
1082 break;
1084 case BCM4336_CHIP_ID:
1085 /* Optimize resources up/down timers */
1086 if (ISSIM_ENAB(sih)) {
1087 pmu_res_updown_table = bcm4336a0_res_updown_qt;
1088 pmu_res_updown_table_sz = ARRAYSIZE(bcm4336a0_res_updown_qt);
1090 else {
1091 pmu_res_updown_table = bcm4336a0_res_updown;
1092 pmu_res_updown_table_sz = ARRAYSIZE(bcm4336a0_res_updown);
1094 /* Optimize resources dependancies masks */
1095 pmu_res_depend_table = bcm4336a0_res_depend;
1096 pmu_res_depend_table_sz = ARRAYSIZE(bcm4336a0_res_depend);
1097 break;
1099 case BCM4330_CHIP_ID:
1100 /* Optimize resources up/down timers */
1101 if (ISSIM_ENAB(sih)) {
1102 pmu_res_updown_table = bcm4330a0_res_updown_qt;
1103 pmu_res_updown_table_sz = ARRAYSIZE(bcm4330a0_res_updown_qt);
1105 else {
1106 pmu_res_updown_table = bcm4330a0_res_updown;
1107 pmu_res_updown_table_sz = ARRAYSIZE(bcm4330a0_res_updown);
1109 /* Optimize resources dependancies masks */
1110 pmu_res_depend_table = bcm4330a0_res_depend;
1111 pmu_res_depend_table_sz = ARRAYSIZE(bcm4330a0_res_depend);
1112 break;
1113 default:
1114 break;
1117 /* # resources */
1118 rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
1120 /* Program up/down timers */
1121 while (pmu_res_updown_table_sz--) {
1122 ASSERT(pmu_res_updown_table != NULL);
1123 PMU_MSG(("Changing rsrc %d res_updn_timer to 0x%x\n",
1124 pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
1125 pmu_res_updown_table[pmu_res_updown_table_sz].updown));
1126 W_REG(osh, &cc->res_table_sel,
1127 pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
1128 W_REG(osh, &cc->res_updn_timer,
1129 pmu_res_updown_table[pmu_res_updown_table_sz].updown);
1131 /* Apply nvram overrides to up/down timers */
1132 for (i = 0; i < rsrcs; i ++) {
1133 snprintf(name, sizeof(name), "r%dt", i);
1134 if ((val = getvar(NULL, name)) == NULL)
1135 continue;
1136 PMU_MSG(("Applying %s=%s to rsrc %d res_updn_timer\n", name, val, i));
1137 W_REG(osh, &cc->res_table_sel, (uint32)i);
1138 W_REG(osh, &cc->res_updn_timer, (uint32)bcm_strtoul(val, NULL, 0));
1141 /* Program resource dependencies table */
1142 while (pmu_res_depend_table_sz--) {
1143 ASSERT(pmu_res_depend_table != NULL);
1144 if (pmu_res_depend_table[pmu_res_depend_table_sz].filter != NULL &&
1145 !(pmu_res_depend_table[pmu_res_depend_table_sz].filter)(sih))
1146 continue;
1147 for (i = 0; i < rsrcs; i ++) {
1148 if ((pmu_res_depend_table[pmu_res_depend_table_sz].res_mask &
1149 PMURES_BIT(i)) == 0)
1150 continue;
1151 W_REG(osh, &cc->res_table_sel, i);
1152 switch (pmu_res_depend_table[pmu_res_depend_table_sz].action) {
1153 case RES_DEPEND_SET:
1154 PMU_MSG(("Changing rsrc %d res_dep_mask to 0x%x\n", i,
1155 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask));
1156 W_REG(osh, &cc->res_dep_mask,
1157 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
1158 break;
1159 case RES_DEPEND_ADD:
1160 PMU_MSG(("Adding 0x%x to rsrc %d res_dep_mask\n",
1161 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
1162 OR_REG(osh, &cc->res_dep_mask,
1163 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
1164 break;
1165 case RES_DEPEND_REMOVE:
1166 PMU_MSG(("Removing 0x%x from rsrc %d res_dep_mask\n",
1167 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
1168 AND_REG(osh, &cc->res_dep_mask,
1169 ~pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
1170 break;
1171 default:
1172 ASSERT(0);
1173 break;
1177 /* Apply nvram overrides to dependancies masks */
1178 for (i = 0; i < rsrcs; i ++) {
1179 snprintf(name, sizeof(name), "r%dd", i);
1180 if ((val = getvar(NULL, name)) == NULL)
1181 continue;
1182 PMU_MSG(("Applying %s=%s to rsrc %d res_dep_mask\n", name, val, i));
1183 W_REG(osh, &cc->res_table_sel, (uint32)i);
1184 W_REG(osh, &cc->res_dep_mask, (uint32)bcm_strtoul(val, NULL, 0));
1187 /* Determine min/max rsrc masks */
1188 si_pmu_res_masks(sih, &min_mask, &max_mask);
1190 /* It is required to program max_mask first and then min_mask */
1191 #ifdef BCM_BOOTLOADER
1192 if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
1193 min_mask |= R_REG(osh, &cc->min_res_mask);
1194 max_mask |= R_REG(osh, &cc->max_res_mask);
1196 #endif /* BCM_BOOTLOADER */
1198 /* Program max resource mask */
1199 #ifdef BCM_BOOTLOADER
1200 /* Apply nvram override to max mask */
1201 if ((val = getvar(NULL, "brmax")) != NULL) {
1202 PMU_MSG(("Applying brmax=%s to max_res_mask\n", val));
1203 max_mask = (uint32)bcm_strtoul(val, NULL, 0);
1205 #endif /* BCM_BOOTLOADER */
1207 if (max_mask) {
1208 PMU_MSG(("Changing max_res_mask to 0x%x\n", max_mask));
1209 W_REG(osh, &cc->max_res_mask, max_mask);
1212 /* Program min resource mask */
1213 #ifdef BCM_BOOTLOADER
1214 /* Apply nvram override to min mask */
1215 if ((val = getvar(NULL, "brmin")) != NULL) {
1216 PMU_MSG(("Applying brmin=%s to min_res_mask\n", val));
1217 min_mask = (uint32)bcm_strtoul(val, NULL, 0);
1219 #endif /* BCM_BOOTLOADER */
1221 if (min_mask) {
1222 PMU_MSG(("Changing min_res_mask to 0x%x\n", min_mask));
1223 W_REG(osh, &cc->min_res_mask, min_mask);
1226 /* Add some delay; allow resources to come up and settle. */
1227 OSL_DELAY(2000);
1229 /* Return to original core */
1230 si_setcoreidx(sih, origidx);
1232 #endif /* !_CFE_ || CFG_WL */
1234 /* WAR for 4319 swctrl tri-state issue */
1235 void
1236 si_pmu_res_4319_swctrl_war(si_t *sih, osl_t *osh, bool enable)
1238 uint32 min_mask;
1239 chipcregs_t *cc;
1240 uint origidx;
1241 ASSERT(sih->cccaps & CC_CAP_PMU);
1243 /* Remember original core before switch to chipc */
1244 origidx = si_coreidx(sih);
1245 cc = si_setcoreidx(sih, SI_CC_IDX);
1246 ASSERT(cc != NULL);
1247 min_mask = R_REG(osh, &cc->min_res_mask);
1248 if (enable)
1249 W_REG(osh, &cc->min_res_mask,
1250 min_mask | PMURES_BIT(RES4319_PALDO_PU));
1251 else
1252 W_REG(osh, &cc->min_res_mask,
1253 min_mask & ~PMURES_BIT(RES4319_PALDO_PU));
1255 /* Return to original core */
1256 si_setcoreidx(sih, origidx);
1259 /* setup pll and query clock speed */
1260 typedef struct {
1261 uint16 freq;
1262 uint8 xf;
1263 uint8 wbint;
1264 uint32 wbfrac;
1265 } pmu0_xtaltab0_t;
1267 /* the following table is based on 880Mhz fvco */
1268 static const pmu0_xtaltab0_t BCMINITDATA(pmu0_xtaltab0)[] = {
1269 { 12000, 1, 73, 349525 },
1270 { 13000, 2, 67, 725937 },
1271 { 14400, 3, 61, 116508 },
1272 { 15360, 4, 57, 305834 },
1273 { 16200, 5, 54, 336579 },
1274 { 16800, 6, 52, 399457 },
1275 { 19200, 7, 45, 873813 },
1276 { 19800, 8, 44, 466033 },
1277 { 20000, 9, 44, 0 },
1278 { 25000, 10, 70, 419430 },
1279 { 26000, 11, 67, 725937 },
1280 { 30000, 12, 58, 699050 },
1281 { 38400, 13, 45, 873813 },
1282 { 40000, 14, 45, 0 },
1283 { 0, 0, 0, 0 }
1286 #ifdef BCMUSBDEV
1287 #define PMU0_XTAL0_DEFAULT 11
1288 #else
1289 #define PMU0_XTAL0_DEFAULT 8
1290 #endif
1292 #ifdef BCMUSBDEV
1294 * Set new backplane PLL clock frequency
1296 static void
1297 BCMATTACHFN(si_pmu0_sbclk4328)(si_t *sih, int freq)
1299 uint32 tmp, oldmax, oldmin, origidx;
1300 chipcregs_t *cc;
1302 /* Remember original core before switch to chipc */
1303 origidx = si_coreidx(sih);
1304 cc = si_setcoreidx(sih, SI_CC_IDX);
1305 ASSERT(cc);
1307 /* Set new backplane PLL clock */
1308 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
1309 tmp = R_REG(osh, &cc->pllcontrol_data);
1310 tmp &= ~(PMU0_PLL0_PC0_DIV_ARM_MASK);
1311 tmp |= freq << PMU0_PLL0_PC0_DIV_ARM_SHIFT;
1312 W_REG(osh, &cc->pllcontrol_data, tmp);
1314 /* Power cycle BB_PLL_PU by disabling/enabling it to take on new freq */
1315 /* Disable PLL */
1316 oldmin = R_REG(osh, &cc->min_res_mask);
1317 oldmax = R_REG(osh, &cc->max_res_mask);
1318 W_REG(osh, &cc->min_res_mask, oldmin & ~PMURES_BIT(RES4328_BB_PLL_PU));
1319 W_REG(osh, &cc->max_res_mask, oldmax & ~PMURES_BIT(RES4328_BB_PLL_PU));
1321 /* It takes over several hundred usec to re-enable the PLL since the
1322 * sequencer state machines run on ILP clock. Set delay at 450us to be safe.
1324 * Be sure PLL is powered down first before re-enabling it.
1327 OSL_DELAY(PLL_DELAY);
1328 SPINWAIT((R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)), PLL_DELAY*3);
1329 if (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)) {
1330 /* If BB_PLL not powered down yet, new backplane PLL clock
1331 * may not take effect.
1333 * Still early during bootup so no serial output here.
1335 PMU_ERROR(("Fatal: BB_PLL not power down yet!\n"));
1336 ASSERT(!(R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)));
1339 /* Enable PLL */
1340 W_REG(osh, &cc->max_res_mask, oldmax);
1342 /* Return to original core */
1343 si_setcoreidx(sih, origidx);
1345 #endif /* BCMUSBDEV */
1347 /* Set up PLL registers in the PMU as per the crystal speed.
1348 * Uses xtalfreq variable, or passed-in default.
1350 static void
1351 BCMATTACHFN(si_pmu0_pllinit0)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal)
1353 uint32 tmp;
1354 const pmu0_xtaltab0_t *xt;
1356 /* Find the frequency in the table */
1357 for (xt = pmu0_xtaltab0; xt->freq; xt ++)
1358 if (xt->freq == xtal)
1359 break;
1360 if (xt->freq == 0)
1361 xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
1363 PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
1365 /* Check current PLL state */
1366 tmp = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1367 PCTL_XTALFREQ_SHIFT;
1368 if (tmp == xt->xf) {
1369 PMU_MSG(("PLL already programmed for %d.%d MHz\n",
1370 xt->freq / 1000, xt->freq % 1000));
1371 #ifdef BCMUSBDEV
1372 if (CHIPID(sih->chip) == BCM4328_CHIP_ID)
1373 si_pmu0_sbclk4328(sih, PMU0_PLL0_PC0_DIV_ARM_88MHZ);
1374 #endif /* BCMUSBDEV */
1375 return;
1378 if (tmp) {
1379 PMU_MSG(("Reprogramming PLL for %d.%d MHz (was %d.%dMHz)\n",
1380 xt->freq / 1000, xt->freq % 1000,
1381 pmu0_xtaltab0[tmp-1].freq / 1000, pmu0_xtaltab0[tmp-1].freq % 1000));
1382 } else {
1383 PMU_MSG(("Programming PLL for %d.%d MHz\n",
1384 xt->freq / 1000, xt->freq % 1000));
1387 /* Make sure the PLL is off */
1388 switch (CHIPID(sih->chip)) {
1389 case BCM4328_CHIP_ID:
1390 AND_REG(osh, &cc->min_res_mask, ~PMURES_BIT(RES4328_BB_PLL_PU));
1391 AND_REG(osh, &cc->max_res_mask, ~PMURES_BIT(RES4328_BB_PLL_PU));
1392 break;
1393 case BCM5354_CHIP_ID:
1394 AND_REG(osh, &cc->min_res_mask, ~PMURES_BIT(RES5354_BB_PLL_PU));
1395 AND_REG(osh, &cc->max_res_mask, ~PMURES_BIT(RES5354_BB_PLL_PU));
1396 break;
1397 default:
1398 ASSERT(0);
1400 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS0_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1401 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS0_HTAVAIL));
1403 PMU_MSG(("Done masking\n"));
1405 /* Write PDIV in pllcontrol[0] */
1406 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
1407 tmp = R_REG(osh, &cc->pllcontrol_data);
1408 if (xt->freq >= PMU0_PLL0_PC0_PDIV_FREQ)
1409 tmp |= PMU0_PLL0_PC0_PDIV_MASK;
1410 else
1411 tmp &= ~PMU0_PLL0_PC0_PDIV_MASK;
1412 W_REG(osh, &cc->pllcontrol_data, tmp);
1414 /* Write WILD in pllcontrol[1] */
1415 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
1416 tmp = R_REG(osh, &cc->pllcontrol_data);
1417 tmp = ((tmp & ~(PMU0_PLL0_PC1_WILD_INT_MASK | PMU0_PLL0_PC1_WILD_FRAC_MASK)) |
1418 (((xt->wbint << PMU0_PLL0_PC1_WILD_INT_SHIFT) &
1419 PMU0_PLL0_PC1_WILD_INT_MASK) |
1420 ((xt->wbfrac << PMU0_PLL0_PC1_WILD_FRAC_SHIFT) &
1421 PMU0_PLL0_PC1_WILD_FRAC_MASK)));
1422 if (xt->wbfrac == 0)
1423 tmp |= PMU0_PLL0_PC1_STOP_MOD;
1424 else
1425 tmp &= ~PMU0_PLL0_PC1_STOP_MOD;
1426 W_REG(osh, &cc->pllcontrol_data, tmp);
1428 /* Write WILD in pllcontrol[2] */
1429 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
1430 tmp = R_REG(osh, &cc->pllcontrol_data);
1431 tmp = ((tmp & ~PMU0_PLL0_PC2_WILD_INT_MASK) |
1432 ((xt->wbint >> PMU0_PLL0_PC2_WILD_INT_SHIFT) &
1433 PMU0_PLL0_PC2_WILD_INT_MASK));
1434 W_REG(osh, &cc->pllcontrol_data, tmp);
1436 PMU_MSG(("Done pll\n"));
1438 /* Write XtalFreq. Set the divisor also. */
1439 tmp = R_REG(osh, &cc->pmucontrol);
1440 tmp = ((tmp & ~PCTL_ILP_DIV_MASK) |
1441 (((((xt->freq + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) & PCTL_ILP_DIV_MASK));
1442 tmp = ((tmp & ~PCTL_XTALFREQ_MASK) |
1443 ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK));
1444 W_REG(osh, &cc->pmucontrol, tmp);
1447 /* query alp/xtal clock frequency */
1448 static uint32
1449 BCMINITFN(si_pmu0_alpclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1451 const pmu0_xtaltab0_t *xt;
1452 uint32 xf;
1454 /* Find the frequency in the table */
1455 xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1456 PCTL_XTALFREQ_SHIFT;
1457 for (xt = pmu0_xtaltab0; xt->freq; xt++)
1458 if (xt->xf == xf)
1459 break;
1460 /* PLL must be configured before */
1461 ASSERT(xt->freq);
1463 return xt->freq * 1000;
1466 #if !defined(_CFE_) || defined(CFG_WL)
1467 /* query CPU clock frequency */
1468 static uint32
1469 BCMINITFN(si_pmu0_cpuclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1471 uint32 tmp, divarm;
1472 #ifdef BCMDBG
1473 uint32 pdiv, wbint, wbfrac, fvco;
1474 uint32 freq;
1475 #endif
1476 uint32 FVCO = FVCO_880;
1478 /* Read divarm from pllcontrol[0] */
1479 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
1480 tmp = R_REG(osh, &cc->pllcontrol_data);
1481 divarm = (tmp & PMU0_PLL0_PC0_DIV_ARM_MASK) >> PMU0_PLL0_PC0_DIV_ARM_SHIFT;
1483 #ifdef BCMDBG
1484 /* Calculate fvco based on xtal freq, pdiv, and wild */
1485 pdiv = tmp & PMU0_PLL0_PC0_PDIV_MASK;
1487 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
1488 tmp = R_REG(osh, &cc->pllcontrol_data);
1489 wbfrac = (tmp & PMU0_PLL0_PC1_WILD_FRAC_MASK) >> PMU0_PLL0_PC1_WILD_FRAC_SHIFT;
1490 wbint = (tmp & PMU0_PLL0_PC1_WILD_INT_MASK) >> PMU0_PLL0_PC1_WILD_INT_SHIFT;
1492 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
1493 tmp = R_REG(osh, &cc->pllcontrol_data);
1494 wbint += (tmp & PMU0_PLL0_PC2_WILD_INT_MASK) << PMU0_PLL0_PC2_WILD_INT_SHIFT;
1496 freq = si_pmu0_alpclk0(sih, osh, cc) / 1000;
1498 fvco = (freq * wbint) << 8;
1499 fvco += (freq * (wbfrac >> 10)) >> 2;
1500 fvco += (freq * (wbfrac & 0x3ff)) >> 10;
1501 fvco >>= 8;
1502 fvco >>= pdiv;
1503 fvco /= 1000;
1504 fvco *= 1000;
1506 PMU_MSG(("si_pmu0_cpuclk0: wbint %u wbfrac %u fvco %u\n",
1507 wbint, wbfrac, fvco));
1509 FVCO = fvco;
1510 #endif /* BCMDBG */
1512 /* Return ARM/SB clock */
1513 return FVCO / (divarm + PMU0_PLL0_PC0_DIV_ARM_BASE) * 1000;
1516 uint
1517 si_pll_minresmask_reset(si_t *sih, osl_t *osh)
1519 chipcregs_t *cc;
1520 uint origidx;
1521 uint err = BCME_OK;
1522 /* Remember original core before switch to chipc */
1523 origidx = si_coreidx(sih);
1524 cc = si_setcoreidx(sih, SI_CC_IDX);
1525 ASSERT(cc != NULL);
1527 switch (CHIPID(sih->chip)) {
1528 case BCM4313_CHIP_ID:
1529 /* write to min_res_mask 0x200d : clear min_rsrc_mask */
1530 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1531 OSL_DELAY(100);
1532 /* write to max_res_mask 0xBFFF: clear max_rsrc_mask */
1533 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1534 OSL_DELAY(100);
1535 /* write to max_res_mask 0xFFFF :set max_rsrc_mask */
1536 OR_REG(osh, &cc->max_res_mask, (PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1538 break;
1539 default:
1540 PMU_ERROR(("%s: PLL reset not supported\n", __FUNCTION__));
1541 err = BCME_UNSUPPORTED;
1542 break;
1544 /* Return to original core */
1545 si_setcoreidx(sih, origidx);
1546 return err;
1549 /* setup pll and query clock speed */
1550 typedef struct {
1551 uint16 fref;
1552 uint8 xf;
1553 uint8 p1div;
1554 uint8 p2div;
1555 uint8 ndiv_int;
1556 uint32 ndiv_frac;
1557 } pmu1_xtaltab0_t;
1559 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880_4329)[] = {
1560 {12000, 1, 3, 22, 0x9, 0xFFFFEF},
1561 {13000, 2, 1, 6, 0xb, 0x483483},
1562 {14400, 3, 1, 10, 0xa, 0x1C71C7},
1563 {15360, 4, 1, 5, 0xb, 0x755555},
1564 {16200, 5, 1, 10, 0x5, 0x6E9E06},
1565 {16800, 6, 1, 10, 0x5, 0x3Cf3Cf},
1566 {19200, 7, 1, 4, 0xb, 0x755555},
1567 {19800, 8, 1, 11, 0x4, 0xA57EB},
1568 {20000, 9, 1, 11, 0x4, 0x0},
1569 {24000, 10, 3, 11, 0xa, 0x0},
1570 {25000, 11, 5, 16, 0xb, 0x0},
1571 {26000, 12, 1, 1, 0x21, 0xD89D89},
1572 {30000, 13, 3, 8, 0xb, 0x0},
1573 {37400, 14, 3, 1, 0x46, 0x969696},
1574 {38400, 15, 1, 1, 0x16, 0xEAAAAA},
1575 {40000, 16, 1, 2, 0xb, 0},
1576 {0, 0, 0, 0, 0, 0}
1579 /* the following table is based on 880Mhz fvco */
1580 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880)[] = {
1581 {12000, 1, 3, 22, 0x9, 0xFFFFEF},
1582 {13000, 2, 1, 6, 0xb, 0x483483},
1583 {14400, 3, 1, 10, 0xa, 0x1C71C7},
1584 {15360, 4, 1, 5, 0xb, 0x755555},
1585 {16200, 5, 1, 10, 0x5, 0x6E9E06},
1586 {16800, 6, 1, 10, 0x5, 0x3Cf3Cf},
1587 {19200, 7, 1, 4, 0xb, 0x755555},
1588 {19800, 8, 1, 11, 0x4, 0xA57EB},
1589 {20000, 9, 1, 11, 0x4, 0x0},
1590 {24000, 10, 3, 11, 0xa, 0x0},
1591 {25000, 11, 5, 16, 0xb, 0x0},
1592 {26000, 12, 1, 2, 0x10, 0xEC4EC4},
1593 {30000, 13, 3, 8, 0xb, 0x0},
1594 {33600, 14, 1, 2, 0xd, 0x186186},
1595 {38400, 15, 1, 2, 0xb, 0x755555},
1596 {40000, 16, 1, 2, 0xb, 0},
1597 {0, 0, 0, 0, 0, 0}
1600 #define PMU1_XTALTAB0_880_12000K 0
1601 #define PMU1_XTALTAB0_880_13000K 1
1602 #define PMU1_XTALTAB0_880_14400K 2
1603 #define PMU1_XTALTAB0_880_15360K 3
1604 #define PMU1_XTALTAB0_880_16200K 4
1605 #define PMU1_XTALTAB0_880_16800K 5
1606 #define PMU1_XTALTAB0_880_19200K 6
1607 #define PMU1_XTALTAB0_880_19800K 7
1608 #define PMU1_XTALTAB0_880_20000K 8
1609 #define PMU1_XTALTAB0_880_24000K 9
1610 #define PMU1_XTALTAB0_880_25000K 10
1611 #define PMU1_XTALTAB0_880_26000K 11
1612 #define PMU1_XTALTAB0_880_30000K 12
1613 #define PMU1_XTALTAB0_880_37400K 13
1614 #define PMU1_XTALTAB0_880_38400K 14
1615 #define PMU1_XTALTAB0_880_40000K 15
1617 /* the following table is based on 1760Mhz fvco */
1618 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1760)[] = {
1619 {12000, 1, 3, 44, 0x9, 0xFFFFEF},
1620 {13000, 2, 1, 12, 0xb, 0x483483},
1621 {14400, 3, 1, 20, 0xa, 0x1C71C7},
1622 {15360, 4, 1, 10, 0xb, 0x755555},
1623 {16200, 5, 1, 20, 0x5, 0x6E9E06},
1624 {16800, 6, 1, 20, 0x5, 0x3Cf3Cf},
1625 {19200, 7, 1, 18, 0x5, 0x17B425},
1626 {19800, 8, 1, 22, 0x4, 0xA57EB},
1627 {20000, 9, 1, 22, 0x4, 0x0},
1628 {24000, 10, 3, 22, 0xa, 0x0},
1629 {25000, 11, 5, 32, 0xb, 0x0},
1630 {26000, 12, 1, 4, 0x10, 0xEC4EC4},
1631 {30000, 13, 3, 16, 0xb, 0x0},
1632 {38400, 14, 1, 10, 0x4, 0x955555},
1633 {40000, 15, 1, 4, 0xb, 0},
1634 {0, 0, 0, 0, 0, 0}
1637 /* table index */
1638 #define PMU1_XTALTAB0_1760_12000K 0
1639 #define PMU1_XTALTAB0_1760_13000K 1
1640 #define PMU1_XTALTAB0_1760_14400K 2
1641 #define PMU1_XTALTAB0_1760_15360K 3
1642 #define PMU1_XTALTAB0_1760_16200K 4
1643 #define PMU1_XTALTAB0_1760_16800K 5
1644 #define PMU1_XTALTAB0_1760_19200K 6
1645 #define PMU1_XTALTAB0_1760_19800K 7
1646 #define PMU1_XTALTAB0_1760_20000K 8
1647 #define PMU1_XTALTAB0_1760_24000K 9
1648 #define PMU1_XTALTAB0_1760_25000K 10
1649 #define PMU1_XTALTAB0_1760_26000K 11
1650 #define PMU1_XTALTAB0_1760_30000K 12
1651 #define PMU1_XTALTAB0_1760_38400K 13
1652 #define PMU1_XTALTAB0_1760_40000K 14
1654 /* the following table is based on 1440Mhz fvco */
1655 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1440)[] = {
1656 {12000, 1, 1, 1, 0x78, 0x0 },
1657 {13000, 2, 1, 1, 0x6E, 0xC4EC4E},
1658 {14400, 3, 1, 1, 0x64, 0x0 },
1659 {15360, 4, 1, 1, 0x5D, 0xC00000},
1660 {16200, 5, 1, 1, 0x58, 0xE38E38},
1661 {16800, 6, 1, 1, 0x55, 0xB6DB6D},
1662 {19200, 7, 1, 1, 0x4B, 0 },
1663 {19800, 8, 1, 1, 0x48, 0xBA2E8B},
1664 {20000, 9, 1, 1, 0x48, 0x0 },
1665 {25000, 10, 1, 1, 0x39, 0x999999},
1666 {26000, 11, 1, 1, 0x37, 0x627627},
1667 {30000, 12, 1, 1, 0x30, 0x0 },
1668 {37400, 13, 2, 1, 0x4D, 0x15E76 },
1669 {38400, 13, 2, 1, 0x4B, 0x0 },
1670 {40000, 14, 2, 1, 0x48, 0x0 },
1671 {48000, 15, 2, 1, 0x3c, 0x0 },
1672 {0, 0, 0, 0, 0, 0}
1675 /* table index */
1676 #define PMU1_XTALTAB0_1440_12000K 0
1677 #define PMU1_XTALTAB0_1440_13000K 1
1678 #define PMU1_XTALTAB0_1440_14400K 2
1679 #define PMU1_XTALTAB0_1440_15360K 3
1680 #define PMU1_XTALTAB0_1440_16200K 4
1681 #define PMU1_XTALTAB0_1440_16800K 5
1682 #define PMU1_XTALTAB0_1440_19200K 6
1683 #define PMU1_XTALTAB0_1440_19800K 7
1684 #define PMU1_XTALTAB0_1440_20000K 8
1685 #define PMU1_XTALTAB0_1440_25000K 9
1686 #define PMU1_XTALTAB0_1440_26000K 10
1687 #define PMU1_XTALTAB0_1440_30000K 11
1688 #define PMU1_XTALTAB0_1440_37400K 12
1689 #define PMU1_XTALTAB0_1440_38400K 13
1690 #define PMU1_XTALTAB0_1440_40000K 14
1691 #define PMU1_XTALTAB0_1440_48000K 15
1693 #define XTAL_FREQ_24000MHZ 24000
1694 #define XTAL_FREQ_30000MHZ 30000
1695 #define XTAL_FREQ_37400MHZ 37400
1696 #define XTAL_FREQ_48000MHZ 48000
1698 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_960)[] = {
1699 {12000, 1, 1, 1, 0x50, 0x0 },
1700 {13000, 2, 1, 1, 0x49, 0xD89D89},
1701 {14400, 3, 1, 1, 0x42, 0xAAAAAA},
1702 {15360, 4, 1, 1, 0x3E, 0x800000},
1703 {16200, 5, 1, 1, 0x39, 0x425ED0},
1704 {16800, 6, 1, 1, 0x39, 0x249249},
1705 {19200, 7, 1, 1, 0x32, 0x0 },
1706 {19800, 8, 1, 1, 0x30, 0x7C1F07},
1707 {20000, 9, 1, 1, 0x30, 0x0 },
1708 {25000, 10, 1, 1, 0x26, 0x666666},
1709 {26000, 11, 1, 1, 0x24, 0xEC4EC4},
1710 {30000, 12, 1, 1, 0x20, 0x0 },
1711 {37400, 13, 2, 1, 0x33, 0x563EF9},
1712 {38400, 14, 2, 1, 0x32, 0x0 },
1713 {40000, 15, 2, 1, 0x30, 0x0 },
1714 {48000, 16, 2, 1, 0x28, 0x0 },
1715 {0, 0, 0, 0, 0, 0 }
1718 /* table index */
1719 #define PMU1_XTALTAB0_960_12000K 0
1720 #define PMU1_XTALTAB0_960_13000K 1
1721 #define PMU1_XTALTAB0_960_14400K 2
1722 #define PMU1_XTALTAB0_960_15360K 3
1723 #define PMU1_XTALTAB0_960_16200K 4
1724 #define PMU1_XTALTAB0_960_16800K 5
1725 #define PMU1_XTALTAB0_960_19200K 6
1726 #define PMU1_XTALTAB0_960_19800K 7
1727 #define PMU1_XTALTAB0_960_20000K 8
1728 #define PMU1_XTALTAB0_960_25000K 9
1729 #define PMU1_XTALTAB0_960_26000K 10
1730 #define PMU1_XTALTAB0_960_30000K 11
1731 #define PMU1_XTALTAB0_960_37400K 12
1732 #define PMU1_XTALTAB0_960_38400K 13
1733 #define PMU1_XTALTAB0_960_40000K 14
1734 #define PMU1_XTALTAB0_960_48000K 15
1736 /* select xtal table for each chip */
1737 static const pmu1_xtaltab0_t *
1738 BCMINITFN(si_pmu1_xtaltab0)(si_t *sih)
1740 #ifdef BCMDBG
1741 char chn[8];
1742 #endif
1743 switch (CHIPID(sih->chip)) {
1744 case BCM4325_CHIP_ID:
1745 return pmu1_xtaltab0_880;
1746 case BCM4329_CHIP_ID:
1747 return pmu1_xtaltab0_880_4329;
1748 case BCM4315_CHIP_ID:
1749 return pmu1_xtaltab0_1760;
1750 case BCM4319_CHIP_ID:
1751 return pmu1_xtaltab0_1440;
1752 case BCM4336_CHIP_ID:
1753 return pmu1_xtaltab0_960;
1754 case BCM4330_CHIP_ID:
1755 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1756 return pmu1_xtaltab0_960;
1757 else
1758 return pmu1_xtaltab0_1440;
1759 default:
1760 PMU_MSG(("si_pmu1_xtaltab0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1761 break;
1763 ASSERT(0);
1764 return NULL;
1767 /* select default xtal frequency for each chip */
1768 static const pmu1_xtaltab0_t *
1769 BCMINITFN(si_pmu1_xtaldef0)(si_t *sih)
1771 #ifdef BCMDBG
1772 char chn[8];
1773 #endif
1775 switch (CHIPID(sih->chip)) {
1776 case BCM4325_CHIP_ID:
1777 /* Default to 26000Khz */
1778 return &pmu1_xtaltab0_880[PMU1_XTALTAB0_880_26000K];
1779 case BCM4329_CHIP_ID:
1780 /* Default to 38400Khz */
1781 return &pmu1_xtaltab0_880_4329[PMU1_XTALTAB0_880_38400K];
1782 case BCM4315_CHIP_ID:
1783 #ifdef BCMUSBDEV
1784 /* Default to 30000Khz */
1785 return &pmu1_xtaltab0_1760[PMU1_XTALTAB0_1760_30000K];
1786 #else
1787 /* Default to 26000Khz */
1788 return &pmu1_xtaltab0_1760[PMU1_XTALTAB0_1760_26000K];
1789 #endif
1790 case BCM4319_CHIP_ID:
1791 /* Default to 30000Khz */
1792 return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_30000K];
1793 case BCM4336_CHIP_ID:
1794 /* Default to 26000Khz */
1795 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_26000K];
1796 case BCM4330_CHIP_ID:
1797 /* Default to 37400Khz */
1798 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1799 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_37400K];
1800 else
1801 return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_37400K];
1802 default:
1803 PMU_MSG(("si_pmu1_xtaldef0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1804 break;
1806 ASSERT(0);
1807 return NULL;
1810 /* select default pll fvco for each chip */
1811 static uint32
1812 BCMINITFN(si_pmu1_pllfvco0)(si_t *sih)
1814 #ifdef BCMDBG
1815 char chn[8];
1816 #endif
1818 switch (CHIPID(sih->chip)) {
1819 case BCM4325_CHIP_ID:
1820 return FVCO_880;
1821 case BCM4329_CHIP_ID:
1822 return FVCO_880;
1823 case BCM4315_CHIP_ID:
1824 return FVCO_1760;
1825 case BCM4319_CHIP_ID:
1826 return FVCO_1440;
1827 case BCM4336_CHIP_ID:
1828 return FVCO_960;
1829 case BCM4330_CHIP_ID:
1830 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1831 return FVCO_960;
1832 else
1833 return FVCO_1440;
1834 default:
1835 PMU_MSG(("si_pmu1_pllfvco0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1836 break;
1838 ASSERT(0);
1839 return 0;
1842 /* query alp/xtal clock frequency */
1843 static uint32
1844 BCMINITFN(si_pmu1_alpclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1846 const pmu1_xtaltab0_t *xt;
1847 uint32 xf;
1849 /* Find the frequency in the table */
1850 xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1851 PCTL_XTALFREQ_SHIFT;
1852 for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
1853 if (xt->xf == xf)
1854 break;
1855 /* Could not find it so assign a default value */
1856 if (xt == NULL || xt->fref == 0)
1857 xt = si_pmu1_xtaldef0(sih);
1858 ASSERT(xt != NULL && xt->fref != 0);
1860 return xt->fref * 1000;
1862 #endif /* !_CFE_ || CFG_WL */
1864 void
1865 si_pmu_minresmask_htavail_set(si_t *sih, osl_t *osh, bool set_clear)
1867 chipcregs_t *cc;
1868 uint origidx;
1869 /* Remember original core before switch to chipc */
1870 origidx = si_coreidx(sih);
1871 cc = si_setcoreidx(sih, SI_CC_IDX);
1872 ASSERT(cc != NULL);
1874 if (!set_clear) {
1875 switch (CHIPID(sih->chip)) {
1876 case BCM4313_CHIP_ID:
1877 if ((cc->min_res_mask) & (PMURES_BIT(RES4313_HT_AVAIL_RSRC)))
1878 AND_REG(osh, &cc->min_res_mask,
1879 ~(PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1880 break;
1881 default:
1882 break;
1886 /* Return to original core */
1887 si_setcoreidx(sih, origidx);
1890 #if !defined(_CFE_) || defined(CFG_WL)
1891 /* Set up PLL registers in the PMU as per the crystal speed.
1892 * XtalFreq field in pmucontrol register being 0 indicates the PLL
1893 * is not programmed and the h/w default is assumed to work, in which
1894 * case the xtal frequency is unknown to the s/w so we need to call
1895 * si_pmu1_xtaldef0() wherever it is needed to return a default value.
1897 static void
1898 BCMATTACHFN(si_pmu1_pllinit0)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal)
1900 const pmu1_xtaltab0_t *xt;
1901 uint32 tmp;
1902 uint32 buf_strength = 0;
1903 uint8 ndiv_mode = 1;
1904 uint32 FVCO = si_pmu1_pllfvco0(sih);
1905 uint8 dacrate;
1907 FVCO = FVCO/1000;
1909 /* Use h/w default PLL config */
1910 if (xtal == 0) {
1911 PMU_MSG(("Unspecified xtal frequency, skip PLL configuration\n"));
1912 return;
1915 /* Find the frequency in the table */
1916 for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
1917 if (xt->fref == xtal)
1918 break;
1920 /* Check current PLL state, bail out if it has been programmed or
1921 * we don't know how to program it.
1923 if (xt == NULL || xt->fref == 0) {
1924 PMU_MSG(("Unsupported xtal frequency %d.%d MHz, skip PLL configuration\n",
1925 xtal / 1000, xtal % 1000));
1926 return;
1928 /* for 4319 bootloader already programs the PLL but bootloader does not program the
1929 PLL4 and PLL5. So Skip this check for 4319
1931 if ((((R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1932 PCTL_XTALFREQ_SHIFT) == xt->xf) &&
1933 !((CHIPID(sih->chip) == BCM4319_CHIP_ID) || (CHIPID(sih->chip) == BCM4330_CHIP_ID)))
1935 PMU_MSG(("PLL already programmed for %d.%d MHz\n",
1936 xt->fref / 1000, xt->fref % 1000));
1937 return;
1940 PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
1941 PMU_MSG(("Programming PLL for %d.%d MHz\n", xt->fref / 1000, xt->fref % 1000));
1943 switch (CHIPID(sih->chip)) {
1944 case BCM4325_CHIP_ID:
1945 /* Change the BBPLL drive strength to 2 for all channels */
1946 buf_strength = 0x222222;
1947 /* Make sure the PLL is off */
1948 AND_REG(osh, &cc->min_res_mask,
1949 ~(PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL)));
1950 AND_REG(osh, &cc->max_res_mask,
1951 ~(PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL)));
1952 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1953 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1954 break;
1955 case BCM4329_CHIP_ID:
1956 /* Change the BBPLL drive strength to 8 for all channels */
1957 buf_strength = 0x888888;
1958 AND_REG(osh, &cc->min_res_mask,
1959 ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) | PMURES_BIT(RES4329_HT_AVAIL)));
1960 AND_REG(osh, &cc->max_res_mask,
1961 ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) | PMURES_BIT(RES4329_HT_AVAIL)));
1962 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1963 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1964 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
1965 if (xt->fref == 38400)
1966 tmp = 0x200024C0;
1967 else if (xt->fref == 37400)
1968 tmp = 0x20004500;
1969 else if (xt->fref == 26000)
1970 tmp = 0x200024C0;
1971 else
1972 tmp = 0x200005C0; /* Chip Dflt Settings */
1973 W_REG(osh, &cc->pllcontrol_data, tmp);
1974 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
1975 tmp = R_REG(osh, &cc->pllcontrol_data) & PMU1_PLL0_PC5_CLK_DRV_MASK;
1976 if ((xt->fref == 38400) || (xt->fref == 37400) || (xt->fref == 26000))
1977 tmp |= 0x15;
1978 else
1979 tmp |= 0x25; /* Chip Dflt Settings */
1980 W_REG(osh, &cc->pllcontrol_data, tmp);
1981 break;
1982 case BCM4315_CHIP_ID:
1983 /* Change the BBPLL drive strength to 2 for all channels */
1984 buf_strength = 0x222222;
1985 /* Make sure the PLL is off */
1986 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4315_HT_AVAIL)));
1987 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4315_HT_AVAIL)));
1988 OSL_DELAY(100);
1990 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4315_BBPLL_PWRSW_PU)));
1991 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4315_BBPLL_PWRSW_PU)));
1992 OSL_DELAY(100);
1994 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1995 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1996 break;
1998 case BCM4319_CHIP_ID:
1999 /* Change the BBPLL drive strength to 2 for all channels */
2000 buf_strength = 0x222222;
2002 /* Make sure the PLL is off */
2003 /* WAR65104: Disable the HT_AVAIL resource first and then
2004 * after a delay (more than downtime for HT_AVAIL) remove the
2005 * BBPLL resource; backplane clock moves to ALP from HT.
2007 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4319_HT_AVAIL)));
2008 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4319_HT_AVAIL)));
2010 OSL_DELAY(100);
2011 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
2012 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
2014 OSL_DELAY(100);
2015 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2016 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2017 break;
2019 case BCM4336_CHIP_ID:
2020 AND_REG(osh, &cc->min_res_mask,
2021 ~(PMURES_BIT(RES4336_HT_AVAIL) | PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
2022 AND_REG(osh, &cc->max_res_mask,
2023 ~(PMURES_BIT(RES4336_HT_AVAIL) | PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
2024 OSL_DELAY(100);
2025 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2026 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2027 break;
2029 case BCM4330_CHIP_ID:
2030 AND_REG(osh, &cc->min_res_mask,
2031 ~(PMURES_BIT(RES4330_HT_AVAIL) | PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
2032 AND_REG(osh, &cc->max_res_mask,
2033 ~(PMURES_BIT(RES4330_HT_AVAIL) | PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
2034 OSL_DELAY(100);
2035 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2036 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2037 break;
2039 default:
2040 ASSERT(0);
2043 PMU_MSG(("Done masking\n"));
2045 /* Write p1div and p2div to pllcontrol[0] */
2046 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2047 tmp = R_REG(osh, &cc->pllcontrol_data) &
2048 ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
2049 tmp |= ((xt->p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) |
2050 ((xt->p2div << PMU1_PLL0_PC0_P2DIV_SHIFT) & PMU1_PLL0_PC0_P2DIV_MASK);
2052 if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
2053 tmp &= ~(PMU1_PLL0_PC0_BYPASS_SDMOD_MASK);
2054 if (!(xt->ndiv_frac))
2055 tmp |= (1<<(PMU1_PLL0_PC0_BYPASS_SDMOD_SHIFT));
2056 else
2057 tmp |= (0<<(PMU1_PLL0_PC0_BYPASS_SDMOD_SHIFT));
2060 W_REG(osh, &cc->pllcontrol_data, tmp);
2062 if ((CHIPID(sih->chip) == BCM4330_CHIP_ID)) {
2063 if (CHIPREV(sih->chiprev) < 2)
2064 dacrate = 160;
2065 else {
2066 if (!(dacrate = (uint8)getintvar(NULL, "dacrate2g")))
2067 dacrate = 80;
2069 si_pmu_set_4330_plldivs(sih, dacrate);
2072 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (CHIPREV(sih->chiprev) == 0)) {
2074 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2075 tmp = R_REG(osh, &cc->pllcontrol_data);
2076 tmp = tmp & (~DOT11MAC_880MHZ_CLK_DIVISOR_MASK);
2077 tmp = tmp | DOT11MAC_880MHZ_CLK_DIVISOR_VAL;
2078 W_REG(osh, &cc->pllcontrol_data, tmp);
2080 if ((CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
2081 (CHIPID(sih->chip) == BCM4330_CHIP_ID))
2082 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
2083 else
2084 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MASH;
2086 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID)) {
2087 if (!(xt->ndiv_frac))
2088 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_INT;
2089 else
2090 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
2091 #ifdef BCMQT
2092 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2093 tmp = 0x120F1010;
2094 W_REG(osh, &cc->pllcontrol_data, tmp);
2095 #endif
2097 /* Write ndiv_int and ndiv_mode to pllcontrol[2] */
2098 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2099 tmp = R_REG(osh, &cc->pllcontrol_data) &
2100 ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
2101 tmp |= ((xt->ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) & PMU1_PLL0_PC2_NDIV_INT_MASK) |
2102 ((ndiv_mode << PMU1_PLL0_PC2_NDIV_MODE_SHIFT) & PMU1_PLL0_PC2_NDIV_MODE_MASK);
2103 W_REG(osh, &cc->pllcontrol_data, tmp);
2105 /* Write ndiv_frac to pllcontrol[3] */
2106 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2107 tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
2108 tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
2109 PMU1_PLL0_PC3_NDIV_FRAC_MASK);
2110 W_REG(osh, &cc->pllcontrol_data, tmp);
2112 /* Writing to pllcontrol[4] */
2113 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID)) {
2114 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2115 if (!(xt->ndiv_frac))
2116 tmp = 0x200005c0;
2117 else
2118 tmp = 0x202C2820;
2120 tmp &= ~(PMU1_PLL0_PC4_KVCO_XS_MASK);
2122 if (FVCO < 1600)
2123 tmp |= (4<<PMU1_PLL0_PC4_KVCO_XS_SHIFT);
2124 else
2125 tmp |= (7<<PMU1_PLL0_PC4_KVCO_XS_SHIFT);
2127 W_REG(osh, &cc->pllcontrol_data, tmp);
2130 /* Write clock driving strength to pllcontrol[5] */
2131 if (buf_strength) {
2132 PMU_MSG(("Adjusting PLL buffer drive strength: %x\n", buf_strength));
2134 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2135 tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
2136 tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
2138 if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
2139 tmp &= ~(PMU1_PLL0_PC5_VCO_RNG_MASK | PMU1_PLL0_PC5_PLL_CTRL_37_32_MASK);
2140 if (!(xt->ndiv_frac))
2141 tmp |= (0x25<<(PMU1_PLL0_PC5_PLL_CTRL_37_32_SHIFT));
2142 else
2143 tmp |= (0x15<<(PMU1_PLL0_PC5_PLL_CTRL_37_32_SHIFT));
2145 if (FVCO < 1600)
2146 tmp |= (0x0<<(PMU1_PLL0_PC5_VCO_RNG_SHIFT));
2147 else
2148 tmp |= (0x1<<(PMU1_PLL0_PC5_VCO_RNG_SHIFT));
2150 W_REG(osh, &cc->pllcontrol_data, tmp);
2153 PMU_MSG(("Done pll\n"));
2155 /* to operate the 4319 usb in 24MHz/48MHz; chipcontrol[2][84:83] needs
2156 * to be updated.
2158 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && (xt->fref != XTAL_FREQ_30000MHZ)) {
2159 W_REG(osh, &cc->chipcontrol_addr, PMU1_PLL0_CHIPCTL2);
2160 tmp = R_REG(osh, &cc->chipcontrol_data) & ~CCTL_4319USB_XTAL_SEL_MASK;
2161 if (xt->fref == XTAL_FREQ_24000MHZ) {
2162 tmp |= (CCTL_4319USB_24MHZ_PLL_SEL << CCTL_4319USB_XTAL_SEL_SHIFT);
2163 } else if (xt->fref == XTAL_FREQ_48000MHZ) {
2164 tmp |= (CCTL_4319USB_48MHZ_PLL_SEL << CCTL_4319USB_XTAL_SEL_SHIFT);
2166 W_REG(osh, &cc->chipcontrol_data, tmp);
2169 /* Flush deferred pll control registers writes */
2170 if (sih->pmurev >= 2)
2171 OR_REG(osh, &cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
2173 /* Write XtalFreq. Set the divisor also. */
2174 tmp = R_REG(osh, &cc->pmucontrol) &
2175 ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
2176 tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
2177 PCTL_ILP_DIV_MASK) |
2178 ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
2180 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && CHIPREV(sih->chiprev) == 0) {
2181 /* clear the htstretch before clearing HTReqEn */
2182 AND_REG(osh, &cc->clkstretch, ~CSTRETCH_HT);
2183 tmp &= ~PCTL_HT_REQ_EN;
2186 W_REG(osh, &cc->pmucontrol, tmp);
2189 /* query the CPU clock frequency */
2190 static uint32
2191 BCMINITFN(si_pmu1_cpuclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
2193 uint32 tmp, m1div;
2194 #ifdef BCMDBG
2195 uint32 ndiv_int, ndiv_frac, p2div, p1div, fvco;
2196 uint32 fref;
2197 #endif
2198 uint32 FVCO = si_pmu1_pllfvco0(sih);
2200 /* Read m1div from pllcontrol[1] */
2201 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2202 tmp = R_REG(osh, &cc->pllcontrol_data);
2203 m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT;
2205 #ifdef BCMDBG
2206 /* Read p2div/p1div from pllcontrol[0] */
2207 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2208 tmp = R_REG(osh, &cc->pllcontrol_data);
2209 p2div = (tmp & PMU1_PLL0_PC0_P2DIV_MASK) >> PMU1_PLL0_PC0_P2DIV_SHIFT;
2210 p1div = (tmp & PMU1_PLL0_PC0_P1DIV_MASK) >> PMU1_PLL0_PC0_P1DIV_SHIFT;
2212 /* Calculate fvco based on xtal freq and ndiv and pdiv */
2213 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2214 tmp = R_REG(osh, &cc->pllcontrol_data);
2215 ndiv_int = (tmp & PMU1_PLL0_PC2_NDIV_INT_MASK) >> PMU1_PLL0_PC2_NDIV_INT_SHIFT;
2217 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2218 tmp = R_REG(osh, &cc->pllcontrol_data);
2219 ndiv_frac = (tmp & PMU1_PLL0_PC3_NDIV_FRAC_MASK) >> PMU1_PLL0_PC3_NDIV_FRAC_SHIFT;
2221 fref = si_pmu1_alpclk0(sih, osh, cc) / 1000;
2223 fvco = (fref * ndiv_int) << 8;
2224 fvco += (fref * (ndiv_frac >> 12)) >> 4;
2225 fvco += (fref * (ndiv_frac & 0xfff)) >> 12;
2226 fvco >>= 8;
2227 fvco *= p2div;
2228 fvco /= p1div;
2229 fvco /= 1000;
2230 fvco *= 1000;
2232 PMU_MSG(("si_pmu1_cpuclk0: ndiv_int %u ndiv_frac %u p2div %u p1div %u fvco %u\n",
2233 ndiv_int, ndiv_frac, p2div, p1div, fvco));
2235 FVCO = fvco;
2236 #endif /* BCMDBG */
2238 /* Return ARM/SB clock */
2239 return FVCO / m1div * 1000;
2241 #endif /* !_CFE_ || CFG_WL */
2243 /* initialize PLL */
2244 void
2245 BCMATTACHFN(si_pmu_pll_init)(si_t *sih, osl_t *osh, uint xtalfreq)
2247 chipcregs_t *cc;
2248 uint origidx;
2249 #ifdef BCMDBG
2250 char chn[8];
2251 #endif
2253 ASSERT(sih->cccaps & CC_CAP_PMU);
2255 /* Remember original core before switch to chipc */
2256 origidx = si_coreidx(sih);
2257 cc = si_setcoreidx(sih, SI_CC_IDX);
2258 ASSERT(cc != NULL);
2260 switch (CHIPID(sih->chip)) {
2261 case BCM5354_CHIP_ID:
2262 if (xtalfreq == 0)
2263 xtalfreq = 25000;
2264 si_pmu0_pllinit0(sih, osh, cc, xtalfreq);
2265 break;
2266 #if !defined(_CFE_) || defined(CFG_WL)
2267 case BCM4328_CHIP_ID:
2268 si_pmu0_pllinit0(sih, osh, cc, xtalfreq);
2269 break;
2270 case BCM4325_CHIP_ID:
2271 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
2272 break;
2273 case BCM4329_CHIP_ID:
2274 if (xtalfreq == 0)
2275 xtalfreq = 38400;
2276 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
2277 break;
2278 case BCM4312_CHIP_ID:
2279 /* assume default works */
2280 break;
2281 case BCM4322_CHIP_ID:
2282 case BCM43221_CHIP_ID:
2283 case BCM43231_CHIP_ID:
2284 case BCM4342_CHIP_ID: {
2285 if (CHIPREV(sih->chiprev) == 0) {
2286 uint32 minmask, maxmask;
2288 minmask = R_REG(osh, &cc->min_res_mask);
2289 maxmask = R_REG(osh, &cc->max_res_mask);
2291 /* Make sure the PLL is off: clear bit 4 & 5 of min/max_res_mask */
2292 /* Have to remove HT Avail request before powering off PLL */
2293 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
2294 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
2295 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2296 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
2297 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
2298 OSL_DELAY(1000);
2299 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2302 W_REG(osh, &cc->pllcontrol_addr, PMU2_SI_PLL_PLLCTL);
2303 W_REG(osh, &cc->pllcontrol_data, 0x380005c0);
2306 OSL_DELAY(100);
2307 W_REG(osh, &cc->max_res_mask, maxmask);
2308 OSL_DELAY(100);
2309 W_REG(osh, &cc->min_res_mask, minmask);
2310 OSL_DELAY(100);
2313 break;
2315 case BCM4313_CHIP_ID:
2316 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
2317 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43420_CHIP_ID:
2318 case BCM43421_CHIP_ID:
2319 case BCM43226_CHIP_ID:
2320 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
2321 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
2322 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
2323 case BCM43227_CHIP_ID:
2324 case BCM43228_CHIP_ID:
2325 case BCM43428_CHIP_ID:
2326 case BCM6362_CHIP_ID:
2327 break;
2328 case BCM4315_CHIP_ID:
2329 case BCM4319_CHIP_ID:
2330 case BCM4336_CHIP_ID:
2331 case BCM4330_CHIP_ID:
2332 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
2333 break;
2334 #endif /* !_CFE_ || CFG_WL */
2335 default:
2336 PMU_MSG(("No PLL init done for chip %s rev %d pmurev %d\n",
2337 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
2338 break;
2341 #ifdef BCMDBG_FORCEHT
2342 OR_REG(osh, &cc->clk_ctl_st, CCS_FORCEHT);
2343 #endif
2345 /* Return to original core */
2346 si_setcoreidx(sih, origidx);
2349 /* query alp/xtal clock frequency */
2350 uint32
2351 BCMINITFN(si_pmu_alp_clock)(si_t *sih, osl_t *osh)
2353 chipcregs_t *cc;
2354 uint origidx;
2355 uint32 clock = ALP_CLOCK;
2356 #ifdef BCMDBG
2357 char chn[8];
2358 #endif
2360 ASSERT(sih->cccaps & CC_CAP_PMU);
2362 /* Remember original core before switch to chipc */
2363 origidx = si_coreidx(sih);
2364 cc = si_setcoreidx(sih, SI_CC_IDX);
2365 ASSERT(cc != NULL);
2367 switch (CHIPID(sih->chip)) {
2368 case BCM4328_CHIP_ID:
2369 clock = si_pmu0_alpclk0(sih, osh, cc);
2370 break;
2371 case BCM5354_CHIP_ID:
2372 clock = si_pmu0_alpclk0(sih, osh, cc);
2373 break;
2374 #if !defined(_CFE_) || defined(CFG_WL)
2375 case BCM4325_CHIP_ID:
2376 case BCM4329_CHIP_ID:
2377 case BCM4315_CHIP_ID:
2378 case BCM4319_CHIP_ID:
2379 case BCM4336_CHIP_ID:
2380 case BCM4330_CHIP_ID:
2381 clock = si_pmu1_alpclk0(sih, osh, cc);
2382 break;
2383 #endif /* !_CFE_ || CFG_WL */
2384 case BCM4312_CHIP_ID:
2385 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
2386 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
2387 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43420_CHIP_ID:
2388 case BCM43421_CHIP_ID:
2389 case BCM43226_CHIP_ID:
2390 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
2391 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
2392 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
2393 case BCM43227_CHIP_ID:
2394 case BCM43228_CHIP_ID:
2395 case BCM43428_CHIP_ID:
2396 case BCM6362_CHIP_ID:
2397 case BCM4342_CHIP_ID:
2398 case BCM4716_CHIP_ID:
2399 case BCM4748_CHIP_ID:
2400 case BCM47162_CHIP_ID:
2401 case BCM4313_CHIP_ID:
2402 case BCM5357_CHIP_ID:
2403 case BCM4749_CHIP_ID:
2404 case BCM53572_CHIP_ID:
2405 /* always 20Mhz */
2406 clock = 20000 * 1000;
2407 break;
2408 case BCM5356_CHIP_ID:
2409 case BCM4706_CHIP_ID:
2410 /* always 25Mhz */
2411 clock = 25000 * 1000;
2412 break;
2413 default:
2414 PMU_MSG(("No ALP clock specified "
2415 "for chip %s rev %d pmurev %d, using default %d Hz\n",
2416 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev, clock));
2417 break;
2420 /* Return to original core */
2421 si_setcoreidx(sih, origidx);
2422 return clock;
2425 /* Find the output of the "m" pll divider given pll controls that start with
2426 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
2428 static uint32
2429 BCMINITFN(si_pmu5_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, uint m)
2431 uint32 tmp, div, ndiv, p1, p2, fc;
2433 if ((pll0 & 3) || (pll0 > PMU4716_MAINPLL_PLL0)) {
2434 PMU_ERROR(("%s: Bad pll0: %d\n", __FUNCTION__, pll0));
2435 return 0;
2439 /* Strictly there is an m5 divider, but I'm not sure we use it */
2440 if ((m == 0) || (m > 4)) {
2441 PMU_ERROR(("%s: Bad m divider: %d\n", __FUNCTION__, m));
2442 return 0;
2445 if ((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
2446 (CHIPID(sih->chip) == BCM4749_CHIP_ID)) {
2447 /* Detect failure in clock setting */
2448 if ((R_REG(osh, &cc->chipstatus) & 0x40000) != 0) {
2449 return (133 * 1000000);
2453 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_P1P2_OFF);
2454 (void)R_REG(osh, &cc->pllcontrol_addr);
2455 tmp = R_REG(osh, &cc->pllcontrol_data);
2456 p1 = (tmp & PMU5_PLL_P1_MASK) >> PMU5_PLL_P1_SHIFT;
2457 p2 = (tmp & PMU5_PLL_P2_MASK) >> PMU5_PLL_P2_SHIFT;
2459 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_M14_OFF);
2460 (void)R_REG(osh, &cc->pllcontrol_addr);
2461 tmp = R_REG(osh, &cc->pllcontrol_data);
2462 div = (tmp >> ((m - 1) * PMU5_PLL_MDIV_WIDTH)) & PMU5_PLL_MDIV_MASK;
2464 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_NM5_OFF);
2465 (void)R_REG(osh, &cc->pllcontrol_addr);
2466 tmp = R_REG(osh, &cc->pllcontrol_data);
2467 ndiv = (tmp & PMU5_PLL_NDIV_MASK) >> PMU5_PLL_NDIV_SHIFT;
2469 /* Do calculation in Mhz */
2470 fc = si_pmu_alp_clock(sih, osh) / 1000000;
2471 fc = (p1 * ndiv * fc) / p2;
2473 PMU_NONE(("%s: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, clock=%d\n",
2474 __FUNCTION__, p1, p2, ndiv, ndiv, m, div, fc, fc / div));
2476 /* Return clock in Hertz */
2477 return ((fc / div) * 1000000);
2480 static uint32
2481 BCMINITFN(si_4706_pmu_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, uint m)
2483 uint32 w;
2484 uint32 clock;
2486 /* Strictly there is an m5 divider, but I'm not sure we use it */
2487 if ((m == 0) || (m > 4)) {
2488 PMU_ERROR(("%s: Bad m divider: %d\n", __FUNCTION__, m));
2489 return 0;
2492 /* Get N divider to determine CPU clock */
2493 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU6_4706_PROCPLL_OFF);
2494 w = (R_REG(NULL, &cc->pllcontrol_data) & PMU6_4706_PROC_NDIV_INT_MASK) >>
2495 PMU6_4706_PROC_NDIV_INT_SHIFT;
2496 /* Fixed reference clock 25MHz and m = 2 */
2497 clock = w * 25000000 / 2;
2498 if (m == PMU5_MAINPLL_MEM)
2499 clock = clock / 2;
2500 else if (m == PMU5_MAINPLL_SI)
2501 clock = clock / 4;
2503 return clock;
2506 /* query backplane clock frequency */
2507 /* For designs that feed the same clock to both backplane
2508 * and CPU just return the CPU clock speed.
2510 uint32
2511 BCMINITFN(si_pmu_si_clock)(si_t *sih, osl_t *osh)
2513 chipcregs_t *cc;
2514 uint origidx;
2515 uint32 clock = HT_CLOCK;
2516 #ifdef BCMDBG
2517 char chn[8];
2518 #endif
2520 ASSERT(sih->cccaps & CC_CAP_PMU);
2522 /* Remember original core before switch to chipc */
2523 origidx = si_coreidx(sih);
2524 cc = si_setcoreidx(sih, SI_CC_IDX);
2525 ASSERT(cc != NULL);
2527 switch (CHIPID(sih->chip)) {
2528 #if !defined(_CFE_) || defined(CFG_WL)
2529 case BCM4328_CHIP_ID:
2530 clock = si_pmu0_cpuclk0(sih, osh, cc);
2531 break;
2532 case BCM4325_CHIP_ID:
2533 clock = si_pmu1_cpuclk0(sih, osh, cc);
2534 break;
2535 case BCM4322_CHIP_ID:
2536 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
2537 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
2538 case BCM43224_CHIP_ID: case BCM43420_CHIP_ID:
2539 case BCM43225_CHIP_ID:
2540 case BCM43421_CHIP_ID:
2541 case BCM43226_CHIP_ID:
2542 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
2543 case BCM6362_CHIP_ID:
2544 case BCM4342_CHIP_ID:
2545 /* 96MHz backplane clock */
2546 clock = 96000 * 1000;
2547 break;
2548 case BCM4329_CHIP_ID:
2549 if (CHIPREV(sih->chiprev) == 0)
2550 clock = 38400 * 1000;
2551 else
2552 clock = si_pmu1_cpuclk0(sih, osh, cc);
2553 break;
2554 case BCM4315_CHIP_ID:
2555 case BCM4319_CHIP_ID:
2556 case BCM4336_CHIP_ID:
2557 case BCM4330_CHIP_ID:
2558 clock = si_pmu1_cpuclk0(sih, osh, cc);
2559 break;
2560 case BCM4313_CHIP_ID:
2561 /* 80MHz backplane clock */
2562 clock = 80000 * 1000;
2563 break;
2564 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
2565 case BCM43234_CHIP_ID:
2566 clock = (cc->chipstatus & CST43236_BP_CLK) ? (120000 * 1000) : (96000 * 1000);
2567 break;
2568 case BCM43237_CHIP_ID:
2569 clock = (cc->chipstatus & CST43237_BP_CLK) ? (96000 * 1000) : (80000 * 1000);
2570 break;
2571 #endif /* !_CFE_ || CFG_WL */
2572 case BCM5354_CHIP_ID:
2573 clock = 120000000;
2574 break;
2575 case BCM4716_CHIP_ID:
2576 case BCM4748_CHIP_ID:
2577 case BCM47162_CHIP_ID:
2578 clock = si_pmu5_clock(sih, osh, cc, PMU4716_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2579 break;
2580 case BCM5356_CHIP_ID:
2581 clock = si_pmu5_clock(sih, osh, cc, PMU5356_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2582 break;
2583 case BCM5357_CHIP_ID:
2584 case BCM4749_CHIP_ID:
2585 clock = si_pmu5_clock(sih, osh, cc, PMU5357_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2586 break;
2587 case BCM4706_CHIP_ID:
2588 clock = si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2589 break;
2590 case BCM53572_CHIP_ID:
2591 clock = 75000000;
2592 break;
2593 default:
2594 PMU_MSG(("No backplane clock specified "
2595 "for chip %s rev %d pmurev %d, using default %d Hz\n",
2596 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev, clock));
2597 break;
2600 /* Return to original core */
2601 si_setcoreidx(sih, origidx);
2602 return clock;
2605 /* query CPU clock frequency */
2606 uint32
2607 BCMINITFN(si_pmu_cpu_clock)(si_t *sih, osl_t *osh)
2609 chipcregs_t *cc;
2610 uint origidx;
2611 uint32 clock;
2613 ASSERT(sih->cccaps & CC_CAP_PMU);
2615 /* 5354 chip uses a non programmable PLL of frequency 240MHz */
2616 if (CHIPID(sih->chip) == BCM5354_CHIP_ID)
2617 return 240000000;
2619 if (CHIPID(sih->chip) == BCM53572_CHIP_ID)
2620 return 300000000;
2622 if ((sih->pmurev >= 5) &&
2623 !((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
2624 (CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
2625 (CHIPID(sih->chip) == BCM43234_CHIP_ID) ||
2626 (CHIPID(sih->chip) == BCM43235_CHIP_ID) ||
2627 (CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
2628 (CHIPID(sih->chip) == BCM43237_CHIP_ID) ||
2629 (CHIPID(sih->chip) == BCM43238_CHIP_ID) ||
2630 (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
2631 (CHIPID(sih->chip) == BCM4330_CHIP_ID))) {
2632 uint pll;
2634 switch (CHIPID(sih->chip)) {
2635 case BCM5356_CHIP_ID:
2636 pll = PMU5356_MAINPLL_PLL0;
2637 break;
2638 case BCM5357_CHIP_ID:
2639 case BCM4749_CHIP_ID:
2640 pll = PMU5357_MAINPLL_PLL0;
2641 break;
2642 default:
2643 pll = PMU4716_MAINPLL_PLL0;
2644 break;
2647 /* Remember original core before switch to chipc */
2648 origidx = si_coreidx(sih);
2649 cc = si_setcoreidx(sih, SI_CC_IDX);
2650 ASSERT(cc != NULL);
2652 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
2653 clock = si_4706_pmu_clock(sih, osh, cc,
2654 PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU);
2655 else
2656 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_CPU);
2658 /* Return to original core */
2659 si_setcoreidx(sih, origidx);
2660 } else
2661 clock = si_pmu_si_clock(sih, osh);
2663 return clock;
2666 /* query memory clock frequency */
2667 uint32
2668 BCMINITFN(si_pmu_mem_clock)(si_t *sih, osl_t *osh)
2670 chipcregs_t *cc;
2671 uint origidx;
2672 uint32 clock;
2674 ASSERT(sih->cccaps & CC_CAP_PMU);
2676 if (CHIPID(sih->chip) == BCM53572_CHIP_ID)
2677 return 150000000;
2679 if ((sih->pmurev >= 5) &&
2680 !((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
2681 (CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
2682 (CHIPID(sih->chip) == BCM4330_CHIP_ID) ||
2683 (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
2684 (CHIPID(sih->chip) == BCM43234_CHIP_ID) ||
2685 (CHIPID(sih->chip) == BCM43235_CHIP_ID) ||
2686 (CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
2687 (CHIPID(sih->chip) == BCM43237_CHIP_ID) ||
2688 (CHIPID(sih->chip) == BCM43238_CHIP_ID) ||
2689 0)) {
2690 uint pll;
2692 switch (CHIPID(sih->chip)) {
2693 case BCM5356_CHIP_ID:
2694 pll = PMU5356_MAINPLL_PLL0;
2695 break;
2696 case BCM5357_CHIP_ID:
2697 case BCM4749_CHIP_ID:
2698 pll = PMU5357_MAINPLL_PLL0;
2699 break;
2700 default:
2701 pll = PMU4716_MAINPLL_PLL0;
2702 break;
2705 /* Remember original core before switch to chipc */
2706 origidx = si_coreidx(sih);
2707 cc = si_setcoreidx(sih, SI_CC_IDX);
2708 ASSERT(cc != NULL);
2710 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
2711 clock = si_4706_pmu_clock(sih, osh, cc,
2712 PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_MEM);
2713 else
2714 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_MEM);
2716 /* Return to original core */
2717 si_setcoreidx(sih, origidx);
2718 } else {
2719 clock = si_pmu_si_clock(sih, osh);
2722 return clock;
2725 /* Measure ILP clock frequency */
2726 #define ILP_CALC_DUR 10 /* ms, make sure 1000 can be divided by it. */
2728 static uint32 ilpcycles_per_sec = 0;
2730 uint32
2731 BCMINITFN(si_pmu_ilp_clock)(si_t *sih, osl_t *osh)
2733 if (ISSIM_ENAB(sih))
2734 return ILP_CLOCK;
2736 if (ilpcycles_per_sec == 0) {
2737 uint32 start, end, delta;
2738 uint32 origidx = si_coreidx(sih);
2739 chipcregs_t *cc = si_setcoreidx(sih, SI_CC_IDX);
2740 ASSERT(cc != NULL);
2741 start = R_REG(osh, &cc->pmutimer);
2742 OSL_DELAY(ILP_CALC_DUR * 1000);
2743 end = R_REG(osh, &cc->pmutimer);
2744 delta = end - start;
2745 ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
2746 si_setcoreidx(sih, origidx);
2749 return ilpcycles_per_sec;
2752 /* SDIO Pad drive strength to select value mappings */
2753 typedef struct {
2754 uint8 strength; /* Pad Drive Strength in mA */
2755 uint8 sel; /* Chip-specific select value */
2756 } sdiod_drive_str_t;
2758 /* SDIO Drive Strength to sel value table for PMU Rev 1 */
2759 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab1)[] = {
2760 {4, 0x2},
2761 {2, 0x3},
2762 {1, 0x0},
2763 {0, 0x0} };
2765 /* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
2766 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab2)[] = {
2767 {12, 0x7},
2768 {10, 0x6},
2769 {8, 0x5},
2770 {6, 0x4},
2771 {4, 0x2},
2772 {2, 0x1},
2773 {0, 0x0} };
2775 /* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
2776 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab3)[] = {
2777 {32, 0x7},
2778 {26, 0x6},
2779 {22, 0x5},
2780 {16, 0x4},
2781 {12, 0x3},
2782 {8, 0x2},
2783 {4, 0x1},
2784 {0, 0x0} };
2786 #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
2788 void
2789 BCMINITFN(si_sdiod_drive_strength_init)(si_t *sih, osl_t *osh, uint32 drivestrength)
2791 chipcregs_t *cc;
2792 uint origidx, intr_val = 0;
2793 sdiod_drive_str_t *str_tab = NULL;
2794 uint32 str_mask = 0;
2795 uint32 str_shift = 0;
2796 #ifdef BCMDBG
2797 char chn[8];
2798 #endif
2800 if (!(sih->cccaps & CC_CAP_PMU)) {
2801 return;
2804 /* Remember original core before switch to chipc */
2805 cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
2807 switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) {
2808 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
2809 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1;
2810 str_mask = 0x30000000;
2811 str_shift = 28;
2812 break;
2813 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
2814 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
2815 case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4):
2816 case SDIOD_DRVSTR_KEY(BCM4319_CHIP_ID, 7):
2817 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2;
2818 str_mask = 0x00003800;
2819 str_shift = 11;
2820 break;
2821 case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
2822 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3;
2823 str_mask = 0x00003800;
2824 str_shift = 11;
2825 break;
2827 default:
2828 PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
2829 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
2831 break;
2834 if (str_tab != NULL) {
2835 uint32 drivestrength_sel = 0;
2836 uint32 cc_data_temp;
2837 int i;
2839 for (i = 0; str_tab[i].strength != 0; i ++) {
2840 if (drivestrength >= str_tab[i].strength) {
2841 drivestrength_sel = str_tab[i].sel;
2842 break;
2846 W_REG(osh, &cc->chipcontrol_addr, 1);
2847 cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
2848 cc_data_temp &= ~str_mask;
2849 drivestrength_sel <<= str_shift;
2850 cc_data_temp |= drivestrength_sel;
2851 W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
2853 PMU_MSG(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
2854 drivestrength, cc_data_temp));
2857 /* Return to original core */
2858 si_restore_core(sih, origidx, intr_val);
2861 /* initialize PMU */
2862 void
2863 BCMATTACHFN(si_pmu_init)(si_t *sih, osl_t *osh)
2865 chipcregs_t *cc;
2866 uint origidx;
2868 ASSERT(sih->cccaps & CC_CAP_PMU);
2870 /* Remember original core before switch to chipc */
2871 origidx = si_coreidx(sih);
2872 cc = si_setcoreidx(sih, SI_CC_IDX);
2873 ASSERT(cc != NULL);
2875 if (sih->pmurev == 1)
2876 AND_REG(osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
2877 else if (sih->pmurev >= 2)
2878 OR_REG(osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT);
2880 #if !defined(_CFE_) || defined(CFG_WL)
2881 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 2)) {
2882 /* Fix for 4329b0 bad LPOM state. */
2883 W_REG(osh, &cc->regcontrol_addr, 2);
2884 OR_REG(osh, &cc->regcontrol_data, 0x100);
2886 W_REG(osh, &cc->regcontrol_addr, 3);
2887 OR_REG(osh, &cc->regcontrol_data, 0x4);
2890 if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
2891 /* Limiting the PALDO spike during init time */
2892 si_pmu_regcontrol(sih, 2, 0x00000007, 0x00000005);
2894 #endif /* !_CFE_ || CFG_WL */
2896 /* Return to original core */
2897 si_setcoreidx(sih, origidx);
2900 #if !defined(_CFE_) || defined(CFG_WL)
2901 /* Return up time in ILP cycles for the given resource. */
2902 static uint
2903 BCMINITFN(si_pmu_res_uptime)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint8 rsrc)
2905 uint32 deps;
2906 uint up, i, dup, dmax;
2907 uint32 min_mask = 0, max_mask = 0;
2909 /* uptime of resource 'rsrc' */
2910 W_REG(osh, &cc->res_table_sel, rsrc);
2911 up = (R_REG(osh, &cc->res_updn_timer) >> 8) & 0xff;
2913 /* direct dependancies of resource 'rsrc' */
2914 deps = si_pmu_res_deps(sih, osh, cc, PMURES_BIT(rsrc), FALSE);
2915 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
2916 if (!(deps & PMURES_BIT(i)))
2917 continue;
2918 deps &= ~si_pmu_res_deps(sih, osh, cc, PMURES_BIT(i), TRUE);
2920 si_pmu_res_masks(sih, &min_mask, &max_mask);
2921 deps &= ~min_mask;
2923 /* max uptime of direct dependancies */
2924 dmax = 0;
2925 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
2926 if (!(deps & PMURES_BIT(i)))
2927 continue;
2928 dup = si_pmu_res_uptime(sih, osh, cc, (uint8)i);
2929 if (dmax < dup)
2930 dmax = dup;
2933 PMU_MSG(("si_pmu_res_uptime: rsrc %u uptime %u(deps 0x%08x uptime %u)\n",
2934 rsrc, up, deps, dmax));
2936 return up + dmax + PMURES_UP_TRANSITION;
2939 /* Return dependancies (direct or all/indirect) for the given resources */
2940 static uint32
2941 si_pmu_res_deps(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 rsrcs, bool all)
2943 uint32 deps = 0;
2944 uint32 i;
2946 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
2947 if (!(rsrcs & PMURES_BIT(i)))
2948 continue;
2949 W_REG(osh, &cc->res_table_sel, i);
2950 deps |= R_REG(osh, &cc->res_dep_mask);
2953 return !all ? deps : (deps ? (deps | si_pmu_res_deps(sih, osh, cc, deps, TRUE)) : 0);
2956 /* power up/down OTP through PMU resources */
2957 void
2958 si_pmu_otp_power(si_t *sih, osl_t *osh, bool on)
2960 chipcregs_t *cc;
2961 uint origidx;
2962 uint32 rsrcs = 0; /* rsrcs to turn on/off OTP power */
2964 ASSERT(sih->cccaps & CC_CAP_PMU);
2966 /* Don't do anything if OTP is disabled */
2967 if (si_is_otp_disabled(sih)) {
2968 PMU_MSG(("si_pmu_otp_power: OTP is disabled\n"));
2969 return;
2972 /* Remember original core before switch to chipc */
2973 origidx = si_coreidx(sih);
2974 cc = si_setcoreidx(sih, SI_CC_IDX);
2975 ASSERT(cc != NULL);
2977 switch (CHIPID(sih->chip)) {
2978 case BCM4322_CHIP_ID:
2979 case BCM43221_CHIP_ID:
2980 case BCM43231_CHIP_ID:
2981 case BCM4342_CHIP_ID:
2982 rsrcs = PMURES_BIT(RES4322_OTP_PU);
2983 break;
2984 case BCM4325_CHIP_ID:
2985 rsrcs = PMURES_BIT(RES4325_OTP_PU);
2986 break;
2987 case BCM4315_CHIP_ID:
2988 rsrcs = PMURES_BIT(RES4315_OTP_PU);
2989 break;
2990 case BCM4329_CHIP_ID:
2991 rsrcs = PMURES_BIT(RES4329_OTP_PU);
2992 break;
2993 case BCM4319_CHIP_ID:
2994 rsrcs = PMURES_BIT(RES4319_OTP_PU);
2995 break;
2996 case BCM4336_CHIP_ID:
2997 rsrcs = PMURES_BIT(RES4336_OTP_PU);
2998 break;
2999 case BCM4330_CHIP_ID:
3000 rsrcs = PMURES_BIT(RES4330_OTP_PU);
3001 break;
3002 default:
3003 break;
3006 if (rsrcs != 0) {
3007 uint32 otps;
3009 /* Figure out the dependancies (exclude min_res_mask) */
3010 uint32 deps = si_pmu_res_deps(sih, osh, cc, rsrcs, TRUE);
3011 uint32 min_mask = 0, max_mask = 0;
3012 si_pmu_res_masks(sih, &min_mask, &max_mask);
3013 deps &= ~min_mask;
3014 /* Turn on/off the power */
3015 if (on) {
3016 PMU_MSG(("Adding rsrc 0x%x to min_res_mask\n", rsrcs | deps));
3017 OR_REG(osh, &cc->min_res_mask, (rsrcs | deps));
3018 OSL_DELAY(1000);
3019 SPINWAIT(!(R_REG(osh, &cc->res_state) & rsrcs), PMU_MAX_TRANSITION_DLY);
3020 ASSERT(R_REG(osh, &cc->res_state) & rsrcs);
3022 else {
3023 PMU_MSG(("Removing rsrc 0x%x from min_res_mask\n", rsrcs | deps));
3024 AND_REG(osh, &cc->min_res_mask, ~(rsrcs | deps));
3027 SPINWAIT((((otps = R_REG(osh, &cc->otpstatus)) & OTPS_READY) !=
3028 (on ? OTPS_READY : 0)), 100);
3029 ASSERT((otps & OTPS_READY) == (on ? OTPS_READY : 0));
3030 if ((otps & OTPS_READY) != (on ? OTPS_READY : 0))
3031 PMU_MSG(("OTP ready bit not %s after wait\n", (on ? "ON" : "OFF")));
3034 /* Return to original core */
3035 si_setcoreidx(sih, origidx);
3038 void
3039 si_pmu_rcal(si_t *sih, osl_t *osh)
3041 chipcregs_t *cc;
3042 uint origidx;
3043 uint rcal_done, BT_out_of_reset;
3045 ASSERT(sih->cccaps & CC_CAP_PMU);
3047 /* Remember original core before switch to chipc */
3048 origidx = si_coreidx(sih);
3049 cc = si_setcoreidx(sih, SI_CC_IDX);
3050 ASSERT(cc != NULL);
3052 switch (CHIPID(sih->chip)) {
3053 case BCM4325_CHIP_ID: {
3054 uint8 rcal_code;
3055 uint32 val;
3057 /* Kick RCal */
3058 W_REG(osh, &cc->chipcontrol_addr, 1);
3060 /* Power Down RCAL Block */
3061 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3063 /* Check if RCAL is already done by BT */
3064 rcal_done = ((R_REG(osh, &cc->chipstatus)) & 0x8) >> 3;
3066 /* If RCAL already done, note that BT is out of reset */
3067 if (rcal_done == 1) {
3068 BT_out_of_reset = 1;
3069 } else {
3070 BT_out_of_reset = 0;
3073 /* Power Up RCAL block */
3074 OR_REG(osh, &cc->chipcontrol_data, 0x04);
3076 /* Wait for completion */
3077 SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08), 10 * 1000 * 1000);
3078 ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
3080 if (BT_out_of_reset) {
3081 rcal_code = 0x6;
3082 } else {
3083 /* Drop the LSB to convert from 5 bit code to 4 bit code */
3084 rcal_code = (uint8)(R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
3087 PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
3088 R_REG(osh, &cc->chipstatus), rcal_code));
3090 /* Write RCal code into pmu_vreg_ctrl[32:29] */
3091 W_REG(osh, &cc->regcontrol_addr, 0);
3092 val = R_REG(osh, &cc->regcontrol_data) & ~((uint32)0x07 << 29);
3093 val |= (uint32)(rcal_code & 0x07) << 29;
3094 W_REG(osh, &cc->regcontrol_data, val);
3095 W_REG(osh, &cc->regcontrol_addr, 1);
3096 val = R_REG(osh, &cc->regcontrol_data) & ~(uint32)0x01;
3097 val |= (uint32)((rcal_code >> 3) & 0x01);
3098 W_REG(osh, &cc->regcontrol_data, val);
3100 /* Write RCal code into pmu_chip_ctrl[33:30] */
3101 W_REG(osh, &cc->chipcontrol_addr, 0);
3102 val = R_REG(osh, &cc->chipcontrol_data) & ~((uint32)0x03 << 30);
3103 val |= (uint32)(rcal_code & 0x03) << 30;
3104 W_REG(osh, &cc->chipcontrol_data, val);
3105 W_REG(osh, &cc->chipcontrol_addr, 1);
3106 val = R_REG(osh, &cc->chipcontrol_data) & ~(uint32)0x03;
3107 val |= (uint32)((rcal_code >> 2) & 0x03);
3108 W_REG(osh, &cc->chipcontrol_data, val);
3110 /* Set override in pmu_chip_ctrl[29] */
3111 W_REG(osh, &cc->chipcontrol_addr, 0);
3112 OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
3114 /* Power off RCal block */
3115 W_REG(osh, &cc->chipcontrol_addr, 1);
3116 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3118 break;
3120 case BCM4329_CHIP_ID: {
3121 uint8 rcal_code;
3122 uint32 val;
3124 /* Kick RCal */
3125 W_REG(osh, &cc->chipcontrol_addr, 1);
3127 /* Power Down RCAL Block */
3128 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3130 /* Power Up RCAL block */
3131 OR_REG(osh, &cc->chipcontrol_data, 0x04);
3133 /* Wait for completion */
3134 SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08), 10 * 1000 * 1000);
3135 ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
3137 /* Drop the LSB to convert from 5 bit code to 4 bit code */
3138 rcal_code = (uint8)(R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
3140 PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
3141 R_REG(osh, &cc->chipstatus), rcal_code));
3143 /* Write RCal code into pmu_vreg_ctrl[32:29] */
3144 W_REG(osh, &cc->regcontrol_addr, 0);
3145 val = R_REG(osh, &cc->regcontrol_data) & ~((uint32)0x07 << 29);
3146 val |= (uint32)(rcal_code & 0x07) << 29;
3147 W_REG(osh, &cc->regcontrol_data, val);
3148 W_REG(osh, &cc->regcontrol_addr, 1);
3149 val = R_REG(osh, &cc->regcontrol_data) & ~(uint32)0x01;
3150 val |= (uint32)((rcal_code >> 3) & 0x01);
3151 W_REG(osh, &cc->regcontrol_data, val);
3153 /* Write RCal code into pmu_chip_ctrl[33:30] */
3154 W_REG(osh, &cc->chipcontrol_addr, 0);
3155 val = R_REG(osh, &cc->chipcontrol_data) & ~((uint32)0x03 << 30);
3156 val |= (uint32)(rcal_code & 0x03) << 30;
3157 W_REG(osh, &cc->chipcontrol_data, val);
3158 W_REG(osh, &cc->chipcontrol_addr, 1);
3159 val = R_REG(osh, &cc->chipcontrol_data) & ~(uint32)0x03;
3160 val |= (uint32)((rcal_code >> 2) & 0x03);
3161 W_REG(osh, &cc->chipcontrol_data, val);
3163 /* Set override in pmu_chip_ctrl[29] */
3164 W_REG(osh, &cc->chipcontrol_addr, 0);
3165 OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
3167 /* Power off RCal block */
3168 W_REG(osh, &cc->chipcontrol_addr, 1);
3169 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3171 break;
3173 default:
3174 break;
3177 /* Return to original core */
3178 si_setcoreidx(sih, origidx);
3181 void
3182 si_pmu_spuravoid(si_t *sih, osl_t *osh, uint8 spuravoid)
3184 chipcregs_t *cc;
3185 uint origidx, intr_val;
3186 uint32 tmp = 0;
3188 /* Remember original core before switch to chipc */
3189 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
3190 ASSERT(cc != NULL);
3192 /* force the HT off */
3193 if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
3194 tmp = R_REG(osh, &cc->max_res_mask);
3195 tmp &= ~RES4336_HT_AVAIL;
3196 W_REG(osh, &cc->max_res_mask, tmp);
3197 /* wait for the ht to really go away */
3198 SPINWAIT(((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0), 10000);
3199 ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0);
3202 /* update the pll changes */
3203 si_pmu_spuravoid_pllupdate(sih, cc, osh, spuravoid);
3205 /* enable HT back on */
3206 if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
3207 tmp = R_REG(osh, &cc->max_res_mask);
3208 tmp |= RES4336_HT_AVAIL;
3209 W_REG(osh, &cc->max_res_mask, tmp);
3212 /* Return to original core */
3213 si_restore_core(sih, origidx, intr_val);
3216 static void
3217 si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, osl_t *osh, uint8 spuravoid)
3219 uint32 tmp = 0;
3220 uint8 phypll_offset = 0;
3221 uint8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5};
3222 uint8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc};
3223 #ifdef BCMDBG_ERR
3224 char chn[8];
3225 #endif
3227 switch (CHIPID(sih->chip)) {
3228 case BCM5357_CHIP_ID: case BCM4749_CHIP_ID:
3229 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
3230 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
3231 case BCM6362_CHIP_ID: case BCM53572_CHIP_ID:
3233 if ((CHIPID(sih->chip) == BCM6362_CHIP_ID) && (sih->chiprev == 0)) {
3234 /* 6362a0 (same clks as 4322[4-6]) */
3235 if (spuravoid == 1) {
3236 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3237 W_REG(osh, &cc->pllcontrol_data, 0x11500010);
3238 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3239 W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
3240 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3241 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3242 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3243 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3244 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3245 W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
3246 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3247 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3248 } else {
3249 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3250 W_REG(osh, &cc->pllcontrol_data, 0x11100010);
3251 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3252 W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
3253 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3254 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3255 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3256 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3257 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3258 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3259 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3260 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3263 } else {
3264 /* 5357[ab]0, 43236[ab]0, and 6362b0 */
3266 /* BCM5357 needs to touch PLL1_PLLCTL[02],so offset PLL0_PLLCTL[02] by 6 */
3267 phypll_offset = ((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
3268 (CHIPID(sih->chip) == BCM4749_CHIP_ID) ||
3269 (CHIPID(sih->chip) == BCM53572_CHIP_ID)) ? 6 : 0;
3271 /* RMW only the P1 divider */
3272 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0 + phypll_offset);
3273 tmp = R_REG(osh, &cc->pllcontrol_data);
3274 tmp &= (~(PMU1_PLL0_PC0_P1DIV_MASK));
3275 tmp |= (bcm5357_bcm43236_p1div[spuravoid] << PMU1_PLL0_PC0_P1DIV_SHIFT);
3276 W_REG(osh, &cc->pllcontrol_data, tmp);
3278 /* RMW only the int feedback divider */
3279 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2 + phypll_offset);
3280 tmp = R_REG(osh, &cc->pllcontrol_data);
3281 tmp &= ~(PMU1_PLL0_PC2_NDIV_INT_MASK);
3282 tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << PMU1_PLL0_PC2_NDIV_INT_SHIFT;
3283 W_REG(osh, &cc->pllcontrol_data, tmp);
3286 tmp = 1 << 10;
3287 break;
3289 case BCM4331_CHIP_ID:
3290 case BCM43431_CHIP_ID:
3291 if (ISSIM_ENAB(sih)) {
3292 if (spuravoid == 2) {
3293 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3294 W_REG(osh, &cc->pllcontrol_data, 0x00000002);
3295 } else if (spuravoid == 1) {
3296 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3297 W_REG(osh, &cc->pllcontrol_data, 0x00000001);
3298 } else {
3299 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3300 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3302 } else {
3303 if (spuravoid == 2) {
3304 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3305 W_REG(osh, &cc->pllcontrol_data, 0x11500014);
3306 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3307 W_REG(osh, &cc->pllcontrol_data, 0x0FC00a08);
3308 } else if (spuravoid == 1) {
3309 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3310 W_REG(osh, &cc->pllcontrol_data, 0x11500014);
3311 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3312 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3313 } else {
3314 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3315 W_REG(osh, &cc->pllcontrol_data, 0x11100014);
3316 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3317 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3320 tmp = 1 << 10;
3321 break;
3323 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID:
3324 case BCM43226_CHIP_ID:
3325 if (spuravoid == 1) {
3326 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3327 W_REG(osh, &cc->pllcontrol_data, 0x11500010);
3328 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3329 W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
3330 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3331 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3332 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3333 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3334 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3335 W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
3336 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3337 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3338 } else {
3339 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3340 W_REG(osh, &cc->pllcontrol_data, 0x11100010);
3341 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3342 W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
3343 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3344 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3345 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3346 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3347 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3348 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3349 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3350 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3352 tmp = 1 << 10;
3353 break;
3355 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
3356 case BCM43420_CHIP_ID:
3357 if (spuravoid == 1) {
3358 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3359 W_REG(osh, &cc->pllcontrol_data, 0x11500008);
3360 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3361 W_REG(osh, &cc->pllcontrol_data, 0x0C000C06);
3362 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3363 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3364 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3365 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3366 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3367 W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
3368 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3369 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3370 } else {
3371 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3372 W_REG(osh, &cc->pllcontrol_data, 0x11100008);
3373 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3374 W_REG(osh, &cc->pllcontrol_data, 0x0c000c06);
3375 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3376 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3377 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3378 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3379 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3380 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3381 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3382 W_REG(osh, &cc->pllcontrol_data, 0x88888855);
3385 tmp = 1 << 10;
3386 break;
3388 case BCM4716_CHIP_ID:
3389 case BCM4748_CHIP_ID:
3390 case BCM47162_CHIP_ID:
3391 if (spuravoid == 1) {
3392 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3393 W_REG(osh, &cc->pllcontrol_data, 0x11500060);
3394 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3395 W_REG(osh, &cc->pllcontrol_data, 0x080C0C06);
3396 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3397 W_REG(osh, &cc->pllcontrol_data, 0x0F600000);
3398 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3399 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3400 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3401 W_REG(osh, &cc->pllcontrol_data, 0x2001E924);
3402 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3403 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3404 } else {
3405 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3406 W_REG(osh, &cc->pllcontrol_data, 0x11100060);
3407 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3408 W_REG(osh, &cc->pllcontrol_data, 0x080c0c06);
3409 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3410 W_REG(osh, &cc->pllcontrol_data, 0x03000000);
3411 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3412 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3413 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3414 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3415 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3416 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3419 tmp = 3 << 9;
3420 break;
3422 case BCM4322_CHIP_ID:
3423 case BCM43221_CHIP_ID:
3424 case BCM43231_CHIP_ID:
3425 case BCM4342_CHIP_ID:
3426 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3427 W_REG(osh, &cc->pllcontrol_data, 0x11100070);
3428 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3429 W_REG(osh, &cc->pllcontrol_data, 0x1014140a);
3430 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3431 W_REG(osh, &cc->pllcontrol_data, 0x88888854);
3433 if (spuravoid == 1) { /* spur_avoid ON, enable 41/82/164Mhz clock mode */
3434 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3435 W_REG(osh, &cc->pllcontrol_data, 0x05201828);
3436 } else { /* enable 40/80/160Mhz clock mode */
3437 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3438 W_REG(osh, &cc->pllcontrol_data, 0x05001828);
3441 tmp = 1 << 10;
3442 break;
3443 case BCM4319_CHIP_ID:
3444 break;
3445 case BCM4336_CHIP_ID:
3446 /* Looks like these are only for default xtal freq 26MHz */
3447 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3448 W_REG(osh, &cc->pllcontrol_data, 0x02100020);
3450 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3451 W_REG(osh, &cc->pllcontrol_data, 0x0C0C0C0C);
3453 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3454 W_REG(osh, &cc->pllcontrol_data, 0x01240C0C);
3456 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3457 W_REG(osh, &cc->pllcontrol_data, 0x202C2820);
3459 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3460 W_REG(osh, &cc->pllcontrol_data, 0x88888825);
3462 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3463 if (spuravoid == 1) {
3464 W_REG(osh, &cc->pllcontrol_data, 0x00EC4EC4);
3465 } else {
3466 W_REG(osh, &cc->pllcontrol_data, 0x00762762);
3469 tmp = PCTL_PLL_PLLCTL_UPD;
3470 break;
3471 case BCM43227_CHIP_ID:
3472 case BCM43228_CHIP_ID:
3473 case BCM43428_CHIP_ID:
3474 /* LCNXN */
3475 /* PLL Settings for spur avoidance on/off mode, no on2 support for 43228A0 */
3476 if (spuravoid == 1) {
3477 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3478 W_REG(osh, &cc->pllcontrol_data, 0x01100014);
3479 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3480 W_REG(osh, &cc->pllcontrol_data, 0x040C0C06);
3481 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3482 W_REG(osh, &cc->pllcontrol_data, 0x03140A08);
3483 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3484 W_REG(osh, &cc->pllcontrol_data, 0x00333333);
3485 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3486 W_REG(osh, &cc->pllcontrol_data, 0x202C2820);
3487 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3488 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3489 } else {
3490 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3491 W_REG(osh, &cc->pllcontrol_data, 0x11100014);
3492 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3493 W_REG(osh, &cc->pllcontrol_data, 0x040c0c06);
3494 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3495 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3496 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3497 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3498 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3499 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3500 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3501 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3503 tmp = 1 << 10;
3504 break;
3505 default:
3506 PMU_ERROR(("%s: unknown spuravoidance settings for chip %s, not changing PLL\n",
3507 __FUNCTION__, bcm_chipname(sih->chip, chn, 8)));
3508 break;
3511 tmp |= R_REG(osh, &cc->pmucontrol);
3512 W_REG(osh, &cc->pmucontrol, tmp);
3515 void
3516 si_pmu_gband_spurwar(si_t *sih, osl_t *osh)
3518 chipcregs_t *cc;
3519 uint origidx, intr_val;
3520 uint32 cc_clk_ctl_st;
3521 uint32 minmask, maxmask;
3523 if ((CHIPID(sih->chip) == BCM43222_CHIP_ID) ||
3524 (CHIPID(sih->chip) == BCM43420_CHIP_ID)) {
3525 /* Remember original core before switch to chipc */
3526 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
3527 ASSERT(cc != NULL);
3529 /* Remove force HT and HT Avail Request from chipc core */
3530 cc_clk_ctl_st = R_REG(osh, &cc->clk_ctl_st);
3531 AND_REG(osh, &cc->clk_ctl_st, ~(CCS_FORCEHT | CCS_HTAREQ));
3533 minmask = R_REG(osh, &cc->min_res_mask);
3534 maxmask = R_REG(osh, &cc->max_res_mask);
3536 /* Make sure the PLL is off: clear bit 4 & 5 of min/max_res_mask */
3537 /* Have to remove HT Avail request before powering off PLL */
3538 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
3539 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
3540 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
3541 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
3542 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
3543 OSL_DELAY(150);
3544 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
3546 /* Change backplane clock speed from 96 MHz to 80 MHz */
3547 W_REG(osh, &cc->pllcontrol_addr, PMU2_PLL_PLLCTL2);
3548 W_REG(osh, &cc->pllcontrol_data, (R_REG(osh, &cc->pllcontrol_data) &
3549 ~(PMU2_PLL_PC2_M6DIV_MASK)) |
3550 (0xc << PMU2_PLL_PC2_M6DIV_SHIFT));
3552 /* Reduce the driver strengths of the phyclk160, adcclk80, and phyck80
3553 * clocks from 0x8 to 0x1
3555 W_REG(osh, &cc->pllcontrol_addr, PMU2_PLL_PLLCTL5);
3556 W_REG(osh, &cc->pllcontrol_data, (R_REG(osh, &cc->pllcontrol_data) &
3557 ~(PMU2_PLL_PC5_CLKDRIVE_CH1_MASK |
3558 PMU2_PLL_PC5_CLKDRIVE_CH2_MASK |
3559 PMU2_PLL_PC5_CLKDRIVE_CH3_MASK |
3560 PMU2_PLL_PC5_CLKDRIVE_CH4_MASK)) |
3561 ((1 << PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT) |
3562 (1 << PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT) |
3563 (1 << PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT) |
3564 (1 << PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT)));
3566 W_REG(osh, &cc->pmucontrol, R_REG(osh, &cc->pmucontrol) | PCTL_PLL_PLLCTL_UPD);
3568 /* Restore min_res_mask and max_res_mask */
3569 OSL_DELAY(100);
3570 W_REG(osh, &cc->max_res_mask, maxmask);
3571 OSL_DELAY(100);
3572 W_REG(osh, &cc->min_res_mask, minmask);
3573 OSL_DELAY(100);
3574 /* Make sure the PLL is on. Spinwait until the HTAvail is True */
3575 SPINWAIT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL), PMU_MAX_TRANSITION_DLY);
3576 ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
3578 /* Restore force HT and HT Avail Request on the chipc core */
3579 W_REG(osh, &cc->clk_ctl_st, cc_clk_ctl_st);
3581 /* Return to original core */
3582 si_restore_core(sih, origidx, intr_val);
3586 bool
3587 si_pmu_is_otp_powered(si_t *sih, osl_t *osh)
3589 uint idx;
3590 chipcregs_t *cc;
3591 bool st;
3593 /* Remember original core before switch to chipc */
3594 idx = si_coreidx(sih);
3595 cc = si_setcoreidx(sih, SI_CC_IDX);
3596 ASSERT(cc != NULL);
3598 switch (CHIPID(sih->chip)) {
3599 case BCM4322_CHIP_ID:
3600 case BCM43221_CHIP_ID:
3601 case BCM43231_CHIP_ID:
3602 case BCM4342_CHIP_ID:
3603 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4322_OTP_PU)) != 0;
3604 break;
3605 case BCM4325_CHIP_ID:
3606 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4325_OTP_PU)) != 0;
3607 break;
3608 case BCM4329_CHIP_ID:
3609 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4329_OTP_PU)) != 0;
3610 break;
3611 case BCM4315_CHIP_ID:
3612 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4315_OTP_PU)) != 0;
3613 break;
3614 case BCM4319_CHIP_ID:
3615 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4319_OTP_PU)) != 0;
3616 break;
3617 case BCM4336_CHIP_ID:
3618 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4336_OTP_PU)) != 0;
3619 break;
3620 case BCM4330_CHIP_ID:
3621 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4330_OTP_PU)) != 0;
3622 break;
3624 /* These chip doesn't use PMU bit to power up/down OTP. OTP always on.
3625 * Use OTP_INIT command to reset/refresh state.
3627 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
3628 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID:
3629 case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID:
3630 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID: case BCM43420_CHIP_ID:
3631 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
3632 st = TRUE;
3633 break;
3634 default:
3635 st = TRUE;
3636 break;
3639 /* Return to original core */
3640 si_setcoreidx(sih, idx);
3641 return st;
3643 #endif /* !_CFE_ || CFG_WL */
3645 void
3646 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
3647 si_pmu_sprom_enable(si_t *sih, osl_t *osh, bool enable)
3648 #else
3649 BCMATTACHFN(si_pmu_sprom_enable)(si_t *sih, osl_t *osh, bool enable)
3650 #endif
3652 chipcregs_t *cc;
3653 uint origidx;
3655 /* Remember original core before switch to chipc */
3656 origidx = si_coreidx(sih);
3657 cc = si_setcoreidx(sih, SI_CC_IDX);
3658 ASSERT(cc != NULL);
3660 switch (CHIPID(sih->chip)) {
3661 case BCM4315_CHIP_ID:
3662 if (CHIPREV(sih->chiprev) < 1)
3663 break;
3664 if (sih->chipst & CST4315_SPROM_SEL) {
3665 uint32 val;
3666 W_REG(osh, &cc->chipcontrol_addr, 0);
3667 val = R_REG(osh, &cc->chipcontrol_data);
3668 if (enable)
3669 val &= ~0x80000000;
3670 else
3671 val |= 0x80000000;
3672 W_REG(osh, &cc->chipcontrol_data, val);
3674 break;
3675 default:
3676 break;
3679 /* Return to original core */
3680 si_setcoreidx(sih, origidx);
3683 bool
3684 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
3685 si_pmu_is_sprom_enabled(si_t *sih, osl_t *osh)
3686 #else
3687 BCMATTACHFN(si_pmu_is_sprom_enabled)(si_t *sih, osl_t *osh)
3688 #endif
3690 chipcregs_t *cc;
3691 uint origidx;
3692 bool enable = TRUE;
3694 /* Remember original core before switch to chipc */
3695 origidx = si_coreidx(sih);
3696 cc = si_setcoreidx(sih, SI_CC_IDX);
3697 ASSERT(cc != NULL);
3699 switch (CHIPID(sih->chip)) {
3700 case BCM4315_CHIP_ID:
3701 if (CHIPREV(sih->chiprev) < 1)
3702 break;
3703 if (!(sih->chipst & CST4315_SPROM_SEL))
3704 break;
3705 W_REG(osh, &cc->chipcontrol_addr, 0);
3706 if (R_REG(osh, &cc->chipcontrol_data) & 0x80000000)
3707 enable = FALSE;
3708 break;
3709 default:
3710 break;
3713 /* Return to original core */
3714 si_setcoreidx(sih, origidx);
3715 return enable;
3718 /* initialize PMU chip controls and other chip level stuff */
3719 void
3720 BCMATTACHFN(si_pmu_chip_init)(si_t *sih, osl_t *osh)
3722 uint origidx;
3724 ASSERT(sih->cccaps & CC_CAP_PMU);
3726 #ifdef CHIPC_UART_ALWAYS_ON
3727 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), CCS_FORCEALP, CCS_FORCEALP);
3728 #endif /* CHIPC_UART_ALWAYS_ON */
3730 #ifndef CONFIG_XIP
3731 /* Gate off SPROM clock and chip select signals */
3732 si_pmu_sprom_enable(sih, osh, FALSE);
3733 #endif
3735 /* Remember original core */
3736 origidx = si_coreidx(sih);
3738 #if !defined(_CFE_) || defined(CFG_WL)
3739 /* Misc. chip control, has nothing to do with PMU */
3740 switch (CHIPID(sih->chip)) {
3741 case BCM4315_CHIP_ID:
3742 #ifdef BCMUSBDEV
3743 si_setcore(sih, PCMCIA_CORE_ID, 0);
3744 si_core_disable(sih, 0);
3745 #endif
3746 break;
3747 case BCM4319_CHIP_ID:
3748 /* No support for external LPO, so power it down */
3749 si_pmu_chipcontrol(sih, 0, (1<<28), (0<<28));
3750 break;
3751 default:
3752 break;
3754 #endif /* !_CFE_ || CFG_WL */
3756 /* Return to original core */
3757 si_setcoreidx(sih, origidx);
3760 /* initialize PMU switch/regulators */
3761 void
3762 BCMATTACHFN(si_pmu_swreg_init)(si_t *sih, osl_t *osh)
3764 #if !defined(_CFE_) || defined(CFG_WL)
3765 ASSERT(sih->cccaps & CC_CAP_PMU);
3767 switch (CHIPID(sih->chip)) {
3768 case BCM4325_CHIP_ID:
3769 if (CHIPREV(sih->chiprev) < 3)
3770 break;
3771 if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >> CST4325_PMUTOP_2B_SHIFT) == 1) {
3772 /* Bump CLDO PWM output voltage to 1.25V */
3773 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xf);
3774 /* Bump CLDO BURST output voltage to 1.25V */
3775 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_BURST, 0xf);
3777 /* Bump CBUCK PWM output voltage to 1.5V */
3778 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0xb);
3779 /* Bump CBUCK BURST output voltage to 1.5V */
3780 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_BURST, 0xb);
3781 /* Bump LNLDO1 output voltage to 1.25V */
3782 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO1, 0x1);
3783 /* Select LNLDO2 output voltage to 2.5V */
3784 if (sih->boardflags & BFL_LNLDO2_2P5)
3785 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO2_SEL, 0x1);
3786 break;
3787 case BCM4315_CHIP_ID: {
3788 uint32 val;
3789 chipcregs_t *cc;
3790 uint origidx;
3792 if (CHIPREV(sih->chiprev) != 2)
3793 break;
3795 /* Remember original core before switch to chipc */
3796 origidx = si_coreidx(sih);
3797 cc = si_setcoreidx(sih, SI_CC_IDX);
3798 ASSERT(cc != NULL);
3800 W_REG(osh, &cc->regcontrol_addr, 4);
3801 val = R_REG(osh, &cc->regcontrol_data);
3802 val |= (uint32)(1 << 16);
3803 W_REG(osh, &cc->regcontrol_data, val);
3805 /* Return to original core */
3806 si_setcoreidx(sih, origidx);
3807 break;
3809 case BCM4336_CHIP_ID:
3810 /* Reduce CLDO PWM output voltage to 1.2V */
3811 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xe);
3812 /* Reduce CLDO BURST output voltage to 1.2V */
3813 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_BURST, 0xe);
3814 /* Reduce LNLDO1 output voltage to 1.2V */
3815 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO1, 0xe);
3816 if (CHIPREV(sih->chiprev) == 0)
3817 si_pmu_regcontrol(sih, 2, 0x400000, 0x400000);
3818 break;
3820 case BCM4330_CHIP_ID:
3821 /* CBUCK Voltage is 1.8 by default and set that to 1.5 */
3822 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0);
3823 break;
3824 default:
3825 break;
3827 #endif /* !_CFE_ || CFG_WL */
3830 void
3831 si_pmu_radio_enable(si_t *sih, bool enable)
3833 ASSERT(sih->cccaps & CC_CAP_PMU);
3835 switch (CHIPID(sih->chip)) {
3836 case BCM4325_CHIP_ID:
3837 if (sih->boardflags & BFL_FASTPWR)
3838 break;
3840 if ((sih->boardflags & BFL_BUCKBOOST)) {
3841 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask),
3842 PMURES_BIT(RES4325_BUCK_BOOST_BURST),
3843 enable ? PMURES_BIT(RES4325_BUCK_BOOST_BURST) : 0);
3846 if (enable) {
3847 OSL_DELAY(100 * 1000);
3849 break;
3850 case BCM4319_CHIP_ID:
3851 if (enable)
3852 si_write_wrapperreg(sih, AI_OOBSELOUTB74, (uint32)0x868584);
3853 else
3854 si_write_wrapperreg(sih, AI_OOBSELOUTB74, (uint32)0x060584);
3855 break;
3859 /* Wait for a particular clock level to be on the backplane */
3860 uint32
3861 si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, uint32 clk, uint32 delay)
3863 chipcregs_t *cc;
3864 uint origidx;
3866 ASSERT(sih->cccaps & CC_CAP_PMU);
3868 /* Remember original core before switch to chipc */
3869 origidx = si_coreidx(sih);
3870 cc = si_setcoreidx(sih, SI_CC_IDX);
3871 ASSERT(cc != NULL);
3873 if (delay)
3874 SPINWAIT(((R_REG(osh, &cc->pmustatus) & clk) != clk), delay);
3876 /* Return to original core */
3877 si_setcoreidx(sih, origidx);
3879 return (R_REG(osh, &cc->pmustatus) & clk);
3883 * Measures the ALP clock frequency in KHz. Returns 0 if not possible.
3884 * Possible only if PMU rev >= 10 and there is an external LPO 32768Hz crystal.
3887 #define EXT_ILP_HZ 32768
3889 uint32
3890 BCMATTACHFN(si_pmu_measure_alpclk)(si_t *sih, osl_t *osh)
3892 chipcregs_t *cc;
3893 uint origidx;
3894 uint32 alp_khz;
3896 if (sih->pmurev < 10)
3897 return 0;
3899 ASSERT(sih->cccaps & CC_CAP_PMU);
3901 /* Remember original core before switch to chipc */
3902 origidx = si_coreidx(sih);
3903 cc = si_setcoreidx(sih, SI_CC_IDX);
3904 ASSERT(cc != NULL);
3906 if (R_REG(osh, &cc->pmustatus) & PST_EXTLPOAVAIL) {
3907 uint32 ilp_ctr, alp_hz;
3909 /* Enable the reg to measure the freq, in case disabled before */
3910 W_REG(osh, &cc->pmu_xtalfreq, 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
3912 /* Delay for well over 4 ILP clocks */
3913 OSL_DELAY(1000);
3915 /* Read the latched number of ALP ticks per 4 ILP ticks */
3916 ilp_ctr = R_REG(osh, &cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
3918 /* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT bit to save power */
3919 W_REG(osh, &cc->pmu_xtalfreq, 0);
3921 /* Calculate ALP frequency */
3922 alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
3924 /* Round to nearest 100KHz, and at the same time convert to KHz */
3925 alp_khz = (alp_hz + 50000) / 100000 * 100;
3926 } else
3927 alp_khz = 0;
3929 /* Return to original core */
3930 si_setcoreidx(sih, origidx);
3932 return alp_khz;
3935 #if !defined(_CFE_) || defined(CFG_WL)
3936 void
3937 si_pmu_set_4330_plldivs(si_t *sih, uint8 dacrate)
3939 uint32 FVCO = si_pmu1_pllfvco0(sih)/1000;
3940 uint32 m1div, m2div, m3div, m4div, m5div, m6div;
3941 uint32 pllc1, pllc2;
3943 m2div = m3div = m4div = m6div = FVCO/80;
3945 m5div = FVCO/dacrate;
3947 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
3948 m1div = FVCO/80;
3949 else
3950 m1div = FVCO/90;
3951 pllc1 = (m1div << PMU1_PLL0_PC1_M1DIV_SHIFT) | (m2div << PMU1_PLL0_PC1_M2DIV_SHIFT) |
3952 (m3div << PMU1_PLL0_PC1_M3DIV_SHIFT) | (m4div << PMU1_PLL0_PC1_M4DIV_SHIFT);
3953 si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, ~0, pllc1);
3955 pllc2 = si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL2, 0, 0);
3956 pllc2 &= ~(PMU1_PLL0_PC2_M5DIV_MASK | PMU1_PLL0_PC2_M6DIV_MASK);
3957 pllc2 |= ((m5div << PMU1_PLL0_PC2_M5DIV_SHIFT) | (m6div << PMU1_PLL0_PC2_M6DIV_SHIFT));
3958 si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL2, ~0, pllc2);
3960 #endif /* !_CFE_ || CFG_WL */