summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2018-08-09 12:25:39 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2018-08-09 12:25:39 +0000
commit6ffdc8f1fd6d28bb8cce4efcdff3539e5a748534 (patch)
tree318a1f505a956a73e1b29d37007ad79fe60e5bca /sys
parentd38fc1b5512450a2b8d8e179071104728a16baad (diff)
Synopsys Designeware PCIe IP isn't 100% ECAM compliant. It doesn't handle
type 0 configuration requests correctly which results in devices on bus 0 appearing multiple times. Fix this by adding a quirk and match the appropriate compatible string. ok jsg@, patrick@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/arm64/dev/pciecam.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/sys/arch/arm64/dev/pciecam.c b/sys/arch/arm64/dev/pciecam.c
index 74ae9a10ffd..9a3c4b603c4 100644
--- a/sys/arch/arm64/dev/pciecam.c
+++ b/sys/arch/arm64/dev/pciecam.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciecam.c,v 1.5 2018/08/03 22:40:05 kettenis Exp $ */
+/* $OpenBSD: pciecam.c,v 1.6 2018/08/09 12:25:38 kettenis Exp $ */
/*
* Copyright (c) 2013,2017 Patrick Wildt <patrick@blueri.se>
*
@@ -74,6 +74,8 @@ struct pciecam_softc {
bus_space_handle_t sc_ioh;
bus_dma_tag_t sc_dmat;
+ int sc_dw_quirk;
+
int sc_acells;
int sc_scells;
int sc_pacells;
@@ -119,7 +121,8 @@ pciecam_match(struct device *parent, void *match, void *aux)
{
struct fdt_attach_args *faa = aux;
- return OF_is_compatible(faa->fa_node, "pci-host-ecam-generic");
+ return (OF_is_compatible(faa->fa_node, "pci-host-ecam-generic") ||
+ OF_is_compatible(faa->fa_node, "snps,dw-pcie-ecam"));
}
void
@@ -135,6 +138,9 @@ pciecam_attach(struct device *parent, struct device *self, void *aux)
sc->sc_iot = faa->fa_iot;
sc->sc_dmat = faa->fa_dmat;
+ if (OF_is_compatible(faa->fa_node, "snps,dw-pcie-ecam"))
+ sc->sc_dw_quirk = 1;
+
sc->sc_acells = OF_getpropint(sc->sc_node, "#address-cells",
faa->fa_acells);
sc->sc_scells = OF_getpropint(sc->sc_node, "#size-cells",
@@ -253,8 +259,13 @@ pciecam_attach_hook(struct device *parent, struct device *self,
}
int
-pciecam_bus_maxdevs(void *sc, int busno) {
- return (32);
+pciecam_bus_maxdevs(void *v, int bus)
+{
+ struct pciecam_softc *sc = (struct pciecam_softc *)v;
+
+ if (bus == 0 && sc->sc_dw_quirk)
+ return 1;
+ return 32;
}
#define BUS_SHIFT 24