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