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