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
74 * number to differentiate different PLLs controlled by the same PMU rev.
76 /* pllcontrol registers:
77 * ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>,
78 * p1div, p2div, _bypass_sdmod
80 #define PMU1_PLL0_PLLCTL0 0
81 #define PMU1_PLL0_PLLCTL1 1
82 #define PMU1_PLL0_PLLCTL2 2
83 #define PMU1_PLL0_PLLCTL3 3
84 #define PMU1_PLL0_PLLCTL4 4
85 #define PMU1_PLL0_PLLCTL5 5
87 /* pmu XtalFreqRatio */
88 #define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
89 #define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000
90 #define PMU_XTALFREQ_REG_MEASURE_SHIFT 31
93 #define RES4313_BB_PU_RSRC 0
94 #define RES4313_ILP_REQ_RSRC 1
95 #define RES4313_XTAL_PU_RSRC 2
96 #define RES4313_ALP_AVAIL_RSRC 3
97 #define RES4313_RADIO_PU_RSRC 4
98 #define RES4313_BG_PU_RSRC 5
99 #define RES4313_VREG1P4_PU_RSRC 6
100 #define RES4313_AFE_PWRSW_RSRC 7
101 #define RES4313_RX_PWRSW_RSRC 8
102 #define RES4313_TX_PWRSW_RSRC 9
103 #define RES4313_BB_PWRSW_RSRC 10
104 #define RES4313_SYNTH_PWRSW_RSRC 11
105 #define RES4313_MISC_PWRSW_RSRC 12
106 #define RES4313_BB_PLL_PWRSW_RSRC 13
107 #define RES4313_HT_AVAIL_RSRC 14
108 #define RES4313_MACPHY_CLK_AVAIL_RSRC 15
110 /* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
111 static void si_pmu_res_masks(struct si_pub
*sih
, u32
* pmin
, u32
* pmax
)
113 u32 min_mask
= 0, max_mask
= 0;
117 rsrcs
= (sih
->pmucaps
& PCAP_RC_MASK
) >> PCAP_RC_SHIFT
;
119 /* determine min/max rsrc masks */
121 case BCM43224_CHIP_ID
:
122 case BCM43225_CHIP_ID
:
126 case BCM4313_CHIP_ID
:
127 min_mask
= PMURES_BIT(RES4313_BB_PU_RSRC
) |
128 PMURES_BIT(RES4313_XTAL_PU_RSRC
) |
129 PMURES_BIT(RES4313_ALP_AVAIL_RSRC
) |
130 PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC
);
142 si_pmu_spuravoid_pllupdate(struct si_pub
*sih
, struct chipcregs __iomem
*cc
,
148 case BCM43224_CHIP_ID
:
149 case BCM43225_CHIP_ID
:
150 if (spuravoid
== 1) {
151 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL0
);
152 W_REG(&cc
->pllcontrol_data
, 0x11500010);
153 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL1
);
154 W_REG(&cc
->pllcontrol_data
, 0x000C0C06);
155 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL2
);
156 W_REG(&cc
->pllcontrol_data
, 0x0F600a08);
157 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL3
);
158 W_REG(&cc
->pllcontrol_data
, 0x00000000);
159 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL4
);
160 W_REG(&cc
->pllcontrol_data
, 0x2001E920);
161 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL5
);
162 W_REG(&cc
->pllcontrol_data
, 0x88888815);
164 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL0
);
165 W_REG(&cc
->pllcontrol_data
, 0x11100010);
166 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL1
);
167 W_REG(&cc
->pllcontrol_data
, 0x000c0c06);
168 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL2
);
169 W_REG(&cc
->pllcontrol_data
, 0x03000a08);
170 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL3
);
171 W_REG(&cc
->pllcontrol_data
, 0x00000000);
172 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL4
);
173 W_REG(&cc
->pllcontrol_data
, 0x200005c0);
174 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL5
);
175 W_REG(&cc
->pllcontrol_data
, 0x88888815);
180 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL0
);
181 W_REG(&cc
->pllcontrol_data
, 0x11100008);
182 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL1
);
183 W_REG(&cc
->pllcontrol_data
, 0x0c000c06);
184 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL2
);
185 W_REG(&cc
->pllcontrol_data
, 0x03000a08);
186 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL3
);
187 W_REG(&cc
->pllcontrol_data
, 0x00000000);
188 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL4
);
189 W_REG(&cc
->pllcontrol_data
, 0x200005c0);
190 W_REG(&cc
->pllcontrol_addr
, PMU1_PLL0_PLLCTL5
);
191 W_REG(&cc
->pllcontrol_data
, 0x88888855);
201 tmp
|= R_REG(&cc
->pmucontrol
);
202 W_REG(&cc
->pmucontrol
, tmp
);
205 u16
si_pmu_fast_pwrup_delay(struct si_pub
*sih
)
207 uint delay
= PMU_MAX_TRANSITION_DLY
;
210 case BCM43224_CHIP_ID
:
211 case BCM43225_CHIP_ID
:
212 case BCM4313_CHIP_ID
:
222 void si_pmu_sprom_enable(struct si_pub
*sih
, bool enable
)
224 struct chipcregs __iomem
*cc
;
227 /* Remember original core before switch to chipc */
228 origidx
= ai_coreidx(sih
);
229 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
231 /* Return to original core */
232 ai_setcoreidx(sih
, origidx
);
235 /* Read/write a chipcontrol reg */
236 u32
si_pmu_chipcontrol(struct si_pub
*sih
, uint reg
, u32 mask
, u32 val
)
238 ai_corereg(sih
, SI_CC_IDX
, offsetof(struct chipcregs
, chipcontrol_addr
),
240 return ai_corereg(sih
, SI_CC_IDX
,
241 offsetof(struct chipcregs
, chipcontrol_data
), mask
,
245 /* Read/write a regcontrol reg */
246 u32
si_pmu_regcontrol(struct si_pub
*sih
, uint reg
, u32 mask
, u32 val
)
248 ai_corereg(sih
, SI_CC_IDX
, offsetof(struct chipcregs
, regcontrol_addr
),
250 return ai_corereg(sih
, SI_CC_IDX
,
251 offsetof(struct chipcregs
, regcontrol_data
), mask
,
255 /* Read/write a pllcontrol reg */
256 u32
si_pmu_pllcontrol(struct si_pub
*sih
, uint reg
, u32 mask
, u32 val
)
258 ai_corereg(sih
, SI_CC_IDX
, offsetof(struct chipcregs
, pllcontrol_addr
),
260 return ai_corereg(sih
, SI_CC_IDX
,
261 offsetof(struct chipcregs
, pllcontrol_data
), mask
,
266 void si_pmu_pllupd(struct si_pub
*sih
)
268 ai_corereg(sih
, SI_CC_IDX
, offsetof(struct chipcregs
, pmucontrol
),
269 PCTL_PLL_PLLCTL_UPD
, PCTL_PLL_PLLCTL_UPD
);
272 /* query alp/xtal clock frequency */
273 u32
si_pmu_alp_clock(struct si_pub
*sih
)
275 u32 clock
= ALP_CLOCK
;
277 /* bail out with default */
278 if (!(sih
->cccaps
& CC_CAP_PMU
))
282 case BCM43224_CHIP_ID
:
283 case BCM43225_CHIP_ID
:
284 case BCM4313_CHIP_ID
:
286 clock
= 20000 * 1000;
295 void si_pmu_spuravoid(struct si_pub
*sih
, u8 spuravoid
)
297 struct chipcregs __iomem
*cc
;
298 uint origidx
, intr_val
;
300 /* Remember original core before switch to chipc */
301 cc
= (struct chipcregs __iomem
*)
302 ai_switch_core(sih
, CC_CORE_ID
, &origidx
, &intr_val
);
304 /* update the pll changes */
305 si_pmu_spuravoid_pllupdate(sih
, cc
, spuravoid
);
307 /* Return to original core */
308 ai_restore_core(sih
, origidx
, intr_val
);
312 void si_pmu_init(struct si_pub
*sih
)
314 struct chipcregs __iomem
*cc
;
317 /* Remember original core before switch to chipc */
318 origidx
= ai_coreidx(sih
);
319 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
321 if (sih
->pmurev
== 1)
322 AND_REG(&cc
->pmucontrol
, ~PCTL_NOILP_ON_WAIT
);
323 else if (sih
->pmurev
>= 2)
324 OR_REG(&cc
->pmucontrol
, PCTL_NOILP_ON_WAIT
);
326 /* Return to original core */
327 ai_setcoreidx(sih
, origidx
);
330 /* initialize PMU chip controls and other chip level stuff */
331 void si_pmu_chip_init(struct si_pub
*sih
)
335 /* Gate off SPROM clock and chip select signals */
336 si_pmu_sprom_enable(sih
, false);
338 /* Remember original core */
339 origidx
= ai_coreidx(sih
);
341 /* Return to original core */
342 ai_setcoreidx(sih
, origidx
);
345 /* initialize PMU switch/regulators */
346 void si_pmu_swreg_init(struct si_pub
*sih
)
351 void si_pmu_pll_init(struct si_pub
*sih
, uint xtalfreq
)
353 struct chipcregs __iomem
*cc
;
356 /* Remember original core before switch to chipc */
357 origidx
= ai_coreidx(sih
);
358 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
361 case BCM4313_CHIP_ID
:
362 case BCM43224_CHIP_ID
:
363 case BCM43225_CHIP_ID
:
370 /* Return to original core */
371 ai_setcoreidx(sih
, origidx
);
374 /* initialize PMU resources */
375 void si_pmu_res_init(struct si_pub
*sih
)
377 struct chipcregs __iomem
*cc
;
379 u32 min_mask
= 0, max_mask
= 0;
381 /* Remember original core before switch to chipc */
382 origidx
= ai_coreidx(sih
);
383 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
385 /* Determine min/max rsrc masks */
386 si_pmu_res_masks(sih
, &min_mask
, &max_mask
);
388 /* It is required to program max_mask first and then min_mask */
390 /* Program max resource mask */
393 W_REG(&cc
->max_res_mask
, max_mask
);
395 /* Program min resource mask */
398 W_REG(&cc
->min_res_mask
, min_mask
);
400 /* Add some delay; allow resources to come up and settle. */
403 /* Return to original core */
404 ai_setcoreidx(sih
, origidx
);
407 u32
si_pmu_measure_alpclk(struct si_pub
*sih
)
409 struct chipcregs __iomem
*cc
;
413 if (sih
->pmurev
< 10)
416 /* Remember original core before switch to chipc */
417 origidx
= ai_coreidx(sih
);
418 cc
= ai_setcoreidx(sih
, SI_CC_IDX
);
420 if (R_REG(&cc
->pmustatus
) & PST_EXTLPOAVAIL
) {
424 * Enable the reg to measure the freq,
425 * in case it was disabled before
427 W_REG(&cc
->pmu_xtalfreq
,
428 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT
);
430 /* Delay for well over 4 ILP clocks */
433 /* Read the latched number of ALP ticks per 4 ILP ticks */
435 R_REG(&cc
->pmu_xtalfreq
) & PMU_XTALFREQ_REG_ILPCTR_MASK
;
438 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
441 W_REG(&cc
->pmu_xtalfreq
, 0);
443 /* Calculate ALP frequency */
444 alp_hz
= (ilp_ctr
* EXT_ILP_HZ
) / 4;
447 * Round to nearest 100KHz, and at
448 * the same time convert to KHz
450 alp_khz
= (alp_hz
+ 50000) / 100000 * 100;
454 /* Return to original core */
455 ai_setcoreidx(sih
, origidx
);