1 /*
2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
4 *
5 * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
6 *
7 * Copyright (C) 1999-2017, 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: siutils.c 701025 2017-05-23 10:23:52Z $
31 */
32
33 #include <bcm_cfg.h>
34 #include <typedefs.h>
35 #include <bcmdefs.h>
36 #include <osl.h>
37 #include <bcmutils.h>
38 #include <siutils.h>
39 #include <bcmdevs.h>
40 #include <hndsoc.h>
41 #include <sbchipc.h>
42 #include <sbgci.h>
43 #ifndef BCMSDIO
44 #include <pcie_core.h>
45 #endif // endif
46 #ifdef BCMPCIEDEV
47 /
48 #endif /* BCMPCIEDEV */
49 #include <pcicfg.h>
50 #include <sbpcmcia.h>
51 #include <sbsysmem.h>
52 #include <sbsocram.h>
53 #ifdef BCMSDIO
54 #include <bcmsdh.h>
55 #include <sdio.h>
56 #include <sbsdio.h>
57 #include <sbhnddma.h>
58 #include <sbsdpcmdev.h>
59 #include <bcmsdpcm.h>
60 #endif /* BCMSDIO */
61 #include <hndpmu.h>
62 #ifdef BCMSPI
63 #include <spid.h>
64 #endif /* BCMSPI */
65
66 #ifdef BCM_SDRBL
67 #include <hndcpu.h>
68 #endif /* BCM_SDRBL */
69 #ifdef HNDGCI
70 #include <hndgci.h>
71 #endif /* HNDGCI */
72 #ifdef WLGCIMBHLR
73 #include <hnd_gci.h>
74 #endif /* WLGCIMBHLR */
75 #ifdef BCMULP
76 #include <ulp.h>
77 #endif /* BCMULP */
78 #include <hndlhl.h>
79
80 #include <lpflags.h>
81
82 #include "siutils_priv.h"
83 #ifdef SECI_UART
84 /* Defines the set of GPIOs to be used for SECI UART if not specified in NVRAM */
85 /* For further details on each ppin functionality please refer to PINMUX table in
86 * Top level architecture of BCMXXXX Chip
87 */
88 #define DEFAULT_SECI_UART_PINMUX 0x08090a0b
89 #define DEFAULT_SECI_UART_PINMUX_43430 0x0102
90 static bool force_seci_clk = 0;
91 #endif /* SECI_UART */
92
93 #define XTAL_FREQ_26000KHZ 26000
94
95 /**
96 * A set of PMU registers is clocked in the ILP domain, which has an implication on register write
97 * behavior: if such a register is written, it takes multiple ILP clocks for the PMU block to absorb
98 * the write. During that time the 'SlowWritePending' bit in the PMUStatus register is set.
99 */
100 #define PMUREGS_ILP_SENSITIVE(regoff) \
101 ((regoff) == OFFSETOF(pmuregs_t, pmutimer) || \
102 (regoff) == OFFSETOF(pmuregs_t, pmuwatchdog) || \
103 (regoff) == OFFSETOF(pmuregs_t, res_req_timer))
104
105 #define CHIPCREGS_ILP_SENSITIVE(regoff) \
106 ((regoff) == OFFSETOF(chipcregs_t, pmutimer) || \
107 (regoff) == OFFSETOF(chipcregs_t, pmuwatchdog) || \
108 (regoff) == OFFSETOF(chipcregs_t, res_req_timer))
109
110 #define GCI_FEM_CTRL_WAR 0x11111111
111
112 #ifndef AXI_TO_VAL
113 #define AXI_TO_VAL 19
114 #endif /* AXI_TO_VAL */
115
116 #ifndef AXI_TO_VAL_4347
117 /*
118 * Increase BP timeout for fast clock and short PCIe timeouts
119 * New timeout: 2 ** 25 cycles
120 */
121 #define AXI_TO_VAL_4347 25
122 #endif /* AXI_TO_VAL_4347 */
123
124 /* local prototypes */
125 static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs,
126 uint bustype, void *sdh, char **vars, uint *varsz);
127 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
128 static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
129 uint *origidx, volatile void *regs);
130
131 static bool si_pmu_is_ilp_sensitive(uint32 idx, uint regoff);
132
133 /* global variable to indicate reservation/release of gpio's */
134 static uint32 si_gpioreservation = 0;
135
136 /* global flag to prevent shared resources from being initialized multiple times in si_attach() */
137 static bool si_onetimeinit = FALSE;
138
139 #ifdef SR_DEBUG
140 static const uint32 si_power_island_test_array[] = {
141 0x0000, 0x0001, 0x0010, 0x0011,
142 0x0100, 0x0101, 0x0110, 0x0111,
143 0x1000, 0x1001, 0x1010, 0x1011,
144 0x1100, 0x1101, 0x1110, 0x1111
145 };
146 #endif /* SR_DEBUG */
147
148 int do_4360_pcie2_war = 0;
149
150 #ifdef BCMULP
151 /* Variable to store boot_type: warm_boot/cold_boot/etc. */
152 static int boot_type = 0;
153 #endif // endif
154
155 /* global kernel resource */
156 static si_info_t ksii;
157 static si_cores_info_t ksii_cores_info;
158
159 /**
160 * Allocate an si handle. This function may be called multiple times.
161 *
162 * devid - pci device id (used to determine chip#)
163 * osh - opaque OS handle
164 * regs - virtual address of initial core registers
165 * bustype - pci/pcmcia/sb/sdio/etc
166 * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
167 * function set 'vars' to NULL, making dereferencing of this parameter undesired.
168 * varsz - pointer to int to return the size of the vars
169 */
170 si_t *
si_attach(uint devid,osl_t * osh,volatile void * regs,uint bustype,void * sdh,char ** vars,uint * varsz)171 si_attach(uint devid, osl_t *osh, volatile void *regs,
172 uint bustype, void *sdh, char **vars, uint *varsz)
173 {
174 si_info_t *sii;
175 si_cores_info_t *cores_info;
176 /* alloc si_info_t */
177 /* freed after ucode download for firmware builds */
178 if ((sii = MALLOCZ_NOPERSIST(osh, sizeof(si_info_t))) == NULL) {
179 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
180 return (NULL);
181 }
182
183 /* alloc si_cores_info_t */
184 if ((cores_info = (si_cores_info_t *)MALLOCZ(osh,
185 sizeof(si_cores_info_t))) == NULL) {
186 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
187 MFREE(osh, sii, sizeof(si_info_t));
188 return (NULL);
189 }
190 sii->cores_info = cores_info;
191
192 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
193 MFREE(osh, sii, sizeof(si_info_t));
194 MFREE(osh, cores_info, sizeof(si_cores_info_t));
195 return (NULL);
196 }
197 sii->vars = vars ? *vars : NULL;
198 sii->varsz = varsz ? *varsz : 0;
199
200 return (si_t *)sii;
201 }
202
203 static uint32 wd_msticks; /**< watchdog timer ticks normalized to ms */
204
205 /** Returns the backplane address of the chipcommon core for a particular chip */
206 uint32
si_enum_base(uint devid)207 si_enum_base(uint devid)
208 {
209 // NIC/DHD build
210 switch (devid) {
211 case BCM7271_CHIP_ID:
212 case BCM7271_D11AC_ID:
213 case BCM7271_D11AC2G_ID:
214 case BCM7271_D11AC5G_ID:
215 return 0xF1800000;
216 }
217
218 return SI_ENUM_BASE_DEFAULT;
219 }
220
221 /** Returns the backplane address of the PCIE core for a particular chip */
222 uint32
si_pcie_enum_base(uint devid)223 si_pcie_enum_base(uint devid)
224 {
225 switch (devid) {
226 case CYW55560_WLAN_ID:
227 case CYW89570_WLAN_ID:
228 return SI_ENUM_PCIE2_BASE;
229 }
230
231 /* Default - In future chips if devid is not matched */
232 return SI_ENUM_PCIE2_BASE;
233 }
234
235 /** generic kernel variant of si_attach(). Is not called for Linux WLAN NIC builds. */
236 si_t *
si_kattach(osl_t * osh)237 si_kattach(osl_t *osh)
238 {
239 static bool ksii_attached = FALSE;
240 si_cores_info_t *cores_info;
241
242 if (!ksii_attached) {
243 void *regs = NULL;
244 const uint device_id = BCM4710_DEVICE_ID; // pick an arbitrary default device_id
245
246 regs = REG_MAP(si_enum_base(device_id), SI_CORE_SIZE); // map physical to virtual
247 cores_info = (si_cores_info_t *)&ksii_cores_info;
248 ksii.cores_info = cores_info;
249
250 ASSERT(osh);
251 if (si_doattach(&ksii, device_id, osh, regs,
252 SI_BUS, NULL,
253 osh != SI_OSH ? &(ksii.vars) : NULL,
254 osh != SI_OSH ? &(ksii.varsz) : NULL) == NULL) {
255 SI_ERROR(("si_kattach: si_doattach failed\n"));
256 REG_UNMAP(regs);
257 return NULL;
258 }
259 REG_UNMAP(regs);
260
261 /* save ticks normalized to ms for si_watchdog_ms() */
262 if (PMUCTL_ENAB(&ksii.pub)) {
263 /* based on 32KHz ILP clock */
264 wd_msticks = 32;
265 } else {
266 wd_msticks = ALP_CLOCK / 1000;
267 }
268
269 ksii_attached = TRUE;
270 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
271 CCREV(ksii.pub.ccrev), wd_msticks));
272 }
273
274 return &ksii.pub;
275 }
276
277 static bool
si_buscore_prep(si_info_t * sii,uint bustype,uint devid,void * sdh)278 si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
279 {
280 BCM_REFERENCE(sdh);
281 BCM_REFERENCE(devid);
282 /* need to set memseg flag for CF card first before any sb registers access */
283 if (BUSTYPE(bustype) == PCMCIA_BUS)
284 sii->memseg = TRUE;
285
286 #if defined(BCMSDIO) && !defined(BCMSDIOLITE)
287 if (BUSTYPE(bustype) == SDIO_BUS) {
288 int err;
289 uint8 clkset;
290
291 /* Try forcing SDIO core to do ALPAvail request only */
292 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
293 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
294 if (!err) {
295 uint8 clkval;
296
297 /* If register supported, wait for ALPAvail and then force ALP */
298 clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
299 if ((clkval & ~SBSDIO_AVBITS) == clkset) {
300 SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
301 SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)),
302 PMU_MAX_TRANSITION_DLY);
303 if (!SBSDIO_ALPAV(clkval)) {
304 SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n",
305 clkval));
306 return FALSE;
307 }
308 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
309 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
310 clkset, &err);
311 OSL_DELAY(65);
312 }
313 }
314
315 /* Also, disable the extra SDIO pull-ups */
316 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
317 }
318
319 #ifdef BCMSPI
320 /* Avoid backplane accesses before wake-wlan (i.e. htavail) for spi.
321 * F1 read accesses may return correct data but with data-not-available dstatus bit set.
322 */
323 if (BUSTYPE(bustype) == SPI_BUS) {
324
325 int err;
326 uint32 regdata;
327 /* wake up wlan function :WAKE_UP goes as HT_AVAIL request in hardware */
328 regdata = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_CONFIG, NULL);
329 SI_MSG(("F0 REG0 rd = 0x%x\n", regdata));
330 regdata |= WAKE_UP;
331
332 bcmsdh_cfg_write_word(sdh, SDIO_FUNC_0, SPID_CONFIG, regdata, &err);
333
334 OSL_DELAY(100000);
335 }
336 #endif /* BCMSPI */
337 #endif /* BCMSDIO && BCMDONGLEHOST && !BCMSDIOLITE */
338
339 return TRUE;
340 }
341
342 uint32
si_get_pmu_reg_addr(si_t * sih,uint32 offset)343 si_get_pmu_reg_addr(si_t *sih, uint32 offset)
344 {
345 si_info_t *sii = SI_INFO(sih);
346 uint32 pmuaddr = INVALID_ADDR;
347 uint origidx = 0;
348
349 SI_MSG(("%s: pmu access, offset: %x\n", __FUNCTION__, offset));
350 if (!(sii->pub.cccaps & CC_CAP_PMU)) {
351 goto done;
352 }
353 if (AOB_ENAB(&sii->pub)) {
354 uint pmucoreidx;
355 pmuregs_t *pmu;
356 SI_MSG(("%s: AOBENAB: %x\n", __FUNCTION__, offset));
357 origidx = sii->curidx;
358 pmucoreidx = si_findcoreidx(&sii->pub, PMU_CORE_ID, 0);
359 pmu = si_setcoreidx(&sii->pub, pmucoreidx);
360 pmuaddr = (uint32)(uintptr)((volatile uint8*)pmu + offset);
361 si_setcoreidx(sih, origidx);
362 } else
363 pmuaddr = SI_ENUM_BASE(sih) + offset;
364
365 done:
366 printf("%s: addrRET: %x\n", __FUNCTION__, pmuaddr);
367 return pmuaddr;
368 }
369
370 static bool
si_buscore_setup(si_info_t * sii,chipcregs_t * cc,uint bustype,uint32 savewin,uint * origidx,volatile void * regs)371 si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
372 uint *origidx, volatile void *regs)
373 {
374 si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
375 bool pci, pcie, pcie_gen2 = FALSE;
376 uint i;
377 uint pciidx, pcieidx, pcirev, pcierev;
378 struct si_pub *sih = &sii->pub;
379
380 #if defined(BCM_BACKPLANE_TIMEOUT) || defined(AXI_TIMEOUTS)
381 /* first, enable backplane timeouts */
382 si_slave_wrapper_add(&sii->pub);
383 #endif // endif
384 sii->curidx = 0;
385
386 cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
387 ASSERT((uintptr)cc);
388
389 /* get chipcommon rev */
390 sii->pub.ccrev = (int)si_corerev(&sii->pub);
391
392 /* get chipcommon chipstatus */
393 if (CCREV(sii->pub.ccrev) >= 11) {
394 /* TODO : We need a better approach to avoid this access in secure mode chips */
395 if (sii->pub.chip != CYW55500_CHIP_ID &&
396 sii->pub.chip != CYW55560_CHIP_ID) {
397 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
398 }
399 }
400
401 if (!sih->chipidpresent) {
402 /* get chipcommon capabilites */
403 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
404 /* get chipcommon extended capabilities */
405 if (CCREV(sii->pub.ccrev) >= 35)
406 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
407
408 /* get pmu rev and caps */
409 if (sii->pub.cccaps & CC_CAP_PMU) {
410 if (AOB_ENAB(&sii->pub)) {
411 uint pmucoreidx;
412 pmuregs_t *pmu;
413 struct si_pub *sih = &sii->pub;
414
415 pmucoreidx = si_findcoreidx(&sii->pub, PMU_CORE_ID, 0);
416 if (!GOODIDX(pmucoreidx)) {
417 SI_ERROR(("si_buscore_setup: si_findcoreidx failed\n"));
418 return FALSE;
419 }
420
421 pmu = si_setcoreidx(&sii->pub, pmucoreidx);
422 sii->pub.pmucaps = R_REG(sii->osh, &pmu->pmucapabilities);
423 si_setcoreidx(&sii->pub, SI_CC_IDX);
424
425 sii->pub.gcirev = si_corereg(sih, GCI_CORE_IDX(sih),
426 GCI_OFFSETOF(sih, gci_corecaps0), 0, 0) &
427 GCI_CAP0_REV_MASK;
428 } else
429 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
430
431 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
432 }
433 }
434
435 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
436 CCREV(sii->pub.ccrev), sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
437 sii->pub.pmucaps));
438
439 /* figure out bus/orignal core idx */
440 sii->pub.buscoretype = NODEV_CORE_ID;
441 sii->pub.buscorerev = (uint)NOREV;
442 sii->pub.buscoreidx = BADIDX;
443
444 pci = pcie = FALSE;
445 pcirev = pcierev = (uint)NOREV;
446 pciidx = pcieidx = BADIDX;
447
448 for (i = 0; i < sii->numcores; i++) {
449 uint cid, crev;
450
451 si_setcoreidx(&sii->pub, i);
452 cid = si_coreid(&sii->pub);
453 crev = si_corerev(&sii->pub);
454
455 /* Display cores found */
456 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x size:%x regs 0x%p\n",
457 i, cid, crev, sii->coresba[i], sii->coresba_size[i],
458 OSL_OBFUSCATE_BUF(sii->regs[i])));
459
460 if (BUSTYPE(bustype) == SI_BUS) {
461 /* now look at the chipstatus register to figure the pacakge */
462 /* for SDIO but downloaded on PCIE dev */
463 #ifdef BCMPCIEDEV_ENABLED
464 if (cid == PCIE2_CORE_ID) {
465 pcieidx = i;
466 pcierev = crev;
467 pcie = TRUE;
468 pcie_gen2 = TRUE;
469 }
470 #endif // endif
471
472 } else if (BUSTYPE(bustype) == PCI_BUS) {
473 if (cid == PCI_CORE_ID) {
474 pciidx = i;
475 pcirev = crev;
476 pci = TRUE;
477 } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) {
478 pcieidx = i;
479 pcierev = crev;
480 pcie = TRUE;
481 if (cid == PCIE2_CORE_ID)
482 pcie_gen2 = TRUE;
483 }
484 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
485 (cid == PCMCIA_CORE_ID)) {
486 sii->pub.buscorerev = crev;
487 sii->pub.buscoretype = cid;
488 sii->pub.buscoreidx = i;
489 }
490 #ifdef BCMSDIO
491 else if (((BUSTYPE(bustype) == SDIO_BUS) ||
492 (BUSTYPE(bustype) == SPI_BUS)) &&
493 ((cid == PCMCIA_CORE_ID) ||
494 (cid == SDIOD_CORE_ID))) {
495 sii->pub.buscorerev = crev;
496 sii->pub.buscoretype = cid;
497 sii->pub.buscoreidx = i;
498 }
499 #endif /* BCMSDIO */
500
501 /* find the core idx before entering this func. */
502 if ((savewin && (savewin == cores_info->coresba[i])) ||
503 (regs == cores_info->regs[i]))
504 *origidx = i;
505 }
506
507 #if defined(PCIE_FULL_DONGLE)
508 if (pcie) {
509 if (pcie_gen2)
510 sii->pub.buscoretype = PCIE2_CORE_ID;
511 else
512 sii->pub.buscoretype = PCIE_CORE_ID;
513 sii->pub.buscorerev = pcierev;
514 sii->pub.buscoreidx = pcieidx;
515 }
516 BCM_REFERENCE(pci);
517 BCM_REFERENCE(pcirev);
518 BCM_REFERENCE(pciidx);
519 #else
520 if (pci) {
521 sii->pub.buscoretype = PCI_CORE_ID;
522 sii->pub.buscorerev = pcirev;
523 sii->pub.buscoreidx = pciidx;
524 } else if (pcie) {
525 if (pcie_gen2)
526 sii->pub.buscoretype = PCIE2_CORE_ID;
527 else
528 sii->pub.buscoretype = PCIE_CORE_ID;
529 sii->pub.buscorerev = pcierev;
530 sii->pub.buscoreidx = pcieidx;
531 }
532 #endif /* defined(PCIE_FULL_DONGLE) */
533
534 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
535 sii->pub.buscorerev));
536
537 #if defined(BCMSDIO)
538 /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was
539 * already running.
540 */
541 if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
542 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
543 si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
544 si_core_disable(&sii->pub, 0);
545 }
546 #endif /* BCMSDIO && BCMDONGLEHOST */
547
548 /* return to the original core */
549 si_setcoreidx(&sii->pub, *origidx);
550
551 return TRUE;
552 }
553
554 uint16
si_chipid(si_t * sih)555 si_chipid(si_t *sih)
556 {
557 si_info_t *sii = SI_INFO(sih);
558
559 return (sii->chipnew) ? sii->chipnew : sih->chip;
560 }
561
562 /* CHIP_ID's being mapped here should not be used anywhere else in the code */
563 static void
si_chipid_fixup(si_t * sih)564 si_chipid_fixup(si_t *sih)
565 {
566 si_info_t *sii = SI_INFO(sih);
567
568 ASSERT(sii->chipnew == 0);
569 switch (sih->chip) {
570 case BCM43567_CHIP_ID:
571 sii->chipnew = sih->chip; /* save it */
572 sii->pub.chip = BCM43570_CHIP_ID; /* chip class */
573 break;
574 case BCM43562_CHIP_ID:
575 case BCM4358_CHIP_ID:
576 case BCM43566_CHIP_ID:
577 sii->chipnew = sih->chip; /* save it */
578 sii->pub.chip = BCM43569_CHIP_ID; /* chip class */
579 break;
580 case BCM4356_CHIP_ID:
581 case BCM4371_CHIP_ID:
582 sii->chipnew = sih->chip; /* save it */
583 sii->pub.chip = BCM4354_CHIP_ID; /* chip class */
584 break;
585 case BCM4357_CHIP_ID:
586 case BCM4361_CHIP_ID:
587 sii->chipnew = sih->chip; /* save it */
588 sii->pub.chip = BCM4347_CHIP_ID; /* chip class */
589 break;
590 #ifdef CHIPS_CUSTOMER_HW6
591 case BCM4377_CHIP_ID:
592 sii->chipnew = sih->chip; /* save it */
593 sii->pub.chip = BCM4369_CHIP_ID; /* chip class */
594 break;
595 #endif /* CHIPS_CUSTOMER_HW6 */
596 default:
597 break;
598 }
599 }
600
601 #ifdef BCMULP
602 static void
si_check_boot_type(si_t * sih,osl_t * osh)603 si_check_boot_type(si_t *sih, osl_t *osh)
604 {
605 if (sih->pmurev >= 30) {
606 boot_type = PMU_REG_NEW(sih, swscratch, 0, 0);
607 } else {
608 boot_type = CHIPC_REG(sih, flashdata, 0, 0);
609 }
610
611 SI_ERROR(("%s: boot_type: 0x%08x\n", __func__, boot_type));
612 }
613 #endif /* BCMULP */
614
615 #ifdef BCM_BACKPLANE_TIMEOUT
616 uint32
si_clear_backplane_to_fast(void * sih,void * addr)617 si_clear_backplane_to_fast(void *sih, void *addr)
618 {
619 si_t *_sih = DISCARD_QUAL(sih, si_t);
620
621 if (CHIPTYPE(_sih->socitype) == SOCI_AI) {
622 return ai_clear_backplane_to_fast(_sih, addr);
623 }
624
625 return 0;
626 }
627
628 const si_axi_error_info_t *
si_get_axi_errlog_info(si_t * sih)629 si_get_axi_errlog_info(si_t *sih)
630 {
631 if (CHIPTYPE(sih->socitype) == SOCI_AI) {
632 return (const si_axi_error_info_t *)sih->err_info;
633 }
634
635 return NULL;
636 }
637
638 void
si_reset_axi_errlog_info(si_t * sih)639 si_reset_axi_errlog_info(si_t *sih)
640 {
641 if (sih->err_info) {
642 sih->err_info->count = 0;
643 }
644 }
645 #endif /* BCM_BACKPLANE_TIMEOUT */
646
647 #ifdef BCMSDIO
648 void *
si_get_sdio_addrbase(void * sdh)649 si_get_sdio_addrbase(void *sdh)
650 {
651 uint8 devctl;
652 int err = 0;
653 uint32 addr = 0;
654
655 devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
656 if (err)
657 return NULL;
658
659 bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
660 SBSDIO_DEVICE_CTL, devctl | SBSDIO_DEVCTL_ADDR_RESET, &err);
661 if (err)
662 goto exit;
663
664 addr |= (bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, NULL) << 8) |
665 (bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, NULL) << 16) |
666 (bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, NULL) << 24);
667
668 SI_MSG(("%s: sdiod core address is 0x%x\n", __FUNCTION__, addr));
669 exit:
670 if (err) {
671 SI_ERROR(("%s: Get SDIO core base address failed, err=%d", __FUNCTION__, err));
672 addr = 0;
673 }
674 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
675
676 return (void *)((uintptr)addr);
677 }
678 #endif /* BCMSDIO */
679
680 /**
681 * Allocate an si handle. This function may be called multiple times. This function is called by
682 * both si_attach() and si_kattach().
683 *
684 * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
685 * function set 'vars' to NULL.
686 */
687 static si_info_t *
si_doattach(si_info_t * sii,uint devid,osl_t * osh,volatile void * regs,uint bustype,void * sdh,char ** vars,uint * varsz)688 si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs,
689 uint bustype, void *sdh, char **vars, uint *varsz)
690 {
691 struct si_pub *sih = &sii->pub;
692 uint32 w = 0;
693 uint32 savewin;
694 chipcregs_t *cc;
695 char *pvars = NULL;
696 uint origidx;
697 #ifdef NVSRCX
698 char *sromvars;
699 #endif // endif
700 uint32 erombase;
701 #ifdef BCMSDIO
702 uint8 cardcap;
703 sdpcmd_regs_t *sdioc;
704 #endif // endif
705
706 ASSERT(GOODREGS(regs));
707
708 savewin = 0;
709
710 sih->buscoreidx = BADIDX;
711 sii->device_removed = FALSE;
712
713 sii->curmap = regs;
714 sii->sdh = sdh;
715 sii->osh = osh;
716 sii->second_bar0win = ~0x0;
717 sih->enum_base = si_enum_base(devid);
718
719 #if defined(BCM_BACKPLANE_TIMEOUT)
720 sih->err_info = MALLOCZ(osh, sizeof(si_axi_error_info_t));
721 if (sih->err_info == NULL) {
722 SI_ERROR(("%s: %zu bytes MALLOC FAILED",
723 __FUNCTION__, sizeof(si_axi_error_info_t)));
724 }
725 #endif /* BCM_BACKPLANE_TIMEOUT */
726
727 #if defined(BCM_BACKPLANE_TIMEOUT)
728 osl_set_bpt_cb(osh, (void *)si_clear_backplane_to_fast, (void *)sih);
729 #endif // endif
730
731 /* check to see if we are a si core mimic'ing a pci core */
732 if ((bustype == PCI_BUS) &&
733 (OSL_PCI_READ_CONFIG(sii->osh, PCI_SPROM_CONTROL, sizeof(uint32)) == 0xffffffff)) {
734 SI_ERROR(("%s: incoming bus is PCI but it's a lie, switching to SI "
735 "devid:0x%x\n", __FUNCTION__, devid));
736 bustype = SI_BUS;
737 }
738
739 /* find Chipcommon address */
740 if (bustype == PCI_BUS) {
741 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
742 if (!GOODCOREADDR(savewin, SI_ENUM_BASE(sih)))
743 savewin = SI_ENUM_BASE(sih);
744 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE(sih));
745 if (!regs)
746 return NULL;
747 cc = (chipcregs_t *)regs;
748 erombase = R_REG(osh, &cc->eromptr);
749 #ifdef BCMSDIO
750 } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) {
751 cc = (chipcregs_t *)sii->curmap;
752 cardcap = bcmsdh_cfg_read(sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, NULL);
753 if (cardcap & SDIOD_CCCR_BRCM_CARDCAP_CHIPID_PRESENT) {
754 sih->chipidpresent = TRUE;
755 sdioc = si_get_sdio_addrbase(sdh);
756 w = R_REG(osh, &sdioc->chipid);
757 erombase = R_REG(osh, &sdioc->eromptr);
758 } else {
759 erombase = R_REG(osh, &cc->eromptr);
760 }
761 if (cardcap & SDIOD_CCCR_BRCM_CARDCAP_SECURE_MODE) {
762 sih->secureboot = TRUE;
763 }
764 #endif // endif
765 } else {
766 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE(sih), SI_CORE_SIZE);
767 erombase = R_REG(osh, &cc->eromptr);
768 }
769
770 sih->bustype = bustype;
771 #ifdef BCMBUSTYPE
772 if (bustype != BUSTYPE(bustype)) {
773 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
774 bustype, BUSTYPE(bustype)));
775 return NULL;
776 }
777 #endif // endif
778
779 /* bus/core/clk setup for register access */
780 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
781 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
782 return NULL;
783 }
784
785 /* ChipID recognition.
786 * We assume we can read chipid at offset 0 from the regs arg.
787 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
788 * some way of recognizing them needs to be added here.
789 */
790 if (!cc) {
791 SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__));
792 return NULL;
793 }
794 if (!w)
795 w = R_REG(osh, &cc->chipid);
796 if ((w & 0xfffff) == 148277) w -= 65532;
797 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
798 /* Might as wll fill in chip id rev & pkg */
799 sih->chip = w & CID_ID_MASK;
800 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
801 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
802
803 si_chipid_fixup(sih);
804
805 if (CHIPID(sih->chip) == BCM43465_CHIP_ID) {
806 sih->chip = BCM4366_CHIP_ID;
807 } else if (CHIPID(sih->chip) == BCM43525_CHIP_ID) {
808 sih->chip = BCM4365_CHIP_ID;
809 }
810
811 sih->issim = IS_SIM(sih->chippkg);
812
813 #ifdef CHIPS_CUSTOMER_HW6
814 if (MULTIBP_CAP(sih))
815 {
816 sih->_multibp_enable = TRUE;
817 }
818 #endif // endif
819
820 /* scan for cores */
821 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
822 SI_MSG(("Found chip type SB (0x%08x)\n", w));
823 sb_scan(&sii->pub, regs, devid);
824 } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) ||
825 (CHIPTYPE(sii->pub.socitype) == SOCI_NAI) ||
826 (CHIPTYPE(sii->pub.socitype) == SOCI_DVTBUS)) {
827
828 if (CHIPTYPE(sii->pub.socitype) == SOCI_AI)
829 SI_MSG(("Found chip type AI (0x%08x)\n", w));
830 else if (CHIPTYPE(sii->pub.socitype) == SOCI_NAI)
831 SI_MSG(("Found chip type NAI (0x%08x)\n", w));
832 else
833 SI_MSG(("Found chip type DVT (0x%08x)\n", w));
834 /* pass chipc address instead of original core base */
835
836 if (sii->osh) {
837 sii->axi_wrapper = (axi_wrapper_t *)MALLOCZ(sii->osh,
838 (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS));
839
840 if (sii->axi_wrapper == NULL) {
841 SI_ERROR(("%s: %zu bytes MALLOC Failed", __FUNCTION__,
842 (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS)));
843 }
844 } else {
845 sii->axi_wrapper = NULL;
846 }
847
848 ai_scan(&sii->pub, (void *)(uintptr)cc, erombase, devid);
849 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
850 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
851 /* pass chipc address instead of original core base */
852 ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
853 } else {
854 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
855 return NULL;
856 }
857 /* no cores found, bail out */
858 if (sii->numcores == 0) {
859 SI_ERROR(("si_doattach: could not find any cores\n"));
860 return NULL;
861 }
862 /* bus/core/clk setup */
863 origidx = SI_CC_IDX;
864 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
865 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
866 goto exit;
867 }
868 #ifdef BCMULP
869 if (BCMULP_ENAB()) {
870 si_check_boot_type(sih, osh);
871 if (ulp_module_init(osh, sih) != BCME_OK) {
872 ULP_ERR(("%s: err in ulp_module_init\n", __FUNCTION__));
873 goto exit;
874 }
875 }
876 #endif /* BCMULP */
877
878 #if !defined(_CFEZ_) || defined(CFG_WL)
879 /* assume current core is CC */
880 if ((CCREV(sii->pub.ccrev) == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
881 CHIPID(sih->chip) == BCM43235_CHIP_ID ||
882 CHIPID(sih->chip) == BCM43234_CHIP_ID ||
883 CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
884 (CHIPREV(sii->pub.chiprev) <= 2))) {
885
886 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
887 uint clkdiv;
888 clkdiv = R_REG(osh, &cc->clkdiv);
889 /* otp_clk_div is even number, 120/14 < 9mhz */
890 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
891 W_REG(osh, &cc->clkdiv, clkdiv);
892 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
893 }
894 OSL_DELAY(10);
895 }
896
897 /* Set the clkdiv2 divisor bits (2:0) to 0x4 if srom is present */
898 if (bustype == SI_BUS) {
899 uint32 clkdiv2, sromprsnt, capabilities, srom_supported;
900 capabilities = R_REG(osh, &cc->capabilities);
901 srom_supported = capabilities & SROM_SUPPORTED;
902 if (srom_supported)
903 {
904 sromprsnt = R_REG(osh, &cc->sromcontrol);
905 sromprsnt = sromprsnt & SROM_PRSNT_MASK;
906 if (sromprsnt) {
907 /* SROM clock come from backplane clock/div2. Must <= 1Mhz */
908 clkdiv2 = (R_REG(osh, &cc->clkdiv2) & ~CLKD2_SROM);
909 clkdiv2 |= CLKD2_SROMDIV_192;
910 W_REG(osh, &cc->clkdiv2, clkdiv2);
911 }
912 }
913 }
914
915 if (bustype == PCI_BUS) {
916
917 #ifdef BCMQT
918 /* Set OTPClkDiv to smaller value otherwise OTP always reads 0xFFFF.
919 * For real-chip we shouldn't set OTPClkDiv to 2 because 20/2 = 10 > 9Mhz
920 */
921 {
922 uint otpclkdiv = 0;
923
924 if ((CHIPID(sih->chip) == BCM43131_CHIP_ID) ||
925 (CHIPID(sih->chip) == BCM43217_CHIP_ID)) {
926 otpclkdiv = 4;
927 }
928
929 if (otpclkdiv != 0) {
930 uint clkdiv, savecore;
931 savecore = si_coreidx(sih);
932 si_setcore(sih, CC_CORE_ID, 0);
933
934 clkdiv = R_REG(osh, &cc->clkdiv);
935 clkdiv = (clkdiv & ~CLKD_OTP) | (otpclkdiv << CLKD_OTP_SHIFT);
936 W_REG(osh, &cc->clkdiv, clkdiv);
937
938 SI_ERROR(("%s: set clkdiv to 0x%x for QT\n", __FUNCTION__, clkdiv));
939 si_setcoreidx(sih, savecore);
940 }
941 }
942 #endif /* BCMQT */
943 }
944 #endif // endif
945 #ifdef BCM_SDRBL
946 /* 4360 rom bootloader in PCIE case, if the SDR is enabled, But preotection is
947 * not turned on, then we want to hold arm in reset.
948 * Bottomline: In sdrenable case, we allow arm to boot only when protection is
949 * turned on.
950 */
951 if (CHIP_HOSTIF_PCIE(&(sii->pub))) {
952 uint32 sflags = si_arm_sflags(&(sii->pub));
953
954 /* If SDR is enabled but protection is not turned on
955 * then we want to force arm to WFI.
956 */
957 if ((sflags & (SISF_SDRENABLE | SISF_TCMPROT)) == SISF_SDRENABLE) {
958 disable_arm_irq();
959 while (1) {
960 hnd_cpu_wait(sih);
961 }
962 }
963 }
964 #endif /* BCM_SDRBL */
965
966 pvars = NULL;
967 BCM_REFERENCE(pvars);
968
969 {
970 sii->lhl_ps_mode = LHL_PS_MODE_0;
971 }
972
973 if (!si_onetimeinit) {
974
975 if (CCREV(sii->pub.ccrev) >= 20) {
976 uint32 gpiopullup = 0, gpiopulldown = 0;
977 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
978 ASSERT(cc != NULL);
979 BCM_REFERENCE(gpiopullup);
980 BCM_REFERENCE(gpiopulldown);
981 si_setcoreidx(sih, origidx);
982 }
983
984 }
985
986 /* clear any previous epidiag-induced target abort */
987 ASSERT(!si_taclear(sih, FALSE));
988
989 #if defined(BCMPMU_STATS) && !defined(BCMPMU_STATS_DISABLED)
990 si_pmustatstimer_init(sih);
991 #endif /* BCMPMU_STATS */
992
993 #ifdef BOOTLOADER_CONSOLE_OUTPUT
994 /* Enable console prints */
995 si_muxenab(sii, 3);
996 #endif // endif
997
998 return (sii);
999
1000 exit:
1001
1002 return NULL;
1003 }
1004
1005 /** may be called with core in reset */
1006 void
si_detach(si_t * sih)1007 si_detach(si_t *sih)
1008 {
1009 si_info_t *sii = SI_INFO(sih);
1010 si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
1011 uint idx;
1012
1013 if (BUSTYPE(sih->bustype) == SI_BUS)
1014 for (idx = 0; idx < SI_MAXCORES; idx++)
1015 if (cores_info->regs[idx]) {
1016 REG_UNMAP(cores_info->regs[idx]);
1017 cores_info->regs[idx] = NULL;
1018 }
1019
1020 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
1021 if (cores_info != &ksii_cores_info)
1022 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
1023 MFREE(sii->osh, cores_info, sizeof(si_cores_info_t));
1024
1025 #if defined(BCM_BACKPLANE_TIMEOUT)
1026 if (sih->err_info) {
1027 MFREE(sii->osh, sih->err_info, sizeof(si_axi_error_info_t));
1028 sii->pub.err_info = NULL;
1029 }
1030 #endif /* BCM_BACKPLANE_TIMEOUT */
1031
1032 if (sii->axi_wrapper) {
1033 MFREE(sii->osh, sii->axi_wrapper,
1034 (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS));
1035 sii->axi_wrapper = NULL;
1036 }
1037
1038 #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
1039 if (sii != &ksii)
1040 #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
1041 MFREE(sii->osh, sii, sizeof(si_info_t));
1042 }
1043
1044 void *
si_osh(si_t * sih)1045 si_osh(si_t *sih)
1046 {
1047 si_info_t *sii;
1048
1049 sii = SI_INFO(sih);
1050 return sii->osh;
1051 }
1052
1053 void
si_setosh(si_t * sih,osl_t * osh)1054 si_setosh(si_t *sih, osl_t *osh)
1055 {
1056 si_info_t *sii;
1057
1058 sii = SI_INFO(sih);
1059 if (sii->osh != NULL) {
1060 SI_ERROR(("osh is already set....\n"));
1061 ASSERT(!sii->osh);
1062 }
1063 sii->osh = osh;
1064 }
1065
1066 /** register driver interrupt disabling and restoring callback functions */
1067 void
si_register_intr_callback(si_t * sih,void * intrsoff_fn,void * intrsrestore_fn,void * intrsenabled_fn,void * intr_arg)1068 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
1069 void *intrsenabled_fn, void *intr_arg)
1070 {
1071 si_info_t *sii = SI_INFO(sih);
1072 si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
1073 sii->intr_arg = intr_arg;
1074 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
1075 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
1076 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
1077 /* save current core id. when this function called, the current core
1078 * must be the core which provides driver functions(il, et, wl, etc.)
1079 */
1080 sii->dev_coreid = cores_info->coreid[sii->curidx];
1081 }
1082
1083 void
si_deregister_intr_callback(si_t * sih)1084 si_deregister_intr_callback(si_t *sih)
1085 {
1086 si_info_t *sii;
1087
1088 sii = SI_INFO(sih);
1089 sii->intrsoff_fn = NULL;
1090 sii->intrsrestore_fn = NULL;
1091 sii->intrsenabled_fn = NULL;
1092 }
1093
1094 uint
si_intflag(si_t * sih)1095 si_intflag(si_t *sih)
1096 {
1097 si_info_t *sii = SI_INFO(sih);
1098
1099 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1100 return sb_intflag(sih);
1101 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1102 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1103 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1104 return R_REG(sii->osh, ((uint32 *)(uintptr)
1105 (sii->oob_router + OOB_STATUSA)));
1106 else {
1107 ASSERT(0);
1108 return 0;
1109 }
1110 }
1111
1112 uint
si_flag(si_t * sih)1113 si_flag(si_t *sih)
1114 {
1115 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1116 return sb_flag(sih);
1117 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1118 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1119 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1120 return ai_flag(sih);
1121 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1122 return ub_flag(sih);
1123 else {
1124 ASSERT(0);
1125 return 0;
1126 }
1127 }
1128
1129 uint
si_flag_alt(si_t * sih)1130 si_flag_alt(si_t *sih)
1131 {
1132 if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1133 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1134 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1135 return ai_flag_alt(sih);
1136 else {
1137 ASSERT(0);
1138 return 0;
1139 }
1140 }
1141
1142 void
si_setint(si_t * sih,int siflag)1143 si_setint(si_t *sih, int siflag)
1144 {
1145 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1146 sb_setint(sih, siflag);
1147 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1148 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1149 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1150 ai_setint(sih, siflag);
1151 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1152 ub_setint(sih, siflag);
1153 else
1154 ASSERT(0);
1155 }
1156
1157 uint32
si_oobr_baseaddr(si_t * sih,bool second)1158 si_oobr_baseaddr(si_t *sih, bool second)
1159 {
1160 si_info_t *sii = SI_INFO(sih);
1161
1162 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1163 return 0;
1164 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1165 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1166 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1167 return (second ? sii->oob_router1 : sii->oob_router);
1168 else {
1169 ASSERT(0);
1170 return 0;
1171 }
1172 }
1173
1174 uint
si_coreid(si_t * sih)1175 si_coreid(si_t *sih)
1176 {
1177 si_info_t *sii = SI_INFO(sih);
1178 si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
1179
1180 return cores_info->coreid[sii->curidx];
1181 }
1182
1183 uint
si_coreidx(si_t * sih)1184 si_coreidx(si_t *sih)
1185 {
1186 si_info_t *sii;
1187
1188 sii = SI_INFO(sih);
1189 return sii->curidx;
1190 }
1191
1192 volatile void *
si_d11_switch_addrbase(si_t * sih,uint coreunit)1193 si_d11_switch_addrbase(si_t *sih, uint coreunit)
1194 {
1195 return si_setcore(sih, D11_CORE_ID, coreunit);
1196 }
1197
1198 /** return the core-type instantiation # of the current core */
1199 uint
si_coreunit(si_t * sih)1200 si_coreunit(si_t *sih)
1201 {
1202 si_info_t *sii = SI_INFO(sih);
1203 si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
1204 uint idx;
1205 uint coreid;
1206 uint coreunit;
1207 uint i;
1208
1209 coreunit = 0;
1210
1211 idx = sii->curidx;
1212
1213 ASSERT(GOODREGS(sii->curmap));
1214 coreid = si_coreid(sih);
1215
1216 /* count the cores of our type */
1217 for (i = 0; i < idx; i++)
1218 if (cores_info->coreid[i] == coreid)
1219 coreunit++;
1220
1221 return (coreunit);
1222 }
1223
1224 uint
si_corevendor(si_t * sih)1225 si_corevendor(si_t *sih)
1226 {
1227 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1228 return sb_corevendor(sih);
1229 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1230 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1231 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1232 return ai_corevendor(sih);
1233 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1234 return ub_corevendor(sih);
1235 else {
1236 ASSERT(0);
1237 return 0;
1238 }
1239 }
1240
1241 bool
si_backplane64(si_t * sih)1242 si_backplane64(si_t *sih)
1243 {
1244 return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
1245 }
1246
1247 uint
si_corerev(si_t * sih)1248 si_corerev(si_t *sih)
1249 {
1250 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1251 return sb_corerev(sih);
1252 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1253 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1254 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1255 return ai_corerev(sih);
1256 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1257 return ub_corerev(sih);
1258 else {
1259 ASSERT(0);
1260 return 0;
1261 }
1262 }
1263
1264 uint
si_corerev_minor(si_t * sih)1265 si_corerev_minor(si_t *sih)
1266 {
1267 if (CHIPTYPE(sih->socitype) == SOCI_AI) {
1268 return ai_corerev_minor(sih);
1269 } else {
1270 return 0;
1271 }
1272 }
1273
1274 /* return index of coreid or BADIDX if not found */
1275 uint
si_findcoreidx(si_t * sih,uint coreid,uint coreunit)1276 si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
1277 {
1278 si_info_t *sii = SI_INFO(sih);
1279 si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
1280 uint found;
1281 uint i;
1282
1283 found = 0;
1284
1285 for (i = 0; i < sii->numcores; i++)
1286 if (cores_info->coreid[i] == coreid) {
1287 if (found == coreunit)
1288 return (i);
1289 found++;
1290 }
1291
1292 return (BADIDX);
1293 }
1294
1295 /** return total coreunit of coreid or zero if not found */
1296 uint
si_numcoreunits(si_t * sih,uint coreid)1297 si_numcoreunits(si_t *sih, uint coreid)
1298 {
1299 si_info_t *sii = SI_INFO(sih);
1300 si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
1301 uint found = 0;
1302 uint i;
1303
1304 for (i = 0; i < sii->numcores; i++) {
1305 if (cores_info->coreid[i] == coreid) {
1306 found++;
1307 }
1308 }
1309
1310 return found;
1311 }
1312
1313 /** return total D11 coreunits */
1314 uint
BCMRAMFN(si_numd11coreunits)1315 BCMRAMFN(si_numd11coreunits)(si_t *sih)
1316 {
1317 uint found = 0;
1318
1319 found = si_numcoreunits(sih, D11_CORE_ID);
1320
1321 #if defined(WLRSDB) && defined(WLRSDB_DISABLED)
1322 /* If RSDB functionality is compiled out,
1323 * then ignore any D11 cores beyond the first
1324 * Used in norsdb dongle build variants for rsdb chip.
1325 */
1326 found = 1;
1327 #endif /* defined(WLRSDB) && !defined(WLRSDB_DISABLED) */
1328
1329 return found;
1330 }
1331
1332 /** return list of found cores */
1333 uint
si_corelist(si_t * sih,uint coreid[])1334 si_corelist(si_t *sih, uint coreid[])
1335 {
1336 si_info_t *sii = SI_INFO(sih);
1337 si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
1338
1339 bcopy((uchar*)cores_info->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
1340 return (sii->numcores);
1341 }
1342
1343 /** return current wrapper mapping */
1344 void *
si_wrapperregs(si_t * sih)1345 si_wrapperregs(si_t *sih)
1346 {
1347 si_info_t *sii;
1348
1349 sii = SI_INFO(sih);
1350 ASSERT(GOODREGS(sii->curwrap));
1351
1352 return (sii->curwrap);
1353 }
1354
1355 /** return current register mapping */
1356 volatile void *
si_coreregs(si_t * sih)1357 si_coreregs(si_t *sih)
1358 {
1359 si_info_t *sii;
1360
1361 sii = SI_INFO(sih);
1362 ASSERT(GOODREGS(sii->curmap));
1363
1364 return (sii->curmap);
1365 }
1366
1367 /**
1368 * This function changes logical "focus" to the indicated core;
1369 * must be called with interrupts off.
1370 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
1371 */
1372 volatile void *
si_setcore(si_t * sih,uint coreid,uint coreunit)1373 si_setcore(si_t *sih, uint coreid, uint coreunit)
1374 {
1375 uint idx;
1376
1377 idx = si_findcoreidx(sih, coreid, coreunit);
1378 if (!GOODIDX(idx))
1379 return (NULL);
1380
1381 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1382 return sb_setcoreidx(sih, idx);
1383 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1384 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1385 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1386 return ai_setcoreidx(sih, idx);
1387 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1388 return ub_setcoreidx(sih, idx);
1389 else {
1390 ASSERT(0);
1391 return NULL;
1392 }
1393 }
1394
1395 volatile void *
si_setcoreidx(si_t * sih,uint coreidx)1396 si_setcoreidx(si_t *sih, uint coreidx)
1397 {
1398 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1399 return sb_setcoreidx(sih, coreidx);
1400 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1401 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1402 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1403 return ai_setcoreidx(sih, coreidx);
1404 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1405 return ub_setcoreidx(sih, coreidx);
1406 else {
1407 ASSERT(0);
1408 return NULL;
1409 }
1410 }
1411
1412 /** Turn off interrupt as required by sb_setcore, before switch core */
1413 volatile void *
si_switch_core(si_t * sih,uint coreid,uint * origidx,uint * intr_val)1414 si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
1415 {
1416 volatile void *cc;
1417 si_info_t *sii = SI_INFO(sih);
1418
1419 if (SI_FAST(sii)) {
1420 /* Overloading the origidx variable to remember the coreid,
1421 * this works because the core ids cannot be confused with
1422 * core indices.
1423 */
1424 *origidx = coreid;
1425 if (coreid == CC_CORE_ID)
1426 return (volatile void *)CCREGS_FAST(sii);
1427 else if (coreid == BUSCORETYPE(sih->buscoretype))
1428 return (volatile void *)PCIEREGS(sii);
1429 }
1430 INTR_OFF(sii, *intr_val);
1431 *origidx = sii->curidx;
1432 cc = si_setcore(sih, coreid, 0);
1433 ASSERT(cc != NULL);
1434
1435 return cc;
1436 }
1437
1438 /* restore coreidx and restore interrupt */
1439 void
si_restore_core(si_t * sih,uint coreid,uint intr_val)1440 si_restore_core(si_t *sih, uint coreid, uint intr_val)
1441 {
1442 si_info_t *sii = SI_INFO(sih);
1443
1444 if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == BUSCORETYPE(sih->buscoretype))))
1445 return;
1446
1447 si_setcoreidx(sih, coreid);
1448 INTR_RESTORE(sii, intr_val);
1449 }
1450
1451 int
si_numaddrspaces(si_t * sih)1452 si_numaddrspaces(si_t *sih)
1453 {
1454 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1455 return sb_numaddrspaces(sih);
1456 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1457 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1458 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1459 return ai_numaddrspaces(sih);
1460 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1461 return ub_numaddrspaces(sih);
1462 else {
1463 ASSERT(0);
1464 return 0;
1465 }
1466 }
1467
1468 /* Return the address of the nth address space in the current core
1469 * Arguments:
1470 * sih : Pointer to struct si_t
1471 * spidx : slave port index
1472 * baidx : base address index
1473 */
1474
1475 uint32
si_addrspace(si_t * sih,uint spidx,uint baidx)1476 si_addrspace(si_t *sih, uint spidx, uint baidx)
1477 {
1478 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1479 return sb_addrspace(sih, baidx);
1480 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1481 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1482 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1483 return ai_addrspace(sih, spidx, baidx);
1484 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1485 return ub_addrspace(sih, baidx);
1486 else {
1487 ASSERT(0);
1488 return 0;
1489 }
1490 }
1491
1492 /* Return the size of the nth address space in the current core
1493 * Arguments:
1494 * sih : Pointer to struct si_t
1495 * spidx : slave port index
1496 * baidx : base address index
1497 */
1498 uint32
si_addrspacesize(si_t * sih,uint spidx,uint baidx)1499 si_addrspacesize(si_t *sih, uint spidx, uint baidx)
1500 {
1501 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1502 return sb_addrspacesize(sih, baidx);
1503 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1504 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1505 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1506 return ai_addrspacesize(sih, spidx, baidx);
1507 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1508 return ub_addrspacesize(sih, baidx);
1509 else {
1510 ASSERT(0);
1511 return 0;
1512 }
1513 }
1514
1515 void
si_coreaddrspaceX(si_t * sih,uint asidx,uint32 * addr,uint32 * size)1516 si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
1517 {
1518 /* Only supported for SOCI_AI */
1519 if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1520 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1521 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1522 ai_coreaddrspaceX(sih, asidx, addr, size);
1523 else
1524 *size = 0;
1525 }
1526
1527 uint32
si_core_cflags(si_t * sih,uint32 mask,uint32 val)1528 si_core_cflags(si_t *sih, uint32 mask, uint32 val)
1529 {
1530 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1531 return sb_core_cflags(sih, mask, val);
1532 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1533 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1534 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1535 return ai_core_cflags(sih, mask, val);
1536 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1537 return ub_core_cflags(sih, mask, val);
1538 else {
1539 ASSERT(0);
1540 return 0;
1541 }
1542 }
1543
1544 void
si_core_cflags_wo(si_t * sih,uint32 mask,uint32 val)1545 si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
1546 {
1547 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1548 sb_core_cflags_wo(sih, mask, val);
1549 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1550 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1551 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1552 ai_core_cflags_wo(sih, mask, val);
1553 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1554 ub_core_cflags_wo(sih, mask, val);
1555 else
1556 ASSERT(0);
1557 }
1558
1559 uint32
si_core_sflags(si_t * sih,uint32 mask,uint32 val)1560 si_core_sflags(si_t *sih, uint32 mask, uint32 val)
1561 {
1562 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1563 return sb_core_sflags(sih, mask, val);
1564 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1565 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1566 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1567 return ai_core_sflags(sih, mask, val);
1568 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1569 return ub_core_sflags(sih, mask, val);
1570 else {
1571 ASSERT(0);
1572 return 0;
1573 }
1574 }
1575
1576 void
si_commit(si_t * sih)1577 si_commit(si_t *sih)
1578 {
1579 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1580 sb_commit(sih);
1581 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1582 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1583 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1584 ;
1585 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1586 ;
1587 else {
1588 ASSERT(0);
1589 }
1590 }
1591
1592 bool
si_iscoreup(si_t * sih)1593 si_iscoreup(si_t *sih)
1594 {
1595 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1596 return sb_iscoreup(sih);
1597 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1598 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1599 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1600 return ai_iscoreup(sih);
1601 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1602 return ub_iscoreup(sih);
1603 else {
1604 ASSERT(0);
1605 return FALSE;
1606 }
1607 }
1608
1609 uint
si_wrapperreg(si_t * sih,uint32 offset,uint32 mask,uint32 val)1610 si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
1611 {
1612 /* only for AI back plane chips */
1613 if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1614 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1615 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1616 return (ai_wrap_reg(sih, offset, mask, val));
1617 return 0;
1618 }
1619 /* si_backplane_access is used to read full backplane address from host for PCIE FD
1620 * it uses secondary bar-0 window which lies at an offset of 16K from primary bar-0
1621 * Provides support for read/write of 1/2/4 bytes of backplane address
1622 * Can be used to read/write
1623 * 1. core regs
1624 * 2. Wrapper regs
1625 * 3. memory
1626 * 4. BT area
1627 * For accessing any 32 bit backplane address, [31 : 12] of backplane should be given in "region"
1628 * [11 : 0] should be the "regoff"
1629 * for reading 4 bytes from reg 0x200 of d11 core use it like below
1630 * : si_backplane_access(sih, 0x18001000, 0x200, 4, 0, TRUE)
1631 */
si_backplane_addr_sane(uint addr,uint size)1632 static int si_backplane_addr_sane(uint addr, uint size)
1633 {
1634 int bcmerror = BCME_OK;
1635
1636 /* For 2 byte access, address has to be 2 byte aligned */
1637 if (size == 2) {
1638 if (addr & 0x1) {
1639 bcmerror = BCME_ERROR;
1640 }
1641 }
1642 /* For 4 byte access, address has to be 4 byte aligned */
1643 if (size == 4) {
1644 if (addr & 0x3) {
1645 bcmerror = BCME_ERROR;
1646 }
1647 }
1648 return bcmerror;
1649 }
1650
1651 void
si_invalidate_second_bar0win(si_t * sih)1652 si_invalidate_second_bar0win(si_t *sih)
1653 {
1654 si_info_t *sii = SI_INFO(sih);
1655 sii->second_bar0win = ~0x0;
1656 }
1657
1658 int
si_backplane_access(si_t * sih,uint addr,uint size,uint * val,bool read)1659 si_backplane_access(si_t *sih, uint addr, uint size, uint *val, bool read)
1660 {
1661 volatile uint32 *r = NULL;
1662 uint32 region = 0;
1663 si_info_t *sii = SI_INFO(sih);
1664
1665 /* Valid only for pcie bus */
1666 if (BUSTYPE(sih->bustype) != PCI_BUS) {
1667 SI_ERROR(("Valid only for pcie bus \n"));
1668 return BCME_ERROR;
1669 }
1670
1671 /* Split adrr into region and address offset */
1672 region = (addr & (0xFFFFF << 12));
1673 addr = addr & 0xFFF;
1674
1675 /* check for address and size sanity */
1676 if (si_backplane_addr_sane(addr, size) != BCME_OK)
1677 return BCME_ERROR;
1678
1679 /* Update window if required */
1680 if (sii->second_bar0win != region) {
1681 OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_CORE2_WIN, 4, region);
1682 sii->second_bar0win = region;
1683 }
1684
1685 /* Estimate effective address
1686 * sii->curmap : bar-0 virtual address
1687 * PCI_SECOND_BAR0_OFFSET : secondar bar-0 offset
1688 * regoff : actual reg offset
1689 */
1690 r = (volatile uint32 *)((volatile char *)sii->curmap + PCI_SECOND_BAR0_OFFSET + addr);
1691
1692 SI_VMSG(("si curmap %p region %x regaddr %x effective addr %p READ %d\n",
1693 (volatile char*)sii->curmap, region, addr, r, read));
1694
1695 switch (size) {
1696 case sizeof(uint8) :
1697 if (read)
1698 *val = R_REG(sii->osh, (volatile uint8*)r);
1699 else
1700 W_REG(sii->osh, (volatile uint8*)r, *val);
1701 break;
1702 case sizeof(uint16) :
1703 if (read)
1704 *val = R_REG(sii->osh, (volatile uint16*)r);
1705 else
1706 W_REG(sii->osh, (volatile uint16*)r, *val);
1707 break;
1708 case sizeof(uint32) :
1709 if (read)
1710 *val = R_REG(sii->osh, (volatile uint32*)r);
1711 else
1712 W_REG(sii->osh, (volatile uint32*)r, *val);
1713 break;
1714 default :
1715 SI_ERROR(("Invalid size %d \n", size));
1716 return (BCME_ERROR);
1717 break;
1718 }
1719
1720 return (BCME_OK);
1721 }
1722 uint
si_corereg(si_t * sih,uint coreidx,uint regoff,uint mask,uint val)1723 si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1724 {
1725 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1726 return sb_corereg(sih, coreidx, regoff, mask, val);
1727 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1728 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1729 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1730 return ai_corereg(sih, coreidx, regoff, mask, val);
1731 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1732 return ub_corereg(sih, coreidx, regoff, mask, val);
1733 else {
1734 ASSERT(0);
1735 return 0;
1736 }
1737 }
1738
1739 uint
si_corereg_writeonly(si_t * sih,uint coreidx,uint regoff,uint mask,uint val)1740 si_corereg_writeonly(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
1741 {
1742 return ai_corereg_writeonly(sih, coreidx, regoff, mask, val);
1743 }
1744
1745 /** ILP sensitive register access needs special treatment to avoid backplane stalls */
si_pmu_is_ilp_sensitive(uint32 idx,uint regoff)1746 bool si_pmu_is_ilp_sensitive(uint32 idx, uint regoff)
1747 {
1748 if (idx == SI_CC_IDX) {
1749 if (CHIPCREGS_ILP_SENSITIVE(regoff))
1750 return TRUE;
1751 } else if (PMUREGS_ILP_SENSITIVE(regoff)) {
1752 return TRUE;
1753 }
1754
1755 return FALSE;
1756 }
1757
1758 /** 'idx' should refer either to the chipcommon core or the PMU core */
1759 uint
si_pmu_corereg(si_t * sih,uint32 idx,uint regoff,uint mask,uint val)1760 si_pmu_corereg(si_t *sih, uint32 idx, uint regoff, uint mask, uint val)
1761 {
1762 int pmustatus_offset;
1763
1764 /* prevent backplane stall on double write to 'ILP domain' registers in the PMU */
1765 if (mask != 0 && PMUREV(sih->pmurev) >= 22 &&
1766 si_pmu_is_ilp_sensitive(idx, regoff)) {
1767 pmustatus_offset = AOB_ENAB(sih) ? OFFSETOF(pmuregs_t, pmustatus) :
1768 OFFSETOF(chipcregs_t, pmustatus);
1769
1770 while (si_corereg(sih, idx, pmustatus_offset, 0, 0) & PST_SLOW_WR_PENDING)
1771 {};
1772 }
1773
1774 return si_corereg(sih, idx, regoff, mask, val);
1775 }
1776
1777 /*
1778 * If there is no need for fiddling with interrupts or core switches (typically silicon
1779 * back plane registers, pci registers and chipcommon registers), this function
1780 * returns the register offset on this core to a mapped address. This address can
1781 * be used for W_REG/R_REG directly.
1782 *
1783 * For accessing registers that would need a core switch, this function will return
1784 * NULL.
1785 */
1786 volatile uint32 *
si_corereg_addr(si_t * sih,uint coreidx,uint regoff)1787 si_corereg_addr(si_t *sih, uint coreidx, uint regoff)
1788 {
1789 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1790 return sb_corereg_addr(sih, coreidx, regoff);
1791 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1792 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1793 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1794 return ai_corereg_addr(sih, coreidx, regoff);
1795 else {
1796 return 0;
1797 }
1798 }
1799
1800 void
si_core_disable(si_t * sih,uint32 bits)1801 si_core_disable(si_t *sih, uint32 bits)
1802 {
1803 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1804 sb_core_disable(sih, bits);
1805 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1806 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1807 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1808 ai_core_disable(sih, bits);
1809 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1810 ub_core_disable(sih, bits);
1811 }
1812
1813 void
si_core_reset(si_t * sih,uint32 bits,uint32 resetbits)1814 si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
1815 {
1816 if (CHIPTYPE(sih->socitype) == SOCI_SB)
1817 sb_core_reset(sih, bits, resetbits);
1818 else if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1819 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1820 (CHIPTYPE(sih->socitype) == SOCI_NAI))
1821 ai_core_reset(sih, bits, resetbits);
1822 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
1823 ub_core_reset(sih, bits, resetbits);
1824 }
1825
1826 /** Run bist on current core. Caller needs to take care of core-specific bist hazards */
1827 int
si_corebist(si_t * sih)1828 si_corebist(si_t *sih)
1829 {
1830 uint32 cflags;
1831 int result = 0;
1832
1833 /* Read core control flags */
1834 cflags = si_core_cflags(sih, 0, 0);
1835
1836 /* Set bist & fgc */
1837 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
1838
1839 /* Wait for bist done */
1840 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
1841
1842 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
1843 result = BCME_ERROR;
1844
1845 /* Reset core control flags */
1846 si_core_cflags(sih, 0xffff, cflags);
1847
1848 return result;
1849 }
1850
1851 uint
si_num_slaveports(si_t * sih,uint coreid)1852 si_num_slaveports(si_t *sih, uint coreid)
1853 {
1854 uint idx = si_findcoreidx(sih, coreid, 0);
1855 uint num = 0;
1856
1857 if (idx != BADIDX) {
1858 if (CHIPTYPE(sih->socitype) == SOCI_AI) {
1859 num = ai_num_slaveports(sih, idx);
1860 }
1861 }
1862 return num;
1863 }
1864
1865 uint32
si_get_slaveport_addr(si_t * sih,uint spidx,uint baidx,uint core_id,uint coreunit)1866 si_get_slaveport_addr(si_t *sih, uint spidx, uint baidx, uint core_id, uint coreunit)
1867 {
1868 si_info_t *sii = SI_INFO(sih);
1869 uint origidx = sii->curidx;
1870 uint32 addr = 0x0;
1871
1872 if (!((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1873 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1874 (CHIPTYPE(sih->socitype) == SOCI_NAI)))
1875 goto done;
1876
1877 si_setcore(sih, core_id, coreunit);
1878
1879 addr = ai_addrspace(sih, spidx, baidx);
1880
1881 si_setcoreidx(sih, origidx);
1882
1883 done:
1884 return addr;
1885 }
1886
1887 uint32
si_get_d11_slaveport_addr(si_t * sih,uint spidx,uint baidx,uint coreunit)1888 si_get_d11_slaveport_addr(si_t *sih, uint spidx, uint baidx, uint coreunit)
1889 {
1890 si_info_t *sii = SI_INFO(sih);
1891 uint origidx = sii->curidx;
1892 uint32 addr = 0x0;
1893
1894 if (!((CHIPTYPE(sih->socitype) == SOCI_AI) ||
1895 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) ||
1896 (CHIPTYPE(sih->socitype) == SOCI_NAI)))
1897 goto done;
1898
1899 si_setcore(sih, D11_CORE_ID, coreunit);
1900
1901 addr = ai_addrspace(sih, spidx, baidx);
1902
1903 si_setcoreidx(sih, origidx);
1904
1905 done:
1906 return addr;
1907 }
1908
1909 static uint32
factor6(uint32 x)1910 factor6(uint32 x)
1911 {
1912 switch (x) {
1913 case CC_F6_2: return 2;
1914 case CC_F6_3: return 3;
1915 case CC_F6_4: return 4;
1916 case CC_F6_5: return 5;
1917 case CC_F6_6: return 6;
1918 case CC_F6_7: return 7;
1919 default: return 0;
1920 }
1921 }
1922
1923 /*
1924 * Divide the clock by the divisor with protection for
1925 * a zero divisor.
1926 */
1927 static uint32
divide_clock(uint32 clock,uint32 div)1928 divide_clock(uint32 clock, uint32 div)
1929 {
1930 return div ? clock / div : 0;
1931 }
1932
1933 /** calculate the speed the SI would run at given a set of clockcontrol values */
1934 uint32
si_clock_rate(uint32 pll_type,uint32 n,uint32 m)1935 si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
1936 {
1937 uint32 n1, n2, clock, m1, m2, m3, mc;
1938
1939 n1 = n & CN_N1_MASK;
1940 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1941
1942 if (pll_type == PLL_TYPE6) {
1943 if (m & CC_T6_MMASK)
1944 return CC_T6_M1;
1945 else
1946 return CC_T6_M0;
1947 } else if ((pll_type == PLL_TYPE1) ||
1948 (pll_type == PLL_TYPE3) ||
1949 (pll_type == PLL_TYPE4) ||
1950 (pll_type == PLL_TYPE7)) {
1951 n1 = factor6(n1);
1952 n2 += CC_F5_BIAS;
1953 } else if (pll_type == PLL_TYPE2) {
1954 n1 += CC_T2_BIAS;
1955 n2 += CC_T2_BIAS;
1956 ASSERT((n1 >= 2) && (n1 <= 7));
1957 ASSERT((n2 >= 5) && (n2 <= 23));
1958 } else if (pll_type == PLL_TYPE5) {
1959 return (100000000);
1960 } else
1961 ASSERT(0);
1962 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1963 if ((pll_type == PLL_TYPE3) ||
1964 (pll_type == PLL_TYPE7)) {
1965 clock = CC_CLOCK_BASE2 * n1 * n2;
1966 } else
1967 clock = CC_CLOCK_BASE1 * n1 * n2;
1968
1969 if (clock == 0)
1970 return 0;
1971
1972 m1 = m & CC_M1_MASK;
1973 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1974 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1975 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1976
1977 if ((pll_type == PLL_TYPE1) ||
1978 (pll_type == PLL_TYPE3) ||
1979 (pll_type == PLL_TYPE4) ||
1980 (pll_type == PLL_TYPE7)) {
1981 m1 = factor6(m1);
1982 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1983 m2 += CC_F5_BIAS;
1984 else
1985 m2 = factor6(m2);
1986 m3 = factor6(m3);
1987
1988 switch (mc) {
1989 case CC_MC_BYPASS: return (clock);
1990 case CC_MC_M1: return divide_clock(clock, m1);
1991 case CC_MC_M1M2: return divide_clock(clock, m1 * m2);
1992 case CC_MC_M1M2M3: return divide_clock(clock, m1 * m2 * m3);
1993 case CC_MC_M1M3: return divide_clock(clock, m1 * m3);
1994 default: return (0);
1995 }
1996 } else {
1997 ASSERT(pll_type == PLL_TYPE2);
1998
1999 m1 += CC_T2_BIAS;
2000 m2 += CC_T2M2_BIAS;
2001 m3 += CC_T2_BIAS;
2002 ASSERT((m1 >= 2) && (m1 <= 7));
2003 ASSERT((m2 >= 3) && (m2 <= 10));
2004 ASSERT((m3 >= 2) && (m3 <= 7));
2005
2006 if ((mc & CC_T2MC_M1BYP) == 0)
2007 clock /= m1;
2008 if ((mc & CC_T2MC_M2BYP) == 0)
2009 clock /= m2;
2010 if ((mc & CC_T2MC_M3BYP) == 0)
2011 clock /= m3;
2012
2013 return (clock);
2014 }
2015 }
2016
2017 /**
2018 * Some chips could have multiple host interfaces, however only one will be active.
2019 * For a given chip. Depending pkgopt and cc_chipst return the active host interface.
2020 */
2021 uint
si_chip_hostif(si_t * sih)2022 si_chip_hostif(si_t *sih)
2023 {
2024 uint hosti = 0;
2025
2026 switch (CHIPID(sih->chip)) {
2027 case BCM43018_CHIP_ID:
2028 case BCM43430_CHIP_ID:
2029 hosti = CHIP_HOSTIF_SDIOMODE;
2030 break;
2031 case BCM43012_CHIP_ID:
2032 hosti = CHIP_HOSTIF_SDIOMODE;
2033 break;
2034 CASE_BCM43602_CHIP:
2035 hosti = CHIP_HOSTIF_PCIEMODE;
2036 break;
2037
2038 case BCM4360_CHIP_ID:
2039 /* chippkg bit-0 == 0 is PCIE only pkgs
2040 * chippkg bit-0 == 1 has both PCIE and USB cores enabled
2041 */
2042 if ((sih->chippkg & 0x1) && (sih->chipst & CST4360_MODE_USB))
2043 hosti = CHIP_HOSTIF_USBMODE;
2044 else
2045 hosti = CHIP_HOSTIF_PCIEMODE;
2046
2047 break;
2048
2049 case BCM4335_CHIP_ID:
2050 /* TBD: like in 4360, do we need to check pkg? */
2051 if (CST4335_CHIPMODE_USB20D(sih->chipst))
2052 hosti = CHIP_HOSTIF_USBMODE;
2053 else if (CST4335_CHIPMODE_SDIOD(sih->chipst))
2054 hosti = CHIP_HOSTIF_SDIOMODE;
2055 else
2056 hosti = CHIP_HOSTIF_PCIEMODE;
2057 break;
2058
2059 CASE_BCM4345_CHIP:
2060 if (CST4345_CHIPMODE_USB20D(sih->chipst) || CST4345_CHIPMODE_HSIC(sih->chipst))
2061 hosti = CHIP_HOSTIF_USBMODE;
2062 else if (CST4345_CHIPMODE_SDIOD(sih->chipst))
2063 hosti = CHIP_HOSTIF_SDIOMODE;
2064 else if (CST4345_CHIPMODE_PCIE(sih->chipst))
2065 hosti = CHIP_HOSTIF_PCIEMODE;
2066 break;
2067
2068 case BCM4349_CHIP_GRPID:
2069 case BCM53573_CHIP_GRPID:
2070 if (CST4349_CHIPMODE_SDIOD(sih->chipst))
2071 hosti = CHIP_HOSTIF_SDIOMODE;
2072 else if (CST4349_CHIPMODE_PCIE(sih->chipst))
2073 hosti = CHIP_HOSTIF_PCIEMODE;
2074 break;
2075 case BCM4364_CHIP_ID:
2076 if (CST4364_CHIPMODE_SDIOD(sih->chipst))
2077 hosti = CHIP_HOSTIF_SDIOMODE;
2078 else if (CST4364_CHIPMODE_PCIE(sih->chipst))
2079 hosti = CHIP_HOSTIF_PCIEMODE;
2080 break;
2081 case BCM4373_CHIP_ID:
2082 if (CST4373_CHIPMODE_USB20D(sih->chipst))
2083 hosti = CHIP_HOSTIF_USBMODE;
2084 else if (CST4373_CHIPMODE_SDIOD(sih->chipst))
2085 hosti = CHIP_HOSTIF_SDIOMODE;
2086 else if (CST4373_CHIPMODE_PCIE(sih->chipst))
2087 hosti = CHIP_HOSTIF_PCIEMODE;
2088 break;
2089
2090 case BCM4347_CHIP_GRPID:
2091 if (CST4347_CHIPMODE_SDIOD(sih->chipst))
2092 hosti = CHIP_HOSTIF_SDIOMODE;
2093 else if (CST4347_CHIPMODE_PCIE(sih->chipst))
2094 hosti = CHIP_HOSTIF_PCIEMODE;
2095 break;
2096 case BCM4369_CHIP_GRPID:
2097 if (CST4369_CHIPMODE_SDIOD(sih->chipst))
2098 hosti = CHIP_HOSTIF_SDIOMODE;
2099 else if (CST4369_CHIPMODE_PCIE(sih->chipst))
2100 hosti = CHIP_HOSTIF_PCIEMODE;
2101 break;
2102 #ifdef CHIPS_CUSTOMER_HW6
2103 case BCM4368_CHIP_GRPID:
2104 hosti = CHIP_HOSTIF_PCIEMODE;
2105 break;
2106 #endif /* CHIPS_CUSTOMER_HW6 */
2107
2108 case BCM4350_CHIP_ID:
2109 case BCM4354_CHIP_ID:
2110 case BCM43556_CHIP_ID:
2111 case BCM43558_CHIP_ID:
2112 case BCM43566_CHIP_ID:
2113 case BCM43568_CHIP_ID:
2114 case BCM43569_CHIP_ID:
2115 case BCM43570_CHIP_ID:
2116 case BCM4358_CHIP_ID:
2117 if (CST4350_CHIPMODE_USB20D(sih->chipst) ||
2118 CST4350_CHIPMODE_HSIC20D(sih->chipst) ||
2119 CST4350_CHIPMODE_USB30D(sih->chipst) ||
2120 CST4350_CHIPMODE_USB30D_WL(sih->chipst) ||
2121 CST4350_CHIPMODE_HSIC30D(sih->chipst))
2122 hosti = CHIP_HOSTIF_USBMODE;
2123 else if (CST4350_CHIPMODE_SDIOD(sih->chipst))
2124 hosti = CHIP_HOSTIF_SDIOMODE;
2125 else if (CST4350_CHIPMODE_PCIE(sih->chipst))
2126 hosti = CHIP_HOSTIF_PCIEMODE;
2127 break;
2128
2129 default:
2130 break;
2131 }
2132
2133 return hosti;
2134 }
2135
2136 /** set chip watchdog reset timer to fire in 'ticks' */
2137 void
si_watchdog(si_t * sih,uint ticks)2138 si_watchdog(si_t *sih, uint ticks)
2139 {
2140 uint nb, maxt;
2141 uint pmu_wdt = 1;
2142
2143 if (PMUCTL_ENAB(sih) && pmu_wdt) {
2144 nb = (CCREV(sih->ccrev) < 26) ? 16 : ((CCREV(sih->ccrev) >= 37) ? 32 : 24);
2145 /* The mips compiler uses the sllv instruction,
2146 * so we specially handle the 32-bit case.
2147 */
2148 if (nb == 32)
2149 maxt = 0xffffffff;
2150 else
2151 maxt = ((1 << nb) - 1);
2152
2153 if (ticks == 1)
2154 ticks = 2;
2155 else if (ticks > maxt)
2156 ticks = maxt;
2157 if (CHIPID(sih->chip) == BCM43012_CHIP_ID) {
2158 PMU_REG_NEW(sih, min_res_mask, ~0, DEFAULT_43012_MIN_RES_MASK);
2159 PMU_REG_NEW(sih, watchdog_res_mask, ~0, DEFAULT_43012_MIN_RES_MASK);
2160 PMU_REG_NEW(sih, pmustatus, PST_WDRESET, PST_WDRESET);
2161 PMU_REG_NEW(sih, pmucontrol_ext, PCTL_EXT_FASTLPO_SWENAB, 0);
2162 SPINWAIT((PMU_REG(sih, pmustatus, 0, 0) & PST_ILPFASTLPO),
2163 PMU_MAX_TRANSITION_DLY);
2164 }
2165 if (sih->chip == CYW55500_CHIP_ID ||
2166 sih->chip == CYW55560_CHIP_ID) {
2167 si_corereg(sih, si_findcoreidx(sih, PMU_CORE_ID, 0),
2168 OFFSETOF(pmuregs_t, pmuwatchdog), ~0, ticks);
2169 } else {
2170 pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, ~0, ticks);
2171 }
2172 } else {
2173 maxt = (1 << 28) - 1;
2174 if (ticks > maxt)
2175 ticks = maxt;
2176
2177 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
2178 }
2179 }
2180
2181 /** trigger watchdog reset after ms milliseconds */
2182 void
si_watchdog_ms(si_t * sih,uint32 ms)2183 si_watchdog_ms(si_t *sih, uint32 ms)
2184 {
2185 si_watchdog(sih, wd_msticks * ms);
2186 }
2187
si_watchdog_msticks(void)2188 uint32 si_watchdog_msticks(void)
2189 {
2190 return wd_msticks;
2191 }
2192
2193 bool
si_taclear(si_t * sih,bool details)2194 si_taclear(si_t *sih, bool details)
2195 {
2196 return FALSE;
2197 }
2198
2199 /** return the slow clock source - LPO, XTAL, or PCI */
2200 static uint
si_slowclk_src(si_info_t * sii)2201 si_slowclk_src(si_info_t *sii)
2202 {
2203 chipcregs_t *cc;
2204
2205 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
2206
2207 if (CCREV(sii->pub.ccrev) < 6) {
2208 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
2209 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
2210 PCI_CFG_GPIO_SCS))
2211 return (SCC_SS_PCI);
2212 else
2213 return (SCC_SS_XTAL);
2214 } else if (CCREV(sii->pub.ccrev) < 10) {
2215 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
2216 ASSERT(cc);
2217 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
2218 } else /* Insta-clock */
2219 return (SCC_SS_XTAL);
2220 }
2221
2222 /** return the ILP (slowclock) min or max frequency */
2223 static uint
si_slowclk_freq(si_info_t * sii,bool max_freq,chipcregs_t * cc)2224 si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
2225 {
2226 uint32 slowclk;
2227 uint div;
2228
2229 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
2230
2231 /* shouldn't be here unless we've established the chip has dynamic clk control */
2232 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
2233
2234 slowclk = si_slowclk_src(sii);
2235 if (CCREV(sii->pub.ccrev) < 6) {
2236 if (slowclk == SCC_SS_PCI)
2237 return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
2238 else
2239 return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
2240 } else if (CCREV(sii->pub.ccrev) < 10) {
2241 div = 4 *
2242 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
2243 if (slowclk == SCC_SS_LPO)
2244 return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
2245 else if (slowclk == SCC_SS_XTAL)
2246 return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
2247 else if (slowclk == SCC_SS_PCI)
2248 return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
2249 else
2250 ASSERT(0);
2251 } else {
2252 /* Chipc rev 10 is InstaClock */
2253 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
2254 div = 4 * (div + 1);
2255 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
2256 }
2257 return (0);
2258 }
2259
2260 static void
si_clkctl_setdelay(si_info_t * sii,void * chipcregs)2261 si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
2262 {
2263 chipcregs_t *cc = (chipcregs_t *)chipcregs;
2264 uint slowmaxfreq, pll_delay, slowclk;
2265 uint pll_on_delay, fref_sel_delay;
2266
2267 pll_delay = PLL_DELAY;
2268
2269 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
2270 * since the xtal will also be powered down by dynamic clk control logic.
2271 */
2272
2273 slowclk = si_slowclk_src(sii);
2274 if (slowclk != SCC_SS_XTAL)
2275 pll_delay += XTAL_ON_DELAY;
2276
2277 /* Starting with 4318 it is ILP that is used for the delays */
2278 slowmaxfreq = si_slowclk_freq(sii, (CCREV(sii->pub.ccrev) >= 10) ? FALSE : TRUE, cc);
2279
2280 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
2281 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
2282
2283 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
2284 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
2285 }
2286
2287 /** initialize power control delay registers */
2288 void
si_clkctl_init(si_t * sih)2289 si_clkctl_init(si_t *sih)
2290 {
2291 si_info_t *sii;
2292 uint origidx = 0;
2293 chipcregs_t *cc;
2294 bool fast;
2295
2296 if (!CCCTL_ENAB(sih))
2297 return;
2298
2299 sii = SI_INFO(sih);
2300 fast = SI_FAST(sii);
2301 if (!fast) {
2302 origidx = sii->curidx;
2303 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
2304 return;
2305 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
2306 return;
2307 ASSERT(cc != NULL);
2308
2309 /* set all Instaclk chip ILP to 1 MHz */
2310 if (CCREV(sih->ccrev) >= 10)
2311 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
2312 (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
2313
2314 si_clkctl_setdelay(sii, (void *)(uintptr)cc);
2315
2316 OSL_DELAY(20000);
2317
2318 if (!fast)
2319 si_setcoreidx(sih, origidx);
2320 }
2321
2322 /** change logical "focus" to the gpio core for optimized access */
2323 volatile void *
si_gpiosetcore(si_t * sih)2324 si_gpiosetcore(si_t *sih)
2325 {
2326 return (si_setcoreidx(sih, SI_CC_IDX));
2327 }
2328
2329 /**
2330 * mask & set gpiocontrol bits.
2331 * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin.
2332 * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated
2333 * to some chip-specific purpose.
2334 */
2335 uint32
si_gpiocontrol(si_t * sih,uint32 mask,uint32 val,uint8 priority)2336 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2337 {
2338 uint regoff;
2339
2340 regoff = 0;
2341
2342 /* gpios could be shared on router platforms
2343 * ignore reservation if it's high priority (e.g., test apps)
2344 */
2345 if ((priority != GPIO_HI_PRIORITY) &&
2346 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2347 mask = priority ? (si_gpioreservation & mask) :
2348 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2349 val &= mask;
2350 }
2351
2352 regoff = OFFSETOF(chipcregs_t, gpiocontrol);
2353 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2354 }
2355
2356 /** mask&set gpio output enable bits */
2357 uint32
si_gpioouten(si_t * sih,uint32 mask,uint32 val,uint8 priority)2358 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2359 {
2360 uint regoff;
2361
2362 regoff = 0;
2363
2364 /* gpios could be shared on router platforms
2365 * ignore reservation if it's high priority (e.g., test apps)
2366 */
2367 if ((priority != GPIO_HI_PRIORITY) &&
2368 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2369 mask = priority ? (si_gpioreservation & mask) :
2370 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2371 val &= mask;
2372 }
2373
2374 regoff = OFFSETOF(chipcregs_t, gpioouten);
2375 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2376 }
2377
2378 /** mask&set gpio output bits */
2379 uint32
si_gpioout(si_t * sih,uint32 mask,uint32 val,uint8 priority)2380 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2381 {
2382 uint regoff;
2383
2384 regoff = 0;
2385
2386 /* gpios could be shared on router platforms
2387 * ignore reservation if it's high priority (e.g., test apps)
2388 */
2389 if ((priority != GPIO_HI_PRIORITY) &&
2390 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2391 mask = priority ? (si_gpioreservation & mask) :
2392 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2393 val &= mask;
2394 }
2395
2396 regoff = OFFSETOF(chipcregs_t, gpioout);
2397 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2398 }
2399
2400 /** reserve one gpio */
2401 uint32
si_gpioreserve(si_t * sih,uint32 gpio_bitmask,uint8 priority)2402 si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2403 {
2404 /* only cores on SI_BUS share GPIO's and only applcation users need to
2405 * reserve/release GPIO
2406 */
2407 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2408 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2409 return 0xffffffff;
2410 }
2411 /* make sure only one bit is set */
2412 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2413 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
2414 return 0xffffffff;
2415 }
2416
2417 /* already reserved */
2418 if (si_gpioreservation & gpio_bitmask)
2419 return 0xffffffff;
2420 /* set reservation */
2421 si_gpioreservation |= gpio_bitmask;
2422
2423 return si_gpioreservation;
2424 }
2425
2426 /**
2427 * release one gpio.
2428 *
2429 * releasing the gpio doesn't change the current value on the GPIO last write value
2430 * persists till someone overwrites it.
2431 */
2432 uint32
si_gpiorelease(si_t * sih,uint32 gpio_bitmask,uint8 priority)2433 si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
2434 {
2435 /* only cores on SI_BUS share GPIO's and only applcation users need to
2436 * reserve/release GPIO
2437 */
2438 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
2439 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
2440 return 0xffffffff;
2441 }
2442 /* make sure only one bit is set */
2443 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
2444 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
2445 return 0xffffffff;
2446 }
2447
2448 /* already released */
2449 if (!(si_gpioreservation & gpio_bitmask))
2450 return 0xffffffff;
2451
2452 /* clear reservation */
2453 si_gpioreservation &= ~gpio_bitmask;
2454
2455 return si_gpioreservation;
2456 }
2457
2458 /* return the current gpioin register value */
2459 uint32
si_gpioin(si_t * sih)2460 si_gpioin(si_t *sih)
2461 {
2462 uint regoff;
2463
2464 regoff = OFFSETOF(chipcregs_t, gpioin);
2465 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
2466 }
2467
2468 /* mask&set gpio interrupt polarity bits */
2469 uint32
si_gpiointpolarity(si_t * sih,uint32 mask,uint32 val,uint8 priority)2470 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2471 {
2472 uint regoff;
2473
2474 /* gpios could be shared on router platforms */
2475 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2476 mask = priority ? (si_gpioreservation & mask) :
2477 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2478 val &= mask;
2479 }
2480
2481 regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
2482 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2483 }
2484
2485 /* mask&set gpio interrupt mask bits */
2486 uint32
si_gpiointmask(si_t * sih,uint32 mask,uint32 val,uint8 priority)2487 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2488 {
2489 uint regoff;
2490
2491 /* gpios could be shared on router platforms */
2492 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2493 mask = priority ? (si_gpioreservation & mask) :
2494 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2495 val &= mask;
2496 }
2497
2498 regoff = OFFSETOF(chipcregs_t, gpiointmask);
2499 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2500 }
2501
2502 uint32
si_gpioeventintmask(si_t * sih,uint32 mask,uint32 val,uint8 priority)2503 si_gpioeventintmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
2504 {
2505 uint regoff;
2506 /* gpios could be shared on router platforms */
2507 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
2508 mask = priority ? (si_gpioreservation & mask) :
2509 ((si_gpioreservation | mask) & ~(si_gpioreservation));
2510 val &= mask;
2511 }
2512 regoff = OFFSETOF(chipcregs_t, gpioeventintmask);
2513 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
2514 }
2515
2516 /* assign the gpio to an led */
2517 uint32
si_gpioled(si_t * sih,uint32 mask,uint32 val)2518 si_gpioled(si_t *sih, uint32 mask, uint32 val)
2519 {
2520 if (CCREV(sih->ccrev) < 16)
2521 return 0xffffffff;
2522
2523 /* gpio led powersave reg */
2524 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
2525 }
2526
2527 /* mask&set gpio timer val */
2528 uint32
si_gpiotimerval(si_t * sih,uint32 mask,uint32 gpiotimerval)2529 si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
2530 {
2531 if (CCREV(sih->ccrev) < 16)
2532 return 0xffffffff;
2533
2534 return (si_corereg(sih, SI_CC_IDX,
2535 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
2536 }
2537
2538 uint32
si_gpiopull(si_t * sih,bool updown,uint32 mask,uint32 val)2539 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
2540 {
2541 uint offs;
2542
2543 if (CCREV(sih->ccrev) < 20)
2544 return 0xffffffff;
2545
2546 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
2547 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
2548 }
2549
2550 uint32
si_gpioevent(si_t * sih,uint regtype,uint32 mask,uint32 val)2551 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
2552 {
2553 uint offs;
2554
2555 if (CCREV(sih->ccrev) < 11)
2556 return 0xffffffff;
2557
2558 if (regtype == GPIO_REGEVT)
2559 offs = OFFSETOF(chipcregs_t, gpioevent);
2560 else if (regtype == GPIO_REGEVT_INTMSK)
2561 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
2562 else if (regtype == GPIO_REGEVT_INTPOL)
2563 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
2564 else
2565 return 0xffffffff;
2566
2567 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
2568 }
2569
2570 uint32
si_gpio_int_enable(si_t * sih,bool enable)2571 si_gpio_int_enable(si_t *sih, bool enable)
2572 {
2573 uint offs;
2574
2575 if (CCREV(sih->ccrev) < 11)
2576 return 0xffffffff;
2577
2578 offs = OFFSETOF(chipcregs_t, intmask);
2579 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
2580 }
2581
2582 /** Return the size of the specified SYSMEM bank */
2583 static uint
sysmem_banksize(si_info_t * sii,sysmemregs_t * regs,uint8 idx)2584 sysmem_banksize(si_info_t *sii, sysmemregs_t *regs, uint8 idx)
2585 {
2586 uint banksize, bankinfo;
2587 uint bankidx = idx;
2588
2589 W_REG(sii->osh, ®s->bankidx, bankidx);
2590 bankinfo = R_REG(sii->osh, ®s->bankinfo);
2591 banksize = SYSMEM_BANKINFO_SZBASE * ((bankinfo & SYSMEM_BANKINFO_SZMASK) + 1);
2592 return banksize;
2593 }
2594
2595 /** Return the RAM size of the SYSMEM core */
2596 uint32
si_sysmem_size(si_t * sih)2597 si_sysmem_size(si_t *sih)
2598 {
2599 si_info_t *sii = SI_INFO(sih);
2600 uint origidx;
2601 uint intr_val = 0;
2602
2603 sysmemregs_t *regs;
2604 bool wasup;
2605 uint32 coreinfo;
2606 uint memsize = 0;
2607 uint8 i;
2608 uint nb, nrb;
2609
2610 /* Block ints and save current core */
2611 INTR_OFF(sii, intr_val);
2612 origidx = si_coreidx(sih);
2613
2614 /* Switch to SYSMEM core */
2615 if (!(regs = si_setcore(sih, SYSMEM_CORE_ID, 0)))
2616 goto done;
2617
2618 /* Get info for determining size */
2619 if (!(wasup = si_iscoreup(sih)))
2620 si_core_reset(sih, 0, 0);
2621 coreinfo = R_REG(sii->osh, ®s->coreinfo);
2622
2623 /* Number of ROM banks, SW need to skip the ROM banks. */
2624 nrb = (coreinfo & SYSMEM_SRCI_ROMNB_MASK) >> SYSMEM_SRCI_ROMNB_SHIFT;
2625
2626 nb = (coreinfo & SYSMEM_SRCI_SRNB_MASK) >> SYSMEM_SRCI_SRNB_SHIFT;
2627 for (i = 0; i < nb; i++)
2628 memsize += sysmem_banksize(sii, regs, i + nrb);
2629
2630 si_setcoreidx(sih, origidx);
2631
2632 done:
2633 INTR_RESTORE(sii, intr_val);
2634
2635 return memsize;
2636 }
2637
2638 /** Return the size of the specified SOCRAM bank */
2639 static uint
socram_banksize(si_info_t * sii,sbsocramregs_t * regs,uint8 idx,uint8 mem_type)2640 socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
2641 {
2642 uint banksize, bankinfo;
2643 uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2644
2645 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
2646
2647 W_REG(sii->osh, ®s->bankidx, bankidx);
2648 bankinfo = R_REG(sii->osh, ®s->bankinfo);
2649 banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
2650 return banksize;
2651 }
2652
si_socram_set_bankpda(si_t * sih,uint32 bankidx,uint32 bankpda)2653 void si_socram_set_bankpda(si_t *sih, uint32 bankidx, uint32 bankpda)
2654 {
2655 si_info_t *sii = SI_INFO(sih);
2656 uint origidx;
2657 uint intr_val = 0;
2658 sbsocramregs_t *regs;
2659 bool wasup;
2660 uint corerev;
2661
2662 /* Block ints and save current core */
2663 INTR_OFF(sii, intr_val);
2664 origidx = si_coreidx(sih);
2665
2666 /* Switch to SOCRAM core */
2667 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2668 goto done;
2669
2670 if (!(wasup = si_iscoreup(sih)))
2671 si_core_reset(sih, 0, 0);
2672
2673 corerev = si_corerev(sih);
2674 if (corerev >= 16) {
2675 W_REG(sii->osh, ®s->bankidx, bankidx);
2676 W_REG(sii->osh, ®s->bankpda, bankpda);
2677 }
2678
2679 /* Return to previous state and core */
2680 if (!wasup)
2681 si_core_disable(sih, 0);
2682 si_setcoreidx(sih, origidx);
2683
2684 done:
2685 INTR_RESTORE(sii, intr_val);
2686 }
2687
2688 void
si_socdevram(si_t * sih,bool set,uint8 * enable,uint8 * protect,uint8 * remap)2689 si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap)
2690 {
2691 si_info_t *sii = SI_INFO(sih);
2692 uint origidx;
2693 uint intr_val = 0;
2694 sbsocramregs_t *regs;
2695 bool wasup;
2696 uint corerev;
2697
2698 /* Block ints and save current core */
2699 INTR_OFF(sii, intr_val);
2700 origidx = si_coreidx(sih);
2701
2702 if (!set)
2703 *enable = *protect = *remap = 0;
2704
2705 /* Switch to SOCRAM core */
2706 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2707 goto done;
2708
2709 /* Get info for determining size */
2710 if (!(wasup = si_iscoreup(sih)))
2711 si_core_reset(sih, 0, 0);
2712
2713 corerev = si_corerev(sih);
2714 if (corerev >= 10) {
2715 uint32 extcinfo;
2716 uint8 nb;
2717 uint8 i;
2718 uint32 bankidx, bankinfo;
2719
2720 extcinfo = R_REG(sii->osh, ®s->extracoreinfo);
2721 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
2722 for (i = 0; i < nb; i++) {
2723 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2724 W_REG(sii->osh, ®s->bankidx, bankidx);
2725 bankinfo = R_REG(sii->osh, ®s->bankinfo);
2726 if (set) {
2727 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
2728 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
2729 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK;
2730 if (*enable) {
2731 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
2732 if (*protect)
2733 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
2734 if ((corerev >= 16) && *remap)
2735 bankinfo |=
2736 (1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT);
2737 }
2738 W_REG(sii->osh, ®s->bankinfo, bankinfo);
2739 } else if (i == 0) {
2740 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
2741 *enable = 1;
2742 if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
2743 *protect = 1;
2744 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK)
2745 *remap = 1;
2746 }
2747 }
2748 }
2749 }
2750
2751 /* Return to previous state and core */
2752 if (!wasup)
2753 si_core_disable(sih, 0);
2754 si_setcoreidx(sih, origidx);
2755
2756 done:
2757 INTR_RESTORE(sii, intr_val);
2758 }
2759
2760 bool
si_socdevram_remap_isenb(si_t * sih)2761 si_socdevram_remap_isenb(si_t *sih)
2762 {
2763 si_info_t *sii = SI_INFO(sih);
2764 uint origidx;
2765 uint intr_val = 0;
2766 sbsocramregs_t *regs;
2767 bool wasup, remap = FALSE;
2768 uint corerev;
2769 uint32 extcinfo;
2770 uint8 nb;
2771 uint8 i;
2772 uint32 bankidx, bankinfo;
2773
2774 /* Block ints and save current core */
2775 INTR_OFF(sii, intr_val);
2776 origidx = si_coreidx(sih);
2777
2778 /* Switch to SOCRAM core */
2779 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2780 goto done;
2781
2782 /* Get info for determining size */
2783 if (!(wasup = si_iscoreup(sih)))
2784 si_core_reset(sih, 0, 0);
2785
2786 corerev = si_corerev(sih);
2787 if (corerev >= 16) {
2788 extcinfo = R_REG(sii->osh, ®s->extracoreinfo);
2789 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
2790 for (i = 0; i < nb; i++) {
2791 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2792 W_REG(sii->osh, ®s->bankidx, bankidx);
2793 bankinfo = R_REG(sii->osh, ®s->bankinfo);
2794 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
2795 remap = TRUE;
2796 break;
2797 }
2798 }
2799 }
2800
2801 /* Return to previous state and core */
2802 if (!wasup)
2803 si_core_disable(sih, 0);
2804 si_setcoreidx(sih, origidx);
2805
2806 done:
2807 INTR_RESTORE(sii, intr_val);
2808 return remap;
2809 }
2810
2811 bool
si_socdevram_pkg(si_t * sih)2812 si_socdevram_pkg(si_t *sih)
2813 {
2814 if (si_socdevram_size(sih) > 0)
2815 return TRUE;
2816 else
2817 return FALSE;
2818 }
2819
2820 uint32
si_socdevram_size(si_t * sih)2821 si_socdevram_size(si_t *sih)
2822 {
2823 si_info_t *sii = SI_INFO(sih);
2824 uint origidx;
2825 uint intr_val = 0;
2826 uint32 memsize = 0;
2827 sbsocramregs_t *regs;
2828 bool wasup;
2829 uint corerev;
2830
2831 /* Block ints and save current core */
2832 INTR_OFF(sii, intr_val);
2833 origidx = si_coreidx(sih);
2834
2835 /* Switch to SOCRAM core */
2836 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2837 goto done;
2838
2839 /* Get info for determining size */
2840 if (!(wasup = si_iscoreup(sih)))
2841 si_core_reset(sih, 0, 0);
2842
2843 corerev = si_corerev(sih);
2844 if (corerev >= 10) {
2845 uint32 extcinfo;
2846 uint8 nb;
2847 uint8 i;
2848
2849 extcinfo = R_REG(sii->osh, ®s->extracoreinfo);
2850 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
2851 for (i = 0; i < nb; i++)
2852 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
2853 }
2854
2855 /* Return to previous state and core */
2856 if (!wasup)
2857 si_core_disable(sih, 0);
2858 si_setcoreidx(sih, origidx);
2859
2860 done:
2861 INTR_RESTORE(sii, intr_val);
2862
2863 return memsize;
2864 }
2865
2866 uint32
si_socdevram_remap_size(si_t * sih)2867 si_socdevram_remap_size(si_t *sih)
2868 {
2869 si_info_t *sii = SI_INFO(sih);
2870 uint origidx;
2871 uint intr_val = 0;
2872 uint32 memsize = 0, banksz;
2873 sbsocramregs_t *regs;
2874 bool wasup;
2875 uint corerev;
2876 uint32 extcinfo;
2877 uint8 nb;
2878 uint8 i;
2879 uint32 bankidx, bankinfo;
2880
2881 /* Block ints and save current core */
2882 INTR_OFF(sii, intr_val);
2883 origidx = si_coreidx(sih);
2884
2885 /* Switch to SOCRAM core */
2886 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2887 goto done;
2888
2889 /* Get info for determining size */
2890 if (!(wasup = si_iscoreup(sih)))
2891 si_core_reset(sih, 0, 0);
2892
2893 corerev = si_corerev(sih);
2894 if (corerev >= 16) {
2895 extcinfo = R_REG(sii->osh, ®s->extracoreinfo);
2896 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
2897
2898 /*
2899 * FIX: A0 Issue: Max addressable is 512KB, instead 640KB
2900 * Only four banks are accessible to ARM
2901 */
2902 if ((corerev == 16) && (nb == 5))
2903 nb = 4;
2904
2905 for (i = 0; i < nb; i++) {
2906 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
2907 W_REG(sii->osh, ®s->bankidx, bankidx);
2908 bankinfo = R_REG(sii->osh, ®s->bankinfo);
2909 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
2910 banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
2911 memsize += banksz;
2912 } else {
2913 /* Account only consecutive banks for now */
2914 break;
2915 }
2916 }
2917 }
2918
2919 /* Return to previous state and core */
2920 if (!wasup)
2921 si_core_disable(sih, 0);
2922 si_setcoreidx(sih, origidx);
2923
2924 done:
2925 INTR_RESTORE(sii, intr_val);
2926
2927 return memsize;
2928 }
2929
2930 /** Return the RAM size of the SOCRAM core */
2931 uint32
si_socram_size(si_t * sih)2932 si_socram_size(si_t *sih)
2933 {
2934 si_info_t *sii = SI_INFO(sih);
2935 uint origidx;
2936 uint intr_val = 0;
2937
2938 sbsocramregs_t *regs;
2939 bool wasup;
2940 uint corerev;
2941 uint32 coreinfo;
2942 uint memsize = 0;
2943
2944 /* Block ints and save current core */
2945 INTR_OFF(sii, intr_val);
2946 origidx = si_coreidx(sih);
2947
2948 /* Switch to SOCRAM core */
2949 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
2950 goto done;
2951
2952 /* Get info for determining size */
2953 if (!(wasup = si_iscoreup(sih)))
2954 si_core_reset(sih, 0, 0);
2955 corerev = si_corerev(sih);
2956 coreinfo = R_REG(sii->osh, ®s->coreinfo);
2957
2958 /* Calculate size from coreinfo based on rev */
2959 if (corerev == 0)
2960 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
2961 else if (corerev < 3) {
2962 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
2963 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2964 } else if ((corerev <= 7) || (corerev == 12)) {
2965 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2966 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
2967 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
2968 if (lss != 0)
2969 nb --;
2970 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
2971 if (lss != 0)
2972 memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
2973 } else {
2974 uint8 i;
2975 uint nb;
2976 /* length of SRAM Banks increased for corerev greater than 23 */
2977 if (corerev >= 23) {
2978 nb = (coreinfo & (SRCI_SRNB_MASK | SRCI_SRNB_MASK_EXT)) >> SRCI_SRNB_SHIFT;
2979 } else {
2980 nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
2981 }
2982 for (i = 0; i < nb; i++)
2983 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
2984 }
2985
2986 /* Return to previous state and core */
2987 if (!wasup)
2988 si_core_disable(sih, 0);
2989 si_setcoreidx(sih, origidx);
2990
2991 done:
2992 INTR_RESTORE(sii, intr_val);
2993
2994 return memsize;
2995 }
2996
2997 /** Return the TCM-RAM size of the ARMCR4 core. */
2998 uint32
si_tcm_size(si_t * sih)2999 si_tcm_size(si_t *sih)
3000 {
3001 si_info_t *sii = SI_INFO(sih);
3002 uint origidx;
3003 uint intr_val = 0;
3004 volatile uint8 *regs;
3005 bool wasup = FALSE;
3006 uint32 corecap;
3007 uint memsize = 0;
3008 uint banku_size = 0;
3009 uint32 nab = 0;
3010 uint32 nbb = 0;
3011 uint32 totb = 0;
3012 uint32 bxinfo = 0;
3013 uint32 idx = 0;
3014 volatile uint32 *arm_cap_reg;
3015 volatile uint32 *arm_bidx;
3016 volatile uint32 *arm_binfo;
3017
3018 /* Block ints and save current core */
3019 INTR_OFF(sii, intr_val);
3020 origidx = si_coreidx(sih);
3021
3022 /* Switch to CR4 core */
3023 if (!(regs = si_setcore(sih, ARMCR4_CORE_ID, 0)))
3024 goto done;
3025
3026 /* Get info for determining size. If in reset, come out of reset,
3027 * but remain in halt
3028 */
3029 if (!sih->secureboot) {
3030 if (!(wasup = si_iscoreup(sih)))
3031 si_core_reset(sih, SICF_CPUHALT, SICF_CPUHALT);
3032 }
3033
3034 arm_cap_reg = (volatile uint32 *)(regs + SI_CR4_CAP);
3035 corecap = R_REG(sii->osh, arm_cap_reg);
3036
3037 nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT;
3038 nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT;
3039 totb = nab + nbb;
3040
3041 arm_bidx = (volatile uint32 *)(regs + SI_CR4_BANKIDX);
3042 arm_binfo = (volatile uint32 *)(regs + SI_CR4_BANKINFO);
3043 for (idx = 0; idx < totb; idx++) {
3044 W_REG(sii->osh, arm_bidx, idx);
3045
3046 bxinfo = R_REG(sii->osh, arm_binfo);
3047 if (bxinfo & ARMCR4_BUNITSZ_MASK) {
3048 banku_size = ARMCR4_BSZ_1K;
3049 } else {
3050 banku_size = ARMCR4_BSZ_8K;
3051 }
3052 memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * banku_size;
3053 }
3054
3055 /* Return to previous state and core */
3056 if (!sih->secureboot) {
3057 if (!wasup)
3058 si_core_disable(sih, 0);
3059 }
3060 si_setcoreidx(sih, origidx);
3061
3062 done:
3063 INTR_RESTORE(sii, intr_val);
3064
3065 return memsize;
3066 }
3067
3068 bool
si_has_flops(si_t * sih)3069 si_has_flops(si_t *sih)
3070 {
3071 uint origidx, cr4_rev;
3072
3073 /* Find out CR4 core revision */
3074 origidx = si_coreidx(sih);
3075 if (si_setcore(sih, ARMCR4_CORE_ID, 0)) {
3076 cr4_rev = si_corerev(sih);
3077 si_setcoreidx(sih, origidx);
3078
3079 if (cr4_rev == 1 || cr4_rev >= 3)
3080 return TRUE;
3081 }
3082 return FALSE;
3083 }
3084
3085 uint32
si_socram_srmem_size(si_t * sih)3086 si_socram_srmem_size(si_t *sih)
3087 {
3088 si_info_t *sii = SI_INFO(sih);
3089 uint origidx;
3090 uint intr_val = 0;
3091
3092 sbsocramregs_t *regs;
3093 bool wasup;
3094 uint corerev;
3095 uint32 coreinfo;
3096 uint memsize = 0;
3097
3098 if (CHIPID(sih->chip) == BCM43430_CHIP_ID ||
3099 CHIPID(sih->chip) == BCM43018_CHIP_ID) {
3100 return (64 * 1024);
3101 }
3102
3103 /* Block ints and save current core */
3104 INTR_OFF(sii, intr_val);
3105 origidx = si_coreidx(sih);
3106
3107 /* Switch to SOCRAM core */
3108 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
3109 goto done;
3110
3111 /* Get info for determining size */
3112 if (!(wasup = si_iscoreup(sih)))
3113 si_core_reset(sih, 0, 0);
3114 corerev = si_corerev(sih);
3115 coreinfo = R_REG(sii->osh, ®s->coreinfo);
3116
3117 /* Calculate size from coreinfo based on rev */
3118 if (corerev >= 16) {
3119 uint8 i;
3120 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
3121 for (i = 0; i < nb; i++) {
3122 W_REG(sii->osh, ®s->bankidx, i);
3123 if (R_REG(sii->osh, ®s->bankinfo) & SOCRAM_BANKINFO_RETNTRAM_MASK)
3124 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
3125 }
3126 }
3127
3128 /* Return to previous state and core */
3129 if (!wasup)
3130 si_core_disable(sih, 0);
3131 si_setcoreidx(sih, origidx);
3132
3133 done:
3134 INTR_RESTORE(sii, intr_val);
3135
3136 return memsize;
3137 }
3138
3139 #if !defined(_CFEZ_) || defined(CFG_WL)
3140 void
si_btcgpiowar(si_t * sih)3141 si_btcgpiowar(si_t *sih)
3142 {
3143 si_info_t *sii = SI_INFO(sih);
3144 uint origidx;
3145 uint intr_val = 0;
3146 chipcregs_t *cc;
3147
3148 /* Make sure that there is ChipCommon core present &&
3149 * UART_TX is strapped to 1
3150 */
3151 if (!(sih->cccaps & CC_CAP_UARTGPIO))
3152 return;
3153
3154 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
3155 INTR_OFF(sii, intr_val);
3156
3157 origidx = si_coreidx(sih);
3158
3159 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
3160 ASSERT(cc != NULL);
3161
3162 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
3163
3164 /* restore the original index */
3165 si_setcoreidx(sih, origidx);
3166
3167 INTR_RESTORE(sii, intr_val);
3168 }
3169
3170 void
si_chipcontrl_restore(si_t * sih,uint32 val)3171 si_chipcontrl_restore(si_t *sih, uint32 val)
3172 {
3173 si_info_t *sii = SI_INFO(sih);
3174 chipcregs_t *cc;
3175 uint origidx = si_coreidx(sih);
3176
3177 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
3178 SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
3179 return;
3180 }
3181 W_REG(sii->osh, &cc->chipcontrol, val);
3182 si_setcoreidx(sih, origidx);
3183 }
3184
3185 uint32
si_chipcontrl_read(si_t * sih)3186 si_chipcontrl_read(si_t *sih)
3187 {
3188 si_info_t *sii = SI_INFO(sih);
3189 chipcregs_t *cc;
3190 uint origidx = si_coreidx(sih);
3191 uint32 val;
3192
3193 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
3194 SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
3195 return -1;
3196 }
3197 val = R_REG(sii->osh, &cc->chipcontrol);
3198 si_setcoreidx(sih, origidx);
3199 return val;
3200 }
3201
3202 /** switch muxed pins, on: SROM, off: FEMCTRL. Called for a family of ac chips, not just 4360. */
3203 void
si_chipcontrl_srom4360(si_t * sih,bool on)3204 si_chipcontrl_srom4360(si_t *sih, bool on)
3205 {
3206 si_info_t *sii = SI_INFO(sih);
3207 chipcregs_t *cc;
3208 uint origidx = si_coreidx(sih);
3209 uint32 val;
3210
3211 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
3212 SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
3213 return;
3214 }
3215 val = R_REG(sii->osh, &cc->chipcontrol);
3216
3217 if (on) {
3218 val &= ~(CCTRL4360_SECI_MODE |
3219 CCTRL4360_BTSWCTRL_MODE |
3220 CCTRL4360_EXTRA_FEMCTRL_MODE |
3221 CCTRL4360_BT_LGCY_MODE |
3222 CCTRL4360_CORE2FEMCTRL4_ON);
3223
3224 W_REG(sii->osh, &cc->chipcontrol, val);
3225 } else {
3226 }
3227
3228 si_setcoreidx(sih, origidx);
3229 }
3230
3231 /**
3232 * The SROM clock is derived from the backplane clock. 4365 (200Mhz) and 43684 (240Mhz) have a fast
3233 * backplane clock that requires a higher-than-POR-default clock divisor ratio for the SROM clock.
3234 */
3235 void
si_srom_clk_set(si_t * sih)3236 si_srom_clk_set(si_t *sih)
3237 {
3238 si_info_t *sii = SI_INFO(sih);
3239 chipcregs_t *cc;
3240 uint origidx = si_coreidx(sih);
3241 uint32 val;
3242 uint32 divisor = 1;
3243
3244 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
3245 SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
3246 return;
3247 }
3248
3249 val = R_REG(sii->osh, &cc->clkdiv2);
3250 if (BCM4365_CHIP(sih->chip)) {
3251 divisor = CLKD2_SROMDIV_192; /* divide 200 by 192 -> SPROM clock ~ 1.04Mhz */
3252 } else {
3253 ASSERT(0);
3254 }
3255
3256 W_REG(sii->osh, &cc->clkdiv2, ((val & ~CLKD2_SROM) | divisor));
3257 si_setcoreidx(sih, origidx);
3258 }
3259 #endif // endif
3260
3261 void
si_pmu_avb_clk_set(si_t * sih,osl_t * osh,bool set_flag)3262 si_pmu_avb_clk_set(si_t *sih, osl_t *osh, bool set_flag)
3263 {
3264 }
3265
3266 void
si_btc_enable_chipcontrol(si_t * sih)3267 si_btc_enable_chipcontrol(si_t *sih)
3268 {
3269 si_info_t *sii = SI_INFO(sih);
3270 chipcregs_t *cc;
3271 uint origidx = si_coreidx(sih);
3272
3273 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) {
3274 SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__));
3275 return;
3276 }
3277
3278 /* BT fix */
3279 W_REG(sii->osh, &cc->chipcontrol,
3280 R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
3281
3282 si_setcoreidx(sih, origidx);
3283 }
3284
3285 /** cache device removed state */
si_set_device_removed(si_t * sih,bool status)3286 void si_set_device_removed(si_t *sih, bool status)
3287 {
3288 si_info_t *sii = SI_INFO(sih);
3289
3290 sii->device_removed = status;
3291 }
3292
3293 /** check if the device is removed */
3294 bool
si_deviceremoved(si_t * sih)3295 si_deviceremoved(si_t *sih)
3296 {
3297 uint32 w;
3298 si_info_t *sii = SI_INFO(sih);
3299
3300 if (sii->device_removed) {
3301 return TRUE;
3302 }
3303
3304 switch (BUSTYPE(sih->bustype)) {
3305 case PCI_BUS:
3306 ASSERT(SI_INFO(sih)->osh != NULL);
3307 w = OSL_PCI_READ_CONFIG(SI_INFO(sih)->osh, PCI_CFG_VID, sizeof(uint32));
3308 if ((w & 0xFFFF) != VENDOR_BROADCOM)
3309 return TRUE;
3310 break;
3311 }
3312 return FALSE;
3313 }
3314
3315 bool
si_is_warmboot(void)3316 si_is_warmboot(void)
3317 {
3318
3319 #ifdef BCMULP
3320 return (boot_type == WARM_BOOT);
3321 #else
3322 return FALSE;
3323 #endif // endif
3324 }
3325
3326 bool
si_is_sprom_available(si_t * sih)3327 si_is_sprom_available(si_t *sih)
3328 {
3329 if (CCREV(sih->ccrev) >= 31) {
3330 si_info_t *sii;
3331 uint origidx;
3332 chipcregs_t *cc;
3333 uint32 sromctrl;
3334
3335 if ((sih->cccaps & CC_CAP_SROM) == 0)
3336 return FALSE;
3337
3338 sii = SI_INFO(sih);
3339 origidx = sii->curidx;
3340 cc = si_setcoreidx(sih, SI_CC_IDX);
3341 ASSERT(cc);
3342 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
3343 si_setcoreidx(sih, origidx);
3344 return (sromctrl & SRC_PRESENT);
3345 }
3346
3347 switch (CHIPID(sih->chip)) {
3348 case BCM43018_CHIP_ID:
3349 case BCM43430_CHIP_ID:
3350 return FALSE;
3351 case BCM4335_CHIP_ID:
3352 CASE_BCM4345_CHIP:
3353 return ((sih->chipst & CST4335_SPROM_MASK) &&
3354 !(sih->chipst & CST4335_SFLASH_MASK));
3355 case BCM4349_CHIP_GRPID:
3356 return (sih->chipst & CST4349_SPROM_PRESENT) != 0;
3357 case BCM53573_CHIP_GRPID:
3358 return FALSE; /* SPROM PRESENT is not defined for 53573 as of now */
3359 case BCM4364_CHIP_ID:
3360 return (sih->chipst & CST4364_SPROM_PRESENT) != 0;
3361 case BCM4369_CHIP_GRPID:
3362 if (CHIPREV(sih->chiprev) == 0) {
3363 /* WAR for 4369a0: HW4369-1729. no sprom, default to otp always. */
3364 return 0;
3365 } else {
3366 return (sih->chipst & CST4369_SPROM_PRESENT) != 0;
3367 }
3368 #ifdef CHIPS_CUSTOMER_HW6
3369 case BCM4368_CHIP_ID:
3370 return FALSE;
3371 #endif /* CHIPS_CUSTOMER_HW6 */
3372 case BCM4347_CHIP_GRPID:
3373 return (sih->chipst & CST4347_SPROM_PRESENT) != 0;
3374 break;
3375 case BCM4350_CHIP_ID:
3376 case BCM4354_CHIP_ID:
3377 case BCM43556_CHIP_ID:
3378 case BCM43558_CHIP_ID:
3379 case BCM43566_CHIP_ID:
3380 case BCM43568_CHIP_ID:
3381 case BCM43569_CHIP_ID:
3382 case BCM43570_CHIP_ID:
3383 case BCM4358_CHIP_ID:
3384 return (sih->chipst & CST4350_SPROM_PRESENT) != 0;
3385 CASE_BCM43602_CHIP:
3386 return (sih->chipst & CST43602_SPROM_PRESENT) != 0;
3387 case BCM43131_CHIP_ID:
3388 case BCM43217_CHIP_ID:
3389 case BCM43428_CHIP_ID:
3390 return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
3391 case BCM4373_CHIP_ID:
3392 case BCM43012_CHIP_ID:
3393 return FALSE;
3394 default:
3395 return TRUE;
3396 }
3397 }
3398
si_get_sromctl(si_t * sih)3399 uint32 si_get_sromctl(si_t *sih)
3400 {
3401 chipcregs_t *cc;
3402 uint origidx = si_coreidx(sih);
3403 uint32 sromctl;
3404 osl_t *osh = si_osh(sih);
3405
3406 cc = si_setcoreidx(sih, SI_CC_IDX);
3407 ASSERT((uintptr)cc);
3408
3409 sromctl = R_REG(osh, &cc->sromcontrol);
3410
3411 /* return to the original core */
3412 si_setcoreidx(sih, origidx);
3413 return sromctl;
3414 }
3415
si_set_sromctl(si_t * sih,uint32 value)3416 int si_set_sromctl(si_t *sih, uint32 value)
3417 {
3418 chipcregs_t *cc;
3419 uint origidx = si_coreidx(sih);
3420 osl_t *osh = si_osh(sih);
3421 int ret = BCME_OK;
3422
3423 cc = si_setcoreidx(sih, SI_CC_IDX);
3424 ASSERT((uintptr)cc);
3425
3426 /* get chipcommon rev */
3427 if (si_corerev(sih) >= 32) {
3428 /* SpromCtrl is only accessible if CoreCapabilities.SpromSupported and
3429 * SpromPresent is 1.
3430 */
3431 if ((R_REG(osh, &cc->capabilities) & CC_CAP_SROM) != 0 &&
3432 (R_REG(osh, &cc->sromcontrol) & SRC_PRESENT)) {
3433 W_REG(osh, &cc->sromcontrol, value);
3434 } else {
3435 ret = BCME_NODEVICE;
3436 }
3437 } else {
3438 ret = BCME_UNSUPPORTED;
3439 }
3440
3441 /* return to the original core */
3442 si_setcoreidx(sih, origidx);
3443
3444 return ret;
3445 }
3446
3447 uint
si_core_wrapperreg(si_t * sih,uint32 coreidx,uint32 offset,uint32 mask,uint32 val)3448 si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val)
3449 {
3450 uint origidx, intr_val = 0;
3451 uint ret_val;
3452 si_info_t *sii = SI_INFO(sih);
3453
3454 origidx = si_coreidx(sih);
3455
3456 INTR_OFF(sii, intr_val);
3457 si_setcoreidx(sih, coreidx);
3458
3459 ret_val = si_wrapperreg(sih, offset, mask, val);
3460
3461 /* return to the original core */
3462 si_setcoreidx(sih, origidx);
3463 INTR_RESTORE(sii, intr_val);
3464 return ret_val;
3465 }
3466
3467 /* cleanup the timer from the host when ARM is been halted
3468 * without a chance for ARM cleanup its resources
3469 * If left not cleanup, Intr from a software timer can still
3470 * request HT clk when ARM is halted.
3471 */
3472 uint32
si_pmu_res_req_timer_clr(si_t * sih)3473 si_pmu_res_req_timer_clr(si_t *sih)
3474 {
3475 uint32 mask;
3476
3477 mask = PRRT_REQ_ACTIVE | PRRT_INTEN | PRRT_HT_REQ;
3478 mask <<= 14;
3479 /* clear mask bits */
3480 pmu_corereg(sih, SI_CC_IDX, res_req_timer, mask, 0);
3481 /* readback to ensure write completes */
3482 return pmu_corereg(sih, SI_CC_IDX, res_req_timer, 0, 0);
3483 }
3484
3485 /** turn on/off rfldo */
3486 void
si_pmu_rfldo(si_t * sih,bool on)3487 si_pmu_rfldo(si_t *sih, bool on)
3488 {
3489 }
3490
3491 /* Caller of this function should make sure is on PCIE core
3492 * Used in pciedev.c.
3493 */
3494 void
si_pcie_disable_oobselltr(si_t * sih)3495 si_pcie_disable_oobselltr(si_t *sih)
3496 {
3497 ASSERT(si_coreid(sih) == PCIE2_CORE_ID);
3498 if (PCIECOREREV(sih->buscorerev) >= 23)
3499 si_wrapperreg(sih, AI_OOBSELIND74, ~0, 0);
3500 else
3501 si_wrapperreg(sih, AI_OOBSELIND30, ~0, 0);
3502 }
3503
3504 void
si_pcie_ltr_war(si_t * sih)3505 si_pcie_ltr_war(si_t *sih)
3506 {
3507 }
3508
3509 void
si_pcie_hw_LTR_war(si_t * sih)3510 si_pcie_hw_LTR_war(si_t *sih)
3511 {
3512 }
3513
3514 void
si_pciedev_reg_pm_clk_period(si_t * sih)3515 si_pciedev_reg_pm_clk_period(si_t *sih)
3516 {
3517 }
3518
3519 void
si_pciedev_crwlpciegen2(si_t * sih)3520 si_pciedev_crwlpciegen2(si_t *sih)
3521 {
3522 }
3523
3524 void
si_pcie_prep_D3(si_t * sih,bool enter_D3)3525 si_pcie_prep_D3(si_t *sih, bool enter_D3)
3526 {
3527 }
3528
3529 #if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT)
3530 uint32
si_clear_backplane_to_per_core(si_t * sih,uint coreid,uint coreunit,void * wrap)3531 si_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wrap)
3532 {
3533 if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
3534 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS)) {
3535 return ai_clear_backplane_to_per_core(sih, coreid, coreunit, wrap);
3536 }
3537
3538 return AXI_WRAP_STS_NONE;
3539 }
3540 #endif /* AXI_TIMEOUTS || BCM_BACKPLANE_TIMEOUT */
3541
3542 uint32
si_clear_backplane_to(si_t * sih)3543 si_clear_backplane_to(si_t *sih)
3544 {
3545 if ((CHIPTYPE(sih->socitype) == SOCI_AI) ||
3546 (CHIPTYPE(sih->socitype) == SOCI_DVTBUS)) {
3547 return ai_clear_backplane_to(sih);
3548 }
3549
3550 return 0;
3551 }
3552
3553 void
si_update_backplane_timeouts(si_t * sih,bool enable,uint32 timeout_exp,uint32 cid)3554 si_update_backplane_timeouts(si_t *sih, bool enable, uint32 timeout_exp, uint32 cid)
3555 {
3556 #if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT)
3557 /* Enable only for AXI */
3558 if (CHIPTYPE(sih->socitype) != SOCI_AI) {
3559 return;
3560 }
3561
3562 ai_update_backplane_timeouts(sih, enable, timeout_exp, cid);
3563 #endif /* AXI_TIMEOUTS || BCM_BACKPLANE_TIMEOUT */
3564 }
3565
3566 /*
3567 * This routine adds the AXI timeouts for
3568 * chipcommon, pcie and ARM slave wrappers
3569 */
3570 void
si_slave_wrapper_add(si_t * sih)3571 si_slave_wrapper_add(si_t *sih)
3572 {
3573 #if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT)
3574 uint32 axi_to = 0;
3575
3576 /* Enable only for AXI */
3577 if ((CHIPTYPE(sih->socitype) != SOCI_AI) &&
3578 (CHIPTYPE(sih->socitype) != SOCI_DVTBUS)) {
3579 return;
3580 }
3581
3582 if (CHIPID(sih->chip) == BCM4345_CHIP_ID && CHIPREV(sih->chiprev) >= 6) {
3583 si_info_t *sii = SI_INFO(sih);
3584
3585 int wrapper_idx = (int)sii->axi_num_wrappers - 1;
3586
3587 ASSERT(wrapper_idx >= 0); /* axi_wrapper[] not initialised */
3588 do {
3589 if (sii->axi_wrapper[wrapper_idx].wrapper_type == AI_SLAVE_WRAPPER &&
3590 sii->axi_wrapper[wrapper_idx].cid == 0xfff) {
3591 sii->axi_wrapper[wrapper_idx].wrapper_addr = 0x1810b000;
3592 break;
3593 }
3594 } while (wrapper_idx-- > 0);
3595 ASSERT(wrapper_idx >= 0); /* all addresses valid for the chiprev under test */
3596 }
3597
3598 if (BCM4347_CHIP(sih->chip)) {
3599 axi_to = AXI_TO_VAL_4347;
3600 }
3601 else {
3602 axi_to = AXI_TO_VAL;
3603 }
3604
3605 /* All required slave wrappers are added in ai_scan */
3606 ai_update_backplane_timeouts(sih, TRUE, axi_to, 0);
3607
3608 #ifdef DISABLE_PCIE2_AXI_TIMEOUT
3609 ai_update_backplane_timeouts(sih, FALSE, 0, PCIE_CORE_ID);
3610 ai_update_backplane_timeouts(sih, FALSE, 0, PCIE2_CORE_ID);
3611 #endif // endif
3612
3613 #endif /* AXI_TIMEOUTS || BCM_BACKPLANE_TIMEOUT */
3614
3615 }
3616
3617 void
si_pll_sr_reinit(si_t * sih)3618 si_pll_sr_reinit(si_t *sih)
3619 {
3620 }
3621
3622 /* Programming d11 core oob settings for 4364
3623 * WARs for HW4364-237 and HW4364-166
3624 */
3625 void
si_config_4364_d11_oob(si_t * sih,uint coreid)3626 si_config_4364_d11_oob(si_t *sih, uint coreid)
3627 {
3628 uint save_idx;
3629
3630 save_idx = si_coreidx(sih);
3631 si_setcore(sih, coreid, 0);
3632 si_wrapperreg(sih, AI_OOBSELINC30, ~0, 0x81828180);
3633 si_wrapperreg(sih, AI_OOBSELINC74, ~0, 0x87868183);
3634 si_wrapperreg(sih, AI_OOBSELOUTB74, ~0, 0x84858484);
3635 si_setcore(sih, coreid, 1);
3636 si_wrapperreg(sih, AI_OOBSELINC30, ~0, 0x81828180);
3637 si_wrapperreg(sih, AI_OOBSELINC74, ~0, 0x87868184);
3638 si_wrapperreg(sih, AI_OOBSELOUTB74, ~0, 0x84868484);
3639 si_setcoreidx(sih, save_idx);
3640 }
3641
3642 void
si_pll_closeloop(si_t * sih)3643 si_pll_closeloop(si_t *sih)
3644 {
3645 #if defined(SAVERESTORE)
3646 uint32 data;
3647
3648 /* disable PLL open loop operation */
3649 switch (CHIPID(sih->chip)) {
3650 #ifdef SAVERESTORE
3651 case BCM43018_CHIP_ID:
3652 case BCM43430_CHIP_ID:
3653 if (SR_ENAB() && sr_isenab(sih)) {
3654 /* read back the pll openloop state */
3655 data = si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL8, 0, 0);
3656 /* current mode is openloop (possible POR) */
3657 if ((data & PMU1_PLLCTL8_OPENLOOP_MASK) != 0) {
3658 si_pmu_pllcontrol(sih, PMU1_PLL0_PLLCTL8,
3659 PMU1_PLLCTL8_OPENLOOP_MASK, 0);
3660 si_pmu_pllupd(sih);
3661 }
3662 }
3663 break;
3664 #endif /* SAVERESTORE */
3665 case BCM4347_CHIP_GRPID:
3666 case BCM4369_CHIP_GRPID:
3667 si_pmu_chipcontrol(sih, PMU_CHIPCTL1,
3668 PMU_CC1_ENABLE_CLOSED_LOOP_MASK, PMU_CC1_ENABLE_CLOSED_LOOP);
3669 break;
3670 default:
3671 /* any unsupported chip bail */
3672 return;
3673 }
3674 #endif // endif
3675 }
3676
3677 #if defined(BCMSRPWR) && !defined(BCMSRPWR_DISABLED)
3678 bool _bcmsrpwr = TRUE;
3679 #else
3680 bool _bcmsrpwr = FALSE;
3681 #endif // endif
3682
3683 #define PWRREQ_OFFSET(sih) OFFSETOF(chipcregs_t, powerctl)
3684
3685 static void
si_corereg_pciefast_write(si_t * sih,uint regoff,uint val)3686 si_corereg_pciefast_write(si_t *sih, uint regoff, uint val)
3687 {
3688 volatile uint32 *r = NULL;
3689 si_info_t *sii = SI_INFO(sih);
3690
3691 ASSERT((BUSTYPE(sih->bustype) == PCI_BUS));
3692
3693 r = (volatile uint32 *)((volatile char *)sii->curmap +
3694 PCI_16KB0_PCIREGS_OFFSET + regoff);
3695
3696 W_REG(sii->osh, r, val);
3697 }
3698
3699 static uint
si_corereg_pciefast_read(si_t * sih,uint regoff)3700 si_corereg_pciefast_read(si_t *sih, uint regoff)
3701 {
3702 volatile uint32 *r = NULL;
3703 si_info_t *sii = SI_INFO(sih);
3704
3705 ASSERT((BUSTYPE(sih->bustype) == PCI_BUS));
3706
3707 r = (volatile uint32 *)((volatile char *)sii->curmap +
3708 PCI_16KB0_PCIREGS_OFFSET + regoff);
3709
3710 return R_REG(sii->osh, r);
3711 }
3712
3713 uint32
si_srpwr_request(si_t * sih,uint32 mask,uint32 val)3714 si_srpwr_request(si_t *sih, uint32 mask, uint32 val)
3715 {
3716 uint32 r, offset = (BUSTYPE(sih->bustype) == SI_BUS) ?
3717 OFFSETOF(chipcregs_t, powerctl) : PWRREQ_OFFSET(sih);
3718 uint32 mask2 = mask;
3719 uint32 val2 = val;
3720 volatile uint32 *fast_srpwr_addr = (volatile uint32 *)((uintptr)SI_ENUM_BASE(sih)
3721 + (uintptr)offset);
3722
3723 if (mask || val) {
3724 mask <<= SRPWR_REQON_SHIFT;
3725 val <<= SRPWR_REQON_SHIFT;
3726
3727 /* Return if requested power request is already set */
3728 if (BUSTYPE(sih->bustype) == SI_BUS) {
3729 r = R_REG(OSH_NULL, fast_srpwr_addr);
3730 } else {
3731 r = si_corereg_pciefast_read(sih, offset);
3732 }
3733
3734 if ((r & mask) == val) {
3735 return r;
3736 }
3737
3738 r = (r & ~mask) | val;
3739
3740 if (BUSTYPE(sih->bustype) == SI_BUS) {
3741 W_REG(OSH_NULL, fast_srpwr_addr, r);
3742 r = R_REG(OSH_NULL, fast_srpwr_addr);
3743 } else {
3744 si_corereg_pciefast_write(sih, offset, r);
3745 r = si_corereg_pciefast_read(sih, offset);
3746 }
3747
3748 if (val2) {
3749 if ((r & (mask2 << SRPWR_STATUS_SHIFT)) ==
3750 (val2 << SRPWR_STATUS_SHIFT)) {
3751 return r;
3752 }
3753 si_srpwr_stat_spinwait(sih, mask2, val2);
3754 }
3755 } else {
3756 if (BUSTYPE(sih->bustype) == SI_BUS) {
3757 r = R_REG(OSH_NULL, fast_srpwr_addr);
3758 } else {
3759 r = si_corereg_pciefast_read(sih, offset);
3760 }
3761 }
3762
3763 return r;
3764 }
3765
3766 uint32
si_srpwr_stat_spinwait(si_t * sih,uint32 mask,uint32 val)3767 si_srpwr_stat_spinwait(si_t *sih, uint32 mask, uint32 val)
3768 {
3769 uint32 r, offset = (BUSTYPE(sih->bustype) == SI_BUS) ?
3770 OFFSETOF(chipcregs_t, powerctl) : PWRREQ_OFFSET(sih);
3771 volatile uint32 *fast_srpwr_addr = (volatile uint32 *)((uintptr)SI_ENUM_BASE(sih)
3772 + (uintptr)offset);
3773
3774 ASSERT(mask);
3775 ASSERT(val);
3776
3777 /* spinwait on pwrstatus */
3778 mask <<= SRPWR_STATUS_SHIFT;
3779 val <<= SRPWR_STATUS_SHIFT;
3780
3781 if (BUSTYPE(sih->bustype) == SI_BUS) {
3782 SPINWAIT(((R_REG(OSH_NULL, fast_srpwr_addr) & mask) != val),
3783 PMU_MAX_TRANSITION_DLY);
3784 r = R_REG(OSH_NULL, fast_srpwr_addr) & mask;
3785 ASSERT(r == val);
3786 } else {
3787 SPINWAIT(((si_corereg_pciefast_read(sih, offset) & mask) != val),
3788 PMU_MAX_TRANSITION_DLY);
3789 r = si_corereg_pciefast_read(sih, offset) & mask;
3790 ASSERT(r == val);
3791 }
3792
3793 r = (r >> SRPWR_STATUS_SHIFT) & SRPWR_DMN_ALL_MASK(sih);
3794
3795 return r;
3796 }
3797
3798 uint32
si_srpwr_stat(si_t * sih)3799 si_srpwr_stat(si_t *sih)
3800 {
3801 uint32 r, offset = (BUSTYPE(sih->bustype) == SI_BUS) ?
3802 OFFSETOF(chipcregs_t, powerctl) : PWRREQ_OFFSET(sih);
3803 uint cidx = (BUSTYPE(sih->bustype) == SI_BUS) ? SI_CC_IDX : sih->buscoreidx;
3804
3805 if (BUSTYPE(sih->bustype) == SI_BUS) {
3806 r = si_corereg(sih, cidx, offset, 0, 0);
3807 } else {
3808 r = si_corereg_pciefast_read(sih, offset);
3809 }
3810
3811 r = (r >> SRPWR_STATUS_SHIFT) & SRPWR_DMN_ALL_MASK(sih);
3812
3813 return r;
3814 }
3815
3816 uint32
si_srpwr_domain(si_t * sih)3817 si_srpwr_domain(si_t *sih)
3818 {
3819 uint32 r, offset = (BUSTYPE(sih->bustype) == SI_BUS) ?
3820 OFFSETOF(chipcregs_t, powerctl) : PWRREQ_OFFSET(sih);
3821 uint cidx = (BUSTYPE(sih->bustype) == SI_BUS) ? SI_CC_IDX : sih->buscoreidx;
3822
3823 if (BUSTYPE(sih->bustype) == SI_BUS) {
3824 r = si_corereg(sih, cidx, offset, 0, 0);
3825 } else {
3826 r = si_corereg_pciefast_read(sih, offset);
3827 }
3828
3829 r = (r >> SRPWR_DMN_ID_SHIFT) & SRPWR_DMN_ID_MASK;
3830
3831 return r;
3832 }
3833
3834 uint32
si_srpwr_domain_all_mask(si_t * sih)3835 si_srpwr_domain_all_mask(si_t *sih)
3836 {
3837 uint32 mask = SRPWR_DMN0_PCIE_MASK |
3838 SRPWR_DMN1_ARMBPSD_MASK |
3839 SRPWR_DMN2_MACAUX_MASK |
3840 SRPWR_DMN3_MACMAIN_MASK;
3841
3842 if (si_scan_core_present(sih)) {
3843 mask |= SRPWR_DMN4_MACSCAN_MASK;
3844 }
3845
3846 return mask;
3847 }
3848
3849 /* Utility API to read/write the raw registers with absolute address.
3850 * This function can be invoked from either FW or host driver.
3851 */
3852 uint32
si_raw_reg(si_t * sih,uint32 reg,uint32 val,uint32 wrire_req)3853 si_raw_reg(si_t *sih, uint32 reg, uint32 val, uint32 wrire_req)
3854 {
3855 si_info_t *sii = SI_INFO(sih);
3856 uint32 address_space = reg & ~0xFFF;
3857 volatile uint32 * addr = (void*)(uintptr)(reg);
3858 uint32 prev_value = 0;
3859 uint32 cfg_reg = 0;
3860
3861 if (sii == NULL) {
3862 return 0;
3863 }
3864
3865 /* No need to translate the absolute address on SI bus */
3866 if (BUSTYPE(sih->bustype) == SI_BUS) {
3867 goto skip_cfg;
3868 }
3869
3870 /* This API supports only the PCI host interface */
3871 if (BUSTYPE(sih->bustype) != PCI_BUS) {
3872 return ID32_INVALID;
3873 }
3874
3875 if (PCIE_GEN2(sii)) {
3876 /* Use BAR0 Secondary window is PCIe Gen2.
3877 * Set the secondary BAR0 Window to current register of interest
3878 */
3879 addr = (volatile uint32*)(((volatile uint8*)sii->curmap) +
3880 PCI_SEC_BAR0_WIN_OFFSET + (reg & 0xfff));
3881 cfg_reg = PCIE2_BAR0_CORE2_WIN;
3882
3883 } else {
3884 /* PCIe Gen1 do not have secondary BAR0 window.
3885 * reuse the BAR0 WIN2
3886 */
3887 addr = (volatile uint32*)(((volatile uint8*)sii->curmap) +
3888 PCI_BAR0_WIN2_OFFSET + (reg & 0xfff));
3889 cfg_reg = PCI_BAR0_WIN2;
3890 }
3891
3892 prev_value = OSL_PCI_READ_CONFIG(sii->osh, cfg_reg, 4);
3893
3894 if (prev_value != address_space) {
3895 OSL_PCI_WRITE_CONFIG(sii->osh, cfg_reg,
3896 sizeof(uint32), address_space);
3897 } else {
3898 prev_value = 0;
3899 }
3900
3901 skip_cfg:
3902 if (wrire_req) {
3903 W_REG(sii->osh, addr, val);
3904 } else {
3905 val = R_REG(sii->osh, addr);
3906 }
3907
3908 if (prev_value) {
3909 /* Restore BAR0 WIN2 for PCIE GEN1 devices */
3910 OSL_PCI_WRITE_CONFIG(sii->osh,
3911 cfg_reg, sizeof(uint32), prev_value);
3912 }
3913
3914 return val;
3915 }
3916
3917 uint8
si_lhl_ps_mode(si_t * sih)3918 si_lhl_ps_mode(si_t *sih)
3919 {
3920 si_info_t *sii = SI_INFO(sih);
3921 return sii->lhl_ps_mode;
3922 }
3923
3924 bool
BCMRAMFN(si_scan_core_present)3925 BCMRAMFN(si_scan_core_present)(si_t *sih)
3926 {
3927 return ((si_numcoreunits(sih, D11_CORE_ID) >= 2) &&
3928 (si_numcoreunits(sih, SR_CORE_ID) > 4));
3929 }
3930