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