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