xref: /linux/drivers/phy/rockchip/phy-rockchip-inno-usb2.c (revision 2ace2e949979b82f82f12dd76d7c5a6145246ca3)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Rockchip USB2.0 PHY with Innosilicon IP block driver
4  *
5  * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
6  */
7 
8 #include <linux/clk.h>
9 #include <linux/clk-provider.h>
10 #include <linux/delay.h>
11 #include <linux/extcon-provider.h>
12 #include <linux/interrupt.h>
13 #include <linux/io.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/jiffies.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/mutex.h>
19 #include <linux/of.h>
20 #include <linux/of_irq.h>
21 #include <linux/phy/phy.h>
22 #include <linux/platform_device.h>
23 #include <linux/power_supply.h>
24 #include <linux/regmap.h>
25 #include <linux/reset.h>
26 #include <linux/mfd/syscon.h>
27 #include <linux/usb/of.h>
28 #include <linux/usb/otg.h>
29 
30 #define BIT_WRITEABLE_SHIFT	16
31 #define SCHEDULE_DELAY		(60 * HZ)
32 #define OTG_SCHEDULE_DELAY	(2 * HZ)
33 
34 struct rockchip_usb2phy;
35 
36 enum rockchip_usb2phy_port_id {
37 	USB2PHY_PORT_OTG,
38 	USB2PHY_PORT_HOST,
39 	USB2PHY_NUM_PORTS,
40 };
41 
42 enum rockchip_usb2phy_host_state {
43 	PHY_STATE_HS_ONLINE	= 0,
44 	PHY_STATE_DISCONNECT	= 1,
45 	PHY_STATE_CONNECT	= 2,
46 	PHY_STATE_FS_LS_ONLINE	= 4,
47 };
48 
49 /**
50  * enum usb_chg_state - Different states involved in USB charger detection.
51  * @USB_CHG_STATE_UNDEFINED:	USB charger is not connected or detection
52  *				process is not yet started.
53  * @USB_CHG_STATE_WAIT_FOR_DCD:	Waiting for Data pins contact.
54  * @USB_CHG_STATE_DCD_DONE:	Data pin contact is detected.
55  * @USB_CHG_STATE_PRIMARY_DONE:	Primary detection is completed (Detects
56  *				between SDP and DCP/CDP).
57  * @USB_CHG_STATE_SECONDARY_DONE: Secondary detection is completed (Detects
58  *				  between DCP and CDP).
59  * @USB_CHG_STATE_DETECTED:	USB charger type is determined.
60  */
61 enum usb_chg_state {
62 	USB_CHG_STATE_UNDEFINED = 0,
63 	USB_CHG_STATE_WAIT_FOR_DCD,
64 	USB_CHG_STATE_DCD_DONE,
65 	USB_CHG_STATE_PRIMARY_DONE,
66 	USB_CHG_STATE_SECONDARY_DONE,
67 	USB_CHG_STATE_DETECTED,
68 };
69 
70 static const unsigned int rockchip_usb2phy_extcon_cable[] = {
71 	EXTCON_USB,
72 	EXTCON_USB_HOST,
73 	EXTCON_CHG_USB_SDP,
74 	EXTCON_CHG_USB_CDP,
75 	EXTCON_CHG_USB_DCP,
76 	EXTCON_CHG_USB_SLOW,
77 	EXTCON_NONE,
78 };
79 
80 struct usb2phy_reg {
81 	unsigned int	offset;
82 	unsigned int	bitend;
83 	unsigned int	bitstart;
84 	unsigned int	disable;
85 	unsigned int	enable;
86 };
87 
88 /**
89  * struct rockchip_chg_det_reg - usb charger detect registers
90  * @cp_det: charging port detected successfully.
91  * @dcp_det: dedicated charging port detected successfully.
92  * @dp_det: assert data pin connect successfully.
93  * @idm_sink_en: open dm sink curren.
94  * @idp_sink_en: open dp sink current.
95  * @idp_src_en: open dm source current.
96  * @rdm_pdwn_en: open dm pull down resistor.
97  * @vdm_src_en: open dm voltage source.
98  * @vdp_src_en: open dp voltage source.
99  * @opmode: utmi operational mode.
100  */
101 struct rockchip_chg_det_reg {
102 	struct usb2phy_reg	cp_det;
103 	struct usb2phy_reg	dcp_det;
104 	struct usb2phy_reg	dp_det;
105 	struct usb2phy_reg	idm_sink_en;
106 	struct usb2phy_reg	idp_sink_en;
107 	struct usb2phy_reg	idp_src_en;
108 	struct usb2phy_reg	rdm_pdwn_en;
109 	struct usb2phy_reg	vdm_src_en;
110 	struct usb2phy_reg	vdp_src_en;
111 	struct usb2phy_reg	opmode;
112 };
113 
114 /**
115  * struct rockchip_usb2phy_port_cfg - usb-phy port configuration.
116  * @phy_sus: phy suspend register.
117  * @bvalid_det_en: vbus valid rise detection enable register.
118  * @bvalid_det_st: vbus valid rise detection status register.
119  * @bvalid_det_clr: vbus valid rise detection clear register.
120  * @disfall_en: host disconnect fall edge detection enable.
121  * @disfall_st: host disconnect fall edge detection state.
122  * @disfall_clr: host disconnect fall edge detection clear.
123  * @disrise_en: host disconnect rise edge detection enable.
124  * @disrise_st: host disconnect rise edge detection state.
125  * @disrise_clr: host disconnect rise edge detection clear.
126  * @idfall_det_en: id detection enable register, falling edge
127  * @idfall_det_st: id detection state register, falling edge
128  * @idfall_det_clr: id detection clear register, falling edge
129  * @idrise_det_en: id detection enable register, rising edge
130  * @idrise_det_st: id detection state register, rising edge
131  * @idrise_det_clr: id detection clear register, rising edge
132  * @ls_det_en: linestate detection enable register.
133  * @ls_det_st: linestate detection state register.
134  * @ls_det_clr: linestate detection clear register.
135  * @utmi_avalid: utmi vbus avalid status register.
136  * @utmi_bvalid: utmi vbus bvalid status register.
137  * @utmi_id: utmi id state register.
138  * @utmi_ls: utmi linestate state register.
139  * @utmi_hstdet: utmi host disconnect register.
140  */
141 struct rockchip_usb2phy_port_cfg {
142 	struct usb2phy_reg	phy_sus;
143 	struct usb2phy_reg	bvalid_det_en;
144 	struct usb2phy_reg	bvalid_det_st;
145 	struct usb2phy_reg	bvalid_det_clr;
146 	struct usb2phy_reg      disfall_en;
147 	struct usb2phy_reg      disfall_st;
148 	struct usb2phy_reg      disfall_clr;
149 	struct usb2phy_reg      disrise_en;
150 	struct usb2phy_reg      disrise_st;
151 	struct usb2phy_reg      disrise_clr;
152 	struct usb2phy_reg	idfall_det_en;
153 	struct usb2phy_reg	idfall_det_st;
154 	struct usb2phy_reg	idfall_det_clr;
155 	struct usb2phy_reg	idrise_det_en;
156 	struct usb2phy_reg	idrise_det_st;
157 	struct usb2phy_reg	idrise_det_clr;
158 	struct usb2phy_reg	ls_det_en;
159 	struct usb2phy_reg	ls_det_st;
160 	struct usb2phy_reg	ls_det_clr;
161 	struct usb2phy_reg	utmi_avalid;
162 	struct usb2phy_reg	utmi_bvalid;
163 	struct usb2phy_reg	utmi_id;
164 	struct usb2phy_reg	utmi_ls;
165 	struct usb2phy_reg	utmi_hstdet;
166 };
167 
168 /**
169  * struct rockchip_usb2phy_cfg - usb-phy configuration.
170  * @reg: the address offset of grf for usb-phy config.
171  * @num_ports: specify how many ports that the phy has.
172  * @phy_tuning: phy default parameters tuning.
173  * @clkout_ctl: register to enable output clk of phy, when set in GRF
174  * @clkout_ctl_phy: register to enable output clk of phy, when set inside phy
175  * @port_cfgs: usb-phy port configurations.
176  * @chg_det: charger detection registers.
177  */
178 struct rockchip_usb2phy_cfg {
179 	unsigned int	reg;
180 	unsigned int	num_ports;
181 	int (*phy_tuning)(struct rockchip_usb2phy *rphy);
182 	struct usb2phy_reg	clkout_ctl;
183 	struct usb2phy_reg	clkout_ctl_phy;
184 	const struct rockchip_usb2phy_port_cfg	port_cfgs[USB2PHY_NUM_PORTS];
185 	const struct rockchip_chg_det_reg	chg_det;
186 };
187 
188 /**
189  * struct rockchip_usb2phy_port - usb-phy port data.
190  * @phy: generic phy.
191  * @port_id: flag for otg port or host port.
192  * @suspended: phy suspended flag.
193  * @vbus_attached: otg device vbus status.
194  * @host_disconnect: usb host disconnect status.
195  * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
196  * @id_irq: IRQ number assigned for ID pin detection.
197  * @ls_irq: IRQ number assigned for linestate detection.
198  * @otg_mux_irq: IRQ number which multiplex otg-id/otg-bvalid/linestate
199  *		 irqs to one irq in otg-port.
200  * @mutex: for register updating in sm_work.
201  * @chg_work: charge detect work.
202  * @otg_sm_work: OTG state machine work.
203  * @sm_work: HOST state machine work.
204  * @port_cfg: port register configuration, assigned by driver data.
205  * @event_nb: hold event notification callback.
206  * @state: define OTG enumeration states before device reset.
207  * @mode: the dr_mode of the controller.
208  */
209 struct rockchip_usb2phy_port {
210 	struct phy	*phy;
211 	unsigned int	port_id;
212 	bool		suspended;
213 	bool		vbus_attached;
214 	bool            host_disconnect;
215 	int		bvalid_irq;
216 	int		id_irq;
217 	int		ls_irq;
218 	int		otg_mux_irq;
219 	struct mutex	mutex;
220 	struct		delayed_work chg_work;
221 	struct		delayed_work otg_sm_work;
222 	struct		delayed_work sm_work;
223 	const struct	rockchip_usb2phy_port_cfg *port_cfg;
224 	struct notifier_block	event_nb;
225 	enum usb_otg_state	state;
226 	enum usb_dr_mode	mode;
227 };
228 
229 /**
230  * struct rockchip_usb2phy - usb2.0 phy driver data.
231  * @dev: pointer to device.
232  * @grf: General Register Files regmap.
233  * @phy_base: USB PHY regmap.
234  * @clks: array of phy input clocks.
235  * @clk480m: clock struct of phy output clk.
236  * @clk480m_hw: clock struct of phy output clk management.
237  * @num_clks: number of phy input clocks.
238  * @phy_reset: phy reset control.
239  * @chg_state: states involved in USB charger detection.
240  * @chg_type: USB charger types.
241  * @dcd_retries: The retry count used to track Data contact
242  *		 detection process.
243  * @edev: extcon device for notification registration
244  * @irq: muxed interrupt for single irq configuration
245  * @phy_cfg: phy register configuration, assigned by driver data.
246  * @ports: phy port instance.
247  */
248 struct rockchip_usb2phy {
249 	struct device	*dev;
250 	struct regmap	*grf;
251 	struct regmap	*phy_base;
252 	struct clk_bulk_data	*clks;
253 	struct clk	*clk480m;
254 	struct clk_hw	clk480m_hw;
255 	int			num_clks;
256 	struct reset_control	*phy_reset;
257 	enum usb_chg_state	chg_state;
258 	enum power_supply_type	chg_type;
259 	u8			dcd_retries;
260 	struct extcon_dev	*edev;
261 	int			irq;
262 	const struct rockchip_usb2phy_cfg	*phy_cfg;
263 	struct rockchip_usb2phy_port	ports[USB2PHY_NUM_PORTS];
264 };
265 
266 static inline int property_enable(struct regmap *base,
267 				  const struct usb2phy_reg *reg, bool en)
268 {
269 	unsigned int val, mask, tmp;
270 
271 	tmp = en ? reg->enable : reg->disable;
272 	mask = GENMASK(reg->bitend, reg->bitstart);
273 	val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
274 
275 	return regmap_write(base, reg->offset, val);
276 }
277 
278 static inline bool property_enabled(struct regmap *base,
279 				    const struct usb2phy_reg *reg)
280 {
281 	int ret;
282 	unsigned int tmp, orig;
283 	unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
284 
285 	ret = regmap_read(base, reg->offset, &orig);
286 	if (ret)
287 		return false;
288 
289 	tmp = (orig & mask) >> reg->bitstart;
290 	return tmp != reg->disable;
291 }
292 
293 static int rockchip_usb2phy_reset(struct rockchip_usb2phy *rphy)
294 {
295 	int ret;
296 
297 	ret = reset_control_assert(rphy->phy_reset);
298 	if (ret)
299 		return ret;
300 
301 	udelay(10);
302 
303 	ret = reset_control_deassert(rphy->phy_reset);
304 	if (ret)
305 		return ret;
306 
307 	usleep_range(100, 200);
308 
309 	return 0;
310 }
311 
312 static void rockchip_usb2phy_clk_bulk_disable(void *data)
313 {
314 	struct rockchip_usb2phy *rphy = data;
315 
316 	clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks);
317 }
318 
319 static void
320 rockchip_usb2phy_clk480m_clkout_ctl(struct clk_hw *hw, struct regmap **base,
321 				    const struct usb2phy_reg **clkout_ctl)
322 {
323 	struct rockchip_usb2phy *rphy =
324 		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
325 
326 	if (rphy->phy_cfg->clkout_ctl_phy.enable) {
327 		*base = rphy->phy_base;
328 		*clkout_ctl = &rphy->phy_cfg->clkout_ctl_phy;
329 	} else {
330 		*base = rphy->grf;
331 		*clkout_ctl = &rphy->phy_cfg->clkout_ctl;
332 	}
333 }
334 
335 static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
336 {
337 	const struct usb2phy_reg *clkout_ctl;
338 	struct regmap *base;
339 	int ret;
340 
341 	rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
342 
343 	/* turn on 480m clk output if it is off */
344 	if (!property_enabled(base, clkout_ctl)) {
345 		ret = property_enable(base, clkout_ctl, true);
346 		if (ret)
347 			return ret;
348 
349 		/* waiting for the clk become stable */
350 		usleep_range(1200, 1300);
351 	}
352 
353 	return 0;
354 }
355 
356 static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
357 {
358 	const struct usb2phy_reg *clkout_ctl;
359 	struct regmap *base;
360 
361 	rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
362 
363 	/* turn off 480m clk output */
364 	property_enable(base, clkout_ctl, false);
365 }
366 
367 static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
368 {
369 	const struct usb2phy_reg *clkout_ctl;
370 	struct regmap *base;
371 
372 	rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
373 
374 	return property_enabled(base, clkout_ctl);
375 }
376 
377 static unsigned long
378 rockchip_usb2phy_clk480m_recalc_rate(struct clk_hw *hw,
379 				     unsigned long parent_rate)
380 {
381 	return 480000000;
382 }
383 
384 static const struct clk_ops rockchip_usb2phy_clkout_ops = {
385 	.prepare = rockchip_usb2phy_clk480m_prepare,
386 	.unprepare = rockchip_usb2phy_clk480m_unprepare,
387 	.is_prepared = rockchip_usb2phy_clk480m_prepared,
388 	.recalc_rate = rockchip_usb2phy_clk480m_recalc_rate,
389 };
390 
391 static void rockchip_usb2phy_clk480m_unregister(void *data)
392 {
393 	struct rockchip_usb2phy *rphy = data;
394 
395 	of_clk_del_provider(rphy->dev->of_node);
396 	clk_unregister(rphy->clk480m);
397 }
398 
399 static int
400 rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
401 {
402 	struct device_node *node = rphy->dev->of_node;
403 	struct clk_init_data init;
404 	struct clk *refclk = NULL;
405 	const char *clk_name;
406 	int i;
407 	int ret = 0;
408 
409 	init.flags = 0;
410 	init.name = "clk_usbphy_480m";
411 	init.ops = &rockchip_usb2phy_clkout_ops;
412 
413 	/* optional override of the clockname */
414 	of_property_read_string(node, "clock-output-names", &init.name);
415 
416 	for (i = 0; i < rphy->num_clks; i++) {
417 		if (!strncmp(rphy->clks[i].id, "phyclk", 6)) {
418 			refclk = rphy->clks[i].clk;
419 			break;
420 		}
421 	}
422 
423 	if (!IS_ERR(refclk)) {
424 		clk_name = __clk_get_name(refclk);
425 		init.parent_names = &clk_name;
426 		init.num_parents = 1;
427 	} else {
428 		init.parent_names = NULL;
429 		init.num_parents = 0;
430 	}
431 
432 	rphy->clk480m_hw.init = &init;
433 
434 	/* register the clock */
435 	rphy->clk480m = clk_register(rphy->dev, &rphy->clk480m_hw);
436 	if (IS_ERR(rphy->clk480m)) {
437 		ret = PTR_ERR(rphy->clk480m);
438 		goto err_ret;
439 	}
440 
441 	ret = of_clk_add_provider(node, of_clk_src_simple_get, rphy->clk480m);
442 	if (ret < 0)
443 		goto err_clk_provider;
444 
445 	return devm_add_action_or_reset(rphy->dev, rockchip_usb2phy_clk480m_unregister, rphy);
446 
447 err_clk_provider:
448 	clk_unregister(rphy->clk480m);
449 err_ret:
450 	return ret;
451 }
452 
453 static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
454 {
455 	struct device_node *node = rphy->dev->of_node;
456 	struct extcon_dev *edev;
457 	int ret;
458 
459 	if (of_property_present(node, "extcon")) {
460 		edev = extcon_get_edev_by_phandle(rphy->dev, 0);
461 		if (IS_ERR(edev))
462 			return dev_err_probe(rphy->dev, PTR_ERR(edev),
463 					     "invalid or missing extcon\n");
464 	} else {
465 		/* Initialize extcon device */
466 		edev = devm_extcon_dev_allocate(rphy->dev,
467 						rockchip_usb2phy_extcon_cable);
468 
469 		if (IS_ERR(edev))
470 			return dev_err_probe(rphy->dev, PTR_ERR(edev),
471 					     "failed to allocate extcon device\n");
472 
473 		ret = devm_extcon_dev_register(rphy->dev, edev);
474 		if (ret)
475 			return dev_err_probe(rphy->dev, ret,
476 					     "failed to register extcon device\n");
477 	}
478 
479 	rphy->edev = edev;
480 
481 	return 0;
482 }
483 
484 static int rockchip_usb2phy_enable_host_disc_irq(struct rockchip_usb2phy *rphy,
485 						 struct rockchip_usb2phy_port *rport,
486 						 bool en)
487 {
488 	int ret;
489 
490 	ret = property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true);
491 	if (ret)
492 		return ret;
493 
494 	ret = property_enable(rphy->grf, &rport->port_cfg->disfall_en, en);
495 	if (ret)
496 		return ret;
497 
498 	ret = property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true);
499 	if (ret)
500 		return ret;
501 
502 	return property_enable(rphy->grf, &rport->port_cfg->disrise_en, en);
503 }
504 
505 static int rockchip_usb2phy_init(struct phy *phy)
506 {
507 	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
508 	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
509 	int ret = 0;
510 
511 	mutex_lock(&rport->mutex);
512 
513 	if (rport->port_id == USB2PHY_PORT_OTG) {
514 		if (rport->mode != USB_DR_MODE_HOST &&
515 		    rport->mode != USB_DR_MODE_UNKNOWN) {
516 			/* clear bvalid status and enable bvalid detect irq */
517 			ret = property_enable(rphy->grf,
518 					      &rport->port_cfg->bvalid_det_clr,
519 					      true);
520 			if (ret)
521 				goto out;
522 
523 			ret = property_enable(rphy->grf,
524 					      &rport->port_cfg->bvalid_det_en,
525 					      true);
526 			if (ret)
527 				goto out;
528 
529 			/* clear id status and enable id detect irqs */
530 			ret = property_enable(rphy->grf,
531 					      &rport->port_cfg->idfall_det_clr,
532 					      true);
533 			if (ret)
534 				goto out;
535 
536 			ret = property_enable(rphy->grf,
537 					      &rport->port_cfg->idrise_det_clr,
538 					      true);
539 			if (ret)
540 				goto out;
541 
542 			ret = property_enable(rphy->grf,
543 					      &rport->port_cfg->idfall_det_en,
544 					      true);
545 			if (ret)
546 				goto out;
547 
548 			ret = property_enable(rphy->grf,
549 					      &rport->port_cfg->idrise_det_en,
550 					      true);
551 			if (ret)
552 				goto out;
553 
554 			schedule_delayed_work(&rport->otg_sm_work,
555 					      OTG_SCHEDULE_DELAY * 3);
556 		} else {
557 			/* If OTG works in host only mode, do nothing. */
558 			dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
559 		}
560 	} else if (rport->port_id == USB2PHY_PORT_HOST) {
561 		if (rport->port_cfg->disfall_en.offset) {
562 			rport->host_disconnect = true;
563 			ret = rockchip_usb2phy_enable_host_disc_irq(rphy, rport, true);
564 			if (ret) {
565 				dev_err(rphy->dev, "failed to enable disconnect irq\n");
566 				goto out;
567 			}
568 		}
569 
570 		/* clear linestate and enable linestate detect irq */
571 		ret = property_enable(rphy->grf,
572 				      &rport->port_cfg->ls_det_clr, true);
573 		if (ret)
574 			goto out;
575 
576 		ret = property_enable(rphy->grf,
577 				      &rport->port_cfg->ls_det_en, true);
578 		if (ret)
579 			goto out;
580 
581 		schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
582 	}
583 
584 out:
585 	mutex_unlock(&rport->mutex);
586 	return ret;
587 }
588 
589 static int rockchip_usb2phy_power_on(struct phy *phy)
590 {
591 	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
592 	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
593 	int ret;
594 
595 	dev_dbg(&rport->phy->dev, "port power on\n");
596 
597 	if (!rport->suspended)
598 		return 0;
599 
600 	ret = clk_prepare_enable(rphy->clk480m);
601 	if (ret)
602 		return ret;
603 
604 	ret = property_enable(rphy->grf, &rport->port_cfg->phy_sus, false);
605 	if (ret) {
606 		clk_disable_unprepare(rphy->clk480m);
607 		return ret;
608 	}
609 
610 	/*
611 	 * For rk3588, it needs to reset phy when exit from
612 	 * suspend mode with common_on_n 1'b1(aka REFCLK_LOGIC,
613 	 * Bias, and PLL blocks are powered down) for lower
614 	 * power consumption. If you don't want to reset phy,
615 	 * please keep the common_on_n 1'b0 to set these blocks
616 	 * remain powered.
617 	 */
618 	ret = rockchip_usb2phy_reset(rphy);
619 	if (ret)
620 		return ret;
621 
622 	/* waiting for the utmi_clk to become stable */
623 	usleep_range(1500, 2000);
624 
625 	rport->suspended = false;
626 	return 0;
627 }
628 
629 static int rockchip_usb2phy_power_off(struct phy *phy)
630 {
631 	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
632 	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
633 	int ret;
634 
635 	dev_dbg(&rport->phy->dev, "port power off\n");
636 
637 	if (rport->suspended)
638 		return 0;
639 
640 	ret = property_enable(rphy->grf, &rport->port_cfg->phy_sus, true);
641 	if (ret)
642 		return ret;
643 
644 	rport->suspended = true;
645 	clk_disable_unprepare(rphy->clk480m);
646 
647 	return 0;
648 }
649 
650 static int rockchip_usb2phy_exit(struct phy *phy)
651 {
652 	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
653 
654 	if (rport->port_id == USB2PHY_PORT_OTG &&
655 	    rport->mode != USB_DR_MODE_HOST &&
656 	    rport->mode != USB_DR_MODE_UNKNOWN) {
657 		cancel_delayed_work_sync(&rport->otg_sm_work);
658 		cancel_delayed_work_sync(&rport->chg_work);
659 	} else if (rport->port_id == USB2PHY_PORT_HOST)
660 		cancel_delayed_work_sync(&rport->sm_work);
661 
662 	return 0;
663 }
664 
665 static const struct phy_ops rockchip_usb2phy_ops = {
666 	.init		= rockchip_usb2phy_init,
667 	.exit		= rockchip_usb2phy_exit,
668 	.power_on	= rockchip_usb2phy_power_on,
669 	.power_off	= rockchip_usb2phy_power_off,
670 	.owner		= THIS_MODULE,
671 };
672 
673 static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
674 {
675 	struct rockchip_usb2phy_port *rport =
676 		container_of(work, struct rockchip_usb2phy_port,
677 			     otg_sm_work.work);
678 	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
679 	static unsigned int cable;
680 	unsigned long delay;
681 	bool vbus_attach, sch_work, notify_charger;
682 
683 	vbus_attach = property_enabled(rphy->grf,
684 				       &rport->port_cfg->utmi_bvalid);
685 
686 	sch_work = false;
687 	notify_charger = false;
688 	delay = OTG_SCHEDULE_DELAY;
689 	dev_dbg(&rport->phy->dev, "%s otg sm work\n",
690 		usb_otg_state_string(rport->state));
691 
692 	switch (rport->state) {
693 	case OTG_STATE_UNDEFINED:
694 		rport->state = OTG_STATE_B_IDLE;
695 		if (!vbus_attach)
696 			rockchip_usb2phy_power_off(rport->phy);
697 		fallthrough;
698 	case OTG_STATE_B_IDLE:
699 		if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) {
700 			dev_dbg(&rport->phy->dev, "usb otg host connect\n");
701 			rport->state = OTG_STATE_A_HOST;
702 			rockchip_usb2phy_power_on(rport->phy);
703 			return;
704 		} else if (vbus_attach) {
705 			dev_dbg(&rport->phy->dev, "vbus_attach\n");
706 			switch (rphy->chg_state) {
707 			case USB_CHG_STATE_UNDEFINED:
708 				schedule_delayed_work(&rport->chg_work, 0);
709 				return;
710 			case USB_CHG_STATE_DETECTED:
711 				switch (rphy->chg_type) {
712 				case POWER_SUPPLY_TYPE_USB:
713 					dev_dbg(&rport->phy->dev, "sdp cable is connected\n");
714 					rockchip_usb2phy_power_on(rport->phy);
715 					rport->state = OTG_STATE_B_PERIPHERAL;
716 					notify_charger = true;
717 					sch_work = true;
718 					cable = EXTCON_CHG_USB_SDP;
719 					break;
720 				case POWER_SUPPLY_TYPE_USB_DCP:
721 					dev_dbg(&rport->phy->dev, "dcp cable is connected\n");
722 					rockchip_usb2phy_power_off(rport->phy);
723 					notify_charger = true;
724 					sch_work = true;
725 					cable = EXTCON_CHG_USB_DCP;
726 					break;
727 				case POWER_SUPPLY_TYPE_USB_CDP:
728 					dev_dbg(&rport->phy->dev, "cdp cable is connected\n");
729 					rockchip_usb2phy_power_on(rport->phy);
730 					rport->state = OTG_STATE_B_PERIPHERAL;
731 					notify_charger = true;
732 					sch_work = true;
733 					cable = EXTCON_CHG_USB_CDP;
734 					break;
735 				default:
736 					break;
737 				}
738 				break;
739 			default:
740 				break;
741 			}
742 		} else {
743 			notify_charger = true;
744 			rphy->chg_state = USB_CHG_STATE_UNDEFINED;
745 			rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
746 		}
747 
748 		if (rport->vbus_attached != vbus_attach) {
749 			rport->vbus_attached = vbus_attach;
750 
751 			if (notify_charger && rphy->edev) {
752 				extcon_set_state_sync(rphy->edev,
753 							cable, vbus_attach);
754 				if (cable == EXTCON_CHG_USB_SDP)
755 					extcon_set_state_sync(rphy->edev,
756 							      EXTCON_USB,
757 							      vbus_attach);
758 			}
759 		}
760 		break;
761 	case OTG_STATE_B_PERIPHERAL:
762 		if (!vbus_attach) {
763 			dev_dbg(&rport->phy->dev, "usb disconnect\n");
764 			rphy->chg_state = USB_CHG_STATE_UNDEFINED;
765 			rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
766 			rport->state = OTG_STATE_B_IDLE;
767 			delay = 0;
768 			rockchip_usb2phy_power_off(rport->phy);
769 		}
770 		sch_work = true;
771 		break;
772 	case OTG_STATE_A_HOST:
773 		if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) == 0) {
774 			dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
775 			rport->state = OTG_STATE_B_IDLE;
776 			rockchip_usb2phy_power_off(rport->phy);
777 		}
778 		break;
779 	default:
780 		break;
781 	}
782 
783 	if (sch_work)
784 		schedule_delayed_work(&rport->otg_sm_work, delay);
785 }
786 
787 static const char *chg_to_string(enum power_supply_type chg_type)
788 {
789 	switch (chg_type) {
790 	case POWER_SUPPLY_TYPE_USB:
791 		return "USB_SDP_CHARGER";
792 	case POWER_SUPPLY_TYPE_USB_DCP:
793 		return "USB_DCP_CHARGER";
794 	case POWER_SUPPLY_TYPE_USB_CDP:
795 		return "USB_CDP_CHARGER";
796 	default:
797 		return "INVALID_CHARGER";
798 	}
799 }
800 
801 static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
802 				    bool en)
803 {
804 	property_enable(rphy->grf, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
805 	property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idp_src_en, en);
806 }
807 
808 static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
809 					    bool en)
810 {
811 	property_enable(rphy->grf, &rphy->phy_cfg->chg_det.vdp_src_en, en);
812 	property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idm_sink_en, en);
813 }
814 
815 static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
816 					      bool en)
817 {
818 	property_enable(rphy->grf, &rphy->phy_cfg->chg_det.vdm_src_en, en);
819 	property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idp_sink_en, en);
820 }
821 
822 #define CHG_DCD_POLL_TIME	(100 * HZ / 1000)
823 #define CHG_DCD_MAX_RETRIES	6
824 #define CHG_PRIMARY_DET_TIME	(40 * HZ / 1000)
825 #define CHG_SECONDARY_DET_TIME	(40 * HZ / 1000)
826 static void rockchip_chg_detect_work(struct work_struct *work)
827 {
828 	struct rockchip_usb2phy_port *rport =
829 		container_of(work, struct rockchip_usb2phy_port, chg_work.work);
830 	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
831 	bool is_dcd, tmout, vout, vbus_attach;
832 	unsigned long delay;
833 
834 	vbus_attach = property_enabled(rphy->grf, &rport->port_cfg->utmi_bvalid);
835 
836 	dev_dbg(&rport->phy->dev, "chg detection work state = %d\n",
837 		rphy->chg_state);
838 	switch (rphy->chg_state) {
839 	case USB_CHG_STATE_UNDEFINED:
840 		if (!rport->suspended && !vbus_attach)
841 			rockchip_usb2phy_power_off(rport->phy);
842 		/* put the controller in non-driving mode */
843 		if (!vbus_attach)
844 			property_enable(rphy->grf, &rphy->phy_cfg->chg_det.opmode, false);
845 		/* Start DCD processing stage 1 */
846 		rockchip_chg_enable_dcd(rphy, true);
847 		rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
848 		rphy->dcd_retries = 0;
849 		delay = CHG_DCD_POLL_TIME;
850 		break;
851 	case USB_CHG_STATE_WAIT_FOR_DCD:
852 		/* get data contact detection status */
853 		is_dcd = property_enabled(rphy->grf,
854 					  &rphy->phy_cfg->chg_det.dp_det);
855 		tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
856 		/* stage 2 */
857 		if (is_dcd || tmout) {
858 			/* stage 4 */
859 			/* Turn off DCD circuitry */
860 			rockchip_chg_enable_dcd(rphy, false);
861 			/* Voltage Source on DP, Probe on DM */
862 			rockchip_chg_enable_primary_det(rphy, true);
863 			delay = CHG_PRIMARY_DET_TIME;
864 			rphy->chg_state = USB_CHG_STATE_DCD_DONE;
865 		} else {
866 			/* stage 3 */
867 			delay = CHG_DCD_POLL_TIME;
868 		}
869 		break;
870 	case USB_CHG_STATE_DCD_DONE:
871 		vout = property_enabled(rphy->grf,
872 					&rphy->phy_cfg->chg_det.cp_det);
873 		rockchip_chg_enable_primary_det(rphy, false);
874 		if (vout) {
875 			/* Voltage Source on DM, Probe on DP  */
876 			rockchip_chg_enable_secondary_det(rphy, true);
877 			delay = CHG_SECONDARY_DET_TIME;
878 			rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE;
879 		} else {
880 			if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) {
881 				/* floating charger found */
882 				rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
883 				rphy->chg_state = USB_CHG_STATE_DETECTED;
884 				delay = 0;
885 			} else {
886 				rphy->chg_type = POWER_SUPPLY_TYPE_USB;
887 				rphy->chg_state = USB_CHG_STATE_DETECTED;
888 				delay = 0;
889 			}
890 		}
891 		break;
892 	case USB_CHG_STATE_PRIMARY_DONE:
893 		vout = property_enabled(rphy->grf,
894 					&rphy->phy_cfg->chg_det.dcp_det);
895 		/* Turn off voltage source */
896 		rockchip_chg_enable_secondary_det(rphy, false);
897 		if (vout)
898 			rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
899 		else
900 			rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP;
901 		fallthrough;
902 	case USB_CHG_STATE_SECONDARY_DONE:
903 		rphy->chg_state = USB_CHG_STATE_DETECTED;
904 		fallthrough;
905 	case USB_CHG_STATE_DETECTED:
906 		/* put the controller in normal mode */
907 		if (!vbus_attach)
908 			property_enable(rphy->grf, &rphy->phy_cfg->chg_det.opmode, true);
909 		rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
910 		dev_dbg(&rport->phy->dev, "charger = %s\n",
911 			 chg_to_string(rphy->chg_type));
912 		return;
913 	default:
914 		return;
915 	}
916 
917 	schedule_delayed_work(&rport->chg_work, delay);
918 }
919 
920 /*
921  * The function manage host-phy port state and suspend/resume phy port
922  * to save power.
923  *
924  * we rely on utmi_linestate and utmi_hostdisconnect to identify whether
925  * devices is disconnect or not. Besides, we do not need care it is FS/LS
926  * disconnected or HS disconnected, actually, we just only need get the
927  * device is disconnected at last through rearm the delayed work,
928  * to suspend the phy port in _PHY_STATE_DISCONNECT_ case.
929  *
930  * NOTE: It may invoke *phy_powr_off or *phy_power_on which will invoke
931  * some clk related APIs, so do not invoke it from interrupt context directly.
932  */
933 static void rockchip_usb2phy_sm_work(struct work_struct *work)
934 {
935 	struct rockchip_usb2phy_port *rport =
936 		container_of(work, struct rockchip_usb2phy_port, sm_work.work);
937 	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
938 	unsigned int sh, ul, uhd, state;
939 	unsigned int ul_mask, uhd_mask;
940 	int ret;
941 
942 	mutex_lock(&rport->mutex);
943 
944 	ret = regmap_read(rphy->grf, rport->port_cfg->utmi_ls.offset, &ul);
945 	if (ret < 0)
946 		goto next_schedule;
947 
948 	ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend,
949 			  rport->port_cfg->utmi_ls.bitstart);
950 
951 	if (rport->port_cfg->utmi_hstdet.offset) {
952 		ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd);
953 		if (ret < 0)
954 			goto next_schedule;
955 
956 		uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend,
957 				   rport->port_cfg->utmi_hstdet.bitstart);
958 
959 		sh = rport->port_cfg->utmi_hstdet.bitend -
960 		     rport->port_cfg->utmi_hstdet.bitstart + 1;
961 		/* stitch on utmi_ls and utmi_hstdet as phy state */
962 		state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) |
963 			(((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh);
964 	} else {
965 		state = ((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << 1 |
966 			rport->host_disconnect;
967 	}
968 
969 	switch (state) {
970 	case PHY_STATE_HS_ONLINE:
971 		dev_dbg(&rport->phy->dev, "HS online\n");
972 		break;
973 	case PHY_STATE_FS_LS_ONLINE:
974 		/*
975 		 * For FS/LS device, the online state share with connect state
976 		 * from utmi_ls and utmi_hstdet register, so we distinguish
977 		 * them via suspended flag.
978 		 *
979 		 * Plus, there are two cases, one is D- Line pull-up, and D+
980 		 * line pull-down, the state is 4; another is D+ line pull-up,
981 		 * and D- line pull-down, the state is 2.
982 		 */
983 		if (!rport->suspended) {
984 			/* D- line pull-up, D+ line pull-down */
985 			dev_dbg(&rport->phy->dev, "FS/LS online\n");
986 			break;
987 		}
988 		fallthrough;
989 	case PHY_STATE_CONNECT:
990 		if (rport->suspended) {
991 			dev_dbg(&rport->phy->dev, "Connected\n");
992 			rockchip_usb2phy_power_on(rport->phy);
993 			rport->suspended = false;
994 		} else {
995 			/* D+ line pull-up, D- line pull-down */
996 			dev_dbg(&rport->phy->dev, "FS/LS online\n");
997 		}
998 		break;
999 	case PHY_STATE_DISCONNECT:
1000 		if (!rport->suspended) {
1001 			dev_dbg(&rport->phy->dev, "Disconnected\n");
1002 			rockchip_usb2phy_power_off(rport->phy);
1003 			rport->suspended = true;
1004 		}
1005 
1006 		/*
1007 		 * activate the linestate detection to get the next device
1008 		 * plug-in irq.
1009 		 */
1010 		property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
1011 		property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true);
1012 
1013 		/*
1014 		 * we don't need to rearm the delayed work when the phy port
1015 		 * is suspended.
1016 		 */
1017 		mutex_unlock(&rport->mutex);
1018 		return;
1019 	default:
1020 		dev_dbg(&rport->phy->dev, "unknown phy state\n");
1021 		break;
1022 	}
1023 
1024 next_schedule:
1025 	mutex_unlock(&rport->mutex);
1026 	schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
1027 }
1028 
1029 static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
1030 {
1031 	struct rockchip_usb2phy_port *rport = data;
1032 	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
1033 
1034 	if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st))
1035 		return IRQ_NONE;
1036 
1037 	mutex_lock(&rport->mutex);
1038 
1039 	/* disable linestate detect irq and clear its status */
1040 	property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false);
1041 	property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
1042 
1043 	mutex_unlock(&rport->mutex);
1044 
1045 	/*
1046 	 * In this case for host phy port, a new device is plugged in,
1047 	 * meanwhile, if the phy port is suspended, we need rearm the work to
1048 	 * resume it and mange its states; otherwise, we do nothing about that.
1049 	 */
1050 	if (rport->suspended && rport->port_id == USB2PHY_PORT_HOST)
1051 		rockchip_usb2phy_sm_work(&rport->sm_work.work);
1052 
1053 	return IRQ_HANDLED;
1054 }
1055 
1056 static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
1057 {
1058 	struct rockchip_usb2phy_port *rport = data;
1059 	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
1060 
1061 	if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st))
1062 		return IRQ_NONE;
1063 
1064 	/* clear bvalid detect irq pending status */
1065 	property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true);
1066 
1067 	rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
1068 
1069 	return IRQ_HANDLED;
1070 }
1071 
1072 static irqreturn_t rockchip_usb2phy_id_irq(int irq, void *data)
1073 {
1074 	struct rockchip_usb2phy_port *rport = data;
1075 	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
1076 	bool id;
1077 
1078 	if (!property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st) &&
1079 	    !property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st))
1080 		return IRQ_NONE;
1081 
1082 	/* clear id detect irq pending status */
1083 	if (property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st))
1084 		property_enable(rphy->grf, &rport->port_cfg->idfall_det_clr, true);
1085 
1086 	if (property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st))
1087 		property_enable(rphy->grf, &rport->port_cfg->idrise_det_clr, true);
1088 
1089 	id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id);
1090 	extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id);
1091 
1092 	return IRQ_HANDLED;
1093 }
1094 
1095 static irqreturn_t rockchip_usb2phy_otg_mux_irq(int irq, void *data)
1096 {
1097 	irqreturn_t ret = IRQ_NONE;
1098 
1099 	ret |= rockchip_usb2phy_bvalid_irq(irq, data);
1100 	ret |= rockchip_usb2phy_id_irq(irq, data);
1101 
1102 	return ret;
1103 }
1104 
1105 static irqreturn_t rockchip_usb2phy_host_disc_irq(int irq, void *data)
1106 {
1107 	struct rockchip_usb2phy_port *rport = data;
1108 	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
1109 
1110 	if (!property_enabled(rphy->grf, &rport->port_cfg->disfall_st) &&
1111 	    !property_enabled(rphy->grf, &rport->port_cfg->disrise_st))
1112 		return IRQ_NONE;
1113 
1114 	mutex_lock(&rport->mutex);
1115 
1116 	/* clear disconnect fall or rise detect irq pending status */
1117 	if (property_enabled(rphy->grf, &rport->port_cfg->disfall_st)) {
1118 		property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true);
1119 		rport->host_disconnect = false;
1120 	} else if (property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) {
1121 		property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true);
1122 		rport->host_disconnect = true;
1123 	}
1124 
1125 	mutex_unlock(&rport->mutex);
1126 
1127 	return IRQ_HANDLED;
1128 }
1129 
1130 static irqreturn_t rockchip_usb2phy_irq(int irq, void *data)
1131 {
1132 	struct rockchip_usb2phy *rphy = data;
1133 	struct rockchip_usb2phy_port *rport;
1134 	irqreturn_t ret = IRQ_NONE;
1135 	unsigned int index;
1136 
1137 	for (index = 0; index < rphy->phy_cfg->num_ports; index++) {
1138 		rport = &rphy->ports[index];
1139 		if (!rport->phy)
1140 			continue;
1141 
1142 		if (rport->port_id == USB2PHY_PORT_HOST &&
1143 		    rport->port_cfg->disfall_en.offset)
1144 			ret |= rockchip_usb2phy_host_disc_irq(irq, rport);
1145 
1146 		switch (rport->port_id) {
1147 		case USB2PHY_PORT_OTG:
1148 			if (rport->mode != USB_DR_MODE_HOST &&
1149 			    rport->mode != USB_DR_MODE_UNKNOWN)
1150 				ret |= rockchip_usb2phy_otg_mux_irq(irq, rport);
1151 			break;
1152 		case USB2PHY_PORT_HOST:
1153 			ret |= rockchip_usb2phy_linestate_irq(irq, rport);
1154 			break;
1155 		}
1156 	}
1157 
1158 	return ret;
1159 }
1160 
1161 static int rockchip_usb2phy_port_irq_init(struct rockchip_usb2phy *rphy,
1162 					  struct rockchip_usb2phy_port *rport,
1163 					  struct device_node *child_np)
1164 {
1165 	int ret;
1166 
1167 	/*
1168 	 * If the usb2 phy used combined irq for otg and host port,
1169 	 * don't need to init otg and host port irq separately.
1170 	 */
1171 	if (rphy->irq > 0)
1172 		return 0;
1173 
1174 	switch (rport->port_id) {
1175 	case USB2PHY_PORT_HOST:
1176 		rport->ls_irq = of_irq_get_byname(child_np, "linestate");
1177 		if (rport->ls_irq < 0) {
1178 			dev_err(rphy->dev, "no linestate irq provided\n");
1179 			return rport->ls_irq;
1180 		}
1181 
1182 		ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL,
1183 						rockchip_usb2phy_linestate_irq,
1184 						IRQF_ONESHOT,
1185 						"rockchip_usb2phy", rport);
1186 		if (ret) {
1187 			dev_err(rphy->dev, "failed to request linestate irq handle\n");
1188 			return ret;
1189 		}
1190 		break;
1191 	case USB2PHY_PORT_OTG:
1192 		/*
1193 		 * Some SoCs use one interrupt with otg-id/otg-bvalid/linestate
1194 		 * interrupts muxed together, so probe the otg-mux interrupt first,
1195 		 * if not found, then look for the regular interrupts one by one.
1196 		 */
1197 		rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux");
1198 		if (rport->otg_mux_irq > 0) {
1199 			ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq,
1200 							NULL,
1201 							rockchip_usb2phy_otg_mux_irq,
1202 							IRQF_ONESHOT,
1203 							"rockchip_usb2phy_otg",
1204 							rport);
1205 			if (ret) {
1206 				dev_err(rphy->dev,
1207 					"failed to request otg-mux irq handle\n");
1208 				return ret;
1209 			}
1210 		} else {
1211 			rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
1212 			if (rport->bvalid_irq < 0) {
1213 				dev_err(rphy->dev, "no vbus valid irq provided\n");
1214 				ret = rport->bvalid_irq;
1215 				return ret;
1216 			}
1217 
1218 			ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq,
1219 							NULL,
1220 							rockchip_usb2phy_bvalid_irq,
1221 							IRQF_ONESHOT,
1222 							"rockchip_usb2phy_bvalid",
1223 							rport);
1224 			if (ret) {
1225 				dev_err(rphy->dev,
1226 					"failed to request otg-bvalid irq handle\n");
1227 				return ret;
1228 			}
1229 
1230 			rport->id_irq = of_irq_get_byname(child_np, "otg-id");
1231 			if (rport->id_irq < 0) {
1232 				dev_err(rphy->dev, "no otg-id irq provided\n");
1233 				ret = rport->id_irq;
1234 				return ret;
1235 			}
1236 
1237 			ret = devm_request_threaded_irq(rphy->dev, rport->id_irq,
1238 							NULL,
1239 							rockchip_usb2phy_id_irq,
1240 							IRQF_ONESHOT,
1241 							"rockchip_usb2phy_id",
1242 							rport);
1243 			if (ret) {
1244 				dev_err(rphy->dev,
1245 					"failed to request otg-id irq handle\n");
1246 				return ret;
1247 			}
1248 		}
1249 		break;
1250 	default:
1251 		return -EINVAL;
1252 	}
1253 
1254 	return 0;
1255 }
1256 
1257 static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
1258 					   struct rockchip_usb2phy_port *rport,
1259 					   struct device_node *child_np)
1260 {
1261 	int ret;
1262 
1263 	rport->port_id = USB2PHY_PORT_HOST;
1264 	rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_HOST];
1265 	rport->suspended = true;
1266 
1267 	mutex_init(&rport->mutex);
1268 	INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work);
1269 
1270 	ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np);
1271 	if (ret) {
1272 		dev_err(rphy->dev, "failed to setup host irq\n");
1273 		return ret;
1274 	}
1275 
1276 	return 0;
1277 }
1278 
1279 static int rockchip_otg_event(struct notifier_block *nb,
1280 			      unsigned long event, void *ptr)
1281 {
1282 	struct rockchip_usb2phy_port *rport =
1283 		container_of(nb, struct rockchip_usb2phy_port, event_nb);
1284 
1285 	schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
1286 
1287 	return NOTIFY_DONE;
1288 }
1289 
1290 static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
1291 					  struct rockchip_usb2phy_port *rport,
1292 					  struct device_node *child_np)
1293 {
1294 	int ret, id;
1295 
1296 	rport->port_id = USB2PHY_PORT_OTG;
1297 	rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
1298 	rport->state = OTG_STATE_UNDEFINED;
1299 
1300 	/*
1301 	 * set suspended flag to true, but actually don't
1302 	 * put phy in suspend mode, it aims to enable usb
1303 	 * phy and clock in power_on() called by usb controller
1304 	 * driver during probe.
1305 	 */
1306 	rport->suspended = true;
1307 	rport->vbus_attached = false;
1308 
1309 	mutex_init(&rport->mutex);
1310 
1311 	rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
1312 	if (rport->mode == USB_DR_MODE_HOST ||
1313 	    rport->mode == USB_DR_MODE_UNKNOWN) {
1314 		ret = 0;
1315 		goto out;
1316 	}
1317 
1318 	INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
1319 	INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
1320 
1321 	ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np);
1322 	if (ret) {
1323 		dev_err(rphy->dev, "failed to init irq for host port\n");
1324 		goto out;
1325 	}
1326 
1327 	if (!IS_ERR(rphy->edev)) {
1328 		rport->event_nb.notifier_call = rockchip_otg_event;
1329 
1330 		ret = devm_extcon_register_notifier(rphy->dev, rphy->edev,
1331 					EXTCON_USB_HOST, &rport->event_nb);
1332 		if (ret) {
1333 			dev_err(rphy->dev, "register USB HOST notifier failed\n");
1334 			goto out;
1335 		}
1336 
1337 		if (!of_property_present(rphy->dev->of_node, "extcon")) {
1338 			/* do initial sync of usb state */
1339 			id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id);
1340 			extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id);
1341 		}
1342 	}
1343 
1344 out:
1345 	return ret;
1346 }
1347 
1348 static int rockchip_usb2phy_probe(struct platform_device *pdev)
1349 {
1350 	struct device *dev = &pdev->dev;
1351 	struct device_node *np = dev->of_node;
1352 	struct device_node *child_np;
1353 	struct phy_provider *provider;
1354 	struct rockchip_usb2phy *rphy;
1355 	const struct rockchip_usb2phy_cfg *phy_cfgs;
1356 	unsigned int reg;
1357 	int index = 0, ret;
1358 
1359 	rphy = devm_kzalloc(dev, sizeof(*rphy), GFP_KERNEL);
1360 	if (!rphy)
1361 		return -ENOMEM;
1362 
1363 	if (!dev->parent || !dev->parent->of_node ||
1364 	    of_property_present(np, "rockchip,usbgrf")) {
1365 		rphy->phy_base = device_node_to_regmap(np);
1366 		if (IS_ERR(rphy->phy_base))
1367 			return PTR_ERR(rphy->phy_base);
1368 		rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf");
1369 	} else {
1370 		rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
1371 		rphy->phy_base = rphy->grf;
1372 	}
1373 	if (IS_ERR(rphy->grf))
1374 		return PTR_ERR(rphy->grf);
1375 
1376 	if (of_property_read_u32_index(np, "reg", 0, &reg)) {
1377 		dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
1378 		return -EINVAL;
1379 	}
1380 
1381 	/* support address_cells=2 */
1382 	if (of_property_count_u32_elems(np, "reg") > 2 && reg == 0) {
1383 		if (of_property_read_u32_index(np, "reg", 1, &reg)) {
1384 			dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
1385 			return -EINVAL;
1386 		}
1387 	}
1388 
1389 	rphy->dev = dev;
1390 	phy_cfgs = device_get_match_data(dev);
1391 	rphy->chg_state = USB_CHG_STATE_UNDEFINED;
1392 	rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
1393 	rphy->irq = platform_get_irq_optional(pdev, 0);
1394 	platform_set_drvdata(pdev, rphy);
1395 
1396 	if (!phy_cfgs)
1397 		return dev_err_probe(dev, -EINVAL, "phy configs are not assigned!\n");
1398 
1399 	ret = rockchip_usb2phy_extcon_register(rphy);
1400 	if (ret)
1401 		return ret;
1402 
1403 	/* find a proper config that can be matched with the DT */
1404 	do {
1405 		if (phy_cfgs[index].reg == reg) {
1406 			rphy->phy_cfg = &phy_cfgs[index];
1407 			break;
1408 		}
1409 
1410 		++index;
1411 	} while (phy_cfgs[index].reg);
1412 
1413 	if (!rphy->phy_cfg) {
1414 		dev_err(dev, "could not find phy config for reg=0x%08x\n", reg);
1415 		return -EINVAL;
1416 	}
1417 
1418 	rphy->phy_reset = devm_reset_control_get_optional(dev, "phy");
1419 	if (IS_ERR(rphy->phy_reset))
1420 		return PTR_ERR(rphy->phy_reset);
1421 
1422 	ret = devm_clk_bulk_get_all(dev, &rphy->clks);
1423 	if (ret == -EPROBE_DEFER)
1424 		return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
1425 				     "failed to get phy clock\n");
1426 
1427 	/* Clocks are optional */
1428 	rphy->num_clks = ret < 0 ? 0 : ret;
1429 
1430 	ret = rockchip_usb2phy_clk480m_register(rphy);
1431 	if (ret)
1432 		return dev_err_probe(dev, ret, "failed to register 480m output clock\n");
1433 
1434 	ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks);
1435 	if (ret)
1436 		return dev_err_probe(dev, ret, "failed to enable phy clock\n");
1437 
1438 	ret = devm_add_action_or_reset(dev, rockchip_usb2phy_clk_bulk_disable, rphy);
1439 	if (ret)
1440 		return ret;
1441 
1442 	if (rphy->phy_cfg->phy_tuning) {
1443 		ret = rphy->phy_cfg->phy_tuning(rphy);
1444 		if (ret)
1445 			return ret;
1446 	}
1447 
1448 	index = 0;
1449 	for_each_available_child_of_node(np, child_np) {
1450 		struct rockchip_usb2phy_port *rport = &rphy->ports[index];
1451 		struct phy *phy;
1452 
1453 		/* This driver aims to support both otg-port and host-port */
1454 		if (!of_node_name_eq(child_np, "host-port") &&
1455 		    !of_node_name_eq(child_np, "otg-port"))
1456 			goto next_child;
1457 
1458 		phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
1459 		if (IS_ERR(phy)) {
1460 			ret = dev_err_probe(dev, PTR_ERR(phy), "failed to create phy\n");
1461 			goto put_child;
1462 		}
1463 
1464 		rport->phy = phy;
1465 		phy_set_drvdata(rport->phy, rport);
1466 
1467 		/* initialize otg/host port separately */
1468 		if (of_node_name_eq(child_np, "host-port")) {
1469 			ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np);
1470 			if (ret)
1471 				goto put_child;
1472 		} else {
1473 			ret = rockchip_usb2phy_otg_port_init(rphy, rport, child_np);
1474 			if (ret)
1475 				goto put_child;
1476 		}
1477 
1478 next_child:
1479 		/* to prevent out of boundary */
1480 		if (++index >= rphy->phy_cfg->num_ports) {
1481 			of_node_put(child_np);
1482 			break;
1483 		}
1484 	}
1485 
1486 	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
1487 
1488 	if (rphy->irq > 0) {
1489 		ret = devm_request_threaded_irq(rphy->dev, rphy->irq, NULL,
1490 						rockchip_usb2phy_irq,
1491 						IRQF_ONESHOT,
1492 						"rockchip_usb2phy",
1493 						rphy);
1494 		if (ret) {
1495 			dev_err_probe(rphy->dev, ret, "failed to request usb2phy irq handle\n");
1496 			return ret;
1497 		}
1498 	}
1499 
1500 	return PTR_ERR_OR_ZERO(provider);
1501 
1502 put_child:
1503 	of_node_put(child_np);
1504 	return ret;
1505 }
1506 
1507 static int rk3128_usb2phy_tuning(struct rockchip_usb2phy *rphy)
1508 {
1509 	/* Turn off differential receiver in suspend mode */
1510 	return regmap_write_bits(rphy->grf, 0x298,
1511 				BIT(2) << BIT_WRITEABLE_SHIFT | BIT(2),
1512 				BIT(2) << BIT_WRITEABLE_SHIFT | 0);
1513 }
1514 
1515 static int rk3528_usb2phy_tuning(struct rockchip_usb2phy *rphy)
1516 {
1517 	int ret;
1518 
1519 	/* Turn off otg port differential receiver in suspend mode */
1520 	ret = regmap_write(rphy->phy_base, 0x30, BIT(18) | 0x0000);
1521 	if (ret)
1522 		return ret;
1523 
1524 	/* Turn off host port differential receiver in suspend mode */
1525 	ret = regmap_write(rphy->phy_base, 0x430, BIT(18) | 0x0000);
1526 	if (ret)
1527 		return ret;
1528 
1529 	/* Set otg port HS eye height to 400mv (default is 450mv) */
1530 	ret = regmap_write(rphy->phy_base, 0x30, GENMASK(22, 20) | 0x0000);
1531 	if (ret)
1532 		return ret;
1533 
1534 	/* Set host port HS eye height to 400mv (default is 450mv) */
1535 	ret = regmap_write(rphy->phy_base, 0x430, GENMASK(22, 20) | 0x0000);
1536 	if (ret)
1537 		return ret;
1538 
1539 	/* Choose the Tx fs/ls data as linestate from TX driver for otg port */
1540 	ret = regmap_write(rphy->phy_base, 0x94, GENMASK(22, 19) | 0x0018);
1541 	if (ret)
1542 		return ret;
1543 
1544 	return 0;
1545 }
1546 
1547 static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy)
1548 {
1549 	int ret;
1550 	u32 reg = rphy->phy_cfg->reg;
1551 
1552 	/* Deassert SIDDQ to power on analog block */
1553 	ret = regmap_write(rphy->grf, reg + 0x0010, GENMASK(29, 29) | 0x0000);
1554 	if (ret)
1555 		return ret;
1556 
1557 	/* Do reset after exit IDDQ mode */
1558 	ret = rockchip_usb2phy_reset(rphy);
1559 	if (ret)
1560 		return ret;
1561 
1562 	/* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */
1563 	ret |= regmap_write(rphy->grf, reg + 0x000c, GENMASK(27, 24) | 0x0900);
1564 
1565 	/* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */
1566 	ret |= regmap_write(rphy->grf, reg + 0x0010, GENMASK(20, 19) | 0x0010);
1567 
1568 	return ret;
1569 }
1570 
1571 static int rk3588_usb2phy_tuning(struct rockchip_usb2phy *rphy)
1572 {
1573 	int ret;
1574 	bool usb3otg = false;
1575 	/*
1576 	 * utmi_termselect = 1'b1 (en FS terminations)
1577 	 * utmi_xcvrselect = 2'b01 (FS transceiver)
1578 	 */
1579 	int suspend_cfg = 0x14;
1580 
1581 	if (rphy->phy_cfg->reg == 0x0000 || rphy->phy_cfg->reg == 0x4000) {
1582 		/* USB2 config for USB3_0 and USB3_1 */
1583 		suspend_cfg |= 0x01; /* utmi_opmode = 2'b01 (no-driving) */
1584 		usb3otg = true;
1585 	} else if (rphy->phy_cfg->reg == 0x8000 || rphy->phy_cfg->reg == 0xc000) {
1586 		/* USB2 config for USB2_0 and USB2_1 */
1587 		suspend_cfg |= 0x00; /* utmi_opmode = 2'b00 (normal) */
1588 	} else {
1589 		return -EINVAL;
1590 	}
1591 
1592 	/* Deassert SIDDQ to power on analog block */
1593 	ret = regmap_write(rphy->grf, 0x0008, GENMASK(29, 29) | 0x0000);
1594 	if (ret)
1595 		return ret;
1596 
1597 	/* Do reset after exit IDDQ mode */
1598 	ret = rockchip_usb2phy_reset(rphy);
1599 	if (ret)
1600 		return ret;
1601 
1602 	/* suspend configuration */
1603 	ret |= regmap_write(rphy->grf, 0x000c, GENMASK(20, 16) | suspend_cfg);
1604 
1605 	/* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */
1606 	ret |= regmap_write(rphy->grf, 0x0004, GENMASK(27, 24) | 0x0900);
1607 
1608 	/* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */
1609 	ret |= regmap_write(rphy->grf, 0x0008, GENMASK(20, 19) | 0x0010);
1610 
1611 	if (!usb3otg)
1612 		return ret;
1613 
1614 	/* Pullup iddig pin for USB3_0 OTG mode */
1615 	ret |= regmap_write(rphy->grf, 0x0010, GENMASK(17, 16) | 0x0003);
1616 
1617 	return ret;
1618 }
1619 
1620 static const struct rockchip_usb2phy_cfg rk3036_phy_cfgs[] = {
1621 	{
1622 		.reg = 0x17c,
1623 		.num_ports	= 2,
1624 		.phy_tuning	= rk3128_usb2phy_tuning,
1625 		.clkout_ctl	= { 0x017c, 11, 11, 1, 0 },
1626 		.port_cfgs	= {
1627 			[USB2PHY_PORT_OTG] = {
1628 				.phy_sus	= { 0x017c, 8, 0, 0, 0x1d1 },
1629 				.bvalid_det_en	= { 0x017c, 14, 14, 0, 1 },
1630 				.bvalid_det_st	= { 0x017c, 15, 15, 0, 1 },
1631 				.bvalid_det_clr	= { 0x017c, 15, 15, 0, 1 },
1632 				.ls_det_en	= { 0x017c, 12, 12, 0, 1 },
1633 				.ls_det_st	= { 0x017c, 13, 13, 0, 1 },
1634 				.ls_det_clr	= { 0x017c, 13, 13, 0, 1 },
1635 				.utmi_bvalid	= { 0x014c, 8, 8, 0, 1 },
1636 				.utmi_id	= { 0x014c, 11, 11, 0, 1 },
1637 				.utmi_ls	= { 0x014c, 10, 9, 0, 1 },
1638 
1639 			},
1640 			[USB2PHY_PORT_HOST] = {
1641 				.phy_sus	= { 0x0194, 8, 0, 0, 0x1d1 },
1642 				.ls_det_en	= { 0x0194, 14, 14, 0, 1 },
1643 				.ls_det_st	= { 0x0194, 15, 15, 0, 1 },
1644 				.ls_det_clr	= { 0x0194, 15, 15, 0, 1 }
1645 			}
1646 		},
1647 	},
1648 	{ /* sentinel */ }
1649 };
1650 
1651 static const struct rockchip_usb2phy_cfg rk3128_phy_cfgs[] = {
1652 	{
1653 		.reg = 0x17c,
1654 		.num_ports	= 2,
1655 		.phy_tuning	= rk3128_usb2phy_tuning,
1656 		.clkout_ctl	= { 0x0190, 15, 15, 1, 0 },
1657 		.port_cfgs	= {
1658 			[USB2PHY_PORT_OTG] = {
1659 				.phy_sus	= { 0x017c, 8, 0, 0, 0x1d1 },
1660 				.bvalid_det_en	= { 0x017c, 14, 14, 0, 1 },
1661 				.bvalid_det_st	= { 0x017c, 15, 15, 0, 1 },
1662 				.bvalid_det_clr	= { 0x017c, 15, 15, 0, 1 },
1663 				.idfall_det_en  = { 0x01a0, 2, 2, 0, 1 },
1664 				.idfall_det_st  = { 0x01a0, 3, 3, 0, 1 },
1665 				.idfall_det_clr = { 0x01a0, 3, 3, 0, 1 },
1666 				.idrise_det_en  = { 0x01a0, 0, 0, 0, 1 },
1667 				.idrise_det_st  = { 0x01a0, 1, 1, 0, 1 },
1668 				.idrise_det_clr = { 0x01a0, 1, 1, 0, 1 },
1669 				.ls_det_en	= { 0x017c, 12, 12, 0, 1 },
1670 				.ls_det_st	= { 0x017c, 13, 13, 0, 1 },
1671 				.ls_det_clr	= { 0x017c, 13, 13, 0, 1 },
1672 				.utmi_bvalid	= { 0x014c, 5, 5, 0, 1 },
1673 				.utmi_id	= { 0x014c, 8, 8, 0, 1 },
1674 				.utmi_ls	= { 0x014c, 7, 6, 0, 1 },
1675 			},
1676 			[USB2PHY_PORT_HOST] = {
1677 				.phy_sus	= { 0x0194, 8, 0, 0, 0x1d1 },
1678 				.ls_det_en	= { 0x0194, 14, 14, 0, 1 },
1679 				.ls_det_st	= { 0x0194, 15, 15, 0, 1 },
1680 				.ls_det_clr	= { 0x0194, 15, 15, 0, 1 }
1681 			}
1682 		},
1683 		.chg_det = {
1684 			.opmode		= { 0x017c, 3, 0, 5, 1 },
1685 			.cp_det		= { 0x02c0, 6, 6, 0, 1 },
1686 			.dcp_det	= { 0x02c0, 5, 5, 0, 1 },
1687 			.dp_det		= { 0x02c0, 7, 7, 0, 1 },
1688 			.idm_sink_en	= { 0x0184, 8, 8, 0, 1 },
1689 			.idp_sink_en	= { 0x0184, 7, 7, 0, 1 },
1690 			.idp_src_en	= { 0x0184, 9, 9, 0, 1 },
1691 			.rdm_pdwn_en	= { 0x0184, 10, 10, 0, 1 },
1692 			.vdm_src_en	= { 0x0184, 12, 12, 0, 1 },
1693 			.vdp_src_en	= { 0x0184, 11, 11, 0, 1 },
1694 		},
1695 	},
1696 	{ /* sentinel */ }
1697 };
1698 
1699 static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
1700 	{
1701 		.reg = 0x760,
1702 		.num_ports	= 2,
1703 		.clkout_ctl	= { 0x0768, 4, 4, 1, 0 },
1704 		.port_cfgs	= {
1705 			[USB2PHY_PORT_OTG] = {
1706 				.phy_sus	= { 0x0760, 15, 0, 0, 0x1d1 },
1707 				.bvalid_det_en	= { 0x0680, 3, 3, 0, 1 },
1708 				.bvalid_det_st	= { 0x0690, 3, 3, 0, 1 },
1709 				.bvalid_det_clr	= { 0x06a0, 3, 3, 0, 1 },
1710 				.idfall_det_en	= { 0x0680, 6, 6, 0, 1 },
1711 				.idfall_det_st	= { 0x0690, 6, 6, 0, 1 },
1712 				.idfall_det_clr	= { 0x06a0, 6, 6, 0, 1 },
1713 				.idrise_det_en	= { 0x0680, 5, 5, 0, 1 },
1714 				.idrise_det_st	= { 0x0690, 5, 5, 0, 1 },
1715 				.idrise_det_clr	= { 0x06a0, 5, 5, 0, 1 },
1716 				.ls_det_en	= { 0x0680, 2, 2, 0, 1 },
1717 				.ls_det_st	= { 0x0690, 2, 2, 0, 1 },
1718 				.ls_det_clr	= { 0x06a0, 2, 2, 0, 1 },
1719 				.utmi_bvalid	= { 0x0480, 4, 4, 0, 1 },
1720 				.utmi_id	= { 0x0480, 1, 1, 0, 1 },
1721 				.utmi_ls	= { 0x0480, 3, 2, 0, 1 },
1722 			},
1723 			[USB2PHY_PORT_HOST] = {
1724 				.phy_sus	= { 0x0764, 15, 0, 0, 0x1d1 },
1725 				.ls_det_en	= { 0x0680, 4, 4, 0, 1 },
1726 				.ls_det_st	= { 0x0690, 4, 4, 0, 1 },
1727 				.ls_det_clr	= { 0x06a0, 4, 4, 0, 1 }
1728 			}
1729 		},
1730 		.chg_det = {
1731 			.opmode		= { 0x0760, 3, 0, 5, 1 },
1732 			.cp_det		= { 0x0884, 4, 4, 0, 1 },
1733 			.dcp_det	= { 0x0884, 3, 3, 0, 1 },
1734 			.dp_det		= { 0x0884, 5, 5, 0, 1 },
1735 			.idm_sink_en	= { 0x0768, 8, 8, 0, 1 },
1736 			.idp_sink_en	= { 0x0768, 7, 7, 0, 1 },
1737 			.idp_src_en	= { 0x0768, 9, 9, 0, 1 },
1738 			.rdm_pdwn_en	= { 0x0768, 10, 10, 0, 1 },
1739 			.vdm_src_en	= { 0x0768, 12, 12, 0, 1 },
1740 			.vdp_src_en	= { 0x0768, 11, 11, 0, 1 },
1741 		},
1742 	},
1743 	{
1744 		.reg = 0x800,
1745 		.num_ports	= 2,
1746 		.clkout_ctl	= { 0x0808, 4, 4, 1, 0 },
1747 		.port_cfgs	= {
1748 			[USB2PHY_PORT_OTG] = {
1749 				.phy_sus	= { 0x800, 15, 0, 0, 0x1d1 },
1750 				.ls_det_en	= { 0x0684, 0, 0, 0, 1 },
1751 				.ls_det_st	= { 0x0694, 0, 0, 0, 1 },
1752 				.ls_det_clr	= { 0x06a4, 0, 0, 0, 1 }
1753 			},
1754 			[USB2PHY_PORT_HOST] = {
1755 				.phy_sus	= { 0x804, 15, 0, 0, 0x1d1 },
1756 				.ls_det_en	= { 0x0684, 1, 1, 0, 1 },
1757 				.ls_det_st	= { 0x0694, 1, 1, 0, 1 },
1758 				.ls_det_clr	= { 0x06a4, 1, 1, 0, 1 }
1759 			}
1760 		},
1761 	},
1762 	{ /* sentinel */ }
1763 };
1764 
1765 static const struct rockchip_usb2phy_cfg rk3308_phy_cfgs[] = {
1766 	{
1767 		.reg = 0x100,
1768 		.num_ports	= 2,
1769 		.clkout_ctl	= { 0x108, 4, 4, 1, 0 },
1770 		.port_cfgs	= {
1771 			[USB2PHY_PORT_OTG] = {
1772 				.phy_sus	= { 0x0100, 8, 0, 0, 0x1d1 },
1773 				.bvalid_det_en	= { 0x3020, 3, 2, 0, 3 },
1774 				.bvalid_det_st	= { 0x3024, 3, 2, 0, 3 },
1775 				.bvalid_det_clr = { 0x3028, 3, 2, 0, 3 },
1776 				.idfall_det_en	= { 0x3020, 5, 5, 0, 1 },
1777 				.idfall_det_st	= { 0x3024, 5, 5, 0, 1 },
1778 				.idfall_det_clr = { 0x3028, 5, 5, 0, 1 },
1779 				.idrise_det_en	= { 0x3020, 4, 4, 0, 1 },
1780 				.idrise_det_st	= { 0x3024, 4, 4, 0, 1 },
1781 				.idrise_det_clr = { 0x3028, 4, 4, 0, 1 },
1782 				.ls_det_en	= { 0x3020, 0, 0, 0, 1 },
1783 				.ls_det_st	= { 0x3024, 0, 0, 0, 1 },
1784 				.ls_det_clr	= { 0x3028, 0, 0, 0, 1 },
1785 				.utmi_avalid	= { 0x0120, 10, 10, 0, 1 },
1786 				.utmi_bvalid	= { 0x0120, 9, 9, 0, 1 },
1787 				.utmi_id	= { 0x0120, 6, 6, 0, 1 },
1788 				.utmi_ls	= { 0x0120, 5, 4, 0, 1 },
1789 			},
1790 			[USB2PHY_PORT_HOST] = {
1791 				.phy_sus	= { 0x0104, 8, 0, 0, 0x1d1 },
1792 				.ls_det_en	= { 0x3020, 1, 1, 0, 1 },
1793 				.ls_det_st	= { 0x3024, 1, 1, 0, 1 },
1794 				.ls_det_clr	= { 0x3028, 1, 1, 0, 1 },
1795 				.utmi_ls	= { 0x0120, 17, 16, 0, 1 },
1796 				.utmi_hstdet	= { 0x0120, 19, 19, 0, 1 }
1797 			}
1798 		},
1799 		.chg_det = {
1800 			.opmode		= { 0x0100, 3, 0, 5, 1 },
1801 			.cp_det		= { 0x0120, 24, 24, 0, 1 },
1802 			.dcp_det	= { 0x0120, 23, 23, 0, 1 },
1803 			.dp_det		= { 0x0120, 25, 25, 0, 1 },
1804 			.idm_sink_en	= { 0x0108, 8, 8, 0, 1 },
1805 			.idp_sink_en	= { 0x0108, 7, 7, 0, 1 },
1806 			.idp_src_en	= { 0x0108, 9, 9, 0, 1 },
1807 			.rdm_pdwn_en	= { 0x0108, 10, 10, 0, 1 },
1808 			.vdm_src_en	= { 0x0108, 12, 12, 0, 1 },
1809 			.vdp_src_en	= { 0x0108, 11, 11, 0, 1 },
1810 		},
1811 	},
1812 	{ /* sentinel */ }
1813 };
1814 
1815 static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
1816 	{
1817 		.reg = 0x100,
1818 		.num_ports	= 2,
1819 		.clkout_ctl	= { 0x108, 4, 4, 1, 0 },
1820 		.port_cfgs	= {
1821 			[USB2PHY_PORT_OTG] = {
1822 				.phy_sus	= { 0x0100, 15, 0, 0, 0x1d1 },
1823 				.bvalid_det_en	= { 0x0110, 3, 2, 0, 3 },
1824 				.bvalid_det_st	= { 0x0114, 3, 2, 0, 3 },
1825 				.bvalid_det_clr = { 0x0118, 3, 2, 0, 3 },
1826 				.idfall_det_en	= { 0x0110, 5, 5, 0, 1 },
1827 				.idfall_det_st	= { 0x0114, 5, 5, 0, 1 },
1828 				.idfall_det_clr = { 0x0118, 5, 5, 0, 1 },
1829 				.idrise_det_en	= { 0x0110, 4, 4, 0, 1 },
1830 				.idrise_det_st	= { 0x0114, 4, 4, 0, 1 },
1831 				.idrise_det_clr = { 0x0118, 4, 4, 0, 1 },
1832 				.ls_det_en	= { 0x0110, 0, 0, 0, 1 },
1833 				.ls_det_st	= { 0x0114, 0, 0, 0, 1 },
1834 				.ls_det_clr	= { 0x0118, 0, 0, 0, 1 },
1835 				.utmi_avalid	= { 0x0120, 10, 10, 0, 1 },
1836 				.utmi_bvalid	= { 0x0120, 9, 9, 0, 1 },
1837 				.utmi_id	= { 0x0120, 6, 6, 0, 1 },
1838 				.utmi_ls	= { 0x0120, 5, 4, 0, 1 },
1839 			},
1840 			[USB2PHY_PORT_HOST] = {
1841 				.phy_sus	= { 0x104, 15, 0, 0, 0x1d1 },
1842 				.ls_det_en	= { 0x110, 1, 1, 0, 1 },
1843 				.ls_det_st	= { 0x114, 1, 1, 0, 1 },
1844 				.ls_det_clr	= { 0x118, 1, 1, 0, 1 },
1845 				.utmi_ls	= { 0x120, 17, 16, 0, 1 },
1846 				.utmi_hstdet	= { 0x120, 19, 19, 0, 1 }
1847 			}
1848 		},
1849 		.chg_det = {
1850 			.opmode		= { 0x0100, 3, 0, 5, 1 },
1851 			.cp_det		= { 0x0120, 24, 24, 0, 1 },
1852 			.dcp_det	= { 0x0120, 23, 23, 0, 1 },
1853 			.dp_det		= { 0x0120, 25, 25, 0, 1 },
1854 			.idm_sink_en	= { 0x0108, 8, 8, 0, 1 },
1855 			.idp_sink_en	= { 0x0108, 7, 7, 0, 1 },
1856 			.idp_src_en	= { 0x0108, 9, 9, 0, 1 },
1857 			.rdm_pdwn_en	= { 0x0108, 10, 10, 0, 1 },
1858 			.vdm_src_en	= { 0x0108, 12, 12, 0, 1 },
1859 			.vdp_src_en	= { 0x0108, 11, 11, 0, 1 },
1860 		},
1861 	},
1862 	{ /* sentinel */ }
1863 };
1864 
1865 static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = {
1866 	{
1867 		.reg = 0x700,
1868 		.num_ports	= 2,
1869 		.clkout_ctl	= { 0x0724, 15, 15, 1, 0 },
1870 		.port_cfgs	= {
1871 			[USB2PHY_PORT_HOST] = {
1872 				.phy_sus	= { 0x0728, 15, 0, 0, 0x1d1 },
1873 				.ls_det_en	= { 0x0680, 4, 4, 0, 1 },
1874 				.ls_det_st	= { 0x0690, 4, 4, 0, 1 },
1875 				.ls_det_clr	= { 0x06a0, 4, 4, 0, 1 },
1876 				.utmi_ls	= { 0x049c, 14, 13, 0, 1 },
1877 				.utmi_hstdet	= { 0x049c, 12, 12, 0, 1 }
1878 			}
1879 		},
1880 	},
1881 	{ /* sentinel */ }
1882 };
1883 
1884 static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
1885 	{
1886 		.reg		= 0xe450,
1887 		.num_ports	= 2,
1888 		.clkout_ctl	= { 0xe450, 4, 4, 1, 0 },
1889 		.port_cfgs	= {
1890 			[USB2PHY_PORT_OTG] = {
1891 				.phy_sus	= { 0xe454, 1, 0, 2, 1 },
1892 				.bvalid_det_en	= { 0xe3c0, 3, 3, 0, 1 },
1893 				.bvalid_det_st	= { 0xe3e0, 3, 3, 0, 1 },
1894 				.bvalid_det_clr	= { 0xe3d0, 3, 3, 0, 1 },
1895 				.idfall_det_en	= { 0xe3c0, 5, 5, 0, 1 },
1896 				.idfall_det_st	= { 0xe3e0, 5, 5, 0, 1 },
1897 				.idfall_det_clr	= { 0xe3d0, 5, 5, 0, 1 },
1898 				.idrise_det_en	= { 0xe3c0, 4, 4, 0, 1 },
1899 				.idrise_det_st	= { 0xe3e0, 4, 4, 0, 1 },
1900 				.idrise_det_clr	= { 0xe3d0, 4, 4, 0, 1 },
1901 				.utmi_avalid	= { 0xe2ac, 7, 7, 0, 1 },
1902 				.utmi_bvalid	= { 0xe2ac, 12, 12, 0, 1 },
1903 				.utmi_id	= { 0xe2ac, 8, 8, 0, 1 },
1904 			},
1905 			[USB2PHY_PORT_HOST] = {
1906 				.phy_sus	= { 0xe458, 1, 0, 0x2, 0x1 },
1907 				.ls_det_en	= { 0xe3c0, 6, 6, 0, 1 },
1908 				.ls_det_st	= { 0xe3e0, 6, 6, 0, 1 },
1909 				.ls_det_clr	= { 0xe3d0, 6, 6, 0, 1 },
1910 				.utmi_ls	= { 0xe2ac, 22, 21, 0, 1 },
1911 				.utmi_hstdet	= { 0xe2ac, 23, 23, 0, 1 }
1912 			}
1913 		},
1914 		.chg_det = {
1915 			.opmode		= { 0xe454, 3, 0, 5, 1 },
1916 			.cp_det		= { 0xe2ac, 2, 2, 0, 1 },
1917 			.dcp_det	= { 0xe2ac, 1, 1, 0, 1 },
1918 			.dp_det		= { 0xe2ac, 0, 0, 0, 1 },
1919 			.idm_sink_en	= { 0xe450, 8, 8, 0, 1 },
1920 			.idp_sink_en	= { 0xe450, 7, 7, 0, 1 },
1921 			.idp_src_en	= { 0xe450, 9, 9, 0, 1 },
1922 			.rdm_pdwn_en	= { 0xe450, 10, 10, 0, 1 },
1923 			.vdm_src_en	= { 0xe450, 12, 12, 0, 1 },
1924 			.vdp_src_en	= { 0xe450, 11, 11, 0, 1 },
1925 		},
1926 	},
1927 	{
1928 		.reg		= 0xe460,
1929 		.num_ports	= 2,
1930 		.clkout_ctl	= { 0xe460, 4, 4, 1, 0 },
1931 		.port_cfgs	= {
1932 			[USB2PHY_PORT_OTG] = {
1933 				.phy_sus        = { 0xe464, 1, 0, 2, 1 },
1934 				.bvalid_det_en  = { 0xe3c0, 8, 8, 0, 1 },
1935 				.bvalid_det_st  = { 0xe3e0, 8, 8, 0, 1 },
1936 				.bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
1937 				.idfall_det_en	= { 0xe3c0, 10, 10, 0, 1 },
1938 				.idfall_det_st	= { 0xe3e0, 10, 10, 0, 1 },
1939 				.idfall_det_clr	= { 0xe3d0, 10, 10, 0, 1 },
1940 				.idrise_det_en	= { 0xe3c0, 9, 9, 0, 1 },
1941 				.idrise_det_st	= { 0xe3e0, 9, 9, 0, 1 },
1942 				.idrise_det_clr	= { 0xe3d0, 9, 9, 0, 1 },
1943 				.utmi_avalid	= { 0xe2ac, 10, 10, 0, 1 },
1944 				.utmi_bvalid    = { 0xe2ac, 16, 16, 0, 1 },
1945 				.utmi_id	= { 0xe2ac, 11, 11, 0, 1 },
1946 			},
1947 			[USB2PHY_PORT_HOST] = {
1948 				.phy_sus	= { 0xe468, 1, 0, 0x2, 0x1 },
1949 				.ls_det_en	= { 0xe3c0, 11, 11, 0, 1 },
1950 				.ls_det_st	= { 0xe3e0, 11, 11, 0, 1 },
1951 				.ls_det_clr	= { 0xe3d0, 11, 11, 0, 1 },
1952 				.utmi_ls	= { 0xe2ac, 26, 25, 0, 1 },
1953 				.utmi_hstdet	= { 0xe2ac, 27, 27, 0, 1 }
1954 			}
1955 		},
1956 	},
1957 	{ /* sentinel */ }
1958 };
1959 
1960 static const struct rockchip_usb2phy_cfg rk3528_phy_cfgs[] = {
1961 	{
1962 		.reg = 0xffdf0000,
1963 		.num_ports	= 2,
1964 		.phy_tuning	= rk3528_usb2phy_tuning,
1965 		.clkout_ctl_phy	= { 0x041c, 7, 2, 0, 0x27 },
1966 		.port_cfgs	= {
1967 			[USB2PHY_PORT_OTG] = {
1968 				.phy_sus	= { 0x004c, 8, 0, 0, 0x1d1 },
1969 				.bvalid_det_en	= { 0x0074, 3, 2, 0, 3 },
1970 				.bvalid_det_st	= { 0x0078, 3, 2, 0, 3 },
1971 				.bvalid_det_clr	= { 0x007c, 3, 2, 0, 3 },
1972 				.idfall_det_en	= { 0x0074, 5, 5, 0, 1 },
1973 				.idfall_det_st	= { 0x0078, 5, 5, 0, 1 },
1974 				.idfall_det_clr	= { 0x007c, 5, 5, 0, 1 },
1975 				.idrise_det_en	= { 0x0074, 4, 4, 0, 1 },
1976 				.idrise_det_st	= { 0x0078, 4, 4, 0, 1 },
1977 				.idrise_det_clr	= { 0x007c, 4, 4, 0, 1 },
1978 				.ls_det_en	= { 0x0074, 0, 0, 0, 1 },
1979 				.ls_det_st	= { 0x0078, 0, 0, 0, 1 },
1980 				.ls_det_clr	= { 0x007c, 0, 0, 0, 1 },
1981 				.utmi_avalid	= { 0x006c, 1, 1, 0, 1 },
1982 				.utmi_bvalid	= { 0x006c, 0, 0, 0, 1 },
1983 				.utmi_id	= { 0x006c, 6, 6, 0, 1 },
1984 				.utmi_ls	= { 0x006c, 5, 4, 0, 1 },
1985 			},
1986 			[USB2PHY_PORT_HOST] = {
1987 				.phy_sus	= { 0x005c, 8, 0, 0x1d2, 0x1d1 },
1988 				.ls_det_en	= { 0x0090, 0, 0, 0, 1 },
1989 				.ls_det_st	= { 0x0094, 0, 0, 0, 1 },
1990 				.ls_det_clr	= { 0x0098, 0, 0, 0, 1 },
1991 				.utmi_ls	= { 0x006c, 13, 12, 0, 1 },
1992 				.utmi_hstdet	= { 0x006c, 15, 15, 0, 1 },
1993 			}
1994 		},
1995 		.chg_det = {
1996 			.opmode		= { 0x004c, 3, 0, 5, 1 },
1997 			.cp_det		= { 0x006c, 19, 19, 0, 1 },
1998 			.dcp_det	= { 0x006c, 18, 18, 0, 1 },
1999 			.dp_det		= { 0x006c, 20, 20, 0, 1 },
2000 			.idm_sink_en	= { 0x0058, 1, 1, 0, 1 },
2001 			.idp_sink_en	= { 0x0058, 0, 0, 0, 1 },
2002 			.idp_src_en	= { 0x0058, 2, 2, 0, 1 },
2003 			.rdm_pdwn_en	= { 0x0058, 3, 3, 0, 1 },
2004 			.vdm_src_en	= { 0x0058, 5, 5, 0, 1 },
2005 			.vdp_src_en	= { 0x0058, 4, 4, 0, 1 },
2006 		},
2007 	},
2008 	{ /* sentinel */ }
2009 };
2010 
2011 static const struct rockchip_usb2phy_cfg rk3562_phy_cfgs[] = {
2012 	{
2013 		.reg = 0xff740000,
2014 		.num_ports	= 2,
2015 		.clkout_ctl	= { 0x0108, 4, 4, 1, 0 },
2016 		.port_cfgs	= {
2017 			[USB2PHY_PORT_OTG] = {
2018 				.phy_sus	= { 0x0100, 8, 0, 0, 0x1d1 },
2019 				.bvalid_det_en	= { 0x0110, 2, 2, 0, 1 },
2020 				.bvalid_det_st	= { 0x0114, 2, 2, 0, 1 },
2021 				.bvalid_det_clr = { 0x0118, 2, 2, 0, 1 },
2022 				.idfall_det_en	= { 0x0110, 5, 5, 0, 1 },
2023 				.idfall_det_st	= { 0x0114, 5, 5, 0, 1 },
2024 				.idfall_det_clr = { 0x0118, 5, 5, 0, 1 },
2025 				.idrise_det_en	= { 0x0110, 4, 4, 0, 1 },
2026 				.idrise_det_st	= { 0x0114, 4, 4, 0, 1 },
2027 				.idrise_det_clr = { 0x0118, 4, 4, 0, 1 },
2028 				.ls_det_en	= { 0x0110, 0, 0, 0, 1 },
2029 				.ls_det_st	= { 0x0114, 0, 0, 0, 1 },
2030 				.ls_det_clr	= { 0x0118, 0, 0, 0, 1 },
2031 				.utmi_avalid	= { 0x0120, 10, 10, 0, 1 },
2032 				.utmi_bvalid	= { 0x0120, 9, 9, 0, 1 },
2033 				.utmi_ls	= { 0x0120, 5, 4, 0, 1 },
2034 			},
2035 			[USB2PHY_PORT_HOST] = {
2036 				.phy_sus	= { 0x0104, 8, 0, 0x1d2, 0x1d1 },
2037 				.ls_det_en	= { 0x0110, 1, 1, 0, 1 },
2038 				.ls_det_st	= { 0x0114, 1, 1, 0, 1 },
2039 				.ls_det_clr	= { 0x0118, 1, 1, 0, 1 },
2040 				.utmi_ls	= { 0x0120, 17, 16, 0, 1 },
2041 				.utmi_hstdet	= { 0x0120, 19, 19, 0, 1 }
2042 			}
2043 		},
2044 		.chg_det = {
2045 			.cp_det		= { 0x0120, 24, 24, 0, 1 },
2046 			.dcp_det	= { 0x0120, 23, 23, 0, 1 },
2047 			.dp_det		= { 0x0120, 25, 25, 0, 1 },
2048 			.idm_sink_en	= { 0x0108, 8, 8, 0, 1 },
2049 			.idp_sink_en	= { 0x0108, 7, 7, 0, 1 },
2050 			.idp_src_en	= { 0x0108, 9, 9, 0, 1 },
2051 			.rdm_pdwn_en	= { 0x0108, 10, 10, 0, 1 },
2052 			.vdm_src_en	= { 0x0108, 12, 12, 0, 1 },
2053 			.vdp_src_en	= { 0x0108, 11, 11, 0, 1 },
2054 		},
2055 	},
2056 	{ /* sentinel */ }
2057 };
2058 
2059 static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = {
2060 	{
2061 		.reg = 0xfe8a0000,
2062 		.num_ports	= 2,
2063 		.clkout_ctl	= { 0x0008, 4, 4, 1, 0 },
2064 		.port_cfgs	= {
2065 			[USB2PHY_PORT_OTG] = {
2066 				.phy_sus	= { 0x0000, 8, 0, 0, 0x1d1 },
2067 				.bvalid_det_en	= { 0x0080, 3, 2, 0, 3 },
2068 				.bvalid_det_st	= { 0x0084, 3, 2, 0, 3 },
2069 				.bvalid_det_clr = { 0x0088, 3, 2, 0, 3 },
2070 				.idfall_det_en	= { 0x0080, 5, 5, 0, 1 },
2071 				.idfall_det_st	= { 0x0084, 5, 5, 0, 1 },
2072 				.idfall_det_clr	= { 0x0088, 5, 5, 0, 1 },
2073 				.idrise_det_en	= { 0x0080, 4, 4, 0, 1 },
2074 				.idrise_det_st	= { 0x0084, 4, 4, 0, 1 },
2075 				.idrise_det_clr	= { 0x0088, 4, 4, 0, 1 },
2076 				.utmi_avalid	= { 0x00c0, 10, 10, 0, 1 },
2077 				.utmi_bvalid	= { 0x00c0, 9, 9, 0, 1 },
2078 				.utmi_id	= { 0x00c0, 6, 6, 0, 1 },
2079 			},
2080 			[USB2PHY_PORT_HOST] = {
2081 				/* Select suspend control from controller */
2082 				.phy_sus	= { 0x0004, 8, 0, 0x1d2, 0x1d2 },
2083 				.ls_det_en	= { 0x0080, 1, 1, 0, 1 },
2084 				.ls_det_st	= { 0x0084, 1, 1, 0, 1 },
2085 				.ls_det_clr	= { 0x0088, 1, 1, 0, 1 },
2086 				.utmi_ls	= { 0x00c0, 17, 16, 0, 1 },
2087 				.utmi_hstdet	= { 0x00c0, 19, 19, 0, 1 }
2088 			}
2089 		},
2090 		.chg_det = {
2091 			.opmode		= { 0x0000, 3, 0, 5, 1 },
2092 			.cp_det		= { 0x00c0, 24, 24, 0, 1 },
2093 			.dcp_det	= { 0x00c0, 23, 23, 0, 1 },
2094 			.dp_det		= { 0x00c0, 25, 25, 0, 1 },
2095 			.idm_sink_en	= { 0x0008, 8, 8, 0, 1 },
2096 			.idp_sink_en	= { 0x0008, 7, 7, 0, 1 },
2097 			.idp_src_en	= { 0x0008, 9, 9, 0, 1 },
2098 			.rdm_pdwn_en	= { 0x0008, 10, 10, 0, 1 },
2099 			.vdm_src_en	= { 0x0008, 12, 12, 0, 1 },
2100 			.vdp_src_en	= { 0x0008, 11, 11, 0, 1 },
2101 		},
2102 	},
2103 	{
2104 		.reg = 0xfe8b0000,
2105 		.num_ports	= 2,
2106 		.clkout_ctl	= { 0x0008, 4, 4, 1, 0 },
2107 		.port_cfgs	= {
2108 			[USB2PHY_PORT_OTG] = {
2109 				.phy_sus	= { 0x0000, 8, 0, 0x1d2, 0x1d1 },
2110 				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2111 				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2112 				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2113 				.utmi_ls	= { 0x00c0, 5, 4, 0, 1 },
2114 				.utmi_hstdet	= { 0x00c0, 7, 7, 0, 1 }
2115 			},
2116 			[USB2PHY_PORT_HOST] = {
2117 				.phy_sus	= { 0x0004, 8, 0, 0x1d2, 0x1d1 },
2118 				.ls_det_en	= { 0x0080, 1, 1, 0, 1 },
2119 				.ls_det_st	= { 0x0084, 1, 1, 0, 1 },
2120 				.ls_det_clr	= { 0x0088, 1, 1, 0, 1 },
2121 				.utmi_ls	= { 0x00c0, 17, 16, 0, 1 },
2122 				.utmi_hstdet	= { 0x00c0, 19, 19, 0, 1 }
2123 			}
2124 		},
2125 	},
2126 	{ /* sentinel */ }
2127 };
2128 
2129 static const struct rockchip_usb2phy_cfg rk3576_phy_cfgs[] = {
2130 	{
2131 		.reg = 0x0,
2132 		.num_ports	= 1,
2133 		.phy_tuning	= rk3576_usb2phy_tuning,
2134 		.clkout_ctl	= { 0x0008, 0, 0, 1, 0 },
2135 		.port_cfgs	= {
2136 			[USB2PHY_PORT_OTG] = {
2137 				.phy_sus	= { 0x0000, 8, 0, 0, 0x1d1 },
2138 				.bvalid_det_en	= { 0x00c0, 1, 1, 0, 1 },
2139 				.bvalid_det_st	= { 0x00c4, 1, 1, 0, 1 },
2140 				.bvalid_det_clr = { 0x00c8, 1, 1, 0, 1 },
2141 				.ls_det_en	= { 0x00c0, 0, 0, 0, 1 },
2142 				.ls_det_st	= { 0x00c4, 0, 0, 0, 1 },
2143 				.ls_det_clr	= { 0x00c8, 0, 0, 0, 1 },
2144 				.disfall_en	= { 0x00c0, 6, 6, 0, 1 },
2145 				.disfall_st	= { 0x00c4, 6, 6, 0, 1 },
2146 				.disfall_clr	= { 0x00c8, 6, 6, 0, 1 },
2147 				.disrise_en	= { 0x00c0, 5, 5, 0, 1 },
2148 				.disrise_st	= { 0x00c4, 5, 5, 0, 1 },
2149 				.disrise_clr	= { 0x00c8, 5, 5, 0, 1 },
2150 				.utmi_avalid	= { 0x0080, 1, 1, 0, 1 },
2151 				.utmi_bvalid	= { 0x0080, 0, 0, 0, 1 },
2152 				.utmi_ls	= { 0x0080, 5, 4, 0, 1 },
2153 			}
2154 		},
2155 		.chg_det = {
2156 			.cp_det		= { 0x0080, 8, 8, 0, 1 },
2157 			.dcp_det	= { 0x0080, 8, 8, 0, 1 },
2158 			.dp_det		= { 0x0080, 9, 9, 1, 0 },
2159 			.idm_sink_en	= { 0x0010, 5, 5, 1, 0 },
2160 			.idp_sink_en	= { 0x0010, 5, 5, 0, 1 },
2161 			.idp_src_en	= { 0x0010, 14, 14, 0, 1 },
2162 			.rdm_pdwn_en	= { 0x0010, 14, 14, 0, 1 },
2163 			.vdm_src_en	= { 0x0010, 7, 6, 0, 3 },
2164 			.vdp_src_en	= { 0x0010, 7, 6, 0, 3 },
2165 		},
2166 	},
2167 	{
2168 		.reg = 0x2000,
2169 		.num_ports	= 1,
2170 		.phy_tuning	= rk3576_usb2phy_tuning,
2171 		.clkout_ctl	= { 0x2008, 0, 0, 1, 0 },
2172 		.port_cfgs	= {
2173 			[USB2PHY_PORT_OTG] = {
2174 				.phy_sus	= { 0x2000, 8, 0, 0, 0x1d1 },
2175 				.bvalid_det_en	= { 0x20c0, 1, 1, 0, 1 },
2176 				.bvalid_det_st	= { 0x20c4, 1, 1, 0, 1 },
2177 				.bvalid_det_clr = { 0x20c8, 1, 1, 0, 1 },
2178 				.ls_det_en	= { 0x20c0, 0, 0, 0, 1 },
2179 				.ls_det_st	= { 0x20c4, 0, 0, 0, 1 },
2180 				.ls_det_clr	= { 0x20c8, 0, 0, 0, 1 },
2181 				.disfall_en	= { 0x20c0, 6, 6, 0, 1 },
2182 				.disfall_st	= { 0x20c4, 6, 6, 0, 1 },
2183 				.disfall_clr	= { 0x20c8, 6, 6, 0, 1 },
2184 				.disrise_en	= { 0x20c0, 5, 5, 0, 1 },
2185 				.disrise_st	= { 0x20c4, 5, 5, 0, 1 },
2186 				.disrise_clr	= { 0x20c8, 5, 5, 0, 1 },
2187 				.utmi_avalid	= { 0x2080, 1, 1, 0, 1 },
2188 				.utmi_bvalid	= { 0x2080, 0, 0, 0, 1 },
2189 				.utmi_ls	= { 0x2080, 5, 4, 0, 1 },
2190 			}
2191 		},
2192 		.chg_det = {
2193 			.cp_det		= { 0x2080, 8, 8, 0, 1 },
2194 			.dcp_det	= { 0x2080, 8, 8, 0, 1 },
2195 			.dp_det		= { 0x2080, 9, 9, 1, 0 },
2196 			.idm_sink_en	= { 0x2010, 5, 5, 1, 0 },
2197 			.idp_sink_en	= { 0x2010, 5, 5, 0, 1 },
2198 			.idp_src_en	= { 0x2010, 14, 14, 0, 1 },
2199 			.rdm_pdwn_en	= { 0x2010, 14, 14, 0, 1 },
2200 			.vdm_src_en	= { 0x2010, 7, 6, 0, 3 },
2201 			.vdp_src_en	= { 0x2010, 7, 6, 0, 3 },
2202 		},
2203 	},
2204 	{ /* sentinel */ }
2205 };
2206 
2207 static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
2208 	{
2209 		.reg = 0x0000,
2210 		.num_ports	= 1,
2211 		.phy_tuning	= rk3588_usb2phy_tuning,
2212 		.clkout_ctl	= { 0x0000, 0, 0, 1, 0 },
2213 		.port_cfgs	= {
2214 			[USB2PHY_PORT_OTG] = {
2215 				.phy_sus	= { 0x000c, 11, 11, 0, 1 },
2216 				.bvalid_det_en	= { 0x0080, 1, 1, 0, 1 },
2217 				.bvalid_det_st	= { 0x0084, 1, 1, 0, 1 },
2218 				.bvalid_det_clr = { 0x0088, 1, 1, 0, 1 },
2219 				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2220 				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2221 				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2222 				.disfall_en	= { 0x0080, 6, 6, 0, 1 },
2223 				.disfall_st	= { 0x0084, 6, 6, 0, 1 },
2224 				.disfall_clr	= { 0x0088, 6, 6, 0, 1 },
2225 				.disrise_en	= { 0x0080, 5, 5, 0, 1 },
2226 				.disrise_st	= { 0x0084, 5, 5, 0, 1 },
2227 				.disrise_clr	= { 0x0088, 5, 5, 0, 1 },
2228 				.utmi_avalid	= { 0x00c0, 7, 7, 0, 1 },
2229 				.utmi_bvalid	= { 0x00c0, 6, 6, 0, 1 },
2230 				.utmi_ls	= { 0x00c0, 10, 9, 0, 1 },
2231 			}
2232 		},
2233 		.chg_det = {
2234 			.cp_det		= { 0x00c0, 0, 0, 0, 1 },
2235 			.dcp_det	= { 0x00c0, 0, 0, 0, 1 },
2236 			.dp_det		= { 0x00c0, 1, 1, 1, 0 },
2237 			.idm_sink_en	= { 0x0008, 5, 5, 1, 0 },
2238 			.idp_sink_en	= { 0x0008, 5, 5, 0, 1 },
2239 			.idp_src_en	= { 0x0008, 14, 14, 0, 1 },
2240 			.rdm_pdwn_en	= { 0x0008, 14, 14, 0, 1 },
2241 			.vdm_src_en	= { 0x0008, 7, 6, 0, 3 },
2242 			.vdp_src_en	= { 0x0008, 7, 6, 0, 3 },
2243 		},
2244 	},
2245 	{
2246 		.reg = 0x4000,
2247 		.num_ports	= 1,
2248 		.phy_tuning	= rk3588_usb2phy_tuning,
2249 		.clkout_ctl	= { 0x0000, 0, 0, 1, 0 },
2250 		.port_cfgs	= {
2251 			[USB2PHY_PORT_OTG] = {
2252 				.phy_sus	= { 0x000c, 11, 11, 0, 1 },
2253 				.bvalid_det_en	= { 0x0080, 1, 1, 0, 1 },
2254 				.bvalid_det_st	= { 0x0084, 1, 1, 0, 1 },
2255 				.bvalid_det_clr = { 0x0088, 1, 1, 0, 1 },
2256 				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2257 				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2258 				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2259 				.disfall_en	= { 0x0080, 6, 6, 0, 1 },
2260 				.disfall_st	= { 0x0084, 6, 6, 0, 1 },
2261 				.disfall_clr	= { 0x0088, 6, 6, 0, 1 },
2262 				.disrise_en	= { 0x0080, 5, 5, 0, 1 },
2263 				.disrise_st	= { 0x0084, 5, 5, 0, 1 },
2264 				.disrise_clr	= { 0x0088, 5, 5, 0, 1 },
2265 				.utmi_avalid	= { 0x00c0, 7, 7, 0, 1 },
2266 				.utmi_bvalid	= { 0x00c0, 6, 6, 0, 1 },
2267 				.utmi_ls	= { 0x00c0, 10, 9, 0, 1 },
2268 			}
2269 		},
2270 		.chg_det = {
2271 			.cp_det		= { 0x00c0, 0, 0, 0, 1 },
2272 			.dcp_det	= { 0x00c0, 0, 0, 0, 1 },
2273 			.dp_det		= { 0x00c0, 1, 1, 1, 0 },
2274 			.idm_sink_en	= { 0x0008, 5, 5, 1, 0 },
2275 			.idp_sink_en	= { 0x0008, 5, 5, 0, 1 },
2276 			.idp_src_en	= { 0x0008, 14, 14, 0, 1 },
2277 			.rdm_pdwn_en	= { 0x0008, 14, 14, 0, 1 },
2278 			.vdm_src_en	= { 0x0008, 7, 6, 0, 3 },
2279 			.vdp_src_en	= { 0x0008, 7, 6, 0, 3 },
2280 		},
2281 	},
2282 	{
2283 		.reg = 0x8000,
2284 		.num_ports	= 1,
2285 		.phy_tuning	= rk3588_usb2phy_tuning,
2286 		.clkout_ctl	= { 0x0000, 0, 0, 1, 0 },
2287 		.port_cfgs	= {
2288 			[USB2PHY_PORT_HOST] = {
2289 				.phy_sus	= { 0x0008, 2, 2, 0, 1 },
2290 				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2291 				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2292 				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2293 				.disfall_en	= { 0x0080, 6, 6, 0, 1 },
2294 				.disfall_st	= { 0x0084, 6, 6, 0, 1 },
2295 				.disfall_clr	= { 0x0088, 6, 6, 0, 1 },
2296 				.disrise_en	= { 0x0080, 5, 5, 0, 1 },
2297 				.disrise_st	= { 0x0084, 5, 5, 0, 1 },
2298 				.disrise_clr	= { 0x0088, 5, 5, 0, 1 },
2299 				.utmi_ls	= { 0x00c0, 10, 9, 0, 1 },
2300 			}
2301 		},
2302 	},
2303 	{
2304 		.reg = 0xc000,
2305 		.num_ports	= 1,
2306 		.phy_tuning	= rk3588_usb2phy_tuning,
2307 		.clkout_ctl	= { 0x0000, 0, 0, 1, 0 },
2308 		.port_cfgs	= {
2309 			[USB2PHY_PORT_HOST] = {
2310 				.phy_sus	= { 0x0008, 2, 2, 0, 1 },
2311 				.ls_det_en	= { 0x0080, 0, 0, 0, 1 },
2312 				.ls_det_st	= { 0x0084, 0, 0, 0, 1 },
2313 				.ls_det_clr	= { 0x0088, 0, 0, 0, 1 },
2314 				.disfall_en	= { 0x0080, 6, 6, 0, 1 },
2315 				.disfall_st	= { 0x0084, 6, 6, 0, 1 },
2316 				.disfall_clr	= { 0x0088, 6, 6, 0, 1 },
2317 				.disrise_en	= { 0x0080, 5, 5, 0, 1 },
2318 				.disrise_st	= { 0x0084, 5, 5, 0, 1 },
2319 				.disrise_clr	= { 0x0088, 5, 5, 0, 1 },
2320 				.utmi_ls	= { 0x00c0, 10, 9, 0, 1 },
2321 			}
2322 		},
2323 	},
2324 	{ /* sentinel */ }
2325 };
2326 
2327 static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = {
2328 	{
2329 		.reg = 0x100,
2330 		.num_ports	= 2,
2331 		.clkout_ctl	= { 0x108, 4, 4, 1, 0 },
2332 		.port_cfgs	= {
2333 			[USB2PHY_PORT_OTG] = {
2334 				.phy_sus	= { 0x0100, 15, 0, 0, 0x1d1 },
2335 				.bvalid_det_en	= { 0x0680, 3, 3, 0, 1 },
2336 				.bvalid_det_st	= { 0x0690, 3, 3, 0, 1 },
2337 				.bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 },
2338 				.ls_det_en	= { 0x0680, 2, 2, 0, 1 },
2339 				.ls_det_st	= { 0x0690, 2, 2, 0, 1 },
2340 				.ls_det_clr	= { 0x06a0, 2, 2, 0, 1 },
2341 				.utmi_bvalid	= { 0x0804, 10, 10, 0, 1 },
2342 				.utmi_ls	= { 0x0804, 13, 12, 0, 1 },
2343 			},
2344 			[USB2PHY_PORT_HOST] = {
2345 				.phy_sus	= { 0x0104, 15, 0, 0, 0x1d1 },
2346 				.ls_det_en	= { 0x0680, 4, 4, 0, 1 },
2347 				.ls_det_st	= { 0x0690, 4, 4, 0, 1 },
2348 				.ls_det_clr	= { 0x06a0, 4, 4, 0, 1 },
2349 				.utmi_ls	= { 0x0804, 9, 8, 0, 1 },
2350 				.utmi_hstdet	= { 0x0804, 7, 7, 0, 1 }
2351 			}
2352 		},
2353 		.chg_det = {
2354 			.opmode		= { 0x0100, 3, 0, 5, 1 },
2355 			.cp_det		= { 0x0804, 1, 1, 0, 1 },
2356 			.dcp_det	= { 0x0804, 0, 0, 0, 1 },
2357 			.dp_det		= { 0x0804, 2, 2, 0, 1 },
2358 			.idm_sink_en	= { 0x0108, 8, 8, 0, 1 },
2359 			.idp_sink_en	= { 0x0108, 7, 7, 0, 1 },
2360 			.idp_src_en	= { 0x0108, 9, 9, 0, 1 },
2361 			.rdm_pdwn_en	= { 0x0108, 10, 10, 0, 1 },
2362 			.vdm_src_en	= { 0x0108, 12, 12, 0, 1 },
2363 			.vdp_src_en	= { 0x0108, 11, 11, 0, 1 },
2364 		},
2365 	},
2366 	{ /* sentinel */ }
2367 };
2368 
2369 static const struct of_device_id rockchip_usb2phy_dt_match[] = {
2370 	{ .compatible = "rockchip,px30-usb2phy", .data = &rk3328_phy_cfgs },
2371 	{ .compatible = "rockchip,rk3036-usb2phy", .data = &rk3036_phy_cfgs },
2372 	{ .compatible = "rockchip,rk3128-usb2phy", .data = &rk3128_phy_cfgs },
2373 	{ .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
2374 	{ .compatible = "rockchip,rk3308-usb2phy", .data = &rk3308_phy_cfgs },
2375 	{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
2376 	{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
2377 	{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
2378 	{ .compatible = "rockchip,rk3528-usb2phy", .data = &rk3528_phy_cfgs },
2379 	{ .compatible = "rockchip,rk3562-usb2phy", .data = &rk3562_phy_cfgs },
2380 	{ .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
2381 	{ .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
2382 	{ .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
2383 	{ .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
2384 	{}
2385 };
2386 MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match);
2387 
2388 static struct platform_driver rockchip_usb2phy_driver = {
2389 	.probe		= rockchip_usb2phy_probe,
2390 	.driver		= {
2391 		.name	= "rockchip-usb2phy",
2392 		.of_match_table = rockchip_usb2phy_dt_match,
2393 	},
2394 };
2395 module_platform_driver(rockchip_usb2phy_driver);
2396 
2397 MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");
2398 MODULE_DESCRIPTION("Rockchip USB2.0 PHY driver");
2399 MODULE_LICENSE("GPL v2");
2400