• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2011 Broadcom Corporation
3  *
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.
7  *
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.
15  */
16 
17 #include <linux/delay.h>
18 #include <linux/io.h>
19 
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"
27 
28 /*
29  * external LPO crystal frequency
30  */
31 #define EXT_ILP_HZ 32768
32 
33 /*
34  * Duration for ILP clock frequency measurment in milliseconds
35  *
36  * remark: 1000 must be an integer multiple of this duration
37  */
38 #define ILP_CALC_DUR	10
39 
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
51 
52 /* ILP clock */
53 #define	ILP_CLOCK		32000
54 
55 /* ALP clock on pre-PMU chips */
56 #define	ALP_CLOCK		20000000
57 
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
69 
70 /* PMU resource bit position */
71 #define PMURES_BIT(bit)	(1 << (bit))
72 
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.
76  */
77 /* pllcontrol registers:
78  * ndiv_pwrdn, pwrdn_ch<x>, refcomp_pwrdn, dly_ch<x>,
79  * p1div, p2div, _bypass_sdmod
80  */
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
87 
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
92 
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
110 
111 /* Determine min/max rsrc masks. Value 0 leaves hardware at default. */
si_pmu_res_masks(struct si_pub * sih,u32 * pmin,u32 * pmax)112 static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
113 {
114 	u32 min_mask = 0, max_mask = 0;
115 	uint rsrcs;
116 
117 	/* # resources */
118 	rsrcs = (ai_get_pmucaps(sih) & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
119 
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;
126 
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;
136 	}
137 
138 	*pmin = min_mask;
139 	*pmax = max_mask;
140 }
141 
si_pmu_spuravoid_pllupdate(struct si_pub * sih,u8 spuravoid)142 void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid)
143 {
144 	u32 tmp = 0;
145 	struct bcma_device *core;
146 
147 	/* switch to chipc */
148 	core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
149 
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);
203 		}
204 		tmp = 1 << 10;
205 		break;
206 
207 	default:
208 		/* bail out */
209 		return;
210 	}
211 
212 	bcma_set32(core, CHIPCREGOFFS(pmucontrol), tmp);
213 }
214 
si_pmu_fast_pwrup_delay(struct si_pub * sih)215 u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
216 {
217 	uint delay = PMU_MAX_TRANSITION_DLY;
218 
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;
227 	}
228 
229 	return (u16) delay;
230 }
231 
232 /* Read/write a chipcontrol reg */
si_pmu_chipcontrol(struct si_pub * sih,uint reg,u32 mask,u32 val)233 u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
234 {
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);
238 }
239 
240 /* Read/write a regcontrol reg */
si_pmu_regcontrol(struct si_pub * sih,uint reg,u32 mask,u32 val)241 u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
242 {
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);
246 }
247 
248 /* Read/write a pllcontrol reg */
si_pmu_pllcontrol(struct si_pub * sih,uint reg,u32 mask,u32 val)249 u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
250 {
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);
254 }
255 
256 /* PMU PLL update */
si_pmu_pllupd(struct si_pub * sih)257 void si_pmu_pllupd(struct si_pub *sih)
258 {
259 	ai_cc_reg(sih, offsetof(struct chipcregs, pmucontrol),
260 		  PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
261 }
262 
263 /* query alp/xtal clock frequency */
si_pmu_alp_clock(struct si_pub * sih)264 u32 si_pmu_alp_clock(struct si_pub *sih)
265 {
266 	u32 clock = ALP_CLOCK;
267 
268 	/* bail out with default */
269 	if (!(ai_get_cccaps(sih) & CC_CAP_PMU))
270 		return clock;
271 
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;
281 	}
282 
283 	return clock;
284 }
285 
286 /* initialize PMU */
si_pmu_init(struct si_pub * sih)287 void si_pmu_init(struct si_pub *sih)
288 {
289 	struct bcma_device *core;
290 
291 	/* select chipc */
292 	core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
293 
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);
299 }
300 
301 /* initialize PMU resources */
si_pmu_res_init(struct si_pub * sih)302 void si_pmu_res_init(struct si_pub *sih)
303 {
304 	struct bcma_device *core;
305 	u32 min_mask = 0, max_mask = 0;
306 
307 	/* select to chipc */
308 	core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
309 
310 	/* Determine min/max rsrc masks */
311 	si_pmu_res_masks(sih, &min_mask, &max_mask);
312 
313 	/* It is required to program max_mask first and then min_mask */
314 
315 	/* Program max resource mask */
316 
317 	if (max_mask)
318 		bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask);
319 
320 	/* Program min resource mask */
321 
322 	if (min_mask)
323 		bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask);
324 
325 	/* Add some delay; allow resources to come up and settle. */
326 	mdelay(2);
327 }
328 
si_pmu_measure_alpclk(struct si_pub * sih)329 u32 si_pmu_measure_alpclk(struct si_pub *sih)
330 {
331 	struct bcma_device *core;
332 	u32 alp_khz;
333 
334 	if (ai_get_pmurev(sih) < 10)
335 		return 0;
336 
337 	/* Remember original core before switch to chipc */
338 	core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
339 
340 	if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) {
341 		u32 ilp_ctr, alp_hz;
342 
343 		/*
344 		 * Enable the reg to measure the freq,
345 		 * in case it was disabled before
346 		 */
347 		bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq),
348 			    1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
349 
350 		/* Delay for well over 4 ILP clocks */
351 		udelay(1000);
352 
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;
356 
357 		/*
358 		 * Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
359 		 * bit to save power
360 		 */
361 		bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 0);
362 
363 		/* Calculate ALP frequency */
364 		alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
365 
366 		/*
367 		 * Round to nearest 100KHz, and at
368 		 * the same time convert to KHz
369 		 */
370 		alp_khz = (alp_hz + 50000) / 100000 * 100;
371 	} else
372 		alp_khz = 0;
373 
374 	return alp_khz;
375 }
376