xref: /freebsd/sys/arm64/rockchip/rk_typec_phy.c (revision 315ee00f)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.Org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 /*
29  * Rockchip PHY TYPEC
30  */
31 
32 #include <sys/cdefs.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/rman.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/gpio.h>
40 #include <machine/bus.h>
41 
42 #include <dev/fdt/fdt_common.h>
43 #include <dev/ofw/ofw_bus.h>
44 #include <dev/ofw/ofw_bus_subr.h>
45 #include <dev/ofw/ofw_subr.h>
46 
47 #include <dev/extres/clk/clk.h>
48 #include <dev/extres/phy/phy_usb.h>
49 #include <dev/extres/syscon/syscon.h>
50 #include <dev/extres/hwreset/hwreset.h>
51 
52 #include "syscon_if.h"
53 
54 #define	GRF_USB3OTG_BASE(x)	(0x2430 + (0x10 * x))
55 #define	GRF_USB3OTG_CON0(x)	(GRF_USB3OTG_BASE(x) + 0x0)
56 #define	GRF_USB3OTG_CON1(x)	(GRF_USB3OTG_BASE(x) + 0x4)
57 #define	 USB3OTG_CON1_U3_DIS	(1 << 0)
58 
59 #define	GRF_USB3PHY_BASE(x)	(0x0e580 + (0xc * (x)))
60 #define	GRF_USB3PHY_CON0(x)	(GRF_USB3PHY_BASE(x) + 0x0)
61 #define	 USB3PHY_CON0_USB2_ONLY	(1 << 3)
62 #define	GRF_USB3PHY_CON1(x)	(GRF_USB3PHY_BASE(x) + 0x4)
63 #define	GRF_USB3PHY_CON2(x)	(GRF_USB3PHY_BASE(x) + 0x8)
64 #define	GRF_USB3PHY_STATUS0	0x0e5c0
65 #define	GRF_USB3PHY_STATUS1	0x0e5c4
66 
67 #define	CMN_PLL0_VCOCAL_INIT		(0x84 << 2)
68 #define	CMN_PLL0_VCOCAL_ITER		(0x85 << 2)
69 #define	CMN_PLL0_INTDIV			(0x94 << 2)
70 #define	CMN_PLL0_FRACDIV		(0x95 << 2)
71 #define	CMN_PLL0_HIGH_THR		(0x96 << 2)
72 #define	CMN_PLL0_DSM_DIAG		(0x97 << 2)
73 #define	CMN_PLL0_SS_CTRL1		(0x98 << 2)
74 #define	CMN_PLL0_SS_CTRL2		(0x99 << 2)
75 #define	CMN_DIAG_PLL0_FBH_OVRD		(0x1c0 << 2)
76 #define	CMN_DIAG_PLL0_FBL_OVRD		(0x1c1 << 2)
77 #define	CMN_DIAG_PLL0_OVRD		(0x1c2 << 2)
78 #define	CMN_DIAG_PLL0_V2I_TUNE		(0x1c5 << 2)
79 #define	CMN_DIAG_PLL0_CP_TUNE		(0x1c6 << 2)
80 #define	CMN_DIAG_PLL0_LF_PROG		(0x1c7 << 2)
81 #define	CMN_DIAG_HSCLK_SEL		(0x1e0 << 2)
82 #define	 CMN_DIAG_HSCLK_SEL_PLL_CONFIG	0x30
83 #define	 CMN_DIAG_HSCLK_SEL_PLL_MASK	0x33
84 
85 #define	TX_TXCC_MGNFS_MULT_000(lane)	((0x4050 | ((lane) << 9)) << 2)
86 #define	XCVR_DIAG_BIDI_CTRL(lane)	((0x40e8 | ((lane) << 9)) << 2)
87 #define	XCVR_DIAG_LANE_FCM_EN_MGN(lane)	((0x40f2 | ((lane) << 9)) << 2)
88 #define	TX_PSC_A0(lane)			((0x4100 | ((lane) << 9)) << 2)
89 #define	TX_PSC_A1(lane)			((0x4101 | ((lane) << 9)) << 2)
90 #define	TX_PSC_A2(lane)			((0x4102 | ((lane) << 9)) << 2)
91 #define	TX_PSC_A3(lane)			((0x4103 | ((lane) << 9)) << 2)
92 #define	TX_RCVDET_EN_TMR(lane)		((0x4122 | ((lane) << 9)) << 2)
93 #define	TX_RCVDET_ST_TMR(lane)		((0x4123 | ((lane) << 9)) << 2)
94 
95 #define	RX_PSC_A0(lane)			((0x8000 | ((lane) << 9)) << 2)
96 #define	RX_PSC_A1(lane)			((0x8001 | ((lane) << 9)) << 2)
97 #define	RX_PSC_A2(lane)			((0x8002 | ((lane) << 9)) << 2)
98 #define	RX_PSC_A3(lane)			((0x8003 | ((lane) << 9)) << 2)
99 #define	RX_PSC_CAL(lane)		((0x8006 | ((lane) << 9)) << 2)
100 #define	RX_PSC_RDY(lane)		((0x8007 | ((lane) << 9)) << 2)
101 #define	RX_SIGDET_HL_FILT_TMR(lane)	((0x8090 | ((lane) << 9)) << 2)
102 #define	RX_REE_CTRL_DATA_MASK(lane)	((0x81bb | ((lane) << 9)) << 2)
103 #define	RX_DIAG_SIGDET_TUNE(lane)	((0x81dc | ((lane) << 9)) << 2)
104 
105 #define	PMA_LANE_CFG			(0xc000 << 2)
106 #define	PIN_ASSIGN_D_F			0x5100
107 #define	DP_MODE_CTL			(0xc008 << 2)
108 #define	DP_MODE_ENTER_A2		0xc104
109 #define	PMA_CMN_CTRL1			(0xc800 << 2)
110 #define	 PMA_CMN_CTRL1_READY		(1 << 0)
111 
112 static struct ofw_compat_data compat_data[] = {
113 	{ "rockchip,rk3399-typec-phy",	1 },
114 	{ NULL,				0 }
115 };
116 
117 static struct resource_spec rk_typec_phy_spec[] = {
118 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
119 	{ -1, 0 }
120 };
121 
122 struct rk_typec_phy_softc {
123 	device_t		dev;
124 	struct resource		*res;
125 	struct syscon		*grf;
126 	clk_t			tcpdcore;
127 	clk_t			tcpdphy_ref;
128 	hwreset_t		rst_uphy;
129 	hwreset_t		rst_pipe;
130 	hwreset_t		rst_tcphy;
131 	int			mode;
132 	int			phy_ctrl_id;
133 };
134 
135 #define	RK_TYPEC_PHY_READ(sc, reg)		bus_read_4(sc->res, (reg))
136 #define	RK_TYPEC_PHY_WRITE(sc, reg, val)	bus_write_4(sc->res, (reg), (val))
137 
138 /* Phy class and methods. */
139 static int rk_typec_phy_enable(struct phynode *phynode, bool enable);
140 static int rk_typec_phy_get_mode(struct phynode *phy, int *mode);
141 static int rk_typec_phy_set_mode(struct phynode *phy, int mode);
142 static phynode_method_t rk_typec_phy_phynode_methods[] = {
143 	PHYNODEMETHOD(phynode_enable,		rk_typec_phy_enable),
144 	PHYNODEMETHOD(phynode_usb_get_mode,	rk_typec_phy_get_mode),
145 	PHYNODEMETHOD(phynode_usb_set_mode,	rk_typec_phy_set_mode),
146 
147 	PHYNODEMETHOD_END
148 };
149 
150 DEFINE_CLASS_1(rk_typec_phy_phynode, rk_typec_phy_phynode_class,
151     rk_typec_phy_phynode_methods,
152     sizeof(struct phynode_usb_sc), phynode_usb_class);
153 
154 enum RK3399_USBPHY {
155 	RK3399_TYPEC_PHY_DP = 0,
156 	RK3399_TYPEC_PHY_USB3,
157 };
158 
159 static void
160 rk_typec_phy_set_usb2_only(struct rk_typec_phy_softc *sc, bool usb2only)
161 {
162 	uint32_t reg;
163 
164 	/* Disable usb3tousb2 only */
165 	reg = SYSCON_READ_4(sc->grf, GRF_USB3PHY_CON0(sc->phy_ctrl_id));
166 	if (usb2only)
167 		reg |= USB3PHY_CON0_USB2_ONLY;
168 	else
169 		reg &= ~USB3PHY_CON0_USB2_ONLY;
170 	/* Write Mask */
171 	reg |= (USB3PHY_CON0_USB2_ONLY) << 16;
172 	SYSCON_WRITE_4(sc->grf, GRF_USB3PHY_CON0(sc->phy_ctrl_id), reg);
173 
174 	/* Enable the USB3 Super Speed port */
175 	reg = SYSCON_READ_4(sc->grf, GRF_USB3OTG_CON1(sc->phy_ctrl_id));
176 	if (usb2only)
177 		reg |= USB3OTG_CON1_U3_DIS;
178 	else
179 		reg &= ~USB3OTG_CON1_U3_DIS;
180 	/* Write Mask */
181 	reg |= (USB3OTG_CON1_U3_DIS) << 16;
182 	SYSCON_WRITE_4(sc->grf, GRF_USB3OTG_CON1(sc->phy_ctrl_id), reg);
183 }
184 
185 static int
186 rk_typec_phy_enable(struct phynode *phynode, bool enable)
187 {
188 	struct rk_typec_phy_softc *sc;
189 	device_t dev;
190 	intptr_t phy;
191 	uint32_t reg;
192 	int err, retry;
193 
194 	dev = phynode_get_device(phynode);
195 	phy = phynode_get_id(phynode);
196 	sc = device_get_softc(dev);
197 
198 	if (phy != RK3399_TYPEC_PHY_USB3)
199 		return (ERANGE);
200 
201 	rk_typec_phy_set_usb2_only(sc, false);
202 
203 	err = clk_enable(sc->tcpdcore);
204 	if (err != 0) {
205 		device_printf(dev, "Could not enable clock %s\n",
206 		    clk_get_name(sc->tcpdcore));
207 		return (ENXIO);
208 	}
209 	err = clk_enable(sc->tcpdphy_ref);
210 	if (err != 0) {
211 		device_printf(dev, "Could not enable clock %s\n",
212 		    clk_get_name(sc->tcpdphy_ref));
213 		clk_disable(sc->tcpdcore);
214 		return (ENXIO);
215 	}
216 
217 	hwreset_deassert(sc->rst_tcphy);
218 
219 	/* 24M configuration, magic values from rockchip */
220 	RK_TYPEC_PHY_WRITE(sc, PMA_CMN_CTRL1, 0x830);
221 	for (int i = 0; i < 4; i++) {
222 		RK_TYPEC_PHY_WRITE(sc, XCVR_DIAG_LANE_FCM_EN_MGN(i), 0x90);
223 		RK_TYPEC_PHY_WRITE(sc, TX_RCVDET_EN_TMR(i), 0x960);
224 		RK_TYPEC_PHY_WRITE(sc, TX_RCVDET_ST_TMR(i), 0x30);
225 	}
226 	reg = RK_TYPEC_PHY_READ(sc, CMN_DIAG_HSCLK_SEL);
227 	reg &= ~CMN_DIAG_HSCLK_SEL_PLL_MASK;
228 	reg |= CMN_DIAG_HSCLK_SEL_PLL_CONFIG;
229 	RK_TYPEC_PHY_WRITE(sc, CMN_DIAG_HSCLK_SEL, reg);
230 
231 	/* PLL configuration, magic values from rockchip */
232 	RK_TYPEC_PHY_WRITE(sc, CMN_PLL0_VCOCAL_INIT, 0xf0);
233 	RK_TYPEC_PHY_WRITE(sc, CMN_PLL0_VCOCAL_ITER, 0x18);
234 	RK_TYPEC_PHY_WRITE(sc, CMN_PLL0_INTDIV, 0xd0);
235 	RK_TYPEC_PHY_WRITE(sc, CMN_PLL0_FRACDIV, 0x4a4a);
236 	RK_TYPEC_PHY_WRITE(sc, CMN_PLL0_HIGH_THR, 0x34);
237 	RK_TYPEC_PHY_WRITE(sc, CMN_PLL0_SS_CTRL1, 0x1ee);
238 	RK_TYPEC_PHY_WRITE(sc, CMN_PLL0_SS_CTRL2, 0x7f03);
239 	RK_TYPEC_PHY_WRITE(sc, CMN_PLL0_DSM_DIAG, 0x20);
240 	RK_TYPEC_PHY_WRITE(sc, CMN_DIAG_PLL0_OVRD, 0);
241 	RK_TYPEC_PHY_WRITE(sc, CMN_DIAG_PLL0_FBH_OVRD, 0);
242 	RK_TYPEC_PHY_WRITE(sc, CMN_DIAG_PLL0_FBL_OVRD, 0);
243 	RK_TYPEC_PHY_WRITE(sc, CMN_DIAG_PLL0_V2I_TUNE, 0x7);
244 	RK_TYPEC_PHY_WRITE(sc, CMN_DIAG_PLL0_CP_TUNE, 0x45);
245 	RK_TYPEC_PHY_WRITE(sc, CMN_DIAG_PLL0_LF_PROG, 0x8);
246 
247 	/* Configure the TX and RX line, magic values from rockchip */
248 	RK_TYPEC_PHY_WRITE(sc, TX_PSC_A0(0), 0x7799);
249 	RK_TYPEC_PHY_WRITE(sc, TX_PSC_A1(0), 0x7798);
250 	RK_TYPEC_PHY_WRITE(sc, TX_PSC_A2(0), 0x5098);
251 	RK_TYPEC_PHY_WRITE(sc, TX_PSC_A3(0), 0x5098);
252 	RK_TYPEC_PHY_WRITE(sc, TX_TXCC_MGNFS_MULT_000(0), 0x0);
253 	RK_TYPEC_PHY_WRITE(sc, XCVR_DIAG_BIDI_CTRL(0), 0xbf);
254 
255 	RK_TYPEC_PHY_WRITE(sc, RX_PSC_A0(1), 0xa6fd);
256 	RK_TYPEC_PHY_WRITE(sc, RX_PSC_A1(1), 0xa6fd);
257 	RK_TYPEC_PHY_WRITE(sc, RX_PSC_A2(1), 0xa410);
258 	RK_TYPEC_PHY_WRITE(sc, RX_PSC_A3(1), 0x2410);
259 	RK_TYPEC_PHY_WRITE(sc, RX_PSC_CAL(1), 0x23ff);
260 	RK_TYPEC_PHY_WRITE(sc, RX_SIGDET_HL_FILT_TMR(1), 0x13);
261 	RK_TYPEC_PHY_WRITE(sc, RX_REE_CTRL_DATA_MASK(1), 0x03e7);
262 	RK_TYPEC_PHY_WRITE(sc, RX_DIAG_SIGDET_TUNE(1), 0x1004);
263 	RK_TYPEC_PHY_WRITE(sc, RX_PSC_RDY(1), 0x2010);
264 	RK_TYPEC_PHY_WRITE(sc, XCVR_DIAG_BIDI_CTRL(1), 0xfb);
265 
266 	RK_TYPEC_PHY_WRITE(sc, PMA_LANE_CFG, PIN_ASSIGN_D_F);
267 
268 	RK_TYPEC_PHY_WRITE(sc, DP_MODE_CTL, DP_MODE_ENTER_A2);
269 
270 	hwreset_deassert(sc->rst_uphy);
271 
272 	for (retry = 10000; retry > 0; retry--) {
273 		reg = RK_TYPEC_PHY_READ(sc, PMA_CMN_CTRL1);
274 		if (reg & PMA_CMN_CTRL1_READY)
275 			break;
276 		DELAY(10);
277 	}
278 	if (retry == 0) {
279 		device_printf(sc->dev, "Timeout waiting for PMA\n");
280 		return (ENXIO);
281 	}
282 
283 	hwreset_deassert(sc->rst_pipe);
284 
285 	return (0);
286 }
287 
288 static int
289 rk_typec_phy_get_mode(struct phynode *phynode, int *mode)
290 {
291 	struct rk_typec_phy_softc *sc;
292 	intptr_t phy;
293 	device_t dev;
294 
295 	dev = phynode_get_device(phynode);
296 	phy = phynode_get_id(phynode);
297 	sc = device_get_softc(dev);
298 
299 	if (phy != RK3399_TYPEC_PHY_USB3)
300 		return (ERANGE);
301 
302 	*mode = sc->mode;
303 
304 	return (0);
305 }
306 
307 static int
308 rk_typec_phy_set_mode(struct phynode *phynode, int mode)
309 {
310 	struct rk_typec_phy_softc *sc;
311 	intptr_t phy;
312 	device_t dev;
313 
314 	dev = phynode_get_device(phynode);
315 	phy = phynode_get_id(phynode);
316 	sc = device_get_softc(dev);
317 
318 	if (phy != RK3399_TYPEC_PHY_USB3)
319 		return (ERANGE);
320 
321 	sc->mode = mode;
322 
323 	return (0);
324 }
325 
326 static int
327 rk_typec_phy_probe(device_t dev)
328 {
329 
330 	if (!ofw_bus_status_okay(dev))
331 		return (ENXIO);
332 
333 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
334 		return (ENXIO);
335 
336 	device_set_desc(dev, "Rockchip RK3399 PHY TYPEC");
337 	return (BUS_PROBE_DEFAULT);
338 }
339 
340 static int
341 rk_typec_phy_attach(device_t dev)
342 {
343 	struct rk_typec_phy_softc *sc;
344 	struct phynode_init_def phy_init;
345 	struct phynode *phynode;
346 	phandle_t node, usb3;
347 	phandle_t reg_prop[4];
348 
349 	sc = device_get_softc(dev);
350 	sc->dev = dev;
351 	node = ofw_bus_get_node(dev);
352 
353 	/*
354 	 * Find out which phy we are.
355 	 * There is not property for this so we need to know the
356 	 * address to use the correct GRF registers.
357 	 */
358 	if (OF_getencprop(node, "reg", reg_prop, sizeof(reg_prop)) <= 0) {
359 		device_printf(dev, "Cannot guess phy controller id\n");
360 		return (ENXIO);
361 	}
362 	switch (reg_prop[1]) {
363 	case 0xff7c0000:
364 		sc->phy_ctrl_id = 0;
365 		break;
366 	case 0xff800000:
367 		sc->phy_ctrl_id = 1;
368 		break;
369 	default:
370 		device_printf(dev, "Unknown address %x for typec-phy\n", reg_prop[1]);
371 		return (ENXIO);
372 	}
373 
374 	if (bus_alloc_resources(dev, rk_typec_phy_spec, &sc->res) != 0) {
375 		device_printf(dev, "cannot allocate resources for device\n");
376 		goto fail;
377 	}
378 
379 	if (syscon_get_by_ofw_property(dev, node,
380 	    "rockchip,grf", &sc->grf) != 0) {
381 		device_printf(dev, "Cannot get syscon handle\n");
382 		goto fail;
383 	}
384 
385 	if (clk_get_by_ofw_name(dev, 0, "tcpdcore", &sc->tcpdcore) != 0) {
386 		device_printf(dev, "Cannot get tcpdcore clock\n");
387 		goto fail;
388 	}
389 	if (clk_get_by_ofw_name(dev, 0, "tcpdphy-ref", &sc->tcpdphy_ref) != 0) {
390 		device_printf(dev, "Cannot get tcpdphy-ref clock\n");
391 		goto fail;
392 	}
393 
394 	if (hwreset_get_by_ofw_name(dev, 0, "uphy", &sc->rst_uphy) != 0) {
395 		device_printf(dev, "Cannot get uphy reset\n");
396 		goto fail;
397 	}
398 	if (hwreset_get_by_ofw_name(dev, 0, "uphy-pipe", &sc->rst_pipe) != 0) {
399 		device_printf(dev, "Cannot get uphy-pipe reset\n");
400 		goto fail;
401 	}
402 	if (hwreset_get_by_ofw_name(dev, 0, "uphy-tcphy", &sc->rst_tcphy) != 0) {
403 		device_printf(dev, "Cannot get uphy-tcphy reset\n");
404 		goto fail;
405 	}
406 
407 	/*
408 	 * Make sure that the module is asserted
409 	 * We need to deassert in a certain order when we enable the phy
410 	 */
411 	hwreset_assert(sc->rst_uphy);
412 	hwreset_assert(sc->rst_pipe);
413 	hwreset_assert(sc->rst_tcphy);
414 
415 	/* Set the assigned clocks parent and freq */
416 	if (clk_set_assigned(dev, node) != 0) {
417 		device_printf(dev, "clk_set_assigned failed\n");
418 		goto fail;
419 	}
420 
421 	/* Only usb3 port is supported right now */
422 	usb3 = ofw_bus_find_child(node, "usb3-port");
423 	if (usb3 == 0) {
424 		device_printf(dev, "Cannot find usb3-port child node\n");
425 		goto fail;
426 	}
427 	/* If the child isn't enable attach the driver
428 	 *  but do not register the PHY.
429 	 */
430 	if (!ofw_bus_node_status_okay(usb3))
431 		return (0);
432 
433 	phy_init.id = RK3399_TYPEC_PHY_USB3;
434 	phy_init.ofw_node = usb3;
435 	phynode = phynode_create(dev, &rk_typec_phy_phynode_class, &phy_init);
436 	if (phynode == NULL) {
437 		device_printf(dev, "failed to create phy usb3-port\n");
438 		goto fail;
439 	}
440 	if (phynode_register(phynode) == NULL) {
441 		device_printf(dev, "failed to register phy usb3-port\n");
442 		goto fail;
443 	}
444 
445 	OF_device_register_xref(OF_xref_from_node(usb3), dev);
446 
447 	return (0);
448 
449 fail:
450 	bus_release_resources(dev, rk_typec_phy_spec, &sc->res);
451 
452 	return (ENXIO);
453 }
454 
455 static device_method_t rk_typec_phy_methods[] = {
456 	/* Device interface */
457 	DEVMETHOD(device_probe,		rk_typec_phy_probe),
458 	DEVMETHOD(device_attach,	rk_typec_phy_attach),
459 
460 	DEVMETHOD_END
461 };
462 
463 static driver_t rk_typec_phy_driver = {
464 	"rk_typec_phy",
465 	rk_typec_phy_methods,
466 	sizeof(struct rk_typec_phy_softc)
467 };
468 
469 EARLY_DRIVER_MODULE(rk_typec_phy, simplebus, rk_typec_phy_driver, 0, 0,
470     BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
471 MODULE_VERSION(rk_typec_phy, 1);
472