Skip to content

Commit e8f7d2f

Browse files
Nagarjuna Kristamthierryreding
authored andcommitted
phy: tegra: xusb: Add usb-phy support
For USB 2 ports that has usb-role-switch enabled, add usb-phy for corresponding USB 2 phy. USB role changes from role switch are then updated to corresponding host and device mode drivers via usb-phy notifier block. Signed-off-by: Nagarjuna Kristam <[email protected]> Acked-by: Kishon Vijay Abraham I <[email protected]> [[email protected]: rebase onto Greg's usb-next branch] Signed-off-by: Thierry Reding <[email protected]>
1 parent f67213c commit e8f7d2f

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

drivers/phy/tegra/xusb.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,8 @@ static void tegra_xusb_port_unregister(struct tegra_xusb_port *port)
544544
if (!IS_ERR_OR_NULL(port->usb_role_sw)) {
545545
of_platform_depopulate(&port->dev);
546546
usb_role_switch_unregister(port->usb_role_sw);
547+
cancel_work_sync(&port->usb_phy_work);
548+
usb_remove_phy(&port->usb_phy);
547549
}
548550

549551
device_unregister(&port->dev);
@@ -562,18 +564,76 @@ static const char * const usb_roles[] = {
562564
[USB_ROLE_DEVICE] = "device",
563565
};
564566

567+
static enum usb_phy_events to_usb_phy_event(enum usb_role role)
568+
{
569+
switch (role) {
570+
case USB_ROLE_DEVICE:
571+
return USB_EVENT_VBUS;
572+
573+
case USB_ROLE_HOST:
574+
return USB_EVENT_ID;
575+
576+
default:
577+
return USB_EVENT_NONE;
578+
}
579+
}
580+
581+
static void tegra_xusb_usb_phy_work(struct work_struct *work)
582+
{
583+
struct tegra_xusb_port *port = container_of(work,
584+
struct tegra_xusb_port,
585+
usb_phy_work);
586+
enum usb_role role = usb_role_switch_get_role(port->usb_role_sw);
587+
588+
usb_phy_set_event(&port->usb_phy, to_usb_phy_event(role));
589+
590+
dev_dbg(&port->dev, "%s(): calling notifier for role %s\n", __func__,
591+
usb_roles[role]);
592+
593+
atomic_notifier_call_chain(&port->usb_phy.notifier, 0, &port->usb_phy);
594+
}
595+
565596
static int tegra_xusb_role_sw_set(struct usb_role_switch *sw,
566597
enum usb_role role)
567598
{
568599
struct tegra_xusb_port *port = usb_role_switch_get_drvdata(sw);
569600

570601
dev_dbg(&port->dev, "%s(): role %s\n", __func__, usb_roles[role]);
571602

603+
schedule_work(&port->usb_phy_work);
604+
605+
return 0;
606+
}
607+
608+
static int tegra_xusb_set_peripheral(struct usb_otg *otg,
609+
struct usb_gadget *gadget)
610+
{
611+
struct tegra_xusb_port *port = container_of(otg->usb_phy,
612+
struct tegra_xusb_port,
613+
usb_phy);
614+
615+
if (gadget != NULL)
616+
schedule_work(&port->usb_phy_work);
617+
572618
return 0;
573619
}
574620

621+
static int tegra_xusb_set_host(struct usb_otg *otg, struct usb_bus *host)
622+
{
623+
struct tegra_xusb_port *port = container_of(otg->usb_phy,
624+
struct tegra_xusb_port,
625+
usb_phy);
626+
627+
if (host != NULL)
628+
schedule_work(&port->usb_phy_work);
629+
630+
return 0;
631+
}
632+
633+
575634
static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
576635
{
636+
struct tegra_xusb_lane *lane;
577637
struct usb_role_switch_desc role_sx_desc = {
578638
.fwnode = dev_fwnode(&port->dev),
579639
.set = tegra_xusb_role_sw_set,
@@ -600,8 +660,32 @@ static int tegra_xusb_setup_usb_role_switch(struct tegra_xusb_port *port)
600660
return err;
601661
}
602662

663+
INIT_WORK(&port->usb_phy_work, tegra_xusb_usb_phy_work);
603664
usb_role_switch_set_drvdata(port->usb_role_sw, port);
604665

666+
port->usb_phy.otg = devm_kzalloc(&port->dev, sizeof(struct usb_otg),
667+
GFP_KERNEL);
668+
if (!port->usb_phy.otg)
669+
return -ENOMEM;
670+
671+
lane = tegra_xusb_find_lane(port->padctl, "usb2", port->index);
672+
673+
/*
674+
* Assign phy dev to usb-phy dev. Host/device drivers can use phy
675+
* reference to retrieve usb-phy details.
676+
*/
677+
port->usb_phy.dev = &lane->pad->lanes[port->index]->dev;
678+
port->usb_phy.dev->driver = port->padctl->dev->driver;
679+
port->usb_phy.otg->usb_phy = &port->usb_phy;
680+
port->usb_phy.otg->set_peripheral = tegra_xusb_set_peripheral;
681+
port->usb_phy.otg->set_host = tegra_xusb_set_host;
682+
683+
err = usb_add_phy_dev(&port->usb_phy);
684+
if (err < 0) {
685+
dev_err(&port->dev, "Failed to add USB PHY: %d\n", err);
686+
return err;
687+
}
688+
605689
/* populate connector entry */
606690
of_platform_populate(port->dev.of_node, NULL, NULL, &port->dev);
607691

drivers/phy/tegra/xusb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ struct tegra_xusb_port {
268268
struct device dev;
269269

270270
struct usb_role_switch *usb_role_sw;
271+
struct work_struct usb_phy_work;
272+
struct usb_phy usb_phy;
271273

272274
const struct tegra_xusb_port_ops *ops;
273275
};

0 commit comments

Comments
 (0)