]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/brcm80211/util/hndpmu.c
Staging: brcm80211: remove BCMATTACHFN macro
[net-next-2.6.git] / drivers / staging / brcm80211 / util / hndpmu.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <typedefs.h>
18 #include <bcmdefs.h>
19 #include <osl.h>
20 #include <linux/string.h>
21 #include <linuxver.h>
22 #include <linux/kernel.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, osl_t *osh, chipcregs_t *cc,
46                              u32 xtal);
47 static u32 si_pmu1_cpuclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
48 static u32 si_pmu1_alpclk0(si_t *sih, osl_t *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, osl_t *osh, chipcregs_t *cc,
56                               u32 rsrcs, bool all);
57 static uint si_pmu_res_uptime(si_t *sih, osl_t *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                                        osl_t *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, osl_t *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, osl_t *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 (CHIPID(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 BCMINITFN(si_pmu_fast_pwrup_delay) (si_t *sih, osl_t *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 (CHIPID(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, osl_t *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 BCMINITDATA(bcm4329_res_updown)[] = {
459         {
460         RES4329_XTAL_PU, 0x1501}
461 };
462
463 static const pmu_res_depend_t BCMINITDATA(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 (CHIPID(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, osl_t *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 (CHIPID(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         OSL_DELAY(2000);
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 BCMINITDATA(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 BCMINITDATA(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 BCMINITDATA(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 BCMINITDATA(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 BCMINITDATA(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 BCMINITDATA(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 *BCMINITFN(si_pmu1_xtaltab0) (si_t *sih)
1096 {
1097 #ifdef BCMDBG
1098         char chn[8];
1099 #endif
1100         switch (CHIPID(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 *BCMINITFN(si_pmu1_xtaldef0) (si_t *sih)
1123 {
1124 #ifdef BCMDBG
1125         char chn[8];
1126 #endif
1127
1128         switch (CHIPID(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 BCMINITFN(si_pmu1_pllfvco0) (si_t *sih)
1155 {
1156 #ifdef BCMDBG
1157         char chn[8];
1158 #endif
1159
1160         switch (CHIPID(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 BCMINITFN(si_pmu1_alpclk0) (si_t *sih, osl_t *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, osl_t *osh, chipcregs_t *cc, u32 xtal)
1209 {
1210         const pmu1_xtaltab0_t *xt;
1211         u32 tmp;
1212         u32 buf_strength = 0;
1213         u8 ndiv_mode = 1;
1214
1215         /* Use h/w default PLL config */
1216         if (xtal == 0) {
1217                 PMU_MSG(("Unspecified xtal frequency, skip PLL configuration\n"));
1218                 return;
1219         }
1220
1221         /* Find the frequency in the table */
1222         for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt++)
1223                 if (xt->fref == xtal)
1224                         break;
1225
1226         /* Check current PLL state, bail out if it has been programmed or
1227          * we don't know how to program it.
1228          */
1229         if (xt == NULL || xt->fref == 0) {
1230                 PMU_MSG(("Unsupported xtal frequency %d.%d MHz, skip PLL configuration\n", xtal / 1000, xtal % 1000));
1231                 return;
1232         }
1233         /*  for 4319 bootloader already programs the PLL but bootloader does not program the
1234            PLL4 and PLL5. So Skip this check for 4319
1235          */
1236         if ((((R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1237               PCTL_XTALFREQ_SHIFT) == xt->xf) &&
1238             !((CHIPID(sih->chip) == BCM4319_CHIP_ID)
1239               || (CHIPID(sih->chip) == BCM4330_CHIP_ID))) {
1240                 PMU_MSG(("PLL already programmed for %d.%d MHz\n",
1241                          xt->fref / 1000, xt->fref % 1000));
1242                 return;
1243         }
1244
1245         PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
1246         PMU_MSG(("Programming PLL for %d.%d MHz\n", xt->fref / 1000,
1247                  xt->fref % 1000));
1248
1249         switch (CHIPID(sih->chip)) {
1250         case BCM4329_CHIP_ID:
1251                 /* Change the BBPLL drive strength to 8 for all channels */
1252                 buf_strength = 0x888888;
1253                 AND_REG(osh, &cc->min_res_mask,
1254                         ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) |
1255                           PMURES_BIT(RES4329_HT_AVAIL)));
1256                 AND_REG(osh, &cc->max_res_mask,
1257                         ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) |
1258                           PMURES_BIT(RES4329_HT_AVAIL)));
1259                 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
1260                          PMU_MAX_TRANSITION_DLY);
1261                 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1262                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
1263                 if (xt->fref == 38400)
1264                         tmp = 0x200024C0;
1265                 else if (xt->fref == 37400)
1266                         tmp = 0x20004500;
1267                 else if (xt->fref == 26000)
1268                         tmp = 0x200024C0;
1269                 else
1270                         tmp = 0x200005C0;       /* Chip Dflt Settings */
1271                 W_REG(osh, &cc->pllcontrol_data, tmp);
1272                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
1273                 tmp =
1274                     R_REG(osh,
1275                           &cc->pllcontrol_data) & PMU1_PLL0_PC5_CLK_DRV_MASK;
1276                 if ((xt->fref == 38400) || (xt->fref == 37400)
1277                     || (xt->fref == 26000))
1278                         tmp |= 0x15;
1279                 else
1280                         tmp |= 0x25;    /* Chip Dflt Settings */
1281                 W_REG(osh, &cc->pllcontrol_data, tmp);
1282                 break;
1283
1284         case BCM4319_CHIP_ID:
1285                 /* Change the BBPLL drive strength to 2 for all channels */
1286                 buf_strength = 0x222222;
1287
1288                 /* Make sure the PLL is off */
1289                 /* WAR65104: Disable the HT_AVAIL resource first and then
1290                  * after a delay (more than downtime for HT_AVAIL) remove the
1291                  * BBPLL resource; backplane clock moves to ALP from HT.
1292                  */
1293                 AND_REG(osh, &cc->min_res_mask,
1294                         ~(PMURES_BIT(RES4319_HT_AVAIL)));
1295                 AND_REG(osh, &cc->max_res_mask,
1296                         ~(PMURES_BIT(RES4319_HT_AVAIL)));
1297
1298                 OSL_DELAY(100);
1299                 AND_REG(osh, &cc->min_res_mask,
1300                         ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
1301                 AND_REG(osh, &cc->max_res_mask,
1302                         ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
1303
1304                 OSL_DELAY(100);
1305                 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
1306                          PMU_MAX_TRANSITION_DLY);
1307                 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1308                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
1309                 tmp = 0x200005c0;
1310                 W_REG(osh, &cc->pllcontrol_data, tmp);
1311                 break;
1312
1313         case BCM4336_CHIP_ID:
1314                 AND_REG(osh, &cc->min_res_mask,
1315                         ~(PMURES_BIT(RES4336_HT_AVAIL) |
1316                           PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
1317                 AND_REG(osh, &cc->max_res_mask,
1318                         ~(PMURES_BIT(RES4336_HT_AVAIL) |
1319                           PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
1320                 OSL_DELAY(100);
1321                 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
1322                          PMU_MAX_TRANSITION_DLY);
1323                 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1324                 break;
1325
1326         case BCM4330_CHIP_ID:
1327                 AND_REG(osh, &cc->min_res_mask,
1328                         ~(PMURES_BIT(RES4330_HT_AVAIL) |
1329                           PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
1330                 AND_REG(osh, &cc->max_res_mask,
1331                         ~(PMURES_BIT(RES4330_HT_AVAIL) |
1332                           PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
1333                 OSL_DELAY(100);
1334                 SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
1335                          PMU_MAX_TRANSITION_DLY);
1336                 ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1337                 break;
1338
1339         default:
1340                 ASSERT(0);
1341         }
1342
1343         PMU_MSG(("Done masking\n"));
1344
1345         /* Write p1div and p2div to pllcontrol[0] */
1346         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
1347         tmp = R_REG(osh, &cc->pllcontrol_data) &
1348             ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
1349         tmp |=
1350             ((xt->
1351               p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) |
1352             ((xt->
1353               p2div << PMU1_PLL0_PC0_P2DIV_SHIFT) & PMU1_PLL0_PC0_P2DIV_MASK);
1354         W_REG(osh, &cc->pllcontrol_data, tmp);
1355
1356         if ((CHIPID(sih->chip) == BCM4330_CHIP_ID))
1357                 si_pmu_set_4330_plldivs(sih);
1358
1359         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID)
1360             && (CHIPREV(sih->chiprev) == 0)) {
1361
1362                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
1363                 tmp = R_REG(osh, &cc->pllcontrol_data);
1364                 tmp = tmp & (~DOT11MAC_880MHZ_CLK_DIVISOR_MASK);
1365                 tmp = tmp | DOT11MAC_880MHZ_CLK_DIVISOR_VAL;
1366                 W_REG(osh, &cc->pllcontrol_data, tmp);
1367         }
1368         if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
1369             (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
1370             (CHIPID(sih->chip) == BCM4330_CHIP_ID))
1371                 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
1372         else
1373                 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MASH;
1374
1375         /* Write ndiv_int and ndiv_mode to pllcontrol[2] */
1376         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
1377         tmp = R_REG(osh, &cc->pllcontrol_data) &
1378             ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
1379         tmp |=
1380             ((xt->
1381               ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) &
1382              PMU1_PLL0_PC2_NDIV_INT_MASK) | ((ndiv_mode <<
1383                                               PMU1_PLL0_PC2_NDIV_MODE_SHIFT) &
1384                                              PMU1_PLL0_PC2_NDIV_MODE_MASK);
1385         W_REG(osh, &cc->pllcontrol_data, tmp);
1386
1387         /* Write ndiv_frac to pllcontrol[3] */
1388         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
1389         tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
1390         tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
1391                 PMU1_PLL0_PC3_NDIV_FRAC_MASK);
1392         W_REG(osh, &cc->pllcontrol_data, tmp);
1393
1394         /* Write clock driving strength to pllcontrol[5] */
1395         if (buf_strength) {
1396                 PMU_MSG(("Adjusting PLL buffer drive strength: %x\n",
1397                          buf_strength));
1398
1399                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
1400                 tmp =
1401                     R_REG(osh,
1402                           &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
1403                 tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
1404                 W_REG(osh, &cc->pllcontrol_data, tmp);
1405         }
1406
1407         PMU_MSG(("Done pll\n"));
1408
1409         /* to operate the 4319 usb in 24MHz/48MHz; chipcontrol[2][84:83] needs
1410          * to be updated.
1411          */
1412         if ((CHIPID(sih->chip) == BCM4319_CHIP_ID)
1413             && (xt->fref != XTAL_FREQ_30000MHZ)) {
1414                 W_REG(osh, &cc->chipcontrol_addr, PMU1_PLL0_CHIPCTL2);
1415                 tmp =
1416                     R_REG(osh,
1417                           &cc->chipcontrol_data) & ~CCTL_4319USB_XTAL_SEL_MASK;
1418                 if (xt->fref == XTAL_FREQ_24000MHZ) {
1419                         tmp |=
1420                             (CCTL_4319USB_24MHZ_PLL_SEL <<
1421                              CCTL_4319USB_XTAL_SEL_SHIFT);
1422                 } else if (xt->fref == XTAL_FREQ_48000MHZ) {
1423                         tmp |=
1424                             (CCTL_4319USB_48MHZ_PLL_SEL <<
1425                              CCTL_4319USB_XTAL_SEL_SHIFT);
1426                 }
1427                 W_REG(osh, &cc->chipcontrol_data, tmp);
1428         }
1429
1430         /* Flush deferred pll control registers writes */
1431         if (sih->pmurev >= 2)
1432                 OR_REG(osh, &cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
1433
1434         /* Write XtalFreq. Set the divisor also. */
1435         tmp = R_REG(osh, &cc->pmucontrol) &
1436             ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
1437         tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
1438                 PCTL_ILP_DIV_MASK) |
1439             ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
1440
1441         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID)
1442             && CHIPREV(sih->chiprev) == 0) {
1443                 /* clear the htstretch before clearing HTReqEn */
1444                 AND_REG(osh, &cc->clkstretch, ~CSTRETCH_HT);
1445                 tmp &= ~PCTL_HT_REQ_EN;
1446         }
1447
1448         W_REG(osh, &cc->pmucontrol, tmp);
1449 }
1450
1451 /* query the CPU clock frequency */
1452 static u32
1453 BCMINITFN(si_pmu1_cpuclk0) (si_t *sih, osl_t *osh, chipcregs_t *cc)
1454 {
1455         u32 tmp, m1div;
1456 #ifdef BCMDBG
1457         u32 ndiv_int, ndiv_frac, p2div, p1div, fvco;
1458         u32 fref;
1459 #endif
1460         u32 FVCO = si_pmu1_pllfvco0(sih);
1461
1462         /* Read m1div from pllcontrol[1] */
1463         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
1464         tmp = R_REG(osh, &cc->pllcontrol_data);
1465         m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT;
1466
1467 #ifdef BCMDBG
1468         /* Read p2div/p1div from pllcontrol[0] */
1469         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
1470         tmp = R_REG(osh, &cc->pllcontrol_data);
1471         p2div = (tmp & PMU1_PLL0_PC0_P2DIV_MASK) >> PMU1_PLL0_PC0_P2DIV_SHIFT;
1472         p1div = (tmp & PMU1_PLL0_PC0_P1DIV_MASK) >> PMU1_PLL0_PC0_P1DIV_SHIFT;
1473
1474         /* Calculate fvco based on xtal freq and ndiv and pdiv */
1475         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
1476         tmp = R_REG(osh, &cc->pllcontrol_data);
1477         ndiv_int =
1478             (tmp & PMU1_PLL0_PC2_NDIV_INT_MASK) >> PMU1_PLL0_PC2_NDIV_INT_SHIFT;
1479
1480         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
1481         tmp = R_REG(osh, &cc->pllcontrol_data);
1482         ndiv_frac =
1483             (tmp & PMU1_PLL0_PC3_NDIV_FRAC_MASK) >>
1484             PMU1_PLL0_PC3_NDIV_FRAC_SHIFT;
1485
1486         fref = si_pmu1_alpclk0(sih, osh, cc) / 1000;
1487
1488         fvco = (fref * ndiv_int) << 8;
1489         fvco += (fref * (ndiv_frac >> 12)) >> 4;
1490         fvco += (fref * (ndiv_frac & 0xfff)) >> 12;
1491         fvco >>= 8;
1492         fvco *= p2div;
1493         fvco /= p1div;
1494         fvco /= 1000;
1495         fvco *= 1000;
1496
1497         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));
1498
1499         FVCO = fvco;
1500 #endif                          /* BCMDBG */
1501
1502         /* Return ARM/SB clock */
1503         return FVCO / m1div * 1000;
1504 }
1505
1506 /* initialize PLL */
1507 void si_pmu_pll_init(si_t *sih, osl_t *osh, uint xtalfreq)
1508 {
1509         chipcregs_t *cc;
1510         uint origidx;
1511 #ifdef BCMDBG
1512         char chn[8];
1513 #endif
1514
1515         ASSERT(sih->cccaps & CC_CAP_PMU);
1516
1517         /* Remember original core before switch to chipc */
1518         origidx = si_coreidx(sih);
1519         cc = si_setcoreidx(sih, SI_CC_IDX);
1520         ASSERT(cc != NULL);
1521
1522         switch (CHIPID(sih->chip)) {
1523         case BCM4329_CHIP_ID:
1524                 if (xtalfreq == 0)
1525                         xtalfreq = 38400;
1526                 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
1527                 break;
1528         case BCM4313_CHIP_ID:
1529         case BCM43224_CHIP_ID:
1530         case BCM43225_CHIP_ID:
1531         case BCM43421_CHIP_ID:
1532         case BCM43235_CHIP_ID:
1533         case BCM43236_CHIP_ID:
1534         case BCM43238_CHIP_ID:
1535         case BCM4331_CHIP_ID:
1536         case BCM6362_CHIP_ID:
1537                 /* ??? */
1538                 break;
1539         case BCM4319_CHIP_ID:
1540         case BCM4336_CHIP_ID:
1541         case BCM4330_CHIP_ID:
1542                 si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
1543                 break;
1544         default:
1545                 PMU_MSG(("No PLL init done for chip %s rev %d pmurev %d\n",
1546                          bcm_chipname(sih->chip, chn, 8), sih->chiprev,
1547                          sih->pmurev));
1548                 break;
1549         }
1550
1551 #ifdef BCMDBG_FORCEHT
1552         OR_REG(osh, &cc->clk_ctl_st, CCS_FORCEHT);
1553 #endif
1554
1555         /* Return to original core */
1556         si_setcoreidx(sih, origidx);
1557 }
1558
1559 /* query alp/xtal clock frequency */
1560 u32 BCMINITFN(si_pmu_alp_clock) (si_t *sih, osl_t *osh)
1561 {
1562         chipcregs_t *cc;
1563         uint origidx;
1564         u32 clock = ALP_CLOCK;
1565 #ifdef BCMDBG
1566         char chn[8];
1567 #endif
1568
1569         ASSERT(sih->cccaps & CC_CAP_PMU);
1570
1571         /* Remember original core before switch to chipc */
1572         origidx = si_coreidx(sih);
1573         cc = si_setcoreidx(sih, SI_CC_IDX);
1574         ASSERT(cc != NULL);
1575
1576         switch (CHIPID(sih->chip)) {
1577         case BCM43224_CHIP_ID:
1578         case BCM43225_CHIP_ID:
1579         case BCM43421_CHIP_ID:
1580         case BCM43235_CHIP_ID:
1581         case BCM43236_CHIP_ID:
1582         case BCM43238_CHIP_ID:
1583         case BCM4331_CHIP_ID:
1584         case BCM6362_CHIP_ID:
1585         case BCM4716_CHIP_ID:
1586         case BCM4748_CHIP_ID:
1587         case BCM47162_CHIP_ID:
1588         case BCM4313_CHIP_ID:
1589         case BCM5357_CHIP_ID:
1590                 /* always 20Mhz */
1591                 clock = 20000 * 1000;
1592                 break;
1593         case BCM4329_CHIP_ID:
1594         case BCM4319_CHIP_ID:
1595         case BCM4336_CHIP_ID:
1596         case BCM4330_CHIP_ID:
1597
1598                 clock = si_pmu1_alpclk0(sih, osh, cc);
1599                 break;
1600         case BCM5356_CHIP_ID:
1601                 /* always 25Mhz */
1602                 clock = 25000 * 1000;
1603                 break;
1604         default:
1605                 PMU_MSG(("No ALP clock specified "
1606                          "for chip %s rev %d pmurev %d, using default %d Hz\n",
1607                          bcm_chipname(sih->chip, chn, 8), sih->chiprev,
1608                          sih->pmurev, clock));
1609                 break;
1610         }
1611
1612         /* Return to original core */
1613         si_setcoreidx(sih, origidx);
1614         return clock;
1615 }
1616
1617 /* Find the output of the "m" pll divider given pll controls that start with
1618  * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
1619  */
1620 static u32
1621 BCMINITFN(si_pmu5_clock) (si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0,
1622                           uint m) {
1623         u32 tmp, div, ndiv, p1, p2, fc;
1624
1625         if ((pll0 & 3) || (pll0 > PMU4716_MAINPLL_PLL0)) {
1626                 PMU_ERROR(("%s: Bad pll0: %d\n", __func__, pll0));
1627                 return 0;
1628         }
1629
1630         /* Strictly there is an m5 divider, but I'm not sure we use it */
1631         if ((m == 0) || (m > 4)) {
1632                 PMU_ERROR(("%s: Bad m divider: %d\n", __func__, m));
1633                 return 0;
1634         }
1635
1636         if (CHIPID(sih->chip) == BCM5357_CHIP_ID) {
1637                 /* Detect failure in clock setting */
1638                 if ((R_REG(osh, &cc->chipstatus) & 0x40000) != 0) {
1639                         return 133 * 1000000;
1640                 }
1641         }
1642
1643         W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_P1P2_OFF);
1644         (void)R_REG(osh, &cc->pllcontrol_addr);
1645         tmp = R_REG(osh, &cc->pllcontrol_data);
1646         p1 = (tmp & PMU5_PLL_P1_MASK) >> PMU5_PLL_P1_SHIFT;
1647         p2 = (tmp & PMU5_PLL_P2_MASK) >> PMU5_PLL_P2_SHIFT;
1648
1649         W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_M14_OFF);
1650         (void)R_REG(osh, &cc->pllcontrol_addr);
1651         tmp = R_REG(osh, &cc->pllcontrol_data);
1652         div = (tmp >> ((m - 1) * PMU5_PLL_MDIV_WIDTH)) & PMU5_PLL_MDIV_MASK;
1653
1654         W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_NM5_OFF);
1655         (void)R_REG(osh, &cc->pllcontrol_addr);
1656         tmp = R_REG(osh, &cc->pllcontrol_data);
1657         ndiv = (tmp & PMU5_PLL_NDIV_MASK) >> PMU5_PLL_NDIV_SHIFT;
1658
1659         /* Do calculation in Mhz */
1660         fc = si_pmu_alp_clock(sih, osh) / 1000000;
1661         fc = (p1 * ndiv * fc) / p2;
1662
1663         PMU_NONE(("%s: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, clock=%d\n",
1664                   __func__, p1, p2, ndiv, ndiv, m, div, fc, fc / div));
1665
1666         /* Return clock in Hertz */
1667         return (fc / div) * 1000000;
1668 }
1669
1670 /* query backplane clock frequency */
1671 /* For designs that feed the same clock to both backplane
1672  * and CPU just return the CPU clock speed.
1673  */
1674 u32 BCMINITFN(si_pmu_si_clock) (si_t *sih, osl_t *osh)
1675 {
1676         chipcregs_t *cc;
1677         uint origidx;
1678         u32 clock = HT_CLOCK;
1679 #ifdef BCMDBG
1680         char chn[8];
1681 #endif
1682
1683         ASSERT(sih->cccaps & CC_CAP_PMU);
1684
1685         /* Remember original core before switch to chipc */
1686         origidx = si_coreidx(sih);
1687         cc = si_setcoreidx(sih, SI_CC_IDX);
1688         ASSERT(cc != NULL);
1689
1690         switch (CHIPID(sih->chip)) {
1691         case BCM43224_CHIP_ID:
1692         case BCM43225_CHIP_ID:
1693         case BCM43421_CHIP_ID:
1694         case BCM4331_CHIP_ID:
1695         case BCM6362_CHIP_ID:
1696                 /* 96MHz backplane clock */
1697                 clock = 96000 * 1000;
1698                 break;
1699         case BCM4716_CHIP_ID:
1700         case BCM4748_CHIP_ID:
1701         case BCM47162_CHIP_ID:
1702                 clock =
1703                     si_pmu5_clock(sih, osh, cc, PMU4716_MAINPLL_PLL0,
1704                                   PMU5_MAINPLL_SI);
1705                 break;
1706         case BCM4329_CHIP_ID:
1707                 if (CHIPREV(sih->chiprev) == 0)
1708                         clock = 38400 * 1000;
1709                 else
1710                         clock = si_pmu1_cpuclk0(sih, osh, cc);
1711                 break;
1712         case BCM4319_CHIP_ID:
1713         case BCM4336_CHIP_ID:
1714         case BCM4330_CHIP_ID:
1715                 clock = si_pmu1_cpuclk0(sih, osh, cc);
1716                 break;
1717         case BCM4313_CHIP_ID:
1718                 /* 80MHz backplane clock */
1719                 clock = 80000 * 1000;
1720                 break;
1721         case BCM43235_CHIP_ID:
1722         case BCM43236_CHIP_ID:
1723         case BCM43238_CHIP_ID:
1724                 clock =
1725                     (cc->chipstatus & CST43236_BP_CLK) ? (120000 *
1726                                                           1000) : (96000 *
1727                                                                    1000);
1728                 break;
1729         case BCM5356_CHIP_ID:
1730                 clock =
1731                     si_pmu5_clock(sih, osh, cc, PMU5356_MAINPLL_PLL0,
1732                                   PMU5_MAINPLL_SI);
1733                 break;
1734         case BCM5357_CHIP_ID:
1735                 clock =
1736                     si_pmu5_clock(sih, osh, cc, PMU5357_MAINPLL_PLL0,
1737                                   PMU5_MAINPLL_SI);
1738                 break;
1739         default:
1740                 PMU_MSG(("No backplane clock specified "
1741                          "for chip %s rev %d pmurev %d, using default %d Hz\n",
1742                          bcm_chipname(sih->chip, chn, 8), sih->chiprev,
1743                          sih->pmurev, clock));
1744                 break;
1745         }
1746
1747         /* Return to original core */
1748         si_setcoreidx(sih, origidx);
1749         return clock;
1750 }
1751
1752 /* query CPU clock frequency */
1753 u32 BCMINITFN(si_pmu_cpu_clock) (si_t *sih, osl_t *osh)
1754 {
1755         chipcregs_t *cc;
1756         uint origidx;
1757         u32 clock;
1758
1759         ASSERT(sih->cccaps & CC_CAP_PMU);
1760
1761         if ((sih->pmurev >= 5) &&
1762             !((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
1763               (CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
1764               (CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
1765               (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
1766               (CHIPID(sih->chip) == BCM4330_CHIP_ID))) {
1767                 uint pll;
1768
1769                 switch (CHIPID(sih->chip)) {
1770                 case BCM5356_CHIP_ID:
1771                         pll = PMU5356_MAINPLL_PLL0;
1772                         break;
1773                 case BCM5357_CHIP_ID:
1774                         pll = PMU5357_MAINPLL_PLL0;
1775                         break;
1776                 default:
1777                         pll = PMU4716_MAINPLL_PLL0;
1778                         break;
1779                 }
1780
1781                 /* Remember original core before switch to chipc */
1782                 origidx = si_coreidx(sih);
1783                 cc = si_setcoreidx(sih, SI_CC_IDX);
1784                 ASSERT(cc != NULL);
1785
1786                 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_CPU);
1787
1788                 /* Return to original core */
1789                 si_setcoreidx(sih, origidx);
1790         } else
1791                 clock = si_pmu_si_clock(sih, osh);
1792
1793         return clock;
1794 }
1795
1796 /* query memory clock frequency */
1797 u32 BCMINITFN(si_pmu_mem_clock) (si_t *sih, osl_t *osh)
1798 {
1799         chipcregs_t *cc;
1800         uint origidx;
1801         u32 clock;
1802
1803         ASSERT(sih->cccaps & CC_CAP_PMU);
1804
1805         if ((sih->pmurev >= 5) &&
1806             !((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
1807               (CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
1808               (CHIPID(sih->chip) == BCM4330_CHIP_ID) ||
1809               (CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
1810               (CHIPID(sih->chip) == BCM43236_CHIP_ID))) {
1811                 uint pll;
1812
1813                 switch (CHIPID(sih->chip)) {
1814                 case BCM5356_CHIP_ID:
1815                         pll = PMU5356_MAINPLL_PLL0;
1816                         break;
1817                 case BCM5357_CHIP_ID:
1818                         pll = PMU5357_MAINPLL_PLL0;
1819                         break;
1820                 default:
1821                         pll = PMU4716_MAINPLL_PLL0;
1822                         break;
1823                 }
1824
1825                 /* Remember original core before switch to chipc */
1826                 origidx = si_coreidx(sih);
1827                 cc = si_setcoreidx(sih, SI_CC_IDX);
1828                 ASSERT(cc != NULL);
1829
1830                 clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_MEM);
1831
1832                 /* Return to original core */
1833                 si_setcoreidx(sih, origidx);
1834         } else {
1835                 clock = si_pmu_si_clock(sih, osh);
1836         }
1837
1838         return clock;
1839 }
1840
1841 /* Measure ILP clock frequency */
1842 #define ILP_CALC_DUR    10      /* ms, make sure 1000 can be divided by it. */
1843
1844 static u32 ilpcycles_per_sec;
1845
1846 u32 BCMINITFN(si_pmu_ilp_clock) (si_t *sih, osl_t *osh)
1847 {
1848         if (ISSIM_ENAB(sih))
1849                 return ILP_CLOCK;
1850
1851         if (ilpcycles_per_sec == 0) {
1852                 u32 start, end, delta;
1853                 u32 origidx = si_coreidx(sih);
1854                 chipcregs_t *cc = si_setcoreidx(sih, SI_CC_IDX);
1855                 ASSERT(cc != NULL);
1856                 start = R_REG(osh, &cc->pmutimer);
1857                 OSL_DELAY(ILP_CALC_DUR * 1000);
1858                 end = R_REG(osh, &cc->pmutimer);
1859                 delta = end - start;
1860                 ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
1861                 si_setcoreidx(sih, origidx);
1862         }
1863
1864         return ilpcycles_per_sec;
1865 }
1866
1867 /* SDIO Pad drive strength to select value mappings */
1868 typedef struct {
1869         u8 strength;            /* Pad Drive Strength in mA */
1870         u8 sel;         /* Chip-specific select value */
1871 } sdiod_drive_str_t;
1872
1873 /* SDIO Drive Strength to sel value table for PMU Rev 1 */
1874 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab1)[] = {
1875         {
1876         4, 0x2}, {
1877         2, 0x3}, {
1878         1, 0x0}, {
1879         0, 0x0}
1880         };
1881
1882 /* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
1883 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab2)[] = {
1884         {
1885         12, 0x7}, {
1886         10, 0x6}, {
1887         8, 0x5}, {
1888         6, 0x4}, {
1889         4, 0x2}, {
1890         2, 0x1}, {
1891         0, 0x0}
1892         };
1893
1894 /* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
1895 static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab3)[] = {
1896         {
1897         32, 0x7}, {
1898         26, 0x6}, {
1899         22, 0x5}, {
1900         16, 0x4}, {
1901         12, 0x3}, {
1902         8, 0x2}, {
1903         4, 0x1}, {
1904         0, 0x0}
1905         };
1906
1907 #define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
1908
1909 void
1910 BCMINITFN(si_sdiod_drive_strength_init) (si_t *sih, osl_t *osh,
1911                                          u32 drivestrength) {
1912         chipcregs_t *cc;
1913         uint origidx, intr_val = 0;
1914         sdiod_drive_str_t *str_tab = NULL;
1915         u32 str_mask = 0;
1916         u32 str_shift = 0;
1917 #ifdef BCMDBG
1918         char chn[8];
1919 #endif
1920
1921         if (!(sih->cccaps & CC_CAP_PMU)) {
1922                 return;
1923         }
1924
1925         /* Remember original core before switch to chipc */
1926         cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx,
1927                                             &intr_val);
1928
1929         switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) {
1930         case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
1931                 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1;
1932                 str_mask = 0x30000000;
1933                 str_shift = 28;
1934                 break;
1935         case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
1936         case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
1937                 str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2;
1938                 str_mask = 0x00003800;
1939                 str_shift = 11;
1940                 break;
1941         case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
1942                 str_tab = (sdiod_drive_str_t *) &sdiod_drive_strength_tab3;
1943                 str_mask = 0x00003800;
1944                 str_shift = 11;
1945                 break;
1946
1947         default:
1948                 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));
1949
1950                 break;
1951         }
1952
1953         if (str_tab != NULL) {
1954                 u32 drivestrength_sel = 0;
1955                 u32 cc_data_temp;
1956                 int i;
1957
1958                 for (i = 0; str_tab[i].strength != 0; i++) {
1959                         if (drivestrength >= str_tab[i].strength) {
1960                                 drivestrength_sel = str_tab[i].sel;
1961                                 break;
1962                         }
1963                 }
1964
1965                 W_REG(osh, &cc->chipcontrol_addr, 1);
1966                 cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
1967                 cc_data_temp &= ~str_mask;
1968                 drivestrength_sel <<= str_shift;
1969                 cc_data_temp |= drivestrength_sel;
1970                 W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
1971
1972                 PMU_MSG(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
1973                          drivestrength, cc_data_temp));
1974         }
1975
1976         /* Return to original core */
1977         si_restore_core(sih, origidx, intr_val);
1978 }
1979
1980 /* initialize PMU */
1981 void si_pmu_init(si_t *sih, osl_t *osh)
1982 {
1983         chipcregs_t *cc;
1984         uint origidx;
1985
1986         ASSERT(sih->cccaps & CC_CAP_PMU);
1987
1988         /* Remember original core before switch to chipc */
1989         origidx = si_coreidx(sih);
1990         cc = si_setcoreidx(sih, SI_CC_IDX);
1991         ASSERT(cc != NULL);
1992
1993         if (sih->pmurev == 1)
1994                 AND_REG(osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
1995         else if (sih->pmurev >= 2)
1996                 OR_REG(osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT);
1997
1998         if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 2)) {
1999                 /* Fix for 4329b0 bad LPOM state. */
2000                 W_REG(osh, &cc->regcontrol_addr, 2);
2001                 OR_REG(osh, &cc->regcontrol_data, 0x100);
2002
2003                 W_REG(osh, &cc->regcontrol_addr, 3);
2004                 OR_REG(osh, &cc->regcontrol_data, 0x4);
2005         }
2006
2007         /* Return to original core */
2008         si_setcoreidx(sih, origidx);
2009 }
2010
2011 /* Return up time in ILP cycles for the given resource. */
2012 static uint
2013 BCMINITFN(si_pmu_res_uptime) (si_t *sih, osl_t *osh, chipcregs_t *cc,
2014                               u8 rsrc) {
2015         u32 deps;
2016         uint up, i, dup, dmax;
2017         u32 min_mask = 0, max_mask = 0;
2018
2019         /* uptime of resource 'rsrc' */
2020         W_REG(osh, &cc->res_table_sel, rsrc);
2021         up = (R_REG(osh, &cc->res_updn_timer) >> 8) & 0xff;
2022
2023         /* direct dependancies of resource 'rsrc' */
2024         deps = si_pmu_res_deps(sih, osh, cc, PMURES_BIT(rsrc), FALSE);
2025         for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
2026                 if (!(deps & PMURES_BIT(i)))
2027                         continue;
2028                 deps &= ~si_pmu_res_deps(sih, osh, cc, PMURES_BIT(i), TRUE);
2029         }
2030         si_pmu_res_masks(sih, &min_mask, &max_mask);
2031         deps &= ~min_mask;
2032
2033         /* max uptime of direct dependancies */
2034         dmax = 0;
2035         for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
2036                 if (!(deps & PMURES_BIT(i)))
2037                         continue;
2038                 dup = si_pmu_res_uptime(sih, osh, cc, (u8) i);
2039                 if (dmax < dup)
2040                         dmax = dup;
2041         }
2042
2043         PMU_MSG(("si_pmu_res_uptime: rsrc %u uptime %u(deps 0x%08x uptime %u)\n", rsrc, up, deps, dmax));
2044
2045         return up + dmax + PMURES_UP_TRANSITION;
2046 }
2047
2048 /* Return dependancies (direct or all/indirect) for the given resources */
2049 static u32
2050 si_pmu_res_deps(si_t *sih, osl_t *osh, chipcregs_t *cc, u32 rsrcs,
2051                 bool all)
2052 {
2053         u32 deps = 0;
2054         u32 i;
2055
2056         for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
2057                 if (!(rsrcs & PMURES_BIT(i)))
2058                         continue;
2059                 W_REG(osh, &cc->res_table_sel, i);
2060                 deps |= R_REG(osh, &cc->res_dep_mask);
2061         }
2062
2063         return !all ? deps : (deps
2064                               ? (deps |
2065                                  si_pmu_res_deps(sih, osh, cc, deps,
2066                                                  TRUE)) : 0);
2067 }
2068
2069 /* power up/down OTP through PMU resources */
2070 void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on)
2071 {
2072         chipcregs_t *cc;
2073         uint origidx;
2074         u32 rsrcs = 0;  /* rsrcs to turn on/off OTP power */
2075
2076         ASSERT(sih->cccaps & CC_CAP_PMU);
2077
2078         /* Don't do anything if OTP is disabled */
2079         if (si_is_otp_disabled(sih)) {
2080                 PMU_MSG(("si_pmu_otp_power: OTP is disabled\n"));
2081                 return;
2082         }
2083
2084         /* Remember original core before switch to chipc */
2085         origidx = si_coreidx(sih);
2086         cc = si_setcoreidx(sih, SI_CC_IDX);
2087         ASSERT(cc != NULL);
2088
2089         switch (CHIPID(sih->chip)) {
2090         case BCM4329_CHIP_ID:
2091                 rsrcs = PMURES_BIT(RES4329_OTP_PU);
2092                 break;
2093         case BCM4319_CHIP_ID:
2094                 rsrcs = PMURES_BIT(RES4319_OTP_PU);
2095                 break;
2096         case BCM4336_CHIP_ID:
2097                 rsrcs = PMURES_BIT(RES4336_OTP_PU);
2098                 break;
2099         case BCM4330_CHIP_ID:
2100                 rsrcs = PMURES_BIT(RES4330_OTP_PU);
2101                 break;
2102         default:
2103                 break;
2104         }
2105
2106         if (rsrcs != 0) {
2107                 u32 otps;
2108
2109                 /* Figure out the dependancies (exclude min_res_mask) */
2110                 u32 deps = si_pmu_res_deps(sih, osh, cc, rsrcs, TRUE);
2111                 u32 min_mask = 0, max_mask = 0;
2112                 si_pmu_res_masks(sih, &min_mask, &max_mask);
2113                 deps &= ~min_mask;
2114                 /* Turn on/off the power */
2115                 if (on) {
2116                         PMU_MSG(("Adding rsrc 0x%x to min_res_mask\n",
2117                                  rsrcs | deps));
2118                         OR_REG(osh, &cc->min_res_mask, (rsrcs | deps));
2119                         SPINWAIT(!(R_REG(osh, &cc->res_state) & rsrcs),
2120                                  PMU_MAX_TRANSITION_DLY);
2121                         ASSERT(R_REG(osh, &cc->res_state) & rsrcs);
2122                 } else {
2123                         PMU_MSG(("Removing rsrc 0x%x from min_res_mask\n",
2124                                  rsrcs | deps));
2125                         AND_REG(osh, &cc->min_res_mask, ~(rsrcs | deps));
2126                 }
2127
2128                 SPINWAIT((((otps = R_REG(osh, &cc->otpstatus)) & OTPS_READY) !=
2129                           (on ? OTPS_READY : 0)), 100);
2130                 ASSERT((otps & OTPS_READY) == (on ? OTPS_READY : 0));
2131                 if ((otps & OTPS_READY) != (on ? OTPS_READY : 0))
2132                         PMU_MSG(("OTP ready bit not %s after wait\n",
2133                                  (on ? "ON" : "OFF")));
2134         }
2135
2136         /* Return to original core */
2137         si_setcoreidx(sih, origidx);
2138 }
2139
2140 void si_pmu_rcal(si_t *sih, osl_t *osh)
2141 {
2142         chipcregs_t *cc;
2143         uint origidx;
2144
2145         ASSERT(sih->cccaps & CC_CAP_PMU);
2146
2147         /* Remember original core before switch to chipc */
2148         origidx = si_coreidx(sih);
2149         cc = si_setcoreidx(sih, SI_CC_IDX);
2150         ASSERT(cc != NULL);
2151
2152         switch (CHIPID(sih->chip)) {
2153         case BCM4329_CHIP_ID:{
2154                         u8 rcal_code;
2155                         u32 val;
2156
2157                         /* Kick RCal */
2158                         W_REG(osh, &cc->chipcontrol_addr, 1);
2159
2160                         /* Power Down RCAL Block */
2161                         AND_REG(osh, &cc->chipcontrol_data, ~0x04);
2162
2163                         /* Power Up RCAL block */
2164                         OR_REG(osh, &cc->chipcontrol_data, 0x04);
2165
2166                         /* Wait for completion */
2167                         SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08),
2168                                  10 * 1000 * 1000);
2169                         ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
2170
2171                         /* Drop the LSB to convert from 5 bit code to 4 bit code */
2172                         rcal_code =
2173                             (u8) (R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
2174
2175                         PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
2176                                  R_REG(osh, &cc->chipstatus), rcal_code));
2177
2178                         /* Write RCal code into pmu_vreg_ctrl[32:29] */
2179                         W_REG(osh, &cc->regcontrol_addr, 0);
2180                         val =
2181                             R_REG(osh,
2182                                   &cc->
2183                                   regcontrol_data) & ~((u32) 0x07 << 29);
2184                         val |= (u32) (rcal_code & 0x07) << 29;
2185                         W_REG(osh, &cc->regcontrol_data, val);
2186                         W_REG(osh, &cc->regcontrol_addr, 1);
2187                         val = R_REG(osh, &cc->regcontrol_data) & ~(u32) 0x01;
2188                         val |= (u32) ((rcal_code >> 3) & 0x01);
2189                         W_REG(osh, &cc->regcontrol_data, val);
2190
2191                         /* Write RCal code into pmu_chip_ctrl[33:30] */
2192                         W_REG(osh, &cc->chipcontrol_addr, 0);
2193                         val =
2194                             R_REG(osh,
2195                                   &cc->
2196                                   chipcontrol_data) & ~((u32) 0x03 << 30);
2197                         val |= (u32) (rcal_code & 0x03) << 30;
2198                         W_REG(osh, &cc->chipcontrol_data, val);
2199                         W_REG(osh, &cc->chipcontrol_addr, 1);
2200                         val =
2201                             R_REG(osh, &cc->chipcontrol_data) & ~(u32) 0x03;
2202                         val |= (u32) ((rcal_code >> 2) & 0x03);
2203                         W_REG(osh, &cc->chipcontrol_data, val);
2204
2205                         /* Set override in pmu_chip_ctrl[29] */
2206                         W_REG(osh, &cc->chipcontrol_addr, 0);
2207                         OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
2208
2209                         /* Power off RCal block */
2210                         W_REG(osh, &cc->chipcontrol_addr, 1);
2211                         AND_REG(osh, &cc->chipcontrol_data, ~0x04);
2212
2213                         break;
2214                 }
2215         default:
2216                 break;
2217         }
2218
2219         /* Return to original core */
2220         si_setcoreidx(sih, origidx);
2221 }
2222
2223 void si_pmu_spuravoid(si_t *sih, osl_t *osh, u8 spuravoid)
2224 {
2225         chipcregs_t *cc;
2226         uint origidx, intr_val;
2227         u32 tmp = 0;
2228
2229         /* Remember original core before switch to chipc */
2230         cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx,
2231                                             &intr_val);
2232         ASSERT(cc != NULL);
2233
2234         /* force the HT off  */
2235         if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
2236                 tmp = R_REG(osh, &cc->max_res_mask);
2237                 tmp &= ~RES4336_HT_AVAIL;
2238                 W_REG(osh, &cc->max_res_mask, tmp);
2239                 /* wait for the ht to really go away */
2240                 SPINWAIT(((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0),
2241                          10000);
2242                 ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0);
2243         }
2244
2245         /* update the pll changes */
2246         si_pmu_spuravoid_pllupdate(sih, cc, osh, spuravoid);
2247
2248         /* enable HT back on  */
2249         if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
2250                 tmp = R_REG(osh, &cc->max_res_mask);
2251                 tmp |= RES4336_HT_AVAIL;
2252                 W_REG(osh, &cc->max_res_mask, tmp);
2253         }
2254
2255         /* Return to original core */
2256         si_restore_core(sih, origidx, intr_val);
2257 }
2258
2259 static void
2260 si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, osl_t *osh,
2261                            u8 spuravoid)
2262 {
2263         u32 tmp = 0;
2264         u8 phypll_offset = 0;
2265         u8 bcm5357_bcm43236_p1div[] = { 0x1, 0x5, 0x5 };
2266         u8 bcm5357_bcm43236_ndiv[] = { 0x30, 0xf6, 0xfc };
2267
2268         switch (CHIPID(sih->chip)) {
2269         case BCM5357_CHIP_ID:
2270         case BCM43235_CHIP_ID:
2271         case BCM43236_CHIP_ID:
2272         case BCM43238_CHIP_ID:
2273
2274                 /* BCM5357 needs to touch PLL1_PLLCTL[02], so offset PLL0_PLLCTL[02] by 6 */
2275                 phypll_offset = (CHIPID(sih->chip) == BCM5357_CHIP_ID) ? 6 : 0;
2276
2277                 /* RMW only the P1 divider */
2278                 W_REG(osh, &cc->pllcontrol_addr,
2279                       PMU1_PLL0_PLLCTL0 + phypll_offset);
2280                 tmp = R_REG(osh, &cc->pllcontrol_data);
2281                 tmp &= (~(PMU1_PLL0_PC0_P1DIV_MASK));
2282                 tmp |=
2283                     (bcm5357_bcm43236_p1div[spuravoid] <<
2284                      PMU1_PLL0_PC0_P1DIV_SHIFT);
2285                 W_REG(osh, &cc->pllcontrol_data, tmp);
2286
2287                 /* RMW only the int feedback divider */
2288                 W_REG(osh, &cc->pllcontrol_addr,
2289                       PMU1_PLL0_PLLCTL2 + phypll_offset);
2290                 tmp = R_REG(osh, &cc->pllcontrol_data);
2291                 tmp &= ~(PMU1_PLL0_PC2_NDIV_INT_MASK);
2292                 tmp |=
2293                     (bcm5357_bcm43236_ndiv[spuravoid]) <<
2294                     PMU1_PLL0_PC2_NDIV_INT_SHIFT;
2295                 W_REG(osh, &cc->pllcontrol_data, tmp);
2296
2297                 tmp = 1 << 10;
2298                 break;
2299
2300         case BCM4331_CHIP_ID:
2301                 if (spuravoid == 2) {
2302                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2303                         W_REG(osh, &cc->pllcontrol_data, 0x11500014);
2304                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2305                         W_REG(osh, &cc->pllcontrol_data, 0x0FC00a08);
2306                 } else if (spuravoid == 1) {
2307                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2308                         W_REG(osh, &cc->pllcontrol_data, 0x11500014);
2309                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2310                         W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
2311                 } else {
2312                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2313                         W_REG(osh, &cc->pllcontrol_data, 0x11100014);
2314                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2315                         W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
2316                 }
2317                 tmp = 1 << 10;
2318                 break;
2319
2320         case BCM43224_CHIP_ID:
2321         case BCM43225_CHIP_ID:
2322         case BCM43421_CHIP_ID:
2323         case BCM6362_CHIP_ID:
2324                 if (spuravoid == 1) {
2325                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2326                         W_REG(osh, &cc->pllcontrol_data, 0x11500010);
2327                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2328                         W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
2329                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2330                         W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
2331                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2332                         W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2333                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2334                         W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
2335                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2336                         W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2337                 } else {
2338                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2339                         W_REG(osh, &cc->pllcontrol_data, 0x11100010);
2340                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2341                         W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
2342                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2343                         W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
2344                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2345                         W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2346                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2347                         W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
2348                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2349                         W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2350                 }
2351                 tmp = 1 << 10;
2352                 break;
2353
2354                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2355                 W_REG(osh, &cc->pllcontrol_data, 0x11100008);
2356                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2357                 W_REG(osh, &cc->pllcontrol_data, 0x0c000c06);
2358                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2359                 W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
2360                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2361                 W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2362                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2363                 W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
2364                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2365                 W_REG(osh, &cc->pllcontrol_data, 0x88888855);
2366
2367                 tmp = 1 << 10;
2368                 break;
2369
2370         case BCM4716_CHIP_ID:
2371         case BCM4748_CHIP_ID:
2372         case BCM47162_CHIP_ID:
2373                 if (spuravoid == 1) {
2374                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2375                         W_REG(osh, &cc->pllcontrol_data, 0x11500060);
2376                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2377                         W_REG(osh, &cc->pllcontrol_data, 0x080C0C06);
2378                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2379                         W_REG(osh, &cc->pllcontrol_data, 0x0F600000);
2380                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2381                         W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2382                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2383                         W_REG(osh, &cc->pllcontrol_data, 0x2001E924);
2384                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2385                         W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2386                 } else {
2387                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2388                         W_REG(osh, &cc->pllcontrol_data, 0x11100060);
2389                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2390                         W_REG(osh, &cc->pllcontrol_data, 0x080c0c06);
2391                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2392                         W_REG(osh, &cc->pllcontrol_data, 0x03000000);
2393                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2394                         W_REG(osh, &cc->pllcontrol_data, 0x00000000);
2395                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2396                         W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
2397                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2398                         W_REG(osh, &cc->pllcontrol_data, 0x88888815);
2399                 }
2400
2401                 tmp = 3 << 9;
2402                 break;
2403
2404         case BCM4319_CHIP_ID:
2405                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2406                 W_REG(osh, &cc->pllcontrol_data, 0x11100070);
2407                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2408                 W_REG(osh, &cc->pllcontrol_data, 0x1014140a);
2409                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2410                 W_REG(osh, &cc->pllcontrol_data, 0x88888854);
2411
2412                 if (spuravoid == 1) {   /* spur_avoid ON, enable 41/82/164Mhz clock mode */
2413                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2414                         W_REG(osh, &cc->pllcontrol_data, 0x05201828);
2415                 } else {        /* enable 40/80/160Mhz clock mode */
2416                         W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2417                         W_REG(osh, &cc->pllcontrol_data, 0x05001828);
2418                 }
2419                 break;
2420         case BCM4336_CHIP_ID:
2421                 /* Looks like these are only for default xtal freq 26MHz */
2422                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
2423                 W_REG(osh, &cc->pllcontrol_data, 0x02100020);
2424
2425                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2426                 W_REG(osh, &cc->pllcontrol_data, 0x0C0C0C0C);
2427
2428                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2429                 W_REG(osh, &cc->pllcontrol_data, 0x01240C0C);
2430
2431                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2432                 W_REG(osh, &cc->pllcontrol_data, 0x202C2820);
2433
2434                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2435                 W_REG(osh, &cc->pllcontrol_data, 0x88888825);
2436
2437                 W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2438                 if (spuravoid == 1) {
2439                         W_REG(osh, &cc->pllcontrol_data, 0x00EC4EC4);
2440                 } else {
2441                         W_REG(osh, &cc->pllcontrol_data, 0x00762762);
2442                 }
2443
2444                 tmp = PCTL_PLL_PLLCTL_UPD;
2445                 break;
2446
2447         default:
2448                 PMU_ERROR(("%s: unknown spuravoidance settings for chip %s, not changing PLL\n", __func__, bcm_chipname(sih->chip, chn, 8)));
2449                 break;
2450         }
2451
2452         tmp |= R_REG(osh, &cc->pmucontrol);
2453         W_REG(osh, &cc->pmucontrol, tmp);
2454 }
2455
2456 bool si_pmu_is_otp_powered(si_t *sih, osl_t *osh)
2457 {
2458         uint idx;
2459         chipcregs_t *cc;
2460         bool st;
2461
2462         /* Remember original core before switch to chipc */
2463         idx = si_coreidx(sih);
2464         cc = si_setcoreidx(sih, SI_CC_IDX);
2465         ASSERT(cc != NULL);
2466
2467         switch (CHIPID(sih->chip)) {
2468         case BCM4329_CHIP_ID:
2469                 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4329_OTP_PU))
2470                     != 0;
2471                 break;
2472         case BCM4319_CHIP_ID:
2473                 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4319_OTP_PU))
2474                     != 0;
2475                 break;
2476         case BCM4336_CHIP_ID:
2477                 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4336_OTP_PU))
2478                     != 0;
2479                 break;
2480         case BCM4330_CHIP_ID:
2481                 st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4330_OTP_PU))
2482                     != 0;
2483                 break;
2484
2485                 /* These chip doesn't use PMU bit to power up/down OTP. OTP always on.
2486                  * Use OTP_INIT command to reset/refresh state.
2487                  */
2488         case BCM43224_CHIP_ID:
2489         case BCM43225_CHIP_ID:
2490         case BCM43421_CHIP_ID:
2491         case BCM43236_CHIP_ID:
2492         case BCM43235_CHIP_ID:
2493         case BCM43238_CHIP_ID:
2494                 st = TRUE;
2495                 break;
2496         default:
2497                 st = TRUE;
2498                 break;
2499         }
2500
2501         /* Return to original core */
2502         si_setcoreidx(sih, idx);
2503         return st;
2504 }
2505
2506 void
2507 #if defined(BCMDBG)
2508 si_pmu_sprom_enable(si_t *sih, osl_t *osh, bool enable)
2509 #else
2510 si_pmu_sprom_enable(si_t *sih, osl_t *osh, bool enable)
2511 #endif
2512 {
2513         chipcregs_t *cc;
2514         uint origidx;
2515
2516         /* Remember original core before switch to chipc */
2517         origidx = si_coreidx(sih);
2518         cc = si_setcoreidx(sih, SI_CC_IDX);
2519         ASSERT(cc != NULL);
2520
2521         /* Return to original core */
2522         si_setcoreidx(sih, origidx);
2523 }
2524
2525 /* initialize PMU chip controls and other chip level stuff */
2526 void si_pmu_chip_init(si_t *sih, osl_t *osh)
2527 {
2528         uint origidx;
2529
2530         ASSERT(sih->cccaps & CC_CAP_PMU);
2531
2532 #ifdef CHIPC_UART_ALWAYS_ON
2533         si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, clk_ctl_st),
2534                    CCS_FORCEALP, CCS_FORCEALP);
2535 #endif                          /* CHIPC_UART_ALWAYS_ON */
2536
2537         /* Gate off SPROM clock and chip select signals */
2538         si_pmu_sprom_enable(sih, osh, FALSE);
2539
2540         /* Remember original core */
2541         origidx = si_coreidx(sih);
2542
2543         /* Return to original core */
2544         si_setcoreidx(sih, origidx);
2545 }
2546
2547 /* initialize PMU switch/regulators */
2548 void si_pmu_swreg_init(si_t *sih, osl_t *osh)
2549 {
2550         ASSERT(sih->cccaps & CC_CAP_PMU);
2551
2552         switch (CHIPID(sih->chip)) {
2553         case BCM4336_CHIP_ID:
2554                 /* Reduce CLDO PWM output voltage to 1.2V */
2555                 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xe);
2556                 /* Reduce CLDO BURST output voltage to 1.2V */
2557                 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_BURST,
2558                                        0xe);
2559                 /* Reduce LNLDO1 output voltage to 1.2V */
2560                 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO1, 0xe);
2561                 if (CHIPREV(sih->chiprev) == 0)
2562                         si_pmu_regcontrol(sih, 2, 0x400000, 0x400000);
2563                 break;
2564
2565         case BCM4330_CHIP_ID:
2566                 /* CBUCK Voltage is 1.8 by default and set that to 1.5 */
2567                 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0);
2568                 break;
2569         default:
2570                 break;
2571         }
2572 }
2573
2574 void si_pmu_radio_enable(si_t *sih, bool enable)
2575 {
2576         ASSERT(sih->cccaps & CC_CAP_PMU);
2577
2578         switch (CHIPID(sih->chip)) {
2579         case BCM4319_CHIP_ID:
2580                 if (enable)
2581                         si_write_wrapperreg(sih, AI_OOBSELOUTB74,
2582                                             (u32) 0x868584);
2583                 else
2584                         si_write_wrapperreg(sih, AI_OOBSELOUTB74,
2585                                             (u32) 0x060584);
2586                 break;
2587         }
2588 }
2589
2590 /* Wait for a particular clock level to be on the backplane */
2591 u32
2592 si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, u32 clk,
2593                                u32 delay)
2594 {
2595         chipcregs_t *cc;
2596         uint origidx;
2597
2598         ASSERT(sih->cccaps & CC_CAP_PMU);
2599
2600         /* Remember original core before switch to chipc */
2601         origidx = si_coreidx(sih);
2602         cc = si_setcoreidx(sih, SI_CC_IDX);
2603         ASSERT(cc != NULL);
2604
2605         if (delay)
2606                 SPINWAIT(((R_REG(osh, &cc->pmustatus) & clk) != clk), delay);
2607
2608         /* Return to original core */
2609         si_setcoreidx(sih, origidx);
2610
2611         return R_REG(osh, &cc->pmustatus) & clk;
2612 }
2613
2614 /*
2615  * Measures the ALP clock frequency in KHz.  Returns 0 if not possible.
2616  * Possible only if PMU rev >= 10 and there is an external LPO 32768Hz crystal.
2617  */
2618
2619 #define EXT_ILP_HZ 32768
2620
2621 u32 si_pmu_measure_alpclk(si_t *sih, osl_t *osh)
2622 {
2623         chipcregs_t *cc;
2624         uint origidx;
2625         u32 alp_khz;
2626
2627         if (sih->pmurev < 10)
2628                 return 0;
2629
2630         ASSERT(sih->cccaps & CC_CAP_PMU);
2631
2632         /* Remember original core before switch to chipc */
2633         origidx = si_coreidx(sih);
2634         cc = si_setcoreidx(sih, SI_CC_IDX);
2635         ASSERT(cc != NULL);
2636
2637         if (R_REG(osh, &cc->pmustatus) & PST_EXTLPOAVAIL) {
2638                 u32 ilp_ctr, alp_hz;
2639
2640                 /* Enable the reg to measure the freq, in case disabled before */
2641                 W_REG(osh, &cc->pmu_xtalfreq,
2642                       1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
2643
2644                 /* Delay for well over 4 ILP clocks */
2645                 OSL_DELAY(1000);
2646
2647                 /* Read the latched number of ALP ticks per 4 ILP ticks */
2648                 ilp_ctr =
2649                     R_REG(osh,
2650                           &cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
2651
2652                 /* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT bit to save power */
2653                 W_REG(osh, &cc->pmu_xtalfreq, 0);
2654
2655                 /* Calculate ALP frequency */
2656                 alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
2657
2658                 /* Round to nearest 100KHz, and at the same time convert to KHz */
2659                 alp_khz = (alp_hz + 50000) / 100000 * 100;
2660         } else
2661                 alp_khz = 0;
2662
2663         /* Return to original core */
2664         si_setcoreidx(sih, origidx);
2665
2666         return alp_khz;
2667 }
2668
2669 static void si_pmu_set_4330_plldivs(si_t *sih)
2670 {
2671         u32 FVCO = si_pmu1_pllfvco0(sih) / 1000;
2672         u32 m1div, m2div, m3div, m4div, m5div, m6div;
2673         u32 pllc1, pllc2;
2674
2675         m2div = m3div = m4div = m6div = FVCO / 80;
2676         m5div = FVCO / 160;
2677
2678         if (CST4330_CHIPMODE_SDIOD(sih->chipst))
2679                 m1div = FVCO / 80;
2680         else
2681                 m1div = FVCO / 90;
2682         pllc1 =
2683             (m1div << PMU1_PLL0_PC1_M1DIV_SHIFT) | (m2div <<
2684                                                     PMU1_PLL0_PC1_M2DIV_SHIFT) |
2685             (m3div << PMU1_PLL0_PC1_M3DIV_SHIFT) | (m4div <<
2686                                                     PMU1_PLL0_PC1_M4DIV_SHIFT);
2687         si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, ~0, pllc1);
2688
2689         pllc2 = si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, 0, 0);
2690         pllc2 &= ~(PMU1_PLL0_PC2_M5DIV_MASK | PMU1_PLL0_PC2_M6DIV_MASK);
2691         pllc2 |=
2692             ((m5div << PMU1_PLL0_PC2_M5DIV_SHIFT) |
2693              (m6div << PMU1_PLL0_PC2_M6DIV_SHIFT));
2694         si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL2, ~0, pllc2);
2695 }