Staging: Add initial release of brcm80211 - Broadcom 802.11n wireless LAN driver.
[linux-2.6-block.git] / drivers / staging / brcm80211 / util / hndpmu.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <typedefs.h>
18 #include <bcmdefs.h>
19 #include <osl.h>
20 #include <bcmutils.h>
21 #include <siutils.h>
22 #include <bcmdevs.h>
23 #include <hndsoc.h>
24 #include <sbchipc.h>
25 #include <hndpmu.h>
26 #include "siutils_priv.h"
27
28 #define PMU_ERROR(args)
29
30 #ifdef BCMDBG
31 #define PMU_MSG(args)   printf args
32 #else
33 #define PMU_MSG(args)
34 #endif                          /* BCMDBG */
35
36 /* To check in verbose debugging messages not intended
37  * to be on except on private builds.
38  */
39 #define PMU_NONE(args)
40
41 /* PLL controls/clocks */
42 static void si_pmu1_pllinit0(si_t * sih, osl_t * osh, chipcregs_t * cc,
43                              uint32 xtal);
44 static uint32 si_pmu1_cpuclk0(si_t * sih, osl_t * osh, chipcregs_t * cc);
45 static uint32 si_pmu1_alpclk0(si_t * sih, osl_t * osh, chipcregs_t * cc);
46
47 /* PMU resources */
48 static bool si_pmu_res_depfltr_bb(si_t * sih);
49 static bool si_pmu_res_depfltr_ncb(si_t * sih);
50 static bool si_pmu_res_depfltr_paldo(si_t * sih);
51 static bool si_pmu_res_depfltr_npaldo(si_t * sih);
52 static uint32 si_pmu_res_deps(si_t * sih, osl_t * osh, chipcregs_t * cc,
53                               uint32 rsrcs, bool all);
54 static uint si_pmu_res_uptime(si_t * sih, osl_t * osh, chipcregs_t * cc,
55                               uint8 rsrc);
56 static void si_pmu_res_masks(si_t * sih, uint32 * pmin, uint32 * pmax);
57 static void si_pmu_spuravoid_pllupdate(si_t * sih, chipcregs_t * cc,
58                                        osl_t * osh, uint8 spuravoid);
59
60 static void si_pmu_set_4330_plldivs(si_t * sih);
61
62 /* FVCO frequency */
63 #define FVCO_880        880000  /* 880MHz */
64 #define FVCO_1760       1760000 /* 1760MHz */
65 #define FVCO_1440       1440000 /* 1440MHz */
66 #define FVCO_960        960000  /* 960MHz */
67
68 /* Read/write a chipcontrol reg */
69 uint32 si_pmu_chipcontrol(si_t * sih, uint reg, uint32 mask, uint32 val)
70 {
71         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr), ~0,
72                    reg);
73         return si_corereg(sih, SI_CC_IDX,
74                           OFFSETOF(chipcregs_t, chipcontrol_data), mask, val);
75 }
76
77 /* Read/write a regcontrol reg */
78 uint32 si_pmu_regcontrol(si_t * sih, uint reg, uint32 mask, uint32 val)
79 {
80         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_addr), ~0,
81                    reg);
82         return si_corereg(sih, SI_CC_IDX,
83                           OFFSETOF(chipcregs_t, regcontrol_data), mask, val);
84 }
85
86 /* Read/write a pllcontrol reg */
87 uint32 si_pmu_pllcontrol(si_t * sih, uint reg, uint32 mask, uint32 val)
88 {
89         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pllcontrol_addr), ~0,
90                    reg);
91         return si_corereg(sih, SI_CC_IDX,
92                           OFFSETOF(chipcregs_t, pllcontrol_data), mask, val);
93 }
94
95 /* PMU PLL update */
96 void si_pmu_pllupd(si_t * sih)
97 {
98         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmucontrol),
99                    PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
100 }
101
102 /* Setup switcher voltage */
103 void
104 BCMATTACHFN(si_pmu_set_switcher_voltage) (si_t * sih, osl_t * osh,
105                                           uint8 bb_voltage, uint8 rf_voltage) {
106         chipcregs_t *cc;
107         uint origidx;
108
109         ASSERT(sih->cccaps & CC_CAP_PMU);
110
111         /* Remember original core before switch to chipc */
112         origidx = si_coreidx(sih);
113         cc = si_setcoreidx(sih, SI_CC_IDX);
114         ASSERT(cc != NULL);
115
116         W_REG(osh, &cc->regcontrol_addr, 0x01);
117         W_REG(osh, &cc->regcontrol_data, (uint32) (bb_voltage & 0x1f) << 22);
118
119         W_REG(osh, &cc->regcontrol_addr, 0x00);
120         W_REG(osh, &cc->regcontrol_data, (uint32) (rf_voltage & 0x1f) << 14);
121
122         /* Return to original core */
123         si_setcoreidx(sih, origidx);
124 }
125
126 void
127 BCMATTACHFN(si_pmu_set_ldo_voltage) (si_t * sih, osl_t * osh, uint8 ldo,
128                                      uint8 voltage) {
129         uint8 sr_cntl_shift = 0, rc_shift = 0, shift = 0, mask = 0;
130         uint8 addr = 0;
131
132         ASSERT(sih->cccaps & CC_CAP_PMU);
133
134         switch (CHIPID(sih->chip)) {
135         case BCM4336_CHIP_ID:
136                 switch (ldo) {
137                 case SET_LDO_VOLTAGE_CLDO_PWM:
138                         addr = 4;
139                         rc_shift = 1;
140                         mask = 0xf;
141                         break;
142                 case SET_LDO_VOLTAGE_CLDO_BURST:
143                         addr = 4;
144                         rc_shift = 5;
145                         mask = 0xf;
146                         break;
147                 case SET_LDO_VOLTAGE_LNLDO1:
148                         addr = 4;
149                         rc_shift = 17;
150                         mask = 0xf;
151                         break;
152                 default:
153                         ASSERT(FALSE);
154                         return;
155                 }
156                 break;
157         case BCM4330_CHIP_ID:
158                 switch (ldo) {
159                 case SET_LDO_VOLTAGE_CBUCK_PWM:
160                         addr = 3;
161                         rc_shift = 0;
162                         mask = 0x1f;
163                         break;
164                 default:
165                         ASSERT(FALSE);
166                         break;
167                 }
168                 break;
169         default:
170                 ASSERT(FALSE);
171                 return;
172         }
173
174         shift = sr_cntl_shift + rc_shift;
175
176         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_addr),
177                    ~0, addr);
178         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_data),
179                    mask << shift, (voltage & mask) << shift);
180 }
181
182 /* d11 slow to fast clock transition time in slow clock cycles */
183 #define D11SCC_SLOW2FAST_TRANSITION     2
184
185 uint16 BCMINITFN(si_pmu_fast_pwrup_delay) (si_t * sih, osl_t * osh) {
186         uint delay = PMU_MAX_TRANSITION_DLY;
187         chipcregs_t *cc;
188         uint origidx;
189 #ifdef BCMDBG
190         char chn[8];
191         chn[0] = 0;             /* to suppress compile error */
192 #endif
193
194         ASSERT(sih->cccaps & CC_CAP_PMU);
195
196         /* Remember original core before switch to chipc */
197         origidx = si_coreidx(sih);
198         cc = si_setcoreidx(sih, SI_CC_IDX);
199         ASSERT(cc != NULL);
200
201         switch (CHIPID(sih->chip)) {
202         case BCM43224_CHIP_ID:
203         case BCM43225_CHIP_ID:
204         case BCM43421_CHIP_ID:
205         case BCM43235_CHIP_ID:
206         case BCM43236_CHIP_ID:
207         case BCM43238_CHIP_ID:
208         case BCM4331_CHIP_ID:
209         case BCM6362_CHIP_ID:
210         case BCM4313_CHIP_ID:
211                 delay = ISSIM_ENAB(sih) ? 70 : 3700;
212                 break;
213         case BCM4329_CHIP_ID:
214                 if (ISSIM_ENAB(sih))
215                         delay = 70;
216                 else {
217                         uint32 ilp = si_ilp_clock(sih);
218                         delay =
219                             (si_pmu_res_uptime(sih, osh, cc, RES4329_HT_AVAIL) +
220                              D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp -
221                                                               1) / ilp);
222                         delay = (11 * delay) / 10;
223                 }
224                 break;
225         case BCM4319_CHIP_ID:
226                 delay = ISSIM_ENAB(sih) ? 70 : 3700;
227                 break;
228         case BCM4336_CHIP_ID:
229                 if (ISSIM_ENAB(sih))
230                         delay = 70;
231                 else {
232                         uint32 ilp = si_ilp_clock(sih);
233                         delay =
234                             (si_pmu_res_uptime(sih, osh, cc, RES4336_HT_AVAIL) +
235                              D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp -
236                                                               1) / ilp);
237                         delay = (11 * delay) / 10;
238                 }
239                 break;
240         case BCM4330_CHIP_ID:
241                 if (ISSIM_ENAB(sih))
242                         delay = 70;
243                 else {
244                         uint32 ilp = si_ilp_clock(sih);
245                         delay =
246                             (si_pmu_res_uptime(sih, osh, cc, RES4330_HT_AVAIL) +
247                              D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp -
248                                                               1) / ilp);
249                         delay = (11 * delay) / 10;
250                 }
251                 break;
252         default:
253                 break;
254         }
255         /* Return to original core */
256         si_setcoreidx(sih, origidx);
257
258         return (uint16) delay;
259 }
260
261 uint32 BCMATTACHFN(si_pmu_force_ilp) (si_t * sih, osl_t * osh, bool force) {
262         chipcregs_t *cc;
263         uint origidx;
264         uint32 oldpmucontrol;
265
266         ASSERT(sih->cccaps & CC_CAP_PMU);
267
268         /* Remember original core before switch to chipc */
269         origidx = si_coreidx(sih);
270         cc = si_setcoreidx(sih, SI_CC_IDX);
271         ASSERT(cc != NULL);
272
273         oldpmucontrol = R_REG(osh, &cc->pmucontrol);
274         if (force)
275                 W_REG(osh, &cc->pmucontrol, oldpmucontrol &
276                       ~(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
277         else
278                 W_REG(osh, &cc->pmucontrol, oldpmucontrol |
279                       (PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
280
281         /* Return to original core */
282         si_setcoreidx(sih, origidx);
283
284         return oldpmucontrol;
285 }
286
287 /* Setup resource up/down timers */
288 typedef struct {
289         uint8 resnum;
290         uint16 updown;
291 } pmu_res_updown_t;
292
293 /* Change resource dependancies masks */
294 typedef struct {
295         uint32 res_mask;        /* resources (chip specific) */
296         int8 action;            /* action */
297         uint32 depend_mask;     /* changes to the dependancies mask */
298          bool(*filter) (si_t * sih);    /* action is taken when filter is NULL or return TRUE */
299 } pmu_res_depend_t;
300
301 /* Resource dependancies mask change action */
302 #define RES_DEPEND_SET          0       /* Override the dependancies mask */
303 #define RES_DEPEND_ADD          1       /* Add to the  dependancies mask */
304 #define RES_DEPEND_REMOVE       -1      /* Remove from the dependancies mask */
305
306 static const pmu_res_updown_t BCMATTACHDATA(bcm4328a0_res_updown)[] =
307 {
308         {
309         RES4328_EXT_SWITCHER_PWM, 0x0101}, {
310         RES4328_BB_SWITCHER_PWM, 0x1f01}, {
311         RES4328_BB_SWITCHER_BURST, 0x010f}, {
312         RES4328_BB_EXT_SWITCHER_BURST, 0x0101}, {
313         RES4328_ILP_REQUEST, 0x0202}, {
314         RES4328_RADIO_SWITCHER_PWM, 0x0f01}, {
315         RES4328_RADIO_SWITCHER_BURST, 0x0f01}, {
316         RES4328_ROM_SWITCH, 0x0101}, {
317         RES4328_PA_REF_LDO, 0x0f01}, {
318         RES4328_RADIO_LDO, 0x0f01}, {
319         RES4328_AFE_LDO, 0x0f01}, {
320         RES4328_PLL_LDO, 0x0f01}, {
321         RES4328_BG_FILTBYP, 0x0101}, {
322         RES4328_TX_FILTBYP, 0x0101}, {
323         RES4328_RX_FILTBYP, 0x0101}, {
324         RES4328_XTAL_PU, 0x0101}, {
325         RES4328_XTAL_EN, 0xa001}, {
326         RES4328_BB_PLL_FILTBYP, 0x0101}, {
327         RES4328_RF_PLL_FILTBYP, 0x0101}, {
328         RES4328_BB_PLL_PU, 0x0701}
329 };
330
331 static const pmu_res_depend_t BCMATTACHDATA(bcm4328a0_res_depend)[] =
332 {
333         /* Adjust ILP request resource not to force ext/BB switchers into burst mode */
334         {
335         PMURES_BIT(RES4328_ILP_REQUEST),
336                     RES_DEPEND_SET,
337                     PMURES_BIT(RES4328_EXT_SWITCHER_PWM) |
338                     PMURES_BIT(RES4328_BB_SWITCHER_PWM), NULL}
339 };
340
341 static const pmu_res_updown_t BCMATTACHDATA(bcm4325a0_res_updown_qt)[] =
342 {
343         {
344         RES4325_HT_AVAIL, 0x0300}, {
345         RES4325_BBPLL_PWRSW_PU, 0x0101}, {
346         RES4325_RFPLL_PWRSW_PU, 0x0101}, {
347         RES4325_ALP_AVAIL, 0x0100}, {
348         RES4325_XTAL_PU, 0x1000}, {
349         RES4325_LNLDO1_PU, 0x0800}, {
350         RES4325_CLDO_CBUCK_PWM, 0x0101}, {
351         RES4325_CBUCK_PWM, 0x0803}
352 };
353
354 static const pmu_res_updown_t BCMATTACHDATA(bcm4325a0_res_updown)[] =
355 {
356         {
357         RES4325_XTAL_PU, 0x1501}
358 };
359
360 static const pmu_res_depend_t BCMATTACHDATA(bcm4325a0_res_depend)[] =
361 {
362         /* Adjust OTP PU resource dependencies - remove BB BURST */
363         {
364         PMURES_BIT(RES4325_OTP_PU),
365                     RES_DEPEND_REMOVE,
366                     PMURES_BIT(RES4325_BUCK_BOOST_BURST), NULL},
367             /* Adjust ALP/HT Avail resource dependencies - bring up BB along if it is used. */
368         {
369         PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_HT_AVAIL),
370                     RES_DEPEND_ADD,
371                     PMURES_BIT(RES4325_BUCK_BOOST_BURST) |
372                     PMURES_BIT(RES4325_BUCK_BOOST_PWM), si_pmu_res_depfltr_bb},
373             /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
374         {
375         PMURES_BIT(RES4325_HT_AVAIL),
376                     RES_DEPEND_ADD,
377                     PMURES_BIT(RES4325_RX_PWRSW_PU) |
378                     PMURES_BIT(RES4325_TX_PWRSW_PU) |
379                     PMURES_BIT(RES4325_LOGEN_PWRSW_PU) |
380                     PMURES_BIT(RES4325_AFE_PWRSW_PU), NULL},
381             /* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
382         {
383         PMURES_BIT(RES4325_ILP_REQUEST) |
384                     PMURES_BIT(RES4325_ABUCK_BURST) |
385                     PMURES_BIT(RES4325_ABUCK_PWM) |
386                     PMURES_BIT(RES4325_LNLDO1_PU) |
387                     PMURES_BIT(RES4325C1_LNLDO2_PU) |
388                     PMURES_BIT(RES4325_XTAL_PU) |
389                     PMURES_BIT(RES4325_ALP_AVAIL) |
390                     PMURES_BIT(RES4325_RX_PWRSW_PU) |
391                     PMURES_BIT(RES4325_TX_PWRSW_PU) |
392                     PMURES_BIT(RES4325_RFPLL_PWRSW_PU) |
393                     PMURES_BIT(RES4325_LOGEN_PWRSW_PU) |
394                     PMURES_BIT(RES4325_AFE_PWRSW_PU) |
395                     PMURES_BIT(RES4325_BBPLL_PWRSW_PU) |
396                     PMURES_BIT(RES4325_HT_AVAIL), RES_DEPEND_REMOVE,
397                     PMURES_BIT(RES4325B0_CBUCK_LPOM) |
398                     PMURES_BIT(RES4325B0_CBUCK_BURST) |
399                     PMURES_BIT(RES4325B0_CBUCK_PWM), si_pmu_res_depfltr_ncb}
400 };
401
402 static const pmu_res_updown_t BCMATTACHDATA(bcm4315a0_res_updown_qt)[] =
403 {
404         {
405         RES4315_HT_AVAIL, 0x0101}, {
406         RES4315_XTAL_PU, 0x0100}, {
407         RES4315_LNLDO1_PU, 0x0100}, {
408         RES4315_PALDO_PU, 0x0100}, {
409         RES4315_CLDO_PU, 0x0100}, {
410         RES4315_CBUCK_PWM, 0x0100}, {
411         RES4315_CBUCK_BURST, 0x0100}, {
412         RES4315_CBUCK_LPOM, 0x0100}
413 };
414
415 static const pmu_res_updown_t BCMATTACHDATA(bcm4315a0_res_updown)[] =
416 {
417         {
418         RES4315_XTAL_PU, 0x2501}
419 };
420
421 static const pmu_res_depend_t BCMATTACHDATA(bcm4315a0_res_depend)[] =
422 {
423         /* Adjust OTP PU resource dependencies - not need PALDO unless write */
424         {
425         PMURES_BIT(RES4315_OTP_PU),
426                     RES_DEPEND_REMOVE,
427                     PMURES_BIT(RES4315_PALDO_PU), si_pmu_res_depfltr_npaldo},
428             /* Adjust ALP/HT Avail resource dependencies - bring up PALDO along if it is used. */
429         {
430         PMURES_BIT(RES4315_ALP_AVAIL) | PMURES_BIT(RES4315_HT_AVAIL),
431                     RES_DEPEND_ADD,
432                     PMURES_BIT(RES4315_PALDO_PU), si_pmu_res_depfltr_paldo},
433             /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
434         {
435         PMURES_BIT(RES4315_HT_AVAIL),
436                     RES_DEPEND_ADD,
437                     PMURES_BIT(RES4315_RX_PWRSW_PU) |
438                     PMURES_BIT(RES4315_TX_PWRSW_PU) |
439                     PMURES_BIT(RES4315_LOGEN_PWRSW_PU) |
440                     PMURES_BIT(RES4315_AFE_PWRSW_PU), NULL},
441             /* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
442         {
443         PMURES_BIT(RES4315_CLDO_PU) | PMURES_BIT(RES4315_ILP_REQUEST) |
444                     PMURES_BIT(RES4315_LNLDO1_PU) |
445                     PMURES_BIT(RES4315_OTP_PU) |
446                     PMURES_BIT(RES4315_LNLDO2_PU) |
447                     PMURES_BIT(RES4315_XTAL_PU) |
448                     PMURES_BIT(RES4315_ALP_AVAIL) |
449                     PMURES_BIT(RES4315_RX_PWRSW_PU) |
450                     PMURES_BIT(RES4315_TX_PWRSW_PU) |
451                     PMURES_BIT(RES4315_RFPLL_PWRSW_PU) |
452                     PMURES_BIT(RES4315_LOGEN_PWRSW_PU) |
453                     PMURES_BIT(RES4315_AFE_PWRSW_PU) |
454                     PMURES_BIT(RES4315_BBPLL_PWRSW_PU) |
455                     PMURES_BIT(RES4315_HT_AVAIL), RES_DEPEND_REMOVE,
456                     PMURES_BIT(RES4315_CBUCK_LPOM) |
457                     PMURES_BIT(RES4315_CBUCK_BURST) |
458                     PMURES_BIT(RES4315_CBUCK_PWM), si_pmu_res_depfltr_ncb}
459 };
460
461         /* 4329 specific. needs to come back this issue later */
462 static const pmu_res_updown_t BCMINITDATA(bcm4329_res_updown)[] =
463 {
464         {
465         RES4329_XTAL_PU, 0x1501}
466 };
467
468 static const pmu_res_depend_t BCMINITDATA(bcm4329_res_depend)[] =
469 {
470         /* Adjust HT Avail resource dependencies */
471         {
472         PMURES_BIT(RES4329_HT_AVAIL),
473                     RES_DEPEND_ADD,
474                     PMURES_BIT(RES4329_CBUCK_LPOM) |
475                     PMURES_BIT(RES4329_CBUCK_BURST) |
476                     PMURES_BIT(RES4329_CBUCK_PWM) |
477                     PMURES_BIT(RES4329_CLDO_PU) |
478                     PMURES_BIT(RES4329_PALDO_PU) |
479                     PMURES_BIT(RES4329_LNLDO1_PU) |
480                     PMURES_BIT(RES4329_XTAL_PU) |
481                     PMURES_BIT(RES4329_ALP_AVAIL) |
482                     PMURES_BIT(RES4329_RX_PWRSW_PU) |
483                     PMURES_BIT(RES4329_TX_PWRSW_PU) |
484                     PMURES_BIT(RES4329_RFPLL_PWRSW_PU) |
485                     PMURES_BIT(RES4329_LOGEN_PWRSW_PU) |
486                     PMURES_BIT(RES4329_AFE_PWRSW_PU) |
487                     PMURES_BIT(RES4329_BBPLL_PWRSW_PU), NULL}
488 };
489
490 static const pmu_res_updown_t BCMATTACHDATA(bcm4319a0_res_updown_qt)[] =
491 {
492         {
493         RES4319_HT_AVAIL, 0x0101}, {
494         RES4319_XTAL_PU, 0x0100}, {
495         RES4319_LNLDO1_PU, 0x0100}, {
496         RES4319_PALDO_PU, 0x0100}, {
497         RES4319_CLDO_PU, 0x0100}, {
498         RES4319_CBUCK_PWM, 0x0100}, {
499         RES4319_CBUCK_BURST, 0x0100}, {
500         RES4319_CBUCK_LPOM, 0x0100}
501 };
502
503 static const pmu_res_updown_t BCMATTACHDATA(bcm4319a0_res_updown)[] =
504 {
505         {
506         RES4319_XTAL_PU, 0x3f01}
507 };
508
509 static const pmu_res_depend_t BCMATTACHDATA(bcm4319a0_res_depend)[] =
510 {
511         /* Adjust OTP PU resource dependencies - not need PALDO unless write */
512         {
513         PMURES_BIT(RES4319_OTP_PU),
514                     RES_DEPEND_REMOVE,
515                     PMURES_BIT(RES4319_PALDO_PU), si_pmu_res_depfltr_npaldo},
516             /* Adjust HT Avail resource dependencies - bring up PALDO along if it is used. */
517         {
518         PMURES_BIT(RES4319_HT_AVAIL),
519                     RES_DEPEND_ADD,
520                     PMURES_BIT(RES4319_PALDO_PU), si_pmu_res_depfltr_paldo},
521             /* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
522         {
523         PMURES_BIT(RES4319_HT_AVAIL),
524                     RES_DEPEND_ADD,
525                     PMURES_BIT(RES4319_RX_PWRSW_PU) |
526                     PMURES_BIT(RES4319_TX_PWRSW_PU) |
527                     PMURES_BIT(RES4319_RFPLL_PWRSW_PU) |
528                     PMURES_BIT(RES4319_LOGEN_PWRSW_PU) |
529                     PMURES_BIT(RES4319_AFE_PWRSW_PU), NULL}
530 };
531
532 static const pmu_res_updown_t BCMATTACHDATA(bcm4336a0_res_updown_qt)[] =
533 {
534         {
535         RES4336_HT_AVAIL, 0x0101}, {
536         RES4336_XTAL_PU, 0x0100}, {
537         RES4336_CLDO_PU, 0x0100}, {
538         RES4336_CBUCK_PWM, 0x0100}, {
539         RES4336_CBUCK_BURST, 0x0100}, {
540         RES4336_CBUCK_LPOM, 0x0100}
541 };
542
543 static const pmu_res_updown_t BCMATTACHDATA(bcm4336a0_res_updown)[] =
544 {
545         {
546         RES4336_HT_AVAIL, 0x0D01}
547 };
548
549 static const pmu_res_depend_t BCMATTACHDATA(bcm4336a0_res_depend)[] =
550 {
551         /* Just a dummy entry for now */
552         {
553         PMURES_BIT(RES4336_RSVD), RES_DEPEND_ADD, 0, NULL}
554 };
555
556 static const pmu_res_updown_t BCMATTACHDATA(bcm4330a0_res_updown_qt)[] =
557 {
558         {
559         RES4330_HT_AVAIL, 0x0101}, {
560         RES4330_XTAL_PU, 0x0100}, {
561         RES4330_CLDO_PU, 0x0100}, {
562         RES4330_CBUCK_PWM, 0x0100}, {
563         RES4330_CBUCK_BURST, 0x0100}, {
564         RES4330_CBUCK_LPOM, 0x0100}
565 };
566
567 static const pmu_res_updown_t BCMATTACHDATA(bcm4330a0_res_updown)[] =
568 {
569         {
570         RES4330_HT_AVAIL, 0x0e02}
571 };
572
573 static const pmu_res_depend_t BCMATTACHDATA(bcm4330a0_res_depend)[] =
574 {
575         /* Just a dummy entry for now */
576         {
577         PMURES_BIT(RES4330_HT_AVAIL), RES_DEPEND_ADD, 0, NULL}
578 };
579
580 /* TRUE if the power topology uses the buck boost to provide 3.3V to VDDIO_RF and WLAN PA */
581 static bool BCMATTACHFN(si_pmu_res_depfltr_bb) (si_t * sih) {
582         return (sih->boardflags & BFL_BUCKBOOST) != 0;
583 }
584
585 /* TRUE if the power topology doesn't use the cbuck. Key on chiprev also if the chip is BCM4325. */
586 static bool BCMATTACHFN(si_pmu_res_depfltr_ncb) (si_t * sih) {
587
588         return ((sih->boardflags & BFL_NOCBUCK) != 0);
589 }
590
591 /* TRUE if the power topology uses the PALDO */
592 static bool BCMATTACHFN(si_pmu_res_depfltr_paldo) (si_t * sih) {
593         return (sih->boardflags & BFL_PALDO) != 0;
594 }
595
596 /* TRUE if the power topology doesn't use the PALDO */
597 static bool BCMATTACHFN(si_pmu_res_depfltr_npaldo) (si_t * sih) {
598         return (sih->boardflags & BFL_PALDO) == 0;
599 }
600
601 #define BCM94325_BBVDDIOSD_BOARDS(sih) (sih->boardtype == BCM94325DEVBU_BOARD || \
602                                         sih->boardtype == BCM94325BGABU_BOARD)
603
604 /* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
605 static void si_pmu_res_masks(si_t * sih, uint32 * pmin, uint32 * pmax)
606 {
607         uint32 min_mask = 0, max_mask = 0;
608         uint rsrcs;
609         char *val;
610
611         /* # resources */
612         rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
613
614         /* determine min/max rsrc masks */
615         switch (CHIPID(sih->chip)) {
616         case BCM43224_CHIP_ID:
617         case BCM43225_CHIP_ID:
618         case BCM43421_CHIP_ID:
619         case BCM43235_CHIP_ID:
620         case BCM43236_CHIP_ID:
621         case BCM43238_CHIP_ID:
622         case BCM4331_CHIP_ID:
623         case BCM6362_CHIP_ID:
624                 /* ??? */
625                 break;
626
627         case BCM4329_CHIP_ID:
628                 /* 4329 spedific issue. Needs to come back this issue later */
629                 /* Down to save the power. */
630                 min_mask =
631                     PMURES_BIT(RES4329_CBUCK_LPOM) |
632                     PMURES_BIT(RES4329_CLDO_PU);
633                 /* Allow (but don't require) PLL to turn on */
634                 max_mask = 0x3ff63e;
635                 break;
636         case BCM4319_CHIP_ID:
637                 /* We only need a few resources to be kept on all the time */
638                 min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
639                     PMURES_BIT(RES4319_CLDO_PU);
640
641                 /* Allow everything else to be turned on upon requests */
642                 max_mask = ~(~0 << rsrcs);
643                 break;
644         case BCM4336_CHIP_ID:
645                 /* Down to save the power. */
646                 min_mask =
647                     PMURES_BIT(RES4336_CBUCK_LPOM) | PMURES_BIT(RES4336_CLDO_PU)
648                     | PMURES_BIT(RES4336_LDO3P3_PU) | PMURES_BIT(RES4336_OTP_PU)
649                     | PMURES_BIT(RES4336_DIS_INT_RESET_PD);
650                 /* Allow (but don't require) PLL to turn on */
651                 max_mask = 0x1ffffff;
652                 break;
653
654         case BCM4330_CHIP_ID:
655                 /* Down to save the power. */
656                 min_mask =
657                     PMURES_BIT(RES4330_CBUCK_LPOM) | PMURES_BIT(RES4330_CLDO_PU)
658                     | PMURES_BIT(RES4330_DIS_INT_RESET_PD) |
659                     PMURES_BIT(RES4330_LDO3P3_PU) | PMURES_BIT(RES4330_OTP_PU);
660                 /* Allow (but don't require) PLL to turn on */
661                 max_mask = 0xfffffff;
662                 break;
663
664         case BCM4313_CHIP_ID:
665                 min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) |
666                     PMURES_BIT(RES4313_XTAL_PU_RSRC) |
667                     PMURES_BIT(RES4313_ALP_AVAIL_RSRC) |
668                     PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC);
669                 max_mask = 0xffff;
670                 break;
671         default:
672                 break;
673         }
674
675         /* Apply nvram override to min mask */
676         if ((val = getvar(NULL, "rmin")) != NULL) {
677                 PMU_MSG(("Applying rmin=%s to min_mask\n", val));
678                 min_mask = (uint32) bcm_strtoul(val, NULL, 0);
679         }
680         /* Apply nvram override to max mask */
681         if ((val = getvar(NULL, "rmax")) != NULL) {
682                 PMU_MSG(("Applying rmax=%s to max_mask\n", val));
683                 max_mask = (uint32) bcm_strtoul(val, NULL, 0);
684         }
685
686         *pmin = min_mask;
687         *pmax = max_mask;
688 }
689
690 /* initialize PMU resources */
691 void BCMATTACHFN(si_pmu_res_init) (si_t * sih, osl_t * osh) {
692         chipcregs_t *cc;
693         uint origidx;
694         const pmu_res_updown_t *pmu_res_updown_table = NULL;
695         uint pmu_res_updown_table_sz = 0;
696         const pmu_res_depend_t *pmu_res_depend_table = NULL;
697         uint pmu_res_depend_table_sz = 0;
698         uint32 min_mask = 0, max_mask = 0;
699         char name[8], *val;
700         uint i, rsrcs;
701
702         ASSERT(sih->cccaps & CC_CAP_PMU);
703
704         /* Remember original core before switch to chipc */
705         origidx = si_coreidx(sih);
706         cc = si_setcoreidx(sih, SI_CC_IDX);
707         ASSERT(cc != NULL);
708
709         switch (CHIPID(sih->chip)) {
710         case BCM4329_CHIP_ID:
711                 /* Optimize resources up/down timers */
712                 if (ISSIM_ENAB(sih)) {
713                         pmu_res_updown_table = NULL;
714                         pmu_res_updown_table_sz = 0;
715                 } else {
716                         pmu_res_updown_table = bcm4329_res_updown;
717                         pmu_res_updown_table_sz = ARRAYSIZE(bcm4329_res_updown);
718                 }
719                 /* Optimize resources dependencies */
720                 pmu_res_depend_table = bcm4329_res_depend;
721                 pmu_res_depend_table_sz = ARRAYSIZE(bcm4329_res_depend);
722                 break;
723
724         case BCM4319_CHIP_ID:
725                 /* Optimize resources up/down timers */
726                 if (ISSIM_ENAB(sih)) {
727                         pmu_res_updown_table = bcm4319a0_res_updown_qt;
728                         pmu_res_updown_table_sz =
729                             ARRAYSIZE(bcm4319a0_res_updown_qt);
730                 } else {
731                         pmu_res_updown_table = bcm4319a0_res_updown;
732                         pmu_res_updown_table_sz =
733                             ARRAYSIZE(bcm4319a0_res_updown);
734                 }
735                 /* Optimize resources dependancies masks */
736                 pmu_res_depend_table = bcm4319a0_res_depend;
737                 pmu_res_depend_table_sz = ARRAYSIZE(bcm4319a0_res_depend);
738                 break;
739
740         case BCM4336_CHIP_ID:
741                 /* Optimize resources up/down timers */
742                 if (ISSIM_ENAB(sih)) {
743                         pmu_res_updown_table = bcm4336a0_res_updown_qt;
744                         pmu_res_updown_table_sz =
745                             ARRAYSIZE(bcm4336a0_res_updown_qt);
746                 } else {
747                         pmu_res_updown_table = bcm4336a0_res_updown;
748                         pmu_res_updown_table_sz =
749                             ARRAYSIZE(bcm4336a0_res_updown);
750                 }
751                 /* Optimize resources dependancies masks */
752                 pmu_res_depend_table = bcm4336a0_res_depend;
753                 pmu_res_depend_table_sz = ARRAYSIZE(bcm4336a0_res_depend);
754                 break;
755
756         case BCM4330_CHIP_ID:
757                 /* Optimize resources up/down timers */
758                 if (ISSIM_ENAB(sih)) {
759                         pmu_res_updown_table = bcm4330a0_res_updown_qt;
760                         pmu_res_updown_table_sz =
761                             ARRAYSIZE(bcm4330a0_res_updown_qt);
762                 } else {
763                         pmu_res_updown_table = bcm4330a0_res_updown;
764                         pmu_res_updown_table_sz =
765                             ARRAYSIZE(bcm4330a0_res_updown);
766                 }
767                 /* Optimize resources dependancies masks */
768                 pmu_res_depend_table = bcm4330a0_res_depend;
769                 pmu_res_depend_table_sz = ARRAYSIZE(bcm4330a0_res_depend);
770                 break;
771
772         default:
773                 break;
774         }
775
776         /* # resources */
777         rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
778
779         /* Program up/down timers */
780         while (pmu_res_updown_table_sz--) {
781                 ASSERT(pmu_res_updown_table != NULL);
782                 PMU_MSG(("Changing rsrc %d res_updn_timer to 0x%x\n",
783                          pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
784                          pmu_res_updown_table[pmu_res_updown_table_sz].updown));
785                 W_REG(osh, &cc->res_table_sel,
786                       pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
787                 W_REG(osh, &cc->res_updn_timer,
788                       pmu_res_updown_table[pmu_res_updown_table_sz].updown);
789         }
790         /* Apply nvram overrides to up/down timers */
791         for (i = 0; i < rsrcs; i++) {
792                 snprintf(name, sizeof(name), "r%dt", i);
793                 if ((val = getvar(NULL, name)) == NULL)
794                         continue;
795                 PMU_MSG(("Applying %s=%s to rsrc %d res_updn_timer\n", name,
796                          val, i));
797                 W_REG(osh, &cc->res_table_sel, (uint32) i);
798                 W_REG(osh, &cc->res_updn_timer,
799                       (uint32) bcm_strtoul(val, NULL, 0));
800         }
801
802         /* Program resource dependencies table */
803         while (pmu_res_depend_table_sz--) {
804                 ASSERT(pmu_res_depend_table != NULL);
805                 if (pmu_res_depend_table[pmu_res_depend_table_sz].filter != NULL
806                     && !(pmu_res_depend_table[pmu_res_depend_table_sz].
807                          filter) (sih))
808                         continue;
809                 for (i = 0; i < rsrcs; i++) {
810                         if ((pmu_res_depend_table[pmu_res_depend_table_sz].
811                              res_mask & PMURES_BIT(i)) == 0)
812                                 continue;
813                         W_REG(osh, &cc->res_table_sel, i);
814                         switch (pmu_res_depend_table[pmu_res_depend_table_sz].
815                                 action) {
816                         case RES_DEPEND_SET:
817                                 PMU_MSG(("Changing rsrc %d res_dep_mask to 0x%x\n", i, pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask));
818                                 W_REG(osh, &cc->res_dep_mask,
819                                       pmu_res_depend_table
820                                       [pmu_res_depend_table_sz].depend_mask);
821                                 break;
822                         case RES_DEPEND_ADD:
823                                 PMU_MSG(("Adding 0x%x to rsrc %d res_dep_mask\n", pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
824                                 OR_REG(osh, &cc->res_dep_mask,
825                                        pmu_res_depend_table
826                                        [pmu_res_depend_table_sz].depend_mask);
827                                 break;
828                         case RES_DEPEND_REMOVE:
829                                 PMU_MSG(("Removing 0x%x from rsrc %d res_dep_mask\n", pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
830                                 AND_REG(osh, &cc->res_dep_mask,
831                                         ~pmu_res_depend_table
832                                         [pmu_res_depend_table_sz].depend_mask);
833                                 break;
834                         default:
835                                 ASSERT(0);
836                                 break;
837                         }
838                 }
839         }
840         /* Apply nvram overrides to dependancies masks */
841         for (i = 0; i < rsrcs; i++) {
842                 snprintf(name, sizeof(name), "r%dd", i);
843                 if ((val = getvar(NULL, name)) == NULL)
844                         continue;
845                 PMU_MSG(("Applying %s=%s to rsrc %d res_dep_mask\n", name, val,
846                          i));
847                 W_REG(osh, &cc->res_table_sel, (uint32) i);
848                 W_REG(osh, &cc->res_dep_mask,
849                       (uint32) bcm_strtoul(val, NULL, 0));
850         }
851
852         /* Determine min/max rsrc masks */
853         si_pmu_res_masks(sih, &min_mask, &max_mask);
854
855         /* It is required to program max_mask first and then min_mask */
856
857         /* Program max resource mask */
858
859         if (max_mask) {
860                 PMU_MSG(("Changing max_res_mask to 0x%x\n", max_mask));
861                 W_REG(osh, &cc->max_res_mask, max_mask);
862         }
863
864         /* Program min resource mask */
865
866         if (min_mask) {
867                 PMU_MSG(("Changing min_res_mask to 0x%x\n", min_mask));
868                 W_REG(osh, &cc->min_res_mask, min_mask);
869         }
870
871         /* Add some delay; allow resources to come up and settle. */
872         OSL_DELAY(2000);
873
874         /* Return to original core */
875         si_setcoreidx(sih, origidx);
876 }
877
878 /* setup pll and query clock speed */
879 typedef struct {
880         uint16 freq;
881         uint8 xf;
882         uint8 wbint;
883         uint32 wbfrac;
884 } pmu0_xtaltab0_t;
885
886 /* the following table is based on 880Mhz fvco */
887 static const pmu0_xtaltab0_t BCMINITDATA(pmu0_xtaltab0)[] =
888 {
889         {
890         12000, 1, 73, 349525}, {
891         13000, 2, 67, 725937}, {
892         14400, 3, 61, 116508}, {
893         15360, 4, 57, 305834}, {
894         16200, 5, 54, 336579}, {
895         16800, 6, 52, 399457}, {
896         19200, 7, 45, 873813}, {
897         19800, 8, 44, 466033}, {
898         20000, 9, 44, 0}, {
899         25000, 10, 70, 419430}, {
900         26000, 11, 67, 725937}, {
901         30000, 12, 58, 699050}, {
902         38400, 13, 45, 873813}, {
903         40000, 14, 45, 0}, {
904         0, 0, 0, 0}
905 };
906
907 #define PMU0_XTAL0_DEFAULT      8
908
909 /* setup pll and query clock speed */
910 typedef struct {
911         uint16 fref;
912         uint8 xf;
913         uint8 p1div;
914         uint8 p2div;
915         uint8 ndiv_int;
916         uint32 ndiv_frac;
917 } pmu1_xtaltab0_t;
918
919 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880_4329)[] =
920 {
921         {
922         12000, 1, 3, 22, 0x9, 0xFFFFEF}, {
923         13000, 2, 1, 6, 0xb, 0x483483}, {
924         14400, 3, 1, 10, 0xa, 0x1C71C7}, {
925         15360, 4, 1, 5, 0xb, 0x755555}, {
926         16200, 5, 1, 10, 0x5, 0x6E9E06}, {
927         16800, 6, 1, 10, 0x5, 0x3Cf3Cf}, {
928         19200, 7, 1, 4, 0xb, 0x755555}, {
929         19800, 8, 1, 11, 0x4, 0xA57EB}, {
930         20000, 9, 1, 11, 0x4, 0x0}, {
931         24000, 10, 3, 11, 0xa, 0x0}, {
932         25000, 11, 5, 16, 0xb, 0x0}, {
933         26000, 12, 1, 1, 0x21, 0xD89D89}, {
934         30000, 13, 3, 8, 0xb, 0x0}, {
935         37400, 14, 3, 1, 0x46, 0x969696}, {
936         38400, 15, 1, 1, 0x16, 0xEAAAAA}, {
937         40000, 16, 1, 2, 0xb, 0}, {
938         0, 0, 0, 0, 0, 0}
939 };
940
941 /* the following table is based on 880Mhz fvco */
942 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880)[] =
943 {
944         {
945         12000, 1, 3, 22, 0x9, 0xFFFFEF}, {
946         13000, 2, 1, 6, 0xb, 0x483483}, {
947         14400, 3, 1, 10, 0xa, 0x1C71C7}, {
948         15360, 4, 1, 5, 0xb, 0x755555}, {
949         16200, 5, 1, 10, 0x5, 0x6E9E06}, {
950         16800, 6, 1, 10, 0x5, 0x3Cf3Cf}, {
951         19200, 7, 1, 4, 0xb, 0x755555}, {
952         19800, 8, 1, 11, 0x4, 0xA57EB}, {
953         20000, 9, 1, 11, 0x4, 0x0}, {
954         24000, 10, 3, 11, 0xa, 0x0}, {
955         25000, 11, 5, 16, 0xb, 0x0}, {
956         26000, 12, 1, 2, 0x10, 0xEC4EC4}, {
957         30000, 13, 3, 8, 0xb, 0x0}, {
958         33600, 14, 1, 2, 0xd, 0x186186}, {
959         38400, 15, 1, 2, 0xb, 0x755555}, {
960         40000, 16, 1, 2, 0xb, 0}, {
961         0, 0, 0, 0, 0, 0}
962 };
963
964 #define PMU1_XTALTAB0_880_12000K        0
965 #define PMU1_XTALTAB0_880_13000K        1
966 #define PMU1_XTALTAB0_880_14400K        2
967 #define PMU1_XTALTAB0_880_15360K        3
968 #define PMU1_XTALTAB0_880_16200K        4
969 #define PMU1_XTALTAB0_880_16800K        5
970 #define PMU1_XTALTAB0_880_19200K        6
971 #define PMU1_XTALTAB0_880_19800K        7
972 #define PMU1_XTALTAB0_880_20000K        8
973 #define PMU1_XTALTAB0_880_24000K        9
974 #define PMU1_XTALTAB0_880_25000K        10
975 #define PMU1_XTALTAB0_880_26000K        11
976 #define PMU1_XTALTAB0_880_30000K        12
977 #define PMU1_XTALTAB0_880_37400K        13
978 #define PMU1_XTALTAB0_880_38400K        14
979 #define PMU1_XTALTAB0_880_40000K        15
980
981 /* the following table is based on 1760Mhz fvco */
982 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1760)[] =
983 {
984         {
985         12000, 1, 3, 44, 0x9, 0xFFFFEF}, {
986         13000, 2, 1, 12, 0xb, 0x483483}, {
987         14400, 3, 1, 20, 0xa, 0x1C71C7}, {
988         15360, 4, 1, 10, 0xb, 0x755555}, {
989         16200, 5, 1, 20, 0x5, 0x6E9E06}, {
990         16800, 6, 1, 20, 0x5, 0x3Cf3Cf}, {
991         19200, 7, 1, 18, 0x5, 0x17B425}, {
992         19800, 8, 1, 22, 0x4, 0xA57EB}, {
993         20000, 9, 1, 22, 0x4, 0x0}, {
994         24000, 10, 3, 22, 0xa, 0x0}, {
995         25000, 11, 5, 32, 0xb, 0x0}, {
996         26000, 12, 1, 4, 0x10, 0xEC4EC4}, {
997         30000, 13, 3, 16, 0xb, 0x0}, {
998         38400, 14, 1, 10, 0x4, 0x955555}, {
999         40000, 15, 1, 4, 0xb, 0}, {
1000         0, 0, 0, 0, 0, 0}
1001 };
1002
1003 /* table index */
1004 #define PMU1_XTALTAB0_1760_12000K       0
1005 #define PMU1_XTALTAB0_1760_13000K       1
1006 #define PMU1_XTALTAB0_1760_14400K       2
1007 #define PMU1_XTALTAB0_1760_15360K       3
1008 #define PMU1_XTALTAB0_1760_16200K       4
1009 #define PMU1_XTALTAB0_1760_16800K       5
1010 #define PMU1_XTALTAB0_1760_19200K       6
1011 #define PMU1_XTALTAB0_1760_19800K       7
1012 #define PMU1_XTALTAB0_1760_20000K       8
1013 #define PMU1_XTALTAB0_1760_24000K       9
1014 #define PMU1_XTALTAB0_1760_25000K       10
1015 #define PMU1_XTALTAB0_1760_26000K       11
1016 #define PMU1_XTALTAB0_1760_30000K       12
1017 #define PMU1_XTALTAB0_1760_38400K       13
1018 #define PMU1_XTALTAB0_1760_40000K       14
1019
1020 /* the following table is based on 1440Mhz fvco */
1021 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1440)[] =
1022 {
1023         {
1024         12000, 1, 1, 1, 0x78, 0x0}, {
1025         13000, 2, 1, 1, 0x6E, 0xC4EC4E}, {
1026         14400, 3, 1, 1, 0x64, 0x0}, {
1027         15360, 4, 1, 1, 0x5D, 0xC00000}, {
1028         16200, 5, 1, 1, 0x58, 0xE38E38}, {
1029         16800, 6, 1, 1, 0x55, 0xB6DB6D}, {
1030         19200, 7, 1, 1, 0x4B, 0}, {
1031         19800, 8, 1, 1, 0x48, 0xBA2E8B}, {
1032         20000, 9, 1, 1, 0x48, 0x0}, {
1033         25000, 10, 1, 1, 0x39, 0x999999}, {
1034         26000, 11, 1, 1, 0x37, 0x627627}, {
1035         30000, 12, 1, 1, 0x30, 0x0}, {
1036         37400, 13, 2, 1, 0x4D, 0x15E76}, {
1037         38400, 13, 2, 1, 0x4B, 0x0}, {
1038         40000, 14, 2, 1, 0x48, 0x0}, {
1039         48000, 15, 2, 1, 0x3c, 0x0}, {
1040         0, 0, 0, 0, 0, 0}
1041 };
1042
1043 /* table index */
1044 #define PMU1_XTALTAB0_1440_12000K       0
1045 #define PMU1_XTALTAB0_1440_13000K       1
1046 #define PMU1_XTALTAB0_1440_14400K       2
1047 #define PMU1_XTALTAB0_1440_15360K       3
1048 #define PMU1_XTALTAB0_1440_16200K       4
1049 #define PMU1_XTALTAB0_1440_16800K       5
1050 #define PMU1_XTALTAB0_1440_19200K       6
1051 #define PMU1_XTALTAB0_1440_19800K       7
1052 #define PMU1_XTALTAB0_1440_20000K       8
1053 #define PMU1_XTALTAB0_1440_25000K       9
1054 #define PMU1_XTALTAB0_1440_26000K       10
1055 #define PMU1_XTALTAB0_1440_30000K       11
1056 #define PMU1_XTALTAB0_1440_37400K       12
1057 #define PMU1_XTALTAB0_1440_38400K       13
1058 #define PMU1_XTALTAB0_1440_40000K       14
1059 #define PMU1_XTALTAB0_1440_48000K       15
1060
1061 #define XTAL_FREQ_24000MHZ              24000
1062 #define XTAL_FREQ_30000MHZ              30000
1063 #define XTAL_FREQ_37400MHZ              37400
1064 #define XTAL_FREQ_48000MHZ              48000
1065
1066 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_960)[] =
1067 {
1068         {
1069         12000, 1, 1, 1, 0x50, 0x0}, {
1070         13000, 2, 1, 1, 0x49, 0xD89D89}, {
1071         14400, 3, 1, 1, 0x42, 0xAAAAAA}, {
1072         15360, 4, 1, 1, 0x3E, 0x800000}, {
1073         16200, 5, 1, 1, 0x39, 0x425ED0}, {
1074         16800, 6, 1, 1, 0x39, 0x249249}, {
1075         19200, 7, 1, 1, 0x32, 0x0}, {
1076         19800, 8, 1, 1, 0x30, 0x7C1F07}, {
1077         20000, 9, 1, 1, 0x30, 0x0}, {
1078         25000, 10, 1, 1, 0x26, 0x666666}, {
1079         26000, 11, 1, 1, 0x24, 0xEC4EC4}, {
1080         30000, 12, 1, 1, 0x20, 0x0}, {
1081         37400, 13, 2, 1, 0x33, 0x563EF9}, {
1082         38400, 14, 2, 1, 0x32, 0x0}, {
1083         40000, 15, 2, 1, 0x30, 0x0}, {
1084         48000, 16, 2, 1, 0x28, 0x0}, {
1085         0, 0, 0, 0, 0, 0}
1086 };
1087
1088 /* table index */
1089 #define PMU1_XTALTAB0_960_12000K        0
1090 #define PMU1_XTALTAB0_960_13000K        1
1091 #define PMU1_XTALTAB0_960_14400K        2
1092 #define PMU1_XTALTAB0_960_15360K        3
1093 #define PMU1_XTALTAB0_960_16200K        4
1094 #define PMU1_XTALTAB0_960_16800K        5
1095 #define PMU1_XTALTAB0_960_19200K        6
1096 #define PMU1_XTALTAB0_960_19800K        7
1097 #define PMU1_XTALTAB0_960_20000K        8
1098 #define PMU1_XTALTAB0_960_25000K        9
1099 #define PMU1_XTALTAB0_960_26000K        10
1100 #define PMU1_XTALTAB0_960_30000K        11
1101 #define PMU1_XTALTAB0_960_37400K        12
1102 #define PMU1_XTALTAB0_960_38400K        13
1103 #define PMU1_XTALTAB0_960_40000K        14
1104 #define PMU1_XTALTAB0_960_48000K        15
1105
1106 /* select xtal table for each chip */
1107 static const pmu1_xtaltab0_t *BCMINITFN(si_pmu1_xtaltab0) (si_t * sih) {
1108 #ifdef BCMDBG
1109         char chn[8];
1110 #endif
1111         switch (CHIPID(sih->chip)) {
1112         case BCM4329_CHIP_ID:
1113                 return pmu1_xtaltab0_880_4329;
1114         case BCM4319_CHIP_ID:
1115                 return pmu1_xtaltab0_1440;
1116         case BCM4336_CHIP_ID:
1117                 return pmu1_xtaltab0_960;
1118         case BCM4330_CHIP_ID:
1119                 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1120                         return pmu1_xtaltab0_960;
1121                 else
1122                         return pmu1_xtaltab0_1440;
1123         default:
1124                 PMU_MSG(("si_pmu1_xtaltab0: Unknown chipid %s\n",
1125                          bcm_chipname(sih->chip, chn, 8)));
1126                 break;
1127         }
1128         ASSERT(0);
1129         return NULL;
1130 }
1131
1132 /* select default xtal frequency for each chip */
1133 static const pmu1_xtaltab0_t *BCMINITFN(si_pmu1_xtaldef0) (si_t * sih) {
1134 #ifdef BCMDBG
1135         char chn[8];
1136 #endif
1137
1138         switch (CHIPID(sih->chip)) {
1139         case BCM4329_CHIP_ID:
1140                 /* Default to 38400Khz */
1141                 return &pmu1_xtaltab0_880_4329[PMU1_XTALTAB0_880_38400K];
1142         case BCM4319_CHIP_ID:
1143                 /* Default to 30000Khz */
1144                 return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_30000K];
1145         case BCM4336_CHIP_ID:
1146                 /* Default to 26000Khz */
1147                 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_26000K];
1148         case BCM4330_CHIP_ID:
1149                 /* Default to 37400Khz */
1150                 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1151                         return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_37400K];
1152                 else
1153                         return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_37400K];
1154         default:
1155                 PMU_MSG(("si_pmu1_xtaldef0: Unknown chipid %s\n",
1156                          bcm_chipname(sih->chip, chn, 8)));
1157                 break;
1158         }
1159         ASSERT(0);
1160         return NULL;
1161 }
1162
1163 /* select default pll fvco for each chip */
1164 static uint32 BCMINITFN(si_pmu1_pllfvco0) (si_t * sih) {
1165 #ifdef BCMDBG
1166         char chn[8];
1167 #endif
1168
1169         switch (CHIPID(sih->chip)) {
1170         case BCM4329_CHIP_ID:
1171                 return FVCO_880;
1172         case BCM4319_CHIP_ID:
1173                 return FVCO_1440;
1174         case BCM4336_CHIP_ID:
1175                 return FVCO_960;
1176         case BCM4330_CHIP_ID:
1177                 if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1178                         return FVCO_960;
1179                 else
1180                         return FVCO_1440;
1181         default:
1182                 PMU_MSG(("si_pmu1_pllfvco0: Unknown chipid %s\n",
1183                          bcm_chipname(sih->chip, chn, 8)));
1184                 break;
1185         }
1186         ASSERT(0);
1187         return 0;
1188 }
1189
1190 /* query alp/xtal clock frequency */
1191 static uint32
1192 BCMINITFN(si_pmu1_alpclk0) (si_t * sih, osl_t * osh, chipcregs_t * cc) {
1193         const pmu1_xtaltab0_t *xt;
1194         uint32 xf;
1195
1196         /* Find the frequency in the table */
1197         xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1198             PCTL_XTALFREQ_SHIFT;
1199         for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt++)
1200                 if (xt->xf == xf)
1201                         break;
1202         /* Could not find it so assign a default value */
1203         if (xt == NULL || xt->fref == 0)
1204                 xt = si_pmu1_xtaldef0(sih);
1205         ASSERT(xt != NULL && xt->fref != 0);
1206
1207         return xt->fref * 1000;
1208 }
1209
1210 /* Set up PLL registers in the PMU as per the crystal speed.
1211  * XtalFreq field in pmucontrol register being 0 indicates the PLL
1212  * is not programmed and the h/w default is assumed to work, in which
1213  * case the xtal frequency is unknown to the s/w so we need to call
1214  * si_pmu1_xtaldef0() wherever it is needed to return a default value.
1215  */
1216 static void
1217 BCMATTACHFN(si_pmu1_pllinit0) (si_t * sih, osl_t * osh, chipcregs_t * cc,
1218                                uint32 xtal) {
1219         const pmu1_xtaltab0_t *xt;
1220         uint32 tmp;
1221         uint32 buf_strength = 0;
1222         uint8 ndiv_mode = 1;
1223
1224         /* Use h/w default PLL config */
1225         if (xtal == 0) {
1226                 PMU_MSG(("Unspecified xtal frequency, skip PLL configuration\n"));
1227                 return;
1228         }
1229
1230         /* Find the frequency in the table */
1231         for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt++)
1232                 if (xt->fref == xtal)
1233                         break;
1234
1235         /* Check current PLL state, bail out if it has been programmed or
1236          * we don't know how to program it.
1237          */
1238         if (xt == NULL || xt->fref == 0) {
1239                 PMU_MSG(("Unsupported xtal frequency %d.%d MHz, skip PLL configuration\n", xtal / 1000, xtal % 1000));
1240                 return;
1241         }
1242         /*  for 4319 bootloader already programs the PLL but bootloader does not program the
1243            PLL4 and PLL5. So Skip this check for 4319
1244          */
1245         if ((((R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1246               PCTL_XTALFREQ_SHIFT) == xt->xf) &&
1247             !((CHIPID(sih->chip) == BCM4319_CHIP_ID)
1248               || (CHIPID(sih->chip) == BCM4330_CHIP_ID))) {
1249                 PMU_MSG(("PLL already programmed for %d.%d MHz\n",
1250                          xt->fref / 1000, xt->fref % 1000));
1251                 return;
1252         }
1253
1254         PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
1255         PMU_MSG(("Programming PLL for %d.%d MHz\n", xt->fref / 1000,
1256                  xt->fref % 1000));
1257
1258         switch (CHIPID(sih->chip)) {
1259         case BCM4329_CHIP_ID:
1260                 /* Change the BBPLL drive strength to 8 for all channels */
1261                 buf_strength = 0x888888;
1262                 AND_REG(osh, &cc->min_res_mask,
1263                         ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) |
1264                           PMURES_BIT(RES4329_HT_AVAIL)));
1265                 AND_REG(osh, &cc->max_res_mask,
1266                         ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) |
1267                           PMURES_BIT(RES4329_HT_AVAIL)));
1268                 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
1269                          PMU_MAX_TRANSITION_DLY);
1270                 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1271                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
1272                 if (xt->fref == 38400)
1273                         tmp = 0x200024C0;
1274                 else if (xt->fref == 37400)
1275                         tmp = 0x20004500;
1276                 else if (xt->fref == 26000)
1277                         tmp = 0x200024C0;
1278                 else
1279                         tmp = 0x200005C0;       /* Chip Dflt Settings */
1280                 W_REG(osh, &cc->pllcontrol_data, tmp);
1281                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
1282                 tmp =
1283                     R_REG(osh,
1284                           &cc->pllcontrol_data) & PMU1_PLL0_PC5_CLK_DRV_MASK;
1285                 if ((xt->fref == 38400) || (xt->fref == 37400)
1286                     || (xt->fref == 26000))
1287                         tmp |= 0x15;
1288                 else
1289                         tmp |= 0x25;    /* Chip Dflt Settings */
1290                 W_REG(osh, &cc->pllcontrol_data, tmp);
1291                 break;
1292
1293         case BCM4319_CHIP_ID:
1294                 /* Change the BBPLL drive strength to 2 for all channels */
1295                 buf_strength = 0x222222;
1296
1297                 /* Make sure the PLL is off */
1298                 /* WAR65104: Disable the HT_AVAIL resource first and then
1299                  * after a delay (more than downtime for HT_AVAIL) remove the
1300                  * BBPLL resource; backplane clock moves to ALP from HT.
1301                  */
1302                 AND_REG(osh, &cc->min_res_mask,
1303                         ~(PMURES_BIT(RES4319_HT_AVAIL)));
1304                 AND_REG(osh, &cc->max_res_mask,
1305                         ~(PMURES_BIT(RES4319_HT_AVAIL)));
1306
1307                 OSL_DELAY(100);
1308                 AND_REG(osh, &cc->min_res_mask,
1309                         ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
1310                 AND_REG(osh, &cc->max_res_mask,
1311                         ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
1312
1313                 OSL_DELAY(100);
1314                 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
1315                          PMU_MAX_TRANSITION_DLY);
1316                 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1317                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
1318                 tmp = 0x200005c0;
1319                 W_REG(osh, &cc->pllcontrol_data, tmp);
1320                 break;
1321
1322         case BCM4336_CHIP_ID:
1323                 AND_REG(osh, &cc->min_res_mask,
1324                         ~(PMURES_BIT(RES4336_HT_AVAIL) |
1325                           PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
1326                 AND_REG(osh, &cc->max_res_mask,
1327                         ~(PMURES_BIT(RES4336_HT_AVAIL) |
1328                           PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
1329                 OSL_DELAY(100);
1330                 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
1331                          PMU_MAX_TRANSITION_DLY);
1332                 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1333                 break;
1334
1335         case BCM4330_CHIP_ID:
1336                 AND_REG(osh, &cc->min_res_mask,
1337                         ~(PMURES_BIT(RES4330_HT_AVAIL) |
1338                           PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
1339                 AND_REG(osh, &cc->max_res_mask,
1340                         ~(PMURES_BIT(RES4330_HT_AVAIL) |
1341                           PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
1342                 OSL_DELAY(100);
1343                 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
1344                          PMU_MAX_TRANSITION_DLY);
1345                 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1346                 break;
1347
1348         default:
1349                 ASSERT(0);
1350         }
1351
1352         PMU_MSG(("Done masking\n"));
1353
1354         /* Write p1div and p2div to pllcontrol[0] */
1355         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
1356         tmp = R_REG(osh, &cc->pllcontrol_data) &
1357             ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
1358         tmp |=
1359             ((xt->
1360               p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) |
1361             ((xt->
1362               p2div << PMU1_PLL0_PC0_P2DIV_SHIFT) & PMU1_PLL0_PC0_P2DIV_MASK);
1363         W_REG(osh, &cc->pllcontrol_data, tmp);
1364
1365         if ((CHIPID(sih->chip) == BCM4330_CHIP_ID))
1366                 si_pmu_set_4330_plldivs(sih);
1367
1368         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID)
1369             && (CHIPREV(sih->chiprev) == 0)) {
1370
1371                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
1372                 tmp = R_REG(osh, &cc->pllcontrol_data);
1373                 tmp = tmp & (~DOT11MAC_880MHZ_CLK_DIVISOR_MASK);
1374                 tmp = tmp | DOT11MAC_880MHZ_CLK_DIVISOR_VAL;
1375                 W_REG(osh, &cc->pllcontrol_data, tmp);
1376         }
1377         if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
1378             (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
1379             (CHIPID(sih->chip) == BCM4330_CHIP_ID))
1380                 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
1381         else
1382                 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MASH;
1383
1384         /* Write ndiv_int and ndiv_mode to pllcontrol[2] */
1385         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
1386         tmp = R_REG(osh, &cc->pllcontrol_data) &
1387             ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
1388         tmp |=
1389             ((xt->
1390               ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) &
1391              PMU1_PLL0_PC2_NDIV_INT_MASK) | ((ndiv_mode <<
1392                                               PMU1_PLL0_PC2_NDIV_MODE_SHIFT) &
1393                                              PMU1_PLL0_PC2_NDIV_MODE_MASK);
1394         W_REG(osh, &cc->pllcontrol_data, tmp);
1395
1396         /* Write ndiv_frac to pllcontrol[3] */
1397         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
1398         tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
1399         tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
1400                 PMU1_PLL0_PC3_NDIV_FRAC_MASK);
1401         W_REG(osh, &cc->pllcontrol_data, tmp);
1402
1403         /* Write clock driving strength to pllcontrol[5] */
1404         if (buf_strength) {
1405                 PMU_MSG(("Adjusting PLL buffer drive strength: %x\n",
1406                          buf_strength));
1407
1408                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
1409                 tmp =
1410                     R_REG(osh,
1411                           &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
1412                 tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
1413                 W_REG(osh, &cc->pllcontrol_data, tmp);
1414         }
1415
1416         PMU_MSG(("Done pll\n"));
1417
1418         /* to operate the 4319 usb in 24MHz/48MHz; chipcontrol[2][84:83] needs
1419          * to be updated.
1420          */
1421         if ((CHIPID(sih->chip) == BCM4319_CHIP_ID)
1422             && (xt->fref != XTAL_FREQ_30000MHZ)) {
1423                 W_REG(osh, &cc->chipcontrol_addr, PMU1_PLL0_CHIPCTL2);
1424                 tmp =
1425                     R_REG(osh,
1426                           &cc->chipcontrol_data) & ~CCTL_4319USB_XTAL_SEL_MASK;
1427                 if (xt->fref == XTAL_FREQ_24000MHZ) {
1428                         tmp |=
1429                             (CCTL_4319USB_24MHZ_PLL_SEL <<
1430                              CCTL_4319USB_XTAL_SEL_SHIFT);
1431                 } else if (xt->fref == XTAL_FREQ_48000MHZ) {
1432                         tmp |=
1433                             (CCTL_4319USB_48MHZ_PLL_SEL <<
1434                              CCTL_4319USB_XTAL_SEL_SHIFT);
1435                 }
1436                 W_REG(osh, &cc->chipcontrol_data, tmp);
1437         }
1438
1439         /* Flush deferred pll control registers writes */
1440         if (sih->pmurev >= 2)
1441                 OR_REG(osh, &cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
1442
1443         /* Write XtalFreq. Set the divisor also. */
1444         tmp = R_REG(osh, &cc->pmucontrol) &
1445             ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
1446         tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
1447                 PCTL_ILP_DIV_MASK) |
1448             ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
1449
1450         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID)
1451             && CHIPREV(sih->chiprev) == 0) {
1452                 /* clear the htstretch before clearing HTReqEn */
1453                 AND_REG(osh, &cc->clkstretch, ~CSTRETCH_HT);
1454                 tmp &= ~PCTL_HT_REQ_EN;
1455         }
1456
1457         W_REG(osh, &cc->pmucontrol, tmp);
1458 }
1459
1460 /* query the CPU clock frequency */
1461 static uint32
1462 BCMINITFN(si_pmu1_cpuclk0) (si_t * sih, osl_t * osh, chipcregs_t * cc) {
1463         uint32 tmp, m1div;
1464 #ifdef BCMDBG
1465         uint32 ndiv_int, ndiv_frac, p2div, p1div, fvco;
1466         uint32 fref;
1467 #endif
1468         uint32 FVCO = si_pmu1_pllfvco0(sih);
1469
1470         /* Read m1div from pllcontrol[1] */
1471         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
1472         tmp = R_REG(osh, &cc->pllcontrol_data);
1473         m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT;
1474
1475 #ifdef BCMDBG
1476         /* Read p2div/p1div from pllcontrol[0] */
1477         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
1478         tmp = R_REG(osh, &cc->pllcontrol_data);
1479         p2div = (tmp & PMU1_PLL0_PC0_P2DIV_MASK) >> PMU1_PLL0_PC0_P2DIV_SHIFT;
1480         p1div = (tmp & PMU1_PLL0_PC0_P1DIV_MASK) >> PMU1_PLL0_PC0_P1DIV_SHIFT;
1481
1482         /* Calculate fvco based on xtal freq and ndiv and pdiv */
1483         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
1484         tmp = R_REG(osh, &cc->pllcontrol_data);
1485         ndiv_int =
1486             (tmp & PMU1_PLL0_PC2_NDIV_INT_MASK) >> PMU1_PLL0_PC2_NDIV_INT_SHIFT;
1487
1488         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
1489         tmp = R_REG(osh, &cc->pllcontrol_data);
1490         ndiv_frac =
1491             (tmp & PMU1_PLL0_PC3_NDIV_FRAC_MASK) >>
1492             PMU1_PLL0_PC3_NDIV_FRAC_SHIFT;
1493
1494         fref = si_pmu1_alpclk0(sih, osh, cc) / 1000;
1495
1496         fvco = (fref * ndiv_int) << 8;
1497         fvco += (fref * (ndiv_frac >> 12)) >> 4;
1498         fvco += (fref * (ndiv_frac & 0xfff)) >> 12;
1499         fvco >>= 8;
1500         fvco *= p2div;
1501         fvco /= p1div;
1502         fvco /= 1000;
1503         fvco *= 1000;
1504
1505         PMU_MSG(("si_pmu1_cpuclk0: ndiv_int %u ndiv_frac %u p2div %u p1div %u fvco %u\n", ndiv_int, ndiv_frac, p2div, p1div, fvco));
1506
1507         FVCO = fvco;
1508 #endif                          /* BCMDBG */
1509
1510         /* Return ARM/SB clock */
1511         return FVCO / m1div * 1000;
1512 }
1513
1514 /* initialize PLL */
1515 void BCMATTACHFN(si_pmu_pll_init) (si_t * sih, osl_t * osh, uint xtalfreq) {
1516         chipcregs_t *cc;
1517         uint origidx;
1518 #ifdef BCMDBG
1519         char chn[8];
1520 #endif
1521
1522         ASSERT(sih->cccaps & CC_CAP_PMU);
1523
1524         /* Remember original core before switch to chipc */
1525         origidx = si_coreidx(sih);
1526         cc = si_setcoreidx(sih, SI_CC_IDX);
1527         ASSERT(cc != NULL);
1528
1529         switch (CHIPID(sih->chip)) {
1530         case BCM4329_CHIP_ID:
1531                 if (xtalfreq == 0)
1532                         xtalfreq = 38400;
1533                 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
1534                 break;
1535         case BCM4313_CHIP_ID:
1536         case BCM43224_CHIP_ID:
1537         case BCM43225_CHIP_ID:
1538         case BCM43421_CHIP_ID:
1539         case BCM43235_CHIP_ID:
1540         case BCM43236_CHIP_ID:
1541         case BCM43238_CHIP_ID:
1542         case BCM4331_CHIP_ID:
1543         case BCM6362_CHIP_ID:
1544                 /* ??? */
1545                 break;
1546         case BCM4319_CHIP_ID:
1547         case BCM4336_CHIP_ID:
1548         case BCM4330_CHIP_ID:
1549                 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
1550                 break;
1551         default:
1552                 PMU_MSG(("No PLL init done for chip %s rev %d pmurev %d\n",
1553                          bcm_chipname(sih->chip, chn, 8), sih->chiprev,
1554                          sih->pmurev));
1555                 break;
1556         }
1557
1558 #ifdef BCMDBG_FORCEHT
1559         OR_REG(osh, &cc->clk_ctl_st, CCS_FORCEHT);
1560 #endif
1561
1562         /* Return to original core */
1563         si_setcoreidx(sih, origidx);
1564 }
1565
1566 /* query alp/xtal clock frequency */
1567 uint32 BCMINITFN(si_pmu_alp_clock) (si_t * sih, osl_t * osh) {
1568         chipcregs_t *cc;
1569         uint origidx;
1570         uint32 clock = ALP_CLOCK;
1571 #ifdef BCMDBG
1572         char chn[8];
1573 #endif
1574
1575         ASSERT(sih->cccaps & CC_CAP_PMU);
1576
1577         /* Remember original core before switch to chipc */
1578         origidx = si_coreidx(sih);
1579         cc = si_setcoreidx(sih, SI_CC_IDX);
1580         ASSERT(cc != NULL);
1581
1582         switch (CHIPID(sih->chip)) {
1583         case BCM43224_CHIP_ID:
1584         case BCM43225_CHIP_ID:
1585         case BCM43421_CHIP_ID:
1586         case BCM43235_CHIP_ID:
1587         case BCM43236_CHIP_ID:
1588         case BCM43238_CHIP_ID:
1589         case BCM4331_CHIP_ID:
1590         case BCM6362_CHIP_ID:
1591         case BCM4716_CHIP_ID:
1592         case BCM4748_CHIP_ID:
1593         case BCM47162_CHIP_ID:
1594         case BCM4313_CHIP_ID:
1595         case BCM5357_CHIP_ID:
1596                 /* always 20Mhz */
1597                 clock = 20000 * 1000;
1598                 break;
1599         case BCM4329_CHIP_ID:
1600         case BCM4319_CHIP_ID:
1601         case BCM4336_CHIP_ID:
1602         case BCM4330_CHIP_ID:
1603
1604                 clock = si_pmu1_alpclk0(sih, osh, cc);
1605                 break;
1606         case BCM5356_CHIP_ID:
1607                 /* always 25Mhz */
1608                 clock = 25000 * 1000;
1609                 break;
1610         default:
1611                 PMU_MSG(("No ALP clock specified "
1612                          "for chip %s rev %d pmurev %d, using default %d Hz\n",
1613                          bcm_chipname(sih->chip, chn, 8), sih->chiprev,
1614                          sih->pmurev, clock));
1615                 break;
1616         }
1617
1618         /* Return to original core */
1619         si_setcoreidx(sih, origidx);
1620         return clock;
1621 }
1622
1623 /* Find the output of the "m" pll divider given pll controls that start with
1624  * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
1625  */
1626 static uint32
1627 BCMINITFN(si_pmu5_clock) (si_t * sih, osl_t * osh, chipcregs_t * cc, uint pll0,
1628                           uint m) {
1629         uint32 tmp, div, ndiv, p1, p2, fc;
1630
1631         if ((pll0 & 3) || (pll0 > PMU4716_MAINPLL_PLL0)) {
1632                 PMU_ERROR(("%s: Bad pll0: %d\n", __func__, pll0));
1633                 return 0;
1634         }
1635
1636         /* Strictly there is an m5 divider, but I'm not sure we use it */
1637         if ((m == 0) || (m > 4)) {
1638                 PMU_ERROR(("%s: Bad m divider: %d\n", __func__, m));
1639                 return 0;
1640         }
1641
1642         if (CHIPID(sih->chip) == BCM5357_CHIP_ID) {
1643                 /* Detect failure in clock setting */
1644                 if ((R_REG(osh, &cc->chipstatus) & 0x40000) != 0) {
1645                         return (133 * 1000000);
1646                 }
1647         }
1648
1649         W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_P1P2_OFF);
1650         (void)R_REG(osh, &cc->pllcontrol_addr);
1651         tmp = R_REG(osh, &cc->pllcontrol_data);
1652         p1 = (tmp & PMU5_PLL_P1_MASK) >> PMU5_PLL_P1_SHIFT;
1653         p2 = (tmp & PMU5_PLL_P2_MASK) >> PMU5_PLL_P2_SHIFT;
1654
1655         W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_M14_OFF);
1656         (void)R_REG(osh, &cc->pllcontrol_addr);
1657         tmp = R_REG(osh, &cc->pllcontrol_data);
1658         div = (tmp >> ((m - 1) * PMU5_PLL_MDIV_WIDTH)) & PMU5_PLL_MDIV_MASK;
1659
1660         W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_NM5_OFF);
1661         (void)R_REG(osh, &cc->pllcontrol_addr);
1662         tmp = R_REG(osh, &cc->pllcontrol_data);
1663         ndiv = (tmp & PMU5_PLL_NDIV_MASK) >> PMU5_PLL_NDIV_SHIFT;
1664
1665         /* Do calculation in Mhz */
1666         fc = si_pmu_alp_clock(sih, osh) / 1000000;
1667         fc = (p1 * ndiv * fc) / p2;
1668
1669         PMU_NONE(("%s: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, clock=%d\n",
1670                   __func__, p1, p2, ndiv, ndiv, m, div, fc, fc / div));
1671
1672         /* Return clock in Hertz */
1673         return ((fc / div) * 1000000);
1674 }
1675
1676 /* query backplane clock frequency */
1677 /* For designs that feed the same clock to both backplane
1678  * and CPU just return the CPU clock speed.
1679  */
1680 uint32 BCMINITFN(si_pmu_si_clock) (si_t * sih, osl_t * osh) {
1681         chipcregs_t *cc;
1682         uint origidx;
1683         uint32 clock = HT_CLOCK;
1684 #ifdef BCMDBG
1685         char chn[8];
1686 #endif
1687
1688         ASSERT(sih->cccaps & CC_CAP_PMU);
1689
1690         /* Remember original core before switch to chipc */
1691         origidx = si_coreidx(sih);
1692         cc = si_setcoreidx(sih, SI_CC_IDX);
1693         ASSERT(cc != NULL);
1694
1695         switch (CHIPID(sih->chip)) {
1696         case BCM43224_CHIP_ID:
1697         case BCM43225_CHIP_ID:
1698         case BCM43421_CHIP_ID:
1699         case BCM4331_CHIP_ID:
1700         case BCM6362_CHIP_ID:
1701                 /* 96MHz backplane clock */
1702                 clock = 96000 * 1000;
1703                 break;
1704         case BCM4716_CHIP_ID:
1705         case BCM4748_CHIP_ID:
1706         case BCM47162_CHIP_ID:
1707                 clock =
1708                     si_pmu5_clock(sih, osh, cc, PMU4716_MAINPLL_PLL0,
1709                                   PMU5_MAINPLL_SI);
1710                 break;
1711         case BCM4329_CHIP_ID:
1712                 if (CHIPREV(sih->chiprev) == 0)
1713                         clock = 38400 * 1000;
1714                 else
1715                         clock = si_pmu1_cpuclk0(sih, osh, cc);
1716                 break;
1717         case BCM4319_CHIP_ID:
1718         case BCM4336_CHIP_ID:
1719         case BCM4330_CHIP_ID:
1720                 clock = si_pmu1_cpuclk0(sih, osh, cc);
1721                 break;
1722         case BCM4313_CHIP_ID:
1723                 /* 80MHz backplane clock */
1724                 clock = 80000 * 1000;
1725                 break;
1726         case BCM43235_CHIP_ID:
1727         case BCM43236_CHIP_ID:
1728         case BCM43238_CHIP_ID:
1729                 clock =
1730                     (cc->chipstatus & CST43236_BP_CLK) ? (120000 *
1731                                                           1000) : (96000 *
1732                                                                    1000);
1733                 break;
1734         case BCM5356_CHIP_ID:
1735                 clock =
1736                     si_pmu5_clock(sih, osh, cc, PMU5356_MAINPLL_PLL0,
1737                                   PMU5_MAINPLL_SI);
1738                 break;
1739         case BCM5357_CHIP_ID:
1740                 clock =
1741                     si_pmu5_clock(sih, osh, cc, PMU5357_MAINPLL_PLL0,
1742                                   PMU5_MAINPLL_SI);
1743                 break;
1744         default:
1745                 PMU_MSG(("No backplane clock specified "
1746                          "for chip %s rev %d pmurev %d, using default %d Hz\n",
1747                          bcm_chipname(sih->chip, chn, 8), sih->chiprev,
1748                          sih->pmurev, clock));
1749                 break;
1750         }
1751
1752         /* Return to original core */
1753         si_setcoreidx(sih, origidx);
1754         return clock;
1755 }
1756
1757 /* query CPU clock frequency */
1758 uint32 BCMINITFN(si_pmu_cpu_clock) (si_t * sih, osl_t * osh) {
1759         chipcregs_t *cc;
1760         uint origidx;
1761         uint32 clock;
1762
1763         ASSERT(sih->cccaps & CC_CAP_PMU);
1764
1765         if ((sih->pmurev >= 5) &&
1766             !((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
1767               (CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
1768               (CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
1769               (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
1770               (CHIPID(sih->chip) == BCM4330_CHIP_ID))) {
1771                 uint pll;
1772
1773                 switch (CHIPID(sih->chip)) {
1774                 case BCM5356_CHIP_ID:
1775                         pll = PMU5356_MAINPLL_PLL0;
1776                         break;
1777                 case BCM5357_CHIP_ID:
1778                         pll = PMU5357_MAINPLL_PLL0;
1779                         break;
1780                 default:
1781                         pll = PMU4716_MAINPLL_PLL0;
1782                         break;
1783                 }
1784
1785                 /* Remember original core before switch to chipc */
1786                 origidx = si_coreidx(sih);
1787                 cc = si_setcoreidx(sih, SI_CC_IDX);
1788                 ASSERT(cc != NULL);
1789
1790                 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_CPU);
1791
1792                 /* Return to original core */
1793                 si_setcoreidx(sih, origidx);
1794         } else
1795                 clock = si_pmu_si_clock(sih, osh);
1796
1797         return clock;
1798 }
1799
1800 /* query memory clock frequency */
1801 uint32 BCMINITFN(si_pmu_mem_clock) (si_t * sih, osl_t * osh) {
1802         chipcregs_t *cc;
1803         uint origidx;
1804         uint32 clock;
1805
1806         ASSERT(sih->cccaps & CC_CAP_PMU);
1807
1808         if ((sih->pmurev >= 5) &&
1809             !((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
1810               (CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
1811               (CHIPID(sih->chip) == BCM4330_CHIP_ID) ||
1812               (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
1813               (CHIPID(sih->chip) == BCM43236_CHIP_ID))) {
1814                 uint pll;
1815
1816                 switch (CHIPID(sih->chip)) {
1817                 case BCM5356_CHIP_ID:
1818                         pll = PMU5356_MAINPLL_PLL0;
1819                         break;
1820                 case BCM5357_CHIP_ID:
1821                         pll = PMU5357_MAINPLL_PLL0;
1822                         break;
1823                 default:
1824                         pll = PMU4716_MAINPLL_PLL0;
1825                         break;
1826                 }
1827
1828                 /* Remember original core before switch to chipc */
1829                 origidx = si_coreidx(sih);
1830                 cc = si_setcoreidx(sih, SI_CC_IDX);
1831                 ASSERT(cc != NULL);
1832
1833                 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_MEM);
1834
1835                 /* Return to original core */
1836                 si_setcoreidx(sih, origidx);
1837         } else {
1838                 clock = si_pmu_si_clock(sih, osh);
1839         }
1840
1841         return clock;
1842 }
1843
1844 /* Measure ILP clock frequency */
1845 #define ILP_CALC_DUR    10      /* ms, make sure 1000 can be divided by it. */
1846
1847 static uint32 ilpcycles_per_sec = 0;
1848
1849 uint32 BCMINITFN(si_pmu_ilp_clock) (si_t * sih, osl_t * osh) {
1850         if (ISSIM_ENAB(sih))
1851                 return ILP_CLOCK;
1852
1853         if (ilpcycles_per_sec == 0) {
1854                 uint32 start, end, delta;
1855                 uint32 origidx = si_coreidx(sih);
1856                 chipcregs_t *cc = si_setcoreidx(sih, SI_CC_IDX);
1857                 ASSERT(cc != NULL);
1858                 start = R_REG(osh, &cc->pmutimer);
1859                 OSL_DELAY(ILP_CALC_DUR * 1000);
1860                 end = R_REG(osh, &cc->pmutimer);
1861                 delta = end - start;
1862                 ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
1863                 si_setcoreidx(sih, origidx);
1864         }
1865
1866         return ilpcycles_per_sec;
1867 }
1868
1869 /* SDIO Pad drive strength to select value mappings */
1870 typedef struct {
1871         uint8 strength;         /* Pad Drive Strength in mA */
1872         uint8 sel;              /* Chip-specific select value */
1873 } sdiod_drive_str_t;
1874
1875 /* SDIO Drive Strength to sel value table for PMU Rev 1 */
1876 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab1)[] =
1877 {
1878         {
1879         4, 0x2}, {
1880         2, 0x3}, {
1881         1, 0x0}, {
1882 0, 0x0}};
1883
1884 /* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
1885 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab2)[] =
1886 {
1887         {
1888         12, 0x7}, {
1889         10, 0x6}, {
1890         8, 0x5}, {
1891         6, 0x4}, {
1892         4, 0x2}, {
1893         2, 0x1}, {
1894 0, 0x0}};
1895
1896 /* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
1897 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab3)[] =
1898 {
1899         {
1900         32, 0x7}, {
1901         26, 0x6}, {
1902         22, 0x5}, {
1903         16, 0x4}, {
1904         12, 0x3}, {
1905         8, 0x2}, {
1906         4, 0x1}, {
1907 0, 0x0}};
1908
1909 #define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
1910
1911 void
1912 BCMINITFN(si_sdiod_drive_strength_init) (si_t * sih, osl_t * osh,
1913                                          uint32 drivestrength) {
1914         chipcregs_t *cc;
1915         uint origidx, intr_val = 0;
1916         sdiod_drive_str_t *str_tab = NULL;
1917         uint32 str_mask = 0;
1918         uint32 str_shift = 0;
1919 #ifdef BCMDBG
1920         char chn[8];
1921 #endif
1922
1923         if (!(sih->cccaps & CC_CAP_PMU)) {
1924                 return;
1925         }
1926
1927         /* Remember original core before switch to chipc */
1928         cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx,
1929                                             &intr_val);
1930
1931         switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) {
1932         case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
1933                 str_tab = (sdiod_drive_str_t *) & sdiod_drive_strength_tab3;
1934                 str_mask = 0x00003800;
1935                 str_shift = 11;
1936                 break;
1937
1938         default:
1939                 PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
1940
1941                 break;
1942         }
1943
1944         if (str_tab != NULL) {
1945                 uint32 drivestrength_sel = 0;
1946                 uint32 cc_data_temp;
1947                 int i;
1948
1949                 for (i = 0; str_tab[i].strength != 0; i++) {
1950                         if (drivestrength >= str_tab[i].strength) {
1951                                 drivestrength_sel = str_tab[i].sel;
1952                                 break;
1953                         }
1954                 }
1955
1956                 W_REG(osh, &cc->chipcontrol_addr, 1);
1957                 cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
1958                 cc_data_temp &= ~str_mask;
1959                 drivestrength_sel <<= str_shift;
1960                 cc_data_temp |= drivestrength_sel;
1961                 W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
1962
1963                 PMU_MSG(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
1964                          drivestrength, cc_data_temp));
1965         }
1966
1967         /* Return to original core */
1968         si_restore_core(sih, origidx, intr_val);
1969 }
1970
1971 /* initialize PMU */
1972 void BCMATTACHFN(si_pmu_init) (si_t * sih, osl_t * osh) {
1973         chipcregs_t *cc;
1974         uint origidx;
1975
1976         ASSERT(sih->cccaps & CC_CAP_PMU);
1977
1978         /* Remember original core before switch to chipc */
1979         origidx = si_coreidx(sih);
1980         cc = si_setcoreidx(sih, SI_CC_IDX);
1981         ASSERT(cc != NULL);
1982
1983         if (sih->pmurev == 1)
1984                 AND_REG(osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
1985         else if (sih->pmurev >= 2)
1986                 OR_REG(osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT);
1987
1988         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 2)) {
1989                 /* Fix for 4329b0 bad LPOM state. */
1990                 W_REG(osh, &cc->regcontrol_addr, 2);
1991                 OR_REG(osh, &cc->regcontrol_data, 0x100);
1992
1993                 W_REG(osh, &cc->regcontrol_addr, 3);
1994                 OR_REG(osh, &cc->regcontrol_data, 0x4);
1995         }
1996
1997         /* Return to original core */
1998         si_setcoreidx(sih, origidx);
1999 }
2000
2001 /* Return up time in ILP cycles for the given resource. */
2002 static uint
2003 BCMINITFN(si_pmu_res_uptime) (si_t * sih, osl_t * osh, chipcregs_t * cc,
2004                               uint8 rsrc) {
2005         uint32 deps;
2006         uint up, i, dup, dmax;
2007         uint32 min_mask = 0, max_mask = 0;
2008
2009         /* uptime of resource 'rsrc' */
2010         W_REG(osh, &cc->res_table_sel, rsrc);
2011         up = (R_REG(osh, &cc->res_updn_timer) >> 8) & 0xff;
2012
2013         /* direct dependancies of resource 'rsrc' */
2014         deps = si_pmu_res_deps(sih, osh, cc, PMURES_BIT(rsrc), FALSE);
2015         for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
2016                 if (!(deps & PMURES_BIT(i)))
2017                         continue;
2018                 deps &= ~si_pmu_res_deps(sih, osh, cc, PMURES_BIT(i), TRUE);
2019         }
2020         si_pmu_res_masks(sih, &min_mask, &max_mask);
2021         deps &= ~min_mask;
2022
2023         /* max uptime of direct dependancies */
2024         dmax = 0;
2025         for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
2026                 if (!(deps & PMURES_BIT(i)))
2027                         continue;
2028                 dup = si_pmu_res_uptime(sih, osh, cc, (uint8) i);
2029                 if (dmax < dup)
2030                         dmax = dup;
2031         }
2032
2033         PMU_MSG(("si_pmu_res_uptime: rsrc %u uptime %u(deps 0x%08x uptime %u)\n", rsrc, up, deps, dmax));
2034
2035         return up + dmax + PMURES_UP_TRANSITION;
2036 }
2037
2038 /* Return dependancies (direct or all/indirect) for the given resources */
2039 static uint32
2040 si_pmu_res_deps(si_t * sih, osl_t * osh, chipcregs_t * cc, uint32 rsrcs,
2041                 bool all)
2042 {
2043         uint32 deps = 0;
2044         uint32 i;
2045
2046         for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
2047                 if (!(rsrcs & PMURES_BIT(i)))
2048                         continue;
2049                 W_REG(osh, &cc->res_table_sel, i);
2050                 deps |= R_REG(osh, &cc->res_dep_mask);
2051         }
2052
2053         return !all ? deps : (deps
2054                               ? (deps |
2055                                  si_pmu_res_deps(sih, osh, cc, deps,
2056                                                  TRUE)) : 0);
2057 }
2058
2059 /* power up/down OTP through PMU resources */
2060 void si_pmu_otp_power(si_t * sih, osl_t * osh, bool on)
2061 {
2062         chipcregs_t *cc;
2063         uint origidx;
2064         uint32 rsrcs = 0;       /* rsrcs to turn on/off OTP power */
2065
2066         ASSERT(sih->cccaps & CC_CAP_PMU);
2067
2068         /* Don't do anything if OTP is disabled */
2069         if (si_is_otp_disabled(sih)) {
2070                 PMU_MSG(("si_pmu_otp_power: OTP is disabled\n"));
2071                 return;
2072         }
2073
2074         /* Remember original core before switch to chipc */
2075         origidx = si_coreidx(sih);
2076         cc = si_setcoreidx(sih, SI_CC_IDX);
2077         ASSERT(cc != NULL);
2078
2079         switch (CHIPID(sih->chip)) {
2080         case BCM4329_CHIP_ID:
2081                 rsrcs = PMURES_BIT(RES4329_OTP_PU);
2082                 break;
2083         case BCM4319_CHIP_ID:
2084                 rsrcs = PMURES_BIT(RES4319_OTP_PU);
2085                 break;
2086         case BCM4336_CHIP_ID:
2087                 rsrcs = PMURES_BIT(RES4336_OTP_PU);
2088                 break;
2089         case BCM4330_CHIP_ID:
2090                 rsrcs = PMURES_BIT(RES4330_OTP_PU);
2091                 break;
2092         default:
2093                 break;
2094         }
2095
2096         if (rsrcs != 0) {
2097                 uint32 otps;
2098
2099                 /* Figure out the dependancies (exclude min_res_mask) */
2100                 uint32 deps = si_pmu_res_deps(sih, osh, cc, rsrcs, TRUE);
2101                 uint32 min_mask = 0, max_mask = 0;
2102                 si_pmu_res_masks(sih, &min_mask, &max_mask);
2103                 deps &= ~min_mask;
2104                 /* Turn on/off the power */
2105                 if (on) {
2106                         PMU_MSG(("Adding rsrc 0x%x to min_res_mask\n",
2107                                  rsrcs | deps));
2108                         OR_REG(osh, &cc->min_res_mask, (rsrcs | deps));
2109                         SPINWAIT(!(R_REG(osh, &cc->res_state) & rsrcs),
2110                                  PMU_MAX_TRANSITION_DLY);
2111                         ASSERT(R_REG(osh, &cc->res_state) & rsrcs);
2112                 } else {
2113                         PMU_MSG(("Removing rsrc 0x%x from min_res_mask\n",
2114                                  rsrcs | deps));
2115                         AND_REG(osh, &cc->min_res_mask, ~(rsrcs | deps));
2116                 }
2117
2118                 SPINWAIT((((otps = R_REG(osh, &cc->otpstatus)) & OTPS_READY) !=
2119                           (on ? OTPS_READY : 0)), 100);
2120                 ASSERT((otps & OTPS_READY) == (on ? OTPS_READY : 0));
2121                 if ((otps & OTPS_READY) != (on ? OTPS_READY : 0))
2122                         PMU_MSG(("OTP ready bit not %s after wait\n",
2123                                  (on ? "ON" : "OFF")));
2124         }
2125
2126         /* Return to original core */
2127         si_setcoreidx(sih, origidx);
2128 }
2129
2130 void si_pmu_rcal(si_t * sih, osl_t * osh)
2131 {
2132         chipcregs_t *cc;
2133         uint origidx;
2134
2135         ASSERT(sih->cccaps & CC_CAP_PMU);
2136
2137         /* Remember original core before switch to chipc */
2138         origidx = si_coreidx(sih);
2139         cc = si_setcoreidx(sih, SI_CC_IDX);
2140         ASSERT(cc != NULL);
2141
2142         switch (CHIPID(sih->chip)) {
2143         case BCM4329_CHIP_ID:{
2144                         uint8 rcal_code;
2145                         uint32 val;
2146
2147                         /* Kick RCal */
2148                         W_REG(osh, &cc->chipcontrol_addr, 1);
2149
2150                         /* Power Down RCAL Block */
2151                         AND_REG(osh, &cc->chipcontrol_data, ~0x04);
2152
2153                         /* Power Up RCAL block */
2154                         OR_REG(osh, &cc->chipcontrol_data, 0x04);
2155
2156                         /* Wait for completion */
2157                         SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08),
2158                                  10 * 1000 * 1000);
2159                         ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
2160
2161                         /* Drop the LSB to convert from 5 bit code to 4 bit code */
2162                         rcal_code =
2163                             (uint8) (R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
2164
2165                         PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
2166                                  R_REG(osh, &cc->chipstatus), rcal_code));
2167
2168                         /* Write RCal code into pmu_vreg_ctrl[32:29] */
2169                         W_REG(osh, &cc->regcontrol_addr, 0);
2170                         val =
2171                             R_REG(osh,
2172                                   &cc->
2173                                   regcontrol_data) & ~((uint32) 0x07 << 29);
2174                         val |= (uint32) (rcal_code & 0x07) << 29;
2175                         W_REG(osh, &cc->regcontrol_data, val);
2176                         W_REG(osh, &cc->regcontrol_addr, 1);
2177                         val = R_REG(osh, &cc->regcontrol_data) & ~(uint32) 0x01;
2178                         val |= (uint32) ((rcal_code >> 3) & 0x01);
2179                         W_REG(osh, &cc->regcontrol_data, val);
2180
2181                         /* Write RCal code into pmu_chip_ctrl[33:30] */
2182                         W_REG(osh, &cc->chipcontrol_addr, 0);
2183                         val =
2184                             R_REG(osh,
2185                                   &cc->
2186                                   chipcontrol_data) & ~((uint32) 0x03 << 30);
2187                         val |= (uint32) (rcal_code & 0x03) << 30;
2188                         W_REG(osh, &cc->chipcontrol_data, val);
2189                         W_REG(osh, &cc->chipcontrol_addr, 1);
2190                         val =
2191                             R_REG(osh, &cc->chipcontrol_data) & ~(uint32) 0x03;
2192                         val |= (uint32) ((rcal_code >> 2) & 0x03);
2193                         W_REG(osh, &cc->chipcontrol_data, val);
2194
2195                         /* Set override in pmu_chip_ctrl[29] */
2196                         W_REG(osh, &cc->chipcontrol_addr, 0);
2197                         OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
2198
2199                         /* Power off RCal block */
2200                         W_REG(osh, &cc->chipcontrol_addr, 1);
2201                         AND_REG(osh, &cc->chipcontrol_data, ~0x04);
2202
2203                         break;
2204                 }
2205         default:
2206                 break;
2207         }
2208
2209         /* Return to original core */
2210         si_setcoreidx(sih, origidx);
2211 }
2212
2213 void si_pmu_spuravoid(si_t * sih, osl_t * osh, uint8 spuravoid)
2214 {
2215         chipcregs_t *cc;
2216         uint origidx, intr_val;
2217         uint32 tmp = 0;
2218
2219         /* Remember original core before switch to chipc */
2220         cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx,
2221                                             &intr_val);
2222         ASSERT(cc != NULL);
2223
2224         /* force the HT off  */
2225         if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
2226                 tmp = R_REG(osh, &cc->max_res_mask);
2227                 tmp &= ~RES4336_HT_AVAIL;
2228                 W_REG(osh, &cc->max_res_mask, tmp);
2229                 /* wait for the ht to really go away */
2230                 SPINWAIT(((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0),
2231                          10000);
2232                 ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0);
2233         }
2234
2235         /* update the pll changes */
2236         si_pmu_spuravoid_pllupdate(sih, cc, osh, spuravoid);
2237
2238         /* enable HT back on  */
2239         if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
2240                 tmp = R_REG(osh, &cc->max_res_mask);
2241                 tmp |= RES4336_HT_AVAIL;
2242                 W_REG(osh, &cc->max_res_mask, tmp);
2243         }
2244
2245         /* Return to original core */
2246         si_restore_core(sih, origidx, intr_val);
2247 }
2248
2249 static void
2250 si_pmu_spuravoid_pllupdate(si_t * sih, chipcregs_t * cc, osl_t * osh,
2251                            uint8 spuravoid)
2252 {
2253         uint32 tmp = 0;
2254         uint8 phypll_offset = 0;
2255         uint8 bcm5357_bcm43236_p1div[] = { 0x1, 0x5, 0x5 };
2256         uint8 bcm5357_bcm43236_ndiv[] = { 0x30, 0xf6, 0xfc };
2257
2258         switch (CHIPID(sih->chip)) {
2259         case BCM5357_CHIP_ID:
2260         case BCM43235_CHIP_ID:
2261         case BCM43236_CHIP_ID:
2262         case BCM43238_CHIP_ID:
2263
2264                 /* BCM5357 needs to touch PLL1_PLLCTL[02], so offset PLL0_PLLCTL[02] by 6 */
2265                 phypll_offset = (CHIPID(sih->chip) == BCM5357_CHIP_ID) ? 6 : 0;
2266
2267                 /* RMW only the P1 divider */
2268                 W_REG(osh, &cc->pllcontrol_addr,
2269                       PMU1_PLL0_PLLCTL0 + phypll_offset);
2270                 tmp = R_REG(osh, &cc->pllcontrol_data);
2271                 tmp &= (~(PMU1_PLL0_PC0_P1DIV_MASK));
2272                 tmp |=
2273                     (bcm5357_bcm43236_p1div[spuravoid] <<
2274                      PMU1_PLL0_PC0_P1DIV_SHIFT);
2275                 W_REG(osh, &cc->pllcontrol_data, tmp);
2276
2277                 /* RMW only the int feedback divider */
2278                 W_REG(osh, &cc->pllcontrol_addr,
2279                       PMU1_PLL0_PLLCTL2 + phypll_offset);
2280                 tmp = R_REG(osh, &cc->pllcontrol_data);
2281                 tmp &= ~(PMU1_PLL0_PC2_NDIV_INT_MASK);
2282                 tmp |=
2283                     (bcm5357_bcm43236_ndiv[spuravoid]) <<
2284                     PMU1_PLL0_PC2_NDIV_INT_SHIFT;
2285                 W_REG(osh, &cc->pllcontrol_data, tmp);
2286
2287                 tmp = 1 << 10;
2288                 break;
2289
2290         case BCM4331_CHIP_ID:
2291                 if (spuravoid == 2) {
2292                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2293                         W_REG(osh, &cc->pllcontrol_data, 0x11500014);
2294                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2295                         W_REG(osh, &cc->pllcontrol_data, 0x0FC00a08);
2296                 } else if (spuravoid == 1) {
2297                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2298                         W_REG(osh, &cc->pllcontrol_data, 0x11500014);
2299                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2300                         W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
2301                 } else {
2302                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2303                         W_REG(osh, &cc->pllcontrol_data, 0x11100014);
2304                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2305                         W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
2306                 }
2307                 tmp = 1 << 10;
2308                 break;
2309
2310         case BCM43224_CHIP_ID:
2311         case BCM43225_CHIP_ID:
2312         case BCM43421_CHIP_ID:
2313         case BCM6362_CHIP_ID:
2314                 if (spuravoid == 1) {
2315                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2316                         W_REG(osh, &cc->pllcontrol_data, 0x11500010);
2317                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2318                         W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
2319                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2320                         W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
2321                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2322                         W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2323                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2324                         W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
2325                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2326                         W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2327                 } else {
2328                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2329                         W_REG(osh, &cc->pllcontrol_data, 0x11100010);
2330                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2331                         W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
2332                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2333                         W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
2334                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2335                         W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2336                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2337                         W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
2338                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2339                         W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2340                 }
2341                 tmp = 1 << 10;
2342                 break;
2343
2344                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2345                 W_REG(osh, &cc->pllcontrol_data, 0x11100008);
2346                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2347                 W_REG(osh, &cc->pllcontrol_data, 0x0c000c06);
2348                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2349                 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
2350                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2351                 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2352                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2353                 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
2354                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2355                 W_REG(osh, &cc->pllcontrol_data, 0x88888855);
2356
2357                 tmp = 1 << 10;
2358                 break;
2359
2360         case BCM4716_CHIP_ID:
2361         case BCM4748_CHIP_ID:
2362         case BCM47162_CHIP_ID:
2363                 if (spuravoid == 1) {
2364                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2365                         W_REG(osh, &cc->pllcontrol_data, 0x11500060);
2366                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2367                         W_REG(osh, &cc->pllcontrol_data, 0x080C0C06);
2368                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2369                         W_REG(osh, &cc->pllcontrol_data, 0x0F600000);
2370                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2371                         W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2372                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2373                         W_REG(osh, &cc->pllcontrol_data, 0x2001E924);
2374                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2375                         W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2376                 } else {
2377                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2378                         W_REG(osh, &cc->pllcontrol_data, 0x11100060);
2379                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2380                         W_REG(osh, &cc->pllcontrol_data, 0x080c0c06);
2381                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2382                         W_REG(osh, &cc->pllcontrol_data, 0x03000000);
2383                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2384                         W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2385                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2386                         W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
2387                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2388                         W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2389                 }
2390
2391                 tmp = 3 << 9;
2392                 break;
2393
2394         case BCM4319_CHIP_ID:
2395                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2396                 W_REG(osh, &cc->pllcontrol_data, 0x11100070);
2397                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2398                 W_REG(osh, &cc->pllcontrol_data, 0x1014140a);
2399                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2400                 W_REG(osh, &cc->pllcontrol_data, 0x88888854);
2401
2402                 if (spuravoid == 1) {   /* spur_avoid ON, enable 41/82/164Mhz clock mode */
2403                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2404                         W_REG(osh, &cc->pllcontrol_data, 0x05201828);
2405                 } else {        /* enable 40/80/160Mhz clock mode */
2406                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2407                         W_REG(osh, &cc->pllcontrol_data, 0x05001828);
2408                 }
2409                 break;
2410         case BCM4336_CHIP_ID:
2411                 /* Looks like these are only for default xtal freq 26MHz */
2412                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2413                 W_REG(osh, &cc->pllcontrol_data, 0x02100020);
2414
2415                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2416                 W_REG(osh, &cc->pllcontrol_data, 0x0C0C0C0C);
2417
2418                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2419                 W_REG(osh, &cc->pllcontrol_data, 0x01240C0C);
2420
2421                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2422                 W_REG(osh, &cc->pllcontrol_data, 0x202C2820);
2423
2424                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2425                 W_REG(osh, &cc->pllcontrol_data, 0x88888825);
2426
2427                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2428                 if (spuravoid == 1) {
2429                         W_REG(osh, &cc->pllcontrol_data, 0x00EC4EC4);
2430                 } else {
2431                         W_REG(osh, &cc->pllcontrol_data, 0x00762762);
2432                 }
2433
2434                 tmp = PCTL_PLL_PLLCTL_UPD;
2435                 break;
2436
2437         default:
2438                 PMU_ERROR(("%s: unknown spuravoidance settings for chip %s, not changing PLL\n", __func__, bcm_chipname(sih->chip, chn, 8)));
2439                 break;
2440         }
2441
2442         tmp |= R_REG(osh, &cc->pmucontrol);
2443         W_REG(osh, &cc->pmucontrol, tmp);
2444 }
2445
2446 bool si_pmu_is_otp_powered(si_t * sih, osl_t * osh)
2447 {
2448         uint idx;
2449         chipcregs_t *cc;
2450         bool st;
2451
2452         /* Remember original core before switch to chipc */
2453         idx = si_coreidx(sih);
2454         cc = si_setcoreidx(sih, SI_CC_IDX);
2455         ASSERT(cc != NULL);
2456
2457         switch (CHIPID(sih->chip)) {
2458         case BCM4329_CHIP_ID:
2459                 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4329_OTP_PU))
2460                     != 0;
2461                 break;
2462         case BCM4319_CHIP_ID:
2463                 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4319_OTP_PU))
2464                     != 0;
2465                 break;
2466         case BCM4336_CHIP_ID:
2467                 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4336_OTP_PU))
2468                     != 0;
2469                 break;
2470         case BCM4330_CHIP_ID:
2471                 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4330_OTP_PU))
2472                     != 0;
2473                 break;
2474
2475                 /* These chip doesn't use PMU bit to power up/down OTP. OTP always on.
2476                  * Use OTP_INIT command to reset/refresh state.
2477                  */
2478         case BCM43224_CHIP_ID:
2479         case BCM43225_CHIP_ID:
2480         case BCM43421_CHIP_ID:
2481         case BCM43236_CHIP_ID:
2482         case BCM43235_CHIP_ID:
2483         case BCM43238_CHIP_ID:
2484                 st = TRUE;
2485                 break;
2486         default:
2487                 st = TRUE;
2488                 break;
2489         }
2490
2491         /* Return to original core */
2492         si_setcoreidx(sih, idx);
2493         return st;
2494 }
2495
2496 void
2497 #if defined(BCMDBG)
2498 si_pmu_sprom_enable(si_t * sih, osl_t * osh, bool enable)
2499 #else
2500 BCMATTACHFN(si_pmu_sprom_enable) (si_t * sih, osl_t * osh, bool enable)
2501 #endif
2502 {
2503         chipcregs_t *cc;
2504         uint origidx;
2505
2506         /* Remember original core before switch to chipc */
2507         origidx = si_coreidx(sih);
2508         cc = si_setcoreidx(sih, SI_CC_IDX);
2509         ASSERT(cc != NULL);
2510
2511         /* Return to original core */
2512         si_setcoreidx(sih, origidx);
2513 }
2514
2515 /* initialize PMU chip controls and other chip level stuff */
2516 void BCMATTACHFN(si_pmu_chip_init) (si_t * sih, osl_t * osh) {
2517         uint origidx;
2518
2519         ASSERT(sih->cccaps & CC_CAP_PMU);
2520
2521 #ifdef CHIPC_UART_ALWAYS_ON
2522         si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st),
2523                    CCS_FORCEALP, CCS_FORCEALP);
2524 #endif                          /* CHIPC_UART_ALWAYS_ON */
2525
2526         /* Gate off SPROM clock and chip select signals */
2527         si_pmu_sprom_enable(sih, osh, FALSE);
2528
2529         /* Remember original core */
2530         origidx = si_coreidx(sih);
2531
2532         /* Return to original core */
2533         si_setcoreidx(sih, origidx);
2534 }
2535
2536 /* initialize PMU switch/regulators */
2537 void BCMATTACHFN(si_pmu_swreg_init) (si_t * sih, osl_t * osh) {
2538         ASSERT(sih->cccaps & CC_CAP_PMU);
2539
2540         switch (CHIPID(sih->chip)) {
2541         case BCM4336_CHIP_ID:
2542                 /* Reduce CLDO PWM output voltage to 1.2V */
2543                 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xe);
2544                 /* Reduce CLDO BURST output voltage to 1.2V */
2545                 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_BURST,
2546                                        0xe);
2547                 /* Reduce LNLDO1 output voltage to 1.2V */
2548                 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO1, 0xe);
2549                 if (CHIPREV(sih->chiprev) == 0)
2550                         si_pmu_regcontrol(sih, 2, 0x400000, 0x400000);
2551                 break;
2552
2553         case BCM4330_CHIP_ID:
2554                 /* CBUCK Voltage is 1.8 by default and set that to 1.5 */
2555                 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0);
2556                 break;
2557         default:
2558                 break;
2559         }
2560 }
2561
2562 void si_pmu_radio_enable(si_t * sih, bool enable)
2563 {
2564         ASSERT(sih->cccaps & CC_CAP_PMU);
2565
2566         switch (CHIPID(sih->chip)) {
2567         case BCM4319_CHIP_ID:
2568                 if (enable)
2569                         si_write_wrapperreg(sih, AI_OOBSELOUTB74,
2570                                             (uint32) 0x868584);
2571                 else
2572                         si_write_wrapperreg(sih, AI_OOBSELOUTB74,
2573                                             (uint32) 0x060584);
2574                 break;
2575         }
2576 }
2577
2578 /* Wait for a particular clock level to be on the backplane */
2579 uint32
2580 si_pmu_waitforclk_on_backplane(si_t * sih, osl_t * osh, uint32 clk,
2581                                uint32 delay)
2582 {
2583         chipcregs_t *cc;
2584         uint origidx;
2585
2586         ASSERT(sih->cccaps & CC_CAP_PMU);
2587
2588         /* Remember original core before switch to chipc */
2589         origidx = si_coreidx(sih);
2590         cc = si_setcoreidx(sih, SI_CC_IDX);
2591         ASSERT(cc != NULL);
2592
2593         if (delay)
2594                 SPINWAIT(((R_REG(osh, &cc->pmustatus) & clk) != clk), delay);
2595
2596         /* Return to original core */
2597         si_setcoreidx(sih, origidx);
2598
2599         return (R_REG(osh, &cc->pmustatus) & clk);
2600 }
2601
2602 /*
2603  * Measures the ALP clock frequency in KHz.  Returns 0 if not possible.
2604  * Possible only if PMU rev >= 10 and there is an external LPO 32768Hz crystal.
2605  */
2606
2607 #define EXT_ILP_HZ 32768
2608
2609 uint32 BCMATTACHFN(si_pmu_measure_alpclk) (si_t * sih, osl_t * osh) {
2610         chipcregs_t *cc;
2611         uint origidx;
2612         uint32 alp_khz;
2613
2614         if (sih->pmurev < 10)
2615                 return 0;
2616
2617         ASSERT(sih->cccaps & CC_CAP_PMU);
2618
2619         /* Remember original core before switch to chipc */
2620         origidx = si_coreidx(sih);
2621         cc = si_setcoreidx(sih, SI_CC_IDX);
2622         ASSERT(cc != NULL);
2623
2624         if (R_REG(osh, &cc->pmustatus) & PST_EXTLPOAVAIL) {
2625                 uint32 ilp_ctr, alp_hz;
2626
2627                 /* Enable the reg to measure the freq, in case disabled before */
2628                 W_REG(osh, &cc->pmu_xtalfreq,
2629                       1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
2630
2631                 /* Delay for well over 4 ILP clocks */
2632                 OSL_DELAY(1000);
2633
2634                 /* Read the latched number of ALP ticks per 4 ILP ticks */
2635                 ilp_ctr =
2636                     R_REG(osh,
2637                           &cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
2638
2639                 /* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT bit to save power */
2640                 W_REG(osh, &cc->pmu_xtalfreq, 0);
2641
2642                 /* Calculate ALP frequency */
2643                 alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
2644
2645                 /* Round to nearest 100KHz, and at the same time convert to KHz */
2646                 alp_khz = (alp_hz + 50000) / 100000 * 100;
2647         } else
2648                 alp_khz = 0;
2649
2650         /* Return to original core */
2651         si_setcoreidx(sih, origidx);
2652
2653         return alp_khz;
2654 }
2655
2656 static void BCMATTACHFN(si_pmu_set_4330_plldivs) (si_t * sih) {
2657         uint32 FVCO = si_pmu1_pllfvco0(sih) / 1000;
2658         uint32 m1div, m2div, m3div, m4div, m5div, m6div;
2659         uint32 pllc1, pllc2;
2660
2661         m2div = m3div = m4div = m6div = FVCO / 80;
2662         m5div = FVCO / 160;
2663
2664         if (CST4330_CHIPMODE_SDIOD(sih->chipst))
2665                 m1div = FVCO / 80;
2666         else
2667                 m1div = FVCO / 90;
2668         pllc1 =
2669             (m1div << PMU1_PLL0_PC1_M1DIV_SHIFT) | (m2div <<
2670                                                     PMU1_PLL0_PC1_M2DIV_SHIFT) |
2671             (m3div << PMU1_PLL0_PC1_M3DIV_SHIFT) | (m4div <<
2672                                                     PMU1_PLL0_PC1_M4DIV_SHIFT);
2673         si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, ~0, pllc1);
2674
2675         pllc2 = si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, 0, 0);
2676         pllc2 &= ~(PMU1_PLL0_PC2_M5DIV_MASK | PMU1_PLL0_PC2_M6DIV_MASK);
2677         pllc2 |=
2678             ((m5div << PMU1_PLL0_PC2_M5DIV_SHIFT) |
2679              (m6div << PMU1_PLL0_PC2_M6DIV_SHIFT));
2680         si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL2, ~0, pllc2);
2681 }