Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/fdt Implement support for IO space, and better-...



details:   https://anonhg.NetBSD.org/src/rev/791d516e7d09
branches:  trunk
changeset: 449235:791d516e7d09
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Thu Feb 28 00:17:13 2019 +0000

description:
Implement support for IO space, and better-handle both variants of MMIO space.

diffstat:

 sys/arch/arm/fdt/pcihost_fdt.c |  109 ++++++++++++++++++++++++++++++++++------
 1 files changed, 92 insertions(+), 17 deletions(-)

diffs (204 lines):

diff -r ce59d0377ea2 -r 791d516e7d09 sys/arch/arm/fdt/pcihost_fdt.c
--- a/sys/arch/arm/fdt/pcihost_fdt.c    Wed Feb 27 23:29:50 2019 +0000
+++ b/sys/arch/arm/fdt/pcihost_fdt.c    Thu Feb 28 00:17:13 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pcihost_fdt.c,v 1.6 2018/11/19 11:08:16 jmcneill Exp $ */
+/* $NetBSD: pcihost_fdt.c,v 1.7 2019/02/28 00:17:13 jakllsch Exp $ */
 
 /*-
  * Copyright (c) 2018 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pcihost_fdt.c,v 1.6 2018/11/19 11:08:16 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pcihost_fdt.c,v 1.7 2019/02/28 00:17:13 jakllsch Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -81,6 +81,19 @@
        PCIHOST_ECAM,
 };
 
+struct pcih_bus_space {
+       struct bus_space        bst;
+
+       int             (*map)(void *, bus_addr_t, bus_size_t,
+                             int, bus_space_handle_t *);
+       struct space_range {
+               bus_addr_t      bpci;
+               bus_addr_t      bbus;
+               bus_size_t      size;
+       }                       ranges[4];
+       size_t                  nranges;
+};
+
 struct pcihost_softc {
        device_t                sc_dev;
        bus_dma_tag_t           sc_dmat;
@@ -95,6 +108,9 @@
        u_int                   sc_bus_max;
 
        struct arm32_pci_chipset sc_pc;
+
+       struct pcih_bus_space   sc_io;
+       struct pcih_bus_space   sc_mem;
 };
 
 static int     pcihost_match(device_t, cfdata_t, void *);
@@ -126,6 +142,9 @@
                                         const char *);
 static void    pcihost_intr_disestablish(void *, void *);
 
+static int     pcihost_bus_space_map(void *, bus_addr_t, bus_size_t,
+               int, bus_space_handle_t *);
+
 CFATTACH_DECL_NEW(pcihost_fdt, sizeof(struct pcihost_softc),
        pcihost_match, pcihost_attach, NULL, NULL);
 
@@ -203,6 +222,7 @@
        pba.pba_flags = PCI_FLAGS_MRL_OKAY |
                        PCI_FLAGS_MRM_OKAY |
                        PCI_FLAGS_MWI_OKAY |
+                       PCI_FLAGS_IO_OKAY |
                        PCI_FLAGS_MEM_OKAY;
 #ifdef __HAVE_PCI_MSI_MSIX
        if (sc->sc_type == PCIHOST_ECAM) {
@@ -210,8 +230,8 @@
                                 PCI_FLAGS_MSIX_OKAY;
        }
 #endif
-       pba.pba_iot = 0;
-       pba.pba_memt = sc->sc_bst;
+       pba.pba_iot = &sc->sc_io.bst;
+       pba.pba_memt = &sc->sc_mem.bst;
        pba.pba_dmat = sc->sc_dmat;
 #ifdef _PCI_HAVE_DMA64
        pba.pba_dmat64 = sc->sc_dmat;
@@ -253,6 +273,18 @@
        u_int probe_only;
        int error, len;
 
+       struct pcih_bus_space * const pibs = &sc->sc_io;
+       pibs->bst = *sc->sc_bst;
+       pibs->bst.bs_cookie = pibs;
+       pibs->map = pibs->bst.bs_map;
+       pibs->bst.bs_map = pcihost_bus_space_map;
+
+       struct pcih_bus_space * const pmbs = &sc->sc_mem;
+       pmbs->bst = *sc->sc_bst;
+       pmbs->bst.bs_cookie = pmbs;
+       pmbs->map = pmbs->bst.bs_map;
+       pmbs->bst.bs_map = pcihost_bus_space_map;
+
        /*
         * If this flag is set, skip configuration of the PCI bus and use existing config.
         */
@@ -276,47 +308,73 @@
         */
        while (len >= 28) {
                const uint32_t phys_hi = be32dec(&ranges[0]);
+               const uint64_t bus_phys = be64dec(&ranges[1]);
                const uint64_t cpu_phys = be64dec(&ranges[3]);
                const uint64_t size = be64dec(&ranges[5]);
 
+               len -= 28;
+               ranges += 7;
+
+               const bool is64 = (__SHIFTOUT(phys_hi, PHYS_HI_SPACE) ==
+                   PHYS_HI_SPACE_MEM64) ? true : false;
                switch (__SHIFTOUT(phys_hi, PHYS_HI_SPACE)) {
                case PHYS_HI_SPACE_IO:
+                       if (pibs->nranges + 1 >= __arraycount(pibs->ranges)) {
+                               aprint_error_dev(sc->sc_dev, "too many IO ranges\n");
+                               continue;
+                       }
+                       pibs->ranges[pibs->nranges].bpci = bus_phys;
+                       pibs->ranges[pibs->nranges].bbus = cpu_phys;
+                       pibs->ranges[pibs->nranges].size = size;
+                       ++pibs->nranges;
                        if (ioext != NULL) {
                                aprint_error_dev(sc->sc_dev, "ignoring duplicate IO space range\n");
                                continue;
                        }
-                       ioext = extent_create("pciio", cpu_phys, cpu_phys + size - 1, NULL, 0, EX_NOWAIT);
+                       ioext = extent_create("pciio", bus_phys, bus_phys + size - 1, NULL, 0, EX_NOWAIT);
                        aprint_verbose_dev(sc->sc_dev,
-                           "I/O memory @ 0x%" PRIx64 " size 0x%" PRIx64 "\n",
-                           cpu_phys, size);
+                           "IO: 0x%" PRIx64 "+0x%" PRIx64 "@0x%" PRIx64 "\n",
+                           bus_phys, size, cpu_phys);
+                       /* reserve a PC-like legacy IO ports range, perhaps for access to VGA registers */
+                       if (bus_phys == 0 && size >= 0x10000)
+                               extent_alloc_region(ioext, 0, 0x1000, EX_WAITOK);
                        break;
+               case PHYS_HI_SPACE_MEM64:
+                       /* FALLTHROUGH */
                case PHYS_HI_SPACE_MEM32:
-                       if ((phys_hi & PHYS_HI_PREFETCH) != 0) {
+                       if (pmbs->nranges + 1 >= __arraycount(pmbs->ranges)) {
+                               aprint_error_dev(sc->sc_dev, "too many mem ranges\n");
+                               continue;
+                       }
+                       /* both pmem and mem spaces are in the same tag */
+                       pmbs->ranges[pmbs->nranges].bpci = bus_phys;
+                       pmbs->ranges[pmbs->nranges].bbus = cpu_phys;
+                       pmbs->ranges[pmbs->nranges].size = size;
+                       ++pmbs->nranges;
+                       if ((phys_hi & PHYS_HI_PREFETCH) != 0 ||
+                           __SHIFTOUT(phys_hi, PHYS_HI_SPACE) == PHYS_HI_SPACE_MEM64) {
                                if (pmemext != NULL) {
                                        aprint_error_dev(sc->sc_dev, "ignoring duplicate mem (prefetchable) range\n");
                                        continue;
                                }
-                               pmemext = extent_create("pcipmem", cpu_phys, cpu_phys + size - 1, NULL, 0, EX_NOWAIT);
+                               pmemext = extent_create("pcipmem", bus_phys, bus_phys + size - 1, NULL, 0, EX_NOWAIT);
                                aprint_verbose_dev(sc->sc_dev,
-                                   "32-bit MMIO (prefetchable) @ 0x%" PRIx64 " size 0x%" PRIx64 "\n",
-                                   cpu_phys, size);
+                                   "MMIO (%d-bit prefetchable): 0x%" PRIx64 "+0x%" PRIx64 "@0x%" PRIx64 "\n",
+                                   is64 ? 64 : 32, bus_phys, size, cpu_phys);
                        } else {
                                if (memext != NULL) {
                                        aprint_error_dev(sc->sc_dev, "ignoring duplicate mem (non-prefetchable) range\n");
                                        continue;
                                }
-                               memext = extent_create("pcimem", cpu_phys, cpu_phys + size - 1, NULL, 0, EX_NOWAIT);
+                               memext = extent_create("pcimem", bus_phys, bus_phys + size - 1, NULL, 0, EX_NOWAIT);
                                aprint_verbose_dev(sc->sc_dev,
-                                   "32-bit MMIO (non-prefetchable) @ 0x%" PRIx64 " size 0x%" PRIx64 "\n",
-                                   cpu_phys, size);
+                                   "MMIO (%d-bit non-prefetchable): 0x%" PRIx64 "+0x%" PRIx64 "@0x%" PRIx64 "\n",
+                                   is64 ? 64 : 32, bus_phys, size, cpu_phys);
                        }
                        break;
                default:
                        break;
                }
-
-               len -= 28;
-               ranges += 7;
        }
 
        error = pci_configure_bus(&sc->sc_pc, ioext, memext, pmemext, sc->sc_bus_min, PCIHOST_CACHELINE_SIZE);
@@ -597,3 +655,20 @@
 
        fdtbus_intr_disestablish(sc->sc_phandle, vih);
 }
+
+static int
+pcihost_bus_space_map(void *t, bus_addr_t bpa, bus_size_t size, int flag,
+    bus_space_handle_t *bshp)
+{
+       struct pcih_bus_space * const pbs = t;
+
+       for (size_t i = 0; i < pbs->nranges; i++) {
+               const bus_addr_t rmin = pbs->ranges[i].bpci;
+               const bus_addr_t rmax = pbs->ranges[i].bpci - 1 + pbs->ranges[i].size;
+               if ((bpa >= rmin) && ((bpa - 1 + size) <= rmax)) {
+                       return pbs->map(t, bpa - pbs->ranges[i].bpci + pbs->ranges[i].bbus, size, flag, bshp);
+               }
+       }
+
+       return ERANGE;
+}



Home | Main Index | Thread Index | Old Index