1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/module.h>
3 #include <linux/platform_device.h>
4 #include <linux/dma-mapping.h>
5 #include <linux/usb/otg.h>
6 #include <linux/usb/usb_phy_generic.h>
7 #include <linux/slab.h>
10 #include <linux/of_address.h>
11 #include <linux/usb/of.h>
13 #include "phy-am335x-control.h"
14 #include "phy-generic.h"
17 struct usb_phy_generic usb_phy_gen
;
18 struct phy_control
*phy_ctrl
;
20 enum usb_dr_mode dr_mode
;
23 static int am335x_init(struct usb_phy
*phy
)
25 struct am335x_phy
*am_phy
= dev_get_drvdata(phy
->dev
);
27 phy_ctrl_power(am_phy
->phy_ctrl
, am_phy
->id
, am_phy
->dr_mode
, true);
31 static void am335x_shutdown(struct usb_phy
*phy
)
33 struct am335x_phy
*am_phy
= dev_get_drvdata(phy
->dev
);
35 phy_ctrl_power(am_phy
->phy_ctrl
, am_phy
->id
, am_phy
->dr_mode
, false);
38 static int am335x_phy_probe(struct platform_device
*pdev
)
40 struct am335x_phy
*am_phy
;
41 struct device
*dev
= &pdev
->dev
;
44 am_phy
= devm_kzalloc(dev
, sizeof(*am_phy
), GFP_KERNEL
);
48 am_phy
->phy_ctrl
= am335x_get_phy_control(dev
);
49 if (!am_phy
->phy_ctrl
)
52 am_phy
->id
= of_alias_get_id(pdev
->dev
.of_node
, "phy");
54 dev_err(&pdev
->dev
, "Missing PHY id: %d\n", am_phy
->id
);
58 am_phy
->dr_mode
= of_usb_get_dr_mode_by_phy(pdev
->dev
.of_node
, -1);
60 ret
= usb_phy_gen_create_phy(dev
, &am_phy
->usb_phy_gen
, NULL
);
64 ret
= usb_add_phy_dev(&am_phy
->usb_phy_gen
.phy
);
67 am_phy
->usb_phy_gen
.phy
.init
= am335x_init
;
68 am_phy
->usb_phy_gen
.phy
.shutdown
= am335x_shutdown
;
70 platform_set_drvdata(pdev
, am_phy
);
71 device_init_wakeup(dev
, true);
74 * If we leave PHY wakeup enabled then AM33XX wakes up
75 * immediately from DS0. To avoid this we mark dev->power.can_wakeup
76 * to false. The same is checked in suspend routine to decide
77 * on whether to enable PHY wakeup or not.
78 * PHY wakeup works fine in standby mode, there by allowing us to
79 * handle remote wakeup, wakeup on disconnect and connect.
82 device_set_wakeup_enable(dev
, false);
83 phy_ctrl_power(am_phy
->phy_ctrl
, am_phy
->id
, am_phy
->dr_mode
, false);
88 static int am335x_phy_remove(struct platform_device
*pdev
)
90 struct am335x_phy
*am_phy
= platform_get_drvdata(pdev
);
92 usb_remove_phy(&am_phy
->usb_phy_gen
.phy
);
96 #ifdef CONFIG_PM_SLEEP
97 static int am335x_phy_suspend(struct device
*dev
)
99 struct platform_device
*pdev
= to_platform_device(dev
);
100 struct am335x_phy
*am_phy
= platform_get_drvdata(pdev
);
103 * Enable phy wakeup only if dev->power.can_wakeup is true.
104 * Make sure to enable wakeup to support remote wakeup in
105 * standby mode ( same is not supported in OFF(DS0) mode).
107 * echo enabled > /sys/bus/platform/devices/<usb-phy-id>/power/wakeup
110 if (device_may_wakeup(dev
))
111 phy_ctrl_wkup(am_phy
->phy_ctrl
, am_phy
->id
, true);
113 phy_ctrl_power(am_phy
->phy_ctrl
, am_phy
->id
, am_phy
->dr_mode
, false);
118 static int am335x_phy_resume(struct device
*dev
)
120 struct platform_device
*pdev
= to_platform_device(dev
);
121 struct am335x_phy
*am_phy
= platform_get_drvdata(pdev
);
123 phy_ctrl_power(am_phy
->phy_ctrl
, am_phy
->id
, am_phy
->dr_mode
, true);
125 if (device_may_wakeup(dev
))
126 phy_ctrl_wkup(am_phy
->phy_ctrl
, am_phy
->id
, false);
132 static SIMPLE_DEV_PM_OPS(am335x_pm_ops
, am335x_phy_suspend
, am335x_phy_resume
);
134 static const struct of_device_id am335x_phy_ids
[] = {
135 { .compatible
= "ti,am335x-usb-phy" },
138 MODULE_DEVICE_TABLE(of
, am335x_phy_ids
);
140 static struct platform_driver am335x_phy_driver
= {
141 .probe
= am335x_phy_probe
,
142 .remove
= am335x_phy_remove
,
144 .name
= "am335x-phy-driver",
145 .pm
= &am335x_pm_ops
,
146 .of_match_table
= am335x_phy_ids
,
150 module_platform_driver(am335x_phy_driver
);
151 MODULE_LICENSE("GPL v2");