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