Root/target/linux/brcm-2.4/files/arch/mips/bcm947xx/hndpmu.c

1/*
2 * Misc utility routines for accessing PMU corerev specific features
3 * of the SiliconBackplane-based Broadcom chips.
4 *
5 * Copyright 2007, Broadcom Corporation
6 * All Rights Reserved.
7 *
8 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
9 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
10 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
11 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
12 */
13
14#include <typedefs.h>
15#include <bcmdefs.h>
16#include <osl.h>
17#include <sbutils.h>
18#include <bcmdevs.h>
19#include <sbconfig.h>
20#include <sbchipc.h>
21#include <hndpmu.h>
22
23/* debug/trace */
24#define PMU_ERROR(args)
25
26#ifdef BCMDBG
27#define PMU_MSG(args) printf args
28#else
29#define PMU_MSG(args)
30#endif /* BCMDBG */
31
32/* PMU & control */
33/* PMU rev 0 pll control for BCM4328 and BCM5354 */
34static void sb_pmu0_pllinit0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc,
35                  uint32 xtal);
36static uint32 sb_pmu0_alpclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc);
37static uint32 sb_pmu0_cpuclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc);
38/* PMU rev 0 pll control for BCM4325 BCM4329 */
39static void sb_pmu1_pllinit0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc,
40                  uint32 xtal);
41static uint32 sb_pmu1_cpuclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc);
42static uint32 sb_pmu1_alpclk0 (sb_t * sbh, osl_t * osh, chipcregs_t * cc);
43
44/* Setup switcher voltage */
45void
46BCMINITFN (sb_pmu_set_switcher_voltage) (sb_t * sbh, osl_t * osh,
47                     uint8 bb_voltage, uint8 rf_voltage)
48{
49  chipcregs_t *cc;
50  uint origidx;
51
52  ASSERT (sbh->cccaps & CC_CAP_PMU);
53
54  /* Remember original core before switch to chipc */
55  origidx = sb_coreidx (sbh);
56  cc = sb_setcore (sbh, SB_CC, 0);
57  ASSERT (cc);
58
59  W_REG (osh, &cc->regcontrol_addr, 0x01);
60  W_REG (osh, &cc->regcontrol_data, (uint32) (bb_voltage & 0x1f) << 22);
61
62  W_REG (osh, &cc->regcontrol_addr, 0x00);
63  W_REG (osh, &cc->regcontrol_data, (uint32) (rf_voltage & 0x1f) << 14);
64
65  /* Return to original core */
66  sb_setcoreidx (sbh, origidx);
67}
68
69void
70sb_pmu_set_ldo_voltage (sb_t * sbh, osl_t * osh, uint8 ldo, uint8 voltage)
71{
72  uint8 sr_cntl_shift, rc_shift, shift, mask;
73  uint32 addr;
74
75  ASSERT (sbh->cccaps & CC_CAP_PMU);
76
77  switch (sbh->chip)
78    {
79    case BCM4328_CHIP_ID:
80    case BCM5354_CHIP_ID:
81      switch (ldo)
82    {
83    case SET_LDO_VOLTAGE_LDO1:
84      addr = 2;
85      sr_cntl_shift = 8;
86      rc_shift = 17;
87      mask = 0xf;
88      break;
89    case SET_LDO_VOLTAGE_LDO2:
90      addr = 3;
91      sr_cntl_shift = 0;
92      rc_shift = 1;
93      mask = 0xf;
94      break;
95    case SET_LDO_VOLTAGE_LDO3:
96      addr = 3;
97      sr_cntl_shift = 0;
98      rc_shift = 9;
99      mask = 0xf;
100      break;
101    case SET_LDO_VOLTAGE_PAREF:
102      addr = 3;
103      sr_cntl_shift = 0;
104      rc_shift = 17;
105      mask = 0x3f;
106      break;
107    default:
108      ASSERT (FALSE);
109      return;
110    }
111      break;
112    case BCM4312_CHIP_ID:
113      switch (ldo)
114    {
115    case SET_LDO_VOLTAGE_PAREF:
116      addr = 0;
117      sr_cntl_shift = 0;
118      rc_shift = 21;
119      mask = 0x3f;
120      break;
121    default:
122      ASSERT (FALSE);
123      return;
124    }
125      break;
126    default:
127      ASSERT (FALSE);
128      return;
129    }
130
131  shift = sr_cntl_shift + rc_shift;
132
133  sb_corereg (sbh, SB_CC_IDX, OFFSETOF (chipcregs_t, regcontrol_addr),
134          ~0, addr);
135  sb_corereg (sbh, SB_CC_IDX, OFFSETOF (chipcregs_t, regcontrol_data),
136          mask << shift, (voltage & mask) << shift);
137}
138
139void
140sb_pmu_paref_ldo_enable (sb_t * sbh, osl_t * osh, bool enable)
141{
142  uint ldo = 0;
143
144  ASSERT (sbh->cccaps & CC_CAP_PMU);
145
146  switch (sbh->chip)
147    {
148    case BCM4328_CHIP_ID:
149      ldo = RES4328_PA_REF_LDO;
150      break;
151    case BCM5354_CHIP_ID:
152      ldo = RES5354_PA_REF_LDO;
153      break;
154    case BCM4312_CHIP_ID:
155      ldo = RES4312_PA_REF_LDO;
156      break;
157    default:
158      return;
159    }
160
161  sb_corereg (sbh, SB_CC_IDX, OFFSETOF (chipcregs_t, min_res_mask),
162          PMURES_BIT (ldo), enable ? PMURES_BIT (ldo) : 0);
163}
164
165uint16 BCMINITFN (sb_pmu_fast_pwrup_delay) (sb_t * sbh, osl_t * osh)
166{
167  uint16 delay = PMU_MAX_TRANSITION_DLY;
168
169  ASSERT (sbh->cccaps & CC_CAP_PMU);
170
171  switch (sbh->chip)
172    {
173    case BCM4328_CHIP_ID:
174      delay = 7000;
175      break;
176
177    case BCM4325_CHIP_ID:
178    case BCM4312_CHIP_ID:
179#ifdef BCMQT
180      delay = 70;
181#else
182      delay = 2800;
183#endif
184      break;
185
186    default:
187      PMU_MSG (("No PMU fast power up delay specified "
188        "for chip %x rev %d, using default %d us\n",
189        sbh->chip, sbh->chiprev, delay));
190      break;
191    }
192
193  return delay;
194}
195
196uint32 BCMINITFN (sb_pmu_force_ilp) (sb_t * sbh, osl_t * osh, bool force)
197{
198  chipcregs_t *cc;
199  uint origidx;
200  uint32 oldpmucontrol;
201
202  ASSERT (sbh->cccaps & CC_CAP_PMU);
203
204  /* Remember original core before switch to chipc */
205  origidx = sb_coreidx (sbh);
206  cc = sb_setcore (sbh, SB_CC, 0);
207  ASSERT (cc);
208
209  oldpmucontrol = R_REG (osh, &cc->pmucontrol);
210  if (force)
211    W_REG (osh, &cc->pmucontrol, oldpmucontrol &
212       ~(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
213  else
214    W_REG (osh, &cc->pmucontrol, oldpmucontrol |
215       (PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
216
217  /* Return to original core */
218  sb_setcoreidx (sbh, origidx);
219
220  return oldpmucontrol;
221}
222
223/* Setup min/max resources and up/down timers */
224typedef struct
225{
226  uint8 resnum;
227  uint16 updown;
228} pmu_res_updown_t;
229
230typedef struct
231{
232  uint8 resnum;
233  int8 action; /* 0 - set, 1 - add, -1 - remove */
234  uint32 depend_mask;
235} pmu_res_depend_t;
236
237static const pmu_res_updown_t
238BCMINITDATA (bcm4328a0_res_updown)[] =
239{
240  {
241  RES4328_EXT_SWITCHER_PWM, 0x0101},
242  {
243  RES4328_BB_SWITCHER_PWM, 0x1f01},
244  {
245  RES4328_BB_SWITCHER_BURST, 0x010f},
246  {
247  RES4328_BB_EXT_SWITCHER_BURST, 0x0101},
248  {
249  RES4328_ILP_REQUEST, 0x0202},
250  {
251  RES4328_RADIO_SWITCHER_PWM, 0x0f01},
252  {
253  RES4328_RADIO_SWITCHER_BURST, 0x0f01},
254  {
255  RES4328_ROM_SWITCH, 0x0101},
256  {
257  RES4328_PA_REF_LDO, 0x0f01},
258  {
259  RES4328_RADIO_LDO, 0x0f01},
260  {
261  RES4328_AFE_LDO, 0x0f01},
262  {
263  RES4328_PLL_LDO, 0x0f01},
264  {
265  RES4328_BG_FILTBYP, 0x0101},
266  {
267  RES4328_TX_FILTBYP, 0x0101},
268  {
269  RES4328_RX_FILTBYP, 0x0101},
270  {
271  RES4328_XTAL_PU, 0x0101},
272  {
273  RES4328_XTAL_EN, 0xa001},
274  {
275  RES4328_BB_PLL_FILTBYP, 0x0101},
276  {
277  RES4328_RF_PLL_FILTBYP, 0x0101},
278  {
279  RES4328_BB_PLL_PU, 0x0701}
280};
281
282static const pmu_res_depend_t
283BCMINITDATA (bcm4328a0_res_depend)[] =
284{
285  /* Adjust ILP request resource not to force ext/BB switchers into burst mode */
286  {
287  RES4328_ILP_REQUEST, 0,
288      PMURES_BIT (RES4328_EXT_SWITCHER_PWM) |
289      PMURES_BIT (RES4328_BB_SWITCHER_PWM)}
290};
291
292#ifdef BCMQT /* for power save on slow QT/small beacon interval */
293static const pmu_res_updown_t
294BCMINITDATA (bcm4325a0_res_updown_qt)[] =
295{
296  {
297  RES4325_HT_AVAIL, 0x0300},
298  {
299  RES4325_BBPLL_PWRSW_PU, 0x0101},
300  {
301  RES4325_RFPLL_PWRSW_PU, 0x0101},
302  {
303  RES4325_ALP_AVAIL, 0x0100},
304  {
305  RES4325_XTAL_PU, 0x1000},
306  {
307  RES4325_LNLDO1_PU, 0x0800},
308  {
309  RES4325_CLDO_CBUCK_PWM, 0x0101},
310  {
311  RES4325_CBUCK_PWM, 0x0803}
312};
313#else
314static const pmu_res_updown_t
315BCMINITDATA (bcm4325a0_res_updown)[] =
316{
317  {
318  RES4325_XTAL_PU, 0x1501}
319};
320#endif /* !BCMQT */
321
322static const pmu_res_depend_t
323BCMINITDATA (bcm4325a0_res_depend)[] =
324{
325  /* Adjust HT Avail resource dependencies */
326  {
327  RES4325_HT_AVAIL, 1,
328      PMURES_BIT (RES4325_RX_PWRSW_PU) | PMURES_BIT (RES4325_TX_PWRSW_PU) |
329      PMURES_BIT (RES4325_LOGEN_PWRSW_PU) | PMURES_BIT (RES4325_AFE_PWRSW_PU)}
330};
331
332void BCMINITFN (sb_pmu_res_init) (sb_t * sbh, osl_t * osh)
333{
334  chipcregs_t *cc;
335  uint origidx;
336  const pmu_res_updown_t *pmu_res_updown_table = NULL;
337  int pmu_res_updown_table_sz = 0;
338  const pmu_res_depend_t *pmu_res_depend_table = NULL;
339  int pmu_res_depend_table_sz = 0;
340  uint32 min_mask = 0, max_mask = 0;
341
342  ASSERT (sbh->cccaps & CC_CAP_PMU);
343
344  /* Remember original core before switch to chipc */
345  origidx = sb_coreidx (sbh);
346  cc = sb_setcore (sbh, SB_CC, 0);
347  ASSERT (cc);
348
349  switch (sbh->chip)
350    {
351    case BCM4328_CHIP_ID:
352      /* Down to ILP request excluding ROM */
353      min_mask = PMURES_BIT (RES4328_EXT_SWITCHER_PWM) |
354    PMURES_BIT (RES4328_BB_SWITCHER_PWM) | PMURES_BIT (RES4328_XTAL_EN);
355#ifdef BCMROMOFFLOAD
356      /* Including ROM */
357      min_mask |= PMURES_BIT (RES4328_ROM_SWITCH);
358#endif
359      /* Allow (but don't require) PLL to turn on */
360      max_mask = 0xfffff;
361      pmu_res_updown_table = bcm4328a0_res_updown;
362      pmu_res_updown_table_sz = ARRAYSIZE (bcm4328a0_res_updown);
363      pmu_res_depend_table = bcm4328a0_res_depend;
364      pmu_res_depend_table_sz = ARRAYSIZE (bcm4328a0_res_depend);
365      break;
366    case BCM4312_CHIP_ID:
367      /* keep default
368       * min_mask = 0xcbb; max_mask = 0x7ffff;
369       * pmu_res_updown_table_sz = 0;
370       * pmu_res_depend_table_sz = 0;
371       */
372      break;
373    case BCM5354_CHIP_ID:
374      /* Allow (but don't require) PLL to turn on */
375      max_mask = 0xfffff;
376      break;
377
378    case BCM4325_CHIP_ID:
379      /* Leave OTP powered up and power it down later. */
380      min_mask =
381    PMURES_BIT (RES4325_CBUCK_BURST) | PMURES_BIT (RES4325_LNLDO2_PU);
382      if (((sbh->chipst & CST4325_PMUTOP_2B_MASK) >>
383       CST4325_PMUTOP_2B_SHIFT) == 1)
384    min_mask |= PMURES_BIT (RES4325_CLDO_CBUCK_BURST);
385      /* Allow (but don't require) PLL to turn on */
386      max_mask = 0x3fffff;
387#ifdef BCMQT
388      pmu_res_updown_table = bcm4325a0_res_updown_qt;
389      pmu_res_updown_table_sz = ARRAYSIZE (bcm4325a0_res_updown_qt);
390#else
391      pmu_res_updown_table = bcm4325a0_res_updown;
392      pmu_res_updown_table_sz = ARRAYSIZE (bcm4325a0_res_updown);
393      pmu_res_depend_table = bcm4325a0_res_depend;
394      pmu_res_depend_table_sz = ARRAYSIZE (bcm4325a0_res_depend);
395#endif
396      break;
397
398    default:
399      break;
400    }
401
402  /* Program up/down timers */
403  while (pmu_res_updown_table_sz--)
404    {
405      ASSERT (pmu_res_updown_table);
406      W_REG (osh, &cc->res_table_sel,
407         pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
408      W_REG (osh, &cc->res_updn_timer,
409         pmu_res_updown_table[pmu_res_updown_table_sz].updown);
410    }
411
412  /* Program resource dependencies table */
413  while (pmu_res_depend_table_sz--)
414    {
415      ASSERT (pmu_res_depend_table);
416      W_REG (osh, &cc->res_table_sel,
417         pmu_res_depend_table[pmu_res_depend_table_sz].resnum);
418      switch (pmu_res_depend_table[pmu_res_depend_table_sz].action)
419    {
420    case 0:
421      W_REG (osh, &cc->res_dep_mask,
422         pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
423      break;
424    case 1:
425      OR_REG (osh, &cc->res_dep_mask,
426          pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
427      break;
428    case -1:
429      AND_REG (osh, &cc->res_dep_mask,
430           ~pmu_res_depend_table[pmu_res_depend_table_sz].
431           depend_mask);
432      break;
433    default:
434      ASSERT (0);
435      break;
436    }
437    }
438
439  /* program min resource mask */
440  if (min_mask)
441    {
442      PMU_MSG (("Changing min_res_mask to 0x%x\n", min_mask));
443      W_REG (osh, &cc->min_res_mask, min_mask);
444    }
445  /* program max resource mask */
446  if (max_mask)
447    {
448      PMU_MSG (("Changing max_res_mask to 0x%x\n", max_mask));
449      W_REG (osh, &cc->max_res_mask, max_mask);
450    }
451
452  /* Return to original core */
453  sb_setcoreidx (sbh, origidx);
454}
455
456/* setup pll and query clock speed */
457typedef struct
458{
459  uint16 freq;
460  uint8 xf;
461  uint8 wbint;
462  uint32 wbfrac;
463} pmu0_xtaltab0_t;
464
465/* the following table is based on 880Mhz Fvco */
466#define PMU0_PLL0_FVCO 880000 /* Fvco 880Mhz */
467static const pmu0_xtaltab0_t
468BCMINITDATA (pmu0_xtaltab0)[] =
469{
470  {
471  12000, 1, 73, 349525},
472  {
473  13000, 2, 67, 725937},
474  {
475  14400, 3, 61, 116508},
476  {
477  15360, 4, 57, 305834},
478  {
479  16200, 5, 54, 336579},
480  {
481  16800, 6, 52, 399457},
482  {
483  19200, 7, 45, 873813},
484  {
485  19800, 8, 44, 466033},
486  {
487  20000, 9, 44, 0},
488  {
489  25000, 10, 70, 419430},
490  {
491  26000, 11, 67, 725937},
492  {
493  30000, 12, 58, 699050},
494  {
495  38400, 13, 45, 873813},
496  {
497  40000, 14, 45, 0},
498  {
499  0, 0, 0, 0}
500};
501
502#ifdef BCMUSBDEV
503#define PMU0_XTAL0_DEFAULT 11
504#else
505#define PMU0_XTAL0_DEFAULT 8
506#endif
507
508#ifdef BCMUSBDEV
509/*
510 * Set new backplane PLL clock frequency
511 */
512static void BCMINITFN (sb_pmu0_sbclk4328) (sb_t * sbh, int freq)
513{
514  uint32 tmp, oldmax, oldmin, origidx;
515  chipcregs_t *cc;
516
517  /* Remember original core before switch to chipc */
518  origidx = sb_coreidx (sbh);
519  cc = sb_setcore (sbh, SB_CC, 0);
520  ASSERT (cc);
521
522  /* Set new backplane PLL clock */
523  W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
524  tmp = R_REG (osh, &cc->pllcontrol_data);
525  tmp &= ~(PMU0_PLL0_PC0_DIV_ARM_MASK);
526  tmp |= freq << PMU0_PLL0_PC0_DIV_ARM_SHIFT;
527  W_REG (osh, &cc->pllcontrol_data, tmp);
528
529  /* Power cycle BB_PLL_PU by disabling/enabling it to take on new freq */
530  /* Disable PLL */
531  oldmin = R_REG (osh, &cc->min_res_mask);
532  oldmax = R_REG (osh, &cc->max_res_mask);
533  W_REG (osh, &cc->min_res_mask, oldmin & ~PMURES_BIT (RES4328_BB_PLL_PU));
534  W_REG (osh, &cc->max_res_mask, oldmax & ~PMURES_BIT (RES4328_BB_PLL_PU));
535
536  /* It takes over several hundred usec to re-enable the PLL since the
537   * sequencer state machines run on ILP clock. Set delay at 450us to be safe.
538   *
539   * Be sure PLL is powered down first before re-enabling it.
540   */
541
542  OSL_DELAY (PLL_DELAY);
543  SPINWAIT ((R_REG (osh, &cc->res_state) & PMURES_BIT (RES4328_BB_PLL_PU)),
544        PLL_DELAY * 3);
545
546  if (R_REG (osh, &cc->res_state) & PMURES_BIT (RES4328_BB_PLL_PU))
547    {
548      /* If BB_PLL not powered down yet, new backplane PLL clock
549       * may not take effect.
550       *
551       * Still early during bootup so no serial output here.
552       */
553      PMU_ERROR (("Fatal: BB_PLL not power down yet!\n"));
554      ASSERT (!
555          (R_REG (osh, &cc->res_state) & PMURES_BIT (RES4328_BB_PLL_PU)));
556    }
557
558  /* Enable PLL */
559  W_REG (osh, &cc->max_res_mask, oldmax);
560
561  /* Return to original core */
562  sb_setcoreidx (sbh, origidx);
563}
564#endif /* BCMUSBDEV */
565
566/* Set up PLL registers in the PMU as per the crystal speed.
567 * Uses xtalfreq variable, or passed-in default.
568 */
569static void
570BCMINITFN (sb_pmu0_pllinit0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc,
571                  uint32 xtal)
572{
573  uint32 tmp;
574  const pmu0_xtaltab0_t *xt;
575
576  if ((sb_chip (sbh) == BCM5354_CHIP_ID) && (xtal == 0))
577    {
578      /* 5354 has xtal freq of 25MHz */
579      xtal = 25000;
580    }
581
582  /* Find the frequency in the table */
583  for (xt = pmu0_xtaltab0; xt->freq; xt++)
584    if (xt->freq == xtal)
585      break;
586  if (xt->freq == 0)
587    xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
588
589  PMU_MSG (("XTAL %d (%d)\n", xtal, xt->xf));
590
591  /* Check current PLL state */
592  tmp = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
593    PCTL_XTALFREQ_SHIFT;
594  if (tmp == xt->xf)
595    {
596      PMU_MSG (("PLL already programmed for %d.%d MHz\n",
597        (xt->freq / 1000), (xt->freq % 1000)));
598
599#ifdef BCMUSBDEV
600      if (sbh->chip == BCM4328_CHIP_ID)
601    sb_pmu0_sbclk4328 (sbh, PMU0_PLL0_PC0_DIV_ARM_88MHZ);
602#endif
603      return;
604    }
605
606  if (tmp)
607    {
608      PMU_MSG (("Reprogramming PLL for %d.%d MHz (was %d.%dMHz)\n",
609        (xt->freq / 1000), (xt->freq % 1000),
610        (pmu0_xtaltab0[tmp - 1].freq / 1000),
611        (pmu0_xtaltab0[tmp - 1].freq % 1000)));
612    }
613  else
614    {
615      PMU_MSG (("Programming PLL for %d.%d MHz\n", (xt->freq / 1000),
616        (xt->freq % 1000)));
617    }
618
619  /* Make sure the PLL is off */
620  switch (sbh->chip)
621    {
622    case BCM4328_CHIP_ID:
623      AND_REG (osh, &cc->min_res_mask, ~PMURES_BIT (RES4328_BB_PLL_PU));
624      AND_REG (osh, &cc->max_res_mask, ~PMURES_BIT (RES4328_BB_PLL_PU));
625      break;
626    case BCM5354_CHIP_ID:
627      AND_REG (osh, &cc->min_res_mask, ~PMURES_BIT (RES5354_BB_PLL_PU));
628      AND_REG (osh, &cc->max_res_mask, ~PMURES_BIT (RES5354_BB_PLL_PU));
629      break;
630    default:
631      ASSERT (0);
632    }
633  SPINWAIT (R_REG (osh, &cc->clk_ctl_st) & CCS0_HTAVAIL,
634        PMU_MAX_TRANSITION_DLY);
635  ASSERT (!(R_REG (osh, &cc->clk_ctl_st) & CCS0_HTAVAIL));
636
637  PMU_MSG (("Done masking\n"));
638
639  /* Write PDIV in pllcontrol[0] */
640  W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
641  tmp = R_REG (osh, &cc->pllcontrol_data);
642  if (xt->freq >= PMU0_PLL0_PC0_PDIV_FREQ)
643    tmp |= PMU0_PLL0_PC0_PDIV_MASK;
644  else
645    tmp &= ~PMU0_PLL0_PC0_PDIV_MASK;
646  W_REG (osh, &cc->pllcontrol_data, tmp);
647
648  /* Write WILD in pllcontrol[1] */
649  W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
650  tmp = R_REG (osh, &cc->pllcontrol_data);
651  tmp =
652    ((tmp & ~(PMU0_PLL0_PC1_WILD_INT_MASK | PMU0_PLL0_PC1_WILD_FRAC_MASK)) |
653     (((xt->
654    wbint << PMU0_PLL0_PC1_WILD_INT_SHIFT) & PMU0_PLL0_PC1_WILD_INT_MASK)
655      | ((xt->wbfrac << PMU0_PLL0_PC1_WILD_FRAC_SHIFT) &
656     PMU0_PLL0_PC1_WILD_FRAC_MASK)));
657  if (xt->wbfrac == 0)
658    tmp |= PMU0_PLL0_PC1_STOP_MOD;
659  else
660    tmp &= ~PMU0_PLL0_PC1_STOP_MOD;
661  W_REG (osh, &cc->pllcontrol_data, tmp);
662
663  /* Write WILD in pllcontrol[2] */
664  W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
665  tmp = R_REG (osh, &cc->pllcontrol_data);
666  tmp = ((tmp & ~PMU0_PLL0_PC2_WILD_INT_MASK) |
667     ((xt->wbint >> PMU0_PLL0_PC2_WILD_INT_SHIFT) &
668      PMU0_PLL0_PC2_WILD_INT_MASK));
669  W_REG (osh, &cc->pllcontrol_data, tmp);
670
671  PMU_MSG (("Done pll\n"));
672
673  /* Write XtalFreq. Set the divisor also. */
674  tmp = R_REG (osh, &cc->pmucontrol);
675  tmp = ((tmp & ~PCTL_ILP_DIV_MASK) |
676     (((((xt->freq + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
677      PCTL_ILP_DIV_MASK));
678  tmp = ((tmp & ~PCTL_XTALFREQ_MASK) |
679     ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK));
680  W_REG (osh, &cc->pmucontrol, tmp);
681}
682
683static uint32
684BCMINITFN (sb_pmu0_alpclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc)
685{
686  const pmu0_xtaltab0_t *xt;
687  uint32 xf;
688
689  /* Find the frequency in the table */
690  xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
691    PCTL_XTALFREQ_SHIFT;
692  for (xt = pmu0_xtaltab0; xt->freq; xt++)
693    if (xt->xf == xf)
694      break;
695  if (xt->freq == 0)
696    xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
697
698  return xt->freq * 1000;
699}
700
701static uint32
702BCMINITFN (sb_pmu0_cpuclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc)
703{
704  const pmu0_xtaltab0_t *xt;
705  uint32 xf, tmp, divarm;
706#ifdef BCMDBG
707  uint32 pdiv, wbint, wbfrac, fvco;
708#endif
709
710  if (sb_chip (sbh) == BCM5354_CHIP_ID)
711    {
712      /* 5354 gets sb clock of 120MHz from main pll */
713      return 120000000;
714    }
715
716  /* Find the xtal frequency in the table */
717  xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
718    PCTL_XTALFREQ_SHIFT;
719  for (xt = pmu0_xtaltab0; xt->freq; xt++)
720    if (xt->xf == xf)
721      break;
722  if (xt->freq == 0)
723    xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
724
725  /* Read divarm from pllcontrol[0] */
726  W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
727  tmp = R_REG (osh, &cc->pllcontrol_data);
728  divarm = (tmp & PMU0_PLL0_PC0_DIV_ARM_MASK) >> PMU0_PLL0_PC0_DIV_ARM_SHIFT;
729
730#ifdef BCMDBG
731  /* Calculate Fvco based on xtal freq, pdiv, and wild */
732  pdiv = tmp & PMU0_PLL0_PC0_PDIV_MASK;
733
734  W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
735  tmp = R_REG (osh, &cc->pllcontrol_data);
736  wbfrac =
737    (tmp & PMU0_PLL0_PC1_WILD_FRAC_MASK) >> PMU0_PLL0_PC1_WILD_FRAC_SHIFT;
738  wbint = (tmp & PMU0_PLL0_PC1_WILD_INT_MASK) >> PMU0_PLL0_PC1_WILD_INT_SHIFT;
739
740  W_REG (osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
741  tmp = R_REG (osh, &cc->pllcontrol_data);
742  wbint +=
743    (tmp & PMU0_PLL0_PC2_WILD_INT_MASK) << PMU0_PLL0_PC2_WILD_INT_SHIFT;
744
745  fvco = (xt->freq * wbint) << 8;
746  fvco += (xt->freq * (wbfrac >> 10)) >> 2;
747  fvco += (xt->freq * (wbfrac & 0x3ff)) >> 10;
748  fvco >>= 8;
749  fvco >>= pdiv;
750  fvco /= 1000;
751  fvco *= 1000;
752
753  PMU_MSG (("sb_pmu0_cpuclk0: wbint %u wbfrac %u fvco %u\n",
754        wbint, wbfrac, fvco));
755  ASSERT (fvco == PMU0_PLL0_FVCO);
756#endif /* BCMDBG */
757
758  /* Return ARM/SB clock */
759  return PMU0_PLL0_FVCO / (divarm + PMU0_PLL0_PC0_DIV_ARM_BASE) * 1000;
760}
761
762/* PMU corerev 1 pll programming for BCM4325 */
763/* setup pll and query clock speed */
764typedef struct
765{
766  uint16 fref;
767  uint8 xf;
768  uint8 p1div;
769  uint8 p2div;
770  uint8 ndiv_int;
771  uint32 ndiv_frac;
772} pmu1_xtaltab0_t;
773
774/* the following table is based on 880Mhz Fvco */
775#define PMU1_PLL0_FVCO 880000 /* Fvco 880Mhz */
776static const pmu1_xtaltab0_t
777BCMINITDATA (pmu1_xtaltab0)[] =
778{
779  {
780  12000, 1, 3, 22, 0x9, 0xFFFFEF},
781  {
782  13000, 2, 1, 6, 0xb, 0x483483},
783  {
784  14400, 3, 1, 10, 0xa, 0x1C71C7},
785  {
786  15360, 4, 1, 5, 0xb, 0x755555},
787  {
788  16200, 5, 1, 10, 0x5, 0x6E9E06},
789  {
790  16800, 6, 1, 10, 0x5, 0x3Cf3Cf},
791  {
792  19200, 7, 1, 9, 0x5, 0x17B425},
793  {
794  19800, 8, 1, 11, 0x4, 0xA57EB},
795  {
796  20000, 9, 1, 11, 0x4, 0x0},
797  {
798  24000, 10, 3, 11, 0xa, 0x0},
799  {
800  25000, 11, 5, 16, 0xb, 0x0},
801  {
802  26000, 12, 1, 2, 0x10, 0xEC4EC4},
803  {
804  30000, 13, 3, 8, 0xb, 0x0},
805  {
806  38400, 14, 1, 5, 0x4, 0x955555},
807  {
808  40000, 15, 1, 2, 0xb, 0},
809  {
810  0, 0, 0, 0, 0, 0}
811};
812
813/* Default to 15360Khz crystal */
814#define PMU1_XTAL0_DEFAULT 3
815
816static uint32
817BCMINITFN (sb_pmu1_alpclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc)
818{
819  const pmu1_xtaltab0_t *xt;
820  uint32 xf;
821
822  /* Find the frequency in the table */
823  xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
824    PCTL_XTALFREQ_SHIFT;
825  for (xt = pmu1_xtaltab0; xt->fref; xt++)
826    if (xt->xf == xf)
827      break;
828  if (xt->fref == 0)
829    xt = &pmu1_xtaltab0[PMU1_XTAL0_DEFAULT];
830
831  return xt->fref * 1000;
832}
833
834/* Set up PLL registers in the PMU as per the crystal speed.
835 * Uses xtalfreq variable, or passed-in default.
836 */
837static void
838BCMINITFN (sb_pmu1_pllinit0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc,
839                  uint32 xtal)
840{
841  const pmu1_xtaltab0_t *xt;
842  uint32 tmp;
843  uint32 buf_strength = 0;
844
845  /* 4312: assume default works */
846  if (sbh->chip == BCM4312_CHIP_ID)
847    return;
848
849  /* Find the frequency in the table */
850  for (xt = pmu1_xtaltab0; xt->fref; xt++)
851    if (xt->fref == xtal)
852      break;
853  if (xt->fref == 0)
854    xt = &pmu1_xtaltab0[PMU1_XTAL0_DEFAULT];
855
856  PMU_MSG (("XTAL %d (%d)\n", xtal, xt->xf));
857
858  /* Check current PLL state */
859  if (((R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
860       PCTL_XTALFREQ_SHIFT) == xt->xf)
861    {
862      PMU_MSG (("PLL already programmed for %d.%d MHz\n",
863        (xt->fref / 1000), (xt->fref % 1000)));
864      return;
865    }
866
867  PMU_MSG (("Programming PLL for %d.%d MHz\n", (xt->fref / 1000),
868        (xt->fref % 1000)));
869
870  /* Make sure the PLL is off */
871  switch (sbh->chip)
872    {
873    case BCM4325_CHIP_ID:
874      AND_REG (osh, &cc->min_res_mask,
875           ~(PMURES_BIT (RES4325_BBPLL_PWRSW_PU) |
876         PMURES_BIT (RES4325_HT_AVAIL)));
877      AND_REG (osh, &cc->max_res_mask,
878           ~(PMURES_BIT (RES4325_BBPLL_PWRSW_PU) |
879         PMURES_BIT (RES4325_HT_AVAIL)));
880
881      /* Change the BBPLL drive strength to 2 for all channels */
882      buf_strength = 0x222222;
883      break;
884    default:
885      ASSERT (0);
886    }
887  SPINWAIT (R_REG (osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
888        PMU_MAX_TRANSITION_DLY);
889  ASSERT (!(R_REG (osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
890
891  PMU_MSG (("Done masking\n"));
892
893  /* Write p1div and p2div to pllcontrol[0] */
894  W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
895  tmp = R_REG (osh, &cc->pllcontrol_data) &
896    ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
897  tmp |=
898    ((xt->
899      p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) | ((xt->
900                                      p2div
901                                      <<
902                                      PMU1_PLL0_PC0_P2DIV_SHIFT)
903                                     &
904                                     PMU1_PLL0_PC0_P2DIV_MASK);
905  W_REG (osh, &cc->pllcontrol_data, tmp);
906
907  /* Write ndiv_int and ndiv_mode to pllcontrol[2] */
908  W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
909  tmp = R_REG (osh, &cc->pllcontrol_data) &
910    ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
911  tmp |=
912    ((xt->
913      ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) & PMU1_PLL0_PC2_NDIV_INT_MASK)
914    | ((1 << PMU1_PLL0_PC2_NDIV_MODE_SHIFT) & PMU1_PLL0_PC2_NDIV_MODE_MASK);
915  W_REG (osh, &cc->pllcontrol_data, tmp);
916
917  /* Write ndiv_frac to pllcontrol[3] */
918  W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
919  tmp = R_REG (osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
920  tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
921      PMU1_PLL0_PC3_NDIV_FRAC_MASK);
922  W_REG (osh, &cc->pllcontrol_data, tmp);
923
924  if (buf_strength)
925    {
926      PMU_MSG (("Adjusting PLL buffer drive strength: %x\n", buf_strength));
927
928      W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
929      tmp = R_REG (osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
930      tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
931      W_REG (osh, &cc->pllcontrol_data, tmp);
932    }
933
934  PMU_MSG (("Done pll\n"));
935
936  /* Write XtalFreq. Set the divisor also. */
937  tmp = R_REG (osh, &cc->pmucontrol) &
938    ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
939  tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
940      PCTL_ILP_DIV_MASK) |
941    ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
942  W_REG (osh, &cc->pmucontrol, tmp);
943}
944
945
946static uint32
947BCMINITFN (sb_pmu1_cpuclk0) (sb_t * sbh, osl_t * osh, chipcregs_t * cc)
948{
949  const pmu1_xtaltab0_t *xt;
950  uint32 xf, tmp, m1div;
951#ifdef BCMDBG
952  uint32 ndiv_int, ndiv_frac, p2div, p1div, fvco;
953#endif
954
955  /* Find the xtal frequency in the table */
956  xf = (R_REG (osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
957    PCTL_XTALFREQ_SHIFT;
958  for (xt = pmu1_xtaltab0; xt->fref; xt++)
959    if (xt->xf == xf)
960      break;
961  if (xt->fref == 0)
962    xt = &pmu1_xtaltab0[PMU1_XTAL0_DEFAULT];
963
964  /* Read m1div from pllcontrol[1] */
965  W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
966  tmp = R_REG (osh, &cc->pllcontrol_data);
967  m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT;
968
969#ifdef BCMDBG
970  /* Read p2div/p1div from pllcontrol[0] */
971  W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
972  tmp = R_REG (osh, &cc->pllcontrol_data);
973  p2div = (tmp & PMU1_PLL0_PC0_P2DIV_MASK) >> PMU1_PLL0_PC0_P2DIV_SHIFT;
974  p1div = (tmp & PMU1_PLL0_PC0_P1DIV_MASK) >> PMU1_PLL0_PC0_P1DIV_SHIFT;
975
976  /* Calculate Fvco based on xtal freq and ndiv and pdiv */
977  W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
978  tmp = R_REG (osh, &cc->pllcontrol_data);
979  ndiv_int =
980    (tmp & PMU1_PLL0_PC2_NDIV_INT_MASK) >> PMU1_PLL0_PC2_NDIV_INT_SHIFT;
981
982  W_REG (osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
983  tmp = R_REG (osh, &cc->pllcontrol_data);
984  ndiv_frac =
985    (tmp & PMU1_PLL0_PC3_NDIV_FRAC_MASK) >> PMU1_PLL0_PC3_NDIV_FRAC_SHIFT;
986
987  fvco = (xt->fref * ndiv_int) << 8;
988  fvco += (xt->fref * (ndiv_frac >> 12)) >> 4;
989  fvco += (xt->fref * (ndiv_frac & 0xfff)) >> 12;
990  fvco >>= 8;
991  fvco *= p2div;
992  fvco /= p1div;
993  fvco /= 1000;
994  fvco *= 1000;
995
996  PMU_MSG (("sb_pmu0_cpuclk0: ndiv_int %u ndiv_frac %u "
997        "p2div %u p1div %u fvco %u\n",
998        ndiv_int, ndiv_frac, p2div, p1div, fvco));
999  ASSERT (fvco == PMU1_PLL0_FVCO);
1000#endif /* BCMDBG */
1001
1002  /* Return ARM/SB clock */
1003  return PMU1_PLL0_FVCO / m1div * 1000;
1004}
1005
1006void BCMINITFN (sb_pmu_pll_init) (sb_t * sbh, osl_t * osh, uint xtalfreq)
1007{
1008  chipcregs_t *cc;
1009  uint origidx;
1010
1011  ASSERT (sbh->cccaps & CC_CAP_PMU);
1012
1013  /* Remember original core before switch to chipc */
1014  origidx = sb_coreidx (sbh);
1015  cc = sb_setcore (sbh, SB_CC, 0);
1016  ASSERT (cc);
1017
1018  switch (sbh->chip)
1019    {
1020    case BCM4328_CHIP_ID:
1021      sb_pmu0_pllinit0 (sbh, osh, cc, xtalfreq);
1022      break;
1023    case BCM5354_CHIP_ID:
1024      sb_pmu0_pllinit0 (sbh, osh, cc, xtalfreq);
1025      break;
1026    case BCM4325_CHIP_ID:
1027      sb_pmu1_pllinit0 (sbh, osh, cc, xtalfreq);
1028      break;
1029    case BCM4312_CHIP_ID:
1030      sb_pmu1_pllinit0 (sbh, osh, cc, xtalfreq);
1031      break;
1032    default:
1033      PMU_MSG (("No PLL init done for chip %x rev %d pmurev %d\n",
1034        sbh->chip, sbh->chiprev, sbh->pmurev));
1035      break;
1036    }
1037
1038  /* Return to original core */
1039  sb_setcoreidx (sbh, origidx);
1040}
1041
1042uint32 BCMINITFN (sb_pmu_alp_clock) (sb_t * sbh, osl_t * osh)
1043{
1044  chipcregs_t *cc;
1045  uint origidx;
1046  uint32 clock = ALP_CLOCK;
1047
1048  ASSERT (sbh->cccaps & CC_CAP_PMU);
1049
1050  /* Remember original core before switch to chipc */
1051  origidx = sb_coreidx (sbh);
1052  cc = sb_setcore (sbh, SB_CC, 0);
1053  ASSERT (cc);
1054
1055  switch (sbh->chip)
1056    {
1057    case BCM4328_CHIP_ID:
1058      clock = sb_pmu0_alpclk0 (sbh, osh, cc);
1059      break;
1060    case BCM5354_CHIP_ID:
1061      clock = sb_pmu0_alpclk0 (sbh, osh, cc);
1062      break;
1063    case BCM4325_CHIP_ID:
1064      clock = sb_pmu1_alpclk0 (sbh, osh, cc);
1065      break;
1066    case BCM4312_CHIP_ID:
1067      clock = sb_pmu1_alpclk0 (sbh, osh, cc);
1068      /* always 20Mhz */
1069      clock = 20000 * 1000;
1070      break;
1071    default:
1072      PMU_MSG (("No ALP clock specified "
1073        "for chip %x rev %d pmurev %d, using default %d Hz\n",
1074        sbh->chip, sbh->chiprev, sbh->pmurev, clock));
1075      break;
1076    }
1077
1078  /* Return to original core */
1079  sb_setcoreidx (sbh, origidx);
1080  return clock;
1081}
1082
1083uint BCMINITFN (sb_pmu_cpu_clock) (sb_t * sbh, osl_t * osh)
1084{
1085  chipcregs_t *cc;
1086  uint origidx;
1087  uint32 clock = HT_CLOCK;
1088
1089  ASSERT (sbh->cccaps & CC_CAP_PMU);
1090
1091  /* Remember original core before switch to chipc */
1092  origidx = sb_coreidx (sbh);
1093  cc = sb_setcore (sbh, SB_CC, 0);
1094  ASSERT (cc);
1095
1096  switch (sbh->chip)
1097    {
1098    case BCM4328_CHIP_ID:
1099      clock = sb_pmu0_cpuclk0 (sbh, osh, cc);
1100      break;
1101    case BCM5354_CHIP_ID:
1102      clock = sb_pmu0_cpuclk0 (sbh, osh, cc);
1103      break;
1104    case BCM4325_CHIP_ID:
1105      clock = sb_pmu1_cpuclk0 (sbh, osh, cc);
1106      break;
1107    case BCM4312_CHIP_ID:
1108      clock = sb_pmu1_cpuclk0 (sbh, osh, cc);
1109      break;
1110    default:
1111      PMU_MSG (("No CPU clock specified "
1112        "for chip %x rev %d pmurev %d, using default %d Hz\n",
1113        sbh->chip, sbh->chiprev, sbh->pmurev, clock));
1114      break;
1115    }
1116
1117  /* Return to original core */
1118  sb_setcoreidx (sbh, origidx);
1119  return clock;
1120}
1121
1122void BCMINITFN (sb_pmu_init) (sb_t * sbh, osl_t * osh)
1123{
1124  chipcregs_t *cc;
1125  uint origidx;
1126
1127  ASSERT (sbh->cccaps & CC_CAP_PMU);
1128
1129  /* Remember original core before switch to chipc */
1130  origidx = sb_coreidx (sbh);
1131  cc = sb_setcore (sbh, SB_CC, 0);
1132  ASSERT (cc);
1133
1134  if (sbh->pmurev >= 1)
1135    {
1136      if (sbh->chip == BCM4325_CHIP_ID && sbh->chiprev <= 1)
1137    AND_REG (osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
1138      else
1139    OR_REG (osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT);
1140    }
1141
1142  /* Return to original core */
1143  sb_setcoreidx (sbh, origidx);
1144}
1145
1146void BCMINITFN (sb_pmu_otp_power) (sb_t * sbh, osl_t * osh, bool on)
1147{
1148  chipcregs_t *cc;
1149  uint origidx;
1150
1151  ASSERT (sbh->cccaps & CC_CAP_PMU);
1152
1153  /* Remember original core before switch to chipc */
1154  origidx = sb_coreidx (sbh);
1155  cc = sb_setcore (sbh, SB_CC, 0);
1156  ASSERT (cc);
1157
1158  switch (sbh->chip)
1159    {
1160    case BCM4325_CHIP_ID:
1161      if (on)
1162    {
1163      OR_REG (osh, &cc->min_res_mask, PMURES_BIT (RES4325_LNLDO2_PU));
1164      if (sbh->boardflags & BFL_BUCKBOOST)
1165        AND_REG (osh, &cc->min_res_mask,
1166             ~PMURES_BIT (RES4325_BUCK_BOOST_PWM));
1167      OSL_DELAY (500);
1168    }
1169      else
1170    {
1171      if (sbh->boardflags & BFL_BUCKBOOST)
1172        OR_REG (osh, &cc->min_res_mask,
1173            PMURES_BIT (RES4325_BUCK_BOOST_PWM));
1174      AND_REG (osh, &cc->min_res_mask, ~PMURES_BIT (RES4325_LNLDO2_PU));
1175    }
1176      break;
1177    default:
1178      break;
1179    }
1180
1181  /* Return to original core */
1182  sb_setcoreidx (sbh, origidx);
1183}
1184
1185void
1186sb_pmu_rcal (sb_t * sbh, osl_t * osh)
1187{
1188  chipcregs_t *cc;
1189  uint origidx;
1190
1191  ASSERT (sbh->cccaps & CC_CAP_PMU);
1192
1193  /* Remember original core before switch to chipc */
1194  origidx = sb_coreidx (sbh);
1195  cc = sb_setcore (sbh, SB_CC, 0);
1196  ASSERT (cc);
1197
1198  switch (sbh->chip)
1199    {
1200    case BCM4325_CHIP_ID:
1201      {
1202    uint8 rcal_code;
1203    uint32 val;
1204
1205    /* Kick RCal */
1206    W_REG (osh, &cc->chipcontrol_addr, 1);
1207    AND_REG (osh, &cc->chipcontrol_data, ~0x04);
1208    OR_REG (osh, &cc->chipcontrol_data, 0x04);
1209
1210    /* Wait for completion */
1211    SPINWAIT (0 == (R_REG (osh, &cc->chipstatus) & 0x08),
1212          10 * 1000 * 1000);
1213    ASSERT (R_REG (osh, &cc->chipstatus) & 0x08);
1214
1215    /* Drop the LSB to convert from 5 bit code to 4 bit code */
1216    rcal_code = (uint8) (R_REG (osh, &cc->chipstatus) >> 5) & 0x0f;
1217    PMU_MSG (("RCal completed, status 0x%x, code 0x%x\n",
1218          R_REG (osh, &cc->chipstatus), rcal_code));
1219
1220    /* Write RCal code into pmu_vreg_ctrl[32:29] */
1221    W_REG (osh, &cc->regcontrol_addr, 0);
1222    val = R_REG (osh, &cc->regcontrol_data) & ~((uint32) 0x07 << 29);
1223    val |= (uint32) (rcal_code & 0x07) << 29;
1224    W_REG (osh, &cc->regcontrol_data, val);
1225    W_REG (osh, &cc->regcontrol_addr, 1);
1226    val = R_REG (osh, &cc->regcontrol_data) & ~(uint32) 0x01;
1227    val |= (uint32) ((rcal_code >> 3) & 0x01);
1228    W_REG (osh, &cc->regcontrol_data, val);
1229
1230    /* Write RCal code into pmu_chip_ctrl[33:30] */
1231    W_REG (osh, &cc->chipcontrol_addr, 0);
1232    val = R_REG (osh, &cc->chipcontrol_data) & ~((uint32) 0x03 << 30);
1233    val |= (uint32) (rcal_code & 0x03) << 30;
1234    W_REG (osh, &cc->chipcontrol_data, val);
1235    W_REG (osh, &cc->chipcontrol_addr, 1);
1236    val = R_REG (osh, &cc->chipcontrol_data) & ~(uint32) 0x03;
1237    val |= (uint32) ((rcal_code >> 2) & 0x03);
1238    W_REG (osh, &cc->chipcontrol_data, val);
1239
1240    /* Set override in pmu_chip_ctrl[29] */
1241    W_REG (osh, &cc->chipcontrol_addr, 0);
1242    OR_REG (osh, &cc->chipcontrol_data, (0x01 << 29));
1243
1244    /* Power off RCal block */
1245    W_REG (osh, &cc->chipcontrol_addr, 1);
1246    AND_REG (osh, &cc->chipcontrol_data, ~0x04);
1247
1248    break;
1249      }
1250    default:
1251      break;
1252    }
1253
1254  /* Return to original core */
1255  sb_setcoreidx (sbh, origidx);
1256}
1257

Archive Download this file



interactive