1/*
2 * Misc utility routines for accessing PMU corerev specific features
3 * of the SiliconBackplane-based Broadcom chips.
4 *
5 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * $Id: hndpmu.c,v 1.234.2.35 2011-02-11 21:35:40 Exp $
20 */
21
22#include <typedefs.h>
23#include <bcmdefs.h>
24#include <osl.h>
25#include <bcmutils.h>
26#include <siutils.h>
27#include <bcmdevs.h>
28#include <hndsoc.h>
29#include <sbchipc.h>
30#include <hndpmu.h>
31
32#define	PMU_ERROR(args)
33
34#define	PMU_MSG(args)
35
36/* To check in verbose debugging messages not intended
37 * to be on except on private builds.
38 */
39#define	PMU_NONE(args)
40
41/* PLL controls/clocks */
42static void si_pmu0_pllinit0(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal);
43static uint32 si_pmu0_alpclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
44#if !defined(_CFE_) || defined(CFG_WL)
45static uint32 si_pmu0_cpuclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
46static void si_pmu1_pllinit0(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal);
47static uint32 si_pmu1_cpuclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
48static uint32 si_pmu1_alpclk0(si_t *sih, osl_t *osh, chipcregs_t *cc);
49
50/* PMU resources */
51static bool si_pmu_res_depfltr_bb(si_t *sih);
52static bool si_pmu_res_depfltr_ncb(si_t *sih);
53static bool si_pmu_res_depfltr_paldo(si_t *sih);
54static bool si_pmu_res_depfltr_npaldo(si_t *sih);
55static uint32 si_pmu_res_deps(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 rsrcs, bool all);
56static uint si_pmu_res_uptime(si_t *sih, osl_t *osh, chipcregs_t *cc, uint8 rsrc);
57static void si_pmu_res_masks(si_t *sih, uint32 *pmin, uint32 *pmax);
58static void si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, osl_t *osh, uint8 spuravoid);
59
60void si_pmu_set_4330_plldivs(si_t *sih, uint8 dacrate);
61#endif /* !_CFE_ || CFG_WL */
62
63/* FVCO frequency */
64#define FVCO_880	880000	/* 880MHz */
65#define FVCO_1760	1760000	/* 1760MHz */
66#define FVCO_1440	1440000	/* 1440MHz */
67#define FVCO_960	960000	/* 960MHz */
68
69/* Read/write a chipcontrol reg */
70uint32
71si_pmu_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
72{
73	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_addr), ~0, reg);
74	return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, chipcontrol_data), mask, val);
75}
76
77/* Read/write a regcontrol reg */
78uint32
79si_pmu_regcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
80{
81	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_addr), ~0, reg);
82	return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_data), mask, val);
83}
84
85/* Read/write a pllcontrol reg */
86uint32
87si_pmu_pllcontrol(si_t *sih, uint reg, uint32 mask, uint32 val)
88{
89	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pllcontrol_addr), ~0, reg);
90	return si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pllcontrol_data), mask, val);
91}
92
93/* PMU PLL update */
94void
95si_pmu_pllupd(si_t *sih)
96{
97	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmucontrol),
98	           PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
99}
100
101/* PMU PLL reset */
102void
103si_pmu_pllreset(si_t *sih)
104{
105	uint32 res_mask = 0;
106	chipcregs_t *cc;
107	uint origidx;
108
109	/* Remember original core before switch to chipc */
110	origidx = si_coreidx(sih);
111	cc = si_setcoreidx(sih, SI_CC_IDX);
112	ASSERT(cc != NULL);
113
114	res_mask = PMURES_BIT(RES4330_BBPLL_PWRSW_PU) | PMURES_BIT(RES4330_MACPHY_CLKAVAIL) |
115		PMURES_BIT(RES4330_HT_AVAIL);
116
117	AND_REG(si_osh(sih), &cc->min_res_mask,	~(res_mask));
118	AND_REG(si_osh(sih), &cc->max_res_mask,	~(res_mask));
119	OR_REG(si_osh(sih), &cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
120	OR_REG(si_osh(sih), &cc->max_res_mask,	res_mask);
121
122	/* Return to original core */
123	si_setcoreidx(sih, origidx);
124}
125
126/* Setup switcher voltage */
127void
128BCMATTACHFN(si_pmu_set_switcher_voltage)(si_t *sih, osl_t *osh,
129                                         uint8 bb_voltage, uint8 rf_voltage)
130{
131	chipcregs_t *cc;
132	uint origidx;
133
134	ASSERT(sih->cccaps & CC_CAP_PMU);
135
136	/* Remember original core before switch to chipc */
137	origidx = si_coreidx(sih);
138	cc = si_setcoreidx(sih, SI_CC_IDX);
139	ASSERT(cc != NULL);
140
141	W_REG(osh, &cc->regcontrol_addr, 0x01);
142	W_REG(osh, &cc->regcontrol_data, (uint32)(bb_voltage & 0x1f) << 22);
143
144	W_REG(osh, &cc->regcontrol_addr, 0x00);
145	W_REG(osh, &cc->regcontrol_data, (uint32)(rf_voltage & 0x1f) << 14);
146
147	/* Return to original core */
148	si_setcoreidx(sih, origidx);
149}
150
151void
152BCMATTACHFN(si_pmu_set_ldo_voltage)(si_t *sih, osl_t *osh, uint8 ldo, uint8 voltage)
153{
154	uint8 sr_cntl_shift = 0, rc_shift = 0, shift = 0, mask = 0;
155	uint8 addr = 0;
156
157	ASSERT(sih->cccaps & CC_CAP_PMU);
158
159	switch (CHIPID(sih->chip)) {
160	case BCM4328_CHIP_ID:
161	case BCM5354_CHIP_ID:
162		switch (ldo) {
163		case SET_LDO_VOLTAGE_LDO1:
164			addr = 2;
165			sr_cntl_shift = 8;
166			rc_shift = 17;
167			mask = 0xf;
168			break;
169		case SET_LDO_VOLTAGE_LDO2:
170			addr = 3;
171			rc_shift = 1;
172			mask = 0xf;
173			break;
174		case SET_LDO_VOLTAGE_LDO3:
175			addr = 3;
176			rc_shift = 9;
177			mask = 0xf;
178			break;
179		case SET_LDO_VOLTAGE_PAREF:
180			addr = 3;
181			rc_shift = 17;
182			mask = 0x3f;
183			break;
184		default:
185			ASSERT(FALSE);
186			return;
187		}
188		break;
189	case BCM4312_CHIP_ID:
190		switch (ldo) {
191		case SET_LDO_VOLTAGE_PAREF:
192			addr = 0;
193			rc_shift = 21;
194			mask = 0x3f;
195			break;
196		default:
197			ASSERT(FALSE);
198			return;
199		}
200		break;
201	case BCM4325_CHIP_ID:
202		switch (ldo) {
203		case SET_LDO_VOLTAGE_CLDO_PWM:
204			addr = 5;
205			rc_shift = 9;
206			mask = 0xf;
207			break;
208		case SET_LDO_VOLTAGE_CLDO_BURST:
209			addr = 5;
210			rc_shift = 13;
211			mask = 0xf;
212			break;
213		case SET_LDO_VOLTAGE_CBUCK_PWM:
214			addr = 3;
215			rc_shift = 20;
216			mask = 0x1f;
217			/* Bit 116 & 119 are inverted in CLB for opt 2b */
218			if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
219			     CST4325_PMUTOP_2B_SHIFT) == 1)
220				voltage ^= 0x9;
221			break;
222		case SET_LDO_VOLTAGE_CBUCK_BURST:
223			addr = 3;
224			rc_shift = 25;
225			mask = 0x1f;
226			/* Bit 121 & 124 are inverted in CLB for opt 2b */
227			if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
228			     CST4325_PMUTOP_2B_SHIFT) == 1)
229				voltage ^= 0x9;
230			break;
231		case SET_LDO_VOLTAGE_LNLDO1:
232			addr = 5;
233			rc_shift = 17;
234			mask = 0x1f;
235			break;
236		case SET_LDO_VOLTAGE_LNLDO2_SEL:
237			addr = 6;
238			rc_shift = 0;
239			mask = 0x1;
240			break;
241		default:
242			ASSERT(FALSE);
243			return;
244		}
245		break;
246	case BCM4336_CHIP_ID:
247		switch (ldo) {
248		case SET_LDO_VOLTAGE_CLDO_PWM:
249			addr = 4;
250			rc_shift = 1;
251			mask = 0xf;
252			break;
253		case SET_LDO_VOLTAGE_CLDO_BURST:
254			addr = 4;
255			rc_shift = 5;
256			mask = 0xf;
257			break;
258		case SET_LDO_VOLTAGE_LNLDO1:
259			addr = 4;
260			rc_shift = 17;
261			mask = 0xf;
262			break;
263		default:
264			ASSERT(FALSE);
265			return;
266		}
267		break;
268	case BCM4330_CHIP_ID:
269		switch (ldo) {
270		case SET_LDO_VOLTAGE_CBUCK_PWM:
271			addr = 3;
272			rc_shift = 0;
273			mask = 0x1f;
274			break;
275		default:
276			ASSERT(FALSE);
277			break;
278		}
279		break;
280	case BCM4331_CHIP_ID:
281		switch (ldo) {
282		case  SET_LDO_VOLTAGE_PAREF:
283			addr = 1;
284			rc_shift = 0;
285			mask = 0xf;
286			break;
287		default:
288			ASSERT(FALSE);
289			break;
290		}
291		break;
292	default:
293		ASSERT(FALSE);
294		return;
295	}
296
297	shift = sr_cntl_shift + rc_shift;
298
299	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_addr),
300		~0, addr);
301	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, regcontrol_data),
302		mask << shift, (voltage & mask) << shift);
303}
304
305void
306si_pmu_paref_ldo_enable(si_t *sih, osl_t *osh, bool enable)
307{
308	uint ldo = 0;
309
310	ASSERT(sih->cccaps & CC_CAP_PMU);
311
312	switch (CHIPID(sih->chip)) {
313	case BCM4328_CHIP_ID:
314		ldo = RES4328_PA_REF_LDO;
315		break;
316	case BCM5354_CHIP_ID:
317		ldo = RES5354_PA_REF_LDO;
318		break;
319	case BCM4312_CHIP_ID:
320		ldo = RES4312_PA_REF_LDO;
321		break;
322	default:
323		return;
324	}
325
326	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask),
327	           PMURES_BIT(ldo), enable ? PMURES_BIT(ldo) : 0);
328}
329
330#if !defined(_CFE_) || defined(CFG_WL)
331/* d11 slow to fast clock transition time in slow clock cycles */
332#define D11SCC_SLOW2FAST_TRANSITION	2
333
334uint16
335BCMINITFN(si_pmu_fast_pwrup_delay)(si_t *sih, osl_t *osh)
336{
337	uint delay = PMU_MAX_TRANSITION_DLY;
338	chipcregs_t *cc;
339	uint origidx;
340
341	ASSERT(sih->cccaps & CC_CAP_PMU);
342
343	/* Remember original core before switch to chipc */
344	origidx = si_coreidx(sih);
345	cc = si_setcoreidx(sih, SI_CC_IDX);
346	ASSERT(cc != NULL);
347
348	switch (CHIPID(sih->chip)) {
349	case BCM4312_CHIP_ID:
350	case BCM4322_CHIP_ID:	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
351	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
352	case BCM43224_CHIP_ID:	case BCM43225_CHIP_ID:  case BCM43420_CHIP_ID:
353	case BCM43421_CHIP_ID:
354	case BCM43226_CHIP_ID:
355	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
356	case BCM43234_CHIP_ID:	case BCM43237_CHIP_ID:
357	case BCM4331_CHIP_ID:
358	case BCM43431_CHIP_ID:
359	case BCM43227_CHIP_ID:
360	case BCM43228_CHIP_ID:
361	case BCM43428_CHIP_ID:
362	case BCM6362_CHIP_ID:
363	case BCM4342_CHIP_ID:
364	case BCM4313_CHIP_ID:
365		delay = ISSIM_ENAB(sih) ? 70 : 3700;
366		break;
367	case BCM4328_CHIP_ID:
368		delay = 7000;
369		break;
370	case BCM4325_CHIP_ID:
371		if (ISSIM_ENAB(sih))
372			delay = 70;
373		else {
374			uint32 ilp = si_ilp_clock(sih);
375			delay = (si_pmu_res_uptime(sih, osh, cc, RES4325_HT_AVAIL) +
376			         D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
377			delay = (11 * delay) / 10;
378		}
379		break;
380	case BCM4329_CHIP_ID:
381		if (ISSIM_ENAB(sih))
382			delay = 70;
383		else {
384			uint32 ilp = si_ilp_clock(sih);
385			delay = (si_pmu_res_uptime(sih, osh, cc, RES4329_HT_AVAIL) +
386			         D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
387			delay = (11 * delay) / 10;
388		}
389		break;
390	case BCM4315_CHIP_ID:
391		if (ISSIM_ENAB(sih))
392			delay = 70;
393		else {
394			uint32 ilp = si_ilp_clock(sih);
395			delay = (si_pmu_res_uptime(sih, osh, cc, RES4315_HT_AVAIL) +
396			         D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
397			delay = (11 * delay) / 10;
398		}
399		break;
400	case BCM4319_CHIP_ID:
401		if (ISSIM_ENAB(sih))
402			delay = 70;
403		else {
404#ifdef BCMUSBDEV
405			/* For USB HT is always available, even durring IEEE PS,
406			* so need minimal delay
407			*/
408			delay = 100;
409#else /* BCMUSBDEV */
410			/* For SDIO, total delay in getting HT available */
411			/* Adjusted for uptime XTAL=672us, HTAVail=128us */
412			uint32 ilp = si_ilp_clock(sih);
413			delay = si_pmu_res_uptime(sih, osh, cc, RES4319_HT_AVAIL);
414			PMU_MSG(("si_ilp_clock (Hz): %u delay (ilp clks): %u\n", ilp, delay));
415			delay = (delay + D11SCC_SLOW2FAST_TRANSITION) * (1000000 / ilp);
416			PMU_MSG(("delay (us): %u\n", delay));
417			delay = (11 * delay) / 10;
418			PMU_MSG(("delay (us): %u\n", delay));
419			/* VDDIO_RF por delay = 3.4ms */
420			if (delay < 3400) delay = 3400;
421#endif /* BCMUSBDEV */
422		}
423		break;
424	case BCM4336_CHIP_ID:
425		if (ISSIM_ENAB(sih))
426			delay = 70;
427		else {
428			uint32 ilp = si_ilp_clock(sih);
429			delay = (si_pmu_res_uptime(sih, osh, cc, RES4336_HT_AVAIL) +
430			         D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
431			delay = (11 * delay) / 10;
432		}
433		break;
434	case BCM4330_CHIP_ID:
435		if (ISSIM_ENAB(sih))
436			delay = 70;
437		else {
438			uint32 ilp = si_ilp_clock(sih);
439			delay = (si_pmu_res_uptime(sih, osh, cc, RES4330_HT_AVAIL) +
440			         D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
441			delay = (11 * delay) / 10;
442		}
443		break;
444	default:
445		break;
446	}
447
448	/* PMU_MSG(("si_pmu_fast_pwrup_delay: chip %s rev %d delay %d\n",
449	 *        bcm_chipname(sih->chip, chn, 8), sih->chiprev, delay));
450	 */
451
452	/* Return to original core */
453	si_setcoreidx(sih, origidx);
454
455	return (uint16)delay;
456}
457#endif /* !_CFE_ || CFG_WL */
458
459uint32
460BCMATTACHFN(si_pmu_force_ilp)(si_t *sih, osl_t *osh, bool force)
461{
462	chipcregs_t *cc;
463	uint origidx;
464	uint32 oldpmucontrol;
465
466	ASSERT(sih->cccaps & CC_CAP_PMU);
467
468	/* Remember original core before switch to chipc */
469	origidx = si_coreidx(sih);
470	cc = si_setcoreidx(sih, SI_CC_IDX);
471	ASSERT(cc != NULL);
472
473	oldpmucontrol = R_REG(osh, &cc->pmucontrol);
474	if (force)
475		W_REG(osh, &cc->pmucontrol, oldpmucontrol &
476			~(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
477	else
478		W_REG(osh, &cc->pmucontrol, oldpmucontrol |
479			(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
480
481	/* Return to original core */
482	si_setcoreidx(sih, origidx);
483
484	return oldpmucontrol;
485}
486
487/* Setup resource up/down timers */
488typedef struct {
489	uint8 resnum;
490	uint16 updown;
491} pmu_res_updown_t;
492
493/* Change resource dependancies masks */
494typedef struct {
495	uint32 res_mask;		/* resources (chip specific) */
496	int8 action;			/* action */
497	uint32 depend_mask;		/* changes to the dependancies mask */
498	bool (*filter)(si_t *sih);	/* action is taken when filter is NULL or return TRUE */
499} pmu_res_depend_t;
500
501/* Resource dependancies mask change action */
502#define RES_DEPEND_SET		0	/* Override the dependancies mask */
503#define RES_DEPEND_ADD		1	/* Add to the  dependancies mask */
504#define RES_DEPEND_REMOVE	-1	/* Remove from the dependancies mask */
505
506#if !defined(_CFE_) || defined(CFG_WL)
507static const pmu_res_updown_t BCMATTACHDATA(bcm4328a0_res_updown)[] = {
508	{ RES4328_EXT_SWITCHER_PWM, 0x0101 },
509	{ RES4328_BB_SWITCHER_PWM, 0x1f01 },
510	{ RES4328_BB_SWITCHER_BURST, 0x010f },
511	{ RES4328_BB_EXT_SWITCHER_BURST, 0x0101 },
512	{ RES4328_ILP_REQUEST, 0x0202 },
513	{ RES4328_RADIO_SWITCHER_PWM, 0x0f01 },
514	{ RES4328_RADIO_SWITCHER_BURST, 0x0f01 },
515	{ RES4328_ROM_SWITCH, 0x0101 },
516	{ RES4328_PA_REF_LDO, 0x0f01 },
517	{ RES4328_RADIO_LDO, 0x0f01 },
518	{ RES4328_AFE_LDO, 0x0f01 },
519	{ RES4328_PLL_LDO, 0x0f01 },
520	{ RES4328_BG_FILTBYP, 0x0101 },
521	{ RES4328_TX_FILTBYP, 0x0101 },
522	{ RES4328_RX_FILTBYP, 0x0101 },
523	{ RES4328_XTAL_PU, 0x0101 },
524	{ RES4328_XTAL_EN, 0xa001 },
525	{ RES4328_BB_PLL_FILTBYP, 0x0101 },
526	{ RES4328_RF_PLL_FILTBYP, 0x0101 },
527	{ RES4328_BB_PLL_PU, 0x0701 }
528};
529
530static const pmu_res_depend_t BCMATTACHDATA(bcm4328a0_res_depend)[] = {
531	/* Adjust ILP request resource not to force ext/BB switchers into burst mode */
532	{
533		PMURES_BIT(RES4328_ILP_REQUEST),
534		RES_DEPEND_SET,
535		PMURES_BIT(RES4328_EXT_SWITCHER_PWM) | PMURES_BIT(RES4328_BB_SWITCHER_PWM),
536		NULL
537	}
538};
539
540static const pmu_res_updown_t BCMATTACHDATA(bcm4325a0_res_updown_qt)[] = {
541	{ RES4325_HT_AVAIL, 0x0300 },
542	{ RES4325_BBPLL_PWRSW_PU, 0x0101 },
543	{ RES4325_RFPLL_PWRSW_PU, 0x0101 },
544	{ RES4325_ALP_AVAIL, 0x0100 },
545	{ RES4325_XTAL_PU, 0x1000 },
546	{ RES4325_LNLDO1_PU, 0x0800 },
547	{ RES4325_CLDO_CBUCK_PWM, 0x0101 },
548	{ RES4325_CBUCK_PWM, 0x0803 }
549};
550
551static const pmu_res_updown_t BCMATTACHDATA(bcm4325a0_res_updown)[] = {
552	{ RES4325_XTAL_PU, 0x1501 }
553};
554
555static const pmu_res_depend_t BCMATTACHDATA(bcm4325a0_res_depend)[] = {
556	/* Adjust OTP PU resource dependencies - remove BB BURST */
557	{
558		PMURES_BIT(RES4325_OTP_PU),
559		RES_DEPEND_REMOVE,
560		PMURES_BIT(RES4325_BUCK_BOOST_BURST),
561		NULL
562	},
563	/* Adjust ALP/HT Avail resource dependencies - bring up BB along if it is used. */
564	{
565		PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_HT_AVAIL),
566		RES_DEPEND_ADD,
567		PMURES_BIT(RES4325_BUCK_BOOST_BURST) | PMURES_BIT(RES4325_BUCK_BOOST_PWM),
568		si_pmu_res_depfltr_bb
569	},
570	/* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
571	{
572		PMURES_BIT(RES4325_HT_AVAIL),
573		RES_DEPEND_ADD,
574		PMURES_BIT(RES4325_RX_PWRSW_PU) | PMURES_BIT(RES4325_TX_PWRSW_PU) |
575		PMURES_BIT(RES4325_LOGEN_PWRSW_PU) | PMURES_BIT(RES4325_AFE_PWRSW_PU),
576		NULL
577	},
578	/* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
579	{
580		PMURES_BIT(RES4325_ILP_REQUEST) | PMURES_BIT(RES4325_ABUCK_BURST) |
581		PMURES_BIT(RES4325_ABUCK_PWM) | PMURES_BIT(RES4325_LNLDO1_PU) |
582		PMURES_BIT(RES4325C1_LNLDO2_PU) | PMURES_BIT(RES4325_XTAL_PU) |
583		PMURES_BIT(RES4325_ALP_AVAIL) | PMURES_BIT(RES4325_RX_PWRSW_PU) |
584		PMURES_BIT(RES4325_TX_PWRSW_PU) | PMURES_BIT(RES4325_RFPLL_PWRSW_PU) |
585		PMURES_BIT(RES4325_LOGEN_PWRSW_PU) | PMURES_BIT(RES4325_AFE_PWRSW_PU) |
586		PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL),
587		RES_DEPEND_REMOVE,
588		PMURES_BIT(RES4325B0_CBUCK_LPOM) | PMURES_BIT(RES4325B0_CBUCK_BURST) |
589		PMURES_BIT(RES4325B0_CBUCK_PWM),
590		si_pmu_res_depfltr_ncb
591	}
592};
593
594static const pmu_res_updown_t BCMATTACHDATA(bcm4315a0_res_updown_qt)[] = {
595	{ RES4315_HT_AVAIL, 0x0101 },
596	{ RES4315_XTAL_PU, 0x0100 },
597	{ RES4315_LNLDO1_PU, 0x0100 },
598	{ RES4315_PALDO_PU, 0x0100 },
599	{ RES4315_CLDO_PU, 0x0100 },
600	{ RES4315_CBUCK_PWM, 0x0100 },
601	{ RES4315_CBUCK_BURST, 0x0100 },
602	{ RES4315_CBUCK_LPOM, 0x0100 }
603};
604
605static const pmu_res_updown_t BCMATTACHDATA(bcm4315a0_res_updown)[] = {
606	{ RES4315_XTAL_PU, 0x2501 }
607};
608
609static const pmu_res_depend_t BCMATTACHDATA(bcm4315a0_res_depend)[] = {
610	/* Adjust OTP PU resource dependencies - not need PALDO unless write */
611	{
612		PMURES_BIT(RES4315_OTP_PU),
613		RES_DEPEND_REMOVE,
614		PMURES_BIT(RES4315_PALDO_PU),
615		si_pmu_res_depfltr_npaldo
616	},
617	/* Adjust ALP/HT Avail resource dependencies - bring up PALDO along if it is used. */
618	{
619		PMURES_BIT(RES4315_ALP_AVAIL) | PMURES_BIT(RES4315_HT_AVAIL),
620		RES_DEPEND_ADD,
621		PMURES_BIT(RES4315_PALDO_PU),
622		si_pmu_res_depfltr_paldo
623	},
624	/* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
625	{
626		PMURES_BIT(RES4315_HT_AVAIL),
627		RES_DEPEND_ADD,
628		PMURES_BIT(RES4315_RX_PWRSW_PU) | PMURES_BIT(RES4315_TX_PWRSW_PU) |
629		PMURES_BIT(RES4315_LOGEN_PWRSW_PU) | PMURES_BIT(RES4315_AFE_PWRSW_PU),
630		NULL
631	},
632	/* Adjust ALL resource dependencies - remove CBUCK dependancies if it is not used. */
633	{
634		PMURES_BIT(RES4315_CLDO_PU) | PMURES_BIT(RES4315_ILP_REQUEST) |
635		PMURES_BIT(RES4315_LNLDO1_PU) | PMURES_BIT(RES4315_OTP_PU) |
636		PMURES_BIT(RES4315_LNLDO2_PU) | PMURES_BIT(RES4315_XTAL_PU) |
637		PMURES_BIT(RES4315_ALP_AVAIL) | PMURES_BIT(RES4315_RX_PWRSW_PU) |
638		PMURES_BIT(RES4315_TX_PWRSW_PU) | PMURES_BIT(RES4315_RFPLL_PWRSW_PU) |
639		PMURES_BIT(RES4315_LOGEN_PWRSW_PU) | PMURES_BIT(RES4315_AFE_PWRSW_PU) |
640		PMURES_BIT(RES4315_BBPLL_PWRSW_PU) | PMURES_BIT(RES4315_HT_AVAIL),
641		RES_DEPEND_REMOVE,
642		PMURES_BIT(RES4315_CBUCK_LPOM) | PMURES_BIT(RES4315_CBUCK_BURST) |
643		PMURES_BIT(RES4315_CBUCK_PWM),
644		si_pmu_res_depfltr_ncb
645	}
646};
647
648static const pmu_res_updown_t BCMATTACHDATA(bcm4329_res_updown)[] = {
649	{ RES4329_XTAL_PU, 0x1501 },
650	{ RES4329_PALDO_PU, 0x3501 }
651};
652
653static const pmu_res_depend_t BCMATTACHDATA(bcm4329_res_depend)[] = {
654	/* Make lnldo1 independant of CBUCK_PWM and CBUCK_BURST */
655	{
656		PMURES_BIT(RES4329_LNLDO1_PU),
657		RES_DEPEND_REMOVE,
658		PMURES_BIT(RES4329_CBUCK_PWM) | PMURES_BIT(RES4329_CBUCK_BURST),
659		NULL
660	},
661	{
662		PMURES_BIT(RES4329_CBUCK_BURST),
663		RES_DEPEND_ADD,
664		PMURES_BIT(RES4329_CBUCK_LPOM) | PMURES_BIT(RES4329_PALDO_PU),
665		NULL
666	},
667	{
668		PMURES_BIT(RES4329_BBPLL_PWRSW_PU),
669		RES_DEPEND_ADD,
670		PMURES_BIT(RES4329_RX_PWRSW_PU) | PMURES_BIT(RES4329_TX_PWRSW_PU) |
671		PMURES_BIT(RES4329_LOGEN_PWRSW_PU) | PMURES_BIT(RES4329_AFE_PWRSW_PU),
672		NULL
673	},
674	/* Adjust HT Avail resource dependencies */
675	{
676		PMURES_BIT(RES4329_HT_AVAIL),
677		RES_DEPEND_ADD,
678		PMURES_BIT(RES4329_PALDO_PU) |
679		PMURES_BIT(RES4329_RX_PWRSW_PU) | PMURES_BIT(RES4329_TX_PWRSW_PU) |
680		PMURES_BIT(RES4329_LOGEN_PWRSW_PU) | PMURES_BIT(RES4329_AFE_PWRSW_PU),
681		NULL
682	}
683};
684
685static const pmu_res_updown_t BCMATTACHDATA(bcm4319a0_res_updown_qt)[] = {
686	{ RES4319_HT_AVAIL, 0x0101 },
687	{ RES4319_XTAL_PU, 0x0100 },
688	{ RES4319_LNLDO1_PU, 0x0100 },
689	{ RES4319_PALDO_PU, 0x0100 },
690	{ RES4319_CLDO_PU, 0x0100 },
691	{ RES4319_CBUCK_PWM, 0x0100 },
692	{ RES4319_CBUCK_BURST, 0x0100 },
693	{ RES4319_CBUCK_LPOM, 0x0100 }
694};
695
696static const pmu_res_updown_t BCMATTACHDATA(bcm4319a0_res_updown)[] = {
697	{ RES4319_XTAL_PU, 0x3f01 }
698};
699
700static const pmu_res_depend_t BCMATTACHDATA(bcm4319a0_res_depend)[] = {
701	/* Adjust OTP PU resource dependencies - not need PALDO unless write */
702	{
703		PMURES_BIT(RES4319_OTP_PU),
704		RES_DEPEND_REMOVE,
705		PMURES_BIT(RES4319_PALDO_PU),
706		si_pmu_res_depfltr_npaldo
707	},
708	/* Adjust HT Avail resource dependencies - bring up PALDO along if it is used. */
709	{
710		PMURES_BIT(RES4319_HT_AVAIL),
711		RES_DEPEND_ADD,
712		PMURES_BIT(RES4319_PALDO_PU),
713		si_pmu_res_depfltr_paldo
714	},
715	/* Adjust HT Avail resource dependencies - bring up RF switches along with HT. */
716	{
717		PMURES_BIT(RES4319_HT_AVAIL),
718		RES_DEPEND_ADD,
719		PMURES_BIT(RES4319_RX_PWRSW_PU) | PMURES_BIT(RES4319_TX_PWRSW_PU) |
720		PMURES_BIT(RES4319_RFPLL_PWRSW_PU) |
721		PMURES_BIT(RES4319_LOGEN_PWRSW_PU) | PMURES_BIT(RES4319_AFE_PWRSW_PU),
722		NULL
723	}
724};
725
726static const pmu_res_updown_t BCMATTACHDATA(bcm4336a0_res_updown_qt)[] = {
727	{ RES4336_HT_AVAIL, 0x0101 },
728	{ RES4336_XTAL_PU, 0x0100 },
729	{ RES4336_CLDO_PU, 0x0100 },
730	{ RES4336_CBUCK_PWM, 0x0100 },
731	{ RES4336_CBUCK_BURST, 0x0100 },
732	{ RES4336_CBUCK_LPOM, 0x0100 }
733};
734
735static const pmu_res_updown_t BCMATTACHDATA(bcm4336a0_res_updown)[] = {
736	{ RES4336_HT_AVAIL, 0x0D01}
737};
738
739static const pmu_res_depend_t BCMATTACHDATA(bcm4336a0_res_depend)[] = {
740	/* Just a dummy entry for now */
741	{
742		PMURES_BIT(RES4336_RSVD),
743		RES_DEPEND_ADD,
744		0,
745		NULL
746	}
747};
748
749static const pmu_res_updown_t BCMATTACHDATA(bcm4330a0_res_updown_qt)[] = {
750	{ RES4330_HT_AVAIL, 0x0101 },
751	{ RES4330_XTAL_PU, 0x0100 },
752	{ RES4330_CLDO_PU, 0x0100 },
753	{ RES4330_CBUCK_PWM, 0x0100 },
754	{ RES4330_CBUCK_BURST, 0x0100 },
755	{ RES4330_CBUCK_LPOM, 0x0100 }
756};
757
758static const pmu_res_updown_t BCMATTACHDATA(bcm4330a0_res_updown)[] = {
759	{ RES4330_HT_AVAIL, 0x0e02}
760};
761
762static const pmu_res_depend_t BCMATTACHDATA(bcm4330a0_res_depend)[] = {
763	/* Just a dummy entry for now */
764	{
765		PMURES_BIT(RES4330_HT_AVAIL),
766		RES_DEPEND_ADD,
767		0,
768		NULL
769	}
770};
771
772/* TRUE if the power topology uses the buck boost to provide 3.3V to VDDIO_RF and WLAN PA */
773static bool
774BCMATTACHFN(si_pmu_res_depfltr_bb)(si_t *sih)
775{
776	return (sih->boardflags & BFL_BUCKBOOST) != 0;
777}
778
779/* TRUE if the power topology doesn't use the cbuck. Key on chiprev also if the chip is BCM4325. */
780static bool
781BCMATTACHFN(si_pmu_res_depfltr_ncb)(si_t *sih)
782{
783	if (CHIPID(sih->chip) == BCM4325_CHIP_ID)
784		return (CHIPREV(sih->chiprev) >= 2) && ((sih->boardflags & BFL_NOCBUCK) != 0);
785	return ((sih->boardflags & BFL_NOCBUCK) != 0);
786}
787
788/* TRUE if the power topology uses the PALDO */
789static bool
790BCMATTACHFN(si_pmu_res_depfltr_paldo)(si_t *sih)
791{
792	return (sih->boardflags & BFL_PALDO) != 0;
793}
794
795/* TRUE if the power topology doesn't use the PALDO */
796static bool
797BCMATTACHFN(si_pmu_res_depfltr_npaldo)(si_t *sih)
798{
799	return (sih->boardflags & BFL_PALDO) == 0;
800}
801
802#define BCM94325_BBVDDIOSD_BOARDS(sih) (sih->boardtype == BCM94325DEVBU_BOARD || \
803					sih->boardtype == BCM94325BGABU_BOARD)
804
805/* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
806static void
807si_pmu_res_masks(si_t *sih, uint32 *pmin, uint32 *pmax)
808{
809	uint32 min_mask = 0, max_mask = 0;
810	uint rsrcs;
811	char *val;
812
813	/* # resources */
814	rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
815
816	/* determine min/max rsrc masks */
817	switch (CHIPID(sih->chip)) {
818	case BCM4328_CHIP_ID:
819		/* Down to ILP request */
820		min_mask = PMURES_BIT(RES4328_EXT_SWITCHER_PWM) |
821		        PMURES_BIT(RES4328_BB_SWITCHER_PWM) |
822		        PMURES_BIT(RES4328_XTAL_EN);
823		/* Allow (but don't require) PLL to turn on */
824		max_mask = 0xfffff;
825		break;
826	case BCM5354_CHIP_ID:
827		/* Allow (but don't require) PLL to turn on */
828		max_mask = 0xfffff;
829		break;
830	case BCM4325_CHIP_ID:
831		ASSERT(CHIPREV(sih->chiprev) >= 2);
832		/* Minimum rsrcs to work in sleep mode */
833		if (!(sih->boardflags & BFL_NOCBUCK))
834			min_mask |= PMURES_BIT(RES4325B0_CBUCK_LPOM);
835		if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >>
836		     CST4325_PMUTOP_2B_SHIFT) == 1)
837			min_mask |= PMURES_BIT(RES4325B0_CLDO_PU);
838		if (!si_is_otp_disabled(sih))
839			min_mask |= PMURES_BIT(RES4325_OTP_PU);
840		/* Leave buck boost on in burst mode for certain boards */
841		if ((sih->boardflags & BFL_BUCKBOOST) && (BCM94325_BBVDDIOSD_BOARDS(sih)))
842			min_mask |= PMURES_BIT(RES4325_BUCK_BOOST_BURST);
843		/* Allow all resources to be turned on upon requests */
844		max_mask = ~(~0 << rsrcs);
845		break;
846	case BCM4312_CHIP_ID:
847		/* default min_mask = 0x80000cbb is wrong */
848		min_mask = 0xcbb;
849		/*
850		 * max_mask = 0x7fff;
851		 * pmu_res_updown_table_sz = 0;
852		 * pmu_res_depend_table_sz = 0;
853		 */
854		break;
855	case BCM4322_CHIP_ID:
856	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
857	case BCM4342_CHIP_ID:
858		if (CHIPREV(sih->chiprev) < 2) {
859			/* request ALP(can skip for A1) */
860			min_mask = PMURES_BIT(RES4322_RF_LDO) |
861			        PMURES_BIT(RES4322_XTAL_PU) |
862				PMURES_BIT(RES4322_ALP_AVAIL);
863			if (BUSTYPE(sih->bustype) == SI_BUS) {
864				min_mask += PMURES_BIT(RES4322_SI_PLL_ON) |
865					PMURES_BIT(RES4322_HT_SI_AVAIL) |
866					PMURES_BIT(RES4322_PHY_PLL_ON) |
867					PMURES_BIT(RES4322_OTP_PU) |
868					PMURES_BIT(RES4322_HT_PHY_AVAIL);
869				max_mask = 0x1ff;
870			}
871		}
872		break;
873	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
874	case BCM43224_CHIP_ID:	case BCM43225_CHIP_ID:	case BCM43421_CHIP_ID:
875	case BCM43226_CHIP_ID:  case BCM43420_CHIP_ID:
876	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
877	case BCM43234_CHIP_ID:	case BCM43237_CHIP_ID:
878	case BCM4331_CHIP_ID:   case BCM43431_CHIP_ID:
879	case BCM6362_CHIP_ID:
880		/* use chip default */
881		break;
882
883	case BCM4329_CHIP_ID:
884
885		/* Down to save the power. */
886		if (CHIPREV(sih->chiprev) >= 0x2) {
887			min_mask = PMURES_BIT(RES4329_CBUCK_LPOM) |
888				PMURES_BIT(RES4329_LNLDO1_PU) | PMURES_BIT(RES4329_CLDO_PU);
889		} else {
890			min_mask = PMURES_BIT(RES4329_CBUCK_LPOM) | PMURES_BIT(RES4329_CLDO_PU);
891		}
892		if (!si_is_otp_disabled(sih))
893			min_mask |= PMURES_BIT(RES4329_OTP_PU);
894		/* Allow (but don't require) PLL to turn on */
895		max_mask = 0x3ff63e;
896
897		break;
898	case BCM4315_CHIP_ID:
899		/* We only need a few resources to be kept on all the time */
900		if (!(sih->boardflags & BFL_NOCBUCK))
901			min_mask = PMURES_BIT(RES4315_CBUCK_LPOM);
902		min_mask |= PMURES_BIT(RES4315_CLDO_PU);
903		/* Allow everything else to be turned on upon requests */
904		max_mask = ~(~0 << rsrcs);
905		break;
906	case BCM4319_CHIP_ID:
907#ifdef  BCM_BOOTLOADER
908		/* Initialize to ResInitMode3 for bootloader */
909		min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
910			PMURES_BIT(RES4319_CBUCK_BURST) |
911			PMURES_BIT(RES4319_CBUCK_PWM) |
912			PMURES_BIT(RES4319_CLDO_PU) |
913			PMURES_BIT(RES4319_PALDO_PU) |
914			PMURES_BIT(RES4319_LNLDO1_PU) |
915			PMURES_BIT(RES4319_XTAL_PU) |
916			PMURES_BIT(RES4319_ALP_AVAIL) |
917			PMURES_BIT(RES4319_RFPLL_PWRSW_PU) |
918			PMURES_BIT(RES4319_BBPLL_PWRSW_PU) |
919			PMURES_BIT(RES4319_HT_AVAIL);
920#else
921		/* We only need a few resources to be kept on all the time */
922#ifdef BCMUSBDEV
923		/* For USB HT is always available, even durring IEEE PS, so RF switches are
924		* made independent of HT Avail and are by default on, but can be made off
925		* during IEEE PS by ucode (and then on)
926		*/
927		min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
928			PMURES_BIT(RES4319_CLDO_PU) |
929			PMURES_BIT(RES4319_RX_PWRSW_PU) | PMURES_BIT(RES4319_TX_PWRSW_PU) |
930			PMURES_BIT(RES4319_LOGEN_PWRSW_PU) | PMURES_BIT(RES4319_AFE_PWRSW_PU);
931#else
932		/* For SDIO RF switches are automatically made on off along with HT */
933		min_mask = PMURES_BIT(RES4319_CBUCK_LPOM) |
934			PMURES_BIT(RES4319_CLDO_PU);
935#endif
936#endif  /* BCM_BOOTLOADER */
937
938		/* Allow everything else to be turned on upon requests */
939		max_mask = ~(~0 << rsrcs);
940		break;
941	case BCM4336_CHIP_ID:
942		/* Down to save the power. */
943		min_mask = PMURES_BIT(RES4336_CBUCK_LPOM) | PMURES_BIT(RES4336_CLDO_PU) |
944			PMURES_BIT(RES4336_LDO3P3_PU) | PMURES_BIT(RES4336_OTP_PU) |
945			PMURES_BIT(RES4336_DIS_INT_RESET_PD);
946		/* Allow (but don't require) PLL to turn on */
947		max_mask = 0x1ffffff;
948		break;
949
950	case BCM4330_CHIP_ID:
951		/* Down to save the power. */
952		min_mask = PMURES_BIT(RES4330_CBUCK_LPOM) | PMURES_BIT(RES4330_CLDO_PU) |
953			PMURES_BIT(RES4330_DIS_INT_RESET_PD) | PMURES_BIT(RES4330_LDO3P3_PU) |
954			PMURES_BIT(RES4330_OTP_PU);
955		/* Allow (but don't require) PLL to turn on */
956		max_mask = 0xfffffff;
957		break;
958
959	case BCM4313_CHIP_ID:
960		min_mask = PMURES_BIT(RES4313_BB_PU_RSRC) |
961			PMURES_BIT(RES4313_XTAL_PU_RSRC) |
962			PMURES_BIT(RES4313_ALP_AVAIL_RSRC) |
963			PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC);
964		max_mask = 0xffff;
965		break;
966	default:
967		break;
968	}
969
970	/* Apply nvram override to min mask */
971	if ((val = getvar(NULL, "rmin")) != NULL) {
972		PMU_MSG(("Applying rmin=%s to min_mask\n", val));
973		min_mask = (uint32)bcm_strtoul(val, NULL, 0);
974	}
975	/* Apply nvram override to max mask */
976	if ((val = getvar(NULL, "rmax")) != NULL) {
977		PMU_MSG(("Applying rmax=%s to max_mask\n", val));
978		max_mask = (uint32)bcm_strtoul(val, NULL, 0);
979	}
980
981	*pmin = min_mask;
982	*pmax = max_mask;
983}
984#endif /* !_CFE_ || CFG_WL */
985
986/* initialize PMU resources */
987void
988BCMATTACHFN(si_pmu_res_init)(si_t *sih, osl_t *osh)
989{
990#if !defined(_CFE_) || defined(CFG_WL)
991	chipcregs_t *cc;
992	uint origidx;
993	const pmu_res_updown_t *pmu_res_updown_table = NULL;
994	uint pmu_res_updown_table_sz = 0;
995	const pmu_res_depend_t *pmu_res_depend_table = NULL;
996	uint pmu_res_depend_table_sz = 0;
997	uint32 min_mask = 0, max_mask = 0;
998	char name[8], *val;
999	uint i, rsrcs;
1000
1001	ASSERT(sih->cccaps & CC_CAP_PMU);
1002
1003	/* Remember original core before switch to chipc */
1004	origidx = si_coreidx(sih);
1005	cc = si_setcoreidx(sih, SI_CC_IDX);
1006	ASSERT(cc != NULL);
1007
1008	switch (CHIPID(sih->chip)) {
1009	case BCM4328_CHIP_ID:
1010		pmu_res_updown_table = bcm4328a0_res_updown;
1011		pmu_res_updown_table_sz = ARRAYSIZE(bcm4328a0_res_updown);
1012		pmu_res_depend_table = bcm4328a0_res_depend;
1013		pmu_res_depend_table_sz = ARRAYSIZE(bcm4328a0_res_depend);
1014		break;
1015	case BCM4325_CHIP_ID:
1016		/* Optimize resources up/down timers */
1017		if (ISSIM_ENAB(sih)) {
1018			pmu_res_updown_table = bcm4325a0_res_updown_qt;
1019			pmu_res_updown_table_sz = ARRAYSIZE(bcm4325a0_res_updown_qt);
1020		} else {
1021			pmu_res_updown_table = bcm4325a0_res_updown;
1022			pmu_res_updown_table_sz = ARRAYSIZE(bcm4325a0_res_updown);
1023		}
1024		/* Optimize resources dependancies */
1025		pmu_res_depend_table = bcm4325a0_res_depend;
1026		pmu_res_depend_table_sz = ARRAYSIZE(bcm4325a0_res_depend);
1027		break;
1028	case BCM4315_CHIP_ID:
1029		/* Optimize resources up/down timers */
1030		if (ISSIM_ENAB(sih)) {
1031			pmu_res_updown_table = bcm4315a0_res_updown_qt;
1032			pmu_res_updown_table_sz = ARRAYSIZE(bcm4315a0_res_updown_qt);
1033		}
1034		else {
1035			pmu_res_updown_table = bcm4315a0_res_updown;
1036			pmu_res_updown_table_sz = ARRAYSIZE(bcm4315a0_res_updown);
1037		}
1038		/* Optimize resources dependancies masks */
1039		pmu_res_depend_table = bcm4315a0_res_depend;
1040		pmu_res_depend_table_sz = ARRAYSIZE(bcm4315a0_res_depend);
1041		break;
1042	case BCM4329_CHIP_ID:
1043		/* Optimize resources up/down timers */
1044		if (ISSIM_ENAB(sih)) {
1045			pmu_res_updown_table = NULL;
1046			pmu_res_updown_table_sz = 0;
1047		} else {
1048			pmu_res_updown_table = bcm4329_res_updown;
1049			pmu_res_updown_table_sz = ARRAYSIZE(bcm4329_res_updown);
1050		}
1051		/* Optimize resources dependencies */
1052		pmu_res_depend_table = bcm4329_res_depend;
1053		pmu_res_depend_table_sz = ARRAYSIZE(bcm4329_res_depend);
1054		break;
1055
1056	case BCM4319_CHIP_ID:
1057		/* Optimize resources up/down timers */
1058		if (ISSIM_ENAB(sih)) {
1059			pmu_res_updown_table = bcm4319a0_res_updown_qt;
1060			pmu_res_updown_table_sz = ARRAYSIZE(bcm4319a0_res_updown_qt);
1061		}
1062		else {
1063			pmu_res_updown_table = bcm4319a0_res_updown;
1064			pmu_res_updown_table_sz = ARRAYSIZE(bcm4319a0_res_updown);
1065		}
1066		/* Optimize resources dependancies masks */
1067		pmu_res_depend_table = bcm4319a0_res_depend;
1068		pmu_res_depend_table_sz = ARRAYSIZE(bcm4319a0_res_depend);
1069		break;
1070
1071	case BCM4336_CHIP_ID:
1072		/* Optimize resources up/down timers */
1073		if (ISSIM_ENAB(sih)) {
1074			pmu_res_updown_table = bcm4336a0_res_updown_qt;
1075			pmu_res_updown_table_sz = ARRAYSIZE(bcm4336a0_res_updown_qt);
1076		}
1077		else {
1078			pmu_res_updown_table = bcm4336a0_res_updown;
1079			pmu_res_updown_table_sz = ARRAYSIZE(bcm4336a0_res_updown);
1080		}
1081		/* Optimize resources dependancies masks */
1082		pmu_res_depend_table = bcm4336a0_res_depend;
1083		pmu_res_depend_table_sz = ARRAYSIZE(bcm4336a0_res_depend);
1084		break;
1085
1086	case BCM4330_CHIP_ID:
1087		/* Optimize resources up/down timers */
1088		if (ISSIM_ENAB(sih)) {
1089			pmu_res_updown_table = bcm4330a0_res_updown_qt;
1090			pmu_res_updown_table_sz = ARRAYSIZE(bcm4330a0_res_updown_qt);
1091		}
1092		else {
1093			pmu_res_updown_table = bcm4330a0_res_updown;
1094			pmu_res_updown_table_sz = ARRAYSIZE(bcm4330a0_res_updown);
1095		}
1096		/* Optimize resources dependancies masks */
1097		pmu_res_depend_table = bcm4330a0_res_depend;
1098		pmu_res_depend_table_sz = ARRAYSIZE(bcm4330a0_res_depend);
1099		break;
1100	default:
1101		break;
1102	}
1103
1104	/* # resources */
1105	rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
1106
1107	/* Program up/down timers */
1108	while (pmu_res_updown_table_sz--) {
1109		ASSERT(pmu_res_updown_table != NULL);
1110		PMU_MSG(("Changing rsrc %d res_updn_timer to 0x%x\n",
1111		         pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
1112		         pmu_res_updown_table[pmu_res_updown_table_sz].updown));
1113		W_REG(osh, &cc->res_table_sel,
1114		      pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
1115		W_REG(osh, &cc->res_updn_timer,
1116		      pmu_res_updown_table[pmu_res_updown_table_sz].updown);
1117	}
1118	/* Apply nvram overrides to up/down timers */
1119	for (i = 0; i < rsrcs; i ++) {
1120		snprintf(name, sizeof(name), "r%dt", i);
1121		if ((val = getvar(NULL, name)) == NULL)
1122			continue;
1123		PMU_MSG(("Applying %s=%s to rsrc %d res_updn_timer\n", name, val, i));
1124		W_REG(osh, &cc->res_table_sel, (uint32)i);
1125		W_REG(osh, &cc->res_updn_timer, (uint32)bcm_strtoul(val, NULL, 0));
1126	}
1127
1128	/* Program resource dependencies table */
1129	while (pmu_res_depend_table_sz--) {
1130		ASSERT(pmu_res_depend_table != NULL);
1131		if (pmu_res_depend_table[pmu_res_depend_table_sz].filter != NULL &&
1132		    !(pmu_res_depend_table[pmu_res_depend_table_sz].filter)(sih))
1133			continue;
1134		for (i = 0; i < rsrcs; i ++) {
1135			if ((pmu_res_depend_table[pmu_res_depend_table_sz].res_mask &
1136			     PMURES_BIT(i)) == 0)
1137				continue;
1138			W_REG(osh, &cc->res_table_sel, i);
1139			switch (pmu_res_depend_table[pmu_res_depend_table_sz].action) {
1140			case RES_DEPEND_SET:
1141				PMU_MSG(("Changing rsrc %d res_dep_mask to 0x%x\n", i,
1142				    pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask));
1143				W_REG(osh, &cc->res_dep_mask,
1144				      pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
1145				break;
1146			case RES_DEPEND_ADD:
1147				PMU_MSG(("Adding 0x%x to rsrc %d res_dep_mask\n",
1148				    pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
1149				OR_REG(osh, &cc->res_dep_mask,
1150				       pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
1151				break;
1152			case RES_DEPEND_REMOVE:
1153				PMU_MSG(("Removing 0x%x from rsrc %d res_dep_mask\n",
1154				    pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
1155				AND_REG(osh, &cc->res_dep_mask,
1156				        ~pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask);
1157				break;
1158			default:
1159				ASSERT(0);
1160				break;
1161			}
1162		}
1163	}
1164	/* Apply nvram overrides to dependancies masks */
1165	for (i = 0; i < rsrcs; i ++) {
1166		snprintf(name, sizeof(name), "r%dd", i);
1167		if ((val = getvar(NULL, name)) == NULL)
1168			continue;
1169		PMU_MSG(("Applying %s=%s to rsrc %d res_dep_mask\n", name, val, i));
1170		W_REG(osh, &cc->res_table_sel, (uint32)i);
1171		W_REG(osh, &cc->res_dep_mask, (uint32)bcm_strtoul(val, NULL, 0));
1172	}
1173
1174	/* Determine min/max rsrc masks */
1175	si_pmu_res_masks(sih, &min_mask, &max_mask);
1176
1177	/* It is required to program max_mask first and then min_mask */
1178#ifdef BCM_BOOTLOADER
1179	if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
1180		min_mask |= R_REG(osh, &cc->min_res_mask);
1181		max_mask |= R_REG(osh, &cc->max_res_mask);
1182	}
1183#endif /* BCM_BOOTLOADER */
1184
1185	/* Program max resource mask */
1186#ifdef BCM_BOOTLOADER
1187	/* Apply nvram override to max mask */
1188	if ((val = getvar(NULL, "brmax")) != NULL) {
1189		PMU_MSG(("Applying brmax=%s to max_res_mask\n", val));
1190		max_mask = (uint32)bcm_strtoul(val, NULL, 0);
1191	}
1192#endif /* BCM_BOOTLOADER */
1193
1194	if (max_mask) {
1195		PMU_MSG(("Changing max_res_mask to 0x%x\n", max_mask));
1196		W_REG(osh, &cc->max_res_mask, max_mask);
1197	}
1198
1199	/* Program min resource mask */
1200#ifdef BCM_BOOTLOADER
1201	/* Apply nvram override to min mask */
1202	if ((val = getvar(NULL, "brmin")) != NULL) {
1203		PMU_MSG(("Applying brmin=%s to min_res_mask\n", val));
1204		min_mask = (uint32)bcm_strtoul(val, NULL, 0);
1205	}
1206#endif /* BCM_BOOTLOADER */
1207
1208	if (min_mask) {
1209		PMU_MSG(("Changing min_res_mask to 0x%x\n", min_mask));
1210		W_REG(osh, &cc->min_res_mask, min_mask);
1211	}
1212
1213	/* Add some delay; allow resources to come up and settle. */
1214	OSL_DELAY(2000);
1215
1216	/* Return to original core */
1217	si_setcoreidx(sih, origidx);
1218
1219#endif /* !_CFE_ || CFG_WL */
1220}
1221/* WAR for 4319 swctrl tri-state issue */
1222void
1223si_pmu_res_4319_swctrl_war(si_t *sih, osl_t *osh, bool enable)
1224{
1225	uint32 min_mask;
1226	chipcregs_t *cc;
1227	uint origidx;
1228	ASSERT(sih->cccaps & CC_CAP_PMU);
1229
1230	/* Remember original core before switch to chipc */
1231	origidx = si_coreidx(sih);
1232	cc = si_setcoreidx(sih, SI_CC_IDX);
1233	ASSERT(cc != NULL);
1234	min_mask = R_REG(osh, &cc->min_res_mask);
1235	if (enable)
1236	        W_REG(osh, &cc->min_res_mask,
1237	                min_mask | PMURES_BIT(RES4319_PALDO_PU));
1238	else
1239	        W_REG(osh, &cc->min_res_mask,
1240	                min_mask & ~PMURES_BIT(RES4319_PALDO_PU));
1241
1242	/* Return to original core */
1243	si_setcoreidx(sih, origidx);
1244}
1245
1246/* setup pll and query clock speed */
1247typedef struct {
1248	uint16	freq;
1249	uint8	xf;
1250	uint8	wbint;
1251	uint32	wbfrac;
1252} pmu0_xtaltab0_t;
1253
1254/* the following table is based on 880Mhz fvco */
1255static const pmu0_xtaltab0_t BCMINITDATA(pmu0_xtaltab0)[] = {
1256	{ 12000,	1,	73,	349525 },
1257	{ 13000,	2,	67,	725937 },
1258	{ 14400,	3,	61,	116508 },
1259	{ 15360,	4,	57,	305834 },
1260	{ 16200,	5,	54,	336579 },
1261	{ 16800,	6,	52,	399457 },
1262	{ 19200,	7,	45,	873813 },
1263	{ 19800,	8,	44,	466033 },
1264	{ 20000,	9,	44,	0 },
1265	{ 25000,	10,	70,	419430 },
1266	{ 26000,	11,	67,	725937 },
1267	{ 30000,	12,	58,	699050 },
1268	{ 38400,	13,	45,	873813 },
1269	{ 40000,	14,	45,	0 },
1270	{ 0,		0,	0,	0 }
1271};
1272
1273#ifdef BCMUSBDEV
1274#define	PMU0_XTAL0_DEFAULT	11
1275#else
1276#define PMU0_XTAL0_DEFAULT	8
1277#endif
1278
1279#ifdef BCMUSBDEV
1280/*
1281 * Set new backplane PLL clock frequency
1282 */
1283static void
1284BCMATTACHFN(si_pmu0_sbclk4328)(si_t *sih, int freq)
1285{
1286	uint32 tmp, oldmax, oldmin, origidx;
1287	chipcregs_t *cc;
1288
1289	/* Remember original core before switch to chipc */
1290	origidx = si_coreidx(sih);
1291	cc = si_setcoreidx(sih, SI_CC_IDX);
1292	ASSERT(cc);
1293
1294	/* Set new backplane PLL clock */
1295	W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
1296	tmp = R_REG(osh, &cc->pllcontrol_data);
1297	tmp &= ~(PMU0_PLL0_PC0_DIV_ARM_MASK);
1298	tmp |= freq << PMU0_PLL0_PC0_DIV_ARM_SHIFT;
1299	W_REG(osh, &cc->pllcontrol_data, tmp);
1300
1301	/* Power cycle BB_PLL_PU by disabling/enabling it to take on new freq */
1302	/* Disable PLL */
1303	oldmin = R_REG(osh, &cc->min_res_mask);
1304	oldmax = R_REG(osh, &cc->max_res_mask);
1305	W_REG(osh, &cc->min_res_mask, oldmin & ~PMURES_BIT(RES4328_BB_PLL_PU));
1306	W_REG(osh, &cc->max_res_mask, oldmax & ~PMURES_BIT(RES4328_BB_PLL_PU));
1307
1308	/* It takes over several hundred usec to re-enable the PLL since the
1309	 * sequencer state machines run on ILP clock. Set delay at 450us to be safe.
1310	 *
1311	 * Be sure PLL is powered down first before re-enabling it.
1312	 */
1313
1314	OSL_DELAY(PLL_DELAY);
1315	SPINWAIT((R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)), PLL_DELAY*3);
1316	if (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)) {
1317		/* If BB_PLL not powered down yet, new backplane PLL clock
1318		 *  may not take effect.
1319		 *
1320		 * Still early during bootup so no serial output here.
1321		 */
1322		PMU_ERROR(("Fatal: BB_PLL not power down yet!\n"));
1323		ASSERT(!(R_REG(osh, &cc->res_state) & PMURES_BIT(RES4328_BB_PLL_PU)));
1324	}
1325
1326	/* Enable PLL */
1327	W_REG(osh, &cc->max_res_mask, oldmax);
1328
1329	/* Return to original core */
1330	si_setcoreidx(sih, origidx);
1331}
1332#endif /* BCMUSBDEV */
1333
1334/* Set up PLL registers in the PMU as per the crystal speed.
1335 * Uses xtalfreq variable, or passed-in default.
1336 */
1337static void
1338BCMATTACHFN(si_pmu0_pllinit0)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal)
1339{
1340	uint32 tmp;
1341	const pmu0_xtaltab0_t *xt;
1342
1343	/* Find the frequency in the table */
1344	for (xt = pmu0_xtaltab0; xt->freq; xt ++)
1345		if (xt->freq == xtal)
1346			break;
1347	if (xt->freq == 0)
1348		xt = &pmu0_xtaltab0[PMU0_XTAL0_DEFAULT];
1349
1350	PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
1351
1352	/* Check current PLL state */
1353	tmp = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1354	        PCTL_XTALFREQ_SHIFT;
1355	if (tmp == xt->xf) {
1356		PMU_MSG(("PLL already programmed for %d.%d MHz\n",
1357		         xt->freq / 1000, xt->freq % 1000));
1358#ifdef BCMUSBDEV
1359		if (CHIPID(sih->chip) == BCM4328_CHIP_ID)
1360			si_pmu0_sbclk4328(sih, PMU0_PLL0_PC0_DIV_ARM_88MHZ);
1361#endif	/* BCMUSBDEV */
1362		return;
1363	}
1364
1365	if (tmp) {
1366		PMU_MSG(("Reprogramming PLL for %d.%d MHz (was %d.%dMHz)\n",
1367		         xt->freq / 1000, xt->freq % 1000,
1368		         pmu0_xtaltab0[tmp-1].freq / 1000, pmu0_xtaltab0[tmp-1].freq % 1000));
1369	} else {
1370		PMU_MSG(("Programming PLL for %d.%d MHz\n",
1371		         xt->freq / 1000, xt->freq % 1000));
1372	}
1373
1374	/* Make sure the PLL is off */
1375	switch (CHIPID(sih->chip)) {
1376	case BCM4328_CHIP_ID:
1377		AND_REG(osh, &cc->min_res_mask, ~PMURES_BIT(RES4328_BB_PLL_PU));
1378		AND_REG(osh, &cc->max_res_mask, ~PMURES_BIT(RES4328_BB_PLL_PU));
1379		break;
1380	case BCM5354_CHIP_ID:
1381		AND_REG(osh, &cc->min_res_mask, ~PMURES_BIT(RES5354_BB_PLL_PU));
1382		AND_REG(osh, &cc->max_res_mask, ~PMURES_BIT(RES5354_BB_PLL_PU));
1383		break;
1384	default:
1385		ASSERT(0);
1386	}
1387	SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS0_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1388	ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS0_HTAVAIL));
1389
1390	PMU_MSG(("Done masking\n"));
1391
1392	/* Write PDIV in pllcontrol[0] */
1393	W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
1394	tmp = R_REG(osh, &cc->pllcontrol_data);
1395	if (xt->freq >= PMU0_PLL0_PC0_PDIV_FREQ)
1396		tmp |= PMU0_PLL0_PC0_PDIV_MASK;
1397	else
1398		tmp &= ~PMU0_PLL0_PC0_PDIV_MASK;
1399	W_REG(osh, &cc->pllcontrol_data, tmp);
1400
1401	/* Write WILD in pllcontrol[1] */
1402	W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL1);
1403	tmp = R_REG(osh, &cc->pllcontrol_data);
1404	tmp = ((tmp & ~(PMU0_PLL0_PC1_WILD_INT_MASK | PMU0_PLL0_PC1_WILD_FRAC_MASK)) |
1405	       (((xt->wbint << PMU0_PLL0_PC1_WILD_INT_SHIFT) &
1406	         PMU0_PLL0_PC1_WILD_INT_MASK) |
1407	        ((xt->wbfrac << PMU0_PLL0_PC1_WILD_FRAC_SHIFT) &
1408	         PMU0_PLL0_PC1_WILD_FRAC_MASK)));
1409	if (xt->wbfrac == 0)
1410		tmp |= PMU0_PLL0_PC1_STOP_MOD;
1411	else
1412		tmp &= ~PMU0_PLL0_PC1_STOP_MOD;
1413	W_REG(osh, &cc->pllcontrol_data, tmp);
1414
1415	/* Write WILD in pllcontrol[2] */
1416	W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL2);
1417	tmp = R_REG(osh, &cc->pllcontrol_data);
1418	tmp = ((tmp & ~PMU0_PLL0_PC2_WILD_INT_MASK) |
1419	       ((xt->wbint >> PMU0_PLL0_PC2_WILD_INT_SHIFT) &
1420	        PMU0_PLL0_PC2_WILD_INT_MASK));
1421	W_REG(osh, &cc->pllcontrol_data, tmp);
1422
1423	PMU_MSG(("Done pll\n"));
1424
1425	/* Write XtalFreq. Set the divisor also. */
1426	tmp = R_REG(osh, &cc->pmucontrol);
1427	tmp = ((tmp & ~PCTL_ILP_DIV_MASK) |
1428	       (((((xt->freq + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) & PCTL_ILP_DIV_MASK));
1429	tmp = ((tmp & ~PCTL_XTALFREQ_MASK) |
1430	       ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK));
1431	W_REG(osh, &cc->pmucontrol, tmp);
1432}
1433
1434/* query alp/xtal clock frequency */
1435static uint32
1436BCMINITFN(si_pmu0_alpclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1437{
1438	const pmu0_xtaltab0_t *xt;
1439	uint32 xf;
1440
1441	/* Find the frequency in the table */
1442	xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1443	        PCTL_XTALFREQ_SHIFT;
1444	for (xt = pmu0_xtaltab0; xt->freq; xt++)
1445		if (xt->xf == xf)
1446			break;
1447	/* PLL must be configured before */
1448	ASSERT(xt->freq);
1449
1450	return xt->freq * 1000;
1451}
1452
1453#if !defined(_CFE_) || defined(CFG_WL)
1454/* query CPU clock frequency */
1455static uint32
1456BCMINITFN(si_pmu0_cpuclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1457{
1458	uint32 tmp, divarm;
1459	uint32 FVCO = FVCO_880;
1460
1461	/* Read divarm from pllcontrol[0] */
1462	W_REG(osh, &cc->pllcontrol_addr, PMU0_PLL0_PLLCTL0);
1463	tmp = R_REG(osh, &cc->pllcontrol_data);
1464	divarm = (tmp & PMU0_PLL0_PC0_DIV_ARM_MASK) >> PMU0_PLL0_PC0_DIV_ARM_SHIFT;
1465
1466
1467	/* Return ARM/SB clock */
1468	return FVCO / (divarm + PMU0_PLL0_PC0_DIV_ARM_BASE) * 1000;
1469}
1470
1471uint
1472si_pll_minresmask_reset(si_t *sih, osl_t *osh)
1473{
1474	chipcregs_t *cc;
1475	uint origidx;
1476	uint err = BCME_OK;
1477	/* Remember original core before switch to chipc */
1478	origidx = si_coreidx(sih);
1479	cc = si_setcoreidx(sih, SI_CC_IDX);
1480	ASSERT(cc != NULL);
1481
1482	switch (CHIPID(sih->chip)) {
1483		case BCM4313_CHIP_ID:
1484			/* write to min_res_mask 0x200d : clear min_rsrc_mask */
1485			AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1486			OSL_DELAY(100);
1487			/* write to max_res_mask 0xBFFF: clear max_rsrc_mask */
1488			AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1489			OSL_DELAY(100);
1490			/* write to max_res_mask 0xFFFF :set max_rsrc_mask */
1491			OR_REG(osh, &cc->max_res_mask, (PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1492
1493			break;
1494		default:
1495			PMU_ERROR(("%s: PLL reset not supported\n", __FUNCTION__));
1496			err = BCME_UNSUPPORTED;
1497			break;
1498	}
1499	/* Return to original core */
1500	si_setcoreidx(sih, origidx);
1501	return err;
1502}
1503
1504/* setup pll and query clock speed */
1505typedef struct {
1506	uint16	fref;
1507	uint8	xf;
1508	uint8	p1div;
1509	uint8	p2div;
1510	uint8	ndiv_int;
1511	uint32	ndiv_frac;
1512} pmu1_xtaltab0_t;
1513
1514static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880_4329)[] = {
1515	{12000,	1,	3,	22,	0x9,	0xFFFFEF},
1516	{13000,	2,	1,	6,	0xb,	0x483483},
1517	{14400,	3,	1,	10,	0xa,	0x1C71C7},
1518	{15360,	4,	1,	5,	0xb,	0x755555},
1519	{16200,	5,	1,	10,	0x5,	0x6E9E06},
1520	{16800,	6,	1,	10,	0x5,	0x3Cf3Cf},
1521	{19200,	7,	1,	4,	0xb,	0x755555},
1522	{19800,	8,	1,	11,	0x4,	0xA57EB},
1523	{20000,	9,	1,	11,	0x4,	0x0},
1524	{24000,	10,	3,	11,	0xa,	0x0},
1525	{25000,	11,	5,	16,	0xb,	0x0},
1526	{26000,	12,	1,	1,	0x21,	0xD89D89},
1527	{30000,	13,	3,	8,	0xb,	0x0},
1528	{37400,	14,	3,	1,	0x46,	0x969696},
1529	{38400,	15,	1,	1,	0x16,	0xEAAAAA},
1530	{40000,	16,	1,	2,	0xb,	0},
1531	{0,	0,	0,	0,	0,	0}
1532};
1533
1534/* the following table is based on 880Mhz fvco */
1535static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880)[] = {
1536	{12000,	1,	3,	22,	0x9,	0xFFFFEF},
1537	{13000,	2,	1,	6,	0xb,	0x483483},
1538	{14400,	3,	1,	10,	0xa,	0x1C71C7},
1539	{15360,	4,	1,	5,	0xb,	0x755555},
1540	{16200,	5,	1,	10,	0x5,	0x6E9E06},
1541	{16800,	6,	1,	10,	0x5,	0x3Cf3Cf},
1542	{19200,	7,	1,	4,	0xb,	0x755555},
1543	{19800,	8,	1,	11,	0x4,	0xA57EB},
1544	{20000,	9,	1,	11,	0x4,	0x0},
1545	{24000,	10,	3,	11,	0xa,	0x0},
1546	{25000,	11,	5,	16,	0xb,	0x0},
1547	{26000,	12,	1,	2,	0x10,	0xEC4EC4},
1548	{30000,	13,	3,	8,	0xb,	0x0},
1549	{33600,	14,	1,	2,	0xd,	0x186186},
1550	{38400,	15,	1,	2,	0xb,	0x755555},
1551	{40000,	16,	1,	2,	0xb,	0},
1552	{0,	0,	0,	0,	0,	0}
1553};
1554
1555#define PMU1_XTALTAB0_880_12000K	0
1556#define PMU1_XTALTAB0_880_13000K	1
1557#define PMU1_XTALTAB0_880_14400K	2
1558#define PMU1_XTALTAB0_880_15360K	3
1559#define PMU1_XTALTAB0_880_16200K	4
1560#define PMU1_XTALTAB0_880_16800K	5
1561#define PMU1_XTALTAB0_880_19200K	6
1562#define PMU1_XTALTAB0_880_19800K	7
1563#define PMU1_XTALTAB0_880_20000K	8
1564#define PMU1_XTALTAB0_880_24000K	9
1565#define PMU1_XTALTAB0_880_25000K	10
1566#define PMU1_XTALTAB0_880_26000K	11
1567#define PMU1_XTALTAB0_880_30000K	12
1568#define PMU1_XTALTAB0_880_37400K	13
1569#define PMU1_XTALTAB0_880_38400K	14
1570#define PMU1_XTALTAB0_880_40000K	15
1571
1572/* the following table is based on 1760Mhz fvco */
1573static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1760)[] = {
1574	{12000,	1,	3,	44,	0x9,	0xFFFFEF},
1575	{13000,	2,	1,	12,	0xb,	0x483483},
1576	{14400,	3,	1,	20,	0xa,	0x1C71C7},
1577	{15360,	4,	1,	10,	0xb,	0x755555},
1578	{16200,	5,	1,	20,	0x5,	0x6E9E06},
1579	{16800,	6,	1,	20,	0x5,	0x3Cf3Cf},
1580	{19200,	7,	1,	18,	0x5,	0x17B425},
1581	{19800,	8,	1,	22,	0x4,	0xA57EB},
1582	{20000,	9,	1,	22,	0x4,	0x0},
1583	{24000,	10,	3,	22,	0xa,	0x0},
1584	{25000,	11,	5,	32,	0xb,	0x0},
1585	{26000,	12,	1,	4,	0x10,	0xEC4EC4},
1586	{30000,	13,	3,	16,	0xb,	0x0},
1587	{38400,	14,	1,	10,	0x4,	0x955555},
1588	{40000,	15,	1,	4,	0xb,	0},
1589	{0,	0,	0,	0,	0,	0}
1590};
1591
1592/* table index */
1593#define PMU1_XTALTAB0_1760_12000K	0
1594#define PMU1_XTALTAB0_1760_13000K	1
1595#define PMU1_XTALTAB0_1760_14400K	2
1596#define PMU1_XTALTAB0_1760_15360K	3
1597#define PMU1_XTALTAB0_1760_16200K	4
1598#define PMU1_XTALTAB0_1760_16800K	5
1599#define PMU1_XTALTAB0_1760_19200K	6
1600#define PMU1_XTALTAB0_1760_19800K	7
1601#define PMU1_XTALTAB0_1760_20000K	8
1602#define PMU1_XTALTAB0_1760_24000K	9
1603#define PMU1_XTALTAB0_1760_25000K	10
1604#define PMU1_XTALTAB0_1760_26000K	11
1605#define PMU1_XTALTAB0_1760_30000K	12
1606#define PMU1_XTALTAB0_1760_38400K	13
1607#define PMU1_XTALTAB0_1760_40000K	14
1608
1609/* the following table is based on 1440Mhz fvco */
1610static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1440)[] = {
1611	{12000,	1,	1,	1,	0x78,	0x0	},
1612	{13000,	2,	1,	1,	0x6E,	0xC4EC4E},
1613	{14400,	3,	1,	1,	0x64,	0x0	},
1614	{15360,	4,	1,	1,	0x5D,	0xC00000},
1615	{16200,	5,	1,	1,	0x58,	0xE38E38},
1616	{16800,	6,	1,	1,	0x55,	0xB6DB6D},
1617	{19200,	7,	1,	1,	0x4B,	0	},
1618	{19800,	8,	1,	1,	0x48,	0xBA2E8B},
1619	{20000,	9,	1,	1,	0x48,	0x0	},
1620	{25000,	10,	1,	1,	0x39,	0x999999},
1621	{26000, 11,     1,      1,      0x37,   0x627627},
1622	{30000,	12,	1,	1,	0x30,	0x0	},
1623	{37400, 13,     2,      1,     	0x4D, 	0x15E76	},
1624	{38400, 13,     2,      1,     	0x4B, 	0x0	},
1625	{40000,	14,	2,	1,	0x48,	0x0	},
1626	{48000,	15,	2,	1,	0x3c,	0x0	},
1627	{0,	0,	0,	0,	0,	0}
1628};
1629
1630/* table index */
1631#define PMU1_XTALTAB0_1440_12000K	0
1632#define PMU1_XTALTAB0_1440_13000K	1
1633#define PMU1_XTALTAB0_1440_14400K	2
1634#define PMU1_XTALTAB0_1440_15360K	3
1635#define PMU1_XTALTAB0_1440_16200K	4
1636#define PMU1_XTALTAB0_1440_16800K	5
1637#define PMU1_XTALTAB0_1440_19200K	6
1638#define PMU1_XTALTAB0_1440_19800K	7
1639#define PMU1_XTALTAB0_1440_20000K	8
1640#define PMU1_XTALTAB0_1440_25000K	9
1641#define PMU1_XTALTAB0_1440_26000K	10
1642#define PMU1_XTALTAB0_1440_30000K	11
1643#define PMU1_XTALTAB0_1440_37400K	12
1644#define PMU1_XTALTAB0_1440_38400K	13
1645#define PMU1_XTALTAB0_1440_40000K	14
1646#define PMU1_XTALTAB0_1440_48000K	15
1647
1648#define XTAL_FREQ_24000MHZ		24000
1649#define XTAL_FREQ_30000MHZ		30000
1650#define XTAL_FREQ_37400MHZ		37400
1651#define XTAL_FREQ_48000MHZ		48000
1652
1653static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_960)[] = {
1654	{12000,   1,       1,      1,     0x50,   0x0     },
1655	{13000,   2,       1,      1,     0x49,   0xD89D89},
1656	{14400,   3,       1,      1,     0x42,   0xAAAAAA},
1657	{15360,   4,       1,      1,     0x3E,   0x800000},
1658	{16200,   5,       1,      1,     0x39,   0x425ED0},
1659	{16800,   6,       1,      1,     0x39,   0x249249},
1660	{19200,   7,       1,      1,     0x32,   0x0     },
1661	{19800,   8,       1,      1,     0x30,   0x7C1F07},
1662	{20000,   9,       1,      1,     0x30,   0x0     },
1663	{25000,   10,      1,      1,     0x26,   0x666666},
1664	{26000,   11,      1,      1,     0x24,   0xEC4EC4},
1665	{30000,   12,      1,      1,     0x20,   0x0     },
1666	{37400,   13,      2,      1,     0x33,   0x563EF9},
1667	{38400,   14,      2,      1,     0x32,   0x0	  },
1668	{40000,   15,      2,      1,     0x30,   0x0     },
1669	{48000,   16,      2,      1,     0x28,   0x0     },
1670	{0,	  0,	   0,	   0,	  0,	    0	  }
1671};
1672
1673/* table index */
1674#define PMU1_XTALTAB0_960_12000K	0
1675#define PMU1_XTALTAB0_960_13000K	1
1676#define PMU1_XTALTAB0_960_14400K	2
1677#define PMU1_XTALTAB0_960_15360K	3
1678#define PMU1_XTALTAB0_960_16200K	4
1679#define PMU1_XTALTAB0_960_16800K	5
1680#define PMU1_XTALTAB0_960_19200K	6
1681#define PMU1_XTALTAB0_960_19800K	7
1682#define PMU1_XTALTAB0_960_20000K	8
1683#define PMU1_XTALTAB0_960_25000K	9
1684#define PMU1_XTALTAB0_960_26000K	10
1685#define PMU1_XTALTAB0_960_30000K	11
1686#define PMU1_XTALTAB0_960_37400K	12
1687#define PMU1_XTALTAB0_960_38400K	13
1688#define PMU1_XTALTAB0_960_40000K	14
1689#define PMU1_XTALTAB0_960_48000K	15
1690
1691/* select xtal table for each chip */
1692static const pmu1_xtaltab0_t *
1693BCMINITFN(si_pmu1_xtaltab0)(si_t *sih)
1694{
1695	switch (CHIPID(sih->chip)) {
1696	case BCM4325_CHIP_ID:
1697		return pmu1_xtaltab0_880;
1698	case BCM4329_CHIP_ID:
1699		return pmu1_xtaltab0_880_4329;
1700	case BCM4315_CHIP_ID:
1701		return pmu1_xtaltab0_1760;
1702	case BCM4319_CHIP_ID:
1703		return pmu1_xtaltab0_1440;
1704	case BCM4336_CHIP_ID:
1705		return pmu1_xtaltab0_960;
1706	case BCM4330_CHIP_ID:
1707		if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1708			return pmu1_xtaltab0_960;
1709		else
1710			return pmu1_xtaltab0_1440;
1711	default:
1712		PMU_MSG(("si_pmu1_xtaltab0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1713		break;
1714	}
1715	ASSERT(0);
1716	return NULL;
1717}
1718
1719/* select default xtal frequency for each chip */
1720static const pmu1_xtaltab0_t *
1721BCMINITFN(si_pmu1_xtaldef0)(si_t *sih)
1722{
1723
1724	switch (CHIPID(sih->chip)) {
1725	case BCM4325_CHIP_ID:
1726		/* Default to 26000Khz */
1727		return &pmu1_xtaltab0_880[PMU1_XTALTAB0_880_26000K];
1728	case BCM4329_CHIP_ID:
1729		/* Default to 38400Khz */
1730		return &pmu1_xtaltab0_880_4329[PMU1_XTALTAB0_880_38400K];
1731	case BCM4315_CHIP_ID:
1732#ifdef BCMUSBDEV
1733		/* Default to 30000Khz */
1734		return &pmu1_xtaltab0_1760[PMU1_XTALTAB0_1760_30000K];
1735#else
1736		/* Default to 26000Khz */
1737		return &pmu1_xtaltab0_1760[PMU1_XTALTAB0_1760_26000K];
1738#endif
1739	case BCM4319_CHIP_ID:
1740		/* Default to 30000Khz */
1741		return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_30000K];
1742	case BCM4336_CHIP_ID:
1743		/* Default to 26000Khz */
1744		return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_26000K];
1745	case BCM4330_CHIP_ID:
1746		/* Default to 37400Khz */
1747		if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1748			return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_37400K];
1749		else
1750			return &pmu1_xtaltab0_1440[PMU1_XTALTAB0_1440_37400K];
1751	default:
1752		PMU_MSG(("si_pmu1_xtaldef0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1753		break;
1754	}
1755	ASSERT(0);
1756	return NULL;
1757}
1758
1759/* select default pll fvco for each chip */
1760static uint32
1761BCMINITFN(si_pmu1_pllfvco0)(si_t *sih)
1762{
1763
1764	switch (CHIPID(sih->chip)) {
1765	case BCM4325_CHIP_ID:
1766		return FVCO_880;
1767	case BCM4329_CHIP_ID:
1768		return FVCO_880;
1769	case BCM4315_CHIP_ID:
1770		return FVCO_1760;
1771	case BCM4319_CHIP_ID:
1772		return FVCO_1440;
1773	case BCM4336_CHIP_ID:
1774		return FVCO_960;
1775	case BCM4330_CHIP_ID:
1776		if (CST4330_CHIPMODE_SDIOD(sih->chipst))
1777			return FVCO_960;
1778		else
1779			return FVCO_1440;
1780	default:
1781		PMU_MSG(("si_pmu1_pllfvco0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
1782		break;
1783	}
1784	ASSERT(0);
1785	return 0;
1786}
1787
1788/* query alp/xtal clock frequency */
1789static uint32
1790BCMINITFN(si_pmu1_alpclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
1791{
1792	const pmu1_xtaltab0_t *xt;
1793	uint32 xf;
1794
1795	/* Find the frequency in the table */
1796	xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1797	        PCTL_XTALFREQ_SHIFT;
1798	for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
1799		if (xt->xf == xf)
1800			break;
1801	/* Could not find it so assign a default value */
1802	if (xt == NULL || xt->fref == 0)
1803		xt = si_pmu1_xtaldef0(sih);
1804	ASSERT(xt != NULL && xt->fref != 0);
1805
1806	return xt->fref * 1000;
1807}
1808#endif /* !_CFE_ || CFG_WL */
1809
1810void
1811si_pmu_minresmask_htavail_set(si_t *sih, osl_t *osh, bool set_clear)
1812{
1813	chipcregs_t *cc;
1814	uint origidx;
1815	/* Remember original core before switch to chipc */
1816	origidx = si_coreidx(sih);
1817	cc = si_setcoreidx(sih, SI_CC_IDX);
1818	ASSERT(cc != NULL);
1819
1820	if (!set_clear) {
1821		switch (CHIPID(sih->chip)) {
1822		case BCM4313_CHIP_ID:
1823			if ((cc->min_res_mask) & (PMURES_BIT(RES4313_HT_AVAIL_RSRC)))
1824				AND_REG(osh, &cc->min_res_mask,
1825					~(PMURES_BIT(RES4313_HT_AVAIL_RSRC)));
1826			break;
1827		default:
1828			break;
1829		}
1830	}
1831
1832	/* Return to original core */
1833	si_setcoreidx(sih, origidx);
1834}
1835
1836#if !defined(_CFE_) || defined(CFG_WL)
1837/* Set up PLL registers in the PMU as per the crystal speed.
1838 * XtalFreq field in pmucontrol register being 0 indicates the PLL
1839 * is not programmed and the h/w default is assumed to work, in which
1840 * case the xtal frequency is unknown to the s/w so we need to call
1841 * si_pmu1_xtaldef0() wherever it is needed to return a default value.
1842 */
1843static void
1844BCMATTACHFN(si_pmu1_pllinit0)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 xtal)
1845{
1846	const pmu1_xtaltab0_t *xt;
1847	uint32 tmp;
1848	uint32 buf_strength = 0;
1849	uint8 ndiv_mode = 1;
1850	uint32 FVCO = si_pmu1_pllfvco0(sih);
1851	uint8 dacrate;
1852
1853	FVCO = FVCO/1000;
1854
1855	/* Use h/w default PLL config */
1856	if (xtal == 0) {
1857		PMU_MSG(("Unspecified xtal frequency, skip PLL configuration\n"));
1858		return;
1859	}
1860
1861	/* Find the frequency in the table */
1862	for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
1863		if (xt->fref == xtal)
1864			break;
1865
1866	/* Check current PLL state, bail out if it has been programmed or
1867	 * we don't know how to program it.
1868	 */
1869	if (xt == NULL || xt->fref == 0) {
1870		PMU_MSG(("Unsupported xtal frequency %d.%d MHz, skip PLL configuration\n",
1871		         xtal / 1000, xtal % 1000));
1872		return;
1873	}
1874	/*  for 4319 bootloader already programs the PLL but bootloader does not program the
1875	    PLL4 and PLL5. So Skip this check for 4319
1876	*/
1877	if ((((R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
1878		PCTL_XTALFREQ_SHIFT) == xt->xf) &&
1879		!((CHIPID(sih->chip) == BCM4319_CHIP_ID) || (CHIPID(sih->chip) == BCM4330_CHIP_ID)))
1880	{
1881		PMU_MSG(("PLL already programmed for %d.%d MHz\n",
1882			xt->fref / 1000, xt->fref % 1000));
1883		return;
1884	}
1885
1886	PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
1887	PMU_MSG(("Programming PLL for %d.%d MHz\n", xt->fref / 1000, xt->fref % 1000));
1888
1889	switch (CHIPID(sih->chip)) {
1890	case BCM4325_CHIP_ID:
1891		/* Change the BBPLL drive strength to 2 for all channels */
1892		buf_strength = 0x222222;
1893		/* Make sure the PLL is off */
1894		AND_REG(osh, &cc->min_res_mask,
1895		        ~(PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL)));
1896		AND_REG(osh, &cc->max_res_mask,
1897		        ~(PMURES_BIT(RES4325_BBPLL_PWRSW_PU) | PMURES_BIT(RES4325_HT_AVAIL)));
1898		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1899		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1900		break;
1901	case BCM4329_CHIP_ID:
1902		/* Change the BBPLL drive strength to 8 for all channels */
1903		buf_strength = 0x888888;
1904		AND_REG(osh, &cc->min_res_mask,
1905		        ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) | PMURES_BIT(RES4329_HT_AVAIL)));
1906		AND_REG(osh, &cc->max_res_mask,
1907		        ~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) | PMURES_BIT(RES4329_HT_AVAIL)));
1908		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1909		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1910		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
1911		if (xt->fref == 38400)
1912			tmp = 0x200024C0;
1913		else if (xt->fref == 37400)
1914			tmp = 0x20004500;
1915		else if (xt->fref == 26000)
1916			tmp = 0x200024C0;
1917		else
1918			tmp = 0x200005C0; /* Chip Dflt Settings */
1919		W_REG(osh, &cc->pllcontrol_data, tmp);
1920		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
1921		tmp = R_REG(osh, &cc->pllcontrol_data) & PMU1_PLL0_PC5_CLK_DRV_MASK;
1922		if ((xt->fref == 38400) || (xt->fref == 37400) || (xt->fref == 26000))
1923			tmp |= 0x15;
1924		else
1925			tmp |= 0x25; /* Chip Dflt Settings */
1926		W_REG(osh, &cc->pllcontrol_data, tmp);
1927		break;
1928	case BCM4315_CHIP_ID:
1929		/* Change the BBPLL drive strength to 2 for all channels */
1930		buf_strength = 0x222222;
1931		/* Make sure the PLL is off */
1932		AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4315_HT_AVAIL)));
1933		AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4315_HT_AVAIL)));
1934		OSL_DELAY(100);
1935
1936		AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4315_BBPLL_PWRSW_PU)));
1937		AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4315_BBPLL_PWRSW_PU)));
1938		OSL_DELAY(100);
1939
1940		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1941		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1942		break;
1943
1944	case BCM4319_CHIP_ID:
1945		/* Change the BBPLL drive strength to 2 for all channels */
1946		buf_strength = 0x222222;
1947
1948		/* Make sure the PLL is off */
1949		/* WAR65104: Disable the HT_AVAIL resource first and then
1950		 * after a delay (more than downtime for HT_AVAIL) remove the
1951		 * BBPLL resource; backplane clock moves to ALP from HT.
1952		 */
1953		AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4319_HT_AVAIL)));
1954		AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4319_HT_AVAIL)));
1955
1956		OSL_DELAY(100);
1957		AND_REG(osh, &cc->min_res_mask, ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
1958		AND_REG(osh, &cc->max_res_mask, ~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
1959
1960		OSL_DELAY(100);
1961		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1962		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1963		break;
1964
1965	case BCM4336_CHIP_ID:
1966		AND_REG(osh, &cc->min_res_mask,
1967			~(PMURES_BIT(RES4336_HT_AVAIL) | PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
1968		AND_REG(osh, &cc->max_res_mask,
1969			~(PMURES_BIT(RES4336_HT_AVAIL) | PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
1970		OSL_DELAY(100);
1971		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1972		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1973		break;
1974
1975	case BCM4330_CHIP_ID:
1976		AND_REG(osh, &cc->min_res_mask,
1977			~(PMURES_BIT(RES4330_HT_AVAIL) | PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
1978		AND_REG(osh, &cc->max_res_mask,
1979			~(PMURES_BIT(RES4330_HT_AVAIL) | PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
1980		OSL_DELAY(100);
1981		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
1982		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
1983		break;
1984
1985	default:
1986		ASSERT(0);
1987	}
1988
1989	PMU_MSG(("Done masking\n"));
1990
1991	/* Write p1div and p2div to pllcontrol[0] */
1992	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
1993	tmp = R_REG(osh, &cc->pllcontrol_data) &
1994	        ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
1995	tmp |= ((xt->p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) |
1996	        ((xt->p2div << PMU1_PLL0_PC0_P2DIV_SHIFT) & PMU1_PLL0_PC0_P2DIV_MASK);
1997
1998	if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
1999		tmp &=  ~(PMU1_PLL0_PC0_BYPASS_SDMOD_MASK);
2000		if (!(xt->ndiv_frac))
2001			tmp |= (1<<(PMU1_PLL0_PC0_BYPASS_SDMOD_SHIFT));
2002		else
2003			tmp |= (0<<(PMU1_PLL0_PC0_BYPASS_SDMOD_SHIFT));
2004	}
2005
2006	W_REG(osh, &cc->pllcontrol_data, tmp);
2007
2008	if ((CHIPID(sih->chip) == BCM4330_CHIP_ID)) {
2009		if (CHIPREV(sih->chiprev) < 2)
2010			dacrate = 160;
2011		else {
2012			if (!(dacrate = (uint8)getintvar(NULL, "dacrate2g")))
2013				dacrate = 80;
2014		}
2015		si_pmu_set_4330_plldivs(sih, dacrate);
2016	}
2017
2018	if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (CHIPREV(sih->chiprev) == 0)) {
2019
2020		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2021		tmp = R_REG(osh, &cc->pllcontrol_data);
2022		tmp = tmp & (~DOT11MAC_880MHZ_CLK_DIVISOR_MASK);
2023		tmp = tmp | DOT11MAC_880MHZ_CLK_DIVISOR_VAL;
2024		W_REG(osh, &cc->pllcontrol_data, tmp);
2025	}
2026	if ((CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
2027		(CHIPID(sih->chip) == BCM4330_CHIP_ID))
2028		ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
2029	else
2030		ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MASH;
2031
2032	if ((CHIPID(sih->chip) == BCM4319_CHIP_ID)) {
2033		if (!(xt->ndiv_frac))
2034			ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_INT;
2035		else
2036			ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MFB;
2037#ifdef BCMQT
2038		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2039		tmp = 0x120F1010;
2040		W_REG(osh, &cc->pllcontrol_data, tmp);
2041#endif
2042	}
2043	/* Write ndiv_int and ndiv_mode to pllcontrol[2] */
2044	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
2045	tmp = R_REG(osh, &cc->pllcontrol_data) &
2046	        ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
2047	tmp |= ((xt->ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT) & PMU1_PLL0_PC2_NDIV_INT_MASK) |
2048	        ((ndiv_mode << PMU1_PLL0_PC2_NDIV_MODE_SHIFT) & PMU1_PLL0_PC2_NDIV_MODE_MASK);
2049	W_REG(osh, &cc->pllcontrol_data, tmp);
2050
2051	/* Write ndiv_frac to pllcontrol[3] */
2052	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
2053	tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
2054	tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
2055	        PMU1_PLL0_PC3_NDIV_FRAC_MASK);
2056	W_REG(osh, &cc->pllcontrol_data, tmp);
2057
2058	/* Writing to pllcontrol[4]  */
2059	if ((CHIPID(sih->chip) == BCM4319_CHIP_ID)) {
2060		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
2061		if (!(xt->ndiv_frac))
2062		        tmp = 0x200005c0;
2063		else
2064		        tmp = 0x202C2820;
2065
2066		tmp &= ~(PMU1_PLL0_PC4_KVCO_XS_MASK);
2067
2068		if (FVCO < 1600)
2069		        tmp |= (4<<PMU1_PLL0_PC4_KVCO_XS_SHIFT);
2070		else
2071		        tmp |= (7<<PMU1_PLL0_PC4_KVCO_XS_SHIFT);
2072
2073		W_REG(osh, &cc->pllcontrol_data, tmp);
2074	}
2075
2076	/* Write clock driving strength to pllcontrol[5] */
2077	if (buf_strength) {
2078		PMU_MSG(("Adjusting PLL buffer drive strength: %x\n", buf_strength));
2079
2080		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
2081		tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
2082		tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
2083
2084		if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
2085			tmp &= ~(PMU1_PLL0_PC5_VCO_RNG_MASK | PMU1_PLL0_PC5_PLL_CTRL_37_32_MASK);
2086			if (!(xt->ndiv_frac))
2087				tmp |= (0x25<<(PMU1_PLL0_PC5_PLL_CTRL_37_32_SHIFT));
2088			else
2089				tmp |= (0x15<<(PMU1_PLL0_PC5_PLL_CTRL_37_32_SHIFT));
2090
2091			if (FVCO < 1600)
2092				tmp |= (0x0<<(PMU1_PLL0_PC5_VCO_RNG_SHIFT));
2093			else
2094				tmp |= (0x1<<(PMU1_PLL0_PC5_VCO_RNG_SHIFT));
2095		}
2096		W_REG(osh, &cc->pllcontrol_data, tmp);
2097	}
2098
2099	PMU_MSG(("Done pll\n"));
2100
2101	/* to operate the 4319 usb in 24MHz/48MHz; chipcontrol[2][84:83] needs
2102	 * to be updated.
2103	 */
2104	if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && (xt->fref != XTAL_FREQ_30000MHZ)) {
2105		W_REG(osh, &cc->chipcontrol_addr, PMU1_PLL0_CHIPCTL2);
2106		tmp = R_REG(osh, &cc->chipcontrol_data) & ~CCTL_4319USB_XTAL_SEL_MASK;
2107		if (xt->fref == XTAL_FREQ_24000MHZ) {
2108			tmp |= (CCTL_4319USB_24MHZ_PLL_SEL << CCTL_4319USB_XTAL_SEL_SHIFT);
2109		} else if (xt->fref == XTAL_FREQ_48000MHZ) {
2110			tmp |= (CCTL_4319USB_48MHZ_PLL_SEL << CCTL_4319USB_XTAL_SEL_SHIFT);
2111		}
2112		W_REG(osh, &cc->chipcontrol_data, tmp);
2113	}
2114
2115	/* Flush deferred pll control registers writes */
2116	if (sih->pmurev >= 2)
2117		OR_REG(osh, &cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
2118
2119	/* Write XtalFreq. Set the divisor also. */
2120	tmp = R_REG(osh, &cc->pmucontrol) &
2121	        ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
2122	tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
2123	        PCTL_ILP_DIV_MASK) |
2124	       ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
2125
2126	if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && CHIPREV(sih->chiprev) == 0) {
2127		/* clear the htstretch before clearing HTReqEn */
2128		AND_REG(osh, &cc->clkstretch, ~CSTRETCH_HT);
2129		tmp &= ~PCTL_HT_REQ_EN;
2130	}
2131
2132	W_REG(osh, &cc->pmucontrol, tmp);
2133}
2134
2135/* query the CPU clock frequency */
2136static uint32
2137BCMINITFN(si_pmu1_cpuclk0)(si_t *sih, osl_t *osh, chipcregs_t *cc)
2138{
2139	uint32 tmp, m1div;
2140	uint32 FVCO = si_pmu1_pllfvco0(sih);
2141
2142	/* Read m1div from pllcontrol[1] */
2143	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
2144	tmp = R_REG(osh, &cc->pllcontrol_data);
2145	m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT;
2146
2147
2148	/* Return ARM/SB clock */
2149	return FVCO / m1div * 1000;
2150}
2151#endif /* !_CFE_ || CFG_WL */
2152
2153/* initialize PLL */
2154void
2155BCMATTACHFN(si_pmu_pll_init)(si_t *sih, osl_t *osh, uint xtalfreq)
2156{
2157	chipcregs_t *cc;
2158	uint origidx;
2159
2160	ASSERT(sih->cccaps & CC_CAP_PMU);
2161
2162	/* Remember original core before switch to chipc */
2163	origidx = si_coreidx(sih);
2164	cc = si_setcoreidx(sih, SI_CC_IDX);
2165	ASSERT(cc != NULL);
2166
2167	switch (CHIPID(sih->chip)) {
2168	case BCM5354_CHIP_ID:
2169		if (xtalfreq == 0)
2170			xtalfreq = 25000;
2171		si_pmu0_pllinit0(sih, osh, cc, xtalfreq);
2172		break;
2173#if !defined(_CFE_) || defined(CFG_WL)
2174	case BCM4328_CHIP_ID:
2175		si_pmu0_pllinit0(sih, osh, cc, xtalfreq);
2176		break;
2177	case BCM4325_CHIP_ID:
2178		si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
2179		break;
2180	case BCM4329_CHIP_ID:
2181		if (xtalfreq == 0)
2182			xtalfreq = 38400;
2183		si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
2184		break;
2185	case BCM4312_CHIP_ID:
2186		/* assume default works */
2187		break;
2188	case BCM4322_CHIP_ID:
2189	case BCM43221_CHIP_ID:
2190	case BCM43231_CHIP_ID:
2191	case BCM4342_CHIP_ID: {
2192		if (CHIPREV(sih->chiprev) == 0) {
2193			uint32 minmask, maxmask;
2194
2195			minmask = R_REG(osh, &cc->min_res_mask);
2196			maxmask = R_REG(osh, &cc->max_res_mask);
2197
2198			/* Make sure the PLL is off: clear bit 4 & 5 of min/max_res_mask */
2199			/* Have to remove HT Avail request before powering off PLL */
2200			AND_REG(osh, &cc->min_res_mask,	~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
2201			AND_REG(osh, &cc->max_res_mask,	~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
2202			SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
2203			AND_REG(osh, &cc->min_res_mask,	~(PMURES_BIT(RES4322_SI_PLL_ON)));
2204			AND_REG(osh, &cc->max_res_mask,	~(PMURES_BIT(RES4322_SI_PLL_ON)));
2205			OSL_DELAY(1000);
2206			ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
2207
2208
2209			W_REG(osh, &cc->pllcontrol_addr, PMU2_SI_PLL_PLLCTL);
2210			W_REG(osh, &cc->pllcontrol_data, 0x380005c0);
2211
2212
2213			OSL_DELAY(100);
2214			W_REG(osh, &cc->max_res_mask, maxmask);
2215			OSL_DELAY(100);
2216			W_REG(osh, &cc->min_res_mask, minmask);
2217			OSL_DELAY(100);
2218		}
2219
2220		break;
2221	}
2222	case BCM4313_CHIP_ID:
2223	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
2224	case BCM43224_CHIP_ID:	case BCM43225_CHIP_ID:  case BCM43420_CHIP_ID:
2225	case BCM43421_CHIP_ID:
2226	case BCM43226_CHIP_ID:
2227	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
2228	case BCM43234_CHIP_ID:	case BCM43237_CHIP_ID:
2229	case BCM4331_CHIP_ID:   case BCM43431_CHIP_ID:
2230	case BCM43227_CHIP_ID:
2231	case BCM43228_CHIP_ID:
2232	case BCM43428_CHIP_ID:
2233	case BCM6362_CHIP_ID:
2234		break;
2235	case BCM4315_CHIP_ID:
2236	case BCM4319_CHIP_ID:
2237	case BCM4336_CHIP_ID:
2238	case BCM4330_CHIP_ID:
2239		si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
2240		break;
2241#endif /* !_CFE_ || CFG_WL */
2242	default:
2243		PMU_MSG(("No PLL init done for chip %s rev %d pmurev %d\n",
2244		         bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
2245		break;
2246	}
2247
2248#ifdef BCMDBG_FORCEHT
2249	OR_REG(osh, &cc->clk_ctl_st, CCS_FORCEHT);
2250#endif
2251
2252	/* Return to original core */
2253	si_setcoreidx(sih, origidx);
2254}
2255
2256/* query alp/xtal clock frequency */
2257uint32
2258BCMINITFN(si_pmu_alp_clock)(si_t *sih, osl_t *osh)
2259{
2260	chipcregs_t *cc;
2261	uint origidx;
2262	uint32 clock = ALP_CLOCK;
2263
2264	ASSERT(sih->cccaps & CC_CAP_PMU);
2265
2266	/* Remember original core before switch to chipc */
2267	origidx = si_coreidx(sih);
2268	cc = si_setcoreidx(sih, SI_CC_IDX);
2269	ASSERT(cc != NULL);
2270
2271	switch (CHIPID(sih->chip)) {
2272	case BCM4328_CHIP_ID:
2273		clock = si_pmu0_alpclk0(sih, osh, cc);
2274		break;
2275	case BCM5354_CHIP_ID:
2276		clock = si_pmu0_alpclk0(sih, osh, cc);
2277		break;
2278#if !defined(_CFE_) || defined(CFG_WL)
2279	case BCM4325_CHIP_ID:
2280	case BCM4329_CHIP_ID:
2281	case BCM4315_CHIP_ID:
2282	case BCM4319_CHIP_ID:
2283	case BCM4336_CHIP_ID:
2284	case BCM4330_CHIP_ID:
2285		clock = si_pmu1_alpclk0(sih, osh, cc);
2286		break;
2287#endif /* !_CFE_ || CFG_WL */
2288	case BCM4312_CHIP_ID:
2289	case BCM4322_CHIP_ID:	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
2290	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
2291	case BCM43224_CHIP_ID:	case BCM43225_CHIP_ID:  case BCM43420_CHIP_ID:
2292	case BCM43421_CHIP_ID:
2293	case BCM43226_CHIP_ID:
2294	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
2295	case BCM43234_CHIP_ID:	case BCM43237_CHIP_ID:
2296	case BCM4331_CHIP_ID:   case BCM43431_CHIP_ID:
2297	case BCM43227_CHIP_ID:
2298	case BCM43228_CHIP_ID:
2299	case BCM43428_CHIP_ID:
2300	case BCM6362_CHIP_ID:
2301	case BCM4342_CHIP_ID:
2302	case BCM4716_CHIP_ID:
2303	case BCM4748_CHIP_ID:
2304	case BCM47162_CHIP_ID:
2305	case BCM4313_CHIP_ID:
2306	case BCM5357_CHIP_ID:
2307	case BCM4749_CHIP_ID:
2308	case BCM53572_CHIP_ID:
2309		/* always 20Mhz */
2310		clock = 20000 * 1000;
2311		break;
2312	case BCM5356_CHIP_ID:
2313	case BCM4706_CHIP_ID:
2314		/* always 25Mhz */
2315		clock = 25000 * 1000;
2316		break;
2317	default:
2318		PMU_MSG(("No ALP clock specified "
2319			"for chip %s rev %d pmurev %d, using default %d Hz\n",
2320			bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev, clock));
2321		break;
2322	}
2323
2324	/* Return to original core */
2325	si_setcoreidx(sih, origidx);
2326	return clock;
2327}
2328
2329/* Find the output of the "m" pll divider given pll controls that start with
2330 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
2331 */
2332static uint32
2333BCMINITFN(si_pmu5_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, uint m)
2334{
2335	uint32 tmp, div, ndiv, p1, p2, fc;
2336
2337	if ((pll0 & 3) || (pll0 > PMU4716_MAINPLL_PLL0)) {
2338		PMU_ERROR(("%s: Bad pll0: %d\n", __FUNCTION__, pll0));
2339		return 0;
2340	}
2341
2342
2343	/* Strictly there is an m5 divider, but I'm not sure we use it */
2344	if ((m == 0) || (m > 4)) {
2345		PMU_ERROR(("%s: Bad m divider: %d\n", __FUNCTION__, m));
2346		return 0;
2347	}
2348
2349	if ((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
2350		(CHIPID(sih->chip) == BCM4749_CHIP_ID)) {
2351		/* Detect failure in clock setting */
2352		if ((R_REG(osh, &cc->chipstatus) & 0x40000) != 0) {
2353			return (133 * 1000000);
2354		}
2355	}
2356
2357	W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_P1P2_OFF);
2358	(void)R_REG(osh, &cc->pllcontrol_addr);
2359	tmp = R_REG(osh, &cc->pllcontrol_data);
2360	p1 = (tmp & PMU5_PLL_P1_MASK) >> PMU5_PLL_P1_SHIFT;
2361	p2 = (tmp & PMU5_PLL_P2_MASK) >> PMU5_PLL_P2_SHIFT;
2362
2363	W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_M14_OFF);
2364	(void)R_REG(osh, &cc->pllcontrol_addr);
2365	tmp = R_REG(osh, &cc->pllcontrol_data);
2366	div = (tmp >> ((m - 1) * PMU5_PLL_MDIV_WIDTH)) & PMU5_PLL_MDIV_MASK;
2367
2368	W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_NM5_OFF);
2369	(void)R_REG(osh, &cc->pllcontrol_addr);
2370	tmp = R_REG(osh, &cc->pllcontrol_data);
2371	ndiv = (tmp & PMU5_PLL_NDIV_MASK) >> PMU5_PLL_NDIV_SHIFT;
2372
2373	/* Do calculation in Mhz */
2374	fc = si_pmu_alp_clock(sih, osh) / 1000000;
2375	fc = (p1 * ndiv * fc) / p2;
2376
2377	PMU_NONE(("%s: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, clock=%d\n",
2378	          __FUNCTION__, p1, p2, ndiv, ndiv, m, div, fc, fc / div));
2379
2380	/* Return clock in Hertz */
2381	return ((fc / div) * 1000000);
2382}
2383
2384static uint32
2385BCMINITFN(si_4706_pmu_clock)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint pll0, uint m)
2386{
2387	uint32  w;
2388	uint32 clock;
2389
2390	/* Strictly there is an m5 divider, but I'm not sure we use it */
2391	if ((m == 0) || (m > 4)) {
2392		PMU_ERROR(("%s: Bad m divider: %d\n", __FUNCTION__, m));
2393		return 0;
2394	}
2395
2396	/* Get N divider to determine CPU clock */
2397	W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU6_4706_PROCPLL_OFF);
2398	w = (R_REG(NULL, &cc->pllcontrol_data) & PMU6_4706_PROC_NDIV_INT_MASK) >>
2399		PMU6_4706_PROC_NDIV_INT_SHIFT;
2400	/* Fixed reference clock 25MHz and m = 2 */
2401	clock = w * 25000000 / 2;
2402	if (m == PMU5_MAINPLL_MEM)
2403		clock = clock / 2;
2404	else if (m == PMU5_MAINPLL_SI)
2405		clock = clock / 4;
2406
2407	return clock;
2408}
2409
2410/* query backplane clock frequency */
2411/* For designs that feed the same clock to both backplane
2412 * and CPU just return the CPU clock speed.
2413 */
2414uint32
2415BCMINITFN(si_pmu_si_clock)(si_t *sih, osl_t *osh)
2416{
2417	chipcregs_t *cc;
2418	uint origidx;
2419	uint32 clock = HT_CLOCK;
2420
2421	ASSERT(sih->cccaps & CC_CAP_PMU);
2422
2423	/* Remember original core before switch to chipc */
2424	origidx = si_coreidx(sih);
2425	cc = si_setcoreidx(sih, SI_CC_IDX);
2426	ASSERT(cc != NULL);
2427
2428	switch (CHIPID(sih->chip)) {
2429#if !defined(_CFE_) || defined(CFG_WL)
2430	case BCM4328_CHIP_ID:
2431		clock = si_pmu0_cpuclk0(sih, osh, cc);
2432		break;
2433	case BCM4325_CHIP_ID:
2434		clock = si_pmu1_cpuclk0(sih, osh, cc);
2435		break;
2436	case BCM4322_CHIP_ID:
2437	case BCM43221_CHIP_ID:	case BCM43231_CHIP_ID:
2438	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
2439	case BCM43224_CHIP_ID:  case BCM43420_CHIP_ID:
2440	case BCM43225_CHIP_ID:
2441	case BCM43421_CHIP_ID:
2442	case BCM43226_CHIP_ID:
2443	case BCM4331_CHIP_ID:   case BCM43431_CHIP_ID:
2444	case BCM6362_CHIP_ID:
2445	case BCM4342_CHIP_ID:
2446		/* 96MHz backplane clock */
2447		clock = 96000 * 1000;
2448		break;
2449	case BCM4329_CHIP_ID:
2450		if (CHIPREV(sih->chiprev) == 0)
2451			clock = 38400 * 1000;
2452		else
2453			clock = si_pmu1_cpuclk0(sih, osh, cc);
2454		break;
2455	case BCM4315_CHIP_ID:
2456	case BCM4319_CHIP_ID:
2457	case BCM4336_CHIP_ID:
2458	case BCM4330_CHIP_ID:
2459		clock = si_pmu1_cpuclk0(sih, osh, cc);
2460		break;
2461	case BCM4313_CHIP_ID:
2462		/* 80MHz backplane clock */
2463		clock = 80000 * 1000;
2464		break;
2465	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
2466	case BCM43234_CHIP_ID:
2467		clock = (cc->chipstatus & CST43236_BP_CLK) ? (120000 * 1000) : (96000 * 1000);
2468		break;
2469	case BCM43237_CHIP_ID:
2470		clock = (cc->chipstatus & CST43237_BP_CLK) ? (96000 * 1000) : (80000 * 1000);
2471		break;
2472#endif /* !_CFE_ || CFG_WL */
2473	case BCM5354_CHIP_ID:
2474		clock = 120000000;
2475		break;
2476	case BCM4716_CHIP_ID:
2477	case BCM4748_CHIP_ID:
2478	case BCM47162_CHIP_ID:
2479		clock = si_pmu5_clock(sih, osh, cc, PMU4716_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2480		break;
2481	case BCM5356_CHIP_ID:
2482		clock = si_pmu5_clock(sih, osh, cc, PMU5356_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2483		break;
2484	case BCM5357_CHIP_ID:
2485	case BCM4749_CHIP_ID:
2486		clock = si_pmu5_clock(sih, osh, cc, PMU5357_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2487		break;
2488	case BCM4706_CHIP_ID:
2489		clock = si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_SI);
2490		break;
2491	case BCM53572_CHIP_ID:
2492		clock = 75000000;
2493		break;
2494	default:
2495		PMU_MSG(("No backplane clock specified "
2496			"for chip %s rev %d pmurev %d, using default %d Hz\n",
2497			bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev, clock));
2498		break;
2499	}
2500
2501	/* Return to original core */
2502	si_setcoreidx(sih, origidx);
2503	return clock;
2504}
2505
2506/* query CPU clock frequency */
2507uint32
2508BCMINITFN(si_pmu_cpu_clock)(si_t *sih, osl_t *osh)
2509{
2510	chipcregs_t *cc;
2511	uint origidx;
2512	uint32 clock;
2513
2514	ASSERT(sih->cccaps & CC_CAP_PMU);
2515
2516	/* 5354 chip uses a non programmable PLL of frequency 240MHz */
2517	if (CHIPID(sih->chip) == BCM5354_CHIP_ID)
2518		return 240000000;
2519
2520	if (CHIPID(sih->chip) == BCM53572_CHIP_ID)
2521		return 300000000;
2522
2523	if ((sih->pmurev >= 5) &&
2524		!((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
2525		(CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
2526		(CHIPID(sih->chip) == BCM43234_CHIP_ID) ||
2527		(CHIPID(sih->chip) == BCM43235_CHIP_ID) ||
2528		(CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
2529		(CHIPID(sih->chip) == BCM43237_CHIP_ID) ||
2530		(CHIPID(sih->chip) == BCM43238_CHIP_ID) ||
2531		(CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
2532		(CHIPID(sih->chip) == BCM4330_CHIP_ID))) {
2533		uint pll;
2534
2535		switch (CHIPID(sih->chip)) {
2536		case BCM5356_CHIP_ID:
2537			pll = PMU5356_MAINPLL_PLL0;
2538			break;
2539		case BCM5357_CHIP_ID:
2540		case BCM4749_CHIP_ID:
2541			pll = PMU5357_MAINPLL_PLL0;
2542			break;
2543		default:
2544			pll = PMU4716_MAINPLL_PLL0;
2545			break;
2546		}
2547
2548		/* Remember original core before switch to chipc */
2549		origidx = si_coreidx(sih);
2550		cc = si_setcoreidx(sih, SI_CC_IDX);
2551		ASSERT(cc != NULL);
2552
2553		if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
2554			clock = si_4706_pmu_clock(sih, osh, cc,
2555				PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU);
2556		else
2557			clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_CPU);
2558
2559		/* Return to original core */
2560		si_setcoreidx(sih, origidx);
2561	} else
2562		clock = si_pmu_si_clock(sih, osh);
2563
2564	return clock;
2565}
2566
2567/* query memory clock frequency */
2568uint32
2569BCMINITFN(si_pmu_mem_clock)(si_t *sih, osl_t *osh)
2570{
2571	chipcregs_t *cc;
2572	uint origidx;
2573	uint32 clock;
2574
2575	ASSERT(sih->cccaps & CC_CAP_PMU);
2576
2577	if (CHIPID(sih->chip) == BCM53572_CHIP_ID)
2578		return 150000000;
2579
2580	if ((sih->pmurev >= 5) &&
2581		!((CHIPID(sih->chip) == BCM4329_CHIP_ID) ||
2582		(CHIPID(sih->chip) == BCM4319_CHIP_ID) ||
2583		(CHIPID(sih->chip) == BCM4330_CHIP_ID) ||
2584		(CHIPID(sih->chip) == BCM4336_CHIP_ID) ||
2585		(CHIPID(sih->chip) == BCM43234_CHIP_ID) ||
2586		(CHIPID(sih->chip) == BCM43235_CHIP_ID) ||
2587		(CHIPID(sih->chip) == BCM43236_CHIP_ID) ||
2588		(CHIPID(sih->chip) == BCM43237_CHIP_ID) ||
2589		(CHIPID(sih->chip) == BCM43238_CHIP_ID) ||
2590	0)) {
2591		uint pll;
2592
2593		switch (CHIPID(sih->chip)) {
2594		case BCM5356_CHIP_ID:
2595			pll = PMU5356_MAINPLL_PLL0;
2596			break;
2597		case BCM5357_CHIP_ID:
2598		case BCM4749_CHIP_ID:
2599			pll = PMU5357_MAINPLL_PLL0;
2600			break;
2601		default:
2602			pll = PMU4716_MAINPLL_PLL0;
2603			break;
2604		}
2605
2606		/* Remember original core before switch to chipc */
2607		origidx = si_coreidx(sih);
2608		cc = si_setcoreidx(sih, SI_CC_IDX);
2609		ASSERT(cc != NULL);
2610
2611		if (CHIPID(sih->chip) == BCM4706_CHIP_ID)
2612			clock = si_4706_pmu_clock(sih, osh, cc,
2613				PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_MEM);
2614		else
2615			clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_MEM);
2616
2617		/* Return to original core */
2618		si_setcoreidx(sih, origidx);
2619	} else {
2620		clock = si_pmu_si_clock(sih, osh);
2621	}
2622
2623	return clock;
2624}
2625
2626/* Measure ILP clock frequency */
2627#define ILP_CALC_DUR	10	/* ms, make sure 1000 can be divided by it. */
2628
2629static uint32 ilpcycles_per_sec = 0;
2630
2631uint32
2632BCMINITFN(si_pmu_ilp_clock)(si_t *sih, osl_t *osh)
2633{
2634	if (ISSIM_ENAB(sih))
2635		return ILP_CLOCK;
2636
2637	if (ilpcycles_per_sec == 0) {
2638		uint32 start, end, delta;
2639		uint32 origidx = si_coreidx(sih);
2640		chipcregs_t *cc = si_setcoreidx(sih, SI_CC_IDX);
2641		ASSERT(cc != NULL);
2642		start = R_REG(osh, &cc->pmutimer);
2643		OSL_DELAY(ILP_CALC_DUR * 1000);
2644		end = R_REG(osh, &cc->pmutimer);
2645		delta = end - start;
2646		ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
2647		si_setcoreidx(sih, origidx);
2648	}
2649
2650	return ilpcycles_per_sec;
2651}
2652
2653/* SDIO Pad drive strength to select value mappings */
2654typedef struct {
2655	uint8 strength;			/* Pad Drive Strength in mA */
2656	uint8 sel;			/* Chip-specific select value */
2657} sdiod_drive_str_t;
2658
2659/* SDIO Drive Strength to sel value table for PMU Rev 1 */
2660static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab1)[] = {
2661	{4, 0x2},
2662	{2, 0x3},
2663	{1, 0x0},
2664	{0, 0x0} };
2665
2666/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
2667static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab2)[] = {
2668	{12, 0x7},
2669	{10, 0x6},
2670	{8, 0x5},
2671	{6, 0x4},
2672	{4, 0x2},
2673	{2, 0x1},
2674	{0, 0x0} };
2675
2676/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
2677static const sdiod_drive_str_t BCMINITDATA(sdiod_drive_strength_tab3)[] = {
2678	{32, 0x7},
2679	{26, 0x6},
2680	{22, 0x5},
2681	{16, 0x4},
2682	{12, 0x3},
2683	{8, 0x2},
2684	{4, 0x1},
2685	{0, 0x0} };
2686
2687#define SDIOD_DRVSTR_KEY(chip, pmu)	(((chip) << 16) | (pmu))
2688
2689void
2690BCMINITFN(si_sdiod_drive_strength_init)(si_t *sih, osl_t *osh, uint32 drivestrength)
2691{
2692	chipcregs_t *cc;
2693	uint origidx, intr_val = 0;
2694	sdiod_drive_str_t *str_tab = NULL;
2695	uint32 str_mask = 0;
2696	uint32 str_shift = 0;
2697
2698	if (!(sih->cccaps & CC_CAP_PMU)) {
2699		return;
2700	}
2701
2702	/* Remember original core before switch to chipc */
2703	cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
2704
2705	switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) {
2706	case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
2707		str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1;
2708		str_mask = 0x30000000;
2709		str_shift = 28;
2710		break;
2711	case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
2712	case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
2713	case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4):
2714	case SDIOD_DRVSTR_KEY(BCM4319_CHIP_ID, 7):
2715		str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2;
2716		str_mask = 0x00003800;
2717		str_shift = 11;
2718		break;
2719	case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
2720		str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3;
2721		str_mask = 0x00003800;
2722		str_shift = 11;
2723		break;
2724
2725	default:
2726		PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
2727		         bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev));
2728
2729		break;
2730	}
2731
2732	if (str_tab != NULL) {
2733		uint32 drivestrength_sel = 0;
2734		uint32 cc_data_temp;
2735		int i;
2736
2737		for (i = 0; str_tab[i].strength != 0; i ++) {
2738			if (drivestrength >= str_tab[i].strength) {
2739				drivestrength_sel = str_tab[i].sel;
2740				break;
2741			}
2742		}
2743
2744		W_REG(osh, &cc->chipcontrol_addr, 1);
2745		cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
2746		cc_data_temp &= ~str_mask;
2747		drivestrength_sel <<= str_shift;
2748		cc_data_temp |= drivestrength_sel;
2749		W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
2750
2751		PMU_MSG(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
2752		         drivestrength, cc_data_temp));
2753	}
2754
2755	/* Return to original core */
2756	si_restore_core(sih, origidx, intr_val);
2757}
2758
2759/* initialize PMU */
2760void
2761BCMATTACHFN(si_pmu_init)(si_t *sih, osl_t *osh)
2762{
2763	chipcregs_t *cc;
2764	uint origidx;
2765
2766	ASSERT(sih->cccaps & CC_CAP_PMU);
2767
2768	/* Remember original core before switch to chipc */
2769	origidx = si_coreidx(sih);
2770	cc = si_setcoreidx(sih, SI_CC_IDX);
2771	ASSERT(cc != NULL);
2772
2773	if (sih->pmurev == 1)
2774		AND_REG(osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
2775	else if (sih->pmurev >= 2)
2776		OR_REG(osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT);
2777
2778#if !defined(_CFE_) || defined(CFG_WL)
2779	if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 2)) {
2780		/* Fix for 4329b0 bad LPOM state. */
2781		W_REG(osh, &cc->regcontrol_addr, 2);
2782		OR_REG(osh, &cc->regcontrol_data, 0x100);
2783
2784		W_REG(osh, &cc->regcontrol_addr, 3);
2785		OR_REG(osh, &cc->regcontrol_data, 0x4);
2786	}
2787
2788	if (CHIPID(sih->chip) == BCM4319_CHIP_ID) {
2789		/* Limiting the PALDO spike during init time */
2790		si_pmu_regcontrol(sih, 2, 0x00000007, 0x00000005);
2791	}
2792#endif /* !_CFE_ || CFG_WL */
2793
2794	/* Return to original core */
2795	si_setcoreidx(sih, origidx);
2796}
2797
2798#if !defined(_CFE_) || defined(CFG_WL)
2799/* Return up time in ILP cycles for the given resource. */
2800static uint
2801BCMINITFN(si_pmu_res_uptime)(si_t *sih, osl_t *osh, chipcregs_t *cc, uint8 rsrc)
2802{
2803	uint32 deps;
2804	uint up, i, dup, dmax;
2805	uint32 min_mask = 0, max_mask = 0;
2806
2807	/* uptime of resource 'rsrc' */
2808	W_REG(osh, &cc->res_table_sel, rsrc);
2809	up = (R_REG(osh, &cc->res_updn_timer) >> 8) & 0xff;
2810
2811	/* direct dependancies of resource 'rsrc' */
2812	deps = si_pmu_res_deps(sih, osh, cc, PMURES_BIT(rsrc), FALSE);
2813	for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
2814		if (!(deps & PMURES_BIT(i)))
2815			continue;
2816		deps &= ~si_pmu_res_deps(sih, osh, cc, PMURES_BIT(i), TRUE);
2817	}
2818	si_pmu_res_masks(sih, &min_mask, &max_mask);
2819	deps &= ~min_mask;
2820
2821	/* max uptime of direct dependancies */
2822	dmax = 0;
2823	for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
2824		if (!(deps & PMURES_BIT(i)))
2825			continue;
2826		dup = si_pmu_res_uptime(sih, osh, cc, (uint8)i);
2827		if (dmax < dup)
2828			dmax = dup;
2829	}
2830
2831	PMU_MSG(("si_pmu_res_uptime: rsrc %u uptime %u(deps 0x%08x uptime %u)\n",
2832	         rsrc, up, deps, dmax));
2833
2834	return up + dmax + PMURES_UP_TRANSITION;
2835}
2836
2837/* Return dependancies (direct or all/indirect) for the given resources */
2838static uint32
2839si_pmu_res_deps(si_t *sih, osl_t *osh, chipcregs_t *cc, uint32 rsrcs, bool all)
2840{
2841	uint32 deps = 0;
2842	uint32 i;
2843
2844	for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
2845		if (!(rsrcs & PMURES_BIT(i)))
2846			continue;
2847		W_REG(osh, &cc->res_table_sel, i);
2848		deps |= R_REG(osh, &cc->res_dep_mask);
2849	}
2850
2851	return !all ? deps : (deps ? (deps | si_pmu_res_deps(sih, osh, cc, deps, TRUE)) : 0);
2852}
2853
2854/* power up/down OTP through PMU resources */
2855void
2856si_pmu_otp_power(si_t *sih, osl_t *osh, bool on)
2857{
2858	chipcregs_t *cc;
2859	uint origidx;
2860	uint32 rsrcs = 0;	/* rsrcs to turn on/off OTP power */
2861
2862	ASSERT(sih->cccaps & CC_CAP_PMU);
2863
2864	/* Don't do anything if OTP is disabled */
2865	if (si_is_otp_disabled(sih)) {
2866		PMU_MSG(("si_pmu_otp_power: OTP is disabled\n"));
2867		return;
2868	}
2869
2870	/* Remember original core before switch to chipc */
2871	origidx = si_coreidx(sih);
2872	cc = si_setcoreidx(sih, SI_CC_IDX);
2873	ASSERT(cc != NULL);
2874
2875	switch (CHIPID(sih->chip)) {
2876	case BCM4322_CHIP_ID:
2877	case BCM43221_CHIP_ID:
2878	case BCM43231_CHIP_ID:
2879	case BCM4342_CHIP_ID:
2880		rsrcs = PMURES_BIT(RES4322_OTP_PU);
2881		break;
2882	case BCM4325_CHIP_ID:
2883		rsrcs = PMURES_BIT(RES4325_OTP_PU);
2884		break;
2885	case BCM4315_CHIP_ID:
2886		rsrcs = PMURES_BIT(RES4315_OTP_PU);
2887		break;
2888	case BCM4329_CHIP_ID:
2889		rsrcs = PMURES_BIT(RES4329_OTP_PU);
2890		break;
2891	case BCM4319_CHIP_ID:
2892		rsrcs = PMURES_BIT(RES4319_OTP_PU);
2893		break;
2894	case BCM4336_CHIP_ID:
2895		rsrcs = PMURES_BIT(RES4336_OTP_PU);
2896		break;
2897	case BCM4330_CHIP_ID:
2898		rsrcs = PMURES_BIT(RES4330_OTP_PU);
2899		break;
2900	default:
2901		break;
2902	}
2903
2904	if (rsrcs != 0) {
2905		uint32 otps;
2906
2907		/* Figure out the dependancies (exclude min_res_mask) */
2908		uint32 deps = si_pmu_res_deps(sih, osh, cc, rsrcs, TRUE);
2909		uint32 min_mask = 0, max_mask = 0;
2910		si_pmu_res_masks(sih, &min_mask, &max_mask);
2911		deps &= ~min_mask;
2912		/* Turn on/off the power */
2913		if (on) {
2914			PMU_MSG(("Adding rsrc 0x%x to min_res_mask\n", rsrcs | deps));
2915			OR_REG(osh, &cc->min_res_mask, (rsrcs | deps));
2916			OSL_DELAY(1000);
2917			SPINWAIT(!(R_REG(osh, &cc->res_state) & rsrcs), PMU_MAX_TRANSITION_DLY);
2918			ASSERT(R_REG(osh, &cc->res_state) & rsrcs);
2919		}
2920		else {
2921			PMU_MSG(("Removing rsrc 0x%x from min_res_mask\n", rsrcs | deps));
2922			AND_REG(osh, &cc->min_res_mask, ~(rsrcs | deps));
2923		}
2924
2925		SPINWAIT((((otps = R_REG(osh, &cc->otpstatus)) & OTPS_READY) !=
2926			(on ? OTPS_READY : 0)), 100);
2927		ASSERT((otps & OTPS_READY) == (on ? OTPS_READY : 0));
2928		if ((otps & OTPS_READY) != (on ? OTPS_READY : 0))
2929			PMU_MSG(("OTP ready bit not %s after wait\n", (on ? "ON" : "OFF")));
2930	}
2931
2932	/* Return to original core */
2933	si_setcoreidx(sih, origidx);
2934}
2935
2936void
2937si_pmu_rcal(si_t *sih, osl_t *osh)
2938{
2939	chipcregs_t *cc;
2940	uint origidx;
2941	uint rcal_done, BT_out_of_reset;
2942
2943	ASSERT(sih->cccaps & CC_CAP_PMU);
2944
2945	/* Remember original core before switch to chipc */
2946	origidx = si_coreidx(sih);
2947	cc = si_setcoreidx(sih, SI_CC_IDX);
2948	ASSERT(cc != NULL);
2949
2950	switch (CHIPID(sih->chip)) {
2951	case BCM4325_CHIP_ID: {
2952		uint8 rcal_code;
2953		uint32 val;
2954
2955		/* Kick RCal */
2956		W_REG(osh, &cc->chipcontrol_addr, 1);
2957
2958		/* Power Down RCAL Block */
2959		AND_REG(osh, &cc->chipcontrol_data, ~0x04);
2960
2961		/* Check if RCAL is already done by BT */
2962		rcal_done = ((R_REG(osh, &cc->chipstatus)) & 0x8) >> 3;
2963
2964		/* If RCAL already done, note that BT is out of reset */
2965		if (rcal_done == 1) {
2966			BT_out_of_reset = 1;
2967		} else {
2968			BT_out_of_reset = 0;
2969		}
2970
2971		/* Power Up RCAL block */
2972		OR_REG(osh, &cc->chipcontrol_data, 0x04);
2973
2974		/* Wait for completion */
2975		SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08), 10 * 1000 * 1000);
2976		ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
2977
2978		if (BT_out_of_reset) {
2979			rcal_code = 0x6;
2980		} else {
2981			/* Drop the LSB to convert from 5 bit code to 4 bit code */
2982			rcal_code =  (uint8)(R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
2983		}
2984
2985		PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
2986			R_REG(osh, &cc->chipstatus), rcal_code));
2987
2988		/* Write RCal code into pmu_vreg_ctrl[32:29] */
2989		W_REG(osh, &cc->regcontrol_addr, 0);
2990		val = R_REG(osh, &cc->regcontrol_data) & ~((uint32)0x07 << 29);
2991		val |= (uint32)(rcal_code & 0x07) << 29;
2992		W_REG(osh, &cc->regcontrol_data, val);
2993		W_REG(osh, &cc->regcontrol_addr, 1);
2994		val = R_REG(osh, &cc->regcontrol_data) & ~(uint32)0x01;
2995		val |= (uint32)((rcal_code >> 3) & 0x01);
2996		W_REG(osh, &cc->regcontrol_data, val);
2997
2998		/* Write RCal code into pmu_chip_ctrl[33:30] */
2999		W_REG(osh, &cc->chipcontrol_addr, 0);
3000		val = R_REG(osh, &cc->chipcontrol_data) & ~((uint32)0x03 << 30);
3001		val |= (uint32)(rcal_code & 0x03) << 30;
3002		W_REG(osh, &cc->chipcontrol_data, val);
3003		W_REG(osh, &cc->chipcontrol_addr, 1);
3004		val = R_REG(osh, &cc->chipcontrol_data) & ~(uint32)0x03;
3005		val |= (uint32)((rcal_code >> 2) & 0x03);
3006		W_REG(osh, &cc->chipcontrol_data, val);
3007
3008		/* Set override in pmu_chip_ctrl[29] */
3009		W_REG(osh, &cc->chipcontrol_addr, 0);
3010		OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
3011
3012		/* Power off RCal block */
3013		W_REG(osh, &cc->chipcontrol_addr, 1);
3014		AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3015
3016		break;
3017	}
3018	case BCM4329_CHIP_ID: {
3019		uint8 rcal_code;
3020		uint32 val;
3021
3022		/* Kick RCal */
3023		W_REG(osh, &cc->chipcontrol_addr, 1);
3024
3025		/* Power Down RCAL Block */
3026		AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3027
3028		/* Power Up RCAL block */
3029		OR_REG(osh, &cc->chipcontrol_data, 0x04);
3030
3031		/* Wait for completion */
3032		SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08), 10 * 1000 * 1000);
3033		ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
3034
3035		/* Drop the LSB to convert from 5 bit code to 4 bit code */
3036		rcal_code =  (uint8)(R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
3037
3038		PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
3039			R_REG(osh, &cc->chipstatus), rcal_code));
3040
3041		/* Write RCal code into pmu_vreg_ctrl[32:29] */
3042		W_REG(osh, &cc->regcontrol_addr, 0);
3043		val = R_REG(osh, &cc->regcontrol_data) & ~((uint32)0x07 << 29);
3044		val |= (uint32)(rcal_code & 0x07) << 29;
3045		W_REG(osh, &cc->regcontrol_data, val);
3046		W_REG(osh, &cc->regcontrol_addr, 1);
3047		val = R_REG(osh, &cc->regcontrol_data) & ~(uint32)0x01;
3048		val |= (uint32)((rcal_code >> 3) & 0x01);
3049		W_REG(osh, &cc->regcontrol_data, val);
3050
3051		/* Write RCal code into pmu_chip_ctrl[33:30] */
3052		W_REG(osh, &cc->chipcontrol_addr, 0);
3053		val = R_REG(osh, &cc->chipcontrol_data) & ~((uint32)0x03 << 30);
3054		val |= (uint32)(rcal_code & 0x03) << 30;
3055		W_REG(osh, &cc->chipcontrol_data, val);
3056		W_REG(osh, &cc->chipcontrol_addr, 1);
3057		val = R_REG(osh, &cc->chipcontrol_data) & ~(uint32)0x03;
3058		val |= (uint32)((rcal_code >> 2) & 0x03);
3059		W_REG(osh, &cc->chipcontrol_data, val);
3060
3061		/* Set override in pmu_chip_ctrl[29] */
3062		W_REG(osh, &cc->chipcontrol_addr, 0);
3063		OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
3064
3065		/* Power off RCal block */
3066		W_REG(osh, &cc->chipcontrol_addr, 1);
3067		AND_REG(osh, &cc->chipcontrol_data, ~0x04);
3068
3069		break;
3070	}
3071	default:
3072		break;
3073	}
3074
3075	/* Return to original core */
3076	si_setcoreidx(sih, origidx);
3077}
3078
3079void
3080si_pmu_spuravoid(si_t *sih, osl_t *osh, uint8 spuravoid)
3081{
3082	chipcregs_t *cc;
3083	uint origidx, intr_val;
3084	uint32 tmp = 0;
3085
3086	/* Remember original core before switch to chipc */
3087	cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
3088	ASSERT(cc != NULL);
3089
3090	/* force the HT off  */
3091	if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
3092		tmp = R_REG(osh, &cc->max_res_mask);
3093		tmp &= ~RES4336_HT_AVAIL;
3094		W_REG(osh, &cc->max_res_mask, tmp);
3095		/* wait for the ht to really go away */
3096		SPINWAIT(((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0), 10000);
3097		ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0);
3098	}
3099
3100	/* update the pll changes */
3101	si_pmu_spuravoid_pllupdate(sih, cc, osh, spuravoid);
3102
3103	/* enable HT back on  */
3104	if (CHIPID(sih->chip) == BCM4336_CHIP_ID) {
3105		tmp = R_REG(osh, &cc->max_res_mask);
3106		tmp |= RES4336_HT_AVAIL;
3107		W_REG(osh, &cc->max_res_mask, tmp);
3108	}
3109
3110	/* Return to original core */
3111	si_restore_core(sih, origidx, intr_val);
3112}
3113
3114static void
3115si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, osl_t *osh, uint8 spuravoid)
3116{
3117	uint32 tmp = 0;
3118	uint8 phypll_offset = 0;
3119	uint8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5};
3120	uint8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc};
3121
3122	switch (CHIPID(sih->chip)) {
3123	case BCM5357_CHIP_ID:   case BCM4749_CHIP_ID:
3124	case BCM43235_CHIP_ID:	case BCM43236_CHIP_ID:	case BCM43238_CHIP_ID:
3125	case BCM43234_CHIP_ID:	case BCM43237_CHIP_ID:
3126	case BCM6362_CHIP_ID:	case BCM53572_CHIP_ID:
3127
3128		if  ((CHIPID(sih->chip) == BCM6362_CHIP_ID) && (sih->chiprev == 0)) {
3129			/* 6362a0 (same clks as 4322[4-6]) */
3130			if (spuravoid == 1) {
3131				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3132				W_REG(osh, &cc->pllcontrol_data, 0x11500010);
3133				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3134				W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
3135				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3136				W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3137				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3138				W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3139				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3140				W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
3141				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3142				W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3143			} else {
3144				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3145				W_REG(osh, &cc->pllcontrol_data, 0x11100010);
3146				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3147				W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
3148				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3149				W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3150				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3151				W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3152				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3153				W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3154				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3155				W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3156			}
3157
3158		} else {
3159			/* 5357[ab]0, 43236[ab]0, and 6362b0 */
3160
3161			/* BCM5357 needs to touch PLL1_PLLCTL[02],so offset PLL0_PLLCTL[02] by 6 */
3162			phypll_offset = ((CHIPID(sih->chip) == BCM5357_CHIP_ID) ||
3163				(CHIPID(sih->chip) == BCM4749_CHIP_ID) ||
3164				(CHIPID(sih->chip) == BCM53572_CHIP_ID)) ? 6 : 0;
3165
3166			/* RMW only the P1 divider */
3167			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0 + phypll_offset);
3168			tmp = R_REG(osh, &cc->pllcontrol_data);
3169			tmp &= (~(PMU1_PLL0_PC0_P1DIV_MASK));
3170			tmp |= (bcm5357_bcm43236_p1div[spuravoid] << PMU1_PLL0_PC0_P1DIV_SHIFT);
3171			W_REG(osh, &cc->pllcontrol_data, tmp);
3172
3173			/* RMW only the int feedback divider */
3174			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2 + phypll_offset);
3175			tmp = R_REG(osh, &cc->pllcontrol_data);
3176			tmp &= ~(PMU1_PLL0_PC2_NDIV_INT_MASK);
3177			tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << PMU1_PLL0_PC2_NDIV_INT_SHIFT;
3178			W_REG(osh, &cc->pllcontrol_data, tmp);
3179		}
3180
3181		tmp = 1 << 10;
3182		break;
3183
3184	case BCM4331_CHIP_ID:
3185	case BCM43431_CHIP_ID:
3186		if (ISSIM_ENAB(sih)) {
3187			if (spuravoid == 2) {
3188				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3189				W_REG(osh, &cc->pllcontrol_data, 0x00000002);
3190			} else if (spuravoid == 1) {
3191				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3192				W_REG(osh, &cc->pllcontrol_data, 0x00000001);
3193			} else {
3194				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3195				W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3196			}
3197		} else {
3198			if (spuravoid == 2) {
3199				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3200				W_REG(osh, &cc->pllcontrol_data, 0x11500014);
3201				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3202				W_REG(osh, &cc->pllcontrol_data, 0x0FC00a08);
3203			} else if (spuravoid == 1) {
3204				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3205				W_REG(osh, &cc->pllcontrol_data, 0x11500014);
3206				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3207				W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3208			} else {
3209				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3210				W_REG(osh, &cc->pllcontrol_data, 0x11100014);
3211				W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3212				W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3213			}
3214		}
3215		tmp = 1 << 10;
3216		break;
3217
3218	case BCM43224_CHIP_ID:	case BCM43225_CHIP_ID:	case BCM43421_CHIP_ID:
3219	case BCM43226_CHIP_ID:
3220		if (spuravoid == 1) {
3221			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3222			W_REG(osh, &cc->pllcontrol_data, 0x11500010);
3223			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3224			W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
3225			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3226			W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3227			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3228			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3229			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3230			W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
3231			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3232			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3233		} else {
3234			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3235			W_REG(osh, &cc->pllcontrol_data, 0x11100010);
3236			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3237			W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
3238			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3239			W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3240			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3241			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3242			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3243			W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3244			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3245			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3246		}
3247		tmp = 1 << 10;
3248		break;
3249
3250	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
3251	case BCM43420_CHIP_ID:
3252		if (spuravoid == 1) {
3253			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3254			W_REG(osh, &cc->pllcontrol_data, 0x11500008);
3255			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3256			W_REG(osh, &cc->pllcontrol_data, 0x0C000C06);
3257			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3258			W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
3259			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3260			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3261			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3262			W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
3263			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3264			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3265		} else {
3266			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3267			W_REG(osh, &cc->pllcontrol_data, 0x11100008);
3268			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3269			W_REG(osh, &cc->pllcontrol_data, 0x0c000c06);
3270			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3271			W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3272			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3273			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3274			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3275			W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3276			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3277			W_REG(osh, &cc->pllcontrol_data, 0x88888855);
3278		}
3279
3280		tmp = 1 << 10;
3281		break;
3282
3283	case BCM4716_CHIP_ID:
3284	case BCM4748_CHIP_ID:
3285	case BCM47162_CHIP_ID:
3286		if (spuravoid == 1) {
3287			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3288			W_REG(osh, &cc->pllcontrol_data, 0x11500060);
3289			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3290			W_REG(osh, &cc->pllcontrol_data, 0x080C0C06);
3291			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3292			W_REG(osh, &cc->pllcontrol_data, 0x0F600000);
3293			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3294			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3295			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3296			W_REG(osh, &cc->pllcontrol_data, 0x2001E924);
3297			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3298			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3299		} else {
3300			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3301			W_REG(osh, &cc->pllcontrol_data, 0x11100060);
3302			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3303			W_REG(osh, &cc->pllcontrol_data, 0x080c0c06);
3304			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3305			W_REG(osh, &cc->pllcontrol_data, 0x03000000);
3306			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3307			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3308			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3309			W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3310			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3311			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3312		}
3313
3314		tmp = 3 << 9;
3315		break;
3316
3317	case BCM4322_CHIP_ID:
3318	case BCM43221_CHIP_ID:
3319	case BCM43231_CHIP_ID:
3320	case BCM4342_CHIP_ID:
3321		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3322		W_REG(osh, &cc->pllcontrol_data, 0x11100070);
3323		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3324		W_REG(osh, &cc->pllcontrol_data, 0x1014140a);
3325		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3326		W_REG(osh, &cc->pllcontrol_data, 0x88888854);
3327
3328		if (spuravoid == 1) { /* spur_avoid ON, enable 41/82/164Mhz clock mode */
3329			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3330			W_REG(osh, &cc->pllcontrol_data, 0x05201828);
3331		} else { /* enable 40/80/160Mhz clock mode */
3332			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3333			W_REG(osh, &cc->pllcontrol_data, 0x05001828);
3334		}
3335
3336		tmp = 1 << 10;
3337		break;
3338	case BCM4319_CHIP_ID:
3339		break;
3340	case BCM4336_CHIP_ID:
3341		/* Looks like these are only for default xtal freq 26MHz */
3342		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3343		W_REG(osh, &cc->pllcontrol_data, 0x02100020);
3344
3345		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3346		W_REG(osh, &cc->pllcontrol_data, 0x0C0C0C0C);
3347
3348		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3349		W_REG(osh, &cc->pllcontrol_data, 0x01240C0C);
3350
3351		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3352		W_REG(osh, &cc->pllcontrol_data, 0x202C2820);
3353
3354		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3355		W_REG(osh, &cc->pllcontrol_data, 0x88888825);
3356
3357		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3358		if (spuravoid == 1) {
3359			W_REG(osh, &cc->pllcontrol_data, 0x00EC4EC4);
3360		} else {
3361			W_REG(osh, &cc->pllcontrol_data, 0x00762762);
3362		}
3363
3364		tmp = PCTL_PLL_PLLCTL_UPD;
3365		break;
3366	case BCM43227_CHIP_ID:
3367	case BCM43228_CHIP_ID:
3368	case BCM43428_CHIP_ID:
3369		/* LCNXN */
3370		/* PLL Settings for spur avoidance on/off mode, no on2 support for 43228A0 */
3371		if (spuravoid == 1) {
3372			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3373			W_REG(osh, &cc->pllcontrol_data, 0x01100014);
3374			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3375			W_REG(osh, &cc->pllcontrol_data, 0x040C0C06);
3376			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3377			W_REG(osh, &cc->pllcontrol_data, 0x03140A08);
3378			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3379			W_REG(osh, &cc->pllcontrol_data, 0x00333333);
3380			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3381			W_REG(osh, &cc->pllcontrol_data, 0x202C2820);
3382			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3383			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3384		} else {
3385			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
3386			W_REG(osh, &cc->pllcontrol_data, 0x11100014);
3387			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
3388			W_REG(osh, &cc->pllcontrol_data, 0x040c0c06);
3389			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
3390			W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
3391			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
3392			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
3393			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
3394			W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
3395			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
3396			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
3397		}
3398		tmp = 1 << 10;
3399		break;
3400	default:
3401		PMU_ERROR(("%s: unknown spuravoidance settings for chip %s, not changing PLL\n",
3402		           __FUNCTION__, bcm_chipname(sih->chip, chn, 8)));
3403		break;
3404	}
3405
3406	tmp |= R_REG(osh, &cc->pmucontrol);
3407	W_REG(osh, &cc->pmucontrol, tmp);
3408}
3409
3410void
3411si_pmu_gband_spurwar(si_t *sih, osl_t *osh)
3412{
3413	chipcregs_t *cc;
3414	uint origidx, intr_val;
3415	uint32 cc_clk_ctl_st;
3416	uint32 minmask, maxmask;
3417
3418	if ((CHIPID(sih->chip) == BCM43222_CHIP_ID) ||
3419		(CHIPID(sih->chip) == BCM43420_CHIP_ID)) {
3420		/* Remember original core before switch to chipc */
3421		cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
3422		ASSERT(cc != NULL);
3423
3424		/* Remove force HT and HT Avail Request from chipc core */
3425		cc_clk_ctl_st = R_REG(osh, &cc->clk_ctl_st);
3426		AND_REG(osh, &cc->clk_ctl_st, ~(CCS_FORCEHT | CCS_HTAREQ));
3427
3428		minmask = R_REG(osh, &cc->min_res_mask);
3429		maxmask = R_REG(osh, &cc->max_res_mask);
3430
3431		/* Make sure the PLL is off: clear bit 4 & 5 of min/max_res_mask */
3432		/* Have to remove HT Avail request before powering off PLL */
3433		AND_REG(osh, &cc->min_res_mask,	~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
3434		AND_REG(osh, &cc->max_res_mask,	~(PMURES_BIT(RES4322_HT_SI_AVAIL)));
3435		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL, PMU_MAX_TRANSITION_DLY);
3436		AND_REG(osh, &cc->min_res_mask,	~(PMURES_BIT(RES4322_SI_PLL_ON)));
3437		AND_REG(osh, &cc->max_res_mask,	~(PMURES_BIT(RES4322_SI_PLL_ON)));
3438		OSL_DELAY(150);
3439		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
3440
3441		/* Change backplane clock speed from 96 MHz to 80 MHz */
3442		W_REG(osh, &cc->pllcontrol_addr, PMU2_PLL_PLLCTL2);
3443		W_REG(osh, &cc->pllcontrol_data, (R_REG(osh, &cc->pllcontrol_data) &
3444		                                  ~(PMU2_PLL_PC2_M6DIV_MASK)) |
3445		      (0xc << PMU2_PLL_PC2_M6DIV_SHIFT));
3446
3447		/* Reduce the driver strengths of the phyclk160, adcclk80, and phyck80
3448		 * clocks from 0x8 to 0x1
3449		 */
3450		W_REG(osh, &cc->pllcontrol_addr, PMU2_PLL_PLLCTL5);
3451		W_REG(osh, &cc->pllcontrol_data, (R_REG(osh, &cc->pllcontrol_data) &
3452		                                  ~(PMU2_PLL_PC5_CLKDRIVE_CH1_MASK |
3453		                                    PMU2_PLL_PC5_CLKDRIVE_CH2_MASK |
3454		                                    PMU2_PLL_PC5_CLKDRIVE_CH3_MASK |
3455		                                    PMU2_PLL_PC5_CLKDRIVE_CH4_MASK)) |
3456		      ((1 << PMU2_PLL_PC5_CLKDRIVE_CH1_SHIFT) |
3457		       (1 << PMU2_PLL_PC5_CLKDRIVE_CH2_SHIFT) |
3458		       (1 << PMU2_PLL_PC5_CLKDRIVE_CH3_SHIFT) |
3459		       (1 << PMU2_PLL_PC5_CLKDRIVE_CH4_SHIFT)));
3460
3461		W_REG(osh, &cc->pmucontrol, R_REG(osh, &cc->pmucontrol) | PCTL_PLL_PLLCTL_UPD);
3462
3463		/* Restore min_res_mask and max_res_mask */
3464		OSL_DELAY(100);
3465		W_REG(osh, &cc->max_res_mask, maxmask);
3466		OSL_DELAY(100);
3467		W_REG(osh, &cc->min_res_mask, minmask);
3468		OSL_DELAY(100);
3469		/* Make sure the PLL is on. Spinwait until the HTAvail is True */
3470		SPINWAIT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL), PMU_MAX_TRANSITION_DLY);
3471		ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
3472
3473		/* Restore force HT and HT Avail Request on the chipc core */
3474		W_REG(osh, &cc->clk_ctl_st, cc_clk_ctl_st);
3475
3476		/* Return to original core */
3477		si_restore_core(sih, origidx, intr_val);
3478	}
3479}
3480
3481bool
3482si_pmu_is_otp_powered(si_t *sih, osl_t *osh)
3483{
3484	uint idx;
3485	chipcregs_t *cc;
3486	bool st;
3487
3488	/* Remember original core before switch to chipc */
3489	idx = si_coreidx(sih);
3490	cc = si_setcoreidx(sih, SI_CC_IDX);
3491	ASSERT(cc != NULL);
3492
3493	switch (CHIPID(sih->chip)) {
3494	case BCM4322_CHIP_ID:
3495	case BCM43221_CHIP_ID:
3496	case BCM43231_CHIP_ID:
3497	case BCM4342_CHIP_ID:
3498		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4322_OTP_PU)) != 0;
3499		break;
3500	case BCM4325_CHIP_ID:
3501		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4325_OTP_PU)) != 0;
3502		break;
3503	case BCM4329_CHIP_ID:
3504		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4329_OTP_PU)) != 0;
3505		break;
3506	case BCM4315_CHIP_ID:
3507		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4315_OTP_PU)) != 0;
3508		break;
3509	case BCM4319_CHIP_ID:
3510		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4319_OTP_PU)) != 0;
3511		break;
3512	case BCM4336_CHIP_ID:
3513		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4336_OTP_PU)) != 0;
3514		break;
3515	case BCM4330_CHIP_ID:
3516		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4330_OTP_PU)) != 0;
3517		break;
3518
3519	/* These chip doesn't use PMU bit to power up/down OTP. OTP always on.
3520	 * Use OTP_INIT command to reset/refresh state.
3521	 */
3522	case BCM43222_CHIP_ID:	case BCM43111_CHIP_ID:	case BCM43112_CHIP_ID:
3523	case BCM43224_CHIP_ID:	case BCM43225_CHIP_ID:	case BCM43421_CHIP_ID:
3524	case BCM43236_CHIP_ID:	case BCM43235_CHIP_ID:	case BCM43238_CHIP_ID:
3525	case BCM43234_CHIP_ID:	case BCM43237_CHIP_ID:  case BCM43420_CHIP_ID:
3526	case BCM4331_CHIP_ID:   case BCM43431_CHIP_ID:
3527		st = TRUE;
3528		break;
3529	default:
3530		st = TRUE;
3531		break;
3532	}
3533
3534	/* Return to original core */
3535	si_setcoreidx(sih, idx);
3536	return st;
3537}
3538#endif /* !_CFE_ || CFG_WL */
3539
3540void
3541#if defined(WLTEST)
3542si_pmu_sprom_enable(si_t *sih, osl_t *osh, bool enable)
3543#else
3544BCMATTACHFN(si_pmu_sprom_enable)(si_t *sih, osl_t *osh, bool enable)
3545#endif
3546{
3547	chipcregs_t *cc;
3548	uint origidx;
3549
3550	/* Remember original core before switch to chipc */
3551	origidx = si_coreidx(sih);
3552	cc = si_setcoreidx(sih, SI_CC_IDX);
3553	ASSERT(cc != NULL);
3554
3555	switch (CHIPID(sih->chip)) {
3556	case BCM4315_CHIP_ID:
3557		if (CHIPREV(sih->chiprev) < 1)
3558			break;
3559		if (sih->chipst & CST4315_SPROM_SEL) {
3560			uint32 val;
3561			W_REG(osh, &cc->chipcontrol_addr, 0);
3562			val = R_REG(osh, &cc->chipcontrol_data);
3563			if (enable)
3564				val &= ~0x80000000;
3565			else
3566				val |= 0x80000000;
3567			W_REG(osh, &cc->chipcontrol_data, val);
3568		}
3569		break;
3570	default:
3571		break;
3572	}
3573
3574	/* Return to original core */
3575	si_setcoreidx(sih, origidx);
3576}
3577
3578bool
3579#if defined(WLTEST)
3580si_pmu_is_sprom_enabled(si_t *sih, osl_t *osh)
3581#else
3582BCMATTACHFN(si_pmu_is_sprom_enabled)(si_t *sih, osl_t *osh)
3583#endif
3584{
3585	chipcregs_t *cc;
3586	uint origidx;
3587	bool enable = TRUE;
3588
3589	/* Remember original core before switch to chipc */
3590	origidx = si_coreidx(sih);
3591	cc = si_setcoreidx(sih, SI_CC_IDX);
3592	ASSERT(cc != NULL);
3593
3594	switch (CHIPID(sih->chip)) {
3595	case BCM4315_CHIP_ID:
3596		if (CHIPREV(sih->chiprev) < 1)
3597			break;
3598		if (!(sih->chipst & CST4315_SPROM_SEL))
3599			break;
3600		W_REG(osh, &cc->chipcontrol_addr, 0);
3601		if (R_REG(osh, &cc->chipcontrol_data) & 0x80000000)
3602			enable = FALSE;
3603		break;
3604	default:
3605		break;
3606	}
3607
3608	/* Return to original core */
3609	si_setcoreidx(sih, origidx);
3610	return enable;
3611}
3612
3613/* initialize PMU chip controls and other chip level stuff */
3614void
3615BCMATTACHFN(si_pmu_chip_init)(si_t *sih, osl_t *osh)
3616{
3617	uint origidx;
3618
3619	ASSERT(sih->cccaps & CC_CAP_PMU);
3620
3621#ifdef CHIPC_UART_ALWAYS_ON
3622	si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), CCS_FORCEALP, CCS_FORCEALP);
3623#endif /* CHIPC_UART_ALWAYS_ON */
3624
3625#ifndef CONFIG_XIP
3626	/* Gate off SPROM clock and chip select signals */
3627	si_pmu_sprom_enable(sih, osh, FALSE);
3628#endif
3629
3630	/* Remember original core */
3631	origidx = si_coreidx(sih);
3632
3633#if !defined(_CFE_) || defined(CFG_WL)
3634	/* Misc. chip control, has nothing to do with PMU */
3635	switch (CHIPID(sih->chip)) {
3636	case BCM4315_CHIP_ID:
3637#ifdef BCMUSBDEV
3638		si_setcore(sih, PCMCIA_CORE_ID, 0);
3639		si_core_disable(sih, 0);
3640#endif
3641		break;
3642	case BCM4319_CHIP_ID:
3643		/* No support for external LPO, so power it down */
3644		si_pmu_chipcontrol(sih, 0, (1<<28), (0<<28));
3645		break;
3646	default:
3647		break;
3648	}
3649#endif /* !_CFE_ || CFG_WL */
3650
3651	/* Return to original core */
3652	si_setcoreidx(sih, origidx);
3653}
3654
3655/* initialize PMU switch/regulators */
3656void
3657BCMATTACHFN(si_pmu_swreg_init)(si_t *sih, osl_t *osh)
3658{
3659#if !defined(_CFE_) || defined(CFG_WL)
3660	ASSERT(sih->cccaps & CC_CAP_PMU);
3661
3662	switch (CHIPID(sih->chip)) {
3663	case BCM4325_CHIP_ID:
3664		if (CHIPREV(sih->chiprev) < 3)
3665			break;
3666		if (((sih->chipst & CST4325_PMUTOP_2B_MASK) >> CST4325_PMUTOP_2B_SHIFT) == 1) {
3667			/* Bump CLDO PWM output voltage to 1.25V */
3668			si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xf);
3669			/* Bump CLDO BURST output voltage to 1.25V */
3670			si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_BURST, 0xf);
3671		}
3672		/* Bump CBUCK PWM output voltage to 1.5V */
3673		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0xb);
3674		/* Bump CBUCK BURST output voltage to 1.5V */
3675		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_BURST, 0xb);
3676		/* Bump LNLDO1 output voltage to 1.25V */
3677		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO1, 0x1);
3678		/* Select LNLDO2 output voltage to 2.5V */
3679		if (sih->boardflags & BFL_LNLDO2_2P5)
3680			si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO2_SEL, 0x1);
3681		break;
3682	case BCM4315_CHIP_ID: {
3683		uint32 val;
3684		chipcregs_t *cc;
3685		uint origidx;
3686
3687		if (CHIPREV(sih->chiprev) != 2)
3688			break;
3689
3690		/* Remember original core before switch to chipc */
3691		origidx = si_coreidx(sih);
3692		cc = si_setcoreidx(sih, SI_CC_IDX);
3693		ASSERT(cc != NULL);
3694
3695		W_REG(osh, &cc->regcontrol_addr, 4);
3696		val = R_REG(osh, &cc->regcontrol_data);
3697		val |= (uint32)(1 << 16);
3698		W_REG(osh, &cc->regcontrol_data, val);
3699
3700		/* Return to original core */
3701		si_setcoreidx(sih, origidx);
3702		break;
3703	}
3704	case BCM4336_CHIP_ID:
3705		/* Reduce CLDO PWM output voltage to 1.2V */
3706		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xe);
3707		/* Reduce CLDO BURST output voltage to 1.2V */
3708		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_BURST, 0xe);
3709		/* Reduce LNLDO1 output voltage to 1.2V */
3710		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO1, 0xe);
3711		if (CHIPREV(sih->chiprev) == 0)
3712			si_pmu_regcontrol(sih, 2, 0x400000, 0x400000);
3713		break;
3714
3715	case BCM4330_CHIP_ID:
3716		/* CBUCK Voltage is 1.8 by default and set that to 1.5 */
3717		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0);
3718		break;
3719	default:
3720		break;
3721	}
3722#endif /* !_CFE_ || CFG_WL */
3723}
3724
3725void
3726si_pmu_radio_enable(si_t *sih, bool enable)
3727{
3728	ASSERT(sih->cccaps & CC_CAP_PMU);
3729
3730	switch (CHIPID(sih->chip)) {
3731	case BCM4325_CHIP_ID:
3732		if (sih->boardflags & BFL_FASTPWR)
3733			break;
3734
3735		if ((sih->boardflags & BFL_BUCKBOOST)) {
3736			si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, min_res_mask),
3737			           PMURES_BIT(RES4325_BUCK_BOOST_BURST),
3738			           enable ? PMURES_BIT(RES4325_BUCK_BOOST_BURST) : 0);
3739		}
3740
3741		if (enable) {
3742			OSL_DELAY(100 * 1000);
3743		}
3744		break;
3745	case BCM4319_CHIP_ID:
3746		if (enable)
3747			si_write_wrapperreg(sih, AI_OOBSELOUTB74, (uint32)0x868584);
3748		else
3749			si_write_wrapperreg(sih, AI_OOBSELOUTB74, (uint32)0x060584);
3750		break;
3751	}
3752}
3753
3754/* Wait for a particular clock level to be on the backplane */
3755uint32
3756si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, uint32 clk, uint32 delay)
3757{
3758	chipcregs_t *cc;
3759	uint origidx;
3760
3761	ASSERT(sih->cccaps & CC_CAP_PMU);
3762
3763	/* Remember original core before switch to chipc */
3764	origidx = si_coreidx(sih);
3765	cc = si_setcoreidx(sih, SI_CC_IDX);
3766	ASSERT(cc != NULL);
3767
3768	if (delay)
3769		SPINWAIT(((R_REG(osh, &cc->pmustatus) & clk) != clk), delay);
3770
3771	/* Return to original core */
3772	si_setcoreidx(sih, origidx);
3773
3774	return (R_REG(osh, &cc->pmustatus) & clk);
3775}
3776
3777/*
3778 * Measures the ALP clock frequency in KHz.  Returns 0 if not possible.
3779 * Possible only if PMU rev >= 10 and there is an external LPO 32768Hz crystal.
3780 */
3781
3782#define EXT_ILP_HZ 32768
3783
3784uint32
3785BCMATTACHFN(si_pmu_measure_alpclk)(si_t *sih, osl_t *osh)
3786{
3787	chipcregs_t *cc;
3788	uint origidx;
3789	uint32 alp_khz;
3790
3791	if (sih->pmurev < 10)
3792		return 0;
3793
3794	ASSERT(sih->cccaps & CC_CAP_PMU);
3795
3796	/* Remember original core before switch to chipc */
3797	origidx = si_coreidx(sih);
3798	cc = si_setcoreidx(sih, SI_CC_IDX);
3799	ASSERT(cc != NULL);
3800
3801	if (R_REG(osh, &cc->pmustatus) & PST_EXTLPOAVAIL) {
3802		uint32 ilp_ctr, alp_hz;
3803
3804		/* Enable the reg to measure the freq, in case disabled before */
3805		W_REG(osh, &cc->pmu_xtalfreq, 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
3806
3807		/* Delay for well over 4 ILP clocks */
3808		OSL_DELAY(1000);
3809
3810		/* Read the latched number of ALP ticks per 4 ILP ticks */
3811		ilp_ctr = R_REG(osh, &cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
3812
3813		/* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT bit to save power */
3814		W_REG(osh, &cc->pmu_xtalfreq, 0);
3815
3816		/* Calculate ALP frequency */
3817		alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
3818
3819		/* Round to nearest 100KHz, and at the same time convert to KHz */
3820		alp_khz = (alp_hz + 50000) / 100000 * 100;
3821	} else
3822		alp_khz = 0;
3823
3824	/* Return to original core */
3825	si_setcoreidx(sih, origidx);
3826
3827	return alp_khz;
3828}
3829
3830#if !defined(_CFE_) || defined(CFG_WL)
3831void
3832si_pmu_set_4330_plldivs(si_t *sih, uint8 dacrate)
3833{
3834	uint32 FVCO = si_pmu1_pllfvco0(sih)/1000;
3835	uint32 m1div, m2div, m3div, m4div, m5div, m6div;
3836	uint32 pllc1, pllc2;
3837
3838	m2div = m3div = m4div = m6div = FVCO/80;
3839
3840	m5div = FVCO/dacrate;
3841
3842	if (CST4330_CHIPMODE_SDIOD(sih->chipst))
3843		m1div = FVCO/80;
3844	else
3845		m1div = FVCO/90;
3846	pllc1 = (m1div << PMU1_PLL0_PC1_M1DIV_SHIFT) | (m2div << PMU1_PLL0_PC1_M2DIV_SHIFT) |
3847		(m3div << PMU1_PLL0_PC1_M3DIV_SHIFT) | (m4div << PMU1_PLL0_PC1_M4DIV_SHIFT);
3848	si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, ~0, pllc1);
3849
3850	pllc2 = si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL2, 0, 0);
3851	pllc2 &= ~(PMU1_PLL0_PC2_M5DIV_MASK | PMU1_PLL0_PC2_M6DIV_MASK);
3852	pllc2 |= ((m5div << PMU1_PLL0_PC2_M5DIV_SHIFT) | (m6div << PMU1_PLL0_PC2_M6DIV_SHIFT));
3853	si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL2, ~0, pllc2);
3854}
3855#endif /* !_CFE_ || CFG_WL */
3856