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