2 * Rockchip USB2.0 PHY with Innosilicon IP block driver
4 * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <linux/clk.h>
18 #include <linux/clk-provider.h>
19 #include <linux/delay.h>
20 #include <linux/interrupt.h>
22 #include <linux/gpio/consumer.h>
23 #include <linux/jiffies.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/mutex.h>
28 #include <linux/of_address.h>
29 #include <linux/of_irq.h>
30 #include <linux/of_platform.h>
31 #include <linux/phy/phy.h>
32 #include <linux/platform_device.h>
33 #include <linux/regmap.h>
34 #include <linux/mfd/syscon.h>
36 #define BIT_WRITEABLE_SHIFT 16
37 #define SCHEDULE_DELAY (60 * HZ)
39 enum rockchip_usb2phy_port_id
{
45 enum rockchip_usb2phy_host_state
{
46 PHY_STATE_HS_ONLINE
= 0,
47 PHY_STATE_DISCONNECT
= 1,
48 PHY_STATE_CONNECT
= 2,
49 PHY_STATE_FS_LS_ONLINE
= 4,
55 unsigned int bitstart
;
61 * struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
62 * @phy_sus: phy suspend register.
63 * @ls_det_en: linestate detection enable register.
64 * @ls_det_st: linestate detection state register.
65 * @ls_det_clr: linestate detection clear register.
66 * @utmi_ls: utmi linestate state register.
67 * @utmi_hstdet: utmi host disconnect register.
69 struct rockchip_usb2phy_port_cfg
{
70 struct usb2phy_reg phy_sus
;
71 struct usb2phy_reg ls_det_en
;
72 struct usb2phy_reg ls_det_st
;
73 struct usb2phy_reg ls_det_clr
;
74 struct usb2phy_reg utmi_ls
;
75 struct usb2phy_reg utmi_hstdet
;
79 * struct rockchip_usb2phy_cfg: usb-phy configuration.
80 * @reg: the address offset of grf for usb-phy config.
81 * @num_ports: specify how many ports that the phy has.
82 * @clkout_ctl: keep on/turn off output clk of phy.
84 struct rockchip_usb2phy_cfg
{
86 unsigned int num_ports
;
87 struct usb2phy_reg clkout_ctl
;
88 const struct rockchip_usb2phy_port_cfg port_cfgs
[USB2PHY_NUM_PORTS
];
92 * struct rockchip_usb2phy_port: usb-phy port data.
93 * @port_id: flag for otg port or host port.
94 * @suspended: phy suspended flag.
95 * @ls_irq: IRQ number assigned for linestate detection.
96 * @mutex: for register updating in sm_work.
97 * @sm_work: OTG state machine work.
98 * @phy_cfg: port register configuration, assigned by driver data.
100 struct rockchip_usb2phy_port
{
102 unsigned int port_id
;
106 struct delayed_work sm_work
;
107 const struct rockchip_usb2phy_port_cfg
*port_cfg
;
111 * struct rockchip_usb2phy: usb2.0 phy driver data.
112 * @grf: General Register Files regmap.
113 * @clk: clock struct of phy input clk.
114 * @clk480m: clock struct of phy output clk.
115 * @clk_hw: clock struct of phy output clk management.
116 * @phy_cfg: phy register configuration, assigned by driver data.
117 * @ports: phy port instance.
119 struct rockchip_usb2phy
{
124 struct clk_hw clk480m_hw
;
125 const struct rockchip_usb2phy_cfg
*phy_cfg
;
126 struct rockchip_usb2phy_port ports
[USB2PHY_NUM_PORTS
];
129 static inline int property_enable(struct rockchip_usb2phy
*rphy
,
130 const struct usb2phy_reg
*reg
, bool en
)
132 unsigned int val
, mask
, tmp
;
134 tmp
= en
? reg
->enable
: reg
->disable
;
135 mask
= GENMASK(reg
->bitend
, reg
->bitstart
);
136 val
= (tmp
<< reg
->bitstart
) | (mask
<< BIT_WRITEABLE_SHIFT
);
138 return regmap_write(rphy
->grf
, reg
->offset
, val
);
141 static inline bool property_enabled(struct rockchip_usb2phy
*rphy
,
142 const struct usb2phy_reg
*reg
)
145 unsigned int tmp
, orig
;
146 unsigned int mask
= GENMASK(reg
->bitend
, reg
->bitstart
);
148 ret
= regmap_read(rphy
->grf
, reg
->offset
, &orig
);
152 tmp
= (orig
& mask
) >> reg
->bitstart
;
153 return tmp
== reg
->enable
;
156 static int rockchip_usb2phy_clk480m_enable(struct clk_hw
*hw
)
158 struct rockchip_usb2phy
*rphy
=
159 container_of(hw
, struct rockchip_usb2phy
, clk480m_hw
);
162 /* turn on 480m clk output if it is off */
163 if (!property_enabled(rphy
, &rphy
->phy_cfg
->clkout_ctl
)) {
164 ret
= property_enable(rphy
, &rphy
->phy_cfg
->clkout_ctl
, true);
168 /* waitting for the clk become stable */
175 static void rockchip_usb2phy_clk480m_disable(struct clk_hw
*hw
)
177 struct rockchip_usb2phy
*rphy
=
178 container_of(hw
, struct rockchip_usb2phy
, clk480m_hw
);
180 /* turn off 480m clk output */
181 property_enable(rphy
, &rphy
->phy_cfg
->clkout_ctl
, false);
184 static int rockchip_usb2phy_clk480m_enabled(struct clk_hw
*hw
)
186 struct rockchip_usb2phy
*rphy
=
187 container_of(hw
, struct rockchip_usb2phy
, clk480m_hw
);
189 return property_enabled(rphy
, &rphy
->phy_cfg
->clkout_ctl
);
193 rockchip_usb2phy_clk480m_recalc_rate(struct clk_hw
*hw
,
194 unsigned long parent_rate
)
199 static const struct clk_ops rockchip_usb2phy_clkout_ops
= {
200 .enable
= rockchip_usb2phy_clk480m_enable
,
201 .disable
= rockchip_usb2phy_clk480m_disable
,
202 .is_enabled
= rockchip_usb2phy_clk480m_enabled
,
203 .recalc_rate
= rockchip_usb2phy_clk480m_recalc_rate
,
206 static void rockchip_usb2phy_clk480m_unregister(void *data
)
208 struct rockchip_usb2phy
*rphy
= data
;
210 of_clk_del_provider(rphy
->dev
->of_node
);
211 clk_unregister(rphy
->clk480m
);
215 rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy
*rphy
)
217 struct device_node
*node
= rphy
->dev
->of_node
;
218 struct clk_init_data init
;
219 const char *clk_name
;
223 init
.name
= "clk_usbphy_480m";
224 init
.ops
= &rockchip_usb2phy_clkout_ops
;
226 /* optional override of the clockname */
227 of_property_read_string(node
, "clock-output-names", &init
.name
);
230 clk_name
= __clk_get_name(rphy
->clk
);
231 init
.parent_names
= &clk_name
;
232 init
.num_parents
= 1;
234 init
.parent_names
= NULL
;
235 init
.num_parents
= 0;
238 rphy
->clk480m_hw
.init
= &init
;
240 /* register the clock */
241 rphy
->clk480m
= clk_register(rphy
->dev
, &rphy
->clk480m_hw
);
242 if (IS_ERR(rphy
->clk480m
)) {
243 ret
= PTR_ERR(rphy
->clk480m
);
247 ret
= of_clk_add_provider(node
, of_clk_src_simple_get
, rphy
->clk480m
);
249 goto err_clk_provider
;
251 ret
= devm_add_action(rphy
->dev
, rockchip_usb2phy_clk480m_unregister
,
254 goto err_unreg_action
;
259 of_clk_del_provider(node
);
261 clk_unregister(rphy
->clk480m
);
266 static int rockchip_usb2phy_init(struct phy
*phy
)
268 struct rockchip_usb2phy_port
*rport
= phy_get_drvdata(phy
);
269 struct rockchip_usb2phy
*rphy
= dev_get_drvdata(phy
->dev
.parent
);
272 if (rport
->port_id
== USB2PHY_PORT_HOST
) {
273 /* clear linestate and enable linestate detect irq */
274 mutex_lock(&rport
->mutex
);
276 ret
= property_enable(rphy
, &rport
->port_cfg
->ls_det_clr
, true);
278 mutex_unlock(&rport
->mutex
);
282 ret
= property_enable(rphy
, &rport
->port_cfg
->ls_det_en
, true);
284 mutex_unlock(&rport
->mutex
);
288 mutex_unlock(&rport
->mutex
);
289 schedule_delayed_work(&rport
->sm_work
, SCHEDULE_DELAY
);
295 static int rockchip_usb2phy_power_on(struct phy
*phy
)
297 struct rockchip_usb2phy_port
*rport
= phy_get_drvdata(phy
);
298 struct rockchip_usb2phy
*rphy
= dev_get_drvdata(phy
->dev
.parent
);
301 dev_dbg(&rport
->phy
->dev
, "port power on\n");
303 if (!rport
->suspended
)
306 ret
= clk_prepare_enable(rphy
->clk480m
);
310 ret
= property_enable(rphy
, &rport
->port_cfg
->phy_sus
, false);
314 rport
->suspended
= false;
318 static int rockchip_usb2phy_power_off(struct phy
*phy
)
320 struct rockchip_usb2phy_port
*rport
= phy_get_drvdata(phy
);
321 struct rockchip_usb2phy
*rphy
= dev_get_drvdata(phy
->dev
.parent
);
324 dev_dbg(&rport
->phy
->dev
, "port power off\n");
326 if (rport
->suspended
)
329 ret
= property_enable(rphy
, &rport
->port_cfg
->phy_sus
, true);
333 rport
->suspended
= true;
334 clk_disable_unprepare(rphy
->clk480m
);
339 static int rockchip_usb2phy_exit(struct phy
*phy
)
341 struct rockchip_usb2phy_port
*rport
= phy_get_drvdata(phy
);
343 if (rport
->port_id
== USB2PHY_PORT_HOST
)
344 cancel_delayed_work_sync(&rport
->sm_work
);
349 static const struct phy_ops rockchip_usb2phy_ops
= {
350 .init
= rockchip_usb2phy_init
,
351 .exit
= rockchip_usb2phy_exit
,
352 .power_on
= rockchip_usb2phy_power_on
,
353 .power_off
= rockchip_usb2phy_power_off
,
354 .owner
= THIS_MODULE
,
358 * The function manage host-phy port state and suspend/resume phy port
361 * we rely on utmi_linestate and utmi_hostdisconnect to identify whether
362 * devices is disconnect or not. Besides, we do not need care it is FS/LS
363 * disconnected or HS disconnected, actually, we just only need get the
364 * device is disconnected at last through rearm the delayed work,
365 * to suspend the phy port in _PHY_STATE_DISCONNECT_ case.
367 * NOTE: It may invoke *phy_powr_off or *phy_power_on which will invoke
368 * some clk related APIs, so do not invoke it from interrupt context directly.
370 static void rockchip_usb2phy_sm_work(struct work_struct
*work
)
372 struct rockchip_usb2phy_port
*rport
=
373 container_of(work
, struct rockchip_usb2phy_port
, sm_work
.work
);
374 struct rockchip_usb2phy
*rphy
= dev_get_drvdata(rport
->phy
->dev
.parent
);
375 unsigned int sh
= rport
->port_cfg
->utmi_hstdet
.bitend
-
376 rport
->port_cfg
->utmi_hstdet
.bitstart
+ 1;
377 unsigned int ul
, uhd
, state
;
378 unsigned int ul_mask
, uhd_mask
;
381 mutex_lock(&rport
->mutex
);
383 ret
= regmap_read(rphy
->grf
, rport
->port_cfg
->utmi_ls
.offset
, &ul
);
387 ret
= regmap_read(rphy
->grf
, rport
->port_cfg
->utmi_hstdet
.offset
,
392 uhd_mask
= GENMASK(rport
->port_cfg
->utmi_hstdet
.bitend
,
393 rport
->port_cfg
->utmi_hstdet
.bitstart
);
394 ul_mask
= GENMASK(rport
->port_cfg
->utmi_ls
.bitend
,
395 rport
->port_cfg
->utmi_ls
.bitstart
);
397 /* stitch on utmi_ls and utmi_hstdet as phy state */
398 state
= ((uhd
& uhd_mask
) >> rport
->port_cfg
->utmi_hstdet
.bitstart
) |
399 (((ul
& ul_mask
) >> rport
->port_cfg
->utmi_ls
.bitstart
) << sh
);
402 case PHY_STATE_HS_ONLINE
:
403 dev_dbg(&rport
->phy
->dev
, "HS online\n");
405 case PHY_STATE_FS_LS_ONLINE
:
407 * For FS/LS device, the online state share with connect state
408 * from utmi_ls and utmi_hstdet register, so we distinguish
409 * them via suspended flag.
411 * Plus, there are two cases, one is D- Line pull-up, and D+
412 * line pull-down, the state is 4; another is D+ line pull-up,
413 * and D- line pull-down, the state is 2.
415 if (!rport
->suspended
) {
416 /* D- line pull-up, D+ line pull-down */
417 dev_dbg(&rport
->phy
->dev
, "FS/LS online\n");
421 case PHY_STATE_CONNECT
:
422 if (rport
->suspended
) {
423 dev_dbg(&rport
->phy
->dev
, "Connected\n");
424 rockchip_usb2phy_power_on(rport
->phy
);
425 rport
->suspended
= false;
427 /* D+ line pull-up, D- line pull-down */
428 dev_dbg(&rport
->phy
->dev
, "FS/LS online\n");
431 case PHY_STATE_DISCONNECT
:
432 if (!rport
->suspended
) {
433 dev_dbg(&rport
->phy
->dev
, "Disconnected\n");
434 rockchip_usb2phy_power_off(rport
->phy
);
435 rport
->suspended
= true;
439 * activate the linestate detection to get the next device
442 property_enable(rphy
, &rport
->port_cfg
->ls_det_clr
, true);
443 property_enable(rphy
, &rport
->port_cfg
->ls_det_en
, true);
446 * we don't need to rearm the delayed work when the phy port
449 mutex_unlock(&rport
->mutex
);
452 dev_dbg(&rport
->phy
->dev
, "unknown phy state\n");
457 mutex_unlock(&rport
->mutex
);
458 schedule_delayed_work(&rport
->sm_work
, SCHEDULE_DELAY
);
461 static irqreturn_t
rockchip_usb2phy_linestate_irq(int irq
, void *data
)
463 struct rockchip_usb2phy_port
*rport
= data
;
464 struct rockchip_usb2phy
*rphy
= dev_get_drvdata(rport
->phy
->dev
.parent
);
466 if (!property_enabled(rphy
, &rport
->port_cfg
->ls_det_st
))
469 mutex_lock(&rport
->mutex
);
471 /* disable linestate detect irq and clear its status */
472 property_enable(rphy
, &rport
->port_cfg
->ls_det_en
, false);
473 property_enable(rphy
, &rport
->port_cfg
->ls_det_clr
, true);
475 mutex_unlock(&rport
->mutex
);
478 * In this case for host phy port, a new device is plugged in,
479 * meanwhile, if the phy port is suspended, we need rearm the work to
480 * resume it and mange its states; otherwise, we do nothing about that.
482 if (rport
->suspended
&& rport
->port_id
== USB2PHY_PORT_HOST
)
483 rockchip_usb2phy_sm_work(&rport
->sm_work
.work
);
488 static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy
*rphy
,
489 struct rockchip_usb2phy_port
*rport
,
490 struct device_node
*child_np
)
494 rport
->port_id
= USB2PHY_PORT_HOST
;
495 rport
->port_cfg
= &rphy
->phy_cfg
->port_cfgs
[USB2PHY_PORT_HOST
];
496 rport
->suspended
= true;
498 mutex_init(&rport
->mutex
);
499 INIT_DELAYED_WORK(&rport
->sm_work
, rockchip_usb2phy_sm_work
);
501 rport
->ls_irq
= of_irq_get_byname(child_np
, "linestate");
502 if (rport
->ls_irq
< 0) {
503 dev_err(rphy
->dev
, "no linestate irq provided\n");
504 return rport
->ls_irq
;
507 ret
= devm_request_threaded_irq(rphy
->dev
, rport
->ls_irq
, NULL
,
508 rockchip_usb2phy_linestate_irq
,
510 "rockchip_usb2phy", rport
);
512 dev_err(rphy
->dev
, "failed to request irq handle\n");
519 static int rockchip_usb2phy_probe(struct platform_device
*pdev
)
521 struct device
*dev
= &pdev
->dev
;
522 struct device_node
*np
= dev
->of_node
;
523 struct device_node
*child_np
;
524 struct phy_provider
*provider
;
525 struct rockchip_usb2phy
*rphy
;
526 const struct rockchip_usb2phy_cfg
*phy_cfgs
;
527 const struct of_device_id
*match
;
531 rphy
= devm_kzalloc(dev
, sizeof(*rphy
), GFP_KERNEL
);
535 match
= of_match_device(dev
->driver
->of_match_table
, dev
);
536 if (!match
|| !match
->data
) {
537 dev_err(dev
, "phy configs are not assigned!\n");
541 if (!dev
->parent
|| !dev
->parent
->of_node
)
544 rphy
->grf
= syscon_node_to_regmap(dev
->parent
->of_node
);
545 if (IS_ERR(rphy
->grf
))
546 return PTR_ERR(rphy
->grf
);
548 if (of_property_read_u32(np
, "reg", ®
)) {
549 dev_err(dev
, "the reg property is not assigned in %s node\n",
555 phy_cfgs
= match
->data
;
556 platform_set_drvdata(pdev
, rphy
);
558 /* find out a proper config which can be matched with dt. */
560 while (phy_cfgs
[index
].reg
) {
561 if (phy_cfgs
[index
].reg
== reg
) {
562 rphy
->phy_cfg
= &phy_cfgs
[index
];
569 if (!rphy
->phy_cfg
) {
570 dev_err(dev
, "no phy-config can be matched with %s node\n",
575 rphy
->clk
= of_clk_get_by_name(np
, "phyclk");
576 if (!IS_ERR(rphy
->clk
)) {
577 clk_prepare_enable(rphy
->clk
);
579 dev_info(&pdev
->dev
, "no phyclk specified\n");
583 ret
= rockchip_usb2phy_clk480m_register(rphy
);
585 dev_err(dev
, "failed to register 480m output clock\n");
590 for_each_available_child_of_node(np
, child_np
) {
591 struct rockchip_usb2phy_port
*rport
= &rphy
->ports
[index
];
595 * This driver aim to support both otg-port and host-port,
596 * but unfortunately, the otg part is not ready in current,
597 * so this comments and below codes are interim, which should
598 * be changed after otg-port is supplied soon.
600 if (of_node_cmp(child_np
->name
, "host-port"))
603 phy
= devm_phy_create(dev
, child_np
, &rockchip_usb2phy_ops
);
605 dev_err(dev
, "failed to create phy\n");
611 phy_set_drvdata(rport
->phy
, rport
);
613 ret
= rockchip_usb2phy_host_port_init(rphy
, rport
, child_np
);
618 /* to prevent out of boundary */
619 if (++index
>= rphy
->phy_cfg
->num_ports
)
623 provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
624 return PTR_ERR_OR_ZERO(provider
);
627 of_node_put(child_np
);
630 clk_disable_unprepare(rphy
->clk
);
636 static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs
[] = {
640 .clkout_ctl
= { 0x0724, 15, 15, 1, 0 },
642 [USB2PHY_PORT_HOST
] = {
643 .phy_sus
= { 0x0728, 15, 0, 0, 0x1d1 },
644 .ls_det_en
= { 0x0680, 4, 4, 0, 1 },
645 .ls_det_st
= { 0x0690, 4, 4, 0, 1 },
646 .ls_det_clr
= { 0x06a0, 4, 4, 0, 1 },
647 .utmi_ls
= { 0x049c, 14, 13, 0, 1 },
648 .utmi_hstdet
= { 0x049c, 12, 12, 0, 1 }
655 static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs
[] = {
659 .clkout_ctl
= { 0xe450, 4, 4, 1, 0 },
661 [USB2PHY_PORT_HOST
] = {
662 .phy_sus
= { 0xe458, 1, 0, 0x2, 0x1 },
663 .ls_det_en
= { 0xe3c0, 6, 6, 0, 1 },
664 .ls_det_st
= { 0xe3e0, 6, 6, 0, 1 },
665 .ls_det_clr
= { 0xe3d0, 6, 6, 0, 1 },
666 .utmi_ls
= { 0xe2ac, 22, 21, 0, 1 },
667 .utmi_hstdet
= { 0xe2ac, 23, 23, 0, 1 }
674 .clkout_ctl
= { 0xe460, 4, 4, 1, 0 },
676 [USB2PHY_PORT_HOST
] = {
677 .phy_sus
= { 0xe468, 1, 0, 0x2, 0x1 },
678 .ls_det_en
= { 0xe3c0, 11, 11, 0, 1 },
679 .ls_det_st
= { 0xe3e0, 11, 11, 0, 1 },
680 .ls_det_clr
= { 0xe3d0, 11, 11, 0, 1 },
681 .utmi_ls
= { 0xe2ac, 26, 25, 0, 1 },
682 .utmi_hstdet
= { 0xe2ac, 27, 27, 0, 1 }
689 static const struct of_device_id rockchip_usb2phy_dt_match
[] = {
690 { .compatible
= "rockchip,rk3366-usb2phy", .data
= &rk3366_phy_cfgs
},
691 { .compatible
= "rockchip,rk3399-usb2phy", .data
= &rk3399_phy_cfgs
},
694 MODULE_DEVICE_TABLE(of
, rockchip_usb2phy_dt_match
);
696 static struct platform_driver rockchip_usb2phy_driver
= {
697 .probe
= rockchip_usb2phy_probe
,
699 .name
= "rockchip-usb2phy",
700 .of_match_table
= rockchip_usb2phy_dt_match
,
703 module_platform_driver(rockchip_usb2phy_driver
);
705 MODULE_AUTHOR("Frank Wang <frank.wang@rock-chips.com>");
706 MODULE_DESCRIPTION("Rockchip USB2.0 PHY driver");
707 MODULE_LICENSE("GPL v2");