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>
29 * external LPO crystal frequency
31 #define EXT_ILP_HZ 32768
34 * Duration for ILP clock frequency measurment in milliseconds
36 * remark: 1000 must be an integer multiple of this duration
38 #define ILP_CALC_DUR 10
40 /* Fields in pmucontrol */
41 #define PCTL_ILP_DIV_MASK 0xffff0000
42 #define PCTL_ILP_DIV_SHIFT 16
43 #define PCTL_PLL_PLLCTL_UPD 0x00000400 /* rev 2 */
44 #define PCTL_NOILP_ON_WAIT 0x00000200 /* rev 1 */
45 #define PCTL_HT_REQ_EN 0x00000100
46 #define PCTL_ALP_REQ_EN 0x00000080
47 #define PCTL_XTALFREQ_MASK 0x0000007c
48 #define PCTL_XTALFREQ_SHIFT 2
49 #define PCTL_ILP_DIV_EN 0x00000002
50 #define PCTL_LPO_SEL 0x00000001
53 #define ILP_CLOCK 32000
55 /* ALP clock on pre-PMU chips */
56 #define ALP_CLOCK 20000000
59 #define PST_EXTLPOAVAIL 0x0100
60 #define PST_WDRESET 0x0080
61 #define PST_INTPEND 0x0040
62 #define PST_SBCLKST 0x0030
63 #define PST_SBCLKST_ILP 0x0010
64 #define PST_SBCLKST_ALP 0x0020
65 #define PST_SBCLKST_HT 0x0030
66 #define PST_ALPAVAIL 0x0008
67 #define PST_HTAVAIL 0x0004
68 #define PST_RESINIT 0x0003
70 /* PMU resource bit position */
71 #define PMURES_BIT(bit) (1 << (bit))
73 /* PMU corerev and chip specific PLL controls.
74 * PMU<rev>_PLL<num>_XX where <rev> is PMU corerev and <num> is an arbitrary
75 * number to differentiate different PLLs controlled by the same PMU rev.
77 /* pllcontrol registers:
78 * ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>,
79 * p1div, p2div, _bypass_sdmod
81 #define PMU1_PLL0_PLLCTL0 0
82 #define PMU1_PLL0_PLLCTL1 1
83 #define PMU1_PLL0_PLLCTL2 2
84 #define PMU1_PLL0_PLLCTL3 3
85 #define PMU1_PLL0_PLLCTL4 4
86 #define PMU1_PLL0_PLLCTL5 5
88 /* pmu XtalFreqRatio */
89 #define PMU_XTALFREQ_REG_ILPCTR_MASK 0x00001FFF
90 #define PMU_XTALFREQ_REG_MEASURE_MASK 0x80000000
91 #define PMU_XTALFREQ_REG_MEASURE_SHIFT 31
94 #define RES4313_BB_PU_RSRC 0
95 #define RES4313_ILP_REQ_RSRC 1
96 #define RES4313_XTAL_PU_RSRC 2
97 #define RES4313_ALP_AVAIL_RSRC 3
98 #define RES4313_RADIO_PU_RSRC 4
99 #define RES4313_BG_PU_RSRC 5
100 #define RES4313_VREG1P4_PU_RSRC 6
101 #define RES4313_AFE_PWRSW_RSRC 7
102 #define RES4313_RX_PWRSW_RSRC 8
103 #define RES4313_TX_PWRSW_RSRC 9
104 #define RES4313_BB_PWRSW_RSRC 10
105 #define RES4313_SYNTH_PWRSW_RSRC 11
106 #define RES4313_MISC_PWRSW_RSRC 12
107 #define RES4313_BB_PLL_PWRSW_RSRC 13
108 #define RES4313_HT_AVAIL_RSRC 14
109 #define RES4313_MACPHY_CLK_AVAIL_RSRC 15
111 /* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
112 static void si_pmu_res_masks(struct si_pub
*sih
, u32
* pmin
, u32
* pmax
)
114 u32 min_mask
= 0, max_mask
= 0;
118 rsrcs
= (ai_get_pmucaps(sih
) & PCAP_RC_MASK
) >> PCAP_RC_SHIFT
;
120 /* determine min/max rsrc masks */
121 switch (ai_get_chip_id(sih
)) {
122 case BCM43224_CHIP_ID
:
123 case BCM43225_CHIP_ID
:
127 case BCM4313_CHIP_ID
:
128 min_mask
= PMURES_BIT(RES4313_BB_PU_RSRC
) |
129 PMURES_BIT(RES4313_XTAL_PU_RSRC
) |
130 PMURES_BIT(RES4313_ALP_AVAIL_RSRC
) |
131 PMURES_BIT(RES4313_BB_PLL_PWRSW_RSRC
);
142 void si_pmu_spuravoid_pllupdate(struct si_pub
*sih
, u8 spuravoid
)
145 struct bcma_device
*core
;
147 /* switch to chipc */
148 core
= ai_findcore(sih
, BCMA_CORE_CHIPCOMMON
, 0);
150 switch (ai_get_chip_id(sih
)) {
151 case BCM43224_CHIP_ID
:
152 case BCM43225_CHIP_ID
:
153 if (spuravoid
== 1) {
154 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
156 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
158 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
160 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
162 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
164 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
166 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
168 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
170 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
172 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
174 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
176 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
179 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
181 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
183 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
185 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
187 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
189 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
191 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
193 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
195 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
197 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
199 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_addr
),
201 bcma_write32(core
, CHIPCREGOFFS(pllcontrol_data
),
212 bcma_set32(core
, CHIPCREGOFFS(pmucontrol
), tmp
);
215 u16
si_pmu_fast_pwrup_delay(struct si_pub
*sih
)
217 uint delay
= PMU_MAX_TRANSITION_DLY
;
219 switch (ai_get_chip_id(sih
)) {
220 case BCM43224_CHIP_ID
:
221 case BCM43225_CHIP_ID
:
222 case BCM4313_CHIP_ID
:
232 /* Read/write a chipcontrol reg */
233 u32
si_pmu_chipcontrol(struct si_pub
*sih
, uint reg
, u32 mask
, u32 val
)
235 ai_cc_reg(sih
, offsetof(struct chipcregs
, chipcontrol_addr
), ~0, reg
);
236 return ai_cc_reg(sih
, offsetof(struct chipcregs
, chipcontrol_data
),
240 /* Read/write a regcontrol reg */
241 u32
si_pmu_regcontrol(struct si_pub
*sih
, uint reg
, u32 mask
, u32 val
)
243 ai_cc_reg(sih
, offsetof(struct chipcregs
, regcontrol_addr
), ~0, reg
);
244 return ai_cc_reg(sih
, offsetof(struct chipcregs
, regcontrol_data
),
248 /* Read/write a pllcontrol reg */
249 u32
si_pmu_pllcontrol(struct si_pub
*sih
, uint reg
, u32 mask
, u32 val
)
251 ai_cc_reg(sih
, offsetof(struct chipcregs
, pllcontrol_addr
), ~0, reg
);
252 return ai_cc_reg(sih
, offsetof(struct chipcregs
, pllcontrol_data
),
257 void si_pmu_pllupd(struct si_pub
*sih
)
259 ai_cc_reg(sih
, offsetof(struct chipcregs
, pmucontrol
),
260 PCTL_PLL_PLLCTL_UPD
, PCTL_PLL_PLLCTL_UPD
);
263 /* query alp/xtal clock frequency */
264 u32
si_pmu_alp_clock(struct si_pub
*sih
)
266 u32 clock
= ALP_CLOCK
;
268 /* bail out with default */
269 if (!(ai_get_cccaps(sih
) & CC_CAP_PMU
))
272 switch (ai_get_chip_id(sih
)) {
273 case BCM43224_CHIP_ID
:
274 case BCM43225_CHIP_ID
:
275 case BCM4313_CHIP_ID
:
277 clock
= 20000 * 1000;
287 void si_pmu_init(struct si_pub
*sih
)
289 struct bcma_device
*core
;
292 core
= ai_findcore(sih
, BCMA_CORE_CHIPCOMMON
, 0);
294 if (ai_get_pmurev(sih
) == 1)
295 bcma_mask32(core
, CHIPCREGOFFS(pmucontrol
),
296 ~PCTL_NOILP_ON_WAIT
);
297 else if (ai_get_pmurev(sih
) >= 2)
298 bcma_set32(core
, CHIPCREGOFFS(pmucontrol
), PCTL_NOILP_ON_WAIT
);
301 /* initialize PMU resources */
302 void si_pmu_res_init(struct si_pub
*sih
)
304 struct bcma_device
*core
;
305 u32 min_mask
= 0, max_mask
= 0;
307 /* select to chipc */
308 core
= ai_findcore(sih
, BCMA_CORE_CHIPCOMMON
, 0);
310 /* Determine min/max rsrc masks */
311 si_pmu_res_masks(sih
, &min_mask
, &max_mask
);
313 /* It is required to program max_mask first and then min_mask */
315 /* Program max resource mask */
318 bcma_write32(core
, CHIPCREGOFFS(max_res_mask
), max_mask
);
320 /* Program min resource mask */
323 bcma_write32(core
, CHIPCREGOFFS(min_res_mask
), min_mask
);
325 /* Add some delay; allow resources to come up and settle. */
329 u32
si_pmu_measure_alpclk(struct si_pub
*sih
)
331 struct bcma_device
*core
;
334 if (ai_get_pmurev(sih
) < 10)
337 /* Remember original core before switch to chipc */
338 core
= ai_findcore(sih
, BCMA_CORE_CHIPCOMMON
, 0);
340 if (bcma_read32(core
, CHIPCREGOFFS(pmustatus
)) & PST_EXTLPOAVAIL
) {
344 * Enable the reg to measure the freq,
345 * in case it was disabled before
347 bcma_write32(core
, CHIPCREGOFFS(pmu_xtalfreq
),
348 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT
);
350 /* Delay for well over 4 ILP clocks */
353 /* Read the latched number of ALP ticks per 4 ILP ticks */
354 ilp_ctr
= bcma_read32(core
, CHIPCREGOFFS(pmu_xtalfreq
)) &
355 PMU_XTALFREQ_REG_ILPCTR_MASK
;
358 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
361 bcma_write32(core
, CHIPCREGOFFS(pmu_xtalfreq
), 0);
363 /* Calculate ALP frequency */
364 alp_hz
= (ilp_ctr
* EXT_ILP_HZ
) / 4;
367 * Round to nearest 100KHz, and at
368 * the same time convert to KHz
370 alp_khz
= (alp_hz
+ 50000) / 100000 * 100;