1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Broadcom specific AMBA
3*4882a593Smuzhiyun * ChipCommon Power Management Unit driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2009, Michael Buesch <m@bues.ch>
6*4882a593Smuzhiyun * Copyright 2007, 2011, Broadcom Corporation
7*4882a593Smuzhiyun * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Licensed under the GNU/GPL. See COPYING for details.
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "bcma_private.h"
13*4882a593Smuzhiyun #include <linux/export.h>
14*4882a593Smuzhiyun #include <linux/bcma/bcma.h>
15*4882a593Smuzhiyun
bcma_chipco_pll_read(struct bcma_drv_cc * cc,u32 offset)16*4882a593Smuzhiyun u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
17*4882a593Smuzhiyun {
18*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset);
19*4882a593Smuzhiyun bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR);
20*4882a593Smuzhiyun return bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA);
21*4882a593Smuzhiyun }
22*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(bcma_chipco_pll_read);
23*4882a593Smuzhiyun
bcma_chipco_pll_write(struct bcma_drv_cc * cc,u32 offset,u32 value)24*4882a593Smuzhiyun void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset);
27*4882a593Smuzhiyun bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR);
28*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value);
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
31*4882a593Smuzhiyun
bcma_chipco_pll_maskset(struct bcma_drv_cc * cc,u32 offset,u32 mask,u32 set)32*4882a593Smuzhiyun void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
33*4882a593Smuzhiyun u32 set)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset);
36*4882a593Smuzhiyun bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR);
37*4882a593Smuzhiyun bcma_pmu_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
40*4882a593Smuzhiyun
bcma_chipco_chipctl_maskset(struct bcma_drv_cc * cc,u32 offset,u32 mask,u32 set)41*4882a593Smuzhiyun void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
42*4882a593Smuzhiyun u32 offset, u32 mask, u32 set)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset);
45*4882a593Smuzhiyun bcma_pmu_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR);
46*4882a593Smuzhiyun bcma_pmu_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set);
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
49*4882a593Smuzhiyun
bcma_chipco_regctl_maskset(struct bcma_drv_cc * cc,u32 offset,u32 mask,u32 set)50*4882a593Smuzhiyun void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
51*4882a593Smuzhiyun u32 set)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset);
54*4882a593Smuzhiyun bcma_pmu_read32(cc, BCMA_CC_PMU_REGCTL_ADDR);
55*4882a593Smuzhiyun bcma_pmu_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
58*4882a593Smuzhiyun
bcma_pmu_xtalfreq(struct bcma_drv_cc * cc)59*4882a593Smuzhiyun static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun u32 ilp_ctl, alp_hz;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun if (!(bcma_pmu_read32(cc, BCMA_CC_PMU_STAT) &
64*4882a593Smuzhiyun BCMA_CC_PMU_STAT_EXT_LPO_AVAIL))
65*4882a593Smuzhiyun return 0;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ,
68*4882a593Smuzhiyun BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT));
69*4882a593Smuzhiyun usleep_range(1000, 2000);
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun ilp_ctl = bcma_pmu_read32(cc, BCMA_CC_PMU_XTAL_FREQ);
72*4882a593Smuzhiyun ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun alp_hz = ilp_ctl * 32768 / 4;
77*4882a593Smuzhiyun return (alp_hz + 50000) / 100000 * 100;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
bcma_pmu2_pll_init0(struct bcma_drv_cc * cc,u32 xtalfreq)80*4882a593Smuzhiyun static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
83*4882a593Smuzhiyun u32 freq_tgt_target = 0, freq_tgt_current;
84*4882a593Smuzhiyun u32 pll0, mask;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun switch (bus->chipinfo.id) {
87*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43142:
88*4882a593Smuzhiyun /* pmu2_xtaltab0_adfll_485 */
89*4882a593Smuzhiyun switch (xtalfreq) {
90*4882a593Smuzhiyun case 12000:
91*4882a593Smuzhiyun freq_tgt_target = 0x50D52;
92*4882a593Smuzhiyun break;
93*4882a593Smuzhiyun case 20000:
94*4882a593Smuzhiyun freq_tgt_target = 0x307FE;
95*4882a593Smuzhiyun break;
96*4882a593Smuzhiyun case 26000:
97*4882a593Smuzhiyun freq_tgt_target = 0x254EA;
98*4882a593Smuzhiyun break;
99*4882a593Smuzhiyun case 37400:
100*4882a593Smuzhiyun freq_tgt_target = 0x19EF8;
101*4882a593Smuzhiyun break;
102*4882a593Smuzhiyun case 52000:
103*4882a593Smuzhiyun freq_tgt_target = 0x12A75;
104*4882a593Smuzhiyun break;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun break;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun if (!freq_tgt_target) {
110*4882a593Smuzhiyun bcma_err(bus, "Unknown TGT frequency for xtalfreq %d\n",
111*4882a593Smuzhiyun xtalfreq);
112*4882a593Smuzhiyun return;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun pll0 = bcma_chipco_pll_read(cc, BCMA_CC_PMU15_PLL_PLLCTL0);
116*4882a593Smuzhiyun freq_tgt_current = (pll0 & BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK) >>
117*4882a593Smuzhiyun BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun if (freq_tgt_current == freq_tgt_target) {
120*4882a593Smuzhiyun bcma_debug(bus, "Target TGT frequency already set\n");
121*4882a593Smuzhiyun return;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /* Turn off PLL */
125*4882a593Smuzhiyun switch (bus->chipinfo.id) {
126*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43142:
127*4882a593Smuzhiyun mask = (u32)~(BCMA_RES_4314_HT_AVAIL |
128*4882a593Smuzhiyun BCMA_RES_4314_MACPHY_CLK_AVAIL);
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun bcma_pmu_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask);
131*4882a593Smuzhiyun bcma_pmu_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask);
132*4882a593Smuzhiyun bcma_wait_value(cc->core, BCMA_CLKCTLST,
133*4882a593Smuzhiyun BCMA_CLKCTLST_HAVEHT, 0, 20000);
134*4882a593Smuzhiyun break;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun pll0 &= ~BCMA_CC_PMU15_PLL_PC0_FREQTGT_MASK;
138*4882a593Smuzhiyun pll0 |= freq_tgt_target << BCMA_CC_PMU15_PLL_PC0_FREQTGT_SHIFT;
139*4882a593Smuzhiyun bcma_chipco_pll_write(cc, BCMA_CC_PMU15_PLL_PLLCTL0, pll0);
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /* Flush */
142*4882a593Smuzhiyun if (cc->pmu.rev >= 2)
143*4882a593Smuzhiyun bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun /* TODO: Do we need to update OTP? */
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
bcma_pmu_pll_init(struct bcma_drv_cc * cc)148*4882a593Smuzhiyun static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
151*4882a593Smuzhiyun u32 xtalfreq = bcma_pmu_xtalfreq(cc);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun switch (bus->chipinfo.id) {
154*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43142:
155*4882a593Smuzhiyun if (xtalfreq == 0)
156*4882a593Smuzhiyun xtalfreq = 20000;
157*4882a593Smuzhiyun bcma_pmu2_pll_init0(cc, xtalfreq);
158*4882a593Smuzhiyun break;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
bcma_pmu_resources_init(struct bcma_drv_cc * cc)162*4882a593Smuzhiyun static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
165*4882a593Smuzhiyun u32 min_msk = 0, max_msk = 0;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun switch (bus->chipinfo.id) {
168*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4313:
169*4882a593Smuzhiyun min_msk = 0x200D;
170*4882a593Smuzhiyun max_msk = 0xFFFF;
171*4882a593Smuzhiyun break;
172*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43142:
173*4882a593Smuzhiyun min_msk = BCMA_RES_4314_LPLDO_PU |
174*4882a593Smuzhiyun BCMA_RES_4314_PMU_SLEEP_DIS |
175*4882a593Smuzhiyun BCMA_RES_4314_PMU_BG_PU |
176*4882a593Smuzhiyun BCMA_RES_4314_CBUCK_LPOM_PU |
177*4882a593Smuzhiyun BCMA_RES_4314_CBUCK_PFM_PU |
178*4882a593Smuzhiyun BCMA_RES_4314_CLDO_PU |
179*4882a593Smuzhiyun BCMA_RES_4314_LPLDO2_LVM |
180*4882a593Smuzhiyun BCMA_RES_4314_WL_PMU_PU |
181*4882a593Smuzhiyun BCMA_RES_4314_LDO3P3_PU |
182*4882a593Smuzhiyun BCMA_RES_4314_OTP_PU |
183*4882a593Smuzhiyun BCMA_RES_4314_WL_PWRSW_PU |
184*4882a593Smuzhiyun BCMA_RES_4314_LQ_AVAIL |
185*4882a593Smuzhiyun BCMA_RES_4314_LOGIC_RET |
186*4882a593Smuzhiyun BCMA_RES_4314_MEM_SLEEP |
187*4882a593Smuzhiyun BCMA_RES_4314_MACPHY_RET |
188*4882a593Smuzhiyun BCMA_RES_4314_WL_CORE_READY;
189*4882a593Smuzhiyun max_msk = 0x3FFFFFFF;
190*4882a593Smuzhiyun break;
191*4882a593Smuzhiyun default:
192*4882a593Smuzhiyun bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n",
193*4882a593Smuzhiyun bus->chipinfo.id);
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun /* Set the resource masks. */
197*4882a593Smuzhiyun if (min_msk)
198*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk);
199*4882a593Smuzhiyun if (max_msk)
200*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk);
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /*
203*4882a593Smuzhiyun * Add some delay; allow resources to come up and settle.
204*4882a593Smuzhiyun * Delay is required for SoC (early init).
205*4882a593Smuzhiyun */
206*4882a593Smuzhiyun usleep_range(2000, 2500);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun /* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc * cc,bool enable)210*4882a593Smuzhiyun void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
213*4882a593Smuzhiyun u32 val;
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL);
216*4882a593Smuzhiyun if (enable) {
217*4882a593Smuzhiyun val |= BCMA_CHIPCTL_4331_EXTPA_EN;
218*4882a593Smuzhiyun if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
219*4882a593Smuzhiyun val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
220*4882a593Smuzhiyun else if (bus->chipinfo.rev > 0)
221*4882a593Smuzhiyun val |= BCMA_CHIPCTL_4331_EXTPA_EN2;
222*4882a593Smuzhiyun } else {
223*4882a593Smuzhiyun val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
224*4882a593Smuzhiyun val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2;
225*4882a593Smuzhiyun val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
bcma_pmu_workarounds(struct bcma_drv_cc * cc)230*4882a593Smuzhiyun static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun switch (bus->chipinfo.id) {
235*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4313:
236*4882a593Smuzhiyun /*
237*4882a593Smuzhiyun * enable 12 mA drive strenth for 4313 and set chipControl
238*4882a593Smuzhiyun * register bit 1
239*4882a593Smuzhiyun */
240*4882a593Smuzhiyun bcma_chipco_chipctl_maskset(cc, 0,
241*4882a593Smuzhiyun ~BCMA_CCTRL_4313_12MA_LED_DRIVE,
242*4882a593Smuzhiyun BCMA_CCTRL_4313_12MA_LED_DRIVE);
243*4882a593Smuzhiyun break;
244*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4331:
245*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43431:
246*4882a593Smuzhiyun /* Ext PA lines must be enabled for tx on BCM4331 */
247*4882a593Smuzhiyun bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true);
248*4882a593Smuzhiyun break;
249*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43224:
250*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43421:
251*4882a593Smuzhiyun /*
252*4882a593Smuzhiyun * enable 12 mA drive strenth for 43224 and set chipControl
253*4882a593Smuzhiyun * register bit 15
254*4882a593Smuzhiyun */
255*4882a593Smuzhiyun if (bus->chipinfo.rev == 0) {
256*4882a593Smuzhiyun bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL,
257*4882a593Smuzhiyun ~BCMA_CCTRL_43224_GPIO_TOGGLE,
258*4882a593Smuzhiyun BCMA_CCTRL_43224_GPIO_TOGGLE);
259*4882a593Smuzhiyun bcma_chipco_chipctl_maskset(cc, 0,
260*4882a593Smuzhiyun ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
261*4882a593Smuzhiyun BCMA_CCTRL_43224A0_12MA_LED_DRIVE);
262*4882a593Smuzhiyun } else {
263*4882a593Smuzhiyun bcma_chipco_chipctl_maskset(cc, 0,
264*4882a593Smuzhiyun ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
265*4882a593Smuzhiyun BCMA_CCTRL_43224B0_12MA_LED_DRIVE);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun break;
268*4882a593Smuzhiyun default:
269*4882a593Smuzhiyun bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n",
270*4882a593Smuzhiyun bus->chipinfo.id);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
bcma_pmu_early_init(struct bcma_drv_cc * cc)274*4882a593Smuzhiyun void bcma_pmu_early_init(struct bcma_drv_cc *cc)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
277*4882a593Smuzhiyun u32 pmucap;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun if (cc->core->id.rev >= 35 &&
280*4882a593Smuzhiyun cc->capabilities_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) {
281*4882a593Smuzhiyun cc->pmu.core = bcma_find_core(bus, BCMA_CORE_PMU);
282*4882a593Smuzhiyun if (!cc->pmu.core)
283*4882a593Smuzhiyun bcma_warn(bus, "Couldn't find expected PMU core");
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun if (!cc->pmu.core)
286*4882a593Smuzhiyun cc->pmu.core = cc->core;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun pmucap = bcma_pmu_read32(cc, BCMA_CC_PMU_CAP);
289*4882a593Smuzhiyun cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION);
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun bcma_debug(bus, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev,
292*4882a593Smuzhiyun pmucap);
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
bcma_pmu_init(struct bcma_drv_cc * cc)295*4882a593Smuzhiyun void bcma_pmu_init(struct bcma_drv_cc *cc)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun if (cc->pmu.rev == 1)
298*4882a593Smuzhiyun bcma_pmu_mask32(cc, BCMA_CC_PMU_CTL,
299*4882a593Smuzhiyun ~BCMA_CC_PMU_CTL_NOILPONW);
300*4882a593Smuzhiyun else
301*4882a593Smuzhiyun bcma_pmu_set32(cc, BCMA_CC_PMU_CTL,
302*4882a593Smuzhiyun BCMA_CC_PMU_CTL_NOILPONW);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun bcma_pmu_pll_init(cc);
305*4882a593Smuzhiyun bcma_pmu_resources_init(cc);
306*4882a593Smuzhiyun bcma_pmu_workarounds(cc);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
bcma_pmu_get_alp_clock(struct bcma_drv_cc * cc)309*4882a593Smuzhiyun u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun switch (bus->chipinfo.id) {
314*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4313:
315*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43224:
316*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43225:
317*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43227:
318*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43228:
319*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4331:
320*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43421:
321*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43428:
322*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43431:
323*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4716:
324*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM47162:
325*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4748:
326*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4749:
327*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM5357:
328*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM53572:
329*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM6362:
330*4882a593Smuzhiyun /* always 20Mhz */
331*4882a593Smuzhiyun return 20000 * 1000;
332*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4706:
333*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM5356:
334*4882a593Smuzhiyun /* always 25Mhz */
335*4882a593Smuzhiyun return 25000 * 1000;
336*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43460:
337*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4352:
338*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4360:
339*4882a593Smuzhiyun if (cc->status & BCMA_CC_CHIPST_4360_XTAL_40MZ)
340*4882a593Smuzhiyun return 40000 * 1000;
341*4882a593Smuzhiyun else
342*4882a593Smuzhiyun return 20000 * 1000;
343*4882a593Smuzhiyun default:
344*4882a593Smuzhiyun bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
345*4882a593Smuzhiyun bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun return BCMA_CC_PMU_ALP_CLOCK;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /* Find the output of the "m" pll divider given pll controls that start with
351*4882a593Smuzhiyun * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
352*4882a593Smuzhiyun */
bcma_pmu_pll_clock(struct bcma_drv_cc * cc,u32 pll0,u32 m)353*4882a593Smuzhiyun static u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun u32 tmp, div, ndiv, p1, p2, fc;
356*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun BUG_ON((pll0 & 3) || (pll0 > BCMA_CC_PMU4716_MAINPLL_PLL0));
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun BUG_ON(!m || m > 4);
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
363*4882a593Smuzhiyun bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) {
364*4882a593Smuzhiyun /* Detect failure in clock setting */
365*4882a593Smuzhiyun tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
366*4882a593Smuzhiyun if (tmp & 0x40000)
367*4882a593Smuzhiyun return 133 * 1000000;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_P1P2_OFF);
371*4882a593Smuzhiyun p1 = (tmp & BCMA_CC_PPL_P1_MASK) >> BCMA_CC_PPL_P1_SHIFT;
372*4882a593Smuzhiyun p2 = (tmp & BCMA_CC_PPL_P2_MASK) >> BCMA_CC_PPL_P2_SHIFT;
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_M14_OFF);
375*4882a593Smuzhiyun div = (tmp >> ((m - 1) * BCMA_CC_PPL_MDIV_WIDTH)) &
376*4882a593Smuzhiyun BCMA_CC_PPL_MDIV_MASK;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PPL_NM5_OFF);
379*4882a593Smuzhiyun ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun /* Do calculation in Mhz */
382*4882a593Smuzhiyun fc = bcma_pmu_get_alp_clock(cc) / 1000000;
383*4882a593Smuzhiyun fc = (p1 * ndiv * fc) / p2;
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun /* Return clock in Hertz */
386*4882a593Smuzhiyun return (fc / div) * 1000000;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc * cc,u32 pll0,u32 m)389*4882a593Smuzhiyun static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun u32 tmp, ndiv, p1div, p2div;
392*4882a593Smuzhiyun u32 clock;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun BUG_ON(!m || m > 4);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* Get N, P1 and P2 dividers to determine CPU clock */
397*4882a593Smuzhiyun tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF);
398*4882a593Smuzhiyun ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK)
399*4882a593Smuzhiyun >> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT;
400*4882a593Smuzhiyun p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK)
401*4882a593Smuzhiyun >> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT;
402*4882a593Smuzhiyun p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK)
403*4882a593Smuzhiyun >> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT;
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
406*4882a593Smuzhiyun if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION)
407*4882a593Smuzhiyun /* Low cost bonding: Fixed reference clock 25MHz and m = 4 */
408*4882a593Smuzhiyun clock = (25000000 / 4) * ndiv * p2div / p1div;
409*4882a593Smuzhiyun else
410*4882a593Smuzhiyun /* Fixed reference clock 25MHz and m = 2 */
411*4882a593Smuzhiyun clock = (25000000 / 2) * ndiv * p2div / p1div;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun if (m == BCMA_CC_PMU5_MAINPLL_SSB)
414*4882a593Smuzhiyun clock = clock / 4;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun return clock;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun /* query bus clock frequency for PMU-enabled chipcommon */
bcma_pmu_get_bus_clock(struct bcma_drv_cc * cc)420*4882a593Smuzhiyun u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun switch (bus->chipinfo.id) {
425*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4716:
426*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4748:
427*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM47162:
428*4882a593Smuzhiyun return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
429*4882a593Smuzhiyun BCMA_CC_PMU5_MAINPLL_SSB);
430*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM5356:
431*4882a593Smuzhiyun return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
432*4882a593Smuzhiyun BCMA_CC_PMU5_MAINPLL_SSB);
433*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM5357:
434*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4749:
435*4882a593Smuzhiyun return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
436*4882a593Smuzhiyun BCMA_CC_PMU5_MAINPLL_SSB);
437*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4706:
438*4882a593Smuzhiyun return bcma_pmu_pll_clock_bcm4706(cc,
439*4882a593Smuzhiyun BCMA_CC_PMU4706_MAINPLL_PLL0,
440*4882a593Smuzhiyun BCMA_CC_PMU5_MAINPLL_SSB);
441*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM53572:
442*4882a593Smuzhiyun return 75000000;
443*4882a593Smuzhiyun default:
444*4882a593Smuzhiyun bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
445*4882a593Smuzhiyun bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun return BCMA_CC_PMU_HT_CLOCK;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(bcma_pmu_get_bus_clock);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun /* query cpu clock frequency for PMU-enabled chipcommon */
bcma_pmu_get_cpu_clock(struct bcma_drv_cc * cc)452*4882a593Smuzhiyun u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572)
457*4882a593Smuzhiyun return 300000000;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun /* New PMUs can have different clock for bus and CPU */
460*4882a593Smuzhiyun if (cc->pmu.rev >= 5) {
461*4882a593Smuzhiyun u32 pll;
462*4882a593Smuzhiyun switch (bus->chipinfo.id) {
463*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4706:
464*4882a593Smuzhiyun return bcma_pmu_pll_clock_bcm4706(cc,
465*4882a593Smuzhiyun BCMA_CC_PMU4706_MAINPLL_PLL0,
466*4882a593Smuzhiyun BCMA_CC_PMU5_MAINPLL_CPU);
467*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM5356:
468*4882a593Smuzhiyun pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
469*4882a593Smuzhiyun break;
470*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM5357:
471*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4749:
472*4882a593Smuzhiyun pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
473*4882a593Smuzhiyun break;
474*4882a593Smuzhiyun default:
475*4882a593Smuzhiyun pll = BCMA_CC_PMU4716_MAINPLL_PLL0;
476*4882a593Smuzhiyun break;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun /* On old PMUs CPU has the same clock as the bus */
483*4882a593Smuzhiyun return bcma_pmu_get_bus_clock(cc);
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun
bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc * cc,u32 offset,u32 value)486*4882a593Smuzhiyun static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset,
487*4882a593Smuzhiyun u32 value)
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset);
490*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value);
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc * cc,int spuravoid)493*4882a593Smuzhiyun void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun u32 tmp = 0;
496*4882a593Smuzhiyun u8 phypll_offset = 0;
497*4882a593Smuzhiyun u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5};
498*4882a593Smuzhiyun u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc};
499*4882a593Smuzhiyun struct bcma_bus *bus = cc->core->bus;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun switch (bus->chipinfo.id) {
502*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM5357:
503*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4749:
504*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM53572:
505*4882a593Smuzhiyun /* 5357[ab]0, 43236[ab]0, and 6362b0 */
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun /*
508*4882a593Smuzhiyun * BCM5357 needs to touch PLL1_PLLCTL[02],
509*4882a593Smuzhiyun * so offset PLL0_PLLCTL[02] by 6
510*4882a593Smuzhiyun */
511*4882a593Smuzhiyun phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
512*4882a593Smuzhiyun bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 ||
513*4882a593Smuzhiyun bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0;
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun /* RMW only the P1 divider */
516*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR,
517*4882a593Smuzhiyun BCMA_CC_PMU_PLL_CTL0 + phypll_offset);
518*4882a593Smuzhiyun tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA);
519*4882a593Smuzhiyun tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK));
520*4882a593Smuzhiyun tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT);
521*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp);
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun /* RMW only the int feedback divider */
524*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR,
525*4882a593Smuzhiyun BCMA_CC_PMU_PLL_CTL2 + phypll_offset);
526*4882a593Smuzhiyun tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA);
527*4882a593Smuzhiyun tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK);
528*4882a593Smuzhiyun tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
529*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp);
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun tmp = BCMA_CC_PMU_CTL_PLL_UPD;
532*4882a593Smuzhiyun break;
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4331:
535*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43431:
536*4882a593Smuzhiyun if (spuravoid == 2) {
537*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
538*4882a593Smuzhiyun 0x11500014);
539*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
540*4882a593Smuzhiyun 0x0FC00a08);
541*4882a593Smuzhiyun } else if (spuravoid == 1) {
542*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
543*4882a593Smuzhiyun 0x11500014);
544*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
545*4882a593Smuzhiyun 0x0F600a08);
546*4882a593Smuzhiyun } else {
547*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
548*4882a593Smuzhiyun 0x11100014);
549*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
550*4882a593Smuzhiyun 0x03000a08);
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun tmp = BCMA_CC_PMU_CTL_PLL_UPD;
553*4882a593Smuzhiyun break;
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43224:
556*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43225:
557*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43421:
558*4882a593Smuzhiyun if (spuravoid == 1) {
559*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
560*4882a593Smuzhiyun 0x11500010);
561*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
562*4882a593Smuzhiyun 0x000C0C06);
563*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
564*4882a593Smuzhiyun 0x0F600a08);
565*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
566*4882a593Smuzhiyun 0x00000000);
567*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
568*4882a593Smuzhiyun 0x2001E920);
569*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
570*4882a593Smuzhiyun 0x88888815);
571*4882a593Smuzhiyun } else {
572*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
573*4882a593Smuzhiyun 0x11100010);
574*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
575*4882a593Smuzhiyun 0x000c0c06);
576*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
577*4882a593Smuzhiyun 0x03000a08);
578*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
579*4882a593Smuzhiyun 0x00000000);
580*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
581*4882a593Smuzhiyun 0x200005c0);
582*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
583*4882a593Smuzhiyun 0x88888815);
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun tmp = BCMA_CC_PMU_CTL_PLL_UPD;
586*4882a593Smuzhiyun break;
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4716:
589*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM4748:
590*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM47162:
591*4882a593Smuzhiyun if (spuravoid == 1) {
592*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
593*4882a593Smuzhiyun 0x11500060);
594*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
595*4882a593Smuzhiyun 0x080C0C06);
596*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
597*4882a593Smuzhiyun 0x0F600000);
598*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
599*4882a593Smuzhiyun 0x00000000);
600*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
601*4882a593Smuzhiyun 0x2001E924);
602*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
603*4882a593Smuzhiyun 0x88888815);
604*4882a593Smuzhiyun } else {
605*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
606*4882a593Smuzhiyun 0x11100060);
607*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
608*4882a593Smuzhiyun 0x080c0c06);
609*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
610*4882a593Smuzhiyun 0x03000000);
611*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
612*4882a593Smuzhiyun 0x00000000);
613*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
614*4882a593Smuzhiyun 0x200005c0);
615*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
616*4882a593Smuzhiyun 0x88888815);
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
620*4882a593Smuzhiyun break;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43131:
623*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43217:
624*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43227:
625*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43228:
626*4882a593Smuzhiyun case BCMA_CHIP_ID_BCM43428:
627*4882a593Smuzhiyun /* LCNXN */
628*4882a593Smuzhiyun /*
629*4882a593Smuzhiyun * PLL Settings for spur avoidance on/off mode,
630*4882a593Smuzhiyun * no on2 support for 43228A0
631*4882a593Smuzhiyun */
632*4882a593Smuzhiyun if (spuravoid == 1) {
633*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
634*4882a593Smuzhiyun 0x01100014);
635*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
636*4882a593Smuzhiyun 0x040C0C06);
637*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
638*4882a593Smuzhiyun 0x03140A08);
639*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
640*4882a593Smuzhiyun 0x00333333);
641*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
642*4882a593Smuzhiyun 0x202C2820);
643*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
644*4882a593Smuzhiyun 0x88888815);
645*4882a593Smuzhiyun } else {
646*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
647*4882a593Smuzhiyun 0x11100014);
648*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
649*4882a593Smuzhiyun 0x040c0c06);
650*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
651*4882a593Smuzhiyun 0x03000a08);
652*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
653*4882a593Smuzhiyun 0x00000000);
654*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
655*4882a593Smuzhiyun 0x200005c0);
656*4882a593Smuzhiyun bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
657*4882a593Smuzhiyun 0x88888815);
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun tmp = BCMA_CC_PMU_CTL_PLL_UPD;
660*4882a593Smuzhiyun break;
661*4882a593Smuzhiyun default:
662*4882a593Smuzhiyun bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
663*4882a593Smuzhiyun bus->chipinfo.id);
664*4882a593Smuzhiyun break;
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun tmp |= bcma_pmu_read32(cc, BCMA_CC_PMU_CTL);
668*4882a593Smuzhiyun bcma_pmu_write32(cc, BCMA_CC_PMU_CTL, tmp);
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate);
671