blob: 1cc977f51ee3c6af60076941c50f226b027b630e [file] [log] [blame]
Dmitry Shmidt66eb9fa2011-05-24 11:14:33 -07001/*
2 * Misc utility routines for accessing chip-specific features
3 * of the SiliconBackplane-based Broadcom chips.
4 *
5 * Copyright (C) 1999-2011, Broadcom Corporation
6 *
7 * Unless you and Broadcom execute a separate written software license
8 * agreement governing use of this software, this software is licensed to you
9 * under the terms of the GNU General Public License version 2 (the "GPL"),
10 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11 * following added to such license:
12 *
13 * As a special exception, the copyright holders of this software give you
14 * permission to link this software with independent modules, and to copy and
15 * distribute the resulting executable under terms of your choice, provided that
16 * you also meet, for each linked independent module, the terms and conditions of
17 * the license of that module. An independent module is a module which is not
18 * derived from this software. The special exception does not apply to any
19 * modifications of the software.
20 *
21 * Notwithstanding the above, under no circumstances may you combine this
22 * software in any way with any other Broadcom software provided under a license
23 * other than the GPL, without Broadcom's express prior written consent.
24 *
Dmitry Shmidt1dddb0c2012-01-24 13:37:34 -080025 * $Id: siutils.c,v 1.813.2.36 2011-02-10 23:43:55 $
Dmitry Shmidt66eb9fa2011-05-24 11:14:33 -070026 */
27
28#include <typedefs.h>
29#include <bcmdefs.h>
30#include <osl.h>
31#include <bcmutils.h>
32#include <siutils.h>
33#include <bcmdevs.h>
34#include <hndsoc.h>
35#include <sbchipc.h>
36#include <pcicfg.h>
37#include <sbpcmcia.h>
38#include <sbsocram.h>
39#include <bcmsdh.h>
40#include <sdio.h>
41#include <sbsdio.h>
42#include <sbhnddma.h>
43#include <sbsdpcmdev.h>
44#include <bcmsdpcm.h>
45#include <hndpmu.h>
46
47#include "siutils_priv.h"
48
49/* local prototypes */
50static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
51 uint bustype, void *sdh, char **vars, uint *varsz);
52static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh);
53static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
54 uint *origidx, void *regs);
55
56
57/* global variable to indicate reservation/release of gpio's */
58static uint32 si_gpioreservation = 0;
59
60/* global flag to prevent shared resources from being initialized multiple times in si_attach() */
61
62/*
63 * Allocate a si handle.
64 * devid - pci device id (used to determine chip#)
65 * osh - opaque OS handle
66 * regs - virtual address of initial core registers
67 * bustype - pci/pcmcia/sb/sdio/etc
68 * vars - pointer to a pointer area for "environment" variables
69 * varsz - pointer to int to return the size of the vars
70 */
71si_t *
72si_attach(uint devid, osl_t *osh, void *regs,
73 uint bustype, void *sdh, char **vars, uint *varsz)
74{
75 si_info_t *sii;
76
77 /* alloc si_info_t */
78 if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) {
79 SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh)));
80 return (NULL);
81 }
82
83 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) {
84 MFREE(osh, sii, sizeof(si_info_t));
85 return (NULL);
86 }
87 sii->vars = vars ? *vars : NULL;
88 sii->varsz = varsz ? *varsz : 0;
89
90 return (si_t *)sii;
91}
92
93/* global kernel resource */
94static si_info_t ksii;
95
96static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */
97
98/* generic kernel variant of si_attach() */
99si_t *
100si_kattach(osl_t *osh)
101{
102 static bool ksii_attached = FALSE;
103
104 if (!ksii_attached) {
105 void *regs;
106 regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
107
108 if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs,
109 SI_BUS, NULL,
110 osh != SI_OSH ? &ksii.vars : NULL,
111 osh != SI_OSH ? &ksii.varsz : NULL) == NULL) {
112 SI_ERROR(("si_kattach: si_doattach failed\n"));
113 REG_UNMAP(regs);
114 return NULL;
115 }
116 REG_UNMAP(regs);
117
118 /* save ticks normalized to ms for si_watchdog_ms() */
119 if (PMUCTL_ENAB(&ksii.pub)) {
120 /* based on 32KHz ILP clock */
121 wd_msticks = 32;
122 } else {
123 wd_msticks = ALP_CLOCK / 1000;
124 }
125
126 ksii_attached = TRUE;
127 SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n",
128 ksii.pub.ccrev, wd_msticks));
129 }
130
131 return &ksii.pub;
132}
133
134
135static bool
136si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
137{
138 /* need to set memseg flag for CF card first before any sb registers access */
139 if (BUSTYPE(bustype) == PCMCIA_BUS)
140 sii->memseg = TRUE;
141
142
143 if (BUSTYPE(bustype) == SDIO_BUS) {
144 int err;
145 uint8 clkset;
146
147 /* Try forcing SDIO core to do ALPAvail request only */
148 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
149 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
150 if (!err) {
151 uint8 clkval;
152
153 /* If register supported, wait for ALPAvail and then force ALP */
154 clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
155 if ((clkval & ~SBSDIO_AVBITS) == clkset) {
156 SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
157 SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)),
158 PMU_MAX_TRANSITION_DLY);
159 if (!SBSDIO_ALPAV(clkval)) {
160 SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n",
161 clkval));
162 return FALSE;
163 }
164 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
165 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
166 clkset, &err);
167 OSL_DELAY(65);
168 }
169 }
170
171 /* Also, disable the extra SDIO pull-ups */
172 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
173 }
174
175
176 return TRUE;
177}
178
179static bool
180si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
181 uint *origidx, void *regs)
182{
183 bool pci, pcie;
184 uint i;
185 uint pciidx, pcieidx, pcirev, pcierev;
186
187 cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
188 ASSERT((uintptr)cc);
189
190 /* get chipcommon rev */
191 sii->pub.ccrev = (int)si_corerev(&sii->pub);
192
193 /* get chipcommon chipstatus */
194 if (sii->pub.ccrev >= 11)
195 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
196
197 /* get chipcommon capabilites */
198 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
199 /* get chipcommon extended capabilities */
200
201 if (sii->pub.ccrev >= 35)
202 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
203
204 /* get pmu rev and caps */
205 if (sii->pub.cccaps & CC_CAP_PMU) {
206 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
207 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
208 }
209
210 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
211 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
212 sii->pub.pmucaps));
213
214 /* figure out bus/orignal core idx */
215 sii->pub.buscoretype = NODEV_CORE_ID;
Dmitry Shmidt1dddb0c2012-01-24 13:37:34 -0800216 sii->pub.buscorerev = (uint)NOREV;
Dmitry Shmidt66eb9fa2011-05-24 11:14:33 -0700217 sii->pub.buscoreidx = BADIDX;
218
219 pci = pcie = FALSE;
Dmitry Shmidt1dddb0c2012-01-24 13:37:34 -0800220 pcirev = pcierev = (uint)NOREV;
Dmitry Shmidt66eb9fa2011-05-24 11:14:33 -0700221 pciidx = pcieidx = BADIDX;
222
223 for (i = 0; i < sii->numcores; i++) {
224 uint cid, crev;
225
226 si_setcoreidx(&sii->pub, i);
227 cid = si_coreid(&sii->pub);
228 crev = si_corerev(&sii->pub);
229
230 /* Display cores found */
231 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
232 i, cid, crev, sii->coresba[i], sii->regs[i]));
233
234 if (BUSTYPE(bustype) == PCI_BUS) {
235 if (cid == PCI_CORE_ID) {
236 pciidx = i;
237 pcirev = crev;
238 pci = TRUE;
239 } else if (cid == PCIE_CORE_ID) {
240 pcieidx = i;
241 pcierev = crev;
242 pcie = TRUE;
243 }
244 } else if ((BUSTYPE(bustype) == PCMCIA_BUS) &&
245 (cid == PCMCIA_CORE_ID)) {
246 sii->pub.buscorerev = crev;
247 sii->pub.buscoretype = cid;
248 sii->pub.buscoreidx = i;
249 }
250 else if (((BUSTYPE(bustype) == SDIO_BUS) ||
251 (BUSTYPE(bustype) == SPI_BUS)) &&
252 ((cid == PCMCIA_CORE_ID) ||
253 (cid == SDIOD_CORE_ID))) {
254 sii->pub.buscorerev = crev;
255 sii->pub.buscoretype = cid;
256 sii->pub.buscoreidx = i;
257 }
258
259 /* find the core idx before entering this func. */
260 if ((savewin && (savewin == sii->coresba[i])) ||
261 (regs == sii->regs[i]))
262 *origidx = i;
263 }
264
265 if (pci) {
266 sii->pub.buscoretype = PCI_CORE_ID;
267 sii->pub.buscorerev = pcirev;
268 sii->pub.buscoreidx = pciidx;
269 } else if (pcie) {
270 sii->pub.buscoretype = PCIE_CORE_ID;
271 sii->pub.buscorerev = pcierev;
272 sii->pub.buscoreidx = pcieidx;
273 }
274
275 SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype,
276 sii->pub.buscorerev));
277
278 if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) &&
279 (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (CHIPREV(sii->pub.chiprev) <= 3))
280 OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL);
281
282
283 /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was
284 * already running.
285 */
286 if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
287 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
288 si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
289 si_core_disable(&sii->pub, 0);
290 }
291
292 /* return to the original core */
293 si_setcoreidx(&sii->pub, *origidx);
294
295 return TRUE;
296}
297
298
299
300static si_info_t *
301si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs,
302 uint bustype, void *sdh, char **vars, uint *varsz)
303{
304 struct si_pub *sih = &sii->pub;
305 uint32 w, savewin;
306 chipcregs_t *cc;
307 char *pvars = NULL;
308 uint origidx;
309
310 ASSERT(GOODREGS(regs));
311
312 bzero((uchar*)sii, sizeof(si_info_t));
313
314 savewin = 0;
315
316 sih->buscoreidx = BADIDX;
317
318 sii->curmap = regs;
319 sii->sdh = sdh;
320 sii->osh = osh;
321
322
323
324 /* find Chipcommon address */
325 if (bustype == PCI_BUS) {
326 savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32));
327 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
328 savewin = SI_ENUM_BASE;
329 OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE);
330 cc = (chipcregs_t *)regs;
331 } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) {
332 cc = (chipcregs_t *)sii->curmap;
333 } else {
334 cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
335 }
336
337 sih->bustype = bustype;
338 if (bustype != BUSTYPE(bustype)) {
339 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n",
340 bustype, BUSTYPE(bustype)));
341 return NULL;
342 }
343
344 /* bus/core/clk setup for register access */
345 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
346 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype));
347 return NULL;
348 }
349
350 /* ChipID recognition.
351 * We assume we can read chipid at offset 0 from the regs arg.
352 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
353 * some way of recognizing them needs to be added here.
354 */
355 w = R_REG(osh, &cc->chipid);
356 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
357 /* Might as wll fill in chip id rev & pkg */
358 sih->chip = w & CID_ID_MASK;
359 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
360 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
361 if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK)
362 >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT |
363 CST4322_SPROM_PRESENT))) {
364 SI_ERROR(("%s: Invalid setting: both SPROM and OTP strapped.\n", __FUNCTION__));
365 return NULL;
366 }
367
Dmitry Shmidt1dddb0c2012-01-24 13:37:34 -0800368#if defined(HW_OOB)
369 if (CHIPID(sih->chip) == BCM43362_CHIP_ID) {
370 uint32 gpiocontrol, addr;
371 addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol);
372 gpiocontrol = bcmsdh_reg_read(sdh, addr, 4);
373 gpiocontrol |= 0x2;
374 bcmsdh_reg_write(sdh, addr, 4, gpiocontrol);
375 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL);
376 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL);
377 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL);
378 }
379#endif
380
Dmitry Shmidt66eb9fa2011-05-24 11:14:33 -0700381 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) &&
382 (sih->chippkg != BCM4329_289PIN_PKG_ID)) {
383 sih->chippkg = BCM4329_182PIN_PKG_ID;
384 }
385
386 sih->issim = IS_SIM(sih->chippkg);
387
388 /* scan for cores */
389 if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) {
390 SI_MSG(("Found chip type SB (0x%08x)\n", w));
391 sb_scan(&sii->pub, regs, devid);
392 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
393 SI_MSG(("Found chip type AI (0x%08x)\n", w));
394 /* pass chipc address instead of original core base */
395 ai_scan(&sii->pub, (void *)(uintptr)cc, devid);
396 } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) {
397 SI_MSG(("Found chip type UBUS (0x%08x), chip id = 0x%4x\n", w, sih->chip));
398 /* pass chipc address instead of original core base */
399 ub_scan(&sii->pub, (void *)(uintptr)cc, devid);
400 } else {
401 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
402 return NULL;
403 }
404 /* no cores found, bail out */
405 if (sii->numcores == 0) {
406 SI_ERROR(("si_doattach: could not find any cores\n"));
407 return NULL;
408 }
409 /* bus/core/clk setup */
410 origidx = SI_CC_IDX;
411 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
412 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
413 goto exit;
414 }
415
416 /* assume current core is CC */
Dmitry Shmidt1dddb0c2012-01-24 13:37:34 -0800417 if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43234_CHIP_ID ||
Dmitry Shmidt66eb9fa2011-05-24 11:14:33 -0700418 CHIPID(sih->chip) == BCM43235_CHIP_ID ||
Dmitry Shmidt1dddb0c2012-01-24 13:37:34 -0800419 CHIPID(sih->chip) == BCM43236_CHIP_ID ||
Dmitry Shmidt66eb9fa2011-05-24 11:14:33 -0700420 CHIPID(sih->chip) == BCM43238_CHIP_ID) &&
421 (CHIPREV(sii->pub.chiprev) == 0))) {
422
423 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
424 uint clkdiv;
425 clkdiv = R_REG(osh, &cc->clkdiv);
426 /* otp_clk_div is even number, 120/14 < 9mhz */
427 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
428 W_REG(osh, &cc->clkdiv, clkdiv);
429 SI_ERROR(("%s: set clkdiv to %x\n", __FUNCTION__, clkdiv));
430 }
431 OSL_DELAY(10);
432 }
433
434
435 pvars = NULL;
436
437
438
439 if (sii->pub.ccrev >= 20) {
440 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
441 ASSERT(cc != NULL);
442 W_REG(osh, &cc->gpiopullup, 0);
443 W_REG(osh, &cc->gpiopulldown, 0);
444 si_setcoreidx(sih, origidx);
445 }
446
447
448
449
450 return (sii);
451
452exit:
453
454 return NULL;
455}
456
457/* may be called with core in reset */
458void
459si_detach(si_t *sih)
460{
461 si_info_t *sii;
462 uint idx;
463
464
465 sii = SI_INFO(sih);
466
467 if (sii == NULL)
468 return;
469
470 if (BUSTYPE(sih->bustype) == SI_BUS)
471 for (idx = 0; idx < SI_MAXCORES; idx++)
472 if (sii->regs[idx]) {
473 REG_UNMAP(sii->regs[idx]);
474 sii->regs[idx] = NULL;
475 }
476
477
478
479#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
480 if (sii != &ksii)
481#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
482 MFREE(sii->osh, sii, sizeof(si_info_t));
483}
484
485void *
486si_osh(si_t *sih)
487{
488 si_info_t *sii;
489
490 sii = SI_INFO(sih);
491 return sii->osh;
492}
493
494void
495si_setosh(si_t *sih, osl_t *osh)
496{
497 si_info_t *sii;
498
499 sii = SI_INFO(sih);
500 if (sii->osh != NULL) {
501 SI_ERROR(("osh is already set....\n"));
502 ASSERT(!sii->osh);
503 }
504 sii->osh = osh;
505}
506
507/* register driver interrupt disabling and restoring callback functions */
508void
509si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
510 void *intrsenabled_fn, void *intr_arg)
511{
512 si_info_t *sii;
513
514 sii = SI_INFO(sih);
515 sii->intr_arg = intr_arg;
516 sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn;
517 sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn;
518 sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn;
519 /* save current core id. when this function called, the current core
520 * must be the core which provides driver functions(il, et, wl, etc.)
521 */
522 sii->dev_coreid = sii->coreid[sii->curidx];
523}
524
525void
526si_deregister_intr_callback(si_t *sih)
527{
528 si_info_t *sii;
529
530 sii = SI_INFO(sih);
531 sii->intrsoff_fn = NULL;
532}
533
534uint
535si_intflag(si_t *sih)
536{
537 si_info_t *sii = SI_INFO(sih);
538
539 if (CHIPTYPE(sih->socitype) == SOCI_SB)
540 return sb_intflag(sih);
541 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
542 return R_REG(sii->osh, ((uint32 *)(uintptr)
543 (sii->oob_router + OOB_STATUSA)));
544 else {
545 ASSERT(0);
546 return 0;
547 }
548}
549
550uint
551si_flag(si_t *sih)
552{
553 if (CHIPTYPE(sih->socitype) == SOCI_SB)
554 return sb_flag(sih);
555 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
556 return ai_flag(sih);
557 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
558 return ub_flag(sih);
559 else {
560 ASSERT(0);
561 return 0;
562 }
563}
564
565void
566si_setint(si_t *sih, int siflag)
567{
568 if (CHIPTYPE(sih->socitype) == SOCI_SB)
569 sb_setint(sih, siflag);
570 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
571 ai_setint(sih, siflag);
572 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
573 ub_setint(sih, siflag);
574 else
575 ASSERT(0);
576}
577
578uint
579si_coreid(si_t *sih)
580{
581 si_info_t *sii;
582
583 sii = SI_INFO(sih);
584 return sii->coreid[sii->curidx];
585}
586
587uint
588si_coreidx(si_t *sih)
589{
590 si_info_t *sii;
591
592 sii = SI_INFO(sih);
593 return sii->curidx;
594}
595
596/* return the core-type instantiation # of the current core */
597uint
598si_coreunit(si_t *sih)
599{
600 si_info_t *sii;
601 uint idx;
602 uint coreid;
603 uint coreunit;
604 uint i;
605
606 sii = SI_INFO(sih);
607 coreunit = 0;
608
609 idx = sii->curidx;
610
611 ASSERT(GOODREGS(sii->curmap));
612 coreid = si_coreid(sih);
613
614 /* count the cores of our type */
615 for (i = 0; i < idx; i++)
616 if (sii->coreid[i] == coreid)
617 coreunit++;
618
619 return (coreunit);
620}
621
622uint
623si_corevendor(si_t *sih)
624{
625 if (CHIPTYPE(sih->socitype) == SOCI_SB)
626 return sb_corevendor(sih);
627 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
628 return ai_corevendor(sih);
629 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
630 return ub_corevendor(sih);
631 else {
632 ASSERT(0);
633 return 0;
634 }
635}
636
637bool
638si_backplane64(si_t *sih)
639{
640 return ((sih->cccaps & CC_CAP_BKPLN64) != 0);
641}
642
643uint
644si_corerev(si_t *sih)
645{
646 if (CHIPTYPE(sih->socitype) == SOCI_SB)
647 return sb_corerev(sih);
648 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
649 return ai_corerev(sih);
650 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
651 return ub_corerev(sih);
652 else {
653 ASSERT(0);
654 return 0;
655 }
656}
657
658/* return index of coreid or BADIDX if not found */
659uint
660si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
661{
662 si_info_t *sii;
663 uint found;
664 uint i;
665
666 sii = SI_INFO(sih);
667
668 found = 0;
669
670 for (i = 0; i < sii->numcores; i++)
671 if (sii->coreid[i] == coreid) {
672 if (found == coreunit)
673 return (i);
674 found++;
675 }
676
677 return (BADIDX);
678}
679
680/* return list of found cores */
681uint
682si_corelist(si_t *sih, uint coreid[])
683{
684 si_info_t *sii;
685
686 sii = SI_INFO(sih);
687
688 bcopy((uchar*)sii->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint)));
689 return (sii->numcores);
690}
691
692/* return current register mapping */
693void *
694si_coreregs(si_t *sih)
695{
696 si_info_t *sii;
697
698 sii = SI_INFO(sih);
699 ASSERT(GOODREGS(sii->curmap));
700
701 return (sii->curmap);
702}
703
704/*
705 * This function changes logical "focus" to the indicated core;
706 * must be called with interrupts off.
707 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
708 */
709void *
710si_setcore(si_t *sih, uint coreid, uint coreunit)
711{
712 uint idx;
713
714 idx = si_findcoreidx(sih, coreid, coreunit);
715 if (!GOODIDX(idx))
716 return (NULL);
717
718 if (CHIPTYPE(sih->socitype) == SOCI_SB)
719 return sb_setcoreidx(sih, idx);
720 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
721 return ai_setcoreidx(sih, idx);
722 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
723 return ub_setcoreidx(sih, idx);
724 else {
725 ASSERT(0);
726 return NULL;
727 }
728}
729
730void *
731si_setcoreidx(si_t *sih, uint coreidx)
732{
733 if (CHIPTYPE(sih->socitype) == SOCI_SB)
734 return sb_setcoreidx(sih, coreidx);
735 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
736 return ai_setcoreidx(sih, coreidx);
737 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
738 return ub_setcoreidx(sih, coreidx);
739 else {
740 ASSERT(0);
741 return NULL;
742 }
743}
744
745/* Turn off interrupt as required by sb_setcore, before switch core */
746void *
747si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
748{
749 void *cc;
750 si_info_t *sii;
751
752 sii = SI_INFO(sih);
753
754 if (SI_FAST(sii)) {
755 /* Overloading the origidx variable to remember the coreid,
756 * this works because the core ids cannot be confused with
757 * core indices.
758 */
759 *origidx = coreid;
760 if (coreid == CC_CORE_ID)
761 return (void *)CCREGS_FAST(sii);
762 else if (coreid == sih->buscoretype)
763 return (void *)PCIEREGS(sii);
764 }
765 INTR_OFF(sii, *intr_val);
766 *origidx = sii->curidx;
767 cc = si_setcore(sih, coreid, 0);
768 ASSERT(cc != NULL);
769
770 return cc;
771}
772
773/* restore coreidx and restore interrupt */
774void
775si_restore_core(si_t *sih, uint coreid, uint intr_val)
776{
777 si_info_t *sii;
778
779 sii = SI_INFO(sih);
780 if (SI_FAST(sii) && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
781 return;
782
783 si_setcoreidx(sih, coreid);
784 INTR_RESTORE(sii, intr_val);
785}
786
787int
788si_numaddrspaces(si_t *sih)
789{
790 if (CHIPTYPE(sih->socitype) == SOCI_SB)
791 return sb_numaddrspaces(sih);
792 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
793 return ai_numaddrspaces(sih);
794 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
795 return ub_numaddrspaces(sih);
796 else {
797 ASSERT(0);
798 return 0;
799 }
800}
801
802uint32
803si_addrspace(si_t *sih, uint asidx)
804{
805 if (CHIPTYPE(sih->socitype) == SOCI_SB)
806 return sb_addrspace(sih, asidx);
807 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
808 return ai_addrspace(sih, asidx);
809 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
810 return ub_addrspace(sih, asidx);
811 else {
812 ASSERT(0);
813 return 0;
814 }
815}
816
817uint32
818si_addrspacesize(si_t *sih, uint asidx)
819{
820 if (CHIPTYPE(sih->socitype) == SOCI_SB)
821 return sb_addrspacesize(sih, asidx);
822 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
823 return ai_addrspacesize(sih, asidx);
824 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
825 return ub_addrspacesize(sih, asidx);
826 else {
827 ASSERT(0);
828 return 0;
829 }
830}
831
832uint32
833si_core_cflags(si_t *sih, uint32 mask, uint32 val)
834{
835 if (CHIPTYPE(sih->socitype) == SOCI_SB)
836 return sb_core_cflags(sih, mask, val);
837 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
838 return ai_core_cflags(sih, mask, val);
839 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
840 return ub_core_cflags(sih, mask, val);
841 else {
842 ASSERT(0);
843 return 0;
844 }
845}
846
847void
848si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val)
849{
850 if (CHIPTYPE(sih->socitype) == SOCI_SB)
851 sb_core_cflags_wo(sih, mask, val);
852 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
853 ai_core_cflags_wo(sih, mask, val);
854 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
855 ub_core_cflags_wo(sih, mask, val);
856 else
857 ASSERT(0);
858}
859
860uint32
861si_core_sflags(si_t *sih, uint32 mask, uint32 val)
862{
863 if (CHIPTYPE(sih->socitype) == SOCI_SB)
864 return sb_core_sflags(sih, mask, val);
865 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
866 return ai_core_sflags(sih, mask, val);
867 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
868 return ub_core_sflags(sih, mask, val);
869 else {
870 ASSERT(0);
871 return 0;
872 }
873}
874
875bool
876si_iscoreup(si_t *sih)
877{
878 if (CHIPTYPE(sih->socitype) == SOCI_SB)
879 return sb_iscoreup(sih);
880 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
881 return ai_iscoreup(sih);
882 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
883 return ub_iscoreup(sih);
884 else {
885 ASSERT(0);
886 return FALSE;
887 }
888}
889
890uint
891si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val)
892{
893 /* only for AI back plane chips */
894 if (CHIPTYPE(sih->socitype) == SOCI_AI)
895 return (ai_wrap_reg(sih, offset, mask, val));
896 return 0;
897}
898
899uint
900si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
901{
902 if (CHIPTYPE(sih->socitype) == SOCI_SB)
903 return sb_corereg(sih, coreidx, regoff, mask, val);
904 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
905 return ai_corereg(sih, coreidx, regoff, mask, val);
906 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
907 return ub_corereg(sih, coreidx, regoff, mask, val);
908 else {
909 ASSERT(0);
910 return 0;
911 }
912}
913
914void
915si_core_disable(si_t *sih, uint32 bits)
916{
917 if (CHIPTYPE(sih->socitype) == SOCI_SB)
918 sb_core_disable(sih, bits);
919 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
920 ai_core_disable(sih, bits);
921 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
922 ub_core_disable(sih, bits);
923}
924
925void
926si_core_reset(si_t *sih, uint32 bits, uint32 resetbits)
927{
928 if (CHIPTYPE(sih->socitype) == SOCI_SB)
929 sb_core_reset(sih, bits, resetbits);
930 else if (CHIPTYPE(sih->socitype) == SOCI_AI)
931 ai_core_reset(sih, bits, resetbits);
932 else if (CHIPTYPE(sih->socitype) == SOCI_UBUS)
933 ub_core_reset(sih, bits, resetbits);
934}
935
936/* Run bist on current core. Caller needs to take care of core-specific bist hazards */
937int
938si_corebist(si_t *sih)
939{
940 uint32 cflags;
941 int result = 0;
942
943 /* Read core control flags */
944 cflags = si_core_cflags(sih, 0, 0);
945
946 /* Set bist & fgc */
947 si_core_cflags(sih, ~0, (SICF_BIST_EN | SICF_FGC));
948
949 /* Wait for bist done */
950 SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000);
951
952 if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR)
953 result = BCME_ERROR;
954
955 /* Reset core control flags */
956 si_core_cflags(sih, 0xffff, cflags);
957
958 return result;
959}
960
961static uint32
962factor6(uint32 x)
963{
964 switch (x) {
965 case CC_F6_2: return 2;
966 case CC_F6_3: return 3;
967 case CC_F6_4: return 4;
968 case CC_F6_5: return 5;
969 case CC_F6_6: return 6;
970 case CC_F6_7: return 7;
971 default: return 0;
972 }
973}
974
975/* calculate the speed the SI would run at given a set of clockcontrol values */
976uint32
977si_clock_rate(uint32 pll_type, uint32 n, uint32 m)
978{
979 uint32 n1, n2, clock, m1, m2, m3, mc;
980
981 n1 = n & CN_N1_MASK;
982 n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT;
983
984 if (pll_type == PLL_TYPE6) {
985 if (m & CC_T6_MMASK)
986 return CC_T6_M1;
987 else
988 return CC_T6_M0;
989 } else if ((pll_type == PLL_TYPE1) ||
990 (pll_type == PLL_TYPE3) ||
991 (pll_type == PLL_TYPE4) ||
992 (pll_type == PLL_TYPE7)) {
993 n1 = factor6(n1);
994 n2 += CC_F5_BIAS;
995 } else if (pll_type == PLL_TYPE2) {
996 n1 += CC_T2_BIAS;
997 n2 += CC_T2_BIAS;
998 ASSERT((n1 >= 2) && (n1 <= 7));
999 ASSERT((n2 >= 5) && (n2 <= 23));
1000 } else if (pll_type == PLL_TYPE5) {
1001 return (100000000);
1002 } else
1003 ASSERT(0);
1004 /* PLL types 3 and 7 use BASE2 (25Mhz) */
1005 if ((pll_type == PLL_TYPE3) ||
1006 (pll_type == PLL_TYPE7)) {
1007 clock = CC_CLOCK_BASE2 * n1 * n2;
1008 } else
1009 clock = CC_CLOCK_BASE1 * n1 * n2;
1010
1011 if (clock == 0)
1012 return 0;
1013
1014 m1 = m & CC_M1_MASK;
1015 m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT;
1016 m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT;
1017 mc = (m & CC_MC_MASK) >> CC_MC_SHIFT;
1018
1019 if ((pll_type == PLL_TYPE1) ||
1020 (pll_type == PLL_TYPE3) ||
1021 (pll_type == PLL_TYPE4) ||
1022 (pll_type == PLL_TYPE7)) {
1023 m1 = factor6(m1);
1024 if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3))
1025 m2 += CC_F5_BIAS;
1026 else
1027 m2 = factor6(m2);
1028 m3 = factor6(m3);
1029
1030 switch (mc) {
1031 case CC_MC_BYPASS: return (clock);
1032 case CC_MC_M1: return (clock / m1);
1033 case CC_MC_M1M2: return (clock / (m1 * m2));
1034 case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3));
1035 case CC_MC_M1M3: return (clock / (m1 * m3));
1036 default: return (0);
1037 }
1038 } else {
1039 ASSERT(pll_type == PLL_TYPE2);
1040
1041 m1 += CC_T2_BIAS;
1042 m2 += CC_T2M2_BIAS;
1043 m3 += CC_T2_BIAS;
1044 ASSERT((m1 >= 2) && (m1 <= 7));
1045 ASSERT((m2 >= 3) && (m2 <= 10));
1046 ASSERT((m3 >= 2) && (m3 <= 7));
1047
1048 if ((mc & CC_T2MC_M1BYP) == 0)
1049 clock /= m1;
1050 if ((mc & CC_T2MC_M2BYP) == 0)
1051 clock /= m2;
1052 if ((mc & CC_T2MC_M3BYP) == 0)
1053 clock /= m3;
1054
1055 return (clock);
1056 }
1057}
1058
1059
1060/* set chip watchdog reset timer to fire in 'ticks' */
1061void
1062si_watchdog(si_t *sih, uint ticks)
1063{
1064 uint nb, maxt;
1065
1066 if (PMUCTL_ENAB(sih)) {
1067
1068 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1069 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1070 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2);
1071 si_setcore(sih, USB20D_CORE_ID, 0);
1072 si_core_disable(sih, 1);
1073 si_setcore(sih, CC_CORE_ID, 0);
1074 }
1075
1076 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1077 /* The mips compiler uses the sllv instruction,
1078 * so we specially handle the 32-bit case.
1079 */
1080 if (nb == 32)
1081 maxt = 0xffffffff;
1082 else
1083 maxt = ((1 << nb) - 1);
1084
1085 if (ticks == 1)
1086 ticks = 2;
1087 else if (ticks > maxt)
1088 ticks = maxt;
1089
1090 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks);
1091 } else {
1092 maxt = (1 << 28) - 1;
1093 if (ticks > maxt)
1094 ticks = maxt;
1095
1096 si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks);
1097 }
1098}
1099
1100/* trigger watchdog reset after ms milliseconds */
1101void
1102si_watchdog_ms(si_t *sih, uint32 ms)
1103{
1104 si_watchdog(sih, wd_msticks * ms);
1105}
1106
1107
1108
1109
Dmitry Shmidt1dddb0c2012-01-24 13:37:34 -08001110/* return the slow clock source - LPO, XTAL, or PCI */
1111static uint
1112si_slowclk_src(si_info_t *sii)
1113{
1114 chipcregs_t *cc;
1115
1116 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1117
1118 if (sii->pub.ccrev < 6) {
1119 if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) &&
1120 (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) &
1121 PCI_CFG_GPIO_SCS))
1122 return (SCC_SS_PCI);
1123 else
1124 return (SCC_SS_XTAL);
1125 } else if (sii->pub.ccrev < 10) {
1126 cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx);
1127 return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK);
1128 } else /* Insta-clock */
1129 return (SCC_SS_XTAL);
1130}
1131
1132/* return the ILP (slowclock) min or max frequency */
1133static uint
1134si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
1135{
1136 uint32 slowclk;
1137 uint div;
1138
1139 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1140
1141 /* shouldn't be here unless we've established the chip has dynamic clk control */
1142 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1143
1144 slowclk = si_slowclk_src(sii);
1145 if (sii->pub.ccrev < 6) {
1146 if (slowclk == SCC_SS_PCI)
1147 return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64));
1148 else
1149 return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32));
1150 } else if (sii->pub.ccrev < 10) {
1151 div = 4 *
1152 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1);
1153 if (slowclk == SCC_SS_LPO)
1154 return (max_freq ? LPOMAXFREQ : LPOMINFREQ);
1155 else if (slowclk == SCC_SS_XTAL)
1156 return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div));
1157 else if (slowclk == SCC_SS_PCI)
1158 return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div));
1159 else
1160 ASSERT(0);
1161 } else {
1162 /* Chipc rev 10 is InstaClock */
1163 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1164 div = 4 * (div + 1);
1165 return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div));
1166 }
1167 return (0);
1168}
1169
1170static void
1171si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
1172{
1173 chipcregs_t *cc = (chipcregs_t *)chipcregs;
1174 uint slowmaxfreq, pll_delay, slowclk;
1175 uint pll_on_delay, fref_sel_delay;
1176
1177 pll_delay = PLL_DELAY;
1178
1179 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1180 * since the xtal will also be powered down by dynamic clk control logic.
1181 */
1182
1183 slowclk = si_slowclk_src(sii);
1184 if (slowclk != SCC_SS_XTAL)
1185 pll_delay += XTAL_ON_DELAY;
1186
1187 /* Starting with 4318 it is ILP that is used for the delays */
1188 slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc);
1189
1190 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1191 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1192
1193 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1194 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1195}
1196
1197/* initialize power control delay registers */
1198void
1199si_clkctl_init(si_t *sih)
1200{
1201 si_info_t *sii;
1202 uint origidx = 0;
1203 chipcregs_t *cc;
1204 bool fast;
1205
1206 if (!CCCTL_ENAB(sih))
1207 return;
1208
1209 sii = SI_INFO(sih);
1210 fast = SI_FAST(sii);
1211 if (!fast) {
1212 origidx = sii->curidx;
1213 if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL)
1214 return;
1215 } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL)
1216 return;
1217 ASSERT(cc != NULL);
1218
1219 /* set all Instaclk chip ILP to 1 MHz */
1220 if (sih->ccrev >= 10)
1221 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1222 (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1223
1224 si_clkctl_setdelay(sii, (void *)(uintptr)cc);
1225
1226 if (!fast)
1227 si_setcoreidx(sih, origidx);
1228}
1229
Dmitry Shmidt66eb9fa2011-05-24 11:14:33 -07001230/* change logical "focus" to the gpio core for optimized access */
1231void *
1232si_gpiosetcore(si_t *sih)
1233{
1234 return (si_setcoreidx(sih, SI_CC_IDX));
1235}
1236
1237/* mask&set gpiocontrol bits */
1238uint32
1239si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1240{
1241 uint regoff;
1242
1243 regoff = 0;
1244
1245 /* gpios could be shared on router platforms
1246 * ignore reservation if it's high priority (e.g., test apps)
1247 */
1248 if ((priority != GPIO_HI_PRIORITY) &&
1249 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1250 mask = priority ? (si_gpioreservation & mask) :
1251 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1252 val &= mask;
1253 }
1254
1255 regoff = OFFSETOF(chipcregs_t, gpiocontrol);
1256 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1257}
1258
1259/* mask&set gpio output enable bits */
1260uint32
1261si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1262{
1263 uint regoff;
1264
1265 regoff = 0;
1266
1267 /* gpios could be shared on router platforms
1268 * ignore reservation if it's high priority (e.g., test apps)
1269 */
1270 if ((priority != GPIO_HI_PRIORITY) &&
1271 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1272 mask = priority ? (si_gpioreservation & mask) :
1273 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1274 val &= mask;
1275 }
1276
1277 regoff = OFFSETOF(chipcregs_t, gpioouten);
1278 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1279}
1280
1281/* mask&set gpio output bits */
1282uint32
1283si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1284{
1285 uint regoff;
1286
1287 regoff = 0;
1288
1289 /* gpios could be shared on router platforms
1290 * ignore reservation if it's high priority (e.g., test apps)
1291 */
1292 if ((priority != GPIO_HI_PRIORITY) &&
1293 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1294 mask = priority ? (si_gpioreservation & mask) :
1295 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1296 val &= mask;
1297 }
1298
1299 regoff = OFFSETOF(chipcregs_t, gpioout);
1300 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1301}
1302
1303/* reserve one gpio */
1304uint32
1305si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1306{
1307 si_info_t *sii;
1308
1309 sii = SI_INFO(sih);
1310
1311 /* only cores on SI_BUS share GPIO's and only applcation users need to
1312 * reserve/release GPIO
1313 */
1314 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1315 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1316 return 0xffffffff;
1317 }
1318 /* make sure only one bit is set */
1319 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1320 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1321 return 0xffffffff;
1322 }
1323
1324 /* already reserved */
1325 if (si_gpioreservation & gpio_bitmask)
1326 return 0xffffffff;
1327 /* set reservation */
1328 si_gpioreservation |= gpio_bitmask;
1329
1330 return si_gpioreservation;
1331}
1332
1333/* release one gpio */
1334/*
1335 * releasing the gpio doesn't change the current value on the GPIO last write value
1336 * persists till some one overwrites it
1337 */
1338
1339uint32
1340si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority)
1341{
1342 si_info_t *sii;
1343
1344 sii = SI_INFO(sih);
1345
1346 /* only cores on SI_BUS share GPIO's and only applcation users need to
1347 * reserve/release GPIO
1348 */
1349 if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) {
1350 ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority));
1351 return 0xffffffff;
1352 }
1353 /* make sure only one bit is set */
1354 if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) {
1355 ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1)));
1356 return 0xffffffff;
1357 }
1358
1359 /* already released */
1360 if (!(si_gpioreservation & gpio_bitmask))
1361 return 0xffffffff;
1362
1363 /* clear reservation */
1364 si_gpioreservation &= ~gpio_bitmask;
1365
1366 return si_gpioreservation;
1367}
1368
1369/* return the current gpioin register value */
1370uint32
1371si_gpioin(si_t *sih)
1372{
1373 si_info_t *sii;
1374 uint regoff;
1375
1376 sii = SI_INFO(sih);
1377 regoff = 0;
1378
1379 regoff = OFFSETOF(chipcregs_t, gpioin);
1380 return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0));
1381}
1382
1383/* mask&set gpio interrupt polarity bits */
1384uint32
1385si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1386{
1387 si_info_t *sii;
1388 uint regoff;
1389
1390 sii = SI_INFO(sih);
1391 regoff = 0;
1392
1393 /* gpios could be shared on router platforms */
1394 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1395 mask = priority ? (si_gpioreservation & mask) :
1396 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1397 val &= mask;
1398 }
1399
1400 regoff = OFFSETOF(chipcregs_t, gpiointpolarity);
1401 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1402}
1403
1404/* mask&set gpio interrupt mask bits */
1405uint32
1406si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority)
1407{
1408 si_info_t *sii;
1409 uint regoff;
1410
1411 sii = SI_INFO(sih);
1412 regoff = 0;
1413
1414 /* gpios could be shared on router platforms */
1415 if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1416 mask = priority ? (si_gpioreservation & mask) :
1417 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1418 val &= mask;
1419 }
1420
1421 regoff = OFFSETOF(chipcregs_t, gpiointmask);
1422 return (si_corereg(sih, SI_CC_IDX, regoff, mask, val));
1423}
1424
1425/* assign the gpio to an led */
1426uint32
1427si_gpioled(si_t *sih, uint32 mask, uint32 val)
1428{
1429 si_info_t *sii;
1430
1431 sii = SI_INFO(sih);
1432 if (sih->ccrev < 16)
1433 return 0xffffffff;
1434
1435 /* gpio led powersave reg */
1436 return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val));
1437}
1438
1439/* mask&set gpio timer val */
1440uint32
1441si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval)
1442{
1443 si_info_t *sii;
1444
1445 sii = SI_INFO(sih);
1446
1447 if (sih->ccrev < 16)
1448 return 0xffffffff;
1449
1450 return (si_corereg(sih, SI_CC_IDX,
1451 OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval));
1452}
1453
1454uint32
1455si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val)
1456{
1457 si_info_t *sii;
1458 uint offs;
1459
1460 sii = SI_INFO(sih);
1461 if (sih->ccrev < 20)
1462 return 0xffffffff;
1463
1464 offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup));
1465 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1466}
1467
1468uint32
1469si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val)
1470{
1471 si_info_t *sii;
1472 uint offs;
1473
1474 sii = SI_INFO(sih);
1475 if (sih->ccrev < 11)
1476 return 0xffffffff;
1477
1478 if (regtype == GPIO_REGEVT)
1479 offs = OFFSETOF(chipcregs_t, gpioevent);
1480 else if (regtype == GPIO_REGEVT_INTMSK)
1481 offs = OFFSETOF(chipcregs_t, gpioeventintmask);
1482 else if (regtype == GPIO_REGEVT_INTPOL)
1483 offs = OFFSETOF(chipcregs_t, gpioeventintpolarity);
1484 else
1485 return 0xffffffff;
1486
1487 return (si_corereg(sih, SI_CC_IDX, offs, mask, val));
1488}
1489
1490void *
1491si_gpio_handler_register(si_t *sih, uint32 event,
1492 bool level, gpio_handler_t cb, void *arg)
1493{
1494 si_info_t *sii;
1495 gpioh_item_t *gi;
1496
1497 ASSERT(event);
1498 ASSERT(cb != NULL);
1499
1500 sii = SI_INFO(sih);
1501 if (sih->ccrev < 11)
1502 return NULL;
1503
1504 if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL)
1505 return NULL;
1506
1507 bzero(gi, sizeof(gpioh_item_t));
1508 gi->event = event;
1509 gi->handler = cb;
1510 gi->arg = arg;
1511 gi->level = level;
1512
1513 gi->next = sii->gpioh_head;
1514 sii->gpioh_head = gi;
1515
1516 return (void *)(gi);
1517}
1518
1519void
1520si_gpio_handler_unregister(si_t *sih, void *gpioh)
1521{
1522 si_info_t *sii;
1523 gpioh_item_t *p, *n;
1524
1525 sii = SI_INFO(sih);
1526 if (sih->ccrev < 11)
1527 return;
1528
1529 ASSERT(sii->gpioh_head != NULL);
1530 if ((void*)sii->gpioh_head == gpioh) {
1531 sii->gpioh_head = sii->gpioh_head->next;
1532 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1533 return;
1534 } else {
1535 p = sii->gpioh_head;
1536 n = p->next;
1537 while (n) {
1538 if ((void*)n == gpioh) {
1539 p->next = n->next;
1540 MFREE(sii->osh, gpioh, sizeof(gpioh_item_t));
1541 return;
1542 }
1543 p = n;
1544 n = n->next;
1545 }
1546 }
1547
1548 ASSERT(0); /* Not found in list */
1549}
1550
1551void
1552si_gpio_handler_process(si_t *sih)
1553{
1554 si_info_t *sii;
1555 gpioh_item_t *h;
1556 uint32 level = si_gpioin(sih);
1557 uint32 levelp = si_gpiointpolarity(sih, 0, 0, 0);
1558 uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0);
1559 uint32 edgep = si_gpioevent(sih, GPIO_REGEVT_INTPOL, 0, 0);
1560
1561 sii = SI_INFO(sih);
1562 for (h = sii->gpioh_head; h != NULL; h = h->next) {
1563 if (h->handler) {
1564 uint32 status = (h->level ? level : edge) & h->event;
1565 uint32 polarity = (h->level ? levelp : edgep) & h->event;
1566
1567 /* polarity bitval is opposite of status bitval */
1568 if (status ^ polarity)
1569 h->handler(status, h->arg);
1570 }
1571 }
1572
1573 si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */
1574}
1575
1576uint32
1577si_gpio_int_enable(si_t *sih, bool enable)
1578{
1579 si_info_t *sii;
1580 uint offs;
1581
1582 sii = SI_INFO(sih);
1583 if (sih->ccrev < 11)
1584 return 0xffffffff;
1585
1586 offs = OFFSETOF(chipcregs_t, intmask);
1587 return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0)));
1588}
1589
1590
1591/* Return the size of the specified SOCRAM bank */
1592static uint
1593socram_banksize(si_info_t *sii, sbsocramregs_t *regs, uint8 index, uint8 mem_type)
1594{
1595 uint banksize, bankinfo;
1596 uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1597
1598 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
1599
1600 W_REG(sii->osh, &regs->bankidx, bankidx);
1601 bankinfo = R_REG(sii->osh, &regs->bankinfo);
1602 banksize = SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
1603 return banksize;
1604}
1605
1606void
1607si_socdevram(si_t *sih, bool set, uint8 *enable, uint8 *protect)
1608{
1609 si_info_t *sii;
1610 uint origidx;
1611 uint intr_val = 0;
1612 sbsocramregs_t *regs;
1613 bool wasup;
1614 uint corerev;
1615
1616 sii = SI_INFO(sih);
1617
1618 /* Block ints and save current core */
1619 INTR_OFF(sii, intr_val);
1620 origidx = si_coreidx(sih);
1621
1622 if (!set)
1623 *enable = *protect = 0;
1624
1625 /* Switch to SOCRAM core */
1626 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1627 goto done;
1628
1629 /* Get info for determining size */
1630 if (!(wasup = si_iscoreup(sih)))
1631 si_core_reset(sih, 0, 0);
1632
1633 corerev = si_corerev(sih);
1634 if (corerev >= 10) {
1635 uint32 extcinfo;
1636 uint8 nb;
1637 uint8 i;
1638 uint32 bankidx, bankinfo;
1639
1640 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1641 nb = ((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT);
1642 for (i = 0; i < nb; i++) {
1643 bankidx = i | (SOCRAM_MEMTYPE_DEVRAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
1644 W_REG(sii->osh, &regs->bankidx, bankidx);
1645 bankinfo = R_REG(sii->osh, &regs->bankinfo);
1646 if (set) {
1647 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMSEL_MASK;
1648 bankinfo &= ~SOCRAM_BANKINFO_DEVRAMPRO_MASK;
1649 if (*enable) {
1650 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMSEL_SHIFT);
1651 if (*protect)
1652 bankinfo |= (1 << SOCRAM_BANKINFO_DEVRAMPRO_SHIFT);
1653 }
1654 W_REG(sii->osh, &regs->bankinfo, bankinfo);
1655 }
1656 else if (i == 0) {
1657 if (bankinfo & SOCRAM_BANKINFO_DEVRAMSEL_MASK) {
1658 *enable = 1;
1659 if (bankinfo & SOCRAM_BANKINFO_DEVRAMPRO_MASK)
1660 *protect = 1;
1661 }
1662 }
1663 }
1664 }
1665
1666 /* Return to previous state and core */
1667 if (!wasup)
1668 si_core_disable(sih, 0);
1669 si_setcoreidx(sih, origidx);
1670
1671done:
1672 INTR_RESTORE(sii, intr_val);
1673}
1674
1675bool
1676si_socdevram_pkg(si_t *sih)
1677{
1678 if (si_socdevram_size(sih) > 0)
1679 return TRUE;
1680 else
1681 return FALSE;
1682}
1683
1684uint32
1685si_socdevram_size(si_t *sih)
1686{
1687 si_info_t *sii;
1688 uint origidx;
1689 uint intr_val = 0;
1690 uint32 memsize = 0;
1691 sbsocramregs_t *regs;
1692 bool wasup;
1693 uint corerev;
1694
1695 sii = SI_INFO(sih);
1696
1697 /* Block ints and save current core */
1698 INTR_OFF(sii, intr_val);
1699 origidx = si_coreidx(sih);
1700
1701 /* Switch to SOCRAM core */
1702 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1703 goto done;
1704
1705 /* Get info for determining size */
1706 if (!(wasup = si_iscoreup(sih)))
1707 si_core_reset(sih, 0, 0);
1708
1709 corerev = si_corerev(sih);
1710 if (corerev >= 10) {
1711 uint32 extcinfo;
1712 uint8 nb;
1713 uint8 i;
1714
1715 extcinfo = R_REG(sii->osh, &regs->extracoreinfo);
1716 nb = (((extcinfo & SOCRAM_DEVRAMBANK_MASK) >> SOCRAM_DEVRAMBANK_SHIFT));
1717 for (i = 0; i < nb; i++)
1718 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_DEVRAM);
1719 }
1720
1721 /* Return to previous state and core */
1722 if (!wasup)
1723 si_core_disable(sih, 0);
1724 si_setcoreidx(sih, origidx);
1725
1726done:
1727 INTR_RESTORE(sii, intr_val);
1728
1729 return memsize;
1730}
1731
1732/* Return the RAM size of the SOCRAM core */
1733uint32
1734si_socram_size(si_t *sih)
1735{
1736 si_info_t *sii;
1737 uint origidx;
1738 uint intr_val = 0;
1739
1740 sbsocramregs_t *regs;
1741 bool wasup;
1742 uint corerev;
1743 uint32 coreinfo;
1744 uint memsize = 0;
1745
1746 sii = SI_INFO(sih);
1747
1748 /* Block ints and save current core */
1749 INTR_OFF(sii, intr_val);
1750 origidx = si_coreidx(sih);
1751
1752 /* Switch to SOCRAM core */
1753 if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0)))
1754 goto done;
1755
1756 /* Get info for determining size */
1757 if (!(wasup = si_iscoreup(sih)))
1758 si_core_reset(sih, 0, 0);
1759 corerev = si_corerev(sih);
1760 coreinfo = R_REG(sii->osh, &regs->coreinfo);
1761
1762 /* Calculate size from coreinfo based on rev */
1763 if (corerev == 0)
1764 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
1765 else if (corerev < 3) {
1766 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
1767 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1768 } else if ((corerev <= 7) || (corerev == 12)) {
1769 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1770 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
1771 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
1772 if (lss != 0)
1773 nb --;
1774 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
1775 if (lss != 0)
1776 memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
1777 } else {
1778 uint8 i;
1779 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1780 for (i = 0; i < nb; i++)
1781 memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
1782 }
1783
1784 /* Return to previous state and core */
1785 if (!wasup)
1786 si_core_disable(sih, 0);
1787 si_setcoreidx(sih, origidx);
1788
1789done:
1790 INTR_RESTORE(sii, intr_val);
1791
1792 return memsize;
1793}
1794
1795
1796void
1797si_btcgpiowar(si_t *sih)
1798{
1799 si_info_t *sii;
1800 uint origidx;
1801 uint intr_val = 0;
1802 chipcregs_t *cc;
1803
1804 sii = SI_INFO(sih);
1805
1806 /* Make sure that there is ChipCommon core present &&
1807 * UART_TX is strapped to 1
1808 */
1809 if (!(sih->cccaps & CC_CAP_UARTGPIO))
1810 return;
1811
1812 /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */
1813 INTR_OFF(sii, intr_val);
1814
1815 origidx = si_coreidx(sih);
1816
1817 cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0);
1818 ASSERT(cc != NULL);
1819
1820 W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04);
1821
1822 /* restore the original index */
1823 si_setcoreidx(sih, origidx);
1824
1825 INTR_RESTORE(sii, intr_val);
1826}
1827
1828uint
1829si_pll_reset(si_t *sih)
1830{
1831 uint err = 0;
1832
1833 return (err);
1834}
1835
1836/* check if the device is removed */
1837bool
1838si_deviceremoved(si_t *sih)
1839{
1840 uint32 w;
1841 si_info_t *sii;
1842
1843 sii = SI_INFO(sih);
1844
1845 switch (BUSTYPE(sih->bustype)) {
1846 case PCI_BUS:
1847 ASSERT(sii->osh != NULL);
1848 w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32));
1849 if ((w & 0xFFFF) != VENDOR_BROADCOM)
1850 return TRUE;
1851 break;
1852 }
1853 return FALSE;
1854}
Dmitry Shmidt1dddb0c2012-01-24 13:37:34 -08001855
1856bool
1857si_is_sprom_available(si_t *sih)
1858{
1859 if (sih->ccrev >= 31) {
1860 si_info_t *sii;
1861 uint origidx;
1862 chipcregs_t *cc;
1863 uint32 sromctrl;
1864
1865 if ((sih->cccaps & CC_CAP_SROM) == 0)
1866 return FALSE;
1867
1868 sii = SI_INFO(sih);
1869 origidx = sii->curidx;
1870 cc = si_setcoreidx(sih, SI_CC_IDX);
1871 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
1872 si_setcoreidx(sih, origidx);
1873 return (sromctrl & SRC_PRESENT);
1874 }
1875
1876 switch (CHIPID(sih->chip)) {
1877 case BCM4312_CHIP_ID:
1878 return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL);
1879 case BCM4325_CHIP_ID:
1880 return (sih->chipst & CST4325_SPROM_SEL) != 0;
1881 case BCM4322_CHIP_ID:
1882 case BCM43221_CHIP_ID:
1883 case BCM43231_CHIP_ID:
1884 case BCM43222_CHIP_ID:
1885 case BCM43111_CHIP_ID:
1886 case BCM43112_CHIP_ID:
1887 case BCM4342_CHIP_ID:
1888 {
1889 uint32 spromotp;
1890 spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >>
1891 CST4322_SPROM_OTP_SEL_SHIFT;
1892 return (spromotp & CST4322_SPROM_PRESENT) != 0;
1893 }
1894 case BCM4329_CHIP_ID:
1895 return (sih->chipst & CST4329_SPROM_SEL) != 0;
1896 case BCM4315_CHIP_ID:
1897 return (sih->chipst & CST4315_SPROM_SEL) != 0;
1898 case BCM4319_CHIP_ID:
1899 return (sih->chipst & CST4319_SPROM_SEL) != 0;
1900 case BCM4330_CHIP_ID:
1901 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
1902 case BCM4313_CHIP_ID:
1903 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
Dmitry Shmidt96034c22012-01-24 13:55:00 -08001904 case BCM43239_CHIP_ID:
1905 return ((sih->chipst & CST43239_SPROM_MASK) &&
1906 !(sih->chipst & CST43239_SFLASH_MASK));
Dmitry Shmidt1dddb0c2012-01-24 13:37:34 -08001907 default:
1908 return TRUE;
1909 }
1910}