hndlhl.c 19 KB

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