2 * Copyright (c) 2011 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <linux/delay.h>
20 #include <brcm_hw_ids.h>
21 #include <chipcommon.h>
22 #include <brcmu_utils.h>
28 * external LPO crystal frequency
30 #define EXT_ILP_HZ 32768
33 * Duration for ILP clock frequency measurment in milliseconds
35 * remark: 1000 must be an integer multiple of this duration
37 #define ILP_CALC_DUR 10
39 /* Fields in pmucontrol */
40 #define PCTL_ILP_DIV_MASK 0xffff0000
41 #define PCTL_ILP_DIV_SHIFT 16
42 #define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */
43 #define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */
44 #define PCTL_HT_REQ_EN 0x00000100
45 #define PCTL_ALP_REQ_EN 0x00000080
46 #define PCTL_XTALFREQ_MASK 0x0000007c
47 #define PCTL_XTALFREQ_SHIFT 2
48 #define PCTL_ILP_DIV_EN 0x00000002
49 #define PCTL_LPO_SEL 0x00000001
52 #define ILP_CLOCK 32000
54 /* ALP clock on pre-PMU chips */
55 #define ALP_CLOCK 20000000
58 #define PST_EXTLPOAVAIL 0x0100
59 #define PST_WDRESET 0x0080
60 #define PST_INTPEND 0x0040
61 #define PST_SBCLKST 0x0030
62 #define PST_SBCLKST_ILP 0x0010
63 #define PST_SBCLKST_ALP 0x0020
64 #define PST_SBCLKST_HT 0x0030
65 #define PST_ALPAVAIL 0x0008
66 #define PST_HTAVAIL 0x0004
67 #define PST_RESINIT 0x0003
69 /* PMU resource bit position */
70 #define PMURES_BIT(bit) (1 << (bit))
72 /* PMU corerev and chip specific PLL controls.
73 * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary number
74 * to differentiate different PLLs controlled by the same PMU rev.
76 /* pllcontrol registers */
77 /* ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>, p1div, p2div, _bypass_sdmod */
78 #define PMU1_PLL0_PLLCTL0 0
79 #define PMU1_PLL0_PLLCTL1 1
80 #define PMU1_PLL0_PLLCTL2 2
81 #define PMU1_PLL0_PLLCTL3 3
82 #define PMU1_PLL0_PLLCTL4 4
83 #define PMU1_PLL0_PLLCTL5 5
85 /* pmu XtalFreqRatio */
86 #define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
87 #define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000
88 #define PMU_XTALFREQ_REG_MEASURE_SHIFT 31
91 #define RES4313_BB_PU_RSRC 0
92 #define RES4313_ILP_REQ_RSRC 1
93 #define RES4313_XTAL_PU_RSRC 2
94 #define RES4313_ALP_AVAIL_RSRC 3
95 #define RES4313_RADIO_PU_RSRC 4
96 #define RES4313_BG_PU_RSRC 5
97 #define RES4313_VREG1P4_PU_RSRC 6
98 #define RES4313_AFE_PWRSW_RSRC 7
99 #define RES4313_RX_PWRSW_RSRC 8
100 #define RES4313_TX_PWRSW_RSRC 9
101 #define RES4313_BB_PWRSW_RSRC 10
102 #define RES4313_SYNTH_PWRSW_RSRC 11
103 #define RES4313_MISC_PWRSW_RSRC 12
104 #define RES4313_BB_PLL_PWRSW_RSRC 13
105 #define RES4313_HT_AVAIL_RSRC 14
106 #define RES4313_MACPHY_CLK_AVAIL_RSRC 15
108 /* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
109 static void si_pmu_res_masks(struct si_pub
*sih
, u32
* pmin
, u32
* pmax
)
111 u32 min_mask
= 0, max_mask
= 0;
115 rsrcs
= (sih
->pmucaps
& PCAP_RC_MASK
) >> PCAP_RC_SHIFT
;
117 /* determine min/max rsrc masks */
119 case BCM43224_CHIP_ID
:
120 case BCM43225_CHIP_ID
:
124 case BCM4313_CHIP_ID
:
125 min_mask
= PMURES_BIT(RES4313_BB_PU_RSRC
) |
126 PMURES_BIT(RES4313_XTAL_PU_RSRC
) |
127 PMURES_BIT(RES4313_ALP_AVAIL_RSRC
) |
128 PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC
);
140 si_pmu_spuravoid_pllupdate(struct si_pub
*sih
, chipcregs_t
*cc
, u8 spuravoid
)
145 case BCM43224_CHIP_ID
:
146 case BCM43225_CHIP_ID
:
147 if (spuravoid
== 1) {
148 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL0
);
149 W_REG(&cc
->pllcontrol_data
, 0x11500010);
150 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL1
);
151 W_REG(&cc
->pllcontrol_data
, 0x000C0C06);
152 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL2
);
153 W_REG(&cc
->pllcontrol_data
, 0x0F600a08);
154 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL3
);
155 W_REG(&cc
->pllcontrol_data
, 0x00000000);
156 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL4
);
157 W_REG(&cc
->pllcontrol_data
, 0x2001E920);
158 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL5
);
159 W_REG(&cc
->pllcontrol_data
, 0x88888815);
161 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL0
);
162 W_REG(&cc
->pllcontrol_data
, 0x11100010);
163 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL1
);
164 W_REG(&cc
->pllcontrol_data
, 0x000c0c06);
165 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL2
);
166 W_REG(&cc
->pllcontrol_data
, 0x03000a08);
167 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL3
);
168 W_REG(&cc
->pllcontrol_data
, 0x00000000);
169 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL4
);
170 W_REG(&cc
->pllcontrol_data
, 0x200005c0);
171 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL5
);
172 W_REG(&cc
->pllcontrol_data
, 0x88888815);
177 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL0
);
178 W_REG(&cc
->pllcontrol_data
, 0x11100008);
179 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL1
);
180 W_REG(&cc
->pllcontrol_data
, 0x0c000c06);
181 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL2
);
182 W_REG(&cc
->pllcontrol_data
, 0x03000a08);
183 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL3
);
184 W_REG(&cc
->pllcontrol_data
, 0x00000000);
185 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL4
);
186 W_REG(&cc
->pllcontrol_data
, 0x200005c0);
187 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL5
);
188 W_REG(&cc
->pllcontrol_data
, 0x88888855);
198 tmp
|= R_REG(&cc
->pmucontrol
);
199 W_REG(&cc
->pmucontrol
, tmp
);
202 u32
si_pmu_ilp_clock(struct si_pub
*sih
)
204 static u32 ilpcycles_per_sec
;
206 if (!PMUCTL_ENAB(sih
))
209 if (ilpcycles_per_sec
== 0) {
210 u32 start
, end
, delta
;
211 u32 origidx
= ai_coreidx(sih
);
212 chipcregs_t
*cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
213 start
= R_REG(&cc
->pmutimer
);
214 mdelay(ILP_CALC_DUR
);
215 end
= R_REG(&cc
->pmutimer
);
217 ilpcycles_per_sec
= delta
* (1000 / ILP_CALC_DUR
);
218 ai_setcoreidx(sih
, origidx
);
221 return ilpcycles_per_sec
;
224 u16
si_pmu_fast_pwrup_delay(struct si_pub
*sih
)
226 uint delay
= PMU_MAX_TRANSITION_DLY
;
229 case BCM43224_CHIP_ID
:
230 case BCM43225_CHIP_ID
:
231 case BCM4313_CHIP_ID
:
241 void si_pmu_sprom_enable(struct si_pub
*sih
, bool enable
)
246 /* Remember original core before switch to chipc */
247 origidx
= ai_coreidx(sih
);
248 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
250 /* Return to original core */
251 ai_setcoreidx(sih
, origidx
);
254 /* Read/write a chipcontrol reg */
255 u32
si_pmu_chipcontrol(struct si_pub
*sih
, uint reg
, u32 mask
, u32 val
)
257 ai_corereg(sih
, SI_CC_IDX
, offsetof(chipcregs_t
, chipcontrol_addr
), ~0,
259 return ai_corereg(sih
, SI_CC_IDX
,
260 offsetof(chipcregs_t
, chipcontrol_data
), mask
, val
);
263 /* Read/write a regcontrol reg */
264 u32
si_pmu_regcontrol(struct si_pub
*sih
, uint reg
, u32 mask
, u32 val
)
266 ai_corereg(sih
, SI_CC_IDX
, offsetof(chipcregs_t
, regcontrol_addr
), ~0,
268 return ai_corereg(sih
, SI_CC_IDX
,
269 offsetof(chipcregs_t
, regcontrol_data
), mask
, val
);
272 /* Read/write a pllcontrol reg */
273 u32
si_pmu_pllcontrol(struct si_pub
*sih
, uint reg
, u32 mask
, u32 val
)
275 ai_corereg(sih
, SI_CC_IDX
, offsetof(chipcregs_t
, pllcontrol_addr
), ~0,
277 return ai_corereg(sih
, SI_CC_IDX
,
278 offsetof(chipcregs_t
, pllcontrol_data
), mask
, val
);
282 void si_pmu_pllupd(struct si_pub
*sih
)
284 ai_corereg(sih
, SI_CC_IDX
, offsetof(chipcregs_t
, pmucontrol
),
285 PCTL_PLL_PLLCTL_UPD
, PCTL_PLL_PLLCTL_UPD
);
288 /* query alp/xtal clock frequency */
289 u32
si_pmu_alp_clock(struct si_pub
*sih
)
291 u32 clock
= ALP_CLOCK
;
293 /* bail out with default */
294 if (!PMUCTL_ENAB(sih
))
298 case BCM43224_CHIP_ID
:
299 case BCM43225_CHIP_ID
:
300 case BCM4313_CHIP_ID
:
302 clock
= 20000 * 1000;
311 void si_pmu_spuravoid(struct si_pub
*sih
, u8 spuravoid
)
314 uint origidx
, intr_val
;
316 /* Remember original core before switch to chipc */
317 cc
= (chipcregs_t
*) ai_switch_core(sih
, CC_CORE_ID
, &origidx
,
320 /* update the pll changes */
321 si_pmu_spuravoid_pllupdate(sih
, cc
, spuravoid
);
323 /* Return to original core */
324 ai_restore_core(sih
, origidx
, intr_val
);
328 void si_pmu_init(struct si_pub
*sih
)
333 /* Remember original core before switch to chipc */
334 origidx
= ai_coreidx(sih
);
335 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
337 if (sih
->pmurev
== 1)
338 AND_REG(&cc
->pmucontrol
, ~PCTL_NOILP_ON_WAIT
);
339 else if (sih
->pmurev
>= 2)
340 OR_REG(&cc
->pmucontrol
, PCTL_NOILP_ON_WAIT
);
342 /* Return to original core */
343 ai_setcoreidx(sih
, origidx
);
346 /* initialize PMU chip controls and other chip level stuff */
347 void si_pmu_chip_init(struct si_pub
*sih
)
351 /* Gate off SPROM clock and chip select signals */
352 si_pmu_sprom_enable(sih
, false);
354 /* Remember original core */
355 origidx
= ai_coreidx(sih
);
357 /* Return to original core */
358 ai_setcoreidx(sih
, origidx
);
361 /* initialize PMU switch/regulators */
362 void si_pmu_swreg_init(struct si_pub
*sih
)
367 void si_pmu_pll_init(struct si_pub
*sih
, uint xtalfreq
)
372 /* Remember original core before switch to chipc */
373 origidx
= ai_coreidx(sih
);
374 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
377 case BCM4313_CHIP_ID
:
378 case BCM43224_CHIP_ID
:
379 case BCM43225_CHIP_ID
:
386 /* Return to original core */
387 ai_setcoreidx(sih
, origidx
);
390 /* initialize PMU resources */
391 void si_pmu_res_init(struct si_pub
*sih
)
395 u32 min_mask
= 0, max_mask
= 0;
397 /* Remember original core before switch to chipc */
398 origidx
= ai_coreidx(sih
);
399 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
401 /* Determine min/max rsrc masks */
402 si_pmu_res_masks(sih
, &min_mask
, &max_mask
);
404 /* It is required to program max_mask first and then min_mask */
406 /* Program max resource mask */
409 W_REG(&cc
->max_res_mask
, max_mask
);
411 /* Program min resource mask */
414 W_REG(&cc
->min_res_mask
, min_mask
);
416 /* Add some delay; allow resources to come up and settle. */
419 /* Return to original core */
420 ai_setcoreidx(sih
, origidx
);
423 u32
si_pmu_measure_alpclk(struct si_pub
*sih
)
429 if (sih
->pmurev
< 10)
432 /* Remember original core before switch to chipc */
433 origidx
= ai_coreidx(sih
);
434 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
436 if (R_REG(&cc
->pmustatus
) & PST_EXTLPOAVAIL
) {
440 * Enable the reg to measure the freq,
441 * in case it was disabled before
443 W_REG(&cc
->pmu_xtalfreq
,
444 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT
);
446 /* Delay for well over 4 ILP clocks */
449 /* Read the latched number of ALP ticks per 4 ILP ticks */
451 R_REG(&cc
->pmu_xtalfreq
) & PMU_XTALFREQ_REG_ILPCTR_MASK
;
454 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
457 W_REG(&cc
->pmu_xtalfreq
, 0);
459 /* Calculate ALP frequency */
460 alp_hz
= (ilp_ctr
* EXT_ILP_HZ
) / 4;
463 * Round to nearest 100KHz, and at
464 * the same time convert to KHz
466 alp_khz
= (alp_hz
+ 50000) / 100000 * 100;
470 /* Return to original core */
471 ai_setcoreidx(sih
, origidx
);