~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/staging/brcm80211/brcmsmac/aiutils.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

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