phy-sun4i-usb: Add support for phy_set_mode
authorHans de Goede <hdegoede@redhat.com>
Wed, 7 Sep 2016 20:20:40 +0000 (22:20 +0200)
committerKishon Vijay Abraham I <kishon@ti.com>
Sat, 10 Sep 2016 11:45:19 +0000 (17:15 +0530)
Together with some musb sunxi glue changes this allows run-time dr_mode
switching support via the "mode" musb sysfs attribute.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
drivers/phy/phy-sun4i-usb.c

index fb2d4f3..af42f8d 100644 (file)
@@ -427,6 +427,35 @@ static int sun4i_usb_phy_power_off(struct phy *_phy)
        return 0;
 }
 
+static int sun4i_usb_phy_set_mode(struct phy *_phy, enum phy_mode mode)
+{
+       struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+       struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+       if (phy->index != 0)
+               return -EINVAL;
+
+       switch (mode) {
+       case PHY_MODE_USB_HOST:
+               data->dr_mode = USB_DR_MODE_HOST;
+               break;
+       case PHY_MODE_USB_DEVICE:
+               data->dr_mode = USB_DR_MODE_PERIPHERAL;
+               break;
+       case PHY_MODE_USB_OTG:
+               data->dr_mode = USB_DR_MODE_OTG;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       dev_info(&_phy->dev, "Changing dr_mode to %d\n", (int)data->dr_mode);
+       data->force_session_end = true;
+       queue_delayed_work(system_wq, &data->detect, 0);
+
+       return 0;
+}
+
 void sun4i_usb_phy_set_squelch_detect(struct phy *_phy, bool enabled)
 {
        struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
@@ -440,6 +469,7 @@ static const struct phy_ops sun4i_usb_phy_ops = {
        .exit           = sun4i_usb_phy_exit,
        .power_on       = sun4i_usb_phy_power_on,
        .power_off      = sun4i_usb_phy_power_off,
+       .set_mode       = sun4i_usb_phy_set_mode,
        .owner          = THIS_MODULE,
 };