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 <[email protected]>
+ *
+ * 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);
+}