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