Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sh5/pci - Hook the PCI arbiter and error interrupts...



details:   https://anonhg.NetBSD.org/src/rev/3f50666e673d
branches:  trunk
changeset: 537665:3f50666e673d
user:      scw <scw%NetBSD.org@localhost>
date:      Fri Oct 04 10:22:24 2002 +0000

description:
- Hook the PCI arbiter and error interrupts, and print something
  useful should one occur.
- Manually poke some config values into the sh5pci host bridge's
  config registers since it doesn't appear in config. space.
- Reserve the first 256 bytes of i/o space to avoid assigning i/o
  address 0 to any cards.
- Slight tweak to the initialisation code after consultation with
  SuperH and the linux driver.

diffstat:

 sys/arch/sh5/pci/sh5_pci.c |  108 +++++++++++++++++++++++++++++++-------------
 1 files changed, 75 insertions(+), 33 deletions(-)

diffs (201 lines):

diff -r 4559df1130a7 -r 3f50666e673d sys/arch/sh5/pci/sh5_pci.c
--- a/sys/arch/sh5/pci/sh5_pci.c        Fri Oct 04 10:21:33 2002 +0000
+++ b/sys/arch/sh5/pci/sh5_pci.c        Fri Oct 04 10:22:24 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sh5_pci.c,v 1.5 2002/10/02 15:52:37 thorpej Exp $      */
+/*     $NetBSD: sh5_pci.c,v 1.6 2002/10/04 10:22:24 scw Exp $  */
 
 /*
  * Copyright 2002 Wasabi Systems, Inc.
@@ -158,6 +158,7 @@
 
 static void    sh5pci_bridge_init(struct sh5pci_softc *);
 static int     sh5pci_check_master_abort(struct sh5pci_softc *);
+static int     sh5pci_interrupt(void *);
 
 /*
  * XXX: These should be allocated dynamically to allow multiple instances.
@@ -302,7 +303,8 @@
         */
        sc->sc_intr = sh5pci_get_intr_hooks(&sh5pci_chipset_tag);
        sc->sc_intr_arg = (sc->sc_intr->ih_init)(&sh5pci_chipset_tag,
-           NULL, NULL, NULL, NULL, NULL, NULL);
+           &sc->sc_ih_serr, sh5pci_interrupt, sc,
+           &sc->sc_ih_err, sh5pci_interrupt, sc);
 
        /*
         * Initialise the host-pci hardware
@@ -322,14 +324,23 @@
            M_DEVBUF, NULL, 0, EX_NOWAIT);
 
        /*
-        * Allocate some I/O space for the bridge's config registers
-        * before assigning addresses to any other device.
-        * (The bridge doesn't seem to be able to see its own config
-        * registers when doing config cycles. Let's hope they're
-        * visible if the bridge is running in non-host mode...)
+        * Reserve the lowest 256 bytes of i/o space. Some (older) PCI
+        * devices don't like to be assigned such low addresses...
         */
        extent_alloc(ioext, 0x100, 0x100, 0, EX_NOWAIT, &cfg_ioaddr);
-       sh5pci_csr_write(sc, SH5PCI_CONF_IOBAR, cfg_ioaddr|PCI_MAPREG_TYPE_IO);
+
+       /*
+        * The SH5 Host-PCI bridge appears to be unable to see its own
+        * configuration registers in PCI config space, so manually fix
+        * up some values.
+        */
+       sh5pci_csr_write(sc, SH5PCI_CONF_IOBAR, 0x40000);
+       {
+               u_int32_t reg;
+               reg = sh5pci_csr_read(sc, PCI_BHLC_REG);
+               reg |= (0x80 << PCI_LATTIMER_SHIFT);
+               sh5pci_csr_write(sc, PCI_BHLC_REG, reg);
+       }
 
        /*
         * Configure up the PCI bus
@@ -347,7 +358,8 @@
        pba.pba_pc        = &sh5pci_chipset_tag;
        pba.pba_bus       = 0;
        pba.pba_bridgetag = NULL;
-       pba.pba_flags     = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
+       pba.pba_flags     = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED |
+           PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY;
        pba.pba_dmat      = &sh5pci_dma_tag;
        pba.pba_iot       = &sh5pci_io_tag;
        pba.pba_memt      = &sh5pci_mem_tag;
@@ -845,6 +857,12 @@
        u_int32_t reg;
        int i;
 
+       /* Disable the bridge */
+       reg = sh5pci_csr_read(sc, SH5PCI_CSR_CR);
+       reg &= ~SH5PCI_CSR_CR_PCI_CFINT_WR(1);
+       reg |= SH5PCI_CSR_CR_PCI_CFINT_WR(0);
+       sh5pci_csr_write(sc, SH5PCI_CSR_CR, reg);
+
        /*
         * Disable snoop
         */
@@ -861,28 +879,29 @@
        sh5pci_csr_write(sc, SH5PCI_CSR_PINTM, 0);
 
        /*
+        * Now enable the bridge.
+        */
+       reg = sh5pci_csr_read(sc, SH5PCI_CSR_CR);
+       reg |= SH5PCI_CSR_CR_PCI_FTO_WR(1);     /* TRDY and IRDY Enable */
+       reg |= SH5PCI_CSR_CR_PCI_PFE_WR(1);     /* Pre-fetch Enable */
+       reg |= SH5PCI_CSR_CR_PCI_BMAM_WR(1);    /* Round-robin arbitration */
+       reg |= SH5PCI_CSR_CR_PCI_PFCS(1);       /* 32-bytes prefetching */
+       sh5pci_csr_write(sc, SH5PCI_CSR_CR, reg);
+       reg |= SH5PCI_CSR_CR_PCI_CFINT_WR(1);   /* Take bridge out of reset */
+       sh5pci_csr_write(sc, SH5PCI_CSR_CR, reg);
+
+       /*
         * Enable Memory and I/O spaces, and enable the bridge to
         * be a bus master.
         */
        reg = sh5pci_csr_read(sc, PCI_COMMAND_STATUS_REG);
-       reg &= (PCI_COMMAND_MASK << PCI_COMMAND_SHIFT);
+       reg &= ~(PCI_COMMAND_MASK << PCI_COMMAND_SHIFT);
        reg |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
-               PCI_COMMAND_MASTER_ENABLE) << PCI_COMMAND_SHIFT;
+               PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_STEPPING_ENABLE)
+               << PCI_COMMAND_SHIFT;
        sh5pci_csr_write(sc, PCI_COMMAND_STATUS_REG, reg);
 
        /*
-        * Now enable the bridge.
-        */
-       reg  = SH5PCI_CSR_CR_PCI_FTO_WR(1);     /* TRDY and IRDY Enable */
-       reg |= SH5PCI_CSR_CR_PCI_PFE_WR(1);     /* Pre-fetch Enable */
-       reg |= SH5PCI_CSR_CR_PCI_BMAM_WR(1);    /* Round-robin arbitration */
-       reg |= SH5PCI_CSR_CR_PCI_HOSTNS(1);
-       reg |= SH5PCI_CSR_CR_PCI_CLKENS(1);
-       sh5pci_csr_write(sc, SH5PCI_CSR_CR, reg);
-       reg |= SH5PCI_CSR_CR_PCI_CFINT_WR(1);   /* Take bridge out of reset */
-       sh5pci_csr_write(sc, SH5PCI_CSR_CR, reg);
-
-       /*
         * Specify the base addresses in PCI memory and I/O space to
         * which SuperHyway accesses are mapped.
         *
@@ -897,7 +916,7 @@
        sh5pci_csr_write(sc, SH5PCI_CSR_MBR, (~SH5PCI_MEMORY_SIZE) + 1);
 
        sh5pci_csr_write(sc, SH5PCI_CSR_IOBMR,
-           SH5PCI_CSR_IOBMR_PCI_IOBAMR(SH5PCI_MB2IOBAMR(8)));
+           SH5PCI_CSR_IOBMR_PCI_IOBAMR(SH5PCI_KB2IOBAMR(256)));
        sh5pci_csr_write(sc, SH5PCI_CSR_IOBR, 0);
 
        /*
@@ -911,7 +930,7 @@
            SH5PCI_CSR_LSR_PCI_MBARE);
        sh5pci_csr_write(sc, SH5PCI_CSR_LAR(0), SH5PCI_RAM_PHYS_BASE);
        sh5pci_csr_write(sc, SH5PCI_CONF_MBAR(0),
-           0x00000000 | PCI_MAPREG_TYPE_MEM |
+           0x80000000 | PCI_MAPREG_TYPE_MEM |
            PCI_MAPREG_MEM_TYPE_32BIT | PCI_MAPREG_MEM_PREFETCHABLE_MASK);
 
        sh5pci_csr_write(sc, SH5PCI_CSR_LSR(1),
@@ -920,7 +939,7 @@
        sh5pci_csr_write(sc, SH5PCI_CSR_LAR(1),
            SH5PCI_RAM_PHYS_BASE + 0x20000000);
        sh5pci_csr_write(sc, SH5PCI_CONF_MBAR(1),
-           0x20000000 | PCI_MAPREG_TYPE_MEM |
+           0xa0000000 | PCI_MAPREG_TYPE_MEM |
            PCI_MAPREG_MEM_TYPE_32BIT | PCI_MAPREG_MEM_PREFETCHABLE_MASK);
 
        /*
@@ -940,15 +959,11 @@
                        sc->sc_map[i].m_start = ~0;
        }
 
-#if 0
        /*
-        * XXX: Not yet
-        *
-        * Enable interrupts
+        * Enable PCI error/arbiter interrupts
         */
-       sh5pci_csr_write(sc, SH5PCI_CSR_INTM, 0);
-       sh5pci_csr_write(sc, SH5PCI_CSR_AINTM, 0);
-#endif
+       sh5pci_csr_write(sc, SH5PCI_CSR_INTM, ~0);
+       sh5pci_csr_write(sc, SH5PCI_CSR_AINTM, ~0);
 }
 
 static int
@@ -970,3 +985,30 @@
 
        return (rv);
 }
+
+static int
+sh5pci_interrupt(void *arg)
+{
+       struct sh5pci_softc *sc = arg;
+       u_int32_t pci_int, pci_air, pci_cir;
+
+       pci_int = sh5pci_csr_read(sc, SH5PCI_CSR_INT);
+       pci_cir = sh5pci_csr_read(sc, SH5PCI_CSR_CIR);
+       pci_air = sh5pci_csr_read(sc, SH5PCI_CSR_AIR);
+
+       if (pci_int) {
+               printf("%s: PCI IRQ: INT 0x%x, CIR 0x%x, AIR 0x%x\n",
+                   sc->sc_dev.dv_xname, pci_int, pci_cir, pci_air);
+               sh5pci_csr_write(sc, SH5PCI_CSR_INT, pci_int);
+       }
+
+       pci_int = sh5pci_csr_read(sc, SH5PCI_CSR_AINT);
+
+       if (pci_int) {
+               printf("%s: PCI Arbiter IRQ: AINT 0x%x, CIR 0x%x, AIR 0x%x\n",
+                   sc->sc_dev.dv_xname, pci_int, pci_cir, pci_air);
+               sh5pci_csr_write(sc, SH5PCI_CSR_AINT, pci_int);
+       }
+
+       return (1);
+}



Home | Main Index | Thread Index | Old Index