blob: dcd0e389bb704be09cf623003fb9a185f32265f8 [file] [log] [blame]
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001/*
2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
4 *
Dmitry Shmidt83252322012-03-16 12:52:00 -07005 * Copyright (C) 1999-2012, Broadcom Corporation
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07006 *
Dmitry Shmidt83252322012-03-16 12:52:00 -07007 * Unless you and Broadcom execute a separate written software license
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07008 * agreement governing use of this software, this software is licensed to you
9 * under the terms of the GNU General Public License version 2 (the "GPL"),
10 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11 * following added to such license:
12 *
13 * As a special exception, the copyright holders of this software give you
14 * permission to link this software with independent modules, and to copy and
15 * distribute the resulting executable under terms of your choice, provided that
16 * you also meet, for each linked independent module, the terms and conditions of
17 * the license of that module. An independent module is a module which is not
18 * derived from this software. The special exception does not apply to any
19 * modifications of the software.
20 *
21 * Notwithstanding the above, under no circumstances may you combine this
22 * software in any way with any other Broadcom software provided under a license
23 * other than the GPL, without Broadcom's express prior written consent.
24 *
Dmitry Shmidt66981be2012-05-15 17:25:40 -070025 * $Id: siutils.c 328733 2012-04-20 14:49:55Z $
Dmitry Shmidt8ce17272011-05-24 11:14:33 -070026 */
27
Dmitry Shmidt83252322012-03-16 12:52:00 -070028#include <bcm_cfg.h>
Dmitry Shmidt8ce17272011-05-24 11:14:33 -070029#include <typedefs.h>
30#include <bcmdefs.h>
31#include <osl.h>
32#include <bcmutils.h>
33#include <siutils.h>
34#include <bcmdevs.h>
35#include <hndsoc.h>
36#include <sbchipc.h>
37#include <pcicfg.h>
38#include <sbpcmcia.h>
39#include <sbsocram.h>
40#include <bcmsdh.h>
41#include <sdio.h>
42#include <sbsdio.h>
43#include <sbhnddma.h>
44#include <sbsdpcmdev.h>
45#include <bcmsdpcm.h>
46#include <hndpmu.h>
47
48#include "siutils_priv.h"
49
50/* local prototypes */
51static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
52 uint bustype, void *sdh, char **vars, uint *varsz);
53static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
54static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
55 uint *origidx, void *regs);
56
57
Dmitry Shmidt83252322012-03-16 12:52:00 -070058
Dmitry Shmidt8ce17272011-05-24 11:14:33 -070059/* global variable to indicate reservation/release of gpio's */
60static uint32 si_gpioreservation = 0;
61
62/* global flag to prevent shared resources from being initialized multiple times in si_attach() */
63
Dmitry Shmidt83252322012-03-16 12:52:00 -070064int do_4360_pcie2_war = 0;
65
Dmitry Shmidt8ce17272011-05-24 11:14:33 -070066/*
67 * Allocate a si handle.
68 * devid - pci device id (used to determine chip#)
69 * osh - opaque OS handle
70 * regs - virtual address of initial core registers
71 * bustype - pci/pcmcia/sb/sdio/etc
72 * vars - pointer to a pointer area for "environment" variables
73 * varsz - pointer to int to return the size of the vars
74 */
75si_t *
76si_attach(uint devid, osl_t *osh, void *regs,
77 uint bustype, void *sdh, char **vars, uint *varsz)
78{
79 si_info_t *sii;
80
81 /* alloc si_info_t */
82 if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
83 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
84 return (NULL);
85 }
86
87 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
88 MFREE(osh, sii, sizeof(si_info_t));
89 return (NULL);
90 }
91 sii->vars = vars ? *vars : NULL;
92 sii->varsz = varsz ? *varsz : 0;
93
94 return (si_t *)sii;
95}
96
97/* global kernel resource */
98static si_info_t ksii;
99
100static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */
101
102/* generic kernel variant of si_attach() */
103si_t *
104si_kattach(osl_t *osh)
105{
106 static bool ksii_attached = FALSE;
107
108 if (!ksii_attached) {
109 void *regs;
110 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
111
112 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
113 SI_BUS, NULL,
114 osh != SI_OSH ? &ksii.vars : NULL,
115 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
116 SI_ERROR(("si_kattach: si_doattach failed\n"));
117 REG_UNMAP(regs);
118 return NULL;
119 }
120 REG_UNMAP(regs);
121
122 /* save ticks normalized to ms for si_watchdog_ms() */
123 if (PMUCTL_ENAB(&ksii.pub)) {
Dmitry Shmidt83252322012-03-16 12:52:00 -0700124 /* based on 32KHz ILP clock */
125 wd_msticks = 32;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700126 } else {
127 wd_msticks = ALP_CLOCK / 1000;
128 }
129
130 ksii_attached = TRUE;
131 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
132 ksii.pub.ccrev, wd_msticks));
133 }
134
135 return &ksii.pub;
136}
137
138
139static bool
140si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
141{
142 /* need to set memseg flag for CF card first before any sb registers access */
143 if (BUSTYPE(bustype) == PCMCIA_BUS)
144 sii->memseg = TRUE;
145
146
147 if (BUSTYPE(bustype) == SDIO_BUS) {
148 int err;
149 uint8 clkset;
150
151 /* Try forcing SDIO core to do ALPAvail request only */
152 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
153 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
154 if (!err) {
155 uint8 clkval;
156
157 /* If register supported, wait for ALPAvail and then force ALP */
158 clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
159 if ((clkval & ~SBSDIO_AVBITS) == clkset) {
160 SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
161 SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)),
162 PMU_MAX_TRANSITION_DLY);
163 if (!SBSDIO_ALPAV(clkval)) {
164 SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n",
165 clkval));
166 return FALSE;
167 }
168 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
169 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
170 clkset, &err);
171 OSL_DELAY(65);
172 }
173 }
174
175 /* Also, disable the extra SDIO pull-ups */
176 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
177 }
178
179
180 return TRUE;
181}
182
183static bool
184si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
185 uint *origidx, void *regs)
186{
Dmitry Shmidt83252322012-03-16 12:52:00 -0700187 bool pci, pcie, pcie_gen2 = FALSE;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700188 uint i;
189 uint pciidx, pcieidx, pcirev, pcierev;
190
191 cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
192 ASSERT((uintptr)cc);
193
194 /* get chipcommon rev */
195 sii->pub.ccrev = (int)si_corerev(&sii->pub);
196
197 /* get chipcommon chipstatus */
198 if (sii->pub.ccrev >= 11)
199 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
200
201 /* get chipcommon capabilites */
202 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
203 /* get chipcommon extended capabilities */
204
205 if (sii->pub.ccrev >= 35)
206 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
207
208 /* get pmu rev and caps */
209 if (sii->pub.cccaps & CC_CAP_PMU) {
210 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
211 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
212 }
213
214 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
215 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
216 sii->pub.pmucaps));
217
218 /* figure out bus/orignal core idx */
219 sii->pub.buscoretype = NODEV_CORE_ID;
220 sii->pub.buscorerev = (uint)NOREV;
221 sii->pub.buscoreidx = BADIDX;
222
223 pci = pcie = FALSE;
224 pcirev = pcierev = (uint)NOREV;
225 pciidx = pcieidx = BADIDX;
226
227 for (i = 0; i < sii->numcores; i++) {
228 uint cid, crev;
229
230 si_setcoreidx(&sii->pub, i);
231 cid = si_coreid(&sii->pub);
232 crev = si_corerev(&sii->pub);
233
234 /* Display cores found */
235 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
236 i, cid, crev, sii->coresba[i], sii->regs[i]));
237
238 if (BUSTYPE(bustype) == PCI_BUS) {
239 if (cid == PCI_CORE_ID) {
240 pciidx = i;
241 pcirev = crev;
242 pci = TRUE;
Dmitry Shmidt83252322012-03-16 12:52:00 -0700243 } else if ((cid == PCIE_CORE_ID) || (cid == PCIE2_CORE_ID)) {
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700244 pcieidx = i;
245 pcierev = crev;
246 pcie = TRUE;
Dmitry Shmidt83252322012-03-16 12:52:00 -0700247 if (cid == PCIE2_CORE_ID)
248 pcie_gen2 = TRUE;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700249 }
250 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
251 (cid == PCMCIA_CORE_ID)) {
252 sii->pub.buscorerev = crev;
253 sii->pub.buscoretype = cid;
254 sii->pub.buscoreidx = i;
255 }
256 else if (((BUSTYPE(bustype) == SDIO_BUS) ||
257 (BUSTYPE(bustype) == SPI_BUS)) &&
258 ((cid == PCMCIA_CORE_ID) ||
259 (cid == SDIOD_CORE_ID))) {
260 sii->pub.buscorerev = crev;
261 sii->pub.buscoretype = cid;
262 sii->pub.buscoreidx = i;
263 }
264
265 /* find the core idx before entering this func. */
266 if ((savewin && (savewin == sii->coresba[i])) ||
267 (regs == sii->regs[i]))
268 *origidx = i;
269 }
270
271 if (pci) {
272 sii->pub.buscoretype = PCI_CORE_ID;
273 sii->pub.buscorerev = pcirev;
274 sii->pub.buscoreidx = pciidx;
275 } else if (pcie) {
Dmitry Shmidt83252322012-03-16 12:52:00 -0700276 if (pcie_gen2)
277 sii->pub.buscoretype = PCIE2_CORE_ID;
278 else
279 sii->pub.buscoretype = PCIE_CORE_ID;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700280 sii->pub.buscorerev = pcierev;
281 sii->pub.buscoreidx = pcieidx;
282 }
283
284 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
285 sii->pub.buscorerev));
286
287 if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
288 (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
289 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
290
291
292 /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was
293 * already running.
294 */
295 if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
296 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
297 si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
298 si_core_disable(&sii->pub, 0);
299 }
300
301 /* return to the original core */
302 si_setcoreidx(&sii->pub, *origidx);
303
304 return TRUE;
305}
306
307
308
Dmitry Shmidt83252322012-03-16 12:52:00 -0700309
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700310static si_info_t *
311si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
312 uint bustype, void *sdh, char **vars, uint *varsz)
313{
314 struct si_pub *sih = &sii->pub;
315 uint32 w, savewin;
316 chipcregs_t *cc;
317 char *pvars = NULL;
318 uint origidx;
319
320 ASSERT(GOODREGS(regs));
321
322 bzero((uchar*)sii, sizeof(si_info_t));
323
324 savewin = 0;
325
326 sih->buscoreidx = BADIDX;
327
328 sii->curmap = regs;
329 sii->sdh = sdh;
330 sii->osh = osh;
331
332
333
334 /* find Chipcommon address */
335 if (bustype == PCI_BUS) {
336 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
337 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
338 savewin = SI_ENUM_BASE;
339 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
Dmitry Shmidt83252322012-03-16 12:52:00 -0700340 if (!regs)
341 return NULL;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700342 cc = (chipcregs_t *)regs;
343 } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) {
344 cc = (chipcregs_t *)sii->curmap;
345 } else {
346 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
347 }
348
349 sih->bustype = bustype;
350 if (bustype != BUSTYPE(bustype)) {
351 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
352 bustype, BUSTYPE(bustype)));
353 return NULL;
354 }
355
356 /* bus/core/clk setup for register access */
357 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
358 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
359 return NULL;
360 }
361
362 /* ChipID recognition.
363 * We assume we can read chipid at offset 0 from the regs arg.
364 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
365 * some way of recognizing them needs to be added here.
366 */
Dmitry Shmidt83252322012-03-16 12:52:00 -0700367 if (!cc) {
368 SI_ERROR(("%s: chipcommon register space is null \n", __FUNCTION__));
369 return NULL;
370 }
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700371 w = R_REG(osh, &cc->chipid);
372 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
373 /* Might as wll fill in chip id rev & pkg */
374 sih->chip = w & CID_ID_MASK;
375 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
376 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700377
378 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
379 (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
380 sih->chippkg = BCM4329_182PIN_PKG_ID;
381 }
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700382 sih->issim = IS_SIM(sih->chippkg);
383
384 /* scan for cores */
385 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
386 SI_MSG(("Found chip type SB (0x%08x)\n", w));
387 sb_scan(&sii->pub, regs, devid);
388 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
389 SI_MSG(("Found chip type AI (0x%08x)\n", w));
390 /* pass chipc address instead of original core base */
391 ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
392 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
393 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
394 /* pass chipc address instead of original core base */
395 ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
396 } else {
397 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
398 return NULL;
399 }
400 /* no cores found, bail out */
401 if (sii->numcores == 0) {
402 SI_ERROR(("si_doattach: could not find any cores\n"));
403 return NULL;
404 }
405 /* bus/core/clk setup */
406 origidx = SI_CC_IDX;
407 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
408 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
409 goto exit;
410 }
411
Dmitry Shmidt83252322012-03-16 12:52:00 -0700412 if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
413 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
414 CST4322_SPROM_PRESENT))) {
415 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
416 return NULL;
417 }
418
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700419 /* assume current core is CC */
Dmitry Shmidt83252322012-03-16 12:52:00 -0700420 if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID ||
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700421 CHIPID(sih->chip) == BCM43235_CHIP_ID ||
Dmitry Shmidt83252322012-03-16 12:52:00 -0700422 CHIPID(sih->chip) == BCM43234_CHIP_ID ||
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700423 CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
Dmitry Shmidt83252322012-03-16 12:52:00 -0700424 (CHIPREV(sii->pub.chiprev) <= 2))) {
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700425
426 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
427 uint clkdiv;
428 clkdiv = R_REG(osh, &cc->clkdiv);
429 /* otp_clk_div is even number, 120/14 < 9mhz */
430 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
431 W_REG(osh, &cc->clkdiv, clkdiv);
432 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
433 }
434 OSL_DELAY(10);
435 }
436
Dmitry Shmidt83252322012-03-16 12:52:00 -0700437 if (bustype == PCI_BUS) {
438
439 }
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700440
441 pvars = NULL;
Dmitry Shmidt83252322012-03-16 12:52:00 -0700442 BCM_REFERENCE(pvars);
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700443
444
445
446 if (sii->pub.ccrev >= 20) {
Dmitry Shmidt83252322012-03-16 12:52:00 -0700447 uint32 gpiopullup = 0, gpiopulldown = 0;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700448 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
449 ASSERT(cc != NULL);
Dmitry Shmidt83252322012-03-16 12:52:00 -0700450
451 /* 4314/43142 has pin muxing, don't clear gpio bits */
452 if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) ||
453 (CHIPID(sih->chip) == BCM43142_CHIP_ID)) {
454 gpiopullup |= 0x402e0;
455 gpiopulldown |= 0x20500;
456 }
457
458 W_REG(osh, &cc->gpiopullup, gpiopullup);
459 W_REG(osh, &cc->gpiopulldown, gpiopulldown);
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700460 si_setcoreidx(sih, origidx);
461 }
462
463
Dmitry Shmidt83252322012-03-16 12:52:00 -0700464 /* clear any previous epidiag-induced target abort */
465 ASSERT(!si_taclear(sih, FALSE));
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700466
467 return (sii);
468
469exit:
470
471 return NULL;
472}
473
474/* may be called with core in reset */
475void
476si_detach(si_t *sih)
477{
478 si_info_t *sii;
479 uint idx;
480
481
482 sii = SI_INFO(sih);
483
484 if (sii == NULL)
485 return;
486
487 if (BUSTYPE(sih->bustype) == SI_BUS)
488 for (idx = 0; idx < SI_MAXCORES; idx++)
489 if (sii->regs[idx]) {
490 REG_UNMAP(sii->regs[idx]);
491 sii->regs[idx] = NULL;
492 }
493
494
495
496#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
497 if (sii != &ksii)
498#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
499 MFREE(sii->osh, sii, sizeof(si_info_t));
500}
501
502void *
503si_osh(si_t *sih)
504{
505 si_info_t *sii;
506
507 sii = SI_INFO(sih);
508 return sii->osh;
509}
510
511void
512si_setosh(si_t *sih, osl_t *osh)
513{
514 si_info_t *sii;
515
516 sii = SI_INFO(sih);
517 if (sii->osh != NULL) {
518 SI_ERROR(("osh is already set....\n"));
519 ASSERT(!sii->osh);
520 }
521 sii->osh = osh;
522}
523
524/* register driver interrupt disabling and restoring callback functions */
525void
526si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
527 void *intrsenabled_fn, void *intr_arg)
528{
529 si_info_t *sii;
530
531 sii = SI_INFO(sih);
532 sii->intr_arg = intr_arg;
533 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
534 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
535 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
536 /* save current core id. when this function called, the current core
537 * must be the core which provides driver functions(il, et, wl, etc.)
538 */
539 sii->dev_coreid = sii->coreid[sii->curidx];
540}
541
542void
543si_deregister_intr_callback(si_t *sih)
544{
545 si_info_t *sii;
546
547 sii = SI_INFO(sih);
548 sii->intrsoff_fn = NULL;
549}
550
551uint
552si_intflag(si_t *sih)
553{
554 si_info_t *sii = SI_INFO(sih);
555
556 if (CHIPTYPE(sih->socitype) == SOCI_SB)
557 return sb_intflag(sih);
558 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
559 return R_REG(sii->osh, ((uint32 *)(uintptr)
560 (sii->oob_router + OOB_STATUSA)));
561 else {
562 ASSERT(0);
563 return 0;
564 }
565}
566
567uint
568si_flag(si_t *sih)
569{
570 if (CHIPTYPE(sih->socitype) == SOCI_SB)
571 return sb_flag(sih);
572 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
573 return ai_flag(sih);
574 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
575 return ub_flag(sih);
576 else {
577 ASSERT(0);
578 return 0;
579 }
580}
581
582void
583si_setint(si_t *sih, int siflag)
584{
585 if (CHIPTYPE(sih->socitype) == SOCI_SB)
586 sb_setint(sih, siflag);
587 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
588 ai_setint(sih, siflag);
589 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
590 ub_setint(sih, siflag);
591 else
592 ASSERT(0);
593}
594
595uint
596si_coreid(si_t *sih)
597{
598 si_info_t *sii;
599
600 sii = SI_INFO(sih);
601 return sii->coreid[sii->curidx];
602}
603
604uint
605si_coreidx(si_t *sih)
606{
607 si_info_t *sii;
608
609 sii = SI_INFO(sih);
610 return sii->curidx;
611}
612
613/* return the core-type instantiation # of the current core */
614uint
615si_coreunit(si_t *sih)
616{
617 si_info_t *sii;
618 uint idx;
619 uint coreid;
620 uint coreunit;
621 uint i;
622
623 sii = SI_INFO(sih);
624 coreunit = 0;
625
626 idx = sii->curidx;
627
628 ASSERT(GOODREGS(sii->curmap));
629 coreid = si_coreid(sih);
630
631 /* count the cores of our type */
632 for (i = 0; i < idx; i++)
633 if (sii->coreid[i] == coreid)
634 coreunit++;
635
636 return (coreunit);
637}
638
639uint
640si_corevendor(si_t *sih)
641{
642 if (CHIPTYPE(sih->socitype) == SOCI_SB)
643 return sb_corevendor(sih);
644 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
645 return ai_corevendor(sih);
646 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
647 return ub_corevendor(sih);
648 else {
649 ASSERT(0);
650 return 0;
651 }
652}
653
654bool
655si_backplane64(si_t *sih)
656{
657 return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
658}
659
660uint
661si_corerev(si_t *sih)
662{
663 if (CHIPTYPE(sih->socitype) == SOCI_SB)
664 return sb_corerev(sih);
665 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
666 return ai_corerev(sih);
667 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
668 return ub_corerev(sih);
669 else {
670 ASSERT(0);
671 return 0;
672 }
673}
674
675/* return index of coreid or BADIDX if not found */
676uint
677si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
678{
679 si_info_t *sii;
680 uint found;
681 uint i;
682
683 sii = SI_INFO(sih);
684
685 found = 0;
686
687 for (i = 0; i < sii->numcores; i++)
688 if (sii->coreid[i] == coreid) {
689 if (found == coreunit)
690 return (i);
691 found++;
692 }
693
694 return (BADIDX);
695}
696
697/* return list of found cores */
698uint
699si_corelist(si_t *sih, uint coreid[])
700{
701 si_info_t *sii;
702
703 sii = SI_INFO(sih);
704
705 bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
706 return (sii->numcores);
707}
708
709/* return current register mapping */
710void *
711si_coreregs(si_t *sih)
712{
713 si_info_t *sii;
714
715 sii = SI_INFO(sih);
716 ASSERT(GOODREGS(sii->curmap));
717
718 return (sii->curmap);
719}
720
721/*
722 * This function changes logical "focus" to the indicated core;
723 * must be called with interrupts off.
724 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
725 */
726void *
727si_setcore(si_t *sih, uint coreid, uint coreunit)
728{
729 uint idx;
730
731 idx = si_findcoreidx(sih, coreid, coreunit);
732 if (!GOODIDX(idx))
733 return (NULL);
734
735 if (CHIPTYPE(sih->socitype) == SOCI_SB)
736 return sb_setcoreidx(sih, idx);
737 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
738 return ai_setcoreidx(sih, idx);
739 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
740 return ub_setcoreidx(sih, idx);
741 else {
742 ASSERT(0);
743 return NULL;
744 }
745}
746
747void *
748si_setcoreidx(si_t *sih, uint coreidx)
749{
750 if (CHIPTYPE(sih->socitype) == SOCI_SB)
751 return sb_setcoreidx(sih, coreidx);
752 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
753 return ai_setcoreidx(sih, coreidx);
754 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
755 return ub_setcoreidx(sih, coreidx);
756 else {
757 ASSERT(0);
758 return NULL;
759 }
760}
761
762/* Turn off interrupt as required by sb_setcore, before switch core */
763void *
764si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
765{
766 void *cc;
767 si_info_t *sii;
768
769 sii = SI_INFO(sih);
770
771 if (SI_FAST(sii)) {
772 /* Overloading the origidx variable to remember the coreid,
773 * this works because the core ids cannot be confused with
774 * core indices.
775 */
776 *origidx = coreid;
777 if (coreid == CC_CORE_ID)
778 return (void *)CCREGS_FAST(sii);
779 else if (coreid == sih->buscoretype)
780 return (void *)PCIEREGS(sii);
781 }
782 INTR_OFF(sii, *intr_val);
783 *origidx = sii->curidx;
784 cc = si_setcore(sih, coreid, 0);
785 ASSERT(cc != NULL);
786
787 return cc;
788}
789
790/* restore coreidx and restore interrupt */
791void
792si_restore_core(si_t *sih, uint coreid, uint intr_val)
793{
794 si_info_t *sii;
795
796 sii = SI_INFO(sih);
797 if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
798 return;
799
800 si_setcoreidx(sih, coreid);
801 INTR_RESTORE(sii, intr_val);
802}
803
804int
805si_numaddrspaces(si_t *sih)
806{
807 if (CHIPTYPE(sih->socitype) == SOCI_SB)
808 return sb_numaddrspaces(sih);
809 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
810 return ai_numaddrspaces(sih);
811 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
812 return ub_numaddrspaces(sih);
813 else {
814 ASSERT(0);
815 return 0;
816 }
817}
818
819uint32
820si_addrspace(si_t *sih, uint asidx)
821{
822 if (CHIPTYPE(sih->socitype) == SOCI_SB)
823 return sb_addrspace(sih, asidx);
824 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
825 return ai_addrspace(sih, asidx);
826 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
827 return ub_addrspace(sih, asidx);
828 else {
829 ASSERT(0);
830 return 0;
831 }
832}
833
834uint32
835si_addrspacesize(si_t *sih, uint asidx)
836{
837 if (CHIPTYPE(sih->socitype) == SOCI_SB)
838 return sb_addrspacesize(sih, asidx);
839 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
840 return ai_addrspacesize(sih, asidx);
841 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
842 return ub_addrspacesize(sih, asidx);
843 else {
844 ASSERT(0);
845 return 0;
846 }
847}
848
Dmitry Shmidt83252322012-03-16 12:52:00 -0700849void
850si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size)
851{
852 /* Only supported for SOCI_AI */
853 if (CHIPTYPE(sih->socitype) == SOCI_AI)
854 ai_coreaddrspaceX(sih, asidx, addr, size);
855 else
856 *size = 0;
857}
858
Dmitry Shmidt8ce17272011-05-24 11:14:33 -0700859uint32
860si_core_cflags(si_t *sih, uint32 mask, uint32 val)
861{
862 if (CHIPTYPE(sih->socitype) == SOCI_SB)
863 return sb_core_cflags(sih, mask, val);
864 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
865 return ai_core_cflags(sih, mask, val);
866 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
867 return ub_core_cflags(sih, mask, val);
868 else {
869 ASSERT(0);
870 return 0;
871 }
872}
873
874void
875si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
876{
877 if (CHIPTYPE(sih->socitype) == SOCI_SB)
878 sb_core_cflags_wo(sih, mask, val);
879 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
880 ai_core_cflags_wo(sih, mask, val);
881 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
882 ub_core_cflags_wo(sih, mask, val);
883 else
884 ASSERT(0);
885}
886
887uint32
888si_core_sflags(si_t *sih, uint32 mask, uint32 val)
889{
890 if (CHIPTYPE(sih->socitype) == SOCI_SB)
891 return sb_core_sflags(sih, mask, val);
892 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
893 return ai_core_sflags(sih, mask, val);
894 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
895 return ub_core_sflags(sih, mask, val);
896 else {
897 ASSERT(0);
898 return 0;
899 }
900}
901
902bool
903si_iscoreup(si_t *sih)
904{
905 if (CHIPTYPE(sih->socitype) == SOCI_SB)
906 return sb_iscoreup(sih);
907 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
908 return ai_iscoreup(sih);
909 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
910 return ub_iscoreup(sih);
911 else {
912 ASSERT(0);
913 return FALSE;
914 }
915}
916
917uint
918si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
919{
920 /* only for AI back plane chips */
921 if (CHIPTYPE(sih->socitype) == SOCI_AI)
922 return (ai_wrap_reg(sih, offset, mask, val));
923 return 0;
924}
925
926uint
927si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
928{
929 if (CHIPTYPE(sih->socitype) == SOCI_SB)
930 return sb_corereg(sih, coreidx, regoff, mask, val);
931 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
932 return ai_corereg(sih, coreidx, regoff, mask, val);
933 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
934 return ub_corereg(sih, coreidx, regoff, mask, val);
935 else {
936 ASSERT(0);
937 return 0;
938 }
939}
940
941void
942si_core_disable(si_t *sih, uint32 bits)
943{
944 if (CHIPTYPE(sih->socitype) == SOCI_SB)
945 sb_core_disable(sih, bits);
946 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
947 ai_core_disable(sih, bits);
948 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
949 ub_core_disable(sih, bits);
950}
951
952void
953si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
954{
955 if (CHIPTYPE(sih->socitype) == SOCI_SB)
956 sb_core_reset(sih, bits, resetbits);
957 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
958 ai_core_reset(sih, bits, resetbits);
959 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
960 ub_core_reset(sih, bits, resetbits);
961}
962
963/* Run bist on current core. Caller needs to take care of core-specific bist hazards */
964int
965si_corebist(si_t *sih)
966{
967 uint32 cflags;
968 int result = 0;
969
970 /* Read core control flags */
971 cflags = si_core_cflags(sih, 0, 0);
972
973 /* Set bist & fgc */
974 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
975
976 /* Wait for bist done */
977 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
978
979 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
980 result = BCME_ERROR;
981
982 /* Reset core control flags */
983 si_core_cflags(sih, 0xffff, cflags);
984
985 return result;
986}
987
988static uint32
989factor6(uint32 x)
990{
991 switch (x) {
992 case CC_F6_2: return 2;
993 case CC_F6_3: return 3;
994 case CC_F6_4: return 4;
995 case CC_F6_5: return 5;
996 case CC_F6_6: return 6;
997 case CC_F6_7: return 7;
998 default: return 0;
999 }
1000}
1001
1002/* calculate the speed the SI would run at given a set of clockcontrol values */
1003uint32
1004si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
1005{
1006 uint32 n1, n2, clock, m1, m2, m3, mc;
1007
1008 n1 = n & CN_N1_MASK;
1009 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
1010
1011 if (pll_type == PLL_TYPE6) {
1012 if (m & CC_T6_MMASK)
1013 return CC_T6_M1;
1014 else
1015 return CC_T6_M0;
1016 } else if ((pll_type == PLL_TYPE1) ||
1017 (pll_type == PLL_TYPE3) ||
1018 (pll_type == PLL_TYPE4) ||
1019 (pll_type == PLL_TYPE7)) {
1020 n1 = factor6(n1);
1021 n2 += CC_F5_BIAS;
1022 } else if (pll_type == PLL_TYPE2) {
1023 n1 += CC_T2_BIAS;
1024 n2 += CC_T2_BIAS;
1025 ASSERT((n1 >= 2) && (n1 <= 7));
1026 ASSERT((n2 >= 5) && (n2 <= 23));
1027 } else if (pll_type == PLL_TYPE5) {
1028 return (100000000);
1029 } else
1030 ASSERT(0);
1031 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1032 if ((pll_type == PLL_TYPE3) ||
1033 (pll_type == PLL_TYPE7)) {
1034 clock = CC_CLOCK_BASE2 * n1 * n2;
1035 } else
1036 clock = CC_CLOCK_BASE1 * n1 * n2;
1037
1038 if (clock == 0)
1039 return 0;
1040
1041 m1 = m & CC_M1_MASK;
1042 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1043 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1044 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1045
1046 if ((pll_type == PLL_TYPE1) ||
1047 (pll_type == PLL_TYPE3) ||
1048 (pll_type == PLL_TYPE4) ||
1049 (pll_type == PLL_TYPE7)) {
1050 m1 = factor6(m1);
1051 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1052 m2 += CC_F5_BIAS;
1053 else
1054 m2 = factor6(m2);
1055 m3 = factor6(m3);
1056
1057 switch (mc) {
1058 case CC_MC_BYPASS: return (clock);
1059 case CC_MC_M1: return (clock / m1);
1060 case CC_MC_M1M2: return (clock / (m1 * m2));
1061 case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3));
1062 case CC_MC_M1M3: return (clock / (m1 * m3));
1063 default: return (0);
1064 }
1065 } else {
1066 ASSERT(pll_type == PLL_TYPE2);
1067
1068 m1 += CC_T2_BIAS;
1069 m2 += CC_T2M2_BIAS;
1070 m3 += CC_T2_BIAS;
1071 ASSERT((m1 >= 2) && (m1 <= 7));
1072 ASSERT((m2 >= 3) && (m2 <= 10));
1073 ASSERT((m3 >= 2) && (m3 <= 7));
1074
1075 if ((mc & CC_T2MC_M1BYP) == 0)
1076 clock /= m1;
1077 if ((mc & CC_T2MC_M2BYP) == 0)
1078 clock /= m2;
1079 if ((mc & CC_T2MC_M3BYP) == 0)
1080 clock /= m3;
1081
1082 return (clock);
1083 }
1084}
1085
1086
1087/* set chip watchdog reset timer to fire in 'ticks' */
1088void
1089si_watchdog(si_t *sih, uint ticks)
1090{
1091 uint nb, maxt;
1092
1093 if (PMUCTL_ENAB(sih)) {
1094
1095 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1096 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1097 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1098 si_setcore(sih, USB20D_CORE_ID, 0);
1099 si_core_disable(sih, 1);
1100 si_setcore(sih, CC_CORE_ID, 0);
1101 }
1102
Dmitry Shmidt83252322012-03-16 12:52:00 -07001103 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001104 /* The mips compiler uses the sllv instruction,
1105 * so we specially handle the 32-bit case.
1106 */
1107 if (nb == 32)
1108 maxt = 0xffffffff;
1109 else
1110 maxt = ((1 << nb) - 1);
1111
1112 if (ticks == 1)
1113 ticks = 2;
1114 else if (ticks > maxt)
1115 ticks = maxt;
1116
1117 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
1118 } else {
1119 maxt = (1 << 28) - 1;
1120 if (ticks > maxt)
1121 ticks = maxt;
1122
1123 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
1124 }
1125}
1126
1127/* trigger watchdog reset after ms milliseconds */
1128void
1129si_watchdog_ms(si_t *sih, uint32 ms)
1130{
1131 si_watchdog(sih, wd_msticks * ms);
1132}
1133
Dmitry Shmidt4a3a0fa2012-04-12 10:18:39 -07001134uint32 si_watchdog_msticks(void)
1135{
1136 return wd_msticks;
1137}
1138
Dmitry Shmidt83252322012-03-16 12:52:00 -07001139bool
1140si_taclear(si_t *sih, bool details)
1141{
1142 return FALSE;
1143}
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001144
1145
1146
1147/* return the slow clock source - LPO, XTAL, or PCI */
1148static uint
1149si_slowclk_src(si_info_t *sii)
1150{
1151 chipcregs_t *cc;
1152
1153 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1154
1155 if (sii->pub.ccrev < 6) {
1156 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1157 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
1158 PCI_CFG_GPIO_SCS))
1159 return (SCC_SS_PCI);
1160 else
1161 return (SCC_SS_XTAL);
1162 } else if (sii->pub.ccrev < 10) {
1163 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
1164 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1165 } else /* Insta-clock */
1166 return (SCC_SS_XTAL);
1167}
1168
1169/* return the ILP (slowclock) min or max frequency */
1170static uint
1171si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1172{
1173 uint32 slowclk;
1174 uint div;
1175
1176 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1177
1178 /* shouldn't be here unless we've established the chip has dynamic clk control */
1179 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1180
1181 slowclk = si_slowclk_src(sii);
1182 if (sii->pub.ccrev < 6) {
1183 if (slowclk == SCC_SS_PCI)
1184 return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
1185 else
1186 return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
1187 } else if (sii->pub.ccrev < 10) {
1188 div = 4 *
1189 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
1190 if (slowclk == SCC_SS_LPO)
1191 return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
1192 else if (slowclk == SCC_SS_XTAL)
1193 return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
1194 else if (slowclk == SCC_SS_PCI)
1195 return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
1196 else
1197 ASSERT(0);
1198 } else {
1199 /* Chipc rev 10 is InstaClock */
1200 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1201 div = 4 * (div + 1);
1202 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
1203 }
1204 return (0);
1205}
1206
1207static void
1208si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
1209{
1210 chipcregs_t *cc = (chipcregs_t *)chipcregs;
1211 uint slowmaxfreq, pll_delay, slowclk;
1212 uint pll_on_delay, fref_sel_delay;
1213
1214 pll_delay = PLL_DELAY;
1215
1216 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1217 * since the xtal will also be powered down by dynamic clk control logic.
1218 */
1219
1220 slowclk = si_slowclk_src(sii);
1221 if (slowclk != SCC_SS_XTAL)
1222 pll_delay += XTAL_ON_DELAY;
1223
1224 /* Starting with 4318 it is ILP that is used for the delays */
1225 slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1226
1227 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1228 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1229
1230 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1231 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1232}
1233
1234/* initialize power control delay registers */
1235void
1236si_clkctl_init(si_t *sih)
1237{
1238 si_info_t *sii;
1239 uint origidx = 0;
1240 chipcregs_t *cc;
1241 bool fast;
1242
1243 if (!CCCTL_ENAB(sih))
1244 return;
1245
1246 sii = SI_INFO(sih);
1247 fast = SI_FAST(sii);
1248 if (!fast) {
1249 origidx = sii->curidx;
1250 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1251 return;
1252 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
1253 return;
1254 ASSERT(cc != NULL);
1255
1256 /* set all Instaclk chip ILP to 1 MHz */
1257 if (sih->ccrev >= 10)
1258 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1259 (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1260
1261 si_clkctl_setdelay(sii, (void *)(uintptr)cc);
1262
1263 if (!fast)
1264 si_setcoreidx(sih, origidx);
1265}
1266
Dmitry Shmidt83252322012-03-16 12:52:00 -07001267
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001268/* change logical "focus" to the gpio core for optimized access */
1269void *
1270si_gpiosetcore(si_t *sih)
1271{
1272 return (si_setcoreidx(sih, SI_CC_IDX));
1273}
1274
Dmitry Shmidt83252322012-03-16 12:52:00 -07001275/*
1276 * mask & set gpiocontrol bits.
1277 * If a gpiocontrol bit is set to 0, chipcommon controls the corresponding GPIO pin.
1278 * If a gpiocontrol bit is set to 1, the GPIO pin is no longer a GPIO and becomes dedicated
1279 * to some chip-specific purpose.
1280 */
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001281uint32
1282si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1283{
1284 uint regoff;
1285
1286 regoff = 0;
1287
1288 /* gpios could be shared on router platforms
1289 * ignore reservation if it's high priority (e.g., test apps)
1290 */
1291 if ((priority != GPIO_HI_PRIORITY) &&
1292 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1293 mask = priority ? (si_gpioreservation & mask) :
1294 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1295 val &= mask;
1296 }
1297
1298 regoff = OFFSETOF(chipcregs_t, gpiocontrol);
1299 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1300}
1301
1302/* mask&set gpio output enable bits */
1303uint32
1304si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1305{
1306 uint regoff;
1307
1308 regoff = 0;
1309
1310 /* gpios could be shared on router platforms
1311 * ignore reservation if it's high priority (e.g., test apps)
1312 */
1313 if ((priority != GPIO_HI_PRIORITY) &&
1314 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1315 mask = priority ? (si_gpioreservation & mask) :
1316 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1317 val &= mask;
1318 }
1319
1320 regoff = OFFSETOF(chipcregs_t, gpioouten);
1321 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1322}
1323
1324/* mask&set gpio output bits */
1325uint32
1326si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1327{
1328 uint regoff;
1329
1330 regoff = 0;
1331
1332 /* gpios could be shared on router platforms
1333 * ignore reservation if it's high priority (e.g., test apps)
1334 */
1335 if ((priority != GPIO_HI_PRIORITY) &&
1336 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1337 mask = priority ? (si_gpioreservation & mask) :
1338 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1339 val &= mask;
1340 }
1341
1342 regoff = OFFSETOF(chipcregs_t, gpioout);
1343 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1344}
1345
1346/* reserve one gpio */
1347uint32
1348si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1349{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001350 /* only cores on SI_BUS share GPIO's and only applcation users need to
1351 * reserve/release GPIO
1352 */
1353 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1354 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1355 return 0xffffffff;
1356 }
1357 /* make sure only one bit is set */
1358 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1359 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1360 return 0xffffffff;
1361 }
1362
1363 /* already reserved */
1364 if (si_gpioreservation & gpio_bitmask)
1365 return 0xffffffff;
1366 /* set reservation */
1367 si_gpioreservation |= gpio_bitmask;
1368
1369 return si_gpioreservation;
1370}
1371
1372/* release one gpio */
1373/*
1374 * releasing the gpio doesn't change the current value on the GPIO last write value
1375 * persists till some one overwrites it
1376 */
1377
1378uint32
1379si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1380{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001381 /* only cores on SI_BUS share GPIO's and only applcation users need to
1382 * reserve/release GPIO
1383 */
1384 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1385 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1386 return 0xffffffff;
1387 }
1388 /* make sure only one bit is set */
1389 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1390 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1391 return 0xffffffff;
1392 }
1393
1394 /* already released */
1395 if (!(si_gpioreservation & gpio_bitmask))
1396 return 0xffffffff;
1397
1398 /* clear reservation */
1399 si_gpioreservation &= ~gpio_bitmask;
1400
1401 return si_gpioreservation;
1402}
1403
1404/* return the current gpioin register value */
1405uint32
1406si_gpioin(si_t *sih)
1407{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001408 uint regoff;
1409
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001410 regoff = OFFSETOF(chipcregs_t, gpioin);
1411 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
1412}
1413
1414/* mask&set gpio interrupt polarity bits */
1415uint32
1416si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1417{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001418 uint regoff;
1419
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001420 /* gpios could be shared on router platforms */
1421 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1422 mask = priority ? (si_gpioreservation & mask) :
1423 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1424 val &= mask;
1425 }
1426
1427 regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
1428 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1429}
1430
1431/* mask&set gpio interrupt mask bits */
1432uint32
1433si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1434{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001435 uint regoff;
1436
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001437 /* gpios could be shared on router platforms */
1438 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1439 mask = priority ? (si_gpioreservation & mask) :
1440 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1441 val &= mask;
1442 }
1443
1444 regoff = OFFSETOF(chipcregs_t, gpiointmask);
1445 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1446}
1447
1448/* assign the gpio to an led */
1449uint32
1450si_gpioled(si_t *sih, uint32 mask, uint32 val)
1451{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001452 if (sih->ccrev < 16)
1453 return 0xffffffff;
1454
1455 /* gpio led powersave reg */
1456 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
1457}
1458
1459/* mask&set gpio timer val */
1460uint32
1461si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
1462{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001463 if (sih->ccrev < 16)
1464 return 0xffffffff;
1465
1466 return (si_corereg(sih, SI_CC_IDX,
1467 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
1468}
1469
1470uint32
1471si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
1472{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001473 uint offs;
1474
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001475 if (sih->ccrev < 20)
1476 return 0xffffffff;
1477
1478 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
1479 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1480}
1481
1482uint32
1483si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
1484{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001485 uint offs;
1486
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001487 if (sih->ccrev < 11)
1488 return 0xffffffff;
1489
1490 if (regtype == GPIO_REGEVT)
1491 offs = OFFSETOF(chipcregs_t, gpioevent);
1492 else if (regtype == GPIO_REGEVT_INTMSK)
1493 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
1494 else if (regtype == GPIO_REGEVT_INTPOL)
1495 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
1496 else
1497 return 0xffffffff;
1498
1499 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1500}
1501
1502void *
1503si_gpio_handler_register(si_t *sih, uint32 event,
1504 bool level, gpio_handler_t cb, void *arg)
1505{
1506 si_info_t *sii;
1507 gpioh_item_t *gi;
1508
1509 ASSERT(event);
1510 ASSERT(cb != NULL);
1511
1512 sii = SI_INFO(sih);
1513 if (sih->ccrev < 11)
1514 return NULL;
1515
1516 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
1517 return NULL;
1518
1519 bzero(gi, sizeof(gpioh_item_t));
1520 gi->event = event;
1521 gi->handler = cb;
1522 gi->arg = arg;
1523 gi->level = level;
1524
1525 gi->next = sii->gpioh_head;
1526 sii->gpioh_head = gi;
1527
1528 return (void *)(gi);
1529}
1530
1531void
1532si_gpio_handler_unregister(si_t *sih, void *gpioh)
1533{
1534 si_info_t *sii;
1535 gpioh_item_t *p, *n;
1536
1537 sii = SI_INFO(sih);
1538 if (sih->ccrev < 11)
1539 return;
1540
1541 ASSERT(sii->gpioh_head != NULL);
1542 if ((void*)sii->gpioh_head == gpioh) {
1543 sii->gpioh_head = sii->gpioh_head->next;
1544 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1545 return;
1546 } else {
1547 p = sii->gpioh_head;
1548 n = p->next;
1549 while (n) {
1550 if ((void*)n == gpioh) {
1551 p->next = n->next;
1552 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1553 return;
1554 }
1555 p = n;
1556 n = n->next;
1557 }
1558 }
1559
1560 ASSERT(0); /* Not found in list */
1561}
1562
1563void
1564si_gpio_handler_process(si_t *sih)
1565{
1566 si_info_t *sii;
1567 gpioh_item_t *h;
1568 uint32 level = si_gpioin(sih);
1569 uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0);
1570 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
1571 uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0);
1572
1573 sii = SI_INFO(sih);
1574 for (h = sii->gpioh_head; h != NULL; h = h->next) {
1575 if (h->handler) {
1576 uint32 status = (h->level ? level : edge) & h->event;
1577 uint32 polarity = (h->level ? levelp : edgep) & h->event;
1578
1579 /* polarity bitval is opposite of status bitval */
1580 if (status ^ polarity)
1581 h->handler(status, h->arg);
1582 }
1583 }
1584
1585 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
1586}
1587
1588uint32
1589si_gpio_int_enable(si_t *sih, bool enable)
1590{
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001591 uint offs;
1592
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001593 if (sih->ccrev < 11)
1594 return 0xffffffff;
1595
1596 offs = OFFSETOF(chipcregs_t, intmask);
1597 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
1598}
1599
1600
1601/* Return the size of the specified SOCRAM bank */
1602static uint
Dmitry Shmidt83252322012-03-16 12:52:00 -07001603socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 idx, uint8 mem_type)
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001604{
1605 uint banksize, bankinfo;
Dmitry Shmidt83252322012-03-16 12:52:00 -07001606 uint bankidx = idx | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001607
1608 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
1609
1610 W_REG(sii->osh, &regs->bankidx, bankidx);
1611 bankinfo = R_REG(sii->osh, &regs->bankinfo);
1612 banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
1613 return banksize;
1614}
1615
1616void
Dmitry Shmidt83252322012-03-16 12:52:00 -07001617si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect, uint8 *remap)
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001618{
1619 si_info_t *sii;
1620 uint origidx;
1621 uint intr_val = 0;
1622 sbsocramregs_t *regs;
1623 bool wasup;
1624 uint corerev;
1625
1626 sii = SI_INFO(sih);
1627
1628 /* Block ints and save current core */
1629 INTR_OFF(sii, intr_val);
1630 origidx = si_coreidx(sih);
1631
1632 if (!set)
Dmitry Shmidt83252322012-03-16 12:52:00 -07001633 *enable = *protect = *remap = 0;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001634
1635 /* Switch to SOCRAM core */
1636 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1637 goto done;
1638
1639 /* Get info for determining size */
1640 if (!(wasup = si_iscoreup(sih)))
1641 si_core_reset(sih, 0, 0);
1642
1643 corerev = si_corerev(sih);
1644 if (corerev >= 10) {
1645 uint32 extcinfo;
1646 uint8 nb;
1647 uint8 i;
1648 uint32 bankidx, bankinfo;
1649
1650 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1651 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
1652 for (i = 0; i < nb; i++) {
1653 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1654 W_REG(sii->osh, &regs->bankidx, bankidx);
1655 bankinfo = R_REG(sii->osh, &regs->bankinfo);
1656 if (set) {
1657 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
1658 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
Dmitry Shmidt83252322012-03-16 12:52:00 -07001659 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMREMAP_MASK;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001660 if (*enable) {
1661 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
1662 if (*protect)
1663 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
Dmitry Shmidt83252322012-03-16 12:52:00 -07001664 if ((corerev >= 16) && *remap)
1665 bankinfo |=
1666 (1 << SOCRAM_BANKINFO_DEVRAMREMAP_SHIFT);
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001667 }
1668 W_REG(sii->osh, &regs->bankinfo, bankinfo);
1669 }
1670 else if (i == 0) {
1671 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
1672 *enable = 1;
1673 if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
1674 *protect = 1;
Dmitry Shmidt83252322012-03-16 12:52:00 -07001675 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK)
1676 *remap = 1;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001677 }
1678 }
1679 }
1680 }
1681
1682 /* Return to previous state and core */
1683 if (!wasup)
1684 si_core_disable(sih, 0);
1685 si_setcoreidx(sih, origidx);
1686
1687done:
1688 INTR_RESTORE(sii, intr_val);
1689}
1690
1691bool
Dmitry Shmidt83252322012-03-16 12:52:00 -07001692si_socdevram_remap_isenb(si_t *sih)
1693{
1694 si_info_t *sii;
1695 uint origidx;
1696 uint intr_val = 0;
1697 sbsocramregs_t *regs;
1698 bool wasup, remap = FALSE;
1699 uint corerev;
1700 uint32 extcinfo;
1701 uint8 nb;
1702 uint8 i;
1703 uint32 bankidx, bankinfo;
1704
1705 sii = SI_INFO(sih);
1706
1707 /* Block ints and save current core */
1708 INTR_OFF(sii, intr_val);
1709 origidx = si_coreidx(sih);
1710
1711 /* Switch to SOCRAM core */
1712 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1713 goto done;
1714
1715 /* Get info for determining size */
1716 if (!(wasup = si_iscoreup(sih)))
1717 si_core_reset(sih, 0, 0);
1718
1719 corerev = si_corerev(sih);
1720 if (corerev >= 16) {
1721 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1722 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
1723 for (i = 0; i < nb; i++) {
1724 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1725 W_REG(sii->osh, &regs->bankidx, bankidx);
1726 bankinfo = R_REG(sii->osh, &regs->bankinfo);
1727 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
1728 remap = TRUE;
1729 break;
1730 }
1731 }
1732 }
1733
1734 /* Return to previous state and core */
1735 if (!wasup)
1736 si_core_disable(sih, 0);
1737 si_setcoreidx(sih, origidx);
1738
1739done:
1740 INTR_RESTORE(sii, intr_val);
1741 return remap;
1742}
1743
1744bool
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001745si_socdevram_pkg(si_t *sih)
1746{
1747 if (si_socdevram_size(sih) > 0)
1748 return TRUE;
1749 else
1750 return FALSE;
1751}
1752
1753uint32
1754si_socdevram_size(si_t *sih)
1755{
1756 si_info_t *sii;
1757 uint origidx;
1758 uint intr_val = 0;
1759 uint32 memsize = 0;
1760 sbsocramregs_t *regs;
1761 bool wasup;
1762 uint corerev;
1763
1764 sii = SI_INFO(sih);
1765
1766 /* Block ints and save current core */
1767 INTR_OFF(sii, intr_val);
1768 origidx = si_coreidx(sih);
1769
1770 /* Switch to SOCRAM core */
1771 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1772 goto done;
1773
1774 /* Get info for determining size */
1775 if (!(wasup = si_iscoreup(sih)))
1776 si_core_reset(sih, 0, 0);
1777
1778 corerev = si_corerev(sih);
1779 if (corerev >= 10) {
1780 uint32 extcinfo;
1781 uint8 nb;
1782 uint8 i;
1783
1784 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1785 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
1786 for (i = 0; i < nb; i++)
1787 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
1788 }
1789
1790 /* Return to previous state and core */
1791 if (!wasup)
1792 si_core_disable(sih, 0);
1793 si_setcoreidx(sih, origidx);
1794
1795done:
1796 INTR_RESTORE(sii, intr_val);
1797
1798 return memsize;
1799}
1800
Dmitry Shmidt83252322012-03-16 12:52:00 -07001801uint32
1802si_socdevram_remap_size(si_t *sih)
1803{
1804 si_info_t *sii;
1805 uint origidx;
1806 uint intr_val = 0;
1807 uint32 memsize = 0, banksz;
1808 sbsocramregs_t *regs;
1809 bool wasup;
1810 uint corerev;
1811 uint32 extcinfo;
1812 uint8 nb;
1813 uint8 i;
1814 uint32 bankidx, bankinfo;
1815
1816 sii = SI_INFO(sih);
1817
1818 /* Block ints and save current core */
1819 INTR_OFF(sii, intr_val);
1820 origidx = si_coreidx(sih);
1821
1822 /* Switch to SOCRAM core */
1823 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1824 goto done;
1825
1826 /* Get info for determining size */
1827 if (!(wasup = si_iscoreup(sih)))
1828 si_core_reset(sih, 0, 0);
1829
1830 corerev = si_corerev(sih);
1831 if (corerev >= 16) {
1832 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1833 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
1834
1835 /*
1836 * FIX: A0 Issue: Max addressable is 512KB, instead 640KB
1837 * Only four banks are accessible to ARM
1838 */
1839 if ((corerev == 16) && (nb == 5))
1840 nb = 4;
1841
1842 for (i = 0; i < nb; i++) {
1843 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1844 W_REG(sii->osh, &regs->bankidx, bankidx);
1845 bankinfo = R_REG(sii->osh, &regs->bankinfo);
1846 if (bankinfo & SOCRAM_BANKINFO_DEVRAMREMAP_MASK) {
1847 banksz = socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
1848 memsize += banksz;
1849 } else {
1850 /* Account only consecutive banks for now */
1851 break;
1852 }
1853 }
1854 }
1855
1856 /* Return to previous state and core */
1857 if (!wasup)
1858 si_core_disable(sih, 0);
1859 si_setcoreidx(sih, origidx);
1860
1861done:
1862 INTR_RESTORE(sii, intr_val);
1863
1864 return memsize;
1865}
1866
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001867/* Return the RAM size of the SOCRAM core */
1868uint32
1869si_socram_size(si_t *sih)
1870{
1871 si_info_t *sii;
1872 uint origidx;
1873 uint intr_val = 0;
1874
1875 sbsocramregs_t *regs;
1876 bool wasup;
1877 uint corerev;
1878 uint32 coreinfo;
1879 uint memsize = 0;
1880
1881 sii = SI_INFO(sih);
1882
1883 /* Block ints and save current core */
1884 INTR_OFF(sii, intr_val);
1885 origidx = si_coreidx(sih);
1886
1887 /* Switch to SOCRAM core */
1888 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1889 goto done;
1890
1891 /* Get info for determining size */
1892 if (!(wasup = si_iscoreup(sih)))
1893 si_core_reset(sih, 0, 0);
1894 corerev = si_corerev(sih);
1895 coreinfo = R_REG(sii->osh, &regs->coreinfo);
1896
1897 /* Calculate size from coreinfo based on rev */
1898 if (corerev == 0)
1899 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
1900 else if (corerev < 3) {
1901 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
1902 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1903 } else if ((corerev <= 7) || (corerev == 12)) {
1904 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1905 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
1906 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
1907 if (lss != 0)
1908 nb --;
1909 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
1910 if (lss != 0)
1911 memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
1912 } else {
1913 uint8 i;
1914 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1915 for (i = 0; i < nb; i++)
1916 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
1917 }
1918
1919 /* Return to previous state and core */
1920 if (!wasup)
1921 si_core_disable(sih, 0);
1922 si_setcoreidx(sih, origidx);
1923
1924done:
1925 INTR_RESTORE(sii, intr_val);
1926
1927 return memsize;
1928}
1929
Dmitry Shmidt83252322012-03-16 12:52:00 -07001930uint32
1931si_socram_srmem_size(si_t *sih)
1932{
1933 si_info_t *sii;
1934 uint origidx;
1935 uint intr_val = 0;
1936
1937 sbsocramregs_t *regs;
1938 bool wasup;
1939 uint corerev;
1940 uint32 coreinfo;
1941 uint memsize = 0;
1942
Dmitry Shmidt4a3a0fa2012-04-12 10:18:39 -07001943 if ((CHIPID(sih->chip) == BCM4334_CHIP_ID) && (CHIPREV(sih->chiprev) < 2)) {
1944 return (32 * 1024);
1945 }
1946
Dmitry Shmidt83252322012-03-16 12:52:00 -07001947 sii = SI_INFO(sih);
1948
1949 /* Block ints and save current core */
1950 INTR_OFF(sii, intr_val);
1951 origidx = si_coreidx(sih);
1952
1953 /* Switch to SOCRAM core */
1954 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1955 goto done;
1956
1957 /* Get info for determining size */
1958 if (!(wasup = si_iscoreup(sih)))
1959 si_core_reset(sih, 0, 0);
1960 corerev = si_corerev(sih);
1961 coreinfo = R_REG(sii->osh, &regs->coreinfo);
1962
1963 /* Calculate size from coreinfo based on rev */
1964 if (corerev >= 16) {
1965 uint8 i;
1966 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1967 for (i = 0; i < nb; i++) {
1968 W_REG(sii->osh, &regs->bankidx, i);
1969 if (R_REG(sii->osh, &regs->bankinfo) & SOCRAM_BANKINFO_RETNTRAM_MASK)
1970 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
1971 }
1972 }
1973
1974 /* Return to previous state and core */
1975 if (!wasup)
1976 si_core_disable(sih, 0);
1977 si_setcoreidx(sih, origidx);
1978
1979done:
1980 INTR_RESTORE(sii, intr_val);
1981
1982 return memsize;
1983}
1984
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07001985
1986void
1987si_btcgpiowar(si_t *sih)
1988{
1989 si_info_t *sii;
1990 uint origidx;
1991 uint intr_val = 0;
1992 chipcregs_t *cc;
1993
1994 sii = SI_INFO(sih);
1995
1996 /* Make sure that there is ChipCommon core present &&
1997 * UART_TX is strapped to 1
1998 */
1999 if (!(sih->cccaps & CC_CAP_UARTGPIO))
2000 return;
2001
2002 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
2003 INTR_OFF(sii, intr_val);
2004
2005 origidx = si_coreidx(sih);
2006
2007 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2008 ASSERT(cc != NULL);
2009
2010 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
2011
2012 /* restore the original index */
2013 si_setcoreidx(sih, origidx);
2014
2015 INTR_RESTORE(sii, intr_val);
2016}
2017
Dmitry Shmidt83252322012-03-16 12:52:00 -07002018void
2019si_chipcontrl_btshd0_4331(si_t *sih, bool on)
2020{
2021 si_info_t *sii;
2022 chipcregs_t *cc;
2023 uint origidx;
2024 uint32 val;
2025 uint intr_val = 0;
2026
2027 sii = SI_INFO(sih);
2028
2029 INTR_OFF(sii, intr_val);
2030
2031 origidx = si_coreidx(sih);
2032
2033 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2034
2035 val = R_REG(sii->osh, &cc->chipcontrol);
2036
2037 /* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */
2038 if (on) {
2039 /* Enable bt_shd0 on gpio4: */
2040 val |= (CCTRL4331_BT_SHD0_ON_GPIO4);
2041 W_REG(sii->osh, &cc->chipcontrol, val);
2042 } else {
2043 val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4);
2044 W_REG(sii->osh, &cc->chipcontrol, val);
2045 }
2046
2047 /* restore the original index */
2048 si_setcoreidx(sih, origidx);
2049
2050 INTR_RESTORE(sii, intr_val);
2051}
2052
2053void
2054si_chipcontrl_restore(si_t *sih, uint32 val)
2055{
2056 si_info_t *sii;
2057 chipcregs_t *cc;
2058 uint origidx;
2059
2060 sii = SI_INFO(sih);
2061 origidx = si_coreidx(sih);
2062 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2063 W_REG(sii->osh, &cc->chipcontrol, val);
2064 si_setcoreidx(sih, origidx);
2065}
2066
2067uint32
2068si_chipcontrl_read(si_t *sih)
2069{
2070 si_info_t *sii;
2071 chipcregs_t *cc;
2072 uint origidx;
2073 uint32 val;
2074
2075 sii = SI_INFO(sih);
2076 origidx = si_coreidx(sih);
2077 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2078 val = R_REG(sii->osh, &cc->chipcontrol);
2079 si_setcoreidx(sih, origidx);
2080 return val;
2081}
2082
2083void
2084si_chipcontrl_epa4331(si_t *sih, bool on)
2085{
2086 si_info_t *sii;
2087 chipcregs_t *cc;
2088 uint origidx;
2089 uint32 val;
2090
2091 sii = SI_INFO(sih);
2092 origidx = si_coreidx(sih);
2093
2094 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2095
2096 val = R_REG(sii->osh, &cc->chipcontrol);
2097
2098 if (on) {
2099 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
2100 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
2101 /* Ext PA Controls for 4331 12x9 Package */
2102 W_REG(sii->osh, &cc->chipcontrol, val);
2103 } else {
2104 /* Ext PA Controls for 4331 12x12 Package */
2105 if (sih->chiprev > 0) {
2106 W_REG(sii->osh, &cc->chipcontrol, val |
2107 (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2));
2108 } else {
2109 W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN));
2110 }
2111 }
2112 } else {
2113 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5);
2114 W_REG(sii->osh, &cc->chipcontrol, val);
2115 }
2116
2117 si_setcoreidx(sih, origidx);
2118}
2119
2120/* switch muxed pins, on: SROM, off: FEMCTRL */
2121void
2122si_chipcontrl_srom4360(si_t *sih, bool on)
2123{
2124 si_info_t *sii;
2125 chipcregs_t *cc;
2126 uint origidx;
2127 uint32 val;
2128
2129 sii = SI_INFO(sih);
2130 origidx = si_coreidx(sih);
2131
2132 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2133
2134 val = R_REG(sii->osh, &cc->chipcontrol);
2135
2136 if (on) {
2137 val &= ~(CCTRL4360_SECI_MODE |
2138 CCTRL4360_BTSWCTRL_MODE |
2139 CCTRL4360_EXTRA_FEMCTRL_MODE |
2140 CCTRL4360_BT_LGCY_MODE |
2141 CCTRL4360_CORE2FEMCTRL4_ON);
2142
2143 W_REG(sii->osh, &cc->chipcontrol, val);
2144 } else {
2145 }
2146
2147 si_setcoreidx(sih, origidx);
2148}
2149
2150void
2151si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl)
2152{
2153 si_info_t *sii;
2154 chipcregs_t *cc;
2155 uint origidx;
2156 uint32 val;
2157 bool sel_chip;
2158
2159 sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
2160 (CHIPID(sih->chip) == BCM43431_CHIP_ID);
2161 sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb));
2162
2163 if (!sel_chip)
2164 return;
2165
2166 sii = SI_INFO(sih);
2167 origidx = si_coreidx(sih);
2168
2169 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2170
2171 val = R_REG(sii->osh, &cc->chipcontrol);
2172
2173 if (enter_wowl) {
2174 val |= CCTRL4331_EXTPA_EN;
2175 W_REG(sii->osh, &cc->chipcontrol, val);
2176 } else {
2177 val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
2178 W_REG(sii->osh, &cc->chipcontrol, val);
2179 }
2180 si_setcoreidx(sih, origidx);
2181}
2182
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07002183uint
2184si_pll_reset(si_t *sih)
2185{
2186 uint err = 0;
2187
2188 return (err);
2189}
2190
Dmitry Shmidt83252322012-03-16 12:52:00 -07002191/* Enable BT-COEX & Ex-PA for 4313 */
2192void
2193si_epa_4313war(si_t *sih)
2194{
2195 si_info_t *sii;
2196 chipcregs_t *cc;
2197 uint origidx;
2198
2199 sii = SI_INFO(sih);
2200 origidx = si_coreidx(sih);
2201
2202 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2203
2204 /* EPA Fix */
2205 W_REG(sii->osh, &cc->gpiocontrol,
2206 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
2207
2208 si_setcoreidx(sih, origidx);
2209}
2210
2211void
2212si_clk_pmu_htavail_set(si_t *sih, bool set_clear)
2213{
2214}
2215
2216/* WL/BT control for 4313 btcombo boards >= P250 */
2217void
2218si_btcombo_p250_4313_war(si_t *sih)
2219{
2220 si_info_t *sii;
2221 chipcregs_t *cc;
2222 uint origidx;
2223
2224 sii = SI_INFO(sih);
2225 origidx = si_coreidx(sih);
2226
2227 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2228 W_REG(sii->osh, &cc->gpiocontrol,
2229 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK);
2230
2231 W_REG(sii->osh, &cc->gpioouten,
2232 R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK);
2233
2234 si_setcoreidx(sih, origidx);
2235}
2236void
2237si_btc_enable_chipcontrol(si_t *sih)
2238{
2239 si_info_t *sii;
2240 chipcregs_t *cc;
2241 uint origidx;
2242
2243 sii = SI_INFO(sih);
2244 origidx = si_coreidx(sih);
2245
2246 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2247
2248 /* BT fix */
2249 W_REG(sii->osh, &cc->chipcontrol,
2250 R_REG(sii->osh, &cc->chipcontrol) | CC_BTCOEX_EN_MASK);
2251
2252 si_setcoreidx(sih, origidx);
2253}
2254void
2255si_btcombo_43228_war(si_t *sih)
2256{
2257 si_info_t *sii;
2258 chipcregs_t *cc;
2259 uint origidx;
2260
2261 sii = SI_INFO(sih);
2262 origidx = si_coreidx(sih);
2263
2264 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
2265
2266 W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK);
2267 W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK);
2268
2269 si_setcoreidx(sih, origidx);
2270}
2271
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07002272/* check if the device is removed */
2273bool
2274si_deviceremoved(si_t *sih)
2275{
2276 uint32 w;
2277 si_info_t *sii;
2278
2279 sii = SI_INFO(sih);
2280
2281 switch (BUSTYPE(sih->bustype)) {
2282 case PCI_BUS:
2283 ASSERT(sii->osh != NULL);
2284 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
2285 if ((w & 0xFFFF) != VENDOR_BROADCOM)
2286 return TRUE;
2287 break;
2288 }
2289 return FALSE;
2290}
2291
2292bool
2293si_is_sprom_available(si_t *sih)
2294{
2295 if (sih->ccrev >= 31) {
2296 si_info_t *sii;
2297 uint origidx;
2298 chipcregs_t *cc;
2299 uint32 sromctrl;
2300
2301 if ((sih->cccaps & CC_CAP_SROM) == 0)
2302 return FALSE;
2303
2304 sii = SI_INFO(sih);
2305 origidx = sii->curidx;
2306 cc = si_setcoreidx(sih, SI_CC_IDX);
2307 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
2308 si_setcoreidx(sih, origidx);
2309 return (sromctrl & SRC_PRESENT);
2310 }
2311
2312 switch (CHIPID(sih->chip)) {
2313 case BCM4312_CHIP_ID:
2314 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
2315 case BCM4325_CHIP_ID:
2316 return (sih->chipst & CST4325_SPROM_SEL) != 0;
Dmitry Shmidt83252322012-03-16 12:52:00 -07002317 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
2318 case BCM43222_CHIP_ID: case BCM43111_CHIP_ID: case BCM43112_CHIP_ID:
2319 case BCM4342_CHIP_ID: {
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07002320 uint32 spromotp;
2321 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
2322 CST4322_SPROM_OTP_SEL_SHIFT;
2323 return (spromotp & CST4322_SPROM_PRESENT) != 0;
2324 }
2325 case BCM4329_CHIP_ID:
2326 return (sih->chipst & CST4329_SPROM_SEL) != 0;
2327 case BCM4315_CHIP_ID:
2328 return (sih->chipst & CST4315_SPROM_SEL) != 0;
2329 case BCM4319_CHIP_ID:
2330 return (sih->chipst & CST4319_SPROM_SEL) != 0;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07002331 case BCM4336_CHIP_ID:
2332 case BCM43362_CHIP_ID:
2333 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07002334 case BCM4330_CHIP_ID:
2335 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
2336 case BCM4313_CHIP_ID:
2337 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
Dmitry Shmidt83252322012-03-16 12:52:00 -07002338 case BCM4331_CHIP_ID:
2339 case BCM43431_CHIP_ID:
2340 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07002341 case BCM43239_CHIP_ID:
2342 return ((sih->chipst & CST43239_SPROM_MASK) &&
2343 !(sih->chipst & CST43239_SFLASH_MASK));
Dmitry Shmidt83252322012-03-16 12:52:00 -07002344 case BCM4324_CHIP_ID:
2345 return ((sih->chipst & CST4324_SPROM_MASK) &&
2346 !(sih->chipst & CST4324_SFLASH_MASK));
2347 case BCM43131_CHIP_ID:
2348 case BCM43217_CHIP_ID:
2349 case BCM43227_CHIP_ID:
2350 case BCM43228_CHIP_ID:
2351 case BCM43428_CHIP_ID:
2352 return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
Dmitry Shmidt8ce17272011-05-24 11:14:33 -07002353 default:
2354 return TRUE;
2355 }
2356}