From 297b60346df8beafee954a0fd7c2d64f33f3b9bc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 11 May 2024 01:44:05 +0000
Subject: [PATCH] rtl8211F_led_control
---
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hndpmu.c | 887 ++++++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 692 insertions(+), 195 deletions(-)
diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hndpmu.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hndpmu.c
index bd1e450..8add713 100644
--- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hndpmu.c
+++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hndpmu.c
@@ -1,16 +1,17 @@
-/* SPDX-License-Identifier: GPL-2.0 */
/*
* Misc utility routines for accessing PMU corerev specific features
* of the SiliconBackplane-based Broadcom chips.
*
- * Copyright (C) 1999-2019, Broadcom Corporation
- *
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
+ *
+ * Copyright (C) 1999-2017, Broadcom Corporation
+ *
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
- *
+ *
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
@@ -18,7 +19,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -26,15 +27,15 @@
*
* <<Broadcom-WL-IPTag/Open:>>
*
- * $Id: hndpmu.c 530092 2015-01-29 04:44:58Z $
+ * $Id: hndpmu.c 700652 2017-05-20 02:44:31Z $
*/
-
-/*
+/**
+ * @file
* Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs.
* However, in the context of this file the baseband ('BB') PLL/FLL is referred to.
*
- * Throughout this code, the prefixes 'pmu0_', 'pmu1_' and 'pmu2_' are used.
+ * Throughout this code, the prefixes 'pmu1_' and 'pmu2_' are used.
* They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012)
* pmu1_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop). It supports
* fractional frequency generation. pmu2_ does not support fractional frequency generation.
@@ -49,7 +50,18 @@
#include <bcmdevs.h>
#include <hndsoc.h>
#include <sbchipc.h>
+#include <hndchipc.h>
#include <hndpmu.h>
+#include <hndlhl.h>
+#if defined(BCMULP)
+#include <ulp.h>
+#endif /* defined(BCMULP) */
+#include <sbgci.h>
+#ifdef EVENT_LOG_COMPILE
+#include <event_log.h>
+#endif // endif
+#include <sbgci.h>
+#include <lpflags.h>
#define PMU_ERROR(args)
@@ -59,6 +71,7 @@
* to be on except on private builds.
*/
#define PMU_NONE(args)
+#define flags_shift 14
/** contains resource bit positions for a specific chip */
struct rsc_per_chip_s {
@@ -66,109 +79,16 @@
uint8 macphy_clkavail;
uint8 ht_start;
uint8 otp_pu;
+ uint8 macphy_aux_clkavail;
};
typedef struct rsc_per_chip_s rsc_per_chip_t;
-
-/* SDIO Pad drive strength to select value mappings.
- * The last strength value in each table must be 0 (the tri-state value).
- */
-typedef struct {
- uint8 strength; /* Pad Drive Strength in mA */
- uint8 sel; /* Chip-specific select value */
-} sdiod_drive_str_t;
-
-/* SDIO Drive Strength to sel value table for PMU Rev 1 */
-static const sdiod_drive_str_t sdiod_drive_strength_tab1[] = {
- {4, 0x2},
- {2, 0x3},
- {1, 0x0},
- {0, 0x0} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
-static const sdiod_drive_str_t sdiod_drive_strength_tab2[] = {
- {12, 0x7},
- {10, 0x6},
- {8, 0x5},
- {6, 0x4},
- {4, 0x2},
- {2, 0x1},
- {0, 0x0} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
-static const sdiod_drive_str_t sdiod_drive_strength_tab3[] = {
- {32, 0x7},
- {26, 0x6},
- {22, 0x5},
- {16, 0x4},
- {12, 0x3},
- {8, 0x2},
- {4, 0x1},
- {0, 0x0} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8v) */
-static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v8[] = {
- {32, 0x6},
- {26, 0x7},
- {22, 0x4},
- {16, 0x5},
- {12, 0x2},
- {8, 0x3},
- {4, 0x0},
- {0, 0x1} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.2v) */
-
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (2.5v) */
-
-/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
-static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = {
- {6, 0x7},
- {5, 0x6},
- {4, 0x5},
- {3, 0x4},
- {2, 0x2},
- {1, 0x1},
- {0, 0x0} };
-
-/* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */
-
-/** SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
-static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = {
- {3, 0x3},
- {2, 0x2},
- {1, 0x1},
- {0, 0x0} };
-
-
-/**
- * SDIO Drive Strength to sel value table for 43143 PMU Rev 17, see Confluence 43143 Toplevel
- * architecture page, section 'PMU Chip Control 1 Register definition', click link to picture
- * BCM43143_sel_sdio_signals.jpg. Valid after PMU Chip Control 0 Register, bit31 (override) has
- * been written '1'.
- */
-#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33
-
-static const sdiod_drive_str_t sdiod_drive_strength_tab7_3v3[] = {
- /* note: for 14, 10, 6 and 2mA hw timing is not met according to rtl team */
- {16, 0x7},
- {12, 0x5},
- {8, 0x3},
- {4, 0x1} }; /* note: 43143 does not support tristate */
-
+#if defined(BCMPMU_STATS) && !defined(BCMPMU_STATS_DISABLED)
+bool _pmustatsenab = TRUE;
#else
-
-static const sdiod_drive_str_t sdiod_drive_strength_tab7_1v8[] = {
- /* note: for 7, 5, 3 and 1mA hw timing is not met according to rtl team */
- {8, 0x7},
- {6, 0x5},
- {4, 0x3},
- {2, 0x1} }; /* note: 43143 does not support tristate */
-
-#endif /* BCM_SDIO_VDDIO */
-
-#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
+bool _pmustatsenab = FALSE;
+#endif /* BCMPMU_STATS */
/**
* Balance between stable SDIO operation and power consumption is achieved using this function.
@@ -182,17 +102,236 @@
void
si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
{
- sdiod_drive_str_t *str_tab = NULL;
- uint32 str_mask = 0; /* only alter desired bits in PMU chipcontrol 1 register */
- uint32 str_shift = 0;
- uint32 str_ovr_pmuctl = PMU_CHIPCTL0; /* PMU chipcontrol register containing override bit */
- uint32 str_ovr_pmuval = 0; /* position of bit within this register */
+ /*
+ * Note:
+ * This function used to set the SDIO drive strength via PMU_CHIPCTL1 for the
+ * 43143, 4330, 4334, 4336, 43362 chips. These chips are now no longer supported, so
+ * the code has been deleted.
+ * Newer chips have the SDIO drive strength setting via a GCI Chip Control register,
+ * but the bit definitions are chip-specific. We are keeping this function available
+ * (accessed via DHD 'sdiod_drive' IOVar) in case these newer chips need to provide access.
+ */
+ UNUSED_PARAMETER(sih);
+ UNUSED_PARAMETER(osh);
+ UNUSED_PARAMETER(drivestrength);
+}
+
+void
+si_switch_pmu_dependency(si_t *sih, uint mode)
+{
+#ifdef DUAL_PMU_SEQUENCE
+ osl_t *osh = si_osh(sih);
+ uint32 current_res_state;
+ uint32 min_mask, max_mask;
+ const pmu_res_depend_t *pmu_res_depend_table = NULL;
+ uint pmu_res_depend_table_sz = 0;
+ uint origidx;
+ pmuregs_t *pmu;
+ chipcregs_t *cc;
+ BCM_REFERENCE(cc);
+
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ cc = si_setcore(sih, CC_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ cc = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ current_res_state = R_REG(osh, &pmu->res_state);
+ min_mask = R_REG(osh, &pmu->min_res_mask);
+ max_mask = R_REG(osh, &pmu->max_res_mask);
+ W_REG(osh, &pmu->min_res_mask, (min_mask | current_res_state));
+ switch (mode) {
+ case PMU_4364_1x1_MODE:
+ {
+ if (CHIPID(sih->chip) == BCM4364_CHIP_ID) {
+ pmu_res_depend_table = bcm4364a0_res_depend_1x1;
+ pmu_res_depend_table_sz =
+ ARRAYSIZE(bcm4364a0_res_depend_1x1);
+ max_mask = PMU_4364_MAX_MASK_1x1;
+ W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE);
+ W_REG(osh, &pmu->res_updn_timer, PMU_4364_SAVE_RESTORE_UPDNTIME_1x1);
+#if defined(SAVERESTORE)
+ if (SR_ENAB()) {
+ /* Disable 3x3 SR engine */
+ W_REG(osh, &cc->sr1_control0,
+ CC_SR0_4364_SR_ENG_CLK_EN |
+ CC_SR0_4364_SR_RSRC_TRIGGER |
+ CC_SR0_4364_SR_WD_MEM_MIN_DIV |
+ CC_SR0_4364_SR_INVERT_CLK |
+ CC_SR0_4364_SR_ENABLE_HT |
+ CC_SR0_4364_SR_ALLOW_PIC |
+ CC_SR0_4364_SR_PMU_MEM_DISABLE);
+ }
+#endif /* SAVERESTORE */
+ }
+ break;
+ }
+ case PMU_4364_3x3_MODE:
+ {
+ if (CHIPID(sih->chip) == BCM4364_CHIP_ID) {
+ W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE);
+ W_REG(osh, &pmu->res_updn_timer,
+ PMU_4364_SAVE_RESTORE_UPDNTIME_3x3);
+ /* Change the dependency table only if required */
+ if ((max_mask != PMU_4364_MAX_MASK_3x3) ||
+ (max_mask != PMU_4364_MAX_MASK_RSDB)) {
+ pmu_res_depend_table = bcm4364a0_res_depend_rsdb;
+ pmu_res_depend_table_sz =
+ ARRAYSIZE(bcm4364a0_res_depend_rsdb);
+ max_mask = PMU_4364_MAX_MASK_3x3;
+ }
+#if defined(SAVERESTORE)
+ if (SR_ENAB()) {
+ /* Enable 3x3 SR engine */
+ W_REG(osh, &cc->sr1_control0,
+ CC_SR0_4364_SR_ENG_CLK_EN |
+ CC_SR0_4364_SR_RSRC_TRIGGER |
+ CC_SR0_4364_SR_WD_MEM_MIN_DIV |
+ CC_SR0_4364_SR_INVERT_CLK |
+ CC_SR0_4364_SR_ENABLE_HT |
+ CC_SR0_4364_SR_ALLOW_PIC |
+ CC_SR0_4364_SR_PMU_MEM_DISABLE |
+ CC_SR0_4364_SR_ENG_EN_MASK);
+ }
+#endif /* SAVERESTORE */
+ }
+ break;
+ }
+ case PMU_4364_RSDB_MODE:
+ default:
+ {
+ if (CHIPID(sih->chip) == BCM4364_CHIP_ID) {
+ W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE);
+ W_REG(osh, &pmu->res_updn_timer,
+ PMU_4364_SAVE_RESTORE_UPDNTIME_3x3);
+ /* Change the dependency table only if required */
+ if ((max_mask != PMU_4364_MAX_MASK_3x3) ||
+ (max_mask != PMU_4364_MAX_MASK_RSDB)) {
+ pmu_res_depend_table =
+ bcm4364a0_res_depend_rsdb;
+ pmu_res_depend_table_sz =
+ ARRAYSIZE(bcm4364a0_res_depend_rsdb);
+ max_mask = PMU_4364_MAX_MASK_RSDB;
+ }
+#if defined(SAVERESTORE)
+ if (SR_ENAB()) {
+ /* Enable 3x3 SR engine */
+ W_REG(osh, &cc->sr1_control0,
+ CC_SR0_4364_SR_ENG_CLK_EN |
+ CC_SR0_4364_SR_RSRC_TRIGGER |
+ CC_SR0_4364_SR_WD_MEM_MIN_DIV |
+ CC_SR0_4364_SR_INVERT_CLK |
+ CC_SR0_4364_SR_ENABLE_HT |
+ CC_SR0_4364_SR_ALLOW_PIC |
+ CC_SR0_4364_SR_PMU_MEM_DISABLE |
+ CC_SR0_4364_SR_ENG_EN_MASK);
+ }
+#endif /* SAVERESTORE */
+ }
+ break;
+ }
+ }
+ si_pmu_resdeptbl_upd(sih, osh, pmu, pmu_res_depend_table, pmu_res_depend_table_sz);
+ W_REG(osh, &pmu->max_res_mask, max_mask);
+ W_REG(osh, &pmu->min_res_mask, min_mask);
+ si_pmu_wait_for_steady_state(sih, osh, pmu);
+ /* Add some delay; allow resources to come up and settle. */
+ OSL_DELAY(200);
+ si_setcoreidx(sih, origidx);
+#endif /* DUAL_PMU_SEQUENCE */
+}
+
+#if defined(BCMULP)
+
+int
+si_pmu_ulp_register(si_t *sih)
+{
+ return ulp_p1_module_register(ULP_MODULE_ID_PMU, &ulp_pmu_ctx, (void *)sih);
+}
+
+static uint
+si_pmu_ulp_get_retention_size_cb(void *handle, ulp_ext_info_t *einfo)
+{
+ ULP_DBG(("%s: sz: %d\n", __FUNCTION__, sizeof(si_pmu_ulp_cr_dat_t)));
+ return sizeof(si_pmu_ulp_cr_dat_t);
+}
+
+static int
+si_pmu_ulp_enter_cb(void *handle, ulp_ext_info_t *einfo, uint8 *cache_data)
+{
+ si_pmu_ulp_cr_dat_t crinfo = {0};
+ crinfo.ilpcycles_per_sec = ilpcycles_per_sec;
+ ULP_DBG(("%s: ilpcycles_per_sec: %x\n", __FUNCTION__, ilpcycles_per_sec));
+ memcpy(cache_data, (void*)&crinfo, sizeof(crinfo));
+ return BCME_OK;
+}
+
+static int
+si_pmu_ulp_exit_cb(void *handle, uint8 *cache_data,
+ uint8 *p2_cache_data)
+{
+ si_pmu_ulp_cr_dat_t *crinfo = (si_pmu_ulp_cr_dat_t *)cache_data;
+
+ ilpcycles_per_sec = crinfo->ilpcycles_per_sec;
+ ULP_DBG(("%s: ilpcycles_per_sec: %x, cache_data: %p\n", __FUNCTION__,
+ ilpcycles_per_sec, cache_data));
+ return BCME_OK;
+}
+
+void
+si_pmu_ulp_chipconfig(si_t *sih, osl_t *osh)
+{
+ uint32 reg_val;
+
+ BCM_REFERENCE(reg_val);
+
+ if (CHIPID(sih->chip) == BCM43012_CHIP_ID) {
+ /* DS1 reset and clk enable init value config */
+ si_pmu_chipcontrol(sih, PMU_CHIPCTL14, ~0x0,
+ (PMUCCTL14_43012_ARMCM3_RESET_INITVAL |
+ PMUCCTL14_43012_DOT11MAC_CLKEN_INITVAL |
+ PMUCCTL14_43012_SDIOD_RESET_INIVAL |
+ PMUCCTL14_43012_SDIO_CLK_DMN_RESET_INITVAL |
+ PMUCCTL14_43012_SOCRAM_CLKEN_INITVAL |
+ PMUCCTL14_43012_M2MDMA_RESET_INITVAL |
+ PMUCCTL14_43012_DOT11MAC_PHY_CLK_EN_INITVAL |
+ PMUCCTL14_43012_DOT11MAC_PHY_CNTL_EN_INITVAL));
+
+ /* Clear SFlash clock request and enable High Quality clock */
+ CHIPC_REG(sih, clk_ctl_st, CCS_SFLASH_CLKREQ | CCS_HQCLKREQ, CCS_HQCLKREQ);
+
+ reg_val = PMU_REG(sih, min_res_mask, ~0x0, ULP_MIN_RES_MASK);
+ ULP_DBG(("si_pmu_ulp_chipconfig: min_res_mask: 0x%08x\n", reg_val));
+
+ /* Force power switch off */
+ si_pmu_chipcontrol(sih, PMU_CHIPCTL2,
+ (PMUCCTL02_43012_SUBCORE_PWRSW_FORCE_ON |
+ PMUCCTL02_43012_PHY_PWRSW_FORCE_ON), 0);
+
+ }
+}
+
+void
+si_pmu_ulp_ilp_config(si_t *sih, osl_t *osh, uint32 ilp_period)
+{
+ pmuregs_t *pmu;
+ pmu = si_setcoreidx(sih, si_findcoreidx(sih, PMU_CORE_ID, 0));
+ W_REG(osh, &pmu->ILPPeriod, ilp_period);
+ si_lhl_ilp_config(sih, osh, ilp_period);
+}
+
+/** Initialize DS1 PMU hardware resources */
+void
+si_pmu_ds1_res_init(si_t *sih, osl_t *osh)
+{
pmuregs_t *pmu;
uint origidx;
-
- if (!(sih->cccaps & CC_CAP_PMU)) {
- return;
- }
+ const pmu_res_updown_t *pmu_res_updown_table = NULL;
+ uint pmu_res_updown_table_sz = 0;
/* Remember original core before switch to chipc/pmu */
origidx = si_coreidx(sih);
@@ -203,91 +342,449 @@
}
ASSERT(pmu != NULL);
- switch (SDIOD_DRVSTR_KEY(CHIPID(sih->chip), sih->pmurev)) {
- case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1;
- str_mask = 0x30000000;
- str_shift = 28;
+ switch (CHIPID(sih->chip)) {
+ case BCM43012_CHIP_ID:
+ pmu_res_updown_table = bcm43012a0_res_updown_ds1;
+ pmu_res_updown_table_sz = ARRAYSIZE(bcm43012a0_res_updown_ds1);
break;
- case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
- case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
- case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4):
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2;
- str_mask = 0x00003800;
- str_shift = 11;
- break;
- case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
- case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 11):
- if (sih->pmurev == 8) {
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3;
- }
- else if (sih->pmurev == 11) {
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8;
- }
- str_mask = 0x00003800;
- str_shift = 11;
- break;
- case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8;
- str_mask = 0x00003800;
- str_shift = 11;
- break;
- case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab5_1v8;
- str_mask = 0x00003800;
- str_shift = 11;
- break;
- case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab6_1v8;
- str_mask = 0x00001800;
- str_shift = 11;
- break;
- case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
-#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33
- if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_3v3)->strength) {
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_3v3;
- }
-#else
- if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_1v8)->strength) {
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_1v8;
- }
-#endif /* BCM_SDIO_VDDIO */
- str_mask = 0x00000007;
- str_ovr_pmuval = PMU43143_CC0_SDIO_DRSTR_OVR;
- break;
+
default:
- PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
- bcm_chipname(
- CHIPID(sih->chip), chn, 8), CHIPREV(sih->chiprev), sih->pmurev));
break;
}
- if (str_tab != NULL) {
- uint32 cc_data_temp;
- int i;
-
- /* Pick the lowest available drive strength equal or greater than the
- * requested strength. Drive strength of 0 requests tri-state.
- */
- for (i = 0; drivestrength < str_tab[i].strength; i++)
- ;
-
- if (i > 0 && drivestrength > str_tab[i].strength)
- i--;
-
- W_REG(osh, &pmu->chipcontrol_addr, PMU_CHIPCTL1);
- cc_data_temp = R_REG(osh, &pmu->chipcontrol_data);
- cc_data_temp &= ~str_mask;
- cc_data_temp |= str_tab[i].sel << str_shift;
- W_REG(osh, &pmu->chipcontrol_data, cc_data_temp);
- if (str_ovr_pmuval) { /* enables the selected drive strength */
- W_REG(osh, &pmu->chipcontrol_addr, str_ovr_pmuctl);
- OR_REG(osh, &pmu->chipcontrol_data, str_ovr_pmuval);
- }
- PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n",
- drivestrength, str_tab[i].strength));
+ /* Program up/down timers */
+ while (pmu_res_updown_table_sz--) {
+ ASSERT(pmu_res_updown_table != NULL);
+ PMU_MSG(("DS1: Changing rsrc %d res_updn_timer to 0x%x\n",
+ pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
+ pmu_res_updown_table[pmu_res_updown_table_sz].updown));
+ W_REG(osh, &pmu->res_table_sel,
+ pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
+ W_REG(osh, &pmu->res_updn_timer,
+ pmu_res_updown_table[pmu_res_updown_table_sz].updown);
}
/* Return to original core */
si_setcoreidx(sih, origidx);
-} /* si_sdiod_drive_strength_init */
+}
+
+#endif /* defined(BCMULP) */
+
+uint32
+si_pmu_wake_bit_offset(si_t *sih)
+{
+ uint32 wakebit;
+
+ switch (CHIPID(sih->chip)) {
+ case BCM4347_CHIP_GRPID:
+ wakebit = CC2_4347_GCI2WAKE_MASK;
+ break;
+ default:
+ wakebit = 0;
+ ASSERT(0);
+ break;
+ }
+
+ return wakebit;
+}
+
+void si_pmu_set_min_res_mask(si_t *sih, osl_t *osh, uint min_res_mask)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ }
+ else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ W_REG(osh, &pmu->min_res_mask, min_res_mask);
+ OSL_DELAY(100);
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+bool
+si_pmu_cap_fast_lpo(si_t *sih)
+{
+ return (PMU_REG(sih, core_cap_ext, 0, 0) & PCAP_EXT_USE_MUXED_ILP_CLK_MASK) ? TRUE : FALSE;
+}
+
+int
+si_pmu_fast_lpo_disable(si_t *sih)
+{
+ if (!si_pmu_cap_fast_lpo(sih)) {
+ PMU_ERROR(("%s: No Fast LPO capability\n", __FUNCTION__));
+ return BCME_ERROR;
+ }
+
+ PMU_REG(sih, pmucontrol_ext,
+ PCTL_EXT_FASTLPO_ENAB |
+ PCTL_EXT_FASTLPO_SWENAB |
+ PCTL_EXT_FASTLPO_PCIE_SWENAB,
+ 0);
+ OSL_DELAY(1000);
+ return BCME_OK;
+}
+
+#ifdef BCMPMU_STATS
+/*
+ * 8 pmu statistics timer default map
+ *
+ * for CORE_RDY_AUX measure, set as below for timer 6 and 7 instead of CORE_RDY_MAIN.
+ * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX)
+ * { SRC_CORE_RDY_AUX, FALSE, TRUE, LEVEL_HIGH},
+ * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX)
+ * { SRC_CORE_RDY_AUX, FALSE, TRUE, EDGE_RISE}
+ */
+static pmu_stats_timer_t pmustatstimer[] = {
+ { SRC_LINK_IN_L12, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l12
+ { SRC_LINK_IN_L23, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l23
+ { SRC_PM_ST_IN_D0, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d0
+ { SRC_PM_ST_IN_D3, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d3
+ //deep-sleep duration : pmu_rsrc_state(XTAL_PU)
+ { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_LEVEL_LOW},
+ //deep-sleep entry count : pmu_rsrc_state(XTAL_PU)
+ { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_EDGE_FALL},
+ //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN)
+ { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_LEVEL_HIGH},
+ //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN)
+ { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_EDGE_RISE}
+};
+
+static void
+si_pmustatstimer_update(osl_t *osh, pmuregs_t *pmu, uint8 timerid)
+{
+ uint32 stats_timer_ctrl;
+
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
+ stats_timer_ctrl =
+ ((pmustatstimer[timerid].src_num << PMU_ST_SRC_SHIFT) &
+ PMU_ST_SRC_MASK) |
+ ((pmustatstimer[timerid].cnt_mode << PMU_ST_CNT_MODE_SHIFT) &
+ PMU_ST_CNT_MODE_MASK) |
+ ((pmustatstimer[timerid].enable << PMU_ST_EN_SHIFT) & PMU_ST_EN_MASK) |
+ ((pmustatstimer[timerid].int_enable << PMU_ST_INT_EN_SHIFT) & PMU_ST_INT_EN_MASK);
+ W_REG(osh, &pmu->pmu_statstimer_ctrl, stats_timer_ctrl);
+ W_REG(osh, &pmu->pmu_statstimer_N, 0);
+}
+
+void
+si_pmustatstimer_int_enable(si_t *sih)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK);
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_pmustatstimer_int_disable(si_t *sih)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ AND_REG(osh, &pmu->pmuintmask0, ~PMU_INT_STAT_TIMER_INT_MASK);
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_pmustatstimer_init(si_t *sih)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+ uint32 core_cap_ext;
+ uint8 max_stats_timer_num;
+ int8 i;
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
+
+ max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1;
+
+ for (i = 0; i < max_stats_timer_num; i++) {
+ si_pmustatstimer_update(osh, pmu, i);
+ }
+
+ OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK);
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_pmustatstimer_dump(si_t *sih)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+ uint32 core_cap_ext, pmucapabilities, AlpPeriod, ILPPeriod, pmuintmask0, pmuintstatus;
+ uint8 max_stats_timer_num, max_stats_timer_src_num;
+ uint32 stat_timer_ctrl, stat_timer_N;
+ uint8 i;
+ uint32 current_time_ms = OSL_SYSUPTIME();
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ pmucapabilities = R_REG(osh, &pmu->pmucapabilities);
+ core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
+ AlpPeriod = R_REG(osh, &pmu->slowclkperiod);
+ ILPPeriod = R_REG(osh, &pmu->ILPPeriod);
+
+ max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >>
+ PCAP_EXT_ST_NUM_SHIFT) + 1;
+ max_stats_timer_src_num = ((core_cap_ext & PCAP_EXT_ST_SRC_NUM_MASK) >>
+ PCAP_EXT_ST_SRC_NUM_SHIFT) + 1;
+
+ pmuintstatus = R_REG(osh, &pmu->pmuintstatus);
+ pmuintmask0 = R_REG(osh, &pmu->pmuintmask0);
+
+ PMU_ERROR(("%s : TIME %d\n", __FUNCTION__, current_time_ms));
+
+ PMU_ERROR(("\tMAX Timer Num %d, MAX Source Num %d\n",
+ max_stats_timer_num, max_stats_timer_src_num));
+ PMU_ERROR(("\tpmucapabilities 0x%8x, core_cap_ext 0x%8x, AlpPeriod 0x%8x, ILPPeriod 0x%8x, "
+ "pmuintmask0 0x%8x, pmuintstatus 0x%8x, pmurev %d\n",
+ pmucapabilities, core_cap_ext, AlpPeriod, ILPPeriod,
+ pmuintmask0, pmuintstatus, PMUREV(sih->pmurev)));
+
+ for (i = 0; i < max_stats_timer_num; i++) {
+ W_REG(osh, &pmu->pmu_statstimer_addr, i);
+ stat_timer_ctrl = R_REG(osh, &pmu->pmu_statstimer_ctrl);
+ stat_timer_N = R_REG(osh, &pmu->pmu_statstimer_N);
+ PMU_ERROR(("\t Timer %d : control 0x%8x, %d\n",
+ i, stat_timer_ctrl, stat_timer_N));
+ }
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_pmustatstimer_start(si_t *sih, uint8 timerid)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ pmustatstimer[timerid].enable = TRUE;
+
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
+ OR_REG(osh, &pmu->pmu_statstimer_ctrl, PMU_ST_ENAB << PMU_ST_EN_SHIFT);
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_pmustatstimer_stop(si_t *sih, uint8 timerid)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ pmustatstimer[timerid].enable = FALSE;
+
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
+ AND_REG(osh, &pmu->pmu_statstimer_ctrl, ~(PMU_ST_ENAB << PMU_ST_EN_SHIFT));
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_pmustatstimer_clear(si_t *sih, uint8 timerid)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
+ W_REG(osh, &pmu->pmu_statstimer_N, 0);
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_pmustatstimer_clear_overflow(si_t *sih)
+{
+ uint8 i;
+ uint32 core_cap_ext;
+ uint8 max_stats_timer_num;
+ uint32 timerN;
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
+ max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1;
+
+ for (i = 0; i < max_stats_timer_num; i++) {
+ W_REG(osh, &pmu->pmu_statstimer_addr, i);
+ timerN = R_REG(osh, &pmu->pmu_statstimer_N);
+ if (timerN == 0xFFFFFFFF) {
+ PMU_ERROR(("pmustatstimer overflow clear - timerid : %d\n", i));
+ si_pmustatstimer_clear(sih, i);
+ }
+ }
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+uint32
+si_pmustatstimer_read(si_t *sih, uint8 timerid)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+ uint32 stats_timer_N;
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
+ stats_timer_N = R_REG(osh, &pmu->pmu_statstimer_N);
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+
+ return stats_timer_N;
+}
+
+void
+si_pmustatstimer_cfg_src_num(si_t *sih, uint8 src_num, uint8 timerid)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ pmustatstimer[timerid].src_num = src_num;
+ si_pmustatstimer_update(osh, pmu, timerid);
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+
+void
+si_pmustatstimer_cfg_cnt_mode(si_t *sih, uint8 cnt_mode, uint8 timerid)
+{
+ pmuregs_t *pmu;
+ uint origidx;
+ osl_t *osh = si_osh(sih);
+
+ /* Remember original core before switch to chipc/pmu */
+ origidx = si_coreidx(sih);
+ if (AOB_ENAB(sih)) {
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
+ } else {
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
+ }
+ ASSERT(pmu != NULL);
+
+ pmustatstimer[timerid].cnt_mode = cnt_mode;
+ si_pmustatstimer_update(osh, pmu, timerid);
+
+ /* Return to original core */
+ si_setcoreidx(sih, origidx);
+}
+#endif /* BCMPMU_STATS */
--
Gitblit v1.6.2