On Wed, Feb 20, 2019 at 10:03:26PM +0900, SASANO Takayoshi wrote:
> Hello,
> 
> Allwinner V3s shares one USB port with MUSB OTG module and EHCI/OHCI.
> The default route of USB-PHY is to OTG module so we have to add workaround
> to sys/dev/fdt/ehci_fdt.c that the port connects to host controller.
> 
> (reference: sun4i_usb_phy0_reroute() at drivers/phy/allwinner/phy-sun4i-usb.c,
> Linux-5.0-RC6 code)

> +     len = OF_getproplen(node, "reg");
> +     if (len <= 0)
> +             return;
> +
> +     reg = malloc(len, M_TEMP, M_WAITOK);
> +     OF_getpropintarray(node, "reg", reg, len);
> +
> +     iot = sc->sc.iot;
> +     if (bus_space_map(iot, reg[idx], reg[idx + 1], 0, &ioh)) {
> +             free(reg, M_TEMP, len);
> +             return;
> +     }

That's not right.  The reg property needs to be translated through
all necessary layers.  This only works if the phy is in the same
layer as the ehci.  Feels like a hack.

I have also done an attempt at fixing this not long ago, but I wasn't
quite ready yet as this enable VBUS all the time and if there is a hw
where someone tries to connect a host to the device... then there are
two VBUSes, heh.  But if (for now) that's fine, we could also just go
ahead with it.

diff --git a/sys/arch/arm64/conf/GENERIC b/sys/arch/arm64/conf/GENERIC
index b85e1099412..edb785662c6 100644
--- a/sys/arch/arm64/conf/GENERIC
+++ b/sys/arch/arm64/conf/GENERIC
@@ -177,6 +177,7 @@ sdmmc*              at sximmc?      # SD/MMC bus
 sxitemp*       at fdt?         # Temperature sensor
 sxitwi*                at fdt?         # I2C controller
 iic*           at sxitwi?      # I2C bus
+sxiuphy*       at fdt?         # USB Phy
 dwxe*          at fdt?
 
 # PCI
diff --git a/sys/arch/arm64/conf/RAMDISK b/sys/arch/arm64/conf/RAMDISK
index 201a5f0fcb2..83ab6602c04 100644
--- a/sys/arch/arm64/conf/RAMDISK
+++ b/sys/arch/arm64/conf/RAMDISK
@@ -169,6 +169,7 @@ sximmc*             at fdt?         # SD/MMC card controller
 sdmmc*         at sximmc?      # SD/MMC bus
 sxitwi*                at fdt?         # I2C controller
 iic*           at sxitwi?      # I2C bus
+sxiuphy*       at fdt?         # USB Phy
 dwxe*          at fdt?
 
 # PCI
diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt
index f90efcdf446..5d6bf652d47 100644
--- a/sys/dev/fdt/files.fdt
+++ b/sys/dev/fdt/files.fdt
@@ -44,6 +44,10 @@ device       sxitwi: i2cbus
 attach sxitwi at fdt
 file   dev/fdt/sxitwi.c                sxitwi
 
+device sxiuphy
+attach sxiuphy at fdt
+file   dev/fdt/sxiuphy.c               sxiuphy
+
 device axppmic
 attach axppmic at i2c
 attach axppmic at rsb with axppmic_rsb
diff --git a/sys/dev/fdt/sxiuphy.c b/sys/dev/fdt/sxiuphy.c
new file mode 100644
index 00000000000..40d22bb2df5
--- /dev/null
+++ b/sys/dev/fdt/sxiuphy.c
@@ -0,0 +1,110 @@
+/*     $OpenBSD$       */
+/*
+ * Copyright (c) 2019 Patrick Wildt <patr...@blueri.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_misc.h>
+#include <dev/ofw/fdt.h>
+
+#define PHY_ISCR               0x00
+#define  PHY_ISCR_DPDM_CHANGE_DET      (1 << 4)
+#define  PHY_ISCR_ID_CHANGE_DET                (1 << 5)
+#define  PHY_ISCR_VBUS_CHANGE_DET      (1 << 6)
+#define  PHY_ISCR_VBUS_LOW             (2 << 12)
+#define  PHY_ISCR_VBUS_HIGH            (3 << 12)
+#define  PHY_ISCR_VBUS_MASK            (3 << 12)
+#define  PHY_ISCR_ID_LOW               (2 << 14)
+#define  PHY_ISCR_ID_HIGH              (3 << 14)
+#define  PHY_ISCR_ID_MASK              (3 << 14)
+#define  PHY_ISCR_DPDM_PULLUP          (1 << 16)
+#define  PHY_ISCR_ID_PULLUP            (1 << 17)
+#define PHY_PHYCTL_A10         0x04
+#define PHY_PHYBIST            0x08
+#define PHY_PHYTUNE            0x0c
+#define PHY_PHYCTL_A33         0x10
+#define PHY_OTGCTL             0x20
+#define  PHY_OTGCTL_ROUTE_MUSB         (1 << 0)
+
+#define PMU_UNK1               0x10
+
+struct sxiuphy_softc {
+       struct device           sc_dev;
+       bus_space_tag_t         sc_iot;
+       bus_space_handle_t      sc_ioh;
+};
+
+int sxiuphy_match(struct device *, void *, void *);
+void sxiuphy_attach(struct device *, struct device *, void *);
+
+struct cfattach        sxiuphy_ca = {
+       sizeof (struct sxiuphy_softc), sxiuphy_match, sxiuphy_attach
+};
+
+struct cfdriver sxiuphy_cd = {
+       NULL, "sxiuphy", DV_DULL
+};
+
+int
+sxiuphy_match(struct device *parent, void *match, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+
+       return (OF_is_compatible(faa->fa_node, "allwinner,sun8i-h3-usb-phy") ||
+           OF_is_compatible(faa->fa_node, "allwinner,sun8i-r40-usb-phy") ||
+           OF_is_compatible(faa->fa_node, "allwinner,sun8i-v3s-usb-phy") ||
+           OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-usb-phy") ||
+           OF_is_compatible(faa->fa_node, "allwinner,sun50i-h6-usb-phy"));
+}
+
+void
+sxiuphy_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct sxiuphy_softc *sc = (struct sxiuphy_softc *)self;
+       struct fdt_attach_args *faa = aux;
+       uint32_t reg;
+
+       if (faa->fa_nreg < 1) {
+               printf(": no registers\n");
+               return;
+       }
+
+       sc->sc_iot = faa->fa_iot;
+
+       if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
+           faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
+               printf(": can't map registers\n");
+               return;
+       }
+
+       printf("\n");
+
+       reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PHY_OTGCTL);
+       reg &= ~(PHY_ISCR_DPDM_CHANGE_DET | PHY_ISCR_ID_CHANGE_DET |
+           PHY_ISCR_VBUS_CHANGE_DET);
+       reg |= (PHY_ISCR_DPDM_PULLUP | PHY_ISCR_ID_PULLUP);
+       reg &= ~(PHY_ISCR_VBUS_MASK | PHY_ISCR_ID_MASK);
+       reg |= (PHY_ISCR_VBUS_HIGH | PHY_ISCR_ID_LOW);
+       reg &= ~PHY_OTGCTL_ROUTE_MUSB;
+       bus_space_write_4(sc->sc_iot, sc->sc_ioh, PHY_OTGCTL, reg);
+}

Reply via email to