sysfs: Remove support for tagged directories with untagged members (again)
[linux-btrfs-devel.git] / drivers / staging / brcm80211 / brcmsmac / pmu.c
blobe8b2b81d2d040faad9ad1459b1e9791017bf322f
1 /*
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>
18 #include <linux/io.h>
20 #include <brcm_hw_ids.h>
21 #include <chipcommon.h>
22 #include <brcmu_utils.h>
23 #include "pub.h"
24 #include "aiutils.h"
25 #include "pmu.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
51 /* ILP clock */
52 #define ILP_CLOCK 32000
54 /* ALP clock on pre-PMU chips */
55 #define ALP_CLOCK 20000000
57 /* pmustatus */
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
90 /* 4313 resources */
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;
112 uint rsrcs;
114 /* # resources */
115 rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
117 /* determine min/max rsrc masks */
118 switch (sih->chip) {
119 case BCM43224_CHIP_ID:
120 case BCM43225_CHIP_ID:
121 /* ??? */
122 break;
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);
129 max_mask = 0xffff;
130 break;
131 default:
132 break;
135 *pmin = min_mask;
136 *pmax = max_mask;
139 static void
140 si_pmu_spuravoid_pllupdate(struct si_pub *sih, chipcregs_t *cc, u8 spuravoid)
142 u32 tmp = 0;
144 switch (sih->chip) {
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);
160 } else {
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);
174 tmp = 1 << 10;
175 break;
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);
190 tmp = 1 << 10;
191 break;
193 default:
194 /* bail out */
195 return;
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))
207 return ILP_CLOCK;
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);
216 delta = end - start;
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;
228 switch (sih->chip) {
229 case BCM43224_CHIP_ID:
230 case BCM43225_CHIP_ID:
231 case BCM4313_CHIP_ID:
232 delay = 3700;
233 break;
234 default:
235 break;
238 return (u16) delay;
241 void si_pmu_sprom_enable(struct si_pub *sih, bool enable)
243 chipcregs_t *cc;
244 uint origidx;
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,
258 reg);
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,
267 reg);
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,
276 reg);
277 return ai_corereg(sih, SI_CC_IDX,
278 offsetof(chipcregs_t, pllcontrol_data), mask, val);
281 /* PMU PLL update */
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))
295 return clock;
297 switch (sih->chip) {
298 case BCM43224_CHIP_ID:
299 case BCM43225_CHIP_ID:
300 case BCM4313_CHIP_ID:
301 /* always 20Mhz */
302 clock = 20000 * 1000;
303 break;
304 default:
305 break;
308 return clock;
311 void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid)
313 chipcregs_t *cc;
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,
318 &intr_val);
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);
327 /* initialize PMU */
328 void si_pmu_init(struct si_pub *sih)
330 chipcregs_t *cc;
331 uint origidx;
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)
349 uint origidx;
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)
366 /* initialize PLL */
367 void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq)
369 chipcregs_t *cc;
370 uint origidx;
372 /* Remember original core before switch to chipc */
373 origidx = ai_coreidx(sih);
374 cc = ai_setcoreidx(sih, SI_CC_IDX);
376 switch (sih->chip) {
377 case BCM4313_CHIP_ID:
378 case BCM43224_CHIP_ID:
379 case BCM43225_CHIP_ID:
380 /* ??? */
381 break;
382 default:
383 break;
386 /* Return to original core */
387 ai_setcoreidx(sih, origidx);
390 /* initialize PMU resources */
391 void si_pmu_res_init(struct si_pub *sih)
393 chipcregs_t *cc;
394 uint origidx;
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 */
408 if (max_mask)
409 W_REG(&cc->max_res_mask, max_mask);
411 /* Program min resource mask */
413 if (min_mask)
414 W_REG(&cc->min_res_mask, min_mask);
416 /* Add some delay; allow resources to come up and settle. */
417 mdelay(2);
419 /* Return to original core */
420 ai_setcoreidx(sih, origidx);
423 u32 si_pmu_measure_alpclk(struct si_pub *sih)
425 chipcregs_t *cc;
426 uint origidx;
427 u32 alp_khz;
429 if (sih->pmurev < 10)
430 return 0;
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) {
437 u32 ilp_ctr, alp_hz;
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 */
447 udelay(1000);
449 /* Read the latched number of ALP ticks per 4 ILP ticks */
450 ilp_ctr =
451 R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
454 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
455 * bit to save power
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;
467 } else
468 alp_khz = 0;
470 /* Return to original core */
471 ai_setcoreidx(sih, origidx);
473 return alp_khz;