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