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