xref: /freebsd/sys/arm64/rockchip/rk_usb2phy.c (revision c3e25952b2ad73a07b841812ba2b9446972766c8)
1*c3e25952SEmmanuel Vadot /*-
2*c3e25952SEmmanuel Vadot  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*c3e25952SEmmanuel Vadot  *
4*c3e25952SEmmanuel Vadot  * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.Org>
5*c3e25952SEmmanuel Vadot  *
6*c3e25952SEmmanuel Vadot  * Redistribution and use in source and binary forms, with or without
7*c3e25952SEmmanuel Vadot  * modification, are permitted provided that the following conditions
8*c3e25952SEmmanuel Vadot  * are met:
9*c3e25952SEmmanuel Vadot  * 1. Redistributions of source code must retain the above copyright
10*c3e25952SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer.
11*c3e25952SEmmanuel Vadot  * 2. Redistributions in binary form must reproduce the above copyright
12*c3e25952SEmmanuel Vadot  *    notice, this list of conditions and the following disclaimer in the
13*c3e25952SEmmanuel Vadot  *    documentation and/or other materials provided with the distribution.
14*c3e25952SEmmanuel Vadot  *
15*c3e25952SEmmanuel Vadot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*c3e25952SEmmanuel Vadot  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*c3e25952SEmmanuel Vadot  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*c3e25952SEmmanuel Vadot  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*c3e25952SEmmanuel Vadot  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*c3e25952SEmmanuel Vadot  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*c3e25952SEmmanuel Vadot  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*c3e25952SEmmanuel Vadot  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*c3e25952SEmmanuel Vadot  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*c3e25952SEmmanuel Vadot  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*c3e25952SEmmanuel Vadot  * SUCH DAMAGE.
26*c3e25952SEmmanuel Vadot  */
27*c3e25952SEmmanuel Vadot 
28*c3e25952SEmmanuel Vadot /*
29*c3e25952SEmmanuel Vadot  * Rockchip USB2PHY
30*c3e25952SEmmanuel Vadot  */
31*c3e25952SEmmanuel Vadot 
32*c3e25952SEmmanuel Vadot #include <sys/cdefs.h>
33*c3e25952SEmmanuel Vadot __FBSDID("$FreeBSD$");
34*c3e25952SEmmanuel Vadot 
35*c3e25952SEmmanuel Vadot #include <sys/param.h>
36*c3e25952SEmmanuel Vadot #include <sys/systm.h>
37*c3e25952SEmmanuel Vadot #include <sys/bus.h>
38*c3e25952SEmmanuel Vadot #include <sys/rman.h>
39*c3e25952SEmmanuel Vadot #include <sys/kernel.h>
40*c3e25952SEmmanuel Vadot #include <sys/module.h>
41*c3e25952SEmmanuel Vadot #include <sys/gpio.h>
42*c3e25952SEmmanuel Vadot #include <machine/bus.h>
43*c3e25952SEmmanuel Vadot 
44*c3e25952SEmmanuel Vadot #include <dev/fdt/fdt_common.h>
45*c3e25952SEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
46*c3e25952SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
47*c3e25952SEmmanuel Vadot #include <dev/ofw/ofw_subr.h>
48*c3e25952SEmmanuel Vadot 
49*c3e25952SEmmanuel Vadot #include <dev/extres/clk/clk.h>
50*c3e25952SEmmanuel Vadot #include <dev/extres/phy/phy_usb.h>
51*c3e25952SEmmanuel Vadot #include <dev/extres/regulator/regulator.h>
52*c3e25952SEmmanuel Vadot #include <dev/extres/syscon/syscon.h>
53*c3e25952SEmmanuel Vadot 
54*c3e25952SEmmanuel Vadot #include "clkdev_if.h"
55*c3e25952SEmmanuel Vadot #include "syscon_if.h"
56*c3e25952SEmmanuel Vadot 
57*c3e25952SEmmanuel Vadot #define	RK3399_GRF_USB20_PHY0_CON0	0x0
58*c3e25952SEmmanuel Vadot #define	RK3399_GRF_USB20_PHY0_CON1	0x4
59*c3e25952SEmmanuel Vadot #define	RK3399_GRF_USB20_PHY0_CON2	0x8
60*c3e25952SEmmanuel Vadot #define	RK3399_GRF_USB20_PHY0_CON3	0xC
61*c3e25952SEmmanuel Vadot 
62*c3e25952SEmmanuel Vadot struct rk_usb2phy_reg {
63*c3e25952SEmmanuel Vadot 	uint32_t	offset;
64*c3e25952SEmmanuel Vadot 	uint32_t	enable_mask;
65*c3e25952SEmmanuel Vadot 	uint32_t	disable_mask;
66*c3e25952SEmmanuel Vadot };
67*c3e25952SEmmanuel Vadot 
68*c3e25952SEmmanuel Vadot struct rk_usb2phy_regs {
69*c3e25952SEmmanuel Vadot 	struct rk_usb2phy_reg	clk_ctl;
70*c3e25952SEmmanuel Vadot };
71*c3e25952SEmmanuel Vadot 
72*c3e25952SEmmanuel Vadot struct rk_usb2phy_regs rk3399_regs = {
73*c3e25952SEmmanuel Vadot 	.clk_ctl = {
74*c3e25952SEmmanuel Vadot 		/* bit 4 put pll in suspend */
75*c3e25952SEmmanuel Vadot 		.enable_mask = 0x100000,
76*c3e25952SEmmanuel Vadot 		.disable_mask = 0x100010,
77*c3e25952SEmmanuel Vadot 	}
78*c3e25952SEmmanuel Vadot };
79*c3e25952SEmmanuel Vadot 
80*c3e25952SEmmanuel Vadot static struct ofw_compat_data compat_data[] = {
81*c3e25952SEmmanuel Vadot 	{ "rockchip,rk3399-usb2phy",	(uintptr_t)&rk3399_regs },
82*c3e25952SEmmanuel Vadot 	{ NULL,				0 }
83*c3e25952SEmmanuel Vadot };
84*c3e25952SEmmanuel Vadot 
85*c3e25952SEmmanuel Vadot struct rk_usb2phy_softc {
86*c3e25952SEmmanuel Vadot 	device_t		dev;
87*c3e25952SEmmanuel Vadot 	struct syscon		*grf;
88*c3e25952SEmmanuel Vadot 	regulator_t		phy_supply;
89*c3e25952SEmmanuel Vadot 	clk_t			clk;
90*c3e25952SEmmanuel Vadot };
91*c3e25952SEmmanuel Vadot 
92*c3e25952SEmmanuel Vadot /* Phy class and methods. */
93*c3e25952SEmmanuel Vadot static int rk_usb2phy_enable(struct phynode *phynode, bool enable);
94*c3e25952SEmmanuel Vadot static phynode_method_t rk_usb2phy_phynode_methods[] = {
95*c3e25952SEmmanuel Vadot 	PHYNODEMETHOD(phynode_enable,	rk_usb2phy_enable),
96*c3e25952SEmmanuel Vadot 
97*c3e25952SEmmanuel Vadot 	PHYNODEMETHOD_END
98*c3e25952SEmmanuel Vadot };
99*c3e25952SEmmanuel Vadot 
100*c3e25952SEmmanuel Vadot DEFINE_CLASS_1(rk_usb2phy_phynode, rk_usb2phy_phynode_class,
101*c3e25952SEmmanuel Vadot     rk_usb2phy_phynode_methods,
102*c3e25952SEmmanuel Vadot     sizeof(struct phynode_usb_sc), phynode_usb_class);
103*c3e25952SEmmanuel Vadot 
104*c3e25952SEmmanuel Vadot enum RK3399_USBPHY {
105*c3e25952SEmmanuel Vadot 	RK3399_USBPHY_HOST = 0,
106*c3e25952SEmmanuel Vadot 	RK3399_USBPHY_OTG,
107*c3e25952SEmmanuel Vadot };
108*c3e25952SEmmanuel Vadot 
109*c3e25952SEmmanuel Vadot static int
110*c3e25952SEmmanuel Vadot rk_usb2phy_enable(struct phynode *phynode, bool enable)
111*c3e25952SEmmanuel Vadot {
112*c3e25952SEmmanuel Vadot 	struct rk_usb2phy_softc *sc;
113*c3e25952SEmmanuel Vadot 	device_t dev;
114*c3e25952SEmmanuel Vadot 	intptr_t phy;
115*c3e25952SEmmanuel Vadot 	int error;
116*c3e25952SEmmanuel Vadot 
117*c3e25952SEmmanuel Vadot 	dev = phynode_get_device(phynode);
118*c3e25952SEmmanuel Vadot 	phy = phynode_get_id(phynode);
119*c3e25952SEmmanuel Vadot 	sc = device_get_softc(dev);
120*c3e25952SEmmanuel Vadot 
121*c3e25952SEmmanuel Vadot 	if (phy != RK3399_USBPHY_HOST)
122*c3e25952SEmmanuel Vadot 		return (ERANGE);
123*c3e25952SEmmanuel Vadot 
124*c3e25952SEmmanuel Vadot 	if (sc->phy_supply) {
125*c3e25952SEmmanuel Vadot 		if (enable)
126*c3e25952SEmmanuel Vadot 			error = regulator_enable(sc->phy_supply);
127*c3e25952SEmmanuel Vadot 		else
128*c3e25952SEmmanuel Vadot 			error = regulator_disable(sc->phy_supply);
129*c3e25952SEmmanuel Vadot 		if (error != 0) {
130*c3e25952SEmmanuel Vadot 			device_printf(dev, "Cannot %sable the regulator\n",
131*c3e25952SEmmanuel Vadot 			    enable ? "En" : "Dis");
132*c3e25952SEmmanuel Vadot 			goto fail;
133*c3e25952SEmmanuel Vadot 		}
134*c3e25952SEmmanuel Vadot 	}
135*c3e25952SEmmanuel Vadot 
136*c3e25952SEmmanuel Vadot 	return (0);
137*c3e25952SEmmanuel Vadot fail:
138*c3e25952SEmmanuel Vadot 	return (ENXIO);
139*c3e25952SEmmanuel Vadot }
140*c3e25952SEmmanuel Vadot 
141*c3e25952SEmmanuel Vadot /* Clock class and method */
142*c3e25952SEmmanuel Vadot struct rk_usb2phy_clk_sc {
143*c3e25952SEmmanuel Vadot 	device_t	clkdev;
144*c3e25952SEmmanuel Vadot 	struct syscon	*grf;
145*c3e25952SEmmanuel Vadot 	struct rk_usb2phy_regs	*regs;
146*c3e25952SEmmanuel Vadot };
147*c3e25952SEmmanuel Vadot 
148*c3e25952SEmmanuel Vadot static int
149*c3e25952SEmmanuel Vadot rk_usb2phy_clk_init(struct clknode *clk, device_t dev)
150*c3e25952SEmmanuel Vadot {
151*c3e25952SEmmanuel Vadot 
152*c3e25952SEmmanuel Vadot 	clknode_init_parent_idx(clk, 0);
153*c3e25952SEmmanuel Vadot 	return (0);
154*c3e25952SEmmanuel Vadot }
155*c3e25952SEmmanuel Vadot 
156*c3e25952SEmmanuel Vadot static int
157*c3e25952SEmmanuel Vadot rk_usb2phy_clk_set_gate(struct clknode *clk, bool enable)
158*c3e25952SEmmanuel Vadot {
159*c3e25952SEmmanuel Vadot 	struct rk_usb2phy_clk_sc *sc;
160*c3e25952SEmmanuel Vadot 
161*c3e25952SEmmanuel Vadot 	sc = clknode_get_softc(clk);
162*c3e25952SEmmanuel Vadot 
163*c3e25952SEmmanuel Vadot 	if (enable)
164*c3e25952SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf, sc->regs->clk_ctl.offset,
165*c3e25952SEmmanuel Vadot 		    sc->regs->clk_ctl.enable_mask);
166*c3e25952SEmmanuel Vadot 	else
167*c3e25952SEmmanuel Vadot 		SYSCON_WRITE_4(sc->grf, sc->regs->clk_ctl.offset,
168*c3e25952SEmmanuel Vadot 		    sc->regs->clk_ctl.disable_mask);
169*c3e25952SEmmanuel Vadot 	return (0);
170*c3e25952SEmmanuel Vadot }
171*c3e25952SEmmanuel Vadot 
172*c3e25952SEmmanuel Vadot static int
173*c3e25952SEmmanuel Vadot rk_usb2phy_clk_recalc(struct clknode *clk, uint64_t *freq)
174*c3e25952SEmmanuel Vadot {
175*c3e25952SEmmanuel Vadot 
176*c3e25952SEmmanuel Vadot 	*freq = 480000000;
177*c3e25952SEmmanuel Vadot 
178*c3e25952SEmmanuel Vadot 	return (0);
179*c3e25952SEmmanuel Vadot }
180*c3e25952SEmmanuel Vadot 
181*c3e25952SEmmanuel Vadot static clknode_method_t rk_usb2phy_clk_clknode_methods[] = {
182*c3e25952SEmmanuel Vadot 	/* Device interface */
183*c3e25952SEmmanuel Vadot 
184*c3e25952SEmmanuel Vadot 	CLKNODEMETHOD(clknode_init,		rk_usb2phy_clk_init),
185*c3e25952SEmmanuel Vadot 	CLKNODEMETHOD(clknode_set_gate,		rk_usb2phy_clk_set_gate),
186*c3e25952SEmmanuel Vadot 	CLKNODEMETHOD(clknode_recalc_freq,	rk_usb2phy_clk_recalc),
187*c3e25952SEmmanuel Vadot 	CLKNODEMETHOD_END
188*c3e25952SEmmanuel Vadot };
189*c3e25952SEmmanuel Vadot 
190*c3e25952SEmmanuel Vadot DEFINE_CLASS_1(rk_usb2phy_clk_clknode, rk_usb2phy_clk_clknode_class,
191*c3e25952SEmmanuel Vadot     rk_usb2phy_clk_clknode_methods, sizeof(struct rk_usb2phy_clk_sc),
192*c3e25952SEmmanuel Vadot     clknode_class);
193*c3e25952SEmmanuel Vadot 
194*c3e25952SEmmanuel Vadot static int
195*c3e25952SEmmanuel Vadot rk_usb2phy_clk_ofw_map(struct clkdom *clkdom, uint32_t ncells,
196*c3e25952SEmmanuel Vadot     phandle_t *cells, struct clknode **clk)
197*c3e25952SEmmanuel Vadot {
198*c3e25952SEmmanuel Vadot 
199*c3e25952SEmmanuel Vadot 	if (ncells != 0)
200*c3e25952SEmmanuel Vadot 		return (ERANGE);
201*c3e25952SEmmanuel Vadot 
202*c3e25952SEmmanuel Vadot 	*clk = clknode_find_by_id(clkdom, 0);
203*c3e25952SEmmanuel Vadot 
204*c3e25952SEmmanuel Vadot 	if (*clk == NULL)
205*c3e25952SEmmanuel Vadot 		return (ENXIO);
206*c3e25952SEmmanuel Vadot 	return (0);
207*c3e25952SEmmanuel Vadot }
208*c3e25952SEmmanuel Vadot 
209*c3e25952SEmmanuel Vadot static int
210*c3e25952SEmmanuel Vadot rk_usb2phy_export_clock(struct rk_usb2phy_softc *devsc)
211*c3e25952SEmmanuel Vadot {
212*c3e25952SEmmanuel Vadot 	struct clknode_init_def def;
213*c3e25952SEmmanuel Vadot 	struct rk_usb2phy_clk_sc *sc;
214*c3e25952SEmmanuel Vadot 	const char **clknames;
215*c3e25952SEmmanuel Vadot 	struct clkdom *clkdom;
216*c3e25952SEmmanuel Vadot 	struct clknode *clk;
217*c3e25952SEmmanuel Vadot 	clk_t clk_parent;
218*c3e25952SEmmanuel Vadot 	phandle_t node;
219*c3e25952SEmmanuel Vadot 	phandle_t regs[2];
220*c3e25952SEmmanuel Vadot 	int i, nclocks, ncells, error;
221*c3e25952SEmmanuel Vadot 
222*c3e25952SEmmanuel Vadot 	node = ofw_bus_get_node(devsc->dev);
223*c3e25952SEmmanuel Vadot 
224*c3e25952SEmmanuel Vadot 	error = ofw_bus_parse_xref_list_get_length(node, "clocks",
225*c3e25952SEmmanuel Vadot 	    "#clock-cells", &ncells);
226*c3e25952SEmmanuel Vadot 	if (error != 0 || ncells != 1) {
227*c3e25952SEmmanuel Vadot 		device_printf(devsc->dev, "couldn't find parent clock\n");
228*c3e25952SEmmanuel Vadot 		return (ENXIO);
229*c3e25952SEmmanuel Vadot 	}
230*c3e25952SEmmanuel Vadot 
231*c3e25952SEmmanuel Vadot 	nclocks = ofw_bus_string_list_to_array(node, "clock-output-names",
232*c3e25952SEmmanuel Vadot 	    &clknames);
233*c3e25952SEmmanuel Vadot 	if (nclocks != 1)
234*c3e25952SEmmanuel Vadot 		return (ENXIO);
235*c3e25952SEmmanuel Vadot 
236*c3e25952SEmmanuel Vadot 	clkdom = clkdom_create(devsc->dev);
237*c3e25952SEmmanuel Vadot 	clkdom_set_ofw_mapper(clkdom, rk_usb2phy_clk_ofw_map);
238*c3e25952SEmmanuel Vadot 
239*c3e25952SEmmanuel Vadot 	memset(&def, 0, sizeof(def));
240*c3e25952SEmmanuel Vadot 	def.id = 0;
241*c3e25952SEmmanuel Vadot 	def.name = clknames[0];
242*c3e25952SEmmanuel Vadot 	def.parent_names = malloc(sizeof(char *) * ncells, M_OFWPROP, M_WAITOK);
243*c3e25952SEmmanuel Vadot 	for (i = 0; i < ncells; i++) {
244*c3e25952SEmmanuel Vadot 		error = clk_get_by_ofw_index(devsc->dev, 0, i, &clk_parent);
245*c3e25952SEmmanuel Vadot 		if (error != 0) {
246*c3e25952SEmmanuel Vadot 			device_printf(devsc->dev, "cannot get clock %d\n", error);
247*c3e25952SEmmanuel Vadot 			return (ENXIO);
248*c3e25952SEmmanuel Vadot 		}
249*c3e25952SEmmanuel Vadot 		def.parent_names[i] = clk_get_name(clk_parent);
250*c3e25952SEmmanuel Vadot 		clk_release(clk_parent);
251*c3e25952SEmmanuel Vadot 	}
252*c3e25952SEmmanuel Vadot 	def.parent_cnt = ncells;
253*c3e25952SEmmanuel Vadot 
254*c3e25952SEmmanuel Vadot 	clk = clknode_create(clkdom, &rk_usb2phy_clk_clknode_class, &def);
255*c3e25952SEmmanuel Vadot 	if (clk == NULL) {
256*c3e25952SEmmanuel Vadot 		device_printf(devsc->dev, "cannot create clknode\n");
257*c3e25952SEmmanuel Vadot 		return (ENXIO);
258*c3e25952SEmmanuel Vadot 	}
259*c3e25952SEmmanuel Vadot 
260*c3e25952SEmmanuel Vadot 	sc = clknode_get_softc(clk);
261*c3e25952SEmmanuel Vadot 	sc->clkdev = device_get_parent(devsc->dev);
262*c3e25952SEmmanuel Vadot 	sc->grf = devsc->grf;
263*c3e25952SEmmanuel Vadot 	sc->regs = (struct rk_usb2phy_regs *)ofw_bus_search_compatible(devsc->dev, compat_data)->ocd_data;
264*c3e25952SEmmanuel Vadot 	OF_getencprop(node, "reg", regs, sizeof(regs));
265*c3e25952SEmmanuel Vadot 	sc->regs->clk_ctl.offset = regs[0];
266*c3e25952SEmmanuel Vadot 	clknode_register(clkdom, clk);
267*c3e25952SEmmanuel Vadot 
268*c3e25952SEmmanuel Vadot 	if (clkdom_finit(clkdom) != 0) {
269*c3e25952SEmmanuel Vadot 		device_printf(devsc->dev, "cannot finalize clkdom initialization\n");
270*c3e25952SEmmanuel Vadot 		return (ENXIO);
271*c3e25952SEmmanuel Vadot 	}
272*c3e25952SEmmanuel Vadot 
273*c3e25952SEmmanuel Vadot 	if (bootverbose)
274*c3e25952SEmmanuel Vadot 		clkdom_dump(clkdom);
275*c3e25952SEmmanuel Vadot 
276*c3e25952SEmmanuel Vadot 	return (0);
277*c3e25952SEmmanuel Vadot }
278*c3e25952SEmmanuel Vadot 
279*c3e25952SEmmanuel Vadot static int
280*c3e25952SEmmanuel Vadot rk_usb2phy_probe(device_t dev)
281*c3e25952SEmmanuel Vadot {
282*c3e25952SEmmanuel Vadot 
283*c3e25952SEmmanuel Vadot 	if (!ofw_bus_status_okay(dev))
284*c3e25952SEmmanuel Vadot 		return (ENXIO);
285*c3e25952SEmmanuel Vadot 
286*c3e25952SEmmanuel Vadot 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
287*c3e25952SEmmanuel Vadot 		return (ENXIO);
288*c3e25952SEmmanuel Vadot 
289*c3e25952SEmmanuel Vadot 	device_set_desc(dev, "Rockchip RK3399 USB2PHY");
290*c3e25952SEmmanuel Vadot 	return (BUS_PROBE_DEFAULT);
291*c3e25952SEmmanuel Vadot }
292*c3e25952SEmmanuel Vadot 
293*c3e25952SEmmanuel Vadot static int
294*c3e25952SEmmanuel Vadot rk_usb2phy_attach(device_t dev)
295*c3e25952SEmmanuel Vadot {
296*c3e25952SEmmanuel Vadot 	struct rk_usb2phy_softc *sc;
297*c3e25952SEmmanuel Vadot 	struct phynode_init_def phy_init;
298*c3e25952SEmmanuel Vadot 	struct phynode *phynode;
299*c3e25952SEmmanuel Vadot 	phandle_t node, host;
300*c3e25952SEmmanuel Vadot 	int err;
301*c3e25952SEmmanuel Vadot 
302*c3e25952SEmmanuel Vadot 	sc = device_get_softc(dev);
303*c3e25952SEmmanuel Vadot 	sc->dev = dev;
304*c3e25952SEmmanuel Vadot 	node = ofw_bus_get_node(dev);
305*c3e25952SEmmanuel Vadot 
306*c3e25952SEmmanuel Vadot 	if (syscon_get_handle_default(dev, &sc->grf) != 0) {
307*c3e25952SEmmanuel Vadot 		device_printf(dev, "Cannot get syscon handle\n");
308*c3e25952SEmmanuel Vadot 		return (ENXIO);
309*c3e25952SEmmanuel Vadot 	}
310*c3e25952SEmmanuel Vadot 
311*c3e25952SEmmanuel Vadot 	if (clk_get_by_ofw_name(dev, 0, "phyclk", &sc->clk) != 0) {
312*c3e25952SEmmanuel Vadot 		device_printf(dev, "Cannot get clock\n");
313*c3e25952SEmmanuel Vadot 		return (ENXIO);
314*c3e25952SEmmanuel Vadot 	}
315*c3e25952SEmmanuel Vadot 	err = clk_enable(sc->clk);
316*c3e25952SEmmanuel Vadot 	if (err != 0) {
317*c3e25952SEmmanuel Vadot 		device_printf(dev, "Could not enable clock %s\n",
318*c3e25952SEmmanuel Vadot 		    clk_get_name(sc->clk));
319*c3e25952SEmmanuel Vadot 		return (ENXIO);
320*c3e25952SEmmanuel Vadot 	}
321*c3e25952SEmmanuel Vadot 
322*c3e25952SEmmanuel Vadot 	err = rk_usb2phy_export_clock(sc);
323*c3e25952SEmmanuel Vadot 	if (err != 0)
324*c3e25952SEmmanuel Vadot 		return (err);
325*c3e25952SEmmanuel Vadot 
326*c3e25952SEmmanuel Vadot 	/* Only host is supported right now */
327*c3e25952SEmmanuel Vadot 
328*c3e25952SEmmanuel Vadot 	host = ofw_bus_find_child(node, "host-port");
329*c3e25952SEmmanuel Vadot 	if (host == 0) {
330*c3e25952SEmmanuel Vadot 		device_printf(dev, "Cannot find host-port child node\n");
331*c3e25952SEmmanuel Vadot 		return (ENXIO);
332*c3e25952SEmmanuel Vadot 	}
333*c3e25952SEmmanuel Vadot 
334*c3e25952SEmmanuel Vadot 	if (!ofw_bus_node_status_okay(host)) {
335*c3e25952SEmmanuel Vadot 		device_printf(dev, "host-port isn't okay\n");
336*c3e25952SEmmanuel Vadot 		return (0);
337*c3e25952SEmmanuel Vadot 	}
338*c3e25952SEmmanuel Vadot 
339*c3e25952SEmmanuel Vadot 	regulator_get_by_ofw_property(dev, host, "phy-supply", &sc->phy_supply);
340*c3e25952SEmmanuel Vadot 	phy_init.id = RK3399_USBPHY_HOST;
341*c3e25952SEmmanuel Vadot 	phy_init.ofw_node = host;
342*c3e25952SEmmanuel Vadot 	phynode = phynode_create(dev, &rk_usb2phy_phynode_class, &phy_init);
343*c3e25952SEmmanuel Vadot 	if (phynode == NULL) {
344*c3e25952SEmmanuel Vadot 		device_printf(dev, "failed to create host USB2PHY\n");
345*c3e25952SEmmanuel Vadot 		return (ENXIO);
346*c3e25952SEmmanuel Vadot 	}
347*c3e25952SEmmanuel Vadot 	if (phynode_register(phynode) == NULL) {
348*c3e25952SEmmanuel Vadot 		device_printf(dev, "failed to register host USB2PHY\n");
349*c3e25952SEmmanuel Vadot 		return (ENXIO);
350*c3e25952SEmmanuel Vadot 	}
351*c3e25952SEmmanuel Vadot 
352*c3e25952SEmmanuel Vadot 	OF_device_register_xref(OF_xref_from_node(host), dev);
353*c3e25952SEmmanuel Vadot 
354*c3e25952SEmmanuel Vadot 	return (0);
355*c3e25952SEmmanuel Vadot }
356*c3e25952SEmmanuel Vadot 
357*c3e25952SEmmanuel Vadot static device_method_t rk_usb2phy_methods[] = {
358*c3e25952SEmmanuel Vadot 	/* Device interface */
359*c3e25952SEmmanuel Vadot 	DEVMETHOD(device_probe,		rk_usb2phy_probe),
360*c3e25952SEmmanuel Vadot 	DEVMETHOD(device_attach,	rk_usb2phy_attach),
361*c3e25952SEmmanuel Vadot 
362*c3e25952SEmmanuel Vadot 	DEVMETHOD_END
363*c3e25952SEmmanuel Vadot };
364*c3e25952SEmmanuel Vadot 
365*c3e25952SEmmanuel Vadot static driver_t rk_usb2phy_driver = {
366*c3e25952SEmmanuel Vadot 	"rk_usb2phy",
367*c3e25952SEmmanuel Vadot 	rk_usb2phy_methods,
368*c3e25952SEmmanuel Vadot 	sizeof(struct rk_usb2phy_softc)
369*c3e25952SEmmanuel Vadot };
370*c3e25952SEmmanuel Vadot 
371*c3e25952SEmmanuel Vadot static devclass_t rk_usb2phy_devclass;
372*c3e25952SEmmanuel Vadot EARLY_DRIVER_MODULE(rk_usb2phy, simplebus, rk_usb2phy_driver,
373*c3e25952SEmmanuel Vadot     rk_usb2phy_devclass, 0, 0, BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
374*c3e25952SEmmanuel Vadot MODULE_VERSION(rk_usb2phy, 1);
375