Commit | Line | Data |
---|---|---|
84813812 LJ |
1 | /* |
2 | * Misc utility routines for accessing lhl specific features | |
3 | * of the SiliconBackplane-based Broadcom chips. | |
4 | * | |
5 | * Copyright (C) 1999-2019, 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 | * Notwithstanding the above, under no circumstances may you combine this | |
22 | * software in any way with any other Broadcom software provided under a license | |
23 | * other than the GPL, without Broadcom's express prior written consent. | |
24 | * | |
25 | * | |
26 | * <<Broadcom-WL-IPTag/Open:>> | |
27 | * | |
28 | * $Id: hndpmu.c 547757 2015-04-13 10:18:04Z $ | |
29 | */ | |
30 | ||
31 | #include <hndpmu.h> | |
32 | #include <hndlhl.h> | |
33 | #include <sbchipc.h> | |
34 | #include <hndsoc.h> | |
35 | #include <bcmdevs.h> | |
36 | #include <osl.h> | |
37 | #include <sbgci.h> | |
38 | #include <siutils.h> | |
39 | #include <bcmutils.h> | |
40 | #ifdef BCMULP | |
41 | #include <ulp.h> | |
42 | #endif // endif | |
43 | ||
44 | #define SI_LHL_EXT_WAKE_REQ_MASK_MAGIC 0x7FBBF7FF /* magic number for LHL EXT */ | |
45 | ||
46 | /* PmuRev1 has a 24-bit PMU RsrcReq timer. However it pushes all other bits | |
47 | * upward. To make the code to run for all revs we use a variable to tell how | |
48 | * many bits we need to shift. | |
49 | */ | |
50 | #define FLAGS_SHIFT 14 | |
51 | #define LHL_ERROR(args) printf args | |
52 | ||
53 | void | |
54 | si_lhl_setup(si_t *sih, osl_t *osh) | |
55 | { | |
56 | if (CHIPID(sih->chip) == BCM43012_CHIP_ID) { | |
57 | /* Enable PMU sleep mode0 */ | |
58 | LHL_REG(sih, lhl_top_pwrseq_ctl_adr, LHL_PWRSEQ_CTL, PMU_SLEEP_MODE_2); | |
59 | /* Modify as per the | |
60 | BCM43012/LHL#LHL-RecommendedsettingforvariousPMUSleepModes: | |
61 | */ | |
62 | LHL_REG(sih, lhl_top_pwrup_ctl_adr, LHL_PWRUP_CTL_MASK, LHL_PWRUP_CTL); | |
63 | LHL_REG(sih, lhl_top_pwrup2_ctl_adr, LHL_PWRUP2_CTL_MASK, LHL_PWRUP2_CTL); | |
64 | LHL_REG(sih, lhl_top_pwrdn_ctl_adr, LHL_PWRDN_CTL_MASK, LHL_PWRDN_SLEEP_CNT); | |
65 | LHL_REG(sih, lhl_top_pwrdn2_ctl_adr, LHL_PWRDN2_CTL_MASK, LHL_PWRDN2_CTL); | |
66 | } else if (BCM4347_CHIP(sih->chip)) { | |
67 | if (LHL_IS_PSMODE_1(sih)) { | |
68 | LHL_REG(sih, lhl_top_pwrseq_ctl_adr, LHL_PWRSEQ_CTL, PMU_SLEEP_MODE_1); | |
69 | } else { | |
70 | LHL_REG(sih, lhl_top_pwrseq_ctl_adr, LHL_PWRSEQ_CTL, PMU_SLEEP_MODE_0); | |
71 | } | |
72 | ||
73 | LHL_REG(sih, lhl_top_pwrup_ctl_adr, LHL_PWRUP_CTL_MASK, LHL_PWRUP_CTL_4347); | |
74 | LHL_REG(sih, lhl_top_pwrup2_ctl_adr, LHL_PWRUP2_CTL_MASK, LHL_PWRUP2_CTL); | |
75 | LHL_REG(sih, lhl_top_pwrdn_ctl_adr, | |
76 | LHL_PWRDN_CTL_MASK, LHL_PWRDN_SLEEP_CNT); | |
77 | LHL_REG(sih, lhl_top_pwrdn2_ctl_adr, LHL_PWRDN2_CTL_MASK, LHL_PWRDN2_CTL); | |
78 | ||
79 | /* | |
80 | * Enable wakeup on GPIO1, PCIE clkreq and perst signal, | |
81 | * GPIO[0] is mapped to GPIO1 | |
82 | * GPIO[1] is mapped to PCIE perst | |
83 | * GPIO[2] is mapped to PCIE clkreq | |
84 | */ | |
85 | ||
86 | /* GPIO1 */ | |
87 | /* Clear any old interrupt status */ | |
88 | LHL_REG(sih, gpio_int_st_port_adr[0], | |
89 | 1 << PCIE_GPIO1_GPIO_PIN, 1 << PCIE_GPIO1_GPIO_PIN); | |
90 | /* active high level trigger */ | |
91 | LHL_REG(sih, gpio_ctrl_iocfg_p_adr[PCIE_GPIO1_GPIO_PIN], ~0, | |
92 | 1 << GCI_GPIO_STS_WL_DIN_SELECT); | |
93 | LHL_REG(sih, gpio_int_en_port_adr[0], | |
94 | 1 << PCIE_GPIO1_GPIO_PIN, 1 << PCIE_GPIO1_GPIO_PIN); | |
95 | LHL_REG(sih, gpio_int_st_port_adr[0], | |
96 | 1 << PCIE_GPIO1_GPIO_PIN, 1 << PCIE_GPIO1_GPIO_PIN); | |
97 | #if !defined(_CFEZ_) | |
98 | si_gci_set_functionsel(sih, 1, CC4347_FNSEL_SAMEASPIN); | |
99 | #endif // endif | |
100 | ||
101 | /* PCIE perst */ | |
102 | LHL_REG(sih, gpio_int_st_port_adr[0], | |
103 | 1 << PCIE_PERST_GPIO_PIN, 1 << PCIE_PERST_GPIO_PIN); | |
104 | LHL_REG(sih, gpio_ctrl_iocfg_p_adr[PCIE_PERST_GPIO_PIN], ~0, | |
105 | (1 << GCI_GPIO_STS_EDGE_TRIG_BIT | | |
106 | 1 << GCI_GPIO_STS_WL_DIN_SELECT)); | |
107 | LHL_REG(sih, gpio_int_en_port_adr[0], | |
108 | 1 << PCIE_PERST_GPIO_PIN, 1 << PCIE_PERST_GPIO_PIN); | |
109 | LHL_REG(sih, gpio_int_st_port_adr[0], | |
110 | 1 << PCIE_PERST_GPIO_PIN, 1 << PCIE_PERST_GPIO_PIN); | |
111 | ||
112 | /* PCIE clkreq */ | |
113 | LHL_REG(sih, gpio_int_st_port_adr[0], | |
114 | 1 << PCIE_CLKREQ_GPIO_PIN, 1 << PCIE_CLKREQ_GPIO_PIN); | |
115 | LHL_REG(sih, gpio_ctrl_iocfg_p_adr[PCIE_CLKREQ_GPIO_PIN], ~0, | |
116 | (1 << GCI_GPIO_STS_EDGE_TRIG_BIT | | |
117 | 1 << GCI_GPIO_STS_NEG_EDGE_TRIG_BIT | | |
118 | 1 << GCI_GPIO_STS_WL_DIN_SELECT)); | |
119 | LHL_REG(sih, gpio_int_en_port_adr[0], | |
120 | 1 << PCIE_CLKREQ_GPIO_PIN, 1 << PCIE_CLKREQ_GPIO_PIN); | |
121 | LHL_REG(sih, gpio_int_st_port_adr[0], | |
122 | 1 << PCIE_CLKREQ_GPIO_PIN, 1 << PCIE_CLKREQ_GPIO_PIN); | |
123 | } | |
124 | } | |
125 | ||
126 | /* To skip this function, specify a invalid "lpo_select" value in nvram */ | |
127 | int | |
128 | si_lhl_set_lpoclk(si_t *sih, osl_t *osh, uint32 lpo_force) | |
129 | { | |
130 | gciregs_t *gciregs; | |
131 | uint clk_det_cnt, status; | |
132 | int lhl_wlclk_sel; | |
133 | uint32 lpo = 0; | |
134 | int timeout = 0; | |
135 | gciregs = si_setcore(sih, GCI_CORE_ID, 0); | |
136 | ||
137 | ASSERT(gciregs != NULL); | |
138 | ||
139 | /* Apply nvram override to lpo */ | |
140 | if ((lpo_force == LHL_LPO_AUTO) && ((lpo = (uint32)getintvar(NULL, "lpo_select")) == 0)) { | |
141 | lpo = LHL_OSC_32k_ENAB; | |
142 | } else { | |
143 | lpo = lpo_force; | |
144 | } | |
145 | ||
146 | /* Power up the desired LPO */ | |
147 | switch (lpo) { | |
148 | case LHL_EXT_LPO_ENAB: | |
149 | LHL_REG(sih, lhl_main_ctl_adr, EXTLPO_BUF_PD, 0); | |
150 | lhl_wlclk_sel = LHL_EXT_SEL; | |
151 | break; | |
152 | ||
153 | case LHL_LPO1_ENAB: | |
154 | LHL_REG(sih, lhl_main_ctl_adr, LPO1_PD_EN, 0); | |
155 | lhl_wlclk_sel = LHL_LPO1_SEL; | |
156 | break; | |
157 | ||
158 | case LHL_LPO2_ENAB: | |
159 | LHL_REG(sih, lhl_main_ctl_adr, LPO2_PD_EN, 0); | |
160 | lhl_wlclk_sel = LHL_LPO2_SEL; | |
161 | break; | |
162 | ||
163 | case LHL_OSC_32k_ENAB: | |
164 | LHL_REG(sih, lhl_main_ctl_adr, OSC_32k_PD, 0); | |
165 | lhl_wlclk_sel = LHL_32k_SEL; | |
166 | break; | |
167 | ||
168 | default: | |
169 | goto done; | |
170 | } | |
171 | ||
172 | LHL_REG(sih, lhl_clk_det_ctl_adr, | |
173 | LHL_CLK_DET_CTL_AD_CNTR_CLK_SEL, lhl_wlclk_sel); | |
174 | ||
175 | /* Detect the desired LPO */ | |
176 | ||
177 | LHL_REG(sih, lhl_clk_det_ctl_adr, LHL_CLK_DET_CTL_ADR_LHL_CNTR_EN, 0); | |
178 | LHL_REG(sih, lhl_clk_det_ctl_adr, | |
179 | LHL_CLK_DET_CTL_ADR_LHL_CNTR_CLR, LHL_CLK_DET_CTL_ADR_LHL_CNTR_CLR); | |
180 | timeout = 0; | |
181 | clk_det_cnt = | |
182 | ((R_REG(osh, &gciregs->lhl_clk_det_ctl_adr) & LHL_CLK_DET_CNT) >> | |
183 | LHL_CLK_DET_CNT_SHIFT); | |
184 | while (clk_det_cnt != 0 && timeout <= LPO_SEL_TIMEOUT) { | |
185 | OSL_DELAY(10); | |
186 | clk_det_cnt = | |
187 | ((R_REG(osh, &gciregs->lhl_clk_det_ctl_adr) & LHL_CLK_DET_CNT) >> | |
188 | LHL_CLK_DET_CNT_SHIFT); | |
189 | timeout++; | |
190 | } | |
191 | ||
192 | if (clk_det_cnt != 0) { | |
193 | LHL_ERROR(("Clock not present as clear did not work timeout = %d\n", timeout)); | |
194 | goto error; | |
195 | } | |
196 | LHL_REG(sih, lhl_clk_det_ctl_adr, LHL_CLK_DET_CTL_ADR_LHL_CNTR_CLR, 0); | |
197 | LHL_REG(sih, lhl_clk_det_ctl_adr, LHL_CLK_DET_CTL_ADR_LHL_CNTR_EN, | |
198 | LHL_CLK_DET_CTL_ADR_LHL_CNTR_EN); | |
199 | clk_det_cnt = | |
200 | ((R_REG(osh, &gciregs->lhl_clk_det_ctl_adr) & LHL_CLK_DET_CNT) >> | |
201 | LHL_CLK_DET_CNT_SHIFT); | |
202 | timeout = 0; | |
203 | ||
204 | while (clk_det_cnt <= CLK_DET_CNT_THRESH && timeout <= LPO_SEL_TIMEOUT) { | |
205 | OSL_DELAY(10); | |
206 | clk_det_cnt = | |
207 | ((R_REG(osh, &gciregs->lhl_clk_det_ctl_adr) & LHL_CLK_DET_CNT) >> | |
208 | LHL_CLK_DET_CNT_SHIFT); | |
209 | timeout++; | |
210 | } | |
211 | ||
212 | if (timeout >= LPO_SEL_TIMEOUT) { | |
213 | LHL_ERROR(("LPO is not available timeout = %u\n, timeout", timeout)); | |
214 | goto error; | |
215 | } | |
216 | ||
217 | /* Select the desired LPO */ | |
218 | ||
219 | LHL_REG(sih, lhl_main_ctl_adr, | |
220 | LHL_MAIN_CTL_ADR_LHL_WLCLK_SEL, (lhl_wlclk_sel) << LPO_SEL_SHIFT); | |
221 | ||
222 | status = ((R_REG(osh, &gciregs->lhl_clk_status_adr) & LHL_MAIN_CTL_ADR_FINAL_CLK_SEL) == | |
223 | (unsigned)(((1 << lhl_wlclk_sel) << LPO_FINAL_SEL_SHIFT))) ? 1 : 0; | |
224 | timeout = 0; | |
225 | while (!status && timeout <= LPO_SEL_TIMEOUT) { | |
226 | OSL_DELAY(10); | |
227 | status = | |
228 | ((R_REG(osh, &gciregs->lhl_clk_status_adr) & LHL_MAIN_CTL_ADR_FINAL_CLK_SEL) == | |
229 | (unsigned)(((1 << lhl_wlclk_sel) << LPO_FINAL_SEL_SHIFT))) ? 1 : 0; | |
230 | timeout++; | |
231 | } | |
232 | ||
233 | if (timeout >= LPO_SEL_TIMEOUT) { | |
234 | LHL_ERROR(("LPO is not available timeout = %u\n, timeout", timeout)); | |
235 | goto error; | |
236 | } | |
237 | /* Power down the rest of the LPOs */ | |
238 | ||
239 | if (lpo != LHL_EXT_LPO_ENAB) { | |
240 | LHL_REG(sih, lhl_main_ctl_adr, EXTLPO_BUF_PD, EXTLPO_BUF_PD); | |
241 | } | |
242 | ||
243 | if (lpo != LHL_LPO1_ENAB) { | |
244 | LHL_REG(sih, lhl_main_ctl_adr, LPO1_PD_EN, LPO1_PD_EN); | |
245 | LHL_REG(sih, lhl_main_ctl_adr, LPO1_PD_SEL, LPO1_PD_SEL_VAL); | |
246 | } | |
247 | if (lpo != LHL_LPO2_ENAB) { | |
248 | LHL_REG(sih, lhl_main_ctl_adr, LPO2_PD_EN, LPO2_PD_EN); | |
249 | LHL_REG(sih, lhl_main_ctl_adr, LPO2_PD_SEL, LPO2_PD_SEL_VAL); | |
250 | } | |
251 | if (lpo != LHL_OSC_32k_ENAB) { | |
252 | LHL_REG(sih, lhl_main_ctl_adr, OSC_32k_PD, OSC_32k_PD); | |
253 | } | |
254 | if (lpo != RADIO_LPO_ENAB) { | |
255 | si_gci_chipcontrol(sih, CC_GCI_CHIPCTRL_06, LPO_SEL, 0); | |
256 | } | |
257 | done: | |
258 | return BCME_OK; | |
259 | error: | |
260 | ROMMABLE_ASSERT(0); | |
261 | return BCME_ERROR; | |
262 | } | |
263 | ||
264 | void | |
265 | si_lhl_timer_config(si_t *sih, osl_t *osh, int timer_type) | |
266 | { | |
267 | uint origidx; | |
268 | pmuregs_t *pmu = NULL; | |
269 | ||
270 | /* Remember original core before switch to chipc/pmu */ | |
271 | origidx = si_coreidx(sih); | |
272 | if (AOB_ENAB(sih)) { | |
273 | pmu = si_setcore(sih, PMU_CORE_ID, 0); | |
274 | } else { | |
275 | pmu = si_setcoreidx(sih, SI_CC_IDX); | |
276 | } | |
277 | ||
278 | ASSERT(pmu != NULL); | |
279 | ||
280 | switch (timer_type) { | |
281 | case LHL_MAC_TIMER: | |
282 | /* Enable MAC Timer interrupt */ | |
283 | LHL_REG(sih, lhl_wl_mactim0_intrp_adr, | |
284 | (LHL_WL_MACTIM0_INTRP_EN | LHL_WL_MACTIM0_INTRP_EDGE_TRIGGER), | |
285 | (LHL_WL_MACTIM0_INTRP_EN | LHL_WL_MACTIM0_INTRP_EDGE_TRIGGER)); | |
286 | ||
287 | /* Programs bits for MACPHY_CLK_AVAIL and all its dependent bits in | |
288 | * MacResourceReqMask0. | |
289 | */ | |
290 | PMU_REG(sih, mac_res_req_mask, ~0, si_pmu_rsrc_macphy_clk_deps(sih, osh, 0)); | |
291 | ||
292 | /* One time init of mac_res_req_timer to enable interrupt and clock request */ | |
293 | HND_PMU_SYNC_WR(sih, pmu, pmu, osh, | |
294 | PMUREGADDR(sih, pmu, pmu, mac_res_req_timer), | |
295 | ((PRRT_ALP_REQ | PRRT_HQ_REQ | PRRT_INTEN) << FLAGS_SHIFT)); | |
296 | ||
297 | if (si_numd11coreunits(sih) > 1) { | |
298 | LHL_REG(sih, lhl_wl_mactim1_intrp_adr, | |
299 | (LHL_WL_MACTIM0_INTRP_EN | LHL_WL_MACTIM0_INTRP_EDGE_TRIGGER), | |
300 | (LHL_WL_MACTIM0_INTRP_EN | LHL_WL_MACTIM0_INTRP_EDGE_TRIGGER)); | |
301 | ||
302 | PMU_REG(sih, mac_res_req_mask1, ~0, | |
303 | si_pmu_rsrc_macphy_clk_deps(sih, osh, 1)); | |
304 | ||
305 | HND_PMU_SYNC_WR(sih, pmu, pmu, osh, | |
306 | PMUREGADDR(sih, pmu, pmu, mac_res_req_timer1), | |
307 | ((PRRT_ALP_REQ | PRRT_HQ_REQ | PRRT_INTEN) << FLAGS_SHIFT)); | |
308 | } | |
309 | ||
310 | break; | |
311 | ||
312 | case LHL_ARM_TIMER: | |
313 | /* Enable ARM Timer interrupt */ | |
314 | LHL_REG(sih, lhl_wl_armtim0_intrp_adr, | |
315 | (LHL_WL_ARMTIM0_INTRP_EN | LHL_WL_ARMTIM0_INTRP_EDGE_TRIGGER), | |
316 | (LHL_WL_ARMTIM0_INTRP_EN | LHL_WL_ARMTIM0_INTRP_EDGE_TRIGGER)); | |
317 | ||
318 | /* Programs bits for HT_AVAIL and all its dependent bits in ResourceReqMask0 */ | |
319 | PMU_REG(sih, res_req_mask, ~0, si_pmu_rsrc_ht_avail_clk_deps(sih, osh)); | |
320 | ||
321 | /* One time init of res_req_timer to enable interrupt and clock request | |
322 | * For low power request only ALP (HT_AVAIL is anyway requested by res_req_mask) | |
323 | */ | |
324 | HND_PMU_SYNC_WR(sih, pmu, pmu, osh, | |
325 | PMUREGADDR(sih, pmu, pmu, res_req_timer), | |
326 | ((PRRT_ALP_REQ | PRRT_HQ_REQ | PRRT_INTEN) << FLAGS_SHIFT)); | |
327 | break; | |
328 | } | |
329 | ||
330 | /* Return to original core */ | |
331 | si_setcoreidx(sih, origidx); | |
332 | } | |
333 | ||
334 | void | |
335 | si_lhl_timer_enable(si_t *sih) | |
336 | { | |
337 | /* Enable clks for pmu int propagation */ | |
338 | PMU_REG(sih, pmuintctrl0, PMU_INTC_ALP_REQ, PMU_INTC_ALP_REQ); | |
339 | ||
340 | PMU_REG(sih, pmuintmask0, RSRC_INTR_MASK_TIMER_INT_0, RSRC_INTR_MASK_TIMER_INT_0); | |
341 | LHL_REG(sih, lhl_main_ctl_adr, LHL_FAST_WRITE_EN, LHL_FAST_WRITE_EN); | |
342 | PMU_REG(sih, pmucontrol_ext, PCTL_EXT_USE_LHL_TIMER, PCTL_EXT_USE_LHL_TIMER); | |
343 | } | |
344 | ||
345 | void | |
346 | si_lhl_ilp_config(si_t *sih, osl_t *osh, uint32 ilp_period) | |
347 | { | |
348 | gciregs_t *gciregs; | |
349 | if (CHIPID(sih->chip) == BCM43012_CHIP_ID) { | |
350 | gciregs = si_setcore(sih, GCI_CORE_ID, 0); | |
351 | ASSERT(gciregs != NULL); | |
352 | W_REG(osh, &gciregs->lhl_wl_ilp_val_adr, ilp_period); | |
353 | } | |
354 | } | |
355 | ||
356 | #ifdef BCMULP | |
357 | void | |
358 | si_lhl_disable_sdio_wakeup(si_t *sih) | |
359 | { | |
360 | /* Disable the interrupt */ | |
361 | LHL_REG(sih, gpio_int_en_port_adr[0], (1 << ULP_SDIO_CMD_PIN), 0); | |
362 | ||
363 | /* Clear the pending interrupt status */ | |
364 | LHL_REG(sih, gpio_int_st_port_adr[0], (1 << ULP_SDIO_CMD_PIN), (1 << ULP_SDIO_CMD_PIN)); | |
365 | } | |
366 | ||
367 | void | |
368 | si_lhl_enable_sdio_wakeup(si_t *sih, osl_t *osh) | |
369 | { | |
370 | ||
371 | gciregs_t *gciregs; | |
372 | pmuregs_t *pmu; | |
373 | gciregs = si_setcore(sih, GCI_CORE_ID, 0); | |
374 | ASSERT(gciregs != NULL); | |
375 | if (CHIPID(sih->chip) == BCM43012_CHIP_ID) { | |
376 | /* For SDIO_CMD configure P8 for wake on negedge | |
377 | * LHL 0 -> edge trigger intr mode, | |
378 | * 1 -> neg edge trigger intr mode , | |
379 | * 6 -> din from wl side enable | |
380 | */ | |
381 | OR_REG(osh, &gciregs->gpio_ctrl_iocfg_p_adr[ULP_SDIO_CMD_PIN], | |
382 | (1 << GCI_GPIO_STS_EDGE_TRIG_BIT | | |
383 | 1 << GCI_GPIO_STS_NEG_EDGE_TRIG_BIT | | |
384 | 1 << GCI_GPIO_STS_WL_DIN_SELECT)); | |
385 | /* Clear any old interrupt status */ | |
386 | OR_REG(osh, &gciregs->gpio_int_st_port_adr[0], 1 << ULP_SDIO_CMD_PIN); | |
387 | ||
388 | /* LHL GPIO[8] intr en , GPIO[8] is mapped to SDIO_CMD */ | |
389 | /* Enable P8 to generate interrupt */ | |
390 | OR_REG(osh, &gciregs->gpio_int_en_port_adr[0], 1 << ULP_SDIO_CMD_PIN); | |
391 | ||
392 | /* Clear LHL GPIO status to trigger GCI Interrupt */ | |
393 | OR_REG(osh, &gciregs->gci_intstat, GCI_INTSTATUS_LHLWLWAKE); | |
394 | /* Enable LHL GPIO Interrupt to trigger GCI Interrupt */ | |
395 | OR_REG(osh, &gciregs->gci_intmask, GCI_INTMASK_LHLWLWAKE); | |
396 | OR_REG(osh, &gciregs->gci_wakemask, GCI_WAKEMASK_LHLWLWAKE); | |
397 | /* Note ->Enable GCI interrupt to trigger Chipcommon interrupt | |
398 | * Set EciGciIntEn in IntMask and will be done from FCBS saved tuple | |
399 | */ | |
400 | /* Enable LHL to trigger extWake upto HT_AVAIL */ | |
401 | /* LHL GPIO Interrupt is mapped to extWake[7] */ | |
402 | pmu = si_setcore(sih, PMU_CORE_ID, 0); | |
403 | ASSERT(pmu != NULL); | |
404 | /* Set bit 4 and 7 in ExtWakeMask */ | |
405 | W_REG(osh, &pmu->extwakemask[0], CI_ECI | CI_WECI); | |
406 | /* Program bits for MACPHY_CLK_AVAIL rsrc in ExtWakeReqMaskN */ | |
407 | W_REG(osh, &pmu->extwakereqmask[0], SI_LHL_EXT_WAKE_REQ_MASK_MAGIC); | |
408 | /* Program 0 (no need to request explicitly for any backplane clk) */ | |
409 | W_REG(osh, &pmu->extwakectrl, 0x0); | |
410 | /* Note: Configure MAC/Ucode to receive interrupt | |
411 | * it will be done from saved tuple using FCBS code | |
412 | */ | |
413 | } | |
414 | } | |
415 | #endif /* BCMULP */ | |
416 | ||
417 | lhl_reg_set_t lv_sleep_mode_4369_lhl_reg_set[] = | |
418 | { | |
419 | /* set wl_sleep_en */ | |
420 | {LHL_REG_OFF(lhl_top_pwrseq_ctl_adr), (1 << 0), (1 << 0)}, | |
421 | ||
422 | /* set top_pwrsw_en, top_slb_en, top_iso_en */ | |
423 | {LHL_REG_OFF(lhl_top_pwrseq_ctl_adr), BCM_MASK32(5, 3), (0x0 << 3)}, | |
424 | ||
425 | /* set VMUX_asr_sel_en */ | |
426 | {LHL_REG_OFF(lhl_top_pwrseq_ctl_adr), (1 << 8), (1 << 8)}, | |
427 | ||
428 | /* lhl_lp_main_ctl_adr, disable lp_mode_en, set CSR and ASR field enables for LV mode */ | |
429 | {LHL_REG_OFF(lhl_lp_main_ctl_adr), BCM_MASK32(21, 0), 0x3F89FF}, | |
430 | ||
431 | /* lhl_lp_main_ctl1_adr, set CSR field values - CSR_adj - 0.64V and trim_adj -5mV */ | |
432 | {LHL_REG_OFF(lhl_lp_main_ctl1_adr), BCM_MASK32(23, 0), 0x9E8F97}, | |
433 | ||
434 | /* lhl_lp_main_ctl2_adr, set ASR field values - ASR_adj - 0.76V and trim_adj +5mV */ | |
435 | {LHL_REG_OFF(lhl_lp_main_ctl2_adr), BCM_MASK32(13, 0), 0x07EE}, | |
436 | ||
437 | /* lhl_lp_dn_ctl_adr, set down count for CSR fields- adj, mode, overi_dis */ | |
438 | {LHL_REG_OFF(lhl_lp_dn_ctl_adr), ~0, ((LHL4369_CSR_OVERI_DIS_DWN_CNT << 16) | | |
439 | (LHL4369_CSR_MODE_DWN_CNT << 8) | (LHL4369_CSR_ADJ_DWN_CNT << 0))}, | |
440 | ||
441 | /* lhl_lp_up_ctl_adr, set up count for CSR fields- adj, mode, overi_dis */ | |
442 | {LHL_REG_OFF(lhl_lp_up_ctl_adr), ~0, ((LHL4369_CSR_OVERI_DIS_UP_CNT << 16) | | |
443 | (LHL4369_CSR_MODE_UP_CNT << 8) | (LHL4369_CSR_ADJ_UP_CNT << 0))}, | |
444 | ||
445 | /* lhl_lp_dn_ctl1_adr, set down count for hpbg_chop_dis, ASR_adj, vddc_sw_dis */ | |
446 | {LHL_REG_OFF(lhl_lp_dn_ctl1_adr), ~0, ((LHL4369_VDDC_SW_DIS_DWN_CNT << 24) | | |
447 | (LHL4369_ASR_ADJ_DWN_CNT << 16) | (LHL4369_HPBG_CHOP_DIS_DWN_CNT << 0))}, | |
448 | ||
449 | /* lhl_lp_up_ctl1_adr, set up count for hpbg_chop_dis, ASR_adj, vddc_sw_dis */ | |
450 | {LHL_REG_OFF(lhl_lp_up_ctl1_adr), ~0, ((LHL4369_VDDC_SW_DIS_UP_CNT << 24) | | |
451 | (LHL4369_ASR_ADJ_UP_CNT << 16) | (LHL4369_HPBG_CHOP_DIS_UP_CNT << 0))}, | |
452 | ||
453 | /* lhl_lp_dn_ctl4_adr, set down count for ASR fields - | |
454 | * clk4m_dis, lppfm_mode, mode_sel, manual_mode | |
455 | */ | |
456 | {LHL_REG_OFF(lhl_lp_dn_ctl4_adr), ~0, ((LHL4369_ASR_MANUAL_MODE_DWN_CNT << 24) | | |
457 | (LHL4369_ASR_MODE_SEL_DWN_CNT << 16) | (LHL4369_ASR_LPPFM_MODE_DWN_CNT << 8) | | |
458 | (LHL4369_ASR_CLK4M_DIS_DWN_CNT << 0))}, | |
459 | ||
460 | /* lhl_lp_up_ctl4_adr, set up count for ASR fields - | |
461 | * clk4m_dis, lppfm_mode, mode_sel, manual_mode | |
462 | */ | |
463 | {LHL_REG_OFF(lhl_lp_up_ctl4_adr), ~0, ((LHL4369_ASR_MANUAL_MODE_UP_CNT << 24) | | |
464 | (LHL4369_ASR_MODE_SEL_UP_CNT << 16)| (LHL4369_ASR_LPPFM_MODE_UP_CNT << 8) | | |
465 | (LHL4369_ASR_CLK4M_DIS_UP_CNT << 0))}, | |
466 | ||
467 | /* lhl_lp_dn_ctl3_adr, set down count for hpbg_pu, srbg_ref, ASR_overi_dis, | |
468 | * CSR_pfm_pwr_slice_en | |
469 | */ | |
470 | {LHL_REG_OFF(lhl_lp_dn_ctl3_adr), ~0, ((LHL4369_PFM_PWR_SLICE_DWN_CNT << 24) | | |
471 | (LHL4369_ASR_OVERI_DIS_DWN_CNT << 16) | (LHL4369_SRBG_REF_SEL_DWN_CNT << 8) | | |
472 | (LHL4369_HPBG_PU_EN_DWN_CNT << 0))}, | |
473 | ||
474 | /* lhl_lp_up_ctl3_adr, set up count for hpbg_pu, srbg_ref, ASR_overi_dis, | |
475 | * CSR_pfm_pwr_slice_en | |
476 | */ | |
477 | {LHL_REG_OFF(lhl_lp_up_ctl3_adr), ~0, ((LHL4369_PFM_PWR_SLICE_UP_CNT << 24) | | |
478 | (LHL4369_ASR_OVERI_DIS_UP_CNT << 16) | (LHL4369_SRBG_REF_SEL_UP_CNT << 8) | | |
479 | (LHL4369_HPBG_PU_EN_UP_CNT << 0))}, | |
480 | ||
481 | /* lhl_lp_dn_ctl2_adr, set down count for CSR_trim_adj */ | |
482 | {LHL_REG_OFF(lhl_lp_dn_ctl2_adr), ~0, (LHL4369_CSR_TRIM_ADJ_DWN_CNT << 16)}, | |
483 | ||
484 | /* lhl_lp_up_ctl2_adr, set up count for CSR_trim_adj */ | |
485 | {LHL_REG_OFF(lhl_lp_up_ctl2_adr), ~0, (LHL4369_CSR_TRIM_ADJ_UP_CNT << 16)}, | |
486 | ||
487 | /* lhl_lp_dn_ctl5_adr, set down count for ASR_trim_adj */ | |
488 | {LHL_REG_OFF(lhl_lp_dn_ctl5_adr), ~0, (LHL4369_ASR_TRIM_ADJ_DWN_CNT << 0)}, | |
489 | ||
490 | /* lhl_lp_up_ctl5_adr, set down count for ASR_trim_adj */ | |
491 | {LHL_REG_OFF(lhl_lp_up_ctl5_adr), ~0, (LHL4369_ASR_TRIM_ADJ_UP_CNT << 0)}, | |
492 | ||
493 | /* Change the default down count values for the resources */ | |
494 | /* lhl_top_pwrdn_ctl_adr, set down count for top_level_sleep, iso, slb and pwrsw */ | |
495 | {LHL_REG_OFF(lhl_top_pwrdn_ctl_adr), ~0, ((LHL4369_PWRSW_EN_DWN_CNT << 24) | | |
496 | (LHL4369_SLB_EN_DWN_CNT << 16) | (LHL4369_ISO_EN_DWN_CNT << 8))}, | |
497 | ||
498 | /* lhl_top_pwrdn2_ctl_adr, set down count for VMUX_asr_sel */ | |
499 | {LHL_REG_OFF(lhl_top_pwrdn2_ctl_adr), ~0, (LHL4369_VMUX_ASR_SEL_DWN_CNT << 16)}, | |
500 | ||
501 | /* Change the default up count values for the resources */ | |
502 | /* lhl_top_pwrup_ctl_adr, set up count for top_level_sleep, iso, slb and pwrsw */ | |
503 | {LHL_REG_OFF(lhl_top_pwrup_ctl_adr), ~0, ((LHL4369_PWRSW_EN_UP_CNT << 24) | | |
504 | (LHL4369_SLB_EN_UP_CNT << 16) | (LHL4369_ISO_EN_UP_CNT << 8))}, | |
505 | ||
506 | /* lhl_top_pwrdn2_ctl_adr, set down count for VMUX_asr_sel */ | |
507 | {LHL_REG_OFF(lhl_top_pwrup2_ctl_adr), ~0, ((LHL4369_VMUX_ASR_SEL_UP_CNT << 16))}, | |
508 | ||
509 | /* Enable lhl interrupt */ | |
510 | {LHL_REG_OFF(gci_intmask), (1 << 30), (1 << 30)}, | |
511 | ||
512 | /* Enable LHL Wake up */ | |
513 | {LHL_REG_OFF(gci_wakemask), (1 << 30), (1 << 30)}, | |
514 | ||
515 | /* Making forceOTPpwrOn 0 */ | |
516 | {LHL_REG_OFF(otpcontrol), (1 << 16), 0} | |
517 | }; | |
518 | ||
519 | /* LV sleep mode summary: | |
520 | * LV mode is where both ABUCK and CBUCK are programmed to low voltages during | |
521 | * sleep, and VMUX selects ABUCK as VDDOUT_AON. LPLDO needs to power off. | |
522 | * With ASR ON, LPLDO OFF | |
523 | */ | |
524 | void | |
525 | si_set_lv_sleep_mode_lhl_config_4369(si_t *sih) | |
526 | { | |
527 | uint i; | |
528 | uint coreidx = si_findcoreidx(sih, GCI_CORE_ID, 0); | |
529 | lhl_reg_set_t *regs = lv_sleep_mode_4369_lhl_reg_set; | |
530 | ||
531 | /* Enable LHL LV mode: | |
532 | * lhl_top_pwrseq_ctl_adr, set wl_sleep_en, iso_en, slb_en, pwrsw_en,VMUX_asr_sel_en | |
533 | */ | |
534 | for (i = 0; i < ARRAYSIZE(lv_sleep_mode_4369_lhl_reg_set); i++) { | |
535 | si_corereg(sih, coreidx, regs[i].offset, regs[i].mask, regs[i].val); | |
536 | } | |
537 | } |