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