void ovc_start(struct usb_notify *u_noti)
{
	struct otg_notify *o_notify = get_otg_notify();

	if (!o_notify) {
		pr_err("%s o_notify is NULL\n", __func__);
		goto skip;
	}

	if (!u_noti->ovc_info.can_ovc)
		goto skip;

	u_noti->ovc_info.prev_state = HNOTIFY_INITIAL;
	u_noti->ovc_info.poll_period = (o_notify->smsc_ovc_poll_sec) ?
			o_notify->smsc_ovc_poll_sec : DEFAULT_OVC_POLL_SEC;
	INIT_COMPLETION(u_noti->ovc_info.scanning_done);
	u_noti->ovc_info.thread_remove = 0;
	u_noti->ovc_info.th = kthread_run(ovc_scan_thread,
			u_noti->ovc_info.data, "ovc-scan-thread");
	if (IS_ERR(u_noti->ovc_info.th)) {
		pr_err("Unable to start the ovc-scanning thread\n");
		complete(&u_noti->ovc_info.scanning_done);
	}
	pr_info("%s on\n", __func__);
	return;
skip:
	complete(&u_noti->ovc_info.scanning_done);
	pr_info("%s skip\n", __func__);
	return;
}
Esempio n. 2
0
static int sec_cable_notifier(struct notifier_block *nb,
                              unsigned long cable_type, void *v)
{
    struct otg_notify *o_notify;
    uint32_t vbus_status = *(uint32_t *)v;

    o_notify = get_otg_notify();

    sec_cable_log((u8)cable_type, vbus_status);

    switch (cable_type) {
    case MUIC_USB_ATTACH_NOTI:
        send_otg_notify(o_notify, NOTIFY_EVENT_VBUS, ATTACH);
        break;
    case MUIC_USB_DETACH_NOTI:
        send_otg_notify(o_notify, NOTIFY_EVENT_VBUS, DETACH);
        break;
    case MUIC_OTG_ATTACH_NOTI:
        send_otg_notify(o_notify, NOTIFY_EVENT_HOST, ATTACH);
        break;
    case MUIC_OTG_DETACH_NOTI:
        send_otg_notify(o_notify, NOTIFY_EVENT_HOST, DETACH);
        break;
    case MUIC_VBUS_NOTI:
        send_otg_notify(o_notify, NOTIFY_EVENT_VBUSPOWER,
                        (bool)vbus_status);
        break;
    default:
        break;
    }
    return 1;

}
static int smb328_otg_over_current_status(struct i2c_client *client)
{
	struct sec_charger_info *charger = i2c_get_clientdata(client);
	u8 irq_c, stat_c = 0;

#ifdef CONFIG_USB_NOTIFY_LAYER
	struct otg_notify *o_notify = get_otg_notify();
#endif

	smb328_i2c_read(client, SMB328_INTERRUPT_STATUS_C, &irq_c);
	pr_info("%s : Charging status C(0x%02x)\n", __func__, stat_c);
	if ((charger->cable_type == POWER_SUPPLY_TYPE_OTG) &&
		(irq_c & 0x40)) {
		pr_info("%s: otg overcurrent limit\n", __func__);
#ifdef CONFIG_USB_NOTIFY_LAYER
		send_otg_notify(o_notify, NOTIFY_EVENT_OVERCURRENT, 0);
#endif
		smb328_charger_otg_control(charger, 0);
	}
}
static int vbus_handle_notification(struct notifier_block *nb,
		unsigned long cmd, void *data)
{
	vbus_status_t vbus_type = *(vbus_status_t *)data;
	struct otg_notify *o_notify;

	o_notify = get_otg_notify();

	pr_info("%s cmd=%lu, vbus_type=%s\n",
		__func__, cmd, vbus_type == STATUS_VBUS_HIGH ? "HIGH" : "LOW");

	switch (vbus_type) {
	case STATUS_VBUS_HIGH:
		send_otg_notify(o_notify, NOTIFY_EVENT_VBUSPOWER, 1);
		break;
	case STATUS_VBUS_LOW:
		send_otg_notify(o_notify, NOTIFY_EVENT_VBUSPOWER, 0);
		break;
	default:
		break;
	}
	return 0;
}
void sm5504_callback(enum cable_type_t cable_type, int attached)
{
	union power_supply_propval value;
	struct power_supply *psy = power_supply_get_by_name("battery");
	struct power_supply *psy_ps = power_supply_get_by_name("ps");
	static enum cable_type_t previous_cable_type = CABLE_TYPE_NONE;
#if defined(CONFIG_USB_NOTIFY_LAYER)
	struct otg_notify *n = get_otg_notify();
#endif
	pr_info("%s, called : cable_type :%d \n",__func__, cable_type);

	set_cable_status = attached ? cable_type : CABLE_TYPE_NONE;

	switch (cable_type) {
	case CABLE_TYPE_USB:
#if defined(USE_TSP_TA_CALLBACKS)
		if (charger_callbacks && charger_callbacks->inform_charger)
			charger_callbacks->inform_charger(charger_callbacks,
			attached);
#endif
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s USB Cable status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s USB Cable Status detached (%d) \n", __func__,status_count);
               }
#endif
#if defined(CONFIG_USB_NOTIFY_LAYER)
		send_otg_notify(n, NOTIFY_EVENT_VBUS, attached);
#else
		sec_otg_set_vbus_state(attached);
#endif
		break;
	case CABLE_TYPE_AC:
#if defined(USE_TSP_TA_CALLBACKS)
		if (charger_callbacks && charger_callbacks->inform_charger)
			charger_callbacks->inform_charger(charger_callbacks,
			attached);
#endif
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s Charger status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s charger status detached (%d) \n", __func__,status_count);
               }
#endif
		break;
	case CABLE_TYPE_UARTOFF:
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s UART Status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s UART status detached (%d) \n", __func__,status_count);
               }
#endif
		switch_set_state(&switch_uart3, attached);
		break;
	case CABLE_TYPE_JIG_UART_OFF_VB:
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s UART OFF VBUS Status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s UART OFF VBUS status detached (%d) \n", __func__,status_count);
               }
#endif
		switch_set_state(&switch_uart3, attached);
		break;
	case CABLE_TYPE_JIG:
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s JIG cable status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s JIG cable status detached (%d) \n", __func__,status_count);
               }
#endif
		return;
	case CABLE_TYPE_CDP:
#if defined(USE_TSP_TA_CALLBACKS)
		if (charger_callbacks && charger_callbacks->inform_charger)
			charger_callbacks->inform_charger(charger_callbacks,
			attached);
#endif
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s CDP status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s CDP Status detached (%d) \n", __func__,status_count);
               }
#endif
#if defined(CONFIG_USB_NOTIFY_LAYER)
		send_otg_notify(n, NOTIFY_EVENT_VBUS, attached);
#else
		sec_otg_set_vbus_state(attached);
#endif
		break;
	case CABLE_TYPE_OTG:
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s OTG status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s OTG status detached (%d) \n", __func__,status_count);
               }
#endif
#if defined(CONFIG_USB_HOST_NOTIFY)
		if (attached) {
			send_otg_notify(n, NOTIFY_EVENT_DRIVE_VBUS, 1);
			send_otg_notify(n, NOTIFY_EVENT_HOST, 1);
		} else {
			send_otg_notify(n, NOTIFY_EVENT_HOST, 0);
			send_otg_notify(n, NOTIFY_EVENT_DRIVE_VBUS, 0);
		}
#endif
	       return;
	case CABLE_TYPE_AUDIO_DOCK:
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s Audiodock status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s Audiodock status detached (%d) \n", __func__,status_count);
               }
#endif
#if defined(CONFIG_USB_HOST_NOTIFY)
		if (attached) {
			send_otg_notify(n, NOTIFY_EVENT_AUDIODOCK, 1);
		} else {
			send_otg_notify(n, NOTIFY_EVENT_AUDIODOCK, 0);
		}
#endif
		switch_set_state(&switch_dock, attached);
		break;
	case CABLE_TYPE_CARDOCK:
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s Cardock status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s Cardock status detached (%d) \n", __func__,status_count);
               }
#endif
		switch_set_state(&switch_dock, attached ? 2 : 0);
		switch_set_state(&switch_uart3, attached);
		break;
	case CABLE_TYPE_UARTON:
#if defined(DEBUG_STATUS)
		if (attached) {
			status_count = status_count+1;
			pr_err("%s Uart On status attached (%d)\n", __func__, status_count);
		} else {
			status_count = status_count-1;
			pr_err("%s Uart On status detached (%d)\n", __func__, status_count);
		}
#endif
		switch_set_state(&switch_uart3, attached);
		break;
	case CABLE_TYPE_DESK_DOCK:
	case CABLE_TYPE_DESK_DOCK_NO_VB:
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s Deskdock %s status attached (%d) \n",__func__,
				((cable_type == CABLE_TYPE_DESK_DOCK)? "VBUS" : "NOVBUS"),status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s Deskdock %s status detached (%d) \n", __func__,
				((cable_type == CABLE_TYPE_DESK_DOCK)? "VBUS" : "NOVBUS"),status_count);
               }
#endif
		switch_set_state(&switch_dock, attached);
		break;
	case CABLE_TYPE_SMART_DOCK:
	case CABLE_TYPE_SMART_DOCK_NO_VB:
#if defined(DEBUG_STATUS)
		if (attached) {
			status_count = status_count+1;
			pr_err("%s Smartdock %s status attached (%d)\n", __func__,
				((cable_type == CABLE_TYPE_SMART_DOCK) ? "VBUS" : "NOVBUS"), status_count);
		} else {
			status_count = status_count-1;
			pr_err("%s Smartdock %s status detached (%d)\n", __func__,
				((cable_type == CABLE_TYPE_SMART_DOCK) ? "VBUS" : "NOVBUS"), status_count);
		}
#endif
		switch_set_state(&switch_dock, attached ? 5 : 0);
		break;
	case CABLE_TYPE_219KUSB:
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s 219K USB status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s 219K USB status detached (%d) \n", __func__,status_count);
               }
#endif
#if defined(CONFIG_USB_NOTIFY_LAYER)
		send_otg_notify(n, NOTIFY_EVENT_VBUS, attached);
#else
		sec_otg_set_vbus_state(attached);
#endif
		break;
	case CABLE_TYPE_INCOMPATIBLE:
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s Incompatible Charger status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s Incomabtible Charger status detached (%d) \n", __func__,status_count);
               }
#endif
		break;
#if defined(CONFIG_MUIC_SUPPORT_CHARGING_CABLE)
	case CABLE_TYPE_CHARGING_CABLE:
		if (attached)
			value.intval = POWER_SUPPLY_TYPE_POWER_SHARING;
		else
			value.intval = POWER_SUPPLY_TYPE_BATTERY;
#if defined(DEBUG_STATUS)
               if (attached)
               {
                       status_count = status_count+1;
                       pr_err("%s Charging Cable status attached (%d) \n",__func__, status_count);
               } else {
                       status_count = status_count-1;
                       pr_err("%s Charging Cable status detached (%d) \n", __func__,status_count);
               }
#endif
		break;
#endif
	default:
		break;
	}

	if (previous_cable_type == set_cable_status) {
		pr_info("%s: SKIP cable setting\n", __func__);
		return;
	}

#if defined(CONFIG_FUELGAUGE_MAX17050)
	if(check_sm5504_jig_state())
	{
		struct power_supply *fuel_psy = power_supply_get_by_name("sec-fuelgauge");
		if (!fuel_psy || !fuel_psy->set_property)
			pr_err("%s: fail to get sec-fuelgauge psy\n", __func__);
		else {
			fuel_psy->set_property(fuel_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &value);
		}
	}
#endif
#if defined(CONFIG_QPNP_BMS)
	if(check_sm5504_jig_state())
	{
	  struct power_supply *fuel_psy = power_supply_get_by_name("bms");
	  if (!fuel_psy || !fuel_psy->set_property)
		pr_err("%s: fail to get BMS psy\n", __func__);
		else {
			fuel_psy->set_property(fuel_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &value);
		}
	}
#endif
#if defined(CONFIG_FUELGAUGE_RT5033)
	if (check_sm5504_jig_state()) {
		struct power_supply *fuel_psy = power_supply_get_by_name("rt5033-fuelgauge");
		if (!fuel_psy || !fuel_psy->set_property)
			pr_err("%s: fail to get rt5033-fuelgauge psy\n", __func__);
		else
			fuel_psy->set_property(fuel_psy, POWER_SUPPLY_PROP_CHARGE_TYPE, &value);
	}
#endif

	switch (set_cable_status) {
	case CABLE_TYPE_MISC:
		value.intval = POWER_SUPPLY_TYPE_MISC;
		break;
	case CABLE_TYPE_USB:
		value.intval = POWER_SUPPLY_TYPE_USB;
		break;
	case CABLE_TYPE_219KUSB:
	case CABLE_TYPE_AC:
	case CABLE_TYPE_AUDIO_DOCK:
	case CABLE_TYPE_UNDEFINED:
		value.intval = POWER_SUPPLY_TYPE_MAINS;
		break;
	case CABLE_TYPE_CARDOCK:
		value.intval = POWER_SUPPLY_TYPE_CARDOCK;
		break;
	case CABLE_TYPE_CDP:
		value.intval = POWER_SUPPLY_TYPE_USB_CDP;
		break;
	case CABLE_TYPE_INCOMPATIBLE:
		value.intval = POWER_SUPPLY_TYPE_UNKNOWN;
		break;
	case CABLE_TYPE_DESK_DOCK:
	case CABLE_TYPE_SMART_DOCK:
		value.intval = POWER_SUPPLY_TYPE_MAINS;
		break;
	case CABLE_TYPE_JIG_UART_OFF_VB:
		value.intval = POWER_SUPPLY_TYPE_UARTOFF;
		break;
	case CABLE_TYPE_DESK_DOCK_NO_VB:
	case CABLE_TYPE_SMART_DOCK_NO_VB:
	case CABLE_TYPE_UARTOFF:
	case CABLE_TYPE_UARTON:
	case CABLE_TYPE_NONE:
		value.intval = POWER_SUPPLY_TYPE_BATTERY;
		break;
	case CABLE_TYPE_CHARGING_CABLE:
		value.intval = POWER_SUPPLY_TYPE_POWER_SHARING;
		break;
	default:
		pr_err("%s: invalid cable :%d\n", __func__, set_cable_status);
		return;
	}
	current_cable_type = value.intval;
	pr_info("%s:MUIC setting the cable type as (%d)\n",__func__,value.intval);

	if (!psy || !psy->set_property || !psy_ps->set_property)
		pr_err("%s: fail to get battery ps/psy\n", __func__);
	else {
		if (current_cable_type == POWER_SUPPLY_TYPE_POWER_SHARING) {
			value.intval = current_cable_type;
			psy_ps->set_property(psy_ps, POWER_SUPPLY_PROP_ONLINE, &value);
		} else {
			if (previous_cable_type == CABLE_TYPE_CHARGING_CABLE) {
				value.intval = current_cable_type;
				psy_ps->set_property(psy_ps, POWER_SUPPLY_PROP_ONLINE, &value);
			} else {
				value.intval = current_cable_type;
				psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
			}
		}
	}
	previous_cable_type = set_cable_status;
}
void sm5504_lanhub_callback(enum cable_type_t cable_type, int attached, bool lanhub_ta)
{
	union power_supply_propval value;
	struct power_supply *psy;
	int i, ret = 0;
#if defined(CONFIG_USB_NOTIFY_LAYER)
	struct otg_notify *n = get_otg_notify();
#endif

	pr_info("SM5504 Lanhub Callback called, cable %d, attached %d, TA: %s \n",
				cable_type,attached,(lanhub_ta ? "Yes":"No"));
	if(lanhub_ta)
		set_cable_status = attached ? CABLE_TYPE_LANHUB : POWER_SUPPLY_TYPE_OTG;
	else
		set_cable_status = attached ? CABLE_TYPE_LANHUB : CABLE_TYPE_NONE;

	pr_info("%s:sm5504 cable type : %d", __func__, set_cable_status);

	for (i = 0; i < 10; i++) {
		psy = power_supply_get_by_name("battery");
		if (psy)
			break;
	}

	if (i == 10) {
		pr_err("%s: fail to get battery ps\n", __func__);
		return;
	}

	if (!psy || !psy->set_property)
                pr_err("%s: fail to set battery psy\n", __func__);
        else {
		switch (set_cable_status) {
		case CABLE_TYPE_LANHUB:
			value.intval = POWER_SUPPLY_TYPE_LAN_HUB;
			break;
	        case POWER_SUPPLY_TYPE_OTG:
	        case CABLE_TYPE_NONE:
			value.intval = lanhub_ta ? POWER_SUPPLY_TYPE_OTG : POWER_SUPPLY_TYPE_BATTERY;
			break;
		default:
	                pr_err("%s invalid status:%d\n", __func__,attached);
	                return;
		}

	        ret = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &value);
		if (ret) {
			pr_err("%s: fail to set power_suppy ONLINE property(%d)\n",
				__func__, ret);
	        }

	}

#ifdef CONFIG_USB_HOST_NOTIFY
	if (attached){
		if(lanhub_ta) {
			pr_info("USB Host HNOTIFY LANHUB_N_TA_ON\n");
		}
		else{
			pr_info("USB Host HNOTIFY_LANHUB_ON\n");
			/*sec_otg_notify(HNOTIFY_LANHUB_ON);*/
		}
	}else{
		if(lanhub_ta) {
                        pr_info("USB Host HNOTIFY LANHUB ON\n");
                }
                else{
			pr_info("USB Host HNOTIFY_LANHUB_OFF");
			/* sec_otg_notify(HNOTIFY_LANHUB_OFF);*/
		}
	}
#endif

}
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;
}
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));
}
static int usb_handle_notification(struct notifier_block *nb,
		unsigned long action, void *data)
{
	muic_attached_dev_t attached_dev = *(muic_attached_dev_t *)data;
	struct otg_notify *o_notify;

	o_notify = get_otg_notify();

	pr_info("%s action=%lu, attached_dev=%d\n",
		__func__, action, attached_dev);

	switch (attached_dev) {
	case ATTACHED_DEV_USB_MUIC:
	case ATTACHED_DEV_CDP_MUIC:
	case ATTACHED_DEV_UNOFFICIAL_ID_USB_MUIC:
	case ATTACHED_DEV_UNOFFICIAL_ID_CDP_MUIC:
	case ATTACHED_DEV_JIG_USB_OFF_MUIC:
	case ATTACHED_DEV_JIG_USB_ON_MUIC:
		if (action == MUIC_NOTIFY_CMD_DETACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_VBUS, 0);
		else if (action == MUIC_NOTIFY_CMD_ATTACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_VBUS, 1);
		else
			pr_err("%s - ACTION Error!\n", __func__);
		break;
	case ATTACHED_DEV_OTG_MUIC:
		if (action == MUIC_NOTIFY_CMD_DETACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_HOST, 0);
		else if (action == MUIC_NOTIFY_CMD_ATTACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_HOST, 1);
		else
			pr_err("%s - ACTION Error!\n", __func__);
		break;
	case ATTACHED_DEV_HMT_MUIC:
		if (action == MUIC_NOTIFY_CMD_DETACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_HMT, 0);
		else if (action == MUIC_NOTIFY_CMD_ATTACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_HMT, 1);
		else
			pr_err("%s - ACTION Error!\n", __func__);
		break;
	case ATTACHED_DEV_JIG_UART_OFF_VB_OTG_MUIC:
		if (action == MUIC_NOTIFY_CMD_DETACH)
			pr_info("%s - USB_HOST_TEST_DETACHED\n", __func__);
		else if (action == MUIC_NOTIFY_CMD_ATTACH)
			pr_info("%s - USB_HOST_TEST_ATTACHED\n", __func__);
		else
			pr_err("%s - ACTION Error!\n", __func__);
		break;
	case ATTACHED_DEV_SMARTDOCK_TA_MUIC:
		if (action == MUIC_NOTIFY_CMD_DETACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_SMARTDOCK_TA, 0);
		else if (action == MUIC_NOTIFY_CMD_ATTACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_SMARTDOCK_TA, 1);
		else
			pr_err("%s - ACTION Error!\n", __func__);
		break;
	case ATTACHED_DEV_SMARTDOCK_USB_MUIC:
		if (action == MUIC_NOTIFY_CMD_DETACH)
			send_otg_notify
				(o_notify, NOTIFY_EVENT_SMARTDOCK_USB, 0);
		else if (action == MUIC_NOTIFY_CMD_ATTACH)
			send_otg_notify
				(o_notify, NOTIFY_EVENT_SMARTDOCK_USB, 1);
		else
			pr_err("%s - ACTION Error!\n", __func__);
		break;
	case ATTACHED_DEV_AUDIODOCK_MUIC:
		if (action == MUIC_NOTIFY_CMD_DETACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_AUDIODOCK, 0);
		else if (action == MUIC_NOTIFY_CMD_ATTACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_AUDIODOCK, 1);
		else
			pr_err("%s - ACTION Error!\n", __func__);
		break;
	case ATTACHED_DEV_UNIVERSAL_MMDOCK_MUIC:
		if (action == MUIC_NOTIFY_CMD_DETACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_MMDOCK, 0);
		else if (action == MUIC_NOTIFY_CMD_ATTACH)
			send_otg_notify(o_notify, NOTIFY_EVENT_MMDOCK, 1);
		else
			pr_err("%s - ACTION Error!\n", __func__);
		break;
	default:
		break;
	}

	return 0;
}