[BACK]Return to s3c2800_pci.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / s3c2xx0

Annotation of sys/arch/arm/s3c2xx0/s3c2800_pci.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $NetBSD: s3c2800_pci.c,v 1.12 2007/03/04 05:59:38 christos Exp $        */
                      2:
                      3: /*
                      4:  * Copyright (c) 2002 Fujitsu Component Limited
                      5:  * Copyright (c) 2002 Genetec Corporation
                      6:  * All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of The Fujitsu Component Limited nor the name of
                     17:  *    Genetec corporation may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
                     21:  * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     22:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
                     23:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     24:  * DISCLAIMED.  IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
                     25:  * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     26:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
                     27:  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
                     28:  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
                     29:  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     30:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
                     31:  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  *
                     34:  * derived from evbarm/ifpga/ifpga_pci.c
                     35:  */
                     36:
                     37: /*
                     38:  * Copyright (c) 2001 ARM Ltd
                     39:  * All rights reserved.
                     40:  *
                     41:  * Redistribution and use in source and binary forms, with or without
                     42:  * modification, are permitted provided that the following conditions
                     43:  * are met:
                     44:  * 1. Redistributions of source code must retain the above copyright
                     45:  *    notice, this list of conditions and the following disclaimer.
                     46:  * 2. Redistributions in binary form must reproduce the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer in the
                     48:  *    documentation and/or other materials provided with the distribution.
                     49:  * 3. The name of the company may not be used to endorse or promote
                     50:  *    products derived from this software without specific prior written
                     51:  *    permission.
                     52:  *
                     53:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
                     54:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
                     55:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     56:  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
                     57:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     58:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     59:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     60:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     61:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     62:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     63:  * SUCH DAMAGE.
                     64:  *
                     65:  * Copyright (c) 1997,1998 Mark Brinicombe.
                     66:  * Copyright (c) 1997,1998 Causality Limited
                     67:  * All rights reserved.
                     68:  *
                     69:  * Redistribution and use in source and binary forms, with or without
                     70:  * modification, are permitted provided that the following conditions
                     71:  * are met:
                     72:  * 1. Redistributions of source code must retain the above copyright
                     73:  *    notice, this list of conditions and the following disclaimer.
                     74:  * 2. Redistributions in binary form must reproduce the above copyright
                     75:  *    notice, this list of conditions and the following disclaimer in the
                     76:  *    documentation and/or other materials provided with the distribution.
                     77:  * 3. All advertising materials mentioning features or use of this software
                     78:  *    must display the following acknowledgement:
                     79:  *     This product includes software developed by Mark Brinicombe
                     80:  *     for the NetBSD Project.
                     81:  * 4. The name of the company nor the name of the author may be used to
                     82:  *    endorse or promote products derived from this software without specific
                     83:  *    prior written permission.
                     84:  *
                     85:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
                     86:  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
                     87:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     88:  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
                     89:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     90:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     91:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     92:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     93:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     94:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     95:  * SUCH DAMAGE.
                     96:  */
                     97:
                     98: /*
                     99:  * PCI configuration support for Samsung s3c2800.
                    100:  */
                    101:
                    102: #include <sys/cdefs.h>
                    103: __KERNEL_RCSID(0, "$NetBSD: s3c2800_pci.c,v 1.12 2007/03/04 05:59:38 christos Exp $");
                    104:
                    105: #include <sys/param.h>
                    106: #include <sys/systm.h>
                    107: #include <sys/kernel.h>
                    108: #include <sys/device.h>
                    109: #include <sys/extent.h>
                    110: #include <sys/malloc.h>
                    111:
                    112: #include <uvm/uvm_extern.h>
                    113:
                    114: #include <machine/bus.h>
                    115:
                    116: #include <arm/s3c2xx0/s3c2800reg.h>
                    117: #include <arm/s3c2xx0/s3c2800var.h>
                    118:
                    119: #include <dev/pci/pcireg.h>
                    120: #include <dev/pci/pciconf.h>
                    121:
                    122: #include "opt_pci.h"
                    123: #include "pci.h"
                    124:
                    125: /*
                    126:  * pci tag encoding.
                    127:  * also useful for configuration type 0 address
                    128:  */
                    129: #define BUSNO_SHIFT    16
                    130: #define BUSNO_MASK     (0xff<<BUSNO_SHIFT)
                    131: #define DEVNO_SHIFT    11
                    132: #define DEVNO_MASK     (0x1f<<DEVNO_SHIFT)
                    133: #define tag_to_devno(tag)      (((tag)&DEVNO_MASK)>>DEVNO_SHIFT)
                    134: #define FUNNO_SHIFT    8
                    135: #define FUNNO_MASK     (0x07<<FUNNO_SHIFT)
                    136:
                    137: #define BUS0_DEV_MIN   1
                    138: #define BUS0_DEV_MAX   21
                    139:
                    140: void   s3c2800_pci_attach_hook(struct device *, struct device *,
                    141:                                struct pcibus_attach_args *);
                    142: int    s3c2800_pci_bus_maxdevs(void *, int);
                    143: pcitag_t s3c2800_pci_make_tag(void *, int, int, int);
                    144: void   s3c2800_pci_decompose_tag(void *, pcitag_t, int *, int *, int *);
                    145: pcireg_t s3c2800_pci_conf_read(void *, pcitag_t, int);
                    146: void   s3c2800_pci_conf_write(void *, pcitag_t, int, pcireg_t);
                    147: int    s3c2800_pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
                    148: const char *s3c2800_pci_intr_string(void *, pci_intr_handle_t);
                    149: const struct evcnt *s3c2800_pci_intr_evcnt(void *, pci_intr_handle_t);
                    150: void *s3c2800_pci_intr_establish(void *, pci_intr_handle_t, int,
                    151:                                  int (*) (void *), void *);
                    152: void   s3c2800_pci_intr_disestablish(void *, void *);
                    153:
                    154: #define        PCI_CONF_LOCK(s)        (s) = disable_interrupts(I32_bit)
                    155: #define        PCI_CONF_UNLOCK(s)      restore_interrupts((s))
                    156:
                    157: struct sspci_irq_handler {
                    158:        int (*func) (void *);
                    159:        void *arg;
                    160:        int level;
                    161:        SLIST_ENTRY(sspci_irq_handler) link;
                    162: };
                    163:
                    164: struct sspci_softc {
                    165:        struct device sc_dev;
                    166:
                    167:        bus_space_tag_t sc_iot;
                    168:        bus_space_handle_t sc_reg_ioh;
                    169:        bus_space_handle_t sc_conf0_ioh;        /* config type0 space */
                    170:        bus_space_handle_t sc_conf1_ioh;        /* config type1 space */
                    171:
                    172:        uint32_t sc_pciinten;   /* copy of PCIINTEN register */
                    173:
                    174:        /* list of interrupt handlers. SLIST is not good for removing
                    175:         * element from it, but intr_disestablish is rarely called */
                    176:        SLIST_HEAD(, sspci_irq_handler) sc_irq_handlers;
                    177:
                    178:        void *sc_softinterrupt;
                    179: };
                    180:
                    181: static int sspci_match(struct device *, struct cfdata *, void *aux);
                    182: static void sspci_attach(struct device *, struct device *, void *);
                    183:
                    184: static int sspci_bs_map(void *, bus_addr_t, bus_size_t, int,
                    185:                             bus_space_handle_t *);
                    186: static int sspci_init_controller(struct sspci_softc *);
                    187: static int sspci_intr(void *);
                    188: static void sspci_softintr(void *);
                    189:
                    190: /* attach structures */
                    191: CFATTACH_DECL(sspci, sizeof(struct sspci_softc), sspci_match, sspci_attach,
                    192:     NULL, NULL);
                    193:
                    194:
                    195: struct arm32_pci_chipset sspci_chipset = {
                    196:        NULL,           /* conf_v */
                    197:        s3c2800_pci_attach_hook,
                    198:        s3c2800_pci_bus_maxdevs,
                    199:        s3c2800_pci_make_tag,
                    200:        s3c2800_pci_decompose_tag,
                    201:        s3c2800_pci_conf_read,
                    202:        s3c2800_pci_conf_write,
                    203:        NULL,           /* intr_v */
                    204:        s3c2800_pci_intr_map,
                    205:        s3c2800_pci_intr_string,
                    206:        s3c2800_pci_intr_evcnt,
                    207:        s3c2800_pci_intr_establish,
                    208:        s3c2800_pci_intr_disestablish
                    209: };
                    210:
                    211:
                    212: /*
                    213:  * bus space tag for PCI IO/Memory access space.
                    214:  * filled in by sspci_attach()
                    215:  */
                    216: struct bus_space sspci_io_tag, sspci_mem_tag;
                    217:
                    218: static int
                    219: sspci_match(struct device *parent, struct cfdata *match, void *aux)
                    220: {
                    221:        return 1;
                    222: }
                    223:
                    224: static void
                    225: sspci_attach(struct device *parent, struct device *self, void *aux)
                    226: {
                    227:        struct sspci_softc *sc = (struct sspci_softc *) self;
                    228:        struct s3c2xx0_attach_args *aa = aux;
                    229:        bus_space_tag_t iot;
                    230:        bus_dma_tag_t pci_dma_tag;
                    231:        const char *error_on;   /* for panic message */
                    232: #if defined(PCI_NETBSD_CONFIGURE)
                    233:        struct extent *ioext, *memext;
                    234:        struct pcibus_attach_args pci_pba;
                    235: #endif
                    236:
                    237: #define FAIL(which)  do { \
                    238:        error_on=(which); goto abort; }while(/*CONSTCOND*/0)
                    239:
                    240:        iot = sc->sc_iot = aa->sa_iot;
                    241:        if (bus_space_map(iot, S3C2800_PCICTL_BASE,
                    242:                S3C2800_PCICTL_SIZE, 0, &sc->sc_reg_ioh))
                    243:                FAIL("control regs");
                    244:
                    245:        if (bus_space_map(iot, S3C2800_PCI_CONF0_BASE,
                    246:                S3C2800_PCI_CONF0_SIZE, 0, &sc->sc_conf0_ioh))
                    247:                FAIL("config type 0 area");
                    248:
                    249: #if 0
                    250:        if (bus_space_map(iot, S3C2800_PCI_CONF1_BASE,
                    251:                S3C2800_PCI_CONF1_SIZE, 0, &sc->sc_conf1_ioh))
                    252:                FAIL("config type 1 area");
                    253: #endif
                    254:        printf("\n");
                    255:
                    256:        SLIST_INIT(&sc->sc_irq_handlers);
                    257:        if (!s3c2800_intr_establish(S3C2800_INT_PCI, IPL_AUDIO, IST_LEVEL,
                    258:                sspci_intr, sc))
                    259:                FAIL("intr_establish");
                    260:
                    261:        sc->sc_softinterrupt = softintr_establish(IPL_SOFT,
                    262:            sspci_softintr, sc);
                    263:        if (sc->sc_softinterrupt == NULL)
                    264:                FAIL("softintr_establish");
                    265:
                    266: #if defined(PCI_NETBSD_CONFIGURE)
                    267:        if (sspci_init_controller(sc)) {
                    268:                printf("%s: failed to initialize controller\n", self->dv_xname);
                    269:                return;
                    270:        }
                    271: #endif
                    272:
                    273:        sc->sc_pciinten =
                    274:            PCIINT_INA | PCIINT_SER | PCIINT_TPE | PCIINT_MPE |
                    275:            PCIINT_MFE | PCIINT_PRA | PCIINT_PRD;
                    276:
                    277:        bus_space_write_4(iot, sc->sc_reg_ioh, PCICTL_PCIINTEN,
                    278:            sc->sc_pciinten);
                    279:
                    280:        {
                    281:                pcireg_t id_reg, class_reg;
                    282:                char buf[1000];
                    283:
                    284:                id_reg = bus_space_read_4(iot, sc->sc_reg_ioh,
                    285:                    PCI_ID_REG);
                    286:                class_reg = bus_space_read_4(iot,
                    287:                    sc->sc_reg_ioh, PCI_CLASS_REG);
                    288:
                    289:                pci_devinfo(id_reg, class_reg, 1, buf, sizeof(buf));
                    290:                printf("%s: %s\n", self->dv_xname, buf);
                    291:        }
                    292:
                    293: #if defined(PCI_NETBSD_CONFIGURE)
                    294:        ioext = extent_create("pciio", 0x100, S3C2800_PCI_IOSPACE_SIZE - 0x100,
                    295:            M_DEVBUF, NULL, 0, EX_NOWAIT);
                    296:
                    297:        memext = extent_create("pcimem", 0, S3C2800_PCI_MEMSPACE_SIZE,
                    298:            M_DEVBUF, NULL, 0, EX_NOWAIT);
                    299:
                    300:        sspci_chipset.pc_conf_v = (void *) sc;
                    301:        sspci_chipset.pc_intr_v = (void *) sc;
                    302:
                    303:        pci_configure_bus(&sspci_chipset, ioext, memext, NULL, 0,
                    304:            arm_dcache_align);
                    305:
                    306:        extent_destroy(memext);
                    307:        extent_destroy(ioext);
                    308: #endif                         /* PCI_NETBSD_CONFIGURE */
                    309:
                    310:        /* initialize bus space tag */
                    311:        sspci_io_tag = *iot;
                    312:        sspci_io_tag.bs_cookie = (void *) S3C2800_PCI_IOSPACE_BASE;
                    313:        sspci_io_tag.bs_map = sspci_bs_map;
                    314:        sspci_mem_tag = *iot;
                    315:        sspci_mem_tag.bs_cookie = (void *) S3C2800_PCI_MEMSPACE_BASE;
                    316:        sspci_mem_tag.bs_map = sspci_bs_map;
                    317:
                    318:
                    319:        /* Platform provides PCI DMA tag */
                    320:        pci_dma_tag = s3c2800_pci_dma_init();
                    321:
                    322:        pci_pba.pba_pc = &sspci_chipset;
                    323:        pci_pba.pba_iot = &sspci_io_tag;
                    324:        pci_pba.pba_memt = &sspci_mem_tag;
                    325:        pci_pba.pba_dmat = pci_dma_tag;
                    326:        pci_pba.pba_dmat64 = NULL;
                    327:        pci_pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
                    328:        pci_pba.pba_bus = 0;
                    329:        pci_pba.pba_bridgetag = NULL;
                    330:
                    331:        config_found_ia(self, "pcibus", &pci_pba, pcibusprint);
                    332:
                    333:        return;
                    334:
                    335: #undef FAIL
                    336: abort:
                    337:        panic("%s: map failed (%s)",
                    338:            self->dv_xname, error_on);
                    339: }
                    340:
                    341:
                    342: static int
                    343: sspci_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int flag,
                    344:             bus_space_handle_t * bshp)
                    345: {
                    346:        bus_addr_t startpa, endpa;
                    347:        vaddr_t va;
                    348:
                    349: #ifdef PCI_DEBUG
                    350:        printf("sspci_bs_map: t=%p, addr=%lx, size=%lx, flag=%d\n",
                    351:            t, bpa, size, flag);
                    352: #endif
                    353:
                    354:        /* Round the allocation to page boundries */
                    355:        startpa = trunc_page(bpa);
                    356:        endpa = round_page(bpa + size);
                    357:
                    358:        /* Get some VM.  */
                    359:        va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
                    360:            UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
                    361:        if (va == 0)
                    362:                return ENOMEM;
                    363:
                    364:        /* Store the bus space handle */
                    365:        *bshp = va + (bpa & PGOFSET);
                    366:
                    367:        /* Now map the pages */
                    368:        /* The cookie is the physical base address for PCI I/O or memory area */
                    369:        while (startpa < endpa) {
                    370:                /* XXX pmap_kenter_pa maps pages cacheable -- not what we
                    371:                 * want.  */
                    372:                pmap_enter(pmap_kernel(), va, (bus_addr_t) t + startpa,
                    373:                    VM_PROT_READ | VM_PROT_WRITE, 0);
                    374:                va += PAGE_SIZE;
                    375:                startpa += PAGE_SIZE;
                    376:        }
                    377:        pmap_update(pmap_kernel());
                    378:
                    379:        return 0;
                    380: }
                    381:
                    382:
                    383:
                    384: void
                    385: pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int dev, int func,
                    386:                   int swiz, int *iline)
                    387: {
                    388: #ifdef PCI_DEBUG
                    389:        printf("pci_conf_interrupt(pc(%lx), bus(%d), dev(%d), func(%d), swiz(%d), *iline(%p)\n", (unsigned long) pc, bus, dev, func, swiz, iline);
                    390: #endif
                    391:        if (bus == 0) {
                    392:                *iline = dev;
                    393:        } else {
                    394:                panic("pci_conf_interrupt: bus=%d: not yet implemented", bus);
                    395:        }
                    396: }
                    397:
                    398: void
                    399: s3c2800_pci_attach_hook(struct device * parent, struct device * self,
                    400:                        struct pcibus_attach_args * pba)
                    401: {
                    402:
                    403:        /* Nothing to do. */
                    404: #ifdef PCI_DEBUG
                    405:        printf("s3c2800_pci_attach_hook()\n");
                    406: #endif
                    407: }
                    408:
                    409: int
                    410: s3c2800_pci_bus_maxdevs(void *v, int busno)
                    411: {
                    412:
                    413: #ifdef PCI_DEBUG
                    414:        printf("s3c2800_pci_bus_maxdevs(v=%p, busno=%d)\n", v, busno);
                    415: #endif
                    416:        return (32);
                    417: }
                    418: pcitag_t
                    419: s3c2800_pci_make_tag(void *v, int bus, int device, int function)
                    420: {
                    421:
                    422:        return ((bus << BUSNO_SHIFT) | (device << DEVNO_SHIFT) |
                    423:            (function << FUNNO_SHIFT));
                    424: }
                    425:
                    426: void
                    427: s3c2800_pci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
                    428: {
                    429:        if (bp != NULL)
                    430:                *bp = (tag >> BUSNO_SHIFT) & 0xff;
                    431:        if (dp != NULL)
                    432:                *dp = (tag >> DEVNO_SHIFT) & 0x1f;
                    433:        if (fp != NULL)
                    434:                *fp = (tag >> FUNNO_SHIFT) & 0x7;
                    435: }
                    436:
                    437: static vaddr_t
                    438: make_pci_conf_va(struct sspci_softc * sc, pcitag_t tag, int offset)
                    439: {
                    440:        if ((tag & BUSNO_MASK) == 0) {
                    441:                /* configuration type 0 */
                    442:                int devno = tag_to_devno(tag);
                    443:
                    444:                if (devno < BUS0_DEV_MIN || BUS0_DEV_MAX < devno)
                    445:                        return 0;
                    446:
                    447:                return (vaddr_t) bus_space_vaddr(sc->sc_iot, sc->sc_conf0_ioh) +
                    448:                    (tag & (DEVNO_MASK | FUNNO_MASK)) + offset;
                    449:        } else {
                    450:                /* XXX */
                    451:                return (vaddr_t) - 1;   /* cause fault */
                    452:        }
                    453: }
                    454:
                    455:
                    456: pcireg_t
                    457: s3c2800_pci_conf_read(void *v, pcitag_t tag, int offset)
                    458: {
                    459:        struct sspci_softc *sc = v;
                    460:        vaddr_t va = make_pci_conf_va(sc, tag, offset);
                    461:        int s;
                    462:        pcireg_t rv;
                    463:
                    464: #ifdef PCI_DEBUG
                    465:        printf("s3c2800_pci_conf_read: base=%lx tag=%lx offset=%x\n",
                    466:            sc->sc_conf0_ioh, tag, offset);
                    467: #endif
                    468:        if (va == 0)
                    469:                return -1;
                    470:
                    471:        PCI_CONF_LOCK(s);
                    472:
                    473:        if (badaddr_read((void *) va, sizeof(rv), &rv)) {
                    474: #if PCI_DEBUG
                    475:                printf("conf_read: %lx bad address\n", va);
                    476: #endif
                    477:                rv = (pcireg_t) - 1;
                    478:        }
                    479:        PCI_CONF_UNLOCK(s);
                    480:
                    481:        return rv;
                    482: }
                    483:
                    484: void
                    485: s3c2800_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
                    486: {
                    487:        struct sspci_softc *sc = v;
                    488:        vaddr_t va = make_pci_conf_va(sc, tag, offset);
                    489:        u_int s;
                    490:
                    491: #ifdef PCI_DEBUG
                    492:        printf("s3c2800_pci_conf_write: tag=%lx offset=%x -> va=%lx\n", tag, offset, va);
                    493: #endif
                    494:
                    495:        PCI_CONF_LOCK(s);
                    496:
                    497:        *(pcireg_t *) va = val;
                    498:
                    499:        PCI_CONF_UNLOCK(s);
                    500: }
                    501:
                    502: void *
                    503: s3c2800_pci_intr_establish(void *pcv, pci_intr_handle_t ih, int level,
                    504:                           int (*func) (void *), void *arg)
                    505: {
                    506:        struct sspci_softc *sc = pcv;
                    507:        struct sspci_irq_handler *handler;
                    508:        int s;
                    509:
                    510: #ifdef PCI_DEBUG
                    511:        printf("s3c2800_pci_intr_establish(pcv=%p, ih=0x%lx, level=%d, "
                    512:            "func=%p, arg=%p)\n", pcv, ih, level, func, arg);
                    513: #endif
                    514:
                    515:        handler = malloc(sizeof *handler, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
                    516:        if (handler == NULL)
                    517:                panic("sspci_intr_establish: can't malloc handler info");
                    518:
                    519:        handler->func = func;
                    520:        handler->arg = arg;
                    521:        handler->level = level;
                    522:
                    523:        s = splhigh();
                    524:        SLIST_INSERT_HEAD(&sc->sc_irq_handlers, handler, link);
                    525:        splx(s);
                    526:
                    527:        return (handler);
                    528: }
                    529:
                    530: void
                    531: s3c2800_pci_intr_disestablish(void *pcv, void *cookie)
                    532: {
                    533:        struct sspci_softc *sc = pcv;
                    534:        struct sspci_irq_handler *ih = cookie;
                    535:        int s;
                    536:
                    537: #ifdef PCI_DEBUG
                    538:        printf("s3c2800_pci_intr_disestablish(pcv=%p, cookie=%p)\n",
                    539:            pcv, cookie);
                    540: #endif
                    541:
                    542:        s = splhigh();
                    543:        SLIST_REMOVE(&sc->sc_irq_handlers, ih, sspci_irq_handler, link);
                    544:        splx(s);
                    545: }
                    546:
                    547: int
                    548: s3c2800_pci_intr_map(struct pci_attach_args * pa, pci_intr_handle_t * ihp)
                    549: {
                    550: #ifdef PCI_DEBUG
                    551:        int pin = pa->pa_intrpin;
                    552:        void *pcv = pa->pa_pc;
                    553:        pcitag_t intrtag = pa->pa_intrtag;
                    554:        int bus, device, function;
                    555:
                    556:        s3c2800_pci_decompose_tag(pcv, intrtag, &bus, &device, &function);
                    557:        printf("s3c2800_pci_intr_map: pcv=%p, tag=%08lx pin=%d dev=%d\n",
                    558:            pcv, intrtag, pin, device);
                    559: #endif
                    560:
                    561:
                    562:        /* S3C2800 has only one interrupt line for PCI */
                    563:        *ihp = 0;
                    564:        return 0;
                    565: }
                    566:
                    567: const char *
                    568: s3c2800_pci_intr_string(void *pcv, pci_intr_handle_t ih)
                    569: {
                    570:        /* We have only one interrupt source from PCI */
                    571:        return "pciint";
                    572: }
                    573:
                    574: const struct evcnt *
                    575: s3c2800_pci_intr_evcnt(void *pcv, pci_intr_handle_t ih)
                    576: {
                    577:
                    578:        /* XXX for now, no evcnt parent reported */
                    579:        return NULL;
                    580: }
                    581: /*
                    582:  * Initialize PCI controller
                    583:  */
                    584: int
                    585: sspci_init_controller(struct sspci_softc * sc)
                    586: {
                    587:        bus_space_tag_t iot = sc->sc_iot;
                    588:        bus_space_handle_t ioh = sc->sc_reg_ioh;
                    589:
                    590:        /* disable PCI command */
                    591:        bus_space_write_4(iot, ioh, PCI_COMMAND_STATUS_REG,
                    592:            0xffff0000);
                    593:
                    594:        /* latency=0x10, cacheline=8 */
                    595:        bus_space_write_4(iot, ioh, PCI_BHLC_REG,
                    596:            PCI_BHLC_CODE(0, 0, 0, 0x10, 8));
                    597:
                    598:        bus_space_write_4(iot, ioh, PCI_INTERRUPT_REG,
                    599:            PCI_INTERRUPT_CODE(0, 0, 0, 0));
                    600:
                    601:
                    602:
                    603: #if 1
                    604:        bus_space_write_4(iot, ioh, PCI_MAPREG_START,
                    605:            PCI_MAPREG_MEM_TYPE_32BIT | 0x80000000);
                    606:        /* Cover all DBANKs with BAR0 */
                    607:        bus_space_write_4(iot, ioh, PCICTL_PCIBAM0, 0xf8000000);
                    608:        bus_space_write_4(iot, ioh, PCICTL_PCIBATPA0, S3C2800_DBANK0_START);
                    609: #else
                    610:        bus_space_write_4(iot, ioh, PCI_MAPREG_START,
                    611:            PCI_MAPREG_MEM_TYPE_32BIT | 0xf0000000);
                    612:        bus_space_write_4(iot, ioh, PCI_MAPREG_START + 4,
                    613:            PCI_MAPREG_MEM_TYPE_32BIT | 0x80000000);
                    614:
                    615:        bus_space_write_4(iot, ioh, PCICTL_PCIBAM0, 0xffff0000);
                    616:        bus_space_write_4(iot, ioh, PCICTL_PCIBATPA0, 0xffff0000);
                    617:        bus_space_write_4(iot, ioh, PCICTL_PCIBAM1, 0xf1000000);
                    618:        bus_space_write_4(iot, ioh, PCICTL_PCIBATPA1, S3C2800_DBANK0_START);
                    619: #endif
                    620:
                    621:        bus_space_write_4(iot, ioh, PCI_COMMAND_STATUS_REG,
                    622:            PCI_STATUS_PARITY_DETECT |
                    623:            PCI_STATUS_SPECIAL_ERROR |
                    624:            PCI_STATUS_MASTER_ABORT |
                    625:            PCI_STATUS_MASTER_TARGET_ABORT |
                    626:            PCI_STATUS_TARGET_TARGET_ABORT |
                    627:            PCI_STATUS_DEVSEL_MEDIUM |
                    628:            PCI_STATUS_PARITY_ERROR |
                    629:            PCI_STATUS_BACKTOBACK_SUPPORT |
                    630:            PCI_STATUS_CAPLIST_SUPPORT |
                    631:            PCI_COMMAND_MASTER_ENABLE |
                    632:            PCI_COMMAND_MEM_ENABLE |
                    633:            PCI_COMMAND_IO_ENABLE);
                    634:
                    635:        bus_space_write_4(iot, ioh, PCICTL_PCICON,
                    636:            PCICON_ARB | PCICON_HST);
                    637:
                    638:        bus_space_write_4(iot, ioh, PCICTL_PCISET, 0);
                    639:        /* clear all interrupts */
                    640:        bus_space_write_4(iot, ioh, PCICTL_PCIINTST, 0xffffffff);
                    641:        bus_space_write_4(iot, ioh, PCICTL_PCIINTEN, 0);
                    642:
                    643:        bus_space_write_4(iot, ioh, PCICTL_PCICON,
                    644:            PCICON_RDY | PCICON_CFD | PCICON_ATS |
                    645:            PCICON_ARB | PCICON_HST);
                    646:
                    647:
                    648: #ifdef PCI_DEBUG
                    649:        {
                    650:                pcireg_t reg;
                    651:                int i;
                    652:
                    653:                for (i = 0; i <= 0x40; i += sizeof(pcireg_t)) {
                    654:                        reg = bus_space_read_4(iot, ioh, i);
                    655:                        printf("%03x: %08x\n", i, reg);
                    656:                }
                    657:                for (i = 0x100; i <= 0x154; i += sizeof(pcireg_t)) {
                    658:                        reg = bus_space_read_4(iot, ioh, i);
                    659:                        printf("%03x: %08x\n", i, reg);
                    660:                }
                    661:        }
                    662: #endif
                    663:        return 0;
                    664: }
                    665:
                    666:
                    667: static const char *pci_abnormal_error_name[] = {
                    668:        "PCI reset deasserted",
                    669:        "PCI reset asserted",
                    670:        "PCI master detected fatal error",
                    671:        "PCI master detected parity error",
                    672:        "PCI target detected parity error",
                    673:        "PCI SERR# asserted",
                    674: };
                    675:
                    676: static int
                    677: sspci_intr(void *arg)
                    678: {
                    679:        struct sspci_softc *sc = arg;
                    680:        int s;
                    681:        bus_space_tag_t iot = sc->sc_iot;
                    682:        bus_space_handle_t ioh = sc->sc_reg_ioh;
                    683:        uint32_t interrupts, errors;
                    684:
                    685:        interrupts = bus_space_read_4(iot, ioh, PCICTL_PCIINTST);
                    686:
                    687:        if (interrupts & PCIINT_INA) {
                    688:                s = splhigh();
                    689:                softintr_schedule(sc->sc_softinterrupt);
                    690:
                    691:                /* mask INTA itnerrupt until softinterrupt is handled */
                    692:                sc->sc_pciinten &= ~PCIINT_INA;
                    693:                bus_space_write_4(iot, ioh, PCICTL_PCIINTEN,
                    694:                    sc->sc_pciinten);
                    695:
                    696:                /* acknowledge INTA interrupt */
                    697:                bus_space_write_4(iot, ioh, PCICTL_PCIINTST, PCIINT_INA);
                    698:
                    699:                splx(s);
                    700:
                    701:                interrupts &= ~PCIINT_INA;
                    702:
                    703:        }
                    704:        errors = interrupts & (PCIINT_SER | PCIINT_TPE | PCIINT_MPE |
                    705:            PCIINT_MFE | PCIINT_PRA | PCIINT_PRD);
                    706:        if (errors) {
                    707:                int i;
                    708:
                    709:                for (i = 0; errors; ++i) {
                    710:                        if ((errors & (1 << i)) == 0)
                    711:                                continue;
                    712:
                    713:                        printf("%s: %s\n", sc->sc_dev.dv_xname,
                    714:                            pci_abnormal_error_name[i > 4 ? 5 : i]);
                    715:
                    716:                        errors &= ~(1 << i);
                    717:                }
                    718:                /* acknowledge interrupts */
                    719:                bus_space_write_4(iot, ioh, PCICTL_PCIINTST, interrupts);
                    720:        }
                    721:        return 0;
                    722: }
                    723:
                    724: static void
                    725: sspci_softintr(void *arg)
                    726: {
                    727:        struct sspci_softc *sc = arg;
                    728:        struct sspci_irq_handler *ih;
                    729:        int s;
                    730:
                    731:
                    732:        SLIST_FOREACH(ih, &(sc->sc_irq_handlers), link) {
                    733:                s = _splraise(ih->level);
                    734:                ih->func(ih->arg);
                    735:                splx(s);
                    736:        }
                    737:
                    738:        /* unmask INTA interrupt */
                    739:        s = splhigh();
                    740:        sc->sc_pciinten |= PCIINT_INA;
                    741:        bus_space_write_4(sc->sc_iot, sc->sc_reg_ioh, PCICTL_PCIINTEN,
                    742:            sc->sc_pciinten);
                    743:        splx(s);
                    744: }

CVSweb