1 /*
2 * Misc utility routines for accessing PMU corerev specific features
3 * of the SiliconBackplane-based Broadcom chips.
4 *
5 * Copyright (C) 2020, Broadcom.
6 *
7 * Unless you and Broadcom execute a separate written software license
8 * agreement governing use of this software, this software is licensed to you
9 * under the terms of the GNU General Public License version 2 (the "GPL"),
10 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11 * following added to such license:
12 *
13 * As a special exception, the copyright holders of this software give you
14 * permission to link this software with independent modules, and to copy and
15 * distribute the resulting executable under terms of your choice, provided that
16 * you also meet, for each linked independent module, the terms and conditions of
17 * the license of that module. An independent module is a module which is not
18 * derived from this software. The special exception does not apply to any
19 * modifications of the software.
20 *
21 *
22 * <<Broadcom-WL-IPTag/Dual:>>
23 */
24
25 /**
26 * @file
27 * Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs.
28 * However, in the context of this file the baseband ('BB') PLL/FLL is referred to.
29 *
30 * Throughout this code, the prefixes 'pmu1_' and 'pmu2_' are used.
31 * They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012)
32 * pmu1_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop). It supports
33 * fractional frequency generation. pmu2_ does not support fractional frequency generation.
34 */
35
36 #include <typedefs.h>
37 #include <bcmdefs.h>
38 #include <osl.h>
39 #include <bcmutils.h>
40 #include <siutils.h>
41 #include <bcmdevs.h>
42 #include <hndsoc.h>
43 #include <sbchipc.h>
44 #include <hndchipc.h>
45 #include <hndpmu.h>
46 #if defined DONGLEBUILD
47 #include <hndcpu.h>
48 #ifdef __arm__
49 #include <hndarm.h>
50 #endif
51 #endif /* DONGLEBUILD */
52 #if !defined(BCMDONGLEHOST)
53 #include <bcm_math.h>
54 #include <bcmotp.h>
55 #ifdef BCM_OTP_API
56 #include <bcm_otp_api.h>
57 #endif /* BCM_OTP_API */
58 #endif /* !BCMDONGLEHOST */
59 #if !defined(BCMDONGLEHOST)
60 #include <saverestore.h>
61 #endif
62 #include <hndlhl.h>
63 #include <sbgci.h>
64 #ifdef EVENT_LOG_COMPILE
65 #include <event_log.h>
66 #endif
67 #include <sbgci.h>
68 #include <lpflags.h>
69
70 #include "siutils_priv.h"
71
72 #ifdef BCM_AVS
73 #include <bcm_avs.h>
74 #endif
75
76 #if defined(EVENT_LOG_COMPILE) && defined(BCMDBG_ERR) && defined(ERR_USE_EVENT_LOG)
77 #if defined(ERR_USE_EVENT_LOG_RA)
78 #define PMU_ERROR(args) EVENT_LOG_RA(EVENT_LOG_TAG_PMU_ERROR, args)
79 #else
80 #define PMU_ERROR(args) EVENT_LOG_COMPACT_CAST_PAREN_ARGS(EVENT_LOG_TAG_PMU_ERROR, args)
81 #endif /* ERR_USE_EVENT_LOG_RA */
82 #elif defined(BCMDBG_ERR)
83 #define PMU_ERROR(args) printf args
84 #else
85 #define PMU_ERROR(args)
86 #endif /* defined(BCMDBG_ERR) && defined(ERR_USE_EVENT_LOG) */
87
88 #ifdef BCMDBG
89 //#define BCMDBG_PMU
90 #endif
91
92 #ifdef BCMDBG_PMU
93 #define PMU_MSG(args) printf args
94 #else
95 #define PMU_MSG(args)
96 #endif /* BCMDBG_MPU */
97
98 /* To check in verbose debugging messages not intended
99 * to be on except on private builds.
100 */
101 #define PMU_NONE(args)
102 #define flags_shift 14
103
104 /** contains resource bit positions for a specific chip */
105 struct rsc_per_chip {
106 uint8 ht_avail;
107 uint8 macphy_clkavail;
108 uint8 ht_start;
109 uint8 otp_pu;
110 uint8 macphy_aux_clkavail;
111 uint8 macphy_scan_clkavail;
112 uint8 cb_ready;
113 uint8 dig_ready;
114 };
115
116 typedef struct rsc_per_chip rsc_per_chip_t;
117
118 #if defined(BCMPMU_STATS) && !defined(BCMPMU_STATS_DISABLED)
119 bool _pmustatsenab = TRUE;
120 #else
121 bool _pmustatsenab = FALSE;
122 #endif /* BCMPMU_STATS */
123
124 /* 1MHz lpo enable */
125 /* PLEASE USE THIS MACRO IN ATTACH PATH ONLY! */
126 #if defined(BCM_FASTLPO) && !defined(BCM_FASTLPO_DISABLED)
127 #define FASTLPO_ENAB() (TRUE)
128 #else
129 #define FASTLPO_ENAB() (FALSE)
130 #endif
131
132 /* Disable the power optimization feature */
133 bool _bcm_pwr_opt_dis = FALSE;
134
135 #ifdef BCMSRTOPOFF
136 bool _srtopoff_enab = FALSE;
137 #endif
138
139 pmuregs_t *hnd_pmur = NULL; /* PMU core regs */
140
141 #if !defined(BCMDONGLEHOST)
142 static void si_pmu_chipcontrol_xtal_settings_4369(si_t *sih);
143 static void si_pmu_chipcontrol_xtal_settings_4362(si_t *sih);
144 static void si_pmu_chipcontrol_xtal_settings_4378(si_t *sih);
145
146 /* PLL controls/clocks */
147 static void si_pmu1_pllinit1(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 xtal);
148 static void si_pmu_pll_off(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 *min_mask,
149 uint32 *max_mask, uint32 *clk_ctl_st);
150 static void si_pmu_pll_on(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 min_mask,
151 uint32 max_mask, uint32 clk_ctl_st);
152 static void si_pmu_otp_pllcontrol(si_t *sih, osl_t *osh);
153 static void si_pmu_otp_vreg_control(si_t *sih, osl_t *osh);
154 static void si_pmu_otp_chipcontrol(si_t *sih, osl_t *osh);
155 static uint32 si_pmu_def_alp_clock(si_t *sih, osl_t *osh);
156 static bool si_pmu_update_pllcontrol(si_t *sih, osl_t *osh, uint32 xtal, bool update_required);
157 static uint32 si_pmu_htclk_mask(si_t *sih);
158
159 static uint32 si_pmu1_cpuclk0(si_t *sih, osl_t *osh, pmuregs_t *pmu);
160 static uint32 si_pmu1_alpclk0(si_t *sih, osl_t *osh, pmuregs_t *pmu);
161
162 static uint32 si_pmu1_cpuclk0_pll2(si_t *sih);
163
164 /* PMU resources */
165 static uint32 si_pmu_res_deps(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 rsrcs, bool all);
166 static uint si_pmu_res_uptime(si_t *sih, osl_t *osh, pmuregs_t *pmu,
167 uint8 rsrc, bool pmu_fast_trans_en);
168 static void si_pmu_res_masks(si_t *sih, uint32 *pmin, uint32 *pmax);
169
170 uint32 si_pmu_get_pmutime_diff(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 *prev);
171 bool si_pmu_wait_for_res_pending(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint usec,
172 bool cond, uint32 *elapsed_time);
173
174 #ifdef __ARM_ARCH_7A__
175 static uint32 si_pmu_mem_ca7clock(si_t *sih, osl_t *osh);
176 #endif
177
178 static uint8 fastlpo_dis_get(void);
179 static uint8 fastlpo_pcie_dis_get(void);
180
181 static uint32 si_pmu_bpclk_4387(si_t *sih);
182
183 static int si_pmu_openloop_cal_43012(si_t *sih, uint16 currtemp);
184
185 static uint32 si_pmu_pll6val_armclk_calc(osl_t *osh, pmuregs_t *pmu, uint32 armclk, uint32 xtal,
186 bool write);
187 static bool si_pmu_armpll_write_required(si_t *sih, uint32 xtal);
188
189 uint8 si_pmu_pll28nm_calc_ndiv(uint32 fvco, uint32 xtal, uint32 *ndiv_int, uint32 *ndiv_frac);
190
191 void si_pmu_armpll_freq_upd(si_t *sih, uint8 p1div, uint32 ndiv_int, uint32 ndiv_frac);
192 void si_pmu_bbpll_freq_upd(si_t *sih, uint8 p1div, uint32 ndiv_int, uint32 ndiv_frac);
193 void si_pmu_armpll_chmdiv_upd(si_t *sih, uint32 ch0_mdiv, uint32 ch1_mdiv);
194
195 #ifdef BCM_LDO3P3_SOFTSTART
196 static int si_pmu_ldo3p3_soft_start_get(si_t *sih, osl_t *osh, uint32 bt_or_wl, int *res);
197 static int si_pmu_ldo3p3_soft_start_set(si_t *sih, osl_t *osh, uint32 bt_or_wl, uint32 slew_rate);
198 #endif /* BCM_LDO3P3_SOFTSTART */
199 #ifdef XTAL_BIAS_FROM_OTP
200 static void si_pmu_chipcontrol_xtal_bias_from_otp(si_t *sih, uint8* flag, uint8* val);
201 #ifndef BCM_OTP_API
202 static void si_pmu_chipcontrol_xtal_bias_cal_done_offsets(si_t *sih, uint16* wrd_offset,
203 uint8* wrd_shift, uint8* wrd_mask);
204 static void si_pmu_chipcontrol_xtal_bias_val_offsets(si_t *sih, uint16* wrd_offset,
205 uint8* wrd_shift, uint8* wrd_mask);
206 #endif /* !BCM_OTP_API */
207 #endif /* XTAL_BIAS_FROM_OTP */
208
209 /* PMU timer ticks once in 32uS */
210 #define PMU_US_STEPS (32)
211
212 void *g_si_pmutmr_lock_arg = NULL;
213 si_pmu_callback_t g_si_pmutmr_lock_cb = NULL, g_si_pmutmr_unlock_cb = NULL;
214
215 /* FVCO frequency in [KHz] */
216 #define FVCO_640 640000 /**< 640MHz */
217 #define FVCO_880 880000 /**< 880MHz */
218 #define FVCO_1760 1760000 /**< 1760MHz */
219 #define FVCO_1440 1440000 /**< 1440MHz */
220 #define FVCO_960 960000 /**< 960MHz */
221 #define FVCO_960p1 960100 /**< 960.1MHz */
222 #define FVCO_960010 960010 /**< 960.0098MHz */
223 #define FVCO_961 961000 /**< 961MHz */
224 #define FVCO_960p5 960500 /**< 960.5MHz */
225 #define FVCO_963 963000 /**< 963MHz */
226 #define FVCO_963p01 963010 /**< 963.01MHz */
227 #define FVCO_1000 1000000 /**< 1000MHz */
228 #define FVCO_1600 1600000 /**< 1600MHz */
229 #define FVCO_1920 1920000 /**< 1920MHz */
230 #define FVCO_1938 1938000 /* 1938MHz */
231 #define FVCO_385 385000 /**< 385MHz */
232 #define FVCO_400 400000 /**< 400MHz */
233 #define FVCO_720 720000 /**< 720MHz */
234 #define FVCO_2880 2880000 /**< 2880 MHz */
235 #define FVCO_2946 2946000 /**< 2946 MHz */
236 #define FVCO_3000 3000000 /**< 3000 MHz */
237 #define FVCO_3200 3200000 /**< 3200 MHz */
238 #define FVCO_1002p8 1002823 /**< 1002.823MHz */
239
240 /* defines to make the code more readable */
241 /* But 0 is a valid resource number! */
242 #define NO_SUCH_RESOURCE 0 /**< means: chip does not have such a PMU resource */
243
244 /* uses these defines instead of 'magic' values when writing to register pllcontrol_addr */
245 #define PMU_PLL_CTRL_REG0 0
246 #define PMU_PLL_CTRL_REG1 1
247 #define PMU_PLL_CTRL_REG2 2
248 #define PMU_PLL_CTRL_REG3 3
249 #define PMU_PLL_CTRL_REG4 4
250 #define PMU_PLL_CTRL_REG5 5
251 #define PMU_PLL_CTRL_REG6 6
252 #define PMU_PLL_CTRL_REG7 7
253 #define PMU_PLL_CTRL_REG8 8
254 #define PMU_PLL_CTRL_REG9 9
255 #define PMU_PLL_CTRL_REG10 10
256 #define PMU_PLL_CTRL_REG11 11
257 #define PMU_PLL_CTRL_REG12 12
258 #define PMU_PLL_CTRL_REG13 13
259 #define PMU_PLL_CTRL_REG14 14
260 #define PMU_PLL_CTRL_REG15 15
261
262 #ifndef BCM_OTP_API
263 #define OTP_XTAL_BIAS_CAL_DONE_4378_WRD_OFFSET 743
264 #define OTP_XTAL_BIAS_CAL_DONE_4378_WRD_SHIFT 8
265 #define OTP_XTAL_BIAS_CAL_DONE_4378_WRD_MASK 0x1
266
267 #define OTP_XTAL_BIAS_VAL_4378_WRD_OFFSET 743
268 #define OTP_XTAL_BIAS_VAL_4378_WRD_SHIFT 0
269 #define OTP_XTAL_BIAS_VAL_4378_WRD_MASK 0xFF
270 #endif /* !BCM_OTP_API */
271
272 /* changes the drive strength of gpio_12 and gpio_14 from 0x3 to 0x01 */
273 #define GPIO_DRIVE_4378_MASK 0x3Fu
274 #define GPIO_DRIVE_4378_VAL 0x09u
275
276 /**
277 * The chip has one or more PLLs/FLLs (e.g. baseband PLL, USB PHY PLL). The settings of each PLL are
278 * contained within one or more 'PLL control' registers. Since the PLL hardware requires that
279 * changes for one PLL are committed at once, the PMU has a provision for 'updating' all PLL control
280 * registers at once.
281 *
282 * When software wants to change the any PLL parameters, it withdraws requests for that PLL clock,
283 * updates the PLL control registers being careful not to alter any control signals for the other
284 * PLLs, and then writes a 1 to PMUCtl.PllCtnlUpdate to commit the changes. Best usage model would
285 * be bring PLL down then update the PLL control register.
286 */
287 void
si_pmu_pllupd(si_t * sih)288 si_pmu_pllupd(si_t *sih)
289 {
290 pmu_corereg(sih, SI_CC_IDX, pmucontrol,
291 PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
292 }
293
294 /* 4360_OTP_PU is used for 4352, not a typo */
295 static rsc_per_chip_t rsc_4352 = {NO_SUCH_RESOURCE, NO_SUCH_RESOURCE,
296 NO_SUCH_RESOURCE, RES4360_OTP_PU, NO_SUCH_RESOURCE,
297 NO_SUCH_RESOURCE, NO_SUCH_RESOURCE, NO_SUCH_RESOURCE};
298 static rsc_per_chip_t rsc_4360 = {RES4360_HT_AVAIL, NO_SUCH_RESOURCE,
299 NO_SUCH_RESOURCE, RES4360_OTP_PU, NO_SUCH_RESOURCE,
300 NO_SUCH_RESOURCE, NO_SUCH_RESOURCE, NO_SUCH_RESOURCE};
301 static rsc_per_chip_t rsc_43602 = {RES43602_HT_AVAIL, RES43602_MACPHY_CLKAVAIL,
302 RES43602_HT_START, NO_SUCH_RESOURCE, NO_SUCH_RESOURCE,
303 NO_SUCH_RESOURCE, NO_SUCH_RESOURCE, NO_SUCH_RESOURCE};
304 static rsc_per_chip_t rsc_43012 = {RES43012_HT_AVAIL, RES43012_MACPHY_CLK_AVAIL,
305 RES43012_HT_START, RES43012_OTP_PU, NO_SUCH_RESOURCE,
306 NO_SUCH_RESOURCE, NO_SUCH_RESOURCE, NO_SUCH_RESOURCE};
307 /* As per the chip team OTP doesn't have the resource in 4369 */
308 static rsc_per_chip_t rsc_4369 = {RES4369_HT_AVAIL, RES4369_MACPHY_MAIN_CLK_AVAIL,
309 RES4369_HT_AVAIL, NO_SUCH_RESOURCE, RES4369_MACPHY_AUX_CLK_AVAIL,
310 NO_SUCH_RESOURCE, NO_SUCH_RESOURCE, RES4369_DIG_CORE_RDY};
311 static rsc_per_chip_t rsc_4378 = {RES4378_HT_AVAIL, RES4378_MACPHY_MAIN_CLK_AVAIL,
312 RES4378_HT_AVAIL, RES4378_PMU_SLEEP, RES4378_MACPHY_AUX_CLK_AVAIL,
313 NO_SUCH_RESOURCE, RES4378_CORE_RDY_CB, RES4378_CORE_RDY_DIG};
314 static rsc_per_chip_t rsc_4387 = {RES4387_HT_AVAIL, RES4387_MACPHY_CLK_MAIN,
315 RES4387_HT_AVAIL, RES4387_PMU_SLEEP, RES4387_MACPHY_CLK_AUX,
316 RES4387_MACPHY_CLK_SCAN, RES4387_CORE_RDY_CB, RES4387_CORE_RDY_DIG};
317 static rsc_per_chip_t rsc_4388 = {RES4388_HT_AVAIL, RES4388_MACPHY_CLK_MAIN,
318 RES4388_HT_AVAIL, RES4388_PMU_LP, RES4388_MACPHY_CLK_AUX,
319 RES4388_MACPHY_CLK_SCAN, RES4388_CORE_RDY_CB, RES4388_CORE_RDY_DIG};
320 static rsc_per_chip_t rsc_4389 = {RES4389_HT_AVAIL, RES4389_MACPHY_CLK_MAIN,
321 RES4389_HT_AVAIL, RES4389_PMU_LP, RES4389_MACPHY_CLK_AUX,
322 RES4389_MACPHY_CLK_SCAN, RES4389_CORE_RDY_CB, RES4389_CORE_RDY_DIG};
323 static rsc_per_chip_t rsc_4397 = {RES4397_HT_AVAIL, RES4397_MACPHY_CLK_MAIN,
324 RES4397_HT_AVAIL, RES4397_PMU_LP, RES4397_MACPHY_CLK_AUX,
325 RES4397_MACPHY_CLK_SCAN, RES4397_CORE_RDY_CB, RES4397_CORE_RDY_DIG};
326
327 static rsc_per_chip_t rsc_4362 = {RES4362_HT_AVAIL, RES4362_MACPHY_MAIN_CLK_AVAIL,
328 RES4362_HT_AVAIL, /* macphy aux clk */
329 NO_SUCH_RESOURCE, NO_SUCH_RESOURCE, NO_SUCH_RESOURCE, NO_SUCH_RESOURCE,
330 RES4362_DIG_CORE_RDY};
331
332 /**
333 * For each chip, location of resource bits (e.g., ht bit) in resource mask registers may differ.
334 * This function abstracts the bit position of commonly used resources, thus making the rest of the
335 * code in hndpmu.c cleaner.
336 */
BCMRAMFN(si_pmu_get_rsc_positions)337 static rsc_per_chip_t* BCMRAMFN(si_pmu_get_rsc_positions)(si_t *sih)
338 {
339 rsc_per_chip_t *rsc = NULL;
340
341 switch (CHIPID(sih->chip)) {
342 case BCM4352_CHIP_ID:
343 case BCM43526_CHIP_ID: /* usb variant of 4352 */
344 rsc = &rsc_4352;
345 break;
346 case BCM4360_CHIP_ID:
347 case BCM43460_CHIP_ID:
348 rsc = &rsc_4360;
349 break;
350 CASE_BCM43602_CHIP:
351 rsc = &rsc_43602;
352 break;
353 case BCM43012_CHIP_ID:
354 case BCM43013_CHIP_ID:
355 case BCM43014_CHIP_ID:
356 rsc = &rsc_43012;
357 break;
358 case BCM4369_CHIP_GRPID:
359 rsc = &rsc_4369;
360 break;
361 case BCM4362_CHIP_GRPID:
362 rsc = &rsc_4362;
363 break;
364 case BCM4376_CHIP_GRPID:
365 case BCM4378_CHIP_GRPID:
366 rsc = &rsc_4378;
367 break;
368 case BCM4385_CHIP_GRPID:
369 case BCM4387_CHIP_GRPID:
370 rsc = &rsc_4387;
371 break;
372 case BCM4388_CHIP_GRPID:
373 rsc = &rsc_4388;
374 break;
375 case BCM4389_CHIP_GRPID:
376 rsc = &rsc_4389;
377 break;
378 case BCM4397_CHIP_GRPID:
379 rsc = &rsc_4397;
380 break;
381 default:
382 ASSERT(0);
383 break;
384 }
385
386 return rsc;
387 }; /* si_pmu_get_rsc_positions */
388
389 static const char BCMATTACHDATA(rstr_pllD)[] = "pll%d";
390 static const char BCMATTACHDATA(rstr_regD)[] = "reg%d";
391 static const char BCMATTACHDATA(rstr_chipcD)[] = "chipc%d";
392 static const char BCMATTACHDATA(rstr_rDt)[] = "r%dt";
393 static const char BCMATTACHDATA(rstr_rDd)[] = "r%dd";
394 static const char BCMATTACHDATA(rstr_Invalid_Unsupported_xtal_value_D)[] =
395 "Invalid/Unsupported xtal value %d";
396 static const char BCMATTACHDATA(rstr_xtalfreq)[] = "xtalfreq";
397 #if defined(SAVERESTORE) && defined(LDO3P3_MIN_RES_MASK)
398 static const char BCMATTACHDATA(rstr_ldo_prot)[] = "ldo_prot";
399 #endif /* SAVERESTORE && LDO3P3_MIN_RES_MASK */
400 static const char BCMATTACHDATA(rstr_btldo3p3pu)[] = "btldopu";
401 #if defined(BCM_FASTLPO_PMU) && !defined(BCM_FASTLPO_PMU_DISABLED)
402 static const char BCMATTACHDATA(rstr_fastlpo_dis)[] = "fastlpo_dis";
403 #endif /* BCM_FASTLPO_PMU */
404 static const char BCMATTACHDATA(rstr_fastlpo_pcie_dis)[] = "fastlpo_pcie_dis";
405 static const char BCMATTACHDATA(rstr_memlpldo_volt)[] = "memlpldo_volt";
406 static const char BCMATTACHDATA(rstr_lpldo_volt)[] = "lpldo_volt";
407 static const char BCMATTACHDATA(rstr_dyn_clksw_en)[] = "dyn_clksw_en";
408 static const char BCMATTACHDATA(rstr_abuck_volt)[] = "abuck_volt";
409 static const char BCMATTACHDATA(rstr_cbuck_volt)[] = "cbuck_volt";
410 static const char BCMATTACHDATA(rstr_csrtune)[] = "csr_tune";
411
412 /* The check for OTP parameters for the PLL control registers is done and if found the
413 * registers are updated accordingly.
414 */
415
416 /**
417 * As a hardware bug workaround, OTP can contain variables in the form 'pll%d=%d'.
418 * If these variables are present, the corresponding PLL control register(s) are
419 * overwritten, but not yet 'updated'.
420 */
421 static void
BCMATTACHFN(si_pmu_otp_pllcontrol)422 BCMATTACHFN(si_pmu_otp_pllcontrol)(si_t *sih, osl_t *osh)
423 {
424 char name[16];
425 const char *otp_val;
426 uint8 i;
427 uint32 val;
428 uint8 pll_ctrlcnt = 0;
429
430 if (FWSIGN_ENAB()) {
431 return;
432 }
433
434 if (PMUREV(sih->pmurev) >= 5) {
435 pll_ctrlcnt = (sih->pmucaps & PCAP5_PC_MASK) >> PCAP5_PC_SHIFT;
436 } else {
437 pll_ctrlcnt = (sih->pmucaps & PCAP_PC_MASK) >> PCAP_PC_SHIFT;
438 }
439
440 for (i = 0; i < pll_ctrlcnt; i++) {
441 snprintf(name, sizeof(name), rstr_pllD, i);
442 if ((otp_val = getvar(NULL, name)) == NULL)
443 continue;
444
445 val = (uint32)bcm_strtoul(otp_val, NULL, 0);
446 si_pmu_pllcontrol(sih, i, ~0, val);
447 }
448 }
449
450 /**
451 * The check for OTP parameters for the Voltage Regulator registers is done and if found the
452 * registers are updated accordingly.
453 */
454 static void
BCMATTACHFN(si_pmu_otp_vreg_control)455 BCMATTACHFN(si_pmu_otp_vreg_control)(si_t *sih, osl_t *osh)
456 {
457 char name[16];
458 const char *otp_val;
459 uint8 i;
460 uint32 val;
461 uint8 vreg_ctrlcnt = 0;
462
463 if (FWSIGN_ENAB()) {
464 return;
465 }
466
467 if (PMUREV(sih->pmurev) >= 5) {
468 vreg_ctrlcnt = (sih->pmucaps & PCAP5_VC_MASK) >> PCAP5_VC_SHIFT;
469 } else {
470 vreg_ctrlcnt = (sih->pmucaps & PCAP_VC_MASK) >> PCAP_VC_SHIFT;
471 }
472
473 for (i = 0; i < vreg_ctrlcnt; i++) {
474 snprintf(name, sizeof(name), rstr_regD, i);
475 if ((otp_val = getvar(NULL, name)) == NULL)
476 continue;
477
478 val = (uint32)bcm_strtoul(otp_val, NULL, 0);
479 si_pmu_vreg_control(sih, i, ~0, val);
480 }
481 }
482
483 /**
484 * The check for OTP parameters for the chip control registers is done and if found the
485 * registers are updated accordingly.
486 */
487 static void
BCMATTACHFN(si_pmu_otp_chipcontrol)488 BCMATTACHFN(si_pmu_otp_chipcontrol)(si_t *sih, osl_t *osh)
489 {
490 uint32 val, cc_ctrlcnt, i;
491 char name[16];
492 const char *otp_val;
493
494 if (FWSIGN_ENAB()) {
495 return;
496 }
497 if (PMUREV(sih->pmurev) >= 5) {
498 cc_ctrlcnt = (sih->pmucaps & PCAP5_CC_MASK) >> PCAP5_CC_SHIFT;
499 } else {
500 cc_ctrlcnt = (sih->pmucaps & PCAP_CC_MASK) >> PCAP_CC_SHIFT;
501 }
502
503 for (i = 0; i < cc_ctrlcnt; i++) {
504 snprintf(name, sizeof(name), rstr_chipcD, i);
505 if ((otp_val = getvar(NULL, name)) == NULL)
506 continue;
507
508 val = (uint32)bcm_strtoul(otp_val, NULL, 0);
509 si_pmu_chipcontrol(sih, i, 0xFFFFFFFF, val); /* writes to PMU chipctrl reg 'i' */
510 }
511 }
512
513 /**
514 * A chip contains one or more LDOs (Low Drop Out regulators). During chip bringup, it can turn out
515 * that the default (POR) voltage of a regulator is not right or optimal.
516 * This function is called only by si_pmu_swreg_init() for specific chips
517 */
518 void
si_pmu_set_ldo_voltage(si_t * sih,osl_t * osh,uint8 ldo,uint8 voltage)519 si_pmu_set_ldo_voltage(si_t *sih, osl_t *osh, uint8 ldo, uint8 voltage)
520 {
521 uint8 sr_cntl_shift = 0, rc_shift = 0, shift = 0, mask = 0;
522 uint8 addr = 0;
523 uint8 do_reg2 = 0, rshift2 = 0, rc_shift2 = 0, mask2 = 0, addr2 = 0;
524
525 BCM_REFERENCE(osh);
526
527 ASSERT(sih->cccaps & CC_CAP_PMU);
528
529 switch (CHIPID(sih->chip)) {
530 case BCM4360_CHIP_ID:
531 case BCM43460_CHIP_ID:
532 case BCM4352_CHIP_ID:
533 case BCM43526_CHIP_ID:
534 switch (ldo) {
535 case SET_LDO_VOLTAGE_PAREF:
536 addr = 1;
537 rc_shift = 0;
538 mask = 0xf;
539 break;
540 default:
541 ASSERT(FALSE);
542 break;
543 }
544 break;
545 CASE_BCM43602_CHIP:
546 switch (ldo) {
547 case SET_LDO_VOLTAGE_PAREF:
548 addr = 0;
549 rc_shift = 29;
550 mask = 0x7;
551 do_reg2 = 1;
552 addr2 = 1;
553 rshift2 = 3;
554 mask2 = 0x8;
555 break;
556 default:
557 ASSERT(FALSE);
558 break;
559 }
560 break;
561 default:
562 ASSERT(FALSE);
563 return;
564 }
565
566 shift = sr_cntl_shift + rc_shift;
567
568 pmu_corereg(sih, SI_CC_IDX, regcontrol_addr, /* PMU VREG register */
569 ~0, addr);
570 pmu_corereg(sih, SI_CC_IDX, regcontrol_data,
571 mask << shift, (voltage & mask) << shift);
572 if (do_reg2) {
573 /* rshift2 - right shift moves mask2 to bit 0, rc_shift2 - left shift in reg */
574 si_pmu_vreg_control(sih, addr2, (mask2 >> rshift2) << rc_shift2,
575 ((voltage & mask2) >> rshift2) << rc_shift2);
576 }
577 } /* si_pmu_set_ldo_voltage */
578
579 /* d11 slow to fast clock transition time in slow clock cycles */
580 #define D11SCC_SLOW2FAST_TRANSITION 2
581
582 /* For legacy chips only, will be discarded eventually */
583 static uint16
BCMINITFN(si_pmu_fast_pwrup_delay_legacy)584 BCMINITFN(si_pmu_fast_pwrup_delay_legacy)(si_t *sih, osl_t *osh, pmuregs_t *pmu)
585 {
586 uint pmudelay = PMU_MAX_TRANSITION_DLY;
587 uint32 ilp; /* ILP clock frequency in [Hz] */
588 rsc_per_chip_t *rsc; /* chip specific resource bit positions */
589
590 /* Should be calculated based on the PMU updown/depend tables */
591 switch (CHIPID(sih->chip)) {
592 case BCM43460_CHIP_ID:
593 case BCM43526_CHIP_ID:
594 pmudelay = 3700;
595 break;
596 case BCM4360_CHIP_ID:
597 case BCM4352_CHIP_ID:
598 if (CHIPREV(sih->chiprev) < 4) {
599 pmudelay = 1500;
600 } else {
601 pmudelay = 3000;
602 }
603 break;
604 case BCM43012_CHIP_ID:
605 case BCM43013_CHIP_ID:
606 case BCM43014_CHIP_ID:
607 pmudelay = 1500; /* In micro seconds for 43012 chip */
608 break;
609 CASE_BCM43602_CHIP:
610 rsc = si_pmu_get_rsc_positions(sih);
611 /* Retrieve time by reading it out of the hardware */
612 ilp = si_ilp_clock(sih);
613 if (ilp != 0) {
614 pmudelay = (si_pmu_res_uptime(sih, osh, pmu, rsc->macphy_clkavail, FALSE) +
615 D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp - 1) / ilp);
616 pmudelay = (11 * pmudelay) / 10;
617 }
618 break;
619 case BCM4362_CHIP_GRPID:
620 rsc = si_pmu_get_rsc_positions(sih);
621 /* Retrieve time by reading it out of the hardware */
622 ilp = si_ilp_clock(sih);
623 if (ilp != 0) {
624 pmudelay = si_pmu_res_uptime(sih, osh, pmu, rsc->ht_avail, FALSE) +
625 D11SCC_SLOW2FAST_TRANSITION;
626 pmudelay = (11 * pmudelay) / 10;
627 /* With PWR SW optimization, Need to add this addtional
628 time to fast power up delay to avoid beacon loss
629 */
630 pmudelay += 600;
631 }
632 break;
633 default:
634 break;
635 }
636
637 return (uint16)pmudelay;
638 } /* si_pmu_fast_pwrup_delay_legacy */
639
640 /**
641 * d11 core has a 'fastpwrup_dly' register that must be written to.
642 * This function returns d11 slow to fast clock transition time in [us] units.
643 * It does not write to the d11 core.
644 */
645 uint16
BCMINITFN(si_pmu_fast_pwrup_delay)646 BCMINITFN(si_pmu_fast_pwrup_delay)(si_t *sih, osl_t *osh)
647 {
648 uint pmudelay = PMU_MAX_TRANSITION_DLY;
649 pmuregs_t *pmu;
650 uint origidx;
651 rsc_per_chip_t *rsc; /* chip specific resource bit positions */
652 uint macunit;
653 bool pmu_fast_trans_en;
654
655 ASSERT(sih->cccaps & CC_CAP_PMU);
656
657 if (ISSIM_ENAB(sih)) {
658 pmudelay = 1000;
659 goto exit;
660 }
661
662 macunit = si_coreunit(sih);
663
664 origidx = si_coreidx(sih);
665 /* Still support 43602 so need AOB check,
666 * 43602 is the only non-AOB chip supported now
667 */
668 if (AOB_ENAB(sih)) {
669 pmu = si_setcore(sih, PMU_CORE_ID, 0);
670 } else {
671 pmu = si_setcoreidx(sih, SI_CC_IDX);
672 }
673 ASSERT(pmu != NULL);
674
675 pmu_fast_trans_en = (R_REG(osh, &pmu->pmucontrol_ext) & PCTL_EXT_FAST_TRANS_ENAB) ?
676 TRUE : FALSE;
677
678 rsc = si_pmu_get_rsc_positions(sih);
679
680 switch (CHIPID(sih->chip)) {
681 case BCM4369_CHIP_GRPID:
682 case BCM4376_CHIP_GRPID:
683 case BCM4378_CHIP_GRPID:
684 case BCM4385_CHIP_GRPID:
685 if (macunit == 0) {
686 pmudelay = si_pmu_res_uptime(sih, osh, pmu,
687 rsc->macphy_clkavail, pmu_fast_trans_en);
688 } else if (macunit == 1) {
689 pmudelay = si_pmu_res_uptime(sih, osh, pmu,
690 rsc->macphy_aux_clkavail, pmu_fast_trans_en);
691 } else {
692 ASSERT(0);
693 }
694 break;
695 case BCM4387_CHIP_GRPID:
696 case BCM4388_CHIP_GRPID:
697 case BCM4389_CHIP_GRPID:
698 case BCM4397_CHIP_GRPID:
699 if (macunit == 0) {
700 pmudelay = si_pmu_res_uptime(sih, osh, pmu,
701 rsc->macphy_clkavail, pmu_fast_trans_en);
702 } else if (macunit == 1) {
703 pmudelay = si_pmu_res_uptime(sih, osh, pmu,
704 rsc->macphy_aux_clkavail, pmu_fast_trans_en);
705 } else if (macunit == 2) {
706 pmudelay = si_pmu_res_uptime(sih, osh, pmu,
707 rsc->macphy_scan_clkavail, pmu_fast_trans_en);
708 } else {
709 ASSERT(0);
710 }
711 break;
712
713 default:
714 pmudelay = si_pmu_fast_pwrup_delay_legacy(sih, osh, pmu);
715 break;
716 }
717
718 /* Return to original core */
719 si_setcoreidx(sih, origidx);
720
721 exit:
722 return (uint16)pmudelay;
723 } /* si_pmu_fast_pwrup_delay */
724
725 /*
726 * Get fast pwrup delay for given resource
727 */
728 static uint
BCMINITFN(si_pmu_fast_pwrup_delay_rsrc)729 BCMINITFN(si_pmu_fast_pwrup_delay_rsrc)(si_t *sih, osl_t *osh, uint8 rsrc)
730 {
731 uint pmudelay = PMU_MAX_TRANSITION_DLY;
732 pmuregs_t *pmu = NULL;
733 bool pmu_fast_trans_en = TRUE;
734 uint origidx;
735
736 origidx = si_coreidx(sih);
737 pmu = si_setcore(sih, PMU_CORE_ID, 0);
738 ASSERT(pmu != NULL);
739
740 pmu_fast_trans_en = (R_REG(osh, &pmu->pmucontrol_ext) & PCTL_EXT_FAST_TRANS_ENAB) ?
741 TRUE : FALSE;
742
743 pmudelay = si_pmu_res_uptime(sih, osh, pmu, rsrc, pmu_fast_trans_en);
744
745 /* Return to original core */
746 si_setcoreidx(sih, origidx);
747
748 return pmudelay;
749 }
750
751 /*
752 * Get fast pwrup delay for given DIG_READY resource
753 */
754 uint
BCMINITFN(si_pmu_fast_pwrup_delay_dig)755 BCMINITFN(si_pmu_fast_pwrup_delay_dig)(si_t *sih, osl_t *osh)
756 {
757 uint delay = 0;
758 rsc_per_chip_t *rsc = si_pmu_get_rsc_positions(sih);
759 ASSERT(rsc);
760
761 if (rsc) {
762 delay = si_pmu_fast_pwrup_delay_rsrc(sih, osh, rsc->dig_ready);
763 }
764 return delay;
765 }
766
767 /*
768 * During chip bringup, it can turn out that the 'hard wired' PMU dependencies are not fully
769 * correct, or that up/down time values can be optimized. The following data structures and arrays
770 * deal with that.
771 */
772
773 /* Setup resource up/down timers */
774 typedef struct {
775 uint8 resnum;
776 uint32 updown;
777 } pmu_res_updown_t;
778
779 #define PMU_RES_SUBSTATE_SHIFT 8
780
781 /* Setup resource substate transition timer value */
782 typedef struct {
783 uint8 resnum;
784 uint8 substate;
785 uint32 tmr;
786 } pmu_res_subst_trans_tmr_t;
787
788 /* Change resource dependencies masks */
789 typedef struct {
790 uint32 res_mask; /* resources (chip specific) */
791 int8 action; /* action, e.g. RES_DEPEND_SET */
792 uint32 depend_mask; /* changes to the dependencies mask */
793 bool (*filter)(si_t *sih); /* action is taken when filter is NULL or return TRUE */
794 } pmu_res_depend_t;
795
796 /* Resource dependencies mask change action */
797 #define RES_DEPEND_SET 0 /* Override the dependencies mask */
798 #define RES_DEPEND_ADD 1 /* Add to the dependencies mask */
799 #define RES_DEPEND_REMOVE -1 /* Remove from the dependencies mask */
800
801 /* Using a safe SAVE_RESTORE up/down time, it will get updated after openloop cal */
802 static const pmu_res_updown_t BCMATTACHDATA(bcm43012a0_res_updown_ds0)[] = {
803 {RES43012_MEMLPLDO_PU, 0x00200020},
804 {RES43012_PMU_SLEEP, 0x00a600a6},
805 {RES43012_FAST_LPO, 0x00D20000},
806 {RES43012_BTLPO_3P3, 0x007D0000},
807 {RES43012_SR_POK, 0x00c80000},
808 {RES43012_DUMMY_PWRSW, 0x01400000},
809 {RES43012_DUMMY_LDO3P3, 0x00000000},
810 {RES43012_DUMMY_BT_LDO3P3, 0x00000000},
811 {RES43012_DUMMY_RADIO, 0x00000000},
812 {RES43012_VDDB_VDDRET, 0x0020000a},
813 {RES43012_HV_LDO3P3, 0x002C0000},
814 {RES43012_XTAL_PU, 0x04000000},
815 {RES43012_SR_CLK_START, 0x00080000},
816 {RES43012_XTAL_STABLE, 0x00000000},
817 {RES43012_FCBS, 0x00000000},
818 {RES43012_CBUCK_MODE, 0x00000000},
819 {RES43012_CORE_READY, 0x00000000},
820 {RES43012_ILP_REQ, 0x00000000},
821 {RES43012_ALP_AVAIL, 0x00280008},
822 {RES43012_RADIOLDO_1P8, 0x00220000},
823 {RES43012_MINI_PMU, 0x00220000},
824 {RES43012_SR_SAVE_RESTORE, 0x02600260},
825 {RES43012_PHY_PWRSW, 0x00800005},
826 {RES43012_VDDB_CLDO, 0x0020000a},
827 {RES43012_SUBCORE_PWRSW, 0x0060000a},
828 {RES43012_SR_SLEEP, 0x00000000},
829 {RES43012_HT_START, 0x00A00000},
830 {RES43012_HT_AVAIL, 0x00000000},
831 {RES43012_MACPHY_CLK_AVAIL, 0x00000000},
832 };
833
834 static const pmu_res_updown_t BCMATTACHDATA(bcm4360_res_updown)[] = {
835 {RES4360_BBPLLPWRSW_PU, 0x00200001}
836 };
837
838 static const pmu_res_updown_t BCMATTACHDATA(bcm43602_res_updown)[] = {
839 {RES43602_SR_SAVE_RESTORE, 0x00190019},
840 {RES43602_XTAL_PU, 0x00280002},
841 {RES43602_RFLDO_PU, 0x00430005}
842 };
843
844 static pmu_res_depend_t BCMATTACHDATA(bcm43012a0_res_depend_ds0)[] = {
845 {0, 0, 0, NULL}
846 };
847
848 static pmu_res_depend_t BCMATTACHDATA(bcm43602_res_depend)[] = {
849 /* JIRA HW43602-131 : PCIe SERDES dependency problem */
850 {
851 PMURES_BIT(RES43602_SR_SUBCORE_PWRSW) | PMURES_BIT(RES43602_SR_CLK_STABLE) |
852 PMURES_BIT(RES43602_SR_SAVE_RESTORE) | PMURES_BIT(RES43602_SR_SLEEP) |
853 PMURES_BIT(RES43602_LQ_START) | PMURES_BIT(RES43602_LQ_AVAIL) |
854 PMURES_BIT(RES43602_WL_CORE_RDY) | PMURES_BIT(RES43602_ILP_REQ) |
855 PMURES_BIT(RES43602_ALP_AVAIL) | PMURES_BIT(RES43602_RFLDO_PU) |
856 PMURES_BIT(RES43602_HT_START) | PMURES_BIT(RES43602_HT_AVAIL) |
857 PMURES_BIT(RES43602_MACPHY_CLKAVAIL),
858 RES_DEPEND_ADD,
859 PMURES_BIT(RES43602_SERDES_PU),
860 NULL
861 },
862 /* set rsrc 7, 8, 9, 12, 13, 14 & 17 add (1<<10 | 1<<4 )] */
863 {
864 PMURES_BIT(RES43602_SR_CLK_START) | PMURES_BIT(RES43602_SR_PHY_PWRSW) |
865 PMURES_BIT(RES43602_SR_SUBCORE_PWRSW) | PMURES_BIT(RES43602_SR_CLK_STABLE) |
866 PMURES_BIT(RES43602_SR_SAVE_RESTORE) | PMURES_BIT(RES43602_SR_SLEEP) |
867 PMURES_BIT(RES43602_WL_CORE_RDY),
868 RES_DEPEND_ADD,
869 PMURES_BIT(RES43602_XTALLDO_PU) | PMURES_BIT(RES43602_XTAL_PU),
870 NULL
871 },
872 /* set rsrc 11 add (1<<13 | 1<<12 | 1<<9 | 1<<8 | 1<<7 )] */
873 {
874 PMURES_BIT(RES43602_PERST_OVR),
875 RES_DEPEND_ADD,
876 PMURES_BIT(RES43602_SR_CLK_START) | PMURES_BIT(RES43602_SR_PHY_PWRSW) |
877 PMURES_BIT(RES43602_SR_SUBCORE_PWRSW) | PMURES_BIT(RES43602_SR_CLK_STABLE) |
878 PMURES_BIT(RES43602_SR_SAVE_RESTORE),
879 NULL
880 },
881 /* set rsrc 19, 21, 22, 23 & 24 remove ~(1<<16 | 1<<15 )] */
882 {
883 PMURES_BIT(RES43602_ALP_AVAIL) | PMURES_BIT(RES43602_RFLDO_PU) |
884 PMURES_BIT(RES43602_HT_START) | PMURES_BIT(RES43602_HT_AVAIL) |
885 PMURES_BIT(RES43602_MACPHY_CLKAVAIL),
886 RES_DEPEND_REMOVE,
887 PMURES_BIT(RES43602_LQ_START) | PMURES_BIT(RES43602_LQ_AVAIL),
888 NULL
889 }
890 };
891
892 #ifndef BCM_BOOTLOADER
893 /** switch off LPLDO for 12x12 package because it can cause a problem when chip is reset */
894 static const pmu_res_depend_t BCMATTACHDATA(bcm43602_12x12_res_depend)[] = {
895 /* set rsrc 19, 21, 22, 23 & 24 remove ~(1<<16 | 1<<15 )] */
896 { /* resources no longer dependent on resource that is going to be removed */
897 PMURES_BIT(RES43602_LPLDO_PU) | PMURES_BIT(RES43602_REGULATOR) |
898 PMURES_BIT(RES43602_PMU_SLEEP) | PMURES_BIT(RES43602_RSVD_3) |
899 PMURES_BIT(RES43602_XTALLDO_PU) | PMURES_BIT(RES43602_SERDES_PU) |
900 PMURES_BIT(RES43602_BBPLL_PWRSW_PU) | PMURES_BIT(RES43602_SR_CLK_START) |
901 PMURES_BIT(RES43602_SR_PHY_PWRSW) | PMURES_BIT(RES43602_SR_SUBCORE_PWRSW) |
902 PMURES_BIT(RES43602_XTAL_PU) | PMURES_BIT(RES43602_PERST_OVR) |
903 PMURES_BIT(RES43602_SR_CLK_STABLE) | PMURES_BIT(RES43602_SR_SAVE_RESTORE) |
904 PMURES_BIT(RES43602_SR_SLEEP) | PMURES_BIT(RES43602_LQ_START) |
905 PMURES_BIT(RES43602_LQ_AVAIL) | PMURES_BIT(RES43602_WL_CORE_RDY) |
906 PMURES_BIT(RES43602_ILP_REQ) | PMURES_BIT(RES43602_ALP_AVAIL) |
907 PMURES_BIT(RES43602_RADIO_PU) | PMURES_BIT(RES43602_RFLDO_PU) |
908 PMURES_BIT(RES43602_HT_START) | PMURES_BIT(RES43602_HT_AVAIL) |
909 PMURES_BIT(RES43602_MACPHY_CLKAVAIL) | PMURES_BIT(RES43602_PARLDO_PU) |
910 PMURES_BIT(RES43602_RSVD_26),
911 RES_DEPEND_REMOVE,
912 /* resource that is going to be removed */
913 PMURES_BIT(RES43602_LPLDO_PU),
914 NULL
915 }
916 };
917
918 static const pmu_res_depend_t BCMATTACHDATA(bcm43602_res_pciewar)[] = {
919 {
920 PMURES_BIT(RES43602_PERST_OVR),
921 RES_DEPEND_ADD,
922 PMURES_BIT(RES43602_REGULATOR) |
923 PMURES_BIT(RES43602_PMU_SLEEP) |
924 PMURES_BIT(RES43602_XTALLDO_PU) |
925 PMURES_BIT(RES43602_XTAL_PU) |
926 PMURES_BIT(RES43602_RADIO_PU),
927 NULL
928 },
929 {
930 PMURES_BIT(RES43602_WL_CORE_RDY),
931 RES_DEPEND_ADD,
932 PMURES_BIT(RES43602_PERST_OVR),
933 NULL
934 },
935 {
936 PMURES_BIT(RES43602_LQ_START),
937 RES_DEPEND_ADD,
938 PMURES_BIT(RES43602_PERST_OVR),
939 NULL
940 },
941 {
942 PMURES_BIT(RES43602_LQ_AVAIL),
943 RES_DEPEND_ADD,
944 PMURES_BIT(RES43602_PERST_OVR),
945 NULL
946 },
947 {
948 PMURES_BIT(RES43602_ALP_AVAIL),
949 RES_DEPEND_ADD,
950 PMURES_BIT(RES43602_PERST_OVR),
951 NULL
952 },
953 {
954 PMURES_BIT(RES43602_HT_START),
955 RES_DEPEND_ADD,
956 PMURES_BIT(RES43602_PERST_OVR),
957 NULL
958 },
959 {
960 PMURES_BIT(RES43602_HT_AVAIL),
961 RES_DEPEND_ADD,
962 PMURES_BIT(RES43602_PERST_OVR),
963 NULL
964 },
965 {
966 PMURES_BIT(RES43602_MACPHY_CLKAVAIL),
967 RES_DEPEND_ADD,
968 PMURES_BIT(RES43602_PERST_OVR),
969 NULL
970 }
971 };
972 #endif /* BCM_BOOTLOADER */
973
974 static const pmu_res_updown_t BCMATTACHDATA(bcm4360B1_res_updown)[] = {
975 /* Need to change elements here, should get default values for this - 4360B1 */
976 {RES4360_XTAL_PU, 0x00430002}, /* Changed for 4360B1 */
977 };
978
979 static pmu_res_depend_t BCMATTACHDATA(bcm4369a0_res_depend)[] = {
980 {PMURES_BIT(RES4369_DUMMY), RES_DEPEND_SET, 0x00000000, NULL},
981 {PMURES_BIT(RES4369_ABUCK), RES_DEPEND_SET, 0x00000005, NULL},
982 {PMURES_BIT(RES4369_PMU_SLEEP), RES_DEPEND_SET, 0x00000001, NULL},
983 {PMURES_BIT(RES4369_MISCLDO), RES_DEPEND_SET, 0x00000007, NULL},
984 {PMURES_BIT(RES4369_LDO3P3), RES_DEPEND_SET, 0x00000001, NULL},
985 {PMURES_BIT(RES4369_FAST_LPO_AVAIL), RES_DEPEND_SET, 0x00000005, NULL},
986 {PMURES_BIT(RES4369_XTAL_PU), RES_DEPEND_SET, 0x00000007, NULL},
987 {PMURES_BIT(RES4369_XTAL_STABLE), RES_DEPEND_SET, 0x00000047, NULL},
988 {PMURES_BIT(RES4369_PWRSW_DIG), RES_DEPEND_SET, 0x060000cf, NULL},
989 {PMURES_BIT(RES4369_SR_DIG), RES_DEPEND_SET, 0x060001cf, NULL},
990 {PMURES_BIT(RES4369_SLEEP_DIG), RES_DEPEND_SET, 0x060003cf, NULL},
991 {PMURES_BIT(RES4369_PWRSW_AUX), RES_DEPEND_SET, 0x040000cf, NULL},
992 {PMURES_BIT(RES4369_SR_AUX), RES_DEPEND_SET, 0x040008cf, NULL},
993 {PMURES_BIT(RES4369_SLEEP_AUX), RES_DEPEND_SET, 0x040018cf, NULL},
994 {PMURES_BIT(RES4369_PWRSW_MAIN), RES_DEPEND_SET, 0x040000cf, NULL},
995 {PMURES_BIT(RES4369_SR_MAIN), RES_DEPEND_SET, 0x040040cf, NULL},
996 {PMURES_BIT(RES4369_SLEEP_MAIN), RES_DEPEND_SET, 0x0400c0cf, NULL},
997 {PMURES_BIT(RES4369_DIG_CORE_RDY), RES_DEPEND_SET, 0x060007cf, NULL},
998 {PMURES_BIT(RES4369_CORE_RDY_AUX), RES_DEPEND_SET, 0x040038cf, NULL},
999 {PMURES_BIT(RES4369_ALP_AVAIL), RES_DEPEND_SET, 0x060207cf, NULL},
1000 {PMURES_BIT(RES4369_RADIO_AUX_PU), RES_DEPEND_SET, 0x040438df, NULL},
1001 {PMURES_BIT(RES4369_MINIPMU_AUX_PU), RES_DEPEND_SET, 0x041438df, NULL},
1002 {PMURES_BIT(RES4369_CORE_RDY_MAIN), RES_DEPEND_SET, 0x0401c0cf, NULL},
1003 {PMURES_BIT(RES4369_RADIO_MAIN_PU), RES_DEPEND_SET, 0x0441c0df, NULL},
1004 {PMURES_BIT(RES4369_MINIPMU_MAIN_PU), RES_DEPEND_SET, 0x04c1c0df, NULL},
1005 {PMURES_BIT(RES4369_PCIE_EP_PU), RES_DEPEND_SET, 0x040000cf, NULL},
1006 {PMURES_BIT(RES4369_COLD_START_WAIT), RES_DEPEND_SET, 0x0000000f, NULL},
1007 {PMURES_BIT(RES4369_ARMHTAVAIL), RES_DEPEND_SET, 0x060a07cf, NULL},
1008 {PMURES_BIT(RES4369_HT_AVAIL), RES_DEPEND_SET, 0x060a07cf, NULL},
1009 {PMURES_BIT(RES4369_MACPHY_AUX_CLK_AVAIL), RES_DEPEND_SET, 0x163e3fdf, NULL},
1010 {PMURES_BIT(RES4369_MACPHY_MAIN_CLK_AVAIL), RES_DEPEND_SET, 0x17cbc7df, NULL},
1011 };
1012
1013 static pmu_res_depend_t BCMATTACHDATA(bcm4369a0_res_depend_fastlpo_pcie)[] = {
1014 {PMURES_BIT(RES4369_DUMMY), RES_DEPEND_SET, 0x00000000, NULL},
1015 {PMURES_BIT(RES4369_ABUCK), RES_DEPEND_SET, 0x00000005, NULL},
1016 {PMURES_BIT(RES4369_PMU_SLEEP), RES_DEPEND_SET, 0x00000001, NULL},
1017 {PMURES_BIT(RES4369_MISCLDO), RES_DEPEND_SET, 0x00000007, NULL},
1018 {PMURES_BIT(RES4369_LDO3P3), RES_DEPEND_SET, 0x00000001, NULL},
1019 {PMURES_BIT(RES4369_FAST_LPO_AVAIL), RES_DEPEND_SET, 0x00000005, NULL},
1020 {PMURES_BIT(RES4369_XTAL_PU), RES_DEPEND_SET, 0x00000007, NULL},
1021 {PMURES_BIT(RES4369_XTAL_STABLE), RES_DEPEND_SET, 0x00000047, NULL},
1022 {PMURES_BIT(RES4369_PWRSW_DIG), RES_DEPEND_SET, 0x060000ef, NULL},
1023 {PMURES_BIT(RES4369_SR_DIG), RES_DEPEND_SET, 0x060001ef, NULL},
1024 {PMURES_BIT(RES4369_SLEEP_DIG), RES_DEPEND_SET, 0x060003ef, NULL},
1025 {PMURES_BIT(RES4369_PWRSW_AUX), RES_DEPEND_SET, 0x040000ef, NULL},
1026 {PMURES_BIT(RES4369_SR_AUX), RES_DEPEND_SET, 0x040008ef, NULL},
1027 {PMURES_BIT(RES4369_SLEEP_AUX), RES_DEPEND_SET, 0x040018ef, NULL},
1028 {PMURES_BIT(RES4369_PWRSW_MAIN), RES_DEPEND_SET, 0x040000ef, NULL},
1029 {PMURES_BIT(RES4369_SR_MAIN), RES_DEPEND_SET, 0x040040ef, NULL},
1030 {PMURES_BIT(RES4369_SLEEP_MAIN), RES_DEPEND_SET, 0x0400c0ef, NULL},
1031 {PMURES_BIT(RES4369_DIG_CORE_RDY), RES_DEPEND_SET, 0x060007ef, NULL},
1032 {PMURES_BIT(RES4369_CORE_RDY_AUX), RES_DEPEND_SET, 0x040038ef, NULL},
1033 {PMURES_BIT(RES4369_ALP_AVAIL), RES_DEPEND_SET, 0x060207ef, NULL},
1034 {PMURES_BIT(RES4369_RADIO_AUX_PU), RES_DEPEND_SET, 0x040438ff, NULL},
1035 {PMURES_BIT(RES4369_MINIPMU_AUX_PU), RES_DEPEND_SET, 0x041438ff, NULL},
1036 {PMURES_BIT(RES4369_CORE_RDY_MAIN), RES_DEPEND_SET, 0x0401c0ef, NULL},
1037 {PMURES_BIT(RES4369_RADIO_MAIN_PU), RES_DEPEND_SET, 0x0441c0ff, NULL},
1038 {PMURES_BIT(RES4369_MINIPMU_MAIN_PU), RES_DEPEND_SET, 0x04c1c0ff, NULL},
1039 {PMURES_BIT(RES4369_PCIE_EP_PU), RES_DEPEND_SET, 0x0400002f, NULL},
1040 {PMURES_BIT(RES4369_COLD_START_WAIT), RES_DEPEND_SET, 0x0000002f, NULL},
1041 {PMURES_BIT(RES4369_ARMHTAVAIL), RES_DEPEND_SET, 0x060a07ef, NULL},
1042 {PMURES_BIT(RES4369_HT_AVAIL), RES_DEPEND_SET, 0x060a07ef, NULL},
1043 {PMURES_BIT(RES4369_MACPHY_AUX_CLK_AVAIL), RES_DEPEND_SET, 0x163e3fff, NULL},
1044 {PMURES_BIT(RES4369_MACPHY_MAIN_CLK_AVAIL), RES_DEPEND_SET, 0x17cbc7ff, NULL},
1045 };
1046
1047 static const pmu_res_updown_t BCMATTACHDATA(bcm4369a0_res_updown)[] = {
1048 {RES4369_DUMMY, 0x00220022},
1049 {RES4369_ABUCK, 0x00c80022},
1050 {RES4369_PMU_SLEEP, 0x00c80022},
1051 {RES4369_MISCLDO, 0x00bd0022},
1052 {RES4369_LDO3P3, 0x00bd0022},
1053 {RES4369_FAST_LPO_AVAIL, 0x01500022},
1054 {RES4369_XTAL_PU, 0x07d00022},
1055 {RES4369_XTAL_STABLE, 0x00220022},
1056 {RES4369_PWRSW_DIG, 0x02100087},
1057 {RES4369_SR_DIG, 0x02000200},
1058 {RES4369_SLEEP_DIG, 0x00220022},
1059 {RES4369_PWRSW_AUX, 0x03900087},
1060 {RES4369_SR_AUX, 0x01cc01cc},
1061 {RES4369_SLEEP_AUX, 0x00220022},
1062 {RES4369_PWRSW_MAIN, 0x03900087},
1063 {RES4369_SR_MAIN, 0x02000200},
1064 {RES4369_SLEEP_MAIN, 0x00220022},
1065 {RES4369_DIG_CORE_RDY, 0x00220044},
1066 {RES4369_CORE_RDY_AUX, 0x00220044},
1067 {RES4369_ALP_AVAIL, 0x00220044},
1068 {RES4369_RADIO_AUX_PU, 0x006e0022},
1069 {RES4369_MINIPMU_AUX_PU, 0x00460022},
1070 {RES4369_CORE_RDY_MAIN, 0x00220022},
1071 {RES4369_RADIO_MAIN_PU, 0x006e0022},
1072 {RES4369_MINIPMU_MAIN_PU, 0x00460022},
1073 {RES4369_PCIE_EP_PU, 0x02100087},
1074 {RES4369_COLD_START_WAIT, 0x00220022},
1075 {RES4369_ARMHTAVAIL, 0x00a80022},
1076 {RES4369_HT_AVAIL, RES4369_HTAVAIL_VAL},
1077 {RES4369_MACPHY_AUX_CLK_AVAIL, 0x00640022},
1078 {RES4369_MACPHY_MAIN_CLK_AVAIL, 0x00640022},
1079 };
1080
1081 static const pmu_res_updown_t BCMATTACHDATA(bcm4369a0_res_updown_fastlpo_pmu)[] = {
1082 {RES4369_DUMMY, 0x00220022},
1083 {RES4369_ABUCK, 0x00c80022},
1084 {RES4369_PMU_SLEEP, 0x00c80022},
1085 {RES4369_MISCLDO, 0x00bd0022},
1086 {RES4369_LDO3P3, 0x00bd0022},
1087 {RES4369_FAST_LPO_AVAIL, 0x01500022},
1088 {RES4369_XTAL_PU, 0x07d00022},
1089 {RES4369_XTAL_STABLE, 0x00220022},
1090 {RES4369_PWRSW_DIG, 0x02100087},
1091 {RES4369_SR_DIG, 0x02000200},
1092 {RES4369_SLEEP_DIG, 0x00220022},
1093 {RES4369_PWRSW_AUX, 0x03900087},
1094 {RES4369_SR_AUX, 0x01cc01cc},
1095 {RES4369_SLEEP_AUX, 0x00220022},
1096 {RES4369_PWRSW_MAIN, 0x03900087},
1097 {RES4369_SR_MAIN, 0x02000200},
1098 {RES4369_SLEEP_MAIN, 0x00220022},
1099 {RES4369_DIG_CORE_RDY, 0x00220044},
1100 {RES4369_CORE_RDY_AUX, 0x00220044},
1101 {RES4369_ALP_AVAIL, 0x00220044},
1102 {RES4369_RADIO_AUX_PU, 0x006e0022},
1103 {RES4369_MINIPMU_AUX_PU, 0x00460022},
1104 {RES4369_CORE_RDY_MAIN, 0x00220022},
1105 {RES4369_RADIO_MAIN_PU, 0x006e0022},
1106 {RES4369_MINIPMU_MAIN_PU, 0x00460022},
1107 {RES4369_PCIE_EP_PU, 0x01200087},
1108 {RES4369_COLD_START_WAIT, 0x00220022},
1109 {RES4369_ARMHTAVAIL, 0x00a80022},
1110 {RES4369_HT_AVAIL, RES4369_HTAVAIL_VAL},
1111 {RES4369_MACPHY_AUX_CLK_AVAIL, 0x00640022},
1112 {RES4369_MACPHY_MAIN_CLK_AVAIL, 0x00640022},
1113 };
1114
1115 static const pmu_res_updown_t BCMATTACHDATA(bcm4369b0_res_updown)[] = {
1116 {RES4369_DUMMY, 0x00220022},
1117 {RES4369_ABUCK, 0x00c80022},
1118 {RES4369_PMU_SLEEP, 0x00c80022},
1119 {RES4369_MISCLDO, 0x00bd0022},
1120 {RES4369_LDO3P3, 0x01ad0022},
1121 {RES4369_FAST_LPO_AVAIL, 0x01500022},
1122 {RES4369_XTAL_PU, 0x05dc0022},
1123 {RES4369_XTAL_STABLE, 0x00220022},
1124 {RES4369_PWRSW_DIG, 0x02100087},
1125 {RES4369_SR_DIG, 0x00A000A0},
1126 {RES4369_SLEEP_DIG, 0x00220022},
1127 {RES4369_PWRSW_AUX, 0x03900087},
1128 {RES4369_SR_AUX, 0x01400140},
1129 {RES4369_SLEEP_AUX, 0x00220022},
1130 {RES4369_PWRSW_MAIN, 0x03900087},
1131 {RES4369_SR_MAIN, 0x01A001A0},
1132 {RES4369_SLEEP_MAIN, 0x00220022},
1133 {RES4369_DIG_CORE_RDY, 0x00220044},
1134 {RES4369_CORE_RDY_AUX, 0x00220044},
1135 {RES4369_ALP_AVAIL, 0x00220044},
1136 {RES4369_RADIO_AUX_PU, 0x006e0022},
1137 {RES4369_MINIPMU_AUX_PU, 0x00460022},
1138 {RES4369_CORE_RDY_MAIN, 0x00220022},
1139 {RES4369_RADIO_MAIN_PU, 0x006e0022},
1140 {RES4369_MINIPMU_MAIN_PU, 0x00460022},
1141 {RES4369_PCIE_EP_PU, 0x02100087},
1142 {RES4369_COLD_START_WAIT, 0x00220022},
1143 {RES4369_ARMHTAVAIL, 0x00a80022},
1144 {RES4369_HT_AVAIL, RES4369_HTAVAIL_VAL},
1145 {RES4369_MACPHY_AUX_CLK_AVAIL, 0x00640022},
1146 {RES4369_MACPHY_MAIN_CLK_AVAIL, 0x00640022},
1147 };
1148
1149 static const pmu_res_updown_t BCMATTACHDATA(bcm4369b0_res_updown_fastlpo_pmu)[] = {
1150 {RES4369_DUMMY, 0x00220022},
1151 {RES4369_ABUCK, 0x00c80022},
1152 {RES4369_PMU_SLEEP, 0x00c80022},
1153 {RES4369_MISCLDO, 0x00bd0022},
1154 {RES4369_LDO3P3, 0x01ad0022},
1155 {RES4369_FAST_LPO_AVAIL, 0x01500022},
1156 {RES4369_XTAL_PU, 0x05dc0022},
1157 {RES4369_XTAL_STABLE, 0x00220022},
1158 {RES4369_PWRSW_DIG, 0x02100087},
1159 {RES4369_SR_DIG, 0x02000200},
1160 {RES4369_SLEEP_DIG, 0x00220022},
1161 {RES4369_PWRSW_AUX, 0x03900087},
1162 {RES4369_SR_AUX, 0x01cc01cc},
1163 {RES4369_SLEEP_AUX, 0x00220022},
1164 {RES4369_PWRSW_MAIN, 0x03900087},
1165 {RES4369_SR_MAIN, 0x02000200},
1166 {RES4369_SLEEP_MAIN, 0x00220022},
1167 {RES4369_DIG_CORE_RDY, 0x00220044},
1168 {RES4369_CORE_RDY_AUX, 0x00220044},
1169 {RES4369_ALP_AVAIL, 0x00220044},
1170 {RES4369_RADIO_AUX_PU, 0x006e0022},
1171 {RES4369_MINIPMU_AUX_PU, 0x00460022},
1172 {RES4369_CORE_RDY_MAIN, 0x00220022},
1173 {RES4369_RADIO_MAIN_PU, 0x006e0022},
1174 {RES4369_MINIPMU_MAIN_PU, 0x00460022},
1175 {RES4369_PCIE_EP_PU, 0x01200087},
1176 {RES4369_COLD_START_WAIT, 0x00220022},
1177 {RES4369_ARMHTAVAIL, 0x00a80022},
1178 {RES4369_HT_AVAIL, RES4369_HTAVAIL_VAL},
1179 {RES4369_MACPHY_AUX_CLK_AVAIL, 0x00640022},
1180 {RES4369_MACPHY_MAIN_CLK_AVAIL, 0x00640022},
1181 };
1182
1183 static pmu_res_depend_t BCMATTACHDATA(bcm4362_res_depend)[] = {
1184 {PMURES_BIT(RES4362_DUMMY), RES_DEPEND_SET, 0x00000000, NULL},
1185 {PMURES_BIT(RES4362_ABUCK), RES_DEPEND_SET, 0x00000005, NULL},
1186 {PMURES_BIT(RES4362_PMU_SLEEP), RES_DEPEND_SET, 0x00000001, NULL},
1187 {PMURES_BIT(RES4362_MISCLDO_PU), RES_DEPEND_SET, 0x00000007, NULL},
1188 {PMURES_BIT(RES4362_LDO3P3_PU), RES_DEPEND_SET, 0x00000005, NULL},
1189 {PMURES_BIT(RES4362_FAST_LPO_AVAIL), RES_DEPEND_SET, 0x00000005, NULL},
1190 {PMURES_BIT(RES4362_XTAL_PU), RES_DEPEND_SET, 0x00000007, NULL},
1191 {PMURES_BIT(RES4362_XTAL_STABLE), RES_DEPEND_SET, 0x00000047, NULL},
1192 {PMURES_BIT(RES4362_PWRSW_DIG), RES_DEPEND_SET, 0x060000cf, NULL},
1193 {PMURES_BIT(RES4362_SR_DIG), RES_DEPEND_SET, 0x060001cf, NULL},
1194 {PMURES_BIT(RES4362_SLEEP_DIG), RES_DEPEND_SET, 0x060003cf, NULL},
1195 {PMURES_BIT(RES4362_PWRSW_AUX), RES_DEPEND_SET, 0x040000cf, NULL},
1196 {PMURES_BIT(RES4362_SR_AUX), RES_DEPEND_SET, 0x040008cf, NULL},
1197 {PMURES_BIT(RES4362_SLEEP_AUX), RES_DEPEND_SET, 0x040018cf, NULL},
1198 {PMURES_BIT(RES4362_PWRSW_MAIN), RES_DEPEND_SET, 0x040000cf, NULL},
1199 {PMURES_BIT(RES4362_SR_MAIN), RES_DEPEND_SET, 0x040040cf, NULL},
1200 {PMURES_BIT(RES4362_SLEEP_MAIN), RES_DEPEND_SET, 0x0400c0cf, NULL},
1201 {PMURES_BIT(RES4362_DIG_CORE_RDY), RES_DEPEND_SET, 0x060007cf, NULL},
1202 {PMURES_BIT(RES4362_CORE_RDY_AUX), RES_DEPEND_SET, 0x040038cf, NULL},
1203 {PMURES_BIT(RES4362_ALP_AVAIL), RES_DEPEND_SET, 0x060207cf, NULL},
1204 {PMURES_BIT(RES4362_RADIO_AUX_PU), RES_DEPEND_SET, 0x040438df, NULL},
1205 {PMURES_BIT(RES4362_MINIPMU_AUX_PU), RES_DEPEND_SET, 0x041438df, NULL},
1206 {PMURES_BIT(RES4362_CORE_RDY_MAIN), RES_DEPEND_SET, 0x0401c0cf, NULL},
1207 {PMURES_BIT(RES4362_RADIO_MAIN_PU), RES_DEPEND_SET, 0x0441c0df, NULL},
1208 {PMURES_BIT(RES4362_MINIPMU_MAIN_PU), RES_DEPEND_SET, 0x04c1c0df, NULL},
1209 {PMURES_BIT(RES4362_PCIE_EP_PU), RES_DEPEND_SET, 0x040000cf, NULL},
1210 {PMURES_BIT(RES4362_COLD_START_WAIT), RES_DEPEND_SET, 0x0000000f, NULL},
1211 {PMURES_BIT(RES4362_ARMHTAVAIL), RES_DEPEND_SET, 0x060a07cf, NULL},
1212 {PMURES_BIT(RES4362_HT_AVAIL), RES_DEPEND_SET, 0x060a07cf, NULL},
1213 {PMURES_BIT(RES4362_MACPHY_AUX_CLK_AVAIL), RES_DEPEND_SET, 0x163e3fdf, NULL},
1214 {PMURES_BIT(RES4362_MACPHY_MAIN_CLK_AVAIL), RES_DEPEND_SET, 0x17cbc7df, NULL},
1215 };
1216
1217 static const pmu_res_updown_t BCMATTACHDATA(bcm4362_res_updown)[] = {
1218 {RES4362_DUMMY, 0x00220022},
1219 {RES4362_ABUCK, 0x00c80022},
1220 {RES4362_PMU_SLEEP, 0x00c80022},
1221 {RES4362_MISCLDO_PU, 0x00bd0022},
1222 {RES4362_LDO3P3_PU, 0x01ad0022},
1223 {RES4362_FAST_LPO_AVAIL, 0x01500022},
1224 {RES4362_XTAL_PU, 0x05dc0022},
1225 {RES4362_XTAL_STABLE, 0x00220022},
1226 {RES4362_PWRSW_DIG, 0x009000ca},
1227 {RES4362_SR_DIG, 0x00A000A0},
1228 {RES4362_SLEEP_DIG, 0x00220022},
1229 {RES4362_PWRSW_AUX, 0x039000ca},
1230 {RES4362_SR_AUX, 0x01400140},
1231 {RES4362_SLEEP_AUX, 0x00220022},
1232 {RES4362_PWRSW_MAIN, 0x039000ca},
1233 {RES4362_SR_MAIN, 0x01a001a0},
1234 {RES4362_SLEEP_MAIN, 0x00220022},
1235 {RES4362_DIG_CORE_RDY, 0x00220044},
1236 {RES4362_CORE_RDY_AUX, 0x00220044},
1237 {RES4362_ALP_AVAIL, 0x00220044},
1238 {RES4362_RADIO_AUX_PU, 0x006e0022},
1239 {RES4362_MINIPMU_AUX_PU, 0x00460022},
1240 {RES4362_CORE_RDY_MAIN, 0x00220022},
1241 {RES4362_RADIO_MAIN_PU, 0x006e0022},
1242 {RES4362_MINIPMU_MAIN_PU, 0x00460022},
1243 {RES4362_PCIE_EP_PU, 0x009000ca},
1244 {RES4362_COLD_START_WAIT, 0x00220022},
1245 {RES4362_ARMHTAVAIL, 0x00a80022},
1246 {RES4362_HT_AVAIL, 0x00a80022},
1247 {RES4362_MACPHY_AUX_CLK_AVAIL, 0x00640022},
1248 {RES4362_MACPHY_MAIN_CLK_AVAIL, 0x00640022},
1249 };
1250
1251 static const pmu_res_updown_t BCMATTACHDATA(bcm4378b0_res_updown)[] = {
1252 {RES4378_ABUCK, 0x00c80022},
1253 {RES4378_PMU_SLEEP, 0x011c0022},
1254 {RES4378_MISC_LDO, 0x00c80022},
1255 {RES4378_XTAL_PU, 0x05dc0022},
1256 {RES4378_SR_DIG, 0x00700070},
1257 {RES4378_SR_AUX, 0x01800180},
1258 {RES4378_SR_MAIN, 0x01a001a0},
1259 {RES4378_RADIO_AUX_PU, 0x006e0022},
1260 {RES4378_MINIPMU_AUX_PU, 0x00460022},
1261 {RES4378_RADIO_MAIN_PU, 0x006e0022},
1262 {RES4378_MINIPMU_MAIN_PU, 0x00460022},
1263 {RES4378_CORE_RDY_CB, 0x00220022},
1264 #ifdef BCMPCIE_TREFUP_HW_SUPPORT
1265 {RES4378_PWRSW_CB, 0x015e00ca},
1266 #endif
1267 {RES4378_MACPHY_AUX_CLK_AVAIL, 0x00640022},
1268 {RES4378_MACPHY_MAIN_CLK_AVAIL, 0x00640022},
1269 };
1270
1271 static pmu_res_depend_t BCMATTACHDATA(bcm4378b0_res_depend)[] = {
1272 {PMURES_BIT(RES4378_ABUCK), RES_DEPEND_SET, 0x00000005, NULL},
1273 {PMURES_BIT(RES4378_PMU_SLEEP), RES_DEPEND_SET, 0x00000001, NULL},
1274 {PMURES_BIT(RES4378_MISC_LDO), RES_DEPEND_SET, 0x00000007, NULL},
1275 {PMURES_BIT(RES4378_LDO3P3_PU), RES_DEPEND_SET, 0x00000001, NULL},
1276 {PMURES_BIT(RES4378_FAST_LPO_AVAIL), RES_DEPEND_SET, 0x00000005, NULL},
1277 {PMURES_BIT(RES4378_XTAL_PU), RES_DEPEND_SET, 0x00000007, NULL},
1278 {PMURES_BIT(RES4378_XTAL_STABLE), RES_DEPEND_SET, 0x00000047, NULL},
1279 {PMURES_BIT(RES4378_PWRSW_DIG), RES_DEPEND_SET, 0x060000ef, NULL},
1280 {PMURES_BIT(RES4378_SR_DIG), RES_DEPEND_SET, 0x060001ef, NULL},
1281 {PMURES_BIT(RES4378_SLEEP_DIG), RES_DEPEND_SET, 0x060003ef, NULL},
1282 {PMURES_BIT(RES4378_PWRSW_AUX), RES_DEPEND_SET, 0x060000ef, NULL},
1283 {PMURES_BIT(RES4378_SR_AUX), RES_DEPEND_SET, 0x060008ef, NULL},
1284 {PMURES_BIT(RES4378_SLEEP_AUX), RES_DEPEND_SET, 0x060018ef, NULL},
1285 {PMURES_BIT(RES4378_PWRSW_MAIN), RES_DEPEND_SET, 0x060000ef, NULL},
1286 {PMURES_BIT(RES4378_SR_MAIN), RES_DEPEND_SET, 0x060040ef, NULL},
1287 {PMURES_BIT(RES4378_SLEEP_MAIN), RES_DEPEND_SET, 0x0600c0ef, NULL},
1288 {PMURES_BIT(RES4378_CORE_RDY_DIG), RES_DEPEND_SET, 0x060007ef, NULL},
1289 {PMURES_BIT(RES4378_CORE_RDY_AUX), RES_DEPEND_SET, 0x06023fef, NULL},
1290 {PMURES_BIT(RES4378_ALP_AVAIL), RES_DEPEND_SET, 0x000000c7, NULL},
1291 {PMURES_BIT(RES4378_RADIO_AUX_PU), RES_DEPEND_SET, 0x06063fff, NULL},
1292 {PMURES_BIT(RES4378_MINIPMU_AUX_PU), RES_DEPEND_SET, 0x06163fff, NULL},
1293 {PMURES_BIT(RES4378_CORE_RDY_MAIN), RES_DEPEND_SET, 0x0603c7ef, NULL},
1294 {PMURES_BIT(RES4378_RADIO_MAIN_PU), RES_DEPEND_SET, 0x0643c7ff, NULL},
1295 {PMURES_BIT(RES4378_MINIPMU_MAIN_PU), RES_DEPEND_SET, 0x06c3c7ff, NULL},
1296 #ifdef BCMPCIE_TREFUP_HW_SUPPORT
1297 {PMURES_BIT(RES4378_CORE_RDY_CB), RES_DEPEND_SET, 0x0400002f, NULL},
1298 #else
1299 {PMURES_BIT(RES4378_CORE_RDY_CB), RES_DEPEND_SET, 0x040000ef, NULL},
1300 #endif
1301 {PMURES_BIT(RES4378_PWRSW_CB), RES_DEPEND_SET, 0x0000002f, NULL},
1302 {PMURES_BIT(RES4378_ARMHTAVAIL), RES_DEPEND_SET, 0x000800c7, NULL},
1303 {PMURES_BIT(RES4378_HT_AVAIL), RES_DEPEND_SET, 0x000800c7, NULL},
1304 {PMURES_BIT(RES4378_MACPHY_AUX_CLK_AVAIL), RES_DEPEND_SET, 0x163e3fff, NULL},
1305 {PMURES_BIT(RES4378_MACPHY_MAIN_CLK_AVAIL), RES_DEPEND_SET, 0x17cbc7ff, NULL},
1306 };
1307
1308 static const pmu_res_updown_t BCMATTACHDATA(bcm4387b0_res_updown_qt)[] = {
1309 {RES4387_XTAL_PU, 0x012c0033},
1310 {RES4387_PWRSW_DIG, 0x38993899},
1311 {RES4387_PWRSW_AUX, 0x38993899},
1312 {RES4387_PWRSW_SCAN, 0x38993899},
1313 {RES4387_PWRSW_MAIN, 0x38993899},
1314 {RES4387_CORE_RDY_CB, 0x00960033},
1315 };
1316
1317 static const pmu_res_subst_trans_tmr_t BCMATTACHDATA(bcm4387b0_res_subst_trans_tmr_qt)[] = {
1318 {RES4387_PWRSW_DIG, 0, 0x38993800},
1319 {RES4387_PWRSW_DIG, 1, 0x36000600},
1320 {RES4387_PWRSW_DIG, 2, 0x01000002},
1321
1322 {RES4387_PWRSW_AUX, 0, 0x38993800},
1323 {RES4387_PWRSW_AUX, 1, 0x36000600},
1324 {RES4387_PWRSW_AUX, 2, 0x01000002},
1325
1326 {RES4387_PWRSW_SCAN, 0, 0x38993800},
1327 {RES4387_PWRSW_SCAN, 1, 0x36000600},
1328 {RES4387_PWRSW_SCAN, 2, 0x01000002},
1329
1330 {RES4387_PWRSW_MAIN, 0, 0x38993800},
1331 {RES4387_PWRSW_MAIN, 1, 0x36000600},
1332 {RES4387_PWRSW_MAIN, 2, 0x01000002},
1333 };
1334
1335 static const pmu_res_updown_t BCMATTACHDATA(bcm4387b0_res_updown)[] = {
1336 {RES4387_PMU_SLEEP, 0x00960022},
1337 {RES4387_MISC_LDO, 0x00320022},
1338 {RES4387_XTAL_HQ, 0x00210021},
1339 {RES4387_XTAL_PU, 0x03e80033},
1340 {RES4387_PWRSW_DIG, 0x04b002bc},
1341 {RES4387_PWRSW_AUX, 0x060e03bc},
1342 {RES4387_PWRSW_SCAN, 0x060e03bc},
1343 {RES4387_PWRSW_MAIN, 0x060e03bc},
1344 {RES4387_CORE_RDY_CB, 0x000a0033},
1345 {RES4387_PWRSW_CB, 0x006400ca},
1346 };
1347
1348 static const pmu_res_subst_trans_tmr_t BCMATTACHDATA(bcm4387b0_res_subst_trans_tmr)[] = {
1349 {RES4387_PWRSW_DIG, 0, 0x04b002bc},
1350 {RES4387_PWRSW_DIG, 1, 0x02500210},
1351 {RES4387_PWRSW_DIG, 2, 0x00a00010},
1352
1353 {RES4387_PWRSW_AUX, 0, 0x060e03ac},
1354 {RES4387_PWRSW_AUX, 1, 0x028a0134},
1355 {RES4387_PWRSW_AUX, 2, 0x00320002},
1356
1357 {RES4387_PWRSW_MAIN, 0, 0x060e03b2},
1358 {RES4387_PWRSW_MAIN, 1, 0x028a0134},
1359 {RES4387_PWRSW_MAIN, 2, 0x00320002},
1360
1361 {RES4387_PWRSW_SCAN, 0, 0x060e03b2},
1362 {RES4387_PWRSW_SCAN, 1, 0x028a0134},
1363 {RES4387_PWRSW_SCAN, 2, 0x00320002},
1364 };
1365
1366 static pmu_res_depend_t BCMATTACHDATA(bcm4387b0_res_depend)[] = {
1367 {PMURES_BIT(RES4387_DUMMY), RES_DEPEND_SET, 0x0, NULL},
1368 {PMURES_BIT(RES4387_RESERVED_1), RES_DEPEND_SET, 0x0, NULL},
1369 {PMURES_BIT(RES4387_PMU_SLEEP), RES_DEPEND_SET, 0x1, NULL},
1370 {PMURES_BIT(RES4387_MISC_LDO), RES_DEPEND_SET, 0x5, NULL},
1371 {PMURES_BIT(RES4387_RESERVED_4), RES_DEPEND_SET, 0x0, NULL},
1372 {PMURES_BIT(RES4387_XTAL_HQ), RES_DEPEND_SET, 0xc5, NULL},
1373 {PMURES_BIT(RES4387_XTAL_PU), RES_DEPEND_SET, 0x5, NULL},
1374 {PMURES_BIT(RES4387_XTAL_STABLE), RES_DEPEND_SET, 0x45, NULL},
1375 {PMURES_BIT(RES4387_PWRSW_DIG), RES_DEPEND_SET, 0x060000CD, NULL},
1376 {PMURES_BIT(RES4387_CORE_RDY_BTMAIN), RES_DEPEND_SET, 0xCD, NULL},
1377 {PMURES_BIT(RES4387_CORE_RDY_BTSC), RES_DEPEND_SET, 0xC5, NULL},
1378 {PMURES_BIT(RES4387_PWRSW_AUX), RES_DEPEND_SET, 0xCD, NULL},
1379 {PMURES_BIT(RES4387_PWRSW_SCAN), RES_DEPEND_SET, 0xCD, NULL},
1380 {PMURES_BIT(RES4387_CORE_RDY_SCAN), RES_DEPEND_SET, 0x060010CD, NULL},
1381 {PMURES_BIT(RES4387_PWRSW_MAIN), RES_DEPEND_SET, 0xCD, NULL},
1382 {PMURES_BIT(RES4387_RESERVED_15), RES_DEPEND_SET, 0x0, NULL},
1383 {PMURES_BIT(RES4387_RESERVED_16), RES_DEPEND_SET, 0x0, NULL},
1384 {PMURES_BIT(RES4387_CORE_RDY_DIG), RES_DEPEND_SET, 0x060001CD, NULL},
1385 {PMURES_BIT(RES4387_CORE_RDY_AUX), RES_DEPEND_SET, 0x060209CD, NULL},
1386 {PMURES_BIT(RES4387_ALP_AVAIL), RES_DEPEND_SET, 0xC5, NULL},
1387 {PMURES_BIT(RES4387_RADIO_PU_AUX), RES_DEPEND_SET, 0x060609CD, NULL},
1388 {PMURES_BIT(RES4387_RADIO_PU_SCAN), RES_DEPEND_SET, 0x060030CD, NULL},
1389 {PMURES_BIT(RES4387_CORE_RDY_MAIN), RES_DEPEND_SET, 0x060241CD, NULL},
1390 {PMURES_BIT(RES4387_RADIO_PU_MAIN), RES_DEPEND_SET, 0x064241CD, NULL},
1391 {PMURES_BIT(RES4387_MACPHY_CLK_SCAN), RES_DEPEND_SET, 0x162830CD, NULL},
1392 {PMURES_BIT(RES4387_CORE_RDY_CB), RES_DEPEND_SET, 0x0400000D, NULL},
1393 {PMURES_BIT(RES4387_PWRSW_CB), RES_DEPEND_SET, 0x0000000D, NULL},
1394 {PMURES_BIT(RES4387_ARMCLK_AVAIL), RES_DEPEND_SET, 0x000800CD, NULL},
1395 {PMURES_BIT(RES4387_HT_AVAIL), RES_DEPEND_SET, 0x000800CD, NULL},
1396 {PMURES_BIT(RES4387_MACPHY_CLK_AUX), RES_DEPEND_SET, 0x161E09ED, NULL},
1397 {PMURES_BIT(RES4387_MACPHY_CLK_MAIN), RES_DEPEND_SET, 0x16CA41ED, NULL},
1398 };
1399
1400 static const pmu_res_updown_t BCMATTACHDATA(bcm4387c0_res_updown_topoff)[] = {
1401 {RES4387_PMU_SLEEP, 0x02000022},
1402 {RES4387_MISC_LDO, 0x00320022},
1403 {RES4387_SERDES_AFE_RET, 0x00010001},
1404 {RES4387_XTAL_HQ, 0x00210021},
1405 {RES4387_XTAL_PU, 0x03e80033},
1406 {RES4387_PWRSW_DIG, 0x00d20102},
1407 {RES4387_PWRSW_AUX, 0x01c201e2},
1408 {RES4387_PWRSW_SCAN, 0x01020122},
1409 {RES4387_PWRSW_MAIN, 0x02220242},
1410 {RES4387_CORE_RDY_CB, 0x000a0033},
1411 {RES4387_PWRSW_CB, 0x006400ca},
1412 };
1413
1414 static const pmu_res_updown_t BCMATTACHDATA(bcm4387c0_res_updown)[] = {
1415 #ifdef BCM_PMU_FLL_PU_MANAGE
1416 {RES4387_FAST_LPO_AVAIL, 0x00960001},
1417 #endif
1418 {RES4387_PMU_SLEEP, 0x00960022},
1419 {RES4387_MISC_LDO, 0x00320022},
1420 {RES4387_XTAL_HQ, 0x00210021},
1421 {RES4387_XTAL_PU, 0x03e80033},
1422 {RES4387_PWRSW_DIG, 0x01320172},
1423 {RES4387_PWRSW_AUX, 0x01c201e2},
1424 {RES4387_PWRSW_SCAN, 0x019201b2},
1425 {RES4387_PWRSW_MAIN, 0x02220242},
1426 {RES4387_CORE_RDY_CB, 0x000a0033},
1427 {RES4387_PWRSW_CB, 0x006400ca},
1428 };
1429
1430 static const pmu_res_subst_trans_tmr_t BCMATTACHDATA(bcm4387c0_res_subst_trans_tmr)[] = {
1431 {RES4387_PWRSW_DIG, 0, 0x01320142},
1432 {RES4387_PWRSW_DIG, 1, 0x00e2005a},
1433 {RES4387_PWRSW_DIG, 2, 0x00c20052},
1434 {RES4387_PWRSW_DIG, 3, 0x00020002},
1435
1436 {RES4387_PWRSW_AUX, 0, 0x01c201b2},
1437 {RES4387_PWRSW_AUX, 1, 0x0172005a},
1438 {RES4387_PWRSW_AUX, 2, 0x01520052},
1439 {RES4387_PWRSW_AUX, 3, 0x00020002},
1440
1441 {RES4387_PWRSW_MAIN, 0, 0x02220212},
1442 {RES4387_PWRSW_MAIN, 1, 0x01d2005a},
1443 {RES4387_PWRSW_MAIN, 2, 0x01b20052},
1444 {RES4387_PWRSW_MAIN, 3, 0x00020002},
1445
1446 {RES4387_PWRSW_SCAN, 0, 0x01920182},
1447 {RES4387_PWRSW_SCAN, 1, 0x0142005a},
1448 {RES4387_PWRSW_SCAN, 2, 0x01220052},
1449 {RES4387_PWRSW_SCAN, 3, 0x00020002},
1450 };
1451
1452 static pmu_res_depend_t BCMATTACHDATA(bcm4387c0_res_depend)[] = {
1453 {PMURES_BIT(RES4387_DUMMY), RES_DEPEND_SET, 0x0, NULL},
1454 {PMURES_BIT(RES4387_FAST_LPO_AVAIL), RES_DEPEND_SET, 0x0, NULL},
1455 {PMURES_BIT(RES4387_PMU_LP), RES_DEPEND_SET, 0x1, NULL},
1456 {PMURES_BIT(RES4387_MISC_LDO), RES_DEPEND_SET, 0x5, NULL},
1457 {PMURES_BIT(RES4387_SERDES_AFE_RET), RES_DEPEND_SET, 0xD, NULL},
1458 {PMURES_BIT(RES4387_XTAL_HQ), RES_DEPEND_SET, 0xC5, NULL},
1459 {PMURES_BIT(RES4387_XTAL_PU), RES_DEPEND_SET, 0x5, NULL},
1460 {PMURES_BIT(RES4387_XTAL_STABLE), RES_DEPEND_SET, 0x45, NULL},
1461 {PMURES_BIT(RES4387_PWRSW_DIG), RES_DEPEND_SET, 0x060000DD, NULL},
1462 {PMURES_BIT(RES4387_CORE_RDY_BTMAIN), RES_DEPEND_SET, 0xCD, NULL},
1463 {PMURES_BIT(RES4387_CORE_RDY_BTSC), RES_DEPEND_SET, 0xC5, NULL},
1464 {PMURES_BIT(RES4387_PWRSW_AUX), RES_DEPEND_SET, 0xCD, NULL},
1465 {PMURES_BIT(RES4387_PWRSW_SCAN), RES_DEPEND_SET, 0xCD, NULL},
1466 {PMURES_BIT(RES4387_CORE_RDY_SCAN), RES_DEPEND_SET, 0x060010DD, NULL},
1467 {PMURES_BIT(RES4387_PWRSW_MAIN), RES_DEPEND_SET, 0xCD, NULL},
1468 {PMURES_BIT(RES4387_XTAL_PM_CLK), RES_DEPEND_SET, 0xC5, NULL},
1469 {PMURES_BIT(RES4387_RESERVED_16), RES_DEPEND_SET, 0x0, NULL},
1470 {PMURES_BIT(RES4387_CORE_RDY_DIG), RES_DEPEND_SET, 0x060001DD, NULL},
1471 {PMURES_BIT(RES4387_CORE_RDY_AUX), RES_DEPEND_SET, 0x060209DD, NULL},
1472 {PMURES_BIT(RES4387_ALP_AVAIL), RES_DEPEND_SET, 0x80C5, NULL},
1473 {PMURES_BIT(RES4387_RADIO_PU_AUX), RES_DEPEND_SET, 0x060609DD, NULL},
1474 {PMURES_BIT(RES4387_RADIO_PU_SCAN), RES_DEPEND_SET, 0x060030DD, NULL},
1475 {PMURES_BIT(RES4387_CORE_RDY_MAIN), RES_DEPEND_SET, 0x060241DD, NULL},
1476 {PMURES_BIT(RES4387_RADIO_PU_MAIN), RES_DEPEND_SET, 0x064241DD, NULL},
1477 {PMURES_BIT(RES4387_MACPHY_CLK_SCAN), RES_DEPEND_SET, 0x1628B0DD, NULL},
1478 {PMURES_BIT(RES4387_CORE_RDY_CB), RES_DEPEND_SET, 0x0400001D, NULL},
1479 {PMURES_BIT(RES4387_PWRSW_CB), RES_DEPEND_SET, 0x0000001D, NULL},
1480 {PMURES_BIT(RES4387_ARMCLK_AVAIL), RES_DEPEND_SET, 0x000880CD, NULL},
1481 {PMURES_BIT(RES4387_HT_AVAIL), RES_DEPEND_SET, 0x000880CD, NULL},
1482 {PMURES_BIT(RES4387_MACPHY_CLK_AUX), RES_DEPEND_SET, 0x161E89FD, NULL},
1483 {PMURES_BIT(RES4387_MACPHY_CLK_MAIN), RES_DEPEND_SET, 0x16CAC1FD, NULL},
1484 };
1485
1486 static const pmu_res_updown_t BCMATTACHDATA(bcm4388a0_res_updown_qt)[] = {
1487 {RES4388_XTAL_PU, 0x012c0033},
1488 {RES4388_PWRSW_DIG, 0x38993899},
1489 {RES4388_PWRSW_AUX, 0x38993899},
1490 {RES4388_PWRSW_SCAN, 0x38993899},
1491 {RES4388_PWRSW_MAIN, 0x38993899},
1492 {RES4388_CORE_RDY_CB, 0x00960033},
1493 };
1494
1495 static const pmu_res_subst_trans_tmr_t BCMATTACHDATA(bcm4388a0_res_subst_trans_tmr_qt)[] = {
1496 {RES4388_PWRSW_DIG, 0, 0x38993800},
1497 {RES4388_PWRSW_DIG, 1, 0x36c00600},
1498 {RES4388_PWRSW_DIG, 2, 0x360005a0},
1499 {RES4388_PWRSW_DIG, 3, 0x01000002},
1500
1501 {RES4388_PWRSW_AUX, 0, 0x38993800},
1502 {RES4388_PWRSW_AUX, 1, 0x36c00600},
1503 {RES4388_PWRSW_AUX, 2, 0x360005a0},
1504 {RES4388_PWRSW_AUX, 3, 0x01000002},
1505
1506 {RES4388_PWRSW_MAIN, 0, 0x38993800},
1507 {RES4388_PWRSW_MAIN, 1, 0x36c00600},
1508 {RES4388_PWRSW_MAIN, 2, 0x360005a0},
1509 {RES4388_PWRSW_MAIN, 3, 0x01000002},
1510
1511 {RES4388_PWRSW_SCAN, 0, 0x38993800},
1512 {RES4388_PWRSW_SCAN, 1, 0x33c00600},
1513 {RES4388_PWRSW_SCAN, 2, 0x330005a0},
1514 {RES4388_PWRSW_SCAN, 3, 0x01000002},
1515 };
1516
1517 static const pmu_res_updown_t BCMATTACHDATA(bcm4388a0_res_updown)[] = {
1518 #ifdef BCM_PMU_FLL_PU_MANAGE
1519 {RES4388_FAST_LPO_AVAIL, 0x00960001},
1520 #endif /* BCM_PMU_FLL_PU_MANAGE */
1521 {RES4388_PMU_LP, 0x00960022},
1522 {RES4388_MISC_LDO, 0x00320022},
1523 {RES4388_XTAL_HQ, 0x00210021},
1524 {RES4388_XTAL_PU, 0x03e80033},
1525 {RES4388_PWRSW_DIG, 0x042c0349},
1526 {RES4388_PWRSW_AUX, 0x0740046a},
1527 {RES4388_PWRSW_SCAN, 0x03c802e8},
1528 {RES4388_PWRSW_MAIN, 0x08080532},
1529 {RES4388_CORE_RDY_CB, 0x000a0033},
1530 {RES4388_PWRSW_CB, 0x006400ca},
1531 {RES4388_MACPHY_CLK_MAIN, 0x00860022},
1532 };
1533
1534 static const pmu_res_subst_trans_tmr_t BCMATTACHDATA(bcm4388a0_res_subst_trans_tmr)[] = {
1535 {RES4388_PWRSW_DIG, 0, 0x0428033c},
1536 {RES4388_PWRSW_DIG, 1, 0x028c0210},
1537 {RES4388_PWRSW_DIG, 2, 0x01cc01b0},
1538 {RES4388_PWRSW_DIG, 3, 0x00a00010},
1539
1540 {RES4388_PWRSW_AUX, 0, 0x0740045a},
1541 {RES4388_PWRSW_AUX, 1, 0x03580202},
1542 {RES4388_PWRSW_AUX, 2, 0x02f801a2},
1543 {RES4388_PWRSW_AUX, 3, 0x00a00002},
1544
1545 {RES4388_PWRSW_MAIN, 0, 0x08080522},
1546 {RES4388_PWRSW_MAIN, 1, 0x04200202},
1547 {RES4388_PWRSW_MAIN, 2, 0x03c001a2},
1548 {RES4388_PWRSW_MAIN, 3, 0x00a00002},
1549
1550 {RES4388_PWRSW_SCAN, 0, 0x03c402d8},
1551 {RES4388_PWRSW_SCAN, 1, 0x02280210},
1552 {RES4388_PWRSW_SCAN, 2, 0x016801b0},
1553 {RES4388_PWRSW_SCAN, 3, 0x00a00010},
1554 };
1555
1556 static pmu_res_depend_t BCMATTACHDATA(bcm4388a0_res_depend)[] = {
1557 {PMURES_BIT(RES4388_DUMMY), RES_DEPEND_SET, 0x00000000, NULL},
1558 {PMURES_BIT(RES4388_FAST_LPO_AVAIL), RES_DEPEND_SET, 0x00000000, NULL},
1559 {PMURES_BIT(RES4388_PMU_LP), RES_DEPEND_SET, 0x00000001, NULL},
1560 {PMURES_BIT(RES4388_MISC_LDO), RES_DEPEND_SET, 0x00000005, NULL},
1561 {PMURES_BIT(RES4388_SERDES_AFE_RET), RES_DEPEND_SET, 0x0000000d, NULL},
1562 {PMURES_BIT(RES4388_XTAL_HQ), RES_DEPEND_SET, 0x000000c5, NULL},
1563 {PMURES_BIT(RES4388_XTAL_PU), RES_DEPEND_SET, 0x00000005, NULL},
1564 {PMURES_BIT(RES4388_XTAL_STABLE), RES_DEPEND_SET, 0x00000045, NULL},
1565 {PMURES_BIT(RES4388_PWRSW_DIG), RES_DEPEND_SET, 0x060000dd, NULL},
1566 {PMURES_BIT(RES4388_BTMC_TOP_RDY), RES_DEPEND_SET, 0x000000cd, NULL},
1567 {PMURES_BIT(RES4388_BTSC_TOP_RDY), RES_DEPEND_SET, 0x000000c5, NULL},
1568 {PMURES_BIT(RES4388_PWRSW_AUX), RES_DEPEND_SET, 0x000000cd, NULL},
1569 {PMURES_BIT(RES4388_PWRSW_SCAN), RES_DEPEND_SET, 0x000000cd, NULL},
1570 {PMURES_BIT(RES4388_CORE_RDY_SCAN), RES_DEPEND_SET, 0x060211dd, NULL},
1571 {PMURES_BIT(RES4388_PWRSW_MAIN), RES_DEPEND_SET, 0x000000cd, NULL},
1572 {PMURES_BIT(RES4388_RESERVED_15), RES_DEPEND_SET, 0x00000000, NULL},
1573 {PMURES_BIT(RES4388_RESERVED_16), RES_DEPEND_SET, 0x00000000, NULL},
1574 {PMURES_BIT(RES4388_CORE_RDY_DIG), RES_DEPEND_SET, 0x060001dd, NULL},
1575 {PMURES_BIT(RES4388_CORE_RDY_AUX), RES_DEPEND_SET, 0x060209dd, NULL},
1576 {PMURES_BIT(RES4388_ALP_AVAIL), RES_DEPEND_SET, 0x000000c5, NULL},
1577 {PMURES_BIT(RES4388_RADIO_PU_AUX), RES_DEPEND_SET, 0x060609dd, NULL},
1578 {PMURES_BIT(RES4388_RADIO_PU_SCAN), RES_DEPEND_SET, 0x060231dd, NULL},
1579 {PMURES_BIT(RES4388_CORE_RDY_MAIN), RES_DEPEND_SET, 0x060241dd, NULL},
1580 {PMURES_BIT(RES4388_RADIO_PU_MAIN), RES_DEPEND_SET, 0x064241dd, NULL},
1581 {PMURES_BIT(RES4388_MACPHY_CLK_SCAN), RES_DEPEND_SET, 0x162a31fd, NULL},
1582 {PMURES_BIT(RES4388_CORE_RDY_CB), RES_DEPEND_SET, 0x040000dd, NULL},
1583 {PMURES_BIT(RES4388_PWRSW_CB), RES_DEPEND_SET, 0x000000dd, NULL},
1584 {PMURES_BIT(RES4388_ARMCLKAVAIL), RES_DEPEND_SET, 0x000800cd, NULL},
1585 {PMURES_BIT(RES4388_HT_AVAIL), RES_DEPEND_SET, 0x000800cd, NULL},
1586 {PMURES_BIT(RES4388_MACPHY_CLK_AUX), RES_DEPEND_SET, 0x161e09fd, NULL},
1587 {PMURES_BIT(RES4388_MACPHY_CLK_MAIN), RES_DEPEND_SET, 0x16ca41fd, NULL},
1588 };
1589
1590 static const pmu_res_updown_t BCMATTACHDATA(bcm4389b0_res_updown_qt)[] = {
1591 {RES4389_XTAL_PU, 0x012c0033},
1592 {RES4389_PWRSW_DIG, 0x38993899},
1593 {RES4389_PWRSW_AUX, 0x38993899},
1594 {RES4389_PWRSW_SCAN, 0x38993899},
1595 {RES4389_PWRSW_MAIN, 0x38993899},
1596 {RES4389_CORE_RDY_CB, 0x00960033},
1597 };
1598
1599 static const pmu_res_subst_trans_tmr_t BCMATTACHDATA(bcm4389b0_res_subst_trans_tmr_qt)[] = {
1600 {RES4389_PWRSW_DIG, 0, 0x38993800},
1601 {RES4389_PWRSW_DIG, 1, 0x36c00600},
1602 {RES4389_PWRSW_DIG, 2, 0x360005a0},
1603 {RES4389_PWRSW_DIG, 3, 0x01000002},
1604
1605 {RES4389_PWRSW_AUX, 0, 0x38993800},
1606 {RES4389_PWRSW_AUX, 1, 0x36c00600},
1607 {RES4389_PWRSW_AUX, 2, 0x360005a0},
1608 {RES4389_PWRSW_AUX, 3, 0x01000002},
1609
1610 {RES4389_PWRSW_MAIN, 0, 0x38993800},
1611 {RES4389_PWRSW_MAIN, 1, 0x36c00600},
1612 {RES4389_PWRSW_MAIN, 2, 0x360005a0},
1613 {RES4389_PWRSW_MAIN, 3, 0x01000002},
1614
1615 {RES4389_PWRSW_SCAN, 0, 0x38993800},
1616 {RES4389_PWRSW_SCAN, 1, 0x33c00600},
1617 {RES4389_PWRSW_SCAN, 2, 0x330005a0},
1618 {RES4389_PWRSW_SCAN, 3, 0x01000002},
1619 };
1620
1621 static const pmu_res_updown_t BCMATTACHDATA(bcm4389b0_res_updown)[] = {
1622 #ifdef BCM_PMU_FLL_PU_MANAGE
1623 {RES4389_FAST_LPO_AVAIL, 0x001e0001},
1624 #endif /* BCM_PMU_FLL_PU_MANAGE */
1625 {RES4389_PMU_LP, 0x00960022},
1626 {RES4389_MISC_LDO, 0x00320022},
1627 {RES4389_XTAL_HQ, 0x00210021},
1628 {RES4389_XTAL_PU, 0x03e80033},
1629 {RES4389_PWRSW_DIG, 0x042c0349},
1630 {RES4389_PWRSW_AUX, 0x0740046a},
1631 {RES4389_PWRSW_SCAN, 0x03c802e8},
1632 {RES4389_PWRSW_MAIN, 0x08080532},
1633 {RES4389_CORE_RDY_CB, 0x000a0033},
1634 {RES4389_PWRSW_CB, 0x006400ca},
1635 {RES4389_MACPHY_CLK_MAIN, 0x00860022},
1636 };
1637
1638 static const pmu_res_subst_trans_tmr_t BCMATTACHDATA(bcm4389b0_res_subst_trans_tmr)[] = {
1639 {RES4389_PWRSW_DIG, 0, 0x0428033c},
1640 {RES4389_PWRSW_DIG, 1, 0x028c0210},
1641 {RES4389_PWRSW_DIG, 2, 0x01cc01b0},
1642 {RES4389_PWRSW_DIG, 3, 0x00a00010},
1643
1644 {RES4389_PWRSW_AUX, 0, 0x0740045a},
1645 {RES4389_PWRSW_AUX, 1, 0x03580202},
1646 {RES4389_PWRSW_AUX, 2, 0x02f801a2},
1647 {RES4389_PWRSW_AUX, 3, 0x00a00002},
1648
1649 {RES4389_PWRSW_MAIN, 0, 0x08080522},
1650 {RES4389_PWRSW_MAIN, 1, 0x04200202},
1651 {RES4389_PWRSW_MAIN, 2, 0x03c001a2},
1652 {RES4389_PWRSW_MAIN, 3, 0x00a00002},
1653
1654 {RES4389_PWRSW_SCAN, 0, 0x03c402d8},
1655 {RES4389_PWRSW_SCAN, 1, 0x02280210},
1656 {RES4389_PWRSW_SCAN, 2, 0x016801b0},
1657 {RES4389_PWRSW_SCAN, 3, 0x00a00010},
1658 };
1659
1660 static pmu_res_depend_t BCMATTACHDATA(bcm4389b0_res_depend)[] = {
1661 {PMURES_BIT(RES4389_DUMMY), RES_DEPEND_SET, 0x00000000, NULL},
1662 {PMURES_BIT(RES4389_FAST_LPO_AVAIL), RES_DEPEND_SET, 0x00000000, NULL},
1663 {PMURES_BIT(RES4389_PMU_LP), RES_DEPEND_SET, 0x00000001, NULL},
1664 {PMURES_BIT(RES4389_MISC_LDO), RES_DEPEND_SET, 0x00000005, NULL},
1665 {PMURES_BIT(RES4389_SERDES_AFE_RET), RES_DEPEND_SET, 0x0000000d, NULL},
1666 {PMURES_BIT(RES4389_XTAL_HQ), RES_DEPEND_SET, 0x000000c5, NULL},
1667 {PMURES_BIT(RES4389_XTAL_PU), RES_DEPEND_SET, 0x00000005, NULL},
1668 {PMURES_BIT(RES4389_XTAL_STABLE), RES_DEPEND_SET, 0x00000045, NULL},
1669 {PMURES_BIT(RES4389_PWRSW_DIG), RES_DEPEND_SET, 0x060000dd, NULL},
1670 {PMURES_BIT(RES4389_BTMC_TOP_RDY), RES_DEPEND_SET, 0x000000cd, NULL},
1671 {PMURES_BIT(RES4389_BTSC_TOP_RDY), RES_DEPEND_SET, 0x000000c5, NULL},
1672 {PMURES_BIT(RES4389_PWRSW_AUX), RES_DEPEND_SET, 0x000000cd, NULL},
1673 {PMURES_BIT(RES4389_PWRSW_SCAN), RES_DEPEND_SET, 0x000000cd, NULL},
1674 {PMURES_BIT(RES4389_CORE_RDY_SCAN), RES_DEPEND_SET, 0x060211dd, NULL},
1675 {PMURES_BIT(RES4389_PWRSW_MAIN), RES_DEPEND_SET, 0x000000cd, NULL},
1676 {PMURES_BIT(RES4389_RESERVED_15), RES_DEPEND_SET, 0x00000000, NULL},
1677 {PMURES_BIT(RES4389_RESERVED_16), RES_DEPEND_SET, 0x00000000, NULL},
1678 {PMURES_BIT(RES4389_CORE_RDY_DIG), RES_DEPEND_SET, 0x060001dd, NULL},
1679 {PMURES_BIT(RES4389_CORE_RDY_AUX), RES_DEPEND_SET, 0x060209dd, NULL},
1680 {PMURES_BIT(RES4389_ALP_AVAIL), RES_DEPEND_SET, 0x000000c5, NULL},
1681 {PMURES_BIT(RES4389_RADIO_PU_AUX), RES_DEPEND_SET, 0x060609dd, NULL},
1682 {PMURES_BIT(RES4389_RADIO_PU_SCAN), RES_DEPEND_SET, 0x060231dd, NULL},
1683 {PMURES_BIT(RES4389_CORE_RDY_MAIN), RES_DEPEND_SET, 0x060241dd, NULL},
1684 {PMURES_BIT(RES4389_RADIO_PU_MAIN), RES_DEPEND_SET, 0x064241dd, NULL},
1685 {PMURES_BIT(RES4389_MACPHY_CLK_SCAN), RES_DEPEND_SET, 0x162a31fd, NULL},
1686 {PMURES_BIT(RES4389_CORE_RDY_CB), RES_DEPEND_SET, 0x040000dd, NULL},
1687 {PMURES_BIT(RES4389_PWRSW_CB), RES_DEPEND_SET, 0x000000dd, NULL},
1688 {PMURES_BIT(RES4389_ARMCLKAVAIL), RES_DEPEND_SET, 0x000800cd, NULL},
1689 {PMURES_BIT(RES4389_HT_AVAIL), RES_DEPEND_SET, 0x000800cd, NULL},
1690 {PMURES_BIT(RES4389_MACPHY_CLK_AUX), RES_DEPEND_SET, 0x161e09fd, NULL},
1691 {PMURES_BIT(RES4389_MACPHY_CLK_MAIN), RES_DEPEND_SET, 0x16ca41fd, NULL},
1692 };
1693
1694 /** To enable avb timer clock feature */
si_pmu_avbtimer_enable(si_t * sih,osl_t * osh,bool set_flag)1695 void si_pmu_avbtimer_enable(si_t *sih, osl_t *osh, bool set_flag)
1696 {
1697 uint32 min_mask = 0, max_mask = 0;
1698 pmuregs_t *pmu;
1699 uint origidx;
1700
1701 /* Remember original core before switch to chipc/pmu */
1702 origidx = si_coreidx(sih);
1703 if (AOB_ENAB(sih)) {
1704 pmu = si_setcore(sih, PMU_CORE_ID, 0);
1705 } else {
1706 pmu = si_setcoreidx(sih, SI_CC_IDX);
1707 }
1708 ASSERT(pmu != NULL);
1709
1710 if ((CHIPID(sih->chip) == BCM4360_CHIP_ID || CHIPID(sih->chip) == BCM43460_CHIP_ID) &&
1711 CHIPREV(sih->chiprev) >= 0x3) {
1712 int cst_ht = CST4360_RSRC_INIT_MODE(sih->chipst) & 0x1;
1713 if (cst_ht == 0) {
1714 /* Enable the AVB timers for proxd feature */
1715 min_mask = R_REG(osh, &pmu->min_res_mask);
1716 max_mask = R_REG(osh, &pmu->max_res_mask);
1717 if (set_flag) {
1718 max_mask |= PMURES_BIT(RES4360_AVB_PLL_PWRSW_PU);
1719 max_mask |= PMURES_BIT(RES4360_PCIE_TL_CLK_AVAIL);
1720 min_mask |= PMURES_BIT(RES4360_AVB_PLL_PWRSW_PU);
1721 min_mask |= PMURES_BIT(RES4360_PCIE_TL_CLK_AVAIL);
1722 W_REG(osh, &pmu->min_res_mask, min_mask);
1723 W_REG(osh, &pmu->max_res_mask, max_mask);
1724 } else {
1725 AND_REG(osh, &pmu->min_res_mask,
1726 ~PMURES_BIT(RES4360_AVB_PLL_PWRSW_PU));
1727 AND_REG(osh, &pmu->min_res_mask,
1728 ~PMURES_BIT(RES4360_PCIE_TL_CLK_AVAIL));
1729 AND_REG(osh, &pmu->max_res_mask,
1730 ~PMURES_BIT(RES4360_AVB_PLL_PWRSW_PU));
1731 AND_REG(osh, &pmu->max_res_mask,
1732 ~PMURES_BIT(RES4360_PCIE_TL_CLK_AVAIL));
1733 }
1734 /* Need to wait 100 millisecond for the uptime */
1735 OSL_DELAY(100);
1736 }
1737 }
1738
1739 /* Return to original core */
1740 si_setcoreidx(sih, origidx);
1741 }
1742
1743 /**
1744 * Determines min/max rsrc masks. Normally hardware contains these masks, and software reads the
1745 * masks from hardware. Note that masks are sometimes dependent on chip straps.
1746 */
1747 static void
si_pmu_res_masks(si_t * sih,uint32 * pmin,uint32 * pmax)1748 si_pmu_res_masks(si_t *sih, uint32 *pmin, uint32 *pmax)
1749 {
1750 uint32 min_mask = 0, max_mask = 0;
1751
1752 /* determine min/max rsrc masks */
1753 switch (CHIPID(sih->chip)) {
1754 case BCM4360_CHIP_ID:
1755 case BCM4352_CHIP_ID:
1756 if (CHIPREV(sih->chiprev) >= 0x4) {
1757 min_mask = 0x103;
1758 }
1759 /* Continue - Don't break */
1760 case BCM43460_CHIP_ID:
1761 case BCM43526_CHIP_ID:
1762 if (CHIPREV(sih->chiprev) >= 0x3) {
1763 /* PR 110203 */
1764 int cst_ht = CST4360_RSRC_INIT_MODE(sih->chipst) & 0x1;
1765 if (cst_ht == 0)
1766 max_mask = 0x1ff;
1767 }
1768 break;
1769
1770 CASE_BCM43602_CHIP:
1771 /* as a bare minimum, have ALP clock running */
1772 min_mask = PMURES_BIT(RES43602_LPLDO_PU) | PMURES_BIT(RES43602_REGULATOR) |
1773 PMURES_BIT(RES43602_PMU_SLEEP) | PMURES_BIT(RES43602_XTALLDO_PU) |
1774 PMURES_BIT(RES43602_SERDES_PU) | PMURES_BIT(RES43602_BBPLL_PWRSW_PU) |
1775 PMURES_BIT(RES43602_SR_CLK_START) | PMURES_BIT(RES43602_SR_PHY_PWRSW) |
1776 PMURES_BIT(RES43602_SR_SUBCORE_PWRSW) | PMURES_BIT(RES43602_XTAL_PU) |
1777 PMURES_BIT(RES43602_PERST_OVR) | PMURES_BIT(RES43602_SR_CLK_STABLE) |
1778 PMURES_BIT(RES43602_SR_SAVE_RESTORE) | PMURES_BIT(RES43602_SR_SLEEP) |
1779 PMURES_BIT(RES43602_LQ_START) | PMURES_BIT(RES43602_LQ_AVAIL) |
1780 PMURES_BIT(RES43602_WL_CORE_RDY) |
1781 PMURES_BIT(RES43602_ALP_AVAIL);
1782
1783 if (sih->chippkg == BCM43602_12x12_PKG_ID) /* LPLDO WAR */
1784 min_mask &= ~PMURES_BIT(RES43602_LPLDO_PU);
1785
1786 max_mask = (1<<3) | min_mask | PMURES_BIT(RES43602_RADIO_PU) |
1787 PMURES_BIT(RES43602_RFLDO_PU) | PMURES_BIT(RES43602_HT_START) |
1788 PMURES_BIT(RES43602_HT_AVAIL) | PMURES_BIT(RES43602_MACPHY_CLKAVAIL);
1789
1790 #if defined(SAVERESTORE)
1791 /* min_mask is updated after SR code is downloaded to txfifo */
1792 if (SR_ENAB() && sr_isenab(sih)) {
1793 ASSERT(sih->chippkg != BCM43602_12x12_PKG_ID);
1794 min_mask = PMURES_BIT(RES43602_LPLDO_PU);
1795 }
1796 #endif /* SAVERESTORE */
1797 break;
1798
1799 case BCM43012_CHIP_ID:
1800 case BCM43013_CHIP_ID:
1801 case BCM43014_CHIP_ID:
1802 /* Set the bits for all resources in the max mask except for the SR Engine */
1803 max_mask = 0x7FFFFFFF;
1804 break;
1805 case BCM4369_CHIP_GRPID:
1806 min_mask = 0x64fffff;
1807 #if defined(SAVERESTORE)
1808 if (SR_ENAB() && sr_isenab(sih)) {
1809 if (si_get_nvram_rfldo3p3_war(sih)) {
1810 min_mask = 0x0000011;
1811 } else {
1812 min_mask = 0x0000001;
1813 }
1814 }
1815 #endif /* SAVERESTORE */
1816 max_mask = 0x7FFFFFFF;
1817 break;
1818 case BCM4376_CHIP_GRPID:
1819 case BCM4378_CHIP_GRPID:
1820 min_mask = 0x064fffff;
1821 #if defined(SAVERESTORE)
1822 if (SR_ENAB()) {
1823 if (!sr_isenab(sih)) {
1824 min_mask = 0x064fffff;
1825 } else {
1826 min_mask = PMURES_BIT(RES4378_DUMMY);
1827 }
1828 }
1829 #endif /* SAVERESTORE */
1830 max_mask = 0x7FFFFFFF;
1831 break;
1832 case BCM4385_CHIP_GRPID:
1833 case BCM4387_CHIP_GRPID:
1834 min_mask = 0x64fffff;
1835 #if defined(SAVERESTORE)
1836 if (SR_ENAB()) {
1837 if (sr_isenab(sih)) {
1838 min_mask = PMURES_BIT(RES4387_DUMMY);
1839 } else {
1840 min_mask = pmu_corereg(sih, SI_CC_IDX, min_res_mask, 0, 0);
1841 if (PMU_FLL_PU_ENAB()) {
1842 min_mask |= PMURES_BIT(RES4387_FAST_LPO_AVAIL) |
1843 PMURES_BIT(RES4387_PMU_LP);
1844 }
1845 }
1846 }
1847 #endif /* SAVERESTORE */
1848
1849 max_mask = 0x7FFFFFFF;
1850 break;
1851
1852 case BCM4388_CHIP_GRPID:
1853 min_mask = 0x64fffff;
1854 #if defined(SAVERESTORE)
1855 if (SR_ENAB()) {
1856 if (sr_isenab(sih)) {
1857 min_mask = PMURES_BIT(RES4388_DUMMY);
1858 } else {
1859 min_mask = pmu_corereg(sih, SI_CC_IDX, min_res_mask, 0, 0);
1860 if (PMU_FLL_PU_ENAB()) {
1861 min_mask |= PMURES_BIT(RES4388_FAST_LPO_AVAIL) |
1862 PMURES_BIT(RES4388_PMU_LP);
1863 }
1864 }
1865 }
1866 #endif /* SAVERESTORE */
1867 max_mask = 0x7FFFFFFF;
1868 break;
1869
1870 case BCM4389_CHIP_GRPID:
1871 /*
1872 * check later if this can be replaced with chip default value read from
1873 * PMU register - min_res_mask and remove the code in SR_ENAB() portion
1874 */
1875 min_mask = 0x64fffff;
1876 #if defined(SAVERESTORE)
1877 if (SR_ENAB()) {
1878 if (sr_isenab(sih)) {
1879 min_mask = PMURES_BIT(RES4389_DUMMY);
1880 } else {
1881 min_mask = pmu_corereg(sih, SI_CC_IDX, min_res_mask, 0, 0);
1882 if (PMU_FLL_PU_ENAB()) {
1883 min_mask |= PMURES_BIT(RES4389_FAST_LPO_AVAIL) |
1884 PMURES_BIT(RES4389_PMU_LP);
1885 }
1886 }
1887 }
1888 #endif /* SAVERESTORE */
1889 max_mask = 0x7FFFFFFF;
1890 break;
1891
1892 case BCM4397_CHIP_GRPID:
1893 min_mask = 0x64fffff;
1894 max_mask = 0x7FFFFFFF;
1895 break;
1896
1897 case BCM4362_CHIP_GRPID:
1898 min_mask = 0x64fffff;
1899 #if defined(SAVERESTORE)
1900 if (SR_ENAB() && sr_isenab(sih)) {
1901 min_mask = (PMURES_BIT(RES4362_DUMMY));
1902 }
1903 #endif /* SAVERESTORE */
1904 max_mask = 0x7FFFFFFF;
1905 break;
1906
1907 default:
1908 PMU_ERROR(("MIN and MAX mask is not programmed\n"));
1909 break;
1910 }
1911
1912 if (!FWSIGN_ENAB()) {
1913 /* nvram override */
1914 si_nvram_res_masks(sih, &min_mask, &max_mask);
1915 }
1916
1917 *pmin = min_mask;
1918 *pmax = max_mask;
1919 } /* si_pmu_res_masks */
1920
1921 /**
1922 * resource dependencies can change because of the host interface
1923 * selected, to work around an issue, or for more optimal power
1924 * savings after tape out
1925 */
1926 #ifdef DUAL_PMU_SEQUENCE
1927 static void
si_pmu_resdeptbl_upd(si_t * sih,osl_t * osh,pmuregs_t * pmu,const pmu_res_depend_t * restable,uint tablesz)1928 si_pmu_resdeptbl_upd(si_t *sih, osl_t *osh, pmuregs_t *pmu,
1929 const pmu_res_depend_t *restable, uint tablesz)
1930 #else
1931 static void
1932 BCMATTACHFN(si_pmu_resdeptbl_upd)(si_t *sih, osl_t *osh, pmuregs_t *pmu,
1933 const pmu_res_depend_t *restable, uint tablesz)
1934 #endif /* DUAL_PMU_SEQUENCE */
1935 {
1936 uint i, rsrcs;
1937
1938 if (tablesz == 0)
1939 return;
1940
1941 ASSERT(restable != NULL);
1942
1943 rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
1944 /* Program resource dependencies table */
1945 while (tablesz--) {
1946 if (restable[tablesz].filter != NULL &&
1947 !(restable[tablesz].filter)(sih))
1948 continue;
1949 for (i = 0; i < rsrcs; i ++) {
1950 if ((restable[tablesz].res_mask &
1951 PMURES_BIT(i)) == 0)
1952 continue;
1953 W_REG(osh, &pmu->res_table_sel, i);
1954 switch (restable[tablesz].action) {
1955 case RES_DEPEND_SET:
1956 PMU_MSG(("Changing rsrc %d res_dep_mask to 0x%x\n", i,
1957 restable[tablesz].depend_mask));
1958 W_REG(osh, &pmu->res_dep_mask,
1959 restable[tablesz].depend_mask);
1960 break;
1961 case RES_DEPEND_ADD:
1962 PMU_MSG(("Adding 0x%x to rsrc %d res_dep_mask\n",
1963 restable[tablesz].depend_mask, i));
1964 OR_REG(osh, &pmu->res_dep_mask,
1965 restable[tablesz].depend_mask);
1966 break;
1967 case RES_DEPEND_REMOVE:
1968 PMU_MSG(("Removing 0x%x from rsrc %d res_dep_mask\n",
1969 restable[tablesz].depend_mask, i));
1970 AND_REG(osh, &pmu->res_dep_mask,
1971 ~restable[tablesz].depend_mask);
1972 break;
1973 default:
1974 ASSERT(0);
1975 break;
1976 }
1977 }
1978 }
1979 } /* si_pmu_resdeptbl_upd */
1980
1981 static void
BCMATTACHFN(si_pmu_dep_table_fll_pu_fixup)1982 BCMATTACHFN(si_pmu_dep_table_fll_pu_fixup)(si_t *sih, osl_t *osh,
1983 pmu_res_depend_t *pmu_res_depend_table, uint pmu_res_depend_table_sz)
1984 {
1985 uint i;
1986
1987 if (!PMU_FLL_PU_ENAB()) {
1988 return;
1989 }
1990
1991 switch (CHIPID(sih->chip)) {
1992 case BCM4387_CHIP_GRPID:
1993 for (i = 0; i < pmu_res_depend_table_sz; i ++) {
1994 if (pmu_res_depend_table[i].res_mask ==
1995 PMURES_BIT(RES4387_FAST_LPO_AVAIL)) {
1996 pmu_res_depend_table[i].depend_mask = PMURES_BIT(RES4387_DUMMY) |
1997 PMURES_BIT(RES4387_PMU_LP);
1998 } else if ((pmu_res_depend_table[i].res_mask !=
1999 PMURES_BIT(RES4387_DUMMY)) &&
2000 (pmu_res_depend_table[i].res_mask !=
2001 PMURES_BIT(RES4387_PMU_LP)) &&
2002 (pmu_res_depend_table[i].res_mask !=
2003 PMURES_BIT(RES4387_RESERVED_16))) {
2004 pmu_res_depend_table[i].depend_mask |=
2005 PMURES_BIT(RES4387_FAST_LPO_AVAIL);
2006 }
2007 }
2008 break;
2009 case BCM4388_CHIP_GRPID:
2010 for (i = 0; i < pmu_res_depend_table_sz; i ++) {
2011 if (pmu_res_depend_table[i].res_mask ==
2012 PMURES_BIT(RES4388_FAST_LPO_AVAIL)) {
2013 pmu_res_depend_table[i].depend_mask = PMURES_BIT(RES4388_DUMMY) |
2014 PMURES_BIT(RES4388_PMU_LP);
2015 } else if ((pmu_res_depend_table[i].res_mask !=
2016 PMURES_BIT(RES4388_DUMMY)) &&
2017 (pmu_res_depend_table[i].res_mask !=
2018 PMURES_BIT(RES4388_PMU_LP)) &&
2019 (pmu_res_depend_table[i].res_mask !=
2020 PMURES_BIT(RES4388_RESERVED_15)) &&
2021 (pmu_res_depend_table[i].res_mask !=
2022 PMURES_BIT(RES4388_RESERVED_16))) {
2023 pmu_res_depend_table[i].depend_mask |=
2024 PMURES_BIT(RES4388_FAST_LPO_AVAIL);
2025 }
2026 }
2027 break;
2028 case BCM4389_CHIP_GRPID:
2029 for (i = 0; i < pmu_res_depend_table_sz; i ++) {
2030 if (pmu_res_depend_table[i].res_mask ==
2031 PMURES_BIT(RES4389_FAST_LPO_AVAIL)) {
2032 pmu_res_depend_table[i].depend_mask = PMURES_BIT(RES4389_DUMMY) |
2033 PMURES_BIT(RES4389_PMU_LP);
2034 } else if ((pmu_res_depend_table[i].res_mask !=
2035 PMURES_BIT(RES4389_DUMMY)) &&
2036 (pmu_res_depend_table[i].res_mask !=
2037 PMURES_BIT(RES4389_PMU_LP)) &&
2038 (pmu_res_depend_table[i].res_mask !=
2039 PMURES_BIT(RES4389_RESERVED_16))) {
2040 pmu_res_depend_table[i].depend_mask |=
2041 PMURES_BIT(RES4389_FAST_LPO_AVAIL);
2042 }
2043 }
2044 break;
2045 default:
2046 PMU_MSG(("si_pmu_dep_table_fll_pu_fixup: unsupported chip!\n"));
2047 ASSERT(0);
2048 break;
2049 }
2050 }
2051
2052 /** Initialize PMU hardware resources. */
2053 void
BCMATTACHFN(si_pmu_res_init)2054 BCMATTACHFN(si_pmu_res_init)(si_t *sih, osl_t *osh)
2055 {
2056 pmuregs_t *pmu;
2057 uint origidx;
2058 const pmu_res_updown_t *pmu_res_updown_table = NULL;
2059 uint pmu_res_updown_table_sz = 0;
2060 const pmu_res_subst_trans_tmr_t *pmu_res_subst_trans_tmr_table = NULL;
2061 uint pmu_res_subst_trans_tmr_table_sz = 0;
2062 pmu_res_depend_t *pmu_res_depend_table = NULL;
2063 uint pmu_res_depend_table_sz = 0;
2064 #ifndef BCM_BOOTLOADER
2065 const pmu_res_depend_t *pmu_res_depend_pciewar_table[2] = {NULL, NULL};
2066 uint pmu_res_depend_pciewar_table_sz[2] = {0, 0};
2067 #endif /* BCM_BOOTLOADER */
2068 uint32 min_mask = 0, max_mask = 0;
2069 char name[8];
2070 const char *val;
2071 uint i, rsrcs;
2072 uint8 fastlpo_dis = fastlpo_dis_get();
2073 uint8 fastlpo_pcie_dis = fastlpo_pcie_dis_get();
2074
2075 ASSERT(sih->cccaps & CC_CAP_PMU);
2076
2077 /* Remember original core before switch to chipc/pmu */
2078 origidx = si_coreidx(sih);
2079 if (AOB_ENAB(sih)) {
2080 pmu = si_setcore(sih, PMU_CORE_ID, 0);
2081 } else {
2082 pmu = si_setcoreidx(sih, SI_CC_IDX);
2083 }
2084 ASSERT(pmu != NULL);
2085
2086 /*
2087 * Hardware contains the resource updown and dependency tables. Only if a chip has a
2088 * hardware problem, software tables can be used to override hardware tables.
2089 */
2090 switch (CHIPID(sih->chip)) {
2091 case BCM4360_CHIP_ID:
2092 case BCM4352_CHIP_ID:
2093 if (CHIPREV(sih->chiprev) < 4) {
2094 pmu_res_updown_table = bcm4360_res_updown;
2095 pmu_res_updown_table_sz = ARRAYSIZE(bcm4360_res_updown);
2096 } else {
2097 /* FOR 4360B1 */
2098 pmu_res_updown_table = bcm4360B1_res_updown;
2099 pmu_res_updown_table_sz = ARRAYSIZE(bcm4360B1_res_updown);
2100 }
2101 break;
2102 CASE_BCM43602_CHIP:
2103 pmu_res_updown_table = bcm43602_res_updown;
2104 pmu_res_updown_table_sz = ARRAYSIZE(bcm43602_res_updown);
2105 pmu_res_depend_table = bcm43602_res_depend;
2106 pmu_res_depend_table_sz = ARRAYSIZE(bcm43602_res_depend);
2107 #ifndef BCM_BOOTLOADER
2108 pmu_res_depend_pciewar_table[0] = bcm43602_res_pciewar;
2109 pmu_res_depend_pciewar_table_sz[0] = ARRAYSIZE(bcm43602_res_pciewar);
2110 if (sih->chippkg == BCM43602_12x12_PKG_ID) { /* LPLDO WAR */
2111 pmu_res_depend_pciewar_table[1] = bcm43602_12x12_res_depend;
2112 pmu_res_depend_pciewar_table_sz[1] = ARRAYSIZE(bcm43602_12x12_res_depend);
2113 }
2114 #endif /* !BCM_BOOTLOADER */
2115 break;
2116 case BCM43012_CHIP_ID:
2117 case BCM43013_CHIP_ID:
2118 case BCM43014_CHIP_ID:
2119 pmu_res_updown_table = bcm43012a0_res_updown_ds0;
2120 pmu_res_updown_table_sz = ARRAYSIZE(bcm43012a0_res_updown_ds0);
2121 pmu_res_depend_table = bcm43012a0_res_depend_ds0;
2122 pmu_res_depend_table_sz = ARRAYSIZE(bcm43012a0_res_depend_ds0);
2123 break;
2124 case BCM4369_CHIP_GRPID:
2125 /* fastlpo_dis is override for PMU1M, updown times are updated accordingly
2126 * if PMU 1M is enabled only Resource Up/Down times are changed
2127 * Also the Up/Down times are different for A0 and B0
2128 */
2129 if (fastlpo_dis) {
2130 /* Only Resource Up/Down times are different b/w A0 and B0 */
2131 if (CHIPREV(sih->chiprev) == 0) {
2132 pmu_res_updown_table = bcm4369a0_res_updown;
2133 pmu_res_updown_table_sz = ARRAYSIZE(bcm4369a0_res_updown);
2134 } else {
2135 pmu_res_updown_table = bcm4369b0_res_updown;
2136 pmu_res_updown_table_sz = ARRAYSIZE(bcm4369b0_res_updown);
2137 }
2138 } else {
2139 if (fastlpo_pcie_dis) {
2140 PMU_ERROR(("INVALID: PCIE 1MHz disabled but PMU 1MHz enabled\n"));
2141 ASSERT(0);
2142 }
2143 /* Only Resource Up/Down times are different b/w A0 and B0 */
2144 if (CHIPREV(sih->chiprev) == 0) {
2145 pmu_res_updown_table = bcm4369a0_res_updown_fastlpo_pmu;
2146 pmu_res_updown_table_sz =
2147 ARRAYSIZE(bcm4369a0_res_updown_fastlpo_pmu);
2148 } else {
2149 pmu_res_updown_table = bcm4369b0_res_updown_fastlpo_pmu;
2150 pmu_res_updown_table_sz =
2151 ARRAYSIZE(bcm4369b0_res_updown_fastlpo_pmu);
2152 }
2153 }
2154
2155 /* fastlpo_pcie_dis is override for PCIE1M, resource dependencies are updated
2156 * if pcie 1M is enabled resource dependency are different
2157 * for A0 and B0 chiprev there is no resource dependency change
2158 */
2159 if (fastlpo_pcie_dis) {
2160 pmu_res_depend_table = bcm4369a0_res_depend;
2161 pmu_res_depend_table_sz = ARRAYSIZE(bcm4369a0_res_depend);
2162 } else {
2163 pmu_res_depend_table = bcm4369a0_res_depend_fastlpo_pcie;
2164 pmu_res_depend_table_sz = ARRAYSIZE(bcm4369a0_res_depend_fastlpo_pcie);
2165 }
2166 break;
2167
2168 case BCM4362_CHIP_GRPID:
2169 pmu_res_updown_table = bcm4362_res_updown;
2170 pmu_res_updown_table_sz = ARRAYSIZE(bcm4362_res_updown);
2171
2172 GCI_REG_NEW(sih, bt_smem_control1, (0xFF<<16), 0);
2173
2174 si_pmu_chipcontrol(sih, PMU_CHIPCTL14,
2175 (PMU_CC14_MAIN_VDDB2VDDRET_UP_DLY_MASK |
2176 PMU_CC14_MAIN_VDDB2VDD_UP_DLY_MASK |
2177 PMU_CC14_AUX_VDDB2VDDRET_UP_DLY_MASK |
2178 PMU_CC14_AUX_VDDB2VDD_UP_DLY_MASK |
2179 PMU_CC14_PCIE_VDDB2VDDRET_UP_DLY_MASK |
2180 PMU_CC14_PCIE_VDDB2VDD_UP_DLY_MASK), 0);
2181
2182 si_pmu_chipcontrol(sih, PMU_CHIPCTL15,
2183 (PMU_CC15_PCIE_VDDB_CURRENT_LIMIT_DELAY_MASK |
2184 PMU_CC15_PCIE_VDDB_FORCE_RPS_PWROK_DELAY_MASK), 0);
2185
2186 si_pmu_chipcontrol(sih, PMU_CHIPCTL10,
2187 (PMU_CC10_PCIE_RESET0_CNT_SLOW_MASK |
2188 PMU_CC10_PCIE_RESET1_CNT_SLOW_MASK), 0);
2189
2190 GCI_REG_NEW(sih, bt_smem_control0, (0xF<<16), 0);
2191 GCI_REG_NEW(sih, bt_smem_control0, (0xF<<24), 0);
2192
2193 pmu_res_depend_table = bcm4362_res_depend;
2194 pmu_res_depend_table_sz = ARRAYSIZE(bcm4362_res_depend);
2195 break;
2196
2197 case BCM4376_CHIP_GRPID:
2198 case BCM4378_CHIP_GRPID:
2199 if (SR_ENAB()) {
2200 pmu_res_updown_table = bcm4378b0_res_updown;
2201 pmu_res_updown_table_sz = ARRAYSIZE(bcm4378b0_res_updown);
2202 pmu_res_depend_table = bcm4378b0_res_depend;
2203 pmu_res_depend_table_sz = ARRAYSIZE(bcm4378b0_res_depend);
2204 }
2205 break;
2206
2207 case BCM4385_CHIP_GRPID:
2208 case BCM4387_CHIP_GRPID:
2209 if (SR_ENAB()) {
2210 if (ISSIM_ENAB(sih)) {
2211 if (PMUREV(sih->pmurev) == 39) {
2212 pmu_res_updown_table = bcm4387c0_res_updown;
2213 pmu_res_updown_table_sz =
2214 ARRAYSIZE(bcm4387c0_res_updown);
2215
2216 pmu_res_subst_trans_tmr_table =
2217 bcm4387c0_res_subst_trans_tmr;
2218 pmu_res_subst_trans_tmr_table_sz =
2219 ARRAYSIZE(bcm4387c0_res_subst_trans_tmr);
2220
2221 pmu_res_depend_table = bcm4387c0_res_depend;
2222 pmu_res_depend_table_sz = ARRAYSIZE(bcm4387c0_res_depend);
2223 } else {
2224 pmu_res_updown_table = bcm4387b0_res_updown_qt;
2225 pmu_res_updown_table_sz =
2226 ARRAYSIZE(bcm4387b0_res_updown_qt);
2227
2228 pmu_res_subst_trans_tmr_table =
2229 bcm4387b0_res_subst_trans_tmr_qt;
2230 pmu_res_subst_trans_tmr_table_sz =
2231 ARRAYSIZE(bcm4387b0_res_subst_trans_tmr_qt);
2232
2233 pmu_res_depend_table = bcm4387b0_res_depend;
2234 pmu_res_depend_table_sz = ARRAYSIZE(bcm4387b0_res_depend);
2235 }
2236 } else {
2237 if (PMUREV(sih->pmurev) == 39) {
2238 if (BCMSRTOPOFF_ENAB()) {
2239 pmu_res_updown_table = bcm4387c0_res_updown_topoff;
2240 pmu_res_updown_table_sz =
2241 ARRAYSIZE(bcm4387c0_res_updown_topoff);
2242 } else {
2243 pmu_res_updown_table = bcm4387c0_res_updown;
2244 pmu_res_updown_table_sz =
2245 ARRAYSIZE(bcm4387c0_res_updown);
2246 }
2247
2248 pmu_res_subst_trans_tmr_table =
2249 bcm4387c0_res_subst_trans_tmr;
2250 pmu_res_subst_trans_tmr_table_sz =
2251 ARRAYSIZE(bcm4387c0_res_subst_trans_tmr);
2252
2253 pmu_res_depend_table = bcm4387c0_res_depend;
2254 pmu_res_depend_table_sz = ARRAYSIZE(bcm4387c0_res_depend);
2255
2256 if (PMU_FLL_PU_ENAB()) {
2257 si_pmu_dep_table_fll_pu_fixup(sih, osh,
2258 pmu_res_depend_table,
2259 pmu_res_depend_table_sz);
2260 }
2261 } else {
2262 pmu_res_updown_table = bcm4387b0_res_updown;
2263 pmu_res_updown_table_sz = ARRAYSIZE(bcm4387b0_res_updown);
2264
2265 pmu_res_subst_trans_tmr_table =
2266 bcm4387b0_res_subst_trans_tmr;
2267 pmu_res_subst_trans_tmr_table_sz =
2268 ARRAYSIZE(bcm4387b0_res_subst_trans_tmr);
2269
2270 pmu_res_depend_table = bcm4387b0_res_depend;
2271 pmu_res_depend_table_sz = ARRAYSIZE(bcm4387b0_res_depend);
2272 }
2273 }
2274 }
2275 break;
2276
2277 case BCM4388_CHIP_GRPID:
2278 if (SR_ENAB()) {
2279 if (ISSIM_ENAB(sih)) {
2280 pmu_res_updown_table = bcm4388a0_res_updown_qt;
2281 pmu_res_updown_table_sz = ARRAYSIZE(bcm4388a0_res_updown_qt);
2282
2283 pmu_res_subst_trans_tmr_table = bcm4388a0_res_subst_trans_tmr_qt;
2284 pmu_res_subst_trans_tmr_table_sz =
2285 ARRAYSIZE(bcm4388a0_res_subst_trans_tmr_qt);
2286 } else {
2287 pmu_res_updown_table = bcm4388a0_res_updown;
2288 pmu_res_updown_table_sz = ARRAYSIZE(bcm4388a0_res_updown);
2289
2290 pmu_res_subst_trans_tmr_table = bcm4388a0_res_subst_trans_tmr;
2291 pmu_res_subst_trans_tmr_table_sz =
2292 ARRAYSIZE(bcm4388a0_res_subst_trans_tmr);
2293 }
2294
2295 pmu_res_depend_table = bcm4388a0_res_depend;
2296 pmu_res_depend_table_sz = ARRAYSIZE(bcm4388a0_res_depend);
2297
2298 if (PMU_FLL_PU_ENAB()) {
2299 si_pmu_dep_table_fll_pu_fixup(sih, osh,
2300 pmu_res_depend_table,
2301 pmu_res_depend_table_sz);
2302 }
2303 }
2304 break;
2305
2306 case BCM4389_CHIP_GRPID:
2307 if (SR_ENAB()) {
2308 if (ISSIM_ENAB(sih)) {
2309 pmu_res_updown_table = bcm4389b0_res_updown_qt;
2310 pmu_res_updown_table_sz = ARRAYSIZE(bcm4389b0_res_updown_qt);
2311
2312 pmu_res_subst_trans_tmr_table = bcm4389b0_res_subst_trans_tmr_qt;
2313 pmu_res_subst_trans_tmr_table_sz =
2314 ARRAYSIZE(bcm4389b0_res_subst_trans_tmr_qt);
2315 } else {
2316 pmu_res_updown_table = bcm4389b0_res_updown;
2317 pmu_res_updown_table_sz = ARRAYSIZE(bcm4389b0_res_updown);
2318
2319 pmu_res_subst_trans_tmr_table = bcm4389b0_res_subst_trans_tmr;
2320 pmu_res_subst_trans_tmr_table_sz =
2321 ARRAYSIZE(bcm4389b0_res_subst_trans_tmr);
2322 }
2323
2324 pmu_res_depend_table = bcm4389b0_res_depend;
2325 pmu_res_depend_table_sz = ARRAYSIZE(bcm4389b0_res_depend);
2326 if (PMU_FLL_PU_ENAB()) {
2327 si_pmu_dep_table_fll_pu_fixup(sih, osh,
2328 pmu_res_depend_table, pmu_res_depend_table_sz);
2329 }
2330 }
2331 break;
2332
2333 default:
2334 break;
2335 }
2336
2337 /* Program up/down timers */
2338 while (pmu_res_updown_table_sz--) {
2339 ASSERT(pmu_res_updown_table != NULL);
2340 PMU_MSG(("Changing rsrc %d res_updn_timer to 0x%x\n",
2341 pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
2342 pmu_res_updown_table[pmu_res_updown_table_sz].updown));
2343 W_REG(osh, &pmu->res_table_sel,
2344 pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
2345 W_REG(osh, &pmu->res_updn_timer,
2346 pmu_res_updown_table[pmu_res_updown_table_sz].updown);
2347 }
2348
2349 if (!FWSIGN_ENAB()) {
2350 /* # resources */
2351 rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
2352
2353 /* Apply nvram overrides to up/down timers */
2354 for (i = 0; i < rsrcs; i ++) {
2355 uint32 r_val;
2356 snprintf(name, sizeof(name), rstr_rDt, i);
2357 if ((val = getvar(NULL, name)) == NULL)
2358 continue;
2359 r_val = (uint32)bcm_strtoul(val, NULL, 0);
2360 /* PMUrev = 13, pmu resource updown times are 12 bits(0:11 DT, 16:27 UT) */
2361 /* OLD values are 8 bits for UT/DT, handle the old nvram format */
2362 if (PMUREV(sih->pmurev) >= 13) {
2363 if (r_val < (1 << 16)) {
2364 uint16 up_time = (r_val >> 8) & 0xFF;
2365 r_val &= 0xFF;
2366 r_val |= (up_time << 16);
2367 }
2368 }
2369 PMU_MSG(("Applying %s=%s to rsrc %d res_updn_timer\n", name, val, i));
2370 W_REG(osh, &pmu->res_table_sel, (uint32)i);
2371 W_REG(osh, &pmu->res_updn_timer, r_val);
2372 }
2373 }
2374
2375 /* Program Rsrc Substate Transition Timer */
2376 while (pmu_res_subst_trans_tmr_table_sz --) {
2377 ASSERT(pmu_res_subst_trans_tmr_table != NULL);
2378 PMU_MSG(("Changing rsrc %d substate %d res_subst_trans_timer to 0x%x\n",
2379 pmu_res_subst_trans_tmr_table[pmu_res_subst_trans_tmr_table_sz].resnum,
2380 pmu_res_subst_trans_tmr_table[pmu_res_subst_trans_tmr_table_sz].substate,
2381 pmu_res_subst_trans_tmr_table[pmu_res_subst_trans_tmr_table_sz].tmr));
2382 W_REG(osh, &pmu->res_table_sel,
2383 pmu_res_subst_trans_tmr_table[pmu_res_subst_trans_tmr_table_sz].resnum |
2384 (pmu_res_subst_trans_tmr_table[pmu_res_subst_trans_tmr_table_sz].substate
2385 << PMU_RES_SUBSTATE_SHIFT));
2386 W_REG(osh, &pmu->rsrc_substate_trans_tmr,
2387 pmu_res_subst_trans_tmr_table[pmu_res_subst_trans_tmr_table_sz].tmr);
2388 }
2389
2390 /* Program resource dependencies table */
2391 si_pmu_resdeptbl_upd(sih, osh, pmu, pmu_res_depend_table, pmu_res_depend_table_sz);
2392
2393 if (!FWSIGN_ENAB()) {
2394 /* Apply nvram overrides to dependencies masks */
2395 for (i = 0; i < rsrcs; i ++) {
2396 snprintf(name, sizeof(name), rstr_rDd, i);
2397 if ((val = getvar(NULL, name)) == NULL)
2398 continue;
2399 PMU_MSG(("Applying %s=%s to rsrc %d res_dep_mask\n", name, val, i));
2400 W_REG(osh, &pmu->res_table_sel, (uint32)i);
2401 W_REG(osh, &pmu->res_dep_mask, (uint32)bcm_strtoul(val, NULL, 0));
2402 }
2403 }
2404
2405 #if !defined(BCM_BOOTLOADER)
2406 /* Initial any chip interface dependent PMU rsrc by looking at the
2407 * chipstatus register to figure the selected interface
2408 */
2409 /* this should be a general change to cover all the chips.
2410 * this also should validate the build where the dongle is
2411 * built for SDIO but downloaded on PCIE dev
2412 */
2413 if (BUSTYPE(sih->bustype) == PCI_BUS || BUSTYPE(sih->bustype) == SI_BUS) {
2414 bool is_pciedev = BCM43602_CHIP(sih->chip);
2415
2416 for (i = 0; i < ARRAYSIZE(pmu_res_depend_pciewar_table); i++) {
2417 if (is_pciedev && pmu_res_depend_pciewar_table[i] &&
2418 pmu_res_depend_pciewar_table_sz[i]) {
2419 si_pmu_resdeptbl_upd(sih, osh, pmu,
2420 pmu_res_depend_pciewar_table[i],
2421 pmu_res_depend_pciewar_table_sz[i]);
2422 }
2423 }
2424 }
2425 #endif /* !BCM_BOOTLOADER */
2426 /* Determine min/max rsrc masks */
2427 si_pmu_res_masks(sih, &min_mask, &max_mask);
2428 /* Add min mask dependencies */
2429 min_mask |= si_pmu_res_deps(sih, osh, pmu, min_mask, FALSE);
2430
2431 #ifdef BCM_BOOTLOADER
2432 /* Apply nvram override to max mask */
2433 if ((val = getvar(NULL, "brmax")) != NULL) {
2434 PMU_MSG(("Applying brmax=%s to max_res_mask\n", val));
2435 max_mask = (uint32)bcm_strtoul(val, NULL, 0);
2436 }
2437
2438 /* Apply nvram override to min mask */
2439 if ((val = getvar(NULL, "brmin")) != NULL) {
2440 PMU_MSG(("Applying brmin=%s to min_res_mask\n", val));
2441 min_mask = (uint32)bcm_strtoul(val, NULL, 0);
2442 }
2443 #endif /* BCM_BOOTLOADER */
2444
2445 /* apply new PLL setting if is ALP strap (need to close out
2446 * if possible apply if is HT strap)
2447 */
2448 if (((CHIPID(sih->chip) == BCM4360_CHIP_ID) || (CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
2449 (CHIPREV(sih->chiprev) < 4) &&
2450 ((CST4360_RSRC_INIT_MODE(sih->chipst) & 1) == 0)) {
2451 /* BBPLL */
2452 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, ~0, 0x09048562);
2453 /* AVB PLL */
2454 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG14, ~0, 0x09048562);
2455 si_pmu_pllupd(sih);
2456 } else if (((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
2457 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
2458 (CHIPREV(sih->chiprev) >= 4) &&
2459 ((CST4360_RSRC_INIT_MODE(sih->chipst) & 1) == 0)) {
2460 /* Changes for 4360B1 */
2461
2462 /* Enable REFCLK bit 11 */
2463 si_pmu_chipcontrol(sih, PMU_CHIPCTL1, 0x800, 0x800);
2464
2465 /* BBPLL */
2466 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, ~0, 0x080004e2);
2467 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG7, ~0, 0xE);
2468 /* AVB PLL */
2469 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG14, ~0, 0x080004e2);
2470 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG15, ~0, 0xE);
2471 si_pmu_pllupd(sih);
2472 }
2473 /* disable PLL open loop operation */
2474 si_pll_closeloop(sih);
2475
2476 if (max_mask) {
2477 /* Ensure there is no bit set in min_mask which is not set in max_mask */
2478 max_mask |= min_mask;
2479
2480 /* First set the bits which change from 0 to 1 in max, then update the
2481 * min_mask register and then reset the bits which change from 1 to 0
2482 * in max. This is required as the bit in MAX should never go to 0 when
2483 * the corresponding bit in min is still 1. Similarly the bit in min cannot
2484 * be 1 when the corresponding bit in max is still 0.
2485 */
2486 OR_REG(osh, &pmu->max_res_mask, max_mask);
2487 } else {
2488 /* First set the bits which change from 0 to 1 in max, then update the
2489 * min_mask register and then reset the bits which change from 1 to 0
2490 * in max. This is required as the bit in MAX should never go to 0 when
2491 * the corresponding bit in min is still 1. Similarly the bit in min cannot
2492 * be 1 when the corresponding bit in max is still 0.
2493 */
2494 if (min_mask)
2495 OR_REG(osh, &pmu->max_res_mask, min_mask);
2496 }
2497
2498 /* Program min resource mask */
2499 if (min_mask) {
2500 PMU_MSG(("Changing min_res_mask to 0x%x\n", min_mask));
2501 W_REG(osh, &pmu->min_res_mask, min_mask);
2502 }
2503
2504 /* Program max resource mask */
2505 if (max_mask) {
2506 PMU_MSG(("Changing max_res_mask to 0x%x\n", max_mask));
2507 W_REG(osh, &pmu->max_res_mask, max_mask);
2508 }
2509 #if defined(SAVERESTORE) && defined(LDO3P3_MIN_RES_MASK)
2510 if (SR_ENAB()) {
2511 /* Set the default state for LDO3P3 protection */
2512 if (getintvar(NULL, rstr_ldo_prot) == 1) {
2513 si_pmu_min_res_ldo3p3_set(sih, osh, TRUE);
2514 }
2515 }
2516 #endif /* SAVERESTORE && LDO3P3_MIN_RES_MASK */
2517
2518 /* request htavail thru pcie core */
2519 if (((CHIPID(sih->chip) == BCM4360_CHIP_ID) || (CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
2520 (BUSTYPE(sih->bustype) == PCI_BUS) &&
2521 (CHIPREV(sih->chiprev) < 4)) {
2522 uint32 pcie_clk_ctl_st;
2523
2524 pcie_clk_ctl_st = si_corereg(sih, 3, 0x1e0, 0, 0);
2525 si_corereg(sih, 3, 0x1e0, ~0, (pcie_clk_ctl_st | CCS_HTAREQ));
2526 }
2527
2528 si_pmu_wait_for_steady_state(sih, osh, pmu);
2529 /* Add some delay; allow resources to come up and settle. */
2530 OSL_DELAY(2000);
2531
2532 /* Return to original core */
2533 si_setcoreidx(sih, origidx);
2534 } /* si_pmu_res_init */
2535
2536 /* setup pll and query clock speed */
2537 typedef struct {
2538 uint16 fref; /* x-tal frequency in [hz] */
2539 uint8 xf; /* x-tal index as contained in PMU control reg, see PMU programmers guide */
2540 uint8 p1div;
2541 uint8 p2div;
2542 uint8 ndiv_int;
2543 uint32 ndiv_frac;
2544 } pmu1_xtaltab0_t;
2545
2546 /* 'xf' values corresponding to the 'xf' definition in the PMU control register */
2547 /* unclear why this enum contains '_640_' since the PMU prog guide says nothing about that */
2548 enum xtaltab0_640 {
2549 XTALTAB0_640_12000K = 1,
2550 XTALTAB0_640_13000K,
2551 XTALTAB0_640_14400K,
2552 XTALTAB0_640_15360K,
2553 XTALTAB0_640_16200K,
2554 XTALTAB0_640_16800K,
2555 XTALTAB0_640_19200K,
2556 XTALTAB0_640_19800K,
2557 XTALTAB0_640_20000K,
2558 XTALTAB0_640_24000K, /* warning: unknown in PMU programmers guide. seems incorrect. */
2559 XTALTAB0_640_25000K,
2560 XTALTAB0_640_26000K,
2561 XTALTAB0_640_30000K,
2562 XTALTAB0_640_33600K, /* warning: unknown in PMU programmers guide. seems incorrect. */
2563 XTALTAB0_640_37400K,
2564 XTALTAB0_640_38400K, /* warning: unknown in PMU programmers guide. seems incorrect. */
2565 XTALTAB0_640_40000K,
2566 XTALTAB0_640_48000K, /* warning: unknown in PMU programmers guide. seems incorrect. */
2567 XTALTAB0_640_52000K
2568 };
2569
2570 /* the following table is based on 880Mhz fvco */
2571 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_880)[] = {
2572 {12000, 1, 3, 22, 0x9, 0xFFFFEF},
2573 {13000, 2, 1, 6, 0xb, 0x483483},
2574 {14400, 3, 1, 10, 0xa, 0x1C71C7},
2575 {15360, 4, 1, 5, 0xb, 0x755555},
2576 {16200, 5, 1, 10, 0x5, 0x6E9E06},
2577 {16800, 6, 1, 10, 0x5, 0x3Cf3Cf},
2578 {19200, 7, 1, 4, 0xb, 0x755555},
2579 {19800, 8, 1, 11, 0x4, 0xA57EB},
2580 {20000, 9, 1, 11, 0x4, 0x0},
2581 {24000, 10, 3, 11, 0xa, 0x0},
2582 {25000, 11, 5, 16, 0xb, 0x0},
2583 {26000, 12, 1, 2, 0x10, 0xEC4EC4},
2584 {30000, 13, 3, 8, 0xb, 0x0},
2585 {33600, 14, 1, 2, 0xd, 0x186186},
2586 {38400, 15, 1, 2, 0xb, 0x755555},
2587 {40000, 16, 1, 2, 0xb, 0},
2588 {0, 0, 0, 0, 0, 0}
2589 };
2590
2591 /* indices into pmu1_xtaltab0_880[] */
2592 #define PMU1_XTALTAB0_880_12000K 0
2593 #define PMU1_XTALTAB0_880_13000K 1
2594 #define PMU1_XTALTAB0_880_14400K 2
2595 #define PMU1_XTALTAB0_880_15360K 3
2596 #define PMU1_XTALTAB0_880_16200K 4
2597 #define PMU1_XTALTAB0_880_16800K 5
2598 #define PMU1_XTALTAB0_880_19200K 6
2599 #define PMU1_XTALTAB0_880_19800K 7
2600 #define PMU1_XTALTAB0_880_20000K 8
2601 #define PMU1_XTALTAB0_880_24000K 9
2602 #define PMU1_XTALTAB0_880_25000K 10
2603 #define PMU1_XTALTAB0_880_26000K 11
2604 #define PMU1_XTALTAB0_880_30000K 12
2605 #define PMU1_XTALTAB0_880_37400K 13
2606 #define PMU1_XTALTAB0_880_38400K 14
2607 #define PMU1_XTALTAB0_880_40000K 15
2608
2609 /* the following table is based on 1760Mhz fvco */
2610 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_1760)[] = {
2611 {12000, 1, 3, 44, 0x9, 0xFFFFEF},
2612 {13000, 2, 1, 12, 0xb, 0x483483},
2613 {14400, 3, 1, 20, 0xa, 0x1C71C7},
2614 {15360, 4, 1, 10, 0xb, 0x755555},
2615 {16200, 5, 1, 20, 0x5, 0x6E9E06},
2616 {16800, 6, 1, 20, 0x5, 0x3Cf3Cf},
2617 {19200, 7, 1, 18, 0x5, 0x17B425},
2618 {19800, 8, 1, 22, 0x4, 0xA57EB},
2619 {20000, 9, 1, 22, 0x4, 0x0},
2620 {24000, 10, 3, 22, 0xa, 0x0},
2621 {25000, 11, 5, 32, 0xb, 0x0},
2622 {26000, 12, 1, 4, 0x10, 0xEC4EC4},
2623 {30000, 13, 3, 16, 0xb, 0x0},
2624 {38400, 14, 1, 10, 0x4, 0x955555},
2625 {40000, 15, 1, 4, 0xb, 0},
2626 {0, 0, 0, 0, 0, 0}
2627 };
2628
2629 #define XTAL_FREQ_24000MHZ 24000
2630 #define XTAL_FREQ_29985MHZ 29985
2631 #define XTAL_FREQ_30000MHZ 30000
2632 #define XTAL_FREQ_37400MHZ 37400
2633 #define XTAL_FREQ_48000MHZ 48000
2634 #define XTAL_FREQ_59970MHZ 59970
2635
2636 /* 'xf' values corresponding to the 'xf' definition in the PMU control register */
2637 /* unclear why this enum contains '_960_' since the PMU prog guide says nothing about that */
2638 enum xtaltab0_960 {
2639 XTALTAB0_960_12000K = 1,
2640 XTALTAB0_960_13000K,
2641 XTALTAB0_960_14400K,
2642 XTALTAB0_960_15360K,
2643 XTALTAB0_960_16200K,
2644 XTALTAB0_960_16800K,
2645 XTALTAB0_960_19200K,
2646 XTALTAB0_960_19800K,
2647 XTALTAB0_960_20000K,
2648 XTALTAB0_960_24000K, /* warning: unknown in PMU programmers guide. seems incorrect. */
2649 XTALTAB0_960_25000K,
2650 XTALTAB0_960_26000K,
2651 XTALTAB0_960_30000K,
2652 XTALTAB0_960_33600K, /* warning: unknown in PMU programmers guide. seems incorrect. */
2653 XTALTAB0_960_37400K,
2654 XTALTAB0_960_38400K, /* warning: unknown in PMU programmers guide. seems incorrect. */
2655 XTALTAB0_960_40000K,
2656 XTALTAB0_960_48000K, /* warning: unknown in PMU programmers guide. seems incorrect. */
2657 XTALTAB0_960_52000K,
2658 XTALTAB0_960_59970K
2659 };
2660
2661 /**
2662 * given an x-tal frequency, this table specifies the PLL params to use to generate a 960Mhz output
2663 * clock. This output clock feeds the clock divider network. The defines of the form
2664 * PMU1_XTALTAB0_960_* index into this array.
2665 */
2666 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_960)[] = {
2667 /* fref xf p1div p2div ndiv_int ndiv_frac */
2668 {12000, 1, 1, 1, 0x50, 0x0 }, /* array index 0 */
2669 {13000, 2, 1, 1, 0x49, 0xD89D89},
2670 {14400, 3, 1, 1, 0x42, 0xAAAAAA},
2671 {15360, 4, 1, 1, 0x3E, 0x800000},
2672 {16200, 5, 1, 1, 0x3B, 0x425ED0},
2673 {16800, 6, 1, 1, 0x39, 0x249249},
2674 {19200, 7, 1, 1, 0x32, 0x0 },
2675 {19800, 8, 1, 1, 0x30, 0x7C1F07},
2676 {20000, 9, 1, 1, 0x30, 0x0 },
2677 {24000, 10, 1, 1, 0x28, 0x0 },
2678 {25000, 11, 1, 1, 0x26, 0x666666}, /* array index 10 */
2679 {26000, 12, 1, 1, 0x24, 0xEC4EC4},
2680 {30000, 13, 1, 1, 0x20, 0x0 },
2681 {33600, 14, 1, 1, 0x1C, 0x924924},
2682 {37400, 15, 2, 1, 0x33, 0x563EF9},
2683 {38400, 16, 2, 1, 0x32, 0x0 },
2684 {40000, 17, 2, 1, 0x30, 0x0 },
2685 {48000, 18, 2, 1, 0x28, 0x0 },
2686 {52000, 19, 2, 1, 0x24, 0xEC4EC4}, /* array index 18 */
2687 {59970, 20, 0, 0, 0, 0 },
2688 /* TBD: will separate 59970 for 4387B0 for new pll scheme */
2689 {0, 0, 0, 0, 0, 0 }
2690 };
2691
2692 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_4369_963)[] = {
2693 /* fref xf p1div NA ndiv_int ndiv_frac */
2694 {12000, 1, 1, 1, 0x50, 0x40000}, /* array index 0 */
2695 {13000, 2, 1, 1, 0x4A, 0x13B14},
2696 {14400, 3, 1, 1, 0x42, 0xE0000},
2697 {15360, 4, 1, 1, 0x3E, 0xB2000},
2698 {16200, 5, 1, 1, 0x3B, 0x71C72},
2699 {16800, 6, 1, 1, 0x39, 0x52492},
2700 {19200, 7, 1, 1, 0x32, 0x28000},
2701 {19800, 8, 1, 1, 0x30, 0xA2E8C},
2702 {20000, 9, 1, 1, 0x30, 0x26666},
2703 {24000, 10, 1, 1, 0x28, 0x20000},
2704 {25000, 11, 1, 1, 0x26, 0x851EC}, /* array index 10 */
2705 {26000, 12, 1, 1, 0x25, 0x09D8A},
2706 {30000, 13, 1, 1, 0x20, 0x1999A},
2707 {33600, 14, 1, 1, 0x1C, 0xA9249},
2708 {37400, 15, 1, 1, 0x19, 0xBFA86},
2709 {38400, 16, 1, 1, 0x19, 0x14000},
2710 {40000, 17, 1, 1, 0x18, 0x13333},
2711 {48000, 18, 1, 1, 0x14, 0x10000},
2712 {52000, 19, 1, 1, 0x12, 0x84EC5}, /* array index 18 */
2713 {0, 0, 0, 0, 0, 0 }
2714 };
2715
2716 static const pmu1_xtaltab0_t BCMINITDATA(pmu1_xtaltab0_4362_963)[] = {
2717 /* fref xf p1div NA ndiv_int ndiv_frac */
2718 {12000, 1, 1, 1, 0x50, 0x40000}, /* array index 0 */
2719 {13000, 2, 1, 1, 0x4A, 0x13B14},
2720 {14400, 3, 1, 1, 0x42, 0xE0000},
2721 {15360, 4, 1, 1, 0x3E, 0xB2000},
2722 {16200, 5, 1, 1, 0x3B, 0x71C72},
2723 {16800, 6, 1, 1, 0x39, 0x52492},
2724 {19200, 7, 1, 1, 0x32, 0x28000},
2725 {19800, 8, 1, 1, 0x30, 0xA2E8C},
2726 {20000, 9, 1, 1, 0x30, 0x26666},
2727 {24000, 10, 1, 1, 0x28, 0x20000},
2728 {25000, 11, 1, 1, 0x26, 0x851EC}, /* array index 10 */
2729 {26000, 12, 1, 1, 0x25, 0x09D8A},
2730 {30000, 13, 1, 1, 0x20, 0x1999A},
2731 {33600, 14, 1, 1, 0x1C, 0xA9249},
2732 {37400, 15, 1, 1, 0x19, 0xBFA86},
2733 {38400, 16, 1, 1, 0x19, 0x14000},
2734 {40000, 17, 1, 1, 0x18, 0x13333},
2735 {48000, 18, 1, 1, 0x14, 0x10000},
2736 {52000, 19, 1, 1, 0x12, 0x84EC5}, /* array index 18 */
2737 {0, 0, 0, 0, 0, 0 }
2738 };
2739
2740 /* Indices into array pmu1_xtaltab0_960[]. Keep array and these defines synchronized. */
2741 #define PMU1_XTALTAB0_960_12000K 0
2742 #define PMU1_XTALTAB0_960_13000K 1
2743 #define PMU1_XTALTAB0_960_14400K 2
2744 #define PMU1_XTALTAB0_960_15360K 3
2745 #define PMU1_XTALTAB0_960_16200K 4
2746 #define PMU1_XTALTAB0_960_16800K 5
2747 #define PMU1_XTALTAB0_960_19200K 6
2748 #define PMU1_XTALTAB0_960_19800K 7
2749 #define PMU1_XTALTAB0_960_20000K 8
2750 #define PMU1_XTALTAB0_960_24000K 9
2751 #define PMU1_XTALTAB0_960_25000K 10
2752 #define PMU1_XTALTAB0_960_26000K 11
2753 #define PMU1_XTALTAB0_960_30000K 12
2754 #define PMU1_XTALTAB0_960_33600K 13
2755 #define PMU1_XTALTAB0_960_37400K 14
2756 #define PMU1_XTALTAB0_960_38400K 15
2757 #define PMU1_XTALTAB0_960_40000K 16
2758 #define PMU1_XTALTAB0_960_48000K 17
2759 #define PMU1_XTALTAB0_960_52000K 18
2760 #define PMU1_XTALTAB0_960_59970K 19
2761
2762 #define PMU15_XTALTAB0_12000K 0
2763 #define PMU15_XTALTAB0_20000K 1
2764 #define PMU15_XTALTAB0_26000K 2
2765 #define PMU15_XTALTAB0_37400K 3
2766 #define PMU15_XTALTAB0_52000K 4
2767 #define PMU15_XTALTAB0_END 5
2768
2769 /* For having the pllcontrol data (info)
2770 * The table with the values of the registers will have one - one mapping.
2771 */
2772 typedef struct {
2773 uint16 clock; /**< x-tal frequency in [KHz] */
2774 uint8 mode; /**< spur mode */
2775 uint8 xf; /**< corresponds with xf bitfield in PMU control register */
2776 } pllctrl_data_t;
2777
2778 /* ***************************** tables for 43012a0 *********************** */
2779
2780 /**
2781 * PLL control register table giving info about the xtal supported for 43012
2782 * There should be a one to one mapping between pmu1_pllctrl_tab_43012_960mhz[] and this table.
2783 */
2784 static const pllctrl_data_t(pmu1_xtaltab0_43012)[] = {
2785 /* clock mode xf */
2786 {37400, 0, XTALTAB0_960_37400K},
2787 {37400, 100, XTALTAB0_960_37400K},
2788 {26000, 0, XTALTAB0_960_26000K},
2789 {24000, 0, XTALTAB0_960_24000K}
2790 };
2791
2792 /*
2793 There should be a one to one mapping between pmu1_pllctrl_tab_43012_640mhz[]
2794 * and this table. PLL control5 register is related to HSIC which is not supported in 43012
2795 * Use a safe DCO code=56 by default, Across PVT openloop VCO Max=320MHz, Min=100
2796 * Mhz
2797 */
2798 #ifdef BCMQT
2799 static const uint32 (pmu1_pllctrl_tab_43012_1600mhz)[] = {
2800 /* Fvco is taken as 160.1 */
2801 /* PLL 0 PLL 1 PLL 2 PLL 3 PLL 4 PLL 5 */
2802 0x072fe811, 0x00800000, 0x00000000, 0x038051e8, 0x00000000, 0x00000000,
2803 0x0e5fd422, 0x00800000, 0x00000000, 0x000011e8, 0x00000000, 0x00000000
2804 };
2805 #else
2806 static const uint32 (pmu1_pllctrl_tab_43012_1600mhz)[] = {
2807 /* Fvco is taken as 160.1 */
2808 /* PLL 0 PLL 1 PLL 2 PLL 3 PLL 4 */
2809 0x07df2411, 0x00800000, 0x00000000, 0x038051e8, 0x00000000,
2810 0x0e5fd422, 0x00800000, 0x00000000, 0x000011e8, 0x00000000,
2811 0x1d89dc12, 0x00800000, 0x00000000, 0x06d04de8, 0x00000000,
2812 0x072fe828, 0x00800000, 0x00000000, 0x06d04de8, 0x00000000
2813 };
2814 #endif /* BCMQT */
2815 /* ************************ tables for 43012a0 END *********************** */
2816
2817 /* ***************************** tables for 4369a0 *********************** */
2818 /* should get real value from hardware guys */
2819 /**
2820 * PLL control register table giving info about the xtal supported for 4369
2821 * There should be a one to one mapping between pmu1_pllctrl_tab_4369_960mhz[] and this table.
2822 * Even though macro suggests XTALTAB0_960_37400K --> BBPLL VCO is set to 963MHz
2823 */
2824 static const pllctrl_data_t BCMATTACHDATA(pmu1_xtaltab0_4369)[] = {
2825 /* clock mode xf */
2826 {37400, 0, XTALTAB0_960_37400K}
2827 };
2828
2829 /**
2830 * PLL control register table giving info about the xtal supported for 4369.
2831 * There should be a one to one mapping between pmu1_pllctrl_tab_4369_963mhz[] and this table.
2832 */
2833
2834 /* For 4369, 960.1MHz BBPLL freq is chosen to avoid the spurs
2835 * freq table : pll1 : fvco 960.1M, pll2 for arm : 400 MHz
2836 */
2837 #define PMU_PLL3_4369B0_DEFAULT 0x006ABF86
2838 static const uint32 BCMATTACHDATA(pmu1_pllctrl_tab_4369_960p1mhz)[] = {
2839 /* Default values for unused registers 4-7 as sw loop execution will go for 8 times */
2840 /* Fvco is taken as 963M */
2841 /* PLL 0 PLL 1 PLL 2 PLL 3 PLL 4 PLL 5 PLL 6 PLL 7 PLL 8 PLL 9 PLL 10 */
2842 0x15000000, 0x06050603, 0x01910806, PMU_PLL3_4369B0_DEFAULT,
2843 0x00000000, 0x32800000, 0xC7AE00A9, 0x40800000,
2844 0x00000000, 0x00000000, 0x00000000
2845 };
2846
2847 /* ************************ tables for 4369a0 END *********************** */
2848
2849 /* ***************************** tables for 4362a0 *********************** */
2850 /* should get real value from hardware guys */
2851 /**
2852 * PLL control register table giving info about the xtal supported for 4362
2853 * There should be a one to one mapping between pmu1_pllctrl_tab_4362_960mhz[] and this table.
2854 * Even though macro suggests XTALTAB0_960_37400K --> BBPLL VCO is set to 963MHz
2855 */
2856 static const pllctrl_data_t BCMATTACHDATA(pmu1_xtaltab0_4362)[] = {
2857 /* clock mode xf */
2858 {37400, 0, XTALTAB0_960_37400K}
2859 };
2860
2861 /* For 4362, 960.1MHz BBPLL freq is chosen to avoid the spurs
2862 * freq table : pll1 : fvco 960.1M, pll2 for arm : 400 MHz
2863 */
2864 /* This freq actually around 960.123 */
2865 #define PMU_PLL3_4362A0_DEFAULT 0x006ABF86
2866
2867 static const uint32 BCMATTACHDATA(pmu1_pllctrl_tab_4362_960p1mhz)[] = {
2868 /* Default values for unused registers 4-7 as sw loop execution will go for 8 times */
2869 /* Fvco is taken as 963M */
2870 /* PLL 0 PLL 1 PLL 2 PLL 3 PLL 4 PLL 5 PLL 6 PLL 7 PLL 8 PLL 9 PLL 10 */
2871 0x15000000, 0x06050603, 0x01910806, PMU_PLL3_4362A0_DEFAULT,
2872 0x00000000, 0x32800000, 0xC7AE00A9, 0x40800000,
2873 0x00000000, 0x00000000, 0x00000000
2874 };
2875
2876 /* ************************ tables for 4362a0 END *********************** */
2877
2878 /* ***************************** tables for 4389 *********************** */
2879 static const pllctrl_data_t BCMATTACHDATA(pmu1_xtaltab0_4389)[] = {
2880 /* clock mode xf */
2881 {XTAL_FREQ_59970MHZ, 0, XTALTAB0_960_59970K}
2882 };
2883
2884 static const uint32 BCMATTACHDATA(pmu1_pllctrl_tab_4389_963mhz)[] = {
2885 /* Default values for all registers */
2886 /* Fvco (BBPLL) is taken as 963M */
2887 /* PLL 0 PLL 1 PLL 2 PLL 3 PLL 4 PLL 5 PLL 6 PLL 7 PLL 8 PLL 9 PLL 10 */
2888 0x29d00000, 0x30100c03, 0x00240c06, 0x597ff060,
2889 0x00000000, 0x00000800, 0x00321d3a, 0x000551ff,
2890 0x00000000, 0x10000000, 0x00000000
2891 };
2892
2893 /* ************************ tables for 4389 END *********************** */
2894
2895 /** returns a table that instructs how to program the BBPLL for a particular xtal frequency */
2896 static const pmu1_xtaltab0_t *
BCMPOSTTRAPFN(si_pmu1_xtaltab0)2897 BCMPOSTTRAPFN(si_pmu1_xtaltab0)(si_t *sih)
2898 {
2899 #ifdef BCMDBG_PMU
2900 char chn[8];
2901 #endif
2902 switch (CHIPID(sih->chip)) {
2903 case BCM4360_CHIP_ID:
2904 case BCM43460_CHIP_ID:
2905 case BCM4352_CHIP_ID:
2906 case BCM43526_CHIP_ID:
2907 CASE_BCM43602_CHIP:
2908 case BCM43012_CHIP_ID:
2909 case BCM43013_CHIP_ID:
2910 case BCM43014_CHIP_ID:
2911 return pmu1_xtaltab0_960;
2912 case BCM4369_CHIP_GRPID:
2913 return pmu1_xtaltab0_4369_963;
2914 case BCM4362_CHIP_GRPID:
2915 return pmu1_xtaltab0_4362_963;
2916 case BCM4376_CHIP_GRPID:
2917 case BCM4378_CHIP_GRPID:
2918 case BCM4385_CHIP_GRPID:
2919 case BCM4387_CHIP_GRPID:
2920 case BCM4388_CHIP_GRPID:
2921 case BCM4389_CHIP_GRPID:
2922 case BCM4397_CHIP_GRPID:
2923 return pmu1_xtaltab0_960;
2924 default:
2925 PMU_MSG(("si_pmu1_xtaltab0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
2926 break;
2927 }
2928 ASSERT(0);
2929 return NULL;
2930 } /* si_pmu1_xtaltab0 */
2931
2932 /** returns chip specific PLL settings for default xtal frequency and VCO output frequency */
2933 static const pmu1_xtaltab0_t *
BCMPOSTTRAPFN(si_pmu1_xtaldef0)2934 BCMPOSTTRAPFN(si_pmu1_xtaldef0)(si_t *sih)
2935 {
2936 #ifdef BCMDBG_PMU
2937 char chn[8];
2938 #endif
2939
2940 switch (CHIPID(sih->chip)) {
2941 case BCM4360_CHIP_ID:
2942 case BCM4352_CHIP_ID:
2943 case BCM43460_CHIP_ID:
2944 case BCM43526_CHIP_ID:
2945 case BCM43012_CHIP_ID:
2946 case BCM43013_CHIP_ID:
2947 /* Default to 37400Khz */
2948 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_37400K];
2949 case BCM43014_CHIP_ID:
2950 /* Default to 24000Khz */
2951 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_24000K];
2952 CASE_BCM43602_CHIP:
2953 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_40000K];
2954
2955 case BCM4376_CHIP_GRPID:
2956 case BCM4378_CHIP_GRPID:
2957 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_37400K];
2958 case BCM4385_CHIP_GRPID:
2959 case BCM4387_CHIP_GRPID:
2960 case BCM4388_CHIP_GRPID:
2961 case BCM4389_CHIP_GRPID:
2962 case BCM4397_CHIP_GRPID:
2963 return &pmu1_xtaltab0_960[PMU1_XTALTAB0_960_59970K];
2964 case BCM4369_CHIP_GRPID:
2965 return &pmu1_xtaltab0_4369_963[PMU1_XTALTAB0_960_37400K];
2966 case BCM4362_CHIP_GRPID:
2967 return &pmu1_xtaltab0_4362_963[PMU1_XTALTAB0_960_37400K];
2968 default:
2969 PMU_MSG(("si_pmu1_xtaldef0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
2970 break;
2971 }
2972 ASSERT(0);
2973 return NULL;
2974 } /* si_pmu1_xtaldef0 */
2975
2976 static uint32 fvco_4360 = 0;
2977
2978 /**
2979 * store the val on init, then if func is called during normal operation
2980 * don't touch core regs anymore
2981 */
2982 static uint32
BCMPOSTTRAPFN(si_pmu_pll1_fvco_4360)2983 BCMPOSTTRAPFN(si_pmu_pll1_fvco_4360)(si_t *sih, osl_t *osh)
2984 {
2985 uint32 xf, ndiv_int, ndiv_frac, fvco, pll_reg, p1_div_scale;
2986 uint32 r_high, r_low, int_part, frac_part, rounding_const;
2987 uint8 p1_div;
2988 uint origidx = 0;
2989 bcm_int_bitmask_t intr_val;
2990
2991 if (fvco_4360) {
2992 printf("si_pmu_pll1_fvco_4360:attempt to query fvco during normal operation\n");
2993 /* this will insure that the func is called only once upon init */
2994 return fvco_4360;
2995 }
2996
2997 /* Remember original core before switch to chipc */
2998 si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
2999
3000 xf = si_pmu_alp_clock(sih, osh)/1000;
3001
3002 /* pll reg 10 , p1div, ndif_mode, ndiv_int */
3003 pll_reg = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG10, 0, 0);
3004 p1_div = pll_reg & 0xf;
3005 ndiv_int = (pll_reg >> 7) & 0x1f;
3006
3007 /* pllctrl11 */
3008 pll_reg = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG11, 0, 0);
3009 ndiv_frac = pll_reg & 0xfffff;
3010
3011 int_part = xf * ndiv_int;
3012
3013 rounding_const = 1 << (BBPLL_NDIV_FRAC_BITS - 1);
3014 math_uint64_multiple_add(&r_high, &r_low, ndiv_frac, xf, rounding_const);
3015 math_uint64_right_shift(&frac_part, r_high, r_low, BBPLL_NDIV_FRAC_BITS);
3016
3017 if (!p1_div) {
3018 PMU_ERROR(("p1_div calc returned 0! [%d]\n", __LINE__));
3019 ROMMABLE_ASSERT(0);
3020 }
3021
3022 if (p1_div == 0) {
3023 ASSERT(p1_div != 0);
3024 p1_div_scale = 0;
3025 } else
3026
3027 p1_div_scale = (1 << P1_DIV_SCALE_BITS) / p1_div;
3028 rounding_const = 1 << (P1_DIV_SCALE_BITS - 1);
3029
3030 math_uint64_multiple_add(&r_high, &r_low, (int_part + frac_part),
3031 p1_div_scale, rounding_const);
3032 math_uint64_right_shift(&fvco, r_high, r_low, P1_DIV_SCALE_BITS);
3033
3034 /* Return to original core */
3035 si_restore_core(sih, origidx, &intr_val);
3036
3037 fvco_4360 = fvco;
3038 return fvco;
3039 } /* si_pmu_pll1_fvco_4360 */
3040
3041 /**
3042 * Specific to 43012 and calculate the FVCO frequency from XTAL freq
3043 * Returns the FCVO frequency in [khz] units
3044 */
3045 static uint32
BCMPOSTTRAPFN(si_pmu_pll1_fvco_43012)3046 BCMPOSTTRAPFN(si_pmu_pll1_fvco_43012)(si_t *sih, osl_t *osh)
3047 {
3048 uint32 xf, ndiv_int, ndiv_frac, fvco, pll_reg, p1_div_scale;
3049 uint32 r_high, r_low, int_part, frac_part, rounding_const;
3050 uint8 p_div;
3051 chipcregs_t *cc;
3052 uint origidx = 0;
3053 bcm_int_bitmask_t intr_val;
3054
3055 /* Remember original core before switch to chipc */
3056 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
3057 ASSERT(cc != NULL);
3058 BCM_REFERENCE(cc);
3059
3060 xf = si_pmu_alp_clock(sih, osh)/1000;
3061
3062 pll_reg = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG0, 0, 0);
3063
3064 ndiv_int = (pll_reg & PMU43012_PLL0_PC0_NDIV_INT_MASK) >>
3065 PMU43012_PLL0_PC0_NDIV_INT_SHIFT;
3066
3067 ndiv_frac = (pll_reg & PMU43012_PLL0_PC0_NDIV_FRAC_MASK) >>
3068 PMU43012_PLL0_PC0_NDIV_FRAC_SHIFT;
3069
3070 pll_reg = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG3, 0, 0);
3071
3072 p_div = (pll_reg & PMU43012_PLL0_PC3_PDIV_MASK) >>
3073 PMU43012_PLL0_PC3_PDIV_SHIFT;
3074
3075 /* If the p_div value read from PLL control register is zero,
3076 * then return default FVCO value instead of computing the FVCO frequency
3077 * using XTAL frequency
3078 */
3079 if (!p_div) {
3080 PMU_ERROR(("pll control register read failed [%d]\n", __LINE__));
3081 ROMMABLE_ASSERT(0);
3082 fvco = 0;
3083 goto done;
3084 }
3085 /* Actual expression is as below */
3086 /* fvco1 = ((xf * (1/p1_div)) * (ndiv_int + (ndiv_frac /(1 << 20)))); */
3087
3088 int_part = xf * ndiv_int;
3089 rounding_const = 1 << (PMU43012_PLL_NDIV_FRAC_BITS - 1);
3090 math_uint64_multiple_add(&r_high, &r_low, ndiv_frac, xf, rounding_const);
3091 math_uint64_right_shift(&frac_part, r_high, r_low, PMU43012_PLL_NDIV_FRAC_BITS);
3092
3093 p1_div_scale = (1 << PMU43012_PLL_P_DIV_SCALE_BITS) / p_div;
3094 rounding_const = 1 << (PMU43012_PLL_P_DIV_SCALE_BITS - 1);
3095
3096 math_uint64_multiple_add(&r_high, &r_low, (int_part + frac_part),
3097 p1_div_scale, rounding_const);
3098 math_uint64_right_shift(&fvco, r_high, r_low, PMU43012_PLL_P_DIV_SCALE_BITS);
3099
3100 done:
3101 /* Return to original core */
3102 si_restore_core(sih, origidx, &intr_val);
3103 return fvco;
3104 } /* si_pmu_pll1_fvco_43012 */
3105
3106 /** returns chip specific default BaseBand pll fvco frequency in [khz] units */
3107 static uint32
BCMPOSTTRAPFN(si_pmu1_pllfvco0)3108 BCMPOSTTRAPFN(si_pmu1_pllfvco0)(si_t *sih)
3109 {
3110 #ifdef BCMDBG_PMU
3111 char chn[8];
3112 #endif
3113
3114 switch (CHIPID(sih->chip)) {
3115 case BCM4352_CHIP_ID:
3116 case BCM43526_CHIP_ID:
3117 return FVCO_960;
3118
3119 CASE_BCM43602_CHIP:
3120 return FVCO_960;
3121 case BCM4360_CHIP_ID:
3122 case BCM43460_CHIP_ID:
3123 {
3124 osl_t *osh;
3125 osh = si_osh(sih);
3126 return si_pmu_pll1_fvco_4360(sih, osh);
3127 }
3128 case BCM43012_CHIP_ID:
3129 case BCM43013_CHIP_ID:
3130 case BCM43014_CHIP_ID:
3131 {
3132 osl_t *osh;
3133 osh = si_osh(sih);
3134 return si_pmu_pll1_fvco_43012(sih, osh);
3135 }
3136 case BCM4369_CHIP_GRPID:
3137 return FVCO_960p1;
3138 case BCM4362_CHIP_GRPID:
3139 return FVCO_960p1;
3140 case BCM4376_CHIP_GRPID:
3141 case BCM4378_CHIP_GRPID:
3142 return FVCO_960p1;
3143 case BCM4385_CHIP_GRPID:
3144 case BCM4387_CHIP_GRPID:
3145 case BCM4388_CHIP_GRPID:
3146 case BCM4389_CHIP_GRPID:
3147 case BCM4397_CHIP_GRPID:
3148 return FVCO_963p01;
3149 default:
3150 PMU_MSG(("si_pmu1_pllfvco0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
3151 break;
3152 }
3153 ASSERT(0);
3154 return 0;
3155 } /* si_pmu1_pllfvco0 */
3156
3157 /**
3158 * returns chip specific default pll fvco frequency in [khz] units
3159 */
3160 static uint32
BCMPOSTTRAPFN(si_pmu1_pllfvco0_pll2)3161 BCMPOSTTRAPFN(si_pmu1_pllfvco0_pll2)(si_t *sih)
3162 {
3163 #ifdef BCMDBG_PMU
3164 char chn[8];
3165 #endif
3166
3167 switch (CHIPID(sih->chip)) {
3168 case BCM4369_CHIP_GRPID:
3169 case BCM4362_CHIP_GRPID:
3170 case BCM4388_CHIP_GRPID:
3171 case BCM4397_CHIP_GRPID:
3172 return si_get_armpllclkfreq(sih) * 1000;
3173 case BCM4389_CHIP_GRPID:
3174 return SI_INFO(sih)->armpllclkfreq ? si_get_armpllclkfreq(sih) * 1000 : FVCO_1002p8;
3175 case BCM4376_CHIP_GRPID:
3176 case BCM4378_CHIP_GRPID:
3177 case BCM4385_CHIP_GRPID:
3178 case BCM4387_CHIP_GRPID:
3179 return FVCO_400;
3180 default:
3181 PMU_MSG(("si_pmu1_pllfvco0_pll2 : Unknown chipid %s\n",
3182 bcm_chipname(sih->chip, chn, 8)));
3183 ASSERT(0);
3184 break;
3185 }
3186 return 0;
3187 } /* si_pmu1_pllfvco0_pll2 */
3188
3189 /** query alp/xtal clock frequency */
3190 static uint32
BCMPOSTTRAPFN(si_pmu1_alpclk0)3191 BCMPOSTTRAPFN(si_pmu1_alpclk0)(si_t *sih, osl_t *osh, pmuregs_t *pmu)
3192 {
3193 const pmu1_xtaltab0_t *xt;
3194 uint32 xf;
3195 uint8 xtdiv = 1;
3196
3197 BCM_REFERENCE(sih);
3198
3199 /* Find the frequency in the table */
3200 xf = (R_REG(osh, &pmu->pmucontrol) & PCTL_XTALFREQ_MASK) >>
3201 PCTL_XTALFREQ_SHIFT;
3202 for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
3203 if (xt->xf == xf)
3204 break;
3205 /* Could not find it so assign a default value */
3206 if (xt == NULL || xt->fref == 0)
3207 xt = si_pmu1_xtaldef0(sih);
3208 ASSERT(xt != NULL && xt->fref != 0);
3209
3210 switch (CHIPID(sih->chip))
3211 {
3212 case BCM4385_CHIP_GRPID:
3213 case BCM4387_CHIP_GRPID:
3214 case BCM4388_CHIP_GRPID:
3215 case BCM4389_CHIP_GRPID:
3216 case BCM4397_CHIP_GRPID:
3217 /* xtalfreq for 4378B0 is 59.97 MHz and
3218 * but ALP clk is xtal / 2 (29.985 MHz) by default.
3219 */
3220 xtdiv = 2;
3221 break;
3222 default:
3223 break;
3224 }
3225
3226 return (xt->fref * 1000) / xtdiv;
3227 }
3228
3229 /**
3230 * Before the PLL is switched off, the HT clocks need to be deactivated, and reactivated
3231 * when the PLL is switched on again.
3232 * This function returns the chip specific HT clock resources (HT and MACPHY clocks).
3233 */
3234 static uint32
si_pmu_htclk_mask(si_t * sih)3235 si_pmu_htclk_mask(si_t *sih)
3236 {
3237 /* chip specific bit position of various resources */
3238 rsc_per_chip_t *rsc = si_pmu_get_rsc_positions(sih);
3239
3240 uint32 ht_req = (PMURES_BIT(rsc->ht_avail) | PMURES_BIT(rsc->macphy_clkavail));
3241
3242 switch (CHIPID(sih->chip))
3243 {
3244 CASE_BCM43602_CHIP:
3245 case BCM43012_CHIP_ID:
3246 case BCM43013_CHIP_ID:
3247 case BCM43014_CHIP_ID:
3248 case BCM4369_CHIP_GRPID:
3249 case BCM4362_CHIP_GRPID:
3250 case BCM4376_CHIP_GRPID:
3251 case BCM4378_CHIP_GRPID:
3252 case BCM4385_CHIP_GRPID:
3253 case BCM4387_CHIP_GRPID:
3254 case BCM4388_CHIP_GRPID:
3255 case BCM4389_CHIP_GRPID:
3256 case BCM4397_CHIP_GRPID:
3257 ht_req |= PMURES_BIT(rsc->ht_start);
3258 break;
3259 default:
3260 ASSERT(0);
3261 break;
3262 }
3263
3264 return ht_req;
3265 } /* si_pmu_htclk_mask */
3266
3267 /** returns ALP frequency in [Hz] */
3268 static uint32
BCMATTACHFN(si_pmu_def_alp_clock)3269 BCMATTACHFN(si_pmu_def_alp_clock)(si_t *sih, osl_t *osh)
3270 {
3271 uint32 clock = ALP_CLOCK;
3272
3273 BCM_REFERENCE(osh);
3274
3275 switch (CHIPID(sih->chip)) {
3276 case BCM43012_CHIP_ID:
3277 case BCM43013_CHIP_ID:
3278 case BCM43014_CHIP_ID:
3279 case BCM4369_CHIP_GRPID:
3280 case BCM4362_CHIP_GRPID:
3281 case BCM4376_CHIP_GRPID:
3282 case BCM4378_CHIP_GRPID:
3283 case BCM4385_CHIP_GRPID:
3284 case BCM4387_CHIP_GRPID:
3285 case BCM4388_CHIP_GRPID:
3286 case BCM4389_CHIP_GRPID:
3287 case BCM4397_CHIP_GRPID:
3288
3289 #ifdef UNRELEASEDCHIP
3290 #endif
3291
3292 clock = 37400*1000;
3293 break;
3294 CASE_BCM43602_CHIP:
3295 clock = 40000 * 1000;
3296 break;
3297 }
3298
3299 return clock;
3300 }
3301
3302 /**
3303 * The BBPLL register set needs to be reprogrammed because the x-tal frequency is not known at
3304 * compile time, or a different spur mode is selected. This function writes appropriate values into
3305 * the BBPLL registers. It returns the 'xf', corresponding to the 'xf' bitfield in the PMU control
3306 * register.
3307 * 'xtal' : xtal frequency in [KHz]
3308 * 'pllctrlreg_update': contains info on what entries to use in 'pllctrlreg_val' for the given
3309 * x-tal frequency and spur mode
3310 * 'pllctrlreg_val' : contains a superset of the BBPLL values to write
3311 *
3312 * Note: if pmu is NULL, this function returns xf, without programming PLL registers.
3313 * This function is only called for pmu1_ type chips, perhaps we should rename it.
3314 */
3315 static uint8
si_pmu_pllctrlreg_update(si_t * sih,osl_t * osh,pmuregs_t * pmu,uint32 xtal,uint8 spur_mode,const pllctrl_data_t * pllctrlreg_update,uint32 array_size,const uint32 * pllctrlreg_val)3316 si_pmu_pllctrlreg_update(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 xtal,
3317 uint8 spur_mode, const pllctrl_data_t *pllctrlreg_update, uint32 array_size,
3318 const uint32 *pllctrlreg_val)
3319 {
3320 uint8 indx, reg_offset, xf = 0;
3321 uint8 pll_ctrlcnt = 0;
3322
3323 ASSERT(pllctrlreg_update);
3324
3325 if (PMUREV(sih->pmurev) >= 5) {
3326 pll_ctrlcnt = (sih->pmucaps & PCAP5_PC_MASK) >> PCAP5_PC_SHIFT;
3327 } else {
3328 pll_ctrlcnt = (sih->pmucaps & PCAP_PC_MASK) >> PCAP_PC_SHIFT;
3329 }
3330
3331 /* Program the PLL control register if the xtal value matches with the table entry value */
3332 for (indx = 0; indx < array_size; indx++) {
3333 /* If the entry does not match the xtal and spur_mode just continue the loop */
3334 if (!((pllctrlreg_update[indx].clock == (uint16)xtal) &&
3335 (pllctrlreg_update[indx].mode == spur_mode)))
3336 continue;
3337 /*
3338 * Don't program the PLL registers if register base is NULL.
3339 * If NULL just return the xref.
3340 */
3341 if (pmu) {
3342 for (reg_offset = 0; reg_offset < pll_ctrlcnt; reg_offset++) {
3343 si_pmu_pllcontrol(sih, reg_offset, ~0,
3344 pllctrlreg_val[indx*pll_ctrlcnt + reg_offset]);
3345 }
3346
3347 /* for 4369, arm clk cycle can be set from nvram - default is 400 MHz */
3348 if ((BCM4369_CHIP(sih->chip) || BCM4362_CHIP(sih->chip)) &&
3349 (pll_ctrlcnt > PMU1_PLL0_PLLCTL6)) {
3350 si_pmu_pll6val_armclk_calc(osh, pmu,
3351 si_get_armpllclkfreq(sih), xtal, TRUE);
3352 }
3353 }
3354 xf = pllctrlreg_update[indx].xf;
3355 break;
3356 }
3357 return xf;
3358 } /* si_pmu_pllctrlreg_update */
3359
3360 /*
3361 * Calculate p1div, ndiv_int, ndiv_frac for clock ratio.
3362 * Input: fvco, xtal
3363 * Output: ndiv_int, ndiv_frac
3364 * Returns: p1div
3365 *
3366 */
3367 uint8
si_pmu_pll28nm_calc_ndiv(uint32 fvco,uint32 xtal,uint32 * ndiv_int,uint32 * ndiv_frac)3368 si_pmu_pll28nm_calc_ndiv(uint32 fvco, uint32 xtal, uint32 *ndiv_int, uint32 *ndiv_frac)
3369 {
3370 uint8 p1div;
3371 uint32 temp_high, temp_low;
3372 ASSERT(xtal <= 0xFFFFFFFF / 1000);
3373 p1div = 1 + (uint8) ((xtal * 1000) / 54000000UL);
3374 *ndiv_int = (fvco * p1div) / xtal;
3375 /* nfrac = 20 */
3376 /* ndiv_frac = (uint32) (((uint64) (fvco * p1div - xtal * ndiv_int) * (1 << 20)) / xtal) */
3377 math_uint64_multiple_add(&temp_high, &temp_low, fvco * p1div - xtal * (*ndiv_int), 1 << 20,
3378 0);
3379 math_uint64_divide(ndiv_frac, temp_high, temp_low, xtal);
3380 return p1div;
3381 }
3382
3383 void
si_pmu_armpll_freq_upd(si_t * sih,uint8 p1div,uint32 ndiv_int,uint32 ndiv_frac)3384 si_pmu_armpll_freq_upd(si_t *sih, uint8 p1div, uint32 ndiv_int, uint32 ndiv_frac)
3385 {
3386 switch (CHIPID(sih->chip)) {
3387 case BCM4388_CHIP_GRPID:
3388 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, PMU4388_ARMPLL_I_NDIV_INT_MASK,
3389 ndiv_int << PMU4388_ARMPLL_I_NDIV_INT_SHIFT);
3390 si_pmu_pllupd(sih);
3391 break;
3392 case BCM4389_CHIP_GRPID:
3393 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, PMU4389_ARMPLL_I_NDIV_INT_MASK,
3394 ndiv_int << PMU4389_ARMPLL_I_NDIV_INT_SHIFT);
3395 si_pmu_pllupd(sih);
3396 break;
3397 case BCM4369_CHIP_GRPID:
3398 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG5, PMU4369_PLL1_PC5_P1DIV_MASK,
3399 ((p1div >> PMU4369_P1DIV_LO_SHIFT) << PMU4369_PLL1_PC5_P1DIV_SHIFT));
3400 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, PMU4369_PLL1_PC6_P1DIV_MASK,
3401 (p1div >> PMU4369_P1DIV_HI_SHIFT));
3402 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, PMU4369_PLL1_PC6_NDIV_INT_MASK,
3403 ndiv_int << PMU4369_PLL1_PC6_NDIV_INT_SHIFT);
3404 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, PMU4369_PLL1_PC6_NDIV_FRAC_MASK,
3405 ndiv_frac << PMU4369_PLL1_PC6_NDIV_FRAC_SHIFT);
3406 si_pmu_pllupd(sih);
3407 break;
3408 case BCM4362_CHIP_GRPID:
3409 /* 4362/69 PLL definitions are same. so reusing definitions */
3410 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG5, PMU4369_PLL1_PC5_P1DIV_MASK,
3411 ((p1div >> PMU4369_P1DIV_LO_SHIFT) << PMU4369_PLL1_PC5_P1DIV_SHIFT));
3412 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, PMU4369_PLL1_PC6_P1DIV_MASK,
3413 (p1div >> PMU4369_P1DIV_HI_SHIFT));
3414 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, PMU4369_PLL1_PC6_NDIV_INT_MASK,
3415 ndiv_int << PMU4369_PLL1_PC6_NDIV_INT_SHIFT);
3416 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6, PMU4369_PLL1_PC6_NDIV_FRAC_MASK,
3417 ndiv_frac << PMU4369_PLL1_PC6_NDIV_FRAC_SHIFT);
3418 si_pmu_pllupd(sih);
3419 break;
3420 default:
3421 ASSERT(0);
3422 break;
3423 }
3424 }
3425
3426 void
si_pmu_bbpll_freq_upd(si_t * sih,uint8 p1div,uint32 ndiv_int,uint32 ndiv_frac)3427 si_pmu_bbpll_freq_upd(si_t *sih, uint8 p1div, uint32 ndiv_int, uint32 ndiv_frac)
3428 {
3429 switch (CHIPID(sih->chip)) {
3430 case BCM4369_CHIP_GRPID:
3431 case BCM4362_CHIP_GRPID:
3432 /* PLL Control 2 Register are the same for 4368, 4369 */
3433 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2, PMU4369_PLL0_PC2_PDIV_MASK, p1div);
3434 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2, PMU4369_PLL0_PC2_NDIV_INT_MASK,
3435 ndiv_int << PMU4369_PLL0_PC2_NDIV_INT_SHIFT);
3436 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2, PMU4369_PLL0_PC3_NDIV_FRAC_MASK,
3437 ndiv_frac << PMU4369_PLL0_PC3_NDIV_FRAC_SHIFT);
3438 si_pmu_pllupd(sih);
3439 break;
3440 default:
3441 ASSERT(0);
3442 break;
3443 }
3444 }
3445
3446 void
si_pmu_armpll_chmdiv_upd(si_t * sih,uint32 ch0_mdiv,uint32 ch1_mdiv)3447 si_pmu_armpll_chmdiv_upd(si_t *sih, uint32 ch0_mdiv, uint32 ch1_mdiv)
3448 {
3449 switch (CHIPID(sih->chip)) {
3450 default:
3451 ASSERT(0);
3452 break;
3453 }
3454 }
3455
3456 static bool
si_pmu_armpll_write_required(si_t * sih,uint32 xtal)3457 si_pmu_armpll_write_required(si_t *sih, uint32 xtal)
3458 {
3459 uint32 def_xtal = 0;
3460 uint32 def_armclk_mhz = 0;
3461 uint32 armclk_mhz = si_get_armpllclkfreq(sih);
3462
3463 switch (CHIPID(sih->chip)) {
3464 case BCM4369_CHIP_GRPID:
3465 def_xtal = XTAL_FREQ_37400MHZ;
3466 def_armclk_mhz = ARMPLL_FREQ_400MHZ;
3467 break;
3468 case BCM4388_CHIP_GRPID:
3469 def_xtal = XTAL_FREQ_59970MHZ;
3470 def_armclk_mhz = ARMPLL_FREQ_1000MHZ;
3471 break;
3472 case BCM4389_CHIP_GRPID:
3473 def_xtal = XTAL_FREQ_59970MHZ;
3474 def_armclk_mhz = ARMPLL_FREQ_1000MHZ;
3475 break;
3476 default:
3477 break;
3478 }
3479
3480 /*
3481 * If programmed xtalfreq is same as xtal, no need to enable pll write. Check for
3482 * armclk and xtalfreq instead of comparing calculated value and pll register value.
3483 */
3484 return (((armclk_mhz == def_armclk_mhz) && (xtal == def_xtal)) ? FALSE : TRUE);
3485 }
3486
3487 /**
3488 * Chip-specific overrides to PLLCONTROL registers during init. If certain conditions (dependent on
3489 * x-tal frequency and current ALP frequency) are met, an update of the PLL is required.
3490 *
3491 * This takes less precedence over OTP PLLCONTROL overrides.
3492 * If update_required=FALSE, it returns TRUE if a update is about to occur.
3493 * No write happens.
3494 *
3495 * Return value: TRUE if the BBPLL registers 'update' field should be written by the caller.
3496 *
3497 * This function is only called for pmu1_ type chips, perhaps we should rename it.
3498 */
3499 static bool
BCMATTACHFN(si_pmu_update_pllcontrol)3500 BCMATTACHFN(si_pmu_update_pllcontrol)(si_t *sih, osl_t *osh, uint32 xtal, bool update_required)
3501 {
3502 pmuregs_t *pmu;
3503 uint origidx;
3504 bool write_en = FALSE;
3505 uint8 xf = 0;
3506 const pmu1_xtaltab0_t *xt;
3507 uint32 tmp;
3508 const pllctrl_data_t *pllctrlreg_update = NULL;
3509 uint32 array_size = 0;
3510 /* points at a set of PLL register values to write for a given x-tal frequency: */
3511 const uint32 *pllctrlreg_val = NULL;
3512 uint8 ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MASH;
3513 uint32 xtalfreq = 0;
3514 uint32 ndiv_int;
3515 uint32 ndiv_frac;
3516 uint8 pdiv;
3517
3518 BCM_REFERENCE(ndiv_int);
3519 BCM_REFERENCE(ndiv_frac);
3520 BCM_REFERENCE(pdiv);
3521 /* If there is OTP or NVRAM entry for xtalfreq, program the
3522 * PLL control register even if it is default xtal.
3523 */
3524 xtalfreq = getintvar(NULL, rstr_xtalfreq);
3525 /* CASE1 */
3526 if (xtalfreq) {
3527 write_en = TRUE;
3528 xtal = xtalfreq;
3529 } else {
3530 /* There is NO OTP value */
3531 if (xtal) {
3532 /* CASE2: If the xtal value was calculated, program the PLL control
3533 * registers only if it is not default xtal value.
3534 */
3535 if (xtal != (si_pmu_def_alp_clock(sih, osh)/1000))
3536 write_en = TRUE;
3537 } else {
3538 /* CASE3: If the xtal obtained is "0", ie., clock is not measured, then
3539 * leave the PLL control register as it is but program the xf in
3540 * pmucontrol register with the default xtal value.
3541 */
3542 xtal = si_pmu_def_alp_clock(sih, osh)/1000;
3543 }
3544 }
3545
3546 switch (CHIPID(sih->chip)) {
3547 case BCM43012_CHIP_ID:
3548 case BCM43013_CHIP_ID:
3549 case BCM43014_CHIP_ID:
3550 pllctrlreg_update = pmu1_xtaltab0_43012;
3551 array_size = ARRAYSIZE(pmu1_xtaltab0_43012);
3552 pllctrlreg_val = pmu1_pllctrl_tab_43012_1600mhz;
3553 break;
3554 case BCM4369_CHIP_GRPID:
3555 pllctrlreg_update = pmu1_xtaltab0_4369;
3556 array_size = ARRAYSIZE(pmu1_xtaltab0_4369);
3557 pllctrlreg_val = pmu1_pllctrl_tab_4369_960p1mhz;
3558 /* default pll programming be true, later based on need disable it */
3559 write_en = TRUE;
3560 break;
3561 case BCM4362_CHIP_GRPID:
3562 pllctrlreg_update = pmu1_xtaltab0_4362;
3563 array_size = ARRAYSIZE(pmu1_xtaltab0_4362);
3564 pllctrlreg_val = pmu1_pllctrl_tab_4362_960p1mhz;
3565 /* default pll programming be true, later based on need disable it */
3566 write_en = TRUE;
3567 break;
3568 case BCM4376_CHIP_GRPID:
3569 case BCM4378_CHIP_GRPID:
3570 case BCM4385_CHIP_GRPID:
3571 case BCM4387_CHIP_GRPID:
3572 /* TBD : bypass PLL programming, So use chip default values */
3573 pllctrlreg_update = NULL;
3574 array_size = 0;
3575 pllctrlreg_val = NULL;
3576 write_en = FALSE;
3577 break;
3578 case BCM4388_CHIP_GRPID:
3579 /* TBD : bypass PLL programming, So use chip default values */
3580 pllctrlreg_update = NULL;
3581 array_size = 0;
3582 pllctrlreg_val = NULL;
3583 write_en = FALSE;
3584 break;
3585 case BCM4389_CHIP_GRPID:
3586 pllctrlreg_update = pmu1_xtaltab0_4389;
3587 array_size = ARRAYSIZE(pmu1_xtaltab0_4389);
3588 pllctrlreg_val = pmu1_pllctrl_tab_4389_963mhz;
3589 break;
3590 CASE_BCM43602_CHIP:
3591 /*
3592 * 43602 has only 1 x-tal value, possibly insert case when an other BBPLL
3593 * frequency than 960Mhz is required (e.g., for spur avoidance)
3594 */
3595 /* fall through */
3596 default:
3597 /* write_en is FALSE in this case. So returns from the function */
3598 write_en = FALSE;
3599 break;
3600 }
3601
3602 /* Remember original core before switch to chipc/pmu */
3603 origidx = si_coreidx(sih);
3604 if (AOB_ENAB(sih)) {
3605 pmu = si_setcore(sih, PMU_CORE_ID, 0);
3606 } else {
3607 pmu = si_setcoreidx(sih, SI_CC_IDX);
3608 }
3609 ASSERT(pmu != NULL);
3610
3611 /* Check if the table has PLL control register values for the requested xtal */
3612 if (!update_required && pllctrlreg_update) {
3613 /* Here the chipcommon register base is passed as NULL, so that we just get
3614 * the xf for the xtal being programmed but don't program the registers now
3615 * as the PLL is not yet turned OFF.
3616 */
3617 xf = si_pmu_pllctrlreg_update(sih, osh, NULL, xtal, 0, pllctrlreg_update,
3618 array_size, pllctrlreg_val);
3619
3620 /* Program the PLL based on the xtal value. */
3621 if (xf != 0) {
3622 /* Write XtalFreq. Set the divisor also. */
3623 tmp = R_REG(osh, &pmu->pmucontrol) &
3624 ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
3625 tmp |= (((((xtal + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
3626 PCTL_ILP_DIV_MASK) |
3627 ((xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
3628 W_REG(osh, &pmu->pmucontrol, tmp);
3629 } else {
3630 write_en = FALSE;
3631 if (!FWSIGN_ENAB()) {
3632 printf(rstr_Invalid_Unsupported_xtal_value_D, xtal);
3633 }
3634 }
3635
3636 write_en = si_pmu_armpll_write_required(sih, xtal);
3637 }
3638
3639 /* If its a check sequence or if there is nothing to write, return here */
3640 if ((update_required == FALSE) || (write_en == FALSE)) {
3641 goto exit;
3642 }
3643
3644 /* Update the PLL control register based on the xtal used. */
3645 if (pllctrlreg_val) {
3646 si_pmu_pllctrlreg_update(sih, osh, pmu, xtal, 0, pllctrlreg_update, array_size,
3647 pllctrlreg_val);
3648 }
3649
3650 /* Chip specific changes to PLL Control registers is done here. */
3651 switch (CHIPID(sih->chip)) {
3652 case BCM4388_CHIP_ID: {
3653 uint32 armclk_mhz = si_get_armpllclkfreq(sih);
3654 uint32 vco_freq = (armclk_mhz * PMU4388_APLL_PDIV * 1000);
3655
3656 ASSERT(vco_freq <= FVCO_3200);
3657
3658 /*
3659 * ndiv_init = Fvco / Frefeff
3660 * Frefeff = Fref / pdiv
3661 * Fref = xtal / 2
3662 * pdiv = 3
3663 *
3664 * ndiv_init = ((Fvco * pdiv * 1000000) / ((xtal * 1000) / 2)
3665 */
3666 ndiv_int = (vco_freq / (xtal / 2));
3667 si_pmu_armpll_freq_upd(sih, 0, ndiv_int, 0);
3668 break;
3669 }
3670
3671 case BCM4389_CHIP_ID: {
3672 uint32 armclk_mhz = si_get_armpllclkfreq(sih);
3673 uint32 vco_freq = (armclk_mhz * PMU4389_APLL_PDIV * 1000);
3674
3675 ASSERT(vco_freq <= FVCO_3200);
3676
3677 /*
3678 * ndiv_init = Fvco / Frefeff
3679 * Frefeff = Fref / pdiv
3680 * Fref = xtal / 2
3681 * pdiv = 3
3682 *
3683 * ndiv_init = ((Fvco * pdiv * 1000000) / ((xtal * 1000) / 2)
3684 */
3685 ndiv_int = (vco_freq / (xtal / 2));
3686 si_pmu_armpll_freq_upd(sih, 0, ndiv_int, 0);
3687 break;
3688 }
3689
3690 default:
3691 break;
3692 }
3693
3694 /* Program the PLL based on the xtal value. */
3695 if (xtal != 0) {
3696 /* Find the frequency in the table */
3697 for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt ++)
3698 if (xt->fref == xtal) {
3699 break;
3700 }
3701
3702 /* Check current PLL state, bail out if it has been programmed or
3703 * we don't know how to program it. But we might still have some programming
3704 * like changing the ARM clock, etc. So cannot return from here.
3705 */
3706 if (xt == NULL || xt->fref == 0) {
3707 goto exit;
3708 }
3709
3710 /* If the PLL is already programmed exit from here. */
3711 if (((R_REG(osh, &pmu->pmucontrol) &
3712 PCTL_XTALFREQ_MASK) >> PCTL_XTALFREQ_SHIFT) == xt->xf) {
3713 goto exit;
3714 }
3715
3716 PMU_MSG(("XTAL %d.%d MHz (%d)\n", xtal / 1000, xtal % 1000, xt->xf));
3717 PMU_MSG(("Programming PLL for %d.%d MHz\n", xt->fref / 1000, xt->fref % 1000));
3718
3719 if (BCM4389_CHIP(sih->chip)) {
3720 /* Write ndiv_int to pllcontrol[6] */
3721 tmp = ((xt->ndiv_int << PMU4389_ARMPLL_I_NDIV_INT_SHIFT)
3722 & PMU4389_ARMPLL_I_NDIV_INT_MASK);
3723 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6,
3724 (PMU4389_ARMPLL_I_NDIV_INT_MASK), tmp);
3725 } else if (BCM4388_CHIP(sih->chip)) {
3726 /* Write ndiv_int to pllcontrol[6] */
3727 tmp = ((xt->ndiv_int << PMU4388_ARMPLL_I_NDIV_INT_SHIFT)
3728 & PMU4388_ARMPLL_I_NDIV_INT_MASK);
3729 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG6,
3730 (PMU4388_ARMPLL_I_NDIV_INT_MASK), tmp);
3731 } else if (BCM4369_CHIP(sih->chip) ||
3732 BCM4362_CHIP(sih->chip) ||
3733 FALSE) {
3734 /* Write pdiv (Actually it is mapped to p1div in the struct)
3735 to pllcontrol[2]
3736 */
3737 tmp = ((xt->p1div << PMU4369_PLL0_PC2_PDIV_SHIFT) &
3738 PMU4369_PLL0_PC2_PDIV_MASK);
3739 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2,
3740 (PMU4369_PLL0_PC2_PDIV_MASK), tmp);
3741
3742 /* Write ndiv_int to pllcontrol[2] */
3743 tmp = ((xt->ndiv_int << PMU4369_PLL0_PC2_NDIV_INT_SHIFT)
3744 & PMU4369_PLL0_PC2_NDIV_INT_MASK);
3745 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2,
3746 (PMU4369_PLL0_PC2_NDIV_INT_MASK), tmp);
3747
3748 /* Write ndiv_frac to pllcontrol[3] */
3749 tmp = ((xt->ndiv_frac << PMU4369_PLL0_PC3_NDIV_FRAC_SHIFT) &
3750 PMU4369_PLL0_PC3_NDIV_FRAC_MASK);
3751 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG3,
3752 PMU4369_PLL0_PC3_NDIV_FRAC_MASK, tmp);
3753 } else {
3754 /* Write p1div and p2div to pllcontrol[0] */
3755 tmp = ((xt->p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) &
3756 PMU1_PLL0_PC0_P1DIV_MASK) |
3757 ((xt->p2div << PMU1_PLL0_PC0_P2DIV_SHIFT) &
3758 PMU1_PLL0_PC0_P2DIV_MASK);
3759 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG0,
3760 (PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK), tmp);
3761
3762 /* Write ndiv_int and ndiv_mode to pllcontrol[2] */
3763 tmp = ((xt->ndiv_int << PMU1_PLL0_PC2_NDIV_INT_SHIFT)
3764 & PMU1_PLL0_PC2_NDIV_INT_MASK) |
3765 ((ndiv_mode << PMU1_PLL0_PC2_NDIV_MODE_SHIFT)
3766 & PMU1_PLL0_PC2_NDIV_MODE_MASK);
3767 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2,
3768 (PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK), tmp);
3769 /* Write ndiv_frac to pllcontrol[3] */
3770 tmp = ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
3771 PMU1_PLL0_PC3_NDIV_FRAC_MASK);
3772 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG3,
3773 PMU1_PLL0_PC3_NDIV_FRAC_MASK, tmp);
3774 }
3775
3776 /* Write XtalFreq. Set the divisor also. */
3777 tmp = R_REG(osh, &pmu->pmucontrol) &
3778 ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
3779 tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
3780 PCTL_ILP_DIV_MASK) |
3781 ((xt->xf << PCTL_XTALFREQ_SHIFT) & PCTL_XTALFREQ_MASK);
3782 W_REG(osh, &pmu->pmucontrol, tmp);
3783 }
3784
3785 exit:
3786 /* Return to original core */
3787 si_setcoreidx(sih, origidx);
3788
3789 return write_en;
3790 } /* si_pmu_update_pllcontrol */
3791
3792 /* returns current value of PMUTimer.
3793 also taking care of PR88659 by multiple reads.
3794 */
3795 uint32
BCMPOSTTRAPFN(si_pmu_get_pmutimer)3796 BCMPOSTTRAPFN(si_pmu_get_pmutimer)(si_t *sih)
3797 {
3798 osl_t *osh = si_osh(sih);
3799 pmuregs_t *pmu;
3800 uint origidx;
3801 uint32 start;
3802 BCM_REFERENCE(sih);
3803
3804 origidx = si_coreidx(sih);
3805 if (AOB_ENAB(sih)) {
3806 pmu = si_setcore(sih, PMU_CORE_ID, 0);
3807 } else {
3808 pmu = si_setcoreidx(sih, SI_CC_IDX);
3809 }
3810 ASSERT(pmu != NULL);
3811
3812 start = R_REG(osh, &pmu->pmutimer);
3813 if (start != R_REG(osh, &pmu->pmutimer))
3814 start = R_REG(osh, &pmu->pmutimer);
3815
3816 si_setcoreidx(sih, origidx);
3817
3818 return (start);
3819 }
3820
3821 /* Get current pmu time API */
3822 uint32
si_cur_pmu_time(si_t * sih)3823 si_cur_pmu_time(si_t *sih)
3824 {
3825 uint origidx;
3826 uint32 pmu_time;
3827
3828 /* Remember original core before switch to chipc/pmu */
3829 origidx = si_coreidx(sih);
3830
3831 pmu_time = si_pmu_get_pmutimer(sih);
3832
3833 /* Return to original core */
3834 si_setcoreidx(sih, origidx);
3835 return (pmu_time);
3836 }
3837
3838 /**
3839 * returns
3840 * a) diff between a 'prev' value of pmu timer and current value
3841 * b) the current pmutime value in 'prev'
3842 * So, 'prev' is an IO parameter.
3843 */
3844 uint32
BCMPOSTTRAPFN(si_pmu_get_pmutime_diff)3845 BCMPOSTTRAPFN(si_pmu_get_pmutime_diff)(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 *prev)
3846 {
3847 uint32 pmutime_diff = 0, pmutime_val = 0;
3848 uint32 prev_val = *prev;
3849 BCM_REFERENCE(osh);
3850 BCM_REFERENCE(pmu);
3851 /* read current value */
3852 pmutime_val = si_pmu_get_pmutimer(sih);
3853 /* diff btween prev and current value, take on wraparound case as well. */
3854 pmutime_diff = (pmutime_val >= prev_val) ?
3855 (pmutime_val - prev_val) :
3856 (~prev_val + pmutime_val + 1);
3857 *prev = pmutime_val;
3858 return pmutime_diff;
3859 }
3860
3861 /**
3862 * wait for usec for the res_pending register to change.
3863 * NOTE: usec SHOULD be > 32uS
3864 * if cond = TRUE, res_pending will be read until it becomes == 0;
3865 * If cond = FALSE, res_pending will be read until it becomes != 0;
3866 * returns TRUE if timedout.
3867 * returns elapsed time in this loop in elapsed_time
3868 */
3869 bool
BCMPOSTTRAPFN(si_pmu_wait_for_res_pending)3870 BCMPOSTTRAPFN(si_pmu_wait_for_res_pending)(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint usec,
3871 bool cond, uint32 *elapsed_time)
3872 {
3873 /* add 32uSec more */
3874 uint countdown = usec;
3875 uint32 pmutime_prev = 0, pmutime_elapsed = 0, res_pend;
3876 bool pending = FALSE;
3877
3878 /* store current time */
3879 pmutime_prev = si_pmu_get_pmutimer(sih);
3880 while (1) {
3881 res_pend = R_REG(osh, &pmu->res_pending);
3882
3883 /* based on the condition, check */
3884 if (cond == TRUE) {
3885 if (res_pend == 0) break;
3886 } else {
3887 if (res_pend != 0) break;
3888 }
3889
3890 /* if required time over */
3891 if ((pmutime_elapsed * PMU_US_STEPS) >= countdown) {
3892 /* timeout. so return as still pending */
3893 pending = TRUE;
3894 break;
3895 }
3896
3897 /* get elapsed time after adding diff between prev and current
3898 * pmutimer value
3899 */
3900 pmutime_elapsed += si_pmu_get_pmutime_diff(sih, osh, pmu, &pmutime_prev);
3901 }
3902
3903 *elapsed_time = pmutime_elapsed * PMU_US_STEPS;
3904 return pending;
3905 } /* si_pmu_wait_for_res_pending */
3906
3907 /**
3908 * The algorithm for pending check is that,
3909 * step1: wait till (res_pending !=0) OR pmu_max_trans_timeout.
3910 * if max_trans_timeout, flag error and exit.
3911 * wait for 1 ILP clk [64uS] based on pmu timer,
3912 * polling to see if res_pending again goes high.
3913 * if res_pending again goes high, go back to step1.
3914 * Note: res_pending is checked repeatedly because, in between switching
3915 * of dependent
3916 * resources, res_pending resets to 0 for a short duration of time before
3917 * it becomes 1 again.
3918 * Note: return 0 is GOOD, 1 is BAD [mainly timeout].
3919 */
3920 int
BCMPOSTTRAPFN(si_pmu_wait_for_steady_state)3921 BCMPOSTTRAPFN(si_pmu_wait_for_steady_state)(si_t *sih, osl_t *osh, pmuregs_t *pmu)
3922 {
3923 si_info_t *sii = SI_INFO(sih);
3924 int stat = 0;
3925 bool timedout = FALSE;
3926 uint32 elapsed = 0, pmutime_total_elapsed = 0;
3927 uint32 pmutime_prev;
3928
3929 sii->res_pend_count = 0;
3930
3931 pmutime_prev = si_pmu_get_pmutimer(sih);
3932
3933 while (1) {
3934 /* wait until all resources are settled down [till res_pending becomes 0] */
3935 timedout = si_pmu_wait_for_res_pending(sih, osh, pmu,
3936 PMU_MAX_TRANSITION_DLY, TRUE, &elapsed);
3937
3938 sii->res_state[sii->res_pend_count].low_time =
3939 si_pmu_get_pmutime_diff(sih, osh, pmu, &pmutime_prev);
3940 sii->res_state[sii->res_pend_count].low = R_REG(osh, &pmu->res_pending);
3941
3942 if (timedout) {
3943 stat = 1;
3944 break;
3945 }
3946
3947 pmutime_total_elapsed += elapsed;
3948 /* wait to check if any resource comes back to non-zero indicating
3949 * that it pends again. The res_pending goes 0 for 1 ILP clock before
3950 * getting set for next resource in the sequence , so if res_pending
3951 * is 0 for more than 1 ILP clk it means nothing is pending
3952 * to indicate some pending dependency.
3953 */
3954 pmutime_prev = R_REG(osh, &pmu->pmutimer);
3955 timedout = si_pmu_wait_for_res_pending(sih, osh, pmu,
3956 64, FALSE, &elapsed);
3957
3958 pmutime_total_elapsed += elapsed;
3959
3960 sii->res_state[sii->res_pend_count].high_time =
3961 si_pmu_get_pmutime_diff(sih, osh, pmu, &pmutime_prev);
3962 sii->res_state[sii->res_pend_count].high = R_REG(osh, &pmu->res_pending);
3963
3964 /* Here, we can also check timedout, but we make sure that,
3965 * we read the res_pending again.
3966 */
3967
3968 if (timedout) {
3969 stat = 0;
3970 break;
3971 }
3972
3973 /* Total wait time for all the waits above added should be
3974 * less than PMU_MAX_TRANSITION_DLY
3975 */
3976 if (pmutime_total_elapsed >= PMU_MAX_TRANSITION_DLY) {
3977 /* timeout. so return as still pending */
3978 stat = 1;
3979 break;
3980 }
3981
3982 sii->res_pend_count++;
3983 sii->res_pend_count %= RES_PEND_STATS_COUNT;
3984 pmutime_prev = R_REG(osh, &pmu->pmutimer);
3985 }
3986 return stat;
3987 } /* si_pmu_wait_for_steady_state */
3988
3989 static uint32
si_pmu_pll_delay_43012(si_t * sih,uint32 delay_us,uint32 poll)3990 si_pmu_pll_delay_43012(si_t *sih, uint32 delay_us, uint32 poll)
3991 {
3992 uint32 delay = 0;
3993
3994 /* In case of NIC builds, we can use OSL_DELAY() for 1 us delay. But in case of DONGLE
3995 * builds, we can't rely on the OSL_DELAY() as it is internally relying on HT clock and
3996 * we are calling this function when ALP clock is present.
3997 */
3998 #if defined(DONGLEBUILD)
3999 uint32 initial, current;
4000
4001 initial = get_arm_cyclecount();
4002 while (delay < delay_us) {
4003 if (poll == 1) {
4004 if (si_gci_chipstatus(sih, GCI_CHIPSTATUS_07) &
4005 GCI43012_CHIPSTATUS_07_BBPLL_LOCK_MASK) {
4006 goto exit;
4007 }
4008 }
4009 current = get_arm_cyclecount();
4010 delay = ((current - initial) * 1000) / si_xtalfreq(sih);
4011 }
4012 #else
4013 for (delay = 0; delay < delay_us; delay++) {
4014 if (poll == 1) {
4015 if (si_gci_chipstatus(sih, GCI_CHIPSTATUS_07) &
4016 GCI43012_CHIPSTATUS_07_BBPLL_LOCK_MASK) {
4017 goto exit;
4018 }
4019 }
4020 OSL_DELAY(1);
4021 }
4022 #endif /* BCMDONGLEHOST */
4023
4024 if (poll == 1) {
4025 PMU_ERROR(("si_pmu_pll_delay_43012: PLL not locked!"));
4026 ASSERT(0);
4027 }
4028 exit:
4029 return delay;
4030 }
4031
4032 static void
si_pmu_pll_on_43012(si_t * sih,osl_t * osh,pmuregs_t * pmu,bool openloop_cal)4033 si_pmu_pll_on_43012(si_t *sih, osl_t *osh, pmuregs_t *pmu, bool openloop_cal)
4034 {
4035 uint32 rsrc_ht, total_time = 0;
4036
4037 si_pmu_chipcontrol(sih, PMU_CHIPCTL4, PMUCCTL04_43012_FORCE_BBPLL_PWROFF, 0);
4038 total_time += si_pmu_pll_delay_43012(sih, 2, 0);
4039 si_pmu_chipcontrol(sih, PMU_CHIPCTL4, PMUCCTL04_43012_FORCE_BBPLL_ISOONHIGH |
4040 PMUCCTL04_43012_FORCE_BBPLL_PWRDN, 0);
4041 total_time += si_pmu_pll_delay_43012(sih, 2, 0);
4042 si_pmu_chipcontrol(sih, PMU_CHIPCTL4, PMUCCTL04_43012_FORCE_BBPLL_ARESET, 0);
4043
4044 rsrc_ht = R_REG(osh, &pmu->res_state) &
4045 ((1 << RES43012_HT_AVAIL) | (1 << RES43012_HT_START));
4046
4047 if (rsrc_ht)
4048 {
4049 /* Wait for PLL to lock in close-loop */
4050 total_time += si_pmu_pll_delay_43012(sih, 200, 1);
4051 }
4052 else {
4053 /* Wait for 1 us for the open-loop clock to start */
4054 total_time += si_pmu_pll_delay_43012(sih, 1, 0);
4055 }
4056
4057 if (!openloop_cal) {
4058 /* Allow clk to be used if its not calibration */
4059 si_pmu_chipcontrol(sih, PMU_CHIPCTL4, PMUCCTL04_43012_FORCE_BBPLL_DRESET, 0);
4060 total_time += si_pmu_pll_delay_43012(sih, 1, 0);
4061 si_pmu_chipcontrol(sih, PMU_CHIPCTL4, PMUCCTL04_43012_DISABLE_LQ_AVAIL, 0);
4062 si_pmu_chipcontrol(sih, PMU_CHIPCTL4, PMUCCTL04_43012_DISABLE_HT_AVAIL, 0);
4063 }
4064
4065 PMU_MSG(("si_pmu_pll_on_43012: time taken: %d us\n", total_time));
4066 }
4067
4068 static void
si_pmu_pll_off_43012(si_t * sih,osl_t * osh,pmuregs_t * pmu)4069 si_pmu_pll_off_43012(si_t *sih, osl_t *osh, pmuregs_t *pmu)
4070 {
4071 uint32 total_time = 0;
4072 BCM_REFERENCE(osh);
4073 BCM_REFERENCE(pmu);
4074 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
4075 PMUCCTL04_43012_DISABLE_LQ_AVAIL | PMUCCTL04_43012_DISABLE_HT_AVAIL,
4076 PMUCCTL04_43012_DISABLE_LQ_AVAIL | PMUCCTL04_43012_DISABLE_HT_AVAIL);
4077 total_time += si_pmu_pll_delay_43012(sih, 1, 0);
4078
4079 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
4080 (PMUCCTL04_43012_FORCE_BBPLL_ARESET | PMUCCTL04_43012_FORCE_BBPLL_DRESET |
4081 PMUCCTL04_43012_FORCE_BBPLL_PWRDN |PMUCCTL04_43012_FORCE_BBPLL_ISOONHIGH),
4082 (PMUCCTL04_43012_FORCE_BBPLL_ARESET | PMUCCTL04_43012_FORCE_BBPLL_DRESET |
4083 PMUCCTL04_43012_FORCE_BBPLL_PWRDN |PMUCCTL04_43012_FORCE_BBPLL_ISOONHIGH));
4084 total_time += si_pmu_pll_delay_43012(sih, 1, 0);
4085
4086 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
4087 PMUCCTL04_43012_FORCE_BBPLL_PWROFF,
4088 PMUCCTL04_43012_FORCE_BBPLL_PWROFF);
4089
4090 PMU_MSG(("si_pmu_pll_off_43012: time taken: %d us\n", total_time));
4091 }
4092
4093 /** Turn Off the PLL - Required before setting the PLL registers */
4094 static void
si_pmu_pll_off(si_t * sih,osl_t * osh,pmuregs_t * pmu,uint32 * min_mask,uint32 * max_mask,uint32 * clk_ctl_st)4095 si_pmu_pll_off(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 *min_mask,
4096 uint32 *max_mask, uint32 *clk_ctl_st)
4097 {
4098 uint32 ht_req;
4099
4100 /* Save the original register values */
4101 *min_mask = R_REG(osh, &pmu->min_res_mask);
4102 *max_mask = R_REG(osh, &pmu->max_res_mask);
4103 *clk_ctl_st = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0);
4104
4105 ht_req = si_pmu_htclk_mask(sih);
4106 if (ht_req == 0)
4107 return;
4108
4109 if ((CHIPID(sih->chip) == BCM43012_CHIP_ID) ||
4110 (CHIPID(sih->chip) == BCM43013_CHIP_ID) ||
4111 (CHIPID(sih->chip) == BCM43014_CHIP_ID) ||
4112 (BCM4369_CHIP(sih->chip)) ||
4113 (BCM4362_CHIP(sih->chip)) ||
4114 (BCM4376_CHIP(sih->chip)) ||
4115 (BCM4378_CHIP(sih->chip)) ||
4116 (BCM4385_CHIP(sih->chip)) ||
4117 (BCM4387_CHIP(sih->chip)) ||
4118 (BCM4388_CHIP(sih->chip)) ||
4119 (BCM4389_CHIP(sih->chip)) ||
4120 BCM43602_CHIP(sih->chip) ||
4121 0) {
4122 /*
4123 * If HT_AVAIL is not set, wait to see if any resources are availing HT.
4124 */
4125 if (((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4126 & CCS_HTAVAIL) != CCS_HTAVAIL))
4127 si_pmu_wait_for_steady_state(sih, osh, pmu);
4128 } else {
4129 OR_REG(osh, &pmu->max_res_mask, ht_req);
4130 /* wait for HT to be ready before taking the HT away...HT could be coming up... */
4131 SPINWAIT(((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4132 & CCS_HTAVAIL) != CCS_HTAVAIL), PMU_MAX_TRANSITION_DLY);
4133 ASSERT((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4134 & CCS_HTAVAIL));
4135 }
4136
4137 if ((CHIPID(sih->chip) == BCM43012_CHIP_ID) ||
4138 (CHIPID(sih->chip) == BCM43013_CHIP_ID) ||
4139 (CHIPID(sih->chip) == BCM43014_CHIP_ID)) {
4140 si_pmu_pll_off_43012(sih, osh, pmu);
4141 } else {
4142 AND_REG(osh, &pmu->min_res_mask, ~ht_req);
4143 AND_REG(osh, &pmu->max_res_mask, ~ht_req);
4144
4145 SPINWAIT(((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4146 & CCS_HTAVAIL) == CCS_HTAVAIL), PMU_MAX_TRANSITION_DLY);
4147 ASSERT(!(si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4148 & CCS_HTAVAIL));
4149 OSL_DELAY(100);
4150 }
4151 } /* si_pmu_pll_off */
4152
4153 /* below function are for BBPLL parallel purpose */
4154 /** Turn Off the PLL - Required before setting the PLL registers */
4155 void
si_pmu_pll_off_PARR(si_t * sih,osl_t * osh,uint32 * min_mask,uint32 * max_mask,uint32 * clk_ctl_st)4156 si_pmu_pll_off_PARR(si_t *sih, osl_t *osh, uint32 *min_mask,
4157 uint32 *max_mask, uint32 *clk_ctl_st)
4158 {
4159 pmuregs_t *pmu;
4160 uint origidx;
4161 bcm_int_bitmask_t intr_val;
4162 uint32 ht_req;
4163
4164 /* Block ints and save current core */
4165 si_introff(sih, &intr_val);
4166 origidx = si_coreidx(sih);
4167 if (AOB_ENAB(sih)) {
4168 pmu = si_setcore(sih, PMU_CORE_ID, 0);
4169 } else {
4170 pmu = si_setcoreidx(sih, SI_CC_IDX);
4171 }
4172 ASSERT(pmu != NULL);
4173
4174 /* Save the original register values */
4175 *min_mask = R_REG(osh, &pmu->min_res_mask);
4176 *max_mask = R_REG(osh, &pmu->max_res_mask);
4177 *clk_ctl_st = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0);
4178 ht_req = si_pmu_htclk_mask(sih);
4179 if (ht_req == 0) {
4180 /* Return to original core */
4181 si_setcoreidx(sih, origidx);
4182 si_intrrestore(sih, &intr_val);
4183 return;
4184 }
4185
4186 if ((CHIPID(sih->chip) == BCM43012_CHIP_ID) ||
4187 (CHIPID(sih->chip) == BCM43013_CHIP_ID) ||
4188 (CHIPID(sih->chip) == BCM43014_CHIP_ID) ||
4189 (BCM4369_CHIP(sih->chip)) ||
4190 (BCM4362_CHIP(sih->chip)) ||
4191 (BCM4376_CHIP(sih->chip)) ||
4192 (BCM4378_CHIP(sih->chip)) ||
4193 (BCM4385_CHIP(sih->chip)) ||
4194 (BCM4387_CHIP(sih->chip)) ||
4195 (BCM4388_CHIP(sih->chip)) ||
4196 (BCM4389_CHIP(sih->chip)) ||
4197 (BCM4397_CHIP(sih->chip)) ||
4198 (BCM43602_CHIP(sih->chip)) ||
4199 0) {
4200 /*
4201 * If HT_AVAIL is not set, wait to see if any resources are availing HT.
4202 */
4203 if (((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4204 & CCS_HTAVAIL)
4205 != CCS_HTAVAIL))
4206 si_pmu_wait_for_steady_state(sih, osh, pmu);
4207 } else {
4208 OR_REG(osh, &pmu->max_res_mask, ht_req);
4209 /* wait for HT to be ready before taking the HT away...HT could be coming up... */
4210 SPINWAIT(((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4211 & CCS_HTAVAIL) != CCS_HTAVAIL), PMU_MAX_TRANSITION_DLY);
4212 ASSERT((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4213 & CCS_HTAVAIL));
4214 }
4215
4216 AND_REG(osh, &pmu->min_res_mask, ~ht_req);
4217 AND_REG(osh, &pmu->max_res_mask, ~ht_req);
4218
4219 /* Return to original core */
4220 si_setcoreidx(sih, origidx);
4221 si_intrrestore(sih, &intr_val);
4222 } /* si_pmu_pll_off_PARR */
4223
4224 /** Turn ON/restore the PLL based on the mask received */
4225 static void
si_pmu_pll_on(si_t * sih,osl_t * osh,pmuregs_t * pmu,uint32 min_mask_mask,uint32 max_mask_mask,uint32 clk_ctl_st_mask)4226 si_pmu_pll_on(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 min_mask_mask,
4227 uint32 max_mask_mask, uint32 clk_ctl_st_mask)
4228 {
4229 uint32 ht_req;
4230
4231 ht_req = si_pmu_htclk_mask(sih);
4232 if (ht_req == 0)
4233 return;
4234
4235 max_mask_mask &= ht_req;
4236 min_mask_mask &= ht_req;
4237
4238 if (max_mask_mask != 0)
4239 OR_REG(osh, &pmu->max_res_mask, max_mask_mask);
4240
4241 if (min_mask_mask != 0)
4242 OR_REG(osh, &pmu->min_res_mask, min_mask_mask);
4243
4244 if (clk_ctl_st_mask & CCS_HTAVAIL) {
4245 /* Wait for HT_AVAIL to come back */
4246 SPINWAIT(((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4247 & CCS_HTAVAIL) != CCS_HTAVAIL), PMU_MAX_TRANSITION_DLY);
4248 ASSERT((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4249 & CCS_HTAVAIL));
4250 }
4251
4252 if ((CHIPID(sih->chip) == BCM43012_CHIP_ID) ||
4253 (CHIPID(sih->chip) == BCM43013_CHIP_ID) ||
4254 (CHIPID(sih->chip) == BCM43014_CHIP_ID)) {
4255 si_pmu_pll_on_43012(sih, osh, pmu, 0);
4256 }
4257 }
4258
4259 /**
4260 * Set up PLL registers in the PMU as per the (optional) OTP values, or, if no OTP values are
4261 * present, optionally update with POR override values contained in firmware. Enables the BBPLL
4262 * when done.
4263 */
4264 static void
BCMATTACHFN(si_pmu1_pllinit1)4265 BCMATTACHFN(si_pmu1_pllinit1)(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 xtal)
4266 {
4267 char name[16];
4268 const char *otp_val;
4269 uint8 i, otp_entry_found = FALSE;
4270 uint32 pll_ctrlcnt;
4271 uint32 min_mask = 0, max_mask = 0, clk_ctl_st = 0;
4272 #if defined(BTOVERPCIE) && !defined(BTOVERPCIE_DISABLED)
4273 uint32 otpval = 0, regval = 0;
4274 #endif /* defined(BTOVERPCIE) && !defined(BTOVERPCIE_DISABLED) */
4275
4276 if (!FWSIGN_ENAB()) {
4277 if (PMUREV(sih->pmurev) >= 5) {
4278 pll_ctrlcnt = (sih->pmucaps & PCAP5_PC_MASK) >> PCAP5_PC_SHIFT;
4279 } else {
4280 pll_ctrlcnt = (sih->pmucaps & PCAP_PC_MASK) >> PCAP_PC_SHIFT;
4281 }
4282
4283 /* Check if there is any otp enter for PLLcontrol registers */
4284 for (i = 0; i < pll_ctrlcnt; i++) {
4285 snprintf(name, sizeof(name), rstr_pllD, i);
4286 if ((otp_val = getvar(NULL, name)) == NULL)
4287 continue;
4288
4289 /* If OTP entry is found for PLL register, then turn off the PLL
4290 * and set the status of the OTP entry accordingly.
4291 */
4292 otp_entry_found = TRUE;
4293 break;
4294 }
4295 }
4296
4297 /* If no OTP parameter is found and no chip-specific updates are needed, return. */
4298 if ((otp_entry_found == FALSE) &&
4299 (si_pmu_update_pllcontrol(sih, osh, xtal, FALSE) == FALSE)) {
4300 #if defined(BTOVERPCIE) && !defined(BTOVERPCIE_DISABLED)
4301 /*
4302 * For 4369/4362 PLL3 could be prorammed by BT, check the value is default and not
4303 * overrided by BT
4304 */
4305 if ((BCM4369_CHIP(sih->chip) || BCM4362_CHIP(sih->chip)) &&
4306 (regval = si_pmu_pllcontrol(sih, 3, 0, 0)) != PMU_PLL3_4369B0_DEFAULT) {
4307 PMU_ERROR(("Default PLL3 value 0x%x is not same as programmed"
4308 "value 0x%x\n", PMU_PLL3_4369B0_DEFAULT, regval));
4309 hnd_gcisem_set_err(GCI_PLL_LOCK_SEM);
4310 return;
4311 }
4312
4313 /* Update SW_READY bit indicating WLAN is ready and verified PLL3 */
4314 si_gci_output(sih, GCI_ECI_SW1(GCI_WLAN_IP_ID), GCI_SWREADY, GCI_SWREADY);
4315 #endif /* defined(BTOVERPCIE) && !defined(BTOVERPCIE_DISABLED) */
4316 return;
4317 }
4318
4319 #if defined(BTOVERPCIE) && !defined(BTOVERPCIE_DISABLED)
4320 if ((hnd_gcisem_acquire(GCI_PLL_LOCK_SEM, TRUE, GCI_PLL_LOCK_SEM_TIMEOUT) != BCME_OK)) {
4321 PMU_ERROR(("Failed to get GCI PLL Lock semaphore...\n"));
4322 hnd_gcisem_set_err(GCI_PLL_LOCK_SEM);
4323 return;
4324 }
4325
4326 /* Skip BB PLL programming if BT has already done it, which is indicated by SW_READY bit */
4327 if (si_gci_input(sih, GCI_ECI_SW1(GCI_BT_IP_ID)) & GCI_SWREADY) {
4328 PMU_MSG(("PLL is already programmed\n"));
4329
4330 /* Program ARM PLL only if xtalfreq(pllctrl6) programmed is different from xtal */
4331 if (si_pmu_update_pllcontrol(sih, osh, xtal, FALSE)) {
4332 /* Make sure PLL is off */
4333 si_pmu_pll_off(sih, osh, pmu, &min_mask, &max_mask, &clk_ctl_st);
4334
4335 /* for 4369, arm clk cycle can be set from nvram - default is 400 MHz */
4336 if ((BCM4369_CHIP(sih->chip) || BCM4362_CHIP(sih->chip)) &&
4337 (pll_ctrlcnt > PMU1_PLL0_PLLCTL6)) {
4338 PMU_MSG(("Programming ARM CLK\n"));
4339 si_pmu_pll6val_armclk_calc(osh, pmu,
4340 si_get_armpllclkfreq(sih), xtal, TRUE);
4341 }
4342
4343 /* Flush ('update') the deferred pll control registers writes */
4344 if (PMUREV(sih->pmurev) >= 2)
4345 OR_REG(osh, &pmu->pmucontrol, PCTL_PLL_PLLCTL_UPD);
4346
4347 /* Restore back the register values. This ensures PLL remains on if it
4348 * was originally on and remains off if it was originally off.
4349 */
4350 si_pmu_pll_on(sih, osh, pmu, min_mask, max_mask, clk_ctl_st);
4351 }
4352
4353 snprintf(name, sizeof(name), rstr_pllD, 3);
4354 if ((otp_val = getvar(NULL, name)) != NULL) {
4355 otpval = (uint32)bcm_strtoul(otp_val, NULL, 0);
4356 if ((regval = si_pmu_pllcontrol(sih, 3, 0, 0)) != otpval) {
4357 PMU_ERROR(("PLL3 programming value 0x%x is not same as programmed"
4358 "value 0x%x\n", otpval, regval));
4359 hnd_gcisem_set_err(GCI_PLL_LOCK_SEM);
4360 }
4361 }
4362 goto done;
4363 }
4364 #endif /* defined(BTOVERPCIE) && !defined(BTOVERPCIE_DISABLED) */
4365
4366 /* Make sure PLL is off */
4367 si_pmu_pll_off(sih, osh, pmu, &min_mask, &max_mask, &clk_ctl_st);
4368
4369 /* Update any chip-specific PLL registers. Does not write PLL 'update' bit yet. */
4370 si_pmu_update_pllcontrol(sih, osh, xtal, TRUE);
4371
4372 /* Update the PLL register if there is a OTP entry for PLL registers */
4373 si_pmu_otp_pllcontrol(sih, osh);
4374
4375 /* Flush ('update') the deferred pll control registers writes */
4376 if (PMUREV(sih->pmurev) >= 2)
4377 OR_REG(osh, &pmu->pmucontrol, PCTL_PLL_PLLCTL_UPD);
4378
4379 /* Restore back the register values. This ensures PLL remains on if it
4380 * was originally on and remains off if it was originally off.
4381 */
4382 si_pmu_pll_on(sih, osh, pmu, min_mask, max_mask, clk_ctl_st);
4383
4384 if ((CHIPID(sih->chip) == BCM43012_CHIP_ID) ||
4385 (CHIPID(sih->chip) == BCM43013_CHIP_ID) ||
4386 (CHIPID(sih->chip) == BCM43014_CHIP_ID)) {
4387 uint32 origidx;
4388 /* PMU clock stretch to be decreased to 8 for HT and ALP
4389 * to reduce DS0 current during high traffic
4390 */
4391 W_REG(osh, &pmu->clkstretch, CSTRETCH_REDUCE_8);
4392
4393 /* SDIOD to request for ALP
4394 * to reduce DS0 current during high traffic
4395 */
4396 origidx = si_coreidx(sih);
4397 si_setcore(sih, SDIOD_CORE_ID, 0);
4398 /* Clear the Bit 8 for ALP REQUEST change */
4399 si_wrapperreg(sih, AI_OOBSELOUTB30, (AI_OOBSEL_MASK << AI_OOBSEL_1_SHIFT),
4400 OOB_B_ALP_REQUEST << AI_OOBSEL_1_SHIFT);
4401 si_setcoreidx(sih, origidx);
4402 }
4403
4404 #if defined(BTOVERPCIE) && !defined(BTOVERPCIE_DISABLED)
4405 done:
4406 /* Update SW_READY bit indicating WLAN is done programming PLL registers */
4407 si_gci_output(sih, GCI_ECI_SW1(GCI_WLAN_IP_ID), GCI_SWREADY, GCI_SWREADY);
4408 if ((hnd_gcisem_release(GCI_PLL_LOCK_SEM) != BCME_OK)) {
4409 PMU_ERROR(("Failed to release GCI PLL Lock semaphore...\n"));
4410 hnd_gcisem_set_err(GCI_PLL_LOCK_SEM);
4411 }
4412 #endif /* defined(BTOVERPCIE) && !defined(BTOVERPCIE_DISABLED) */
4413 } /* si_pmu1_pllinit1 */
4414
4415 #if defined(EDV)
4416 /* returns backplane clk programmed in pll cntl 1 */
4417 /* WHY NOT JUST CALL si_pmu_si_clock()? */
si_pmu_get_backplaneclkspeed(si_t * sih)4418 uint32 si_pmu_get_backplaneclkspeed(si_t *sih)
4419 {
4420 uint32 FVCO;
4421 uint32 tmp, mdiv = 1;
4422
4423 switch (CHIPID(sih->chip)) {
4424 case BCM4385_CHIP_GRPID:
4425 case BCM4387_CHIP_GRPID:
4426 case BCM4388_CHIP_GRPID:
4427 case BCM4389_CHIP_GRPID:
4428 case BCM4397_CHIP_GRPID:
4429 return si_pmu_bpclk_4387(sih);
4430 default:
4431 break;
4432 }
4433
4434 FVCO = si_pmu1_pllfvco0(sih);
4435
4436 switch (CHIPID(sih->chip)) {
4437 case BCM4369_CHIP_GRPID:
4438 case BCM4376_CHIP_GRPID:
4439 case BCM4378_CHIP_GRPID:
4440 tmp = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG1, 0, 0);
4441 mdiv = (tmp & PMU1_PLL0_PC1_M4DIV_MASK) >> PMU1_PLL0_PC1_M4DIV_SHIFT;
4442 break;
4443 default:
4444 ASSERT(FALSE);
4445 break;
4446 }
4447 return FVCO / mdiv * 1000u;
4448 }
4449
4450 /* Update backplane clock speed */
4451 void
si_pmu_update_backplane_clock(si_t * sih,osl_t * osh,uint reg,uint32 mask,uint32 val)4452 si_pmu_update_backplane_clock(si_t *sih, osl_t *osh, uint reg, uint32 mask, uint32 val)
4453 {
4454
4455 pmuregs_t *pmu;
4456 uint origidx;
4457 uint32 max_mask = 0, min_mask = 0, clk_ctl_st = 0;
4458
4459 /* Remember original core before switch to chipc/pmu */
4460 origidx = si_coreidx(sih);
4461
4462 if (AOB_ENAB(sih)) {
4463 pmu = si_setcore(sih, PMU_CORE_ID, 0);
4464 } else {
4465 pmu = si_setcoreidx(sih, SI_CC_IDX);
4466 }
4467
4468 ASSERT(pmu != NULL);
4469
4470 /* Make sure PLL is off */
4471 si_pmu_pll_off(sih, osh, pmu, &min_mask, &max_mask, &clk_ctl_st);
4472
4473 si_pmu_pllcontrol(sih, reg, mask, val);
4474
4475 /* Flush ('update') the deferred pll control registers writes */
4476 if (PMUREV(sih->pmurev) >= 2)
4477 OR_REG(osh, &pmu->pmucontrol, PCTL_PLL_PLLCTL_UPD);
4478
4479 /* Restore back the register values. This ensures PLL remains on if it
4480 * was originally on and remains off if it was originally off.
4481 */
4482 si_pmu_pll_on(sih, osh, pmu, min_mask, max_mask, clk_ctl_st);
4483 si_setcoreidx(sih, origidx);
4484 }
4485 #endif /* si_pmu_update_backplane_clock */
4486
4487 /**
4488 * returns the backplane clock frequency.
4489 * Does this by determining current Fvco and the setting of the
4490 * clock divider that leads up to the backplane. Returns value in [Hz] units.
4491 */
4492 static uint32
BCMPOSTTRAPFN(si_pmu_bpclk_4387)4493 BCMPOSTTRAPFN(si_pmu_bpclk_4387)(si_t *sih)
4494 {
4495 uint32 tmp, mdiv;
4496 uint32 FVCO; /* in [khz] units */
4497
4498 FVCO = si_pmu1_pllfvco0(sih);
4499
4500 tmp = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2, 0, 0);
4501 mdiv = (tmp & PMU4387_PLL0_PC2_ICH3_MDIV_MASK);
4502 ASSERT(mdiv != 0);
4503
4504 return FVCO / mdiv * 1000;
4505 }
4506
4507 /**
4508 * returns the CPU clock frequency. Does this by determining current Fvco and the setting of the
4509 * clock divider that leads up to the ARM. Returns value in [Hz] units.
4510 */
4511 static uint32
BCMPOSTTRAPFN(si_pmu1_cpuclk0)4512 BCMPOSTTRAPFN(si_pmu1_cpuclk0)(si_t *sih, osl_t *osh, pmuregs_t *pmu)
4513 {
4514 uint32 tmp, mdiv = 1;
4515 #ifdef BCMDBG
4516 uint32 ndiv_int, ndiv_frac, p2div, p1div, fvco;
4517 uint32 fref;
4518 #endif
4519 #ifdef BCMDBG_PMU
4520 char chn[8];
4521 #endif
4522 uint32 FVCO; /* in [khz] units */
4523
4524 FVCO = si_pmu1_pllfvco0(sih);
4525
4526 if (BCM43602_CHIP(sih->chip) &&
4527 #ifdef DONGLEBUILD
4528 #ifdef __arm__
4529 (si_arm_clockratio(sih, 0) == 1) &&
4530 #endif
4531 #endif /* DONGLEBUILD */
4532 TRUE) {
4533 /* CR4 running on backplane_clk */
4534 return si_pmu_si_clock(sih, osh); /* in [hz] units */
4535 }
4536
4537 switch (CHIPID(sih->chip)) {
4538 case BCM4360_CHIP_ID:
4539 case BCM43460_CHIP_ID:
4540 case BCM43526_CHIP_ID:
4541 case BCM4352_CHIP_ID:
4542 /* Read m6div from pllcontrol[5] */
4543 tmp = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG5, 0, 0);
4544 mdiv = (tmp & PMU1_PLL0_PC2_M6DIV_MASK) >> PMU1_PLL0_PC2_M6DIV_SHIFT;
4545 break;
4546 #ifdef DONGLEBUILD
4547 CASE_BCM43602_CHIP:
4548 #ifdef __arm__
4549 ASSERT(si_arm_clockratio(sih, 0) == 2);
4550 #endif
4551 /* CR4 running on armcr4_clk (Ch5). Read 'bbpll_i_m5div' from pllctl[5] */
4552 tmp = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG5, 0, 0);
4553 mdiv = (tmp & PMU1_PLL0_PC2_M5DIV_MASK) >> PMU1_PLL0_PC2_M5DIV_SHIFT;
4554 break;
4555 case BCM43012_CHIP_ID:
4556 case BCM43013_CHIP_ID:
4557 case BCM43014_CHIP_ID:
4558 /* mdiv is not supported for 43012 and FVCO frequency should be divided by 2 */
4559 mdiv = 2;
4560 break;
4561 #endif /* DONGLEBUILD */
4562
4563 case BCM4369_CHIP_GRPID:
4564 tmp = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG1, 0, 0);
4565 mdiv = (tmp & PMU1_PLL0_PC1_M4DIV_MASK) >> PMU1_PLL0_PC1_M4DIV_SHIFT;
4566 break;
4567 case BCM4362_CHIP_GRPID:
4568 tmp = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG1, 0, 0);
4569 mdiv = (tmp & PMU1_PLL0_PC1_M4DIV_MASK) >> PMU1_PLL0_PC1_M4DIV_SHIFT;
4570 break;
4571
4572 case BCM4376_CHIP_GRPID:
4573 case BCM4378_CHIP_GRPID:
4574 tmp = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG1, 0, 0);
4575 mdiv = (tmp & PMU1_PLL0_PC1_M4DIV_MASK) >> PMU1_PLL0_PC1_M4DIV_SHIFT;
4576 break;
4577
4578 default:
4579 PMU_MSG(("si_pmu1_cpuclk0: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
4580 ASSERT(0);
4581 break;
4582 }
4583
4584 ASSERT(mdiv != 0);
4585
4586 #ifdef BCMDBG
4587 /* Read p2div/p1div from pllcontrol[0] */
4588 tmp = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG0, 0, 0);
4589 p2div = (tmp & PMU1_PLL0_PC0_P2DIV_MASK) >> PMU1_PLL0_PC0_P2DIV_SHIFT;
4590 p1div = (tmp & PMU1_PLL0_PC0_P1DIV_MASK) >> PMU1_PLL0_PC0_P1DIV_SHIFT;
4591
4592 /* Calculate fvco based on xtal freq and ndiv and pdiv */
4593 tmp = PMU1_PLL0_PLLCTL2;
4594
4595 tmp = si_pmu_pllcontrol(sih, tmp, 0, 0);
4596
4597 if (BCM4362_CHIP(sih->chip) ||
4598 BCM4369_CHIP(sih->chip)) {
4599 p2div = 1;
4600 p1div = (tmp & PMU4369_PLL0_PC2_PDIV_MASK) >> PMU4369_PLL0_PC2_PDIV_SHIFT;
4601 ndiv_int = (tmp & PMU4369_PLL0_PC2_NDIV_INT_MASK) >>
4602 PMU4369_PLL0_PC2_NDIV_INT_SHIFT;
4603 } else if (BCM4378_CHIP(sih->chip) || BCM4376_CHIP(sih->chip)) {
4604 p2div = 1;
4605 p1div = (tmp & PMU4378_PLL0_PC2_P1DIV_MASK) >> PMU4378_PLL0_PC2_P1DIV_SHIFT;
4606 ndiv_int = (tmp & PMU4378_PLL0_PC2_NDIV_INT_MASK) >>
4607 PMU4378_PLL0_PC2_NDIV_INT_SHIFT;
4608 } else {
4609 ndiv_int = (tmp & PMU1_PLL0_PC2_NDIV_INT_MASK) >> PMU1_PLL0_PC2_NDIV_INT_SHIFT;
4610 }
4611
4612 ASSERT(p1div != 0);
4613
4614 tmp = PMU1_PLL0_PLLCTL3;
4615
4616 tmp = si_pmu_pllcontrol(sih, tmp, 0, 0);
4617
4618 if (BCM4369_CHIP(sih->chip) || BCM4362_CHIP(sih->chip) ||
4619 BCM4376_CHIP(sih->chip) ||
4620 BCM4378_CHIP(sih->chip) ||
4621 FALSE) {
4622 ndiv_frac =
4623 (tmp & PMU4369_PLL0_PC3_NDIV_FRAC_MASK) >>
4624 PMU4369_PLL0_PC3_NDIV_FRAC_SHIFT;
4625 fref = si_pmu1_alpclk0(sih, osh, pmu) / 1000; /* [KHz] */
4626
4627 fvco = (fref * ndiv_int) << 8;
4628 fvco += (fref * ((ndiv_frac & 0xfffff) >> 4)) >> 8;
4629 fvco >>= 8;
4630 fvco *= p1div;
4631 fvco /= 1000;
4632 fvco *= 1000;
4633 } else {
4634 ndiv_frac =
4635 (tmp & PMU1_PLL0_PC3_NDIV_FRAC_MASK) >> PMU1_PLL0_PC3_NDIV_FRAC_SHIFT;
4636
4637 fref = si_pmu1_alpclk0(sih, osh, pmu) / 1000;
4638
4639 fvco = (fref * ndiv_int) << 8;
4640 fvco += (fref * (ndiv_frac >> 12)) >> 4;
4641 fvco += (fref * (ndiv_frac & 0xfff)) >> 12;
4642 fvco >>= 8;
4643 fvco *= p2div;
4644 fvco /= p1div;
4645 fvco /= 1000;
4646 fvco *= 1000;
4647 }
4648
4649 PMU_MSG(("si_pmu1_cpuclk0: ndiv_int %u ndiv_frac %u p2div %u p1div %u fvco %u\n",
4650 ndiv_int, ndiv_frac, p2div, p1div, fvco));
4651
4652 FVCO = fvco;
4653 #endif /* BCMDBG */
4654
4655 return FVCO / mdiv * 1000; /* Return CPU clock in [Hz] */
4656 } /* si_pmu1_cpuclk0 */
4657
4658 /**
4659 * BCM4369/4378/4387 specific function returning the CPU clock frequency.
4660 * Does this by determining current Fvco and the setting of the clock divider that leads up to
4661 * the ARM.
4662 * Returns value in [Hz] units.
4663 */
4664 static uint32
BCMPOSTTRAPFN(si_pmu1_cpuclk0_pll2)4665 BCMPOSTTRAPFN(si_pmu1_cpuclk0_pll2)(si_t *sih)
4666 {
4667 uint32 FVCO = si_pmu1_pllfvco0_pll2(sih); /* in [khz] units */
4668
4669 /* Return ARM/SB clock */
4670 return FVCO * 1000;
4671 } /* si_pmu1_cpuclk0_pll2 */
4672
4673 /**
4674 * Returns the MAC clock frequency. Called when e.g. MAC clk frequency has to change because of
4675 * interference mitigation.
4676 */
4677 uint32
si_mac_clk(si_t * sih,osl_t * osh)4678 si_mac_clk(si_t *sih, osl_t *osh)
4679 {
4680 uint8 mdiv2 = 0;
4681 uint32 mac_clk = 0;
4682 chipcregs_t *cc;
4683 uint origidx;
4684 bcm_int_bitmask_t intr_val;
4685 #ifdef BCMDBG_PMU
4686 char chn[8];
4687 #endif
4688
4689 uint32 FVCO = si_pmu1_pllfvco0(sih); /* in [khz] units */
4690
4691 BCM_REFERENCE(osh);
4692
4693 /* Remember original core before switch to chipc */
4694 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
4695 ASSERT(cc != NULL);
4696 BCM_REFERENCE(cc);
4697
4698 switch (CHIPID(sih->chip)) {
4699 case BCM43012_CHIP_ID:
4700 case BCM43013_CHIP_ID:
4701 case BCM43014_CHIP_ID:
4702 mdiv2 = 2;
4703 mac_clk = FVCO / mdiv2;
4704 break;
4705 default:
4706 PMU_MSG(("si_mac_clk: Unknown chipid %s\n",
4707 bcm_chipname(CHIPID(sih->chip), chn, 8)));
4708 ASSERT(0);
4709 break;
4710 }
4711
4712 /* Return to original core */
4713 si_restore_core(sih, origidx, &intr_val);
4714
4715 return mac_clk;
4716 } /* si_mac_clk */
4717
4718 /* 4387 pll MAC channel divisor - for ftm */
4719 static uint32
si_pmu_macdiv_4387(si_t * sih)4720 si_pmu_macdiv_4387(si_t *sih)
4721 {
4722 uint32 tmp, mdiv;
4723
4724 /* TODO: when it's needed return different MAC clock freq.
4725 * for different MAC/slice!
4726 */
4727 tmp = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG1, 0, 0);
4728 mdiv = (tmp & PMU4387_PLL0_PC1_ICH2_MDIV_MASK) >> PMU4387_PLL0_PC1_ICH2_MDIV_SHIFT;
4729 ASSERT(mdiv != 0);
4730
4731 return mdiv;
4732 }
4733
4734 /** Get chip's FVCO and PLLCTRL1 register value */
4735 int
si_pmu_fvco_macdiv(si_t * sih,uint32 * fvco,uint32 * div)4736 si_pmu_fvco_macdiv(si_t *sih, uint32 *fvco, uint32 *div)
4737 {
4738 chipcregs_t *cc;
4739 uint origidx;
4740 bcm_int_bitmask_t intr_val;
4741 int err = BCME_OK;
4742 #ifdef BCMDBG_PMU
4743 char chn[8];
4744 #endif
4745
4746 if (fvco)
4747 *fvco = si_pmu1_pllfvco0(sih)/1000;
4748
4749 /* Remember original core before switch to chipc */
4750 cc = (chipcregs_t *)si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
4751 ASSERT(cc != NULL);
4752 BCM_REFERENCE(cc);
4753
4754 switch (CHIPID(sih->chip)) {
4755 case BCM4360_CHIP_ID:
4756 case BCM43460_CHIP_ID:
4757 if (div)
4758 *div = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG12, 0, 0) &
4759 PMU1_PLL0_PC1_M1DIV_MASK;
4760 break;
4761
4762 case BCM43602_CHIP_ID:
4763 if (div) {
4764 *div = (si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG4, 0, 0) &
4765 PMU1_PLL0_PC1_M3DIV_MASK) >> PMU1_PLL0_PC1_M3DIV_SHIFT;
4766 }
4767 break;
4768 case BCM4369_CHIP_GRPID:
4769 case BCM4362_CHIP_GRPID:
4770 if (div) {
4771 *div = (si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, 0, 0)
4772 & PMU1_PLL0_PC1_M4DIV_MASK) >> PMU1_PLL0_PC1_M4DIV_SHIFT;
4773 }
4774 break;
4775 case BCM43012_CHIP_ID:
4776 case BCM43013_CHIP_ID:
4777 case BCM43014_CHIP_ID:
4778 /* mDIV is not supported for 43012 & divisor value is always 2 */
4779 if (div)
4780 *div = 2;
4781 break;
4782 case BCM4376_CHIP_GRPID:
4783 case BCM4378_CHIP_GRPID:
4784 if (div) {
4785 *div = (si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL1, 0, 0)
4786 & PMU1_PLL0_PC1_M4DIV_MASK) >> PMU1_PLL0_PC1_M4DIV_SHIFT;
4787 }
4788 break;
4789 case BCM4385_CHIP_GRPID:
4790 case BCM4387_CHIP_GRPID:
4791 case BCM4389_CHIP_GRPID:
4792 case BCM4388_CHIP_GRPID:
4793 if (div) {
4794 *div = si_pmu_macdiv_4387(sih);
4795 }
4796 break;
4797 default:
4798 PMU_MSG(("si_mac_clk: Unknown chipid %s\n", bcm_chipname(sih->chip, chn, 8)));
4799 err = BCME_ERROR;
4800 }
4801
4802 /* Return to original core */
4803 si_restore_core(sih, origidx, &intr_val);
4804
4805 return err;
4806 }
4807
4808 /** Return TRUE if scan retention memory's sleep/pm signal was asserted */
4809 bool
BCMPOSTTRAPFN(si_pmu_reset_ret_sleep_log)4810 BCMPOSTTRAPFN(si_pmu_reset_ret_sleep_log)(si_t *sih, osl_t *osh)
4811 {
4812 pmuregs_t *pmu;
4813 uint origidx;
4814 uint32 ret_ctl;
4815 bool was_sleep = FALSE;
4816
4817 /* Remember original core before switch to chipc */
4818 origidx = si_coreidx(sih);
4819 if (AOB_ENAB(sih)) {
4820 pmu = si_setcore(sih, PMU_CORE_ID, 0);
4821 } else {
4822 pmu = si_setcoreidx(sih, SI_CC_IDX);
4823 }
4824 ASSERT(pmu != NULL);
4825
4826 ret_ctl = R_REG(osh, &pmu->retention_ctl);
4827 if (ret_ctl & RCTL_MEM_RET_SLEEP_LOG_MASK) {
4828 W_REG(osh, &pmu->retention_ctl, ret_ctl);
4829 was_sleep = TRUE;
4830 }
4831
4832 /* Return to original core */
4833 si_setcoreidx(sih, origidx);
4834
4835 return was_sleep;
4836 }
4837
4838 /** Return TRUE if pmu rsrc XTAL_PU was de-asserted */
4839 bool
BCMPOSTTRAPFN(si_pmu_reset_chip_sleep_log)4840 BCMPOSTTRAPFN(si_pmu_reset_chip_sleep_log)(si_t *sih, osl_t *osh)
4841 {
4842 pmuregs_t *pmu;
4843 uint origidx;
4844 bool was_sleep = FALSE;
4845
4846 /* Remember original core before switch to chipc */
4847 origidx = si_coreidx(sih);
4848 if (AOB_ENAB(sih)) {
4849 pmu = si_setcore(sih, PMU_CORE_ID, 0);
4850 } else {
4851 pmu = si_setcoreidx(sih, SI_CC_IDX);
4852 }
4853 ASSERT(pmu != NULL);
4854
4855 if (PMUREV(sih->pmurev) >= 36) {
4856 uint32 pmu_int_sts = R_REG(osh, &pmu->pmuintstatus);
4857 if (pmu_int_sts & PMU_INT_STAT_RSRC_EVENT_INT0_MASK) {
4858 /* write 1 to clear the status */
4859 W_REG(osh, &pmu->pmuintstatus, PMU_INT_STAT_RSRC_EVENT_INT0_MASK);
4860 was_sleep = TRUE;
4861 }
4862 } else {
4863 was_sleep = si_pmu_reset_ret_sleep_log(sih, osh);
4864 }
4865
4866 /* Return to original core */
4867 si_setcoreidx(sih, origidx);
4868
4869 return was_sleep;
4870 }
4871
4872 /* For 43602a0 MCH2/MCH5 boards: power up PA Reference LDO */
4873 void
si_pmu_switch_on_PARLDO(si_t * sih,osl_t * osh)4874 si_pmu_switch_on_PARLDO(si_t *sih, osl_t *osh)
4875 {
4876 uint32 mask;
4877 pmuregs_t *pmu;
4878 uint origidx;
4879
4880 /* Remember original core before switch to chipc/pmu */
4881 origidx = si_coreidx(sih);
4882 if (AOB_ENAB(sih)) {
4883 pmu = si_setcore(sih, PMU_CORE_ID, 0);
4884 } else {
4885 pmu = si_setcoreidx(sih, SI_CC_IDX);
4886 }
4887 ASSERT(pmu != NULL);
4888
4889 switch (CHIPID(sih->chip)) {
4890 CASE_BCM43602_CHIP:
4891 mask = R_REG(osh, &pmu->min_res_mask) | PMURES_BIT(RES43602_PARLDO_PU);
4892 W_REG(osh, &pmu->min_res_mask, mask);
4893 mask = R_REG(osh, &pmu->max_res_mask) | PMURES_BIT(RES43602_PARLDO_PU);
4894 W_REG(osh, &pmu->max_res_mask, mask);
4895 break;
4896 default:
4897 break;
4898 }
4899 /* Return to original core */
4900 si_setcoreidx(sih, origidx);
4901 }
4902
4903 /* For 43602a0 MCH2/MCH5 boards: power off PA Reference LDO */
4904 void
si_pmu_switch_off_PARLDO(si_t * sih,osl_t * osh)4905 si_pmu_switch_off_PARLDO(si_t *sih, osl_t *osh)
4906 {
4907 uint32 mask;
4908 pmuregs_t *pmu;
4909 uint origidx;
4910
4911 /* Remember original core before switch to chipc/pmu */
4912 origidx = si_coreidx(sih);
4913 if (AOB_ENAB(sih)) {
4914 pmu = si_setcore(sih, PMU_CORE_ID, 0);
4915 } else {
4916 pmu = si_setcoreidx(sih, SI_CC_IDX);
4917 }
4918 ASSERT(pmu != NULL);
4919
4920 switch (CHIPID(sih->chip)) {
4921 case BCM43602_CHIP_ID:
4922 case BCM43462_CHIP_ID:
4923 mask = R_REG(osh, &pmu->min_res_mask) & ~PMURES_BIT(RES43602_PARLDO_PU);
4924 W_REG(osh, &pmu->min_res_mask, mask);
4925 mask = R_REG(osh, &pmu->max_res_mask) & ~PMURES_BIT(RES43602_PARLDO_PU);
4926 W_REG(osh, &pmu->max_res_mask, mask);
4927 break;
4928 default:
4929 break;
4930 }
4931 /* Return to original core */
4932 si_setcoreidx(sih, origidx);
4933 }
4934
4935 /**
4936 * Change VCO frequency (slightly), e.g. to avoid PHY errors due to spurs.
4937 */
4938 static void
BCMATTACHFN(si_set_bb_vcofreq_frac)4939 BCMATTACHFN(si_set_bb_vcofreq_frac)(si_t *sih, osl_t *osh, int vcofreq, int frac, int xtalfreq)
4940 {
4941 uint32 vcofreq_withfrac, p1div, ndiv_int, fraca, ndiv_mode, reg;
4942 /* shifts / masks for PMU PLL control register #2 : */
4943 uint32 ndiv_int_shift, ndiv_mode_shift, p1div_shift, pllctrl2_mask;
4944 /* shifts / masks for PMU PLL control register #3 : */
4945 uint32 pllctrl3_mask;
4946 BCM_REFERENCE(osh);
4947
4948 if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
4949 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
4950 (CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
4951 (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
4952 BCM43602_CHIP(sih->chip)) {
4953 if (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
4954 & CCS_HTAVAIL) {
4955 PMU_MSG(("HTAVAIL is set, so not updating BBPLL Frequency \n"));
4956 return;
4957 }
4958
4959 ndiv_int_shift = 7;
4960 ndiv_mode_shift = 4;
4961 p1div_shift = 0;
4962 pllctrl2_mask = 0xffffffff;
4963 pllctrl3_mask = 0xffffffff;
4964 } else {
4965 /* put more chips here */
4966 PMU_ERROR(("si_set_bb_vcofreq_frac: only work on 4360, 4352\n"));
4967 return;
4968 }
4969
4970 vcofreq_withfrac = vcofreq * 10000 + frac;
4971 p1div = 0x1;
4972 ndiv_int = vcofreq / xtalfreq;
4973 ndiv_mode = (vcofreq_withfrac % (xtalfreq * 10000)) ? 3 : 0;
4974 PMU_ERROR(("ChangeVCO => vco:%d, xtalF:%d, frac: %d, ndivMode: %d, ndivint: %d\n",
4975 vcofreq, xtalfreq, frac, ndiv_mode, ndiv_int));
4976
4977 reg = (ndiv_int << ndiv_int_shift) |
4978 (ndiv_mode << ndiv_mode_shift) |
4979 (p1div << p1div_shift);
4980 PMU_ERROR(("Data written into the PLL_CNTRL_ADDR2: %08x\n", reg));
4981 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2, pllctrl2_mask, reg);
4982
4983 if (ndiv_mode) {
4984 /* frac = (vcofreq_withfrac % (xtalfreq * 10000)) * 2^24) / (xtalfreq * 10000) */
4985 uint32 r1, r0;
4986 math_uint64_multiple_add(
4987 &r1, &r0, vcofreq_withfrac % (xtalfreq * 10000), 1 << 24, 0);
4988 math_uint64_divide(&fraca, r1, r0, xtalfreq * 10000);
4989 PMU_ERROR(("Data written into the PLL_CNTRL_ADDR3 (Fractional): %08x\n", fraca));
4990 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG3, pllctrl3_mask, fraca);
4991 }
4992
4993 si_pmu_pllupd(sih);
4994 } /* si_set_bb_vcofreq_frac */
4995
4996 /**
4997 * given x-tal frequency, returns BaseBand vcofreq with fraction in 100Hz
4998 * @param xtalfreq In [Mhz] units.
4999 * @return In [100Hz] units.
5000 */
5001 uint32
si_pmu_get_bb_vcofreq(si_t * sih,osl_t * osh,int xtalfreq)5002 si_pmu_get_bb_vcofreq(si_t *sih, osl_t *osh, int xtalfreq)
5003 {
5004 uint32 ndiv_int, /* 9 bits integer divider */
5005 ndiv_mode,
5006 frac = 0, /* 24 bits fractional divider */
5007 p1div; /* predivider: divides x-tal freq */
5008 uint32 xtal1, vcofrac = 0, vcofreq;
5009 uint32 r1, r0, reg;
5010
5011 BCM_REFERENCE(osh);
5012
5013 if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
5014 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
5015 (CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
5016 (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
5017 BCM43602_CHIP(sih->chip)) {
5018 reg = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2, 0, 0);
5019 ndiv_int = reg >> 7;
5020 ndiv_mode = (reg >> 4) & 7;
5021 p1div = 1; /* do not divide x-tal frequency */
5022
5023 if (ndiv_mode)
5024 frac = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG3, 0, 0);
5025 } else if ((BCM4369_CHIP(sih->chip) &&
5026 CST4369_CHIPMODE_PCIE(sih->chipst)) ||
5027 BCM4376_CHIP(sih->chip) ||
5028 BCM4378_CHIP(sih->chip) ||
5029 (BCM4362_CHIP(sih->chip) &&
5030 CST4362_CHIPMODE_PCIE(sih->chipst))) {
5031 reg = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG2, 0, 0);
5032 ndiv_int = reg >> 20;
5033 p1div = (reg >> 16) & 0xf;
5034 frac = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG3, 0, 0) & 0x00fffff;
5035 ndiv_mode = 1;
5036 } else {
5037 /* put more chips here */
5038 PMU_ERROR(("si_pmu_get_bb_vcofreq: only work on 4360, 4352, 4369, 4378\n"));
5039 ASSERT(FALSE);
5040 return 0;
5041 }
5042
5043 xtal1 = 10000 * xtalfreq / p1div; /* in [100Hz] units */
5044
5045 if (ndiv_mode) {
5046 /* vcofreq fraction = (xtal1 * frac + (1 << 23)) / (1 << 24);
5047 * handle overflow
5048 */
5049 math_uint64_multiple_add(&r1, &r0, xtal1, frac, 1 << 23);
5050 vcofrac = (r1 << 8) | (r0 >> 24);
5051 }
5052
5053 if (ndiv_int == 0) {
5054 ASSERT(0);
5055 return 0;
5056 }
5057
5058 if ((int)xtal1 > (int)((0xffffffff - vcofrac) / ndiv_int)) {
5059 PMU_ERROR(("si_pmu_get_bb_vcofreq: xtalfreq is too big, %d\n", xtalfreq));
5060 return 0;
5061 }
5062
5063 vcofreq = xtal1 * ndiv_int + vcofrac;
5064 return vcofreq;
5065 } /* si_pmu_get_bb_vcofreq */
5066
5067 /** Enable PMU 1Mhz clock */
5068 static void
si_pmu_enb_slow_clk(si_t * sih,osl_t * osh,uint32 xtalfreq)5069 si_pmu_enb_slow_clk(si_t *sih, osl_t *osh, uint32 xtalfreq)
5070 {
5071 uint32 val;
5072 pmuregs_t *pmu;
5073 uint origidx;
5074
5075 if (PMUREV(sih->pmurev) < 24) {
5076 PMU_ERROR(("si_pmu_enb_slow_clk: Not supported %d\n", PMUREV(sih->pmurev)));
5077 return;
5078 }
5079
5080 /* Remember original core before switch to chipc/pmu */
5081 origidx = si_coreidx(sih);
5082 if (AOB_ENAB(sih)) {
5083 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5084 } else {
5085 pmu = si_setcoreidx(sih, SI_CC_IDX);
5086 }
5087 ASSERT(pmu != NULL);
5088
5089 /* twiki PmuRev30, OneMhzToggleEn:31, AlpPeriod[23:0] */
5090 if (PMUREV(sih->pmurev) >= 38) {
5091 /* Use AlpPeriod[23:0] only chip default value for PmuRev >= 38 chips
5092 * eg. ROUND(POWER(2,26) / (55.970 / 2 MHz) for 4387/4385, etc
5093 */
5094 val = R_REG(osh, &pmu->slowclkperiod) | PMU30_ALPCLK_ONEMHZ_ENAB;
5095 } else {
5096 if (PMUREV(sih->pmurev) >= 30) {
5097 /* AlpPeriod = ROUND(POWER(2,26)/ALP_CLK_FREQ_IN_MHz,0) */
5098 /* Calculation will be accurate for only one decimal of xtal (like 37.4),
5099 * and will not be accurate for more than one decimal
5100 * of xtal freq (like 37.43)
5101 * Also no rounding is done on final result
5102 */
5103 ROMMABLE_ASSERT((xtalfreq/100)*100 == xtalfreq);
5104 val = (((1 << 26)*10)/(xtalfreq/100));
5105 /* set the 32 bit to enable OneMhzToggle
5106 * -usec wide toggle signal will be generated
5107 */
5108 val |= PMU30_ALPCLK_ONEMHZ_ENAB;
5109 } else { /* twiki PmuRev24, OneMhzToggleEn:16, AlpPeriod[15:0] */
5110 if (xtalfreq == 37400) {
5111 val = 0x101B6;
5112 } else if (xtalfreq == 40000) {
5113 val = 0x10199;
5114 } else {
5115 PMU_ERROR(("si_pmu_enb_slow_clk: xtalfreq is not supported, %d\n",
5116 xtalfreq));
5117 /* Return to original core */
5118 si_setcoreidx(sih, origidx);
5119 return;
5120 }
5121 }
5122 }
5123
5124 W_REG(osh, &pmu->slowclkperiod, val);
5125
5126 /* Return to original core */
5127 si_setcoreidx(sih, origidx);
5128 }
5129
5130 /**
5131 * Initializes PLL given an x-tal frequency.
5132 * Calls si_pmuX_pllinitY() type of functions, where the reasoning behind 'X' and 'Y' is historical
5133 * rather than logical.
5134 *
5135 * xtalfreq : x-tal frequency in [KHz]
5136 */
5137 void
BCMATTACHFN(si_pmu_pll_init)5138 BCMATTACHFN(si_pmu_pll_init)(si_t *sih, osl_t *osh, uint xtalfreq)
5139 {
5140 pmuregs_t *pmu;
5141 uint origidx;
5142 #ifdef BCMDBG_PMU
5143 char chn[8];
5144 #endif
5145 BCM_REFERENCE(pmu1_xtaltab0_880);
5146 BCM_REFERENCE(pmu1_xtaltab0_1760);
5147
5148 ASSERT(sih->cccaps & CC_CAP_PMU);
5149
5150 /* Remember original core before switch to chipc/pmu */
5151 origidx = si_coreidx(sih);
5152 if (AOB_ENAB(sih)) {
5153 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5154 } else {
5155 pmu = si_setcoreidx(sih, SI_CC_IDX);
5156 }
5157 ASSERT(pmu != NULL);
5158
5159 switch (CHIPID(sih->chip)) {
5160 case BCM4360_CHIP_ID:
5161 case BCM43460_CHIP_ID:
5162 case BCM4352_CHIP_ID: {
5163 if (CHIPREV(sih->chiprev) > 2)
5164 si_set_bb_vcofreq_frac(sih, osh, 960, 98, 40);
5165 break;
5166 }
5167 CASE_BCM43602_CHIP:
5168 si_set_bb_vcofreq_frac(sih, osh, 960, 98, 40);
5169 break;
5170 case BCM43012_CHIP_ID:
5171 case BCM43013_CHIP_ID:
5172 case BCM43014_CHIP_ID:
5173 case BCM4369_CHIP_GRPID:
5174 case BCM4362_CHIP_GRPID:
5175 case BCM4376_CHIP_GRPID:
5176 case BCM4378_CHIP_GRPID:
5177 case BCM4385_CHIP_GRPID:
5178 case BCM4387_CHIP_GRPID:
5179 case BCM4388_CHIP_GRPID:
5180 case BCM4389_CHIP_GRPID:
5181 si_pmu1_pllinit1(sih, osh, pmu, xtalfreq); /* nvram PLL overrides + enables PLL */
5182 break;
5183 default:
5184 PMU_MSG(("No PLL init done for chip %s rev %d pmurev %d\n",
5185 bcm_chipname(
5186 CHIPID(sih->chip), chn, 8), CHIPREV(sih->chiprev), PMUREV(sih->pmurev)));
5187 break;
5188 }
5189
5190 #ifdef BCMDBG_FORCEHT
5191 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), CCS_FORCEHT, CCS_FORCEHT)
5192 #endif
5193
5194 si_pmu_enb_slow_clk(sih, osh, xtalfreq);
5195
5196 /* Return to original core */
5197 si_setcoreidx(sih, origidx);
5198 } /* si_pmu_pll_init */
5199
5200 /** get alp clock frequency in [Hz] units */
5201 uint32
BCMPOSTTRAPFN(si_pmu_alp_clock)5202 BCMPOSTTRAPFN(si_pmu_alp_clock)(si_t *sih, osl_t *osh)
5203 {
5204 pmuregs_t *pmu;
5205 uint origidx;
5206 uint32 clock = ALP_CLOCK;
5207 #ifdef BCMDBG_PMU
5208 char chn[8];
5209 #endif
5210
5211 ASSERT(sih->cccaps & CC_CAP_PMU);
5212
5213 /* Remember original core before switch to chipc/pmu */
5214 origidx = si_coreidx(sih);
5215 if (AOB_ENAB(sih)) {
5216 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5217 } else {
5218 pmu = si_setcoreidx(sih, SI_CC_IDX);
5219 }
5220 ASSERT(pmu != NULL);
5221
5222 switch (CHIPID(sih->chip)) {
5223 case BCM4360_CHIP_ID:
5224 case BCM43460_CHIP_ID:
5225 case BCM4352_CHIP_ID:
5226 case BCM43526_CHIP_ID:
5227 if (sih->chipst & CST4360_XTAL_40MZ)
5228 clock = 40000 * 1000;
5229 else
5230 clock = 20000 * 1000;
5231 break;
5232
5233 CASE_BCM43602_CHIP:
5234 /* always 40Mhz */
5235 clock = 40000 * 1000;
5236 break;
5237 case BCM43012_CHIP_ID:
5238 case BCM43013_CHIP_ID:
5239 case BCM43014_CHIP_ID:
5240 #ifndef BCMSDIOLITE
5241 case BCM4369_CHIP_GRPID:
5242 #endif /* BCMSDIOLITE */
5243 case BCM4362_CHIP_GRPID:
5244 case BCM4376_CHIP_GRPID:
5245 case BCM4378_CHIP_GRPID:
5246 case BCM4385_CHIP_GRPID:
5247 case BCM4387_CHIP_GRPID:
5248 case BCM4388_CHIP_GRPID:
5249 case BCM4389_CHIP_GRPID:
5250 case BCM4397_CHIP_GRPID:
5251 clock = si_pmu1_alpclk0(sih, osh, pmu);
5252 break;
5253 #ifdef BCMSDIOLITE
5254 case BCM4369_CHIP_ID:
5255 /* always 25Mhz */
5256 clock = 25000 * 1000;
5257 break;
5258 #endif /* BCMSDIOLITE */
5259 default:
5260 PMU_MSG(("No ALP clock specified "
5261 "for chip %s rev %d pmurev %d, using default %d Hz\n",
5262 bcm_chipname(
5263 CHIPID(sih->chip), chn, 8), CHIPREV(sih->chiprev),
5264 PMUREV(sih->pmurev), clock));
5265 break;
5266 }
5267
5268 /* Return to original core */
5269 si_setcoreidx(sih, origidx);
5270
5271 return clock; /* in [Hz] units */
5272 } /* si_pmu_alp_clock */
5273
5274 /**
5275 * Find the output of the "m" pll divider given pll controls that start with
5276 * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
5277 */
5278 static uint32
BCMPOSTTRAPFN(si_pmu5_clock)5279 BCMPOSTTRAPFN(si_pmu5_clock)(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint pll0, uint m)
5280 {
5281 uint32 tmp, div, ndiv, p1, p2, fc;
5282
5283 if ((pll0 & 3) || (pll0 > PMU4716_MAINPLL_PLL0)) {
5284 PMU_ERROR(("si_pmu5_clock: Bad pll0: %d\n", pll0));
5285 return 0;
5286 }
5287
5288 /* Strictly there is an m5 divider, but I'm not sure we use it */
5289 if ((m == 0) || (m > 4)) {
5290 PMU_ERROR(("si_pmu5_clock: Bad m divider: %d\n", m));
5291 return 0;
5292 }
5293
5294 W_REG(osh, &pmu->pllcontrol_addr, pll0 + PMU5_PLL_P1P2_OFF);
5295 (void)R_REG(osh, &pmu->pllcontrol_addr);
5296 tmp = R_REG(osh, &pmu->pllcontrol_data);
5297 p1 = (tmp & PMU5_PLL_P1_MASK) >> PMU5_PLL_P1_SHIFT;
5298 p2 = (tmp & PMU5_PLL_P2_MASK) >> PMU5_PLL_P2_SHIFT;
5299
5300 W_REG(osh, &pmu->pllcontrol_addr, pll0 + PMU5_PLL_M14_OFF);
5301 (void)R_REG(osh, &pmu->pllcontrol_addr);
5302 tmp = R_REG(osh, &pmu->pllcontrol_data);
5303 div = (tmp >> ((m - 1) * PMU5_PLL_MDIV_WIDTH)) & PMU5_PLL_MDIV_MASK;
5304
5305 W_REG(osh, &pmu->pllcontrol_addr, pll0 + PMU5_PLL_NM5_OFF);
5306 (void)R_REG(osh, &pmu->pllcontrol_addr);
5307 tmp = R_REG(osh, &pmu->pllcontrol_data);
5308 ndiv = (tmp & PMU5_PLL_NDIV_MASK) >> PMU5_PLL_NDIV_SHIFT;
5309
5310 /* Do calculation in Mhz */
5311 fc = si_pmu_alp_clock(sih, osh) / 1000000;
5312 fc = (p1 * ndiv * fc) / p2;
5313
5314 PMU_NONE(("si_pmu5_clock: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, clock=%d\n",
5315 p1, p2, ndiv, ndiv, m, div, fc, fc / div));
5316
5317 /* Return clock in Hertz */
5318 return ((fc / div) * 1000000);
5319 } /* si_pmu5_clock */
5320
5321 /**
5322 * Get backplane clock frequency, returns a value in [hz] units.
5323 * For designs that feed the same clock to both backplane and CPU just return the CPU clock speed.
5324 */
5325 uint32
BCMPOSTTRAPFN(si_pmu_si_clock)5326 BCMPOSTTRAPFN(si_pmu_si_clock)(si_t *sih, osl_t *osh)
5327 {
5328 pmuregs_t *pmu;
5329 uint origidx;
5330 uint32 clock = HT_CLOCK; /* in [hz] units */
5331 #ifdef BCMDBG_PMU
5332 char chn[8];
5333 #endif
5334
5335 ASSERT(sih->cccaps & CC_CAP_PMU);
5336
5337 /* Remember original core before switch to chipc/pmu */
5338 origidx = si_coreidx(sih);
5339 if (AOB_ENAB(sih)) {
5340 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5341 } else {
5342 pmu = si_setcoreidx(sih, SI_CC_IDX);
5343 }
5344 ASSERT(pmu != NULL);
5345
5346 switch (CHIPID(sih->chip)) {
5347 case BCM4360_CHIP_ID:
5348 case BCM43460_CHIP_ID:
5349 case BCM43526_CHIP_ID:
5350 case BCM4352_CHIP_ID:
5351 case BCM43012_CHIP_ID:
5352 case BCM43013_CHIP_ID:
5353 case BCM43014_CHIP_ID:
5354 clock = si_pmu1_cpuclk0(sih, osh, pmu);
5355 break;
5356
5357 CASE_BCM43602_CHIP: {
5358 uint32 mdiv;
5359 /* Ch3 is connected to backplane_clk. Read 'bbpll_i_m3div' from pllctl[4] */
5360 mdiv = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG4, 0, 0);
5361 mdiv = (mdiv & PMU1_PLL0_PC1_M3DIV_MASK) >> PMU1_PLL0_PC1_M3DIV_SHIFT;
5362 ASSERT(mdiv != 0);
5363 clock = si_pmu1_pllfvco0(sih) / mdiv * 1000;
5364 break;
5365 }
5366
5367 case BCM4369_CHIP_GRPID:
5368 case BCM4362_CHIP_GRPID:
5369 case BCM4376_CHIP_GRPID:
5370 case BCM4378_CHIP_GRPID:
5371 clock = si_pmu1_cpuclk0(sih, osh, pmu);
5372 break;
5373
5374 case BCM4385_CHIP_GRPID:
5375 case BCM4387_CHIP_GRPID:
5376 case BCM4388_CHIP_GRPID:
5377 case BCM4389_CHIP_GRPID:
5378 case BCM4397_CHIP_GRPID:
5379 clock = si_pmu_bpclk_4387(sih);
5380 break;
5381
5382 default:
5383 PMU_MSG(("No backplane clock specified "
5384 "for chip %s rev %d pmurev %d, using default %d Hz\n",
5385 bcm_chipname(
5386 CHIPID(sih->chip), chn, 8), CHIPREV(sih->chiprev),
5387 PMUREV(sih->pmurev), clock));
5388 break;
5389 }
5390
5391 /* Return to original core */
5392 si_setcoreidx(sih, origidx);
5393
5394 return clock;
5395 } /* si_pmu_si_clock */
5396
5397 /** returns CPU clock frequency in [hz] units */
5398 uint32
BCMPOSTTRAPFN(si_pmu_cpu_clock)5399 BCMPOSTTRAPFN(si_pmu_cpu_clock)(si_t *sih, osl_t *osh)
5400 {
5401 pmuregs_t *pmu;
5402 uint origidx;
5403 uint32 clock; /* in [hz] units */
5404
5405 uint32 tmp;
5406 uint32 armclk_offcnt, armclk_oncnt;
5407
5408 ASSERT(sih->cccaps & CC_CAP_PMU);
5409
5410 /* Remember original core before switch to chipc/pmu */
5411 origidx = si_coreidx(sih);
5412 if (AOB_ENAB(sih)) {
5413 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5414 } else {
5415 pmu = si_setcoreidx(sih, SI_CC_IDX);
5416 }
5417 ASSERT(pmu != NULL);
5418
5419 if (BCM4369_CHIP(sih->chip) ||
5420 BCM4376_CHIP(sih->chip) ||
5421 BCM4378_CHIP(sih->chip) ||
5422 BCM4385_CHIP(sih->chip) ||
5423 BCM4387_CHIP(sih->chip) ||
5424 BCM4388_CHIP(sih->chip) ||
5425 BCM4389_CHIP(sih->chip) ||
5426 BCM4397_CHIP(sih->chip) ||
5427 BCM4362_CHIP(sih->chip)) {
5428 clock = si_pmu1_cpuclk0_pll2(sih); /* for chips with separate CPU PLL */
5429 } else if ((PMUREV(sih->pmurev) >= 5) &&
5430 !((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
5431 (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
5432 (CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
5433 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
5434 (CHIPID(sih->chip) == BCM43012_CHIP_ID) ||
5435 (CHIPID(sih->chip) == BCM43013_CHIP_ID) ||
5436 (CHIPID(sih->chip) == BCM43014_CHIP_ID) ||
5437 0)) {
5438 uint pll = PMU4716_MAINPLL_PLL0;
5439
5440 if (BCM43602_CHIP(sih->chip)) {
5441 clock = si_pmu1_cpuclk0(sih, osh, pmu);
5442 } else {
5443 clock = si_pmu5_clock(sih, osh, pmu, pll, PMU5_MAINPLL_CPU);
5444 }
5445 } else {
5446 clock = si_pmu_si_clock(sih, osh);
5447 }
5448
5449 if ((CHIPID(sih->chip) == BCM43012_CHIP_ID) ||
5450 (CHIPID(sih->chip) == BCM43013_CHIP_ID) ||
5451 (CHIPID(sih->chip) == BCM43014_CHIP_ID)) {
5452 /* Fout = (on_count + 1) * Fin/(on_count + 1 + off_count)
5453 * ARM clock using Fast divider calculation
5454 * Fin = FVCO/2
5455 */
5456 tmp = si_pmu_chipcontrol(sih, PMU1_PLL0_CHIPCTL1, 0, 0);
5457 armclk_offcnt =
5458 (tmp & CCTL_43012_ARM_OFFCOUNT_MASK) >> CCTL_43012_ARM_OFFCOUNT_SHIFT;
5459 armclk_oncnt =
5460 (tmp & CCTL_43012_ARM_ONCOUNT_MASK) >> CCTL_43012_ARM_ONCOUNT_SHIFT;
5461 clock = (armclk_oncnt + 1) * clock/(armclk_oncnt + 1 + armclk_offcnt);
5462 }
5463
5464 /* Return to original core */
5465 si_setcoreidx(sih, origidx);
5466 return clock;
5467 } /* si_pmu_cpu_clock */
5468
5469 #ifdef __ARM_ARCH_7A__
5470 static uint32
si_pmu_mem_ca7clock(si_t * sih,osl_t * osh)5471 si_pmu_mem_ca7clock(si_t *sih, osl_t *osh)
5472 {
5473 uint32 clock = 0;
5474 int8 mdiv = 1;
5475 uint idx = si_coreidx(sih);
5476 bool fastclk;
5477 ca7regs_t *regs = si_setcore(sih, ARMCA7_CORE_ID, 0);
5478
5479 if (regs == NULL) {
5480 goto end;
5481 }
5482
5483 fastclk = ((R_REG(osh, ARMREG(regs, clk_ctl_st)) & CCS_ARMFASTCLOCKREQ) != 0);
5484
5485 if (fastclk) {
5486 uint32 fvco = si_pmu_pll28nm_fvco(sih);
5487 if (si_corerev(sih) >= 7) {
5488 mdiv = (R_REG(osh, ARMREG(regs, corecontrol)) & ACC_CLOCKRATIO_MASK) >>
5489 ACC_CLOCKRATIO_SHIFT;
5490 } else {
5491 ASSERT(0);
5492 }
5493
5494 if (mdiv == 0) {
5495 ASSERT(0);
5496 clock = 0;
5497 } else {
5498 clock = (fvco / mdiv);
5499 }
5500 } else {
5501 clock = si_pmu_si_clock(sih, osh);
5502 }
5503
5504 end:
5505 si_setcoreidx(sih, idx);
5506 return clock;
5507
5508 }
5509 #endif /* __ARM_ARCH_7A__ */
5510
5511 /** get memory clock frequency, which is the same as the HT clock for newer chips. Returns [Hz]. */
5512 uint32
BCMINITFN(si_pmu_mem_clock)5513 BCMINITFN(si_pmu_mem_clock)(si_t *sih, osl_t *osh)
5514 {
5515 pmuregs_t *pmu;
5516 uint origidx;
5517 uint32 clock;
5518
5519 ASSERT(sih->cccaps & CC_CAP_PMU);
5520
5521 /* Remember original core before switch to chipc/pmu */
5522 origidx = si_coreidx(sih);
5523 if (AOB_ENAB(sih)) {
5524 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5525 } else {
5526 pmu = si_setcoreidx(sih, SI_CC_IDX);
5527 }
5528 ASSERT(pmu != NULL);
5529
5530 if ((PMUREV(sih->pmurev) >= 5) &&
5531 !((BCM4369_CHIP(sih->chip)) ||
5532 (BCM4362_CHIP(sih->chip)) ||
5533 BCM43602_CHIP(sih->chip) ||
5534 (CHIPID(sih->chip) == BCM43012_CHIP_ID) ||
5535 (CHIPID(sih->chip) == BCM43013_CHIP_ID) ||
5536 (CHIPID(sih->chip) == BCM43014_CHIP_ID) ||
5537 BCM4376_CHIP(sih->chip) ||
5538 BCM4378_CHIP(sih->chip) ||
5539 BCM4387_CHIP(sih->chip) ||
5540 BCM4388_CHIP(sih->chip) ||
5541 BCM4389_CHIP(sih->chip) ||
5542 BCM4397_CHIP(sih->chip) ||
5543 0)) {
5544 uint pll = PMU4716_MAINPLL_PLL0;
5545
5546 clock = si_pmu5_clock(sih, osh, pmu, pll, PMU5_MAINPLL_MEM);
5547 } else {
5548 #ifdef __ARM_ARCH_7A__
5549 clock = si_pmu_mem_ca7clock(sih, osh);
5550 #else /* !__ARM_ARCH_7A__ */
5551 clock = si_pmu_si_clock(sih, osh); /* mem clk same as backplane clk */
5552 #endif /* __ARM_ARCH_7A__ */
5553 }
5554 /* Return to original core */
5555 si_setcoreidx(sih, origidx);
5556 return clock;
5557 } /* si_pmu_mem_clock */
5558
5559 /*
5560 * ilpcycles per sec are now calculated during CPU init in a new way
5561 * for better accuracy. We set it here for compatability.
5562 *
5563 * On platforms that do not do this we resort to the old way.
5564 */
5565
5566 #define ILP_CALC_DUR 10 /* ms, make sure 1000 can be divided by it. */
5567
5568 static uint32 ilpcycles_per_sec = 0;
5569
5570 void
BCMPOSTTRAPFN(si_pmu_ilp_clock_set)5571 BCMPOSTTRAPFN(si_pmu_ilp_clock_set)(uint32 cycles_per_sec)
5572 {
5573 ilpcycles_per_sec = cycles_per_sec;
5574 }
5575
5576 /**
5577 * Measure ILP clock frequency. Returns a value in [Hz] units.
5578 *
5579 * The variable ilpcycles_per_sec is used to store the ILP clock speed. The value
5580 * is calculated when the function is called the first time and then cached.
5581 * The change in PMU timer count is measured across a delay of ILP_CALC_DUR msec.
5582 * Before the first time the function is called, one must make sure the HT clock is
5583 * turned on and used to feed the CPU and that OSL_DELAY() is calibrated.
5584 */
5585 uint32
BCMINITFN(si_pmu_ilp_clock)5586 BCMINITFN(si_pmu_ilp_clock)(si_t *sih, osl_t *osh)
5587 {
5588 if (ISSIM_ENAB(sih))
5589 return ILP_CLOCK;
5590
5591 if (ilpcycles_per_sec == 0) {
5592 uint32 start, end, delta;
5593 pmuregs_t *pmu;
5594 uint origidx = si_coreidx(sih);
5595
5596 if (AOB_ENAB(sih)) {
5597 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5598 } else {
5599 pmu = si_setcoreidx(sih, SI_CC_IDX);
5600 }
5601 ASSERT(pmu != NULL);
5602 start = R_REG(osh, &pmu->pmutimer);
5603 /* PR88659: verify pmutimer reads */
5604 if (start != R_REG(osh, &pmu->pmutimer))
5605 start = R_REG(osh, &pmu->pmutimer);
5606 OSL_DELAY(ILP_CALC_DUR * 1000);
5607 end = R_REG(osh, &pmu->pmutimer);
5608 if (end != R_REG(osh, &pmu->pmutimer))
5609 end = R_REG(osh, &pmu->pmutimer);
5610 delta = end - start;
5611 ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
5612 /* Return to original core */
5613 si_setcoreidx(sih, origidx);
5614 }
5615
5616 ASSERT(ilpcycles_per_sec != 0);
5617 return ilpcycles_per_sec;
5618 }
5619 #endif /* !defined(BCMDONGLEHOST) */
5620
5621 /**
5622 * Reads/writes a chipcontrol reg. Performes core switching if required, at function exit the
5623 * original core is restored. Depending on chip type, read/writes to chipcontrol regs in CC core
5624 * (older chips) or to chipcontrol regs in PMU core (later chips).
5625 */
5626 uint32
BCMPOSTTRAPFN(si_pmu_chipcontrol)5627 BCMPOSTTRAPFN(si_pmu_chipcontrol)(si_t *sih, uint reg, uint32 mask, uint32 val)
5628 {
5629 pmu_corereg(sih, SI_CC_IDX, chipcontrol_addr, ~0, reg);
5630 return pmu_corereg(sih, SI_CC_IDX, chipcontrol_data, mask, val);
5631 }
5632
5633 /**
5634 * Reads/writes a voltage regulator (vreg) register. Performes core switching if required, at
5635 * function exit the original core is restored. Depending on chip type, writes to regulator regs
5636 * in CC core (older chips) or to regulator regs in PMU core (later chips).
5637 */
5638 uint32
BCMPOSTTRAPFN(si_pmu_vreg_control)5639 BCMPOSTTRAPFN(si_pmu_vreg_control)(si_t *sih, uint reg, uint32 mask, uint32 val)
5640 {
5641 pmu_corereg(sih, SI_CC_IDX, regcontrol_addr, ~0, reg);
5642 return pmu_corereg(sih, SI_CC_IDX, regcontrol_data, mask, val);
5643 }
5644
5645 /**
5646 * Reads/writes a PLL control register. Performes core switching if required, at function exit the
5647 * original core is restored. Depending on chip type, writes to PLL control regs in CC core (older
5648 * chips) or to PLL control regs in PMU core (later chips).
5649 */
5650 uint32
BCMPOSTTRAPFN(si_pmu_pllcontrol)5651 BCMPOSTTRAPFN(si_pmu_pllcontrol)(si_t *sih, uint reg, uint32 mask, uint32 val)
5652 {
5653 pmu_corereg(sih, SI_CC_IDX, pllcontrol_addr, ~0, reg);
5654 return pmu_corereg(sih, SI_CC_IDX, pllcontrol_data, mask, val);
5655 }
5656
5657 /**
5658 * Balance between stable SDIO operation and power consumption is achieved using this function.
5659 * Note that each drive strength table is for a specific VDDIO of the SDIO pads, ideally this
5660 * function should read the VDDIO itself to select the correct table. For now it has been solved
5661 * with the 'BCM_SDIO_VDDIO' preprocessor constant.
5662 *
5663 * 'drivestrength': desired pad drive strength in mA. Drive strength of 0 requests tri-state (if
5664 * hardware supports this), if no hw support drive strength is not programmed.
5665 */
5666 void
BCMINITFN(si_sdiod_drive_strength_init)5667 BCMINITFN(si_sdiod_drive_strength_init)(si_t *sih, osl_t *osh, uint32 drivestrength)
5668 {
5669 /*
5670 * Note:
5671 * This function used to set the SDIO drive strength via PMU_CHIPCTL1 for the
5672 * 43143, 4330, 4334, 4336, 43362 chips. These chips are now no longer supported, so
5673 * the code has been deleted.
5674 * Newer chips have the SDIO drive strength setting via a GCI Chip Control register,
5675 * but the bit definitions are chip-specific. We are keeping this function available
5676 * (accessed via DHD 'sdiod_drive' IOVar) in case these newer chips need to provide access.
5677 */
5678 UNUSED_PARAMETER(sih);
5679 UNUSED_PARAMETER(osh);
5680 UNUSED_PARAMETER(drivestrength);
5681 }
5682
5683 #if !defined(BCMDONGLEHOST)
5684 /** initialize PMU */
5685 void
BCMATTACHFN(si_pmu_init)5686 BCMATTACHFN(si_pmu_init)(si_t *sih, osl_t *osh)
5687 {
5688 pmuregs_t *pmu;
5689 uint origidx;
5690
5691 ASSERT(sih->cccaps & CC_CAP_PMU);
5692
5693 /* Remember original core before switch to chipc/pmu */
5694 origidx = si_coreidx(sih);
5695 if (AOB_ENAB(sih)) {
5696 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5697 } else {
5698 pmu = si_setcoreidx(sih, SI_CC_IDX);
5699 }
5700 ASSERT(pmu != NULL);
5701
5702 #if defined(BT_WLAN_REG_ON_WAR)
5703 si_pmu_reg_on_war_ext_wake_perst_clear(sih);
5704 si_pmu_reg_on_war_ext_wake_perst_set(sih);
5705 #endif /* BT_WLAN_REG_ON_WAR */
5706
5707 /* Feature is added in PMU rev. 1 but doesn't work until rev. 2 */
5708 if (PMUREV(sih->pmurev) == 1)
5709 AND_REG(osh, &pmu->pmucontrol, ~PCTL_NOILP_ON_WAIT);
5710 else if (PMUREV(sih->pmurev) >= 2)
5711 OR_REG(osh, &pmu->pmucontrol, PCTL_NOILP_ON_WAIT);
5712
5713 /* Changes from PMU revision 26 are not included in revision 27 */
5714 if ((PMUREV(sih->pmurev) >= 26) && (PMUREV(sih->pmurev) != 27)) {
5715 uint32 val = PMU_INTC_ALP_REQ | PMU_INTC_HT_REQ | PMU_INTC_HQ_REQ;
5716 pmu_corereg(sih, SI_CC_IDX, pmuintctrl0, val, val);
5717
5718 val = RSRC_INTR_MASK_TIMER_INT_0;
5719 pmu_corereg(sih, SI_CC_IDX, pmuintmask0, val, val);
5720 (void)pmu_corereg(sih, SI_CC_IDX, pmuintmask0, 0, 0);
5721 }
5722
5723 /* Return to original core */
5724 si_setcoreidx(sih, origidx);
5725 }
5726
5727 uint32
si_pmu_rsrc_macphy_clk_deps(si_t * sih,osl_t * osh,int macunit)5728 si_pmu_rsrc_macphy_clk_deps(si_t *sih, osl_t *osh, int macunit)
5729 {
5730 uint32 deps = 0;
5731 rsc_per_chip_t *rsc;
5732 uint origidx;
5733 pmuregs_t *pmu = NULL;
5734 uint8 rsc_num;
5735
5736 /* Remember original core before switch to chipc/pmu */
5737 origidx = si_coreidx(sih);
5738 if (AOB_ENAB(sih)) {
5739 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5740 } else {
5741 pmu = si_setcoreidx(sih, SI_CC_IDX);
5742 }
5743
5744 ASSERT(pmu != NULL);
5745
5746 rsc = si_pmu_get_rsc_positions(sih);
5747 if (macunit == 0) {
5748 rsc_num = rsc->macphy_clkavail;
5749 } else if (macunit == 1) {
5750 rsc_num = rsc->macphy_aux_clkavail;
5751 } else if (macunit == 2) {
5752 rsc_num = rsc->macphy_scan_clkavail;
5753 } else {
5754 PMU_ERROR(("si_pmu_rsrc_macphy_clk_deps: slice %d is not supported\n", macunit));
5755 rsc_num = NO_SUCH_RESOURCE; /* to satisfy the compiler */
5756 ASSERT(0);
5757 }
5758 deps = si_pmu_res_deps(sih, osh, pmu, PMURES_BIT(rsc_num), TRUE);
5759 deps |= PMURES_BIT(rsc_num);
5760
5761 /* Return to original core */
5762 si_setcoreidx(sih, origidx);
5763
5764 return deps;
5765 }
5766
5767 void
si_pmu_set_mac_rsrc_req_sc(si_t * sih,osl_t * osh)5768 si_pmu_set_mac_rsrc_req_sc(si_t *sih, osl_t *osh)
5769 {
5770 uint32 deps = 0;
5771 rsc_per_chip_t *rsc;
5772 uint origidx;
5773 pmuregs_t *pmu = NULL;
5774 uint32 rsrc = 0;
5775
5776 /* Remember original core before switch to chipc/pmu */
5777 origidx = si_coreidx(sih);
5778 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5779 ASSERT(pmu != NULL);
5780
5781 rsc = si_pmu_get_rsc_positions(sih);
5782
5783 rsrc = (PMURES_BIT(rsc->macphy_scan_clkavail) |
5784 PMURES_BIT(rsc->dig_ready));
5785
5786 deps = si_pmu_res_deps(sih, osh, pmu, rsrc, TRUE);
5787 deps |= rsrc;
5788
5789 W_REG(osh, &pmu->mac_res_req_timer2, PMU32_MAC_SCAN_RSRC_REQ_TIMER);
5790 W_REG(osh, &pmu->mac_res_req_mask2, deps);
5791
5792 /* Return to original core */
5793 si_setcoreidx(sih, origidx);
5794 }
5795
5796 uint32
BCMATTACHFN(si_pmu_rsrc_ht_avail_clk_deps)5797 BCMATTACHFN(si_pmu_rsrc_ht_avail_clk_deps)(si_t *sih, osl_t *osh)
5798 {
5799 uint32 deps;
5800 rsc_per_chip_t *rsc;
5801 uint origidx;
5802 pmuregs_t *pmu = NULL;
5803
5804 /* Remember original core before switch to chipc/pmu */
5805 origidx = si_coreidx(sih);
5806 if (AOB_ENAB(sih)) {
5807 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5808 } else {
5809 pmu = si_setcoreidx(sih, SI_CC_IDX);
5810 }
5811
5812 ASSERT(pmu != NULL);
5813
5814 rsc = si_pmu_get_rsc_positions(sih);
5815 deps = si_pmu_res_deps(sih, osh, pmu, PMURES_BIT(rsc->ht_avail), FALSE);
5816 deps |= PMURES_BIT(rsc->ht_avail);
5817
5818 /* Return to original core */
5819 si_setcoreidx(sih, origidx);
5820
5821 return deps;
5822 }
5823
5824 uint32
BCMATTACHFN(si_pmu_rsrc_cb_ready_deps)5825 BCMATTACHFN(si_pmu_rsrc_cb_ready_deps)(si_t *sih, osl_t *osh)
5826 {
5827 uint32 deps;
5828 rsc_per_chip_t *rsc;
5829 uint origidx;
5830 pmuregs_t *pmu = NULL;
5831
5832 /* Remember original core before switch to chipc/pmu */
5833 origidx = si_coreidx(sih);
5834 if (AOB_ENAB(sih)) {
5835 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5836 } else {
5837 pmu = si_setcoreidx(sih, SI_CC_IDX);
5838 }
5839
5840 ASSERT(pmu != NULL);
5841
5842 rsc = si_pmu_get_rsc_positions(sih);
5843 if (rsc->cb_ready == NO_SUCH_RESOURCE) {
5844 deps = 0;
5845 } else {
5846 deps = si_pmu_res_deps(sih, osh, pmu, PMURES_BIT(rsc->cb_ready), FALSE);
5847 deps |= PMURES_BIT(rsc->cb_ready);
5848 }
5849
5850 /* Return to original core */
5851 si_setcoreidx(sih, origidx);
5852
5853 return deps;
5854 }
5855
5856 void
si_pmu_set_mac_rsrc_req(si_t * sih,int macunit)5857 si_pmu_set_mac_rsrc_req(si_t *sih, int macunit)
5858 {
5859 pmuregs_t *pmu;
5860 uint origidx;
5861 osl_t *osh = si_osh(sih);
5862
5863 /* Remember original core before switch to chipc/pmu */
5864 origidx = si_coreidx(sih);
5865 if (AOB_ENAB(sih)) {
5866 pmu = si_setcore(sih, PMU_CORE_ID, 0);
5867 } else {
5868 pmu = si_setcoreidx(sih, SI_CC_IDX);
5869 }
5870 ASSERT(pmu != NULL);
5871
5872 if (macunit == 0) {
5873 W_REG(osh, &pmu->mac_res_req_timer, PMU32_MAC_MAIN_RSRC_REQ_TIMER);
5874 W_REG(osh, &pmu->mac_res_req_mask, si_pmu_rsrc_macphy_clk_deps(sih, osh, macunit));
5875 } else if (macunit == 1) {
5876 W_REG(osh, &pmu->mac_res_req_timer1, PMU32_MAC_AUX_RSRC_REQ_TIMER);
5877 W_REG(osh, &pmu->mac_res_req_mask1, si_pmu_rsrc_macphy_clk_deps(sih, osh, macunit));
5878 } else if (macunit == 2) {
5879 W_REG(osh, &pmu->mac_res_req_timer2, PMU32_MAC_SCAN_RSRC_REQ_TIMER);
5880 W_REG(osh, &pmu->mac_res_req_mask2, si_pmu_rsrc_macphy_clk_deps(sih, osh, macunit));
5881 }
5882
5883 /* Return to original core */
5884 si_setcoreidx(sih, origidx);
5885 }
5886
5887 /**
5888 * Return worst case up time in [ILP cycles] for the given resource.
5889 *
5890 * Example use case: the d11 core needs to be programmed with the max time it
5891 * takes to make the HT clock available.
5892 *
5893 * need to check circular dependancies and prevent dead recursion.
5894 */
5895 static uint
BCMINITFN(si_pmu_res_uptime)5896 BCMINITFN(si_pmu_res_uptime)(si_t *sih, osl_t *osh,
5897 pmuregs_t *pmu, uint8 rsrc, bool pmu_fast_trans_en)
5898 {
5899 uint32 deps;
5900 uint uptime, i, dup, dmax, uptrans, ret;
5901 uint32 min_mask = 0;
5902 #ifndef SR_DEBUG
5903 uint32 max_mask = 0;
5904 #endif /* SR_DEBUG */
5905
5906 /* uptime of resource 'rsrc' */
5907 W_REG(osh, &pmu->res_table_sel, rsrc);
5908 if (PMUREV(sih->pmurev) >= 30)
5909 uptime = (R_REG(osh, &pmu->res_updn_timer) >> 16) & 0x7fff;
5910 else if (PMUREV(sih->pmurev) >= 13)
5911 uptime = (R_REG(osh, &pmu->res_updn_timer) >> 16) & 0x3ff;
5912 else
5913 uptime = (R_REG(osh, &pmu->res_updn_timer) >> 8) & 0xff;
5914
5915 /* direct dependencies of resource 'rsrc' */
5916 deps = si_pmu_res_deps(sih, osh, pmu, PMURES_BIT(rsrc), FALSE);
5917 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
5918 if (!(deps & PMURES_BIT(i)))
5919 continue;
5920 deps &= ~si_pmu_res_deps(sih, osh, pmu, PMURES_BIT(i), TRUE);
5921 }
5922 #ifndef SR_DEBUG
5923 si_pmu_res_masks(sih, &min_mask, &max_mask);
5924 #else
5925 /* Recalculate fast pwr up delay if min res mask/max res mask has changed */
5926 min_mask = R_REG(osh, &pmu->min_res_mask);
5927 #endif /* SR_DEBUG */
5928 deps &= ~min_mask;
5929
5930 /* max uptime of direct dependencies */
5931 dmax = 0;
5932 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
5933 if (!(deps & PMURES_BIT(i)))
5934 continue;
5935 dup = si_pmu_res_uptime(sih, osh, pmu, (uint8)i, pmu_fast_trans_en);
5936 if (dmax < dup)
5937 dmax = dup;
5938 }
5939
5940 PMU_MSG(("si_pmu_res_uptime: rsrc %u uptime %u(deps 0x%08x uptime %u)\n",
5941 rsrc, uptime, deps, dmax));
5942
5943 uptrans = pmu_fast_trans_en ? 0 : PMURES_UP_TRANSITION;
5944 ret = uptime + dmax + uptrans;
5945 return ret;
5946 }
5947
5948 /* Return dependencies (direct or all/indirect) for the given resources */
5949 /* need to check circular dependencies and prevent dead recursion */
5950 static uint32
si_pmu_res_deps(si_t * sih,osl_t * osh,pmuregs_t * pmu,uint32 rsrcs,bool all)5951 si_pmu_res_deps(si_t *sih, osl_t *osh, pmuregs_t *pmu, uint32 rsrcs, bool all)
5952 {
5953 uint32 deps = 0;
5954 uint32 i;
5955
5956 for (i = 0; i <= PMURES_MAX_RESNUM; i ++) {
5957 if (!(rsrcs & PMURES_BIT(i)))
5958 continue;
5959 W_REG(osh, &pmu->res_table_sel, i);
5960 deps |= R_REG(osh, &pmu->res_dep_mask);
5961 }
5962
5963 return !all ? deps : (deps ? (deps | si_pmu_res_deps(sih, osh, pmu, deps, TRUE)) : 0);
5964 }
5965
5966 static bool
si_pmu_otp_is_ready(si_t * sih)5967 si_pmu_otp_is_ready(si_t *sih)
5968 {
5969 uint32 otps = 0u;
5970
5971 if (AOB_ENAB(sih)) {
5972 otps = si_corereg(sih, si_findcoreidx(sih, GCI_CORE_ID, 0u),
5973 OFFSETOF(gciregs_t, otpstatus), 0u, 0u);
5974 } else {
5975 otps = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otpstatus), 0u, 0u);
5976 }
5977 return !!(otps & OTPS_READY);
5978 }
5979
5980 static bool
si_pmu_otp_is_ready_and_wait(si_t * sih,bool on)5981 si_pmu_otp_is_ready_and_wait(si_t *sih, bool on)
5982 {
5983 SPINWAIT((si_pmu_otp_is_ready(sih) != on), 3000u);
5984
5985 if (si_pmu_otp_is_ready(sih) != on) {
5986 PMU_ERROR(("OTP ready bit not %s after wait\n", (on ? "Set" : "Clear")));
5987 OSL_SYS_HALT();
5988 }
5989
5990 return si_pmu_otp_is_ready(sih) == on;
5991 }
5992
5993 /**
5994 * OTP is powered down/up as a means of resetting it, or for saving current when OTP is unused.
5995 * OTP is powered up/down through PMU resources.
5996 * OTP will turn OFF only if its not in the dependency of any "higher" rsrc in min_res_mask
5997 */
5998 void
si_pmu_otp_power(si_t * sih,osl_t * osh,bool on,uint32 * min_res_mask)5999 si_pmu_otp_power(si_t *sih, osl_t *osh, bool on, uint32* min_res_mask)
6000 {
6001 pmuregs_t *pmu;
6002 uint origidx;
6003 uint32 rsrcs = 0; /* rsrcs to turn on/off OTP power */
6004 rsc_per_chip_t *rsc; /* chip specific resource bit positions */
6005
6006 ASSERT(sih->cccaps & CC_CAP_PMU);
6007
6008 /* Don't do anything if OTP is disabled */
6009 if (si_is_otp_disabled(sih)) {
6010 PMU_MSG(("si_pmu_otp_power: OTP is disabled\n"));
6011 return;
6012 }
6013
6014 /* Remember original core before switch to chipc/pmu */
6015 origidx = si_coreidx(sih);
6016 if (AOB_ENAB(sih)) {
6017 pmu = si_setcore(sih, PMU_CORE_ID, 0);
6018 } else {
6019 pmu = si_setcoreidx(sih, SI_CC_IDX);
6020 }
6021 ASSERT(pmu != NULL);
6022
6023 /*
6024 * OTP can't be power cycled by toggling OTP_PU for always on OTP chips. For now
6025 * corerev 45 is the only one that has always on OTP.
6026 * Instead, the chipc register OTPCtrl1 (Offset 0xF4) bit 25 (forceOTPpwrDis) is used.
6027 * Please refer to http://hwnbu-twiki.broadcom.com/bin/view/Mwgroup/ChipcommonRev45
6028 */
6029 if (CCREV(sih->ccrev) == 45) {
6030 uint32 otpctrl1;
6031 otpctrl1 = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otpcontrol1), 0, 0);
6032 if (on)
6033 otpctrl1 &= ~OTPC_FORCE_PWR_OFF;
6034 else
6035 otpctrl1 |= OTPC_FORCE_PWR_OFF;
6036 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otpcontrol1), ~0, otpctrl1);
6037 /* Return to original core */
6038 si_setcoreidx(sih, origidx);
6039 return;
6040 }
6041
6042 switch (CHIPID(sih->chip)) {
6043 case BCM43012_CHIP_ID:
6044 case BCM43013_CHIP_ID:
6045 case BCM43014_CHIP_ID:
6046 case BCM4360_CHIP_ID:
6047 case BCM43460_CHIP_ID:
6048 case BCM4352_CHIP_ID:
6049 case BCM43526_CHIP_ID:
6050 case BCM4376_CHIP_GRPID:
6051 case BCM4385_CHIP_GRPID:
6052
6053 #ifdef UNRELEASEDCHIP
6054 #endif
6055
6056 rsc = si_pmu_get_rsc_positions(sih);
6057 rsrcs = PMURES_BIT(rsc->otp_pu);
6058 break;
6059 case BCM4378_CHIP_GRPID:
6060 case BCM4387_CHIP_GRPID:
6061 case BCM4388_CHIP_GRPID:
6062 case BCM4389_CHIP_GRPID:
6063 case BCM4397_CHIP_GRPID:
6064 si_gci_direct(sih, GCI_OFFSETOF(sih, otpcontrol), OTPC_FORCE_OTP_PWR_DIS,
6065 on ? 0u : OTPC_FORCE_OTP_PWR_DIS);
6066 if (!si_pmu_otp_is_ready_and_wait(sih, on)) {
6067 PMU_MSG(("OTP ready bit not %s after wait\n", (on ? "ON" : "OFF")));
6068 }
6069 break;
6070 default:
6071 break;
6072 }
6073
6074 if (rsrcs != 0) {
6075 bool on_check = FALSE; /* Stores otp_ready state */
6076 uint32 min_mask = 0;
6077
6078 /* Turn on/off the power */
6079 if (on) {
6080 min_mask = R_REG(osh, &pmu->min_res_mask);
6081 *min_res_mask = min_mask;
6082
6083 min_mask |= rsrcs;
6084 min_mask |= si_pmu_res_deps(sih, osh, pmu, min_mask, TRUE);
6085 on_check = TRUE;
6086 /* Assuming max rsc mask defines OTP_PU, so not programming max */
6087 PMU_MSG(("Adding rsrc 0x%x to min_res_mask\n", min_mask));
6088 W_REG(osh, &pmu->min_res_mask, min_mask);
6089 si_pmu_wait_for_steady_state(sih, osh, pmu);
6090 OSL_DELAY(1000);
6091 SPINWAIT(!(R_REG(osh, &pmu->res_state) & rsrcs),
6092 PMU_MAX_TRANSITION_DLY);
6093 ASSERT(R_REG(osh, &pmu->res_state) & rsrcs);
6094 } else {
6095 /*
6096 * Restore back the min_res_mask,
6097 * but keep OTP powered off if allowed by dependencies
6098 */
6099 if (*min_res_mask)
6100 min_mask = *min_res_mask;
6101 else
6102 min_mask = R_REG(osh, &pmu->min_res_mask);
6103
6104 min_mask &= ~rsrcs;
6105 /*
6106 * OTP rsrc can be cleared only if its not
6107 * in the dependency of any "higher" rsrc in min_res_mask
6108 */
6109 min_mask |= si_pmu_res_deps(sih, osh, pmu, min_mask, TRUE);
6110 on_check = ((min_mask & rsrcs) != 0);
6111
6112 PMU_MSG(("Removing rsrc 0x%x from min_res_mask\n", min_mask));
6113 W_REG(osh, &pmu->min_res_mask, min_mask);
6114 si_pmu_wait_for_steady_state(sih, osh, pmu);
6115 }
6116
6117 if (!si_pmu_otp_is_ready_and_wait(sih, on_check)) {
6118 PMU_MSG(("OTP ready bit not %s after wait\n", (on_check ? "ON" : "OFF")));
6119 }
6120 #ifdef NOT_YET
6121 /*
6122 * FIXME: Temporarily disabling OTPS_READY ASSERT check. Right now ASSERT in
6123 * ROM is enabled only for 4389B0/C0. Therefore this change anyway will not
6124 * affect other chips. Once the correct spin-wait value is updated by the
6125 * HW team, then this ASSERT will be enabled back.
6126 */
6127 ASSERT(si_pmu_otp_is_ready(sih) == on_check);
6128 #endif /* NOT_YET */
6129 }
6130
6131 /* Return to original core */
6132 si_setcoreidx(sih, origidx);
6133 } /* si_pmu_otp_power */
6134
6135 void
si_pmu_spuravoid(si_t * sih,osl_t * osh,uint8 spuravoid)6136 si_pmu_spuravoid(si_t *sih, osl_t *osh, uint8 spuravoid)
6137 {
6138 uint origidx;
6139 bcm_int_bitmask_t intr_val;
6140
6141 /* Block ints and save current core */
6142 si_introff(sih, &intr_val);
6143 origidx = si_coreidx(sih);
6144
6145 /* Return to original core */
6146 si_setcoreidx(sih, origidx);
6147 si_intrrestore(sih, &intr_val);
6148 } /* si_pmu_spuravoid */
6149
6150 /* below function are only for BBPLL parallel purpose */
6151 /* For having the pllcontrol data values for spuravoid */
6152 typedef struct {
6153 uint8 spuravoid_mode;
6154 uint8 pllctrl_reg;
6155 uint32 pllctrl_regval;
6156 } pllctrl_spuravoid_t;
6157
6158 uint32
si_pmu_pll28nm_fvco(si_t * sih)6159 si_pmu_pll28nm_fvco(si_t *sih)
6160 {
6161 uint32 r_high, r_low, r;
6162 uint32 xf = si_alp_clock(sih);
6163 /* PLL registers for 4368 */
6164 uint32 pllreg5 = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG5, 0, 0);
6165 uint32 pllreg4 = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG4, 0, 0);
6166 /* p1div has lower 2 bits in pll4 and high 2 bits in pll5 */
6167 uint8 p1div_lo = (pllreg4 & PMU4368_PLL1_PC4_P1DIV_MASK) >> PMU4368_PLL1_PC4_P1DIV_SHIFT;
6168 uint8 p1div_hi = (pllreg5 & PMU4368_PLL1_PC5_P1DIV_MASK) >> PMU4368_PLL1_PC5_P1DIV_SHIFT;
6169 uint8 p1div = (p1div_hi << PMU4368_P1DIV_HI_SHIFT) | (p1div_lo << PMU4368_P1DIV_LO_SHIFT);
6170 uint32 ndiv_int = (pllreg5 & PMU4368_PLL1_PC5_NDIV_INT_MASK) >>
6171 PMU4368_PLL1_PC5_NDIV_INT_SHIFT;
6172 uint32 ndiv_frac = (pllreg5 & PMU4368_PLL1_PC5_NDIV_FRAC_MASK) >>
6173 PMU4368_PLL1_PC5_NDIV_FRAC_SHIFT;
6174
6175 if (ISSIM_ENAB(sih)) {
6176 /* PLL CTRL registers are meaningless under QT, return the pre-configured freq */
6177 return (FVCO_720 * 1000);
6178 } else if (p1div == 0) {
6179 /* PLL register read fails, return 0 so caller can retry */
6180 PMU_ERROR(("p1div is invalid\n"));
6181 return 0;
6182 }
6183
6184 /* Calculate xf * ( ndiv_frac / (1 << 20) + ndiv_int) / p1div)
6185 * To reduce the inaccuracy in division,
6186 * Covert to (xf * ndiv_frac / (1 << 20) + xf * ndiv_int) / p1div
6187 */
6188 math_uint64_multiple_add(&r_high, &r_low, xf, ndiv_frac, 0);
6189 /* Make sure the caclulated 64 bits number is in the safe rage (with in 52 bits),
6190 * so we have a valid 32 bits result after divided by 1<<20
6191 */
6192 ASSERT((r_high & 0xFFE00000) == 0);
6193 math_uint64_right_shift(&r, r_high, r_low, 20);
6194
6195 return (r + ndiv_int * xf) / p1div;
6196 }
6197
6198 bool
si_pmu_is_otp_powered(si_t * sih,osl_t * osh)6199 si_pmu_is_otp_powered(si_t *sih, osl_t *osh)
6200 {
6201 uint idx;
6202 pmuregs_t *pmu;
6203 bool st;
6204 rsc_per_chip_t *rsc; /* chip specific resource bit positions */
6205
6206 /* Remember original core before switch to chipc/pmu */
6207 idx = si_coreidx(sih);
6208 if (AOB_ENAB(sih)) {
6209 pmu = si_setcore(sih, PMU_CORE_ID, 0);
6210 } else {
6211 pmu = si_setcoreidx(sih, SI_CC_IDX);
6212 }
6213 ASSERT(pmu != NULL);
6214
6215 si_pmu_wait_for_steady_state(sih, osh, pmu);
6216
6217 switch (CHIPID(sih->chip)) {
6218 case BCM43012_CHIP_ID:
6219 case BCM43013_CHIP_ID:
6220 case BCM43014_CHIP_ID:
6221 case BCM4360_CHIP_ID:
6222 case BCM43460_CHIP_ID:
6223 case BCM43526_CHIP_ID:
6224 case BCM4352_CHIP_ID:
6225 case BCM4369_CHIP_GRPID:
6226 case BCM4362_CHIP_GRPID:
6227 case BCM4376_CHIP_GRPID:
6228 case BCM4385_CHIP_GRPID:
6229 rsc = si_pmu_get_rsc_positions(sih);
6230 st = (R_REG(osh, &pmu->res_state) & PMURES_BIT(rsc->otp_pu)) != 0;
6231 break;
6232 case BCM4378_CHIP_GRPID:
6233 case BCM4387_CHIP_GRPID:
6234 case BCM4388_CHIP_GRPID:
6235 case BCM4389_CHIP_GRPID:
6236 case BCM4397_CHIP_GRPID:
6237 st = (!(si_gci_direct(sih, GCI_OFFSETOF(sih, otpcontrol), 0u, 0u) &
6238 OTPC_FORCE_OTP_PWR_DIS)) && si_pmu_otp_is_ready_and_wait(sih, TRUE);
6239 break;
6240 default:
6241 st = TRUE;
6242 break;
6243 }
6244
6245 /* Return to original core */
6246 si_setcoreidx(sih, idx);
6247 return st;
6248 } /* si_pmu_is_otp_powered */
6249
6250 /**
6251 * Some chip/boards can be optionally fitted with an external 32Khz clock source for increased power
6252 * savings (due to more accurate sleep intervals).
6253 */
6254 static void
BCMATTACHFN(si_pmu_set_lpoclk)6255 BCMATTACHFN(si_pmu_set_lpoclk)(si_t *sih, osl_t *osh)
6256 {
6257 uint32 ext_lpo_sel, int_lpo_sel, timeout = 0,
6258 ext_lpo_avail = 0, lpo_sel = 0;
6259 uint32 ext_lpo_isclock; /* On e.g. 43602a0, either x-tal or clock can be on LPO pins */
6260 pmuregs_t *pmu;
6261 uint origidx;
6262
6263 if (!(getintvar(NULL, "boardflags3")))
6264 return;
6265
6266 /* Remember original core before switch to chipc/pmu */
6267 origidx = si_coreidx(sih);
6268 if (AOB_ENAB(sih)) {
6269 pmu = si_setcore(sih, PMU_CORE_ID, 0);
6270 } else {
6271 pmu = si_setcoreidx(sih, SI_CC_IDX);
6272 }
6273 ASSERT(pmu != NULL);
6274
6275 ext_lpo_sel = getintvar(NULL, "boardflags3") & BFL3_FORCE_EXT_LPO_SEL;
6276 int_lpo_sel = getintvar(NULL, "boardflags3") & BFL3_FORCE_INT_LPO_SEL;
6277 ext_lpo_isclock = getintvar(NULL, "boardflags3") & BFL3_EXT_LPO_ISCLOCK;
6278
6279 BCM_REFERENCE(ext_lpo_isclock);
6280
6281 if (ext_lpo_sel != 0) {
6282 switch (CHIPID(sih->chip)) {
6283 CASE_BCM43602_CHIP:
6284 /* External LPO is POR default enabled */
6285 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, PMU43602_CC2_XTAL32_SEL,
6286 ext_lpo_isclock ? 0 : PMU43602_CC2_XTAL32_SEL);
6287 break;
6288 default:
6289 /* Force External LPO Power Up */
6290 si_pmu_chipcontrol(sih, PMU_CHIPCTL0, CC_EXT_LPO_PU, CC_EXT_LPO_PU);
6291 si_gci_chipcontrol(sih, CHIPCTRLREG6, GC_EXT_LPO_PU, GC_EXT_LPO_PU);
6292 break;
6293 }
6294
6295 ext_lpo_avail = R_REG(osh, &pmu->pmustatus) & EXT_LPO_AVAIL;
6296 while (ext_lpo_avail == 0 && timeout < LPO_SEL_TIMEOUT) {
6297 OSL_DELAY(1000);
6298 ext_lpo_avail = R_REG(osh, &pmu->pmustatus) & EXT_LPO_AVAIL;
6299 timeout++;
6300 }
6301
6302 if (timeout >= LPO_SEL_TIMEOUT) {
6303 PMU_ERROR(("External LPO is not available\n"));
6304 } else {
6305 /* External LPO is available, lets use (=select) it */
6306 OSL_DELAY(1000);
6307 timeout = 0;
6308
6309 switch (CHIPID(sih->chip)) {
6310 CASE_BCM43602_CHIP:
6311 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, PMU43602_CC2_FORCE_EXT_LPO,
6312 PMU43602_CC2_FORCE_EXT_LPO); /* switches to external LPO */
6313 break;
6314 default:
6315 /* Force External LPO Sel up */
6316 si_gci_chipcontrol(sih, CHIPCTRLREG6, EXT_LPO_SEL, EXT_LPO_SEL);
6317 /* Clear Force Internal LPO Sel */
6318 si_gci_chipcontrol(sih, CHIPCTRLREG6, INT_LPO_SEL, 0x0);
6319 OSL_DELAY(1000);
6320
6321 lpo_sel = R_REG(osh, &pmu->pmucontrol) & LPO_SEL;
6322 while (lpo_sel != 0 && timeout < LPO_SEL_TIMEOUT) {
6323 OSL_DELAY(1000);
6324 lpo_sel = R_REG(osh, &pmu->pmucontrol) & LPO_SEL;
6325 timeout++;
6326 }
6327 }
6328
6329 if (timeout >= LPO_SEL_TIMEOUT) {
6330 PMU_ERROR(("External LPO is not set\n"));
6331 /* Clear Force External LPO Sel */
6332 switch (CHIPID(sih->chip)) {
6333 CASE_BCM43602_CHIP:
6334 si_pmu_chipcontrol(sih, PMU_CHIPCTL2,
6335 PMU43602_CC2_FORCE_EXT_LPO, 0);
6336 break;
6337 default:
6338 si_gci_chipcontrol(sih, CHIPCTRLREG6, EXT_LPO_SEL, 0x0);
6339 break;
6340 }
6341 } else {
6342 /* Clear Force Internal LPO Power Up */
6343 switch (CHIPID(sih->chip)) {
6344 CASE_BCM43602_CHIP:
6345 break;
6346 default:
6347 si_pmu_chipcontrol(sih, PMU_CHIPCTL0, CC_INT_LPO_PU, 0x0);
6348 si_gci_chipcontrol(sih, CHIPCTRLREG6, GC_INT_LPO_PU, 0x0);
6349 break;
6350 }
6351 } /* if (timeout) */
6352 } /* if (timeout) */
6353 } else if (int_lpo_sel != 0) {
6354 switch (CHIPID(sih->chip)) {
6355 CASE_BCM43602_CHIP:
6356 break; /* do nothing, internal LPO is POR default powered and selected */
6357 default:
6358 /* Force Internal LPO Power Up */
6359 si_pmu_chipcontrol(sih, PMU_CHIPCTL0, CC_INT_LPO_PU, CC_INT_LPO_PU);
6360 si_gci_chipcontrol(sih, CHIPCTRLREG6, GC_INT_LPO_PU, GC_INT_LPO_PU);
6361
6362 OSL_DELAY(1000);
6363
6364 /* Force Internal LPO Sel up */
6365 si_gci_chipcontrol(sih, CHIPCTRLREG6, INT_LPO_SEL, INT_LPO_SEL);
6366 /* Clear Force External LPO Sel */
6367 si_gci_chipcontrol(sih, CHIPCTRLREG6, EXT_LPO_SEL, 0x0);
6368
6369 OSL_DELAY(1000);
6370
6371 lpo_sel = R_REG(osh, &pmu->pmucontrol) & LPO_SEL;
6372 timeout = 0;
6373 while (lpo_sel == 0 && timeout < LPO_SEL_TIMEOUT) {
6374 OSL_DELAY(1000);
6375 lpo_sel = R_REG(osh, &pmu->pmucontrol) & LPO_SEL;
6376 timeout++;
6377 }
6378 if (timeout >= LPO_SEL_TIMEOUT) {
6379 PMU_ERROR(("Internal LPO is not set\n"));
6380 /* Clear Force Internal LPO Sel */
6381 si_gci_chipcontrol(sih, CHIPCTRLREG6, INT_LPO_SEL, 0x0);
6382 } else {
6383 /* Clear Force External LPO Power Up */
6384 si_pmu_chipcontrol(sih, PMU_CHIPCTL0, CC_EXT_LPO_PU, 0x0);
6385 si_gci_chipcontrol(sih, CHIPCTRLREG6, GC_EXT_LPO_PU, 0x0);
6386 }
6387 break;
6388 }
6389 if ((PMUREV(sih->pmurev) >= 33)) {
6390 /* Enabling FAST_SEQ */
6391 PMU_REG(sih, pmucontrol_ext, PCTL_EXT_FASTSEQ_ENAB, PCTL_EXT_FASTSEQ_ENAB);
6392 }
6393 }
6394
6395 /* Return to original core */
6396 si_setcoreidx(sih, origidx);
6397 } /* si_pmu_set_lpoclk */
6398
6399 static int
si_pmu_fast_lpo_locked(si_t * sih,osl_t * osh)6400 si_pmu_fast_lpo_locked(si_t *sih, osl_t *osh)
6401 {
6402 int lock = 0;
6403 switch (CHIPID(sih->chip)) {
6404 case BCM43012_CHIP_ID:
6405 case BCM43013_CHIP_ID:
6406 case BCM43014_CHIP_ID:
6407 lock = CHIPC_REG(sih, chipstatus, 0, 0) & CST43012_FLL_LOCK;
6408 break;
6409 case BCM4369_CHIP_GRPID:
6410 case BCM4376_CHIP_GRPID:
6411 case BCM4378_CHIP_GRPID:
6412 lock = si_gci_chipstatus(sih, GCI_CHIPSTATUS_13) & GCI_CS_4369_FLL1MHZ_LOCK_MASK;
6413 break;
6414 case BCM4385_CHIP_GRPID:
6415 case BCM4387_CHIP_GRPID:
6416 case BCM4388_CHIP_GRPID:
6417 case BCM4389_CHIP_GRPID:
6418 case BCM4397_CHIP_GRPID:
6419 lock = si_gci_chipstatus(sih, GCI_CHIPSTATUS_15) & GCI_CS_4387_FLL1MHZ_LOCK_MASK;
6420 break;
6421 default:
6422 PMU_MSG(("si_pmu_fast_lpo_locked: LPO enable: unsupported chip!\n"));
6423 }
6424 return lock ? 1 : 0;
6425 }
6426
6427 /* Turn ON FAST LPO FLL (1MHz) */
6428 static void
BCMATTACHFN(si_pmu_fast_lpo_enable)6429 BCMATTACHFN(si_pmu_fast_lpo_enable)(si_t *sih, osl_t *osh)
6430 {
6431 int i = 0, lock = 0;
6432
6433 BCM_REFERENCE(i);
6434 BCM_REFERENCE(lock);
6435
6436 switch (CHIPID(sih->chip)) {
6437 case BCM43012_CHIP_ID:
6438 case BCM43013_CHIP_ID:
6439 case BCM43014_CHIP_ID:
6440 PMU_REG(sih, pmucontrol_ext, PCTL_EXT_FASTLPO_ENAB, PCTL_EXT_FASTLPO_ENAB);
6441 lock = CHIPC_REG(sih, chipstatus, 0, 0) & CST43012_FLL_LOCK;
6442
6443 for (i = 0; ((i <= 30) && (!lock)); i++)
6444 {
6445 lock = CHIPC_REG(sih, chipstatus, 0, 0) & CST43012_FLL_LOCK;
6446 OSL_DELAY(10);
6447 }
6448
6449 PMU_MSG(("si_pmu_fast_lpo_enable: duration: %d\n", i*10));
6450
6451 if (!lock) {
6452 PMU_MSG(("si_pmu_fast_lpo_enable: FLL lock not present!"));
6453 ROMMABLE_ASSERT(0);
6454 }
6455
6456 /* Now switch to using FAST LPO clk */
6457 PMU_REG(sih, pmucontrol_ext, PCTL_EXT_FASTLPO_SWENAB, PCTL_EXT_FASTLPO_SWENAB);
6458 break;
6459 case BCM4369_CHIP_GRPID:
6460 case BCM4376_CHIP_GRPID:
6461 case BCM4378_CHIP_GRPID:
6462 case BCM4385_CHIP_GRPID:
6463 case BCM4387_CHIP_GRPID:
6464 case BCM4388_CHIP_GRPID:
6465 case BCM4389_CHIP_GRPID:
6466 case BCM4397_CHIP_GRPID:
6467 {
6468 uint8 fastlpo_dis = fastlpo_dis_get();
6469 uint8 fastlpo_pcie_dis = fastlpo_pcie_dis_get();
6470
6471 if (!fastlpo_dis || !fastlpo_pcie_dis) {
6472 /* LHL rev 6 in 4387 requires this bit to be set first */
6473 if ((LHLREV(sih->lhlrev) >= 6) && !PMU_FLL_PU_ENAB()) {
6474 LHL_REG(sih, lhl_top_pwrseq_ctl_adr,
6475 LHL_PWRSEQCTL_PMU_LPLDO_PD, LHL_PWRSEQCTL_WL_FLLPU_EN);
6476 }
6477
6478 PMU_REG(sih, pmucontrol_ext, PCTL_EXT_FASTLPO_ENAB, PCTL_EXT_FASTLPO_ENAB);
6479
6480 lock = si_pmu_fast_lpo_locked(sih, osh);
6481 for (i = 0; ((i < 300) && (!lock)); i++) {
6482 lock = si_pmu_fast_lpo_locked(sih, osh);
6483 OSL_DELAY(10);
6484 }
6485 ASSERT(lock);
6486 }
6487
6488 if (!fastlpo_dis) {
6489 /* Now switch to using FAST LPO clk */
6490 PMU_REG(sih, pmucontrol_ext,
6491 PCTL_EXT_FASTLPO_SWENAB, PCTL_EXT_FASTLPO_SWENAB);
6492
6493 OSL_DELAY(1000);
6494 PMU_MSG(("pmu fast lpo enabled\n"));
6495 }
6496 break;
6497 }
6498 default:
6499 PMU_MSG(("si_pmu_fast_lpo_enable: LPO enable: unsupported chip!\n"));
6500 }
6501 }
6502
6503 /* Turn ON FAST LPO FLL (1MHz) for PCIE */
6504 bool
BCMATTACHFN(si_pmu_fast_lpo_enable_pcie)6505 BCMATTACHFN(si_pmu_fast_lpo_enable_pcie)(si_t *sih)
6506 {
6507 if (!FASTLPO_ENAB()) {
6508 return FALSE;
6509 }
6510
6511 switch (CHIPID(sih->chip)) {
6512 case BCM4369_CHIP_GRPID:
6513 case BCM4376_CHIP_GRPID:
6514 case BCM4378_CHIP_GRPID:
6515 case BCM4385_CHIP_GRPID:
6516 case BCM4387_CHIP_GRPID:
6517 case BCM4388_CHIP_GRPID:
6518 case BCM4389_CHIP_GRPID:
6519 case BCM4397_CHIP_GRPID:
6520 {
6521 uint8 fastlpo_pcie_dis = fastlpo_pcie_dis_get();
6522
6523 if (!fastlpo_pcie_dis) {
6524 PMU_REG(sih, pmucontrol_ext,
6525 PCTL_EXT_FASTLPO_PCIE_SWENAB, PCTL_EXT_FASTLPO_PCIE_SWENAB);
6526 OSL_DELAY(1000);
6527 PMU_MSG(("pcie fast lpo enabled\n"));
6528 return TRUE;
6529 }
6530 break;
6531 }
6532 default:
6533 PMU_MSG(("si_pmu_fast_lpo_enable_pcie: LPO enable: unsupported chip!\n"));
6534 }
6535
6536 return FALSE;
6537 }
6538
6539 /* Turn ON FAST LPO FLL (1MHz) for PMU */
6540 bool
BCMATTACHFN(si_pmu_fast_lpo_enable_pmu)6541 BCMATTACHFN(si_pmu_fast_lpo_enable_pmu)(si_t *sih)
6542 {
6543 if (!FASTLPO_ENAB()) {
6544 return FALSE;
6545 }
6546
6547 switch (CHIPID(sih->chip)) {
6548 case BCM4369_CHIP_GRPID:
6549 case BCM4376_CHIP_GRPID:
6550 case BCM4378_CHIP_GRPID:
6551 case BCM4385_CHIP_GRPID:
6552 case BCM4387_CHIP_GRPID:
6553 case BCM4388_CHIP_GRPID:
6554 case BCM4389_CHIP_GRPID:
6555 case BCM4397_CHIP_GRPID:
6556 {
6557 uint8 fastlpo_dis = fastlpo_dis_get();
6558
6559 if (!fastlpo_dis) {
6560 PMU_MSG(("pmu fast lpo enabled\n"));
6561 return TRUE;
6562 }
6563 break;
6564 }
6565 default:
6566 PMU_MSG(("si_pmu_fast_lpo_enable_pmu: LPO enable: unsupported chip!\n"));
6567 }
6568
6569 return FALSE;
6570 }
6571
6572 static uint8
BCMATTACHFN(fastlpo_dis_get)6573 BCMATTACHFN(fastlpo_dis_get)(void)
6574 {
6575 uint8 fastlpo_dis = 1;
6576
6577 #if defined(BCM_FASTLPO_PMU) && !defined(BCM_FASTLPO_PMU_DISABLED)
6578 if (FASTLPO_ENAB()) {
6579 fastlpo_dis = 0;
6580 if (getvar(NULL, rstr_fastlpo_dis) != NULL) {
6581 fastlpo_dis = (uint8)getintvar(NULL, rstr_fastlpo_dis);
6582 }
6583 }
6584 #endif /* BCM_FASTLPO_PMU */
6585 return fastlpo_dis;
6586 }
6587
6588 static uint8
BCMATTACHFN(fastlpo_pcie_dis_get)6589 BCMATTACHFN(fastlpo_pcie_dis_get)(void)
6590 {
6591 uint8 fastlpo_pcie_dis = 1;
6592
6593 if (FASTLPO_ENAB()) {
6594 fastlpo_pcie_dis = 0;
6595 if (getvar(NULL, rstr_fastlpo_pcie_dis) != NULL) {
6596 fastlpo_pcie_dis = (uint8)getintvar(NULL, rstr_fastlpo_pcie_dis);
6597 }
6598 }
6599 return fastlpo_pcie_dis;
6600 }
6601
6602 static void
BCMATTACHFN(si_pmu_fll_preload_enable)6603 BCMATTACHFN(si_pmu_fll_preload_enable)(si_t *sih)
6604 {
6605 if (!PMU_FLL_PU_ENAB()) {
6606 return;
6607 }
6608
6609 switch (CHIPID(sih->chip)) {
6610 case BCM4387_CHIP_GRPID:
6611 case BCM4388_CHIP_GRPID:
6612 case BCM4389_CHIP_GRPID:
6613 {
6614 uint32 fll_dac_out;
6615
6616 fll_dac_out = (si_gci_chipstatus(sih, GCI_CHIPSTATUS_15) &
6617 GCI_CS_4387_FLL1MHZ_DAC_OUT_MASK)
6618 >> GCI_CS_4387_FLL1MHZ_DAC_OUT_SHIFT;
6619
6620 LHL_REG(sih, lhl_wl_hw_ctl_adr[1],
6621 LHL_1MHZ_FLL_DAC_EXT_MASK,
6622 (fll_dac_out) << LHL_1MHZ_FLL_DAC_EXT_SHIFT);
6623 LHL_REG(sih, lhl_wl_hw_ctl_adr[1],
6624 LHL_1MHZ_FLL_PRELOAD_MASK,
6625 LHL_1MHZ_FLL_PRELOAD_MASK);
6626 break;
6627 }
6628 default:
6629 PMU_MSG(("si_pmu_fll_preload_enable: unsupported chip!\n"));
6630 ASSERT(0);
6631 break;
6632 }
6633 }
6634
6635 /* LV sleep mode summary:
6636 * LV mode is where both ABUCK and CBUCK are programmed to low voltages during
6637 * sleep, and VMUX selects ABUCK as VDDOUT_AON. LPLDO needs to power off.
6638 * With ASR ON, LPLDO OFF
6639 */
6640 #if defined(SAVERESTORE)
6641 static void
BCMATTACHFN(si_set_lv_sleep_mode_pmu)6642 BCMATTACHFN(si_set_lv_sleep_mode_pmu)(si_t *sih, osl_t *osh)
6643 {
6644 /* jtag_udr_write USER_REG9W jtag_serdes_pic_enable 1 */
6645 if (BCM4369_CHIP(sih->chip) && (CHIPREV(sih->chiprev) == 0)) {
6646 si_pmu_chipcontrol(sih, PMU_CHIPCTL4, PMU_CC4_4369_AUX_PD_MEMLPLDO2VDDB_ON, 0);
6647
6648 //JTAG_SEL override. When this bit is set, jtag_sel 0, Required for JTAG writes
6649 /* Temporarily we are disabling this as it is not required..
6650 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_06, 0x10, 0x10);
6651 jtag_setbit_128(sih, 9, 103, 1);
6652 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_06, 0x10, 0x0);
6653 */
6654
6655 }
6656
6657 /* Program pmu VREG resgiter for Resouce based ABUCK and CBUCK modes
6658 * cbuck rsrc 0 - PWM and abuck rsrc 0 - Auto, rsrc 1 - PWM
6659 */
6660 si_pmu_vreg_control(sih, PMU_VREG_16, PMU_4369_VREG16_RSRC0_CBUCK_MODE_MASK,
6661 0x3u << PMU_4369_VREG16_RSRC0_CBUCK_MODE_SHIFT);
6662 si_pmu_vreg_control(sih, PMU_VREG_16, PMU_4369_VREG16_RSRC0_ABUCK_MODE_MASK,
6663 0x3u << PMU_4369_VREG16_RSRC0_ABUCK_MODE_SHIFT);
6664 si_pmu_vreg_control(sih, PMU_VREG_16, PMU_4369_VREG16_RSRC1_ABUCK_MODE_MASK,
6665 0x3u << PMU_4369_VREG16_RSRC1_ABUCK_MODE_SHIFT);
6666 si_pmu_vreg_control(sih, PMU_VREG_16, PMU_4369_VREG16_RSRC2_ABUCK_MODE_MASK,
6667 0x3u << PMU_4369_VREG16_RSRC2_ABUCK_MODE_SHIFT);
6668
6669 /* asr voltage adjust PWM - 0.8V */
6670 si_pmu_vreg_control(sih, PMU_VREG_8, PMU_4369_VREG8_ASR_OVADJ_LPPFM_MASK,
6671 0x10u << PMU_4369_VREG8_ASR_OVADJ_LPPFM_SHIFT);
6672
6673 /* Enable rsrc_en_asr_msk[0] and msk[1] */
6674 si_pmu_vreg_control(sih, PMU_VREG_13, PMU_4369_VREG13_RSRC_EN0_ASR_MASK,
6675 0x1u << PMU_4369_VREG13_RSRC_EN0_ASR_SHIFT);
6676 si_pmu_vreg_control(sih, PMU_VREG_13, PMU_4369_VREG13_RSRC_EN1_ASR_MASK,
6677 0x1u << PMU_4369_VREG13_RSRC_EN1_ASR_SHIFT);
6678 si_pmu_vreg_control(sih, PMU_VREG_13, PMU_4369_VREG13_RSRC_EN2_ASR_MASK,
6679 0x1u << PMU_4369_VREG13_RSRC_EN2_ASR_SHIFT);
6680
6681 si_pmu_vreg_control(sih, PMU_VREG_14, PMU_4369_VREG14_RSRC_EN_CSR_MASK0_MASK,
6682 0x1u << PMU_4369_VREG14_RSRC_EN_CSR_MASK0_SHIFT);
6683
6684 /* disable force_hp_mode and enable wl_pmu_lv_mod */
6685 si_pmu_vreg_control(sih, PMU_VREG_7,
6686 (PMU_4369_VREG_7_WL_PMU_LV_MODE_MASK | PMU_4369_VREG_7_WL_PMU_LP_MODE_MASK |
6687 PMU_4369_VREG_7_PMU_FORCE_HP_MODE_MASK), PMU_4369_VREG_7_WL_PMU_LV_MODE_MASK);
6688
6689 /* Enable MISCLDO only for A0, MEMLPLDO_adj -0.7V, Disable LPLDO power up */
6690 /* For 4387, should not disable because this is PU when analog PMU is out of sleep
6691 * and bypass when in sleep mode
6692 */
6693 if (!(BCM4389_CHIP(sih->chip) || BCM4388_CHIP(sih->chip) || BCM4397_CHIP(sih->chip) ||
6694 BCM4387_CHIP(sih->chip))) {
6695 si_pmu_vreg_control(sih, PMU_VREG_5, PMU_4369_VREG_5_MISCLDO_POWER_UP_MASK,
6696 ((CHIPREV(sih->chiprev) == 0) ? 1 : 0) <<
6697 PMU_4369_VREG_5_MISCLDO_POWER_UP_SHIFT);
6698 }
6699 si_pmu_vreg_control(sih, PMU_VREG_5, PMU_4369_VREG_5_LPLDO_POWER_UP_MASK, 0x0u);
6700 si_pmu_vreg_control(sih, PMU_VREG_5, PMU_4369_VREG_5_MEMLPLDO_OP_VLT_ADJ_CTRL_MASK,
6701 0xDu << PMU_4369_VREG_5_MEMLPLDO_OP_VLT_ADJ_CTRL_SHIFT);
6702 si_pmu_vreg_control(sih, PMU_VREG_5, PMU_4369_VREG_5_LPLDO_OP_VLT_ADJ_CTRL_MASK,
6703 0xFu << PMU_4369_VREG_5_LPLDO_OP_VLT_ADJ_CTRL_SHIFT);
6704
6705 /* Enabale MEMLPLDO ( to enable 0x08)and BTLDO is enabled. At sleep RFLDO is disabled */
6706 si_pmu_vreg_control(sih, PMU_VREG_6, PMU_4369_VREG_6_MEMLPLDO_POWER_UP_MASK,
6707 0x1u << PMU_4369_VREG_6_MEMLPLDO_POWER_UP_SHIFT);
6708
6709 /* Program PMU chip cntrl register to control
6710 * cbuck2vddb_pwrsw_force_on =1 and memlpldo2vddb_pwrsw_force_off = 1
6711 * cbuck2ret_pwrsw_force_on = 1 and memlpldo2vddb_pwrsw_force_off = 1
6712 * set d11_2x2_bw80_cbuck2vddb_pwrsw_force_on and
6713 * d11_2x2_bw20_cbuck2vddb_pwrsw_force_on cbuck2ret_pwrsw on 4 cores
6714 */
6715 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
6716 (PMU_CC4_4369_MAIN_PD_CBUCK2VDDB_ON | PMU_CC4_4369_MAIN_PD_CBUCK2VDDRET_ON |
6717 PMU_CC4_4369_MAIN_PD_MEMLPLDO2VDDB_ON | PMU_CC4_4369_MAIN_PD_MEMLPDLO2VDDRET_ON),
6718 (PMU_CC4_4369_MAIN_PD_CBUCK2VDDB_ON | PMU_CC4_4369_MAIN_PD_CBUCK2VDDRET_ON));
6719 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
6720 (PMU_CC4_4369_AUX_PD_CBUCK2VDDB_ON | PMU_CC4_4369_AUX_PD_CBUCK2VDDRET_ON |
6721 PMU_CC4_4369_AUX_PD_MEMLPLDO2VDDB_ON | PMU_CC4_4369_AUX_PD_MEMLPLDO2VDDRET_ON),
6722 (PMU_CC4_4369_AUX_PD_CBUCK2VDDB_ON | PMU_CC4_4369_AUX_PD_CBUCK2VDDRET_ON));
6723
6724 /* set subcore_cbuck2vddb_pwrsw_force_on */
6725 si_pmu_chipcontrol(sih, PMU_CHIPCTL5,
6726 (PMU_CC5_4369_SUBCORE_CBUCK2VDDB_ON | PMU_CC5_4369_SUBCORE_CBUCK2VDDRET_ON |
6727 PMU_CC5_4369_SUBCORE_MEMLPLDO2VDDB_ON | PMU_CC5_4369_SUBCORE_MEMLPLDO2VDDRET_ON),
6728 (PMU_CC5_4369_SUBCORE_CBUCK2VDDB_ON | PMU_CC5_4369_SUBCORE_CBUCK2VDDRET_ON));
6729
6730 /* Set subcore_memlpldo2vddb_pwrsw_force_off, d11_2x2_bw80_memlpldo2vddb_pwrsw_force_off
6731 * and d11_2x2_bw20_memlpldo2vddb_pwrsw_force_off
6732 * Set subcore_memlpldo2vddret_pwrsw_force_off,d11_2x2_bw80_memlpldo2vddret_pwrsw_force_off
6733 * and d11_2x2_bw20_memlpldo2vddret_pwrsw_force_off
6734 */
6735 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6736 (PMU_CC13_SUBCORE_CBUCK2VDDB_OFF | PMU_CC13_SUBCORE_CBUCK2VDDRET_OFF |
6737 PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF | PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF),
6738 (PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF | PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF));
6739 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6740 (PMU_CC13_MAIN_CBUCK2VDDB_OFF | PMU_CC13_MAIN_CBUCK2VDDRET_OFF |
6741 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF | PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF),
6742 (PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF | PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF));
6743 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6744 (PMU_CC13_AUX_CBUCK2VDDB_OFF | PMU_CC13_AUX_CBUCK2VDDRET_OFF |
6745 PMU_CC13_AUX_MEMLPLDO2VDDB_OFF | PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF),
6746 (PMU_CC13_AUX_MEMLPLDO2VDDB_OFF | PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF));
6747
6748 /* PCIE retention mode enable */
6749 si_pmu_chipcontrol(sih, PMU_CHIPCTL6,
6750 PMU_CC6_ENABLE_PCIE_RETENTION, PMU_CC6_ENABLE_PCIE_RETENTION);
6751 }
6752
6753 static void
BCMATTACHFN(si_set_lv_sleep_mode_4369)6754 BCMATTACHFN(si_set_lv_sleep_mode_4369)(si_t *sih, osl_t *osh)
6755 {
6756 si_set_lv_sleep_mode_pmu(sih, osh);
6757
6758 si_set_lv_sleep_mode_lhl_config_4369(sih);
6759
6760 /* Enable PMU interrupts */
6761 CHIPC_REG(sih, intmask, (1u << 4u), (1u << 4u));
6762 }
6763
si_set_abuck_mode_4362(si_t * sih,uint8 mode)6764 void si_set_abuck_mode_4362(si_t *sih, uint8 mode)
6765 {
6766
6767 if (mode < 2 || mode > 4) {
6768 ASSERT(0);
6769 return;
6770 }
6771
6772 si_pmu_vreg_control(sih, PMU_VREG_16, PMU_4362_VREG16_RSRC0_ABUCK_MODE_MASK,
6773 mode << PMU_4362_VREG16_RSRC0_ABUCK_MODE_SHIFT);
6774 si_pmu_vreg_control(sih, PMU_VREG_16, PMU_4362_VREG16_RSRC1_ABUCK_MODE_MASK,
6775 mode << PMU_4362_VREG16_RSRC1_ABUCK_MODE_SHIFT);
6776 si_pmu_vreg_control(sih, PMU_VREG_16, PMU_4362_VREG16_RSRC2_ABUCK_MODE_MASK,
6777 mode << PMU_4362_VREG16_RSRC2_ABUCK_MODE_SHIFT);
6778 }
6779
6780 static void
BCMATTACHFN(si_set_lv_sleep_mode_4378)6781 BCMATTACHFN(si_set_lv_sleep_mode_4378)(si_t *sih, osl_t *osh)
6782 {
6783 si_set_lv_sleep_mode_pmu(sih, osh);
6784
6785 si_set_lv_sleep_mode_lhl_config_4378(sih);
6786 }
6787
6788 static void
BCMATTACHFN(si_set_lv_sleep_mode_pmu_4387)6789 BCMATTACHFN(si_set_lv_sleep_mode_pmu_4387)(si_t *sih, osl_t *osh)
6790 {
6791 /* Program pmu VREG resgiter for Resouce based ABUCK and CBUCK modes
6792 * cbuck rsrc 0 - PWM and abuck rsrc 0 - Auto, rsrc 1 - PWM
6793 */
6794 si_pmu_vreg_control(sih, PMU_VREG_16, PMU_4369_VREG16_RSRC1_ABUCK_MODE_MASK,
6795 0x2u << PMU_4369_VREG16_RSRC1_ABUCK_MODE_SHIFT);
6796
6797 /* asr voltage adjust PWM - 0.8V */
6798 si_pmu_vreg_control(sih, PMU_VREG_8, PMU_4369_VREG8_ASR_OVADJ_LPPFM_MASK,
6799 0x10u << PMU_4369_VREG8_ASR_OVADJ_LPPFM_SHIFT);
6800
6801 /* Enable rsrc_en_asr_msk[0] and msk[1] */
6802 si_pmu_vreg_control(sih, PMU_VREG_13, PMU_4369_VREG13_RSRC_EN0_ASR_MASK,
6803 0x1u << PMU_4369_VREG13_RSRC_EN0_ASR_SHIFT);
6804 si_pmu_vreg_control(sih, PMU_VREG_13, PMU_4369_VREG13_RSRC_EN1_ASR_MASK,
6805 0x1u << PMU_4369_VREG13_RSRC_EN1_ASR_SHIFT);
6806 si_pmu_vreg_control(sih, PMU_VREG_13, PMU_4369_VREG13_RSRC_EN2_ASR_MASK,
6807 0x1u << PMU_4369_VREG13_RSRC_EN2_ASR_SHIFT);
6808
6809 si_pmu_vreg_control(sih, PMU_VREG_14, PMU_4369_VREG14_RSRC_EN_CSR_MASK0_MASK,
6810 0x1u << PMU_4369_VREG14_RSRC_EN_CSR_MASK0_SHIFT);
6811
6812 /* disable force_hp_mode and enable wl_pmu_lv_mod */
6813 si_pmu_vreg_control(sih, PMU_VREG_7,
6814 (PMU_4369_VREG_7_WL_PMU_LV_MODE_MASK | PMU_4369_VREG_7_WL_PMU_LP_MODE_MASK |
6815 PMU_4369_VREG_7_PMU_FORCE_HP_MODE_MASK), PMU_4369_VREG_7_WL_PMU_LV_MODE_MASK);
6816
6817 /* Enabale MEMLPLDO ( to enable 0x08)and BTLDO is enabled. At sleep RFLDO is disabled */
6818 si_pmu_vreg_control(sih, PMU_VREG_6, PMU_4369_VREG_6_MEMLPLDO_POWER_UP_MASK,
6819 0x1u << PMU_4369_VREG_6_MEMLPLDO_POWER_UP_SHIFT);
6820
6821 /* For 4387C0, we don't need memlpldo2vddret_on nor cldo2vddb_on.
6822 * We just need to clear the memlpldo2vddb_forceoff to turn on all the memlpldo2vddb pwrsw
6823 */
6824 if (PMUREV(sih->pmurev) < 39) {
6825 /* Program PMU chip cntrl register to control
6826 * cbuck2vddb_pwrsw_force_on =1 and memlpldo2vddb_pwrsw_force_off = 1
6827 * cbuck2ret_pwrsw_force_on = 1 and memlpldo2vddb_pwrsw_force_off = 1
6828 * set d11_2x2_bw80_cbuck2vddb_pwrsw_force_on and
6829 * d11_2x2_bw20_cbuck2vddb_pwrsw_force_on cbuck2ret_pwrsw on 4 cores
6830 */
6831 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
6832 (PMU_CC4_4369_MAIN_PD_CBUCK2VDDB_ON | PMU_CC4_4369_MAIN_PD_CBUCK2VDDRET_ON |
6833 PMU_CC4_4369_MAIN_PD_MEMLPLDO2VDDB_ON |
6834 PMU_CC4_4369_MAIN_PD_MEMLPDLO2VDDRET_ON),
6835 (PMU_CC4_4369_MAIN_PD_CBUCK2VDDB_ON |
6836 PMU_CC4_4369_MAIN_PD_CBUCK2VDDRET_ON));
6837 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
6838 (PMU_CC4_4369_AUX_PD_CBUCK2VDDB_ON | PMU_CC4_4369_AUX_PD_CBUCK2VDDRET_ON |
6839 PMU_CC4_4369_AUX_PD_MEMLPLDO2VDDB_ON |
6840 PMU_CC4_4369_AUX_PD_MEMLPLDO2VDDRET_ON),
6841 (PMU_CC4_4369_AUX_PD_CBUCK2VDDB_ON | PMU_CC4_4369_AUX_PD_CBUCK2VDDRET_ON));
6842
6843 /* set subcore_cbuck2vddb_pwrsw_force_on */
6844 si_pmu_chipcontrol(sih, PMU_CHIPCTL5,
6845 (PMU_CC5_4369_SUBCORE_CBUCK2VDDB_ON | PMU_CC5_4369_SUBCORE_CBUCK2VDDRET_ON |
6846 PMU_CC5_4369_SUBCORE_MEMLPLDO2VDDB_ON |
6847 PMU_CC5_4369_SUBCORE_MEMLPLDO2VDDRET_ON),
6848 (PMU_CC5_4369_SUBCORE_CBUCK2VDDB_ON |
6849 PMU_CC5_4369_SUBCORE_CBUCK2VDDRET_ON));
6850
6851 /* Set subcore_memlpldo2vddb_pwrsw_force_off,
6852 * d11_2x2_bw80_memlpldo2vddb_pwrsw_force_off
6853 * and d11_2x2_bw20_memlpldo2vddb_pwrsw_force_off
6854 * Set subcore_memlpldo2vddret_pwrsw_force_off,
6855 * d11_2x2_bw80_memlpldo2vddret_pwrsw_force_off
6856 * and d11_2x2_bw20_memlpldo2vddret_pwrsw_force_off
6857 */
6858 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6859 (PMU_CC13_SUBCORE_CBUCK2VDDB_OFF | PMU_CC13_SUBCORE_CBUCK2VDDRET_OFF |
6860 PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF | PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF),
6861 (PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF |
6862 PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF));
6863 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6864 (PMU_CC13_MAIN_CBUCK2VDDB_OFF | PMU_CC13_MAIN_CBUCK2VDDRET_OFF |
6865 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF | PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF),
6866 (PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF | PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF));
6867 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6868 (PMU_CC13_AUX_CBUCK2VDDB_OFF | PMU_CC13_AUX_CBUCK2VDDRET_OFF |
6869 PMU_CC13_AUX_MEMLPLDO2VDDB_OFF | PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF),
6870 (PMU_CC13_AUX_MEMLPLDO2VDDB_OFF | PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF));
6871 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
6872 PMU_CC4_4369_AUX_PD_MEMLPLDO2VDDRET_ON,
6873 PMU_CC4_4369_AUX_PD_MEMLPLDO2VDDRET_ON);
6874 si_pmu_chipcontrol(sih, PMU_CHIPCTL5,
6875 PMU_CC5_4369_SUBCORE_MEMLPLDO2VDDRET_ON,
6876 PMU_CC5_4369_SUBCORE_MEMLPLDO2VDDRET_ON),
6877 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6878 PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF |
6879 PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF |
6880 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF |
6881 PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF |
6882 PMU_CC13_AUX_MEMLPLDO2VDDB_OFF |
6883 PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF |
6884 PMU_CC13_CMN_MEMLPLDO2VDDRET_ON,
6885 PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF |
6886 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF |
6887 PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF |
6888 PMU_CC13_AUX_MEMLPLDO2VDDB_OFF |
6889 PMU_CC13_CMN_MEMLPLDO2VDDRET_ON);
6890 si_pmu_chipcontrol(sih, PMU_CHIPCTL17,
6891 PMU_CC17_SCAN_MEMLPLDO2VDDRET_ON |
6892 PMU_CC17_SCAN_CBUCK2VDDB_ON |
6893 PMU_CC17_SCAN_MEMLPLDO2VDDRET_OFF,
6894 PMU_CC17_SCAN_MEMLPLDO2VDDRET_ON |
6895 PMU_CC17_SCAN_CBUCK2VDDB_ON);
6896 } else {
6897 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6898 PMU_CC13_CMN_MEMLPLDO2VDDRET_ON |
6899 PMU_CC13_AUX_MEMLPLDO2VDDB_OFF |
6900 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF |
6901 PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF,
6902 PMU_CC13_CMN_MEMLPLDO2VDDRET_ON);
6903 si_pmu_chipcontrol(sih, PMU_CHIPCTL17,
6904 PMU_CC17_SCAN_MEMLPLDO2VDDB_OFF, 0);
6905 }
6906
6907 /* PCIE retention mode enable */
6908 si_pmu_chipcontrol(sih, PMU_CHIPCTL6,
6909 PMU_CC6_ENABLE_PCIE_RETENTION, PMU_CC6_ENABLE_PCIE_RETENTION);
6910
6911 /* H/W JIRA http://jira.broadcom.com/browse/HW4387-825
6912 * B0 only, the h/w bug is fixed in C0
6913 */
6914 if (PMUREV(sih->pmurev) == 38) {
6915 si_pmu_vreg_control(sih, PMU_VREG_14,
6916 PMU_VREG14_RSRC_EN_ASR_PWM_PFM_MASK,
6917 PMU_VREG14_RSRC_EN_ASR_PWM_PFM_MASK);
6918 }
6919
6920 /* WAR for jira HW4387-922 */
6921 si_pmu_vreg_control(sih, PMU_VREG_1,
6922 PMU_4387_VREG1_CSR_OVERI_DIS_MASK,
6923 PMU_4387_VREG1_CSR_OVERI_DIS_MASK);
6924
6925 /* Clear Misc_LDO override */
6926 si_pmu_vreg_control(sih, PMU_VREG_5, VREG5_4387_MISCLDO_PU_MASK, 0);
6927
6928 si_pmu_vreg_control(sih, PMU_VREG_8,
6929 PMU_4387_VREG8_ASR_OVERI_DIS_MASK,
6930 PMU_4387_VREG8_ASR_OVERI_DIS_MASK);
6931
6932 if (BCMSRTOPOFF_ENAB()) {
6933 si_pmu_vreg_control(sih, PMU_VREG_6,
6934 PMU_4387_VREG6_WL_PMU_LV_MODE_MASK, 0);
6935
6936 /* Clear memldo_pu bit as 4387 doesn't plan to use MEMLDO */
6937 si_pmu_vreg_control(sih, PMU_VREG_6,
6938 PMU_4387_VREG6_MEMLDO_PU_MASK, 0);
6939 } else {
6940 si_pmu_vreg_control(sih, PMU_VREG_6,
6941 PMU_4387_VREG6_WL_PMU_LV_MODE_MASK,
6942 PMU_4387_VREG6_WL_PMU_LV_MODE_MASK);
6943 }
6944 }
6945
6946 static void
BCMATTACHFN(si_set_lv_sleep_mode_4387)6947 BCMATTACHFN(si_set_lv_sleep_mode_4387)(si_t *sih, osl_t *osh)
6948 {
6949 si_set_lv_sleep_mode_pmu_4387(sih, osh);
6950 si_set_lv_sleep_mode_lhl_config_4387(sih);
6951 }
6952
6953 static void
BCMATTACHFN(si_set_lv_sleep_mode_4389)6954 BCMATTACHFN(si_set_lv_sleep_mode_4389)(si_t *sih, osl_t *osh)
6955 {
6956 si_set_lv_sleep_mode_pmu(sih, osh);
6957
6958 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
6959 PMU_CC4_4387_MAIN_PD_CBUCK2VDDRET_ON |
6960 PMU_CC4_4387_AUX_PD_CBUCK2VDDRET_ON,
6961 0);
6962 si_pmu_chipcontrol(sih, PMU_CHIPCTL5,
6963 PMU_CC5_4387_SUBCORE_CBUCK2VDDRET_ON,
6964 0);
6965 si_pmu_chipcontrol(sih, PMU_CHIPCTL6,
6966 PMU_CC6_RX4_CLK_SEQ_SELECT_MASK,
6967 0);
6968 /* Disable lq_clk - HW4387-254 */
6969 si_pmu_chipcontrol(sih, PMU_CHIPCTL12,
6970 PMU_CC12_DISABLE_LQ_CLK_ON,
6971 PMU_CC12_DISABLE_LQ_CLK_ON);
6972 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6973 PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF |
6974 PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF |
6975 PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF,
6976 0);
6977
6978 #ifdef NOT_YET
6979 /* FIXME: this setting is causing the load switch from CSR to ASR */
6980 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
6981 PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF |
6982 PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF |
6983 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF |
6984 PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF |
6985 PMU_CC13_AUX_MEMLPLDO2VDDB_OFF |
6986 PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF |
6987 PMU_CC13_CMN_MEMLPLDO2VDDRET_ON, 0);
6988 #endif /* NOT_YET */
6989
6990 si_pmu_chipcontrol(sih, PMU_CHIPCTL17,
6991 PMU_CC17_SCAN_MEMLPLDO2VDDRET_ON |
6992 PMU_CC17_SCAN_CBUCK2VDDB_ON |
6993 PMU_CC17_SCAN_MEMLPLDO2VDDRET_OFF,
6994 PMU_CC17_SCAN_MEMLPLDO2VDDRET_ON |
6995 PMU_CC17_SCAN_CBUCK2VDDB_ON);
6996
6997 si_set_lv_sleep_mode_lhl_config_4389(sih);
6998
6999 si_pmu_vreg_control(sih, PMU_VREG_6,
7000 (PMU_4389_VREG6_WL_PMU_LV_MODE_MASK | PMU_4389_VREG6_MEMLDO_PU_MASK),
7001 PMU_4389_VREG6_WL_PMU_LV_MODE_MASK);
7002
7003 /* SW WAR for 4389B0(rev 01) issue - HW4387-922. 4389C0(rev 02) already has HW fix */
7004 if (CHIPREV(sih->chiprev) == 1) {
7005 si_pmu_vreg_control(sih, PMU_VREG_1,
7006 PMU_4387_VREG1_CSR_OVERI_DIS_MASK,
7007 PMU_4387_VREG1_CSR_OVERI_DIS_MASK);
7008
7009 si_pmu_vreg_control(sih, PMU_VREG_8,
7010 PMU_4387_VREG8_ASR_OVERI_DIS_MASK,
7011 PMU_4387_VREG8_ASR_OVERI_DIS_MASK);
7012 }
7013 }
7014
7015 static void
BCMATTACHFN(si_set_lv_sleep_mode_4362)7016 BCMATTACHFN(si_set_lv_sleep_mode_4362)(si_t *sih, osl_t *osh)
7017 {
7018 /* Program pmu VREG resgiter for Resouce based ABUCK and CBUCK modes
7019 * cbuck rsrc 0 - PWM and abuck rsrc 0 - Auto, rsrc 1 - PWM
7020 */
7021 si_pmu_vreg_control(sih, PMU_VREG_16, PMU_4362_VREG16_RSRC0_CBUCK_MODE_MASK,
7022 0x3u << PMU_4362_VREG16_RSRC0_CBUCK_MODE_SHIFT);
7023
7024 si_set_abuck_mode_4362(sih, 0x3u);
7025
7026 /* asr voltage adjust PWM - 0.8V */
7027 si_pmu_vreg_control(sih, PMU_VREG_8, PMU_4362_VREG8_ASR_OVADJ_LPPFM_MASK,
7028 0x10u << PMU_4362_VREG8_ASR_OVADJ_LPPFM_SHIFT);
7029
7030 /* Enable rsrc_en_asr_msk[0] and msk[1] */
7031 si_pmu_vreg_control(sih, PMU_VREG_13, PMU_4362_VREG13_RSRC_EN0_ASR_MASK,
7032 0x1u << PMU_4362_VREG13_RSRC_EN0_ASR_SHIFT);
7033 si_pmu_vreg_control(sih, PMU_VREG_13, PMU_4362_VREG13_RSRC_EN1_ASR_MASK,
7034 0x1u << PMU_4362_VREG13_RSRC_EN1_ASR_SHIFT);
7035 si_pmu_vreg_control(sih, PMU_VREG_13, PMU_4362_VREG13_RSRC_EN2_ASR_MASK,
7036 0x1u << PMU_4362_VREG13_RSRC_EN2_ASR_SHIFT);
7037
7038 si_pmu_vreg_control(sih, PMU_VREG_14, PMU_4362_VREG14_RSRC_EN_CSR_MASK0_MASK,
7039 0x1u << PMU_4362_VREG14_RSRC_EN_CSR_MASK0_SHIFT);
7040
7041 /* disable force_hp_mode and enable wl_pmu_lv_mod */
7042 si_pmu_vreg_control(sih, PMU_VREG_7,
7043 (PMU_4362_VREG_7_WL_PMU_LV_MODE_MASK | PMU_4362_VREG_7_WL_PMU_LP_MODE_MASK |
7044 PMU_4362_VREG_7_PMU_FORCE_HP_MODE_MASK), PMU_4362_VREG_7_WL_PMU_LV_MODE_MASK);
7045
7046 /* Enable MISCLDO, MEMLPLDO_adj -0.7V, Disable LPLDO power up */
7047 si_pmu_vreg_control(sih, PMU_VREG_5, PMU_4362_VREG_5_MISCLDO_POWER_UP_MASK,
7048 0x1u << PMU_4362_VREG_5_MISCLDO_POWER_UP_SHIFT);
7049 si_pmu_vreg_control(sih, PMU_VREG_5, PMU_4362_VREG_5_LPLDO_POWER_UP_MASK, 0x0u);
7050 si_pmu_vreg_control(sih, PMU_VREG_5, PMU_4362_VREG_5_MEMLPLDO_OP_VLT_ADJ_CTRL_MASK,
7051 0xBu << PMU_4362_VREG_5_MEMLPLDO_OP_VLT_ADJ_CTRL_SHIFT);
7052
7053 /* Enabale MEMLPLDO ( to enable 0x08)and BTLDO is enabled. At sleep RFLDO is disabled */
7054 si_pmu_vreg_control(sih, PMU_VREG_6, PMU_4362_VREG_6_MEMLPLDO_POWER_UP_MASK,
7055 0x1u << PMU_4362_VREG_6_MEMLPLDO_POWER_UP_SHIFT);
7056
7057 /* Program PMU chip cntrl register to control
7058 * cbuck2vddb_pwrsw_force_on =1 and memlpldo2vddb_pwrsw_force_off = 1
7059 * cbuck2ret_pwrsw_force_on = 1 and memlpldo2vddb_pwrsw_force_off = 1
7060 * set d11_2x2_bw80_cbuck2vddb_pwrsw_force_on and
7061 * d11_2x2_bw20_cbuck2vddb_pwrsw_force_on cbuck2ret_pwrsw on 4 cores
7062 */
7063 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
7064 (PMU_CC4_4362_PD_CBUCK2VDDB_ON | PMU_CC4_4362_PD_CBUCK2VDDRET_ON |
7065 PMU_CC4_4362_PD_MEMLPLDO2VDDB_ON | PMU_CC4_4362_PD_MEMLPDLO2VDDRET_ON),
7066 (PMU_CC4_4362_PD_CBUCK2VDDB_ON | PMU_CC4_4362_PD_CBUCK2VDDRET_ON));
7067
7068 /* set subcore_cbuck2vddb_pwrsw_force_on */
7069 si_pmu_chipcontrol(sih, PMU_CHIPCTL5,
7070 (PMU_CC5_4362_SUBCORE_CBUCK2VDDB_ON | PMU_CC5_4362_SUBCORE_CBUCK2VDDRET_ON |
7071 PMU_CC5_4362_SUBCORE_MEMLPLDO2VDDB_ON | PMU_CC5_4362_SUBCORE_MEMLPLDO2VDDRET_ON),
7072 (PMU_CC5_4362_SUBCORE_CBUCK2VDDB_ON | PMU_CC5_4362_SUBCORE_CBUCK2VDDRET_ON));
7073
7074 /* Set subcore_memlpldo2vddb_pwrsw_force_off, d11_2x2_bw80_memlpldo2vddb_pwrsw_force_off
7075 * and d11_2x2_bw20_memlpldo2vddb_pwrsw_force_off
7076 * Set subcore_memlpldo2vddret_pwrsw_force_off,d11_2x2_bw80_memlpldo2vddret_pwrsw_force_off
7077 * and d11_2x2_bw20_memlpldo2vddret_pwrsw_force_off
7078 */
7079 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
7080 (PMU_CC13_SUBCORE_CBUCK2VDDB_OFF | PMU_CC13_SUBCORE_CBUCK2VDDRET_OFF |
7081 PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF | PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF),
7082 (PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF | PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF));
7083 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
7084 (PMU_CC13_MAIN_CBUCK2VDDB_OFF | PMU_CC13_MAIN_CBUCK2VDDB_OFF |
7085 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF | PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF),
7086 (PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF | PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF));
7087
7088 /* PCIE retention mode enable */
7089 si_pmu_chipcontrol(sih, PMU_CHIPCTL6,
7090 PMU_CC6_ENABLE_PCIE_RETENTION, PMU_CC6_ENABLE_PCIE_RETENTION);
7091
7092 si_set_lv_sleep_mode_lhl_config_4362(sih);
7093
7094 /* Enable PMU interrupts */
7095 CHIPC_REG(sih, intmask, (1u << 4u), (1u << 4u));
7096 }
7097
7098 void
BCMATTACHFN(si_pmu_fis_setup)7099 BCMATTACHFN(si_pmu_fis_setup)(si_t *sih)
7100 {
7101 uint origidx;
7102 pmuregs_t *pmu;
7103 int val;
7104 osl_t *osh = si_osh(sih);
7105
7106 origidx = si_coreidx(sih);
7107 if (AOB_ENAB(sih)) {
7108 pmu = si_setcore(sih, PMU_CORE_ID, 0);
7109 } else {
7110 pmu = si_setcoreidx(sih, SI_CC_IDX);
7111 }
7112 ASSERT(pmu != NULL);
7113
7114 switch (CHIPID(sih->chip)) {
7115 case BCM4376_CHIP_GRPID:
7116 case BCM4378_CHIP_GRPID:
7117 val = R_REG(osh, &pmu->max_res_mask);
7118 W_REG(osh, &pmu->fis_start_min_res_mask, val);
7119
7120 val = R_REG(osh, &pmu->min_res_mask);
7121 W_REG(osh, &pmu->fis_min_res_mask, val);
7122
7123 W_REG(osh, &pmu->fis_ctrl_status,
7124 (PMU_FIS_DN_TIMER_VAL_4378 << PMU_FIS_DN_TIMER_VAL_SHIFT)
7125 & PMU_FIS_DN_TIMER_VAL_MASK);
7126 break;
7127 case BCM4388_CHIP_GRPID:
7128 val = R_REG(osh, &pmu->max_res_mask);
7129 W_REG(osh, &pmu->fis_start_min_res_mask, val);
7130
7131 val = R_REG(osh, &pmu->min_res_mask);
7132 W_REG(osh, &pmu->fis_min_res_mask, val);
7133
7134 W_REG(osh, &pmu->fis_ctrl_status,
7135 ((PMU_FIS_DN_TIMER_VAL_4388 << PMU_FIS_DN_TIMER_VAL_SHIFT)
7136 & PMU_FIS_DN_TIMER_VAL_MASK) | PMU_FIS_PCIE_SAVE_EN_VALUE);
7137 break;
7138 case BCM4389_CHIP_GRPID:
7139 val = R_REG(osh, &pmu->max_res_mask);
7140 W_REG(osh, &pmu->fis_start_min_res_mask, val);
7141
7142 val = R_REG(osh, &pmu->min_res_mask);
7143 W_REG(osh, &pmu->fis_min_res_mask, val);
7144
7145 W_REG(osh, &pmu->fis_ctrl_status,
7146 ((PMU_FIS_DN_TIMER_VAL_4389 << PMU_FIS_DN_TIMER_VAL_SHIFT)
7147 & PMU_FIS_DN_TIMER_VAL_MASK) | PMU_FIS_PCIE_SAVE_EN_VALUE);
7148 break;
7149
7150 default:
7151 break;
7152 }
7153 si_setcoreidx(sih, origidx);
7154 }
7155 #endif /* defined(SAVERESTORE) */
7156
7157 /*
7158 * Enable: Dynamic Clk Switching
7159 * Disable: Mirrored Mode
7160 * use nvram to enable
7161 */
7162 static void
BCMATTACHFN(si_pmu_dynamic_clk_switch_enab)7163 BCMATTACHFN(si_pmu_dynamic_clk_switch_enab)(si_t *sih)
7164 {
7165 if (PMUREV(sih->pmurev) >= 36) {
7166 if (getintvar(NULL, rstr_dyn_clksw_en)) {
7167 PMU_REG(sih, pmucontrol_ext,
7168 PCTL_EXT_REQ_MIRROR_ENAB, 0);
7169 si_pmu_chipcontrol(sih, PMU_CHIPCTL2,
7170 CC2_4378_USE_WLAN_BP_CLK_ON_REQ_MASK |
7171 CC2_4378_USE_CMN_BP_CLK_ON_REQ_MASK,
7172 0);
7173 }
7174 }
7175 }
7176
7177 /* use pmu rsrc XTAL_PU to count deep sleep of chip */
7178 static void
BCMATTACHFN(si_pmu_enb_slp_cnt_on_rsrc)7179 BCMATTACHFN(si_pmu_enb_slp_cnt_on_rsrc)(si_t *sih, osl_t *osh)
7180 {
7181 uint origidx;
7182 pmuregs_t *pmu;
7183 uint32 rsrc_slp = 0xffffffff;
7184
7185 origidx = si_coreidx(sih);
7186 if (AOB_ENAB(sih)) {
7187 pmu = si_setcore(sih, PMU_CORE_ID, 0);
7188 } else {
7189 pmu = si_setcoreidx(sih, SI_CC_IDX);
7190 }
7191 ASSERT(pmu != NULL);
7192
7193 switch (CHIPID(sih->chip)) {
7194
7195 case BCM4376_CHIP_GRPID:
7196 case BCM4378_CHIP_GRPID:
7197 rsrc_slp = RES4378_XTAL_PU;
7198 break;
7199
7200 case BCM4385_CHIP_GRPID:
7201 case BCM4387_CHIP_GRPID:
7202 rsrc_slp = RES4387_XTAL_PU;
7203 break;
7204
7205 case BCM4388_CHIP_GRPID:
7206 case BCM4389_CHIP_GRPID:
7207 case BCM4397_CHIP_GRPID:
7208 rsrc_slp = RES4389_XTAL_PU;
7209 break;
7210
7211 default:
7212 break;
7213 }
7214
7215 if (rsrc_slp != 0xffffffff) {
7216 W_REG(osh, &pmu->rsrc_event0, PMURES_BIT(rsrc_slp));
7217 }
7218
7219 si_setcoreidx(sih, origidx);
7220 }
7221
7222 #define MISC_LDO_STEPPING_DELAY (150u) /* 150 us, includes 50us additional margin */
7223
7224 /** initialize PMU chip controls and other chip level stuff */
7225 void
BCMATTACHFN(si_pmu_chip_init)7226 BCMATTACHFN(si_pmu_chip_init)(si_t *sih, osl_t *osh)
7227 {
7228 ASSERT(sih->cccaps & CC_CAP_PMU);
7229 if (AOB_ENAB(sih)) {
7230 if (hnd_pmur == NULL) {
7231 uint coreidx = si_coreidx(sih);
7232 hnd_pmur = si_setcore(sih, PMU_CORE_ID, 0);
7233 ASSERT(hnd_pmur != NULL);
7234 /* Restore to CC */
7235 si_setcoreidx(sih, coreidx);
7236 }
7237 }
7238
7239 si_pmu_otp_chipcontrol(sih, osh);
7240
7241 #ifdef CHIPC_UART_ALWAYS_ON
7242 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), CCS_FORCEALP, CCS_FORCEALP);
7243 #endif /* CHIPC_UART_ALWAYS_ON */
7244
7245 si_pmu_enb_slp_cnt_on_rsrc(sih, osh);
7246
7247 /* Misc. chip control, has nothing to do with PMU */
7248 switch (CHIPID(sih->chip)) {
7249
7250 case BCM43012_CHIP_ID:
7251 case BCM43013_CHIP_ID:
7252 case BCM43014_CHIP_ID:
7253 {
7254 #ifdef USE_LHL_TIMER
7255 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, PMUCCTL02_43012_LHL_TIMER_SELECT,
7256 PMUCCTL02_43012_LHL_TIMER_SELECT);
7257 #else
7258 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, PMUCCTL02_43012_LHL_TIMER_SELECT, 0);
7259 #endif /* USE_LHL_TIMER */
7260
7261 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, PMUCCTL02_43012_RFLDO3P3_PU_FORCE_ON, 0);
7262 si_pmu_chipcontrol(sih, PMU_CHIPCTL4, PMUCCTL14_43012_DISABLE_LQ_AVAIL, 0);
7263
7264 PMU_REG_NEW(sih, extwakemask0,
7265 PMU_EXT_WAKE_MASK_0_SDIO, PMU_EXT_WAKE_MASK_0_SDIO);
7266 PMU_REG_NEW(sih, extwakereqmask[0], ~0, si_pmu_rsrc_ht_avail_clk_deps(sih, osh));
7267
7268 if (sih->lpflags & LPFLAGS_SI_FORCE_PWM_WHEN_RADIO_ON) {
7269 /* Force PWM when Radio ON */
7270 /* 2G_Listen/2G_RX/2G_TX/5G_Listen/5G_RX/5G_TX = PWM */
7271 si_pmu_vreg_control(sih, PMU_VREG_8,
7272 PMU_43012_VREG8_DYNAMIC_CBUCK_MODE_MASK,
7273 PMU_43012_VREG8_DYNAMIC_CBUCK_MODE0);
7274 si_pmu_vreg_control(sih, PMU_VREG_9,
7275 PMU_43012_VREG9_DYNAMIC_CBUCK_MODE_MASK,
7276 PMU_43012_VREG9_DYNAMIC_CBUCK_MODE0);
7277 }
7278 else {
7279 /* LPPFM opt setting for ePA */
7280 si_pmu_chipcontrol(sih, PMU_CHIPCTL16, PMU_CC16_CLK4M_DIS, 1);
7281 si_pmu_chipcontrol(sih, PMU_CHIPCTL16, PMU_CC16_FF_ZERO_ADJ, 4);
7282 /* 2G_Listen/2G_RX = LPPFM, 2G_TX/5G_Listen/5G_RX/5G_TX = PWM */
7283 si_pmu_vreg_control(sih, PMU_VREG_8,
7284 PMU_43012_VREG8_DYNAMIC_CBUCK_MODE_MASK,
7285 PMU_43012_VREG8_DYNAMIC_CBUCK_MODE1);
7286 si_pmu_vreg_control(sih, PMU_VREG_9,
7287 PMU_43012_VREG9_DYNAMIC_CBUCK_MODE_MASK,
7288 PMU_43012_VREG9_DYNAMIC_CBUCK_MODE1);
7289 }
7290 /* Set external LPO */
7291 si_lhl_set_lpoclk(sih, osh, LHL_LPO_AUTO);
7292
7293 /* Enabling WL2CDIG sleep */
7294 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, PMUCCTL02_43012_WL2CDIG_I_PMU_SLEEP_ENAB,
7295 PMUCCTL02_43012_WL2CDIG_I_PMU_SLEEP_ENAB);
7296
7297 si_pmu_chipcontrol(sih, PMU_CHIPCTL9,
7298 PMUCCTL09_43012_XTAL_CORESIZE_BIAS_ADJ_STARTUP_MASK,
7299 PMUCCTL09_43012_XTAL_CORESIZE_BIAS_ADJ_STARTUP_VAL <<
7300 PMUCCTL09_43012_XTAL_CORESIZE_BIAS_ADJ_STARTUP_SHIFT);
7301
7302 /* Setting MemLPLDO voltage to 0.74 */
7303 si_pmu_vreg_control(sih, PMU_VREG_6, VREG6_43012_MEMLPLDO_ADJ_MASK,
7304 0x8 << VREG6_43012_MEMLPLDO_ADJ_SHIFT);
7305
7306 /* Setting LPLDO voltage to 0.8 */
7307 si_pmu_vreg_control(sih, PMU_VREG_6, VREG6_43012_LPLDO_ADJ_MASK,
7308 0xB << VREG6_43012_LPLDO_ADJ_SHIFT);
7309
7310 /* Turn off power switch 1P8 in sleep */
7311 si_pmu_vreg_control(sih, PMU_VREG_7, VREG7_43012_PWRSW_1P8_PU_MASK, 0);
7312
7313 /* Enable PMU sleep mode0 (DS0-PS0) */
7314 LHL_REG(sih, lhl_top_pwrseq_ctl_adr, ~0, PMU_SLEEP_MODE_0);
7315
7316 si_pmu_fast_lpo_enable(sih, osh);
7317
7318 /* Enable the 'power kill' (power off selected retention memories) */
7319 GCI_REG_NEW(sih, bt_smem_control0, GCI_BT_SMEM_CTRL0_SUBCORE_ENABLE_PKILL,
7320 GCI_BT_SMEM_CTRL0_SUBCORE_ENABLE_PKILL);
7321
7322 break;
7323 }
7324 case BCM4362_CHIP_GRPID:
7325 {
7326 pmuregs_t *pmu = si_setcore(sih, PMU_CORE_ID, 0);
7327 uint32 lpo = LHL_LPO_AUTO;
7328 uint32 lhl_tmr_sel = 0;
7329
7330 /* DMAHANG WAR:SWWLAN:171729
7331 * Stretch the ALP and HT clocks after de-asserting
7332 * the request. During the RX frame transfer from RXFIFO to
7333 * DP FIFO, in certain cases the clock is getting de-asserted
7334 * by ucode as it does not have visibility beyond BM
7335 */
7336 W_REG(osh, &pmu->clkstretch, 0x0fff0fff);
7337
7338 #ifdef USE_LHL_TIMER
7339 lhl_tmr_sel = PMU_CC13_LHL_TIMER_SELECT;
7340 #endif /* USE_LHL_TIMER */
7341 si_pmu_chipcontrol(sih, PMU_CHIPCTL13, PMU_CC13_LHL_TIMER_SELECT, lhl_tmr_sel);
7342
7343 if (R_REG(osh, &pmu->pmustatus) & PST_EXTLPOAVAIL) {
7344 lpo = LHL_EXT_LPO_ENAB;
7345 }
7346
7347 if (!ISSIM_ENAB(sih)) {
7348 si_lhl_set_lpoclk(sih, osh, lpo);
7349 }
7350
7351 if (getintvar(NULL, rstr_btldo3p3pu)) {
7352 si_pmu_regcontrol(sih, 4,
7353 PMU_28NM_VREG4_WL_LDO_CNTL_EN,
7354 PMU_28NM_VREG4_WL_LDO_CNTL_EN);
7355 si_pmu_regcontrol(sih, 6,
7356 PMU_28NM_VREG6_BTLDO3P3_PU,
7357 PMU_28NM_VREG6_BTLDO3P3_PU);
7358 }
7359
7360 /* write the XTAL preferred startup/normal A0/B0 revision */
7361 si_pmu_chipcontrol_xtal_settings_4362(sih);
7362
7363 si_pmu_chipcontrol(sih, PMU_CHIPCTL6,
7364 (PMU_CC6_ENABLE_CLKREQ_WAKEUP | PMU_CC6_ENABLE_PCIE_RETENTION),
7365 (PMU_CC6_ENABLE_CLKREQ_WAKEUP | PMU_CC6_ENABLE_PCIE_RETENTION));
7366
7367 si_pmu_vreg_control(sih, PMU_VREG_8, PMU_4362_VREG8_ASR_OVADJ_LPPFM_MASK,
7368 0x02u << PMU_4362_VREG8_ASR_OVADJ_LPPFM_SHIFT);
7369 si_pmu_vreg_control(sih, PMU_VREG_8, PMU_4362_VREG8_ASR_OVADJ_PFM_MASK,
7370 0x02u << PMU_4362_VREG8_ASR_OVADJ_PFM_SHIFT);
7371 si_pmu_vreg_control(sih, PMU_VREG_8, PMU_4362_VREG8_ASR_OVADJ_PWM_MASK,
7372 0x02u << PMU_4362_VREG8_ASR_OVADJ_PWM_SHIFT);
7373 #if defined(SAVERESTORE)
7374 if (SR_ENAB()) {
7375 si_set_lv_sleep_mode_4362(sih, osh);
7376 }
7377 #endif /* SAVERESTORE */
7378
7379 si_pmu_fast_lpo_enable(sih, osh);
7380 if ((PMUREV(sih->pmurev) >= 33) && FASTLPO_ENAB()) {
7381 /* Enabling FAST_SEQ */
7382 uint8 fastlpo_dis = fastlpo_dis_get();
7383 uint8 fastlpo_pcie_dis = fastlpo_pcie_dis_get();
7384 if (!fastlpo_dis || !fastlpo_pcie_dis) {
7385 PMU_REG(sih, pmucontrol_ext, PCTL_EXT_FASTSEQ_ENAB,
7386 PCTL_EXT_FASTSEQ_ENAB);
7387 }
7388 }
7389
7390 break;
7391 }
7392
7393 case BCM4369_CHIP_GRPID:
7394 {
7395 pmuregs_t *pmu = si_setcore(sih, PMU_CORE_ID, 0);
7396 uint32 lpo = LHL_LPO_AUTO;
7397 uint32 lhl_tmr_sel = 0;
7398
7399 /* DMAHANG WAR:SWWLAN:171729
7400 * Stretch the ALP and HT clocks after de-asserting
7401 * the request. During the RX frame transfer from RXFIFO to
7402 * DP FIFO, in certain cases the clock is getting de-asserted
7403 * by ucode as it does not have visibility beyond BM
7404 */
7405 #ifndef ATE_BUILD
7406 W_REG(osh, &pmu->clkstretch, 0x0fff0fff);
7407 #endif
7408
7409 #ifdef USE_LHL_TIMER
7410 lhl_tmr_sel = PMU_CC13_4369_LHL_TIMER_SELECT;
7411 #endif
7412 si_pmu_chipcontrol(sih, PMU_CHIPCTL13, PMU_CC13_4369_LHL_TIMER_SELECT, lhl_tmr_sel);
7413
7414 if (R_REG(osh, &pmu->pmustatus) & PST_EXTLPOAVAIL) {
7415 lpo = LHL_EXT_LPO_ENAB;
7416 }
7417
7418 if (!ISSIM_ENAB(sih)) {
7419 si_lhl_set_lpoclk(sih, osh, lpo);
7420 }
7421
7422 if (getintvar(NULL, rstr_btldo3p3pu)) {
7423 si_pmu_regcontrol(sih, 4,
7424 PMU_28NM_VREG4_WL_LDO_CNTL_EN,
7425 PMU_28NM_VREG4_WL_LDO_CNTL_EN);
7426 si_pmu_regcontrol(sih, 6,
7427 PMU_28NM_VREG6_BTLDO3P3_PU,
7428 PMU_28NM_VREG6_BTLDO3P3_PU);
7429 }
7430
7431 /* write the XTAL preferred startup/normal A0/B0 revision */
7432 si_pmu_chipcontrol_xtal_settings_4369(sih);
7433
7434 si_pmu_chipcontrol(sih, PMU_CHIPCTL6,
7435 (PMU_CC6_ENABLE_CLKREQ_WAKEUP | PMU_CC6_ENABLE_PCIE_RETENTION),
7436 (PMU_CC6_ENABLE_CLKREQ_WAKEUP | PMU_CC6_ENABLE_PCIE_RETENTION));
7437
7438 /* write the PWRSW CLK start/stop delay only for A0 revision */
7439 if (CHIPREV(sih->chiprev) == 0) {
7440 si_pmu_chipcontrol(sih, PMU_CHIPCTL1, PMU_CC1_PWRSW_CLKSTRSTP_DELAY_MASK,
7441 PMU_CC1_PWRSW_CLKSTRSTP_DELAY);
7442 }
7443
7444 #if defined(SAVERESTORE)
7445 if (SR_ENAB()) {
7446 si_set_lv_sleep_mode_4369(sih, osh);
7447 }
7448 #endif /* SAVERESTORE */
7449
7450 si_pmu_fast_lpo_enable(sih, osh);
7451 #ifdef BCM_LDO3P3_SOFTSTART
7452 if (CHIPID(sih->chip) != BCM4377_CHIP_ID) {
7453 si_pmu_ldo3p3_soft_start_wl_set(sih, osh, 3);
7454 }
7455 #endif
7456 if ((PMUREV(sih->pmurev) >= 33) && FASTLPO_ENAB()) {
7457 /* Enabling FAST_SEQ */
7458 uint8 fastlpo_dis = fastlpo_dis_get();
7459 uint8 fastlpo_pcie_dis = fastlpo_pcie_dis_get();
7460 if (!fastlpo_dis || !fastlpo_pcie_dis) {
7461 PMU_REG(sih, pmucontrol_ext, PCTL_EXT_FASTSEQ_ENAB,
7462 PCTL_EXT_FASTSEQ_ENAB);
7463 }
7464 }
7465
7466 break;
7467 }
7468
7469 CASE_BCM43602_CHIP: /* fall through */
7470 /* Set internal/external LPO */
7471 si_pmu_set_lpoclk(sih, osh);
7472 break;
7473
7474 case BCM4376_CHIP_GRPID:
7475 case BCM4378_CHIP_GRPID:
7476 {
7477 pmuregs_t *pmu = si_setcore(sih, PMU_CORE_ID, 0);
7478 uint32 lpo = LHL_LPO_AUTO;
7479 uint32 lhl_tmr_sel = 0;
7480
7481 #ifdef USE_LHL_TIMER
7482 lhl_tmr_sel = PMU_CC13_4378_LHL_TIMER_SELECT;
7483 #endif
7484 si_pmu_chipcontrol(sih, PMU_CHIPCTL13, PMU_CC13_4378_LHL_TIMER_SELECT, lhl_tmr_sel);
7485
7486 if (R_REG(osh, &pmu->pmustatus) & PST_EXTLPOAVAIL) {
7487 lpo = LHL_EXT_LPO_ENAB;
7488 }
7489
7490 if (!ISSIM_ENAB(sih)) {
7491 si_lhl_set_lpoclk(sih, osh, lpo);
7492 }
7493
7494 /* JIRA: SWWLAN-228979
7495 * BT LDO is required for Aux 2G Tx only. Keep powerd down until Aux is up
7496 */
7497 si_pmu_bt_ldo_pu(sih, FALSE);
7498
7499 /* Updating xtal pmu registers to combat slow powerup issue */
7500 si_pmu_chipcontrol_xtal_settings_4378(sih);
7501
7502 if (LHL_IS_PSMODE_1(sih)) {
7503 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_07,
7504 ((1 << GCI_CC7_AAON_BYPASS_PWRSW_SEL) |
7505 (1 << GCI_CC7_AAON_BYPASS_PWRSW_SEQ_ON)),
7506 0);
7507 }
7508
7509 si_lhl_setup(sih, osh);
7510
7511 /* Setting MemLPLDO voltage */
7512 if (getvar(NULL, rstr_memlpldo_volt) != NULL) {
7513 int memlpldo_volt = getintvar(NULL, rstr_memlpldo_volt);
7514
7515 if (memlpldo_volt >= PMU_VREG5_LPLDO_VOLT_0_90 &&
7516 memlpldo_volt <= PMU_VREG5_LPLDO_VOLT_0_88) {
7517 si_pmu_regcontrol(sih, PMU_VREG_5, VREG5_4378_MEMLPLDO_ADJ_MASK,
7518 memlpldo_volt << VREG5_4378_MEMLPLDO_ADJ_SHIFT);
7519 } else {
7520 PMU_MSG(("Invalid memlpldo value: %d\n", memlpldo_volt));
7521 }
7522 }
7523
7524 /* Setting LPLDO voltage */
7525 if (getvar(NULL, rstr_lpldo_volt) != NULL) {
7526 int lpldo_volt = getintvar(NULL, rstr_lpldo_volt);
7527
7528 if (lpldo_volt >= PMU_VREG5_LPLDO_VOLT_0_90 &&
7529 lpldo_volt <= PMU_VREG5_LPLDO_VOLT_0_88) {
7530 si_pmu_regcontrol(sih, PMU_VREG_5, VREG5_4378_LPLDO_ADJ_MASK,
7531 lpldo_volt << VREG5_4378_LPLDO_ADJ_SHIFT);
7532 } else {
7533 PMU_MSG(("Invalid lpldo value: %d\n", lpldo_volt));
7534 }
7535 }
7536
7537 /* Enable fast LPO */
7538 si_pmu_fast_lpo_enable(sih, osh);
7539
7540 #if defined(SAVERESTORE)
7541 if (SR_ENAB()) {
7542 si_set_lv_sleep_mode_4378(sih, osh);
7543 }
7544 #endif /* SAVERESTORE */
7545
7546 si_pmu_dynamic_clk_switch_enab(sih);
7547
7548 if (CHIPID(sih->chip) == BCM4378_CHIP_GRPID) {
7549 si_pmu_vreg_control(sih, PMU_VREG_0,
7550 VREG0_4378_CSR_VOLT_ADJ_PWM_MASK |
7551 VREG0_4378_CSR_VOLT_ADJ_PFM_MASK |
7552 VREG0_4378_CSR_VOLT_ADJ_LP_PFM_MASK |
7553 VREG0_4378_CSR_OUT_VOLT_TRIM_ADJ_MASK,
7554 (CSR_VOLT_ADJ_PWM_4378 << VREG0_4378_CSR_VOLT_ADJ_PWM_SHIFT) |
7555 (CSR_VOLT_ADJ_PFM_4378 << VREG0_4378_CSR_VOLT_ADJ_PFM_SHIFT) |
7556 (CSR_VOLT_ADJ_LP_PFM_4378 << VREG0_4378_CSR_VOLT_ADJ_LP_PFM_SHIFT) |
7557 (CSR_OUT_VOLT_TRIM_ADJ_4378 <<
7558 VREG0_4378_CSR_OUT_VOLT_TRIM_ADJ_SHIFT));
7559 #ifdef BCM_LDO3P3_SOFTSTART
7560 si_pmu_ldo3p3_soft_start_wl_set(sih, osh, 0x03u);
7561 si_pmu_ldo3p3_soft_start_bt_set(sih, osh, 0x03u);
7562 #endif
7563 } else {
7564 /* 4368 */
7565 int nvcsr;
7566 if ((nvcsr = getintvar(NULL, rstr_csrtune))) {
7567 si_pmu_vreg_control(sih, PMU_VREG_0,
7568 VREG0_4378_CSR_VOLT_ADJ_PWM_MASK |
7569 VREG0_4378_CSR_VOLT_ADJ_PFM_MASK |
7570 VREG0_4378_CSR_VOLT_ADJ_LP_PFM_MASK,
7571 (nvcsr << VREG0_4378_CSR_VOLT_ADJ_PWM_SHIFT) |
7572 (nvcsr << VREG0_4378_CSR_VOLT_ADJ_PFM_SHIFT) |
7573 (nvcsr << VREG0_4378_CSR_VOLT_ADJ_LP_PFM_SHIFT));
7574 }
7575 }
7576 }
7577 break;
7578
7579 case BCM4385_CHIP_GRPID:
7580 case BCM4387_CHIP_GRPID:
7581 {
7582 pmuregs_t *pmu = si_setcore(sih, PMU_CORE_ID, 0);
7583 uint32 lpo = LHL_LPO_AUTO;
7584 uint32 lhl_tmr_sel = 0;
7585 uint32 abuck_volt, cbuck_volt;
7586 uint32 min_mask;
7587 uint32 misc_ldo_volt, curr_misc_ldo_volt, i;
7588
7589 #ifdef DONGLEBUILD
7590 si_set_arm_clkfreq_high(sih);
7591 #endif
7592
7593 if (PMU_FLL_PU_ENAB()) {
7594 min_mask = R_REG(osh, &pmu->min_res_mask) |
7595 PMURES_BIT(RES4387_FAST_LPO_AVAIL) |
7596 PMURES_BIT(RES4387_PMU_LP);
7597 W_REG(osh, &pmu->min_res_mask, min_mask);
7598 }
7599
7600 #ifdef USE_LHL_TIMER
7601 lhl_tmr_sel = PMU_CC13_4387_LHL_TIMER_SELECT;
7602 #endif
7603 si_pmu_chipcontrol(sih, PMU_CHIPCTL13, PMU_CC13_4387_LHL_TIMER_SELECT, lhl_tmr_sel);
7604
7605 #if defined(SAVERESTORE)
7606 if (SR_ENAB()) {
7607 si_set_lv_sleep_mode_4387(sih, osh);
7608 }
7609 #endif /* SAVERESTORE */
7610
7611 if (R_REG(osh, &pmu->pmustatus) & PST_EXTLPOAVAIL) {
7612 lpo = LHL_EXT_LPO_ENAB;
7613 }
7614
7615 if (!ISSIM_ENAB(sih)) {
7616 si_lhl_set_lpoclk(sih, osh, lpo);
7617 }
7618
7619 if (getintvar(NULL, rstr_btldo3p3pu)) {
7620 si_pmu_regcontrol(sih, 4,
7621 PMU_28NM_VREG4_WL_LDO_CNTL_EN,
7622 PMU_28NM_VREG4_WL_LDO_CNTL_EN);
7623 si_pmu_regcontrol(sih, 6,
7624 PMU_4387_VREG6_BTLDO3P3_PU,
7625 PMU_4387_VREG6_BTLDO3P3_PU);
7626 }
7627
7628 if (LHL_IS_PSMODE_1(sih)) {
7629 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_07,
7630 ((1 << GCI_CC7_AAON_BYPASS_PWRSW_SEL) |
7631 (1 << GCI_CC7_AAON_BYPASS_PWRSW_SEQ_ON)),
7632 0);
7633 }
7634
7635 si_lhl_setup(sih, osh);
7636
7637 /* Setting MemLPLDO voltage */
7638 if (getvar(NULL, rstr_memlpldo_volt) != NULL) {
7639 int memlpldo_volt = getintvar(NULL, rstr_memlpldo_volt);
7640
7641 if (memlpldo_volt >= PMU_VREG5_LPLDO_VOLT_0_90 &&
7642 memlpldo_volt <= PMU_VREG5_LPLDO_VOLT_0_88) {
7643 si_pmu_regcontrol(sih, PMU_VREG_5, VREG5_4387_MEMLPLDO_ADJ_MASK,
7644 memlpldo_volt << VREG5_4387_MEMLPLDO_ADJ_SHIFT);
7645 } else {
7646 PMU_MSG(("Invalid memlpldo value: %d\n", memlpldo_volt));
7647 }
7648 }
7649
7650 /* Setting LPLDO voltage */
7651 if (getvar(NULL, rstr_lpldo_volt) != NULL) {
7652 int lpldo_volt = getintvar(NULL, rstr_lpldo_volt);
7653
7654 if (lpldo_volt >= PMU_VREG5_LPLDO_VOLT_0_90 &&
7655 lpldo_volt <= PMU_VREG5_LPLDO_VOLT_0_88) {
7656 si_pmu_regcontrol(sih, PMU_VREG_5, VREG5_4387_LPLDO_ADJ_MASK,
7657 lpldo_volt << VREG5_4387_LPLDO_ADJ_SHIFT);
7658 } else {
7659 PMU_MSG(("Invalid lpldo value: %d\n", lpldo_volt));
7660 }
7661 }
7662
7663 /* Setting misc ldo voltage to 0.85625V but need stepping up */
7664 curr_misc_ldo_volt = (si_pmu_regcontrol(sih, PMU_VREG_5, 0, 0) &
7665 VREG5_4387_MISC_LDO_ADJ_MASK) >> VREG5_4387_MISC_LDO_ADJ_SHIFT;
7666
7667 /* Only after POR, chip default is 0.8V */
7668 if (curr_misc_ldo_volt == PMU_VREG5_MISC_LDO_VOLT_0p800) {
7669 misc_ldo_volt = PMU_VREG5_MISC_LDO_VOLT_0p856; /* 0.85625V */
7670
7671 for (i = PMU_VREG5_MISC_LDO_VOLT_0p818; i <= misc_ldo_volt; i ++) {
7672 si_pmu_regcontrol(sih, PMU_VREG_5, VREG5_4387_MISC_LDO_ADJ_MASK,
7673 i << VREG5_4387_MISC_LDO_ADJ_SHIFT);
7674 OSL_DELAY(MISC_LDO_STEPPING_DELAY);
7675 }
7676 }
7677
7678 /* Enable fast LPO */
7679 si_pmu_fast_lpo_enable(sih, osh);
7680
7681 if (PMU_FLL_PU_ENAB()) {
7682 /* Wait until fast LPO is stable */
7683 OSL_DELAY(500u);
7684 si_pmu_fll_preload_enable(sih);
7685 }
7686
7687 si_pmu_dynamic_clk_switch_enab(sih);
7688
7689 /* HQ settings */
7690 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_25,
7691 0xFFFFFFFF, XTAL_HQ_SETTING_4387);
7692
7693 /* LQ settings */
7694 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_26,
7695 0xFFFFFFFF, XTAL_LQ_SETTING_4387);
7696
7697 /* Enable Radiodig Clk Gating */
7698 si_pmu_chipcontrol(sih, PMU_CHIPCTL13, PMU_CC13_4387_ENAB_RADIO_REG_CLK, 0);
7699
7700 /* Set up HW based switch-off of select BBPLL channels when SCAN-only mode
7701 *
7702 * Assign bbpll_ch_control_grp_pd_trigger_mask = {gci_chip_cntrl[559:554],
7703 * gci_chip_cntrl[543:522], 1'b0, gci_chip_cntrl[521], 1'b0};
7704 */
7705 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_16,
7706 CC_GCI_16_BBPLL_CH_CTRL_GRP_PD_TRIG_1_MASK |
7707 CC_GCI_16_BBPLL_CH_CTRL_GRP_PD_TRIG_24_3_MASK,
7708 (((GRP_PD_TRIGGER_MASK_4387 >> 1) & 0x1) << /* bit 1 */
7709 CC_GCI_16_BBPLL_CH_CTRL_GRP_PD_TRIG_1_SHIFT) |
7710 (((GRP_PD_TRIGGER_MASK_4387 >> 3) & 0x3FFFFF) << /* bit 24:3 */
7711 CC_GCI_16_BBPLL_CH_CTRL_GRP_PD_TRIG_24_3_SHIFT));
7712
7713 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_17,
7714 CC_GCI_17_BBPLL_CH_CTRL_GRP_PD_TRIG_30_25_MASK |
7715 CC_GCI_17_BBPLL_CH_CTRL_EN_MASK,
7716 (((GRP_PD_TRIGGER_MASK_4387 >> 25) & 0x3F) << /* bits 30:25 */
7717 CC_GCI_17_BBPLL_CH_CTRL_GRP_PD_TRIG_30_25_SHIFT) |
7718 CC_GCI_17_BBPLL_CH_CTRL_EN_MASK);
7719
7720 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_20,
7721 CC_GCI_20_BBPLL_CH_CTRL_GRP_MASK,
7722 (GRP_PD_MASK_4387 << CC_GCI_20_BBPLL_CH_CTRL_GRP_SHIFT));
7723
7724 if (CHIPID(sih->chip) == BCM4397_CHIP_GRPID) {
7725 /* For Phy Reg Access configure IHRP access */
7726 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_28,
7727 GCI_CC28_IHRP_SEL_MASK,
7728 0u << GCI_CC28_IHRP_SEL_SHIFT);
7729 }
7730
7731 if (getvar(NULL, rstr_abuck_volt) != NULL) {
7732 abuck_volt = getintvar(NULL, rstr_abuck_volt);
7733 } else {
7734 abuck_volt = ABUCK_VOLT_SW_DEFAULT_4387;
7735 }
7736
7737 if (CHIPID(sih->chip) == BCM4397_CHIP_GRPID) {
7738 /* For Phy Reg Access configure IHRP access */
7739 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_28,
7740 GCI_CC28_IHRP_SEL_MASK,
7741 0u << GCI_CC28_IHRP_SEL_SHIFT);
7742 }
7743
7744 /* For 4397, PMU has only 11 Regulator Registers */
7745 if (sih->chip != BCM4397_CHIP_ID) {
7746 si_pmu_vreg_control(sih, PMU_VREG_13,
7747 PMU_VREG13_ASR_OVADJ_PWM_MASK,
7748 abuck_volt << PMU_VREG13_ASR_OVADJ_PWM_SHIFT);
7749 }
7750 if (BCM_PWR_OPT_ENAB()) {
7751 if (getvar(NULL, rstr_cbuck_volt) != NULL) {
7752 cbuck_volt = getintvar(NULL, rstr_cbuck_volt);
7753 } else {
7754 cbuck_volt = CBUCK_VOLT_SW_DEFAULT_4387;
7755 }
7756
7757 si_pmu_vreg_control(sih, PMU_VREG_0,
7758 VREG0_4378_CSR_VOLT_ADJ_PWM_MASK,
7759 cbuck_volt << VREG0_4378_CSR_VOLT_ADJ_PWM_SHIFT);
7760 }
7761
7762 PMU_REG(sih, pmucontrol_ext, PCTL_EXT_FAST_TRANS_ENAB, PCTL_EXT_FAST_TRANS_ENAB);
7763
7764 if (si_hib_ext_wakeup_isenab(sih)) {
7765 /* pull up common BP */
7766 int rsrc_num = RES4387_CORE_RDY_CB;
7767 uint32 deps = PMURES_BIT(rsrc_num) |
7768 si_pmu_res_deps(sih, osh, pmu, PMURES_BIT(rsrc_num), TRUE);
7769 W_REG(osh, &pmu->extwakereqmask[0], deps);
7770 }
7771
7772 si_pmu_chipcontrol(sih, PMU_CHIPCTL17,
7773 PMU_CC17_SCAN_DIG_SR_CLK_MASK,
7774 SCAN_DIG_SR_CLK_40_MHZ << PMU_CC17_SCAN_DIG_SR_CLK_SHIFT);
7775 }
7776 break;
7777
7778 case BCM4388_CHIP_GRPID:
7779 case BCM4389_CHIP_GRPID:
7780 case BCM4397_CHIP_GRPID:
7781 {
7782 pmuregs_t *pmu = si_setcore(sih, PMU_CORE_ID, 0);
7783 uint32 lpo = LHL_LPO_AUTO;
7784 uint32 lhl_tmr_sel = 0;
7785 uint32 abuck_volt, cbuck_volt;
7786 uint32 min_mask;
7787
7788 if (PMU_FLL_PU_ENAB()) {
7789 min_mask = R_REG(osh, &pmu->min_res_mask) |
7790 PMURES_BIT(RES4389_FAST_LPO_AVAIL) |
7791 PMURES_BIT(RES4389_PMU_LP);
7792 W_REG(osh, &pmu->min_res_mask, min_mask);
7793 }
7794
7795 #ifdef USE_LHL_TIMER
7796 lhl_tmr_sel = PMU_CC13_4387_LHL_TIMER_SELECT;
7797 #endif
7798 si_pmu_chipcontrol(sih, PMU_CHIPCTL13, PMU_CC13_4387_LHL_TIMER_SELECT, lhl_tmr_sel);
7799
7800 #if defined(SAVERESTORE)
7801 if (SR_ENAB()) {
7802 si_set_lv_sleep_mode_4389(sih, osh);
7803 }
7804 #endif /* SAVERESTORE */
7805 /* SET CB2WL Intr PWR Request irrespective of Default value */
7806 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, PMU_CC2_CB2WL_INTR_PWRREQ_EN,
7807 PMU_CC2_CB2WL_INTR_PWRREQ_EN);
7808
7809 if (R_REG(osh, &pmu->pmustatus) & PST_EXTLPOAVAIL) {
7810 lpo = LHL_EXT_LPO_ENAB;
7811 }
7812
7813 if (!ISSIM_ENAB(sih)) {
7814 si_lhl_set_lpoclk(sih, osh, lpo);
7815 }
7816
7817 if (getintvar(NULL, rstr_btldo3p3pu)) {
7818 si_pmu_regcontrol(sih, 4,
7819 PMU_28NM_VREG4_WL_LDO_CNTL_EN,
7820 PMU_28NM_VREG4_WL_LDO_CNTL_EN);
7821 si_pmu_regcontrol(sih, 6,
7822 PMU_4387_VREG6_BTLDO3P3_PU,
7823 PMU_4387_VREG6_BTLDO3P3_PU);
7824 }
7825
7826 if (LHL_IS_PSMODE_1(sih)) {
7827 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_07,
7828 ((1 << GCI_CC7_AAON_BYPASS_PWRSW_SEL) |
7829 (1 << GCI_CC7_AAON_BYPASS_PWRSW_SEQ_ON)),
7830 0);
7831 }
7832
7833 si_lhl_setup(sih, osh);
7834
7835 /* Setting MemLPLDO voltage */
7836 if (getvar(NULL, rstr_memlpldo_volt) != NULL) {
7837 int memlpldo_volt = getintvar(NULL, rstr_memlpldo_volt);
7838
7839 if (memlpldo_volt >= PMU_VREG5_LPLDO_VOLT_0_90 &&
7840 memlpldo_volt <= PMU_VREG5_LPLDO_VOLT_0_88) {
7841 si_pmu_regcontrol(sih, PMU_VREG_5, VREG5_4387_MEMLPLDO_ADJ_MASK,
7842 memlpldo_volt << VREG5_4387_MEMLPLDO_ADJ_SHIFT);
7843 } else {
7844 PMU_MSG(("Invalid memlpldo value: %d\n", memlpldo_volt));
7845 }
7846 }
7847
7848 /* Setting LPLDO voltage */
7849 if (getvar(NULL, rstr_lpldo_volt) != NULL) {
7850 int lpldo_volt = getintvar(NULL, rstr_lpldo_volt);
7851
7852 if (lpldo_volt >= PMU_VREG5_LPLDO_VOLT_0_90 &&
7853 lpldo_volt <= PMU_VREG5_LPLDO_VOLT_0_88) {
7854 si_pmu_regcontrol(sih, PMU_VREG_5, VREG5_4387_LPLDO_ADJ_MASK,
7855 lpldo_volt << VREG5_4387_LPLDO_ADJ_SHIFT);
7856 } else {
7857 PMU_MSG(("Invalid lpldo value: %d\n", lpldo_volt));
7858 }
7859 }
7860
7861 /* Enable fast LPO */
7862 si_pmu_fast_lpo_enable(sih, osh);
7863
7864 if (PMU_FLL_PU_ENAB()) {
7865 /* Wait until fast LPO is stable */
7866 OSL_DELAY(500u);
7867 si_pmu_fll_preload_enable(sih);
7868 }
7869
7870 si_pmu_dynamic_clk_switch_enab(sih);
7871
7872 /* HQ settings */
7873 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_25,
7874 0xFFFFFFFF, XTAL_HQ_SETTING_4387);
7875
7876 /* LQ settings */
7877 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_26,
7878 0xFFFFFFFF, XTAL_LQ_SETTING_4387);
7879
7880 /* Enable Radiodig Clk Gating */
7881 si_pmu_chipcontrol(sih, PMU_CHIPCTL13, PMU_CC13_4387_ENAB_RADIO_REG_CLK, 0);
7882
7883 /* Set up HW based switch-off of select BBPLL channels when SCAN-only mode
7884 *
7885 * Assign bbpll_ch_control_grp_pd_trigger_mask = {gci_chip_cntrl[559:554],
7886 * gci_chip_cntrl[543:522], 1'b0, gci_chip_cntrl[521], 1'b0};
7887 */
7888 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_16,
7889 CC_GCI_16_BBPLL_CH_CTRL_GRP_PD_TRIG_1_MASK |
7890 CC_GCI_16_BBPLL_CH_CTRL_GRP_PD_TRIG_24_3_MASK,
7891 (((GRP_PD_TRIGGER_MASK_4387 >> 1) & 0x1) << /* bit 1 */
7892 CC_GCI_16_BBPLL_CH_CTRL_GRP_PD_TRIG_1_SHIFT) |
7893 (((GRP_PD_TRIGGER_MASK_4387 >> 3) & 0x3FFFFF) << /* bit 24:3 */
7894 CC_GCI_16_BBPLL_CH_CTRL_GRP_PD_TRIG_24_3_SHIFT));
7895
7896 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_17,
7897 CC_GCI_17_BBPLL_CH_CTRL_GRP_PD_TRIG_30_25_MASK |
7898 CC_GCI_17_BBPLL_CH_CTRL_EN_MASK,
7899 (((GRP_PD_TRIGGER_MASK_4387 >> 25) & 0x3F) << /* bits 30:25 */
7900 CC_GCI_17_BBPLL_CH_CTRL_GRP_PD_TRIG_30_25_SHIFT) |
7901 CC_GCI_17_BBPLL_CH_CTRL_EN_MASK);
7902
7903 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_20,
7904 CC_GCI_20_BBPLL_CH_CTRL_GRP_MASK,
7905 (GRP_PD_MASK_4387 << CC_GCI_20_BBPLL_CH_CTRL_GRP_SHIFT));
7906
7907 if (getvar(NULL, rstr_abuck_volt) != NULL) {
7908 abuck_volt = getintvar(NULL, rstr_abuck_volt);
7909 } else {
7910 abuck_volt = ABUCK_VOLT_SW_DEFAULT_4387;
7911 }
7912
7913 if (CHIPID(sih->chip) == BCM4397_CHIP_GRPID) {
7914 /* For Phy Reg Access configure IHRP access */
7915 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_28,
7916 GCI_CC28_IHRP_SEL_MASK,
7917 0u << GCI_CC28_IHRP_SEL_SHIFT);
7918 }
7919
7920 /* For 4397, PMU has only 11 Regulator Registers */
7921 if (sih->chip != BCM4397_CHIP_ID) {
7922 si_pmu_vreg_control(sih, PMU_VREG_13,
7923 PMU_VREG13_ASR_OVADJ_PWM_MASK,
7924 abuck_volt << PMU_VREG13_ASR_OVADJ_PWM_SHIFT);
7925 }
7926
7927 if (BCM_PWR_OPT_ENAB()) {
7928 if (getvar(NULL, rstr_cbuck_volt) != NULL) {
7929 cbuck_volt = getintvar(NULL, rstr_cbuck_volt);
7930 } else {
7931 cbuck_volt = CBUCK_VOLT_SW_DEFAULT_4387;
7932 }
7933
7934 si_pmu_vreg_control(sih, PMU_VREG_0,
7935 VREG0_4378_CSR_VOLT_ADJ_PWM_MASK,
7936 cbuck_volt << VREG0_4378_CSR_VOLT_ADJ_PWM_SHIFT);
7937 }
7938
7939 PMU_REG(sih, pmucontrol_ext, PCTL_EXT_FAST_TRANS_ENAB, PCTL_EXT_FAST_TRANS_ENAB);
7940
7941 if (PMUREV(sih->pmurev) == 39) {
7942 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_04,
7943 CC_GCI_04_4387C0_XTAL_PM_CLK,
7944 CC_GCI_04_4387C0_XTAL_PM_CLK);
7945 }
7946 }
7947 break;
7948
7949 default:
7950 break;
7951 }
7952 } /* si_pmu_chip_init */
7953
7954 /** Reference: http://confluence.broadcom.com/display/WLAN/Open+loop+Calibration+Sequence */
7955 int
si_pmu_openloop_cal(si_t * sih,uint16 currtemp)7956 si_pmu_openloop_cal(si_t *sih, uint16 currtemp)
7957 {
7958 int err = BCME_OK;
7959 switch (CHIPID(sih->chip)) {
7960 case BCM43012_CHIP_ID:
7961 case BCM43013_CHIP_ID:
7962 case BCM43014_CHIP_ID:
7963 err = si_pmu_openloop_cal_43012(sih, currtemp);
7964 break;
7965
7966 default:
7967 PMU_MSG(("si_pmu_openloop_cal: chip not supported!\n"));
7968 break;
7969 }
7970 return err;
7971 }
7972
7973 static int
si_pmu_openloop_cal_43012(si_t * sih,uint16 currtemp)7974 si_pmu_openloop_cal_43012(si_t *sih, uint16 currtemp)
7975 {
7976 int32 a1 = -27, a2 = -15, b1 = 18704, b2 = 7531, a3, y1, y2, b3, y3;
7977 int32 xtal, array_size = 0, dco_code = 0, origidx = 0, pll_reg = 0, err;
7978 bcm_int_bitmask_t intr_val;
7979 pmuregs_t *pmu = NULL;
7980 const pllctrl_data_t *pllctrlreg_update;
7981 const uint32 *pllctrlreg_val;
7982 osl_t *osh = si_osh(sih);
7983 uint32 final_dco_code = si_get_openloop_dco_code(sih);
7984
7985 xtal = si_xtalfreq(sih);
7986 err = BCME_OK;
7987
7988 origidx = si_coreidx(sih);
7989 pmu = si_setcore(sih, PMU_CORE_ID, 0);
7990 if (!pmu) {
7991 PMU_MSG(("si_pmu_openloop_cal_43012: NULL pmu pointer \n"));
7992 err = BCME_ERROR;
7993 goto done;
7994 }
7995
7996 if (final_dco_code == 0) {
7997 currtemp = (currtemp == 0)?-1: currtemp;
7998
7999 SPINWAIT(((si_corereg(sih, SI_CC_IDX,
8000 OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
8001 & CCS_HTAVAIL) != CCS_HTAVAIL), PMU_MAX_TRANSITION_DLY);
8002 ASSERT((si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), 0, 0)
8003 & CCS_HTAVAIL));
8004
8005 /* Stop using PLL clks, by programming the disable_ht_avail */
8006 /* and disable_lq_avail in the pmu chip control bit */
8007 /* Turn Off PLL */
8008 si_pmu_pll_off_43012(sih, osh, pmu);
8009
8010 /* Program PLL for 320MHz VCO */
8011 pllctrlreg_update = pmu1_xtaltab0_43012;
8012 array_size = ARRAYSIZE(pmu1_xtaltab0_43012);
8013 pllctrlreg_val = pmu1_pllctrl_tab_43012_1600mhz;
8014 si_pmu_pllctrlreg_update(sih, osh, pmu, xtal, 100,
8015 pllctrlreg_update, array_size, pllctrlreg_val);
8016
8017 /* Update PLL control register */
8018 /* Set the Update bit (bit 10) in PMU for PLL registers */
8019 OR_REG(osh, &pmu->pmucontrol, PCTL_PLL_PLLCTL_UPD);
8020
8021 /* Turn PLL ON but ensure that force_bbpll_dreset */
8022 /* bit is set , so that PLL 320Mhz clocks cannot be consumed */
8023 si_pmu_pll_on_43012(sih, osh, pmu, 1);
8024
8025 /* Settings to get dco_code on PLL test outputs and then read */
8026 /* from gci chip status */
8027 pll_reg = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG1, 0, 0);
8028 pll_reg = (pll_reg & (~0x3C000)) | (0x4<<14);
8029 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG1, ~0, pll_reg);
8030 OR_REG(osh, &pmu->pmucontrol, PCTL_PLL_PLLCTL_UPD);
8031
8032 pll_reg = pll_reg | (1<<17);
8033 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG1, ~0, pll_reg);
8034 OR_REG(osh, &pmu->pmucontrol, PCTL_PLL_PLLCTL_UPD);
8035
8036 /* Get the DCO code from GCI CHIP STATUS Register 7 , bits 27 downto 16 */
8037 dco_code = (si_gci_chipstatus(sih, GCI_CHIPSTATUS_07));
8038 dco_code = ((dco_code & 0x0FFF0000) >> 16);
8039 dco_code = (dco_code >> 4);
8040
8041 /* The DCO code obtained above and the temperature */
8042 /* sensed at this time will give us the DCO code */
8043 /* that needs to be programmed to ensure VCO does not crosses 160 MHz at 125C */
8044 y1 = ((a1 * currtemp) + b1);
8045 y2 = ((a2 * currtemp) + b2);
8046 dco_code = (dco_code * 100);
8047 b3 = b1 + (((b2-b1)/(y2 - y1)) * (dco_code - y1));
8048 if (b3 > dco_code) {
8049 a3 = (b3 - dco_code) / currtemp;
8050 y3 = b3 - (a3 * 125);
8051 }
8052 else {
8053 a3 = (dco_code - b3) / currtemp;
8054 y3 = b3 + (a3 * 125);
8055 }
8056 y3 = (y3/100);
8057 PMU_MSG(("DCO_CODE = %d\n", y3));
8058
8059 /* Turning ON PLL at 160.1 MHz for Normal Operation */
8060 si_pmu_pll_off_43012(sih, osh, pmu);
8061 pllctrlreg_update = pmu1_xtaltab0_43012;
8062 array_size = ARRAYSIZE(pmu1_xtaltab0_43012);
8063 pllctrlreg_val = pmu1_pllctrl_tab_43012_1600mhz;
8064 si_pmu_pllctrlreg_update(sih, osh, pmu, xtal, 0,
8065 pllctrlreg_update, array_size, pllctrlreg_val);
8066
8067 /* Update PLL control register */
8068 /* Set the Update bit (bit 10) in PMU for PLL registers */
8069 OR_REG(osh, &pmu->pmucontrol, PCTL_PLL_PLLCTL_UPD);
8070
8071 si_pmu_pll_on_43012(sih, osh, pmu, 0);
8072 y3 = (y3 << 4);
8073 final_dco_code = y3;
8074 PMU_MSG(("openloop_dco_code = %x\n", final_dco_code));
8075 }
8076
8077 pll_reg = si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG3, 0, 0);
8078 y3 = (pll_reg >> 16) & 0xFFF;
8079
8080 if (final_dco_code != (uint32)y3) {
8081
8082 /* Program the DCO code to bits 27 */
8083 /* downto 16 of the PLL control 3 register */
8084 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG3,
8085 0x0FFF0000, (final_dco_code << 16));
8086
8087 /* Enable Extra post divison for Open Loop */
8088 /* by writing 1 to bit 14 of above register */
8089 si_pmu_pllcontrol(sih, PMU_PLL_CTRL_REG3, 0x00004000, (1<<14));
8090
8091 /* Update PLL control register */
8092 /* Set the Update bit (bit 10) in PMU for PLL registers */
8093 OR_REG(osh, &pmu->pmucontrol, PCTL_PLL_PLLCTL_UPD);
8094 /* After cal openloop VCO Max=320MHz, Min=240Mhz (with extra margin */
8095 /* 230-220MHz). Update SAVE_RESTORE up/down times accordingly */
8096 W_REG(osh, &pmu->res_table_sel, RES43012_SR_SAVE_RESTORE);
8097 W_REG(osh, &pmu->res_updn_timer, 0x01800180);
8098 }
8099
8100 si_restore_core(sih, origidx, &intr_val);
8101 si_set_openloop_dco_code(sih, final_dco_code);
8102 done:
8103 return err;
8104 }
8105
8106 void
si_pmu_slow_clk_reinit(si_t * sih,osl_t * osh)8107 si_pmu_slow_clk_reinit(si_t *sih, osl_t *osh)
8108 {
8109 #if !defined(BCMDONGLEHOST)
8110 chipcregs_t *cc;
8111 uint origidx;
8112 uint32 xtalfreq;
8113
8114 /* PMU specific initializations */
8115 if (!PMUCTL_ENAB(sih))
8116 return;
8117 /* Remember original core before switch to chipc */
8118 origidx = si_coreidx(sih);
8119 cc = si_setcoreidx(sih, SI_CC_IDX);
8120 ASSERT(cc != NULL);
8121 if (cc == NULL)
8122 return;
8123
8124 xtalfreq = getintvar(NULL, rstr_xtalfreq);
8125 /*
8126 * workaround for chips that don't support external LPO, thus ALP clock
8127 * can not be measured accurately:
8128 */
8129 switch (CHIPID(sih->chip)) {
8130 CASE_BCM43602_CHIP:
8131 xtalfreq = XTAL_FREQ_54MHZ;
8132 break;
8133 default:
8134 break;
8135 }
8136 /* If xtalfreq var not available, try to measure it */
8137 if (xtalfreq == 0)
8138 xtalfreq = si_pmu_measure_alpclk(sih, osh);
8139 si_pmu_enb_slow_clk(sih, osh, xtalfreq);
8140 /* Return to original core */
8141 si_setcoreidx(sih, origidx);
8142 #endif /* !BCMDONGLEHOST */
8143 }
8144
8145 /** initialize PMU registers in case default values proved to be suboptimal */
8146 void
BCMATTACHFN(si_pmu_swreg_init)8147 BCMATTACHFN(si_pmu_swreg_init)(si_t *sih, osl_t *osh)
8148 {
8149 ASSERT(sih->cccaps & CC_CAP_PMU);
8150
8151 switch (CHIPID(sih->chip)) {
8152 CASE_BCM43602_CHIP:
8153 /* adjust PA Vref to 2.80V */
8154 si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_PAREF, 0x0c);
8155 break;
8156 case BCM4378_CHIP_GRPID:
8157 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_04, GPIO_DRIVE_4378_MASK,
8158 GPIO_DRIVE_4378_VAL);
8159 /* fall through */
8160 case BCM4376_CHIP_GRPID:
8161 case BCM4385_CHIP_GRPID:
8162 case BCM4387_CHIP_GRPID:
8163 #ifdef BCM_AVS
8164 if (BCM_AVS_ENAB()) {
8165 si_pmu_set_avs(sih);
8166 }
8167 #endif
8168 break;
8169 default:
8170 break;
8171 }
8172 si_pmu_otp_vreg_control(sih, osh);
8173 } /* si_pmu_swreg_init */
8174
8175 /** Wait for a particular clock level to be on the backplane */
8176 uint32
si_pmu_waitforclk_on_backplane(si_t * sih,osl_t * osh,uint32 clk,uint32 delay_val)8177 si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, uint32 clk, uint32 delay_val)
8178 {
8179 pmuregs_t *pmu;
8180 uint origidx;
8181 uint32 val;
8182
8183 ASSERT(sih->cccaps & CC_CAP_PMU);
8184 /* Remember original core before switch to chipc/pmu */
8185 origidx = si_coreidx(sih);
8186 if (AOB_ENAB(sih)) {
8187 pmu = si_setcore(sih, PMU_CORE_ID, 0);
8188 } else {
8189 pmu = si_setcoreidx(sih, SI_CC_IDX);
8190 }
8191 ASSERT(pmu != NULL);
8192
8193 if (delay_val)
8194 SPINWAIT(((R_REG(osh, &pmu->pmustatus) & clk) != clk), delay_val);
8195 val = R_REG(osh, &pmu->pmustatus) & clk;
8196
8197 /* Return to original core */
8198 si_setcoreidx(sih, origidx);
8199 return (val);
8200 }
8201
8202 #define EXT_ILP_HZ 32768
8203
8204 /**
8205 * Measures the ALP clock frequency in KHz. Returns 0 if not possible.
8206 * Possible only if PMU rev >= 10 and there is an external LPO 32768Hz crystal.
8207 */
8208 uint32
BCMATTACHFN(si_pmu_measure_alpclk)8209 BCMATTACHFN(si_pmu_measure_alpclk)(si_t *sih, osl_t *osh)
8210 {
8211 uint32 alp_khz;
8212 uint32 pmustat_lpo = 0;
8213 pmuregs_t *pmu;
8214 uint origidx;
8215
8216 if (PMUREV(sih->pmurev) < 10)
8217 return 0;
8218
8219 ASSERT(sih->cccaps & CC_CAP_PMU);
8220
8221 /* Remember original core before switch to chipc/pmu */
8222 origidx = si_coreidx(sih);
8223 if (AOB_ENAB(sih)) {
8224 pmu = si_setcore(sih, PMU_CORE_ID, 0);
8225 } else {
8226 pmu = si_setcoreidx(sih, SI_CC_IDX);
8227 }
8228 ASSERT(pmu != NULL);
8229
8230 if ((CHIPID(sih->chip) == BCM43012_CHIP_ID) ||
8231 (CHIPID(sih->chip) == BCM43013_CHIP_ID) ||
8232 (CHIPID(sih->chip) == BCM43014_CHIP_ID) ||
8233 (PMUREV(sih->pmurev) >= 22))
8234 pmustat_lpo = !(R_REG(osh, &pmu->pmucontrol) & PCTL_LPO_SEL);
8235 else
8236 pmustat_lpo = R_REG(osh, &pmu->pmustatus) & PST_EXTLPOAVAIL;
8237
8238 if (pmustat_lpo) {
8239 uint32 ilp_ctr, alp_hz;
8240
8241 /* Enable the reg to measure the freq, in case disabled before */
8242 W_REG(osh, &pmu->pmu_xtalfreq, 1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
8243
8244 /* Delay for well over 4 ILP clocks */
8245 OSL_DELAY(1000);
8246
8247 /* Read the latched number of ALP ticks per 4 ILP ticks */
8248 ilp_ctr = R_REG(osh, &pmu->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
8249
8250 /* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT bit to save power */
8251 W_REG(osh, &pmu->pmu_xtalfreq, 0);
8252
8253 /* Calculate ALP frequency */
8254 alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
8255
8256 /* Round to nearest 100KHz, and at the same time convert to KHz */
8257 alp_khz = (alp_hz + 50000) / 100000 * 100;
8258 } else
8259 alp_khz = 0;
8260
8261 /* Return to original core */
8262 si_setcoreidx(sih, origidx);
8263
8264 return alp_khz;
8265 } /* si_pmu_measure_alpclk */
8266
8267 /** Update min/max resources after SR-ASM download to d11 txfifo */
8268 void
si_pmu_res_minmax_update(si_t * sih,osl_t * osh)8269 si_pmu_res_minmax_update(si_t *sih, osl_t *osh)
8270 {
8271 uint32 min_mask = 0, max_mask = 0;
8272 pmuregs_t *pmu;
8273 uint origidx;
8274 bcm_int_bitmask_t intr_val;
8275
8276 /* Block ints and save current core */
8277 si_introff(sih, &intr_val);
8278 /* Remember original core before switch to chipc/pmu */
8279 origidx = si_coreidx(sih);
8280 if (AOB_ENAB(sih)) {
8281 pmu = si_setcore(sih, PMU_CORE_ID, 0);
8282 } else {
8283 pmu = si_setcoreidx(sih, SI_CC_IDX);
8284 }
8285 ASSERT(pmu != NULL);
8286
8287 switch (CHIPID(sih->chip)) {
8288 CASE_BCM43602_CHIP:
8289 max_mask = 0; /* Only care about min_mask for now */
8290 break;
8291 case BCM43012_CHIP_ID:
8292 case BCM43013_CHIP_ID:
8293 case BCM43014_CHIP_ID:
8294 min_mask = RES43012_PMU_SLEEP;
8295 break;
8296 case BCM4369_CHIP_GRPID:
8297 case BCM4362_CHIP_GRPID:
8298 case BCM4376_CHIP_GRPID:
8299 case BCM4378_CHIP_GRPID:
8300 case BCM4385_CHIP_GRPID:
8301 case BCM4387_CHIP_GRPID:
8302 case BCM4388_CHIP_GRPID:
8303 case BCM4389_CHIP_GRPID:
8304 case BCM4397_CHIP_GRPID:
8305 si_pmu_res_masks(sih, &min_mask, &max_mask);
8306 max_mask = 0; /* Don't need to update max */
8307 break;
8308 default:
8309 break;
8310 }
8311 if (min_mask) {
8312 /* Add min mask dependencies */
8313 min_mask |= si_pmu_res_deps(sih, osh, pmu, min_mask, FALSE);
8314 W_REG(osh, &pmu->min_res_mask, min_mask);
8315 }
8316 if (max_mask) {
8317 max_mask |= si_pmu_res_deps(sih, osh, pmu, max_mask, FALSE);
8318 W_REG(osh, &pmu->max_res_mask, max_mask);
8319 }
8320
8321 si_pmu_wait_for_steady_state(sih, osh, pmu);
8322
8323 /* Return to original core */
8324 si_setcoreidx(sih, origidx);
8325 si_intrrestore(sih, &intr_val);
8326 } /* si_pmu_res_minmax_update */
8327
8328 #ifdef DONGLEBUILD
8329
8330 #define PMUCAP_DUMP_TAG_SIZE_BYTES 4
8331
8332 /* Move the below definitions to .ro_ontrap section so they
8333 * won't be reused when reusing rodata section after trap.
8334 */
8335 static const uint32 BCMPOST_TRAP_RODATA(chipc_regs_to_dump)[] = {
8336 OFFSETOF(chipcregs_t, clk_ctl_st),
8337 OFFSETOF(chipcregs_t, powerctl)
8338 };
8339
8340 static const uint BCMPOST_TRAP_RODATA(pmuregsdump)[] = {
8341 OFFSETOF(pmuregs_t, pmucontrol),
8342 OFFSETOF(pmuregs_t, pmucapabilities),
8343 OFFSETOF(pmuregs_t, pmustatus),
8344 OFFSETOF(pmuregs_t, res_state),
8345 OFFSETOF(pmuregs_t, res_pending),
8346 OFFSETOF(pmuregs_t, pmutimer),
8347 OFFSETOF(pmuregs_t, min_res_mask),
8348 OFFSETOF(pmuregs_t, max_res_mask),
8349 OFFSETOF(pmuregs_t, clkstretch),
8350 OFFSETOF(pmuregs_t, res_req_timer),
8351 OFFSETOF(pmuregs_t, res_req_mask),
8352 OFFSETOF(pmuregs_t, mac_res_req_timer),
8353 OFFSETOF(pmuregs_t, mac_res_req_mask),
8354 OFFSETOF(pmuregs_t, pmuintmask0),
8355 OFFSETOF(pmuregs_t, pmuintstatus),
8356 OFFSETOF(pmuregs_t, pmuintctrl0),
8357 OFFSETOF(pmuregs_t, extwakeupstatus),
8358 OFFSETOF(pmuregs_t, extwakemask0)
8359 };
8360
8361 static const uint BCMPOST_TRAP_RODATA(pmuregsdump_mac_res1)[] = {
8362 OFFSETOF(pmuregs_t, mac_res_req_timer1),
8363 OFFSETOF(pmuregs_t, mac_res_req_mask1)
8364 };
8365
8366 static const uint BCMPOST_TRAP_RODATA(pmuregsdump_mac_res2)[] = {
8367 OFFSETOF(pmuregs_t, mac_res_req_timer2),
8368 OFFSETOF(pmuregs_t, mac_res_req_mask2)
8369 };
8370
8371 static const uint BCMPOST_TRAP_RODATA(pmuregsdump_pmu_int1)[] = {
8372 OFFSETOF(pmuregs_t, pmuintmask1),
8373 OFFSETOF(pmuregs_t, pmuintctrl1)
8374 };
8375
8376 /* Pointer to location in ROdata where PMU registers are stored.
8377 * It is good to avoid re-reading PMU registers as: 1. reading regs is slow
8378 * 2. As part of trap, these registers are dumped to RO data section anyway.
8379 * so why not read directly from ROdata section and send to host?
8380 * these registers will be dumped n RODATA first and then hnd_minidump_pmuegs_dump()
8381 * will pick these up. For it to pick these up, it
8382 * needs to know where they are stored.
8383 */
8384 /* Length of the reg dump containing address, value pair */
8385 #define SI_PMU_REG_DUMP_BASE_SIZE (ARRAYSIZE(pmuregsdump) * 2u * sizeof(uint32))
8386 #define SI_PMU_REG_DUMP_MACRSRC1_SIZE (ARRAYSIZE(pmuregsdump_mac_res1) * 2u * sizeof(uint32))
8387 #define SI_PMU_REG_DUMP_MACRSRC2_SIZE (ARRAYSIZE(pmuregsdump_mac_res2) * 2u * sizeof(uint32))
8388 #define SI_PMU_REG_DUMP_INTRCV1_SIZE (ARRAYSIZE(pmuregsdump_pmu_int1) * 2u * sizeof(uint32))
8389
8390 static uint32 *rodata_pmuregdump_ptr = NULL;
8391
8392 /** size of the buffer needed to store the PMU register dump specifically PMU indirect registers */
8393 uint32
BCMATTACHFN(si_pmu_dump_buf_size_pmucap)8394 BCMATTACHFN(si_pmu_dump_buf_size_pmucap)(si_t *sih)
8395 {
8396 uint32 buf_size = 0;
8397 uint32 pmu_size = 0;
8398 uint32 cnt;
8399
8400 if (PMUREV(sih->pmurev) < 5)
8401 return 0;
8402
8403 /* pmu resources resource mask and resource updown */
8404 cnt = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
8405 if (cnt) {
8406 buf_size += (cnt * 2 * sizeof(uint32)) + PMUCAP_DUMP_TAG_SIZE_BYTES;
8407 }
8408 /* pll controls */
8409 cnt = (sih->pmucaps & PCAP5_PC_MASK) >> PCAP5_PC_SHIFT;
8410 if (cnt) {
8411 buf_size += (cnt * sizeof(uint32)) + PMUCAP_DUMP_TAG_SIZE_BYTES;
8412 }
8413
8414 /* voltage controls */
8415 cnt = (sih->pmucaps & PCAP5_VC_MASK) >> PCAP5_VC_SHIFT;
8416 if (cnt) {
8417 buf_size += (cnt * sizeof(uint32)) + PMUCAP_DUMP_TAG_SIZE_BYTES;
8418 }
8419
8420 /* chip controls */
8421 cnt = (sih->pmucaps & PCAP5_CC_MASK) >> PCAP5_CC_SHIFT;
8422 if (cnt) {
8423 buf_size += (cnt * sizeof(uint32)) + PMUCAP_DUMP_TAG_SIZE_BYTES;
8424 }
8425
8426 /* include chip common regsiters from the list */
8427 /* cnt indicates how many registers, tag_id 0 will say these are address/value */
8428 if (ARRAYSIZE(chipc_regs_to_dump)) {
8429 buf_size += PMUCAP_DUMP_TAG_SIZE_BYTES;
8430 /* address/value pairs */
8431 buf_size += sizeof(chipc_regs_to_dump);
8432 buf_size += sizeof(chipc_regs_to_dump);
8433 }
8434
8435 /* include PMU regsiters from the list 'pmuregsdumpXX' */
8436 if ((PMUREV(sih->pmurev) > 27) && ARRAYSIZE(pmuregsdump) != 0) {
8437 uint8 rsrc_cnt = si_pmu_get_mac_rsrc_req_tmr_cnt(sih);
8438 buf_size += PMUCAP_DUMP_TAG_SIZE_BYTES;
8439 pmu_size += sizeof(pmuregsdump);
8440 if (ARRAYSIZE(pmuregsdump_mac_res1) != 0 && rsrc_cnt > 1) {
8441 buf_size += PMUCAP_DUMP_TAG_SIZE_BYTES;
8442 pmu_size += sizeof(pmuregsdump_mac_res1);
8443 }
8444 if (ARRAYSIZE(pmuregsdump_mac_res2) != 0 && rsrc_cnt > 2) {
8445 buf_size += PMUCAP_DUMP_TAG_SIZE_BYTES;
8446 pmu_size += sizeof(pmuregsdump_mac_res2);
8447 }
8448 if (ARRAYSIZE(pmuregsdump_pmu_int1) != 0 &&
8449 si_pmu_get_pmu_interrupt_rcv_cnt(sih) > 1) {
8450 buf_size += PMUCAP_DUMP_TAG_SIZE_BYTES;
8451 pmu_size += sizeof(pmuregsdump_pmu_int1);
8452 }
8453 /* address/value pairs */
8454 buf_size += (pmu_size << 1);
8455 }
8456
8457 return buf_size;
8458 }
8459
8460 /**
8461 * routine to dump the registers into the user specified buffer
8462 * needed to store the PMU register dump specifically PMU indirect registers
8463 * format is sets of count, base regiser, register values
8464 */
8465 uint32
BCMPOSTTRAPFN(si_pmu_dump_pmucap_binary)8466 BCMPOSTTRAPFN(si_pmu_dump_pmucap_binary)(si_t *sih, uchar *p)
8467 {
8468 uint32 cnt, i;
8469 osl_t *osh;
8470 pmuregs_t *pmu;
8471 uint origidx;
8472 uint mac_res_cnt;
8473 uint pmu_int_rcv_cnt;
8474 uint32 pmu_totalsize = 0;
8475
8476 uint32 *p32 = (uint32 *)p;
8477
8478 if (PMUREV(sih->pmurev) < 5)
8479 return 0;
8480
8481 origidx = si_coreidx(sih);
8482
8483 if (AOB_ENAB(sih)) {
8484 pmu = si_setcore(sih, PMU_CORE_ID, 0);
8485 }
8486 else {
8487 pmu = si_setcoreidx(sih, SI_CC_IDX);
8488 }
8489 ASSERT(pmu != NULL);
8490
8491 osh = si_osh(sih);
8492
8493 cnt = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
8494 if (cnt) {
8495 *p32++ = (cnt << 16 | RSRCTABLEADDR);
8496 for (i = 0; i < cnt; i++) {
8497 W_REG(osh, &pmu->res_table_sel, i);
8498 *p32++ = R_REG(osh, &pmu->res_dep_mask);
8499 *p32++ = R_REG(osh, &pmu->res_updn_timer);
8500 }
8501 }
8502
8503 cnt = (sih->pmucaps & PCAP5_PC_MASK) >> PCAP5_PC_SHIFT;
8504 if (cnt) {
8505 *p32++ = (cnt << 16 | PMU_PLL_CONTROL_ADDR);
8506 for (i = 0; i < cnt; i++) {
8507 *p32++ = si_pmu_pllcontrol(sih, i, 0, 0);
8508 }
8509 }
8510
8511 cnt = (sih->pmucaps & PCAP5_VC_MASK) >> PCAP5_VC_SHIFT;
8512 if (cnt) {
8513 *p32++ = (cnt << 16 | PMU_REG_CONTROL_ADDR);
8514 for (i = 0; i < cnt; i++) {
8515 *p32++ = si_pmu_vreg_control(sih, i, 0, 0);
8516 }
8517 }
8518 cnt = (sih->pmucaps & PCAP5_CC_MASK) >> PCAP5_CC_SHIFT;
8519 if (cnt) {
8520 *p32++ = (cnt << 16 | CC_CHIPCTL_ADDR);
8521 for (i = 0; i < cnt; i++) {
8522 *p32++ = si_pmu_chipcontrol(sih, i, 0, 0);
8523 }
8524 }
8525 if (ARRAYSIZE(chipc_regs_to_dump)) {
8526 uint32 *addr;
8527 *p32++ = (ARRAYSIZE(chipc_regs_to_dump) << 16 | 0);
8528 for (i = 0; i < ARRAYSIZE(chipc_regs_to_dump); i++) {
8529 addr = (uint32 *)(SI_ENUM_BASE(sih) + chipc_regs_to_dump[i]);
8530 *p32++ = (uint32)addr;
8531 *p32++ = R_REG(osh, addr);
8532 }
8533 }
8534
8535 if ((PMUREV(sih->pmurev) > 27)) {
8536 volatile uint32 *addr;
8537 *p32++ = (ARRAYSIZE(pmuregsdump) << 16 | 1);
8538 for (i = 0; i < ARRAYSIZE(pmuregsdump); i++) {
8539 addr = (volatile uint32*)((volatile char*)pmu + pmuregsdump[i]);
8540 *p32++ = (uint32)addr;
8541 *p32++ = R_REG(osh, addr);
8542 }
8543 pmu_totalsize += (ARRAYSIZE(pmuregsdump));
8544 mac_res_cnt = si_pmu_get_mac_rsrc_req_tmr_cnt(sih);
8545 if (mac_res_cnt > 1) {
8546 *p32++ = (ARRAYSIZE(pmuregsdump_mac_res1) << 16 | 1);
8547 for (i = 0; i < ARRAYSIZE(pmuregsdump_mac_res1); i++) {
8548 addr = (volatile uint32*)((volatile char*)pmu +
8549 pmuregsdump_mac_res1[i]);
8550 *p32++ = (uint32)addr;
8551 *p32++ = R_REG(osh, addr);
8552 }
8553 pmu_totalsize += (ARRAYSIZE(pmuregsdump_mac_res1));
8554 }
8555 if (mac_res_cnt > 2) {
8556 *p32++ = (ARRAYSIZE(pmuregsdump_mac_res2) << 16 | 1);
8557 for (i = 0; i < ARRAYSIZE(pmuregsdump_mac_res2); i++) {
8558 addr = (volatile uint32*)((volatile char*)pmu +
8559 pmuregsdump_mac_res2[i]);
8560 *p32++ = (uint32)addr;
8561 *p32++ = R_REG(osh, addr);
8562 }
8563 pmu_totalsize += (ARRAYSIZE(pmuregsdump_mac_res2));
8564 }
8565 pmu_int_rcv_cnt = si_pmu_get_pmu_interrupt_rcv_cnt(sih);
8566 if (pmu_int_rcv_cnt > 1) {
8567 *p32++ = (ARRAYSIZE(pmuregsdump_pmu_int1) << 16 | 1);
8568 for (i = 0; i < ARRAYSIZE(pmuregsdump_pmu_int1); i++) {
8569 addr = (volatile uint32*)((volatile char*)pmu +
8570 pmuregsdump_pmu_int1[i]);
8571 *p32++ = (uint32)addr;
8572 *p32++ = R_REG(osh, addr);
8573 }
8574 pmu_totalsize += (ARRAYSIZE(pmuregsdump_pmu_int1));
8575 }
8576 /* Mark the location where these registers are dumped to avoid a re-read in
8577 * trap context.
8578 */
8579 rodata_pmuregdump_ptr = (p32 - (2 * pmu_totalsize));
8580 }
8581
8582 /* Return to original core */
8583 si_setcoreidx(sih, origidx);
8584 return 1;
8585 } /* si_pmu_dump_pmucap_binary */
8586
8587 #endif /* DONGLEBUILD */
8588 /**
8589 * Function to enable the min_mask with specified resources along with its dependencies.
8590 * Also it can be used for bringing back to the default value of the device.
8591 */
8592 int
si_pmu_min_res_set(si_t * sih,osl_t * osh,uint min_mask,bool set)8593 si_pmu_min_res_set(si_t *sih, osl_t *osh, uint min_mask, bool set)
8594 {
8595 uint32 min_res, max_res;
8596 uint origidx;
8597 bcm_int_bitmask_t intr_val;
8598 pmuregs_t *pmu;
8599
8600 /* Block ints and save current core */
8601 si_introff(sih, &intr_val);
8602
8603 /* Remember original core before switch to chipc */
8604 origidx = si_coreidx(sih);
8605 if (AOB_ENAB(sih)) {
8606 pmu = si_setcore(sih, PMU_CORE_ID, 0);
8607 } else {
8608 pmu = si_setcoreidx(sih, SI_CC_IDX);
8609 }
8610 ASSERT(pmu != NULL);
8611
8612 si_pmu_res_masks(sih, &min_res, &max_res);
8613 min_mask |= si_pmu_res_deps(sih, osh, pmu, min_mask, TRUE);
8614
8615 /*
8616 * If set is enabled, the resources specified in the min_mask is brought up. If not set,
8617 * go to the default min_resource of the device.
8618 */
8619 if (set) {
8620 OR_REG(osh, &pmu->min_res_mask, min_mask);
8621 } else {
8622 min_mask &= ~min_res;
8623 AND_REG(osh, &pmu->min_res_mask, ~min_mask);
8624 }
8625
8626 si_pmu_wait_for_steady_state(sih, osh, pmu);
8627
8628 /* Return to original core */
8629 si_setcoreidx(sih, origidx);
8630 si_intrrestore(sih, &intr_val);
8631
8632 return min_mask;
8633 }
8634
8635 void
si_pmu_bt_ldo_pu(si_t * sih,bool up)8636 si_pmu_bt_ldo_pu(si_t *sih, bool up)
8637 {
8638 si_pmu_regcontrol(sih, PMU_VREG_6, PMU_28NM_VREG6_BTLDO3P3_PU,
8639 (up == TRUE) ? PMU_28NM_VREG6_BTLDO3P3_PU : 0x00);
8640 }
8641
8642 #ifdef BCM_LDO3P3_SOFTSTART
si_pmu_ldo3p3_soft_start_wl_get(si_t * sih,osl_t * osh,int * res)8643 int si_pmu_ldo3p3_soft_start_wl_get(si_t *sih, osl_t *osh, int *res)
8644 {
8645 uint32 bt_or_wl = 0u;
8646 return si_pmu_ldo3p3_soft_start_get(sih, osh, bt_or_wl, res);
8647 }
8648
si_pmu_ldo3p3_soft_start_bt_get(si_t * sih,osl_t * osh,int * res)8649 int si_pmu_ldo3p3_soft_start_bt_get(si_t *sih, osl_t *osh, int *res)
8650 {
8651 uint32 bt_or_wl = 1u;
8652 return si_pmu_ldo3p3_soft_start_get(sih, osh, bt_or_wl, res);
8653 }
8654
8655 static int
si_pmu_soft_start_params(si_t * sih,uint32 bt_or_wl,uint * en_reg,uint32 * en_shift,uint32 * en_mask,uint32 * en_val,uint * val_reg,uint32 * val_shift,uint32 * val_mask)8656 si_pmu_soft_start_params(si_t *sih, uint32 bt_or_wl, uint *en_reg, uint32 *en_shift,
8657 uint32 *en_mask, uint32 *en_val, uint *val_reg, uint32 *val_shift, uint32 *val_mask)
8658 {
8659 switch (CHIPID(sih->chip)) {
8660 case BCM4369_CHIP_GRPID:
8661 *en_reg = SOFT_START_EN_REG_4369;
8662 *en_shift = SOFT_START_EN_SHIFT_4369(bt_or_wl);
8663 *en_mask = SOFT_START_EN_MASK_4369;
8664 *en_val = SOFT_START_EN_VALUE_4369;
8665 *val_reg = SLEW_RATE_VALUE_REG_4369;
8666 *val_shift = SLEW_RATE_SHIFT_4369(bt_or_wl);
8667 *val_mask = SLEW_RATE_MASK_4369;
8668 break;
8669 case BCM4376_CHIP_GRPID:
8670 case BCM4378_CHIP_GRPID:
8671 *en_reg = SOFT_START_EN_REG_4378;
8672 *en_shift = SOFT_START_EN_SHIFT_4378(bt_or_wl);
8673 *en_mask = SOFT_START_EN_MASK_4378;
8674 *en_val = SOFT_START_EN_VALUE_4378;
8675 *val_reg = SLEW_RATE_VALUE_REG_4378;
8676 *val_shift = SLEW_RATE_SHIFT_4378(bt_or_wl);
8677 *val_mask = SLEW_RATE_MASK_4378;
8678 if (BCM4378_CHIP(sih->chip) && PMUREV(sih->pmurev) == 37) {
8679 *en_val = SOFT_START_EN_VALUE_4378_REV37;
8680 }
8681 break;
8682 case BCM4387_CHIP_GRPID:
8683 if (bt_or_wl == 0) {
8684 return BCME_UNSUPPORTED;
8685 }
8686 *en_reg = SOFT_START_EN_REG_4387;
8687 *en_shift = SOFT_START_EN_SHIFT_4387(bt_or_wl);
8688 *en_mask = SOFT_START_EN_MASK_4387;
8689 *en_val = SOFT_START_EN_VALUE_4387;
8690 *val_reg = SLEW_RATE_VALUE_REG_4387;
8691 *val_shift = SLEW_RATE_SHIFT_4387(bt_or_wl);
8692 *val_mask = SLEW_RATE_MASK_4387;
8693 break;
8694 default:
8695 /* Add support */
8696 ASSERT(0);
8697 break;
8698 }
8699 return BCME_OK;
8700 }
8701
si_pmu_ldo3p3_soft_start_get(si_t * sih,osl_t * osh,uint32 bt_or_wl,int * res)8702 static int si_pmu_ldo3p3_soft_start_get(si_t *sih, osl_t *osh, uint32 bt_or_wl, int *res)
8703 {
8704 uint en_reg = 0, val_reg = 0;
8705 uint32 en_shift = 0, en_mask = 0, en_val = 0, val_shift = 0, val_mask = 0;
8706 uint32 soft_start_en, slew_rate;
8707 int ret = si_pmu_soft_start_params(sih, bt_or_wl, &en_reg, &en_shift, &en_mask, &en_val,
8708 &val_reg, &val_shift, &val_mask);
8709
8710 if (BCME_OK != ret) {
8711 return ret;
8712 }
8713 soft_start_en = (si_pmu_vreg_control(sih, en_reg, 0, 0) >> en_shift);
8714 soft_start_en &= en_mask;
8715 if (en_val == 0u) {
8716 soft_start_en = !soft_start_en;
8717 }
8718 if (soft_start_en) {
8719 slew_rate = (si_pmu_vreg_control(sih, val_reg, 0, 0) >> val_shift);
8720 slew_rate &= val_mask;
8721 *res = slew_rate;
8722 } else {
8723 *res = -1;
8724 }
8725 return BCME_OK;
8726 }
8727
si_pmu_ldo3p3_soft_start_wl_set(si_t * sih,osl_t * osh,uint32 slew_rate)8728 int si_pmu_ldo3p3_soft_start_wl_set(si_t *sih, osl_t *osh, uint32 slew_rate)
8729 {
8730 uint32 bt_or_wl = 0u;
8731 return si_pmu_ldo3p3_soft_start_set(sih, osh, bt_or_wl, slew_rate);
8732 }
8733
si_pmu_ldo3p3_soft_start_bt_set(si_t * sih,osl_t * osh,uint32 slew_rate)8734 int si_pmu_ldo3p3_soft_start_bt_set(si_t *sih, osl_t *osh, uint32 slew_rate)
8735 {
8736 uint32 bt_or_wl = 1u;
8737 return si_pmu_ldo3p3_soft_start_set(sih, osh, bt_or_wl, slew_rate);
8738 }
8739
si_pmu_ldo3p3_soft_start_set(si_t * sih,osl_t * osh,uint32 bt_or_wl,uint32 slew_rate)8740 static int si_pmu_ldo3p3_soft_start_set(si_t *sih, osl_t *osh, uint32 bt_or_wl, uint32 slew_rate)
8741 {
8742 uint en_reg = 0, val_reg = 0;
8743 uint32 en_shift = 0, en_mask = 0, en_val = 0, val_shift = 0, val_mask = 0;
8744 int ret = si_pmu_soft_start_params(sih, bt_or_wl, &en_reg, &en_shift, &en_mask, &en_val,
8745 &val_reg, &val_shift, &val_mask);
8746 uint32 dis_val = en_val ? 0u : 1u;
8747
8748 if (BCME_OK != ret) {
8749 return ret;
8750 }
8751
8752 if (slew_rate != (uint32)(~0u)) {
8753
8754 /* Without disabling soft start bit
8755 * programming a new slew rate value
8756 * doesn't take effect
8757 */
8758
8759 /* Disable soft start */
8760 si_pmu_vreg_control(sih, en_reg, (en_mask << en_shift), (dis_val << en_shift));
8761
8762 /* Program Slew rate */
8763 si_pmu_vreg_control(sih, val_reg, (val_mask << val_shift),
8764 ((slew_rate & val_mask) << val_shift));
8765
8766 /* Enable Soft start */
8767 si_pmu_vreg_control(sih, en_reg, (en_mask << en_shift), (en_val << en_shift));
8768 } else {
8769 /* Slew rate value of 0xFFFF is used as a special value
8770 * to disable/reset soft start feature
8771 */
8772
8773 /* Disable soft start */
8774 si_pmu_vreg_control(sih, en_reg, (en_mask << en_shift), (dis_val << en_shift));
8775
8776 /* Set slew rate value to zero */
8777 si_pmu_vreg_control(sih, val_reg, (val_mask << val_shift), 0u);
8778 }
8779 return BCME_OK;
8780 }
8781 #endif /* BCM_LDO3P3_SOFTSTART */
8782
8783 #ifdef LDO3P3_MIN_RES_MASK
8784 static bool ldo3p3_min_res_enabled = FALSE;
8785 /** Set ldo 3.3V mask in the min resources mask register */
8786 int
si_pmu_min_res_ldo3p3_set(si_t * sih,osl_t * osh,bool on)8787 si_pmu_min_res_ldo3p3_set(si_t *sih, osl_t *osh, bool on)
8788 {
8789 uint32 min_mask = 0;
8790 uint coreidx = si_findcoreidx(sih, GCI_CORE_ID, 0);
8791
8792 switch (CHIPID(sih->chip)) {
8793 case BCM4369_CHIP_GRPID:
8794 case BCM4362_CHIP_GRPID:
8795 min_mask = PMURES_BIT(RES4369_LDO3P3_PU);
8796 if (on) {
8797 si_corereg(sih, coreidx, LHL_REG_OFF(lhl_lp_main_ctl1_adr),
8798 BCM_MASK32(23, 0), 0x9E9F9F);
8799 } else {
8800 si_corereg(sih, coreidx, LHL_REG_OFF(lhl_lp_main_ctl1_adr),
8801 BCM_MASK32(23, 0), 0x9E9F97);
8802 }
8803 break;
8804 case BCM4376_CHIP_GRPID:
8805 case BCM4378_CHIP_GRPID:
8806 min_mask = PMURES_BIT(RES4378_LDO3P3_PU);
8807 break;
8808 default:
8809 return BCME_UNSUPPORTED;
8810 }
8811
8812 si_pmu_min_res_set(sih, osh, min_mask, on);
8813 ldo3p3_min_res_enabled = on;
8814
8815 return BCME_OK;
8816 }
8817
8818 int
si_pmu_min_res_ldo3p3_get(si_t * sih,osl_t * osh,int * res)8819 si_pmu_min_res_ldo3p3_get(si_t *sih, osl_t *osh, int *res)
8820 {
8821 *res = (int)ldo3p3_min_res_enabled;
8822 return BCME_OK;
8823 }
8824 #endif /* LDO3P3_MIN_RES_MASK */
8825 int
si_pmu_min_res_otp_pu_set(si_t * sih,osl_t * osh,bool on)8826 si_pmu_min_res_otp_pu_set(si_t *sih, osl_t *osh, bool on)
8827 {
8828 uint32 min_mask = 0;
8829 rsc_per_chip_t *rsc;
8830
8831 rsc = si_pmu_get_rsc_positions(sih);
8832 if (rsc) {
8833 min_mask = PMURES_BIT(rsc->otp_pu);
8834 } else {
8835 return BCME_UNSUPPORTED;
8836 }
8837 si_pmu_min_res_set(sih, osh, min_mask, on);
8838 return BCME_OK;
8839 }
8840 #endif /* !defined(BCMDONGLEHOST) */
8841
8842 uint32
BCMPOSTTRAPFN(si_pmu_wake_bit_offset)8843 BCMPOSTTRAPFN(si_pmu_wake_bit_offset)(si_t *sih)
8844 {
8845 uint32 wakebit;
8846
8847 switch (CHIPID(sih->chip)) {
8848 case BCM4369_CHIP_GRPID:
8849 wakebit = PMU_CC2_GCI2_WAKE;
8850 break;
8851 case BCM4376_CHIP_GRPID:
8852 case BCM4378_CHIP_GRPID:
8853 wakebit = CC2_4378_GCI2WAKE_MASK;
8854 break;
8855 case BCM4385_CHIP_GRPID:
8856 case BCM4387_CHIP_GRPID:
8857 wakebit = CC2_4387_GCI2WAKE_MASK;
8858 break;
8859 case BCM4388_CHIP_GRPID:
8860 case BCM4389_CHIP_GRPID:
8861 case BCM4397_CHIP_GRPID:
8862 wakebit = CC2_4389_GCI2WAKE_MASK;
8863 break;
8864 default:
8865 wakebit = 0;
8866 ASSERT(0);
8867 break;
8868 }
8869
8870 return wakebit;
8871 }
8872
8873 #ifdef ATE_BUILD
hnd_pmu_clr_int_sts_req_active(osl_t * hnd_osh,si_t * sih)8874 void hnd_pmu_clr_int_sts_req_active(osl_t *hnd_osh, si_t *sih)
8875 {
8876 uint32 res_req_timer;
8877 pmuregs_t *pmu;
8878 if (AOB_ENAB(sih)) {
8879 pmu = si_setcore(sih, PMU_CORE_ID, 0);
8880 } else {
8881 pmu = si_setcoreidx(sih, SI_CC_IDX);
8882 }
8883 ASSERT(pmu != NULL);
8884 W_REG(hnd_osh, &pmu->pmuintstatus,
8885 RSRC_INTR_MASK_TIMER_INT_0);
8886 (void)R_REG(hnd_osh, &pmu->pmuintstatus);
8887 res_req_timer = R_REG(hnd_osh, &pmu->res_req_timer);
8888 W_REG(hnd_osh, &pmu->res_req_timer,
8889 res_req_timer & ~(PRRT_REQ_ACTIVE << flags_shift));
8890 (void)R_REG(hnd_osh, &pmu->res_req_timer);
8891 }
8892 #endif /* ATE_BUILD */
8893
si_pmu_set_min_res_mask(si_t * sih,osl_t * osh,uint min_res_mask)8894 void si_pmu_set_min_res_mask(si_t *sih, osl_t *osh, uint min_res_mask)
8895 {
8896 pmuregs_t *pmu;
8897 uint origidx;
8898
8899 /* Remember original core before switch to chipc/pmu */
8900 origidx = si_coreidx(sih);
8901 if (AOB_ENAB(sih)) {
8902 pmu = si_setcore(sih, PMU_CORE_ID, 0);
8903 }
8904 else {
8905 pmu = si_setcoreidx(sih, SI_CC_IDX);
8906 }
8907 ASSERT(pmu != NULL);
8908
8909 W_REG(osh, &pmu->min_res_mask, min_res_mask);
8910 OSL_DELAY(100);
8911
8912 /* Return to original core */
8913 si_setcoreidx(sih, origidx);
8914 }
8915
8916 bool
si_pmu_cap_fast_lpo(si_t * sih)8917 si_pmu_cap_fast_lpo(si_t *sih)
8918 {
8919 return (PMU_REG(sih, core_cap_ext, 0, 0) & PCAP_EXT_USE_MUXED_ILP_CLK_MASK) ? TRUE : FALSE;
8920 }
8921
8922 int
si_pmu_fast_lpo_disable(si_t * sih)8923 si_pmu_fast_lpo_disable(si_t *sih)
8924 {
8925 if (!si_pmu_cap_fast_lpo(sih)) {
8926 PMU_ERROR(("si_pmu_fast_lpo_disable: No Fast LPO capability\n"));
8927 return BCME_ERROR;
8928 }
8929
8930 PMU_REG(sih, pmucontrol_ext,
8931 PCTL_EXT_FASTLPO_ENAB |
8932 PCTL_EXT_FASTLPO_SWENAB |
8933 PCTL_EXT_FASTLPO_PCIE_SWENAB,
8934 0);
8935 OSL_DELAY(1000);
8936 return BCME_OK;
8937 }
8938
8939 /*
8940 * 4389B0/C0 - WL and BT turn on WAR,
8941 * set below bits in PMU chip control 6
8942 * - global bit[195] / bit[3] - enable legacy pmu_wakeup to make
8943 * domain 1 (WL) power request
8944 * - global bit[206] / bit[14] - perst_wake_en
8945 */
8946 void
si_pmu_dmn1_perst_wakeup(si_t * sih,bool set)8947 si_pmu_dmn1_perst_wakeup(si_t *sih, bool set)
8948 {
8949 if (PMUREV(sih->pmurev) == 40) {
8950 if (set) {
8951 si_pmu_chipcontrol(sih, PMU_CHIPCTL6,
8952 (PMU_CC6_ENABLE_DMN1_WAKEUP |
8953 PMU_CC6_ENABLE_PMU_WAKEUP_PERST),
8954 (PMU_CC6_ENABLE_DMN1_WAKEUP |
8955 PMU_CC6_ENABLE_PMU_WAKEUP_PERST));
8956 } else {
8957 si_pmu_chipcontrol(sih, PMU_CHIPCTL6,
8958 (PMU_CC6_ENABLE_DMN1_WAKEUP |
8959 PMU_CC6_ENABLE_PMU_WAKEUP_PERST),
8960 0);
8961 }
8962 }
8963 }
8964
8965 #if !defined(BCMDONGLEHOST)
8966
8967 /* write :
8968 * TRUE - Programs the PLLCTRL6 with xtal and returns value written in pllctrl6 register.
8969 * FALSE - returns 0 if xtal programming is same as pllctrl6 register else retruns value of
8970 * pllctrl6 val. This will not program any register.
8971 */
8972 static uint32
si_pmu_pll6val_armclk_calc(osl_t * osh,pmuregs_t * pmu,uint32 armclk,uint32 xtal,bool write)8973 si_pmu_pll6val_armclk_calc(osl_t *osh, pmuregs_t *pmu, uint32 armclk, uint32 xtal, bool write)
8974 {
8975 uint32 q, r;
8976 uint32 xtal_scale;
8977 uint32 pll6val;
8978 if (armclk == 0 || xtal == 0) {
8979 PMU_ERROR((" si_pmu_pll6val_armclk_calc: invalid armclk = %d or xtal = %d\n",
8980 armclk, xtal));
8981 return 0;
8982 }
8983 q = (armclk * 1000 * PMU4369_PLL6VAL_P1DIV) / xtal;
8984 xtal_scale = xtal / 100;
8985 r = ((armclk * 10 * PMU4369_PLL6VAL_P1DIV * PMU4369_PLL6VAL_PRE_SCALE) / xtal_scale) -
8986 (q * PMU4369_PLL6VAL_PRE_SCALE);
8987 r *= PMU4369_PLL6VAL_POST_SCALE;
8988
8989 pll6val = (r << PMU4369_PLL1_PC6_NDIV_FRAC_SHIFT) |
8990 (q << PMU4369_PLL1_PC6_NDIV_INT_SHIFT) | PMU4369_PLL6VAL_P1DIV_BIT3_2;
8991
8992 PMU_MSG(("si_pmu_pll6val_armclk_calc, armclk %d, xtal %d, q %d, r 0x%8x, pll6val 0x%8x\n",
8993 armclk, xtal, q, r, pll6val));
8994
8995 if (write) {
8996 W_REG(osh, &pmu->pllcontrol_addr, PMU1_PLL0_PLLCTL6);
8997 W_REG(osh, &pmu->pllcontrol_data, pll6val);
8998 } else {
8999 W_REG(osh, &pmu->pllcontrol_addr, PMU1_PLL0_PLLCTL6);
9000 if (pll6val == R_REG(osh, &pmu->pllcontrol_data))
9001 return 0;
9002 }
9003
9004 return pll6val;
9005 }
9006
9007 static void
BCMATTACHFN(si_pmu_chipcontrol_xtal_settings_4369)9008 BCMATTACHFN(si_pmu_chipcontrol_xtal_settings_4369)(si_t *sih)
9009 {
9010
9011 /* 4369 XTAL Bias settings */
9012 /*
9013 Reg name startup Normal
9014 xtal_bias_adj 0xFF 0x1A
9015 xtal_coresize_nmos 0x3f 0x3f
9016 xtal_coresize_pmos 0x3f 0x3f
9017 xtal_sel_bias_res 0x2 0x6
9018 xt_res_bypass 0x0 0x1
9019 */
9020 uint32 u32Val;
9021 uint32 u32Mask;
9022 u32Val = (PMU_CC0_4369B0_XTALCORESIZE_BIAS_ADJ_NORMAL_VAL |
9023 PMU_CC0_4369_XTAL_RES_BYPASS_NORMAL_VAL);
9024
9025 u32Mask = (PMU_CC0_4369_XTALCORESIZE_BIAS_ADJ_NORMAL_MASK |
9026 PMU_CC0_4369_XTAL_RES_BYPASS_NORMAL_MASK);
9027
9028 si_pmu_chipcontrol(sih, PMU_CHIPCTL0, u32Mask, u32Val);
9029
9030 u32Val = (PMU_CC2_4369_XTALCORESIZE_BIAS_ADJ_NORMAL_VAL);
9031 u32Mask = (PMU_CC2_4369_XTALCORESIZE_BIAS_ADJ_NORMAL_MASK);
9032 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, u32Mask, u32Val);
9033
9034 u32Val = (PMU_CC3_4369_XTALCORESIZE_PMOS_NORMAL_VAL |
9035 PMU_CC3_4369_XTALCORESIZE_NMOS_NORMAL_VAL |
9036 PMU_CC3_4369_XTALSEL_BIAS_RES_NORMAL_VAL);
9037
9038 u32Mask = (PMU_CC3_4369_XTALCORESIZE_PMOS_NORMAL_MASK |
9039 PMU_CC3_4369_XTALCORESIZE_NMOS_NORMAL_MASK |
9040 PMU_CC3_4369_XTALSEL_BIAS_RES_NORMAL_MASK);
9041
9042 si_pmu_chipcontrol(sih, PMU_CHIPCTL3, u32Mask, u32Val);
9043
9044 }
9045
9046 static void
BCMATTACHFN(si_pmu_chipcontrol_xtal_settings_4362)9047 BCMATTACHFN(si_pmu_chipcontrol_xtal_settings_4362)(si_t *sih)
9048 {
9049 /* 4369 XTAL Bias settings */
9050 /*
9051 Reg name startup Normal
9052 xtal_bias_adj 0xFF 0x1A
9053 xtal_coresize_nmos 0x3f 0x3f
9054 xtal_coresize_pmos 0x3f 0x3f
9055 xtal_sel_bias_res 0x2 0x6
9056 xt_res_bypass 0x0 0x1
9057 */
9058 uint32 u32Val;
9059 uint32 u32Mask;
9060 u32Val = (PMU_CC0_4362_XTALCORESIZE_BIAS_ADJ_NORMAL_VAL |
9061 PMU_CC0_4362_XTAL_RES_BYPASS_NORMAL_VAL);
9062
9063 u32Mask = (PMU_CC0_4362_XTALCORESIZE_BIAS_ADJ_NORMAL_MASK |
9064 PMU_CC0_4362_XTAL_RES_BYPASS_NORMAL_MASK);
9065
9066 si_pmu_chipcontrol(sih, PMU_CHIPCTL0, u32Mask, u32Val);
9067
9068 u32Val = (PMU_CC2_4362_XTALCORESIZE_BIAS_ADJ_NORMAL_VAL);
9069 u32Mask = (PMU_CC2_4362_XTALCORESIZE_BIAS_ADJ_NORMAL_MASK);
9070 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, u32Mask, u32Val);
9071
9072 u32Val = (PMU_CC3_4362_XTALCORESIZE_PMOS_NORMAL_VAL |
9073 PMU_CC3_4362_XTALCORESIZE_NMOS_NORMAL_VAL |
9074 PMU_CC3_4362_XTALSEL_BIAS_RES_NORMAL_VAL);
9075
9076 u32Mask = (PMU_CC3_4362_XTALCORESIZE_PMOS_NORMAL_MASK |
9077 PMU_CC3_4362_XTALCORESIZE_NMOS_NORMAL_MASK |
9078 PMU_CC3_4362_XTALSEL_BIAS_RES_NORMAL_MASK);
9079
9080 si_pmu_chipcontrol(sih, PMU_CHIPCTL3, u32Mask, u32Val);
9081
9082 }
9083
9084 /* 4378 based on 4369 XTAL Bias settings
9085 * Reg name startup Normal
9086 * xtal_bias_adj 0xFF 0x1A
9087 * xtal_coresize_nmos 0x3f 0x3f
9088 * xtal_coresize_pmos 0x3f 0x3f
9089 * xtal_sel_bias_res 0x2 0x2
9090 * xt_res_bypass 0x0 0x2
9091 */
9092 static void
BCMATTACHFN(si_pmu_chipcontrol_xtal_settings_4378)9093 BCMATTACHFN(si_pmu_chipcontrol_xtal_settings_4378)(si_t *sih)
9094 {
9095 uint32 u32Val;
9096 uint32 u32Mask;
9097 uint16 xtal_bias_adj;
9098 uint8 xtal_bias_adj_otp = 0, xtal_bias_cal_otp_done = 0;
9099
9100 #ifdef XTAL_BIAS_FROM_OTP
9101 /* Read xtal bias cal done bit and xtal biase from OTP */
9102 si_pmu_chipcontrol_xtal_bias_from_otp(sih, &xtal_bias_cal_otp_done, &xtal_bias_adj_otp);
9103 #endif /* XTAL_BIAS_FROM_OTP */
9104
9105 /*
9106 * If xtal_bias_cal_done flag is read as non zero, write the xtal biase in PMU control
9107 * register from OTP otherwise write the default value of 0x1a.
9108 */
9109 xtal_bias_adj = (uint16)xtal_bias_adj_otp;
9110 xtal_bias_adj = xtal_bias_cal_otp_done != 0 ? (xtal_bias_adj << 6) :
9111 PMU_CC0_4378_XTALCORESIZE_BIAS_ADJ_NORMAL_VAL;
9112
9113 u32Val = (xtal_bias_adj | PMU_CC0_4378_XTAL_RES_BYPASS_NORMAL_VAL);
9114
9115 u32Mask = (PMU_CC0_4378_XTALCORESIZE_BIAS_ADJ_NORMAL_MASK |
9116 PMU_CC0_4378_XTAL_RES_BYPASS_NORMAL_MASK);
9117
9118 si_pmu_chipcontrol(sih, PMU_CHIPCTL0, u32Mask, u32Val);
9119
9120 u32Val = (PMU_CC2_4378_XTALCORESIZE_BIAS_ADJ_NORMAL_VAL);
9121 u32Mask = (PMU_CC2_4378_XTALCORESIZE_BIAS_ADJ_NORMAL_MASK);
9122 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, u32Mask, u32Val);
9123
9124 u32Val = (PMU_CC3_4378_XTALCORESIZE_PMOS_NORMAL_VAL |
9125 PMU_CC3_4378_XTALCORESIZE_NMOS_NORMAL_VAL |
9126 PMU_CC3_4378_XTALSEL_BIAS_RES_NORMAL_VAL);
9127
9128 u32Mask = (PMU_CC3_4378_XTALCORESIZE_PMOS_NORMAL_MASK |
9129 PMU_CC3_4378_XTALCORESIZE_NMOS_NORMAL_MASK |
9130 PMU_CC3_4378_XTALSEL_BIAS_RES_NORMAL_MASK);
9131
9132 si_pmu_chipcontrol(sih, PMU_CHIPCTL3, u32Mask, u32Val);
9133
9134 }
9135
9136 #ifdef XTAL_BIAS_FROM_OTP
9137 static void
BCMATTACHFN(si_pmu_chipcontrol_xtal_bias_from_otp)9138 BCMATTACHFN(si_pmu_chipcontrol_xtal_bias_from_otp)(si_t *sih, uint8* flag, uint8* val)
9139 {
9140 uint8 xtal_bias_adj = 0, xtal_bias_cal_otp_done = 0;
9141 #ifndef BCM_OTP_API
9142 uint16 datum, offset;
9143 uint8 shift, mask;
9144 #endif /* !BCM_OTP_API */
9145
9146 /* Read the XTAL BIAS CAL value from OTP.
9147 * 1) Read the xtal cal done bit and the xtal biase value from OTP.
9148 * 2) OTP memory is zero by default, so the chips which aren't OTP programmed will read a
9149 * '0' for xtal_bias_cal_otp_done.
9150 */
9151 #ifdef BCM_OTP_API
9152 otp_read_8b_field(sih, BCM_OTP_FLD_XTAL_BIAS_FLAG, &xtal_bias_cal_otp_done);
9153 if (xtal_bias_cal_otp_done) {
9154 otp_read_8b_field(sih, BCM_OTP_FLD_XTAL_BIAS_ADJ, &xtal_bias_adj);
9155 }
9156 #else
9157 si_pmu_chipcontrol_xtal_bias_cal_done_offsets(sih, &offset, &shift, &mask);
9158 if (!otp_read_word(sih, offset, &datum)) {
9159 xtal_bias_cal_otp_done = ((datum >> shift) & mask);
9160 }
9161
9162 si_pmu_chipcontrol_xtal_bias_val_offsets(sih, &offset, &shift, &mask);
9163 if (xtal_bias_cal_otp_done && (!otp_read_word(sih, offset, &datum)))
9164 {
9165 xtal_bias_adj = ((datum >> shift) & mask);
9166 }
9167 #endif /* BCM_OTP_API */
9168 *flag = xtal_bias_cal_otp_done;
9169 *val = xtal_bias_adj;
9170 }
9171
9172 #ifndef BCM_OTP_API
9173 static void
BCMATTACHFN(si_pmu_chipcontrol_xtal_bias_cal_done_offsets)9174 BCMATTACHFN(si_pmu_chipcontrol_xtal_bias_cal_done_offsets)(si_t *sih, uint16* wrd_offset,
9175 uint8* wrd_shift, uint8* wrd_mask)
9176 {
9177 /* Offset is 16 bit aligned address, shift is the starting bit position of the value
9178 * mask defines the bitwidth of the value. Each value in the array is for one of the
9179 * cores.
9180 */
9181 /* XTAL BIAS CAL done 11896 */
9182 switch (CHIPID(sih->chip)) {
9183 case BCM4376_CHIP_GRPID:
9184 case BCM4378_CHIP_GRPID:
9185 *wrd_offset = OTP_XTAL_BIAS_CAL_DONE_4378_WRD_OFFSET;
9186 *wrd_shift = OTP_XTAL_BIAS_CAL_DONE_4378_WRD_SHIFT;
9187 *wrd_mask = OTP_XTAL_BIAS_CAL_DONE_4378_WRD_MASK;
9188 break;
9189 default:
9190 ASSERT(0);
9191 break;
9192 }
9193 }
9194
9195 static void
BCMATTACHFN(si_pmu_chipcontrol_xtal_bias_val_offsets)9196 BCMATTACHFN(si_pmu_chipcontrol_xtal_bias_val_offsets)(si_t *sih, uint16* wrd_offset,
9197 uint8* wrd_shift, uint8* wrd_mask)
9198 {
9199 /* Offset is 16 bit aligned address, shift is the starting bit position of the value
9200 * mask defines the bitwidth of the value. Each value in the array is for one of the
9201 * cores.
9202 */
9203 /* XTAL BIAS value 11888 */
9204 switch (CHIPID(sih->chip)) {
9205 case BCM4376_CHIP_GRPID:
9206 case BCM4378_CHIP_GRPID:
9207 *wrd_offset = OTP_XTAL_BIAS_VAL_4378_WRD_OFFSET;
9208 *wrd_shift = OTP_XTAL_BIAS_VAL_4378_WRD_SHIFT;
9209 *wrd_mask = OTP_XTAL_BIAS_VAL_4378_WRD_MASK;
9210 break;
9211 default:
9212 ASSERT(0);
9213 break;
9214 }
9215 }
9216 #endif /* !BCM_OTP_API */
9217 #endif /* XTAL_BIAS_FROM_OTP */
9218
9219 #endif /* !BCMDONGLEHOST */
9220
9221 #ifdef BCMPMU_STATS
9222 /*
9223 * 8 pmu statistics timer default map
9224 *
9225 * for CORE_RDY_AUX measure, set as below for timer 6 and 7 instead of CORE_RDY_MAIN.
9226 * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX)
9227 * { SRC_CORE_RDY_AUX, FALSE, TRUE, LEVEL_HIGH},
9228 * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX)
9229 * { SRC_CORE_RDY_AUX, FALSE, TRUE, EDGE_RISE}
9230 */
9231 static pmu_stats_timer_t pmustatstimer[] = {
9232 { SRC_LINK_IN_L12, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l12
9233 { SRC_LINK_IN_L23, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l23
9234 { SRC_PM_ST_IN_D0, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d0
9235 { SRC_PM_ST_IN_D3, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d3
9236 //deep-sleep duration : pmu_rsrc_state(XTAL_PU)
9237 { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_LEVEL_LOW},
9238 //deep-sleep entry count : pmu_rsrc_state(XTAL_PU)
9239 { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_EDGE_FALL},
9240 //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN)
9241 { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_LEVEL_HIGH},
9242 //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN)
9243 { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_EDGE_RISE}
9244 };
9245
9246 static void
si_pmustatstimer_update(osl_t * osh,pmuregs_t * pmu,uint8 timerid)9247 si_pmustatstimer_update(osl_t *osh, pmuregs_t *pmu, uint8 timerid)
9248 {
9249 uint32 stats_timer_ctrl;
9250
9251 W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
9252 stats_timer_ctrl =
9253 ((pmustatstimer[timerid].src_num << PMU_ST_SRC_SHIFT) &
9254 PMU_ST_SRC_MASK) |
9255 ((pmustatstimer[timerid].cnt_mode << PMU_ST_CNT_MODE_SHIFT) &
9256 PMU_ST_CNT_MODE_MASK) |
9257 ((pmustatstimer[timerid].enable << PMU_ST_EN_SHIFT) & PMU_ST_EN_MASK) |
9258 ((pmustatstimer[timerid].int_enable << PMU_ST_INT_EN_SHIFT) & PMU_ST_INT_EN_MASK);
9259 W_REG(osh, &pmu->pmu_statstimer_ctrl, stats_timer_ctrl);
9260 W_REG(osh, &pmu->pmu_statstimer_N, 0);
9261 }
9262
9263 void
si_pmustatstimer_int_enable(si_t * sih)9264 si_pmustatstimer_int_enable(si_t *sih)
9265 {
9266 pmuregs_t *pmu;
9267 uint origidx;
9268 osl_t *osh = si_osh(sih);
9269
9270 /* Remember original core before switch to chipc/pmu */
9271 origidx = si_coreidx(sih);
9272 if (AOB_ENAB(sih)) {
9273 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9274 } else {
9275 pmu = si_setcoreidx(sih, SI_CC_IDX);
9276 }
9277 ASSERT(pmu != NULL);
9278
9279 OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK);
9280
9281 /* Return to original core */
9282 si_setcoreidx(sih, origidx);
9283 }
9284
9285 void
si_pmustatstimer_int_disable(si_t * sih)9286 si_pmustatstimer_int_disable(si_t *sih)
9287 {
9288 pmuregs_t *pmu;
9289 uint origidx;
9290 osl_t *osh = si_osh(sih);
9291
9292 /* Remember original core before switch to chipc/pmu */
9293 origidx = si_coreidx(sih);
9294 if (AOB_ENAB(sih)) {
9295 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9296 } else {
9297 pmu = si_setcoreidx(sih, SI_CC_IDX);
9298 }
9299 ASSERT(pmu != NULL);
9300
9301 AND_REG(osh, &pmu->pmuintmask0, ~PMU_INT_STAT_TIMER_INT_MASK);
9302
9303 /* Return to original core */
9304 si_setcoreidx(sih, origidx);
9305 }
9306
9307 void
si_pmustatstimer_init(si_t * sih)9308 si_pmustatstimer_init(si_t *sih)
9309 {
9310 pmuregs_t *pmu;
9311 uint origidx;
9312 osl_t *osh = si_osh(sih);
9313 uint32 core_cap_ext;
9314 uint8 max_stats_timer_num;
9315 int8 i;
9316
9317 /* Remember original core before switch to chipc/pmu */
9318 origidx = si_coreidx(sih);
9319 if (AOB_ENAB(sih)) {
9320 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9321 } else {
9322 pmu = si_setcoreidx(sih, SI_CC_IDX);
9323 }
9324 ASSERT(pmu != NULL);
9325
9326 core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
9327
9328 max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1;
9329
9330 for (i = 0; i < max_stats_timer_num; i++) {
9331 si_pmustatstimer_update(osh, pmu, i);
9332 }
9333
9334 OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK);
9335
9336 /* Return to original core */
9337 si_setcoreidx(sih, origidx);
9338 }
9339
9340 void
si_pmustatstimer_dump(si_t * sih)9341 si_pmustatstimer_dump(si_t *sih)
9342 {
9343 pmuregs_t *pmu;
9344 uint origidx;
9345 osl_t *osh = si_osh(sih);
9346 uint32 core_cap_ext, pmucapabilities, AlpPeriod, ILPPeriod, pmuintmask0, pmuintstatus;
9347 uint8 max_stats_timer_num, max_stats_timer_src_num;
9348 uint32 stat_timer_ctrl, stat_timer_N;
9349 uint8 i;
9350 uint32 current_time_ms = OSL_SYSUPTIME();
9351
9352 /* Remember original core before switch to chipc/pmu */
9353 origidx = si_coreidx(sih);
9354 if (AOB_ENAB(sih)) {
9355 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9356 } else {
9357 pmu = si_setcoreidx(sih, SI_CC_IDX);
9358 }
9359 ASSERT(pmu != NULL);
9360
9361 pmucapabilities = R_REG(osh, &pmu->pmucapabilities);
9362 core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
9363 AlpPeriod = R_REG(osh, &pmu->slowclkperiod);
9364 ILPPeriod = R_REG(osh, &pmu->ILPPeriod);
9365
9366 max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >>
9367 PCAP_EXT_ST_NUM_SHIFT) + 1;
9368 max_stats_timer_src_num = ((core_cap_ext & PCAP_EXT_ST_SRC_NUM_MASK) >>
9369 PCAP_EXT_ST_SRC_NUM_SHIFT) + 1;
9370
9371 pmuintstatus = R_REG(osh, &pmu->pmuintstatus);
9372 pmuintmask0 = R_REG(osh, &pmu->pmuintmask0);
9373
9374 PMU_ERROR(("si_pmustatstimer_dump : TIME %d\n", current_time_ms));
9375
9376 PMU_ERROR(("\tMAX Timer Num %d, MAX Source Num %d\n",
9377 max_stats_timer_num, max_stats_timer_src_num));
9378 PMU_ERROR(("\tpmucapabilities 0x%8x, core_cap_ext 0x%8x, AlpPeriod 0x%8x, ILPPeriod 0x%8x, "
9379 "pmuintmask0 0x%8x, pmuintstatus 0x%8x, pmurev %d\n",
9380 pmucapabilities, core_cap_ext, AlpPeriod, ILPPeriod,
9381 pmuintmask0, pmuintstatus, PMUREV(sih->pmurev)));
9382
9383 for (i = 0; i < max_stats_timer_num; i++) {
9384 W_REG(osh, &pmu->pmu_statstimer_addr, i);
9385 stat_timer_ctrl = R_REG(osh, &pmu->pmu_statstimer_ctrl);
9386 stat_timer_N = R_REG(osh, &pmu->pmu_statstimer_N);
9387 PMU_ERROR(("\t Timer %d : control 0x%8x, %d\n",
9388 i, stat_timer_ctrl, stat_timer_N));
9389 }
9390
9391 /* Return to original core */
9392 si_setcoreidx(sih, origidx);
9393 }
9394
9395 void
si_pmustatstimer_start(si_t * sih,uint8 timerid)9396 si_pmustatstimer_start(si_t *sih, uint8 timerid)
9397 {
9398 pmuregs_t *pmu;
9399 uint origidx;
9400 osl_t *osh = si_osh(sih);
9401
9402 /* Remember original core before switch to chipc/pmu */
9403 origidx = si_coreidx(sih);
9404 if (AOB_ENAB(sih)) {
9405 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9406 } else {
9407 pmu = si_setcoreidx(sih, SI_CC_IDX);
9408 }
9409 ASSERT(pmu != NULL);
9410
9411 pmustatstimer[timerid].enable = TRUE;
9412
9413 W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
9414 OR_REG(osh, &pmu->pmu_statstimer_ctrl, PMU_ST_ENAB << PMU_ST_EN_SHIFT);
9415
9416 /* Return to original core */
9417 si_setcoreidx(sih, origidx);
9418 }
9419
9420 void
si_pmustatstimer_stop(si_t * sih,uint8 timerid)9421 si_pmustatstimer_stop(si_t *sih, uint8 timerid)
9422 {
9423 pmuregs_t *pmu;
9424 uint origidx;
9425 osl_t *osh = si_osh(sih);
9426
9427 /* Remember original core before switch to chipc/pmu */
9428 origidx = si_coreidx(sih);
9429 if (AOB_ENAB(sih)) {
9430 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9431 } else {
9432 pmu = si_setcoreidx(sih, SI_CC_IDX);
9433 }
9434 ASSERT(pmu != NULL);
9435
9436 pmustatstimer[timerid].enable = FALSE;
9437
9438 W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
9439 AND_REG(osh, &pmu->pmu_statstimer_ctrl, ~(PMU_ST_ENAB << PMU_ST_EN_SHIFT));
9440
9441 /* Return to original core */
9442 si_setcoreidx(sih, origidx);
9443 }
9444
9445 void
si_pmustatstimer_clear(si_t * sih,uint8 timerid)9446 si_pmustatstimer_clear(si_t *sih, uint8 timerid)
9447 {
9448 pmuregs_t *pmu;
9449 uint origidx;
9450 osl_t *osh = si_osh(sih);
9451
9452 /* Remember original core before switch to chipc/pmu */
9453 origidx = si_coreidx(sih);
9454 if (AOB_ENAB(sih)) {
9455 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9456 } else {
9457 pmu = si_setcoreidx(sih, SI_CC_IDX);
9458 }
9459 ASSERT(pmu != NULL);
9460
9461 W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
9462 W_REG(osh, &pmu->pmu_statstimer_N, 0);
9463
9464 /* Return to original core */
9465 si_setcoreidx(sih, origidx);
9466 }
9467
9468 void
si_pmustatstimer_clear_overflow(si_t * sih)9469 si_pmustatstimer_clear_overflow(si_t *sih)
9470 {
9471 uint8 i;
9472 uint32 core_cap_ext;
9473 uint8 max_stats_timer_num;
9474 uint32 timerN;
9475 pmuregs_t *pmu;
9476 uint origidx;
9477 osl_t *osh = si_osh(sih);
9478
9479 /* Remember original core before switch to chipc/pmu */
9480 origidx = si_coreidx(sih);
9481 if (AOB_ENAB(sih)) {
9482 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9483 } else {
9484 pmu = si_setcoreidx(sih, SI_CC_IDX);
9485 }
9486 ASSERT(pmu != NULL);
9487
9488 core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
9489 max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1;
9490
9491 for (i = 0; i < max_stats_timer_num; i++) {
9492 W_REG(osh, &pmu->pmu_statstimer_addr, i);
9493 timerN = R_REG(osh, &pmu->pmu_statstimer_N);
9494 if (timerN == 0xFFFFFFFF) {
9495 PMU_ERROR(("pmustatstimer overflow clear - timerid : %d\n", i));
9496 si_pmustatstimer_clear(sih, i);
9497 }
9498 }
9499
9500 /* Return to original core */
9501 si_setcoreidx(sih, origidx);
9502 }
9503
9504 uint32
si_pmustatstimer_read(si_t * sih,uint8 timerid)9505 si_pmustatstimer_read(si_t *sih, uint8 timerid)
9506 {
9507 pmuregs_t *pmu;
9508 uint origidx;
9509 osl_t *osh = si_osh(sih);
9510 uint32 stats_timer_N;
9511
9512 /* Remember original core before switch to chipc/pmu */
9513 origidx = si_coreidx(sih);
9514 if (AOB_ENAB(sih)) {
9515 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9516 } else {
9517 pmu = si_setcoreidx(sih, SI_CC_IDX);
9518 }
9519 ASSERT(pmu != NULL);
9520
9521 W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
9522 stats_timer_N = R_REG(osh, &pmu->pmu_statstimer_N);
9523
9524 /* Return to original core */
9525 si_setcoreidx(sih, origidx);
9526
9527 return stats_timer_N;
9528 }
9529
9530 void
si_pmustatstimer_cfg_src_num(si_t * sih,uint8 src_num,uint8 timerid)9531 si_pmustatstimer_cfg_src_num(si_t *sih, uint8 src_num, uint8 timerid)
9532 {
9533 pmuregs_t *pmu;
9534 uint origidx;
9535 osl_t *osh = si_osh(sih);
9536
9537 /* Remember original core before switch to chipc/pmu */
9538 origidx = si_coreidx(sih);
9539 if (AOB_ENAB(sih)) {
9540 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9541 } else {
9542 pmu = si_setcoreidx(sih, SI_CC_IDX);
9543 }
9544 ASSERT(pmu != NULL);
9545
9546 pmustatstimer[timerid].src_num = src_num;
9547 si_pmustatstimer_update(osh, pmu, timerid);
9548
9549 /* Return to original core */
9550 si_setcoreidx(sih, origidx);
9551 }
9552
9553 void
si_pmustatstimer_cfg_cnt_mode(si_t * sih,uint8 cnt_mode,uint8 timerid)9554 si_pmustatstimer_cfg_cnt_mode(si_t *sih, uint8 cnt_mode, uint8 timerid)
9555 {
9556 pmuregs_t *pmu;
9557 uint origidx;
9558 osl_t *osh = si_osh(sih);
9559
9560 /* Remember original core before switch to chipc/pmu */
9561 origidx = si_coreidx(sih);
9562 if (AOB_ENAB(sih)) {
9563 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9564 } else {
9565 pmu = si_setcoreidx(sih, SI_CC_IDX);
9566 }
9567 ASSERT(pmu != NULL);
9568
9569 pmustatstimer[timerid].cnt_mode = cnt_mode;
9570 si_pmustatstimer_update(osh, pmu, timerid);
9571
9572 /* Return to original core */
9573 si_setcoreidx(sih, origidx);
9574 }
9575 #endif /* BCMPMU_STATS */
9576
9577 #ifdef DONGLEBUILD
9578 /* Note this could be called from trap context !!
9579 * So observe caution. Do NOT ASSERT() in this function
9580 * len parameter is dual purpose - On input it is length of the
9581 * buffer provided. On output it is the amount of data written in
9582 * bytes.
9583 */
9584 /* This includes address data pair
9585 * Note presence of arg2. arg2 could further define what subset of information
9586 * needs to be dumped. Some external entities such as SMD could optionally pass
9587 * arg2 to define subset of information needed
9588 */
9589 int
BCMPOSTTRAPFN(si_pmu_regs_in_rodata_dump)9590 BCMPOSTTRAPFN(si_pmu_regs_in_rodata_dump)(void *sih, void *arg2,
9591 uint32 *bufptr, uint16 *len)
9592 {
9593 int rc = BCME_OK;
9594 uint16 totalsize = SI_PMU_REG_DUMP_BASE_SIZE;
9595
9596 if ((bufptr == NULL) || (len == NULL)) {
9597 rc = BCME_NOMEM;
9598 goto fail;
9599 }
9600
9601 /* Are PMU registers available in rodata? If not, bail out
9602 * Avoid re-read. If data is not there, then there could have been
9603 * an error in reading these regs.
9604 */
9605 if (rodata_pmuregdump_ptr == NULL) {
9606 rc = BCME_ERROR;
9607 goto fail;
9608 }
9609
9610 if (si_pmu_get_mac_rsrc_req_tmr_cnt(sih) > 1) {
9611 totalsize += SI_PMU_REG_DUMP_MACRSRC1_SIZE;
9612 }
9613 if (si_pmu_get_mac_rsrc_req_tmr_cnt(sih) > 2) {
9614 totalsize += SI_PMU_REG_DUMP_MACRSRC2_SIZE;
9615 }
9616 if (si_pmu_get_pmu_interrupt_rcv_cnt(sih) > 1) {
9617 totalsize += SI_PMU_REG_DUMP_INTRCV1_SIZE;
9618 }
9619
9620 /* Make sure there is enough space for address value pair */
9621 if (len && *len < totalsize) {
9622 rc = BCME_BUFTOOSHORT;
9623 goto fail;
9624 }
9625
9626 /* Write registers to supplied buffer */
9627 /* Note that rodata_pmuregdump_size needs to be
9628 * a multiple of a word size
9629 */
9630 memcpy((uint8*)bufptr, rodata_pmuregdump_ptr, totalsize);
9631
9632 *len = totalsize;
9633 fail:
9634 return rc;
9635
9636 }
9637 #endif /* DONGLEBUILD */
9638
9639 /* query the # of mac resource request timers */
9640 uint
BCMPOSTTRAPFN(si_pmu_get_mac_rsrc_req_tmr_cnt)9641 BCMPOSTTRAPFN(si_pmu_get_mac_rsrc_req_tmr_cnt)(si_t *sih)
9642 {
9643 if (PMUREV(sih->pmurev) >= 26) {
9644 uint32 core_cap_ext = PMU_REG(sih, core_cap_ext, 0, 0);
9645 uint mac_rsrc_cnt =
9646 ((core_cap_ext & PCAP_EXT_MAC_RSRC_REQ_TMR_CNT_MASK) >>
9647 PCAP_EXT_MAC_RSRC_REQ_TMR_CNT_SHIFT) + 1;
9648 return mac_rsrc_cnt;
9649 }
9650
9651 return si_numd11coreunits(sih);
9652 }
9653
9654 /* query the # of pmu interrupt recevier */
9655 uint
BCMPOSTTRAPFN(si_pmu_get_pmu_interrupt_rcv_cnt)9656 BCMPOSTTRAPFN(si_pmu_get_pmu_interrupt_rcv_cnt)(si_t *sih)
9657 {
9658 if (PMUREV(sih->pmurev) >= 26) {
9659 uint32 core_cap_ext = PMU_REG(sih, core_cap_ext, 0, 0);
9660 uint pmu_intr_rcvr_cnt =
9661 ((core_cap_ext & PCAP_EXT_PMU_INTR_RCVR_CNT_MASK) >>
9662 PCAP_EXT_PMU_INTR_RCVR_CNT_SHIFT) + 1;
9663 return pmu_intr_rcvr_cnt;
9664 }
9665
9666 return si_numd11coreunits(sih);
9667 }
9668
9669 #ifdef DONGLEBUILD
9670 int
si_pmu_mem_pwr_off(si_t * sih,int core_idx)9671 si_pmu_mem_pwr_off(si_t *sih, int core_idx)
9672 {
9673 int ret = BCME_OK;
9674
9675 if (si_setcore(sih, D11_CORE_ID, core_idx) == NULL) {
9676 /* core_idx doesn't exsist */
9677 return BCME_BADOPTION;
9678 }
9679
9680 switch (CHIPID(sih->chip)) {
9681 case BCM4385_CHIP_GRPID:
9682 case BCM4387_CHIP_GRPID:
9683 if (core_idx == 0) {
9684 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
9685 (PMU_CC4_4387_MAIN_PD_CBUCK2VDDB_ON |
9686 PMU_CC4_4387_MAIN_PD_CBUCK2VDDRET_ON |
9687 PMU_CC4_4387_MAIN_PD_MEMLPLDO2VDDB_ON |
9688 PMU_CC4_4387_MAIN_PD_MEMLPDLO2VDDRET_ON),
9689 0);
9690
9691 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
9692 (PMU_CC13_MAIN_CBUCK2VDDB_OFF |
9693 PMU_CC13_MAIN_CBUCK2VDDRET_OFF |
9694 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF |
9695 PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF),
9696 (PMU_CC13_MAIN_CBUCK2VDDB_OFF |
9697 PMU_CC13_MAIN_CBUCK2VDDRET_OFF |
9698 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF |
9699 PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF));
9700
9701 /* LQ settings */
9702 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_25,
9703 0xFFFFFFFF, XTAL_LQ_SETTING_4387);
9704 } else if (core_idx == 1) {
9705 si_pmu_chipcontrol(sih, PMU_CHIPCTL4,
9706 (PMU_CC4_4387_AUX_PD_CBUCK2VDDB_ON |
9707 PMU_CC4_4387_AUX_PD_CBUCK2VDDRET_ON |
9708 PMU_CC4_4387_AUX_PD_MEMLPLDO2VDDB_ON |
9709 PMU_CC4_4387_AUX_PD_MEMLPLDO2VDDRET_ON),
9710 0);
9711
9712 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
9713 (PMU_CC13_AUX_CBUCK2VDDB_OFF |
9714 PMU_CC13_AUX_CBUCK2VDDRET_OFF |
9715 PMU_CC13_AUX_MEMLPLDO2VDDB_OFF |
9716 PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF),
9717 (PMU_CC13_AUX_CBUCK2VDDB_OFF |
9718 PMU_CC13_AUX_CBUCK2VDDRET_OFF |
9719 PMU_CC13_AUX_MEMLPLDO2VDDB_OFF |
9720 PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF));
9721 } else if (core_idx == 2) {
9722 si_pmu_chipcontrol(sih, PMU_CHIPCTL17,
9723 (PMU_CC17_SCAN_CBUCK2VDDB_ON |
9724 PMU_CC17_SCAN_MEMLPLDO2VDDB_ON |
9725 PMU_CC17_SCAN_MEMLPLDO2VDDRET_ON),
9726 0);
9727 si_pmu_chipcontrol(sih, PMU_CHIPCTL17,
9728 (PMU_CC17_SCAN_CBUCK2VDDB_OFF |
9729 PMU_CC17_SCAN_MEMLPLDO2VDDB_OFF |
9730 PMU_CC17_SCAN_MEMLPLDO2VDDRET_OFF),
9731 (PMU_CC17_SCAN_CBUCK2VDDB_OFF |
9732 PMU_CC17_SCAN_MEMLPLDO2VDDB_OFF |
9733 PMU_CC17_SCAN_MEMLPLDO2VDDRET_OFF));
9734 }
9735 break;
9736
9737 default:
9738 ret = BCME_UNSUPPORTED;
9739 break;
9740 }
9741
9742 return ret;
9743 }
9744
9745 int
BCMPOSTTRAPFN(si_pmu_mem_pwr_on)9746 BCMPOSTTRAPFN(si_pmu_mem_pwr_on)(si_t *sih)
9747 {
9748 int ret = BCME_OK;
9749
9750 switch (CHIPID(sih->chip)) {
9751 case BCM4385_CHIP_GRPID:
9752 case BCM4387_CHIP_GRPID:
9753 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
9754 (PMU_CC13_MAIN_CBUCK2VDDB_OFF |
9755 PMU_CC13_MAIN_CBUCK2VDDRET_OFF |
9756 PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF |
9757 PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF),
9758 PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF);
9759 si_pmu_chipcontrol(sih, PMU_CHIPCTL13,
9760 (PMU_CC13_AUX_CBUCK2VDDB_OFF |
9761 PMU_CC13_AUX_CBUCK2VDDRET_OFF |
9762 PMU_CC13_AUX_MEMLPLDO2VDDB_OFF |
9763 PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF),
9764 PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF);
9765 si_pmu_chipcontrol(sih, PMU_CHIPCTL17,
9766 (PMU_CC17_SCAN_CBUCK2VDDB_OFF |
9767 PMU_CC17_SCAN_MEMLPLDO2VDDB_OFF |
9768 PMU_CC17_SCAN_MEMLPLDO2VDDRET_OFF),
9769 PMU_CC17_SCAN_MEMLPLDO2VDDRET_OFF);
9770
9771 /* HQ settings */
9772 si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_25,
9773 0xFFFFFFFF, XTAL_HQ_SETTING_4387);
9774 break;
9775
9776 default:
9777 ret = BCME_UNSUPPORTED;
9778 break;
9779 }
9780
9781 return ret;
9782 }
9783
9784 void
BCMPOSTTRAPFN(si_pmu_disable_intr_pwrreq)9785 BCMPOSTTRAPFN(si_pmu_disable_intr_pwrreq)(si_t *sih)
9786 {
9787 if (MULTIBP_CAP(sih)) {
9788 switch (CHIPID(sih->chip)) {
9789 case BCM4376_CHIP_GRPID:
9790 case BCM4378_CHIP_GRPID:
9791 case BCM4385_CHIP_GRPID:
9792 case BCM4387_CHIP_GRPID:
9793 case BCM4388_CHIP_GRPID:
9794 case BCM4389_CHIP_GRPID:
9795 case BCM4397_CHIP_GRPID:
9796 si_pmu_chipcontrol(sih, PMU_CHIPCTL2, PMU_CC2_CB2WL_INTR_PWRREQ_EN, 0);
9797 si_pmu_chipcontrol(sih, PMU_CHIPCTL6, PMU_CC6_ENABLE_DMN1_WAKEUP, 0);
9798 break;
9799 default:
9800 PMU_ERROR(("si_pmu_disable_intr_pwrreq: add support for this chip!\n"));
9801 OSL_SYS_HALT();
9802 break;
9803 }
9804 }
9805 }
9806
9807 void
BCMPOSTTRAPFN(si_pmu_clear_intmask)9808 BCMPOSTTRAPFN(si_pmu_clear_intmask)(si_t *sih)
9809 {
9810 pmuregs_t *pmu;
9811 uint origidx;
9812 osl_t *osh = si_osh(sih);
9813 uint pmu_intr_recvr_cnt;
9814
9815 /* Remember original core before switch to chipc/pmu */
9816 origidx = si_coreidx(sih);
9817 if (AOB_ENAB(sih)) {
9818 pmu = si_setcore(sih, PMU_CORE_ID, 0);
9819 } else {
9820 pmu = si_setcoreidx(sih, SI_CC_IDX);
9821 }
9822
9823 ASSERT(pmu != NULL);
9824 W_REG(osh, &pmu->pmuintmask0, 0);
9825
9826 pmu_intr_recvr_cnt = ((R_REG(osh, &pmu->core_cap_ext) & PCAP_EXT_PMU_INTR_RCVR_CNT_MASK)
9827 >> PCAP_EXT_PMU_INTR_RCVR_CNT_SHIFT) + 1;
9828
9829 if (pmu_intr_recvr_cnt > 1) {
9830 W_REG(osh, &pmu->pmuintmask1, 0);
9831 }
9832
9833 /* Return to original core */
9834 si_setcoreidx(sih, origidx);
9835 }
9836 #endif /* DONGLEBUILD */
9837
9838 int
si_pmu_res_state_pwrsw_main_wait(si_t * sih)9839 si_pmu_res_state_pwrsw_main_wait(si_t *sih)
9840 {
9841 int ret = BCME_OK;
9842
9843 switch (CHIPID(sih->chip)) {
9844 case BCM4387_CHIP_GRPID:
9845 if (PMU_REG(sih, res_state, 0, 0) & PMURES_BIT(RES4387_PWRSW_MAIN)) {
9846 SPINWAIT((PMU_REG(sih, res_state, 0, 0) &
9847 PMURES_BIT(RES4387_PWRSW_MAIN)), 10000);
9848 OSL_DELAY(1000);
9849 }
9850 ret = (PMU_REG(sih, res_state, 0, 0) & PMURES_BIT(RES4387_PWRSW_MAIN)) ?
9851 BCME_ERROR : BCME_OK;
9852 break;
9853 default:
9854 PMU_ERROR(("si_pmu_res_state_pwrsw_main_wait: add support for this chip!\n"));
9855 OSL_SYS_HALT();
9856 break;
9857 }
9858
9859 return ret;
9860 }
9861
9862 int
si_pmu_lvm_csr_update(si_t * sih,bool lvm)9863 si_pmu_lvm_csr_update(si_t *sih, bool lvm)
9864 {
9865
9866 #ifdef BCMDVFS
9867 if (BCMDVFS_ENAB() && si_dvfs_enable_status(sih)) {
9868 uint32 ndv_volt = lvm ? DVFS_VOLTAGE_NDV : DVFS_VOLTAGE_NDV_NON_LVM;
9869 si_dvfs_set_ndv_voltage(sih, ndv_volt);
9870 } else
9871 #endif /* BCMDVFS */
9872 {
9873 uint32 cbuck_volt = lvm ? CBUCK_VOLT_SW_DEFAULT_4387 : CBUCK_VOLT_NON_LVM;
9874 si_pmu_vreg_control(sih, PMU_VREG_0,
9875 VREG0_4378_CSR_VOLT_ADJ_PWM_MASK,
9876 cbuck_volt << VREG0_4378_CSR_VOLT_ADJ_PWM_SHIFT);
9877 }
9878 return BCME_OK;
9879 }
9880
9881 #if defined(BT_WLAN_REG_ON_WAR)
9882 void
si_pmu_reg_on_war_ext_wake_perst_set(si_t * sih)9883 si_pmu_reg_on_war_ext_wake_perst_set(si_t *sih)
9884 {
9885 uint origidx = si_coreidx(sih);
9886 pmuregs_t *pmu = si_setcore(sih, PMU_CORE_ID, 0);
9887 osl_t *osh = si_osh(sih);
9888
9889 if (PMUREV(sih->pmurev) == 40) {
9890 /*
9891 * set PCIEPerstReq (bit-5) as a wake-up source in
9892 * ExtWakeMask0 (0x760) register
9893 */
9894 W_REG(osh, &pmu->extwakemask0, PMU_EXT_WAKE_MASK_0_PCIE_PERST);
9895
9896 /*
9897 * configure the wakemask as "common backplane" resources to
9898 * be up during wake-up in ExtWakeReqMask0 (0x770) register
9899 */
9900 W_REG(osh, &pmu->extwakereqmask[0], REG_ON_WAR_PMU_EXT_WAKE_REQ_MASK0_VAL);
9901 }
9902
9903 si_setcoreidx(sih, origidx);
9904 }
9905
9906 void
si_pmu_reg_on_war_ext_wake_perst_clear(si_t * sih)9907 si_pmu_reg_on_war_ext_wake_perst_clear(si_t *sih)
9908 {
9909 uint32 val = 0;
9910 uint origidx = si_coreidx(sih);
9911 pmuregs_t *pmu = si_setcore(sih, PMU_CORE_ID, 0);
9912 osl_t *osh = si_osh(sih);
9913
9914 if (PMUREV(sih->pmurev) == 40) {
9915 /* clear all set bits in ExtWakeupStatus (0x744) register */
9916 val = R_REG(osh, &pmu->extwakeupstatus);
9917 W_REG(osh, &pmu->extwakeupstatus, val);
9918 }
9919
9920 si_setcoreidx(sih, origidx);
9921 }
9922 #endif /* BT_WLAN_REG_ON_WAR */
9923
9924 void
si_pmu_res_state_wait(si_t * sih,uint rsrc)9925 si_pmu_res_state_wait(si_t *sih, uint rsrc)
9926 {
9927 SPINWAIT(!(PMU_REG(sih, res_state, 0, 0) & PMURES_BIT(rsrc)), PMU_MAX_TRANSITION_DLY);
9928 ASSERT(PMU_REG(sih, res_state, 0, 0) & PMURES_BIT(rsrc));
9929 }
9930