xref: /openbsd/sys/dev/fdt/rkusbphy.c (revision b3b04c1d)
1*b3b04c1dSkettenis /*	$OpenBSD: rkusbphy.c,v 1.6 2024/11/24 22:46:54 kettenis Exp $ */
2302cd816Sdlg 
3302cd816Sdlg /*
4302cd816Sdlg  * Copyright (c) 2023 David Gwynne <dlg@openbsd.org>
5302cd816Sdlg  *
6302cd816Sdlg  * Permission to use, copy, modify, and distribute this software for any
7302cd816Sdlg  * purpose with or without fee is hereby granted, provided that the above
8302cd816Sdlg  * copyright notice and this permission notice appear in all copies.
9302cd816Sdlg  *
10302cd816Sdlg  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11302cd816Sdlg  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12302cd816Sdlg  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13302cd816Sdlg  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14302cd816Sdlg  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15302cd816Sdlg  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16302cd816Sdlg  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17302cd816Sdlg  */
18302cd816Sdlg 
19302cd816Sdlg /*
20302cd816Sdlg  * Rockchip USB2PHY with Innosilicon IP
21302cd816Sdlg  */
22302cd816Sdlg 
23302cd816Sdlg #include <sys/param.h>
24302cd816Sdlg #include <sys/systm.h>
25302cd816Sdlg #include <sys/device.h>
26302cd816Sdlg 
27302cd816Sdlg #include <machine/intr.h>
28302cd816Sdlg #include <machine/bus.h>
29302cd816Sdlg #include <machine/fdt.h>
30302cd816Sdlg 
31302cd816Sdlg #include <dev/ofw/openfirm.h>
32302cd816Sdlg #include <dev/ofw/ofw_clock.h>
33302cd816Sdlg #include <dev/ofw/ofw_regulator.h>
34302cd816Sdlg #include <dev/ofw/ofw_misc.h>
35302cd816Sdlg #include <dev/ofw/fdt.h>
36302cd816Sdlg 
37302cd816Sdlg /*
38302cd816Sdlg  * chip stuff
39302cd816Sdlg  */
40302cd816Sdlg 
41302cd816Sdlg struct rkusbphy_reg {
42302cd816Sdlg 	bus_size_t			r_offs;
435b0e3269Sdlg 	unsigned int			r_shift;
445b0e3269Sdlg 	uint32_t			r_mask;
455b0e3269Sdlg 	uint32_t			r_set;
46302cd816Sdlg };
47302cd816Sdlg 
48302cd816Sdlg struct rkusbphy_port_regs {
495b0e3269Sdlg 	struct rkusbphy_reg		phy_enable;
505b0e3269Sdlg };
515b0e3269Sdlg 
525b0e3269Sdlg struct rkusbphy_regs {
535b0e3269Sdlg 	struct rkusbphy_reg		clk_enable;
545b0e3269Sdlg 
555b0e3269Sdlg 	struct rkusbphy_port_regs	otg;
565b0e3269Sdlg 	struct rkusbphy_port_regs	host;
57302cd816Sdlg };
58302cd816Sdlg 
59302cd816Sdlg struct rkusbphy_chip {
60302cd816Sdlg 	bus_addr_t			 c_base_addr;
615b0e3269Sdlg 	const struct rkusbphy_regs	*c_regs;
625b0e3269Sdlg };
635b0e3269Sdlg 
645b0e3269Sdlg /*
65*b3b04c1dSkettenis  * RK3399 has two USB2PHY nodes that share a GRF.
66*b3b04c1dSkettenis  */
67*b3b04c1dSkettenis 
68*b3b04c1dSkettenis static const struct rkusbphy_regs rkusbphy_rk3399_usb0_regs = {
69*b3b04c1dSkettenis 	/*				shift,	mask,	set */
70*b3b04c1dSkettenis 	.clk_enable =	{ 0xe450,	4,	0x1,	0x0 },
71*b3b04c1dSkettenis 
72*b3b04c1dSkettenis 	.otg = {
73*b3b04c1dSkettenis 		.phy_enable =	{ 0xe454,	0,	0x3,	0x2 },
74*b3b04c1dSkettenis 	},
75*b3b04c1dSkettenis 
76*b3b04c1dSkettenis 	.host = {
77*b3b04c1dSkettenis 		.phy_enable =	{ 0xe458,	0,	0x3,	0x2 },
78*b3b04c1dSkettenis 	},
79*b3b04c1dSkettenis };
80*b3b04c1dSkettenis 
81*b3b04c1dSkettenis static const struct rkusbphy_regs rkusbphy_rk3399_usb1_regs = {
82*b3b04c1dSkettenis 	/*				shift,	mask,	set */
83*b3b04c1dSkettenis 	.clk_enable =	{ 0xe460,	4,	0x1,	0x0 },
84*b3b04c1dSkettenis 
85*b3b04c1dSkettenis 	.otg = {
86*b3b04c1dSkettenis 		.phy_enable =	{ 0xe464,	0,	0x3,	0x2 },
87*b3b04c1dSkettenis 	},
88*b3b04c1dSkettenis 
89*b3b04c1dSkettenis 	.host = {
90*b3b04c1dSkettenis 		.phy_enable =	{ 0xe468,	0,	0x3,	0x2 },
91*b3b04c1dSkettenis 	},
92*b3b04c1dSkettenis  };
93*b3b04c1dSkettenis 
94*b3b04c1dSkettenis static const struct rkusbphy_chip rkusbphy_rk3399[] = {
95*b3b04c1dSkettenis 	{
96*b3b04c1dSkettenis 		.c_base_addr = 0xe450,
97*b3b04c1dSkettenis 		.c_regs = &rkusbphy_rk3399_usb0_regs,
98*b3b04c1dSkettenis 	},
99*b3b04c1dSkettenis 	{
100*b3b04c1dSkettenis 		.c_base_addr = 0xe460,
101*b3b04c1dSkettenis 		.c_regs = &rkusbphy_rk3399_usb1_regs,
102*b3b04c1dSkettenis 	},
103*b3b04c1dSkettenis };
104*b3b04c1dSkettenis 
105*b3b04c1dSkettenis /*
1065b0e3269Sdlg  * RK3568 has two USB2PHY nodes that have a GRF each. Each GRF has
1075b0e3269Sdlg  * the same register layout.
1085b0e3269Sdlg  */
1095b0e3269Sdlg 
1105b0e3269Sdlg static const struct rkusbphy_regs rkusbphy_rk3568_regs = {
1115b0e3269Sdlg 	/*				shift,	mask,	set */
1125b0e3269Sdlg 	.clk_enable =	{ 0x0008,	4,	0x1,	0x0 },
1135b0e3269Sdlg 
1145b0e3269Sdlg 	.otg = {
1155b0e3269Sdlg 		.phy_enable =	{ 0x0000,	0,	0x1ff,	0x1d2 },
1165b0e3269Sdlg 	},
1175b0e3269Sdlg 
1185b0e3269Sdlg 	.host = {
1195b0e3269Sdlg 		.phy_enable =	{ 0x0004,	0,	0x1ff,	0x1d2 },
1205b0e3269Sdlg 	},
121302cd816Sdlg };
122302cd816Sdlg 
123302cd816Sdlg static const struct rkusbphy_chip rkusbphy_rk3568[] = {
124302cd816Sdlg 	{
125302cd816Sdlg 		.c_base_addr = 0xfe8a0000,
1265b0e3269Sdlg 		.c_regs = &rkusbphy_rk3568_regs,
127302cd816Sdlg 	},
128302cd816Sdlg 	{
129302cd816Sdlg 		.c_base_addr = 0xfe8b0000,
1305b0e3269Sdlg 		.c_regs = &rkusbphy_rk3568_regs,
131302cd816Sdlg 	},
132302cd816Sdlg };
133302cd816Sdlg 
134411d8e97Skettenis static const struct rkusbphy_regs rkusbphy_rk3588_regs = {
135411d8e97Skettenis 	/*				shift,	mask,	set */
136411d8e97Skettenis 	.clk_enable =	{ 0x0000,	0,	0x1,	0x0 },
137411d8e97Skettenis 
138411d8e97Skettenis 	.otg = {
139411d8e97Skettenis 		.phy_enable =	{ 0x000c,	11,	0x1,	0x0 },
140411d8e97Skettenis 	},
141411d8e97Skettenis 
142411d8e97Skettenis 	.host = {
143411d8e97Skettenis 		.phy_enable =	{ 0x0008,	2,	0x1,	0x0 },
144411d8e97Skettenis 	},
145411d8e97Skettenis };
146411d8e97Skettenis 
147411d8e97Skettenis static const struct rkusbphy_chip rkusbphy_rk3588[] = {
148411d8e97Skettenis 	{
149411d8e97Skettenis 		.c_base_addr = 0x0000,
150411d8e97Skettenis 		.c_regs = &rkusbphy_rk3588_regs,
151411d8e97Skettenis 	},
152411d8e97Skettenis 	{
153411d8e97Skettenis 		.c_base_addr = 0x4000,
154411d8e97Skettenis 		.c_regs = &rkusbphy_rk3588_regs,
155411d8e97Skettenis 	},
156411d8e97Skettenis 	{
157411d8e97Skettenis 		.c_base_addr = 0x8000,
158411d8e97Skettenis 		.c_regs = &rkusbphy_rk3588_regs,
159411d8e97Skettenis 	},
160411d8e97Skettenis 	{
161411d8e97Skettenis 		.c_base_addr = 0xc000,
162411d8e97Skettenis 		.c_regs = &rkusbphy_rk3588_regs,
163411d8e97Skettenis 	},
164411d8e97Skettenis };
165411d8e97Skettenis 
166302cd816Sdlg /*
167302cd816Sdlg  * driver stuff
168302cd816Sdlg  */
169302cd816Sdlg 
170302cd816Sdlg struct rkusbphy_softc {
171302cd816Sdlg 	struct device			 sc_dev;
1725b0e3269Sdlg 	const struct rkusbphy_regs	*sc_regs;
173302cd816Sdlg 	struct regmap			*sc_grf;
174302cd816Sdlg 	int				 sc_node;
175302cd816Sdlg 
1765b0e3269Sdlg 	int				 sc_running;
1775b0e3269Sdlg 
178302cd816Sdlg 	struct phy_device		 sc_otg_phy;
179302cd816Sdlg 	struct phy_device		 sc_host_phy;
180302cd816Sdlg };
181302cd816Sdlg #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
182302cd816Sdlg 
183302cd816Sdlg static int		rkusbphy_match(struct device *, void *, void *);
1845b0e3269Sdlg static void		rkusbphy_attach(struct device *, struct device *,
1855b0e3269Sdlg 			    void *);
1865b0e3269Sdlg 
1875b0e3269Sdlg static uint32_t		rkusbphy_rd(struct rkusbphy_softc *,
1885b0e3269Sdlg 			    const struct rkusbphy_reg *);
1895b0e3269Sdlg static int		rkusbphy_isset(struct rkusbphy_softc *,
1905b0e3269Sdlg 			    const struct rkusbphy_reg *);
1915b0e3269Sdlg static void		rkusbphy_wr(struct rkusbphy_softc *,
1925b0e3269Sdlg 			    const struct rkusbphy_reg *, uint32_t);
1935b0e3269Sdlg static void		rkusbphy_set(struct rkusbphy_softc *,
1945b0e3269Sdlg 			    const struct rkusbphy_reg *);
195302cd816Sdlg 
196302cd816Sdlg static int		rkusbphy_otg_phy_enable(void *, uint32_t *);
197302cd816Sdlg static int		rkusbphy_host_phy_enable(void *, uint32_t *);
198302cd816Sdlg 
199302cd816Sdlg struct rkusbphy_port_config {
200302cd816Sdlg 	const char			*pc_name;
201302cd816Sdlg 	int (*pc_enable)(void *, uint32_t *);
202302cd816Sdlg };
203302cd816Sdlg 
204302cd816Sdlg static void	rkusbphy_register(struct rkusbphy_softc *,
205302cd816Sdlg 		    struct phy_device *, const struct rkusbphy_port_config *);
206302cd816Sdlg 
207302cd816Sdlg static const struct rkusbphy_port_config rkusbphy_otg_config = {
208302cd816Sdlg 	.pc_name = "otg-port",
209302cd816Sdlg 	.pc_enable = rkusbphy_otg_phy_enable,
210302cd816Sdlg };
211302cd816Sdlg 
212302cd816Sdlg static const struct rkusbphy_port_config rkusbphy_host_config = {
213302cd816Sdlg 	.pc_name = "host-port",
214302cd816Sdlg 	.pc_enable = rkusbphy_host_phy_enable,
215302cd816Sdlg };
216302cd816Sdlg 
217302cd816Sdlg const struct cfattach rkusbphy_ca = {
218302cd816Sdlg 	sizeof (struct rkusbphy_softc), rkusbphy_match, rkusbphy_attach
219302cd816Sdlg };
220302cd816Sdlg 
221302cd816Sdlg struct cfdriver rkusbphy_cd = {
222302cd816Sdlg 	NULL, "rkusbphy", DV_DULL
223302cd816Sdlg };
224302cd816Sdlg 
225302cd816Sdlg struct rkusbphy_id {
226302cd816Sdlg 	const char			*id_name;
227302cd816Sdlg 	const struct rkusbphy_chip	*id_chips;
228302cd816Sdlg 	size_t				 id_nchips;
229302cd816Sdlg };
230302cd816Sdlg 
231302cd816Sdlg #define RKUSBPHY_ID(_n, _c) { _n, _c, nitems(_c) }
232302cd816Sdlg 
233302cd816Sdlg static const struct rkusbphy_id rkusbphy_ids[] = {
234*b3b04c1dSkettenis 	RKUSBPHY_ID("rockchip,rk3399-usb2phy", rkusbphy_rk3399),
235302cd816Sdlg 	RKUSBPHY_ID("rockchip,rk3568-usb2phy", rkusbphy_rk3568),
236411d8e97Skettenis 	RKUSBPHY_ID("rockchip,rk3588-usb2phy", rkusbphy_rk3588),
237302cd816Sdlg };
238302cd816Sdlg 
239302cd816Sdlg static const struct rkusbphy_id *
rkusbphy_lookup(struct fdt_attach_args * faa)240302cd816Sdlg rkusbphy_lookup(struct fdt_attach_args *faa)
241302cd816Sdlg {
242302cd816Sdlg 	size_t i;
243302cd816Sdlg 
244302cd816Sdlg 	for (i = 0; i < nitems(rkusbphy_ids); i++) {
245302cd816Sdlg 		const struct rkusbphy_id *id = &rkusbphy_ids[i];
246302cd816Sdlg 		if (OF_is_compatible(faa->fa_node, id->id_name))
247302cd816Sdlg 			return (id);
248302cd816Sdlg 	}
249302cd816Sdlg 
250302cd816Sdlg 	return (NULL);
251302cd816Sdlg }
252302cd816Sdlg 
253302cd816Sdlg static int
rkusbphy_match(struct device * parent,void * match,void * aux)254302cd816Sdlg rkusbphy_match(struct device *parent, void *match, void *aux)
255302cd816Sdlg {
256302cd816Sdlg 	struct fdt_attach_args *faa = aux;
257302cd816Sdlg 
258302cd816Sdlg 	return (rkusbphy_lookup(faa) != NULL ? 1 : 0);
259302cd816Sdlg }
260302cd816Sdlg 
261302cd816Sdlg static void
rkusbphy_attach(struct device * parent,struct device * self,void * aux)262302cd816Sdlg rkusbphy_attach(struct device *parent, struct device *self, void *aux)
263302cd816Sdlg {
264302cd816Sdlg 	struct rkusbphy_softc *sc = (struct rkusbphy_softc *)self;
265302cd816Sdlg 	struct fdt_attach_args *faa = aux;
266302cd816Sdlg 	const struct rkusbphy_id *id = rkusbphy_lookup(faa);
267302cd816Sdlg 	size_t i;
268302cd816Sdlg 	uint32_t grfph;
269302cd816Sdlg 
270302cd816Sdlg 	if (faa->fa_nreg < 1) {
271302cd816Sdlg 		printf(": no registers\n");
272302cd816Sdlg 		return;
273302cd816Sdlg 	}
274302cd816Sdlg 
275302cd816Sdlg 	for (i = 0; i < id->id_nchips; i++) {
276302cd816Sdlg 		const struct rkusbphy_chip *c = &id->id_chips[i];
277302cd816Sdlg 		if (faa->fa_reg[0].addr == c->c_base_addr) {
278302cd816Sdlg 			printf(": phy %zu\n", i);
2795b0e3269Sdlg 			sc->sc_regs = c->c_regs;
280302cd816Sdlg 			break;
281302cd816Sdlg 		}
282302cd816Sdlg 	}
2835b0e3269Sdlg 	if (sc->sc_regs == NULL) {
284302cd816Sdlg 		printf(": unknown base address 0x%llu\n", faa->fa_reg[0].addr);
285302cd816Sdlg 		return;
286302cd816Sdlg 	}
287302cd816Sdlg 
288302cd816Sdlg 	sc->sc_node = faa->fa_node;
289302cd816Sdlg 
290302cd816Sdlg 	grfph = OF_getpropint(sc->sc_node, "rockchip,usbgrf", 0);
291411d8e97Skettenis 	if (grfph)
292302cd816Sdlg 		sc->sc_grf = regmap_byphandle(grfph);
293411d8e97Skettenis 	else
294411d8e97Skettenis 		sc->sc_grf = regmap_bynode(OF_parent(faa->fa_node));
295302cd816Sdlg 	if (sc->sc_grf == NULL) {
296302cd816Sdlg 		printf("%s: rockchip,usbgrf 0x%x not found\n", DEVNAME(sc),
297302cd816Sdlg 		    grfph);
298302cd816Sdlg 		return;
299302cd816Sdlg 	}
300302cd816Sdlg 
301302cd816Sdlg 	rkusbphy_register(sc, &sc->sc_otg_phy, &rkusbphy_otg_config);
302302cd816Sdlg 	rkusbphy_register(sc, &sc->sc_host_phy, &rkusbphy_host_config);
303302cd816Sdlg }
304302cd816Sdlg 
3055b0e3269Sdlg static uint32_t
rkusbphy_rd(struct rkusbphy_softc * sc,const struct rkusbphy_reg * r)3065b0e3269Sdlg rkusbphy_rd(struct rkusbphy_softc *sc, const struct rkusbphy_reg *r)
3075b0e3269Sdlg {
3085b0e3269Sdlg 	uint32_t v;
3095b0e3269Sdlg 
3105b0e3269Sdlg 	if (r->r_mask == 0)
3115b0e3269Sdlg 		return (0);
3125b0e3269Sdlg 
3135b0e3269Sdlg 	v = regmap_read_4(sc->sc_grf, r->r_offs);
3145b0e3269Sdlg 
3155b0e3269Sdlg 	return ((v >> r->r_shift) & r->r_mask);
3165b0e3269Sdlg }
3175b0e3269Sdlg 
3185b0e3269Sdlg static int
rkusbphy_isset(struct rkusbphy_softc * sc,const struct rkusbphy_reg * r)3195b0e3269Sdlg rkusbphy_isset(struct rkusbphy_softc *sc, const struct rkusbphy_reg *r)
3205b0e3269Sdlg {
3215b0e3269Sdlg 	return (rkusbphy_rd(sc, r) == r->r_set);
3225b0e3269Sdlg }
3235b0e3269Sdlg 
3245b0e3269Sdlg static void
rkusbphy_wr(struct rkusbphy_softc * sc,const struct rkusbphy_reg * r,uint32_t v)3255b0e3269Sdlg rkusbphy_wr(struct rkusbphy_softc *sc, const struct rkusbphy_reg *r, uint32_t v)
3265b0e3269Sdlg {
3275b0e3269Sdlg 	if (r->r_mask == 0)
3285b0e3269Sdlg 		return;
3295b0e3269Sdlg 
3305b0e3269Sdlg 	regmap_write_4(sc->sc_grf, r->r_offs,
3315b0e3269Sdlg 	    (r->r_mask << (r->r_shift + 16)) | (v << r->r_shift));
3325b0e3269Sdlg }
3335b0e3269Sdlg 
3345b0e3269Sdlg static void
rkusbphy_set(struct rkusbphy_softc * sc,const struct rkusbphy_reg * r)3355b0e3269Sdlg rkusbphy_set(struct rkusbphy_softc *sc, const struct rkusbphy_reg *r)
3365b0e3269Sdlg {
3375b0e3269Sdlg 	rkusbphy_wr(sc, r, r->r_set);
3385b0e3269Sdlg }
3395b0e3269Sdlg 
340302cd816Sdlg static void
rkusbphy_register(struct rkusbphy_softc * sc,struct phy_device * pd,const struct rkusbphy_port_config * pc)341302cd816Sdlg rkusbphy_register(struct rkusbphy_softc *sc, struct phy_device *pd,
342302cd816Sdlg     const struct rkusbphy_port_config *pc)
343302cd816Sdlg {
344302cd816Sdlg 	char status[32];
345302cd816Sdlg 	int node;
346302cd816Sdlg 
347302cd816Sdlg 	node = OF_getnodebyname(sc->sc_node, pc->pc_name);
348411d8e97Skettenis 	if (node == 0)
349302cd816Sdlg 		return;
350302cd816Sdlg 
351302cd816Sdlg 	if (OF_getprop(node, "status", status, sizeof(status)) > 0 &&
352302cd816Sdlg 	    strcmp(status, "disabled") == 0)
353302cd816Sdlg 		return;
354302cd816Sdlg 
355302cd816Sdlg 	pd->pd_node = node;
356302cd816Sdlg 	pd->pd_cookie = sc;
357302cd816Sdlg 	pd->pd_enable = pc->pc_enable;
358302cd816Sdlg 	phy_register(pd);
359302cd816Sdlg }
360302cd816Sdlg 
361302cd816Sdlg static void
rkusbphy_phy_supply(struct rkusbphy_softc * sc,int node)362302cd816Sdlg rkusbphy_phy_supply(struct rkusbphy_softc *sc, int node)
363302cd816Sdlg {
364302cd816Sdlg 	int phandle;
365302cd816Sdlg 
3665b0e3269Sdlg 	if (!sc->sc_running) {
3675b0e3269Sdlg 		clock_enable(sc->sc_node, "phyclk");
3685b0e3269Sdlg 		if (!rkusbphy_isset(sc, &sc->sc_regs->clk_enable)) {
3695b0e3269Sdlg 			rkusbphy_set(sc, &sc->sc_regs->clk_enable);
3705b0e3269Sdlg 
3715b0e3269Sdlg 			delay(1200);
3725b0e3269Sdlg 		}
3735b0e3269Sdlg 
3745b0e3269Sdlg 		sc->sc_running = 1;
3755b0e3269Sdlg 	}
3765b0e3269Sdlg 
377302cd816Sdlg 	phandle = OF_getpropint(node, "phy-supply", 0);
378302cd816Sdlg 	if (phandle == 0)
379302cd816Sdlg 		return;
380302cd816Sdlg 
381302cd816Sdlg 	regulator_enable(phandle);
382302cd816Sdlg }
383302cd816Sdlg 
384302cd816Sdlg static int
rkusbphy_otg_phy_enable(void * cookie,uint32_t * cells)385302cd816Sdlg rkusbphy_otg_phy_enable(void *cookie, uint32_t *cells)
386302cd816Sdlg {
387302cd816Sdlg 	struct rkusbphy_softc *sc = cookie;
388302cd816Sdlg 
389302cd816Sdlg 	rkusbphy_phy_supply(sc, sc->sc_otg_phy.pd_node);
390302cd816Sdlg 
3915b0e3269Sdlg 	rkusbphy_set(sc, &sc->sc_regs->otg.phy_enable);
3925b0e3269Sdlg 	delay(1500);
3935b0e3269Sdlg 
394302cd816Sdlg 	return (EINVAL);
395302cd816Sdlg }
396302cd816Sdlg 
397302cd816Sdlg static int
rkusbphy_host_phy_enable(void * cookie,uint32_t * cells)398302cd816Sdlg rkusbphy_host_phy_enable(void *cookie, uint32_t *cells)
399302cd816Sdlg {
400302cd816Sdlg 	struct rkusbphy_softc *sc = cookie;
401302cd816Sdlg 
402302cd816Sdlg 	rkusbphy_phy_supply(sc, sc->sc_host_phy.pd_node);
403302cd816Sdlg 
4045b0e3269Sdlg 	rkusbphy_set(sc, &sc->sc_regs->host.phy_enable);
4055b0e3269Sdlg 	delay(1500);
4065b0e3269Sdlg 
407302cd816Sdlg 	return (EINVAL);
408302cd816Sdlg }
409