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