Resync with broadcom drivers 5.100.138.20 and utilities.
[tomato.git] / release / src-rt / shared / hndpmu.c
blob689ed2a40e12ff528058b66605f4b80aa900bfe6
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_val = 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 BCM43131_CHIP_ID:
373 case BCM43227_CHIP_ID:
374 case BCM43228_CHIP_ID:
375 case BCM43428_CHIP_ID:
376 case BCM6362_CHIP_ID:
377 case BCM4342_CHIP_ID:
378 case BCM4313_CHIP_ID:
379 delay_val = ISSIM_ENAB(sih) ? 70 : 3700;
380 break;
381 case BCM4328_CHIP_ID:
382 delay_val = 7000;
383 break;
384 case BCM4325_CHIP_ID:
385 if (ISSIM_ENAB(sih))
386 delay_val = 70;
387 else {
388 uint32 ilp = si_ilp_clock(sih);
389 delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4325_HT_AVAIL) +
390 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
391 delay_val = (11 * delay_val) / 10;
393 break;
394 case BCM4329_CHIP_ID:
395 if (ISSIM_ENAB(sih))
396 delay_val = 70;
397 else {
398 uint32 ilp = si_ilp_clock(sih);
399 delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4329_HT_AVAIL) +
400 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
401 delay_val = (11 * delay_val) / 10;
403 break;
404 case BCM4315_CHIP_ID:
405 if (ISSIM_ENAB(sih))
406 delay_val = 70;
407 else {
408 uint32 ilp = si_ilp_clock(sih);
409 delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4315_HT_AVAIL) +
410 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
411 delay_val = (11 * delay_val) / 10;
413 break;
414 case BCM4319_CHIP_ID:
415 if (ISSIM_ENAB(sih))
416 delay_val = 70;
417 else {
418 #ifdef BCMUSBDEV
419 /* For USB HT is always available, even durring IEEE PS,
420 * so need minimal delay
422 delay_val = 100;
423 #else /* BCMUSBDEV */
424 /* For SDIO, total delay in getting HT available */
425 /* Adjusted for uptime XTAL=672us, HTAVail=128us */
426 uint32 ilp = si_ilp_clock(sih);
427 delay_val = si_pmu_res_uptime(sih, osh, cc, RES4319_HT_AVAIL);
428 PMU_MSG(("si_ilp_clock (Hz): %u delay (ilp clks): %u\n", ilp, delay_val));
429 delay_val = (delay_val + D11SCC_SLOW2FAST_TRANSITION) * (1000000 / ilp);
430 PMU_MSG(("delay (us): %u\n", delay_val));
431 delay_val = (11 * delay_val) / 10;
432 PMU_MSG(("delay (us): %u\n", delay_val));
433 /* VDDIO_RF por delay = 3.4ms */
434 if (delay_val < 3400) delay_val = 3400;
435 #endif /* BCMUSBDEV */
437 break;
438 case BCM4336_CHIP_ID:
439 if (ISSIM_ENAB(sih))
440 delay_val = 70;
441 else {
442 uint32 ilp = si_ilp_clock(sih);
443 delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4336_HT_AVAIL) +
444 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
445 delay_val = (11 * delay_val) / 10;
447 break;
448 case BCM4330_CHIP_ID:
449 if (ISSIM_ENAB(sih))
450 delay_val = 70;
451 else {
452 uint32 ilp = si_ilp_clock(sih);
453 delay_val = (si_pmu_res_uptime(sih, osh, cc, RES4330_HT_AVAIL) +
454 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
455 delay_val = (11 * delay_val) / 10;
457 break;
458 default:
459 break;
462 /* PMU_MSG(("si_pmu_fast_pwrup_delay: chip %s rev %d delay %d\n",
463 * bcm_chipname(sih->chip, chn, 8), sih->chiprev, delay));
466 /* Return to original core */
467 si_setcoreidx(sih, origidx);
469 return (uint16)delay_val;
471 #endif /* !_CFE_ || CFG_WL */
473 uint32
474 BCMATTACHFN(si_pmu_force_ilp)(si_t *sih, osl_t *osh, bool force)
476 chipcregs_t *cc;
477 uint origidx;
478 uint32 oldpmucontrol;
480 ASSERT(sih->cccaps & CC_CAP_PMU);
482 /* Remember original core before switch to chipc */
483 origidx = si_coreidx(sih);
484 cc = si_setcoreidx(sih, SI_CC_IDX);
485 ASSERT(cc != NULL);
487 oldpmucontrol = R_REG(osh, &cc->pmucontrol);
488 if (force)
489 W_REG(osh, &cc->pmucontrol, oldpmucontrol &
490 ~(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
491 else
492 W_REG(osh, &cc->pmucontrol, oldpmucontrol |
493 (PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
495 /* Return to original core */
496 si_setcoreidx(sih, origidx);
498 return oldpmucontrol;
501 /* Setup resource up/down timers */
502 typedef struct {
503 uint8 resnum;
504 uint16 updown;
505 } pmu_res_updown_t;
507 /* Change resource dependancies masks */
508 typedef struct {
509 uint32 res_mask; /* resources (chip specific) */
510 int8 action; /* action */
511 uint32 depend_mask; /* changes to the dependancies mask */
512 bool (*filter)(si_t *sih); /* action is taken when filter is NULL or return TRUE */
513 } pmu_res_depend_t;
515 /* Resource dependancies mask change action */
516 #define RES_DEPEND_SET 0 /* Override the dependancies mask */
517 #define RES_DEPEND_ADD 1 /* Add to the dependancies mask */
518 #define RES_DEPEND_REMOVE -1 /* Remove from the dependancies mask */
520 #if !defined(_CFE_) || defined(CFG_WL)
521 static const pmu_res_updown_t BCMATTACHDATA(bcm4328a0_res_updown)[] = {
522 { RES4328_EXT_SWITCHER_PWM, 0x0101 },
523 { RES4328_BB_SWITCHER_PWM, 0x1f01 },
524 { RES4328_BB_SWITCHER_BURST, 0x010f },
525 { RES4328_BB_EXT_SWITCHER_BURST, 0x0101 },
526 { RES4328_ILP_REQUEST, 0x0202 },
527 { RES4328_RADIO_SWITCHER_PWM, 0x0f01 },
528 { RES4328_RADIO_SWITCHER_BURST, 0x0f01 },
529 { RES4328_ROM_SWITCH, 0x0101 },
530 { RES4328_PA_REF_LDO, 0x0f01 },
531 { RES4328_RADIO_LDO, 0x0f01 },
532 { RES4328_AFE_LDO, 0x0f01 },
533 { RES4328_PLL_LDO, 0x0f01 },
534 { RES4328_BG_FILTBYP, 0x0101 },
535 { RES4328_TX_FILTBYP, 0x0101 },
536 { RES4328_RX_FILTBYP, 0x0101 },
537 { RES4328_XTAL_PU, 0x0101 },
538 { RES4328_XTAL_EN, 0xa001 },
539 { RES4328_BB_PLL_FILTBYP, 0x0101 },
540 { RES4328_RF_PLL_FILTBYP, 0x0101 },
541 { RES4328_BB_PLL_PU, 0x0701 }
544 static const pmu_res_depend_t BCMATTACHDATA(bcm4328a0_res_depend)[] = {
545 /* Adjust ILP request resource not to force ext/BB switchers into burst mode */
547 PMURES_BIT(RES4328_ILP_REQUEST),
548 RES_DEPEND_SET,
549 PMURES_BIT(RES4328_EXT_SWITCHER_PWM) | PMURES_BIT(RES4328_BB_SWITCHER_PWM),
550 NULL
554 static const pmu_res_updown_t BCMATTACHDATA(bcm4325a0_res_updown_qt)[] = {
555 { RES4325_HT_AVAIL, 0x0300 },
556 { RES4325_BBPLL_PWRSW_PU, 0x0101 },
557 { RES4325_RFPLL_PWRSW_PU, 0x0101 },
558 { RES4325_ALP_AVAIL, 0x0100 },
559 { RES4325_XTAL_PU, 0x1000 },
560 { RES4325_LNLDO1_PU, 0x0800 },
561 { RES4325_CLDO_CBUCK_PWM, 0x0101 },
562 { RES4325_CBUCK_PWM, 0x0803 }
565 static const pmu_res_updown_t BCMATTACHDATA(bcm4325a0_res_updown)[] = {
566 { RES4325_XTAL_PU, 0x1501 }
569 static const pmu_res_depend_t BCMATTACHDATA(bcm4325a0_res_depend)[] = {
570 /* Adjust OTP PU resource dependencies - remove BB BURST */
572 PMURES_BIT(RES4325_OTP_PU),
573 RES_DEPEND_REMOVE,
574 PMURES_BIT(RES4325_BUCK_BOOST_BURST),
575 NULL
577 /* Adjust ALP/HT Avail resource dependencies - bring up BB along if it is used. */
579 PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_HT_AVAIL),
580 RES_DEPEND_ADD,
581 PMURES_BIT(RES4325_BUCK_BOOST_BURST) | PMURES_BIT(RES4325_BUCK_BOOST_PWM),
582 si_pmu_res_depfltr_bb
584 /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
586 PMURES_BIT(RES4325_HT_AVAIL),
587 RES_DEPEND_ADD,
588 PMURES_BIT(RES4325_RX_PWRSW_PU) | PMURES_BIT(RES4325_TX_PWRSW_PU) |
589 PMURES_BIT(RES4325_LOGEN_PWRSW_PU) | PMURES_BIT(RES4325_AFE_PWRSW_PU),
590 NULL
592 /* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
594 PMURES_BIT(RES4325_ILP_REQUEST) | PMURES_BIT(RES4325_ABUCK_BURST) |
595 PMURES_BIT(RES4325_ABUCK_PWM) | PMURES_BIT(RES4325_LNLDO1_PU) |
596 PMURES_BIT(RES4325C1_LNLDO2_PU) | PMURES_BIT(RES4325_XTAL_PU) |
597 PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_RX_PWRSW_PU) |
598 PMURES_BIT(RES4325_TX_PWRSW_PU) | PMURES_BIT(RES4325_RFPLL_PWRSW_PU) |
599 PMURES_BIT(RES4325_LOGEN_PWRSW_PU) | PMURES_BIT(RES4325_AFE_PWRSW_PU) |
600 PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL),
601 RES_DEPEND_REMOVE,
602 PMURES_BIT(RES4325B0_CBUCK_LPOM) | PMURES_BIT(RES4325B0_CBUCK_BURST) |
603 PMURES_BIT(RES4325B0_CBUCK_PWM),
604 si_pmu_res_depfltr_ncb
608 static const pmu_res_updown_t BCMATTACHDATA(bcm4315a0_res_updown_qt)[] = {
609 { RES4315_HT_AVAIL, 0x0101 },
610 { RES4315_XTAL_PU, 0x0100 },
611 { RES4315_LNLDO1_PU, 0x0100 },
612 { RES4315_PALDO_PU, 0x0100 },
613 { RES4315_CLDO_PU, 0x0100 },
614 { RES4315_CBUCK_PWM, 0x0100 },
615 { RES4315_CBUCK_BURST, 0x0100 },
616 { RES4315_CBUCK_LPOM, 0x0100 }
619 static const pmu_res_updown_t BCMATTACHDATA(bcm4315a0_res_updown)[] = {
620 { RES4315_XTAL_PU, 0x2501 }
623 static const pmu_res_depend_t BCMATTACHDATA(bcm4315a0_res_depend)[] = {
624 /* Adjust OTP PU resource dependencies - not need PALDO unless write */
626 PMURES_BIT(RES4315_OTP_PU),
627 RES_DEPEND_REMOVE,
628 PMURES_BIT(RES4315_PALDO_PU),
629 si_pmu_res_depfltr_npaldo
631 /* Adjust ALP/HT Avail resource dependencies - bring up PALDO along if it is used. */
633 PMURES_BIT(RES4315_ALP_AVAIL) | PMURES_BIT(RES4315_HT_AVAIL),
634 RES_DEPEND_ADD,
635 PMURES_BIT(RES4315_PALDO_PU),
636 si_pmu_res_depfltr_paldo
638 /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
640 PMURES_BIT(RES4315_HT_AVAIL),
641 RES_DEPEND_ADD,
642 PMURES_BIT(RES4315_RX_PWRSW_PU) | PMURES_BIT(RES4315_TX_PWRSW_PU) |
643 PMURES_BIT(RES4315_LOGEN_PWRSW_PU) | PMURES_BIT(RES4315_AFE_PWRSW_PU),
644 NULL
646 /* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
648 PMURES_BIT(RES4315_CLDO_PU) | PMURES_BIT(RES4315_ILP_REQUEST) |
649 PMURES_BIT(RES4315_LNLDO1_PU) | PMURES_BIT(RES4315_OTP_PU) |
650 PMURES_BIT(RES4315_LNLDO2_PU) | PMURES_BIT(RES4315_XTAL_PU) |
651 PMURES_BIT(RES4315_ALP_AVAIL) | PMURES_BIT(RES4315_RX_PWRSW_PU) |
652 PMURES_BIT(RES4315_TX_PWRSW_PU) | PMURES_BIT(RES4315_RFPLL_PWRSW_PU) |
653 PMURES_BIT(RES4315_LOGEN_PWRSW_PU) | PMURES_BIT(RES4315_AFE_PWRSW_PU) |
654 PMURES_BIT(RES4315_BBPLL_PWRSW_PU) | PMURES_BIT(RES4315_HT_AVAIL),
655 RES_DEPEND_REMOVE,
656 PMURES_BIT(RES4315_CBUCK_LPOM) | PMURES_BIT(RES4315_CBUCK_BURST) |
657 PMURES_BIT(RES4315_CBUCK_PWM),
658 si_pmu_res_depfltr_ncb
662 static const pmu_res_updown_t BCMATTACHDATA(bcm4329_res_updown)[] = {
663 { RES4329_XTAL_PU, 0x1501 },
664 { RES4329_PALDO_PU, 0x3501 }
667 static const pmu_res_depend_t BCMATTACHDATA(bcm4329_res_depend)[] = {
668 /* Make lnldo1 independant of CBUCK_PWM and CBUCK_BURST */
670 PMURES_BIT(RES4329_LNLDO1_PU),
671 RES_DEPEND_REMOVE,
672 PMURES_BIT(RES4329_CBUCK_PWM) | PMURES_BIT(RES4329_CBUCK_BURST),
673 NULL
676 PMURES_BIT(RES4329_CBUCK_BURST),
677 RES_DEPEND_ADD,
678 PMURES_BIT(RES4329_CBUCK_LPOM) | PMURES_BIT(RES4329_PALDO_PU),
679 NULL
682 PMURES_BIT(RES4329_BBPLL_PWRSW_PU),
683 RES_DEPEND_ADD,
684 PMURES_BIT(RES4329_RX_PWRSW_PU) | PMURES_BIT(RES4329_TX_PWRSW_PU) |
685 PMURES_BIT(RES4329_LOGEN_PWRSW_PU) | PMURES_BIT(RES4329_AFE_PWRSW_PU),
686 NULL
688 /* Adjust HT Avail resource dependencies */
690 PMURES_BIT(RES4329_HT_AVAIL),
691 RES_DEPEND_ADD,
692 PMURES_BIT(RES4329_PALDO_PU) |
693 PMURES_BIT(RES4329_RX_PWRSW_PU) | PMURES_BIT(RES4329_TX_PWRSW_PU) |
694 PMURES_BIT(RES4329_LOGEN_PWRSW_PU) | PMURES_BIT(RES4329_AFE_PWRSW_PU),
695 NULL
699 static const pmu_res_updown_t BCMATTACHDATA(bcm4319a0_res_updown_qt)[] = {
700 { RES4319_HT_AVAIL, 0x0101 },
701 { RES4319_XTAL_PU, 0x0100 },
702 { RES4319_LNLDO1_PU, 0x0100 },
703 { RES4319_PALDO_PU, 0x0100 },
704 { RES4319_CLDO_PU, 0x0100 },
705 { RES4319_CBUCK_PWM, 0x0100 },
706 { RES4319_CBUCK_BURST, 0x0100 },
707 { RES4319_CBUCK_LPOM, 0x0100 }
710 static const pmu_res_updown_t BCMATTACHDATA(bcm4319a0_res_updown)[] = {
711 { RES4319_XTAL_PU, 0x3f01 }
714 static const pmu_res_depend_t BCMATTACHDATA(bcm4319a0_res_depend)[] = {
715 /* Adjust OTP PU resource dependencies - not need PALDO unless write */
717 PMURES_BIT(RES4319_OTP_PU),
718 RES_DEPEND_REMOVE,
719 PMURES_BIT(RES4319_PALDO_PU),
720 si_pmu_res_depfltr_npaldo
722 /* Adjust HT Avail resource dependencies - bring up PALDO along if it is used. */
724 PMURES_BIT(RES4319_HT_AVAIL),
725 RES_DEPEND_ADD,
726 PMURES_BIT(RES4319_PALDO_PU),
727 si_pmu_res_depfltr_paldo
729 /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
731 PMURES_BIT(RES4319_HT_AVAIL),
732 RES_DEPEND_ADD,
733 PMURES_BIT(RES4319_RX_PWRSW_PU) | PMURES_BIT(RES4319_TX_PWRSW_PU) |
734 PMURES_BIT(RES4319_RFPLL_PWRSW_PU) |
735 PMURES_BIT(RES4319_LOGEN_PWRSW_PU) | PMURES_BIT(RES4319_AFE_PWRSW_PU),
736 NULL
740 static const pmu_res_updown_t BCMATTACHDATA(bcm4336a0_res_updown_qt)[] = {
741 { RES4336_HT_AVAIL, 0x0101 },
742 { RES4336_XTAL_PU, 0x0100 },
743 { RES4336_CLDO_PU, 0x0100 },
744 { RES4336_CBUCK_PWM, 0x0100 },
745 { RES4336_CBUCK_BURST, 0x0100 },
746 { RES4336_CBUCK_LPOM, 0x0100 }
749 static const pmu_res_updown_t BCMATTACHDATA(bcm4336a0_res_updown)[] = {
750 { RES4336_HT_AVAIL, 0x0D01}
753 static const pmu_res_depend_t BCMATTACHDATA(bcm4336a0_res_depend)[] = {
754 /* Just a dummy entry for now */
756 PMURES_BIT(RES4336_RSVD),
757 RES_DEPEND_ADD,
759 NULL
763 static const pmu_res_updown_t BCMATTACHDATA(bcm4330a0_res_updown_qt)[] = {
764 { RES4330_HT_AVAIL, 0x0101 },
765 { RES4330_XTAL_PU, 0x0100 },
766 { RES4330_CLDO_PU, 0x0100 },
767 { RES4330_CBUCK_PWM, 0x0100 },
768 { RES4330_CBUCK_BURST, 0x0100 },
769 { RES4330_CBUCK_LPOM, 0x0100 }
772 static const pmu_res_updown_t BCMATTACHDATA(bcm4330a0_res_updown)[] = {
773 { RES4330_HT_AVAIL, 0x0e02}
776 static const pmu_res_depend_t BCMATTACHDATA(bcm4330a0_res_depend)[] = {
777 /* Just a dummy entry for now */
779 PMURES_BIT(RES4330_HT_AVAIL),
780 RES_DEPEND_ADD,
782 NULL
786 /* TRUE if the power topology uses the buck boost to provide 3.3V to VDDIO_RF and WLAN PA */
787 static bool
788 BCMATTACHFN(si_pmu_res_depfltr_bb)(si_t *sih)
790 return (sih->boardflags & BFL_BUCKBOOST) != 0;
793 /* TRUE if the power topology doesn't use the cbuck. Key on chiprev also if the chip is BCM4325. */
794 static bool
795 BCMATTACHFN(si_pmu_res_depfltr_ncb)(si_t *sih)
797 if (CHIPID(sih->chip) == BCM4325_CHIP_ID)
798 return (CHIPREV(sih->chiprev) >= 2) && ((sih->boardflags & BFL_NOCBUCK) != 0);
799 return ((sih->boardflags & BFL_NOCBUCK) != 0);
802 /* TRUE if the power topology uses the PALDO */
803 static bool
804 BCMATTACHFN(si_pmu_res_depfltr_paldo)(si_t *sih)
806 return (sih->boardflags & BFL_PALDO) != 0;
809 /* TRUE if the power topology doesn't use the PALDO */
810 static bool
811 BCMATTACHFN(si_pmu_res_depfltr_npaldo)(si_t *sih)
813 return (sih->boardflags & BFL_PALDO) == 0;
816 #define BCM94325_BBVDDIOSD_BOARDS(sih) (sih->boardtype == BCM94325DEVBU_BOARD || \
817 sih->boardtype == BCM94325BGABU_BOARD)
819 /* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
820 static void
821 si_pmu_res_masks(si_t *sih, uint32 *pmin, uint32 *pmax)
823 uint32 min_mask = 0, max_mask = 0;
824 uint rsrcs;
825 char *val;
827 /* # resources */
828 rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
830 /* determine min/max rsrc masks */
831 switch (CHIPID(sih->chip)) {
832 case BCM4328_CHIP_ID:
833 /* Down to ILP request */
834 min_mask = PMURES_BIT(RES4328_EXT_SWITCHER_PWM) |
835 PMURES_BIT(RES4328_BB_SWITCHER_PWM) |
836 PMURES_BIT(RES4328_XTAL_EN);
837 /* Allow (but don't require) PLL to turn on */
838 max_mask = 0xfffff;
839 break;
840 case BCM5354_CHIP_ID:
841 /* Allow (but don't require) PLL to turn on */
842 max_mask = 0xfffff;
843 break;
844 case BCM4325_CHIP_ID:
845 ASSERT(CHIPREV(sih->chiprev) >= 2);
846 /* Minimum rsrcs to work in sleep mode */
847 if (!(sih->boardflags & BFL_NOCBUCK))
848 min_mask |= PMURES_BIT(RES4325B0_CBUCK_LPOM);
849 if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
850 CST4325_PMUTOP_2B_SHIFT) == 1)
851 min_mask |= PMURES_BIT(RES4325B0_CLDO_PU);
852 if (!si_is_otp_disabled(sih))
853 min_mask |= PMURES_BIT(RES4325_OTP_PU);
854 /* Leave buck boost on in burst mode for certain boards */
855 if ((sih->boardflags & BFL_BUCKBOOST) && (BCM94325_BBVDDIOSD_BOARDS(sih)))
856 min_mask |= PMURES_BIT(RES4325_BUCK_BOOST_BURST);
857 /* Allow all resources to be turned on upon requests */
858 max_mask = ~(~0 << rsrcs);
859 break;
860 case BCM4312_CHIP_ID:
861 /* default min_mask = 0x80000cbb is wrong */
862 min_mask = 0xcbb;
864 * max_mask = 0x7fff;
865 * pmu_res_updown_table_sz = 0;
866 * pmu_res_depend_table_sz = 0;
868 break;
869 case BCM4322_CHIP_ID:
870 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
871 case BCM4342_CHIP_ID:
872 if (CHIPREV(sih->chiprev) < 2) {
873 /* request ALP(can skip for A1) */
874 min_mask = PMURES_BIT(RES4322_RF_LDO) |
875 PMURES_BIT(RES4322_XTAL_PU) |
876 PMURES_BIT(RES4322_ALP_AVAIL);
877 if (BUSTYPE(sih->bustype) == SI_BUS) {
878 min_mask += PMURES_BIT(RES4322_SI_PLL_ON) |
879 PMURES_BIT(RES4322_HT_SI_AVAIL) |
880 PMURES_BIT(RES4322_PHY_PLL_ON) |
881 PMURES_BIT(RES4322_OTP_PU) |
882 PMURES_BIT(RES4322_HT_PHY_AVAIL);
883 max_mask = 0x1ff;
886 break;
887 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
888 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID:
889 case BCM43226_CHIP_ID: case BCM43420_CHIP_ID:
890 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
891 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
892 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
893 case BCM6362_CHIP_ID:
894 /* use chip default */
895 break;
897 case BCM4329_CHIP_ID:
899 /* Down to save the power. */
900 if (CHIPREV(sih->chiprev) >= 0x2) {
901 min_mask = PMURES_BIT(RES4329_CBUCK_LPOM) |
902 PMURES_BIT(RES4329_LNLDO1_PU) | PMURES_BIT(RES4329_CLDO_PU);
903 } else {
904 min_mask = PMURES_BIT(RES4329_CBUCK_LPOM) | PMURES_BIT(RES4329_CLDO_PU);
906 if (!si_is_otp_disabled(sih))
907 min_mask |= PMURES_BIT(RES4329_OTP_PU);
908 /* Allow (but don't require) PLL to turn on */
909 max_mask = 0x3ff63e;
911 break;
912 case BCM4315_CHIP_ID:
913 /* We only need a few resources to be kept on all the time */
914 if (!(sih->boardflags & BFL_NOCBUCK))
915 min_mask = PMURES_BIT(RES4315_CBUCK_LPOM);
916 min_mask |= PMURES_BIT(RES4315_CLDO_PU);
917 /* Allow everything else to be turned on upon requests */
918 max_mask = ~(~0 << rsrcs);
919 break;
920 case BCM4319_CHIP_ID:
921 #ifdef BCM_BOOTLOADER
922 /* Initialize to ResInitMode3 for bootloader */
923 min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
924 PMURES_BIT(RES4319_CBUCK_BURST) |
925 PMURES_BIT(RES4319_CBUCK_PWM) |
926 PMURES_BIT(RES4319_CLDO_PU) |
927 PMURES_BIT(RES4319_PALDO_PU) |
928 PMURES_BIT(RES4319_LNLDO1_PU) |
929 PMURES_BIT(RES4319_XTAL_PU) |
930 PMURES_BIT(RES4319_ALP_AVAIL) |
931 PMURES_BIT(RES4319_RFPLL_PWRSW_PU) |
932 PMURES_BIT(RES4319_BBPLL_PWRSW_PU) |
933 PMURES_BIT(RES4319_HT_AVAIL);
934 #else
935 /* We only need a few resources to be kept on all the time */
936 #ifdef BCMUSBDEV
937 /* For USB HT is always available, even durring IEEE PS, so RF switches are
938 * made independent of HT Avail and are by default on, but can be made off
939 * during IEEE PS by ucode (and then on)
941 min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
942 PMURES_BIT(RES4319_CLDO_PU) |
943 PMURES_BIT(RES4319_RX_PWRSW_PU) | PMURES_BIT(RES4319_TX_PWRSW_PU) |
944 PMURES_BIT(RES4319_LOGEN_PWRSW_PU) | PMURES_BIT(RES4319_AFE_PWRSW_PU);
945 #else
946 /* For SDIO RF switches are automatically made on off along with HT */
947 min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
948 PMURES_BIT(RES4319_CLDO_PU);
949 #endif
950 #endif /* BCM_BOOTLOADER */
952 /* Allow everything else to be turned on upon requests */
953 max_mask = ~(~0 << rsrcs);
954 break;
955 case BCM4336_CHIP_ID:
956 /* Down to save the power. */
957 min_mask = PMURES_BIT(RES4336_CBUCK_LPOM) | PMURES_BIT(RES4336_CLDO_PU) |
958 PMURES_BIT(RES4336_LDO3P3_PU) | PMURES_BIT(RES4336_OTP_PU) |
959 PMURES_BIT(RES4336_DIS_INT_RESET_PD);
960 /* Allow (but don't require) PLL to turn on */
961 max_mask = 0x1ffffff;
962 break;
964 case BCM4330_CHIP_ID:
965 /* Down to save the power. */
966 min_mask = PMURES_BIT(RES4330_CBUCK_LPOM) | PMURES_BIT(RES4330_CLDO_PU) |
967 PMURES_BIT(RES4330_DIS_INT_RESET_PD) | PMURES_BIT(RES4330_LDO3P3_PU) |
968 PMURES_BIT(RES4330_OTP_PU);
969 /* Allow (but don't require) PLL to turn on */
970 max_mask = 0xfffffff;
971 break;
973 case BCM4313_CHIP_ID:
974 min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) |
975 PMURES_BIT(RES4313_XTAL_PU_RSRC) |
976 PMURES_BIT(RES4313_ALP_AVAIL_RSRC) |
977 PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC);
978 max_mask = 0xffff;
979 break;
980 default:
981 break;
984 /* Apply nvram override to min mask */
985 if ((val = getvar(NULL, "rmin")) != NULL) {
986 PMU_MSG(("Applying rmin=%s to min_mask\n", val));
987 min_mask = (uint32)bcm_strtoul(val, NULL, 0);
989 /* Apply nvram override to max mask */
990 if ((val = getvar(NULL, "rmax")) != NULL) {
991 PMU_MSG(("Applying rmax=%s to max_mask\n", val));
992 max_mask = (uint32)bcm_strtoul(val, NULL, 0);
995 *pmin = min_mask;
996 *pmax = max_mask;
998 #endif /* !_CFE_ || CFG_WL */
1000 /* initialize PMU resources */
1001 void
1002 BCMATTACHFN(si_pmu_res_init)(si_t *sih, osl_t *osh)
1004 #if !defined(_CFE_) || defined(CFG_WL)
1005 chipcregs_t *cc;
1006 uint origidx;
1007 const pmu_res_updown_t *pmu_res_updown_table = NULL;
1008 uint pmu_res_updown_table_sz = 0;
1009 const pmu_res_depend_t *pmu_res_depend_table = NULL;
1010 uint pmu_res_depend_table_sz = 0;
1011 uint32 min_mask = 0, max_mask = 0;
1012 char name[8], *val;
1013 uint i, rsrcs;
1015 ASSERT(sih->cccaps & CC_CAP_PMU);
1017 /* Remember original core before switch to chipc */
1018 origidx = si_coreidx(sih);
1019 cc = si_setcoreidx(sih, SI_CC_IDX);
1020 ASSERT(cc != NULL);
1022 switch (CHIPID(sih->chip)) {
1023 case BCM4328_CHIP_ID:
1024 pmu_res_updown_table = bcm4328a0_res_updown;
1025 pmu_res_updown_table_sz = ARRAYSIZE(bcm4328a0_res_updown);
1026 pmu_res_depend_table = bcm4328a0_res_depend;
1027 pmu_res_depend_table_sz = ARRAYSIZE(bcm4328a0_res_depend);
1028 break;
1029 case BCM4325_CHIP_ID:
1030 /* Optimize resources up/down timers */
1031 if (ISSIM_ENAB(sih)) {
1032 pmu_res_updown_table = bcm4325a0_res_updown_qt;
1033 pmu_res_updown_table_sz = ARRAYSIZE(bcm4325a0_res_updown_qt);
1034 } else {
1035 pmu_res_updown_table = bcm4325a0_res_updown;
1036 pmu_res_updown_table_sz = ARRAYSIZE(bcm4325a0_res_updown);
1038 /* Optimize resources dependancies */
1039 pmu_res_depend_table = bcm4325a0_res_depend;
1040 pmu_res_depend_table_sz = ARRAYSIZE(bcm4325a0_res_depend);
1041 break;
1042 case BCM4315_CHIP_ID:
1043 /* Optimize resources up/down timers */
1044 if (ISSIM_ENAB(sih)) {
1045 pmu_res_updown_table = bcm4315a0_res_updown_qt;
1046 pmu_res_updown_table_sz = ARRAYSIZE(bcm4315a0_res_updown_qt);
1048 else {
1049 pmu_res_updown_table = bcm4315a0_res_updown;
1050 pmu_res_updown_table_sz = ARRAYSIZE(bcm4315a0_res_updown);
1052 /* Optimize resources dependancies masks */
1053 pmu_res_depend_table = bcm4315a0_res_depend;
1054 pmu_res_depend_table_sz = ARRAYSIZE(bcm4315a0_res_depend);
1055 break;
1056 case BCM4329_CHIP_ID:
1057 /* Optimize resources up/down timers */
1058 if (ISSIM_ENAB(sih)) {
1059 pmu_res_updown_table = NULL;
1060 pmu_res_updown_table_sz = 0;
1061 } else {
1062 pmu_res_updown_table = bcm4329_res_updown;
1063 pmu_res_updown_table_sz = ARRAYSIZE(bcm4329_res_updown);
1065 /* Optimize resources dependencies */
1066 pmu_res_depend_table = bcm4329_res_depend;
1067 pmu_res_depend_table_sz = ARRAYSIZE(bcm4329_res_depend);
1068 break;
1070 case BCM4319_CHIP_ID:
1071 /* Optimize resources up/down timers */
1072 if (ISSIM_ENAB(sih)) {
1073 pmu_res_updown_table = bcm4319a0_res_updown_qt;
1074 pmu_res_updown_table_sz = ARRAYSIZE(bcm4319a0_res_updown_qt);
1076 else {
1077 pmu_res_updown_table = bcm4319a0_res_updown;
1078 pmu_res_updown_table_sz = ARRAYSIZE(bcm4319a0_res_updown);
1080 /* Optimize resources dependancies masks */
1081 pmu_res_depend_table = bcm4319a0_res_depend;
1082 pmu_res_depend_table_sz = ARRAYSIZE(bcm4319a0_res_depend);
1083 break;
1085 case BCM4336_CHIP_ID:
1086 /* Optimize resources up/down timers */
1087 if (ISSIM_ENAB(sih)) {
1088 pmu_res_updown_table = bcm4336a0_res_updown_qt;
1089 pmu_res_updown_table_sz = ARRAYSIZE(bcm4336a0_res_updown_qt);
1091 else {
1092 pmu_res_updown_table = bcm4336a0_res_updown;
1093 pmu_res_updown_table_sz = ARRAYSIZE(bcm4336a0_res_updown);
1095 /* Optimize resources dependancies masks */
1096 pmu_res_depend_table = bcm4336a0_res_depend;
1097 pmu_res_depend_table_sz = ARRAYSIZE(bcm4336a0_res_depend);
1098 break;
1100 case BCM4330_CHIP_ID:
1101 /* Optimize resources up/down timers */
1102 if (ISSIM_ENAB(sih)) {
1103 pmu_res_updown_table = bcm4330a0_res_updown_qt;
1104 pmu_res_updown_table_sz = ARRAYSIZE(bcm4330a0_res_updown_qt);
1106 else {
1107 pmu_res_updown_table = bcm4330a0_res_updown;
1108 pmu_res_updown_table_sz = ARRAYSIZE(bcm4330a0_res_updown);
1110 /* Optimize resources dependancies masks */
1111 pmu_res_depend_table = bcm4330a0_res_depend;
1112 pmu_res_depend_table_sz = ARRAYSIZE(bcm4330a0_res_depend);
1113 break;
1114 default:
1115 break;
1118 /* # resources */
1119 rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
1121 /* Program up/down timers */
1122 while (pmu_res_updown_table_sz--) {
1123 ASSERT(pmu_res_updown_table != NULL);
1124 PMU_MSG(("Changing rsrc %d res_updn_timer to 0x%x\n",
1125 pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
1126 pmu_res_updown_table[pmu_res_updown_table_sz].updown));
1127 W_REG(osh, &cc->res_table_sel,
1128 pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
1129 W_REG(osh, &cc->res_updn_timer,
1130 pmu_res_updown_table[pmu_res_updown_table_sz].updown);
1132 /* Apply nvram overrides to up/down timers */
1133 for (i = 0; i < rsrcs; i ++) {
1134 snprintf(name, sizeof(name), "r%dt", i);
1135 if ((val = getvar(NULL, name)) == NULL)
1136 continue;
1137 PMU_MSG(("Applying %s=%s to rsrc %d res_updn_timer\n", name, val, i));
1138 W_REG(osh, &cc->res_table_sel, (uint32)i);
1139 W_REG(osh, &cc->res_updn_timer, (uint32)bcm_strtoul(val, NULL, 0));
1142 /* Program resource dependencies table */
1143 while (pmu_res_depend_table_sz--) {
1144 ASSERT(pmu_res_depend_table != NULL);
1145 if (pmu_res_depend_table[pmu_res_depend_table_sz].filter != NULL &&
1146 !(pmu_res_depend_table[pmu_res_depend_table_sz].filter)(sih))
1147 continue;
1148 for (i = 0; i < rsrcs; i ++) {
1149 if ((pmu_res_depend_table[pmu_res_depend_table_sz].res_mask &
1150 PMURES_BIT(i)) == 0)
1151 continue;
1152 W_REG(osh, &cc->res_table_sel, i);
1153 switch (pmu_res_depend_table[pmu_res_depend_table_sz].action) {
1154 case RES_DEPEND_SET:
1155 PMU_MSG(("Changing rsrc %d res_dep_mask to 0x%x\n", i,
1156 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask));
1157 W_REG(osh, &cc->res_dep_mask,
1158 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
1159 break;
1160 case RES_DEPEND_ADD:
1161 PMU_MSG(("Adding 0x%x to rsrc %d res_dep_mask\n",
1162 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
1163 OR_REG(osh, &cc->res_dep_mask,
1164 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
1165 break;
1166 case RES_DEPEND_REMOVE:
1167 PMU_MSG(("Removing 0x%x from rsrc %d res_dep_mask\n",
1168 pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
1169 AND_REG(osh, &cc->res_dep_mask,
1170 ~pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
1171 break;
1172 default:
1173 ASSERT(0);
1174 break;
1178 /* Apply nvram overrides to dependancies masks */
1179 for (i = 0; i < rsrcs; i ++) {
1180 snprintf(name, sizeof(name), "r%dd", i);
1181 if ((val = getvar(NULL, name)) == NULL)
1182 continue;
1183 PMU_MSG(("Applying %s=%s to rsrc %d res_dep_mask\n", name, val, i));
1184 W_REG(osh, &cc->res_table_sel, (uint32)i);
1185 W_REG(osh, &cc->res_dep_mask, (uint32)bcm_strtoul(val, NULL, 0));
1188 /* Determine min/max rsrc masks */
1189 si_pmu_res_masks(sih, &min_mask, &max_mask);
1191 /* It is required to program max_mask first and then min_mask */
1192 #ifdef BCM_BOOTLOADER
1193 if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
1194 min_mask |= R_REG(osh, &cc->min_res_mask);
1195 max_mask |= R_REG(osh, &cc->max_res_mask);
1197 #endif /* BCM_BOOTLOADER */
1199 /* Program max resource mask */
1200 #ifdef BCM_BOOTLOADER
1201 /* Apply nvram override to max mask */
1202 if ((val = getvar(NULL, "brmax")) != NULL) {
1203 PMU_MSG(("Applying brmax=%s to max_res_mask\n", val));
1204 max_mask = (uint32)bcm_strtoul(val, NULL, 0);
1206 #endif /* BCM_BOOTLOADER */
1208 if (max_mask) {
1209 PMU_MSG(("Changing max_res_mask to 0x%x\n", max_mask));
1210 W_REG(osh, &cc->max_res_mask, max_mask);
1213 /* Program min resource mask */
1214 #ifdef BCM_BOOTLOADER
1215 /* Apply nvram override to min mask */
1216 if ((val = getvar(NULL, "brmin")) != NULL) {
1217 PMU_MSG(("Applying brmin=%s to min_res_mask\n", val));
1218 min_mask = (uint32)bcm_strtoul(val, NULL, 0);
1220 #endif /* BCM_BOOTLOADER */
1222 if (min_mask) {
1223 PMU_MSG(("Changing min_res_mask to 0x%x\n", min_mask));
1224 W_REG(osh, &cc->min_res_mask, min_mask);
1227 /* Add some delay; allow resources to come up and settle. */
1228 OSL_DELAY(2000);
1230 /* Return to original core */
1231 si_setcoreidx(sih, origidx);
1233 #endif /* !_CFE_ || CFG_WL */
1235 /* WAR for 4319 swctrl tri-state issue */
1236 void
1237 si_pmu_res_4319_swctrl_war(si_t *sih, osl_t *osh, bool enable)
1239 uint32 min_mask;
1240 chipcregs_t *cc;
1241 uint origidx;
1242 ASSERT(sih->cccaps & CC_CAP_PMU);
1244 /* Remember original core before switch to chipc */
1245 origidx = si_coreidx(sih);
1246 cc = si_setcoreidx(sih, SI_CC_IDX);
1247 ASSERT(cc != NULL);
1248 min_mask = R_REG(osh, &cc->min_res_mask);
1249 if (enable)
1250 W_REG(osh, &cc->min_res_mask,
1251 min_mask | PMURES_BIT(RES4319_PALDO_PU));
1252 else
1253 W_REG(osh, &cc->min_res_mask,
1254 min_mask & ~PMURES_BIT(RES4319_PALDO_PU));
1256 /* Return to original core */
1257 si_setcoreidx(sih, origidx);
1260 /* setup pll and query clock speed */
1261 typedef struct {
1262 uint16 freq;
1263 uint8 xf;
1264 uint8 wbint;
1265 uint32 wbfrac;
1266 } pmu0_xtaltab0_t;
1268 /* the following table is based on 880Mhz fvco */
1269 static const pmu0_xtaltab0_t BCMINITDATA(pmu0_xtaltab0)[] = {
1270 { 12000, 1, 73, 349525 },
1271 { 13000, 2, 67, 725937 },
1272 { 14400, 3, 61, 116508 },
1273 { 15360, 4, 57, 305834 },
1274 { 16200, 5, 54, 336579 },
1275 { 16800, 6, 52, 399457 },
1276 { 19200, 7, 45, 873813 },
1277 { 19800, 8, 44, 466033 },
1278 { 20000, 9, 44, 0 },
1279 { 25000, 10, 70, 419430 },
1280 { 26000, 11, 67, 725937 },
1281 { 30000, 12, 58, 699050 },
1282 { 38400, 13, 45, 873813 },
1283 { 40000, 14, 45, 0 },
1284 { 0, 0, 0, 0 }
1287 #ifdef BCMUSBDEV
1288 #define PMU0_XTAL0_DEFAULT 11
1289 #else
1290 #define PMU0_XTAL0_DEFAULT 8
1291 #endif
1293 #ifdef BCMUSBDEV
1295 * Set new backplane PLL clock frequency
1297 static void
1298 BCMATTACHFN(si_pmu0_sbclk4328)(si_t *sih, int freq)
1300 uint32 tmp, oldmax, oldmin, origidx;
1301 chipcregs_t *cc;
1303 /* Remember original core before switch to chipc */
1304 origidx = si_coreidx(sih);
1305 cc = si_setcoreidx(sih, SI_CC_IDX);
1306 ASSERT(cc);
1308 /* Set new backplane PLL clock */
1309 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
1310 tmp = R_REG(osh, &cc->pllcontrol_data);
1311 tmp &= ~(PMU0_PLL0_PC0_DIV_ARM_MASK);
1312 tmp |= freq << PMU0_PLL0_PC0_DIV_ARM_SHIFT;
1313 W_REG(osh, &cc->pllcontrol_data, tmp);
1315 /* Power cycle BB_PLL_PU by disabling/enabling it to take on new freq */
1316 /* Disable PLL */
1317 oldmin = R_REG(osh, &cc->min_res_mask);
1318 oldmax = R_REG(osh, &cc->max_res_mask);
1319 W_REG(osh, &cc->min_res_mask, oldmin & ~PMURES_BIT(RES4328_BB_PLL_PU));
1320 W_REG(osh, &cc->max_res_mask, oldmax & ~PMURES_BIT(RES4328_BB_PLL_PU));
1322 /* It takes over several hundred usec to re-enable the PLL since the
1323 * sequencer state machines run on ILP clock. Set delay at 450us to be safe.
1325 * Be sure PLL is powered down first before re-enabling it.
1328 OSL_DELAY(PLL_DELAY);
1329 SPINWAIT((R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)), PLL_DELAY*3);
1330 if (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)) {
1331 /* If BB_PLL not powered down yet, new backplane PLL clock
1332 * may not take effect.
1334 * Still early during bootup so no serial output here.
1336 PMU_ERROR(("Fatal: BB_PLL not power down yet!\n"));
1337 ASSERT(!(R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)));
1340 /* Enable PLL */
1341 W_REG(osh, &cc->max_res_mask, oldmax);
1343 /* Return to original core */
1344 si_setcoreidx(sih, origidx);
1346 #endif /* BCMUSBDEV */
1348 /* Set up PLL registers in the PMU as per the crystal speed.
1349 * Uses xtalfreq variable, or passed-in default.
1351 static void
1352 BCMATTACHFN(si_pmu0_pllinit0)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal)
1354 uint32 tmp;
1355 const pmu0_xtaltab0_t *xt;
1357 /* Find the frequency in the table */
1358 for (xt = pmu0_xtaltab0; xt->freq; xt ++)
1359 if (xt->freq == xtal)
1360 break;
1361 if (xt->freq == 0)
1362 xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
1364 PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
1366 /* Check current PLL state */
1367 tmp = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1368 PCTL_XTALFREQ_SHIFT;
1369 if (tmp == xt->xf) {
1370 PMU_MSG(("PLL already programmed for %d.%d MHz\n",
1371 xt->freq / 1000, xt->freq % 1000));
1372 #ifdef BCMUSBDEV
1373 if (CHIPID(sih->chip) == BCM4328_CHIP_ID)
1374 si_pmu0_sbclk4328(sih, PMU0_PLL0_PC0_DIV_ARM_88MHZ);
1375 #endif /* BCMUSBDEV */
1376 return;
1379 if (tmp) {
1380 PMU_MSG(("Reprogramming PLL for %d.%d MHz (was %d.%dMHz)\n",
1381 xt->freq / 1000, xt->freq % 1000,
1382 pmu0_xtaltab0[tmp-1].freq / 1000, pmu0_xtaltab0[tmp-1].freq % 1000));
1383 } else {
1384 PMU_MSG(("Programming PLL for %d.%d MHz\n",
1385 xt->freq / 1000, xt->freq % 1000));
1388 /* Make sure the PLL is off */
1389 switch (CHIPID(sih->chip)) {
1390 case BCM4328_CHIP_ID:
1391 AND_REG(osh, &cc->min_res_mask, ~PMURES_BIT(RES4328_BB_PLL_PU));
1392 AND_REG(osh, &cc->max_res_mask, ~PMURES_BIT(RES4328_BB_PLL_PU));
1393 break;
1394 case BCM5354_CHIP_ID:
1395 AND_REG(osh, &cc->min_res_mask, ~PMURES_BIT(RES5354_BB_PLL_PU));
1396 AND_REG(osh, &cc->max_res_mask, ~PMURES_BIT(RES5354_BB_PLL_PU));
1397 break;
1398 default:
1399 ASSERT(0);
1401 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS0_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1402 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS0_HTAVAIL));
1404 PMU_MSG(("Done masking\n"));
1406 /* Write PDIV in pllcontrol[0] */
1407 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
1408 tmp = R_REG(osh, &cc->pllcontrol_data);
1409 if (xt->freq >= PMU0_PLL0_PC0_PDIV_FREQ)
1410 tmp |= PMU0_PLL0_PC0_PDIV_MASK;
1411 else
1412 tmp &= ~PMU0_PLL0_PC0_PDIV_MASK;
1413 W_REG(osh, &cc->pllcontrol_data, tmp);
1415 /* Write WILD in pllcontrol[1] */
1416 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
1417 tmp = R_REG(osh, &cc->pllcontrol_data);
1418 tmp = ((tmp & ~(PMU0_PLL0_PC1_WILD_INT_MASK | PMU0_PLL0_PC1_WILD_FRAC_MASK)) |
1419 (((xt->wbint << PMU0_PLL0_PC1_WILD_INT_SHIFT) &
1420 PMU0_PLL0_PC1_WILD_INT_MASK) |
1421 ((xt->wbfrac << PMU0_PLL0_PC1_WILD_FRAC_SHIFT) &
1422 PMU0_PLL0_PC1_WILD_FRAC_MASK)));
1423 if (xt->wbfrac == 0)
1424 tmp |= PMU0_PLL0_PC1_STOP_MOD;
1425 else
1426 tmp &= ~PMU0_PLL0_PC1_STOP_MOD;
1427 W_REG(osh, &cc->pllcontrol_data, tmp);
1429 /* Write WILD in pllcontrol[2] */
1430 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
1431 tmp = R_REG(osh, &cc->pllcontrol_data);
1432 tmp = ((tmp & ~PMU0_PLL0_PC2_WILD_INT_MASK) |
1433 ((xt->wbint >> PMU0_PLL0_PC2_WILD_INT_SHIFT) &
1434 PMU0_PLL0_PC2_WILD_INT_MASK));
1435 W_REG(osh, &cc->pllcontrol_data, tmp);
1437 PMU_MSG(("Done pll\n"));
1439 /* Write XtalFreq. Set the divisor also. */
1440 tmp = R_REG(osh, &cc->pmucontrol);
1441 tmp = ((tmp & ~PCTL_ILP_DIV_MASK) |
1442 (((((xt->freq + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) & PCTL_ILP_DIV_MASK));
1443 tmp = ((tmp & ~PCTL_XTALFREQ_MASK) |
1444 ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK));
1445 W_REG(osh, &cc->pmucontrol, tmp);
1448 /* query alp/xtal clock frequency */
1449 static uint32
1450 BCMINITFN(si_pmu0_alpclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1452 const pmu0_xtaltab0_t *xt;
1453 uint32 xf;
1455 /* Find the frequency in the table */
1456 xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1457 PCTL_XTALFREQ_SHIFT;
1458 for (xt = pmu0_xtaltab0; xt->freq; xt++)
1459 if (xt->xf == xf)
1460 break;
1461 /* PLL must be configured before */
1462 ASSERT(xt->freq);
1464 return xt->freq * 1000;
1467 #if !defined(_CFE_) || defined(CFG_WL)
1468 /* query CPU clock frequency */
1469 static uint32
1470 BCMINITFN(si_pmu0_cpuclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1472 uint32 tmp, divarm;
1473 #ifdef BCMDBG
1474 uint32 pdiv, wbint, wbfrac, fvco;
1475 uint32 freq;
1476 #endif
1477 uint32 FVCO = FVCO_880;
1479 /* Read divarm from pllcontrol[0] */
1480 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
1481 tmp = R_REG(osh, &cc->pllcontrol_data);
1482 divarm = (tmp & PMU0_PLL0_PC0_DIV_ARM_MASK) >> PMU0_PLL0_PC0_DIV_ARM_SHIFT;
1484 #ifdef BCMDBG
1485 /* Calculate fvco based on xtal freq, pdiv, and wild */
1486 pdiv = tmp & PMU0_PLL0_PC0_PDIV_MASK;
1488 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
1489 tmp = R_REG(osh, &cc->pllcontrol_data);
1490 wbfrac = (tmp & PMU0_PLL0_PC1_WILD_FRAC_MASK) >> PMU0_PLL0_PC1_WILD_FRAC_SHIFT;
1491 wbint = (tmp & PMU0_PLL0_PC1_WILD_INT_MASK) >> PMU0_PLL0_PC1_WILD_INT_SHIFT;
1493 W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
1494 tmp = R_REG(osh, &cc->pllcontrol_data);
1495 wbint += (tmp & PMU0_PLL0_PC2_WILD_INT_MASK) << PMU0_PLL0_PC2_WILD_INT_SHIFT;
1497 freq = si_pmu0_alpclk0(sih, osh, cc) / 1000;
1499 fvco = (freq * wbint) << 8;
1500 fvco += (freq * (wbfrac >> 10)) >> 2;
1501 fvco += (freq * (wbfrac & 0x3ff)) >> 10;
1502 fvco >>= 8;
1503 fvco >>= pdiv;
1504 fvco /= 1000;
1505 fvco *= 1000;
1507 PMU_MSG(("si_pmu0_cpuclk0: wbint %u wbfrac %u fvco %u\n",
1508 wbint, wbfrac, fvco));
1510 FVCO = fvco;
1511 #endif /* BCMDBG */
1513 /* Return ARM/SB clock */
1514 return FVCO / (divarm + PMU0_PLL0_PC0_DIV_ARM_BASE) * 1000;
1517 uint
1518 si_pll_minresmask_reset(si_t *sih, osl_t *osh)
1520 chipcregs_t *cc;
1521 uint origidx;
1522 uint err = BCME_OK;
1523 /* Remember original core before switch to chipc */
1524 origidx = si_coreidx(sih);
1525 cc = si_setcoreidx(sih, SI_CC_IDX);
1526 ASSERT(cc != NULL);
1528 switch (CHIPID(sih->chip)) {
1529 case BCM4313_CHIP_ID:
1530 /* write to min_res_mask 0x200d : clear min_rsrc_mask */
1531 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1532 OSL_DELAY(100);
1533 /* write to max_res_mask 0xBFFF: clear max_rsrc_mask */
1534 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1535 OSL_DELAY(100);
1536 /* write to max_res_mask 0xFFFF :set max_rsrc_mask */
1537 OR_REG(osh, &cc->max_res_mask, (PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1539 break;
1540 default:
1541 PMU_ERROR(("%s: PLL reset not supported\n", __FUNCTION__));
1542 err = BCME_UNSUPPORTED;
1543 break;
1545 /* Return to original core */
1546 si_setcoreidx(sih, origidx);
1547 return err;
1550 /* setup pll and query clock speed */
1551 typedef struct {
1552 uint16 fref;
1553 uint8 xf;
1554 uint8 p1div;
1555 uint8 p2div;
1556 uint8 ndiv_int;
1557 uint32 ndiv_frac;
1558 } pmu1_xtaltab0_t;
1560 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880_4329)[] = {
1561 {12000, 1, 3, 22, 0x9, 0xFFFFEF},
1562 {13000, 2, 1, 6, 0xb, 0x483483},
1563 {14400, 3, 1, 10, 0xa, 0x1C71C7},
1564 {15360, 4, 1, 5, 0xb, 0x755555},
1565 {16200, 5, 1, 10, 0x5, 0x6E9E06},
1566 {16800, 6, 1, 10, 0x5, 0x3Cf3Cf},
1567 {19200, 7, 1, 4, 0xb, 0x755555},
1568 {19800, 8, 1, 11, 0x4, 0xA57EB},
1569 {20000, 9, 1, 11, 0x4, 0x0},
1570 {24000, 10, 3, 11, 0xa, 0x0},
1571 {25000, 11, 5, 16, 0xb, 0x0},
1572 {26000, 12, 1, 1, 0x21, 0xD89D89},
1573 {30000, 13, 3, 8, 0xb, 0x0},
1574 {37400, 14, 3, 1, 0x46, 0x969696},
1575 {38400, 15, 1, 1, 0x16, 0xEAAAAA},
1576 {40000, 16, 1, 2, 0xb, 0},
1577 {0, 0, 0, 0, 0, 0}
1580 /* the following table is based on 880Mhz fvco */
1581 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880)[] = {
1582 {12000, 1, 3, 22, 0x9, 0xFFFFEF},
1583 {13000, 2, 1, 6, 0xb, 0x483483},
1584 {14400, 3, 1, 10, 0xa, 0x1C71C7},
1585 {15360, 4, 1, 5, 0xb, 0x755555},
1586 {16200, 5, 1, 10, 0x5, 0x6E9E06},
1587 {16800, 6, 1, 10, 0x5, 0x3Cf3Cf},
1588 {19200, 7, 1, 4, 0xb, 0x755555},
1589 {19800, 8, 1, 11, 0x4, 0xA57EB},
1590 {20000, 9, 1, 11, 0x4, 0x0},
1591 {24000, 10, 3, 11, 0xa, 0x0},
1592 {25000, 11, 5, 16, 0xb, 0x0},
1593 {26000, 12, 1, 2, 0x10, 0xEC4EC4},
1594 {30000, 13, 3, 8, 0xb, 0x0},
1595 {33600, 14, 1, 2, 0xd, 0x186186},
1596 {38400, 15, 1, 2, 0xb, 0x755555},
1597 {40000, 16, 1, 2, 0xb, 0},
1598 {0, 0, 0, 0, 0, 0}
1601 #define PMU1_XTALTAB0_880_12000K 0
1602 #define PMU1_XTALTAB0_880_13000K 1
1603 #define PMU1_XTALTAB0_880_14400K 2
1604 #define PMU1_XTALTAB0_880_15360K 3
1605 #define PMU1_XTALTAB0_880_16200K 4
1606 #define PMU1_XTALTAB0_880_16800K 5
1607 #define PMU1_XTALTAB0_880_19200K 6
1608 #define PMU1_XTALTAB0_880_19800K 7
1609 #define PMU1_XTALTAB0_880_20000K 8
1610 #define PMU1_XTALTAB0_880_24000K 9
1611 #define PMU1_XTALTAB0_880_25000K 10
1612 #define PMU1_XTALTAB0_880_26000K 11
1613 #define PMU1_XTALTAB0_880_30000K 12
1614 #define PMU1_XTALTAB0_880_37400K 13
1615 #define PMU1_XTALTAB0_880_38400K 14
1616 #define PMU1_XTALTAB0_880_40000K 15
1618 /* the following table is based on 1760Mhz fvco */
1619 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1760)[] = {
1620 {12000, 1, 3, 44, 0x9, 0xFFFFEF},
1621 {13000, 2, 1, 12, 0xb, 0x483483},
1622 {14400, 3, 1, 20, 0xa, 0x1C71C7},
1623 {15360, 4, 1, 10, 0xb, 0x755555},
1624 {16200, 5, 1, 20, 0x5, 0x6E9E06},
1625 {16800, 6, 1, 20, 0x5, 0x3Cf3Cf},
1626 {19200, 7, 1, 18, 0x5, 0x17B425},
1627 {19800, 8, 1, 22, 0x4, 0xA57EB},
1628 {20000, 9, 1, 22, 0x4, 0x0},
1629 {24000, 10, 3, 22, 0xa, 0x0},
1630 {25000, 11, 5, 32, 0xb, 0x0},
1631 {26000, 12, 1, 4, 0x10, 0xEC4EC4},
1632 {30000, 13, 3, 16, 0xb, 0x0},
1633 {38400, 14, 1, 10, 0x4, 0x955555},
1634 {40000, 15, 1, 4, 0xb, 0},
1635 {0, 0, 0, 0, 0, 0}
1638 /* table index */
1639 #define PMU1_XTALTAB0_1760_12000K 0
1640 #define PMU1_XTALTAB0_1760_13000K 1
1641 #define PMU1_XTALTAB0_1760_14400K 2
1642 #define PMU1_XTALTAB0_1760_15360K 3
1643 #define PMU1_XTALTAB0_1760_16200K 4
1644 #define PMU1_XTALTAB0_1760_16800K 5
1645 #define PMU1_XTALTAB0_1760_19200K 6
1646 #define PMU1_XTALTAB0_1760_19800K 7
1647 #define PMU1_XTALTAB0_1760_20000K 8
1648 #define PMU1_XTALTAB0_1760_24000K 9
1649 #define PMU1_XTALTAB0_1760_25000K 10
1650 #define PMU1_XTALTAB0_1760_26000K 11
1651 #define PMU1_XTALTAB0_1760_30000K 12
1652 #define PMU1_XTALTAB0_1760_38400K 13
1653 #define PMU1_XTALTAB0_1760_40000K 14
1655 /* the following table is based on 1440Mhz fvco */
1656 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1440)[] = {
1657 {12000, 1, 1, 1, 0x78, 0x0 },
1658 {13000, 2, 1, 1, 0x6E, 0xC4EC4E},
1659 {14400, 3, 1, 1, 0x64, 0x0 },
1660 {15360, 4, 1, 1, 0x5D, 0xC00000},
1661 {16200, 5, 1, 1, 0x58, 0xE38E38},
1662 {16800, 6, 1, 1, 0x55, 0xB6DB6D},
1663 {19200, 7, 1, 1, 0x4B, 0 },
1664 {19800, 8, 1, 1, 0x48, 0xBA2E8B},
1665 {20000, 9, 1, 1, 0x48, 0x0 },
1666 {25000, 10, 1, 1, 0x39, 0x999999},
1667 {26000, 11, 1, 1, 0x37, 0x627627},
1668 {30000, 12, 1, 1, 0x30, 0x0 },
1669 {37400, 13, 2, 1, 0x4D, 0x15E76 },
1670 {38400, 13, 2, 1, 0x4B, 0x0 },
1671 {40000, 14, 2, 1, 0x48, 0x0 },
1672 {48000, 15, 2, 1, 0x3c, 0x0 },
1673 {0, 0, 0, 0, 0, 0}
1676 /* table index */
1677 #define PMU1_XTALTAB0_1440_12000K 0
1678 #define PMU1_XTALTAB0_1440_13000K 1
1679 #define PMU1_XTALTAB0_1440_14400K 2
1680 #define PMU1_XTALTAB0_1440_15360K 3
1681 #define PMU1_XTALTAB0_1440_16200K 4
1682 #define PMU1_XTALTAB0_1440_16800K 5
1683 #define PMU1_XTALTAB0_1440_19200K 6
1684 #define PMU1_XTALTAB0_1440_19800K 7
1685 #define PMU1_XTALTAB0_1440_20000K 8
1686 #define PMU1_XTALTAB0_1440_25000K 9
1687 #define PMU1_XTALTAB0_1440_26000K 10
1688 #define PMU1_XTALTAB0_1440_30000K 11
1689 #define PMU1_XTALTAB0_1440_37400K 12
1690 #define PMU1_XTALTAB0_1440_38400K 13
1691 #define PMU1_XTALTAB0_1440_40000K 14
1692 #define PMU1_XTALTAB0_1440_48000K 15
1694 #define XTAL_FREQ_24000MHZ 24000
1695 #define XTAL_FREQ_30000MHZ 30000
1696 #define XTAL_FREQ_37400MHZ 37400
1697 #define XTAL_FREQ_48000MHZ 48000
1699 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_960)[] = {
1700 {12000, 1, 1, 1, 0x50, 0x0 },
1701 {13000, 2, 1, 1, 0x49, 0xD89D89},
1702 {14400, 3, 1, 1, 0x42, 0xAAAAAA},
1703 {15360, 4, 1, 1, 0x3E, 0x800000},
1704 {16200, 5, 1, 1, 0x39, 0x425ED0},
1705 {16800, 6, 1, 1, 0x39, 0x249249},
1706 {19200, 7, 1, 1, 0x32, 0x0 },
1707 {19800, 8, 1, 1, 0x30, 0x7C1F07},
1708 {20000, 9, 1, 1, 0x30, 0x0 },
1709 {25000, 10, 1, 1, 0x26, 0x666666},
1710 {26000, 11, 1, 1, 0x24, 0xEC4EC4},
1711 {30000, 12, 1, 1, 0x20, 0x0 },
1712 {37400, 13, 2, 1, 0x33, 0x563EF9},
1713 {38400, 14, 2, 1, 0x32, 0x0 },
1714 {40000, 15, 2, 1, 0x30, 0x0 },
1715 {48000, 16, 2, 1, 0x28, 0x0 },
1716 {0, 0, 0, 0, 0, 0 }
1719 /* table index */
1720 #define PMU1_XTALTAB0_960_12000K 0
1721 #define PMU1_XTALTAB0_960_13000K 1
1722 #define PMU1_XTALTAB0_960_14400K 2
1723 #define PMU1_XTALTAB0_960_15360K 3
1724 #define PMU1_XTALTAB0_960_16200K 4
1725 #define PMU1_XTALTAB0_960_16800K 5
1726 #define PMU1_XTALTAB0_960_19200K 6
1727 #define PMU1_XTALTAB0_960_19800K 7
1728 #define PMU1_XTALTAB0_960_20000K 8
1729 #define PMU1_XTALTAB0_960_25000K 9
1730 #define PMU1_XTALTAB0_960_26000K 10
1731 #define PMU1_XTALTAB0_960_30000K 11
1732 #define PMU1_XTALTAB0_960_37400K 12
1733 #define PMU1_XTALTAB0_960_38400K 13
1734 #define PMU1_XTALTAB0_960_40000K 14
1735 #define PMU1_XTALTAB0_960_48000K 15
1737 /* select xtal table for each chip */
1738 static const pmu1_xtaltab0_t *
1739 BCMINITFN(si_pmu1_xtaltab0)(si_t *sih)
1741 #ifdef BCMDBG
1742 char chn[8];
1743 #endif
1744 switch (CHIPID(sih->chip)) {
1745 case BCM4325_CHIP_ID:
1746 return pmu1_xtaltab0_880;
1747 case BCM4329_CHIP_ID:
1748 return pmu1_xtaltab0_880_4329;
1749 case BCM4315_CHIP_ID:
1750 return pmu1_xtaltab0_1760;
1751 case BCM4319_CHIP_ID:
1752 return pmu1_xtaltab0_1440;
1753 case BCM4336_CHIP_ID:
1754 return pmu1_xtaltab0_960;
1755 case BCM4330_CHIP_ID:
1756 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1757 return pmu1_xtaltab0_960;
1758 else
1759 return pmu1_xtaltab0_1440;
1760 default:
1761 PMU_MSG(("si_pmu1_xtaltab0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1762 break;
1764 ASSERT(0);
1765 return NULL;
1768 /* select default xtal frequency for each chip */
1769 static const pmu1_xtaltab0_t *
1770 BCMINITFN(si_pmu1_xtaldef0)(si_t *sih)
1772 #ifdef BCMDBG
1773 char chn[8];
1774 #endif
1776 switch (CHIPID(sih->chip)) {
1777 case BCM4325_CHIP_ID:
1778 /* Default to 26000Khz */
1779 return &pmu1_xtaltab0_880[PMU1_XTALTAB0_880_26000K];
1780 case BCM4329_CHIP_ID:
1781 /* Default to 38400Khz */
1782 return &pmu1_xtaltab0_880_4329[PMU1_XTALTAB0_880_38400K];
1783 case BCM4315_CHIP_ID:
1784 #ifdef BCMUSBDEV
1785 /* Default to 30000Khz */
1786 return &pmu1_xtaltab0_1760[PMU1_XTALTAB0_1760_30000K];
1787 #else
1788 /* Default to 26000Khz */
1789 return &pmu1_xtaltab0_1760[PMU1_XTALTAB0_1760_26000K];
1790 #endif
1791 case BCM4319_CHIP_ID:
1792 /* Default to 30000Khz */
1793 return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_30000K];
1794 case BCM4336_CHIP_ID:
1795 /* Default to 26000Khz */
1796 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_26000K];
1797 case BCM4330_CHIP_ID:
1798 /* Default to 37400Khz */
1799 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1800 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_37400K];
1801 else
1802 return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_37400K];
1803 default:
1804 PMU_MSG(("si_pmu1_xtaldef0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1805 break;
1807 ASSERT(0);
1808 return NULL;
1811 /* select default pll fvco for each chip */
1812 static uint32
1813 BCMINITFN(si_pmu1_pllfvco0)(si_t *sih)
1815 #ifdef BCMDBG
1816 char chn[8];
1817 #endif
1819 switch (CHIPID(sih->chip)) {
1820 case BCM4325_CHIP_ID:
1821 return FVCO_880;
1822 case BCM4329_CHIP_ID:
1823 return FVCO_880;
1824 case BCM4315_CHIP_ID:
1825 return FVCO_1760;
1826 case BCM4319_CHIP_ID:
1827 return FVCO_1440;
1828 case BCM4336_CHIP_ID:
1829 return FVCO_960;
1830 case BCM4330_CHIP_ID:
1831 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1832 return FVCO_960;
1833 else
1834 return FVCO_1440;
1835 default:
1836 PMU_MSG(("si_pmu1_pllfvco0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1837 break;
1839 ASSERT(0);
1840 return 0;
1843 /* query alp/xtal clock frequency */
1844 static uint32
1845 BCMINITFN(si_pmu1_alpclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1847 const pmu1_xtaltab0_t *xt;
1848 uint32 xf;
1850 /* Find the frequency in the table */
1851 xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1852 PCTL_XTALFREQ_SHIFT;
1853 for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
1854 if (xt->xf == xf)
1855 break;
1856 /* Could not find it so assign a default value */
1857 if (xt == NULL || xt->fref == 0)
1858 xt = si_pmu1_xtaldef0(sih);
1859 ASSERT(xt != NULL && xt->fref != 0);
1861 return xt->fref * 1000;
1863 #endif /* !_CFE_ || CFG_WL */
1865 void
1866 si_pmu_minresmask_htavail_set(si_t *sih, osl_t *osh, bool set_clear)
1868 chipcregs_t *cc;
1869 uint origidx;
1870 /* Remember original core before switch to chipc */
1871 origidx = si_coreidx(sih);
1872 cc = si_setcoreidx(sih, SI_CC_IDX);
1873 ASSERT(cc != NULL);
1875 if (!set_clear) {
1876 switch (CHIPID(sih->chip)) {
1877 case BCM4313_CHIP_ID:
1878 if ((cc->min_res_mask) & (PMURES_BIT(RES4313_HT_AVAIL_RSRC)))
1879 AND_REG(osh, &cc->min_res_mask,
1880 ~(PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1881 break;
1882 default:
1883 break;
1887 /* Return to original core */
1888 si_setcoreidx(sih, origidx);
1891 #if !defined(_CFE_) || defined(CFG_WL)
1892 /* Set up PLL registers in the PMU as per the crystal speed.
1893 * XtalFreq field in pmucontrol register being 0 indicates the PLL
1894 * is not programmed and the h/w default is assumed to work, in which
1895 * case the xtal frequency is unknown to the s/w so we need to call
1896 * si_pmu1_xtaldef0() wherever it is needed to return a default value.
1898 static void
1899 BCMATTACHFN(si_pmu1_pllinit0)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal)
1901 const pmu1_xtaltab0_t *xt;
1902 uint32 tmp;
1903 uint32 buf_strength = 0;
1904 uint8 ndiv_mode = 1;
1905 uint32 FVCO = si_pmu1_pllfvco0(sih);
1906 uint8 dacrate;
1908 FVCO = FVCO/1000;
1910 /* Use h/w default PLL config */
1911 if (xtal == 0) {
1912 PMU_MSG(("Unspecified xtal frequency, skip PLL configuration\n"));
1913 return;
1916 /* Find the frequency in the table */
1917 for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
1918 if (xt->fref == xtal)
1919 break;
1921 /* Check current PLL state, bail out if it has been programmed or
1922 * we don't know how to program it.
1924 if (xt == NULL || xt->fref == 0) {
1925 PMU_MSG(("Unsupported xtal frequency %d.%d MHz, skip PLL configuration\n",
1926 xtal / 1000, xtal % 1000));
1927 return;
1929 /* for 4319 bootloader already programs the PLL but bootloader does not program the
1930 PLL4 and PLL5. So Skip this check for 4319
1932 if ((((R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1933 PCTL_XTALFREQ_SHIFT) == xt->xf) &&
1934 !((CHIPID(sih->chip) == BCM4319_CHIP_ID) || (CHIPID(sih->chip) == BCM4330_CHIP_ID)))
1936 PMU_MSG(("PLL already programmed for %d.%d MHz\n",
1937 xt->fref / 1000, xt->fref % 1000));
1938 return;
1941 PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
1942 PMU_MSG(("Programming PLL for %d.%d MHz\n", xt->fref / 1000, xt->fref % 1000));
1944 switch (CHIPID(sih->chip)) {
1945 case BCM4325_CHIP_ID:
1946 /* Change the BBPLL drive strength to 2 for all channels */
1947 buf_strength = 0x222222;
1948 /* Make sure the PLL is off */
1949 AND_REG(osh, &cc->min_res_mask,
1950 ~(PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL)));
1951 AND_REG(osh, &cc->max_res_mask,
1952 ~(PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL)));
1953 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1954 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1955 break;
1956 case BCM4329_CHIP_ID:
1957 /* Change the BBPLL drive strength to 8 for all channels */
1958 buf_strength = 0x888888;
1959 AND_REG(osh, &cc->min_res_mask,
1960 ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) | PMURES_BIT(RES4329_HT_AVAIL)));
1961 AND_REG(osh, &cc->max_res_mask,
1962 ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) | PMURES_BIT(RES4329_HT_AVAIL)));
1963 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1964 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1965 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
1966 if (xt->fref == 38400)
1967 tmp = 0x200024C0;
1968 else if (xt->fref == 37400)
1969 tmp = 0x20004500;
1970 else if (xt->fref == 26000)
1971 tmp = 0x200024C0;
1972 else
1973 tmp = 0x200005C0; /* Chip Dflt Settings */
1974 W_REG(osh, &cc->pllcontrol_data, tmp);
1975 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
1976 tmp = R_REG(osh, &cc->pllcontrol_data) & PMU1_PLL0_PC5_CLK_DRV_MASK;
1977 if ((xt->fref == 38400) || (xt->fref == 37400) || (xt->fref == 26000))
1978 tmp |= 0x15;
1979 else
1980 tmp |= 0x25; /* Chip Dflt Settings */
1981 W_REG(osh, &cc->pllcontrol_data, tmp);
1982 break;
1983 case BCM4315_CHIP_ID:
1984 /* Change the BBPLL drive strength to 2 for all channels */
1985 buf_strength = 0x222222;
1986 /* Make sure the PLL is off */
1987 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4315_HT_AVAIL)));
1988 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4315_HT_AVAIL)));
1989 OSL_DELAY(100);
1991 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4315_BBPLL_PWRSW_PU)));
1992 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4315_BBPLL_PWRSW_PU)));
1993 OSL_DELAY(100);
1995 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1996 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1997 break;
1999 case BCM4319_CHIP_ID:
2000 /* Change the BBPLL drive strength to 2 for all channels */
2001 buf_strength = 0x222222;
2003 /* Make sure the PLL is off */
2004 /* WAR65104: Disable the HT_AVAIL resource first and then
2005 * after a delay (more than downtime for HT_AVAIL) remove the
2006 * BBPLL resource; backplane clock moves to ALP from HT.
2008 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4319_HT_AVAIL)));
2009 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4319_HT_AVAIL)));
2011 OSL_DELAY(100);
2012 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
2013 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
2015 OSL_DELAY(100);
2016 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2017 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2018 break;
2020 case BCM4336_CHIP_ID:
2021 AND_REG(osh, &cc->min_res_mask,
2022 ~(PMURES_BIT(RES4336_HT_AVAIL) | PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
2023 AND_REG(osh, &cc->max_res_mask,
2024 ~(PMURES_BIT(RES4336_HT_AVAIL) | PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
2025 OSL_DELAY(100);
2026 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2027 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2028 break;
2030 case BCM4330_CHIP_ID:
2031 AND_REG(osh, &cc->min_res_mask,
2032 ~(PMURES_BIT(RES4330_HT_AVAIL) | PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
2033 AND_REG(osh, &cc->max_res_mask,
2034 ~(PMURES_BIT(RES4330_HT_AVAIL) | PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
2035 OSL_DELAY(100);
2036 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2037 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2038 break;
2040 default:
2041 ASSERT(0);
2044 PMU_MSG(("Done masking\n"));
2046 /* Write p1div and p2div to pllcontrol[0] */
2047 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2048 tmp = R_REG(osh, &cc->pllcontrol_data) &
2049 ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
2050 tmp |= ((xt->p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) |
2051 ((xt->p2div << PMU1_PLL0_PC0_P2DIV_SHIFT) & PMU1_PLL0_PC0_P2DIV_MASK);
2053 if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
2054 tmp &= ~(PMU1_PLL0_PC0_BYPASS_SDMOD_MASK);
2055 if (!(xt->ndiv_frac))
2056 tmp |= (1<<(PMU1_PLL0_PC0_BYPASS_SDMOD_SHIFT));
2057 else
2058 tmp |= (0<<(PMU1_PLL0_PC0_BYPASS_SDMOD_SHIFT));
2061 W_REG(osh, &cc->pllcontrol_data, tmp);
2063 if ((CHIPID(sih->chip) == BCM4330_CHIP_ID)) {
2064 if (CHIPREV(sih->chiprev) < 2)
2065 dacrate = 160;
2066 else {
2067 if (!(dacrate = (uint8)getintvar(NULL, "dacrate2g")))
2068 dacrate = 80;
2070 si_pmu_set_4330_plldivs(sih, dacrate);
2073 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (CHIPREV(sih->chiprev) == 0)) {
2075 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2076 tmp = R_REG(osh, &cc->pllcontrol_data);
2077 tmp = tmp & (~DOT11MAC_880MHZ_CLK_DIVISOR_MASK);
2078 tmp = tmp | DOT11MAC_880MHZ_CLK_DIVISOR_VAL;
2079 W_REG(osh, &cc->pllcontrol_data, tmp);
2081 if ((CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
2082 (CHIPID(sih->chip) == BCM4330_CHIP_ID))
2083 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
2084 else
2085 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MASH;
2087 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID)) {
2088 if (!(xt->ndiv_frac))
2089 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_INT;
2090 else
2091 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
2092 #ifdef BCMQT
2093 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2094 tmp = 0x120F1010;
2095 W_REG(osh, &cc->pllcontrol_data, tmp);
2096 #endif
2098 /* Write ndiv_int and ndiv_mode to pllcontrol[2] */
2099 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2100 tmp = R_REG(osh, &cc->pllcontrol_data) &
2101 ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
2102 tmp |= ((xt->ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) & PMU1_PLL0_PC2_NDIV_INT_MASK) |
2103 ((ndiv_mode << PMU1_PLL0_PC2_NDIV_MODE_SHIFT) & PMU1_PLL0_PC2_NDIV_MODE_MASK);
2104 W_REG(osh, &cc->pllcontrol_data, tmp);
2106 /* Write ndiv_frac to pllcontrol[3] */
2107 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2108 tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
2109 tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
2110 PMU1_PLL0_PC3_NDIV_FRAC_MASK);
2111 W_REG(osh, &cc->pllcontrol_data, tmp);
2113 /* Writing to pllcontrol[4] */
2114 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID)) {
2115 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2116 if (!(xt->ndiv_frac))
2117 tmp = 0x200005c0;
2118 else
2119 tmp = 0x202C2820;
2121 tmp &= ~(PMU1_PLL0_PC4_KVCO_XS_MASK);
2123 if (FVCO < 1600)
2124 tmp |= (4<<PMU1_PLL0_PC4_KVCO_XS_SHIFT);
2125 else
2126 tmp |= (7<<PMU1_PLL0_PC4_KVCO_XS_SHIFT);
2128 W_REG(osh, &cc->pllcontrol_data, tmp);
2131 /* Write clock driving strength to pllcontrol[5] */
2132 if (buf_strength) {
2133 PMU_MSG(("Adjusting PLL buffer drive strength: %x\n", buf_strength));
2135 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2136 tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
2137 tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
2139 if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
2140 tmp &= ~(PMU1_PLL0_PC5_VCO_RNG_MASK | PMU1_PLL0_PC5_PLL_CTRL_37_32_MASK);
2141 if (!(xt->ndiv_frac))
2142 tmp |= (0x25<<(PMU1_PLL0_PC5_PLL_CTRL_37_32_SHIFT));
2143 else
2144 tmp |= (0x15<<(PMU1_PLL0_PC5_PLL_CTRL_37_32_SHIFT));
2146 if (FVCO < 1600)
2147 tmp |= (0x0<<(PMU1_PLL0_PC5_VCO_RNG_SHIFT));
2148 else
2149 tmp |= (0x1<<(PMU1_PLL0_PC5_VCO_RNG_SHIFT));
2151 W_REG(osh, &cc->pllcontrol_data, tmp);
2154 PMU_MSG(("Done pll\n"));
2156 /* to operate the 4319 usb in 24MHz/48MHz; chipcontrol[2][84:83] needs
2157 * to be updated.
2159 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && (xt->fref != XTAL_FREQ_30000MHZ)) {
2160 W_REG(osh, &cc->chipcontrol_addr, PMU1_PLL0_CHIPCTL2);
2161 tmp = R_REG(osh, &cc->chipcontrol_data) & ~CCTL_4319USB_XTAL_SEL_MASK;
2162 if (xt->fref == XTAL_FREQ_24000MHZ) {
2163 tmp |= (CCTL_4319USB_24MHZ_PLL_SEL << CCTL_4319USB_XTAL_SEL_SHIFT);
2164 } else if (xt->fref == XTAL_FREQ_48000MHZ) {
2165 tmp |= (CCTL_4319USB_48MHZ_PLL_SEL << CCTL_4319USB_XTAL_SEL_SHIFT);
2167 W_REG(osh, &cc->chipcontrol_data, tmp);
2170 /* Flush deferred pll control registers writes */
2171 if (sih->pmurev >= 2)
2172 OR_REG(osh, &cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
2174 /* Write XtalFreq. Set the divisor also. */
2175 tmp = R_REG(osh, &cc->pmucontrol) &
2176 ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
2177 tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
2178 PCTL_ILP_DIV_MASK) |
2179 ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
2181 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && CHIPREV(sih->chiprev) == 0) {
2182 /* clear the htstretch before clearing HTReqEn */
2183 AND_REG(osh, &cc->clkstretch, ~CSTRETCH_HT);
2184 tmp &= ~PCTL_HT_REQ_EN;
2187 W_REG(osh, &cc->pmucontrol, tmp);
2190 /* query the CPU clock frequency */
2191 static uint32
2192 BCMINITFN(si_pmu1_cpuclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
2194 uint32 tmp, m1div;
2195 #ifdef BCMDBG
2196 uint32 ndiv_int, ndiv_frac, p2div, p1div, fvco;
2197 uint32 fref;
2198 #endif
2199 uint32 FVCO = si_pmu1_pllfvco0(sih);
2201 /* Read m1div from pllcontrol[1] */
2202 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2203 tmp = R_REG(osh, &cc->pllcontrol_data);
2204 m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT;
2206 #ifdef BCMDBG
2207 /* Read p2div/p1div from pllcontrol[0] */
2208 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2209 tmp = R_REG(osh, &cc->pllcontrol_data);
2210 p2div = (tmp & PMU1_PLL0_PC0_P2DIV_MASK) >> PMU1_PLL0_PC0_P2DIV_SHIFT;
2211 p1div = (tmp & PMU1_PLL0_PC0_P1DIV_MASK) >> PMU1_PLL0_PC0_P1DIV_SHIFT;
2213 /* Calculate fvco based on xtal freq and ndiv and pdiv */
2214 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2215 tmp = R_REG(osh, &cc->pllcontrol_data);
2216 ndiv_int = (tmp & PMU1_PLL0_PC2_NDIV_INT_MASK) >> PMU1_PLL0_PC2_NDIV_INT_SHIFT;
2218 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2219 tmp = R_REG(osh, &cc->pllcontrol_data);
2220 ndiv_frac = (tmp & PMU1_PLL0_PC3_NDIV_FRAC_MASK) >> PMU1_PLL0_PC3_NDIV_FRAC_SHIFT;
2222 fref = si_pmu1_alpclk0(sih, osh, cc) / 1000;
2224 fvco = (fref * ndiv_int) << 8;
2225 fvco += (fref * (ndiv_frac >> 12)) >> 4;
2226 fvco += (fref * (ndiv_frac & 0xfff)) >> 12;
2227 fvco >>= 8;
2228 fvco *= p2div;
2229 fvco /= p1div;
2230 fvco /= 1000;
2231 fvco *= 1000;
2233 PMU_MSG(("si_pmu1_cpuclk0: ndiv_int %u ndiv_frac %u p2div %u p1div %u fvco %u\n",
2234 ndiv_int, ndiv_frac, p2div, p1div, fvco));
2236 FVCO = fvco;
2237 #endif /* BCMDBG */
2239 /* Return ARM/SB clock */
2240 return FVCO / m1div * 1000;
2242 #endif /* !_CFE_ || CFG_WL */
2244 /* initialize PLL */
2245 void
2246 BCMATTACHFN(si_pmu_pll_init)(si_t *sih, osl_t *osh, uint xtalfreq)
2248 chipcregs_t *cc;
2249 uint origidx;
2250 #ifdef BCMDBG
2251 char chn[8];
2252 #endif
2254 ASSERT(sih->cccaps & CC_CAP_PMU);
2256 /* Remember original core before switch to chipc */
2257 origidx = si_coreidx(sih);
2258 cc = si_setcoreidx(sih, SI_CC_IDX);
2259 ASSERT(cc != NULL);
2261 switch (CHIPID(sih->chip)) {
2262 case BCM5354_CHIP_ID:
2263 if (xtalfreq == 0)
2264 xtalfreq = 25000;
2265 si_pmu0_pllinit0(sih, osh, cc, xtalfreq);
2266 break;
2267 #if !defined(_CFE_) || defined(CFG_WL)
2268 case BCM4328_CHIP_ID:
2269 si_pmu0_pllinit0(sih, osh, cc, xtalfreq);
2270 break;
2271 case BCM4325_CHIP_ID:
2272 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
2273 break;
2274 case BCM4329_CHIP_ID:
2275 if (xtalfreq == 0)
2276 xtalfreq = 38400;
2277 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
2278 break;
2279 case BCM4312_CHIP_ID:
2280 /* assume default works */
2281 break;
2282 case BCM4322_CHIP_ID:
2283 case BCM43221_CHIP_ID:
2284 case BCM43231_CHIP_ID:
2285 case BCM4342_CHIP_ID: {
2286 if (CHIPREV(sih->chiprev) == 0) {
2287 uint32 minmask, maxmask;
2289 minmask = R_REG(osh, &cc->min_res_mask);
2290 maxmask = R_REG(osh, &cc->max_res_mask);
2292 /* Make sure the PLL is off: clear bit 4 & 5 of min/max_res_mask */
2293 /* Have to remove HT Avail request before powering off PLL */
2294 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
2295 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
2296 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2297 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
2298 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
2299 OSL_DELAY(1000);
2300 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2303 W_REG(osh, &cc->pllcontrol_addr, PMU2_SI_PLL_PLLCTL);
2304 W_REG(osh, &cc->pllcontrol_data, 0x380005c0);
2307 OSL_DELAY(100);
2308 W_REG(osh, &cc->max_res_mask, maxmask);
2309 OSL_DELAY(100);
2310 W_REG(osh, &cc->min_res_mask, minmask);
2311 OSL_DELAY(100);
2314 break;
2316 case BCM4313_CHIP_ID:
2317 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
2318 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43420_CHIP_ID:
2319 case BCM43421_CHIP_ID:
2320 case BCM43226_CHIP_ID:
2321 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
2322 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
2323 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
2324 case BCM43131_CHIP_ID:
2325 case BCM43227_CHIP_ID:
2326 case BCM43228_CHIP_ID:
2327 case BCM43428_CHIP_ID:
2328 case BCM6362_CHIP_ID:
2329 break;
2330 case BCM4315_CHIP_ID:
2331 case BCM4319_CHIP_ID:
2332 case BCM4336_CHIP_ID:
2333 case BCM4330_CHIP_ID:
2334 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
2335 break;
2336 #endif /* !_CFE_ || CFG_WL */
2337 default:
2338 PMU_MSG(("No PLL init done for chip %s rev %d pmurev %d\n",
2339 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
2340 break;
2343 #ifdef BCMDBG_FORCEHT
2344 OR_REG(osh, &cc->clk_ctl_st, CCS_FORCEHT);
2345 #endif
2347 /* Return to original core */
2348 si_setcoreidx(sih, origidx);
2351 /* query alp/xtal clock frequency */
2352 uint32
2353 BCMINITFN(si_pmu_alp_clock)(si_t *sih, osl_t *osh)
2355 chipcregs_t *cc;
2356 uint origidx;
2357 uint32 clock = ALP_CLOCK;
2358 #ifdef BCMDBG
2359 char chn[8];
2360 #endif
2362 ASSERT(sih->cccaps & CC_CAP_PMU);
2364 /* Remember original core before switch to chipc */
2365 origidx = si_coreidx(sih);
2366 cc = si_setcoreidx(sih, SI_CC_IDX);
2367 ASSERT(cc != NULL);
2369 switch (CHIPID(sih->chip)) {
2370 case BCM4328_CHIP_ID:
2371 clock = si_pmu0_alpclk0(sih, osh, cc);
2372 break;
2373 case BCM5354_CHIP_ID:
2374 clock = si_pmu0_alpclk0(sih, osh, cc);
2375 break;
2376 #if !defined(_CFE_) || defined(CFG_WL)
2377 case BCM4325_CHIP_ID:
2378 case BCM4329_CHIP_ID:
2379 case BCM4315_CHIP_ID:
2380 case BCM4319_CHIP_ID:
2381 case BCM4336_CHIP_ID:
2382 case BCM4330_CHIP_ID:
2383 clock = si_pmu1_alpclk0(sih, osh, cc);
2384 break;
2385 #endif /* !_CFE_ || CFG_WL */
2386 case BCM4312_CHIP_ID:
2387 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
2388 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
2389 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43420_CHIP_ID:
2390 case BCM43421_CHIP_ID:
2391 case BCM43226_CHIP_ID:
2392 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
2393 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
2394 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
2395 case BCM43131_CHIP_ID:
2396 case BCM43227_CHIP_ID:
2397 case BCM43228_CHIP_ID:
2398 case BCM43428_CHIP_ID:
2399 case BCM6362_CHIP_ID:
2400 case BCM4342_CHIP_ID:
2401 case BCM4716_CHIP_ID:
2402 case BCM4748_CHIP_ID:
2403 case BCM47162_CHIP_ID:
2404 case BCM4313_CHIP_ID:
2405 case BCM5357_CHIP_ID:
2406 case BCM4749_CHIP_ID:
2407 case BCM53572_CHIP_ID:
2408 /* always 20Mhz */
2409 clock = 20000 * 1000;
2410 break;
2411 case BCM5356_CHIP_ID:
2412 case BCM4706_CHIP_ID:
2413 /* always 25Mhz */
2414 clock = 25000 * 1000;
2415 break;
2416 default:
2417 PMU_MSG(("No ALP clock specified "
2418 "for chip %s rev %d pmurev %d, using default %d Hz\n",
2419 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev, clock));
2420 break;
2423 /* Return to original core */
2424 si_setcoreidx(sih, origidx);
2425 return clock;
2428 /* Find the output of the "m" pll divider given pll controls that start with
2429 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
2431 static uint32
2432 BCMINITFN(si_pmu5_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, uint m)
2434 uint32 tmp, div, ndiv, p1, p2, fc;
2436 if ((pll0 & 3) || (pll0 > PMU4716_MAINPLL_PLL0)) {
2437 PMU_ERROR(("%s: Bad pll0: %d\n", __FUNCTION__, pll0));
2438 return 0;
2442 /* Strictly there is an m5 divider, but I'm not sure we use it */
2443 if ((m == 0) || (m > 4)) {
2444 PMU_ERROR(("%s: Bad m divider: %d\n", __FUNCTION__, m));
2445 return 0;
2448 if ((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
2449 (CHIPID(sih->chip) == BCM4749_CHIP_ID)) {
2450 /* Detect failure in clock setting */
2451 if ((R_REG(osh, &cc->chipstatus) & 0x40000) != 0) {
2452 return (133 * 1000000);
2456 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_P1P2_OFF);
2457 (void)R_REG(osh, &cc->pllcontrol_addr);
2458 tmp = R_REG(osh, &cc->pllcontrol_data);
2459 p1 = (tmp & PMU5_PLL_P1_MASK) >> PMU5_PLL_P1_SHIFT;
2460 p2 = (tmp & PMU5_PLL_P2_MASK) >> PMU5_PLL_P2_SHIFT;
2462 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_M14_OFF);
2463 (void)R_REG(osh, &cc->pllcontrol_addr);
2464 tmp = R_REG(osh, &cc->pllcontrol_data);
2465 div = (tmp >> ((m - 1) * PMU5_PLL_MDIV_WIDTH)) & PMU5_PLL_MDIV_MASK;
2467 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_NM5_OFF);
2468 (void)R_REG(osh, &cc->pllcontrol_addr);
2469 tmp = R_REG(osh, &cc->pllcontrol_data);
2470 ndiv = (tmp & PMU5_PLL_NDIV_MASK) >> PMU5_PLL_NDIV_SHIFT;
2472 /* Do calculation in Mhz */
2473 fc = si_pmu_alp_clock(sih, osh) / 1000000;
2474 fc = (p1 * ndiv * fc) / p2;
2476 PMU_NONE(("%s: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, clock=%d\n",
2477 __FUNCTION__, p1, p2, ndiv, ndiv, m, div, fc, fc / div));
2479 /* Return clock in Hertz */
2480 return ((fc / div) * 1000000);
2483 static uint32
2484 BCMINITFN(si_4706_pmu_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, uint m)
2486 uint32 w, ndiv, p1div, p2div;
2487 uint32 clock;
2489 /* Strictly there is an m5 divider, but I'm not sure we use it */
2490 if ((m == 0) || (m > 4)) {
2491 PMU_ERROR(("%s: Bad m divider: %d\n", __FUNCTION__, m));
2492 return 0;
2495 /* Get N, P1 and P2 dividers to determine CPU clock */
2496 W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU6_4706_PROCPLL_OFF);
2497 w = R_REG(NULL, &cc->pllcontrol_data);
2498 ndiv = (w & PMU6_4706_PROC_NDIV_INT_MASK) >> PMU6_4706_PROC_NDIV_INT_SHIFT;
2499 p1div = (w & PMU6_4706_PROC_P1DIV_MASK) >> PMU6_4706_PROC_P1DIV_SHIFT;
2500 p2div = (w & PMU6_4706_PROC_P2DIV_MASK) >> PMU6_4706_PROC_P2DIV_SHIFT;
2501 /* Fixed reference clock 25MHz and m = 2 */
2502 clock = (25000000 / 2) * ndiv * p2div / p1div;
2503 if (m == PMU5_MAINPLL_MEM)
2504 clock = clock / 2;
2505 else if (m == PMU5_MAINPLL_SI)
2506 clock = clock / 4;
2508 return clock;
2511 /* query backplane clock frequency */
2512 /* For designs that feed the same clock to both backplane
2513 * and CPU just return the CPU clock speed.
2515 uint32
2516 BCMINITFN(si_pmu_si_clock)(si_t *sih, osl_t *osh)
2518 chipcregs_t *cc;
2519 uint origidx;
2520 uint32 clock = HT_CLOCK;
2521 #ifdef BCMDBG
2522 char chn[8];
2523 #endif
2525 ASSERT(sih->cccaps & CC_CAP_PMU);
2527 /* Remember original core before switch to chipc */
2528 origidx = si_coreidx(sih);
2529 cc = si_setcoreidx(sih, SI_CC_IDX);
2530 ASSERT(cc != NULL);
2532 switch (CHIPID(sih->chip)) {
2533 #if !defined(_CFE_) || defined(CFG_WL)
2534 case BCM4328_CHIP_ID:
2535 clock = si_pmu0_cpuclk0(sih, osh, cc);
2536 break;
2537 case BCM4325_CHIP_ID:
2538 clock = si_pmu1_cpuclk0(sih, osh, cc);
2539 break;
2540 case BCM4322_CHIP_ID:
2541 case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
2542 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
2543 case BCM43224_CHIP_ID: case BCM43420_CHIP_ID:
2544 case BCM43225_CHIP_ID:
2545 case BCM43421_CHIP_ID:
2546 case BCM43226_CHIP_ID:
2547 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
2548 case BCM6362_CHIP_ID:
2549 case BCM4342_CHIP_ID:
2550 /* 96MHz backplane clock */
2551 clock = 96000 * 1000;
2552 break;
2553 case BCM4329_CHIP_ID:
2554 if (CHIPREV(sih->chiprev) == 0)
2555 clock = 38400 * 1000;
2556 else
2557 clock = si_pmu1_cpuclk0(sih, osh, cc);
2558 break;
2559 case BCM4315_CHIP_ID:
2560 case BCM4319_CHIP_ID:
2561 case BCM4336_CHIP_ID:
2562 case BCM4330_CHIP_ID:
2563 clock = si_pmu1_cpuclk0(sih, osh, cc);
2564 break;
2565 case BCM4313_CHIP_ID:
2566 /* 80MHz backplane clock */
2567 clock = 80000 * 1000;
2568 break;
2569 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
2570 case BCM43234_CHIP_ID:
2571 clock = (cc->chipstatus & CST43236_BP_CLK) ? (120000 * 1000) : (96000 * 1000);
2572 break;
2573 case BCM43237_CHIP_ID:
2574 clock = (cc->chipstatus & CST43237_BP_CLK) ? (96000 * 1000) : (80000 * 1000);
2575 break;
2576 #endif /* !_CFE_ || CFG_WL */
2577 case BCM5354_CHIP_ID:
2578 clock = 120000000;
2579 break;
2580 case BCM4716_CHIP_ID:
2581 case BCM4748_CHIP_ID:
2582 case BCM47162_CHIP_ID:
2583 clock = si_pmu5_clock(sih, osh, cc, PMU4716_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2584 break;
2585 case BCM5356_CHIP_ID:
2586 clock = si_pmu5_clock(sih, osh, cc, PMU5356_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2587 break;
2588 case BCM5357_CHIP_ID:
2589 case BCM4749_CHIP_ID:
2590 clock = si_pmu5_clock(sih, osh, cc, PMU5357_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2591 break;
2592 case BCM4706_CHIP_ID:
2593 clock = si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2594 break;
2595 case BCM53572_CHIP_ID:
2596 clock = 75000000;
2597 break;
2598 default:
2599 PMU_MSG(("No backplane clock specified "
2600 "for chip %s rev %d pmurev %d, using default %d Hz\n",
2601 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev, clock));
2602 break;
2605 /* Return to original core */
2606 si_setcoreidx(sih, origidx);
2607 return clock;
2610 /* query CPU clock frequency */
2611 uint32
2612 BCMINITFN(si_pmu_cpu_clock)(si_t *sih, osl_t *osh)
2614 chipcregs_t *cc;
2615 uint origidx;
2616 uint32 clock;
2618 ASSERT(sih->cccaps & CC_CAP_PMU);
2620 /* 5354 chip uses a non programmable PLL of frequency 240MHz */
2621 if (CHIPID(sih->chip) == BCM5354_CHIP_ID)
2622 return 240000000;
2624 if (CHIPID(sih->chip) == BCM53572_CHIP_ID)
2625 return 300000000;
2627 if ((sih->pmurev >= 5) &&
2628 !((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
2629 (CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
2630 (CHIPID(sih->chip) == BCM43234_CHIP_ID) ||
2631 (CHIPID(sih->chip) == BCM43235_CHIP_ID) ||
2632 (CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
2633 (CHIPID(sih->chip) == BCM43237_CHIP_ID) ||
2634 (CHIPID(sih->chip) == BCM43238_CHIP_ID) ||
2635 (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
2636 (CHIPID(sih->chip) == BCM4330_CHIP_ID))) {
2637 uint pll;
2639 switch (CHIPID(sih->chip)) {
2640 case BCM5356_CHIP_ID:
2641 pll = PMU5356_MAINPLL_PLL0;
2642 break;
2643 case BCM5357_CHIP_ID:
2644 case BCM4749_CHIP_ID:
2645 pll = PMU5357_MAINPLL_PLL0;
2646 break;
2647 default:
2648 pll = PMU4716_MAINPLL_PLL0;
2649 break;
2652 /* Remember original core before switch to chipc */
2653 origidx = si_coreidx(sih);
2654 cc = si_setcoreidx(sih, SI_CC_IDX);
2655 ASSERT(cc != NULL);
2657 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
2658 clock = si_4706_pmu_clock(sih, osh, cc,
2659 PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU);
2660 else
2661 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_CPU);
2663 /* Return to original core */
2664 si_setcoreidx(sih, origidx);
2665 } else
2666 clock = si_pmu_si_clock(sih, osh);
2668 return clock;
2671 /* query memory clock frequency */
2672 uint32
2673 BCMINITFN(si_pmu_mem_clock)(si_t *sih, osl_t *osh)
2675 chipcregs_t *cc;
2676 uint origidx;
2677 uint32 clock;
2679 ASSERT(sih->cccaps & CC_CAP_PMU);
2681 if (CHIPID(sih->chip) == BCM53572_CHIP_ID)
2682 return 150000000;
2684 if ((sih->pmurev >= 5) &&
2685 !((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
2686 (CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
2687 (CHIPID(sih->chip) == BCM4330_CHIP_ID) ||
2688 (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
2689 (CHIPID(sih->chip) == BCM43234_CHIP_ID) ||
2690 (CHIPID(sih->chip) == BCM43235_CHIP_ID) ||
2691 (CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
2692 (CHIPID(sih->chip) == BCM43237_CHIP_ID) ||
2693 (CHIPID(sih->chip) == BCM43238_CHIP_ID) ||
2694 0)) {
2695 uint pll;
2697 switch (CHIPID(sih->chip)) {
2698 case BCM5356_CHIP_ID:
2699 pll = PMU5356_MAINPLL_PLL0;
2700 break;
2701 case BCM5357_CHIP_ID:
2702 case BCM4749_CHIP_ID:
2703 pll = PMU5357_MAINPLL_PLL0;
2704 break;
2705 default:
2706 pll = PMU4716_MAINPLL_PLL0;
2707 break;
2710 /* Remember original core before switch to chipc */
2711 origidx = si_coreidx(sih);
2712 cc = si_setcoreidx(sih, SI_CC_IDX);
2713 ASSERT(cc != NULL);
2715 if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
2716 clock = si_4706_pmu_clock(sih, osh, cc,
2717 PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_MEM);
2718 else
2719 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_MEM);
2721 /* Return to original core */
2722 si_setcoreidx(sih, origidx);
2723 } else {
2724 clock = si_pmu_si_clock(sih, osh);
2727 return clock;
2730 /* Measure ILP clock frequency */
2731 #define ILP_CALC_DUR 10 /* ms, make sure 1000 can be divided by it. */
2733 static uint32 ilpcycles_per_sec = 0;
2735 uint32
2736 BCMINITFN(si_pmu_ilp_clock)(si_t *sih, osl_t *osh)
2738 if (ISSIM_ENAB(sih))
2739 return ILP_CLOCK;
2741 if (ilpcycles_per_sec == 0) {
2742 uint32 start, end, delta;
2743 uint32 origidx = si_coreidx(sih);
2744 chipcregs_t *cc = si_setcoreidx(sih, SI_CC_IDX);
2745 ASSERT(cc != NULL);
2746 start = R_REG(osh, &cc->pmutimer);
2747 OSL_DELAY(ILP_CALC_DUR * 1000);
2748 end = R_REG(osh, &cc->pmutimer);
2749 delta = end - start;
2750 ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
2751 si_setcoreidx(sih, origidx);
2754 return ilpcycles_per_sec;
2757 /* SDIO Pad drive strength to select value mappings */
2758 typedef struct {
2759 uint8 strength; /* Pad Drive Strength in mA */
2760 uint8 sel; /* Chip-specific select value */
2761 } sdiod_drive_str_t;
2763 /* SDIO Drive Strength to sel value table for PMU Rev 1 */
2764 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab1)[] = {
2765 {4, 0x2},
2766 {2, 0x3},
2767 {1, 0x0},
2768 {0, 0x0} };
2770 /* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
2771 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab2)[] = {
2772 {12, 0x7},
2773 {10, 0x6},
2774 {8, 0x5},
2775 {6, 0x4},
2776 {4, 0x2},
2777 {2, 0x1},
2778 {0, 0x0} };
2780 /* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
2781 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab3)[] = {
2782 {32, 0x7},
2783 {26, 0x6},
2784 {22, 0x5},
2785 {16, 0x4},
2786 {12, 0x3},
2787 {8, 0x2},
2788 {4, 0x1},
2789 {0, 0x0} };
2791 #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
2793 void
2794 BCMINITFN(si_sdiod_drive_strength_init)(si_t *sih, osl_t *osh, uint32 drivestrength)
2796 chipcregs_t *cc;
2797 uint origidx, intr_val = 0;
2798 sdiod_drive_str_t *str_tab = NULL;
2799 uint32 str_mask = 0;
2800 uint32 str_shift = 0;
2801 #ifdef BCMDBG
2802 char chn[8];
2803 #endif
2805 if (!(sih->cccaps & CC_CAP_PMU)) {
2806 return;
2809 /* Remember original core before switch to chipc */
2810 cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
2812 switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) {
2813 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
2814 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1;
2815 str_mask = 0x30000000;
2816 str_shift = 28;
2817 break;
2818 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
2819 case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
2820 case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4):
2821 case SDIOD_DRVSTR_KEY(BCM4319_CHIP_ID, 7):
2822 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2;
2823 str_mask = 0x00003800;
2824 str_shift = 11;
2825 break;
2826 case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
2827 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3;
2828 str_mask = 0x00003800;
2829 str_shift = 11;
2830 break;
2832 default:
2833 PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
2834 bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
2836 break;
2839 if (str_tab != NULL) {
2840 uint32 drivestrength_sel = 0;
2841 uint32 cc_data_temp;
2842 int i;
2844 for (i = 0; str_tab[i].strength != 0; i ++) {
2845 if (drivestrength >= str_tab[i].strength) {
2846 drivestrength_sel = str_tab[i].sel;
2847 break;
2851 W_REG(osh, &cc->chipcontrol_addr, 1);
2852 cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
2853 cc_data_temp &= ~str_mask;
2854 drivestrength_sel <<= str_shift;
2855 cc_data_temp |= drivestrength_sel;
2856 W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
2858 PMU_MSG(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
2859 drivestrength, cc_data_temp));
2862 /* Return to original core */
2863 si_restore_core(sih, origidx, intr_val);
2866 /* initialize PMU */
2867 void
2868 BCMATTACHFN(si_pmu_init)(si_t *sih, osl_t *osh)
2870 chipcregs_t *cc;
2871 uint origidx;
2873 ASSERT(sih->cccaps & CC_CAP_PMU);
2875 /* Remember original core before switch to chipc */
2876 origidx = si_coreidx(sih);
2877 cc = si_setcoreidx(sih, SI_CC_IDX);
2878 ASSERT(cc != NULL);
2880 if (sih->pmurev == 1)
2881 AND_REG(osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
2882 else if (sih->pmurev >= 2)
2883 OR_REG(osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT);
2885 #if !defined(_CFE_) || defined(CFG_WL)
2886 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 2)) {
2887 /* Fix for 4329b0 bad LPOM state. */
2888 W_REG(osh, &cc->regcontrol_addr, 2);
2889 OR_REG(osh, &cc->regcontrol_data, 0x100);
2891 W_REG(osh, &cc->regcontrol_addr, 3);
2892 OR_REG(osh, &cc->regcontrol_data, 0x4);
2895 if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
2896 /* Limiting the PALDO spike during init time */
2897 si_pmu_regcontrol(sih, 2, 0x00000007, 0x00000005);
2899 #endif /* !_CFE_ || CFG_WL */
2901 /* Return to original core */
2902 si_setcoreidx(sih, origidx);
2905 #if !defined(_CFE_) || defined(CFG_WL)
2906 /* Return up time in ILP cycles for the given resource. */
2907 static uint
2908 BCMINITFN(si_pmu_res_uptime)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint8 rsrc)
2910 uint32 deps;
2911 uint up, i, dup, dmax;
2912 uint32 min_mask = 0, max_mask = 0;
2914 /* uptime of resource 'rsrc' */
2915 W_REG(osh, &cc->res_table_sel, rsrc);
2916 up = (R_REG(osh, &cc->res_updn_timer) >> 8) & 0xff;
2918 /* direct dependancies of resource 'rsrc' */
2919 deps = si_pmu_res_deps(sih, osh, cc, PMURES_BIT(rsrc), FALSE);
2920 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
2921 if (!(deps & PMURES_BIT(i)))
2922 continue;
2923 deps &= ~si_pmu_res_deps(sih, osh, cc, PMURES_BIT(i), TRUE);
2925 si_pmu_res_masks(sih, &min_mask, &max_mask);
2926 deps &= ~min_mask;
2928 /* max uptime of direct dependancies */
2929 dmax = 0;
2930 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
2931 if (!(deps & PMURES_BIT(i)))
2932 continue;
2933 dup = si_pmu_res_uptime(sih, osh, cc, (uint8)i);
2934 if (dmax < dup)
2935 dmax = dup;
2938 PMU_MSG(("si_pmu_res_uptime: rsrc %u uptime %u(deps 0x%08x uptime %u)\n",
2939 rsrc, up, deps, dmax));
2941 return up + dmax + PMURES_UP_TRANSITION;
2944 /* Return dependancies (direct or all/indirect) for the given resources */
2945 static uint32
2946 si_pmu_res_deps(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 rsrcs, bool all)
2948 uint32 deps = 0;
2949 uint32 i;
2951 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
2952 if (!(rsrcs & PMURES_BIT(i)))
2953 continue;
2954 W_REG(osh, &cc->res_table_sel, i);
2955 deps |= R_REG(osh, &cc->res_dep_mask);
2958 return !all ? deps : (deps ? (deps | si_pmu_res_deps(sih, osh, cc, deps, TRUE)) : 0);
2961 /* power up/down OTP through PMU resources */
2962 void
2963 si_pmu_otp_power(si_t *sih, osl_t *osh, bool on)
2965 chipcregs_t *cc;
2966 uint origidx;
2967 uint32 rsrcs = 0; /* rsrcs to turn on/off OTP power */
2969 ASSERT(sih->cccaps & CC_CAP_PMU);
2971 /* Don't do anything if OTP is disabled */
2972 if (si_is_otp_disabled(sih)) {
2973 PMU_MSG(("si_pmu_otp_power: OTP is disabled\n"));
2974 return;
2977 /* Remember original core before switch to chipc */
2978 origidx = si_coreidx(sih);
2979 cc = si_setcoreidx(sih, SI_CC_IDX);
2980 ASSERT(cc != NULL);
2982 switch (CHIPID(sih->chip)) {
2983 case BCM4322_CHIP_ID:
2984 case BCM43221_CHIP_ID:
2985 case BCM43231_CHIP_ID:
2986 case BCM4342_CHIP_ID:
2987 rsrcs = PMURES_BIT(RES4322_OTP_PU);
2988 break;
2989 case BCM4325_CHIP_ID:
2990 rsrcs = PMURES_BIT(RES4325_OTP_PU);
2991 break;
2992 case BCM4315_CHIP_ID:
2993 rsrcs = PMURES_BIT(RES4315_OTP_PU);
2994 break;
2995 case BCM4329_CHIP_ID:
2996 rsrcs = PMURES_BIT(RES4329_OTP_PU);
2997 break;
2998 case BCM4319_CHIP_ID:
2999 rsrcs = PMURES_BIT(RES4319_OTP_PU);
3000 break;
3001 case BCM4336_CHIP_ID:
3002 rsrcs = PMURES_BIT(RES4336_OTP_PU);
3003 break;
3004 case BCM4330_CHIP_ID:
3005 rsrcs = PMURES_BIT(RES4330_OTP_PU);
3006 break;
3007 default:
3008 break;
3011 if (rsrcs != 0) {
3012 uint32 otps;
3014 /* Figure out the dependancies (exclude min_res_mask) */
3015 uint32 deps = si_pmu_res_deps(sih, osh, cc, rsrcs, TRUE);
3016 uint32 min_mask = 0, max_mask = 0;
3017 si_pmu_res_masks(sih, &min_mask, &max_mask);
3018 deps &= ~min_mask;
3019 /* Turn on/off the power */
3020 if (on) {
3021 PMU_MSG(("Adding rsrc 0x%x to min_res_mask\n", rsrcs | deps));
3022 OR_REG(osh, &cc->min_res_mask, (rsrcs | deps));
3023 OSL_DELAY(1000);
3024 SPINWAIT(!(R_REG(osh, &cc->res_state) & rsrcs), PMU_MAX_TRANSITION_DLY);
3025 ASSERT(R_REG(osh, &cc->res_state) & rsrcs);
3027 else {
3028 PMU_MSG(("Removing rsrc 0x%x from min_res_mask\n", rsrcs | deps));
3029 AND_REG(osh, &cc->min_res_mask, ~(rsrcs | deps));
3032 SPINWAIT((((otps = R_REG(osh, &cc->otpstatus)) & OTPS_READY) !=
3033 (on ? OTPS_READY : 0)), 100);
3034 ASSERT((otps & OTPS_READY) == (on ? OTPS_READY : 0));
3035 if ((otps & OTPS_READY) != (on ? OTPS_READY : 0))
3036 PMU_MSG(("OTP ready bit not %s after wait\n", (on ? "ON" : "OFF")));
3039 /* Return to original core */
3040 si_setcoreidx(sih, origidx);
3043 void
3044 si_pmu_rcal(si_t *sih, osl_t *osh)
3046 chipcregs_t *cc;
3047 uint origidx;
3048 uint rcal_done, BT_out_of_reset;
3050 ASSERT(sih->cccaps & CC_CAP_PMU);
3052 /* Remember original core before switch to chipc */
3053 origidx = si_coreidx(sih);
3054 cc = si_setcoreidx(sih, SI_CC_IDX);
3055 ASSERT(cc != NULL);
3057 switch (CHIPID(sih->chip)) {
3058 case BCM4325_CHIP_ID: {
3059 uint8 rcal_code;
3060 uint32 val;
3062 /* Kick RCal */
3063 W_REG(osh, &cc->chipcontrol_addr, 1);
3065 /* Power Down RCAL Block */
3066 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3068 /* Check if RCAL is already done by BT */
3069 rcal_done = ((R_REG(osh, &cc->chipstatus)) & 0x8) >> 3;
3071 /* If RCAL already done, note that BT is out of reset */
3072 if (rcal_done == 1) {
3073 BT_out_of_reset = 1;
3074 } else {
3075 BT_out_of_reset = 0;
3078 /* Power Up RCAL block */
3079 OR_REG(osh, &cc->chipcontrol_data, 0x04);
3081 /* Wait for completion */
3082 SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08), 10 * 1000 * 1000);
3083 ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
3085 if (BT_out_of_reset) {
3086 rcal_code = 0x6;
3087 } else {
3088 /* Drop the LSB to convert from 5 bit code to 4 bit code */
3089 rcal_code = (uint8)(R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
3092 PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
3093 R_REG(osh, &cc->chipstatus), rcal_code));
3095 /* Write RCal code into pmu_vreg_ctrl[32:29] */
3096 W_REG(osh, &cc->regcontrol_addr, 0);
3097 val = R_REG(osh, &cc->regcontrol_data) & ~((uint32)0x07 << 29);
3098 val |= (uint32)(rcal_code & 0x07) << 29;
3099 W_REG(osh, &cc->regcontrol_data, val);
3100 W_REG(osh, &cc->regcontrol_addr, 1);
3101 val = R_REG(osh, &cc->regcontrol_data) & ~(uint32)0x01;
3102 val |= (uint32)((rcal_code >> 3) & 0x01);
3103 W_REG(osh, &cc->regcontrol_data, val);
3105 /* Write RCal code into pmu_chip_ctrl[33:30] */
3106 W_REG(osh, &cc->chipcontrol_addr, 0);
3107 val = R_REG(osh, &cc->chipcontrol_data) & ~((uint32)0x03 << 30);
3108 val |= (uint32)(rcal_code & 0x03) << 30;
3109 W_REG(osh, &cc->chipcontrol_data, val);
3110 W_REG(osh, &cc->chipcontrol_addr, 1);
3111 val = R_REG(osh, &cc->chipcontrol_data) & ~(uint32)0x03;
3112 val |= (uint32)((rcal_code >> 2) & 0x03);
3113 W_REG(osh, &cc->chipcontrol_data, val);
3115 /* Set override in pmu_chip_ctrl[29] */
3116 W_REG(osh, &cc->chipcontrol_addr, 0);
3117 OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
3119 /* Power off RCal block */
3120 W_REG(osh, &cc->chipcontrol_addr, 1);
3121 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3123 break;
3125 case BCM4329_CHIP_ID: {
3126 uint8 rcal_code;
3127 uint32 val;
3129 /* Kick RCal */
3130 W_REG(osh, &cc->chipcontrol_addr, 1);
3132 /* Power Down RCAL Block */
3133 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3135 /* Power Up RCAL block */
3136 OR_REG(osh, &cc->chipcontrol_data, 0x04);
3138 /* Wait for completion */
3139 SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08), 10 * 1000 * 1000);
3140 ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
3142 /* Drop the LSB to convert from 5 bit code to 4 bit code */
3143 rcal_code = (uint8)(R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
3145 PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
3146 R_REG(osh, &cc->chipstatus), rcal_code));
3148 /* Write RCal code into pmu_vreg_ctrl[32:29] */
3149 W_REG(osh, &cc->regcontrol_addr, 0);
3150 val = R_REG(osh, &cc->regcontrol_data) & ~((uint32)0x07 << 29);
3151 val |= (uint32)(rcal_code & 0x07) << 29;
3152 W_REG(osh, &cc->regcontrol_data, val);
3153 W_REG(osh, &cc->regcontrol_addr, 1);
3154 val = R_REG(osh, &cc->regcontrol_data) & ~(uint32)0x01;
3155 val |= (uint32)((rcal_code >> 3) & 0x01);
3156 W_REG(osh, &cc->regcontrol_data, val);
3158 /* Write RCal code into pmu_chip_ctrl[33:30] */
3159 W_REG(osh, &cc->chipcontrol_addr, 0);
3160 val = R_REG(osh, &cc->chipcontrol_data) & ~((uint32)0x03 << 30);
3161 val |= (uint32)(rcal_code & 0x03) << 30;
3162 W_REG(osh, &cc->chipcontrol_data, val);
3163 W_REG(osh, &cc->chipcontrol_addr, 1);
3164 val = R_REG(osh, &cc->chipcontrol_data) & ~(uint32)0x03;
3165 val |= (uint32)((rcal_code >> 2) & 0x03);
3166 W_REG(osh, &cc->chipcontrol_data, val);
3168 /* Set override in pmu_chip_ctrl[29] */
3169 W_REG(osh, &cc->chipcontrol_addr, 0);
3170 OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
3172 /* Power off RCal block */
3173 W_REG(osh, &cc->chipcontrol_addr, 1);
3174 AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3176 break;
3178 default:
3179 break;
3182 /* Return to original core */
3183 si_setcoreidx(sih, origidx);
3186 void
3187 si_pmu_spuravoid(si_t *sih, osl_t *osh, uint8 spuravoid)
3189 chipcregs_t *cc;
3190 uint origidx, intr_val;
3191 uint32 tmp = 0;
3193 /* Remember original core before switch to chipc */
3194 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
3195 ASSERT(cc != NULL);
3197 /* force the HT off */
3198 if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
3199 tmp = R_REG(osh, &cc->max_res_mask);
3200 tmp &= ~RES4336_HT_AVAIL;
3201 W_REG(osh, &cc->max_res_mask, tmp);
3202 /* wait for the ht to really go away */
3203 SPINWAIT(((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0), 10000);
3204 ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0);
3207 /* update the pll changes */
3208 si_pmu_spuravoid_pllupdate(sih, cc, osh, spuravoid);
3210 /* enable HT back on */
3211 if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
3212 tmp = R_REG(osh, &cc->max_res_mask);
3213 tmp |= RES4336_HT_AVAIL;
3214 W_REG(osh, &cc->max_res_mask, tmp);
3217 /* Return to original core */
3218 si_restore_core(sih, origidx, intr_val);
3221 static void
3222 si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, osl_t *osh, uint8 spuravoid)
3224 uint32 tmp = 0;
3225 uint8 phypll_offset = 0;
3226 uint8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5};
3227 uint8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc};
3228 #ifdef BCMDBG_ERR
3229 char chn[8];
3230 #endif
3232 switch (CHIPID(sih->chip)) {
3233 case BCM5357_CHIP_ID: case BCM4749_CHIP_ID:
3234 case BCM43235_CHIP_ID: case BCM43236_CHIP_ID: case BCM43238_CHIP_ID:
3235 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID:
3236 case BCM6362_CHIP_ID: case BCM53572_CHIP_ID:
3238 if ((CHIPID(sih->chip) == BCM6362_CHIP_ID) && (sih->chiprev == 0)) {
3239 /* 6362a0 (same clks as 4322[4-6]) */
3240 if (spuravoid == 1) {
3241 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3242 W_REG(osh, &cc->pllcontrol_data, 0x11500010);
3243 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3244 W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
3245 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3246 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3247 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3248 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3249 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3250 W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
3251 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3252 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3253 } else {
3254 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3255 W_REG(osh, &cc->pllcontrol_data, 0x11100010);
3256 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3257 W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
3258 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3259 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3260 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3261 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3262 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3263 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3264 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3265 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3268 } else {
3269 /* 5357[ab]0, 43236[ab]0, and 6362b0 */
3271 /* BCM5357 needs to touch PLL1_PLLCTL[02],so offset PLL0_PLLCTL[02] by 6 */
3272 phypll_offset = ((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
3273 (CHIPID(sih->chip) == BCM4749_CHIP_ID) ||
3274 (CHIPID(sih->chip) == BCM53572_CHIP_ID)) ? 6 : 0;
3276 /* RMW only the P1 divider */
3277 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0 + phypll_offset);
3278 tmp = R_REG(osh, &cc->pllcontrol_data);
3279 tmp &= (~(PMU1_PLL0_PC0_P1DIV_MASK));
3280 tmp |= (bcm5357_bcm43236_p1div[spuravoid] << PMU1_PLL0_PC0_P1DIV_SHIFT);
3281 W_REG(osh, &cc->pllcontrol_data, tmp);
3283 /* RMW only the int feedback divider */
3284 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2 + phypll_offset);
3285 tmp = R_REG(osh, &cc->pllcontrol_data);
3286 tmp &= ~(PMU1_PLL0_PC2_NDIV_INT_MASK);
3287 tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << PMU1_PLL0_PC2_NDIV_INT_SHIFT;
3288 W_REG(osh, &cc->pllcontrol_data, tmp);
3291 tmp = 1 << 10;
3292 break;
3294 case BCM4331_CHIP_ID:
3295 case BCM43431_CHIP_ID:
3296 if (ISSIM_ENAB(sih)) {
3297 if (spuravoid == 2) {
3298 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3299 W_REG(osh, &cc->pllcontrol_data, 0x00000002);
3300 } else if (spuravoid == 1) {
3301 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3302 W_REG(osh, &cc->pllcontrol_data, 0x00000001);
3303 } else {
3304 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3305 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3307 } else {
3308 if (spuravoid == 2) {
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, 0x0FC00a08);
3313 } else if (spuravoid == 1) {
3314 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3315 W_REG(osh, &cc->pllcontrol_data, 0x11500014);
3316 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3317 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3318 } else {
3319 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3320 W_REG(osh, &cc->pllcontrol_data, 0x11100014);
3321 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3322 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3325 tmp = 1 << 10;
3326 break;
3328 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID:
3329 case BCM43226_CHIP_ID:
3330 if (spuravoid == 1) {
3331 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3332 W_REG(osh, &cc->pllcontrol_data, 0x11500010);
3333 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3334 W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
3335 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3336 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3337 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3338 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3339 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3340 W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
3341 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3342 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3343 } else {
3344 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3345 W_REG(osh, &cc->pllcontrol_data, 0x11100010);
3346 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3347 W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
3348 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3349 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3350 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3351 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3352 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3353 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3354 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3355 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3357 tmp = 1 << 10;
3358 break;
3360 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
3361 case BCM43420_CHIP_ID:
3362 if (spuravoid == 1) {
3363 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3364 W_REG(osh, &cc->pllcontrol_data, 0x11500008);
3365 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3366 W_REG(osh, &cc->pllcontrol_data, 0x0C000C06);
3367 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3368 W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3369 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3370 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3371 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3372 W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
3373 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3374 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3375 } else {
3376 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3377 W_REG(osh, &cc->pllcontrol_data, 0x11100008);
3378 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3379 W_REG(osh, &cc->pllcontrol_data, 0x0c000c06);
3380 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3381 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3382 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3383 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3384 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3385 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3386 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3387 W_REG(osh, &cc->pllcontrol_data, 0x88888855);
3390 tmp = 1 << 10;
3391 break;
3393 case BCM4716_CHIP_ID:
3394 case BCM4748_CHIP_ID:
3395 case BCM47162_CHIP_ID:
3396 if (spuravoid == 1) {
3397 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3398 W_REG(osh, &cc->pllcontrol_data, 0x11500060);
3399 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3400 W_REG(osh, &cc->pllcontrol_data, 0x080C0C06);
3401 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3402 W_REG(osh, &cc->pllcontrol_data, 0x0F600000);
3403 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3404 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3405 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3406 W_REG(osh, &cc->pllcontrol_data, 0x2001E924);
3407 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3408 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3409 } else {
3410 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3411 W_REG(osh, &cc->pllcontrol_data, 0x11100060);
3412 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3413 W_REG(osh, &cc->pllcontrol_data, 0x080c0c06);
3414 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3415 W_REG(osh, &cc->pllcontrol_data, 0x03000000);
3416 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3417 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3418 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3419 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3420 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3421 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3424 tmp = 3 << 9;
3425 break;
3427 case BCM4322_CHIP_ID:
3428 case BCM43221_CHIP_ID:
3429 case BCM43231_CHIP_ID:
3430 case BCM4342_CHIP_ID:
3431 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3432 W_REG(osh, &cc->pllcontrol_data, 0x11100070);
3433 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3434 W_REG(osh, &cc->pllcontrol_data, 0x1014140a);
3435 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3436 W_REG(osh, &cc->pllcontrol_data, 0x88888854);
3438 if (spuravoid == 1) { /* spur_avoid ON, enable 41/82/164Mhz clock mode */
3439 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3440 W_REG(osh, &cc->pllcontrol_data, 0x05201828);
3441 } else { /* enable 40/80/160Mhz clock mode */
3442 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3443 W_REG(osh, &cc->pllcontrol_data, 0x05001828);
3446 tmp = 1 << 10;
3447 break;
3448 case BCM4319_CHIP_ID:
3449 break;
3450 case BCM4336_CHIP_ID:
3451 /* Looks like these are only for default xtal freq 26MHz */
3452 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3453 W_REG(osh, &cc->pllcontrol_data, 0x02100020);
3455 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3456 W_REG(osh, &cc->pllcontrol_data, 0x0C0C0C0C);
3458 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3459 W_REG(osh, &cc->pllcontrol_data, 0x01240C0C);
3461 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3462 W_REG(osh, &cc->pllcontrol_data, 0x202C2820);
3464 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3465 W_REG(osh, &cc->pllcontrol_data, 0x88888825);
3467 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3468 if (spuravoid == 1) {
3469 W_REG(osh, &cc->pllcontrol_data, 0x00EC4EC4);
3470 } else {
3471 W_REG(osh, &cc->pllcontrol_data, 0x00762762);
3474 tmp = PCTL_PLL_PLLCTL_UPD;
3475 break;
3476 case BCM43131_CHIP_ID:
3477 case BCM43227_CHIP_ID:
3478 case BCM43228_CHIP_ID:
3479 case BCM43428_CHIP_ID:
3480 /* LCNXN */
3481 /* PLL Settings for spur avoidance on/off mode, no on2 support for 43228A0 */
3482 if (spuravoid == 1) {
3483 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3484 W_REG(osh, &cc->pllcontrol_data, 0x01100014);
3485 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3486 W_REG(osh, &cc->pllcontrol_data, 0x040C0C06);
3487 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3488 W_REG(osh, &cc->pllcontrol_data, 0x03140A08);
3489 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3490 W_REG(osh, &cc->pllcontrol_data, 0x00333333);
3491 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3492 W_REG(osh, &cc->pllcontrol_data, 0x202C2820);
3493 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3494 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3495 } else {
3496 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3497 W_REG(osh, &cc->pllcontrol_data, 0x11100014);
3498 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3499 W_REG(osh, &cc->pllcontrol_data, 0x040c0c06);
3500 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3501 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3502 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3503 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3504 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3505 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3506 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3507 W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3509 tmp = 1 << 10;
3510 break;
3511 default:
3512 PMU_ERROR(("%s: unknown spuravoidance settings for chip %s, not changing PLL\n",
3513 __FUNCTION__, bcm_chipname(sih->chip, chn, 8)));
3514 break;
3517 tmp |= R_REG(osh, &cc->pmucontrol);
3518 W_REG(osh, &cc->pmucontrol, tmp);
3521 void
3522 si_pmu_gband_spurwar(si_t *sih, osl_t *osh)
3524 chipcregs_t *cc;
3525 uint origidx, intr_val;
3526 uint32 cc_clk_ctl_st;
3527 uint32 minmask, maxmask;
3529 if ((CHIPID(sih->chip) == BCM43222_CHIP_ID) ||
3530 (CHIPID(sih->chip) == BCM43420_CHIP_ID)) {
3531 /* Remember original core before switch to chipc */
3532 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
3533 ASSERT(cc != NULL);
3535 /* Remove force HT and HT Avail Request from chipc core */
3536 cc_clk_ctl_st = R_REG(osh, &cc->clk_ctl_st);
3537 AND_REG(osh, &cc->clk_ctl_st, ~(CCS_FORCEHT | CCS_HTAREQ));
3539 minmask = R_REG(osh, &cc->min_res_mask);
3540 maxmask = R_REG(osh, &cc->max_res_mask);
3542 /* Make sure the PLL is off: clear bit 4 & 5 of min/max_res_mask */
3543 /* Have to remove HT Avail request before powering off PLL */
3544 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
3545 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
3546 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
3547 AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
3548 AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4322_SI_PLL_ON)));
3549 OSL_DELAY(150);
3550 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
3552 /* Change backplane clock speed from 96 MHz to 80 MHz */
3553 W_REG(osh, &cc->pllcontrol_addr, PMU2_PLL_PLLCTL2);
3554 W_REG(osh, &cc->pllcontrol_data, (R_REG(osh, &cc->pllcontrol_data) &
3555 ~(PMU2_PLL_PC2_M6DIV_MASK)) |
3556 (0xc << PMU2_PLL_PC2_M6DIV_SHIFT));
3558 /* Reduce the driver strengths of the phyclk160, adcclk80, and phyck80
3559 * clocks from 0x8 to 0x1
3561 W_REG(osh, &cc->pllcontrol_addr, PMU2_PLL_PLLCTL5);
3562 W_REG(osh, &cc->pllcontrol_data, (R_REG(osh, &cc->pllcontrol_data) &
3563 ~(PMU2_PLL_PC5_CLKDRIVE_CH1_MASK |
3564 PMU2_PLL_PC5_CLKDRIVE_CH2_MASK |
3565 PMU2_PLL_PC5_CLKDRIVE_CH3_MASK |
3566 PMU2_PLL_PC5_CLKDRIVE_CH4_MASK)) |
3567 ((1 << PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT) |
3568 (1 << PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT) |
3569 (1 << PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT) |
3570 (1 << PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT)));
3572 W_REG(osh, &cc->pmucontrol, R_REG(osh, &cc->pmucontrol) | PCTL_PLL_PLLCTL_UPD);
3574 /* Restore min_res_mask and max_res_mask */
3575 OSL_DELAY(100);
3576 W_REG(osh, &cc->max_res_mask, maxmask);
3577 OSL_DELAY(100);
3578 W_REG(osh, &cc->min_res_mask, minmask);
3579 OSL_DELAY(100);
3580 /* Make sure the PLL is on. Spinwait until the HTAvail is True */
3581 SPINWAIT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL), PMU_MAX_TRANSITION_DLY);
3582 ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
3584 /* Restore force HT and HT Avail Request on the chipc core */
3585 W_REG(osh, &cc->clk_ctl_st, cc_clk_ctl_st);
3587 /* Return to original core */
3588 si_restore_core(sih, origidx, intr_val);
3592 bool
3593 si_pmu_is_otp_powered(si_t *sih, osl_t *osh)
3595 uint idx;
3596 chipcregs_t *cc;
3597 bool st;
3599 /* Remember original core before switch to chipc */
3600 idx = si_coreidx(sih);
3601 cc = si_setcoreidx(sih, SI_CC_IDX);
3602 ASSERT(cc != NULL);
3604 switch (CHIPID(sih->chip)) {
3605 case BCM4322_CHIP_ID:
3606 case BCM43221_CHIP_ID:
3607 case BCM43231_CHIP_ID:
3608 case BCM4342_CHIP_ID:
3609 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4322_OTP_PU)) != 0;
3610 break;
3611 case BCM4325_CHIP_ID:
3612 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4325_OTP_PU)) != 0;
3613 break;
3614 case BCM4329_CHIP_ID:
3615 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4329_OTP_PU)) != 0;
3616 break;
3617 case BCM4315_CHIP_ID:
3618 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4315_OTP_PU)) != 0;
3619 break;
3620 case BCM4319_CHIP_ID:
3621 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4319_OTP_PU)) != 0;
3622 break;
3623 case BCM4336_CHIP_ID:
3624 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4336_OTP_PU)) != 0;
3625 break;
3626 case BCM4330_CHIP_ID:
3627 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4330_OTP_PU)) != 0;
3628 break;
3630 /* These chip doesn't use PMU bit to power up/down OTP. OTP always on.
3631 * Use OTP_INIT command to reset/refresh state.
3633 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
3634 case BCM43224_CHIP_ID: case BCM43225_CHIP_ID: case BCM43421_CHIP_ID:
3635 case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID:
3636 case BCM43234_CHIP_ID: case BCM43237_CHIP_ID: case BCM43420_CHIP_ID:
3637 case BCM4331_CHIP_ID: case BCM43431_CHIP_ID:
3638 st = TRUE;
3639 break;
3640 default:
3641 st = TRUE;
3642 break;
3645 /* Return to original core */
3646 si_setcoreidx(sih, idx);
3647 return st;
3649 #endif /* !_CFE_ || CFG_WL */
3651 void
3652 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
3653 si_pmu_sprom_enable(si_t *sih, osl_t *osh, bool enable)
3654 #else
3655 BCMATTACHFN(si_pmu_sprom_enable)(si_t *sih, osl_t *osh, bool enable)
3656 #endif
3658 chipcregs_t *cc;
3659 uint origidx;
3661 /* Remember original core before switch to chipc */
3662 origidx = si_coreidx(sih);
3663 cc = si_setcoreidx(sih, SI_CC_IDX);
3664 ASSERT(cc != NULL);
3666 switch (CHIPID(sih->chip)) {
3667 case BCM4315_CHIP_ID:
3668 if (CHIPREV(sih->chiprev) < 1)
3669 break;
3670 if (sih->chipst & CST4315_SPROM_SEL) {
3671 uint32 val;
3672 W_REG(osh, &cc->chipcontrol_addr, 0);
3673 val = R_REG(osh, &cc->chipcontrol_data);
3674 if (enable)
3675 val &= ~0x80000000;
3676 else
3677 val |= 0x80000000;
3678 W_REG(osh, &cc->chipcontrol_data, val);
3680 break;
3681 default:
3682 break;
3685 /* Return to original core */
3686 si_setcoreidx(sih, origidx);
3689 bool
3690 #if defined(BCMDBG) || defined(WLTEST) || defined(BCMDBG_ERR)
3691 si_pmu_is_sprom_enabled(si_t *sih, osl_t *osh)
3692 #else
3693 BCMATTACHFN(si_pmu_is_sprom_enabled)(si_t *sih, osl_t *osh)
3694 #endif
3696 chipcregs_t *cc;
3697 uint origidx;
3698 bool enable = TRUE;
3700 /* Remember original core before switch to chipc */
3701 origidx = si_coreidx(sih);
3702 cc = si_setcoreidx(sih, SI_CC_IDX);
3703 ASSERT(cc != NULL);
3705 switch (CHIPID(sih->chip)) {
3706 case BCM4315_CHIP_ID:
3707 if (CHIPREV(sih->chiprev) < 1)
3708 break;
3709 if (!(sih->chipst & CST4315_SPROM_SEL))
3710 break;
3711 W_REG(osh, &cc->chipcontrol_addr, 0);
3712 if (R_REG(osh, &cc->chipcontrol_data) & 0x80000000)
3713 enable = FALSE;
3714 break;
3715 default:
3716 break;
3719 /* Return to original core */
3720 si_setcoreidx(sih, origidx);
3721 return enable;
3724 /* initialize PMU chip controls and other chip level stuff */
3725 void
3726 BCMATTACHFN(si_pmu_chip_init)(si_t *sih, osl_t *osh)
3728 uint origidx;
3730 ASSERT(sih->cccaps & CC_CAP_PMU);
3732 #ifdef CHIPC_UART_ALWAYS_ON
3733 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), CCS_FORCEALP, CCS_FORCEALP);
3734 #endif /* CHIPC_UART_ALWAYS_ON */
3736 #ifndef CONFIG_XIP
3737 /* Gate off SPROM clock and chip select signals */
3738 si_pmu_sprom_enable(sih, osh, FALSE);
3739 #endif
3741 /* Remember original core */
3742 origidx = si_coreidx(sih);
3744 #if !defined(_CFE_) || defined(CFG_WL)
3745 /* Misc. chip control, has nothing to do with PMU */
3746 switch (CHIPID(sih->chip)) {
3747 case BCM4315_CHIP_ID:
3748 #ifdef BCMUSBDEV
3749 si_setcore(sih, PCMCIA_CORE_ID, 0);
3750 si_core_disable(sih, 0);
3751 #endif
3752 break;
3753 case BCM4319_CHIP_ID:
3754 /* No support for external LPO, so power it down */
3755 si_pmu_chipcontrol(sih, 0, (1<<28), (0<<28));
3756 break;
3757 default:
3758 break;
3760 #endif /* !_CFE_ || CFG_WL */
3762 /* Return to original core */
3763 si_setcoreidx(sih, origidx);
3766 /* initialize PMU switch/regulators */
3767 void
3768 BCMATTACHFN(si_pmu_swreg_init)(si_t *sih, osl_t *osh)
3770 #if !defined(_CFE_) || defined(CFG_WL)
3771 ASSERT(sih->cccaps & CC_CAP_PMU);
3773 switch (CHIPID(sih->chip)) {
3774 case BCM4325_CHIP_ID:
3775 if (CHIPREV(sih->chiprev) < 3)
3776 break;
3777 if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >> CST4325_PMUTOP_2B_SHIFT) == 1) {
3778 /* Bump CLDO PWM output voltage to 1.25V */
3779 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xf);
3780 /* Bump CLDO BURST output voltage to 1.25V */
3781 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_BURST, 0xf);
3783 /* Bump CBUCK PWM output voltage to 1.5V */
3784 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0xb);
3785 /* Bump CBUCK BURST output voltage to 1.5V */
3786 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_BURST, 0xb);
3787 /* Bump LNLDO1 output voltage to 1.25V */
3788 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO1, 0x1);
3789 /* Select LNLDO2 output voltage to 2.5V */
3790 if (sih->boardflags & BFL_LNLDO2_2P5)
3791 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO2_SEL, 0x1);
3792 break;
3793 case BCM4315_CHIP_ID: {
3794 uint32 val;
3795 chipcregs_t *cc;
3796 uint origidx;
3798 if (CHIPREV(sih->chiprev) != 2)
3799 break;
3801 /* Remember original core before switch to chipc */
3802 origidx = si_coreidx(sih);
3803 cc = si_setcoreidx(sih, SI_CC_IDX);
3804 ASSERT(cc != NULL);
3806 W_REG(osh, &cc->regcontrol_addr, 4);
3807 val = R_REG(osh, &cc->regcontrol_data);
3808 val |= (uint32)(1 << 16);
3809 W_REG(osh, &cc->regcontrol_data, val);
3811 /* Return to original core */
3812 si_setcoreidx(sih, origidx);
3813 break;
3815 case BCM4336_CHIP_ID:
3816 /* Reduce CLDO PWM output voltage to 1.2V */
3817 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xe);
3818 /* Reduce CLDO BURST output voltage to 1.2V */
3819 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_BURST, 0xe);
3820 /* Reduce LNLDO1 output voltage to 1.2V */
3821 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO1, 0xe);
3822 if (CHIPREV(sih->chiprev) == 0)
3823 si_pmu_regcontrol(sih, 2, 0x400000, 0x400000);
3824 break;
3826 case BCM4330_CHIP_ID:
3827 /* CBUCK Voltage is 1.8 by default and set that to 1.5 */
3828 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0);
3829 break;
3830 default:
3831 break;
3833 #endif /* !_CFE_ || CFG_WL */
3836 void
3837 si_pmu_radio_enable(si_t *sih, bool enable)
3839 ASSERT(sih->cccaps & CC_CAP_PMU);
3841 switch (CHIPID(sih->chip)) {
3842 case BCM4325_CHIP_ID:
3843 if (sih->boardflags & BFL_FASTPWR)
3844 break;
3846 if ((sih->boardflags & BFL_BUCKBOOST)) {
3847 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask),
3848 PMURES_BIT(RES4325_BUCK_BOOST_BURST),
3849 enable ? PMURES_BIT(RES4325_BUCK_BOOST_BURST) : 0);
3852 if (enable) {
3853 OSL_DELAY(100 * 1000);
3855 break;
3856 case BCM4319_CHIP_ID:
3857 if (enable)
3858 si_write_wrapperreg(sih, AI_OOBSELOUTB74, (uint32)0x868584);
3859 else
3860 si_write_wrapperreg(sih, AI_OOBSELOUTB74, (uint32)0x060584);
3861 break;
3865 /* Wait for a particular clock level to be on the backplane */
3866 uint32
3867 si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, uint32 clk, uint32 delay_val)
3869 chipcregs_t *cc;
3870 uint origidx;
3872 ASSERT(sih->cccaps & CC_CAP_PMU);
3874 /* Remember original core before switch to chipc */
3875 origidx = si_coreidx(sih);
3876 cc = si_setcoreidx(sih, SI_CC_IDX);
3877 ASSERT(cc != NULL);
3879 if (delay_val)
3880 SPINWAIT(((R_REG(osh, &cc->pmustatus) & clk) != clk), delay_val);
3882 /* Return to original core */
3883 si_setcoreidx(sih, origidx);
3885 return (R_REG(osh, &cc->pmustatus) & clk);
3889 * Measures the ALP clock frequency in KHz. Returns 0 if not possible.
3890 * Possible only if PMU rev >= 10 and there is an external LPO 32768Hz crystal.
3893 #define EXT_ILP_HZ 32768
3895 uint32
3896 BCMATTACHFN(si_pmu_measure_alpclk)(si_t *sih, osl_t *osh)
3898 chipcregs_t *cc;
3899 uint origidx;
3900 uint32 alp_khz;
3902 if (sih->pmurev < 10)
3903 return 0;
3905 ASSERT(sih->cccaps & CC_CAP_PMU);
3907 /* Remember original core before switch to chipc */
3908 origidx = si_coreidx(sih);
3909 cc = si_setcoreidx(sih, SI_CC_IDX);
3910 ASSERT(cc != NULL);
3912 if (R_REG(osh, &cc->pmustatus) & PST_EXTLPOAVAIL) {
3913 uint32 ilp_ctr, alp_hz;
3915 /* Enable the reg to measure the freq, in case disabled before */
3916 W_REG(osh, &cc->pmu_xtalfreq, 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
3918 /* Delay for well over 4 ILP clocks */
3919 OSL_DELAY(1000);
3921 /* Read the latched number of ALP ticks per 4 ILP ticks */
3922 ilp_ctr = R_REG(osh, &cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
3924 /* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT bit to save power */
3925 W_REG(osh, &cc->pmu_xtalfreq, 0);
3927 /* Calculate ALP frequency */
3928 alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
3930 /* Round to nearest 100KHz, and at the same time convert to KHz */
3931 alp_khz = (alp_hz + 50000) / 100000 * 100;
3932 } else
3933 alp_khz = 0;
3935 /* Return to original core */
3936 si_setcoreidx(sih, origidx);
3938 return alp_khz;
3941 #if !defined(_CFE_) || defined(CFG_WL)
3942 void
3943 si_pmu_set_4330_plldivs(si_t *sih, uint8 dacrate)
3945 uint32 FVCO = si_pmu1_pllfvco0(sih)/1000;
3946 uint32 m1div, m2div, m3div, m4div, m5div, m6div;
3947 uint32 pllc1, pllc2;
3949 m2div = m3div = m4div = m6div = FVCO/80;
3951 m5div = FVCO/dacrate;
3953 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
3954 m1div = FVCO/80;
3955 else
3956 m1div = FVCO/90;
3957 pllc1 = (m1div << PMU1_PLL0_PC1_M1DIV_SHIFT) | (m2div << PMU1_PLL0_PC1_M2DIV_SHIFT) |
3958 (m3div << PMU1_PLL0_PC1_M3DIV_SHIFT) | (m4div << PMU1_PLL0_PC1_M4DIV_SHIFT);
3959 si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, ~0, pllc1);
3961 pllc2 = si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL2, 0, 0);
3962 pllc2 &= ~(PMU1_PLL0_PC2_M5DIV_MASK | PMU1_PLL0_PC2_M6DIV_MASK);
3963 pllc2 |= ((m5div << PMU1_PLL0_PC2_M5DIV_SHIFT) | (m6div << PMU1_PLL0_PC2_M6DIV_SHIFT));
3964 si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL2, ~0, pllc2);
3966 #endif /* !_CFE_ || CFG_WL */