spi-topcliff-pch: add recovery processing in case wait-event timeout
[zen-stable.git] / drivers / net / wireless / brcm80211 / brcmsmac / pmu.c
blob4931d29d077bf6e45b6ff1b5ed2045aa7102af61
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"
26 #include "soc.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
52 /* ILP clock */
53 #define ILP_CLOCK 32000
55 /* ALP clock on pre-PMU chips */
56 #define ALP_CLOCK 20000000
58 /* pmustatus */
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
93 /* 4313 resources */
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;
115 uint rsrcs;
117 /* # resources */
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:
124 /* ??? */
125 break;
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);
132 max_mask = 0xffff;
133 break;
134 default:
135 break;
138 *pmin = min_mask;
139 *pmax = max_mask;
142 void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid)
144 u32 tmp = 0;
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),
155 PMU1_PLL0_PLLCTL0);
156 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
157 0x11500010);
158 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
159 PMU1_PLL0_PLLCTL1);
160 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
161 0x000C0C06);
162 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
163 PMU1_PLL0_PLLCTL2);
164 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
165 0x0F600a08);
166 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
167 PMU1_PLL0_PLLCTL3);
168 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
169 0x00000000);
170 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
171 PMU1_PLL0_PLLCTL4);
172 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
173 0x2001E920);
174 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
175 PMU1_PLL0_PLLCTL5);
176 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
177 0x88888815);
178 } else {
179 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
180 PMU1_PLL0_PLLCTL0);
181 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
182 0x11100010);
183 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
184 PMU1_PLL0_PLLCTL1);
185 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
186 0x000c0c06);
187 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
188 PMU1_PLL0_PLLCTL2);
189 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
190 0x03000a08);
191 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
192 PMU1_PLL0_PLLCTL3);
193 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
194 0x00000000);
195 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
196 PMU1_PLL0_PLLCTL4);
197 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
198 0x200005c0);
199 bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
200 PMU1_PLL0_PLLCTL5);
201 bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
202 0x88888815);
204 tmp = 1 << 10;
205 break;
207 default:
208 /* bail out */
209 return;
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:
223 delay = 3700;
224 break;
225 default:
226 break;
229 return (u16) delay;
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),
237 mask, val);
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),
245 mask, val);
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),
253 mask, val);
256 /* PMU PLL update */
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))
270 return clock;
272 switch (ai_get_chip_id(sih)) {
273 case BCM43224_CHIP_ID:
274 case BCM43225_CHIP_ID:
275 case BCM4313_CHIP_ID:
276 /* always 20Mhz */
277 clock = 20000 * 1000;
278 break;
279 default:
280 break;
283 return clock;
286 /* initialize PMU */
287 void si_pmu_init(struct si_pub *sih)
289 struct bcma_device *core;
291 /* select chipc */
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 */
317 if (max_mask)
318 bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask);
320 /* Program min resource mask */
322 if (min_mask)
323 bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask);
325 /* Add some delay; allow resources to come up and settle. */
326 mdelay(2);
329 u32 si_pmu_measure_alpclk(struct si_pub *sih)
331 struct bcma_device *core;
332 u32 alp_khz;
334 if (ai_get_pmurev(sih) < 10)
335 return 0;
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) {
341 u32 ilp_ctr, alp_hz;
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 */
351 udelay(1000);
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
359 * bit to save power
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;
371 } else
372 alp_khz = 0;
374 return alp_khz;