summaryrefslogtreecommitdiff
path: root/sys/dev/fdt
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-08-12 03:20:38 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-08-12 03:20:38 +0000
commit45488543c5169949863ead4998725194f6dd958b (patch)
tree0b9d2fa39d11f3d1b356c6508e77ea844992bffc /sys/dev/fdt
parent05c4fc25d854db69d69b447993ed2b10cd0affd7 (diff)
Improve snps,dwc3 support. Enough to make the USB3 controller on the
rk3399-firefly work in USB2 mode. ok patrick@
Diffstat (limited to 'sys/dev/fdt')
-rw-r--r--sys/dev/fdt/xhci_fdt.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/sys/dev/fdt/xhci_fdt.c b/sys/dev/fdt/xhci_fdt.c
index a1132389ad7..c2bf354e547 100644
--- a/sys/dev/fdt/xhci_fdt.c
+++ b/sys/dev/fdt/xhci_fdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xhci_fdt.c,v 1.4 2017/08/01 16:18:12 visa Exp $ */
+/* $OpenBSD: xhci_fdt.c,v 1.5 2017/08/12 03:20:37 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark kettenis <kettenis@openbsd.org>
*
@@ -49,6 +49,7 @@ struct cfattach xhci_fdt_ca = {
sizeof(struct xhci_fdt_softc), xhci_fdt_match, xhci_fdt_attach
};
+void xhci_dwc3_init(struct xhci_fdt_softc *);
void xhci_init_phys(struct xhci_fdt_softc *);
int
@@ -93,6 +94,13 @@ xhci_fdt_attach(struct device *parent, struct device *self, void *aux)
printf("\n");
+ /*
+ * Synopsys Designware USB3 controller needs some extra
+ * attention because of the additional OTG functionality.
+ */
+ if (OF_is_compatible(sc->sc_node, "snps,dwc3"))
+ xhci_dwc3_init(sc);
+
xhci_init_phys(sc);
if ((error = xhci_init(&sc->sc)) != 0) {
@@ -115,6 +123,56 @@ unmap:
bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
}
+
+/*
+ * Synopsys Designware USB3 controller.
+ */
+
+#define USB3_GCTL 0xc110
+#define USB3_GCTL_PRTCAPDIR_MASK (0x3 << 12)
+#define USB3_GCTL_PRTCAPDIR_HOST (0x1 << 12)
+#define USB3_GCTL_PRTCAPDIR_DEVICE (0x2 << 12)
+#define USB3_GUSB2PHYCFG0 0xc200
+#define USB3_GUSB2PHYCFG0_U2_FREECLK_EXISTS (1 << 30)
+#define USB3_GUSB2PHYCFG0_USBTRDTIM(n) ((n) << 10)
+#define USB3_GUSB2PHYCFG0_SUSPENDUSB20 (1 << 6)
+#define USB3_GUSB2PHYCFG0_PHYIF (1 << 3)
+
+void
+xhci_dwc3_init(struct xhci_fdt_softc *sc)
+{
+ char phy_type[16] = { 0 };
+ int node = sc->sc_node;
+ uint32_t reg;
+
+ /* We don't support device mode, so alway force host mode. */
+ reg = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USB3_GCTL);
+ reg &= ~USB3_GCTL_PRTCAPDIR_MASK;
+ reg |= USB3_GCTL_PRTCAPDIR_HOST;
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USB3_GCTL, reg);
+
+ /* Configure USB2 PHY type and quirks. */
+ OF_getprop(node, "phy_type", phy_type, sizeof(phy_type));
+ reg = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USB3_GUSB2PHYCFG0);
+ reg &= ~USB3_GUSB2PHYCFG0_USBTRDTIM(0xf);
+ if (strcmp(phy_type, "utmi_wide") == 0) {
+ reg |= USB3_GUSB2PHYCFG0_PHYIF;
+ reg |= USB3_GUSB2PHYCFG0_USBTRDTIM(0x5);
+ } else {
+ reg &= ~USB3_GUSB2PHYCFG0_PHYIF;
+ reg |= USB3_GUSB2PHYCFG0_USBTRDTIM(0x9);
+ }
+ if (OF_getproplen(node, "snps,dis-u2-freeclk-exists-quirk") == 0)
+ reg &= ~USB3_GUSB2PHYCFG0_U2_FREECLK_EXISTS;
+ if (OF_getproplen(node, "snps,dis_u2_susphy_quirk") == 0)
+ reg &= ~USB3_GUSB2PHYCFG0_SUSPENDUSB20;
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USB3_GUSB2PHYCFG0, reg);
+}
+
+/*
+ * PHY initialization.
+ */
+
struct xhci_phy {
const char *compat;
void (*init)(struct xhci_fdt_softc *, uint32_t *);