diff --git a/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt b/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt
index 00fc52a..3a501fe 100644
--- a/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt
+++ b/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt
@@ -30,6 +30,16 @@ the USB channel; see the selector meanings below:
 | 2         | PCI EHCI/OHCI | xHCI          |
 +-----------+---------------+---------------+
 
+Optional properties:
+  - renesas,pwr-gpio: 		A gpio specifier that will be active when the
+				PHY is powered on.
+  - renesas,id-gpio:		A gpio specifier that is read to get the USB
+				ID signal.
+  - renesas,vbus-gpio:		A gpio specifier that is read to get the USB
+				VBUS signal.
+  - renesas,vbus-pwr-gpio:	A gpio specifier that will be active when VBUS
+				is required to be powered.
+
 Example (Lager board):
 
 	usb-phy@e6590100 {
diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c
index 97d45f4..1286892 100644
--- a/drivers/phy/phy-rcar-gen2.c
+++ b/drivers/phy/phy-rcar-gen2.c
@@ -1,5 +1,5 @@
 /*
- * Renesas R-Car Gen2 PHY driver
+ * Renesas R-Car Gen2 USB PHY driver
  *
  * Copyright (C) 2014 Renesas Solutions Corp.
  * Copyright (C) 2014 Cogent Embedded, Inc.
@@ -12,11 +12,16 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
+#include <linux/workqueue.h>
 
 #include <asm/cmpxchg.h>
 
@@ -58,6 +63,18 @@ struct rcar_gen2_channel {
 	struct rcar_gen2_phy phys[PHYS_PER_CHANNEL];
 	int selected_phy;
 	u32 select_mask;
+
+	/* external power enable pin */
+	int			gpio_pwr;
+
+	/* Host/Function switching */
+	struct delayed_work	work;
+	int			use_otg;
+	int			gpio_vbus;
+	int			gpio_id;
+	int			gpio_vbus_pwr;
+	struct usb_phy		*usbphy;
+	struct usb_otg		*otg;
 };
 
 struct rcar_gen2_phy_driver {
@@ -68,31 +85,50 @@ struct rcar_gen2_phy_driver {
 	struct rcar_gen2_channel *channels;
 };
 
-static int rcar_gen2_phy_init(struct phy *p)
+static void rcar_gen2_phy_switch(struct rcar_gen2_channel *channel,
+	u32 select_value)
 {
-	struct rcar_gen2_phy *phy = phy_get_drvdata(p);
-	struct rcar_gen2_channel *channel = phy->channel;
 	struct rcar_gen2_phy_driver *drv = channel->drv;
 	unsigned long flags;
 	u32 ugctrl2;
 
-	/*
-	 * Try to acquire exclusive access to PHY.  The first driver calling
-	 * phy_init()  on a given channel wins, and all attempts  to use another
-	 * PHY on this channel will fail until phy_exit() is called by the first
-	 * driver.   Achieving this with cmpxcgh() should be SMP-safe.
-	 */
-	if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1)
-		return -EBUSY;
-
-	clk_prepare_enable(drv->clk);
-
 	spin_lock_irqsave(&drv->lock, flags);
 	ugctrl2 = readl(drv->base + USBHS_UGCTRL2);
 	ugctrl2 &= ~channel->select_mask;
-	ugctrl2 |= phy->select_value;
+	ugctrl2 |= select_value;
 	writel(ugctrl2, drv->base + USBHS_UGCTRL2);
 	spin_unlock_irqrestore(&drv->lock, flags);
+}
+
+static int rcar_gen2_phy_init(struct phy *p)
+{
+	struct rcar_gen2_phy *phy = phy_get_drvdata(p);
+	struct rcar_gen2_channel *channel = phy->channel;
+	struct rcar_gen2_phy_driver *drv = channel->drv;
+
+	if (!channel->use_otg) {
+		/*
+		 * Static Host/Function role.
+		 * Try to acquire exclusive access to PHY. The first driver
+		 * calling phy_init() on a given channel wins, and all attempts
+		 * to use another PHY on this channel will fail until
+		 * phy_exit() is called by the first driver. Achieving this
+		 * with cmpxcgh() should be SMP-safe.
+		 */
+		if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1)
+			return -EBUSY;
+
+		clk_prepare_enable(drv->clk);
+		rcar_gen2_phy_switch(channel, phy->select_value);
+	} else {
+		/*
+		 * Using Host/Function switching, so schedule work to determine
+		 * which role to use.
+		 */
+		clk_prepare_enable(drv->clk);
+		schedule_delayed_work(&channel->work, 100);
+	}
+
 	return 0;
 }
 
@@ -117,9 +153,9 @@ static int rcar_gen2_phy_power_on(struct phy *p)
 	u32 value;
 	int err = 0, i;
 
-	/* Skip if it's not USBHS */
-	if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
-		return 0;
+	/* Optional external power pin */
+	if (gpio_is_valid(phy->channel->gpio_pwr))
+		gpio_direction_output(phy->channel->gpio_pwr, 1);
 
 	spin_lock_irqsave(&drv->lock, flags);
 
@@ -160,9 +196,9 @@ static int rcar_gen2_phy_power_off(struct phy *p)
 	unsigned long flags;
 	u32 value;
 
-	/* Skip if it's not USBHS */
-	if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB)
-		return 0;
+	/* External power pin */
+	if (gpio_is_valid(phy->channel->gpio_pwr))
+		gpio_direction_output(phy->channel->gpio_pwr, 0);
 
 	spin_lock_irqsave(&drv->lock, flags);
 
@@ -236,6 +272,132 @@ static const u32 select_value[][PHYS_PER_CHANNEL] = {
 	[2]	= { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 },
 };
 
+
+#define VBUS_IRQ_FLAGS \
+	(IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)
+
+static void gpio_vbus_work(struct work_struct *work)
+{
+	struct rcar_gen2_channel *channel = container_of(work,
+					struct rcar_gen2_channel, work.work);
+	struct usb_phy *usbphy = channel->usbphy;
+	int status, vbus, id;
+
+	vbus = !!gpio_get_value(channel->gpio_vbus);
+	id = !!gpio_get_value(channel->gpio_id);
+
+	/* Switch the PHY over */
+	if (id)
+		rcar_gen2_phy_switch(channel, USBHS_UGCTRL2_USB0SEL_HS_USB);
+	else
+		rcar_gen2_phy_switch(channel, USBHS_UGCTRL2_USB0SEL_PCI);
+
+	/* If VBUS is powered and we are not the initial Host, turn off VBUS */
+	if (gpio_is_valid(channel->gpio_vbus_pwr))
+		gpio_direction_output(channel->gpio_vbus_pwr, !(id && vbus));
+
+	if (!channel->otg->gadget)
+		return;
+
+	/* Function handling: vbus=1 when initially plugged into a Host */
+	if (vbus) {
+		status = USB_EVENT_VBUS;
+		usbphy->otg->state = OTG_STATE_B_PERIPHERAL;
+		usbphy->last_event = status;
+		usb_gadget_vbus_connect(usbphy->otg->gadget);
+
+		atomic_notifier_call_chain(&usbphy->notifier,
+					   status, usbphy->otg->gadget);
+	} else {
+		usb_gadget_vbus_disconnect(usbphy->otg->gadget);
+		status = USB_EVENT_NONE;
+		usbphy->otg->state = OTG_STATE_B_IDLE;
+		usbphy->last_event = status;
+
+		atomic_notifier_call_chain(&usbphy->notifier,
+					   status, usbphy->otg->gadget);
+	}
+}
+
+/* VBUS change IRQ handler */
+static irqreturn_t gpio_vbus_irq(int irq, void *data)
+{
+	struct rcar_gen2_channel *channel = data;
+
+	/* Wait 20ms before doing anything as VBUS needs to settle */
+	schedule_delayed_work(&channel->work, msecs_to_jiffies(20));
+
+	return IRQ_HANDLED;
+}
+
+static int probe_otg(struct platform_device *pdev,
+	struct rcar_gen2_phy_driver *drv)
+{
+	struct device *dev = &pdev->dev;
+	struct rcar_gen2_channel *ch = drv->channels;
+	int irq;
+	int ret;
+
+	/* GPIOs for Host/Fn switching */
+	ch->gpio_id = of_get_named_gpio_flags(dev->of_node,
+				"renesas,id-gpio", 0, NULL);
+	ch->gpio_vbus = of_get_named_gpio_flags(dev->of_node,
+				"renesas,vbus-gpio", 0, NULL);
+
+	/* Need valid ID and VBUS gpios for Host/Fn switching */
+	if (gpio_is_valid(ch->gpio_id) && gpio_is_valid(ch->gpio_vbus)) {
+		ch->use_otg = 1;
+
+		/* GPIO for ID input */
+		ret = devm_gpio_request_one(dev, ch->gpio_id, GPIOF_IN, "id");
+		if (ret)
+			return ret;
+
+		/* GPIO for VBUS input */
+		ret = devm_gpio_request_one(dev, ch->gpio_vbus, GPIOF_IN, "vbus");
+		if (ret)
+			return ret;
+
+		irq = gpio_to_irq(ch->gpio_vbus);
+		ret = devm_request_irq(dev, irq, gpio_vbus_irq, VBUS_IRQ_FLAGS,
+				"vbus_detect", ch);
+		if (ret)
+			return ret;
+
+		/* Optional GPIO for VBUS power */
+		ch->gpio_vbus_pwr = of_get_named_gpio_flags(dev->of_node,
+					"renesas,vbus-pwr-gpio", 0, NULL);
+		if (gpio_is_valid(ch->gpio_id)) {
+			ret = devm_gpio_request_one(dev, ch->gpio_vbus_pwr,
+					GPIOF_OUT_INIT_LOW, "vbus-pwr");
+			if (ret)
+				return ret;
+		}
+
+	} else if (gpio_is_valid(ch->gpio_id)) {
+		dev_err(dev, "Failed to get VBUS gpio\n");
+		return ch->gpio_vbus;
+	} else if (gpio_is_valid(ch->gpio_vbus)) {
+		dev_err(dev, "Failed to get ID gpio\n");
+		return ch->gpio_id;
+	}
+
+	return 0;
+}
+
+/* bind/unbind the peripheral controller */
+static int rcar_gen2_usb_set_peripheral(struct usb_otg *otg,
+					struct usb_gadget *gadget)
+{
+	if (!gadget) {
+		usb_gadget_vbus_disconnect(otg->gadget);
+		otg->state = OTG_STATE_UNDEFINED;
+	}
+	otg->gadget = gadget;
+
+	return 0;
+}
+
 static int rcar_gen2_phy_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -245,7 +407,9 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
 	struct resource *res;
 	void __iomem *base;
 	struct clk *clk;
+	struct usb_otg *otg;
 	int i = 0;
+	int err;
 
 	if (!dev->of_node) {
 		dev_err(dev,
@@ -280,6 +444,57 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
 	if (!drv->channels)
 		return -ENOMEM;
 
+	/* USB0 optional GPIO power pin for external devices */
+	drv->channels->gpio_pwr = of_get_named_gpio_flags(dev->of_node,
+						"renesas,pwr-gpio", 0, NULL);
+	if (drv->channels->gpio_pwr == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
+	if (gpio_is_valid(drv->channels->gpio_pwr)) {
+		err = devm_gpio_request(dev, drv->channels->gpio_pwr, "pwr");
+		if (err)
+			return err;
+	}
+
+	/* USB0 Host/Function switching info */
+	err = probe_otg(pdev, drv);
+	if (err)
+		return err;
+
+	/*
+	 * The PHY connected to channel 0 can be used to steer signals to the
+	 * USB Host IP that stils behind a PCI bridge (pci0), or the USB Func
+	 * IP (hsusb). We can dynamically switch this based on VBUS and ID
+	 * signals connected to gpios, to get something approaching OTG.
+	 */
+	if (drv->channels->use_otg) {
+		struct usb_phy *usbphy;
+
+		usbphy = devm_kzalloc(dev, sizeof(*usbphy), GFP_KERNEL);
+		if (!usbphy)
+			return -ENOMEM;
+
+		otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
+		if (!otg)
+			return -ENOMEM;
+
+		usbphy->dev		= dev;
+		usbphy->otg		= otg;
+
+		otg->usb_phy		= usbphy;
+		otg->state		= OTG_STATE_UNDEFINED;
+		otg->set_peripheral	= rcar_gen2_usb_set_peripheral;
+
+		drv->channels->otg	= otg;
+		drv->channels->usbphy	= usbphy;
+
+		ATOMIC_INIT_NOTIFIER_HEAD(&usbphy->notifier);
+
+		INIT_DELAYED_WORK(&drv->channels->work, gpio_vbus_work);
+
+		usb_add_phy_dev(usbphy);
+	}
+
 	for_each_child_of_node(dev->of_node, np) {
 		struct rcar_gen2_channel *channel = drv->channels + i;
 		u32 channel_num;
@@ -288,6 +503,8 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
 		channel->of_node = np;
 		channel->drv = drv;
 		channel->selected_phy = -1;
+		if (i != 0)
+			channel->gpio_pwr = -ENOENT;
 
 		error = of_property_read_u32(np, "reg", &channel_num);
 		if (error || channel_num > 2) {
@@ -323,6 +540,14 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(dev, drv);
 
+	/*
+	 * If we already have something plugged into USB0, we won't get an edge
+	 * on VBUS, so we have to manually schedule work to look at the VBUS
+	 * and ID signals.
+	 */
+	if (drv->channels->use_otg)
+		schedule_delayed_work(&drv->channels->work, msecs_to_jiffies(100));
+
 	return 0;
 }
 
