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 am_phy
->usb_phy_gen
.phy
.init
= am335x_init
;
65 am_phy
->usb_phy_gen
.phy
.shutdown
= am335x_shutdown
;
67 platform_set_drvdata(pdev
, am_phy
);
68 device_init_wakeup(dev
, true);
71 * If we leave PHY wakeup enabled then AM33XX wakes up
72 * immediately from DS0. To avoid this we mark dev->power.can_wakeup
73 * to false. The same is checked in suspend routine to decide
74 * on whether to enable PHY wakeup or not.
75 * PHY wakeup works fine in standby mode, there by allowing us to
76 * handle remote wakeup, wakeup on disconnect and connect.
79 device_set_wakeup_enable(dev
, false);
80 phy_ctrl_power(am_phy
->phy_ctrl
, am_phy
->id
, am_phy
->dr_mode
, false);
82 return usb_add_phy_dev(&am_phy
->usb_phy_gen
.phy
);
85 static int am335x_phy_remove(struct platform_device
*pdev
)
87 struct am335x_phy
*am_phy
= platform_get_drvdata(pdev
);
89 usb_remove_phy(&am_phy
->usb_phy_gen
.phy
);
93 #ifdef CONFIG_PM_SLEEP
94 static int am335x_phy_suspend(struct device
*dev
)
96 struct am335x_phy
*am_phy
= dev_get_drvdata(dev
);
99 * Enable phy wakeup only if dev->power.can_wakeup is true.
100 * Make sure to enable wakeup to support remote wakeup in
101 * standby mode ( same is not supported in OFF(DS0) mode).
103 * echo enabled > /sys/bus/platform/devices/<usb-phy-id>/power/wakeup
106 if (device_may_wakeup(dev
))
107 phy_ctrl_wkup(am_phy
->phy_ctrl
, am_phy
->id
, true);
109 phy_ctrl_power(am_phy
->phy_ctrl
, am_phy
->id
, am_phy
->dr_mode
, false);
114 static int am335x_phy_resume(struct device
*dev
)
116 struct am335x_phy
*am_phy
= dev_get_drvdata(dev
);
118 phy_ctrl_power(am_phy
->phy_ctrl
, am_phy
->id
, am_phy
->dr_mode
, true);
120 if (device_may_wakeup(dev
))
121 phy_ctrl_wkup(am_phy
->phy_ctrl
, am_phy
->id
, false);
127 static SIMPLE_DEV_PM_OPS(am335x_pm_ops
, am335x_phy_suspend
, am335x_phy_resume
);
129 static const struct of_device_id am335x_phy_ids
[] = {
130 { .compatible
= "ti,am335x-usb-phy" },
133 MODULE_DEVICE_TABLE(of
, am335x_phy_ids
);
135 static struct platform_driver am335x_phy_driver
= {
136 .probe
= am335x_phy_probe
,
137 .remove
= am335x_phy_remove
,
139 .name
= "am335x-phy-driver",
140 .pm
= &am335x_pm_ops
,
141 .of_match_table
= am335x_phy_ids
,
145 module_platform_driver(am335x_phy_driver
);
146 MODULE_LICENSE("GPL v2");