xref: /netbsd-src/sys/arch/arm/rockchip/rk_usb.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
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