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

Annotation of sys/arch/arm/xscale/i80321_pci.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: i80321_pci.c,v 1.3 2007/08/06 08:28:09 tom Exp $      */
        !             2: /*     $NetBSD: i80321_pci.c,v 1.7 2005/12/15 01:44:00 briggs Exp $    */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed for the NetBSD Project by
        !            21:  *     Wasabi Systems, Inc.
        !            22:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
        !            23:  *    or promote products derived from this software without specific prior
        !            24:  *    written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
        !            30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            36:  * POSSIBILITY OF SUCH DAMAGE.
        !            37:  */
        !            38:
        !            39: /*
        !            40:  * PCI configuration support for i80321 I/O Processor chip.
        !            41:  */
        !            42:
        !            43: #include <sys/param.h>
        !            44: #include <sys/systm.h>
        !            45: #include <sys/device.h>
        !            46: #include <sys/extent.h>
        !            47: #include <sys/malloc.h>
        !            48:
        !            49: #include <uvm/uvm_extern.h>
        !            50:
        !            51: #include <machine/bus.h>
        !            52:
        !            53: #include <arm/xscale/i80321reg.h>
        !            54: #include <arm/xscale/i80321var.h>
        !            55:
        !            56: #include <dev/pci/ppbreg.h>
        !            57:
        !            58: #include "pci.h"
        !            59:
        !            60: void           i80321_pci_attach_hook(struct device *, struct device *,
        !            61:                    struct pcibus_attach_args *);
        !            62: int            i80321_pci_bus_maxdevs(void *, int);
        !            63: pcitag_t       i80321_pci_make_tag(void *, int, int, int);
        !            64: void           i80321_pci_decompose_tag(void *, pcitag_t, int *, int *,
        !            65:                    int *);
        !            66: pcireg_t       i80321_pci_conf_read(void *, pcitag_t, int);
        !            67: void           i80321_pci_conf_write(void *, pcitag_t, int, pcireg_t);
        !            68:
        !            69: #define        PCI_CONF_LOCK(s)        (s) = disable_interrupts(I32_bit)
        !            70: #define        PCI_CONF_UNLOCK(s)      restore_interrupts((s))
        !            71:
        !            72: void
        !            73: i80321_pci_init(pci_chipset_tag_t pc, void *cookie)
        !            74: {
        !            75: #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
        !            76:        struct i80321_softc *sc = cookie;
        !            77:        struct extent *ioext, *memext;
        !            78:        uint32_t busno;
        !            79: #endif
        !            80:
        !            81:        pc->pc_conf_v = cookie;
        !            82:        pc->pc_attach_hook = i80321_pci_attach_hook;
        !            83:        pc->pc_bus_maxdevs = i80321_pci_bus_maxdevs;
        !            84:        pc->pc_make_tag = i80321_pci_make_tag;
        !            85:        pc->pc_decompose_tag = i80321_pci_decompose_tag;
        !            86:        pc->pc_conf_read = i80321_pci_conf_read;
        !            87:        pc->pc_conf_write = i80321_pci_conf_write;
        !            88:
        !            89: #if NPCI > 0 && defined(PCI_NETBSD_CONFIGURE)
        !            90:        /*
        !            91:         * Configure the PCI bus.
        !            92:         *
        !            93:         * XXX We need to revisit this.  We only configure the Secondary
        !            94:         * bus (and its children).  The bus configure code needs changes
        !            95:         * to support how the busses are arranged on this chip.  We also
        !            96:         * need to only configure devices in the private device space on
        !            97:         * the Secondary bus.
        !            98:         */
        !            99:
        !           100:        busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
        !           101:        busno = PCIXSR_BUSNO(busno);
        !           102:        if (busno == 0xff)
        !           103:                busno = 0;
        !           104:
        !           105:        ioext  = extent_create("pciio",
        !           106:            sc->sc_ioout_xlate + sc->sc_ioout_xlate_offset,
        !           107:            sc->sc_ioout_xlate + VERDE_OUT_XLATE_IO_WIN_SIZE - 1,
        !           108:            M_DEVBUF, NULL, 0, EX_NOWAIT);
        !           109:        memext = extent_create("pcimem", sc->sc_owin[0].owin_xlate_lo,
        !           110:            sc->sc_owin[0].owin_xlate_lo + VERDE_OUT_XLATE_MEM_WIN_SIZE - 1,
        !           111:            M_DEVBUF, NULL, 0, EX_NOWAIT);
        !           112:
        !           113:        aprint_normal("%s: configuring PCI bus\n", sc->sc_dev.dv_xname);
        !           114:        pci_configure_bus(pc, ioext, memext, NULL, busno, arm_dcache_align);
        !           115:
        !           116:        extent_destroy(ioext);
        !           117:        extent_destroy(memext);
        !           118: #endif
        !           119: }
        !           120:
        !           121: void
        !           122: i80321_pci_attach_hook(struct device *parent, struct device *self,
        !           123:     struct pcibus_attach_args *pba)
        !           124: {
        !           125:
        !           126:        /* Nothing to do. */
        !           127: }
        !           128:
        !           129: int
        !           130: i80321_pci_bus_maxdevs(void *v, int busno)
        !           131: {
        !           132:
        !           133:        return (32);
        !           134: }
        !           135:
        !           136: pcitag_t
        !           137: i80321_pci_make_tag(void *v, int b, int d, int f)
        !           138: {
        !           139:
        !           140:        return ((b << 16) | (d << 11) | (f << 8));
        !           141: }
        !           142:
        !           143: void
        !           144: i80321_pci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp)
        !           145: {
        !           146:
        !           147:        if (bp != NULL)
        !           148:                *bp = (tag >> 16) & 0xff;
        !           149:        if (dp != NULL)
        !           150:                *dp = (tag >> 11) & 0x1f;
        !           151:        if (fp != NULL)
        !           152:                *fp = (tag >> 8) & 0x7;
        !           153: }
        !           154:
        !           155: struct pciconf_state {
        !           156:        uint32_t ps_addr_val;
        !           157:
        !           158:        int ps_b, ps_d, ps_f;
        !           159: };
        !           160:
        !           161: static int
        !           162: i80321_pci_conf_setup(struct i80321_softc *sc, pcitag_t tag, int offset,
        !           163:     struct pciconf_state *ps)
        !           164: {
        !           165:        uint32_t busno;
        !           166:
        !           167:        i80321_pci_decompose_tag(sc, tag, &ps->ps_b, &ps->ps_d, &ps->ps_f);
        !           168:
        !           169:        busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
        !           170:        busno = PCIXSR_BUSNO(busno);
        !           171:        if (busno == 0xff)
        !           172:                busno = 0;
        !           173:
        !           174:        /*
        !           175:         * If the bus # is the same as our own, then use Type 0 cycles,
        !           176:         * else use Type 1.
        !           177:         *
        !           178:         * XXX We should filter out all non-private devices here!
        !           179:         * XXX How does private space interact with PCI-PCI bridges?
        !           180:         */
        !           181:        if (ps->ps_b == busno) {
        !           182:                if (ps->ps_d > (31 - 16))
        !           183:                        return (1);
        !           184:                /*
        !           185:                 * NOTE: PCI-X requires that devices update their
        !           186:                 * PCIXSR on every config write with the device number
        !           187:                 * specified in AD[15:11].  If we don't set this field,
        !           188:                 * each device could end of thinking it is at device 0,
        !           189:                 * which can cause a number of problems.  Doing this
        !           190:                 * unconditionally should be OK when only PCI devices
        !           191:                 * are present.
        !           192:                 */
        !           193:                ps->ps_addr_val = (1U << (ps->ps_d + 16)) |
        !           194:                    (ps->ps_d << 11) | (ps->ps_f << 8) | offset;
        !           195:        } else {
        !           196:                /* The tag is already in the correct format. */
        !           197:                ps->ps_addr_val = tag | offset | 1;
        !           198:        }
        !           199:
        !           200:        return (0);
        !           201: }
        !           202:
        !           203: pcireg_t
        !           204: i80321_pci_conf_read(void *v, pcitag_t tag, int offset)
        !           205: {
        !           206:        struct i80321_softc *sc = v;
        !           207:        struct pciconf_state ps;
        !           208:        vaddr_t va;
        !           209:        uint32_t isr;
        !           210:        pcireg_t rv;
        !           211:        u_int s;
        !           212:
        !           213:        if (i80321_pci_conf_setup(sc, tag, offset, &ps))
        !           214:                return ((pcireg_t) -1);
        !           215:
        !           216:        PCI_CONF_LOCK(s);
        !           217:
        !           218:        bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR,
        !           219:            ps.ps_addr_val);
        !           220:
        !           221:        va = (vaddr_t) bus_space_vaddr(sc->sc_st, sc->sc_atu_sh);
        !           222:        if (badaddr_read((void *) (va + ATU_OCCDR), sizeof(rv), &rv)) {
        !           223:                isr = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR);
        !           224:                bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_ATUISR,
        !           225:                    isr & (ATUISR_P_SERR_DET|ATUISR_PMA|ATUISR_PTAM|
        !           226:                           ATUISR_PTAT|ATUISR_PMPE));
        !           227: #if 0
        !           228:                printf("conf_read: %d/%d/%d bad address\n",
        !           229:                    ps.ps_b, ps.ps_d, ps.ps_f);
        !           230: #endif
        !           231:                rv = (pcireg_t) -1;
        !           232:        }
        !           233:
        !           234:        PCI_CONF_UNLOCK(s);
        !           235:
        !           236: #if 0
        !           237:        if (rv != 0xffffffff)
        !           238:                printf("conf read %x %x %x %x: %x\n",
        !           239:                    ps.ps_b, ps.ps_d, ps.ps_f, offset, rv);
        !           240: #endif
        !           241:
        !           242:        return (rv);
        !           243: }
        !           244:
        !           245: void
        !           246: i80321_pci_conf_write(void *v, pcitag_t tag, int offset, pcireg_t val)
        !           247: {
        !           248:        struct i80321_softc *sc = v;
        !           249:        struct pciconf_state ps;
        !           250:        u_int s;
        !           251:
        !           252:        if (i80321_pci_conf_setup(sc, tag, offset, &ps))
        !           253:                return;
        !           254:
        !           255:        PCI_CONF_LOCK(s);
        !           256:
        !           257:        bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCAR,
        !           258:            ps.ps_addr_val);
        !           259:        bus_space_write_4(sc->sc_st, sc->sc_atu_sh, ATU_OCCDR, val);
        !           260:
        !           261:        PCI_CONF_UNLOCK(s);
        !           262: }

CVSweb