Hello, Here is new diff, ok?
Index: ehci_fdt.c =================================================================== RCS file: /cvs/src/sys/dev/fdt/ehci_fdt.c,v diff -u -p -r1.11 ehci_fdt.c --- ehci_fdt.c 26 Jan 2024 17:11:50 -0000 1.11 +++ ehci_fdt.c 11 Feb 2024 00:57:15 -0000 @@ -207,6 +207,7 @@ struct ehci_phy ehci_phys[] = { { "allwinner,sun8i-v3s-usb-phy", sun4i_phy_init }, { "allwinner,sun20i-d1-usb-phy", sun4i_phy_init }, { "allwinner,sun50i-h6-usb-phy", sun4i_phy_init }, + { "allwinner,sun50i-h616-usb-phy", sun4i_phy_init }, { "allwinner,sun50i-a64-usb-phy", sun4i_phy_init }, { "allwinner,sun9i-a80-usb-phy", sun9i_phy_init }, }; @@ -287,6 +288,62 @@ ehci_init_phys(struct ehci_fdt_softc *sc #define SUNXI_AHB_INCR16 (1 << 11) void +sun50i_h616_phy2_init(struct ehci_fdt_softc *sc, int node) +{ + int len, idx; + uint32_t *reg, val; + bus_size_t size; + bus_space_handle_t ioh; + + /* + * to access USB2-PHY register, get address from "reg" property of + * current "allwinner,...-usb-phy" node + */ + len = OF_getproplen(node, "reg"); + if (len <= 0) + goto out; + + reg = malloc(len, M_TEMP, M_WAITOK); + OF_getpropintarray(node, "reg", reg, len); + + idx = OF_getindex(node, "pmu2", "reg-names"); + if (idx < 0 || (idx + 1) > (len / (sizeof(uint32_t) * 2))) { + printf(": no phy2 register\n"); + goto free; + } + + /* convert "reg-names" index to "reg" (address-size pair) index */ + idx *= 2; + + size = reg[idx + 1]; + if (bus_space_map(sc->sc.iot, reg[idx], size, 0, &ioh)) { + printf(": can't map phy2 registers\n"); + goto free; + } + + clock_enable(node, "usb2_phy"); + reset_deassert(node, "usb2_reset"); + clock_enable(node, "pmu2_clk"); + + /* + * address is offset from "pmu2", not EHCI2 base address + * (normally it points EHCI2 base address + 0x810) + */ + val = bus_space_read_4(sc->sc.iot, ioh, 0x10); + val &= ~(1 << 3); /* clear SIDDQ */ + bus_space_write_4(sc->sc.iot, ioh, 0x10, val); + + clock_disable(node, "pmu2_clk"); + /* "usb2_reset" and "usb2_phy" unchanged */ + + bus_space_unmap(sc->sc.iot, ioh, size); +free: + free(reg, M_TEMP, len); +out: + return; +} + +void sun4i_phy_init(struct ehci_fdt_softc *sc, uint32_t *cells) { uint32_t vbus_supply; @@ -298,6 +355,11 @@ sun4i_phy_init(struct ehci_fdt_softc *sc if (node == -1) return; + /* Allwinner H616 needs to clear PHY2's SIDDQ flag */ + if (OF_is_compatible(node, "allwinner,sun50i-h616-usb-phy") && + cells[1] != 2) + sun50i_h616_phy2_init(sc, node); + val = bus_space_read_4(sc->sc.iot, sc->sc.ioh, SUNXI_HCI_ICR); val |= SUNXI_AHB_INCR8 | SUNXI_AHB_INCR4; val |= SUNXI_AHB_INCRX_ALIGN; @@ -315,9 +377,17 @@ sun4i_phy_init(struct ehci_fdt_softc *sc val = bus_space_read_4(sc->sc.iot, sc->sc.ioh, 0x810); val &= ~(1 << 1); bus_space_write_4(sc->sc.iot, sc->sc.ioh, 0x810, val); - } else if (OF_is_compatible(node, "allwinner,sun20i-d1-usb-phy")) { + } else if (OF_is_compatible(node, "allwinner,sun8i-a83t-usb-phy") || + OF_is_compatible(node, "allwinner,sun20i-d1-usb-phy") || + OF_is_compatible(node, "allwinner,sun50i-h616-usb-phy")) { val = bus_space_read_4(sc->sc.iot, sc->sc.ioh, 0x810); val &= ~(1 << 3); + bus_space_write_4(sc->sc.iot, sc->sc.ioh, 0x810, val); + } + if (OF_is_compatible(node, "allwinner,sun8i-a83t-usb-phy") || + OF_is_compatible(node, "allwinner,sun50i-h616-usb-phy")) { + val = bus_space_read_4(sc->sc.iot, sc->sc.ioh, 0x810); + val |= 1 << 5; bus_space_write_4(sc->sc.iot, sc->sc.ioh, 0x810, val); } -- SASANO Takayoshi (JG1UAA) <u...@mx5.nisiq.net>