USB: msm_otg: Update HTC variant of msm_otg

HTC kernel version: m7stock_3.4.10-g1a25406

Change-Id: I2707390c287a6d2a9f05814aea25362347240048
diff --git a/arch/arm/mach-msm/include/mach/board-ext-htc.h b/arch/arm/mach-msm/include/mach/board-ext-htc.h
index 8d14695..defd95b 100644
--- a/arch/arm/mach-msm/include/mach/board-ext-htc.h
+++ b/arch/arm/mach-msm/include/mach/board-ext-htc.h
@@ -27,6 +27,7 @@
 void msm_otg_set_vbus_state(int online);
 
 enum usb_connect_type {
+	CONNECT_TYPE_NOTIFY = -3,
 	CONNECT_TYPE_CLEAR = -2,
 	CONNECT_TYPE_UNKNOWN = -1,
 	CONNECT_TYPE_NONE = 0,
diff --git a/arch/arm/mach-msm/include/mach/cable_detect.h b/arch/arm/mach-msm/include/mach/cable_detect.h
index 172692a..0217be7 100644
--- a/arch/arm/mach-msm/include/mach/cable_detect.h
+++ b/arch/arm/mach-msm/include/mach/cable_detect.h
@@ -10,12 +10,24 @@
 #define DOCK_STATE_USB_HOST				(1 << 4)
 #define DOCK_STATE_DMB						(1 << 5)
 #define DOCK_STATE_AUDIO_DOCK				(1 << 6)
-
+#ifdef CONFIG_USB_OTG_HOST_CHG
+#define DOCK_STATE_HOST_CHG_DOCK			(1 << 7)
+#else
+#define DOCK_STATE_THREE_POGO_DOCK		(1 << 7)
+#endif
 #define DOCK_DET_DELAY		HZ/4
-
+#ifdef CONFIG_MACH_TC2
+#define ADC_RETRY 5
+#else
 #define ADC_RETRY 3
-#define ADC_DELAY HZ/8
+#endif
 
+#ifdef CONFIG_USB_OTG_HOST_CHG
+#define ADC_DELAY HZ/8
+#define HOST_DET_DELAY HZ/2
+#else
+#define ADC_DELAY HZ/8
+#endif
 #define PM8058ADC_15BIT(adc) ((adc * 2200) / 32767) 
 
 #define CABLE_ERR(fmt, args...) \
@@ -83,6 +95,9 @@
 	bool dock_detect;
 	int dock_pin_gpio;
 #endif
+	int idpin_irq;
+	int carkit_only;
+	int (*detect_three_pogo_dock)(void);
 	int enable_vbus_usb_switch;
 };
 
@@ -95,4 +110,5 @@
 extern int cable_get_usb_id_level(void);
 extern void cable_set_uart_switch(int);
 extern irqreturn_t cable_detection_vbus_irq_handler(void);
+extern int check_three_pogo_dock(void);
 #endif
diff --git a/drivers/misc/cable_detect_8xxx.c b/drivers/misc/cable_detect_8xxx.c
index 2264469..f321e2b 100644
--- a/drivers/misc/cable_detect_8xxx.c
+++ b/drivers/misc/cable_detect_8xxx.c
@@ -90,6 +90,7 @@
 
 	int  audio_dock_lock;
 	int notify_init;
+	int (*detect_three_pogo_dock)(void);
 	int enable_vbus_usb_switch;
 } the_cable_info;
 
@@ -158,6 +159,7 @@
 	return 0;
 }
 
+#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
 static DEFINE_MUTEX(usb_host_notify_sem);
 static void send_usb_host_connect_notify(int cable_in)
 {
@@ -189,11 +191,15 @@
 	mutex_unlock(&usb_host_notify_sem);
 	return 0;
 }
+#endif
 
 static void check_vbus_in(struct work_struct *w)
 {
 	int vbus_in;
 	int level;
+#if 0
+	int three_pogo_charging_type;
+#endif
 	struct cable_detect_info *pInfo = container_of(
 			w, struct cable_detect_info, vbus_detect_work.work);
 
@@ -213,7 +219,6 @@
 			&pInfo->cable_detect_work, ADC_DELAY);
 	}
 #endif
-
 	if (pInfo->notify_init == 0 && vbus_in == 0 && vbus == 0)
 		send_cable_connect_notify(CONNECT_TYPE_NONE);
 	if (pInfo->notify_init == 0 && vbus == vbus_in)
@@ -221,6 +226,37 @@
 
 	pInfo->notify_init = 1;
 
+#if 0
+	if (pInfo->detect_three_pogo_dock) {
+		printk(KERN_INFO "[CABLE]cable detect_three_pogo_dock\n");
+		if (vbus_in && pInfo->accessory_type == DOCK_STATE_UNDOCKED) {
+			three_pogo_charging_type = pInfo->detect_three_pogo_dock();
+			printk(KERN_INFO "[CABLE]cable detect_three_pogo_dock return %d\n",three_pogo_charging_type);
+			if (three_pogo_charging_type > 0) {
+				switch_set_state(&dock_switch, DOCK_STATE_DESK);
+				pInfo->accessory_type = DOCK_STATE_THREE_POGO_DOCK;
+				CABLE_INFO("three pogo dock\n");
+				if (three_pogo_charging_type == 1)
+					send_cable_connect_notify(CONNECT_TYPE_USB);
+				else if (three_pogo_charging_type == 2)
+					send_cable_connect_notify(CONNECT_TYPE_AC);
+				wake_unlock(&pInfo->vbus_wlock);
+				return;
+			}
+		} else {
+			if (pInfo->accessory_type == DOCK_STATE_THREE_POGO_DOCK) {
+				
+				switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
+				pInfo->accessory_type = DOCK_STATE_UNDOCKED;
+				CABLE_INFO("three pogo dock removed\n");
+				send_cable_connect_notify(CONNECT_TYPE_NONE);
+				wake_unlock(&pInfo->vbus_wlock);
+				return;
+			}
+		}
+	}
+#endif
+
 	if (vbus != vbus_in) {
 		vbus = vbus_in;
 
@@ -284,7 +320,11 @@
 		if (adc > -100 && adc < 100)
 			type = second_detect(pInfo);
 		else {
+#ifdef CONFIG_MACH_DUMMY
+			if (adc > 120 && adc < 220)
+#else
 			if (adc > 150 && adc < 220)
+#endif
 				type = DOCK_STATE_CAR;
 			else if (adc > 370 && adc < 440)
 				type = DOCK_STATE_USB_HEADSET;
@@ -318,7 +358,6 @@
 			w, struct cable_detect_info, cable_detect_work.work);
 	int value;
 	int accessory_type;
-
 	if (pInfo == NULL)
 		return;
 	if(pInfo->audio_dock_lock == 1) {
@@ -338,7 +377,6 @@
 		}
 	} else
 		accessory_type = DOCK_STATE_UNDOCKED;
-
 #ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
 	if (pInfo->mhl_reset_gpio != 0)
 		gpio_set_value_cansleep(pInfo->mhl_reset_gpio, 1); 
@@ -392,12 +430,14 @@
 		sii9234_mhl_device_wakeup();
 		break;
 #endif
+#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
 	case DOCK_STATE_USB_HOST:
 		CABLE_INFO("USB Host inserted\n");
 		send_usb_host_connect_notify(1);
 		pInfo->accessory_type = DOCK_STATE_USB_HOST;
 		switch_set_state(&dock_switch, DOCK_STATE_USB_HOST);
 		break;
+#endif
 	case DOCK_STATE_DMB:
 		CABLE_INFO("DMB inserted\n");
 		send_cable_connect_notify(CONNECT_TYPE_CLEAR);
@@ -422,6 +462,14 @@
 #endif
 #endif
 		break;
+#ifdef CONFIG_USB_OTG_HOST_CHG
+	case DOCK_STATE_HOST_CHG_DOCK:
+		CABLE_INFO("USB Host charger inserted\n");
+		send_usb_host_connect_notify(1);
+		pInfo->accessory_type = DOCK_STATE_HOST_CHG_DOCK;
+		switch_set_state(&dock_switch, DOCK_STATE_USB_HOST);
+		break;
+#endif
 	case DOCK_STATE_UNDEFINED:
 	case DOCK_STATE_UNDOCKED:
 		switch (pInfo->accessory_type) {
@@ -451,12 +499,14 @@
 			sii9234_disableIRQ();
 			break;
 #endif
+#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
 		case DOCK_STATE_USB_HOST:
 			CABLE_INFO("USB host cable removed\n");
 			pInfo->accessory_type = DOCK_STATE_UNDOCKED;
 			send_usb_host_connect_notify(0);
 			switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
 			break;
+#endif
 		case DOCK_STATE_DMB:
 			CABLE_INFO("DMB removed\n");
 			switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
@@ -470,6 +520,13 @@
 #endif
 			pInfo->accessory_type = DOCK_STATE_UNDOCKED;
 			break;
+#ifdef CONFIG_USB_OTG_HOST_CHG
+		case DOCK_STATE_HOST_CHG_DOCK:
+			CABLE_INFO("USB host charger removed\n");
+			send_usb_host_connect_notify(0);
+			switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
+			break;
+#endif
 		}
 	default :
 		break;
@@ -504,6 +561,17 @@
 	return the_cable_info.accessory_type;
 }
 
+int check_three_pogo_dock(void)
+{
+	int three_pogo_charging_type;
+	if (the_cable_info.detect_three_pogo_dock) {
+		three_pogo_charging_type = the_cable_info.detect_three_pogo_dock();
+		printk(KERN_INFO "[CABLE]cable detect_three_pogo_dock return %d\n",three_pogo_charging_type);
+		return three_pogo_charging_type;
+	}
+	return 0;
+}
+
 static int cable_detect_get_adc(void)
 {
 	struct cable_detect_info *pInfo = &the_cable_info;
@@ -541,9 +609,17 @@
 		type = DOCK_STATE_UNDEFINED;
 #endif
 	else if(adc_value >= 1021 && adc_value <= 1224)
+#ifdef CONFIG_USB_OTG_HOST_CHG
+		type = DOCK_STATE_HOST_CHG_DOCK;
+#else
 		type = DOCK_STATE_AUDIO_DOCK;
+#endif
 	else
+#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
 		type = DOCK_STATE_USB_HOST;
+#else
+		type = DOCK_STATE_UNDEFINED;
+#endif
 
 	if (pInfo->config_usb_id_gpios)
 		pInfo->config_usb_id_gpios(0);
@@ -586,8 +662,13 @@
 
 	CABLE_INFO("usb: id interrupt\n");
 	pInfo->cable_redetect = 0;
+#ifdef CONFIG_USB_OTG_HOST_CHG
+	queue_delayed_work(pInfo->cable_detect_wq,
+		&pInfo->cable_detect_work, HOST_DET_DELAY);
+#else
 	queue_delayed_work(pInfo->cable_detect_wq,
 		&pInfo->cable_detect_work, ADC_DELAY);
+#endif
 	wake_lock_timeout(&pInfo->cable_detect_wlock, HZ*2);
 	return IRQ_HANDLED;
 }
@@ -879,6 +960,7 @@
 		pInfo->mhl_version_ctrl_flag = pdata->mhl_version_ctrl_flag;
 		pInfo->mhl_1v2_power = pdata->mhl_1v2_power;
 		pInfo->get_adc_cb = pdata->get_adc_cb;
+		pInfo->detect_three_pogo_dock = pdata->detect_three_pogo_dock;
 		pInfo->enable_vbus_usb_switch = pdata->enable_vbus_usb_switch;
 #endif
 
@@ -991,7 +1073,7 @@
 	struct cable_detect_info*pInfo = &the_cable_info;
 
 	CABLE_INFO("%s: cable_type = %d\n", __func__, cable_type);
-
+#ifndef CONFIG_USB_OTG_HOST_CHG
 	
 	if(pInfo->audio_dock_lock == 0 && (cable_type == CONNECT_TYPE_USB || cable_type == CONNECT_TYPE_AC || cable_type == CONNECT_TYPE_MHL_AC))
 		if(pInfo->accessory_type == DOCK_STATE_AUDIO_DOCK) {
@@ -1008,7 +1090,7 @@
 			}
 #endif
 		}
-
+#endif
 	if (cable_type > CONNECT_TYPE_NONE ||
 			cable_type == CONNECT_TYPE_UNKNOWN) {
 		if (pInfo->ad_en_gpio) {
diff --git a/drivers/usb/otg/msm_otg_htc.c b/drivers/usb/otg/msm_otg_htc.c
index 6fc9595..29977bb 100644
--- a/drivers/usb/otg/msm_otg_htc.c
+++ b/drivers/usb/otg/msm_otg_htc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2013, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -41,6 +41,9 @@
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/misc.h>
 #include <linux/power_supply.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>
 
 #include <mach/clk.h>
 #include <mach/msm_xo.h>
@@ -53,23 +56,38 @@
 #define MSM_USB_BASE	(motg->regs)
 #define DRIVER_NAME	"msm_otg"
 
+extern int htc_battery_set_max_input_current(int target_ma);
 static int htc_otg_vbus;
-static int USB_disabled;
+int USB_disabled;
 static struct msm_otg *the_msm_otg;
 
+static int re_enable_host;
+static int stop_usb_host;
+
 enum {
     NOT_ON_AUTOBOT,
     DOCK_ON_AUTOBOT,
     HTC_MODE_RUNNING
 };
 
+
+enum {
+	DEFAULT_STATE,
+	TRY_STOP_HOST_STATE,
+	STOP_HOST_STATE,
+	TRY_ENABLE_HOST_STATE
+};
+
+static DEFINE_MUTEX(smwork_sem);
 static DEFINE_MUTEX(notify_sem);
 static void send_usb_connect_notify(struct work_struct *w)
 {
 	static struct t_usb_status_notifier *notifier;
 	struct msm_otg *motg = container_of(w, struct msm_otg,	notifier_work);
+	struct usb_otg *otg;
 	if (!motg)
 		return;
+	otg = motg->phy.otg;
 
 	motg->connect_type_ready = 1;
 	USBH_INFO("send connect type %d\n", motg->connect_type);
@@ -78,13 +96,21 @@
 		if (notifier->func != NULL) {
 			/* Notify other drivers about connect type. */
 			/* use slow charging for unknown type*/
+#if 0
 			if (motg->connect_type == CONNECT_TYPE_UNKNOWN)
 				notifier->func(CONNECT_TYPE_USB);
 			else
+#endif
 				notifier->func(motg->connect_type);
 		}
 	}
 	mutex_unlock(&notify_sem);
+	if ((board_mfg_mode() == 5 || USB_disabled )&& motg->connect_type == CONNECT_TYPE_USB) { 
+		pm_runtime_put_noidle(otg->phy->dev);
+		pm_runtime_suspend(otg->phy->dev);
+	}
+	if (motg->chg_type == USB_CDP_CHARGER)
+		htc_battery_set_max_input_current(900);
 }
 
 int htc_usb_register_notifier(struct t_usb_status_notifier *notifier)
@@ -171,7 +197,6 @@
 static struct regulator *hsusb_3p3;
 static struct regulator *hsusb_1p8;
 static struct regulator *hsusb_vddcx;
-/*static struct regulator *vbus_otg;*/
 static struct regulator *mhl_usb_hs_switch;
 static struct power_supply *psy;
 
@@ -934,7 +959,7 @@
 	struct usb_otg *otg = motg->phy.otg;
 	struct msm_otg_platform_data *pdata = motg->pdata;
 	int cnt = 0;
-	bool host_bus_suspend, device_bus_suspend, dcp;
+	bool host_bus_suspend, device_bus_suspend, dcp, prop_charger;
 	u32 phy_ctrl_val = 0, cmd_val;
 	unsigned ret;
 	u32 portsc;
@@ -950,6 +975,15 @@
 		test_bit(A_BUS_SUSPEND, &motg->inputs) &&
 		motg->caps & ALLOW_LPM_ON_DEV_SUSPEND;
 	dcp = motg->chg_type == USB_DCP_CHARGER;
+	prop_charger = motg->chg_type == USB_PROPRIETARY_CHARGER;
+
+	
+	if (test_bit(B_SESS_VLD, &motg->inputs) && !device_bus_suspend &&
+			!dcp && !prop_charger) {
+		enable_irq(motg->irq);
+		return -EBUSY;
+	}
+
 	/*
 	 * Chipidea 45-nm PHY suspend sequence:
 	 *
@@ -1011,11 +1045,12 @@
 	 * enable asynchronous interrupt to detect charger disconnection when
 	 * PMIC notifications are unavailable.
 	 */
+
 	if (otg->phy->state == OTG_STATE_A_WAIT_BCON) {
 		USBH_INFO("%s:enable the ASYNC_INTR\n", __func__);
 		cmd_val = readl_relaxed(USB_USBCMD);
 		if (host_bus_suspend || device_bus_suspend ||
-				(motg->pdata->otg_control == OTG_PHY_CONTROL && dcp))
+				(motg->pdata->otg_control == OTG_PHY_CONTROL))
 			cmd_val |= ASYNC_INTR_CTRL | ULPI_STP_CTRL;
 		else
 			cmd_val |= ULPI_STP_CTRL;
@@ -1065,7 +1100,9 @@
 		motg->lpm_flags |= PHY_PWR_COLLAPSED;
 	}
 
-	if (motg->lpm_flags & PHY_RETENTIONED) {
+	
+	if ((motg->lpm_flags & PHY_RETENTIONED) ||
+	    (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY &&	!host_bus_suspend && !device_bus_suspend && !dcp)) {
 		msm_hsusb_config_vddcx(0);
 		msm_hsusb_mhl_switch_enable(motg, 0);
 	}
@@ -1086,25 +1123,23 @@
 	return 0;
 }
 
-/*HTC_WIFI_START*/
 int msm_otg_setclk(int on)
 {
     if (on) {
         if (!the_msm_otg->pdata->core_clk_always_on_workaround) {
             clk_prepare_enable(the_msm_otg->core_clk);
-            //clk_prepare_enable(the_msm_otg->pclk);
+            
         }
     }
     else {
         if (!the_msm_otg->pdata->core_clk_always_on_workaround) {
             clk_disable_unprepare(the_msm_otg->core_clk);
-            //clk_disable_unprepare(the_msm_otg->pclk);
+            
         }
     }
     return 0;
 }
 EXPORT_SYMBOL(msm_otg_setclk);
-/*HTC_WIFI_END*/
 
 static int msm_otg_resume(struct msm_otg *motg)
 {
@@ -1140,6 +1175,12 @@
 		USBH_DEBUG("exit phy power collapse...\n");
 	}
 
+	
+	if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
+		msm_hsusb_mhl_switch_enable(motg, 1);
+		msm_hsusb_config_vddcx(1);
+	}
+
 	if (motg->lpm_flags & PHY_RETENTIONED) {
 		msm_hsusb_mhl_switch_enable(motg, 1);
 		msm_hsusb_config_vddcx(1);
@@ -1210,22 +1251,6 @@
 	return 0;
 }
 #endif
-/*
-static int msm_otg_notify_host_mode(struct msm_otg *motg, bool host_mode)
-{
-	if (!psy)
-		goto psy_not_supported;
-
-	if (host_mode)
-		power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_SYSTEM);
-	else
-		power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_DEVICE);
-
-psy_not_supported:
-	dev_dbg(motg->phy.dev, "Power Supply doesn't support USB charger\n");
-	return -ENXIO;
-}
-*/
 static int msm_otg_notify_chg_type(struct msm_otg *motg)
 {
 	static int charger_type;
@@ -1354,6 +1379,21 @@
 	if (!otg->host)
 		return;
 
+	if (USB_disabled) {
+		if (stop_usb_host == TRY_STOP_HOST_STATE) {
+			USBH_INFO("[USB_disabled] %s(%d) to stop host \n", __func__ , on);
+			stop_usb_host = STOP_HOST_STATE;
+		} else {
+			USBH_INFO("[USB_disabled] %s(%d) return\n", __func__ , on);
+			
+			if (on) {
+				re_enable_host = TRY_ENABLE_HOST_STATE;
+				stop_usb_host = STOP_HOST_STATE;
+			}
+			return;
+		}
+	}
+
 	hcd = bus_to_hcd(otg->host);
 
 	if (on) {
@@ -1531,15 +1571,6 @@
 		USBH_INFO("Host mode is not supported\n");
 		return -ENODEV;
 	}
-/*
-	if (!motg->pdata->vbus_power && host) {
-		vbus_otg = devm_regulator_get(motg->phy.dev, "vbus_otg");
-		if (IS_ERR(vbus_otg)) {
-			pr_err("Unable to get vbus_otg\n");
-			return -ENODEV;
-		}
-	}
-*/
 
 	if (!host) {
 		USB_WARNING("%s: no host\n", __func__);
@@ -1631,6 +1662,27 @@
 
 }
 
+static void usb_disable_work(struct work_struct *w)
+{
+	struct msm_otg *motg = the_msm_otg;
+	struct usb_phy *usb_phy = &motg->phy;
+	USBH_INFO("%s\n", __func__);
+	motg->chg_type = USB_DCP_CHARGER;
+	motg->chg_state = USB_CHG_STATE_DETECTED;
+	msm_otg_start_peripheral(usb_phy->otg, 0);
+	usb_phy->state = OTG_STATE_B_IDLE;
+	queue_work(system_nrt_wq, &motg->sm_work);
+}
+
+static void msm_otg_notify_usb_disabled(void)
+{
+	struct msm_otg *motg = the_msm_otg;
+	struct usb_phy *usb_phy = &motg->phy;
+	USBH_INFO("%s\n", __func__);
+	usb_gadget_vbus_disconnect(usb_phy->otg->gadget);
+	queue_work(system_nrt_wq, &motg->usb_disable_work);
+}
+
 static int msm_otg_set_peripheral(struct usb_otg *otg,
 			struct usb_gadget *gadget)
 {
@@ -2047,6 +2099,8 @@
 		udelay(20);
 		break;
 	case SNPS_28NM_INTEGRATED_PHY:
+		
+		ulpi_write(phy, 0x6, 0xC);
 		/* Clear charger detecting control bits */
 		ulpi_write(phy, 0x1F, 0x86);
 		/* Clear alt interrupt latch and enable bits */
@@ -2077,6 +2131,8 @@
 		/* Clear alt interrupt latch and enable bits */
 		ulpi_write(phy, 0x1F, 0x92);
 		ulpi_write(phy, 0x1F, 0x95);
+		
+		ulpi_write(phy, 0x6, 0xB);
 		break;
 	default:
 		break;
@@ -2104,8 +2160,8 @@
 	}
 }
 
-#define MSM_CHG_DCD_POLL_TIME		(100 * HZ/1000) /* 100 msec */
-#define MSM_CHG_DCD_MAX_RETRIES		6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_DCD_TIMEOUT			(750 * HZ/1000) /* 750 msec */
+#define MSM_CHG_DCD_POLL_TIME		(50 * HZ/1000) /* 50 msec */
 #define MSM_CHG_PRIMARY_DET_TIME	(50 * HZ/1000) /* TVDPSRC_ON */
 #define MSM_CHG_SECONDARY_DET_TIME	(50 * HZ/1000) /* TVDMSRC_ON */
 static void msm_chg_detect_work(struct work_struct *w)
@@ -2115,10 +2171,13 @@
 	bool is_dcd = false, tmout, vout, is_aca;
 	u32 line_state, dm_vlgc;
 	unsigned long delay;
-
 	USBH_INFO("%s: state:%s\n", __func__,
 		chg_state_string(motg->chg_state));
+#ifdef CONFIG_USB_OTG_HOST_CHG
+	if (otg->phy->state >= OTG_STATE_A_IDLE && cable_get_accessory_type() != DOCK_STATE_HOST_CHG_DOCK) {
+#else
 	if (otg->phy->state >= OTG_STATE_A_IDLE) {
+#endif
 		motg->chg_state = USB_CHG_STATE_UNDEFINED;
 		USBH_INFO("%s: usb host, charger state:%s\n", __func__, chg_state_string(motg->chg_state));
 		if (motg->connect_type != CONNECT_TYPE_NONE) {
@@ -2127,11 +2186,11 @@
 		}
 		return;
 	}
+
 	switch (motg->chg_state) {
 	case USB_CHG_STATE_UNDEFINED:
 		msm_chg_block_on(motg);
-		if (motg->pdata->enable_dcd)
-			msm_chg_enable_dcd(motg);
+		msm_chg_enable_dcd(motg);
 		msm_chg_enable_aca_det(motg);
 		motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
 		motg->dcd_time = 0;
@@ -2151,12 +2210,11 @@
 				break;
 			}
 		}
-		if (motg->pdata->enable_dcd)
-			is_dcd = msm_chg_check_dcd(motg);
-		tmout = ++motg->dcd_time == MSM_CHG_DCD_MAX_RETRIES;
+		is_dcd = msm_chg_check_dcd(motg);
+		motg->dcd_time += MSM_CHG_DCD_POLL_TIME;
+		tmout = motg->dcd_time >= MSM_CHG_DCD_TIMEOUT;
 		if (is_dcd || tmout) {
-			if (motg->pdata->enable_dcd)
-				msm_chg_disable_dcd(motg);
+			msm_chg_disable_dcd(motg);
 			msm_chg_enable_primary_det(motg);
 			delay = MSM_CHG_PRIMARY_DET_TIME;
 			motg->chg_state = USB_CHG_STATE_DCD_DONE;
@@ -2168,16 +2226,20 @@
 		vout = msm_chg_check_primary_det(motg);
 		line_state = readl_relaxed(USB_PORTSC) & PORTSC_LS;
 		dm_vlgc = line_state & PORTSC_LS_DM;
+		USBH_INFO("line_state = %x\n",line_state);
 		if (vout && !dm_vlgc) { /* VDAT_REF < DM < VLGC */
 			if (test_bit(ID_A, &motg->inputs)) {
 				motg->chg_type = USB_ACA_DOCK_CHARGER;
 				motg->chg_state = USB_CHG_STATE_DETECTED;
+				motg->connect_type = CONNECT_TYPE_UNKNOWN;
 				delay = 0;
 				break;
 			}
 			if (line_state) { /* DP > VLGC */
 				motg->chg_type = USB_PROPRIETARY_CHARGER;
 				motg->chg_state = USB_CHG_STATE_DETECTED;
+				motg->connect_type = CONNECT_TYPE_AC;
+				USBH_INFO("DP > VLGC\n");
 				delay = 0;
 			} else {
 				msm_chg_enable_secondary_det(motg);
@@ -2188,32 +2250,39 @@
 			if (test_bit(ID_A, &motg->inputs)) {
 				motg->chg_type = USB_ACA_A_CHARGER;
 				motg->chg_state = USB_CHG_STATE_DETECTED;
+				motg->connect_type = CONNECT_TYPE_UNKNOWN;
 				delay = 0;
 				break;
 			}
 
-			if (line_state) /* DP > VLGC or/and DM > VLGC */
+			if (line_state) { /* DP > VLGC or/and DM > VLGC */
 				motg->chg_type = USB_PROPRIETARY_CHARGER;
-			else
+				motg->connect_type = CONNECT_TYPE_AC;
+				USBH_INFO("DP > VLGC or/and DM > VLGC\n");
+			} else {
 				motg->chg_type = USB_SDP_CHARGER;
+				motg->connect_type = CONNECT_TYPE_UNKNOWN;
+			}
 
 			motg->chg_state = USB_CHG_STATE_DETECTED;
-			motg->connect_type = CONNECT_TYPE_UNKNOWN;
 			delay = 0;
 		}
 		break;
 	case USB_CHG_STATE_PRIMARY_DONE:
 		vout = msm_chg_check_secondary_det(motg);
-		if (vout)
+		if (vout) {
 			motg->chg_type = USB_DCP_CHARGER;
-		else
+			motg->connect_type = CONNECT_TYPE_AC;
+		} else {
 			motg->chg_type = USB_CDP_CHARGER;
-		motg->connect_type = CONNECT_TYPE_AC;
+			motg->connect_type = CONNECT_TYPE_USB;
+		}
 		motg->chg_state = USB_CHG_STATE_SECONDARY_DONE;
-		/* fall through */
+		
 	case USB_CHG_STATE_SECONDARY_DONE:
 		motg->chg_state = USB_CHG_STATE_DETECTED;
 	case USB_CHG_STATE_DETECTED:
+		msm_otg_notify_chg_type(motg);
 		msm_chg_block_off(motg);
 		msm_chg_enable_aca_det(motg);
 		/*
@@ -2330,6 +2399,7 @@
 						__func__, motg->phy.state);
 		return;
 	}
+	mutex_lock(&smwork_sem);
 	pm_runtime_resume(otg->phy->dev);
 	pr_debug("%s work\n", otg_state_string(otg->phy->state));
 	switch (otg->phy->state) {
@@ -2356,7 +2426,11 @@
 			clear_bit(B_BUS_REQ, &motg->inputs);
 			set_bit(A_BUS_REQ, &motg->inputs);
 			otg->phy->state = OTG_STATE_A_IDLE;
+#ifdef CONFIG_USB_OTG_HOST_CHG
+			if (motg->connect_type != CONNECT_TYPE_NONE && cable_get_accessory_type() != DOCK_STATE_HOST_CHG_DOCK && motg->connect_type != CONNECT_TYPE_CLEAR) {
+#else
 			if (motg->connect_type != CONNECT_TYPE_NONE) {
+#endif
 				motg->connect_type = CONNECT_TYPE_NONE;
 				queue_work(motg->usb_wq, &motg->notifier_work);
 			}
@@ -2404,27 +2478,13 @@
 						OTG_STATE_B_PERIPHERAL;
 					break;
 				case USB_SDP_CHARGER:
-					/* Change USB SDP charger current from 100mA to 500mA
-					 * msm_otg_notify_charger(motg, IUNIT);
-					 */
-					if (USB_disabled) {
-						USBH_INFO("Fake Sleep: disable USB function\n");
-						/* Enable VDP_SRC */
-						ulpi_write(otg->phy, 0x2, 0x85);
-						msm_otg_notify_charger(motg,IDEV_CHG_MIN);
-						if (motg->reset_phy_before_lpm)
-							msm_otg_reset(otg->phy);
-						pm_runtime_put_noidle(otg->phy->dev);
-						pm_runtime_suspend(otg->phy->dev);
-					} else {
-						/* Turn off VDP_SRC */
-						ulpi_write(otg->phy, 0x3, 0x86);
-						msm_otg_notify_charger(motg, IDEV_CHG_MIN);
-						msm_otg_start_peripheral(otg, 1);
-						otg->phy->state = OTG_STATE_B_PERIPHERAL;
-						motg->ac_detect_count = 0;
-						queue_delayed_work(system_nrt_wq, &motg->ac_detect_work, 3 * HZ);
-					 }
+					/* Turn off VDP_SRC */
+					ulpi_write(otg->phy, 0x3, 0x86);
+					msm_otg_notify_charger(motg, IDEV_CHG_MIN);
+					msm_otg_start_peripheral(otg, 1);
+					otg->phy->state = OTG_STATE_B_PERIPHERAL;
+					motg->ac_detect_count = 0;
+					queue_delayed_work(system_nrt_wq, &motg->ac_detect_work, 2 * HZ);
 					break;
 				default:
 					break;
@@ -2499,10 +2559,12 @@
 				queue_work(motg->usb_wq, &motg->notifier_work);
 			}
 
-                        //			if (check_htc_mode_status() != NOT_ON_AUTOBOT) {
-                        //				htc_mode_enable(0);
-                        //				android_switch_default();
-                        //			}
+#if 0
+			if (check_htc_mode_status() != NOT_ON_AUTOBOT) {
+				htc_mode_enable(0);
+				android_switch_default();
+			}
+#endif
 			USBH_INFO("!id  || id_a/b || !b_sess_vld\n");
 			motg->chg_state = USB_CHG_STATE_UNDEFINED;
 			motg->chg_type = USB_INVALID_CHARGER;
@@ -2660,10 +2722,19 @@
 			 */
 			usleep_range(10000, 12000);
 			/* ACA: ID_A: Stop charging untill enumeration */
-			if (test_bit(ID_A, &motg->inputs))
+			if (test_bit(ID_A, &motg->inputs)) {
 				msm_otg_notify_charger(motg, 0);
-			else
+			}
+			else {
+#ifdef CONFIG_USB_OTG_HOST_CHG
+				if (htc_otg_vbus == 1 && cable_get_accessory_type() == DOCK_STATE_HOST_CHG_DOCK)
+					msm_hsusb_vbus_power(motg, 0);
+				else
+					msm_hsusb_vbus_power(motg, 1);
+#else
 				msm_hsusb_vbus_power(motg, 1);
+#endif
+			}
 			msm_otg_start_timer(motg, TA_WAIT_VRISE, A_WAIT_VRISE);
 		} else {
 			USBH_INFO("No session requested\n");
@@ -2752,7 +2823,22 @@
 			if (TA_WAIT_BCON < 0)
 				pm_runtime_put_sync(otg->phy->dev);
 		} else if (!test_bit(ID, &motg->inputs)) {
-			msm_hsusb_vbus_power(motg, 1);
+#ifdef CONFIG_USB_OTG_HOST_CHG
+			if (cable_get_accessory_type() != DOCK_STATE_HOST_CHG_DOCK)
+				msm_hsusb_vbus_power(motg, 1);
+#endif
+		}
+
+		if (USB_disabled && stop_usb_host != STOP_HOST_STATE) {
+			USBH_INFO("[USB_disabled] disable USB Host function\n");
+			stop_usb_host = TRY_STOP_HOST_STATE;
+			re_enable_host = TRY_ENABLE_HOST_STATE;
+			msm_otg_start_host(otg, 0);
+		} else if (!USB_disabled && re_enable_host == TRY_ENABLE_HOST_STATE) {
+			USBH_INFO("[USB_disabled] re-enable USB Host function\n");
+			re_enable_host = DEFAULT_STATE;
+			stop_usb_host = DEFAULT_STATE;
+			msm_otg_start_host(otg, 1);
 		}
 		break;
 	case OTG_STATE_A_HOST:
@@ -2810,8 +2896,23 @@
 		} else if (!test_bit(ID, &motg->inputs)) {
 			motg->chg_state = USB_CHG_STATE_UNDEFINED;
 			motg->chg_type = USB_INVALID_CHARGER;
+#ifdef CONFIG_USB_OTG_HOST_CHG
+			if (htc_otg_vbus == 1 && cable_get_accessory_type() == DOCK_STATE_HOST_CHG_DOCK)
+				msm_hsusb_vbus_power(motg, 0);
+			else {
+				msm_otg_notify_charger(motg, 0);
+				msm_hsusb_vbus_power(motg, 1);
+			}
+#else
 			msm_otg_notify_charger(motg, 0);
 			msm_hsusb_vbus_power(motg, 1);
+#endif
+			if (USB_disabled) {
+				USBH_INFO("[USB_disabled] disable USB Host function\n");
+				re_enable_host = TRY_ENABLE_HOST_STATE;
+				stop_usb_host = TRY_STOP_HOST_STATE;
+				msm_otg_start_host(otg, 0);
+			}
 		}
 		break;
 	case OTG_STATE_A_SUSPEND:
@@ -2855,6 +2956,13 @@
 			if (TA_WAIT_BCON > 0)
 				msm_otg_start_timer(motg, TA_WAIT_BCON,
 					A_WAIT_BCON);
+
+			if (!USB_disabled && re_enable_host == TRY_ENABLE_HOST_STATE) {
+				USBH_INFO("[USB_disabled] re-enable USB Host function\n");
+				re_enable_host = DEFAULT_STATE;
+				stop_usb_host = DEFAULT_STATE;
+				msm_otg_start_host(otg, 1);
+			}
 		} else if (test_bit(ID_A, &motg->inputs)) {
 			msm_hsusb_vbus_power(motg, 0);
 			msm_otg_notify_charger(motg,
@@ -2931,6 +3039,7 @@
 	default:
 		break;
 	}
+	mutex_unlock(&smwork_sem);
 	if (work)
 		queue_work(system_nrt_wq, &motg->sm_work);
 }
@@ -2985,27 +3094,6 @@
 		work = 1;
 	} else if (otgsc & OTGSC_BSVIS) {
 		writel_relaxed(otgsc, USB_OTGSC);
-		/*
-		 * BSV interrupt comes when operating as an A-device
-		 * (VBUS on/off).
-		 * But, handle BSV when charger is removed from ACA in ID_A
-		 */
-		/*
-		if ((otg->phy->state >= OTG_STATE_A_IDLE) &&
-			!test_bit(ID_A, &motg->inputs))
-			return IRQ_HANDLED;
-		if (otgsc & OTGSC_BSV) {
-			pr_debug("BSV set\n");
-			set_bit(B_SESS_VLD, &motg->inputs);
-		} else {
-			pr_debug("BSV clear\n");
-			clear_bit(B_SESS_VLD, &motg->inputs);
-			clear_bit(A_BUS_SUSPEND, &motg->inputs);
-
-			msm_chg_check_aca_intr(motg);
-		}
-		work = 1;
-		*/
 	} else if (usbsts & STS_PCI) {
 		pc = readl_relaxed(USB_PORTSC);
 		pr_debug("portsc = %x\n", pc);
@@ -3099,29 +3187,25 @@
 	return ret;
 }
 
-
 /* The dedicated 9V detection GPIO will be high if VBUS is in and over 6V.
  * Since D+/D- status is not involved, there is no timing issue between
  * D+/D- and VBUS. 9V AC should NOT be found here.
  */
 static void ac_detect_expired_work(struct work_struct *w)
 {
-	u32 delay = 0;
+	u32 delay = 0, line_state;
 	struct msm_otg *motg = the_msm_otg;
 	struct usb_phy *usb_phy = &motg->phy;
 
-	USBH_INFO("%s: count = %d, connect_type = %d\n", __func__,
-			motg->ac_detect_count, motg->connect_type);
+	line_state = readl(USB_PORTSC) & PORTSC_LS;
+	USBH_INFO("%s: count = %d, connect_type = %d, line_state = %x\n", __func__,
+			motg->ac_detect_count, motg->connect_type,line_state << 10);
 
-	if (motg->connect_type == CONNECT_TYPE_USB || motg->ac_detect_count >= 3)
+	if (motg->connect_type == CONNECT_TYPE_USB || motg->ac_detect_count >= 5)
 		return;
 
 	/* detect shorted D+/D-, indicating AC power */
-	if ((readl(USB_PORTSC) & PORTSC_LS) != PORTSC_LS) {
-		/* Some carkit can't be recognized as AC mode.
-		 * Add SW solution here to notify battery driver should
-		 * work as AC charger when car mode activated.
-		 */
+	if (line_state != PORTSC_LS) {
 #ifdef CONFIG_CABLE_DETECT_ACCESSORY
 		if (cable_get_accessory_type() == DOCK_STATE_CAR
 			||cable_get_accessory_type() == DOCK_STATE_AUDIO_DOCK) {
@@ -3134,16 +3218,40 @@
 				msm_otg_start_peripheral(usb_phy->otg, 0);
 				usb_phy->state = OTG_STATE_B_IDLE;
 				queue_work(system_nrt_wq, &motg->sm_work);
-
 				queue_work(motg->usb_wq, &motg->notifier_work);
 				return;
 		}
+		{
+			int dock_result = check_three_pogo_dock();
+			if (dock_result == 2) {
+				USBH_INFO("three pogo dock AC type\n");
+				motg->chg_type = USB_DCP_CHARGER;
+				motg->chg_state = USB_CHG_STATE_DETECTED;
+				motg->connect_type = CONNECT_TYPE_AC;
+				motg->ac_detect_count = 0;
+
+				msm_otg_start_peripheral(usb_phy->otg, 0);
+				usb_phy->state = OTG_STATE_B_IDLE;
+				queue_work(system_nrt_wq, &motg->sm_work);
+				queue_work(motg->usb_wq, &motg->notifier_work);
+				return;
+			} else if (dock_result == 1) {
+				USBH_INFO("three pogo dock USB type\n");
+				motg->chg_type = USB_INVALID_CHARGER;
+				motg->chg_state = USB_CHG_STATE_DETECTED;
+				motg->connect_type = CONNECT_TYPE_NONE;
+				motg->ac_detect_count = 0;
+
+				msm_otg_start_peripheral(usb_phy->otg, 0);
+				usb_phy->state = OTG_STATE_B_IDLE;
+				queue_work(system_nrt_wq, &motg->sm_work);
+				queue_work(motg->usb_wq, &motg->notifier_work);
+				return;
+			}
+		}
 #endif
-		motg->ac_detect_count++;
-		if (motg->ac_detect_count == 1)
-			delay = 5 * HZ;
-		else if (motg->ac_detect_count == 2)
-			delay = 10 * HZ;
+		if (motg->ac_detect_count++ < 5)
+			delay = 2 * HZ;
 
 		queue_delayed_work(system_nrt_wq, &motg->ac_detect_work, delay);
 	} else {
@@ -3161,11 +3269,12 @@
 	}
 }
 
+#ifndef CONFIG_CABLE_DETECT_8X60
 static void htc_vbus_notify(int online)
 {
 	cable_detection_vbus_irq_handler();
-	/*cable_detection_vbus_notify(online);*/
 }
+#endif
 
 int msm_otg_get_vbus_state(void)
 {
@@ -3178,12 +3287,15 @@
 	struct msm_otg *motg = the_msm_otg;
 	struct usb_otg *otg = motg->phy.otg;
 	USBH_INFO("%s: %d\n", __func__, online);
-
 	htc_otg_vbus = online;
+#ifdef CONFIG_USB_OTG_HOST_CHG
 	/* In A Host Mode, ignore received BSV interrupts */
+	if (online && otg->phy->state >= OTG_STATE_A_IDLE && cable_get_accessory_type() == DOCK_STATE_HOST_CHG_DOCK)
+		return;
+#else
 	if (online && otg->phy->state >= OTG_STATE_A_IDLE)
 		return;
-
+#endif
 	if (online) {
 		pr_debug("PMIC: BSV set\n");
 		set_bit(B_SESS_VLD, &motg->inputs);
@@ -3193,6 +3305,10 @@
 		/*USB*/
 		if (motg->pdata->usb_uart_switch)
 			motg->pdata->usb_uart_switch(0);
+		if (motg->connect_type == 0) {
+			motg->connect_type = CONNECT_TYPE_NOTIFY;
+			queue_work(motg->usb_wq, &motg->notifier_work);
+		}
 	} else {
 		pr_debug("PMIC: BSV clear\n");
 		clear_bit(B_SESS_VLD, &motg->inputs);
@@ -3217,6 +3333,7 @@
 }
 
 
+#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
 void msm_otg_set_id_state(int id)
 {
 	struct msm_otg *motg = the_msm_otg;
@@ -3243,6 +3360,7 @@
 	else
 		msm_otg_set_id_state(1);
 }
+#endif
 
 void msm_otg_set_disable_usb(int disable_usb)
 {
@@ -3250,6 +3368,8 @@
 
 	USB_disabled = disable_usb;
 
+	if (!disable_usb)
+		motg->chg_state = USB_CHG_STATE_UNDEFINED;
 	queue_work(system_nrt_wq, &motg->sm_work);
 }
 
@@ -3606,10 +3726,12 @@
 	debugfs_remove_recursive(msm_otg_dbg_root);
 }
 
+#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
 static struct t_usb_host_status_notifier usb_host_status_notifier = {
 	.name = "usb_host",
 	.func = usb_host_cable_detect,
 };
+#endif
 
 static u64 msm_otg_dma_mask = DMA_BIT_MASK(64);
 static struct platform_device *msm_otg_add_pdev(
@@ -3981,6 +4103,7 @@
 	wake_lock_init(&motg->cable_detect_wlock, WAKE_LOCK_SUSPEND, "msm_usb_cable");
 	msm_otg_init_timer(motg);
 	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
+	INIT_WORK(&motg->usb_disable_work, usb_disable_work);
 	INIT_WORK(&motg->notifier_work, send_usb_connect_notify);
 	INIT_DELAYED_WORK(&motg->ac_detect_work, ac_detect_expired_work);
 	INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
@@ -4000,6 +4123,7 @@
 	phy->set_power = msm_otg_set_power;
 	phy->set_suspend = msm_otg_set_suspend;
 	phy->notify_usb_attached = msm_otg_notify_usb_attached;
+	phy->notify_usb_disabled = msm_otg_notify_usb_disabled;
 	phy->io_ops = &msm_otg_io_ops;
 	phy->send_event = msm_otg_send_event;
 	phy->otg->send_event = msm_otg_send_event2;
@@ -4028,12 +4152,7 @@
 				goto remove_phy;
 			}
 		} else {
-			/* HTC hw design doesn't need the following code. mask it when hw is not EVM*/
-			/*
-			ret = -ENODEV;
-			dev_err(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist\n");
-			goto remove_otg;
-			*/
+			
 			dev_dbg(&pdev->dev, "PMIC IRQ for ID notifications doesn't exist. Maybe monitor id pin by GPIO");
 		}
 	}
@@ -4049,17 +4168,24 @@
 		dev_dbg(&pdev->dev, "mode debugfs file is"
 			"not available\n");
 
-	if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
-		pm8921_charger_register_vbus_sn(&htc_vbus_notify/*&msm_otg_set_vbus_state*/);
+	if (motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+#ifdef CONFIG_CABLE_DETECT_8X60
+		pm8921_charger_register_vbus_sn(&msm_otg_set_vbus_state);
+#else
+		pm8921_charger_register_vbus_sn(&htc_vbus_notify);
+#endif
+	}
 
+#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
 	usb_host_detect_register_notifier(&usb_host_status_notifier);
+#endif
 
 	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY) {
 #if 0
 		if (motg->pdata->otg_control == OTG_PMIC_CONTROL &&
 			(!(motg->pdata->mode == USB_OTG) ||
 			 motg->pdata->pmic_id_irq))
-			motg->caps = /*ALLOW_PHY_POWER_COLLAPSE |*/ ALLOW_PHY_RETENTION;
+			motg->caps =  ALLOW_PHY_RETENTION;
 #endif
 
 		if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index aaf0a05..24dc1de 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -220,7 +220,7 @@
 	bool mhl_enable;
 	bool disable_reset_on_disconnect;
 #ifdef CONFIG_MACH_HTC
-        bool enable_dcd;
+	bool enable_dcd;
 #endif
 	bool enable_lpm_on_dev_suspend;
 	bool core_clk_always_on_workaround;
@@ -398,6 +398,7 @@
 	int connect_type_ready;
 	struct workqueue_struct *usb_wq;
 	struct delayed_work ac_detect_work;
+	struct work_struct usb_disable_work;
 	int ac_detect_count;
 	int reset_phy_before_lpm;
 #endif
@@ -407,6 +408,9 @@
 	u8 active_tmout;
 	struct hrtimer timer;
 	enum usb_vdd_type vdd_type;
+#ifdef CONFIG_MACH_HTC
+	struct delayed_work init_work;
+#endif
 };
 
 struct msm_hsic_host_platform_data {
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index a584d24..9b58245d 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -161,6 +161,7 @@
 			enum usb_otg_event event);
 
 	void	(*notify_usb_attached)(void);
+	void	(*notify_usb_disabled)(void);
 #endif
 };