hndpmu.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. /*
  2. * Misc utility routines for accessing PMU corerev 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 700652 2017-05-20 02:44:31Z $
  31. */
  32. /**
  33. * @file
  34. * Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs.
  35. * However, in the context of this file the baseband ('BB') PLL/FLL is referred to.
  36. *
  37. * Throughout this code, the prefixes 'pmu1_' and 'pmu2_' are used.
  38. * They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012)
  39. * pmu1_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop). It supports
  40. * fractional frequency generation. pmu2_ does not support fractional frequency generation.
  41. */
  42. #include <bcm_cfg.h>
  43. #include <typedefs.h>
  44. #include <bcmdefs.h>
  45. #include <osl.h>
  46. #include <bcmutils.h>
  47. #include <siutils.h>
  48. #include <bcmdevs.h>
  49. #include <hndsoc.h>
  50. #include <sbchipc.h>
  51. #include <hndchipc.h>
  52. #include <hndpmu.h>
  53. #include <hndlhl.h>
  54. #if defined(BCMULP)
  55. #include <ulp.h>
  56. #endif /* defined(BCMULP) */
  57. #include <sbgci.h>
  58. #ifdef EVENT_LOG_COMPILE
  59. #include <event_log.h>
  60. #endif // endif
  61. #include <sbgci.h>
  62. #include <lpflags.h>
  63. #define PMU_ERROR(args)
  64. #define PMU_MSG(args)
  65. /* To check in verbose debugging messages not intended
  66. * to be on except on private builds.
  67. */
  68. #define PMU_NONE(args)
  69. #define flags_shift 14
  70. /** contains resource bit positions for a specific chip */
  71. struct rsc_per_chip_s {
  72. uint8 ht_avail;
  73. uint8 macphy_clkavail;
  74. uint8 ht_start;
  75. uint8 otp_pu;
  76. uint8 macphy_aux_clkavail;
  77. };
  78. typedef struct rsc_per_chip_s rsc_per_chip_t;
  79. #if defined(BCMPMU_STATS) && !defined(BCMPMU_STATS_DISABLED)
  80. bool _pmustatsenab = TRUE;
  81. #else
  82. bool _pmustatsenab = FALSE;
  83. #endif /* BCMPMU_STATS */
  84. /**
  85. * Balance between stable SDIO operation and power consumption is achieved using this function.
  86. * Note that each drive strength table is for a specific VDDIO of the SDIO pads, ideally this
  87. * function should read the VDDIO itself to select the correct table. For now it has been solved
  88. * with the 'BCM_SDIO_VDDIO' preprocessor constant.
  89. *
  90. * 'drivestrength': desired pad drive strength in mA. Drive strength of 0 requests tri-state (if
  91. * hardware supports this), if no hw support drive strength is not programmed.
  92. */
  93. void
  94. si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
  95. {
  96. /*
  97. * Note:
  98. * This function used to set the SDIO drive strength via PMU_CHIPCTL1 for the
  99. * 43143, 4330, 4334, 4336, 43362 chips. These chips are now no longer supported, so
  100. * the code has been deleted.
  101. * Newer chips have the SDIO drive strength setting via a GCI Chip Control register,
  102. * but the bit definitions are chip-specific. We are keeping this function available
  103. * (accessed via DHD 'sdiod_drive' IOVar) in case these newer chips need to provide access.
  104. */
  105. UNUSED_PARAMETER(sih);
  106. UNUSED_PARAMETER(osh);
  107. UNUSED_PARAMETER(drivestrength);
  108. }
  109. void
  110. si_switch_pmu_dependency(si_t *sih, uint mode)
  111. {
  112. #ifdef DUAL_PMU_SEQUENCE
  113. osl_t *osh = si_osh(sih);
  114. uint32 current_res_state;
  115. uint32 min_mask, max_mask;
  116. const pmu_res_depend_t *pmu_res_depend_table = NULL;
  117. uint pmu_res_depend_table_sz = 0;
  118. uint origidx;
  119. pmuregs_t *pmu;
  120. chipcregs_t *cc;
  121. BCM_REFERENCE(cc);
  122. origidx = si_coreidx(sih);
  123. if (AOB_ENAB(sih)) {
  124. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  125. cc = si_setcore(sih, CC_CORE_ID, 0);
  126. } else {
  127. pmu = si_setcoreidx(sih, SI_CC_IDX);
  128. cc = si_setcoreidx(sih, SI_CC_IDX);
  129. }
  130. ASSERT(pmu != NULL);
  131. current_res_state = R_REG(osh, &pmu->res_state);
  132. min_mask = R_REG(osh, &pmu->min_res_mask);
  133. max_mask = R_REG(osh, &pmu->max_res_mask);
  134. W_REG(osh, &pmu->min_res_mask, (min_mask | current_res_state));
  135. switch (mode) {
  136. case PMU_4364_1x1_MODE:
  137. {
  138. if (CHIPID(sih->chip) == BCM4364_CHIP_ID) {
  139. pmu_res_depend_table = bcm4364a0_res_depend_1x1;
  140. pmu_res_depend_table_sz =
  141. ARRAYSIZE(bcm4364a0_res_depend_1x1);
  142. max_mask = PMU_4364_MAX_MASK_1x1;
  143. W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE);
  144. W_REG(osh, &pmu->res_updn_timer, PMU_4364_SAVE_RESTORE_UPDNTIME_1x1);
  145. #if defined(SAVERESTORE)
  146. if (SR_ENAB()) {
  147. /* Disable 3x3 SR engine */
  148. W_REG(osh, &cc->sr1_control0,
  149. CC_SR0_4364_SR_ENG_CLK_EN |
  150. CC_SR0_4364_SR_RSRC_TRIGGER |
  151. CC_SR0_4364_SR_WD_MEM_MIN_DIV |
  152. CC_SR0_4364_SR_INVERT_CLK |
  153. CC_SR0_4364_SR_ENABLE_HT |
  154. CC_SR0_4364_SR_ALLOW_PIC |
  155. CC_SR0_4364_SR_PMU_MEM_DISABLE);
  156. }
  157. #endif /* SAVERESTORE */
  158. }
  159. break;
  160. }
  161. case PMU_4364_3x3_MODE:
  162. {
  163. if (CHIPID(sih->chip) == BCM4364_CHIP_ID) {
  164. W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE);
  165. W_REG(osh, &pmu->res_updn_timer,
  166. PMU_4364_SAVE_RESTORE_UPDNTIME_3x3);
  167. /* Change the dependency table only if required */
  168. if ((max_mask != PMU_4364_MAX_MASK_3x3) ||
  169. (max_mask != PMU_4364_MAX_MASK_RSDB)) {
  170. pmu_res_depend_table = bcm4364a0_res_depend_rsdb;
  171. pmu_res_depend_table_sz =
  172. ARRAYSIZE(bcm4364a0_res_depend_rsdb);
  173. max_mask = PMU_4364_MAX_MASK_3x3;
  174. }
  175. #if defined(SAVERESTORE)
  176. if (SR_ENAB()) {
  177. /* Enable 3x3 SR engine */
  178. W_REG(osh, &cc->sr1_control0,
  179. CC_SR0_4364_SR_ENG_CLK_EN |
  180. CC_SR0_4364_SR_RSRC_TRIGGER |
  181. CC_SR0_4364_SR_WD_MEM_MIN_DIV |
  182. CC_SR0_4364_SR_INVERT_CLK |
  183. CC_SR0_4364_SR_ENABLE_HT |
  184. CC_SR0_4364_SR_ALLOW_PIC |
  185. CC_SR0_4364_SR_PMU_MEM_DISABLE |
  186. CC_SR0_4364_SR_ENG_EN_MASK);
  187. }
  188. #endif /* SAVERESTORE */
  189. }
  190. break;
  191. }
  192. case PMU_4364_RSDB_MODE:
  193. default:
  194. {
  195. if (CHIPID(sih->chip) == BCM4364_CHIP_ID) {
  196. W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE);
  197. W_REG(osh, &pmu->res_updn_timer,
  198. PMU_4364_SAVE_RESTORE_UPDNTIME_3x3);
  199. /* Change the dependency table only if required */
  200. if ((max_mask != PMU_4364_MAX_MASK_3x3) ||
  201. (max_mask != PMU_4364_MAX_MASK_RSDB)) {
  202. pmu_res_depend_table =
  203. bcm4364a0_res_depend_rsdb;
  204. pmu_res_depend_table_sz =
  205. ARRAYSIZE(bcm4364a0_res_depend_rsdb);
  206. max_mask = PMU_4364_MAX_MASK_RSDB;
  207. }
  208. #if defined(SAVERESTORE)
  209. if (SR_ENAB()) {
  210. /* Enable 3x3 SR engine */
  211. W_REG(osh, &cc->sr1_control0,
  212. CC_SR0_4364_SR_ENG_CLK_EN |
  213. CC_SR0_4364_SR_RSRC_TRIGGER |
  214. CC_SR0_4364_SR_WD_MEM_MIN_DIV |
  215. CC_SR0_4364_SR_INVERT_CLK |
  216. CC_SR0_4364_SR_ENABLE_HT |
  217. CC_SR0_4364_SR_ALLOW_PIC |
  218. CC_SR0_4364_SR_PMU_MEM_DISABLE |
  219. CC_SR0_4364_SR_ENG_EN_MASK);
  220. }
  221. #endif /* SAVERESTORE */
  222. }
  223. break;
  224. }
  225. }
  226. si_pmu_resdeptbl_upd(sih, osh, pmu, pmu_res_depend_table, pmu_res_depend_table_sz);
  227. W_REG(osh, &pmu->max_res_mask, max_mask);
  228. W_REG(osh, &pmu->min_res_mask, min_mask);
  229. si_pmu_wait_for_steady_state(sih, osh, pmu);
  230. /* Add some delay; allow resources to come up and settle. */
  231. OSL_DELAY(200);
  232. si_setcoreidx(sih, origidx);
  233. #endif /* DUAL_PMU_SEQUENCE */
  234. }
  235. #if defined(BCMULP)
  236. int
  237. si_pmu_ulp_register(si_t *sih)
  238. {
  239. return ulp_p1_module_register(ULP_MODULE_ID_PMU, &ulp_pmu_ctx, (void *)sih);
  240. }
  241. static uint
  242. si_pmu_ulp_get_retention_size_cb(void *handle, ulp_ext_info_t *einfo)
  243. {
  244. ULP_DBG(("%s: sz: %d\n", __FUNCTION__, sizeof(si_pmu_ulp_cr_dat_t)));
  245. return sizeof(si_pmu_ulp_cr_dat_t);
  246. }
  247. static int
  248. si_pmu_ulp_enter_cb(void *handle, ulp_ext_info_t *einfo, uint8 *cache_data)
  249. {
  250. si_pmu_ulp_cr_dat_t crinfo = {0};
  251. crinfo.ilpcycles_per_sec = ilpcycles_per_sec;
  252. ULP_DBG(("%s: ilpcycles_per_sec: %x\n", __FUNCTION__, ilpcycles_per_sec));
  253. memcpy(cache_data, (void*)&crinfo, sizeof(crinfo));
  254. return BCME_OK;
  255. }
  256. static int
  257. si_pmu_ulp_exit_cb(void *handle, uint8 *cache_data,
  258. uint8 *p2_cache_data)
  259. {
  260. si_pmu_ulp_cr_dat_t *crinfo = (si_pmu_ulp_cr_dat_t *)cache_data;
  261. ilpcycles_per_sec = crinfo->ilpcycles_per_sec;
  262. ULP_DBG(("%s: ilpcycles_per_sec: %x, cache_data: %p\n", __FUNCTION__,
  263. ilpcycles_per_sec, cache_data));
  264. return BCME_OK;
  265. }
  266. void
  267. si_pmu_ulp_chipconfig(si_t *sih, osl_t *osh)
  268. {
  269. uint32 reg_val;
  270. BCM_REFERENCE(reg_val);
  271. if (CHIPID(sih->chip) == BCM43012_CHIP_ID) {
  272. /* DS1 reset and clk enable init value config */
  273. si_pmu_chipcontrol(sih, PMU_CHIPCTL14, ~0x0,
  274. (PMUCCTL14_43012_ARMCM3_RESET_INITVAL |
  275. PMUCCTL14_43012_DOT11MAC_CLKEN_INITVAL |
  276. PMUCCTL14_43012_SDIOD_RESET_INIVAL |
  277. PMUCCTL14_43012_SDIO_CLK_DMN_RESET_INITVAL |
  278. PMUCCTL14_43012_SOCRAM_CLKEN_INITVAL |
  279. PMUCCTL14_43012_M2MDMA_RESET_INITVAL |
  280. PMUCCTL14_43012_DOT11MAC_PHY_CLK_EN_INITVAL |
  281. PMUCCTL14_43012_DOT11MAC_PHY_CNTL_EN_INITVAL));
  282. /* Clear SFlash clock request and enable High Quality clock */
  283. CHIPC_REG(sih, clk_ctl_st, CCS_SFLASH_CLKREQ | CCS_HQCLKREQ, CCS_HQCLKREQ);
  284. reg_val = PMU_REG(sih, min_res_mask, ~0x0, ULP_MIN_RES_MASK);
  285. ULP_DBG(("si_pmu_ulp_chipconfig: min_res_mask: 0x%08x\n", reg_val));
  286. /* Force power switch off */
  287. si_pmu_chipcontrol(sih, PMU_CHIPCTL2,
  288. (PMUCCTL02_43012_SUBCORE_PWRSW_FORCE_ON |
  289. PMUCCTL02_43012_PHY_PWRSW_FORCE_ON), 0);
  290. }
  291. }
  292. void
  293. si_pmu_ulp_ilp_config(si_t *sih, osl_t *osh, uint32 ilp_period)
  294. {
  295. pmuregs_t *pmu;
  296. pmu = si_setcoreidx(sih, si_findcoreidx(sih, PMU_CORE_ID, 0));
  297. W_REG(osh, &pmu->ILPPeriod, ilp_period);
  298. si_lhl_ilp_config(sih, osh, ilp_period);
  299. }
  300. /** Initialize DS1 PMU hardware resources */
  301. void
  302. si_pmu_ds1_res_init(si_t *sih, osl_t *osh)
  303. {
  304. pmuregs_t *pmu;
  305. uint origidx;
  306. const pmu_res_updown_t *pmu_res_updown_table = NULL;
  307. uint pmu_res_updown_table_sz = 0;
  308. /* Remember original core before switch to chipc/pmu */
  309. origidx = si_coreidx(sih);
  310. if (AOB_ENAB(sih)) {
  311. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  312. } else {
  313. pmu = si_setcoreidx(sih, SI_CC_IDX);
  314. }
  315. ASSERT(pmu != NULL);
  316. switch (CHIPID(sih->chip)) {
  317. case BCM43012_CHIP_ID:
  318. pmu_res_updown_table = bcm43012a0_res_updown_ds1;
  319. pmu_res_updown_table_sz = ARRAYSIZE(bcm43012a0_res_updown_ds1);
  320. break;
  321. default:
  322. break;
  323. }
  324. /* Program up/down timers */
  325. while (pmu_res_updown_table_sz--) {
  326. ASSERT(pmu_res_updown_table != NULL);
  327. PMU_MSG(("DS1: Changing rsrc %d res_updn_timer to 0x%x\n",
  328. pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
  329. pmu_res_updown_table[pmu_res_updown_table_sz].updown));
  330. W_REG(osh, &pmu->res_table_sel,
  331. pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
  332. W_REG(osh, &pmu->res_updn_timer,
  333. pmu_res_updown_table[pmu_res_updown_table_sz].updown);
  334. }
  335. /* Return to original core */
  336. si_setcoreidx(sih, origidx);
  337. }
  338. #endif /* defined(BCMULP) */
  339. uint32
  340. si_pmu_wake_bit_offset(si_t *sih)
  341. {
  342. uint32 wakebit;
  343. switch (CHIPID(sih->chip)) {
  344. case BCM4347_CHIP_GRPID:
  345. wakebit = CC2_4347_GCI2WAKE_MASK;
  346. break;
  347. default:
  348. wakebit = 0;
  349. ASSERT(0);
  350. break;
  351. }
  352. return wakebit;
  353. }
  354. void si_pmu_set_min_res_mask(si_t *sih, osl_t *osh, uint min_res_mask)
  355. {
  356. pmuregs_t *pmu;
  357. uint origidx;
  358. /* Remember original core before switch to chipc/pmu */
  359. origidx = si_coreidx(sih);
  360. if (AOB_ENAB(sih)) {
  361. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  362. }
  363. else {
  364. pmu = si_setcoreidx(sih, SI_CC_IDX);
  365. }
  366. ASSERT(pmu != NULL);
  367. W_REG(osh, &pmu->min_res_mask, min_res_mask);
  368. OSL_DELAY(100);
  369. /* Return to original core */
  370. si_setcoreidx(sih, origidx);
  371. }
  372. bool
  373. si_pmu_cap_fast_lpo(si_t *sih)
  374. {
  375. return (PMU_REG(sih, core_cap_ext, 0, 0) & PCAP_EXT_USE_MUXED_ILP_CLK_MASK) ? TRUE : FALSE;
  376. }
  377. int
  378. si_pmu_fast_lpo_disable(si_t *sih)
  379. {
  380. if (!si_pmu_cap_fast_lpo(sih)) {
  381. PMU_ERROR(("%s: No Fast LPO capability\n", __FUNCTION__));
  382. return BCME_ERROR;
  383. }
  384. PMU_REG(sih, pmucontrol_ext,
  385. PCTL_EXT_FASTLPO_ENAB |
  386. PCTL_EXT_FASTLPO_SWENAB |
  387. PCTL_EXT_FASTLPO_PCIE_SWENAB,
  388. 0);
  389. OSL_DELAY(1000);
  390. return BCME_OK;
  391. }
  392. #ifdef BCMPMU_STATS
  393. /*
  394. * 8 pmu statistics timer default map
  395. *
  396. * for CORE_RDY_AUX measure, set as below for timer 6 and 7 instead of CORE_RDY_MAIN.
  397. * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX)
  398. * { SRC_CORE_RDY_AUX, FALSE, TRUE, LEVEL_HIGH},
  399. * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX)
  400. * { SRC_CORE_RDY_AUX, FALSE, TRUE, EDGE_RISE}
  401. */
  402. static pmu_stats_timer_t pmustatstimer[] = {
  403. { SRC_LINK_IN_L12, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l12
  404. { SRC_LINK_IN_L23, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l23
  405. { SRC_PM_ST_IN_D0, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d0
  406. { SRC_PM_ST_IN_D3, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d3
  407. //deep-sleep duration : pmu_rsrc_state(XTAL_PU)
  408. { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_LEVEL_LOW},
  409. //deep-sleep entry count : pmu_rsrc_state(XTAL_PU)
  410. { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_EDGE_FALL},
  411. //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN)
  412. { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_LEVEL_HIGH},
  413. //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN)
  414. { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_EDGE_RISE}
  415. };
  416. static void
  417. si_pmustatstimer_update(osl_t *osh, pmuregs_t *pmu, uint8 timerid)
  418. {
  419. uint32 stats_timer_ctrl;
  420. W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
  421. stats_timer_ctrl =
  422. ((pmustatstimer[timerid].src_num << PMU_ST_SRC_SHIFT) &
  423. PMU_ST_SRC_MASK) |
  424. ((pmustatstimer[timerid].cnt_mode << PMU_ST_CNT_MODE_SHIFT) &
  425. PMU_ST_CNT_MODE_MASK) |
  426. ((pmustatstimer[timerid].enable << PMU_ST_EN_SHIFT) & PMU_ST_EN_MASK) |
  427. ((pmustatstimer[timerid].int_enable << PMU_ST_INT_EN_SHIFT) & PMU_ST_INT_EN_MASK);
  428. W_REG(osh, &pmu->pmu_statstimer_ctrl, stats_timer_ctrl);
  429. W_REG(osh, &pmu->pmu_statstimer_N, 0);
  430. }
  431. void
  432. si_pmustatstimer_int_enable(si_t *sih)
  433. {
  434. pmuregs_t *pmu;
  435. uint origidx;
  436. osl_t *osh = si_osh(sih);
  437. /* Remember original core before switch to chipc/pmu */
  438. origidx = si_coreidx(sih);
  439. if (AOB_ENAB(sih)) {
  440. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  441. } else {
  442. pmu = si_setcoreidx(sih, SI_CC_IDX);
  443. }
  444. ASSERT(pmu != NULL);
  445. OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK);
  446. /* Return to original core */
  447. si_setcoreidx(sih, origidx);
  448. }
  449. void
  450. si_pmustatstimer_int_disable(si_t *sih)
  451. {
  452. pmuregs_t *pmu;
  453. uint origidx;
  454. osl_t *osh = si_osh(sih);
  455. /* Remember original core before switch to chipc/pmu */
  456. origidx = si_coreidx(sih);
  457. if (AOB_ENAB(sih)) {
  458. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  459. } else {
  460. pmu = si_setcoreidx(sih, SI_CC_IDX);
  461. }
  462. ASSERT(pmu != NULL);
  463. AND_REG(osh, &pmu->pmuintmask0, ~PMU_INT_STAT_TIMER_INT_MASK);
  464. /* Return to original core */
  465. si_setcoreidx(sih, origidx);
  466. }
  467. void
  468. si_pmustatstimer_init(si_t *sih)
  469. {
  470. pmuregs_t *pmu;
  471. uint origidx;
  472. osl_t *osh = si_osh(sih);
  473. uint32 core_cap_ext;
  474. uint8 max_stats_timer_num;
  475. int8 i;
  476. /* Remember original core before switch to chipc/pmu */
  477. origidx = si_coreidx(sih);
  478. if (AOB_ENAB(sih)) {
  479. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  480. } else {
  481. pmu = si_setcoreidx(sih, SI_CC_IDX);
  482. }
  483. ASSERT(pmu != NULL);
  484. core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
  485. max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1;
  486. for (i = 0; i < max_stats_timer_num; i++) {
  487. si_pmustatstimer_update(osh, pmu, i);
  488. }
  489. OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK);
  490. /* Return to original core */
  491. si_setcoreidx(sih, origidx);
  492. }
  493. void
  494. si_pmustatstimer_dump(si_t *sih)
  495. {
  496. pmuregs_t *pmu;
  497. uint origidx;
  498. osl_t *osh = si_osh(sih);
  499. uint32 core_cap_ext, pmucapabilities, AlpPeriod, ILPPeriod, pmuintmask0, pmuintstatus;
  500. uint8 max_stats_timer_num, max_stats_timer_src_num;
  501. uint32 stat_timer_ctrl, stat_timer_N;
  502. uint8 i;
  503. uint32 current_time_ms = OSL_SYSUPTIME();
  504. /* Remember original core before switch to chipc/pmu */
  505. origidx = si_coreidx(sih);
  506. if (AOB_ENAB(sih)) {
  507. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  508. } else {
  509. pmu = si_setcoreidx(sih, SI_CC_IDX);
  510. }
  511. ASSERT(pmu != NULL);
  512. pmucapabilities = R_REG(osh, &pmu->pmucapabilities);
  513. core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
  514. AlpPeriod = R_REG(osh, &pmu->slowclkperiod);
  515. ILPPeriod = R_REG(osh, &pmu->ILPPeriod);
  516. max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >>
  517. PCAP_EXT_ST_NUM_SHIFT) + 1;
  518. max_stats_timer_src_num = ((core_cap_ext & PCAP_EXT_ST_SRC_NUM_MASK) >>
  519. PCAP_EXT_ST_SRC_NUM_SHIFT) + 1;
  520. pmuintstatus = R_REG(osh, &pmu->pmuintstatus);
  521. pmuintmask0 = R_REG(osh, &pmu->pmuintmask0);
  522. PMU_ERROR(("%s : TIME %d\n", __FUNCTION__, current_time_ms));
  523. PMU_ERROR(("\tMAX Timer Num %d, MAX Source Num %d\n",
  524. max_stats_timer_num, max_stats_timer_src_num));
  525. PMU_ERROR(("\tpmucapabilities 0x%8x, core_cap_ext 0x%8x, AlpPeriod 0x%8x, ILPPeriod 0x%8x, "
  526. "pmuintmask0 0x%8x, pmuintstatus 0x%8x, pmurev %d\n",
  527. pmucapabilities, core_cap_ext, AlpPeriod, ILPPeriod,
  528. pmuintmask0, pmuintstatus, PMUREV(sih->pmurev)));
  529. for (i = 0; i < max_stats_timer_num; i++) {
  530. W_REG(osh, &pmu->pmu_statstimer_addr, i);
  531. stat_timer_ctrl = R_REG(osh, &pmu->pmu_statstimer_ctrl);
  532. stat_timer_N = R_REG(osh, &pmu->pmu_statstimer_N);
  533. PMU_ERROR(("\t Timer %d : control 0x%8x, %d\n",
  534. i, stat_timer_ctrl, stat_timer_N));
  535. }
  536. /* Return to original core */
  537. si_setcoreidx(sih, origidx);
  538. }
  539. void
  540. si_pmustatstimer_start(si_t *sih, uint8 timerid)
  541. {
  542. pmuregs_t *pmu;
  543. uint origidx;
  544. osl_t *osh = si_osh(sih);
  545. /* Remember original core before switch to chipc/pmu */
  546. origidx = si_coreidx(sih);
  547. if (AOB_ENAB(sih)) {
  548. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  549. } else {
  550. pmu = si_setcoreidx(sih, SI_CC_IDX);
  551. }
  552. ASSERT(pmu != NULL);
  553. pmustatstimer[timerid].enable = TRUE;
  554. W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
  555. OR_REG(osh, &pmu->pmu_statstimer_ctrl, PMU_ST_ENAB << PMU_ST_EN_SHIFT);
  556. /* Return to original core */
  557. si_setcoreidx(sih, origidx);
  558. }
  559. void
  560. si_pmustatstimer_stop(si_t *sih, uint8 timerid)
  561. {
  562. pmuregs_t *pmu;
  563. uint origidx;
  564. osl_t *osh = si_osh(sih);
  565. /* Remember original core before switch to chipc/pmu */
  566. origidx = si_coreidx(sih);
  567. if (AOB_ENAB(sih)) {
  568. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  569. } else {
  570. pmu = si_setcoreidx(sih, SI_CC_IDX);
  571. }
  572. ASSERT(pmu != NULL);
  573. pmustatstimer[timerid].enable = FALSE;
  574. W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
  575. AND_REG(osh, &pmu->pmu_statstimer_ctrl, ~(PMU_ST_ENAB << PMU_ST_EN_SHIFT));
  576. /* Return to original core */
  577. si_setcoreidx(sih, origidx);
  578. }
  579. void
  580. si_pmustatstimer_clear(si_t *sih, uint8 timerid)
  581. {
  582. pmuregs_t *pmu;
  583. uint origidx;
  584. osl_t *osh = si_osh(sih);
  585. /* Remember original core before switch to chipc/pmu */
  586. origidx = si_coreidx(sih);
  587. if (AOB_ENAB(sih)) {
  588. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  589. } else {
  590. pmu = si_setcoreidx(sih, SI_CC_IDX);
  591. }
  592. ASSERT(pmu != NULL);
  593. W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
  594. W_REG(osh, &pmu->pmu_statstimer_N, 0);
  595. /* Return to original core */
  596. si_setcoreidx(sih, origidx);
  597. }
  598. void
  599. si_pmustatstimer_clear_overflow(si_t *sih)
  600. {
  601. uint8 i;
  602. uint32 core_cap_ext;
  603. uint8 max_stats_timer_num;
  604. uint32 timerN;
  605. pmuregs_t *pmu;
  606. uint origidx;
  607. osl_t *osh = si_osh(sih);
  608. /* Remember original core before switch to chipc/pmu */
  609. origidx = si_coreidx(sih);
  610. if (AOB_ENAB(sih)) {
  611. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  612. } else {
  613. pmu = si_setcoreidx(sih, SI_CC_IDX);
  614. }
  615. ASSERT(pmu != NULL);
  616. core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
  617. max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1;
  618. for (i = 0; i < max_stats_timer_num; i++) {
  619. W_REG(osh, &pmu->pmu_statstimer_addr, i);
  620. timerN = R_REG(osh, &pmu->pmu_statstimer_N);
  621. if (timerN == 0xFFFFFFFF) {
  622. PMU_ERROR(("pmustatstimer overflow clear - timerid : %d\n", i));
  623. si_pmustatstimer_clear(sih, i);
  624. }
  625. }
  626. /* Return to original core */
  627. si_setcoreidx(sih, origidx);
  628. }
  629. uint32
  630. si_pmustatstimer_read(si_t *sih, uint8 timerid)
  631. {
  632. pmuregs_t *pmu;
  633. uint origidx;
  634. osl_t *osh = si_osh(sih);
  635. uint32 stats_timer_N;
  636. /* Remember original core before switch to chipc/pmu */
  637. origidx = si_coreidx(sih);
  638. if (AOB_ENAB(sih)) {
  639. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  640. } else {
  641. pmu = si_setcoreidx(sih, SI_CC_IDX);
  642. }
  643. ASSERT(pmu != NULL);
  644. W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
  645. stats_timer_N = R_REG(osh, &pmu->pmu_statstimer_N);
  646. /* Return to original core */
  647. si_setcoreidx(sih, origidx);
  648. return stats_timer_N;
  649. }
  650. void
  651. si_pmustatstimer_cfg_src_num(si_t *sih, uint8 src_num, uint8 timerid)
  652. {
  653. pmuregs_t *pmu;
  654. uint origidx;
  655. osl_t *osh = si_osh(sih);
  656. /* Remember original core before switch to chipc/pmu */
  657. origidx = si_coreidx(sih);
  658. if (AOB_ENAB(sih)) {
  659. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  660. } else {
  661. pmu = si_setcoreidx(sih, SI_CC_IDX);
  662. }
  663. ASSERT(pmu != NULL);
  664. pmustatstimer[timerid].src_num = src_num;
  665. si_pmustatstimer_update(osh, pmu, timerid);
  666. /* Return to original core */
  667. si_setcoreidx(sih, origidx);
  668. }
  669. void
  670. si_pmustatstimer_cfg_cnt_mode(si_t *sih, uint8 cnt_mode, uint8 timerid)
  671. {
  672. pmuregs_t *pmu;
  673. uint origidx;
  674. osl_t *osh = si_osh(sih);
  675. /* Remember original core before switch to chipc/pmu */
  676. origidx = si_coreidx(sih);
  677. if (AOB_ENAB(sih)) {
  678. pmu = si_setcore(sih, PMU_CORE_ID, 0);
  679. } else {
  680. pmu = si_setcoreidx(sih, SI_CC_IDX);
  681. }
  682. ASSERT(pmu != NULL);
  683. pmustatstimer[timerid].cnt_mode = cnt_mode;
  684. si_pmustatstimer_update(osh, pmu, timerid);
  685. /* Return to original core */
  686. si_setcoreidx(sih, origidx);
  687. }
  688. #endif /* BCMPMU_STATS */