diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index a3777a1..8826cdb 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -133,6 +133,7 @@ struct hw_bank {
  * @id_event: indicates there is a id event, and handled at ci_otg_work
  * @b_sess_valid_event: indicates there is a vbus event, and handled
  * at ci_otg_work
+ * @reg_vbus: used to control internal vbus regulator
  */
 struct ci13xxx {
 	struct device			*dev;
@@ -172,6 +173,7 @@ struct ci13xxx {
 	struct usb_otg      		otg;
 	bool				id_event;
 	bool				b_sess_valid_event;
+	struct regulator		*reg_vbus;
 };
 
 static inline struct ci_role_driver *ci_role(struct ci13xxx *ci)
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index c563e17..e0ff335 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -63,6 +63,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
@@ -364,17 +365,10 @@ static void ci_handle_id_switch(struct ci13xxx *ci)
 		hw_device_reset(ci, USBMODE_CM_IDLE);
 
 		/* 2. Turn on/off vbus according to coming role */
-		if (role == CI_ROLE_GADGET) {
-			otg_set_vbus(&ci->otg, false);
+		if (role == CI_ROLE_GADGET)
 			/* wait vbus lower than OTGSC_BSV */
 			hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
 					CI_VBUS_STABLE_TIMEOUT);
-		} else if (role == CI_ROLE_HOST) {
-			otg_set_vbus(&ci->otg, true);
-			/* wait vbus higher than OTGSC_AVV */
-			hw_wait_reg(ci, OP_OTGSC, OTGSC_AVV, OTGSC_AVV,
-					CI_VBUS_STABLE_TIMEOUT);
-		}
 
 		/* 3. Begin the new role */
 		ci_role_start(ci, role);
@@ -416,17 +410,14 @@ static void ci_delayed_work(struct work_struct *work)
 	struct delayed_work *dwork = to_delayed_work(work);
 	struct ci13xxx *ci = container_of(dwork, struct ci13xxx, dwork);
 
+	/*
+	 * If it is gadget mode, the vbus operation should be done like below:
+	 * 1. Enable vbus detect
+	 * 2. If it has already connected to host, notify udc
+	 */
 	if (ci->role == CI_ROLE_GADGET) {
-		/*
-		 * if it is device mode:
-		 * - Enable vbus detect
-		 * - If it has already connected to host, notify udc
-		 */
 		ci_enable_otg_interrupt(ci, OTGSC_BSVIE);
 		ci_handle_vbus_change(ci);
-	} else if (ci->is_otg && (ci->role == CI_ROLE_HOST)) {
-		/* USB Device at the MicroB to A cable */
-		otg_set_vbus(&ci->otg, true);
 	}
 }
 
@@ -603,6 +594,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 
 	ci->dev = dev;
 	ci->platdata = dev->platform_data;
+	ci->reg_vbus = ci->platdata->reg_vbus;
 	if (ci->platdata->phy)
 		ci->transceiver = ci->platdata->phy;
 	else
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index ead3158..8efbd44 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -21,6 +21,7 @@
 
 #include <linux/kernel.h>
 #include <linux/io.h>
+#include <linux/regulator/consumer.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/usb/chipidea.h>
@@ -64,9 +65,19 @@ static int host_start(struct ci13xxx *ci)
 	ehci->caps = ci->hw_bank.cap;
 	ehci->has_hostpc = ci->hw_bank.lpm;
 
+	if (ci->reg_vbus) {
+		ret = regulator_enable(ci->reg_vbus);
+		if (ret) {
+			dev_err(ci->dev,
+				"Failed to enable vbus regulator, ret=%d\n",
+				ret);
+			goto put_hcd;
+		}
+	}
+
 	ret = usb_add_hcd(hcd, 0, 0);
 	if (ret)
-		usb_put_hcd(hcd);
+		goto disable_reg;
 	else
 		ci->hcd = hcd;
 
@@ -74,6 +85,14 @@ static int host_start(struct ci13xxx *ci)
 		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
 
 	return ret;
+
+disable_reg:
+	if (ci->reg_vbus)
+		regulator_disable(ci->reg_vbus);
+put_hcd:
+	usb_put_hcd(hcd);
+
+	return ret;
 }
 
 static void host_stop(struct ci13xxx *ci)
@@ -82,6 +101,8 @@ static void host_stop(struct ci13xxx *ci)
 
 	usb_remove_hcd(hcd);
 	usb_put_hcd(hcd);
+	if (ci->reg_vbus)
+		regulator_disable(ci->reg_vbus);
 }
 
 int ci_hdrc_host_init(struct ci13xxx *ci)
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index d543e4a..1430403 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -23,6 +23,7 @@ struct ci13xxx_platform_data {
 #define CI13XXX_CONTROLLER_RESET_EVENT		0
 #define CI13XXX_CONTROLLER_STOPPED_EVENT	1
 	void	(*notify_event) (struct ci13xxx *ci, unsigned event);
+	struct regulator *reg_vbus;
 };
 
 /* Default offset of capability registers */
