1 /* 2 * HND SiliconBackplane PMU support. 3 * 4 * Copyright (C) 2020, Broadcom. 5 * 6 * Unless you and Broadcom execute a separate written software license 7 * agreement governing use of this software, this software is licensed to you 8 * under the terms of the GNU General Public License version 2 (the "GPL"), 9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10 * following added to such license: 11 * 12 * As a special exception, the copyright holders of this software give you 13 * permission to link this software with independent modules, and to copy and 14 * distribute the resulting executable under terms of your choice, provided that 15 * you also meet, for each linked independent module, the terms and conditions of 16 * the license of that module. An independent module is a module which is not 17 * derived from this software. The special exception does not apply to any 18 * modifications of the software. 19 * 20 * 21 * <<Broadcom-WL-IPTag/Dual:>> 22 */ 23 24 #ifndef _hndpmu_h_ 25 #define _hndpmu_h_ 26 27 #include <typedefs.h> 28 #include <osl_decl.h> 29 #include <siutils.h> 30 #include <sbchipc.h> 31 #if defined(BTOVERPCIE) || defined(BT_WLAN_REG_ON_WAR) 32 #include <hnd_gcisem.h> 33 #endif /* BTOVERPCIE || BT_WLAN_REG_ON_WAR */ 34 35 #if !defined(BCMDONGLEHOST) 36 37 #define SET_LDO_VOLTAGE_LDO1 1 38 #define SET_LDO_VOLTAGE_LDO2 2 39 #define SET_LDO_VOLTAGE_LDO3 3 40 #define SET_LDO_VOLTAGE_PAREF 4 41 #define SET_LDO_VOLTAGE_CLDO_PWM 5 42 #define SET_LDO_VOLTAGE_CLDO_BURST 6 43 #define SET_LDO_VOLTAGE_CBUCK_PWM 7 44 #define SET_LDO_VOLTAGE_CBUCK_BURST 8 45 #define SET_LDO_VOLTAGE_LNLDO1 9 46 #define SET_LDO_VOLTAGE_LNLDO2_SEL 10 47 #define SET_LNLDO_PWERUP_LATCH_CTRL 11 48 #define SET_LDO_VOLTAGE_LDO3P3 12 49 50 #define BBPLL_NDIV_FRAC_BITS 24 51 #define P1_DIV_SCALE_BITS 12 52 53 #define PMUREQTIMER (1 << 0) 54 55 #define XTAL_FREQ_40MHZ 40000 56 #define XTAL_FREQ_54MHZ 54000 57 58 /* selects core based on AOB_ENAB() */ 59 #define PMUREGADDR(sih, pmur, ccr, member) \ 60 (AOB_ENAB(sih) ? (&(pmur)->member) : (&(ccr)->member)) 61 62 /* prevents backplane stall caused by subsequent writes to 'ilp domain' PMU registers */ 63 #define HND_PMU_SYNC_WR(sih, pmur, ccr, osh, r, v) do { \ 64 if ((sih) && (sih)->pmurev >= 22) { \ 65 while (R_REG(osh, PMUREGADDR(sih, pmur, ccr, pmustatus)) & \ 66 PST_SLOW_WR_PENDING) { \ 67 ; /* empty */ \ 68 } \ 69 } \ 70 W_REG(osh, r, v); \ 71 (void)R_REG(osh, r); \ 72 } while (0) 73 74 /* PMU Stat Timer */ 75 76 /* for count mode */ 77 enum { 78 PMU_STATS_LEVEL_HIGH = 0, 79 PMU_STATS_LEVEL_LOW, 80 PMU_STATS_EDGE_RISE, 81 PMU_STATS_EDGE_FALL 82 }; 83 84 typedef struct { 85 uint8 src_num; /* predefined source hw signal num to map timer */ 86 bool enable; /* timer enable/disable */ 87 bool int_enable; /* overflow interrupts enable/disable */ 88 uint8 cnt_mode; 89 } pmu_stats_timer_t; 90 91 /* internal hw signal source number for Timer */ 92 #define SRC_PMU_RESRC_OFFSET 0x40 93 94 #define SRC_LINK_IN_L12 0 95 #define SRC_LINK_IN_L23 1 96 #define SRC_PM_ST_IN_D0 2 97 #define SRC_PM_ST_IN_D3 3 98 99 #define SRC_XTAL_PU (SRC_PMU_RESRC_OFFSET + RES4347_XTAL_PU) 100 #define SRC_CORE_RDY_MAIN (SRC_PMU_RESRC_OFFSET + RES4347_CORE_RDY_MAIN) 101 #define SRC_CORE_RDY_AUX (SRC_PMU_RESRC_OFFSET + RES4347_CORE_RDY_AUX) 102 103 #ifdef BCMPMU_STATS 104 extern bool _pmustatsenab; 105 #if defined(ROM_ENAB_RUNTIME_CHECK) 106 #define PMU_STATS_ENAB() (_pmustatsenab) 107 #elif defined(BCMPMU_STATS_DISABLED) 108 #define PMU_STATS_ENAB() (0) 109 #else 110 #define PMU_STATS_ENAB() (1) 111 #endif 112 #else 113 #define PMU_STATS_ENAB() (0) 114 #endif /* BCMPMU_STATS */ 115 116 #define RES4369_HTAVAIL_VAL 0x00a80022 117 118 #if defined(BTOVERPCIE) && defined(BT_WLAN_REG_ON_WAR) 119 #error "'BT over PCIe' and 'WLAN/BT REG_ON WAR' are mutually exclusive as " 120 "both share the same GCI semaphore - THREAD_0_GCI_SEM_3_ID" 121 #endif /* BTOVERPCIE && BT_WLAN_REG_ON_WAR */ 122 123 #if defined(BTOVERPCIE) 124 #define GCI_PLL_LOCK_SEM THREAD_0_GCI_SEM_3_ID 125 /* changed from msec to usec */ 126 #define GCI_PLL_LOCK_SEM_TIMEOUT (GCI_SEM_TIMEOUT_AFTER_RESERVE * 1000) 127 #endif /* BTOVERPCIE */ 128 129 #if defined(BT_WLAN_REG_ON_WAR) 130 #define GCI_BT_WLAN_REG_ON_WAR_SEM THREAD_0_GCI_SEM_3_ID 131 #define GCI_BT_WLAN_REG_ON_WAR_SEM_TIMEOUT (GCI_SEM_TIMEOUT_AFTER_RESERVE * 1000) 132 #endif /* BT_WLAN_REG_ON_WAR */ 133 134 #define GCI_INDIRECT_ACCESS_SEM THREAD_0_GCI_SEM_2_ID 135 #define GCI_INDIRECT_ACCESS_SEM_TIMEOUT (GCI_SEM_TIMEOUT_AFTER_RESERVE * 1000) 136 137 #define GCI_TREFUP_DS_SEM THREAD_0_GCI_SEM_5_ID 138 #define GCI_TREFUP_DS_SEM_TIMEOUT (GCI_SEM_TIMEOUT_AFTER_RESERVE * 1000) 139 140 #define GCI_BT_BOOTSTAGE_MEMOFFSET (0x570u) 141 #define GCI_BT_BOOTSTAGE_FW_WAIT 0u /* BT ROM code waiting on FW boot */ 142 #define GCI_BT_BOOTSTAGE_FW_BOOT 2u /* upon FW boot/start */ 143 #define GCI_BT_BOOTSTAGE_FW_TRAP 3u /* upon a trap */ 144 #define GCI_BT_BOOTSTAGE_FW_INVALID 0xFFu 145 146 #define GCI_TREFUP_DS_MEMOFFSET (0x57Cu) 147 #define GCI_TREFUP_DS_WLAN (1u << 0u) 148 #define GCI_TREFUP_DS_BT (1u << 1u) 149 #define GCI_SHARED_SFLASH_RSVD (1u << 2u) 150 151 #define GCI_SHARED_SFLASH_SEM THREAD_0_GCI_SEM_6_ID 152 #define GCI_SHARED_SFLASH_SEM_TIMEOUT GCI_SEM_TIMEOUT_AFTER_RESERVE * 1000 153 #define GCI_SHARED_SFLASH_SEM_ERASE_RSVD_TIMEOUT 50 + 30 /* 50 us + headroom */ 154 155 #define SLEW_RATE_VALUE_REG_4369 (PMU_VREG_6) 156 #define SLEW_RATE_SHIFT_4369(x) (9u + (x * 8u)) 157 #define SLEW_RATE_SIZE_4369 (3u) 158 #define SLEW_RATE_MASK_4369 ((1u << SLEW_RATE_SIZE_4369) - 1u) 159 #define SOFT_START_EN_REG_4369 (PMU_VREG_5) 160 #define SOFT_START_EN_SHIFT_4369(x) (4u + x) 161 #define SOFT_START_EN_SIZE_4369 (1u) 162 #define SOFT_START_EN_MASK_4369 ((1u << SOFT_START_EN_SIZE_4369) - 1u) 163 #define SOFT_START_EN_VALUE_4369 (1u) 164 165 #define SLEW_RATE_VALUE_REG_4378 (PMU_VREG_6) 166 #define SLEW_RATE_SHIFT_4378(x) (9u + (x * 8u)) 167 #define SLEW_RATE_SIZE_4378 (3u) 168 #define SLEW_RATE_MASK_4378 ((1u << SLEW_RATE_SIZE_4378) - 1u) 169 #define SOFT_START_EN_REG_4378 (PMU_VREG_5) 170 #define SOFT_START_EN_SHIFT_4378(x) (4u + x) 171 #define SOFT_START_EN_SIZE_4378 (1u) 172 #define SOFT_START_EN_MASK_4378 ((1u << SOFT_START_EN_SIZE_4378) - 1u) 173 #define SOFT_START_EN_VALUE_4378 (1u) 174 #define SOFT_START_EN_VALUE_4378_REV37 (0u) 175 176 #define SLEW_RATE_VALUE_REG_4387 (PMU_VREG_6) 177 #define SLEW_RATE_SHIFT_4387(x) (18u) 178 #define SLEW_RATE_SIZE_4387 (2u) 179 #define SLEW_RATE_MASK_4387 ((1u << SLEW_RATE_SIZE_4387) - 1u) 180 #define SOFT_START_EN_REG_4387 (PMU_VREG_6) 181 #define SOFT_START_EN_SHIFT_4387(x) (17u) 182 #define SOFT_START_EN_SIZE_4387 (1u) 183 #define SOFT_START_EN_MASK_4387 ((1u << SOFT_START_EN_SIZE_4387) - 1u) 184 #define SOFT_START_EN_VALUE_4387 (0u) 185 186 extern void si_pmu_init(si_t *sih, osl_t *osh); 187 extern void si_pmu_chip_init(si_t *sih, osl_t *osh); 188 extern void si_pmu_pll_init(si_t *sih, osl_t *osh, uint32 xtalfreq); 189 extern void si_pmu_res_init(si_t *sih, osl_t *osh); 190 extern void si_pmu_swreg_init(si_t *sih, osl_t *osh); 191 extern void si_pmu_res_minmax_update(si_t *sih, osl_t *osh); 192 extern void si_pmu_clear_intmask(si_t *sih); 193 194 extern uint32 si_pmu_si_clock(si_t *sih, osl_t *osh); /* returns [Hz] units */ 195 extern uint32 si_pmu_cpu_clock(si_t *sih, osl_t *osh); /* returns [hz] units */ 196 extern uint32 si_pmu_mem_clock(si_t *sih, osl_t *osh); /* returns [Hz] units */ 197 extern uint32 si_pmu_alp_clock(si_t *sih, osl_t *osh); /* returns [Hz] units */ 198 extern void si_pmu_ilp_clock_set(uint32 cycles); 199 extern uint32 si_pmu_ilp_clock(si_t *sih, osl_t *osh); /* returns [Hz] units */ 200 201 extern void si_pmu_set_ldo_voltage(si_t *sih, osl_t *osh, uint8 ldo, uint8 voltage); 202 extern uint16 si_pmu_fast_pwrup_delay(si_t *sih, osl_t *osh); 203 extern uint si_pmu_fast_pwrup_delay_dig(si_t *sih, osl_t *osh); 204 extern void si_pmu_pllupd(si_t *sih); 205 extern void si_pmu_spuravoid(si_t *sih, osl_t *osh, uint8 spuravoid); 206 extern void si_pmu_pll_off_PARR(si_t *sih, osl_t *osh, uint32 *min_res_mask, 207 uint32 *max_res_mask, uint32 *clk_ctl_st); 208 extern uint32 si_pmu_pll28nm_fvco(si_t *sih); 209 /* below function are only for BBPLL parallel purpose */ 210 extern void si_pmu_gband_spurwar(si_t *sih, osl_t *osh); 211 212 extern bool si_pmu_is_otp_powered(si_t *sih, osl_t *osh); 213 extern uint32 si_pmu_measure_alpclk(si_t *sih, osl_t *osh); 214 215 extern uint32 si_pmu_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val); 216 #if defined(SAVERESTORE) 217 extern void si_set_abuck_mode_4362(si_t *sih, uint8 mode); 218 #endif /* SAVERESTORE */ 219 220 #define si_pmu_regcontrol si_pmu_vreg_control /* prevents build err because of usage in PHY */ 221 extern uint32 si_pmu_vreg_control(si_t *sih, uint reg, uint32 mask, uint32 val); 222 extern uint32 si_pmu_pllcontrol(si_t *sih, uint reg, uint32 mask, uint32 val); 223 extern void si_pmu_pllupd(si_t *sih); 224 225 extern uint32 si_pmu_waitforclk_on_backplane(si_t *sih, osl_t *osh, uint32 clk, uint32 delay); 226 extern uint32 si_pmu_get_bb_vcofreq(si_t *sih, osl_t *osh, int xtalfreq); 227 typedef void (*si_pmu_callback_t)(void* arg); 228 229 extern uint32 si_mac_clk(si_t *sih, osl_t *osh); 230 extern void si_pmu_switch_on_PARLDO(si_t *sih, osl_t *osh); 231 extern void si_pmu_switch_off_PARLDO(si_t *sih, osl_t *osh); 232 233 /* TODO: need a better fn name or better abstraction than the raw fvco 234 * and MAC clock channel divisor... 235 */ 236 extern int si_pmu_fvco_macdiv(si_t *sih, uint32 *fvco, uint32 *div); 237 238 extern bool si_pmu_reset_ret_sleep_log(si_t *sih, osl_t *osh); 239 extern bool si_pmu_reset_chip_sleep_log(si_t *sih, osl_t *osh); 240 extern int si_pmu_openloop_cal(si_t *sih, uint16 currtemp); 241 242 #ifdef LDO3P3_MIN_RES_MASK 243 extern int si_pmu_min_res_ldo3p3_set(si_t *sih, osl_t *osh, bool on); 244 extern int si_pmu_min_res_ldo3p3_get(si_t *sih, osl_t *osh, int *res); 245 #endif /* LDO3P3_MIN_RES_MASK */ 246 247 void si_pmu_bt_ldo_pu(si_t *sih, bool up); 248 249 int si_pmu_ldo3p3_soft_start_wl_get(si_t *sih, osl_t *osh, int *res); 250 int si_pmu_ldo3p3_soft_start_wl_set(si_t *sih, osl_t *osh, uint32 slew_rate); 251 int si_pmu_ldo3p3_soft_start_bt_get(si_t *sih, osl_t *osh, int *res); 252 int si_pmu_ldo3p3_soft_start_bt_set(si_t *sih, osl_t *osh, uint32 slew_rate); 253 extern int si_pmu_min_res_otp_pu_set(si_t *sih, osl_t *osh, bool on); 254 #endif /* !defined(BCMDONGLEHOST) */ 255 256 #if defined(EDV) 257 extern uint32 si_pmu_get_backplaneclkspeed(si_t *sih); 258 extern void si_pmu_update_backplane_clock(si_t *sih, osl_t *osh, uint reg, uint32 mask, uint32 val); 259 #endif 260 261 extern uint32 si_pmu_rsrc_macphy_clk_deps(si_t *sih, osl_t *osh, int maccore_index); 262 extern uint32 si_pmu_rsrc_ht_avail_clk_deps(si_t *sih, osl_t *osh); 263 extern uint32 si_pmu_rsrc_cb_ready_deps(si_t *sih, osl_t *osh); 264 265 extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on, uint32* min_res_mask); 266 extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength); 267 268 extern void si_pmu_slow_clk_reinit(si_t *sih, osl_t *osh); 269 extern void si_pmu_avbtimer_enable(si_t *sih, osl_t *osh, bool set_flag); 270 extern uint32 si_pmu_dump_pmucap_binary(si_t *sih, uchar *p); 271 extern uint32 si_pmu_dump_buf_size_pmucap(si_t *sih); 272 extern int si_pmu_wait_for_steady_state(si_t *sih, osl_t *osh, pmuregs_t *pmu); 273 #ifdef ATE_BUILD 274 extern void hnd_pmu_clr_int_sts_req_active(osl_t *hnd_osh, si_t *hnd_sih); 275 #endif 276 extern uint32 si_pmu_wake_bit_offset(si_t *sih); 277 extern uint32 si_pmu_get_pmutimer(si_t *sih); 278 extern void si_pmu_set_min_res_mask(si_t *sih, osl_t *osh, uint min_res_mask); 279 extern void si_pmu_set_mac_rsrc_req(si_t *sih, int macunit); 280 extern void si_pmu_set_mac_rsrc_req_sc(si_t *sih, osl_t *osh); 281 extern bool si_pmu_fast_lpo_enable_pcie(si_t *sih); 282 extern bool si_pmu_fast_lpo_enable_pmu(si_t *sih); 283 extern uint32 si_cur_pmu_time(si_t *sih); 284 extern bool si_pmu_cap_fast_lpo(si_t *sih); 285 extern int si_pmu_fast_lpo_disable(si_t *sih); 286 extern void si_pmu_dmn1_perst_wakeup(si_t *sih, bool set); 287 #ifdef BCMPMU_STATS 288 extern void si_pmustatstimer_init(si_t *sih); 289 extern void si_pmustatstimer_dump(si_t *sih); 290 extern void si_pmustatstimer_start(si_t *sih, uint8 timerid); 291 extern void si_pmustatstimer_stop(si_t *sih, uint8 timerid); 292 extern void si_pmustatstimer_clear(si_t *sih, uint8 timerid); 293 extern void si_pmustatstimer_clear_overflow(si_t *sih); 294 extern uint32 si_pmustatstimer_read(si_t *sih, uint8 timerid); 295 extern void si_pmustatstimer_cfg_src_num(si_t *sih, uint8 src_num, uint8 timerid); 296 extern void si_pmustatstimer_cfg_cnt_mode(si_t *sih, uint8 cnt_mode, uint8 timerid); 297 extern void si_pmustatstimer_int_enable(si_t *sih); 298 extern void si_pmustatstimer_int_disable(si_t *sih); 299 #endif /* BCMPMU_STATS */ 300 extern int si_pmu_min_res_set(si_t *sih, osl_t *osh, uint min_mask, bool set); 301 extern void si_pmu_disable_intr_pwrreq(si_t *sih); 302 303 #ifdef DONGLEBUILD 304 /* Get PMU registers in rodata */ 305 extern int si_pmu_regs_in_rodata_dump(void *sih, void *arg2, uint32 *bufptr, uint16 *len); 306 #endif 307 308 extern void si_pmu_fis_setup(si_t *sih); 309 310 extern uint si_pmu_get_mac_rsrc_req_tmr_cnt(si_t *sih); 311 extern uint si_pmu_get_pmu_interrupt_rcv_cnt(si_t *sih); 312 313 extern bool _bcm_pwr_opt_dis; 314 #define BCM_PWR_OPT_ENAB() (FALSE) 315 316 extern int si_pmu_mem_pwr_off(si_t *sih, int core_idx); 317 extern int si_pmu_mem_pwr_on(si_t *sih); 318 extern int si_pmu_lvm_csr_update(si_t *sih, bool lvm); 319 320 #if defined(BT_WLAN_REG_ON_WAR) 321 #define REG_ON_WAR_PMU_EXT_WAKE_REQ_MASK0_VAL 0x060000CDu 322 323 extern void si_pmu_reg_on_war_ext_wake_perst_set(si_t *sih); 324 extern void si_pmu_reg_on_war_ext_wake_perst_clear(si_t *sih); 325 #endif /* BT_WLAN_REG_ON_WAR */ 326 327 #if defined (BCMSRTOPOFF) 328 extern bool _srtopoff_enab; 329 #if defined(ROM_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD) 330 #define BCMSRTOPOFF_ENAB() (_srtopoff_enab) 331 #elif defined(BCMSRTOPOFF_DISABLED) 332 #define BCMSRTOPOFF_ENAB() (0) 333 #else 334 #define BCMSRTOPOFF_ENAB() (_srtopoff_enab) 335 #endif 336 #else 337 #define BCMSRTOPOFF_ENAB() (0) 338 #endif /* BCMSRTOPOFF */ 339 340 #ifdef BCM_PMU_FLL_PU_MANAGE 341 #define PMU_FLL_PU_ENAB() (TRUE) 342 #else 343 #define PMU_FLL_PU_ENAB() (FALSE) 344 #endif 345 346 extern pmuregs_t *hnd_pmur; /* PMU core regs */ 347 extern void si_pmu_res_state_wait(si_t *sih, uint rsrc); 348 #endif /* _hndpmu_h_ */ 349