1*c7fb772bSthorpej /* $NetBSD: rk_usb.c,v 1.13 2021/08/07 16:18:45 thorpej Exp $ */
26726462dSjmcneill
36726462dSjmcneill /*-
46726462dSjmcneill * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
56726462dSjmcneill * All rights reserved.
66726462dSjmcneill *
76726462dSjmcneill * Redistribution and use in source and binary forms, with or without
86726462dSjmcneill * modification, are permitted provided that the following conditions
96726462dSjmcneill * are met:
106726462dSjmcneill * 1. Redistributions of source code must retain the above copyright
116726462dSjmcneill * notice, this list of conditions and the following disclaimer.
126726462dSjmcneill * 2. Redistributions in binary form must reproduce the above copyright
136726462dSjmcneill * notice, this list of conditions and the following disclaimer in the
146726462dSjmcneill * documentation and/or other materials provided with the distribution.
156726462dSjmcneill *
166726462dSjmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
176726462dSjmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
186726462dSjmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
196726462dSjmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
206726462dSjmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
216726462dSjmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
226726462dSjmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
236726462dSjmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
246726462dSjmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
256726462dSjmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
266726462dSjmcneill * POSSIBILITY OF SUCH DAMAGE.
276726462dSjmcneill */
286726462dSjmcneill
296726462dSjmcneill #include <sys/cdefs.h>
306726462dSjmcneill
31*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: rk_usb.c,v 1.13 2021/08/07 16:18:45 thorpej Exp $");
326726462dSjmcneill
336726462dSjmcneill #include <sys/param.h>
346726462dSjmcneill #include <sys/bus.h>
356726462dSjmcneill #include <sys/device.h>
366726462dSjmcneill #include <sys/intr.h>
376726462dSjmcneill #include <sys/systm.h>
386726462dSjmcneill #include <sys/time.h>
396726462dSjmcneill #include <sys/kmem.h>
406726462dSjmcneill
416726462dSjmcneill #include <dev/clk/clk_backend.h>
426726462dSjmcneill
436726462dSjmcneill #include <dev/fdt/fdtvar.h>
445403e5e5Sjmcneill #include <dev/fdt/syscon.h>
456726462dSjmcneill
466726462dSjmcneill static int rk_usb_match(device_t, cfdata_t, void *);
476726462dSjmcneill static void rk_usb_attach(device_t, device_t, void *);
486726462dSjmcneill
498c7bec30Sjmcneill #define RK3328_CON0_REG 0x100
508c7bec30Sjmcneill #define RK3328_CON1_REG 0x104
518c7bec30Sjmcneill #define RK3328_CON2_REG 0x108
528c7bec30Sjmcneill #define RK3328_USBPHY_COMMONONN __BIT(4)
538c7bec30Sjmcneill
548c7bec30Sjmcneill #define RK3399_GRF_USB20_PHY0_CON0_REG 0x0e450
558c7bec30Sjmcneill #define RK3399_GRF_USB20_PHY1_CON0_REG 0x0e460
568c7bec30Sjmcneill #define RK3399_USBPHY_COMMONONN __BIT(4)
578c7bec30Sjmcneill #define RK3399_GRF_USB20_PHY0_CON1_REG 0x0e454
588c7bec30Sjmcneill #define RK3399_GRF_USB20_PHY1_CON1_REG 0x0e464
598c7bec30Sjmcneill #define RK3399_GRF_USB20_PHY0_CON2_REG 0x0e458
608c7bec30Sjmcneill #define RK3399_GRF_USB20_PHY1_CON2_REG 0x0e468
618c7bec30Sjmcneill #define RK3399_USBPHY_SUSPEND_N __BIT(1)
628c7bec30Sjmcneill #define RK3399_USBPHY_UTMI_SEL __BIT(0)
638c7bec30Sjmcneill
648c7bec30Sjmcneill #define RK3399_PHY_NO(_sc) ((_sc)->sc_reg == 0xe450 ? 0 : 1)
656726462dSjmcneill
666726462dSjmcneill enum rk_usb_type {
676726462dSjmcneill USB_RK3328 = 1,
688c7bec30Sjmcneill USB_RK3399,
696726462dSjmcneill };
706726462dSjmcneill
71646c0f59Sthorpej static const struct device_compatible_entry compat_data[] = {
72646c0f59Sthorpej { .compat = "rockchip,rk3328-usb2phy", .value = USB_RK3328 },
73646c0f59Sthorpej { .compat = "rockchip,rk3399-usb2phy", .value = USB_RK3399 },
74ec189949Sthorpej DEVICE_COMPAT_EOL
756726462dSjmcneill };
766726462dSjmcneill
776726462dSjmcneill struct rk_usb_clk {
786726462dSjmcneill struct clk base;
796726462dSjmcneill };
806726462dSjmcneill
816726462dSjmcneill struct rk_usb_softc {
826726462dSjmcneill device_t sc_dev;
835403e5e5Sjmcneill struct syscon *sc_syscon;
846726462dSjmcneill enum rk_usb_type sc_type;
856726462dSjmcneill
866726462dSjmcneill struct clk_domain sc_clkdom;
876726462dSjmcneill struct rk_usb_clk sc_usbclk;
888c7bec30Sjmcneill
898c7bec30Sjmcneill bus_addr_t sc_reg;
906726462dSjmcneill };
916726462dSjmcneill
926726462dSjmcneill CFATTACH_DECL_NEW(rk_usb, sizeof(struct rk_usb_softc),
936726462dSjmcneill rk_usb_match, rk_usb_attach, NULL, NULL);
946726462dSjmcneill
956726462dSjmcneill static struct clk *
rk_usb_clk_get(void * priv,const char * name)966726462dSjmcneill rk_usb_clk_get(void *priv, const char *name)
976726462dSjmcneill {
986726462dSjmcneill struct rk_usb_softc * const sc = priv;
996726462dSjmcneill
1006726462dSjmcneill if (strcmp(name, sc->sc_usbclk.base.name) != 0)
1016726462dSjmcneill return NULL;
1026726462dSjmcneill
1036726462dSjmcneill return &sc->sc_usbclk.base;
1046726462dSjmcneill }
1056726462dSjmcneill
1066726462dSjmcneill static void
rk_usb_clk_put(void * priv,struct clk * clk)1076726462dSjmcneill rk_usb_clk_put(void *priv, struct clk *clk)
1086726462dSjmcneill {
1096726462dSjmcneill }
1106726462dSjmcneill
1116726462dSjmcneill static u_int
rk_usb_clk_get_rate(void * priv,struct clk * clk)1126726462dSjmcneill rk_usb_clk_get_rate(void *priv, struct clk *clk)
1136726462dSjmcneill {
1146726462dSjmcneill return 480000000;
1156726462dSjmcneill }
1166726462dSjmcneill
1176726462dSjmcneill static int
rk_usb_clk_enable(void * priv,struct clk * clk)1186726462dSjmcneill rk_usb_clk_enable(void *priv, struct clk *clk)
1196726462dSjmcneill {
1206726462dSjmcneill struct rk_usb_softc * const sc = priv;
1218c7bec30Sjmcneill uint32_t reg, write_mask, write_val;
1226726462dSjmcneill
1238c7bec30Sjmcneill switch (sc->sc_type) {
1248c7bec30Sjmcneill case USB_RK3328:
1258c7bec30Sjmcneill reg = RK3328_CON2_REG;
1268c7bec30Sjmcneill write_mask = RK3328_USBPHY_COMMONONN << 16;
1278c7bec30Sjmcneill write_val = 0;
1288c7bec30Sjmcneill break;
1298c7bec30Sjmcneill case USB_RK3399:
1308c7bec30Sjmcneill reg = RK3399_PHY_NO(sc) == 0 ?
1318c7bec30Sjmcneill RK3399_GRF_USB20_PHY0_CON0_REG :
1328c7bec30Sjmcneill RK3399_GRF_USB20_PHY1_CON0_REG;
1338c7bec30Sjmcneill write_mask = RK3399_USBPHY_COMMONONN << 16;
1348c7bec30Sjmcneill write_val = 0;
1358c7bec30Sjmcneill break;
1368c7bec30Sjmcneill default:
1378c7bec30Sjmcneill return ENXIO;
1388c7bec30Sjmcneill }
1395403e5e5Sjmcneill
1405403e5e5Sjmcneill syscon_lock(sc->sc_syscon);
1418c7bec30Sjmcneill syscon_write_4(sc->sc_syscon, reg, write_mask | write_val);
1425403e5e5Sjmcneill syscon_unlock(sc->sc_syscon);
1436726462dSjmcneill
1446726462dSjmcneill return 0;
1456726462dSjmcneill }
1466726462dSjmcneill
1476726462dSjmcneill static int
rk_usb_clk_disable(void * priv,struct clk * clk)1486726462dSjmcneill rk_usb_clk_disable(void *priv, struct clk *clk)
1496726462dSjmcneill {
1506726462dSjmcneill struct rk_usb_softc * const sc = priv;
1518c7bec30Sjmcneill uint32_t reg, write_mask, write_val;
1526726462dSjmcneill
1538c7bec30Sjmcneill switch (sc->sc_type) {
1548c7bec30Sjmcneill case USB_RK3328:
1558c7bec30Sjmcneill reg = RK3328_CON2_REG;
1568c7bec30Sjmcneill write_mask = RK3328_USBPHY_COMMONONN << 16;
1578c7bec30Sjmcneill write_val = RK3328_USBPHY_COMMONONN;
1588c7bec30Sjmcneill break;
1598c7bec30Sjmcneill case USB_RK3399:
1608c7bec30Sjmcneill reg = RK3399_PHY_NO(sc) == 0 ?
1618c7bec30Sjmcneill RK3399_GRF_USB20_PHY0_CON0_REG :
1628c7bec30Sjmcneill RK3399_GRF_USB20_PHY1_CON0_REG;
1638c7bec30Sjmcneill write_mask = RK3399_USBPHY_COMMONONN << 16;
1648c7bec30Sjmcneill write_val = RK3399_USBPHY_COMMONONN;
1658c7bec30Sjmcneill break;
1668c7bec30Sjmcneill default:
1678c7bec30Sjmcneill return ENXIO;
1688c7bec30Sjmcneill }
1695403e5e5Sjmcneill
1705403e5e5Sjmcneill syscon_lock(sc->sc_syscon);
1718c7bec30Sjmcneill syscon_write_4(sc->sc_syscon, reg, write_mask | write_val);
1725403e5e5Sjmcneill syscon_unlock(sc->sc_syscon);
1736726462dSjmcneill
1746726462dSjmcneill return 0;
1756726462dSjmcneill }
1766726462dSjmcneill
1776726462dSjmcneill static const struct clk_funcs rk_usb_clk_funcs = {
1786726462dSjmcneill .get = rk_usb_clk_get,
1796726462dSjmcneill .put = rk_usb_clk_put,
1806726462dSjmcneill .get_rate = rk_usb_clk_get_rate,
1816726462dSjmcneill .enable = rk_usb_clk_enable,
1826726462dSjmcneill .disable = rk_usb_clk_disable,
1836726462dSjmcneill };
1846726462dSjmcneill
1856726462dSjmcneill static struct clk *
rk_usb_fdt_decode(device_t dev,int cc_phandle,const void * data,size_t len)18651b425efSaymeric rk_usb_fdt_decode(device_t dev, int cc_phandle, const void *data, size_t len)
1876726462dSjmcneill {
1886726462dSjmcneill struct rk_usb_softc * const sc = device_private(dev);
1896726462dSjmcneill
1906726462dSjmcneill if (len != 0)
1916726462dSjmcneill return NULL;
1926726462dSjmcneill
1936726462dSjmcneill return &sc->sc_usbclk.base;
1946726462dSjmcneill }
1956726462dSjmcneill
1966726462dSjmcneill static const struct fdtbus_clock_controller_func rk_usb_fdt_funcs = {
1976726462dSjmcneill .decode = rk_usb_fdt_decode
1986726462dSjmcneill };
1996726462dSjmcneill
2006726462dSjmcneill static int
rk_usb_match(device_t parent,cfdata_t cf,void * aux)2016726462dSjmcneill rk_usb_match(device_t parent, cfdata_t cf, void *aux)
2026726462dSjmcneill {
2036726462dSjmcneill struct fdt_attach_args * const faa = aux;
2046726462dSjmcneill
2056e54367aSthorpej return of_compatible_match(faa->faa_phandle, compat_data);
2066726462dSjmcneill }
2076726462dSjmcneill
2086726462dSjmcneill static void
rk_usb_attach(device_t parent,device_t self,void * aux)2096726462dSjmcneill rk_usb_attach(device_t parent, device_t self, void *aux)
2106726462dSjmcneill {
2116726462dSjmcneill struct rk_usb_softc * const sc = device_private(self);
2126726462dSjmcneill struct fdt_attach_args * const faa = aux;
2136726462dSjmcneill const int phandle = faa->faa_phandle;
2148c7bec30Sjmcneill struct clk *clk;
2156726462dSjmcneill int child;
2166726462dSjmcneill
2178c7bec30Sjmcneill /* Cache the base address of this PHY so we know which instance we are */
2188c7bec30Sjmcneill if (fdtbus_get_reg(phandle, 0, &sc->sc_reg, NULL) != 0) {
2198c7bec30Sjmcneill aprint_error(": couldn't get registers\n");
2208c7bec30Sjmcneill return;
2218c7bec30Sjmcneill }
2228c7bec30Sjmcneill
2238c7bec30Sjmcneill clk = fdtbus_clock_get(phandle, "phyclk");
2248c7bec30Sjmcneill if (clk && clk_enable(clk) != 0) {
2258c7bec30Sjmcneill aprint_error(": couldn't enable phy clock\n");
2268c7bec30Sjmcneill return;
2278c7bec30Sjmcneill }
2288c7bec30Sjmcneill
2296726462dSjmcneill sc->sc_dev = self;
2306e54367aSthorpej sc->sc_type = of_compatible_lookup(phandle, compat_data)->value;
2315403e5e5Sjmcneill sc->sc_syscon = fdtbus_syscon_lookup(OF_parent(phandle));
2325403e5e5Sjmcneill if (sc->sc_syscon == NULL) {
2335403e5e5Sjmcneill aprint_error(": couldn't get grf syscon\n");
2346726462dSjmcneill return;
2356726462dSjmcneill }
2366726462dSjmcneill
2376726462dSjmcneill const char *clkname = fdtbus_get_string(phandle, "clock-output-names");
2386726462dSjmcneill if (clkname == NULL)
2396726462dSjmcneill clkname = faa->faa_name;
2406726462dSjmcneill
2416726462dSjmcneill sc->sc_clkdom.name = device_xname(self);
2426726462dSjmcneill sc->sc_clkdom.funcs = &rk_usb_clk_funcs;
2436726462dSjmcneill sc->sc_clkdom.priv = sc;
2446726462dSjmcneill sc->sc_usbclk.base.domain = &sc->sc_clkdom;
2456726462dSjmcneill sc->sc_usbclk.base.name = kmem_asprintf("%s", clkname);
2466726462dSjmcneill clk_attach(&sc->sc_usbclk.base);
2476726462dSjmcneill
2486726462dSjmcneill aprint_naive("\n");
2496726462dSjmcneill aprint_normal(": USB2 PHY\n");
2506726462dSjmcneill
2516726462dSjmcneill fdtbus_register_clock_controller(self, phandle, &rk_usb_fdt_funcs);
2526726462dSjmcneill
2536726462dSjmcneill for (child = OF_child(phandle); child; child = OF_peer(child)) {
2546726462dSjmcneill if (!fdtbus_status_okay(child))
2556726462dSjmcneill continue;
2566726462dSjmcneill
2576726462dSjmcneill struct fdt_attach_args cfaa = *faa;
2586726462dSjmcneill cfaa.faa_phandle = child;
2596726462dSjmcneill cfaa.faa_name = fdtbus_get_string(child, "name");
2606726462dSjmcneill cfaa.faa_quiet = false;
2616726462dSjmcneill
262*c7fb772bSthorpej config_found(self, &cfaa, NULL, CFARGS_NONE);
2636726462dSjmcneill }
2646726462dSjmcneill }
2656726462dSjmcneill
2666726462dSjmcneill /*
2676726462dSjmcneill * USB PHY
2686726462dSjmcneill */
2696726462dSjmcneill
2706726462dSjmcneill static int rk_usbphy_match(device_t, cfdata_t, void *);
2716726462dSjmcneill static void rk_usbphy_attach(device_t, device_t, void *);
2726726462dSjmcneill
2736726462dSjmcneill struct rk_usbphy_softc {
2746726462dSjmcneill device_t sc_dev;
2756726462dSjmcneill int sc_phandle;
2768c7bec30Sjmcneill struct fdtbus_regulator *sc_supply;
2776726462dSjmcneill };
2786726462dSjmcneill
2796726462dSjmcneill CFATTACH_DECL_NEW(rk_usbphy, sizeof(struct rk_usbphy_softc),
2806726462dSjmcneill rk_usbphy_match, rk_usbphy_attach, NULL, NULL);
2816726462dSjmcneill
2826726462dSjmcneill static void *
rk_usbphy_acquire(device_t dev,const void * data,size_t len)2836726462dSjmcneill rk_usbphy_acquire(device_t dev, const void *data, size_t len)
2846726462dSjmcneill {
2856726462dSjmcneill struct rk_usbphy_softc * const sc = device_private(dev);
2866726462dSjmcneill
2876726462dSjmcneill if (len != 0)
2886726462dSjmcneill return NULL;
2896726462dSjmcneill
2906726462dSjmcneill return sc;
2916726462dSjmcneill }
2926726462dSjmcneill
2936726462dSjmcneill static void
rk_usbphy_release(device_t dev,void * priv)2946726462dSjmcneill rk_usbphy_release(device_t dev, void *priv)
2956726462dSjmcneill {
2966726462dSjmcneill }
2976726462dSjmcneill
2986726462dSjmcneill static int
rk_usbphy_otg_enable(device_t dev,void * priv,bool enable)2996726462dSjmcneill rk_usbphy_otg_enable(device_t dev, void *priv, bool enable)
3006726462dSjmcneill {
3018c7bec30Sjmcneill struct rk_usbphy_softc * const sc = device_private(dev);
3026726462dSjmcneill struct rk_usb_softc * const usb_sc = device_private(device_parent(dev));
3038c7bec30Sjmcneill uint32_t reg, write_mask, write_val;
3048c7bec30Sjmcneill int error;
3056726462dSjmcneill
3068c7bec30Sjmcneill switch (usb_sc->sc_type) {
3078c7bec30Sjmcneill case USB_RK3328:
3088c7bec30Sjmcneill reg = RK3328_CON0_REG;
3098c7bec30Sjmcneill write_mask = 0x1ffU << 16;
3108c7bec30Sjmcneill write_val = enable ? 0 : 0x1d1;
3118c7bec30Sjmcneill break;
3128c7bec30Sjmcneill case USB_RK3399:
3138c7bec30Sjmcneill reg = RK3399_PHY_NO(usb_sc) == 0 ?
3148c7bec30Sjmcneill RK3399_GRF_USB20_PHY0_CON1_REG :
3158c7bec30Sjmcneill RK3399_GRF_USB20_PHY1_CON1_REG;
3168c7bec30Sjmcneill write_mask = (RK3399_USBPHY_SUSPEND_N|RK3399_USBPHY_UTMI_SEL) << 16;
3175923de4eSjmcneill write_val = enable ? 0 : RK3399_USBPHY_UTMI_SEL;
3188c7bec30Sjmcneill break;
3198c7bec30Sjmcneill default:
3208c7bec30Sjmcneill return ENXIO;
3218c7bec30Sjmcneill }
3228c7bec30Sjmcneill
3238c7bec30Sjmcneill if (sc->sc_supply) {
3248c7bec30Sjmcneill error = enable ? fdtbus_regulator_enable(sc->sc_supply) :
3258c7bec30Sjmcneill fdtbus_regulator_disable(sc->sc_supply);
3268c7bec30Sjmcneill if (error != 0)
3278c7bec30Sjmcneill return error;
3288c7bec30Sjmcneill }
3295403e5e5Sjmcneill
3305403e5e5Sjmcneill syscon_lock(usb_sc->sc_syscon);
3318c7bec30Sjmcneill syscon_write_4(usb_sc->sc_syscon, reg, write_mask | write_val);
3325403e5e5Sjmcneill syscon_unlock(usb_sc->sc_syscon);
3336726462dSjmcneill
3346726462dSjmcneill return 0;
3356726462dSjmcneill }
3366726462dSjmcneill
3376726462dSjmcneill static int
rk_usbphy_host_enable(device_t dev,void * priv,bool enable)3386726462dSjmcneill rk_usbphy_host_enable(device_t dev, void *priv, bool enable)
3396726462dSjmcneill {
3408c7bec30Sjmcneill struct rk_usbphy_softc * const sc = device_private(dev);
3416726462dSjmcneill struct rk_usb_softc * const usb_sc = device_private(device_parent(dev));
3428c7bec30Sjmcneill uint32_t reg, write_mask, write_val;
3438c7bec30Sjmcneill int error;
3446726462dSjmcneill
3458c7bec30Sjmcneill switch (usb_sc->sc_type) {
3468c7bec30Sjmcneill case USB_RK3328:
3478c7bec30Sjmcneill reg = RK3328_CON1_REG;
3488c7bec30Sjmcneill write_mask = 0x1ffU << 16;
3498c7bec30Sjmcneill write_val = enable ? 0 : 0x1d1;
3508c7bec30Sjmcneill break;
3518c7bec30Sjmcneill case USB_RK3399:
3528c7bec30Sjmcneill reg = RK3399_PHY_NO(usb_sc) == 0 ?
3538c7bec30Sjmcneill RK3399_GRF_USB20_PHY0_CON2_REG :
3548c7bec30Sjmcneill RK3399_GRF_USB20_PHY1_CON2_REG;
3558c7bec30Sjmcneill write_mask = (RK3399_USBPHY_SUSPEND_N|RK3399_USBPHY_UTMI_SEL) << 16;
3565923de4eSjmcneill write_val = enable ? 0 : RK3399_USBPHY_UTMI_SEL;
3578c7bec30Sjmcneill break;
3588c7bec30Sjmcneill default:
3598c7bec30Sjmcneill return ENXIO;
3608c7bec30Sjmcneill }
3618c7bec30Sjmcneill
3628c7bec30Sjmcneill if (sc->sc_supply) {
3638c7bec30Sjmcneill error = enable ? fdtbus_regulator_enable(sc->sc_supply) :
3648c7bec30Sjmcneill fdtbus_regulator_disable(sc->sc_supply);
3658c7bec30Sjmcneill if (error != 0)
3668c7bec30Sjmcneill return error;
3678c7bec30Sjmcneill }
3685403e5e5Sjmcneill
3695403e5e5Sjmcneill syscon_lock(usb_sc->sc_syscon);
3708c7bec30Sjmcneill syscon_write_4(usb_sc->sc_syscon, reg, write_mask | write_val);
3715403e5e5Sjmcneill syscon_unlock(usb_sc->sc_syscon);
3726726462dSjmcneill
3736726462dSjmcneill return 0;
3746726462dSjmcneill }
3756726462dSjmcneill
3766726462dSjmcneill const struct fdtbus_phy_controller_func rk_usbphy_otg_funcs = {
3776726462dSjmcneill .acquire = rk_usbphy_acquire,
3786726462dSjmcneill .release = rk_usbphy_release,
3796726462dSjmcneill .enable = rk_usbphy_otg_enable,
3806726462dSjmcneill };
3816726462dSjmcneill
3826726462dSjmcneill const struct fdtbus_phy_controller_func rk_usbphy_host_funcs = {
3836726462dSjmcneill .acquire = rk_usbphy_acquire,
3846726462dSjmcneill .release = rk_usbphy_release,
3856726462dSjmcneill .enable = rk_usbphy_host_enable,
3866726462dSjmcneill };
3876726462dSjmcneill
3886726462dSjmcneill static int
rk_usbphy_match(device_t parent,cfdata_t cf,void * aux)3896726462dSjmcneill rk_usbphy_match(device_t parent, cfdata_t cf, void *aux)
3906726462dSjmcneill {
3916726462dSjmcneill struct fdt_attach_args * const faa = aux;
3926726462dSjmcneill const int phandle = faa->faa_phandle;
3936726462dSjmcneill const char *name = fdtbus_get_string(phandle, "name");
3946726462dSjmcneill
3956726462dSjmcneill if (strcmp(name, "otg-port") == 0 || strcmp(name, "host-port") == 0)
3966726462dSjmcneill return 1;
3976726462dSjmcneill
3986726462dSjmcneill return 0;
3996726462dSjmcneill }
4006726462dSjmcneill
4016726462dSjmcneill static void
rk_usbphy_attach(device_t parent,device_t self,void * aux)4026726462dSjmcneill rk_usbphy_attach(device_t parent, device_t self, void *aux)
4036726462dSjmcneill {
4046726462dSjmcneill struct rk_usbphy_softc * const sc = device_private(self);
4056726462dSjmcneill struct fdt_attach_args * const faa = aux;
4066726462dSjmcneill const int phandle = faa->faa_phandle;
4076726462dSjmcneill const char *name = fdtbus_get_string(phandle, "name");
4086726462dSjmcneill
4096726462dSjmcneill sc->sc_dev = self;
4106726462dSjmcneill sc->sc_phandle = phandle;
4118c7bec30Sjmcneill if (of_hasprop(phandle, "phy-supply")) {
4128c7bec30Sjmcneill sc->sc_supply = fdtbus_regulator_acquire(phandle, "phy-supply");
4138c7bec30Sjmcneill if (sc->sc_supply == NULL) {
4148c7bec30Sjmcneill aprint_error(": couldn't acquire regulator\n");
4158c7bec30Sjmcneill return;
4168c7bec30Sjmcneill }
4178c7bec30Sjmcneill }
4186726462dSjmcneill
4196726462dSjmcneill aprint_naive("\n");
4206726462dSjmcneill
4216726462dSjmcneill if (strcmp(name, "otg-port") == 0) {
4226726462dSjmcneill aprint_normal(": USB2 OTG port\n");
4236726462dSjmcneill fdtbus_register_phy_controller(self, phandle, &rk_usbphy_otg_funcs);
4246726462dSjmcneill } else if (strcmp(name, "host-port") == 0) {
4256726462dSjmcneill aprint_normal(": USB2 host port\n");
4266726462dSjmcneill fdtbus_register_phy_controller(self, phandle, &rk_usbphy_host_funcs);
4276726462dSjmcneill }
4286726462dSjmcneill }
429