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

source code of linux/drivers/phy/rockchip/phy-rockchip-inno-usb2.c