hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/hndpmu.c
....@@ -1,16 +1,17 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * Misc utility routines for accessing PMU corerev specific features
43 * of the SiliconBackplane-based Broadcom chips.
54 *
6
- * Copyright (C) 1999-2019, Broadcom Corporation
7
- *
5
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
6
+ *
7
+ * Copyright (C) 1999-2017, Broadcom Corporation
8
+ *
89 * Unless you and Broadcom execute a separate written software license
910 * agreement governing use of this software, this software is licensed to you
1011 * under the terms of the GNU General Public License version 2 (the "GPL"),
1112 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1213 * following added to such license:
13
- *
14
+ *
1415 * As a special exception, the copyright holders of this software give you
1516 * permission to link this software with independent modules, and to copy and
1617 * distribute the resulting executable under terms of your choice, provided that
....@@ -18,7 +19,7 @@
1819 * the license of that module. An independent module is a module which is not
1920 * derived from this software. The special exception does not apply to any
2021 * modifications of the software.
21
- *
22
+ *
2223 * Notwithstanding the above, under no circumstances may you combine this
2324 * software in any way with any other Broadcom software provided under a license
2425 * other than the GPL, without Broadcom's express prior written consent.
....@@ -26,15 +27,15 @@
2627 *
2728 * <<Broadcom-WL-IPTag/Open:>>
2829 *
29
- * $Id: hndpmu.c 530092 2015-01-29 04:44:58Z $
30
+ * $Id: hndpmu.c 700652 2017-05-20 02:44:31Z $
3031 */
3132
32
-
33
-/*
33
+/**
34
+ * @file
3435 * Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs.
3536 * However, in the context of this file the baseband ('BB') PLL/FLL is referred to.
3637 *
37
- * Throughout this code, the prefixes 'pmu0_', 'pmu1_' and 'pmu2_' are used.
38
+ * Throughout this code, the prefixes 'pmu1_' and 'pmu2_' are used.
3839 * They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012)
3940 * pmu1_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop). It supports
4041 * fractional frequency generation. pmu2_ does not support fractional frequency generation.
....@@ -49,7 +50,18 @@
4950 #include <bcmdevs.h>
5051 #include <hndsoc.h>
5152 #include <sbchipc.h>
53
+#include <hndchipc.h>
5254 #include <hndpmu.h>
55
+#include <hndlhl.h>
56
+#if defined(BCMULP)
57
+#include <ulp.h>
58
+#endif /* defined(BCMULP) */
59
+#include <sbgci.h>
60
+#ifdef EVENT_LOG_COMPILE
61
+#include <event_log.h>
62
+#endif // endif
63
+#include <sbgci.h>
64
+#include <lpflags.h>
5365
5466 #define PMU_ERROR(args)
5567
....@@ -59,6 +71,7 @@
5971 * to be on except on private builds.
6072 */
6173 #define PMU_NONE(args)
74
+#define flags_shift 14
6275
6376 /** contains resource bit positions for a specific chip */
6477 struct rsc_per_chip_s {
....@@ -66,109 +79,16 @@
6679 uint8 macphy_clkavail;
6780 uint8 ht_start;
6881 uint8 otp_pu;
82
+ uint8 macphy_aux_clkavail;
6983 };
7084
7185 typedef struct rsc_per_chip_s rsc_per_chip_t;
7286
73
-
74
-/* SDIO Pad drive strength to select value mappings.
75
- * The last strength value in each table must be 0 (the tri-state value).
76
- */
77
-typedef struct {
78
- uint8 strength; /* Pad Drive Strength in mA */
79
- uint8 sel; /* Chip-specific select value */
80
-} sdiod_drive_str_t;
81
-
82
-/* SDIO Drive Strength to sel value table for PMU Rev 1 */
83
-static const sdiod_drive_str_t sdiod_drive_strength_tab1[] = {
84
- {4, 0x2},
85
- {2, 0x3},
86
- {1, 0x0},
87
- {0, 0x0} };
88
-
89
-/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
90
-static const sdiod_drive_str_t sdiod_drive_strength_tab2[] = {
91
- {12, 0x7},
92
- {10, 0x6},
93
- {8, 0x5},
94
- {6, 0x4},
95
- {4, 0x2},
96
- {2, 0x1},
97
- {0, 0x0} };
98
-
99
-/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
100
-static const sdiod_drive_str_t sdiod_drive_strength_tab3[] = {
101
- {32, 0x7},
102
- {26, 0x6},
103
- {22, 0x5},
104
- {16, 0x4},
105
- {12, 0x3},
106
- {8, 0x2},
107
- {4, 0x1},
108
- {0, 0x0} };
109
-
110
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8v) */
111
-static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v8[] = {
112
- {32, 0x6},
113
- {26, 0x7},
114
- {22, 0x4},
115
- {16, 0x5},
116
- {12, 0x2},
117
- {8, 0x3},
118
- {4, 0x0},
119
- {0, 0x1} };
120
-
121
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.2v) */
122
-
123
-/* SDIO Drive Strength to sel value table for PMU Rev 11 (2.5v) */
124
-
125
-/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */
126
-static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = {
127
- {6, 0x7},
128
- {5, 0x6},
129
- {4, 0x5},
130
- {3, 0x4},
131
- {2, 0x2},
132
- {1, 0x1},
133
- {0, 0x0} };
134
-
135
-/* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */
136
-
137
-/** SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */
138
-static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = {
139
- {3, 0x3},
140
- {2, 0x2},
141
- {1, 0x1},
142
- {0, 0x0} };
143
-
144
-
145
-/**
146
- * SDIO Drive Strength to sel value table for 43143 PMU Rev 17, see Confluence 43143 Toplevel
147
- * architecture page, section 'PMU Chip Control 1 Register definition', click link to picture
148
- * BCM43143_sel_sdio_signals.jpg. Valid after PMU Chip Control 0 Register, bit31 (override) has
149
- * been written '1'.
150
- */
151
-#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33
152
-
153
-static const sdiod_drive_str_t sdiod_drive_strength_tab7_3v3[] = {
154
- /* note: for 14, 10, 6 and 2mA hw timing is not met according to rtl team */
155
- {16, 0x7},
156
- {12, 0x5},
157
- {8, 0x3},
158
- {4, 0x1} }; /* note: 43143 does not support tristate */
159
-
87
+#if defined(BCMPMU_STATS) && !defined(BCMPMU_STATS_DISABLED)
88
+bool _pmustatsenab = TRUE;
16089 #else
161
-
162
-static const sdiod_drive_str_t sdiod_drive_strength_tab7_1v8[] = {
163
- /* note: for 7, 5, 3 and 1mA hw timing is not met according to rtl team */
164
- {8, 0x7},
165
- {6, 0x5},
166
- {4, 0x3},
167
- {2, 0x1} }; /* note: 43143 does not support tristate */
168
-
169
-#endif /* BCM_SDIO_VDDIO */
170
-
171
-#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu))
90
+bool _pmustatsenab = FALSE;
91
+#endif /* BCMPMU_STATS */
17292
17393 /**
17494 * Balance between stable SDIO operation and power consumption is achieved using this function.
....@@ -182,17 +102,236 @@
182102 void
183103 si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength)
184104 {
185
- sdiod_drive_str_t *str_tab = NULL;
186
- uint32 str_mask = 0; /* only alter desired bits in PMU chipcontrol 1 register */
187
- uint32 str_shift = 0;
188
- uint32 str_ovr_pmuctl = PMU_CHIPCTL0; /* PMU chipcontrol register containing override bit */
189
- uint32 str_ovr_pmuval = 0; /* position of bit within this register */
105
+ /*
106
+ * Note:
107
+ * This function used to set the SDIO drive strength via PMU_CHIPCTL1 for the
108
+ * 43143, 4330, 4334, 4336, 43362 chips. These chips are now no longer supported, so
109
+ * the code has been deleted.
110
+ * Newer chips have the SDIO drive strength setting via a GCI Chip Control register,
111
+ * but the bit definitions are chip-specific. We are keeping this function available
112
+ * (accessed via DHD 'sdiod_drive' IOVar) in case these newer chips need to provide access.
113
+ */
114
+ UNUSED_PARAMETER(sih);
115
+ UNUSED_PARAMETER(osh);
116
+ UNUSED_PARAMETER(drivestrength);
117
+}
118
+
119
+void
120
+si_switch_pmu_dependency(si_t *sih, uint mode)
121
+{
122
+#ifdef DUAL_PMU_SEQUENCE
123
+ osl_t *osh = si_osh(sih);
124
+ uint32 current_res_state;
125
+ uint32 min_mask, max_mask;
126
+ const pmu_res_depend_t *pmu_res_depend_table = NULL;
127
+ uint pmu_res_depend_table_sz = 0;
128
+ uint origidx;
129
+ pmuregs_t *pmu;
130
+ chipcregs_t *cc;
131
+ BCM_REFERENCE(cc);
132
+
133
+ origidx = si_coreidx(sih);
134
+ if (AOB_ENAB(sih)) {
135
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
136
+ cc = si_setcore(sih, CC_CORE_ID, 0);
137
+ } else {
138
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
139
+ cc = si_setcoreidx(sih, SI_CC_IDX);
140
+ }
141
+ ASSERT(pmu != NULL);
142
+
143
+ current_res_state = R_REG(osh, &pmu->res_state);
144
+ min_mask = R_REG(osh, &pmu->min_res_mask);
145
+ max_mask = R_REG(osh, &pmu->max_res_mask);
146
+ W_REG(osh, &pmu->min_res_mask, (min_mask | current_res_state));
147
+ switch (mode) {
148
+ case PMU_4364_1x1_MODE:
149
+ {
150
+ if (CHIPID(sih->chip) == BCM4364_CHIP_ID) {
151
+ pmu_res_depend_table = bcm4364a0_res_depend_1x1;
152
+ pmu_res_depend_table_sz =
153
+ ARRAYSIZE(bcm4364a0_res_depend_1x1);
154
+ max_mask = PMU_4364_MAX_MASK_1x1;
155
+ W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE);
156
+ W_REG(osh, &pmu->res_updn_timer, PMU_4364_SAVE_RESTORE_UPDNTIME_1x1);
157
+#if defined(SAVERESTORE)
158
+ if (SR_ENAB()) {
159
+ /* Disable 3x3 SR engine */
160
+ W_REG(osh, &cc->sr1_control0,
161
+ CC_SR0_4364_SR_ENG_CLK_EN |
162
+ CC_SR0_4364_SR_RSRC_TRIGGER |
163
+ CC_SR0_4364_SR_WD_MEM_MIN_DIV |
164
+ CC_SR0_4364_SR_INVERT_CLK |
165
+ CC_SR0_4364_SR_ENABLE_HT |
166
+ CC_SR0_4364_SR_ALLOW_PIC |
167
+ CC_SR0_4364_SR_PMU_MEM_DISABLE);
168
+ }
169
+#endif /* SAVERESTORE */
170
+ }
171
+ break;
172
+ }
173
+ case PMU_4364_3x3_MODE:
174
+ {
175
+ if (CHIPID(sih->chip) == BCM4364_CHIP_ID) {
176
+ W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE);
177
+ W_REG(osh, &pmu->res_updn_timer,
178
+ PMU_4364_SAVE_RESTORE_UPDNTIME_3x3);
179
+ /* Change the dependency table only if required */
180
+ if ((max_mask != PMU_4364_MAX_MASK_3x3) ||
181
+ (max_mask != PMU_4364_MAX_MASK_RSDB)) {
182
+ pmu_res_depend_table = bcm4364a0_res_depend_rsdb;
183
+ pmu_res_depend_table_sz =
184
+ ARRAYSIZE(bcm4364a0_res_depend_rsdb);
185
+ max_mask = PMU_4364_MAX_MASK_3x3;
186
+ }
187
+#if defined(SAVERESTORE)
188
+ if (SR_ENAB()) {
189
+ /* Enable 3x3 SR engine */
190
+ W_REG(osh, &cc->sr1_control0,
191
+ CC_SR0_4364_SR_ENG_CLK_EN |
192
+ CC_SR0_4364_SR_RSRC_TRIGGER |
193
+ CC_SR0_4364_SR_WD_MEM_MIN_DIV |
194
+ CC_SR0_4364_SR_INVERT_CLK |
195
+ CC_SR0_4364_SR_ENABLE_HT |
196
+ CC_SR0_4364_SR_ALLOW_PIC |
197
+ CC_SR0_4364_SR_PMU_MEM_DISABLE |
198
+ CC_SR0_4364_SR_ENG_EN_MASK);
199
+ }
200
+#endif /* SAVERESTORE */
201
+ }
202
+ break;
203
+ }
204
+ case PMU_4364_RSDB_MODE:
205
+ default:
206
+ {
207
+ if (CHIPID(sih->chip) == BCM4364_CHIP_ID) {
208
+ W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE);
209
+ W_REG(osh, &pmu->res_updn_timer,
210
+ PMU_4364_SAVE_RESTORE_UPDNTIME_3x3);
211
+ /* Change the dependency table only if required */
212
+ if ((max_mask != PMU_4364_MAX_MASK_3x3) ||
213
+ (max_mask != PMU_4364_MAX_MASK_RSDB)) {
214
+ pmu_res_depend_table =
215
+ bcm4364a0_res_depend_rsdb;
216
+ pmu_res_depend_table_sz =
217
+ ARRAYSIZE(bcm4364a0_res_depend_rsdb);
218
+ max_mask = PMU_4364_MAX_MASK_RSDB;
219
+ }
220
+#if defined(SAVERESTORE)
221
+ if (SR_ENAB()) {
222
+ /* Enable 3x3 SR engine */
223
+ W_REG(osh, &cc->sr1_control0,
224
+ CC_SR0_4364_SR_ENG_CLK_EN |
225
+ CC_SR0_4364_SR_RSRC_TRIGGER |
226
+ CC_SR0_4364_SR_WD_MEM_MIN_DIV |
227
+ CC_SR0_4364_SR_INVERT_CLK |
228
+ CC_SR0_4364_SR_ENABLE_HT |
229
+ CC_SR0_4364_SR_ALLOW_PIC |
230
+ CC_SR0_4364_SR_PMU_MEM_DISABLE |
231
+ CC_SR0_4364_SR_ENG_EN_MASK);
232
+ }
233
+#endif /* SAVERESTORE */
234
+ }
235
+ break;
236
+ }
237
+ }
238
+ si_pmu_resdeptbl_upd(sih, osh, pmu, pmu_res_depend_table, pmu_res_depend_table_sz);
239
+ W_REG(osh, &pmu->max_res_mask, max_mask);
240
+ W_REG(osh, &pmu->min_res_mask, min_mask);
241
+ si_pmu_wait_for_steady_state(sih, osh, pmu);
242
+ /* Add some delay; allow resources to come up and settle. */
243
+ OSL_DELAY(200);
244
+ si_setcoreidx(sih, origidx);
245
+#endif /* DUAL_PMU_SEQUENCE */
246
+}
247
+
248
+#if defined(BCMULP)
249
+
250
+int
251
+si_pmu_ulp_register(si_t *sih)
252
+{
253
+ return ulp_p1_module_register(ULP_MODULE_ID_PMU, &ulp_pmu_ctx, (void *)sih);
254
+}
255
+
256
+static uint
257
+si_pmu_ulp_get_retention_size_cb(void *handle, ulp_ext_info_t *einfo)
258
+{
259
+ ULP_DBG(("%s: sz: %d\n", __FUNCTION__, sizeof(si_pmu_ulp_cr_dat_t)));
260
+ return sizeof(si_pmu_ulp_cr_dat_t);
261
+}
262
+
263
+static int
264
+si_pmu_ulp_enter_cb(void *handle, ulp_ext_info_t *einfo, uint8 *cache_data)
265
+{
266
+ si_pmu_ulp_cr_dat_t crinfo = {0};
267
+ crinfo.ilpcycles_per_sec = ilpcycles_per_sec;
268
+ ULP_DBG(("%s: ilpcycles_per_sec: %x\n", __FUNCTION__, ilpcycles_per_sec));
269
+ memcpy(cache_data, (void*)&crinfo, sizeof(crinfo));
270
+ return BCME_OK;
271
+}
272
+
273
+static int
274
+si_pmu_ulp_exit_cb(void *handle, uint8 *cache_data,
275
+ uint8 *p2_cache_data)
276
+{
277
+ si_pmu_ulp_cr_dat_t *crinfo = (si_pmu_ulp_cr_dat_t *)cache_data;
278
+
279
+ ilpcycles_per_sec = crinfo->ilpcycles_per_sec;
280
+ ULP_DBG(("%s: ilpcycles_per_sec: %x, cache_data: %p\n", __FUNCTION__,
281
+ ilpcycles_per_sec, cache_data));
282
+ return BCME_OK;
283
+}
284
+
285
+void
286
+si_pmu_ulp_chipconfig(si_t *sih, osl_t *osh)
287
+{
288
+ uint32 reg_val;
289
+
290
+ BCM_REFERENCE(reg_val);
291
+
292
+ if (CHIPID(sih->chip) == BCM43012_CHIP_ID) {
293
+ /* DS1 reset and clk enable init value config */
294
+ si_pmu_chipcontrol(sih, PMU_CHIPCTL14, ~0x0,
295
+ (PMUCCTL14_43012_ARMCM3_RESET_INITVAL |
296
+ PMUCCTL14_43012_DOT11MAC_CLKEN_INITVAL |
297
+ PMUCCTL14_43012_SDIOD_RESET_INIVAL |
298
+ PMUCCTL14_43012_SDIO_CLK_DMN_RESET_INITVAL |
299
+ PMUCCTL14_43012_SOCRAM_CLKEN_INITVAL |
300
+ PMUCCTL14_43012_M2MDMA_RESET_INITVAL |
301
+ PMUCCTL14_43012_DOT11MAC_PHY_CLK_EN_INITVAL |
302
+ PMUCCTL14_43012_DOT11MAC_PHY_CNTL_EN_INITVAL));
303
+
304
+ /* Clear SFlash clock request and enable High Quality clock */
305
+ CHIPC_REG(sih, clk_ctl_st, CCS_SFLASH_CLKREQ | CCS_HQCLKREQ, CCS_HQCLKREQ);
306
+
307
+ reg_val = PMU_REG(sih, min_res_mask, ~0x0, ULP_MIN_RES_MASK);
308
+ ULP_DBG(("si_pmu_ulp_chipconfig: min_res_mask: 0x%08x\n", reg_val));
309
+
310
+ /* Force power switch off */
311
+ si_pmu_chipcontrol(sih, PMU_CHIPCTL2,
312
+ (PMUCCTL02_43012_SUBCORE_PWRSW_FORCE_ON |
313
+ PMUCCTL02_43012_PHY_PWRSW_FORCE_ON), 0);
314
+
315
+ }
316
+}
317
+
318
+void
319
+si_pmu_ulp_ilp_config(si_t *sih, osl_t *osh, uint32 ilp_period)
320
+{
321
+ pmuregs_t *pmu;
322
+ pmu = si_setcoreidx(sih, si_findcoreidx(sih, PMU_CORE_ID, 0));
323
+ W_REG(osh, &pmu->ILPPeriod, ilp_period);
324
+ si_lhl_ilp_config(sih, osh, ilp_period);
325
+}
326
+
327
+/** Initialize DS1 PMU hardware resources */
328
+void
329
+si_pmu_ds1_res_init(si_t *sih, osl_t *osh)
330
+{
190331 pmuregs_t *pmu;
191332 uint origidx;
192
-
193
- if (!(sih->cccaps & CC_CAP_PMU)) {
194
- return;
195
- }
333
+ const pmu_res_updown_t *pmu_res_updown_table = NULL;
334
+ uint pmu_res_updown_table_sz = 0;
196335
197336 /* Remember original core before switch to chipc/pmu */
198337 origidx = si_coreidx(sih);
....@@ -203,91 +342,449 @@
203342 }
204343 ASSERT(pmu != NULL);
205344
206
- switch (SDIOD_DRVSTR_KEY(CHIPID(sih->chip), sih->pmurev)) {
207
- case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
208
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1;
209
- str_mask = 0x30000000;
210
- str_shift = 28;
345
+ switch (CHIPID(sih->chip)) {
346
+ case BCM43012_CHIP_ID:
347
+ pmu_res_updown_table = bcm43012a0_res_updown_ds1;
348
+ pmu_res_updown_table_sz = ARRAYSIZE(bcm43012a0_res_updown_ds1);
211349 break;
212
- case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
213
- case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
214
- case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4):
215
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2;
216
- str_mask = 0x00003800;
217
- str_shift = 11;
218
- break;
219
- case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
220
- case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 11):
221
- if (sih->pmurev == 8) {
222
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3;
223
- }
224
- else if (sih->pmurev == 11) {
225
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8;
226
- }
227
- str_mask = 0x00003800;
228
- str_shift = 11;
229
- break;
230
- case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
231
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8;
232
- str_mask = 0x00003800;
233
- str_shift = 11;
234
- break;
235
- case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
236
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab5_1v8;
237
- str_mask = 0x00003800;
238
- str_shift = 11;
239
- break;
240
- case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
241
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab6_1v8;
242
- str_mask = 0x00001800;
243
- str_shift = 11;
244
- break;
245
- case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
246
-#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33
247
- if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_3v3)->strength) {
248
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_3v3;
249
- }
250
-#else
251
- if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_1v8)->strength) {
252
- str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_1v8;
253
- }
254
-#endif /* BCM_SDIO_VDDIO */
255
- str_mask = 0x00000007;
256
- str_ovr_pmuval = PMU43143_CC0_SDIO_DRSTR_OVR;
257
- break;
350
+
258351 default:
259
- PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n",
260
- bcm_chipname(
261
- CHIPID(sih->chip), chn, 8), CHIPREV(sih->chiprev), sih->pmurev));
262352 break;
263353 }
264354
265
- if (str_tab != NULL) {
266
- uint32 cc_data_temp;
267
- int i;
268
-
269
- /* Pick the lowest available drive strength equal or greater than the
270
- * requested strength. Drive strength of 0 requests tri-state.
271
- */
272
- for (i = 0; drivestrength < str_tab[i].strength; i++)
273
- ;
274
-
275
- if (i > 0 && drivestrength > str_tab[i].strength)
276
- i--;
277
-
278
- W_REG(osh, &pmu->chipcontrol_addr, PMU_CHIPCTL1);
279
- cc_data_temp = R_REG(osh, &pmu->chipcontrol_data);
280
- cc_data_temp &= ~str_mask;
281
- cc_data_temp |= str_tab[i].sel << str_shift;
282
- W_REG(osh, &pmu->chipcontrol_data, cc_data_temp);
283
- if (str_ovr_pmuval) { /* enables the selected drive strength */
284
- W_REG(osh, &pmu->chipcontrol_addr, str_ovr_pmuctl);
285
- OR_REG(osh, &pmu->chipcontrol_data, str_ovr_pmuval);
286
- }
287
- PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n",
288
- drivestrength, str_tab[i].strength));
355
+ /* Program up/down timers */
356
+ while (pmu_res_updown_table_sz--) {
357
+ ASSERT(pmu_res_updown_table != NULL);
358
+ PMU_MSG(("DS1: Changing rsrc %d res_updn_timer to 0x%x\n",
359
+ pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
360
+ pmu_res_updown_table[pmu_res_updown_table_sz].updown));
361
+ W_REG(osh, &pmu->res_table_sel,
362
+ pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
363
+ W_REG(osh, &pmu->res_updn_timer,
364
+ pmu_res_updown_table[pmu_res_updown_table_sz].updown);
289365 }
290366
291367 /* Return to original core */
292368 si_setcoreidx(sih, origidx);
293
-} /* si_sdiod_drive_strength_init */
369
+}
370
+
371
+#endif /* defined(BCMULP) */
372
+
373
+uint32
374
+si_pmu_wake_bit_offset(si_t *sih)
375
+{
376
+ uint32 wakebit;
377
+
378
+ switch (CHIPID(sih->chip)) {
379
+ case BCM4347_CHIP_GRPID:
380
+ wakebit = CC2_4347_GCI2WAKE_MASK;
381
+ break;
382
+ default:
383
+ wakebit = 0;
384
+ ASSERT(0);
385
+ break;
386
+ }
387
+
388
+ return wakebit;
389
+}
390
+
391
+void si_pmu_set_min_res_mask(si_t *sih, osl_t *osh, uint min_res_mask)
392
+{
393
+ pmuregs_t *pmu;
394
+ uint origidx;
395
+
396
+ /* Remember original core before switch to chipc/pmu */
397
+ origidx = si_coreidx(sih);
398
+ if (AOB_ENAB(sih)) {
399
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
400
+ }
401
+ else {
402
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
403
+ }
404
+ ASSERT(pmu != NULL);
405
+
406
+ W_REG(osh, &pmu->min_res_mask, min_res_mask);
407
+ OSL_DELAY(100);
408
+
409
+ /* Return to original core */
410
+ si_setcoreidx(sih, origidx);
411
+}
412
+
413
+bool
414
+si_pmu_cap_fast_lpo(si_t *sih)
415
+{
416
+ return (PMU_REG(sih, core_cap_ext, 0, 0) & PCAP_EXT_USE_MUXED_ILP_CLK_MASK) ? TRUE : FALSE;
417
+}
418
+
419
+int
420
+si_pmu_fast_lpo_disable(si_t *sih)
421
+{
422
+ if (!si_pmu_cap_fast_lpo(sih)) {
423
+ PMU_ERROR(("%s: No Fast LPO capability\n", __FUNCTION__));
424
+ return BCME_ERROR;
425
+ }
426
+
427
+ PMU_REG(sih, pmucontrol_ext,
428
+ PCTL_EXT_FASTLPO_ENAB |
429
+ PCTL_EXT_FASTLPO_SWENAB |
430
+ PCTL_EXT_FASTLPO_PCIE_SWENAB,
431
+ 0);
432
+ OSL_DELAY(1000);
433
+ return BCME_OK;
434
+}
435
+
436
+#ifdef BCMPMU_STATS
437
+/*
438
+ * 8 pmu statistics timer default map
439
+ *
440
+ * for CORE_RDY_AUX measure, set as below for timer 6 and 7 instead of CORE_RDY_MAIN.
441
+ * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX)
442
+ * { SRC_CORE_RDY_AUX, FALSE, TRUE, LEVEL_HIGH},
443
+ * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX)
444
+ * { SRC_CORE_RDY_AUX, FALSE, TRUE, EDGE_RISE}
445
+ */
446
+static pmu_stats_timer_t pmustatstimer[] = {
447
+ { SRC_LINK_IN_L12, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l12
448
+ { SRC_LINK_IN_L23, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l23
449
+ { SRC_PM_ST_IN_D0, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d0
450
+ { SRC_PM_ST_IN_D3, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d3
451
+ //deep-sleep duration : pmu_rsrc_state(XTAL_PU)
452
+ { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_LEVEL_LOW},
453
+ //deep-sleep entry count : pmu_rsrc_state(XTAL_PU)
454
+ { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_EDGE_FALL},
455
+ //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN)
456
+ { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_LEVEL_HIGH},
457
+ //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN)
458
+ { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_EDGE_RISE}
459
+};
460
+
461
+static void
462
+si_pmustatstimer_update(osl_t *osh, pmuregs_t *pmu, uint8 timerid)
463
+{
464
+ uint32 stats_timer_ctrl;
465
+
466
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
467
+ stats_timer_ctrl =
468
+ ((pmustatstimer[timerid].src_num << PMU_ST_SRC_SHIFT) &
469
+ PMU_ST_SRC_MASK) |
470
+ ((pmustatstimer[timerid].cnt_mode << PMU_ST_CNT_MODE_SHIFT) &
471
+ PMU_ST_CNT_MODE_MASK) |
472
+ ((pmustatstimer[timerid].enable << PMU_ST_EN_SHIFT) & PMU_ST_EN_MASK) |
473
+ ((pmustatstimer[timerid].int_enable << PMU_ST_INT_EN_SHIFT) & PMU_ST_INT_EN_MASK);
474
+ W_REG(osh, &pmu->pmu_statstimer_ctrl, stats_timer_ctrl);
475
+ W_REG(osh, &pmu->pmu_statstimer_N, 0);
476
+}
477
+
478
+void
479
+si_pmustatstimer_int_enable(si_t *sih)
480
+{
481
+ pmuregs_t *pmu;
482
+ uint origidx;
483
+ osl_t *osh = si_osh(sih);
484
+
485
+ /* Remember original core before switch to chipc/pmu */
486
+ origidx = si_coreidx(sih);
487
+ if (AOB_ENAB(sih)) {
488
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
489
+ } else {
490
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
491
+ }
492
+ ASSERT(pmu != NULL);
493
+
494
+ OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK);
495
+
496
+ /* Return to original core */
497
+ si_setcoreidx(sih, origidx);
498
+}
499
+
500
+void
501
+si_pmustatstimer_int_disable(si_t *sih)
502
+{
503
+ pmuregs_t *pmu;
504
+ uint origidx;
505
+ osl_t *osh = si_osh(sih);
506
+
507
+ /* Remember original core before switch to chipc/pmu */
508
+ origidx = si_coreidx(sih);
509
+ if (AOB_ENAB(sih)) {
510
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
511
+ } else {
512
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
513
+ }
514
+ ASSERT(pmu != NULL);
515
+
516
+ AND_REG(osh, &pmu->pmuintmask0, ~PMU_INT_STAT_TIMER_INT_MASK);
517
+
518
+ /* Return to original core */
519
+ si_setcoreidx(sih, origidx);
520
+}
521
+
522
+void
523
+si_pmustatstimer_init(si_t *sih)
524
+{
525
+ pmuregs_t *pmu;
526
+ uint origidx;
527
+ osl_t *osh = si_osh(sih);
528
+ uint32 core_cap_ext;
529
+ uint8 max_stats_timer_num;
530
+ int8 i;
531
+
532
+ /* Remember original core before switch to chipc/pmu */
533
+ origidx = si_coreidx(sih);
534
+ if (AOB_ENAB(sih)) {
535
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
536
+ } else {
537
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
538
+ }
539
+ ASSERT(pmu != NULL);
540
+
541
+ core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
542
+
543
+ max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1;
544
+
545
+ for (i = 0; i < max_stats_timer_num; i++) {
546
+ si_pmustatstimer_update(osh, pmu, i);
547
+ }
548
+
549
+ OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK);
550
+
551
+ /* Return to original core */
552
+ si_setcoreidx(sih, origidx);
553
+}
554
+
555
+void
556
+si_pmustatstimer_dump(si_t *sih)
557
+{
558
+ pmuregs_t *pmu;
559
+ uint origidx;
560
+ osl_t *osh = si_osh(sih);
561
+ uint32 core_cap_ext, pmucapabilities, AlpPeriod, ILPPeriod, pmuintmask0, pmuintstatus;
562
+ uint8 max_stats_timer_num, max_stats_timer_src_num;
563
+ uint32 stat_timer_ctrl, stat_timer_N;
564
+ uint8 i;
565
+ uint32 current_time_ms = OSL_SYSUPTIME();
566
+
567
+ /* Remember original core before switch to chipc/pmu */
568
+ origidx = si_coreidx(sih);
569
+ if (AOB_ENAB(sih)) {
570
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
571
+ } else {
572
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
573
+ }
574
+ ASSERT(pmu != NULL);
575
+
576
+ pmucapabilities = R_REG(osh, &pmu->pmucapabilities);
577
+ core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
578
+ AlpPeriod = R_REG(osh, &pmu->slowclkperiod);
579
+ ILPPeriod = R_REG(osh, &pmu->ILPPeriod);
580
+
581
+ max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >>
582
+ PCAP_EXT_ST_NUM_SHIFT) + 1;
583
+ max_stats_timer_src_num = ((core_cap_ext & PCAP_EXT_ST_SRC_NUM_MASK) >>
584
+ PCAP_EXT_ST_SRC_NUM_SHIFT) + 1;
585
+
586
+ pmuintstatus = R_REG(osh, &pmu->pmuintstatus);
587
+ pmuintmask0 = R_REG(osh, &pmu->pmuintmask0);
588
+
589
+ PMU_ERROR(("%s : TIME %d\n", __FUNCTION__, current_time_ms));
590
+
591
+ PMU_ERROR(("\tMAX Timer Num %d, MAX Source Num %d\n",
592
+ max_stats_timer_num, max_stats_timer_src_num));
593
+ PMU_ERROR(("\tpmucapabilities 0x%8x, core_cap_ext 0x%8x, AlpPeriod 0x%8x, ILPPeriod 0x%8x, "
594
+ "pmuintmask0 0x%8x, pmuintstatus 0x%8x, pmurev %d\n",
595
+ pmucapabilities, core_cap_ext, AlpPeriod, ILPPeriod,
596
+ pmuintmask0, pmuintstatus, PMUREV(sih->pmurev)));
597
+
598
+ for (i = 0; i < max_stats_timer_num; i++) {
599
+ W_REG(osh, &pmu->pmu_statstimer_addr, i);
600
+ stat_timer_ctrl = R_REG(osh, &pmu->pmu_statstimer_ctrl);
601
+ stat_timer_N = R_REG(osh, &pmu->pmu_statstimer_N);
602
+ PMU_ERROR(("\t Timer %d : control 0x%8x, %d\n",
603
+ i, stat_timer_ctrl, stat_timer_N));
604
+ }
605
+
606
+ /* Return to original core */
607
+ si_setcoreidx(sih, origidx);
608
+}
609
+
610
+void
611
+si_pmustatstimer_start(si_t *sih, uint8 timerid)
612
+{
613
+ pmuregs_t *pmu;
614
+ uint origidx;
615
+ osl_t *osh = si_osh(sih);
616
+
617
+ /* Remember original core before switch to chipc/pmu */
618
+ origidx = si_coreidx(sih);
619
+ if (AOB_ENAB(sih)) {
620
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
621
+ } else {
622
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
623
+ }
624
+ ASSERT(pmu != NULL);
625
+
626
+ pmustatstimer[timerid].enable = TRUE;
627
+
628
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
629
+ OR_REG(osh, &pmu->pmu_statstimer_ctrl, PMU_ST_ENAB << PMU_ST_EN_SHIFT);
630
+
631
+ /* Return to original core */
632
+ si_setcoreidx(sih, origidx);
633
+}
634
+
635
+void
636
+si_pmustatstimer_stop(si_t *sih, uint8 timerid)
637
+{
638
+ pmuregs_t *pmu;
639
+ uint origidx;
640
+ osl_t *osh = si_osh(sih);
641
+
642
+ /* Remember original core before switch to chipc/pmu */
643
+ origidx = si_coreidx(sih);
644
+ if (AOB_ENAB(sih)) {
645
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
646
+ } else {
647
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
648
+ }
649
+ ASSERT(pmu != NULL);
650
+
651
+ pmustatstimer[timerid].enable = FALSE;
652
+
653
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
654
+ AND_REG(osh, &pmu->pmu_statstimer_ctrl, ~(PMU_ST_ENAB << PMU_ST_EN_SHIFT));
655
+
656
+ /* Return to original core */
657
+ si_setcoreidx(sih, origidx);
658
+}
659
+
660
+void
661
+si_pmustatstimer_clear(si_t *sih, uint8 timerid)
662
+{
663
+ pmuregs_t *pmu;
664
+ uint origidx;
665
+ osl_t *osh = si_osh(sih);
666
+
667
+ /* Remember original core before switch to chipc/pmu */
668
+ origidx = si_coreidx(sih);
669
+ if (AOB_ENAB(sih)) {
670
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
671
+ } else {
672
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
673
+ }
674
+ ASSERT(pmu != NULL);
675
+
676
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
677
+ W_REG(osh, &pmu->pmu_statstimer_N, 0);
678
+
679
+ /* Return to original core */
680
+ si_setcoreidx(sih, origidx);
681
+}
682
+
683
+void
684
+si_pmustatstimer_clear_overflow(si_t *sih)
685
+{
686
+ uint8 i;
687
+ uint32 core_cap_ext;
688
+ uint8 max_stats_timer_num;
689
+ uint32 timerN;
690
+ pmuregs_t *pmu;
691
+ uint origidx;
692
+ osl_t *osh = si_osh(sih);
693
+
694
+ /* Remember original core before switch to chipc/pmu */
695
+ origidx = si_coreidx(sih);
696
+ if (AOB_ENAB(sih)) {
697
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
698
+ } else {
699
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
700
+ }
701
+ ASSERT(pmu != NULL);
702
+
703
+ core_cap_ext = R_REG(osh, &pmu->core_cap_ext);
704
+ max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1;
705
+
706
+ for (i = 0; i < max_stats_timer_num; i++) {
707
+ W_REG(osh, &pmu->pmu_statstimer_addr, i);
708
+ timerN = R_REG(osh, &pmu->pmu_statstimer_N);
709
+ if (timerN == 0xFFFFFFFF) {
710
+ PMU_ERROR(("pmustatstimer overflow clear - timerid : %d\n", i));
711
+ si_pmustatstimer_clear(sih, i);
712
+ }
713
+ }
714
+
715
+ /* Return to original core */
716
+ si_setcoreidx(sih, origidx);
717
+}
718
+
719
+uint32
720
+si_pmustatstimer_read(si_t *sih, uint8 timerid)
721
+{
722
+ pmuregs_t *pmu;
723
+ uint origidx;
724
+ osl_t *osh = si_osh(sih);
725
+ uint32 stats_timer_N;
726
+
727
+ /* Remember original core before switch to chipc/pmu */
728
+ origidx = si_coreidx(sih);
729
+ if (AOB_ENAB(sih)) {
730
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
731
+ } else {
732
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
733
+ }
734
+ ASSERT(pmu != NULL);
735
+
736
+ W_REG(osh, &pmu->pmu_statstimer_addr, timerid);
737
+ stats_timer_N = R_REG(osh, &pmu->pmu_statstimer_N);
738
+
739
+ /* Return to original core */
740
+ si_setcoreidx(sih, origidx);
741
+
742
+ return stats_timer_N;
743
+}
744
+
745
+void
746
+si_pmustatstimer_cfg_src_num(si_t *sih, uint8 src_num, uint8 timerid)
747
+{
748
+ pmuregs_t *pmu;
749
+ uint origidx;
750
+ osl_t *osh = si_osh(sih);
751
+
752
+ /* Remember original core before switch to chipc/pmu */
753
+ origidx = si_coreidx(sih);
754
+ if (AOB_ENAB(sih)) {
755
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
756
+ } else {
757
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
758
+ }
759
+ ASSERT(pmu != NULL);
760
+
761
+ pmustatstimer[timerid].src_num = src_num;
762
+ si_pmustatstimer_update(osh, pmu, timerid);
763
+
764
+ /* Return to original core */
765
+ si_setcoreidx(sih, origidx);
766
+}
767
+
768
+void
769
+si_pmustatstimer_cfg_cnt_mode(si_t *sih, uint8 cnt_mode, uint8 timerid)
770
+{
771
+ pmuregs_t *pmu;
772
+ uint origidx;
773
+ osl_t *osh = si_osh(sih);
774
+
775
+ /* Remember original core before switch to chipc/pmu */
776
+ origidx = si_coreidx(sih);
777
+ if (AOB_ENAB(sih)) {
778
+ pmu = si_setcore(sih, PMU_CORE_ID, 0);
779
+ } else {
780
+ pmu = si_setcoreidx(sih, SI_CC_IDX);
781
+ }
782
+ ASSERT(pmu != NULL);
783
+
784
+ pmustatstimer[timerid].cnt_mode = cnt_mode;
785
+ si_pmustatstimer_update(osh, pmu, timerid);
786
+
787
+ /* Return to original core */
788
+ si_setcoreidx(sih, origidx);
789
+}
790
+#endif /* BCMPMU_STATS */