staging: brcm80211: remove unused dhd_ops_virt variable definition
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / brcm80211 / util / siutils.c
CommitLineData
a9533e7e
HP
1/*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
3327989a
BR
17#include <linux/kernel.h>
18#include <linux/string.h>
a1c16ed2 19#include <bcmdefs.h>
c6ac24e9
BR
20#ifdef BRCM_FULLMAC
21#include <linux/netdevice.h>
22#endif
a1c16ed2 23#include <osl.h>
c6ac24e9
BR
24#include <linux/module.h>
25#include <linux/pci.h>
a9533e7e
HP
26#include <bcmutils.h>
27#include <siutils.h>
28#include <bcmdevs.h>
29#include <hndsoc.h>
30#include <sbchipc.h>
31#include <pci_core.h>
32#include <pcie_core.h>
33#include <nicpci.h>
34#include <bcmnvram.h>
35#include <bcmsrom.h>
a9533e7e
HP
36#include <pcicfg.h>
37#include <sbsocram.h>
38#ifdef BCMSDIO
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#endif /* BCMSDIO */
46#include <hndpmu.h>
47
48/* this file now contains only definitions for sb functions, only necessary
49*for devices using Sonics backplanes (bcm4329)
50*/
51
52/* if an amba SDIO device is supported, please further restrict the inclusion
53 * of this file
54 */
55#ifdef BCMSDIO
56#include "siutils_priv.h"
57#endif
58
59/* local prototypes */
e69284f2 60static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
a9533e7e 61 void *regs, uint bustype, void *sdh, char **vars,
7cc4a4c0
JC
62 uint *varsz);
63static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid,
a9533e7e 64 void *sdh);
7cc4a4c0 65static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
66cbd3ab 66 u32 savewin, uint *origidx, void *regs);
7cc4a4c0 67static void si_nvram_process(si_info_t *sii, char *pvars);
a9533e7e
HP
68
69/* dev path concatenation util */
7cc4a4c0
JC
70static char *si_devpathvar(si_t *sih, char *var, int len, const char *name);
71static bool _si_clkctl_cc(si_info_t *sii, uint mode);
72static bool si_ispcie(si_info_t *sii);
b4f790ee 73static uint socram_banksize(si_info_t *sii, sbsocramregs_t *r,
36ef9a1e 74 u8 idx, u8 mtype);
a9533e7e
HP
75
76/* global variable to indicate reservation/release of gpio's */
66cbd3ab 77static u32 si_gpioreservation;
a9533e7e 78
a9533e7e
HP
79/*
80 * Allocate a si handle.
81 * devid - pci device id (used to determine chip#)
82 * osh - opaque OS handle
83 * regs - virtual address of initial core registers
84 * bustype - pci/sb/sdio/etc
85 * vars - pointer to a pointer area for "environment" variables
86 * varsz - pointer to int to return the size of the vars
87 */
e69284f2
BR
88si_t *si_attach(uint devid, struct osl_info *osh, void *regs, uint bustype,
89 void *sdh, char **vars, uint *varsz)
0d2f0724 90{
a9533e7e
HP
91 si_info_t *sii;
92
93 /* alloc si_info_t */
5fcc1fcb 94 sii = kmalloc(sizeof(si_info_t), GFP_ATOMIC);
ca8c1e59 95 if (sii == NULL) {
97e17d0e 96 SI_ERROR(("si_attach: malloc failed!\n"));
90ea2296 97 return NULL;
a9533e7e
HP
98 }
99
100 if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) ==
101 NULL) {
182acb3c 102 kfree(sii);
90ea2296 103 return NULL;
a9533e7e
HP
104 }
105 sii->vars = vars ? *vars : NULL;
106 sii->varsz = varsz ? *varsz : 0;
107
108 return (si_t *) sii;
109}
110
111/* global kernel resource */
112static si_info_t ksii;
113
0d2f0724
GKH
114static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid,
115 void *sdh)
116{
a9533e7e 117
cf2b4488 118#ifndef BRCM_FULLMAC
a9533e7e
HP
119 /* kludge to enable the clock on the 4306 which lacks a slowclock */
120 if (BUSTYPE(bustype) == PCI_BUS && !si_ispcie(sii))
121 si_clkctl_xtal(&sii->pub, XTAL | PLL, ON);
cf2b4488 122#endif
a9533e7e
HP
123
124#if defined(BCMSDIO)
125 if (BUSTYPE(bustype) == SDIO_BUS) {
126 int err;
36ef9a1e 127 u8 clkset;
a9533e7e
HP
128
129 /* Try forcing SDIO core to do ALPAvail request only */
130 clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
131 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
132 clkset, &err);
133 if (!err) {
36ef9a1e 134 u8 clkval;
a9533e7e
HP
135
136 /* If register supported, wait for ALPAvail and then force ALP */
137 clkval =
138 bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
139 SBSDIO_FUNC1_CHIPCLKCSR, NULL);
140 if ((clkval & ~SBSDIO_AVBITS) == clkset) {
141 SPINWAIT(((clkval =
142 bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
143 SBSDIO_FUNC1_CHIPCLKCSR,
144 NULL)),
145 !SBSDIO_ALPAV(clkval)),
146 PMU_MAX_TRANSITION_DLY);
147 if (!SBSDIO_ALPAV(clkval)) {
148 SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n", clkval));
0965ae88 149 return false;
a9533e7e
HP
150 }
151 clkset =
152 SBSDIO_FORCE_HW_CLKREQ_OFF |
153 SBSDIO_FORCE_ALP;
154 bcmsdh_cfg_write(sdh, SDIO_FUNC_1,
155 SBSDIO_FUNC1_CHIPCLKCSR,
156 clkset, &err);
7383141b 157 udelay(65);
a9533e7e
HP
158 }
159 }
160
161 /* Also, disable the extra SDIO pull-ups */
162 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0,
163 NULL);
164 }
165#endif /* defined(BCMSDIO) */
166
0f0881b0 167 return true;
a9533e7e
HP
168}
169
0d2f0724
GKH
170static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
171 u32 savewin, uint *origidx, void *regs)
172{
a9533e7e
HP
173 bool pci, pcie;
174 uint i;
175 uint pciidx, pcieidx, pcirev, pcierev;
176
177 cc = si_setcoreidx(&sii->pub, SI_CC_IDX);
c03b63c1 178 ASSERT(cc);
a9533e7e
HP
179
180 /* get chipcommon rev */
181 sii->pub.ccrev = (int)si_corerev(&sii->pub);
182
183 /* get chipcommon chipstatus */
184 if (sii->pub.ccrev >= 11)
185 sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
186
187 /* get chipcommon capabilites */
188 sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
189 /* get chipcommon extended capabilities */
190
cf2b4488 191#ifndef BRCM_FULLMAC
a9533e7e
HP
192 if (sii->pub.ccrev >= 35)
193 sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
cf2b4488 194#endif
a9533e7e
HP
195 /* get pmu rev and caps */
196 if (sii->pub.cccaps & CC_CAP_PMU) {
197 sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
198 sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
199 }
200
201 /*
202 SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n",
203 sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev,
204 sii->pub.pmucaps));
205 */
206
207 /* figure out bus/orignal core idx */
208 sii->pub.buscoretype = NODEV_CORE_ID;
209 sii->pub.buscorerev = NOREV;
210 sii->pub.buscoreidx = BADIDX;
211
0965ae88 212 pci = pcie = false;
a9533e7e
HP
213 pcirev = pcierev = NOREV;
214 pciidx = pcieidx = BADIDX;
215
216 for (i = 0; i < sii->numcores; i++) {
217 uint cid, crev;
218
219 si_setcoreidx(&sii->pub, i);
220 cid = si_coreid(&sii->pub);
221 crev = si_corerev(&sii->pub);
222
223 /* Display cores found */
224 SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n",
225 i, cid, crev, sii->coresba[i], sii->regs[i]));
226
227 if (BUSTYPE(bustype) == PCI_BUS) {
228 if (cid == PCI_CORE_ID) {
229 pciidx = i;
230 pcirev = crev;
0f0881b0 231 pci = true;
a9533e7e
HP
232 } else if (cid == PCIE_CORE_ID) {
233 pcieidx = i;
234 pcierev = crev;
0f0881b0 235 pcie = true;
a9533e7e
HP
236 }
237 }
238#ifdef BCMSDIO
239 else if (((BUSTYPE(bustype) == SDIO_BUS) ||
240 (BUSTYPE(bustype) == SPI_BUS)) &&
241 ((cid == PCMCIA_CORE_ID) || (cid == SDIOD_CORE_ID))) {
242 sii->pub.buscorerev = crev;
243 sii->pub.buscoretype = cid;
244 sii->pub.buscoreidx = i;
245 }
246#endif /* BCMSDIO */
247
248 /* find the core idx before entering this func. */
249 if ((savewin && (savewin == sii->coresba[i])) ||
250 (regs == sii->regs[i]))
251 *origidx = i;
252 }
253
cf2b4488
HP
254#ifdef BRCM_FULLMAC
255 SI_MSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx,
256 sii->pub.buscoretype, sii->pub.buscorerev));
257
258 /* Make sure any on-chip ARM is off (in case strapping is wrong),
259 * or downloaded code was
260 * already running.
261 */
262 if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) {
263 if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) ||
264 si_setcore(&sii->pub, ARMCM3_CORE_ID, 0))
265 si_core_disable(&sii->pub, 0);
266 }
267#else
a9533e7e
HP
268 if (pci && pcie) {
269 if (si_ispcie(sii))
0965ae88 270 pci = false;
a9533e7e 271 else
0965ae88 272 pcie = false;
a9533e7e
HP
273 }
274 if (pci) {
275 sii->pub.buscoretype = PCI_CORE_ID;
276 sii->pub.buscorerev = pcirev;
277 sii->pub.buscoreidx = pciidx;
278 } else if (pcie) {
279 sii->pub.buscoretype = PCIE_CORE_ID;
280 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,
285 sii->pub.buscoretype, sii->pub.buscorerev));
286
287 /* fixup necessary chip/core configurations */
288 if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
289 if (SI_FAST(sii)) {
ca8c1e59 290 if (!sii->pch) {
c03b63c1 291 sii->pch = (void *)pcicore_init(
ca8c1e59
JC
292 &sii->pub, sii->osh,
293 (void *)PCIEREGS(sii));
294 if (sii->pch == NULL)
0965ae88 295 return false;
ca8c1e59 296 }
a9533e7e
HP
297 }
298 if (si_pci_fixcfg(&sii->pub)) {
299 SI_ERROR(("si_doattach: sb_pci_fixcfg failed\n"));
0965ae88 300 return false;
a9533e7e
HP
301 }
302 }
cf2b4488 303#endif
a9533e7e
HP
304 /* return to the original core */
305 si_setcoreidx(&sii->pub, *origidx);
306
0f0881b0 307 return true;
a9533e7e
HP
308}
309
0d2f0724 310static __used void si_nvram_process(si_info_t *sii, char *pvars)
a2627bc0 311{
a9533e7e
HP
312 uint w = 0;
313
314 /* get boardtype and boardrev */
315 switch (BUSTYPE(sii->pub.bustype)) {
316 case PCI_BUS:
317 /* do a pci config read to get subsystem id and subvendor id */
57d8cd23 318 pci_read_config_dword(sii->osh->pdev, PCI_CFG_SVID, &w);
a9533e7e 319 /* Let nvram variables override subsystem Vend/ID */
7d4df48e 320 sii->pub.boardvendor = (u16)si_getdevpathintvar(&sii->pub,
ca8c1e59
JC
321 "boardvendor");
322 if (sii->pub.boardvendor == 0)
a9533e7e
HP
323 sii->pub.boardvendor = w & 0xffff;
324 else
325 SI_ERROR(("Overriding boardvendor: 0x%x instead of 0x%x\n", sii->pub.boardvendor, w & 0xffff));
7d4df48e 326 sii->pub.boardtype = (u16)si_getdevpathintvar(&sii->pub,
ca8c1e59
JC
327 "boardtype");
328 if (sii->pub.boardtype == 0)
a9533e7e
HP
329 sii->pub.boardtype = (w >> 16) & 0xffff;
330 else
331 SI_ERROR(("Overriding boardtype: 0x%x instead of 0x%x\n", sii->pub.boardtype, (w >> 16) & 0xffff));
332 break;
333
334#ifdef BCMSDIO
335 case SDIO_BUS:
336#endif
337 sii->pub.boardvendor = getintvar(pvars, "manfid");
338 sii->pub.boardtype = getintvar(pvars, "prodid");
339 break;
340
341#ifdef BCMSDIO
342 case SPI_BUS:
343 sii->pub.boardvendor = VENDOR_BROADCOM;
344 sii->pub.boardtype = SPI_BOARD;
345 break;
346#endif
347
348 case SI_BUS:
349 case JTAG_BUS:
350 sii->pub.boardvendor = VENDOR_BROADCOM;
ca8c1e59
JC
351 sii->pub.boardtype = getintvar(pvars, "prodid");
352 if (pvars == NULL || (sii->pub.boardtype == 0)) {
353 sii->pub.boardtype = getintvar(NULL, "boardtype");
354 if (sii->pub.boardtype == 0)
a9533e7e 355 sii->pub.boardtype = 0xffff;
ca8c1e59 356 }
a9533e7e
HP
357 break;
358 }
359
360 if (sii->pub.boardtype == 0) {
361 SI_ERROR(("si_doattach: unknown board type\n"));
362 ASSERT(sii->pub.boardtype);
363 }
364
365 sii->pub.boardflags = getintvar(pvars, "boardflags");
366}
367
368/* this is will make Sonics calls directly, since Sonics is no longer supported in the Si abstraction */
369/* this has been customized for the bcm 4329 ONLY */
370#ifdef BCMSDIO
e69284f2 371static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
0d2f0724
GKH
372 void *regs, uint bustype, void *sdh,
373 char **vars, uint *varsz)
374{
a9533e7e 375 struct si_pub *sih = &sii->pub;
66cbd3ab 376 u32 w, savewin;
a9533e7e
HP
377 chipcregs_t *cc;
378 char *pvars = NULL;
379 uint origidx;
380
381 ASSERT(GOODREGS(regs));
382
580a0bd9 383 bzero((unsigned char *) sii, sizeof(si_info_t));
a9533e7e
HP
384
385 savewin = 0;
386
387 sih->buscoreidx = BADIDX;
388
389 sii->curmap = regs;
390 sii->sdh = sdh;
391 sii->osh = osh;
392
393 /* find Chipcommon address */
394 cc = (chipcregs_t *) sii->curmap;
395 sih->bustype = bustype;
396
397 if (bustype != BUSTYPE(bustype)) {
398 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
399 return NULL;
400 }
401
402 /* bus/core/clk setup for register access */
403 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
404 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
405 bustype));
406 return NULL;
407 }
408
409 /* ChipID recognition.
410 * We assume we can read chipid at offset 0 from the regs arg.
411 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
412 * some way of recognizing them needs to be added here.
413 */
414 w = R_REG(osh, &cc->chipid);
415 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
416 /* Might as wll fill in chip id rev & pkg */
417 sih->chip = w & CID_ID_MASK;
418 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
419 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
420
cf2b4488
HP
421 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) &&
422 (sih->chippkg != BCM4329_289PIN_PKG_ID))
423 sih->chippkg = BCM4329_182PIN_PKG_ID;
424
a9533e7e
HP
425 sih->issim = IS_SIM(sih->chippkg);
426
427 /* scan for cores */
428 /* SI_MSG(("Found chip type SB (0x%08x)\n", w)); */
429 sb_scan(&sii->pub, regs, devid);
430
431 /* no cores found, bail out */
432 if (sii->numcores == 0) {
433 SI_ERROR(("si_doattach: could not find any cores\n"));
434 return NULL;
435 }
436 /* bus/core/clk setup */
437 origidx = SI_CC_IDX;
438 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
439 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
440 goto exit;
441 }
442
cf2b4488
HP
443#ifdef BRCM_FULLMAC
444 pvars = NULL;
445#else
a9533e7e
HP
446 /* Init nvram from flash if it exists */
447 nvram_init((void *)&(sii->pub));
448
449 /* Init nvram from sprom/otp if they exist */
450 if (srom_var_init
451 (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
452 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
453 goto exit;
454 }
455 pvars = vars ? *vars : NULL;
456 si_nvram_process(sii, pvars);
cf2b4488 457#endif
a9533e7e
HP
458
459 /* === NVRAM, clock is ready === */
460
cf2b4488
HP
461#ifdef BRCM_FULLMAC
462 if (sii->pub.ccrev >= 20) {
463#endif
a9533e7e
HP
464 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
465 W_REG(osh, &cc->gpiopullup, 0);
466 W_REG(osh, &cc->gpiopulldown, 0);
467 sb_setcoreidx(sih, origidx);
cf2b4488
HP
468#ifdef BRCM_FULLMAC
469 }
470#endif
a9533e7e 471
cf2b4488 472#ifndef BRCM_FULLMAC
a9533e7e
HP
473 /* PMU specific initializations */
474 if (PMUCTL_ENAB(sih)) {
66cbd3ab 475 u32 xtalfreq;
a9533e7e
HP
476 si_pmu_init(sih, sii->osh);
477 si_pmu_chip_init(sih, sii->osh);
478 xtalfreq = getintvar(pvars, "xtalfreq");
479 /* If xtalfreq var not available, try to measure it */
480 if (xtalfreq == 0)
481 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
482 si_pmu_pll_init(sih, sii->osh, xtalfreq);
483 si_pmu_res_init(sih, sii->osh);
484 si_pmu_swreg_init(sih, sii->osh);
485 }
486
487 /* setup the GPIO based LED powersave register */
ca8c1e59
JC
488 w = getintvar(pvars, "leddc");
489 if (w == 0)
a9533e7e 490 w = DEFAULT_GPIOTIMERVAL;
ce0f1b8c 491 sb_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, gpiotimerval), ~0, w);
a9533e7e
HP
492
493#ifdef BCMDBG
494 /* clear any previous epidiag-induced target abort */
0965ae88 495 sb_taclear(sih, false);
a9533e7e 496#endif /* BCMDBG */
cf2b4488 497#endif
a9533e7e 498
90ea2296 499 return sii;
a9533e7e
HP
500
501 exit:
502 return NULL;
503}
504
505#else /* BCMSDIO */
e69284f2 506static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
0d2f0724
GKH
507 void *regs, uint bustype, void *sdh,
508 char **vars, uint *varsz)
509{
a9533e7e 510 struct si_pub *sih = &sii->pub;
66cbd3ab 511 u32 w, savewin;
a9533e7e
HP
512 chipcregs_t *cc;
513 char *pvars = NULL;
514 uint origidx;
515
516 ASSERT(GOODREGS(regs));
517
580a0bd9 518 bzero((unsigned char *) sii, sizeof(si_info_t));
a9533e7e
HP
519
520 savewin = 0;
521
522 sih->buscoreidx = BADIDX;
523
524 sii->curmap = regs;
525 sii->sdh = sdh;
526 sii->osh = osh;
527
528 /* check to see if we are a si core mimic'ing a pci core */
57d8cd23
BR
529 if (bustype == PCI_BUS) {
530 pci_read_config_dword(sii->osh->pdev, PCI_SPROM_CONTROL, &w);
531 if (w == 0xffffffff) {
532 SI_ERROR(("%s: incoming bus is PCI but it's a lie, "
533 " switching to SI devid:0x%x\n",
534 __func__, devid));
535 bustype = SI_BUS;
536 }
a9533e7e
HP
537 }
538
539 /* find Chipcommon address */
540 if (bustype == PCI_BUS) {
57d8cd23 541 pci_read_config_dword(sii->osh->pdev, PCI_BAR0_WIN, &savewin);
a9533e7e
HP
542 if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
543 savewin = SI_ENUM_BASE;
57d8cd23
BR
544 pci_write_config_dword(sii->osh->pdev, PCI_BAR0_WIN,
545 SI_ENUM_BASE);
a9533e7e
HP
546 cc = (chipcregs_t *) regs;
547 } else {
548 cc = (chipcregs_t *) REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE);
549 }
550
551 sih->bustype = bustype;
552 if (bustype != BUSTYPE(bustype)) {
553 SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype)));
554 return NULL;
555 }
556
557 /* bus/core/clk setup for register access */
558 if (!si_buscore_prep(sii, bustype, devid, sdh)) {
559 SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
560 bustype));
561 return NULL;
562 }
563
564 /* ChipID recognition.
565 * We assume we can read chipid at offset 0 from the regs arg.
566 * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
567 * some way of recognizing them needs to be added here.
568 */
569 w = R_REG(osh, &cc->chipid);
570 sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
571 /* Might as wll fill in chip id rev & pkg */
572 sih->chip = w & CID_ID_MASK;
573 sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
574 sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
575
576 sih->issim = IS_SIM(sih->chippkg);
577
578 /* scan for cores */
579 if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) {
580 SI_MSG(("Found chip type AI (0x%08x)\n", w));
581 /* pass chipc address instead of original core base */
c03b63c1 582 ai_scan(&sii->pub, (void *)cc, devid);
a9533e7e
HP
583 } else {
584 SI_ERROR(("Found chip of unknown type (0x%08x)\n", w));
585 return NULL;
586 }
587 /* no cores found, bail out */
588 if (sii->numcores == 0) {
589 SI_ERROR(("si_doattach: could not find any cores\n"));
590 return NULL;
591 }
592 /* bus/core/clk setup */
593 origidx = SI_CC_IDX;
594 if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) {
595 SI_ERROR(("si_doattach: si_buscore_setup failed\n"));
596 goto exit;
597 }
598
599 /* assume current core is CC */
600 if ((sii->pub.ccrev == 0x25)
601 &&
602 ((CHIPID(sih->chip) == BCM43236_CHIP_ID
603 || CHIPID(sih->chip) == BCM43235_CHIP_ID
604 || CHIPID(sih->chip) == BCM43238_CHIP_ID)
605 && (CHIPREV(sii->pub.chiprev) <= 2))) {
606
607 if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
608 uint clkdiv;
609 clkdiv = R_REG(osh, &cc->clkdiv);
610 /* otp_clk_div is even number, 120/14 < 9mhz */
611 clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
612 W_REG(osh, &cc->clkdiv, clkdiv);
613 SI_ERROR(("%s: set clkdiv to %x\n", __func__, clkdiv));
614 }
7383141b 615 udelay(10);
a9533e7e
HP
616 }
617
618 /* Init nvram from flash if it exists */
619 nvram_init((void *)&(sii->pub));
620
621 /* Init nvram from sprom/otp if they exist */
622 if (srom_var_init
623 (&sii->pub, BUSTYPE(bustype), regs, sii->osh, vars, varsz)) {
624 SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
625 goto exit;
626 }
627 pvars = vars ? *vars : NULL;
628 si_nvram_process(sii, pvars);
629
630 /* === NVRAM, clock is ready === */
631 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
632 W_REG(osh, &cc->gpiopullup, 0);
633 W_REG(osh, &cc->gpiopulldown, 0);
634 si_setcoreidx(sih, origidx);
635
636 /* PMU specific initializations */
637 if (PMUCTL_ENAB(sih)) {
66cbd3ab 638 u32 xtalfreq;
a9533e7e
HP
639 si_pmu_init(sih, sii->osh);
640 si_pmu_chip_init(sih, sii->osh);
641 xtalfreq = getintvar(pvars, "xtalfreq");
642 /* If xtalfreq var not available, try to measure it */
643 if (xtalfreq == 0)
644 xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
645 si_pmu_pll_init(sih, sii->osh, xtalfreq);
646 si_pmu_res_init(sih, sii->osh);
647 si_pmu_swreg_init(sih, sii->osh);
648 }
649
650 /* setup the GPIO based LED powersave register */
ca8c1e59
JC
651 w = getintvar(pvars, "leddc");
652 if (w == 0)
a9533e7e 653 w = DEFAULT_GPIOTIMERVAL;
ce0f1b8c 654 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, gpiotimerval), ~0, w);
a9533e7e
HP
655
656 if (PCIE(sii)) {
657 ASSERT(sii->pch != NULL);
658 pcicore_attach(sii->pch, pvars, SI_DOATTACH);
659 }
660
661 if ((CHIPID(sih->chip) == BCM43224_CHIP_ID) ||
662 (CHIPID(sih->chip) == BCM43421_CHIP_ID)) {
663 /* enable 12 mA drive strenth for 43224 and set chipControl register bit 15 */
664 if (CHIPREV(sih->chiprev) == 0) {
665 SI_MSG(("Applying 43224A0 WARs\n"));
666 si_corereg(sih, SI_CC_IDX,
ce0f1b8c 667 offsetof(chipcregs_t, chipcontrol),
a9533e7e
HP
668 CCTRL43224_GPIO_TOGGLE,
669 CCTRL43224_GPIO_TOGGLE);
670 si_pmu_chipcontrol(sih, 0, CCTRL_43224A0_12MA_LED_DRIVE,
671 CCTRL_43224A0_12MA_LED_DRIVE);
672 }
673 if (CHIPREV(sih->chiprev) >= 1) {
674 SI_MSG(("Applying 43224B0+ WARs\n"));
675 si_pmu_chipcontrol(sih, 0, CCTRL_43224B0_12MA_LED_DRIVE,
676 CCTRL_43224B0_12MA_LED_DRIVE);
677 }
678 }
679
680 if (CHIPID(sih->chip) == BCM4313_CHIP_ID) {
681 /* enable 12 mA drive strenth for 4313 and set chipControl register bit 1 */
682 SI_MSG(("Applying 4313 WARs\n"));
683 si_pmu_chipcontrol(sih, 0, CCTRL_4313_12MA_LED_DRIVE,
684 CCTRL_4313_12MA_LED_DRIVE);
685 }
686
687 if (CHIPID(sih->chip) == BCM4331_CHIP_ID) {
688 /* Enable Ext PA lines depending on chip package option */
0f0881b0 689 si_chipcontrl_epa4331(sih, true);
a9533e7e
HP
690 }
691
90ea2296 692 return sii;
a9533e7e
HP
693 exit:
694 if (BUSTYPE(sih->bustype) == PCI_BUS) {
695 if (sii->pch)
696 pcicore_deinit(sii->pch);
697 sii->pch = NULL;
698 }
699
700 return NULL;
701}
702#endif /* BCMSDIO */
703
704/* may be called with core in reset */
0d2f0724 705void si_detach(si_t *sih)
a2627bc0 706{
a9533e7e
HP
707 si_info_t *sii;
708 uint idx;
709
710 struct si_pub *si_local = NULL;
711 bcopy(&sih, &si_local, sizeof(si_t **));
712
713 sii = SI_INFO(sih);
714
715 if (sii == NULL)
716 return;
717
718 if (BUSTYPE(sih->bustype) == SI_BUS)
719 for (idx = 0; idx < SI_MAXCORES; idx++)
720 if (sii->regs[idx]) {
721 REG_UNMAP(sii->regs[idx]);
722 sii->regs[idx] = NULL;
723 }
724
cf2b4488 725#ifndef BRCM_FULLMAC
a9533e7e
HP
726 nvram_exit((void *)si_local); /* free up nvram buffers */
727
728 if (BUSTYPE(sih->bustype) == PCI_BUS) {
729 if (sii->pch)
730 pcicore_deinit(sii->pch);
731 sii->pch = NULL;
732 }
cf2b4488 733#endif
a9533e7e
HP
734#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS)
735 if (sii != &ksii)
736#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */
182acb3c 737 kfree(sii);
a9533e7e
HP
738}
739
7cc4a4c0 740void *si_osh(si_t *sih)
a9533e7e
HP
741{
742 si_info_t *sii;
743
744 sii = SI_INFO(sih);
745 return sii->osh;
746}
747
a9533e7e
HP
748/* register driver interrupt disabling and restoring callback functions */
749void
7cc4a4c0 750si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
a9533e7e
HP
751 void *intrsenabled_fn, void *intr_arg)
752{
753 si_info_t *sii;
754
755 sii = SI_INFO(sih);
756 sii->intr_arg = intr_arg;
757 sii->intrsoff_fn = (si_intrsoff_t) intrsoff_fn;
758 sii->intrsrestore_fn = (si_intrsrestore_t) intrsrestore_fn;
759 sii->intrsenabled_fn = (si_intrsenabled_t) intrsenabled_fn;
760 /* save current core id. when this function called, the current core
761 * must be the core which provides driver functions(il, et, wl, etc.)
762 */
763 sii->dev_coreid = sii->coreid[sii->curidx];
764}
765
7cc4a4c0 766void si_deregister_intr_callback(si_t *sih)
a9533e7e
HP
767{
768 si_info_t *sii;
769
770 sii = SI_INFO(sih);
771 sii->intrsoff_fn = NULL;
772}
773
7cc4a4c0 774uint si_flag(si_t *sih)
a9533e7e
HP
775{
776 if (CHIPTYPE(sih->socitype) == SOCI_AI)
777 return ai_flag(sih);
778 else {
779 ASSERT(0);
780 return 0;
781 }
782}
783
7cc4a4c0 784void si_setint(si_t *sih, int siflag)
a9533e7e
HP
785{
786 if (CHIPTYPE(sih->socitype) == SOCI_AI)
787 ai_setint(sih, siflag);
788 else
789 ASSERT(0);
790}
791
792#ifndef BCMSDIO
7cc4a4c0 793uint si_coreid(si_t *sih)
a9533e7e
HP
794{
795 si_info_t *sii;
796
797 sii = SI_INFO(sih);
798 return sii->coreid[sii->curidx];
799}
800#endif
801
7cc4a4c0 802uint si_coreidx(si_t *sih)
a9533e7e
HP
803{
804 si_info_t *sii;
805
806 sii = SI_INFO(sih);
807 return sii->curidx;
808}
809
7cc4a4c0 810bool si_backplane64(si_t *sih)
a9533e7e 811{
90ea2296 812 return (sih->cccaps & CC_CAP_BKPLN64) != 0;
a9533e7e
HP
813}
814
815#ifndef BCMSDIO
7cc4a4c0 816uint si_corerev(si_t *sih)
a9533e7e
HP
817{
818 if (CHIPTYPE(sih->socitype) == SOCI_AI)
819 return ai_corerev(sih);
820 else {
821 ASSERT(0);
822 return 0;
823 }
824}
825#endif
826
827/* return index of coreid or BADIDX if not found */
7cc4a4c0 828uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit)
a9533e7e
HP
829{
830 si_info_t *sii;
831 uint found;
832 uint i;
833
834 sii = SI_INFO(sih);
835
836 found = 0;
837
838 for (i = 0; i < sii->numcores; i++)
839 if (sii->coreid[i] == coreid) {
840 if (found == coreunit)
90ea2296 841 return i;
a9533e7e
HP
842 found++;
843 }
844
90ea2296 845 return BADIDX;
a9533e7e
HP
846}
847
a9533e7e
HP
848/*
849 * This function changes logical "focus" to the indicated core;
850 * must be called with interrupts off.
851 * Moreover, callers should keep interrupts off during switching out of and back to d11 core
852 */
7cc4a4c0 853void *si_setcore(si_t *sih, uint coreid, uint coreunit)
a9533e7e
HP
854{
855 uint idx;
856
857 idx = si_findcoreidx(sih, coreid, coreunit);
858 if (!GOODIDX(idx))
90ea2296 859 return NULL;
a9533e7e
HP
860
861 if (CHIPTYPE(sih->socitype) == SOCI_AI)
862 return ai_setcoreidx(sih, idx);
863 else {
864#ifdef BCMSDIO
865 return sb_setcoreidx(sih, idx);
866#else
867 ASSERT(0);
868 return NULL;
869#endif
870 }
871}
872
873#ifndef BCMSDIO
7cc4a4c0 874void *si_setcoreidx(si_t *sih, uint coreidx)
a9533e7e
HP
875{
876 if (CHIPTYPE(sih->socitype) == SOCI_AI)
877 return ai_setcoreidx(sih, coreidx);
878 else {
879 ASSERT(0);
880 return NULL;
881 }
882}
883#endif
884
885/* Turn off interrupt as required by sb_setcore, before switch core */
7cc4a4c0 886void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val)
a9533e7e
HP
887{
888 void *cc;
889 si_info_t *sii;
890
891 sii = SI_INFO(sih);
892
893 if (SI_FAST(sii)) {
894 /* Overloading the origidx variable to remember the coreid,
895 * this works because the core ids cannot be confused with
896 * core indices.
897 */
898 *origidx = coreid;
899 if (coreid == CC_CORE_ID)
900 return (void *)CCREGS_FAST(sii);
901 else if (coreid == sih->buscoretype)
902 return (void *)PCIEREGS(sii);
903 }
904 INTR_OFF(sii, *intr_val);
905 *origidx = sii->curidx;
906 cc = si_setcore(sih, coreid, 0);
907 ASSERT(cc != NULL);
908
909 return cc;
910}
911
912/* restore coreidx and restore interrupt */
7cc4a4c0 913void si_restore_core(si_t *sih, uint coreid, uint intr_val)
a9533e7e
HP
914{
915 si_info_t *sii;
916
917 sii = SI_INFO(sih);
918 if (SI_FAST(sii)
919 && ((coreid == CC_CORE_ID) || (coreid == sih->buscoretype)))
920 return;
921
922 si_setcoreidx(sih, coreid);
923 INTR_RESTORE(sii, intr_val);
924}
925
66cbd3ab 926u32 si_core_cflags(si_t *sih, u32 mask, u32 val)
a9533e7e
HP
927{
928 if (CHIPTYPE(sih->socitype) == SOCI_AI)
929 return ai_core_cflags(sih, mask, val);
930 else {
931 ASSERT(0);
932 return 0;
933 }
934}
935
66cbd3ab 936u32 si_core_sflags(si_t *sih, u32 mask, u32 val)
a9533e7e
HP
937{
938 if (CHIPTYPE(sih->socitype) == SOCI_AI)
939 return ai_core_sflags(sih, mask, val);
940 else {
941 ASSERT(0);
942 return 0;
943 }
944}
945
7cc4a4c0 946bool si_iscoreup(si_t *sih)
a9533e7e
HP
947{
948 if (CHIPTYPE(sih->socitype) == SOCI_AI)
949 return ai_iscoreup(sih);
950 else {
951#ifdef BCMSDIO
952 return sb_iscoreup(sih);
953#else
954 ASSERT(0);
0965ae88 955 return false;
a9533e7e
HP
956#endif
957 }
958}
959
66cbd3ab 960void si_write_wrapperreg(si_t *sih, u32 offset, u32 val)
a9533e7e
HP
961{
962 /* only for 4319, no requirement for SOCI_SB */
963 if (CHIPTYPE(sih->socitype) == SOCI_AI) {
964 ai_write_wrap_reg(sih, offset, val);
965 }
966}
967
7cc4a4c0 968uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
a9533e7e
HP
969{
970
971 if (CHIPTYPE(sih->socitype) == SOCI_AI)
972 return ai_corereg(sih, coreidx, regoff, mask, val);
973 else {
974#ifdef BCMSDIO
975 return sb_corereg(sih, coreidx, regoff, mask, val);
976#else
977 ASSERT(0);
978 return 0;
979#endif
980 }
981}
982
66cbd3ab 983void si_core_disable(si_t *sih, u32 bits)
a9533e7e
HP
984{
985
986 if (CHIPTYPE(sih->socitype) == SOCI_AI)
987 ai_core_disable(sih, bits);
988#ifdef BCMSDIO
989 else
990 sb_core_disable(sih, bits);
991#endif
992}
993
66cbd3ab 994void si_core_reset(si_t *sih, u32 bits, u32 resetbits)
a9533e7e
HP
995{
996 if (CHIPTYPE(sih->socitype) == SOCI_AI)
997 ai_core_reset(sih, bits, resetbits);
998#ifdef BCMSDIO
999 else
1000 sb_core_reset(sih, bits, resetbits);
1001#endif
1002}
1003
b4f790ee 1004u32 si_alp_clock(si_t *sih)
a2627bc0 1005{
a9533e7e
HP
1006 if (PMUCTL_ENAB(sih))
1007 return si_pmu_alp_clock(sih, si_osh(sih));
1008
1009 return ALP_CLOCK;
1010}
1011
b4f790ee 1012u32 si_ilp_clock(si_t *sih)
a2627bc0 1013{
a9533e7e
HP
1014 if (PMUCTL_ENAB(sih))
1015 return si_pmu_ilp_clock(sih, si_osh(sih));
1016
1017 return ILP_CLOCK;
1018}
1019
1020/* set chip watchdog reset timer to fire in 'ticks' */
cf2b4488
HP
1021#ifdef BRCM_FULLMAC
1022void
1023si_watchdog(si_t *sih, uint ticks)
1024{
1025 if (PMUCTL_ENAB(sih)) {
1026
1027 if ((sih->chip == BCM4319_CHIP_ID) && (sih->chiprev == 0) &&
1028 (ticks != 0)) {
ce0f1b8c 1029 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t,
cf2b4488
HP
1030 clk_ctl_st), ~0, 0x2);
1031 si_setcore(sih, USB20D_CORE_ID, 0);
1032 si_core_disable(sih, 1);
1033 si_setcore(sih, CC_CORE_ID, 0);
1034 }
1035
1036 if (ticks == 1)
1037 ticks = 2;
ce0f1b8c 1038 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmuwatchdog),
cf2b4488
HP
1039 ~0, ticks);
1040 } else {
1041 /* instant NMI */
ce0f1b8c 1042 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, watchdog),
cf2b4488
HP
1043 ~0, ticks);
1044 }
1045}
1046#else
7cc4a4c0 1047void si_watchdog(si_t *sih, uint ticks)
a9533e7e
HP
1048{
1049 uint nb, maxt;
1050
1051 if (PMUCTL_ENAB(sih)) {
1052
1053 if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) &&
1054 (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) {
1055 si_corereg(sih, SI_CC_IDX,
ce0f1b8c 1056 offsetof(chipcregs_t, clk_ctl_st), ~0, 0x2);
a9533e7e
HP
1057 si_setcore(sih, USB20D_CORE_ID, 0);
1058 si_core_disable(sih, 1);
1059 si_setcore(sih, CC_CORE_ID, 0);
1060 }
1061
1062 nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24);
1063 /* The mips compiler uses the sllv instruction,
1064 * so we specially handle the 32-bit case.
1065 */
1066 if (nb == 32)
1067 maxt = 0xffffffff;
1068 else
1069 maxt = ((1 << nb) - 1);
1070
1071 if (ticks == 1)
1072 ticks = 2;
1073 else if (ticks > maxt)
1074 ticks = maxt;
1075
ce0f1b8c 1076 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, pmuwatchdog),
a9533e7e
HP
1077 ~0, ticks);
1078 } else {
1079 /* make sure we come up in fast clock mode; or if clearing, clear clock */
1080 si_clkctl_cc(sih, ticks ? CLK_FAST : CLK_DYNAMIC);
1081 maxt = (1 << 28) - 1;
1082 if (ticks > maxt)
1083 ticks = maxt;
1084
ce0f1b8c 1085 si_corereg(sih, SI_CC_IDX, offsetof(chipcregs_t, watchdog), ~0,
a9533e7e
HP
1086 ticks);
1087 }
1088}
cf2b4488 1089#endif
a9533e7e 1090
a9533e7e 1091/* return the slow clock source - LPO, XTAL, or PCI */
7cc4a4c0 1092static uint si_slowclk_src(si_info_t *sii)
a9533e7e
HP
1093{
1094 chipcregs_t *cc;
57d8cd23 1095 u32 val;
a9533e7e
HP
1096
1097 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1098
1099 if (sii->pub.ccrev < 6) {
57d8cd23
BR
1100 if (BUSTYPE(sii->pub.bustype) == PCI_BUS) {
1101 pci_read_config_dword(sii->osh->pdev, PCI_GPIO_OUT,
1102 &val);
1103 if (val & PCI_CFG_GPIO_SCS)
1104 return SCC_SS_PCI;
1105 }
1106 return SCC_SS_XTAL;
a9533e7e
HP
1107 } else if (sii->pub.ccrev < 10) {
1108 cc = (chipcregs_t *) si_setcoreidx(&sii->pub, sii->curidx);
90ea2296 1109 return R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK;
a9533e7e 1110 } else /* Insta-clock */
90ea2296 1111 return SCC_SS_XTAL;
a9533e7e
HP
1112}
1113
1114/* return the ILP (slowclock) min or max frequency */
7cc4a4c0 1115static uint si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
a9533e7e 1116{
66cbd3ab 1117 u32 slowclk;
a9533e7e
HP
1118 uint div;
1119
1120 ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
1121
1122 /* shouldn't be here unless we've established the chip has dynamic clk control */
1123 ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
1124
1125 slowclk = si_slowclk_src(sii);
1126 if (sii->pub.ccrev < 6) {
1127 if (slowclk == SCC_SS_PCI)
90ea2296
JC
1128 return max_freq ? (PCIMAXFREQ / 64)
1129 : (PCIMINFREQ / 64);
a9533e7e 1130 else
90ea2296
JC
1131 return max_freq ? (XTALMAXFREQ / 32)
1132 : (XTALMINFREQ / 32);
a9533e7e
HP
1133 } else if (sii->pub.ccrev < 10) {
1134 div = 4 *
1135 (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >>
1136 SCC_CD_SHIFT) + 1);
1137 if (slowclk == SCC_SS_LPO)
90ea2296 1138 return max_freq ? LPOMAXFREQ : LPOMINFREQ;
a9533e7e 1139 else if (slowclk == SCC_SS_XTAL)
90ea2296
JC
1140 return max_freq ? (XTALMAXFREQ / div)
1141 : (XTALMINFREQ / div);
a9533e7e 1142 else if (slowclk == SCC_SS_PCI)
90ea2296
JC
1143 return max_freq ? (PCIMAXFREQ / div)
1144 : (PCIMINFREQ / div);
a9533e7e
HP
1145 else
1146 ASSERT(0);
1147 } else {
1148 /* Chipc rev 10 is InstaClock */
1149 div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
1150 div = 4 * (div + 1);
90ea2296 1151 return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
a9533e7e 1152 }
90ea2296 1153 return 0;
a9533e7e
HP
1154}
1155
b4f790ee 1156static void si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
a2627bc0 1157{
a9533e7e
HP
1158 chipcregs_t *cc = (chipcregs_t *) chipcregs;
1159 uint slowmaxfreq, pll_delay, slowclk;
1160 uint pll_on_delay, fref_sel_delay;
1161
1162 pll_delay = PLL_DELAY;
1163
1164 /* If the slow clock is not sourced by the xtal then add the xtal_on_delay
1165 * since the xtal will also be powered down by dynamic clk control logic.
1166 */
1167
1168 slowclk = si_slowclk_src(sii);
1169 if (slowclk != SCC_SS_XTAL)
1170 pll_delay += XTAL_ON_DELAY;
1171
1172 /* Starting with 4318 it is ILP that is used for the delays */
1173 slowmaxfreq =
0965ae88 1174 si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? false : true, cc);
a9533e7e
HP
1175
1176 pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
1177 fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
1178
1179 W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
1180 W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
1181}
1182
1183/* initialize power control delay registers */
b4f790ee 1184void si_clkctl_init(si_t *sih)
a2627bc0 1185{
a9533e7e
HP
1186 si_info_t *sii;
1187 uint origidx = 0;
1188 chipcregs_t *cc;
1189 bool fast;
1190
1191 if (!CCCTL_ENAB(sih))
1192 return;
1193
1194 sii = SI_INFO(sih);
1195 fast = SI_FAST(sii);
1196 if (!fast) {
1197 origidx = sii->curidx;
ca8c1e59
JC
1198 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1199 if (cc == NULL)
a9533e7e 1200 return;
ca8c1e59
JC
1201 } else {
1202 cc = (chipcregs_t *) CCREGS_FAST(sii);
1203 if (cc == NULL)
1204 return;
1205 }
a9533e7e
HP
1206 ASSERT(cc != NULL);
1207
1208 /* set all Instaclk chip ILP to 1 MHz */
1209 if (sih->ccrev >= 10)
1210 SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
1211 (ILP_DIV_1MHZ << SYCC_CD_SHIFT));
1212
c03b63c1 1213 si_clkctl_setdelay(sii, (void *)cc);
a9533e7e
HP
1214
1215 if (!fast)
1216 si_setcoreidx(sih, origidx);
1217}
1218
1219/* return the value suitable for writing to the dot11 core FAST_PWRUP_DELAY register */
b4f790ee 1220u16 si_clkctl_fast_pwrup_delay(si_t *sih)
a2627bc0 1221{
a9533e7e
HP
1222 si_info_t *sii;
1223 uint origidx = 0;
1224 chipcregs_t *cc;
1225 uint slowminfreq;
7d4df48e 1226 u16 fpdelay;
a9533e7e
HP
1227 uint intr_val = 0;
1228 bool fast;
1229
1230 sii = SI_INFO(sih);
1231 if (PMUCTL_ENAB(sih)) {
1232 INTR_OFF(sii, intr_val);
1233 fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
1234 INTR_RESTORE(sii, intr_val);
1235 return fpdelay;
1236 }
1237
1238 if (!CCCTL_ENAB(sih))
1239 return 0;
1240
1241 fast = SI_FAST(sii);
1242 fpdelay = 0;
1243 if (!fast) {
1244 origidx = sii->curidx;
1245 INTR_OFF(sii, intr_val);
ca8c1e59
JC
1246 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1247 if (cc == NULL)
a9533e7e 1248 goto done;
ca8c1e59
JC
1249 } else {
1250 cc = (chipcregs_t *) CCREGS_FAST(sii);
1251 if (cc == NULL)
1252 goto done;
1253 }
a9533e7e
HP
1254 ASSERT(cc != NULL);
1255
0965ae88 1256 slowminfreq = si_slowclk_freq(sii, false, cc);
a9533e7e
HP
1257 fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
1258 (slowminfreq - 1)) / slowminfreq;
1259
1260 done:
1261 if (!fast) {
1262 si_setcoreidx(sih, origidx);
1263 INTR_RESTORE(sii, intr_val);
1264 }
1265 return fpdelay;
1266}
1267
1268/* turn primary xtal and/or pll off/on */
7cc4a4c0 1269int si_clkctl_xtal(si_t *sih, uint what, bool on)
a9533e7e
HP
1270{
1271 si_info_t *sii;
66cbd3ab 1272 u32 in, out, outen;
a9533e7e
HP
1273
1274 sii = SI_INFO(sih);
1275
1276 switch (BUSTYPE(sih->bustype)) {
1277
1278#ifdef BCMSDIO
1279 case SDIO_BUS:
90ea2296 1280 return -1;
a9533e7e
HP
1281#endif /* BCMSDIO */
1282
1283 case PCI_BUS:
1284 /* pcie core doesn't have any mapping to control the xtal pu */
1285 if (PCIE(sii))
1286 return -1;
1287
57d8cd23
BR
1288 pci_read_config_dword(sii->osh->pdev, PCI_GPIO_IN, &in);
1289 pci_read_config_dword(sii->osh->pdev, PCI_GPIO_OUT, &out);
1290 pci_read_config_dword(sii->osh->pdev, PCI_GPIO_OUTEN, &outen);
a9533e7e
HP
1291
1292 /*
1293 * Avoid glitching the clock if GPRS is already using it.
1294 * We can't actually read the state of the PLLPD so we infer it
1295 * by the value of XTAL_PU which *is* readable via gpioin.
1296 */
1297 if (on && (in & PCI_CFG_GPIO_XTAL))
90ea2296 1298 return 0;
a9533e7e
HP
1299
1300 if (what & XTAL)
1301 outen |= PCI_CFG_GPIO_XTAL;
1302 if (what & PLL)
1303 outen |= PCI_CFG_GPIO_PLL;
1304
1305 if (on) {
1306 /* turn primary xtal on */
1307 if (what & XTAL) {
1308 out |= PCI_CFG_GPIO_XTAL;
1309 if (what & PLL)
1310 out |= PCI_CFG_GPIO_PLL;
57d8cd23
BR
1311 pci_write_config_dword(sii->osh->pdev,
1312 PCI_GPIO_OUT, out);
1313 pci_write_config_dword(sii->osh->pdev,
1314 PCI_GPIO_OUTEN, outen);
7383141b 1315 udelay(XTAL_ON_DELAY);
a9533e7e
HP
1316 }
1317
1318 /* turn pll on */
1319 if (what & PLL) {
1320 out &= ~PCI_CFG_GPIO_PLL;
57d8cd23
BR
1321 pci_write_config_dword(sii->osh->pdev,
1322 PCI_GPIO_OUT, out);
7383141b 1323 mdelay(2);
a9533e7e
HP
1324 }
1325 } else {
1326 if (what & XTAL)
1327 out &= ~PCI_CFG_GPIO_XTAL;
1328 if (what & PLL)
1329 out |= PCI_CFG_GPIO_PLL;
57d8cd23
BR
1330 pci_write_config_dword(sii->osh->pdev,
1331 PCI_GPIO_OUT, out);
1332 pci_write_config_dword(sii->osh->pdev,
1333 PCI_GPIO_OUTEN, outen);
a9533e7e
HP
1334 }
1335
1336 default:
90ea2296 1337 return -1;
a9533e7e
HP
1338 }
1339
90ea2296 1340 return 0;
a9533e7e
HP
1341}
1342
1343/*
1344 * clock control policy function throught chipcommon
1345 *
1346 * set dynamic clk control mode (forceslow, forcefast, dynamic)
1347 * returns true if we are forcing fast clock
1348 * this is a wrapper over the next internal function
1349 * to allow flexible policy settings for outside caller
1350 */
7cc4a4c0 1351bool si_clkctl_cc(si_t *sih, uint mode)
a9533e7e
HP
1352{
1353 si_info_t *sii;
1354
1355 sii = SI_INFO(sih);
1356
1357 /* chipcommon cores prior to rev6 don't support dynamic clock control */
1358 if (sih->ccrev < 6)
0965ae88 1359 return false;
a9533e7e
HP
1360
1361 if (PCI_FORCEHT(sii))
90ea2296 1362 return mode == CLK_FAST;
a9533e7e
HP
1363
1364 return _si_clkctl_cc(sii, mode);
1365}
1366
1367/* clk control mechanism through chipcommon, no policy checking */
7cc4a4c0 1368static bool _si_clkctl_cc(si_info_t *sii, uint mode)
a9533e7e
HP
1369{
1370 uint origidx = 0;
1371 chipcregs_t *cc;
66cbd3ab 1372 u32 scc;
a9533e7e
HP
1373 uint intr_val = 0;
1374 bool fast = SI_FAST(sii);
1375
1376 /* chipcommon cores prior to rev6 don't support dynamic clock control */
1377 if (sii->pub.ccrev < 6)
0965ae88 1378 return false;
a9533e7e
HP
1379
1380 /* Chips with ccrev 10 are EOL and they don't have SYCC_HR which we use below */
1381 ASSERT(sii->pub.ccrev != 10);
1382
1383 if (!fast) {
1384 INTR_OFF(sii, intr_val);
1385 origidx = sii->curidx;
1386
1387 if ((BUSTYPE(sii->pub.bustype) == SI_BUS) &&
1388 si_setcore(&sii->pub, MIPS33_CORE_ID, 0) &&
1389 (si_corerev(&sii->pub) <= 7) && (sii->pub.ccrev >= 10))
1390 goto done;
1391
1392 cc = (chipcregs_t *) si_setcore(&sii->pub, CC_CORE_ID, 0);
ca8c1e59
JC
1393 } else {
1394 cc = (chipcregs_t *) CCREGS_FAST(sii);
1395 if (cc == NULL)
1396 goto done;
1397 }
a9533e7e
HP
1398 ASSERT(cc != NULL);
1399
1400 if (!CCCTL_ENAB(&sii->pub) && (sii->pub.ccrev < 20))
1401 goto done;
1402
1403 switch (mode) {
1404 case CLK_FAST: /* FORCEHT, fast (pll) clock */
1405 if (sii->pub.ccrev < 10) {
1406 /* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
1407 si_clkctl_xtal(&sii->pub, XTAL, ON);
1408 SET_REG(sii->osh, &cc->slow_clk_ctl,
1409 (SCC_XC | SCC_FS | SCC_IP), SCC_IP);
1410 } else if (sii->pub.ccrev < 20) {
1411 OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
1412 } else {
1413 OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
1414 }
1415
1416 /* wait for the PLL */
1417 if (PMUCTL_ENAB(&sii->pub)) {
66cbd3ab 1418 u32 htavail = CCS_HTAVAIL;
a9533e7e
HP
1419 SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail)
1420 == 0), PMU_MAX_TRANSITION_DLY);
1421 ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
1422 } else {
7383141b 1423 udelay(PLL_DELAY);
a9533e7e
HP
1424 }
1425 break;
1426
1427 case CLK_DYNAMIC: /* enable dynamic clock control */
1428 if (sii->pub.ccrev < 10) {
1429 scc = R_REG(sii->osh, &cc->slow_clk_ctl);
1430 scc &= ~(SCC_FS | SCC_IP | SCC_XC);
1431 if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
1432 scc |= SCC_XC;
1433 W_REG(sii->osh, &cc->slow_clk_ctl, scc);
1434
1435 /* for dynamic control, we have to release our xtal_pu "force on" */
1436 if (scc & SCC_XC)
1437 si_clkctl_xtal(&sii->pub, XTAL, OFF);
1438 } else if (sii->pub.ccrev < 20) {
1439 /* Instaclock */
1440 AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
1441 } else {
1442 AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
1443 }
1444 break;
1445
1446 default:
1447 ASSERT(0);
1448 }
1449
1450 done:
1451 if (!fast) {
1452 si_setcoreidx(&sii->pub, origidx);
1453 INTR_RESTORE(sii, intr_val);
1454 }
90ea2296 1455 return mode == CLK_FAST;
a9533e7e
HP
1456}
1457
1458/* Build device path. Support SI, PCI, and JTAG for now. */
0d2f0724 1459int si_devpath(si_t *sih, char *path, int size)
a2627bc0 1460{
a9533e7e
HP
1461 int slen;
1462
1463 ASSERT(path != NULL);
1464 ASSERT(size >= SI_DEVPATH_BUFSZ);
1465
1466 if (!path || size <= 0)
1467 return -1;
1468
1469 switch (BUSTYPE(sih->bustype)) {
1470 case SI_BUS:
1471 case JTAG_BUS:
1472 slen = snprintf(path, (size_t) size, "sb/%u/", si_coreidx(sih));
1473 break;
1474 case PCI_BUS:
1475 ASSERT((SI_INFO(sih))->osh != NULL);
1476 slen = snprintf(path, (size_t) size, "pci/%u/%u/",
1477 OSL_PCI_BUS((SI_INFO(sih))->osh),
1478 OSL_PCI_SLOT((SI_INFO(sih))->osh));
1479 break;
1480
1481#ifdef BCMSDIO
1482 case SDIO_BUS:
1483 SI_ERROR(("si_devpath: device 0 assumed\n"));
1484 slen = snprintf(path, (size_t) size, "sd/%u/", si_coreidx(sih));
1485 break;
1486#endif
1487 default:
1488 slen = -1;
1489 ASSERT(0);
1490 break;
1491 }
1492
1493 if (slen < 0 || slen >= size) {
1494 path[0] = '\0';
1495 return -1;
1496 }
1497
1498 return 0;
1499}
1500
1501/* Get a variable, but only if it has a devpath prefix */
0d2f0724 1502char *si_getdevpathvar(si_t *sih, const char *name)
a2627bc0 1503{
a9533e7e
HP
1504 char varname[SI_DEVPATH_BUFSZ + 32];
1505
1506 si_devpathvar(sih, varname, sizeof(varname), name);
1507
90ea2296 1508 return getvar(NULL, varname);
a9533e7e
HP
1509}
1510
1511/* Get a variable, but only if it has a devpath prefix */
0d2f0724 1512int si_getdevpathintvar(si_t *sih, const char *name)
a2627bc0 1513{
a9533e7e 1514#if defined(BCMBUSTYPE) && (BCMBUSTYPE == SI_BUS)
90ea2296 1515 return getintvar(NULL, name);
a9533e7e
HP
1516#else
1517 char varname[SI_DEVPATH_BUFSZ + 32];
1518
1519 si_devpathvar(sih, varname, sizeof(varname), name);
1520
90ea2296 1521 return getintvar(NULL, varname);
a9533e7e
HP
1522#endif
1523}
1524
7cc4a4c0 1525char *si_getnvramflvar(si_t *sih, const char *name)
a9533e7e 1526{
90ea2296 1527 return getvar(NULL, name);
a9533e7e
HP
1528}
1529
1530/* Concatenate the dev path with a varname into the given 'var' buffer
1531 * and return the 'var' pointer.
1532 * Nothing is done to the arguments if len == 0 or var is NULL, var is still returned.
1533 * On overflow, the first char will be set to '\0'.
1534 */
0d2f0724
GKH
1535static char *si_devpathvar(si_t *sih, char *var, int len, const char *name)
1536{
a9533e7e
HP
1537 uint path_len;
1538
1539 if (!var || len <= 0)
1540 return var;
1541
1542 if (si_devpath(sih, var, len) == 0) {
1543 path_len = strlen(var);
1544
1545 if (strlen(name) + 1 > (uint) (len - path_len))
1546 var[0] = '\0';
1547 else
1548 strncpy(var + path_len, name, len - path_len - 1);
1549 }
1550
1551 return var;
1552}
1553
0f0881b0 1554/* return true if PCIE capability exists in the pci config space */
84b9fac2 1555static __used bool si_ispcie(si_info_t *sii)
a9533e7e 1556{
36ef9a1e 1557 u8 cap_ptr;
a9533e7e
HP
1558
1559 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
0965ae88 1560 return false;
a9533e7e
HP
1561
1562 cap_ptr =
1563 pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL,
1564 NULL);
1565 if (!cap_ptr)
0965ae88 1566 return false;
a9533e7e 1567
0f0881b0 1568 return true;
a9533e7e
HP
1569}
1570
a9533e7e
HP
1571#ifdef BCMSDIO
1572/* initialize the sdio core */
7cc4a4c0 1573void si_sdio_init(si_t *sih)
a9533e7e
HP
1574{
1575 si_info_t *sii = SI_INFO(sih);
1576
1577 if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) ||
1578 (sih->buscoretype == SDIOD_CORE_ID)) {
1579 uint idx;
1580 sdpcmd_regs_t *sdpregs;
1581
1582 /* get the current core index */
1583 idx = sii->curidx;
1584 ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0));
1585
1586 /* switch to sdio core */
ca8c1e59
JC
1587 sdpregs = (sdpcmd_regs_t *) si_setcore(sih, PCMCIA_CORE_ID, 0);
1588 if (!sdpregs)
a9533e7e
HP
1589 sdpregs =
1590 (sdpcmd_regs_t *) si_setcore(sih, SDIOD_CORE_ID, 0);
1591 ASSERT(sdpregs);
1592
1593 SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d " "through SD core %d (%p)\n", sih->buscorerev, idx, sii->curidx, sdpregs));
1594
1595 /* enable backplane error and core interrupts */
1596 W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT);
1597 W_REG(sii->osh, &sdpregs->sbintmask,
1598 (I_SB_SERR | I_SB_RESPERR | (1 << idx)));
1599
1600 /* switch back to previous core */
1601 si_setcoreidx(sih, idx);
1602 }
1603
1604 /* enable interrupts */
1605 bcmsdh_intr_enable(sii->sdh);
1606
1607}
1608#endif /* BCMSDIO */
1609
0d2f0724 1610bool si_pci_war16165(si_t *sih)
a2627bc0 1611{
a9533e7e
HP
1612 si_info_t *sii;
1613
1614 sii = SI_INFO(sih);
1615
90ea2296 1616 return PCI(sii) && (sih->buscorerev <= 10);
a9533e7e
HP
1617}
1618
b4f790ee 1619void si_pci_up(si_t *sih)
a2627bc0 1620{
a9533e7e
HP
1621 si_info_t *sii;
1622
1623 sii = SI_INFO(sih);
1624
1625 /* if not pci bus, we're done */
1626 if (BUSTYPE(sih->bustype) != PCI_BUS)
1627 return;
1628
1629 if (PCI_FORCEHT(sii))
1630 _si_clkctl_cc(sii, CLK_FAST);
1631
1632 if (PCIE(sii))
1633 pcicore_up(sii->pch, SI_PCIUP);
1634
1635}
1636
1637/* Unconfigure and/or apply various WARs when system is going to sleep mode */
9927fc2e 1638void si_pci_sleep(si_t *sih)
a2627bc0 1639{
a9533e7e
HP
1640 si_info_t *sii;
1641
1642 sii = SI_INFO(sih);
1643
1644 pcicore_sleep(sii->pch);
1645}
1646
1647/* Unconfigure and/or apply various WARs when going down */
b4f790ee 1648void si_pci_down(si_t *sih)
a2627bc0 1649{
a9533e7e
HP
1650 si_info_t *sii;
1651
1652 sii = SI_INFO(sih);
1653
1654 /* if not pci bus, we're done */
1655 if (BUSTYPE(sih->bustype) != PCI_BUS)
1656 return;
1657
1658 /* release FORCEHT since chip is going to "down" state */
1659 if (PCI_FORCEHT(sii))
1660 _si_clkctl_cc(sii, CLK_DYNAMIC);
1661
1662 pcicore_down(sii->pch, SI_PCIDOWN);
1663}
1664
1665/*
1666 * Configure the pci core for pci client (NIC) action
1667 * coremask is the bitvec of cores by index to be enabled.
1668 */
0d2f0724 1669void si_pci_setup(si_t *sih, uint coremask)
a2627bc0 1670{
a9533e7e 1671 si_info_t *sii;
c11b0ef8 1672 struct sbpciregs *pciregs = NULL;
66cbd3ab 1673 u32 siflag = 0, w;
a9533e7e
HP
1674 uint idx = 0;
1675
1676 sii = SI_INFO(sih);
1677
1678 if (BUSTYPE(sii->pub.bustype) != PCI_BUS)
1679 return;
1680
1681 ASSERT(PCI(sii) || PCIE(sii));
1682 ASSERT(sii->pub.buscoreidx != BADIDX);
1683
1684 if (PCI(sii)) {
1685 /* get current core index */
1686 idx = sii->curidx;
1687
1688 /* we interrupt on this backplane flag number */
1689 siflag = si_flag(sih);
1690
1691 /* switch over to pci core */
c11b0ef8 1692 pciregs = (struct sbpciregs *)si_setcoreidx(sih, sii->pub.buscoreidx);
a9533e7e
HP
1693 }
1694
1695 /*
1696 * Enable sb->pci interrupts. Assume
1697 * PCI rev 2.3 support was added in pci core rev 6 and things changed..
1698 */
1699 if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
1700 /* pci config write to set this core bit in PCIIntMask */
57d8cd23 1701 pci_read_config_dword(sii->osh->pdev, PCI_INT_MASK, &w);
a9533e7e 1702 w |= (coremask << PCI_SBIM_SHIFT);
57d8cd23 1703 pci_write_config_dword(sii->osh->pdev, PCI_INT_MASK, w);
a9533e7e
HP
1704 } else {
1705 /* set sbintvec bit for our flag number */
1706 si_setint(sih, siflag);
1707 }
1708
1709 if (PCI(sii)) {
1710 OR_REG(sii->osh, &pciregs->sbtopci2,
1711 (SBTOPCI_PREF | SBTOPCI_BURST));
1712 if (sii->pub.buscorerev >= 11) {
1713 OR_REG(sii->osh, &pciregs->sbtopci2,
1714 SBTOPCI_RC_READMULTI);
1715 w = R_REG(sii->osh, &pciregs->clkrun);
1716 W_REG(sii->osh, &pciregs->clkrun,
1717 (w | PCI_CLKRUN_DSBL));
1718 w = R_REG(sii->osh, &pciregs->clkrun);
1719 }
1720
1721 /* switch back to previous core */
1722 si_setcoreidx(sih, idx);
1723 }
1724}
1725
a9533e7e
HP
1726/*
1727 * Fixup SROMless PCI device's configuration.
1728 * The current core may be changed upon return.
1729 */
7cc4a4c0 1730int si_pci_fixcfg(si_t *sih)
a9533e7e
HP
1731{
1732 uint origidx, pciidx;
c11b0ef8 1733 struct sbpciregs *pciregs = NULL;
a9533e7e
HP
1734 sbpcieregs_t *pcieregs = NULL;
1735 void *regs = NULL;
7d4df48e 1736 u16 val16, *reg16 = NULL;
a9533e7e
HP
1737
1738 si_info_t *sii = SI_INFO(sih);
1739
1740 ASSERT(BUSTYPE(sii->pub.bustype) == PCI_BUS);
1741
1742 /* Fixup PI in SROM shadow area to enable the correct PCI core access */
1743 /* save the current index */
1744 origidx = si_coreidx(&sii->pub);
1745
1746 /* check 'pi' is correct and fix it if not */
1747 if (sii->pub.buscoretype == PCIE_CORE_ID) {
1748 pcieregs =
1749 (sbpcieregs_t *) si_setcore(&sii->pub, PCIE_CORE_ID, 0);
1750 regs = pcieregs;
1751 ASSERT(pcieregs != NULL);
1752 reg16 = &pcieregs->sprom[SRSH_PI_OFFSET];
1753 } else if (sii->pub.buscoretype == PCI_CORE_ID) {
c11b0ef8 1754 pciregs = (struct sbpciregs *)si_setcore(&sii->pub, PCI_CORE_ID, 0);
a9533e7e
HP
1755 regs = pciregs;
1756 ASSERT(pciregs != NULL);
1757 reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
1758 }
1759 pciidx = si_coreidx(&sii->pub);
1760 val16 = R_REG(sii->osh, reg16);
7d4df48e 1761 if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16) pciidx) {
a9533e7e 1762 val16 =
7d4df48e 1763 (u16) (pciidx << SRSH_PI_SHIFT) | (val16 &
a9533e7e
HP
1764 ~SRSH_PI_MASK);
1765 W_REG(sii->osh, reg16, val16);
1766 }
1767
1768 /* restore the original index */
1769 si_setcoreidx(&sii->pub, origidx);
1770
1771 pcicore_hwup(sii->pch);
1772 return 0;
1773}
1774
a9533e7e 1775/* mask&set gpiocontrol bits */
66cbd3ab 1776u32 si_gpiocontrol(si_t *sih, u32 mask, u32 val, u8 priority)
a9533e7e
HP
1777{
1778 uint regoff;
1779
1780 regoff = 0;
1781
1782 /* gpios could be shared on router platforms
1783 * ignore reservation if it's high priority (e.g., test apps)
1784 */
1785 if ((priority != GPIO_HI_PRIORITY) &&
1786 (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) {
1787 mask = priority ? (si_gpioreservation & mask) :
1788 ((si_gpioreservation | mask) & ~(si_gpioreservation));
1789 val &= mask;
1790 }
1791
ce0f1b8c 1792 regoff = offsetof(chipcregs_t, gpiocontrol);
90ea2296 1793 return si_corereg(sih, SI_CC_IDX, regoff, mask, val);
a9533e7e
HP
1794}
1795
1e3950b8
HP
1796/* Return the size of the specified SOCRAM bank */
1797static uint
1798socram_banksize(si_info_t *sii, sbsocramregs_t *regs, u8 index,
1799 u8 mem_type)
a9533e7e 1800{
1e3950b8
HP
1801 uint banksize, bankinfo;
1802 uint bankidx = index | (mem_type << SOCRAM_BANKIDX_MEMTYPE_SHIFT);
a9533e7e 1803
1e3950b8 1804 ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
a9533e7e
HP
1805
1806 W_REG(sii->osh, &regs->bankidx, bankidx);
1807 bankinfo = R_REG(sii->osh, &regs->bankinfo);
1808 banksize =
1809 SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
1810 return banksize;
1811}
1812
a9533e7e 1813/* Return the RAM size of the SOCRAM core */
66cbd3ab 1814u32 si_socram_size(si_t *sih)
a9533e7e
HP
1815{
1816 si_info_t *sii;
1817 uint origidx;
1818 uint intr_val = 0;
1819
1820 sbsocramregs_t *regs;
1821 bool wasup;
1822 uint corerev;
66cbd3ab 1823 u32 coreinfo;
a9533e7e
HP
1824 uint memsize = 0;
1825
1826 sii = SI_INFO(sih);
1827
1828 /* Block ints and save current core */
1829 INTR_OFF(sii, intr_val);
1830 origidx = si_coreidx(sih);
1831
1832 /* Switch to SOCRAM core */
ca8c1e59
JC
1833 regs = si_setcore(sih, SOCRAM_CORE_ID, 0);
1834 if (!regs)
a9533e7e
HP
1835 goto done;
1836
1837 /* Get info for determining size */
ca8c1e59
JC
1838 wasup = si_iscoreup(sih);
1839 if (!wasup)
a9533e7e
HP
1840 si_core_reset(sih, 0, 0);
1841 corerev = si_corerev(sih);
1842 coreinfo = R_REG(sii->osh, &regs->coreinfo);
1843
1844 /* Calculate size from coreinfo based on rev */
1845 if (corerev == 0)
1846 memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK));
1847 else if (corerev < 3) {
1848 memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK));
1849 memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1850 } else if ((corerev <= 7) || (corerev == 12)) {
1851 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1852 uint bsz = (coreinfo & SRCI_SRBSZ_MASK);
1853 uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT;
1854 if (lss != 0)
1855 nb--;
1856 memsize = nb * (1 << (bsz + SR_BSZ_BASE));
1857 if (lss != 0)
1858 memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
1859 } else {
36ef9a1e 1860 u8 i;
a9533e7e
HP
1861 uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
1862 for (i = 0; i < nb; i++)
1863 memsize +=
1864 socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
1865 }
1866
1867 /* Return to previous state and core */
1868 if (!wasup)
1869 si_core_disable(sih, 0);
1870 si_setcoreidx(sih, origidx);
1871
1872 done:
1873 INTR_RESTORE(sii, intr_val);
1874
1875 return memsize;
1876}
1877
7cc4a4c0 1878void si_chipcontrl_epa4331(si_t *sih, bool on)
a9533e7e
HP
1879{
1880 si_info_t *sii;
1881 chipcregs_t *cc;
1882 uint origidx;
66cbd3ab 1883 u32 val;
a9533e7e
HP
1884
1885 sii = SI_INFO(sih);
1886 origidx = si_coreidx(sih);
1887
1888 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1889
1890 val = R_REG(sii->osh, &cc->chipcontrol);
1891
1892 if (on) {
1893 if (sih->chippkg == 9 || sih->chippkg == 0xb) {
1894 /* Ext PA Controls for 4331 12x9 Package */
1895 W_REG(sii->osh, &cc->chipcontrol, val |
1896 (CCTRL4331_EXTPA_EN |
1897 CCTRL4331_EXTPA_ON_GPIO2_5));
1898 } else {
1899 /* Ext PA Controls for 4331 12x12 Package */
1900 W_REG(sii->osh, &cc->chipcontrol,
1901 val | (CCTRL4331_EXTPA_EN));
1902 }
1903 } else {
1904 val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
1905 W_REG(sii->osh, &cc->chipcontrol, val);
1906 }
1907
1908 si_setcoreidx(sih, origidx);
1909}
1910
1911/* Enable BT-COEX & Ex-PA for 4313 */
7cc4a4c0 1912void si_epa_4313war(si_t *sih)
a9533e7e
HP
1913{
1914 si_info_t *sii;
1915 chipcregs_t *cc;
1916 uint origidx;
1917
1918 sii = SI_INFO(sih);
1919 origidx = si_coreidx(sih);
1920
1921 cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
1922
1923 /* EPA Fix */
1924 W_REG(sii->osh, &cc->gpiocontrol,
1925 R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
1926
1927 si_setcoreidx(sih, origidx);
1928}
1929
1930/* check if the device is removed */
7cc4a4c0 1931bool si_deviceremoved(si_t *sih)
a9533e7e 1932{
66cbd3ab 1933 u32 w;
a9533e7e
HP
1934 si_info_t *sii;
1935
1936 sii = SI_INFO(sih);
1937
1938 switch (BUSTYPE(sih->bustype)) {
1939 case PCI_BUS:
1940 ASSERT(sii->osh != NULL);
57d8cd23 1941 pci_read_config_dword(sii->osh->pdev, PCI_CFG_VID, &w);
a9533e7e 1942 if ((w & 0xFFFF) != VENDOR_BROADCOM)
0f0881b0 1943 return true;
a9533e7e
HP
1944 break;
1945 }
0965ae88 1946 return false;
a9533e7e
HP
1947}
1948
7cc4a4c0 1949bool si_is_sprom_available(si_t *sih)
a9533e7e
HP
1950{
1951 if (sih->ccrev >= 31) {
1952 si_info_t *sii;
1953 uint origidx;
1954 chipcregs_t *cc;
66cbd3ab 1955 u32 sromctrl;
a9533e7e
HP
1956
1957 if ((sih->cccaps & CC_CAP_SROM) == 0)
0965ae88 1958 return false;
a9533e7e
HP
1959
1960 sii = SI_INFO(sih);
1961 origidx = sii->curidx;
1962 cc = si_setcoreidx(sih, SI_CC_IDX);
1963 sromctrl = R_REG(sii->osh, &cc->sromcontrol);
1964 si_setcoreidx(sih, origidx);
90ea2296 1965 return sromctrl & SRC_PRESENT;
a9533e7e
HP
1966 }
1967
1968 switch (CHIPID(sih->chip)) {
1969 case BCM4329_CHIP_ID:
1970 return (sih->chipst & CST4329_SPROM_SEL) != 0;
1971 case BCM4319_CHIP_ID:
1972 return (sih->chipst & CST4319_SPROM_SEL) != 0;
1973 case BCM4336_CHIP_ID:
1974 return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
1975 case BCM4330_CHIP_ID:
1976 return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
1977 case BCM4313_CHIP_ID:
1978 return (sih->chipst & CST4313_SPROM_PRESENT) != 0;
1979 case BCM4331_CHIP_ID:
1980 return (sih->chipst & CST4331_SPROM_PRESENT) != 0;
1981 default:
0f0881b0 1982 return true;
a9533e7e
HP
1983 }
1984}
1985
7cc4a4c0 1986bool si_is_otp_disabled(si_t *sih)
a9533e7e
HP
1987{
1988 switch (CHIPID(sih->chip)) {
1989 case BCM4329_CHIP_ID:
1990 return (sih->chipst & CST4329_SPROM_OTP_SEL_MASK) ==
1991 CST4329_OTP_PWRDN;
1992 case BCM4319_CHIP_ID:
1993 return (sih->chipst & CST4319_SPROM_OTP_SEL_MASK) ==
1994 CST4319_OTP_PWRDN;
1995 case BCM4336_CHIP_ID:
90ea2296 1996 return (sih->chipst & CST4336_OTP_PRESENT) == 0;
a9533e7e 1997 case BCM4330_CHIP_ID:
90ea2296 1998 return (sih->chipst & CST4330_OTP_PRESENT) == 0;
a9533e7e
HP
1999 case BCM4313_CHIP_ID:
2000 return (sih->chipst & CST4313_OTP_PRESENT) == 0;
2001 /* These chips always have their OTP on */
2002 case BCM43224_CHIP_ID:
2003 case BCM43225_CHIP_ID:
2004 case BCM43421_CHIP_ID:
2005 case BCM43235_CHIP_ID:
2006 case BCM43236_CHIP_ID:
2007 case BCM43238_CHIP_ID:
2008 case BCM4331_CHIP_ID:
2009 default:
0965ae88 2010 return false;
a9533e7e
HP
2011 }
2012}
2013
7cc4a4c0 2014bool si_is_otp_powered(si_t *sih)
a9533e7e
HP
2015{
2016 if (PMUCTL_ENAB(sih))
2017 return si_pmu_is_otp_powered(sih, si_osh(sih));
0f0881b0 2018 return true;
a9533e7e
HP
2019}
2020
7cc4a4c0 2021void si_otp_power(si_t *sih, bool on)
a9533e7e
HP
2022{
2023 if (PMUCTL_ENAB(sih))
2024 si_pmu_otp_power(sih, si_osh(sih), on);
7383141b 2025 udelay(1000);
a9533e7e
HP
2026}
2027