Root/target/linux/brcm-2.4/files/arch/mips/bcm947xx/sbpci.c

1/*
2 * Low-Level PCI and SB support for BCM47xx
3 *
4 * Copyright 2006, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 */
13
14#include <typedefs.h>
15#include <osl.h>
16#include <pcicfg.h>
17#include <bcmdevs.h>
18#include <sbconfig.h>
19#include <sbutils.h>
20#include <sbpci.h>
21#include <bcmendian.h>
22#include <bcmnvram.h>
23#include <hndcpu.h>
24#include <hndmips.h>
25#include <hndpci.h>
26
27/* debug/trace */
28#ifdef BCMDBG_PCI
29#define PCI_MSG(args) printf args
30#else
31#define PCI_MSG(args)
32#endif /* BCMDBG_PCI */
33
34/* Can free sbpci_init() memory after boot */
35#ifndef linux
36#define __init
37#endif /* linux */
38
39/* Emulated configuration space */
40typedef struct {
41    int n;
42    uint size0;
43    uint size1;
44    uint size2;
45    uint size3;
46} sb_bar_cfg_t;
47static pci_config_regs sb_config_regs[SB_MAXCORES];
48static sb_bar_cfg_t sb_bar_cfg[SB_MAXCORES];
49
50/* Links to emulated and real PCI configuration spaces */
51#define MAXFUNCS 2
52typedef struct {
53    pci_config_regs *emu; /* emulated PCI config */
54    pci_config_regs *pci; /* real PCI config */
55    sb_bar_cfg_t *bar; /* region sizes */
56} sb_pci_cfg_t;
57static sb_pci_cfg_t sb_pci_cfg[SB_MAXCORES][MAXFUNCS];
58
59/* Special emulated config space for non-existing device */
60static pci_config_regs sb_pci_null = { 0xffff, 0xffff };
61
62/* Banned cores */
63static uint16 pci_ban[SB_MAXCORES] = { 0 };
64static uint pci_banned = 0;
65
66/* CardBus mode */
67static bool cardbus = FALSE;
68
69/* Disable PCI host core */
70static bool pci_disabled = FALSE;
71
72/* Host bridge slot #, default to 0 */
73static uint8 pci_hbslot = 0;
74
75/* Internal macros */
76#define PCI_SLOTAD_MAP 16 /* SLOT<n> mapps to AD<n+16> */
77#define PCI_HBSBCFG_REV 8 /* MIN. core rev. required to
78                 * access host bridge PCI cfg space
79                 * from SB
80                 */
81
82/*
83 * Functions for accessing external PCI configuration space
84 */
85
86/* Assume one-hot slot wiring */
87#define PCI_SLOT_MAX 16 /* Max. PCI Slots */
88
89static uint32 config_cmd(sb_t * sbh, uint bus, uint dev, uint func, uint off)
90{
91    uint coreidx;
92    sbpciregs_t *regs;
93    uint32 addr = 0;
94    osl_t *osh;
95
96    /* CardBusMode supports only one device */
97    if (cardbus && dev > 1)
98        return 0;
99
100    osh = sb_osh(sbh);
101
102    coreidx = sb_coreidx(sbh);
103    regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
104
105    /* Type 0 transaction */
106    if (bus == 1) {
107        /* Skip unwired slots */
108        if (dev < PCI_SLOT_MAX) {
109            uint32 win;
110
111            /* Slide the PCI window to the appropriate slot */
112            win =
113                (SBTOPCI_CFG0 |
114                 ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK));
115            W_REG(osh, &regs->sbtopci1, win);
116            addr = SB_PCI_CFG |
117                ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) |
118                (func << PCICFG_FUN_SHIFT) | (off & ~3);
119        }
120    } else {
121        /* Type 1 transaction */
122        W_REG(osh, &regs->sbtopci1, SBTOPCI_CFG1);
123        addr = SB_PCI_CFG |
124            (bus << PCICFG_BUS_SHIFT) |
125            (dev << PCICFG_SLOT_SHIFT) |
126            (func << PCICFG_FUN_SHIFT) | (off & ~3);
127    }
128
129    sb_setcoreidx(sbh, coreidx);
130
131    return addr;
132}
133
134/*
135 * Read host bridge PCI config registers from Silicon Backplane (>=rev8).
136 *
137 * It returns TRUE to indicate that access to the host bridge's pci config
138 * from SB is ok, and values in 'addr' and 'val' are valid.
139 *
140 * It can only read registers at multiple of 4-bytes. Callers must pick up
141 * needed bytes from 'val' based on 'off' value. Value in 'addr' reflects
142 * the register address where value in 'val' is read.
143 */
144static bool
145sb_pcihb_read_config(sb_t * sbh, uint bus, uint dev, uint func, uint off,
146             uint32 ** addr, uint32 * val)
147{
148    sbpciregs_t *regs;
149    osl_t *osh;
150    uint coreidx;
151    bool ret = FALSE;
152
153    /* sanity check */
154    ASSERT(bus == 1);
155    ASSERT(dev == pci_hbslot);
156    ASSERT(func == 0);
157
158    osh = sb_osh(sbh);
159
160    /* read pci config when core rev >= 8 */
161    coreidx = sb_coreidx(sbh);
162    regs = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0);
163    if (regs && sb_corerev(sbh) >= PCI_HBSBCFG_REV) {
164        *addr = (uint32 *) & regs->pcicfg[func][off >> 2];
165        *val = R_REG(osh, *addr);
166        ret = TRUE;
167    }
168    sb_setcoreidx(sbh, coreidx);
169
170    return ret;
171}
172
173int
174extpci_read_config(sb_t * sbh, uint bus, uint dev, uint func, uint off,
175           void *buf, int len)
176{
177    uint32 addr = 0, *reg = NULL, val;
178    int ret = 0;
179
180    /*
181     * Set value to -1 when:
182     * flag 'pci_disabled' is true;
183     * value of 'addr' is zero;
184     * REG_MAP() fails;
185     * BUSPROBE() fails;
186     */
187    if (pci_disabled)
188        val = 0xffffffff;
189    else if (bus == 1 && dev == pci_hbslot && func == 0 &&
190         sb_pcihb_read_config(sbh, bus, dev, func, off, &reg, &val)) ;
191    else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) ||
192         ((reg = (uint32 *) REG_MAP(addr, len)) == 0) ||
193         (BUSPROBE(val, reg) != 0))
194        val = 0xffffffff;
195
196    PCI_MSG(("%s: 0x%x <= 0x%p(0x%x), len %d, off 0x%x, buf 0x%p\n",
197         __FUNCTION__, val, reg, addr, len, off, buf));
198
199    val >>= 8 * (off & 3);
200    if (len == 4)
201        *((uint32 *) buf) = val;
202    else if (len == 2)
203        *((uint16 *) buf) = (uint16) val;
204    else if (len == 1)
205        *((uint8 *) buf) = (uint8) val;
206    else
207        ret = -1;
208
209    if (reg && addr)
210        REG_UNMAP(reg);
211
212    return ret;
213}
214
215int
216extpci_write_config(sb_t * sbh, uint bus, uint dev, uint func, uint off,
217            void *buf, int len)
218{
219    osl_t *osh;
220    uint32 addr = 0, *reg = NULL, val;
221    int ret = 0;
222
223    osh = sb_osh(sbh);
224
225    /*
226     * Ignore write attempt when:
227     * flag 'pci_disabled' is true;
228     * value of 'addr' is zero;
229     * REG_MAP() fails;
230     * BUSPROBE() fails;
231     */
232    if (pci_disabled)
233        return 0;
234    else if (bus == 1 && dev == pci_hbslot && func == 0 &&
235         sb_pcihb_read_config(sbh, bus, dev, func, off, &reg, &val)) ;
236    else if (((addr = config_cmd(sbh, bus, dev, func, off)) == 0) ||
237         ((reg = (uint32 *) REG_MAP(addr, len)) == 0) ||
238         (BUSPROBE(val, reg) != 0))
239        goto done;
240
241    if (len == 4)
242        val = *((uint32 *) buf);
243    else if (len == 2) {
244        val &= ~(0xffff << (8 * (off & 3)));
245        val |= *((uint16 *) buf) << (8 * (off & 3));
246    } else if (len == 1) {
247        val &= ~(0xff << (8 * (off & 3)));
248        val |= *((uint8 *) buf) << (8 * (off & 3));
249    } else {
250        ret = -1;
251        goto done;
252    }
253
254    PCI_MSG(("%s: 0x%x => 0x%p\n", __FUNCTION__, val, reg));
255
256    W_REG(osh, reg, val);
257
258      done:
259    if (reg && addr)
260        REG_UNMAP(reg);
261
262    return ret;
263}
264
265/*
266 * Must access emulated PCI configuration at these locations even when
267 * the real PCI config space exists and is accessible.
268 *
269 * PCI_CFG_VID (0x00)
270 * PCI_CFG_DID (0x02)
271 * PCI_CFG_PROGIF (0x09)
272 * PCI_CFG_SUBCL (0x0a)
273 * PCI_CFG_BASECL (0x0b)
274 * PCI_CFG_HDR (0x0e)
275 * PCI_CFG_INT (0x3c)
276 * PCI_CFG_PIN (0x3d)
277 */
278#define FORCE_EMUCFG(off, len) \
279    ((off == PCI_CFG_VID) || (off == PCI_CFG_DID) || \
280     (off == PCI_CFG_PROGIF) || \
281     (off == PCI_CFG_SUBCL) || (off == PCI_CFG_BASECL) || \
282     (off == PCI_CFG_HDR) || \
283     (off == PCI_CFG_INT) || (off == PCI_CFG_PIN))
284
285/* Sync the emulation registers and the real PCI config registers. */
286static void
287sb_pcid_read_config(sb_t * sbh, uint coreidx, sb_pci_cfg_t * cfg,
288            uint off, uint len)
289{
290    osl_t *osh;
291    uint oldidx;
292
293    ASSERT(cfg);
294    ASSERT(cfg->emu);
295    ASSERT(cfg->pci);
296
297    /* decide if real PCI config register access is necessary */
298    if (FORCE_EMUCFG(off, len))
299        return;
300
301    osh = sb_osh(sbh);
302
303    /* access to the real pci config space only when the core is up */
304    oldidx = sb_coreidx(sbh);
305    sb_setcoreidx(sbh, coreidx);
306    if (sb_iscoreup(sbh)) {
307        if (len == 4)
308            *(uint32 *) ((ulong) cfg->emu + off) =
309                htol32(R_REG
310                   (osh, (uint32 *) ((ulong) cfg->pci + off)));
311        else if (len == 2)
312            *(uint16 *) ((ulong) cfg->emu + off) =
313                htol16(R_REG
314                   (osh, (uint16 *) ((ulong) cfg->pci + off)));
315        else if (len == 1)
316            *(uint8 *) ((ulong) cfg->emu + off) =
317                R_REG(osh, (uint8 *) ((ulong) cfg->pci + off));
318    }
319    sb_setcoreidx(sbh, oldidx);
320}
321
322static void
323sb_pcid_write_config(sb_t * sbh, uint coreidx, sb_pci_cfg_t * cfg,
324             uint off, uint len)
325{
326    osl_t *osh;
327    uint oldidx;
328
329    ASSERT(cfg);
330    ASSERT(cfg->emu);
331    ASSERT(cfg->pci);
332
333    osh = sb_osh(sbh);
334
335    /* decide if real PCI config register access is necessary */
336    if (FORCE_EMUCFG(off, len))
337        return;
338
339    /* access to the real pci config space only when the core is up */
340    oldidx = sb_coreidx(sbh);
341    sb_setcoreidx(sbh, coreidx);
342    if (sb_iscoreup(sbh)) {
343        if (len == 4)
344            W_REG(osh, (uint32 *) ((ulong) cfg->pci + off),
345                  ltoh32(*(uint32 *) ((ulong) cfg->emu + off)));
346        else if (len == 2)
347            W_REG(osh, (uint16 *) ((ulong) cfg->pci + off),
348                  ltoh16(*(uint16 *) ((ulong) cfg->emu + off)));
349        else if (len == 1)
350            W_REG(osh, (uint8 *) ((ulong) cfg->pci + off),
351                  *(uint8 *) ((ulong) cfg->emu + off));
352    }
353    sb_setcoreidx(sbh, oldidx);
354}
355
356/*
357 * Functions for accessing translated SB configuration space
358 */
359static int
360sb_read_config(sb_t * sbh, uint bus, uint dev, uint func, uint off, void *buf,
361           int len)
362{
363    pci_config_regs *cfg;
364
365    if (dev >= SB_MAXCORES || func >= MAXFUNCS
366        || (off + len) > sizeof(pci_config_regs))
367        return -1;
368    cfg = sb_pci_cfg[dev][func].emu;
369
370    ASSERT(ISALIGNED(off, len));
371    ASSERT(ISALIGNED((uintptr) buf, len));
372
373    /* use special config space if the device does not exist */
374    if (!cfg)
375        cfg = &sb_pci_null;
376    /* sync emulation with real PCI config if necessary */
377    else if (sb_pci_cfg[dev][func].pci)
378        sb_pcid_read_config(sbh, dev, &sb_pci_cfg[dev][func], off, len);
379
380    if (len == 4)
381        *((uint32 *) buf) = ltoh32(*((uint32 *) ((ulong) cfg + off)));
382    else if (len == 2)
383        *((uint16 *) buf) = ltoh16(*((uint16 *) ((ulong) cfg + off)));
384    else if (len == 1)
385        *((uint8 *) buf) = *((uint8 *) ((ulong) cfg + off));
386    else
387        return -1;
388
389    return 0;
390}
391
392static int
393sb_write_config(sb_t * sbh, uint bus, uint dev, uint func, uint off, void *buf,
394        int len)
395{
396    uint coreidx;
397    void *regs;
398    pci_config_regs *cfg;
399    osl_t *osh;
400    sb_bar_cfg_t *bar;
401
402    if (dev >= SB_MAXCORES || func >= MAXFUNCS
403        || (off + len) > sizeof(pci_config_regs))
404        return -1;
405    cfg = sb_pci_cfg[dev][func].emu;
406    if (!cfg)
407        return -1;
408
409    ASSERT(ISALIGNED(off, len));
410    ASSERT(ISALIGNED((uintptr) buf, len));
411
412    osh = sb_osh(sbh);
413
414    /* Emulate BAR sizing */
415    if (off >= OFFSETOF(pci_config_regs, base[0]) &&
416        off <= OFFSETOF(pci_config_regs, base[3]) &&
417        len == 4 && *((uint32 *) buf) == ~0) {
418        coreidx = sb_coreidx(sbh);
419        if ((regs = sb_setcoreidx(sbh, dev))) {
420            bar = sb_pci_cfg[dev][func].bar;
421            /* Highest numbered address match register */
422            if (off == OFFSETOF(pci_config_regs, base[0]))
423                cfg->base[0] = ~(bar->size0 - 1);
424            else if (off == OFFSETOF(pci_config_regs, base[1])
425                 && bar->n >= 1)
426                cfg->base[1] = ~(bar->size1 - 1);
427            else if (off == OFFSETOF(pci_config_regs, base[2])
428                 && bar->n >= 2)
429                cfg->base[2] = ~(bar->size2 - 1);
430            else if (off == OFFSETOF(pci_config_regs, base[3])
431                 && bar->n >= 3)
432                cfg->base[3] = ~(bar->size3 - 1);
433        }
434        sb_setcoreidx(sbh, coreidx);
435    } else if (len == 4)
436        *((uint32 *) ((ulong) cfg + off)) = htol32(*((uint32 *) buf));
437    else if (len == 2)
438        *((uint16 *) ((ulong) cfg + off)) = htol16(*((uint16 *) buf));
439    else if (len == 1)
440        *((uint8 *) ((ulong) cfg + off)) = *((uint8 *) buf);
441    else
442        return -1;
443
444    /* sync emulation with real PCI config if necessary */
445    if (sb_pci_cfg[dev][func].pci)
446        sb_pcid_write_config(sbh, dev, &sb_pci_cfg[dev][func], off,
447                     len);
448
449    return 0;
450}
451
452int
453sbpci_read_config(sb_t * sbh, uint bus, uint dev, uint func, uint off,
454          void *buf, int len)
455{
456    if (bus == 0)
457        return sb_read_config(sbh, bus, dev, func, off, buf, len);
458    else
459        return extpci_read_config(sbh, bus, dev, func, off, buf, len);
460}
461
462int
463sbpci_write_config(sb_t * sbh, uint bus, uint dev, uint func, uint off,
464           void *buf, int len)
465{
466    if (bus == 0)
467        return sb_write_config(sbh, bus, dev, func, off, buf, len);
468    else
469        return extpci_write_config(sbh, bus, dev, func, off, buf, len);
470}
471
472void sbpci_ban(uint16 core)
473{
474    if (pci_banned < ARRAYSIZE(pci_ban))
475        pci_ban[pci_banned++] = core;
476}
477
478/*
479 * Initiliaze PCI core. Return 0 after a successful initialization.
480 * Otherwise return -1 to indicate there is no PCI core and return 1
481 * to indicate PCI core is disabled.
482 */
483int __init sbpci_init_pci(sb_t * sbh)
484{
485    uint chip, chiprev, chippkg, host;
486    uint32 boardflags;
487    sbpciregs_t *pci;
488    sbconfig_t *sb;
489    uint32 val;
490    int ret = 0;
491    char *hbslot;
492    osl_t *osh;
493
494    chip = sb_chip(sbh);
495    chiprev = sb_chiprev(sbh);
496    chippkg = sb_chippkg(sbh);
497
498    osh = sb_osh(sbh);
499
500    if (!(pci = (sbpciregs_t *) sb_setcore(sbh, SB_PCI, 0))) {
501        printk("PCI: no core\n");
502        pci_disabled = TRUE;
503        return -1;
504    }
505
506    if ((chip == 0x4310) && (chiprev == 0))
507        pci_disabled = TRUE;
508
509    sb = (sbconfig_t *) ((ulong) pci + SBCONFIGOFF);
510
511    boardflags = (uint32) getintvar(NULL, "boardflags");
512
513    /*
514     * The 200-pin BCM4712 package does not bond out PCI. Even when
515     * PCI is bonded out, some boards may leave the pins
516     * floating.
517     */
518    if (((chip == BCM4712_CHIP_ID) &&
519         ((chippkg == BCM4712SMALL_PKG_ID) ||
520          (chippkg == BCM4712MID_PKG_ID))) || (boardflags & BFL_NOPCI))
521        pci_disabled = TRUE;
522
523    /* Enable the core */
524    sb_core_reset(sbh, 0, 0);
525
526    /*
527     * If the PCI core should not be touched (disabled, not bonded
528     * out, or pins floating), do not even attempt to access core
529     * registers. Otherwise, try to determine if it is in host
530     * mode.
531     */
532    if (pci_disabled)
533        host = 0;
534    else
535        host = !BUSPROBE(val, &pci->control);
536
537    if (!host) {
538        ret = 1;
539
540        /* Disable PCI interrupts in client mode */
541        W_REG(osh, &sb->sbintvec, 0);
542
543        /* Disable the PCI bridge in client mode */
544        sbpci_ban(SB_PCI);
545        sb_core_disable(sbh, 0);
546
547        printk("PCI: Disabled\n");
548    } else {
549        printk("PCI: Initializing host\n");
550
551        /* Disable PCI SBReqeustTimeout for BCM4785 */
552        if (chip == BCM4785_CHIP_ID) {
553            AND_REG(osh, &sb->sbimconfiglow, ~0x00000070);
554            sb_commit(sbh);
555        }
556
557        /* Reset the external PCI bus and enable the clock */
558        W_REG(osh, &pci->control, 0x5); /* enable the tristate drivers */
559        W_REG(osh, &pci->control, 0xd); /* enable the PCI clock */
560        OSL_DELAY(150); /* delay > 100 us */
561        W_REG(osh, &pci->control, 0xf); /* deassert PCI reset */
562        /* Use internal arbiter and park REQ/GRNT at external master 0 */
563        W_REG(osh, &pci->arbcontrol, PCI_INT_ARB);
564        OSL_DELAY(1); /* delay 1 us */
565        if (sb_corerev(sbh) >= 8) {
566            val = getintvar(NULL, "parkid");
567            ASSERT(val <= PCI_PARKID_LAST);
568            OR_REG(osh, &pci->arbcontrol, val << PCI_PARKID_SHIFT);
569            OSL_DELAY(1);
570        }
571
572        /* Enable CardBusMode */
573        cardbus = getintvar(NULL, "cardbus") == 1;
574        if (cardbus) {
575            printk("PCI: Enabling CardBus\n");
576            /* GPIO 1 resets the CardBus device on bcm94710ap */
577            sb_gpioout(sbh, 1, 1, GPIO_DRV_PRIORITY);
578            sb_gpioouten(sbh, 1, 1, GPIO_DRV_PRIORITY);
579            W_REG(osh, &pci->sprom[0],
580                  R_REG(osh, &pci->sprom[0]) | 0x400);
581        }
582
583        /* 64 MB I/O access window */
584        W_REG(osh, &pci->sbtopci0, SBTOPCI_IO);
585        /* 64 MB configuration access window */
586        W_REG(osh, &pci->sbtopci1, SBTOPCI_CFG0);
587        /* 1 GB memory access window */
588        W_REG(osh, &pci->sbtopci2, SBTOPCI_MEM | SB_PCI_DMA);
589
590        /* Host bridge slot # nvram overwrite */
591        if ((hbslot = nvram_get("pcihbslot"))) {
592            pci_hbslot = simple_strtoul(hbslot, NULL, 0);
593            ASSERT(pci_hbslot < PCI_MAX_DEVICES);
594        }
595
596        /* Enable PCI bridge BAR0 prefetch and burst */
597        val = 6;
598        sbpci_write_config(sbh, 1, pci_hbslot, 0, PCI_CFG_CMD, &val,
599                   sizeof(val));
600
601        /* Enable PCI interrupts */
602        W_REG(osh, &pci->intmask, PCI_INTA);
603    }
604
605    return ret;
606}
607
608/*
609 * Get the PCI region address and size information.
610 */
611static void __init
612sbpci_init_regions(sb_t * sbh, uint func, pci_config_regs * cfg,
613           sb_bar_cfg_t * bar)
614{
615    osl_t *osh;
616    uint16 coreid;
617    void *regs;
618    sbconfig_t *sb;
619    uint32 base;
620
621    osh = sb_osh(sbh);
622    coreid = sb_coreid(sbh);
623    regs = sb_coreregs(sbh);
624    sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF);
625
626    switch (coreid) {
627    case SB_USB20H:
628        base = htol32(sb_base(R_REG(osh, &sb->sbadmatch0)));
629
630        cfg->base[0] = func == 0 ? base : base + 0x800; /* OHCI/EHCI */
631        cfg->base[1] = 0;
632        cfg->base[2] = 0;
633        cfg->base[3] = 0;
634        cfg->base[4] = 0;
635        cfg->base[5] = 0;
636        bar->n = 1;
637        bar->size0 = func == 0 ? 0x200 : 0x100; /* OHCI/EHCI */
638        bar->size1 = 0;
639        bar->size2 = 0;
640        bar->size3 = 0;
641        break;
642    default:
643        cfg->base[0] = htol32(sb_base(R_REG(osh, &sb->sbadmatch0)));
644        cfg->base[1] = htol32(sb_base(R_REG(osh, &sb->sbadmatch1)));
645        cfg->base[2] = htol32(sb_base(R_REG(osh, &sb->sbadmatch2)));
646        cfg->base[3] = htol32(sb_base(R_REG(osh, &sb->sbadmatch3)));
647        cfg->base[4] = 0;
648        cfg->base[5] = 0;
649        bar->n =
650            (R_REG(osh, &sb->sbidlow) & SBIDL_AR_MASK) >>
651            SBIDL_AR_SHIFT;
652        bar->size0 = sb_size(R_REG(osh, &sb->sbadmatch0));
653        bar->size1 = sb_size(R_REG(osh, &sb->sbadmatch1));
654        bar->size2 = sb_size(R_REG(osh, &sb->sbadmatch2));
655        bar->size3 = sb_size(R_REG(osh, &sb->sbadmatch3));
656        break;
657    }
658}
659
660/*
661 * Construct PCI config spaces for SB cores so that they
662 * can be accessed as if they were PCI devices.
663 */
664static void __init sbpci_init_cores(sb_t * sbh)
665{
666    uint chiprev, coreidx, i;
667    sbconfig_t *sb;
668    pci_config_regs *cfg, *pci;
669    sb_bar_cfg_t *bar;
670    void *regs;
671    osl_t *osh;
672    uint16 vendor, device;
673    uint16 coreid;
674    uint8 class, subclass, progif;
675    uint dev;
676    uint8 header;
677    uint func;
678
679    chiprev = sb_chiprev(sbh);
680    coreidx = sb_coreidx(sbh);
681
682    osh = sb_osh(sbh);
683
684    /* Scan the SB bus */
685    bzero(sb_config_regs, sizeof(sb_config_regs));
686    bzero(sb_bar_cfg, sizeof(sb_bar_cfg));
687    bzero(sb_pci_cfg, sizeof(sb_pci_cfg));
688    memset(&sb_pci_null, -1, sizeof(sb_pci_null));
689    cfg = sb_config_regs;
690    bar = sb_bar_cfg;
691    for (dev = 0; dev < SB_MAXCORES; dev++) {
692        /* Check if the core exists */
693        if (!(regs = sb_setcoreidx(sbh, dev)))
694            continue;
695        sb = (sbconfig_t *) ((ulong) regs + SBCONFIGOFF);
696
697        /* Check if this core is banned */
698        coreid = sb_coreid(sbh);
699        for (i = 0; i < pci_banned; i++)
700            if (coreid == pci_ban[i])
701                break;
702        if (i < pci_banned)
703            continue;
704
705        for (func = 0; func < MAXFUNCS; ++func) {
706            /* Make sure we won't go beyond the limit */
707            if (cfg >= &sb_config_regs[SB_MAXCORES]) {
708                printk("PCI: too many emulated devices\n");
709                goto done;
710            }
711
712            /* Convert core id to pci id */
713            if (sb_corepciid
714                (sbh, func, &vendor, &device, &class, &subclass,
715                 &progif, &header))
716                continue;
717
718            /*
719             * Differentiate real PCI config from emulated.
720             * non zero 'pci' indicate there is a real PCI config space
721             * for this device.
722             */
723            switch (device) {
724            case BCM47XX_GIGETH_ID:
725                pci =
726                    (pci_config_regs *) ((uint32) regs + 0x800);
727                break;
728            case BCM47XX_SATAXOR_ID:
729                pci =
730                    (pci_config_regs *) ((uint32) regs + 0x400);
731                break;
732            case BCM47XX_ATA100_ID:
733                pci =
734                    (pci_config_regs *) ((uint32) regs + 0x800);
735                break;
736            default:
737                pci = NULL;
738                break;
739            }
740            /* Supported translations */
741            cfg->vendor = htol16(vendor);
742            cfg->device = htol16(device);
743            cfg->rev_id = chiprev;
744            cfg->prog_if = progif;
745            cfg->sub_class = subclass;
746            cfg->base_class = class;
747            cfg->header_type = header;
748            sbpci_init_regions(sbh, func, cfg, bar);
749            /* Save core interrupt flag */
750            cfg->int_pin =
751                R_REG(osh, &sb->sbtpsflag) & SBTPS_NUM0_MASK;
752            /* Save core interrupt assignment */
753            cfg->int_line = sb_irq(sbh);
754            /* Indicate there is no SROM */
755            *((uint32 *) & cfg->sprom_control) = 0xffffffff;
756
757            /* Point to the PCI config spaces */
758            sb_pci_cfg[dev][func].emu = cfg;
759            sb_pci_cfg[dev][func].pci = pci;
760            sb_pci_cfg[dev][func].bar = bar;
761            cfg++;
762            bar++;
763        }
764    }
765
766      done:
767    sb_setcoreidx(sbh, coreidx);
768}
769
770/*
771 * Initialize PCI core and construct PCI config spaces for SB cores.
772 * Must propagate sbpci_init_pci() return value to the caller to let
773 * them know the PCI core initialization status.
774 */
775int __init sbpci_init(sb_t * sbh)
776{
777    int status = sbpci_init_pci(sbh);
778    sbpci_init_cores(sbh);
779    return status;
780}
781

Archive Download this file



interactive