예제 #1
0
static void msm_otg_power_work(struct work_struct *w)
{
	struct msm_otg *motg = container_of(w, struct msm_otg, otg_power_work);
	int otg_test = gpio_get_value_cansleep(motg->pdata->otg_test_gpio);

	msleep(200);

	pr_info("id: %d, otg_test: %d\n",
			test_bit(ID, &motg->inputs), otg_test);

	/* host */
	if (!test_bit(ID, &motg->inputs)) {
		if (otg_test) {
			motg->ndev.booster = NOTIFY_POWER_ON;
		} else {
			motg->ndev.booster = NOTIFY_POWER_OFF;
			host_state_notify(&motg->ndev, NOTIFY_HOST_OVERCURRENT);
			pr_err("OTG Overcurrent!\n");
		}

	} else {
		if (motg->ndev.mode == NOTIFY_HOST_MODE && otg_test == 0)
			motg->ndev.booster = NOTIFY_POWER_OFF;
	}
}
예제 #2
0
static irqreturn_t host_notifier_currentlimit_irq_thread
						(int irq, void *data)
{
	unsigned long flags = 0;
	int gpio_value = 0;
	spin_lock_irqsave(&ninfo.vbus_gpio.lock, flags);
	if (ninfo.pdata->inverse_vbus_trigger)
		gpio_value = !ninfo.vbus_gpio.gpio_status ;
	else
		gpio_value = ninfo.vbus_gpio.gpio_status ;
	spin_unlock_irqrestore(&ninfo.vbus_gpio.lock, flags);

	if (gpio_value) {
		ninfo.pdata->ndev.booster = NOTIFY_POWER_ON;
		pr_info("Acc power on detect\n");
	} else {
		if ((ninfo.pdata->ndev.mode == NOTIFY_HOST_MODE)
			&& (ninfo.pdata->ndev.booster == NOTIFY_POWER_ON)) {
			host_state_notify(&ninfo.pdata->ndev,
				NOTIFY_HOST_OVERCURRENT);
			pr_err("OTG overcurrent!!!!!!\n");
		}
		ninfo.pdata->ndev.booster = NOTIFY_POWER_OFF;
	}
	return IRQ_HANDLED;
}
예제 #3
0
static irqreturn_t currentlimit_irq_thread(int irq, void *data)
{
	struct host_notifier_info *hostinfo = data;
	struct host_notify_dev *ndev = &hostinfo->pdata->ndev;
	int gpio = hostinfo->pdata->gpio;
	int prev = ndev->booster;
	int ret = 0;

	ret = gpio_get_value(gpio);
	pr_info("currentlimit_irq_thread gpio : %d, value : %d\n", gpio, ret);

	if (prev != ret) {
		pr_info("host_notifier currentlimit_irq_thread: gpio %d = %s\n",
				gpio, ret ? "HIGH" : "LOW");
		ndev->booster = ret ?
			NOTIFY_POWER_ON : NOTIFY_POWER_OFF;
		prev = ret;

		if (!ret && ndev->mode == NOTIFY_HOST_MODE) {
			host_state_notify(ndev,
					NOTIFY_HOST_OVERCURRENT);
			pr_err("host_notifier currentlimit_irq_thread: overcurrent\n");
		}
	}
	return IRQ_HANDLED;
}
예제 #4
0
static int currentlimit_thread(void *data)
{
	struct host_notifier_info *ninfo = data;
	struct host_notify_dev *ndev = &ninfo->pdata->ndev;
	int gpio = ninfo->pdata->gpio;
	int prev = ndev->booster;
	int ret = 0;

	pr_info("host_notifier usbhostd: start %d\n", prev);

	while (!kthread_should_stop()) {
		wait_event_interruptible_timeout(ninfo->delay_wait,
				ninfo->thread_remove, 1 * HZ);

		ret = gpio_get_value(gpio);
		if (prev != ret) {
			pr_info("host_notifier usbhostd: gpio %d = %s\n",
					gpio, ret ? "HIGH" : "LOW");
			ndev->booster = ret ?
				NOTIFY_POWER_ON : NOTIFY_POWER_OFF;
			prev = ret;

			if (!ret && ndev->mode == NOTIFY_HOST_MODE) {
				host_state_notify(ndev,
						NOTIFY_HOST_OVERCURRENT);
				pr_err("host_notifier usbhostd: overcurrent\n");
				break;
			}
		}
	}

	ninfo->thread_remove = 1;
	pr_info("host_notifier usbhostd: exit %d\n", ret);
	return 0;
}
static int ovc_scan_thread(void *data)
{
	struct ovc *ovcinfo = NULL;
	int state;

	if (!u_notify) {
		pr_err("%s u_notify is NULL\n", __func__);
		return 0;
	}

	ovcinfo = &u_notify->ovc_info;
	while (!kthread_should_stop()) {
		wait_event_interruptible_timeout(ovcinfo->delay_wait,
			ovcinfo->thread_remove, (ovcinfo->poll_period)*HZ);
		if (ovcinfo->thread_remove)
			break;
		mutex_lock(&u_notify->ovc_info.ovc_lock);
		if (ovcinfo->check_state
			&& ovcinfo->data
				&& ovcinfo->can_ovc) {

			state = ovcinfo->check_state(data);

			if (ovcinfo->prev_state != state) {
				if (state == HNOTIFY_LOW) {
					pr_err("%s overcurrent detected\n",
							__func__);
					host_state_notify(&u_notify->ndev,
						NOTIFY_HOST_OVERCURRENT);
				} else if (state == HNOTIFY_HIGH) {
					pr_info("%s vbus draw detected\n",
							__func__);
					host_state_notify(&u_notify->ndev,
						NOTIFY_HOST_NONE);
				}
			}
			ovcinfo->prev_state = state;
		}
		mutex_unlock(&u_notify->ovc_info.ovc_lock);
		if (!ovcinfo->can_ovc)
			ovcinfo->thread_remove = 1;
	}

	pr_info("ovc_scan_thread exit\n");
	complete_and_exit(&ovcinfo->scanning_done, 0);
	return 0;
}
예제 #6
0
static int start_usbhostd_notify(void)
{
	pr_info("host_notifier: start usbhostd notify\n");

	host_state_notify(&ninfo.pdata->ndev, NOTIFY_HOST_ADD);
	wake_lock(&ninfo.wlock);

	return 0;
}
예제 #7
0
static int stop_usbhostd_notify(void)
{
	pr_info("host_notifier: stop usbhostd notify\n");

	host_state_notify(&ninfo.pdata->ndev, NOTIFY_HOST_REMOVE);
	wake_unlock(&ninfo.wlock);

	return 0;
}
예제 #8
0
static void msm_otg_host_notify(struct msm_otg *motg, int on)
{
	pr_info("host_notify: %d, dock %d\n", on, motg->smartdock);

	if (on)
		msm_otg_host_phy_tune(motg, 0x33, 0x14);

	if (motg->smartdock) {
		motg->ndev.state = NOTIFY_HOST_REMOVE;
		return;
	}

	if (on) {
		motg->ndev.mode = NOTIFY_HOST_MODE;
		host_state_notify(&motg->ndev, NOTIFY_HOST_ADD);
	} else {
		motg->ndev.mode = NOTIFY_NONE_MODE;
		host_state_notify(&motg->ndev, NOTIFY_HOST_REMOVE);
	}
}
예제 #9
0
static int start_usbhostd_notify(void)
{
	pr_info("host_notifier: start usbhostd notify\n");
#ifdef CONFIG_MACH_P4NOTE
	host_notifier_enable_irq();
#endif

	host_state_notify(&ninfo.pdata->ndev, NOTIFY_HOST_ADD);
	wake_lock(&ninfo.wlock);

	return 0;
}
예제 #10
0
static int stop_usbhostd_notify(void)
{
	pr_info("host_notifier: stop usbhostd notify\n");
#ifdef CONFIG_MACH_P4NOTE
	host_notifier_disable_irq();
#endif

	host_state_notify(&ninfo.pdata->ndev, NOTIFY_HOST_REMOVE);
	wake_unlock(&ninfo.wlock);

	return 0;
}
예제 #11
0
static int stop_usbhostd_thread(void)
{
	if (ninfo.th) {
		pr_info("host_notifier: stop thread\n");

		if (!ninfo.thread_remove)
			kthread_stop(ninfo.th);

		ninfo.th = NULL;
		host_state_notify(&ninfo.pdata->ndev, NOTIFY_HOST_REMOVE);
		wake_unlock(&ninfo.wlock);
	} else
		pr_info("host_notifier: no thread\n");

	return 0;
}
예제 #12
0
static void otg_power_work(struct work_struct *work)
{
	struct sec_otghost *otghost = container_of(work,
				struct sec_otghost, work);
	struct sec_otghost_data *hdata = otghost->otg_data;

	if (hdata && hdata->set_pwr_cb) {
		pr_info("otg power off - don't turn off the power\n");
		hdata->set_pwr_cb(0);
#ifdef CONFIG_USB_HOST_NOTIFY
		if (g_pUsbHcd)
			host_state_notify(&g_pUsbHcd->ndev,
					NOTIFY_HOST_OVERCURRENT);
#endif
	} else {
		otg_err(true, "invalid otghost data\n");
	}
}
예제 #13
0
static int currentlimit_thread(void *data)
{
	struct host_notifier_info *ninfo = data;
	struct host_notify_dev *ndev = &ninfo->pdata->ndev;
	int gpio = ninfo->pdata->gpio;
	int count = 0;
	int ret = 0;

	pr_info("host_notifier usbhostd: start mode %d\n",
			ndev->mode);

	ndev->booster = NOTIFY_POWER_ON;

	while (!kthread_should_stop()) {
		wait_event_interruptible_timeout(ninfo->delay_wait,
				ninfo->thread_remove, 1 * HZ);

		ret = gpio_get_value(gpio);

		if ((count++ % 10) == 0) {
			pr_info("host_notifier usbhostd: mode %d, count %d, %s\n",
				ndev->mode, count, ret ? "HIGH" : "LOW");
		}

		if (!ret) {
			pr_info("host_notifier usbhostd: mode %d, count %d, (%d, %d)\n",
				ndev->mode, count, ndev->booster, ret);

			ndev->booster = NOTIFY_POWER_OFF;

			if (ndev->mode == NOTIFY_HOST_MODE) {
				host_state_notify(ndev,
						NOTIFY_HOST_OVERCURRENT);
				pr_err("host_notifier usbhostd: overcurrent\n");
				break;
			}
		}
	}

	ninfo->thread_remove = 1;

	pr_info("host_notifier usbhostd: exit %d\n", ret);
	return 0;
}
예제 #14
0
static irqreturn_t tegra_currentlimit_irq_thread(int irq, void *data)
{
	struct tegra_otg_data *tegra = data;

	if (tegra_get_accpower_level(tegra->currentlimit_irq)) {
#ifdef CONFIG_USB_HOST_NOTIFY
		tegra->ndev.booster = NOTIFY_POWER_ON;
#endif
		dev_info(tegra->otg.dev, "Acc power on detect\n");
	} else {
#ifdef CONFIG_USB_HOST_NOTIFY
		if (tegra->ndev.mode == NOTIFY_HOST_MODE) {
			host_state_notify(&tegra->ndev,
				NOTIFY_HOST_OVERCURRENT, false);
			dev_err(tegra->otg.dev, "OTG overcurrent!!!!!!\n");
		}
		tegra->ndev.booster = NOTIFY_POWER_OFF;
#endif
	}
	return IRQ_HANDLED;
}
예제 #15
0
static void msm_otg_notify_work(struct work_struct *w)
{
	struct msm_otg *motg = container_of(w, struct msm_otg, notify_work);

	if (motg->smartdock)
		return;

	switch (motg->notify_state) {
	case ACC_POWER_ON:
		dev_info(motg->phy.dev, "Acc power on detect\n");
		break;
	case ACC_POWER_OFF:
		dev_info(motg->phy.dev, "Acc power off detect\n");
		break;
	case ACC_POWER_OVER_CURRENT:
		host_state_notify(&motg->ndev, NOTIFY_HOST_OVERCURRENT);
		dev_err(motg->phy.dev, "OTG overcurrent!!!!!!\n");
		break;
	default:
		break;
	}
}
static irqreturn_t vbus_irq_thread(int irq, void *data)
{
	struct otg_notify *notify = NULL;
	unsigned long flags = 0;
	int gpio_value = 0;

	if (!u_notify) {
		pr_err("u_notify is NULL\n");
		return IRQ_HANDLED;
	}
	notify = u_notify->o_notify;

	spin_lock_irqsave(&u_notify->v_gpio.lock, flags);
	gpio_value = u_notify->v_gpio.gpio_status;
	spin_unlock_irqrestore(&u_notify->v_gpio.lock, flags);

	if (gpio_value) {
		u_notify->ndev.booster = NOTIFY_POWER_ON;
		pr_info("vbus on detect\n");
		if (notify->post_vbus_detect)
			notify->post_vbus_detect(NOTIFY_POWER_ON);
	} else {
		if ((u_notify->ndev.mode == NOTIFY_HOST_MODE)
			&& (u_notify->ndev.booster == NOTIFY_POWER_ON
				&& u_notify->oc_noti)) {
			host_state_notify(&u_notify->ndev,
					NOTIFY_HOST_OVERCURRENT);
			pr_err("OTG overcurrent!!!!!!\n");
		} else {
			pr_info("vbus off detect\n");
			if (notify->post_vbus_detect)
				notify->post_vbus_detect(NOTIFY_POWER_OFF);
		}
		u_notify->ndev.booster = NOTIFY_POWER_OFF;
	}
	return IRQ_HANDLED;
}
예제 #17
0
static int start_usbhostd_thread(void)
{
	if (!ninfo.th) {
		pr_info("host_notifier: start usbhostd thread\n");

		init_waitqueue_head(&ninfo.delay_wait);
		ninfo.thread_remove = 0;
		ninfo.th = kthread_run(currentlimit_thread,
				&ninfo, "usbhostd");

		if (IS_ERR(ninfo.th)) {
			pr_err("host_notifier: Unable to start usbhostd\n");
			ninfo.th = NULL;
			ninfo.thread_remove = 1;
			return -1;
		}
		host_state_notify(&ninfo.pdata->ndev, NOTIFY_HOST_ADD);
		wake_lock(&ninfo.wlock);

	} else
		pr_info("host_notifier: usbhostd already started!\n");

	return 0;
}
예제 #18
0
static void irq_work(struct work_struct *work)
{
	struct tegra_otg_data *tegra =
		container_of(work, struct tegra_otg_data, work);
	struct otg_transceiver *otg = &tegra->otg;
	enum usb_otg_state from = otg->state;
	enum usb_otg_state to = OTG_STATE_UNDEFINED;
	unsigned long flags;
	unsigned long status;

	if (tegra->detect_vbus) {
		tegra->detect_vbus = false;
		tegra_otg_enable_clk();
		return;
	}

	clk_enable(tegra->clk);

	spin_lock_irqsave(&tegra->lock, flags);

	status = tegra->int_status;

	/* Debug prints */
	DBG("%s(%d) status = 0x%x\n", __func__, __LINE__, status);
	if ((status & USB_ID_INT_STATUS) &&
			(status & USB_VBUS_INT_STATUS))
		DBG("%s(%d) got vbus & id interrupt\n", __func__, __LINE__);
	else {
		if (status & USB_ID_INT_STATUS)
			DBG("%s(%d) got id interrupt\n", __func__, __LINE__);
		if (status & USB_VBUS_INT_STATUS)
			DBG("%s(%d) got vbus interrupt\n", __func__, __LINE__);
	}

	if (tegra->int_status & USB_ID_INT_STATUS) {
		if (status & USB_ID_STATUS) {
			if ((status & USB_VBUS_STATUS) && (from != OTG_STATE_A_HOST))
				to = OTG_STATE_B_PERIPHERAL;
			else
				to = OTG_STATE_A_SUSPEND;
		}
		else
			to = OTG_STATE_A_HOST;
	}
	if (from != OTG_STATE_A_HOST) {
		if (tegra->int_status & USB_VBUS_INT_STATUS) {
			if (status & USB_VBUS_STATUS)
				to = OTG_STATE_B_PERIPHERAL;
			else
				to = OTG_STATE_A_SUSPEND;
		}
	}
	spin_unlock_irqrestore(&tegra->lock, flags);

	if (to != OTG_STATE_UNDEFINED) {
		otg->state = to;

		dev_info(tegra->otg.dev, "%s --> %s\n", tegra_state_name(from),
					      tegra_state_name(to));

		if (tegra->charger_cb)
			tegra->charger_cb(to, from, tegra->charger_cb_data);

		if (to == OTG_STATE_A_SUSPEND) {
#ifdef CONFIG_MACH_SAMSUNG_VARIATION_TEGRA
#ifdef CONFIG_USB_HOST_NOTIFY
			tegra->ndev.mode = NOTIFY_NONE_MODE;
#endif
#endif
			if (from == OTG_STATE_A_HOST) {
#ifdef CONFIG_MACH_SAMSUNG_VARIATION_TEGRA
#ifdef CONFIG_USB_HOST_NOTIFY
				host_state_notify(&tegra->ndev,
					 NOTIFY_HOST_REMOVE, false);
#endif
#endif
				tegra_stop_host(tegra);
			} else if (from == OTG_STATE_B_PERIPHERAL
					&& otg->gadget)
#ifdef _SEC_DM_
				if (!usb_access_lock)
#endif
					usb_gadget_vbus_disconnect(otg->gadget);
		} else if (to == OTG_STATE_B_PERIPHERAL && otg->gadget) {
			if (from != OTG_STATE_B_PERIPHERAL)
#ifdef _SEC_DM_
				if (!usb_access_lock)
#endif
					usb_gadget_vbus_connect(otg->gadget);
#ifdef CONFIG_MACH_SAMSUNG_VARIATION_TEGRA
#ifdef CONFIG_USB_HOST_NOTIFY
			tegra->ndev.mode = NOTIFY_PERIPHERAL_MODE;
#endif
#endif
		} else if (to == OTG_STATE_A_HOST) {
			if (from == OTG_STATE_A_SUSPEND)
				tegra_start_host(tegra);
#ifdef CONFIG_MACH_SAMSUNG_VARIATION_TEGRA
			else if (from == OTG_STATE_B_PERIPHERAL) {
#ifdef _SEC_DM_
				if (!usb_access_lock)
#endif
					usb_gadget_vbus_disconnect(otg->gadget);
				tegra_start_host(tegra);
			}
#ifdef CONFIG_USB_HOST_NOTIFY
			tegra->ndev.mode = NOTIFY_HOST_MODE;
			host_state_notify(&tegra->ndev, NOTIFY_HOST_ADD, false);
#endif
#endif
		}
	}
	clk_disable(tegra->clk);
	tegra_otg_disable_clk();
}
static void otg_notify_state(unsigned long event, int enable)
{
	struct otg_notify *notify = NULL;

	if (!u_notify) {
		pr_err("u_notify is NULL\n");
		goto no_save_event;
	}

	pr_info("%s+ event=%s(%lu), enable=%s\n", __func__,
		event_string(event), event, enable == 0 ? "off" : "on");

	notify = get_otg_notify();

	switch (event) {
	case NOTIFY_EVENT_NONE:
		break;
	case NOTIFY_EVENT_SMARTDOCK_USB:
	case NOTIFY_EVENT_VBUS:
		if (enable) {
			u_notify->ndev.mode = NOTIFY_PERIPHERAL_MODE;
			if (notify->is_wakelock)
				wake_lock(&u_notify->wlock);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 1);
			if (notify->set_peripheral)
				notify->set_peripheral(true);
		} else {
			u_notify->ndev.mode = NOTIFY_NONE_MODE;
			if (notify->set_peripheral)
				notify->set_peripheral(false);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 0);
			if (notify->is_wakelock)
				wake_unlock(&u_notify->wlock);
		}
		break;
	case NOTIFY_EVENT_LANHUB_TA:
		u_notify->diable_v_drive = enable;
		if (enable)
			u_notify->oc_noti = 0;
		if (notify->set_lanhubta)
			notify->set_lanhubta(enable);
		break;
	case NOTIFY_EVENT_LANHUB:
		if (notify->unsupport_host) {
			pr_err("This model doesn't support usb host\n");
			goto err;
		}
		u_notify->diable_v_drive = enable;
		if (enable) {
			u_notify->oc_noti = 0;
			u_notify->ndev.mode = NOTIFY_HOST_MODE;
			if (notify->is_wakelock)
				wake_lock(&u_notify->wlock);
			host_state_notify(&u_notify->ndev, NOTIFY_HOST_ADD);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 1);
			if (notify->set_host)
				notify->set_host(true);
		} else {
			u_notify->ndev.mode = NOTIFY_NONE_MODE;
			if (notify->set_host)
				notify->set_host(false);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 0);
			host_state_notify(&u_notify->ndev, NOTIFY_HOST_REMOVE);
			if (notify->is_wakelock)
				wake_unlock(&u_notify->wlock);
		}
		break;
	case NOTIFY_EVENT_HOST:
		if (notify->unsupport_host) {
			pr_err("This model doesn't support usb host\n");
			goto err;
		}
		u_notify->diable_v_drive = 0;
		if (enable) {
			u_notify->ndev.mode = NOTIFY_HOST_MODE;
			if (notify->is_wakelock)
				wake_lock(&u_notify->wlock);
			host_state_notify(&u_notify->ndev, NOTIFY_HOST_ADD);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 1);
			if (notify->auto_drive_vbus) {
				u_notify->oc_noti = 1;
				if (notify->vbus_drive)
					notify->vbus_drive(1);
			}
			if (notify->set_host)
				notify->set_host(true);
		} else {
			u_notify->ndev.mode = NOTIFY_NONE_MODE;
			if (notify->auto_drive_vbus) {
				u_notify->oc_noti = 0;
				if (notify->vbus_drive)
					notify->vbus_drive(0);
			}
			if (notify->set_host)
				notify->set_host(false);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 0);
			host_state_notify(&u_notify->ndev, NOTIFY_HOST_REMOVE);
			if (notify->is_wakelock)
				wake_unlock(&u_notify->wlock);
		}
		break;
	case NOTIFY_EVENT_CHARGER:
		if (notify->set_charger)
			notify->set_charger(enable);
		break;
	case NOTIFY_EVENT_MMDOCK:
		enable_ovc(u_notify, enable);
		/* To detect overcurrent, ndev state is initialized */
		if (enable)
			host_state_notify(&u_notify->ndev,
							NOTIFY_HOST_NONE);
	case NOTIFY_EVENT_SMARTDOCK_TA:
	case NOTIFY_EVENT_AUDIODOCK:
		if (notify->unsupport_host) {
			pr_err("This model doesn't support usb host\n");
			goto err;
		}
		u_notify->diable_v_drive = enable;
		if (enable) {
			u_notify->ndev.mode = NOTIFY_HOST_MODE;
			if (notify->is_wakelock)
				wake_lock(&u_notify->wlock);
			if (notify->set_host)
				notify->set_host(true);
		} else {
			u_notify->ndev.mode = NOTIFY_NONE_MODE;
			if (notify->set_host)
				notify->set_host(false);
			if (notify->is_wakelock)
				wake_unlock(&u_notify->wlock);
		}
		break;
	case NOTIFY_EVENT_DRIVE_VBUS:
		if (notify->unsupport_host) {
			pr_err("This model doesn't support usb host\n");
			goto no_save_event;
		}
		if (u_notify->diable_v_drive) {
			pr_info("cable type=%s disable vbus draw\n",
					event_string(u_notify->c_type));
			goto no_save_event;
		}
		u_notify->oc_noti = enable;
		if (notify->vbus_drive)
			notify->vbus_drive((bool)enable);
		goto no_save_event;
	default:
		break;
	}
err:
	if (enable)
		u_notify->c_type = event;
	else
		u_notify->c_type = NOTIFY_EVENT_NONE;

no_save_event:
	pr_info("%s- event=%s, cable=%s\n", __func__,
		event_string(event),
			event_string(u_notify->c_type));
}
예제 #20
0
/* usb cable call back function */
void max77803_muic_usb_cb(u8 usb_mode)
{
#ifdef CONFIG_USB_HOST_NOTIFY
	struct host_notifier_platform_data *host_noti_pdata =
	    host_notifier_device.dev.platform_data;
	int cable_type = max77803_muic_get_charging_type();
#endif

	if (is_usb_locked) {
		pr_info("%s: usb locked by mdm\n", __func__);
		return;
	}

	if (usb_mode == USB_CABLE_ATTACHED) {
#if defined(CONFIG_MFD_MAX77803) || defined(CONFIG_MFD_MAX77888)
		g_usbvbus = USB_CABLE_ATTACHED;
#endif
#ifdef CONFIG_HA_3G
		if(system_rev >= 6)
			usb30_redriver_en(1);
#elif defined(CONFIG_V1A) || defined(CONFIG_V2A)
		usb30_redriver_en(1);
#endif
		max77803_set_vbus_state(USB_CABLE_ATTACHED);
		pr_info("%s - USB_CABLE_ATTACHED\n", __func__);
	} else if (usb_mode == USB_CABLE_DETACHED) {
#if defined(CONFIG_MFD_MAX77803) || defined(CONFIG_MFD_MAX77888)
		g_usbvbus = USB_CABLE_DETACHED;
#endif
#ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE
#ifdef CONFIG_HA_3G
		usb30en = 0;
#endif
#endif

#ifdef CONFIG_HA_3G
		if(system_rev >= 6)
			usb30_redriver_en(0);
#elif defined(CONFIG_V1A) || defined(CONFIG_V2A)
		usb30_redriver_en(0);
#endif
		max77803_set_vbus_state(USB_CABLE_DETACHED);
		pr_info("%s - USB_CABLE_DETACHED\n", __func__);
	} else if (usb_mode == USB_OTGHOST_ATTACHED) {
#ifdef CONFIG_USB_HOST_NOTIFY
		host_noti_pdata->booster(1);
		host_noti_pdata->ndev.mode = NOTIFY_HOST_MODE;
		if (host_noti_pdata->usbhostd_start)
			host_noti_pdata->usbhostd_start();
		/* defense code for otg mis-detecing issue */
		msleep(50);
#endif
		max77803_check_id_state(0);
		pr_info("%s - USB_OTGHOST_ATTACHED\n", __func__);
	} else if (usb_mode == USB_OTGHOST_DETACHED) {
		max77803_check_id_state(1);
#ifdef CONFIG_USB_HOST_NOTIFY
		host_noti_pdata->ndev.mode = NOTIFY_NONE_MODE;
		if (host_noti_pdata->usbhostd_stop)
			host_noti_pdata->usbhostd_stop();
		host_noti_pdata->booster(0);
#endif
		pr_info("%s - USB_OTGHOST_DETACHED\n", __func__);
	} else if (usb_mode == USB_POWERED_HOST_ATTACHED) {
#ifdef CONFIG_USB_HOST_NOTIFY
		host_noti_pdata->powered_booster(1);

		if (cable_type == CABLE_TYPE_MMDOCK_MUIC) {
			enable_ovc(1);
			host_state_notify(&host_noti_pdata->ndev,
				NOTIFY_HOST_NONE);
		}

		if (cable_type == CABLE_TYPE_LANHUB_MUIC)
		{
			host_noti_pdata->ndev.mode = NOTIFY_HOST_MODE;
			if (host_noti_pdata->usbhostd_start)
				host_noti_pdata->usbhostd_start();
		}
		else
			start_usbhostd_wakelock();
#endif
		max77803_check_id_state(0);
		pr_info("%s - USB_POWERED_HOST_ATTACHED\n", __func__);
	} else if (usb_mode == USB_POWERED_HOST_DETACHED) {
		max77803_check_id_state(1);
#ifdef CONFIG_USB_HOST_NOTIFY
		host_noti_pdata->powered_booster(0);

		if (cable_type == CABLE_TYPE_MMDOCK_MUIC) {
			enable_ovc(0);
		}

		if (host_noti_pdata->ndev.mode == NOTIFY_HOST_MODE)
		{
			host_noti_pdata->ndev.mode = NOTIFY_NONE_MODE;
			if (host_noti_pdata->usbhostd_stop)
				host_noti_pdata->usbhostd_stop();
		}
		else
			stop_usbhostd_wakelock();
#endif
		pr_info("%s - USB_POWERED_HOST_DETACHED\n", __func__);
	}
}
static void extra_notify_state(unsigned long event, int enable)
{
	struct otg_notify *notify = NULL;

	if (!u_notify) {
		pr_err("u_notify is NULL\n");
		goto err;
	}

	pr_info("%s+ event=%s(%lu), enable=%s\n", __func__,
		event_string(event), event, enable == 0 ? "off" : "on");

	notify = get_otg_notify();

	switch (event) {
	case NOTIFY_EVENT_NONE:
		break;
	case NOTIFY_EVENT_OVERCURRENT:
		if (!u_notify->ndev.dev) {
			pr_err("ndev is NULL. Maybe usb host is not supported.\n");
			break;
		}
		host_state_notify(&u_notify->ndev,
						NOTIFY_HOST_OVERCURRENT);
		pr_err("OTG overcurrent!!!!!!\n");
		break;
	case NOTIFY_EVENT_VBUSPOWER:
		 if (enable)
			u_notify->ndev.booster = NOTIFY_POWER_ON;
		 else
			u_notify->ndev.booster = NOTIFY_POWER_OFF;
		break;
	case NOTIFY_EVENT_SMSC_OVC:
		if (enable)
			ovc_start(u_notify);
		else
			ovc_stop(u_notify);
		break;
	case NOTIFY_EVENT_SMTD_EXT_CURRENT:
		if (u_notify->c_type != NOTIFY_EVENT_SMARTDOCK_TA) {
			pr_err("No smart dock!!!!!!\n");
			break;
		}
		if (notify->set_battcall)
			notify->set_battcall
				(NOTIFY_EVENT_SMTD_EXT_CURRENT, enable);
		break;
	case NOTIFY_EVENT_MMD_EXT_CURRENT:
		if (u_notify->c_type != NOTIFY_EVENT_MMDOCK) {
			pr_err("No mmdock!!!!!!\n");
			break;
		}
		if (notify->set_battcall)
			notify->set_battcall
				(NOTIFY_EVENT_MMD_EXT_CURRENT, enable);
		break;
	default:
		break;
	}

	pr_info("%s- event=%s(%lu), cable=%s\n", __func__,
		event_string(event), event,
		event_string(u_notify->c_type));
err:
	return;
}