static int sleep_until_event(struct dwc_otg2 *otg, u32 otg_mask, u32 user_mask, u32 *otg_events, u32 *user_events, int timeout) { int rc = 0; pm_runtime_mark_last_busy(otg->dev); pm_runtime_put_autosuspend(otg->dev); /* Wait until it occurs, or timeout, or interrupt. */ if (timeout) { otg_dbg(otg, "Waiting for event (timeout=%d)...\n", timeout); rc = sleep_main_thread_until_condition_timeout(otg, check_event(otg, otg_mask, user_mask, otg_events, user_events), timeout); } else { otg_dbg(otg, "Waiting for event (no timeout)...\n"); rc = sleep_main_thread_until_condition(otg, check_event(otg, otg_mask, user_mask, otg_events, user_events)); } pm_runtime_get_sync(otg->dev); /* Disable the events */ otg_write(otg, OEVTEN, 0); otg_write(otg, ADPEVTEN, 0); otg_dbg(otg, "Woke up rc=%d\n", rc); return rc; }
static ssize_t store_vbus_evt(struct device *_dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long flags; struct dwc_otg2 *otg = dwc3_get_otg(); if (count != 2) { otg_err(otg, "return EINVAL\n"); return -EINVAL; } if (count > 0 && buf[count-1] == '\n') ((char *) buf)[count-1] = 0; switch (buf[0]) { case '1': otg_dbg(otg, "Change the VBUS to High\n"); otg->otg_events |= OEVT_B_DEV_SES_VLD_DET_EVNT; spin_lock_irqsave(&otg->lock, flags); dwc3_wakeup_otg_thread(otg); spin_unlock_irqrestore(&otg->lock, flags); return count; case '0': otg_dbg(otg, "Change the VBUS to Low\n"); otg->otg_events |= OEVT_A_DEV_SESS_END_DET_EVNT; spin_lock_irqsave(&otg->lock, flags); dwc3_wakeup_otg_thread(otg); spin_unlock_irqrestore(&otg->lock, flags); return count; default: return -EINVAL; } return count; }
static int check_event(struct dwc_otg2 *otg, u32 otg_mask, u32 user_mask, u32 *otg_events, u32 *user_events) { get_and_clear_events(otg, otg_mask, user_mask, otg_events, user_events); otg_dbg(otg, "Event occurred:"); if (otg_events && (*otg_events & otg_mask)) { otg_dbg(otg, "otg_events=0x%x, otg_mask=0x%x", *otg_events, otg_mask); return 1; } if (user_events && (*user_events & user_mask)) { otg_dbg(otg, "user_events=0x%x, user_mask=0x%x", *user_events, user_mask); return 1; } return 0; }
static int do_b_peripheral(struct dwc_otg2 *otg) { int rc = 0; u32 otg_mask, user_mask, otg_events, user_events; otg_mask = 0; user_mask = 0; otg_events = 0; user_events = 0; otg_mask = OEVT_A_DEV_SESS_END_DET_EVNT; user_mask = USER_ID_A_CHANGE_EVENT; rc = sleep_until_event(otg, otg_mask, user_mask, &otg_events, &user_events, 0); if (rc < 0) return DWC_STATE_EXIT; if (otg_events & OEVT_A_DEV_SESS_END_DET_EVNT) { otg_dbg(otg, "OEVT_A_DEV_SESS_END_DET_EVNT\n"); dwc_otg_notify_charger_type(otg, POWER_SUPPLY_CHARGER_EVENT_DISCONNECT); return DWC_STATE_B_IDLE; } if (user_events & USER_ID_A_CHANGE_EVENT) { otg_dbg(otg, "USER_ID_A_CHANGE_EVENT\n"); otg->user_events |= USER_ID_A_CHANGE_EVENT; return DWC_STATE_B_IDLE; } return DWC_STATE_INVALID; }
static int dwc_otg_charger_hwdet(bool enable) { int retval; struct usb_phy *phy; struct dwc_otg2 *otg = dwc3_get_otg(); /* Just return if charger detection is not enabled */ if (!charger_detect_enable(otg)) return 0; phy = usb_get_phy(USB_PHY_TYPE_USB2); if (!phy) return -ENODEV; if (enable) { retval = usb_phy_io_write(phy, PWCTRL_HWDETECT, TUSB1211_POWER_CONTROL_SET); if (retval) return retval; otg_dbg(otg, "set HWDETECT\n"); } else { retval = usb_phy_io_write(phy, PWCTRL_HWDETECT, TUSB1211_POWER_CONTROL_CLR); if (retval) return retval; otg_dbg(otg, "clear HWDETECT\n"); } usb_put_phy(phy); return 0; }
int dwc3_intel_platform_init(struct dwc_otg2 *otg) { int retval; struct intel_dwc_otg_pdata *data; data = (struct intel_dwc_otg_pdata *)otg->otg_data; /* Init a_bus_drop callback */ otg->usb2_phy.a_bus_drop = dwc_a_bus_drop; otg->usb2_phy.vbus_state = VBUS_ENABLED; /* Get usb2 phy type */ otg->usb2_phy.intf = data->usb2_phy_type; /* Turn off VUSBPHY if it haven't used by USB2 PHY. * Otherwise, it will consume ~2.6mA(on VSYS) on MOFD. */ if (!data->using_vusbphy) { retval = control_usb_phy_power(PMIC_VLDOCNT, false); if (retval) otg_err(otg, "Fail to turn off VUSBPHY\n"); } else if (!is_utmi_phy(otg)) { /* If the current USB2 PHY low power controlled by VUSBPHY. Then * we need to de-assert USBRST pin to make USB2 PHY always stay * in active state. */ retval = control_usb_phy_power(PMIC_USBPHYCTRL, true); if (retval) otg_err(otg, "Fail to de-assert USBRST#\n"); } else { /* If we are using utmi phy, and through VUSBPHY to do power * control. Then we need to assert USBRST# for external ULPI phy * to ask it under inactive state saving power. */ retval = control_usb_phy_power(PMIC_USBPHYCTRL, false); if (retval) otg_err(otg, "Fail to de-assert USBRST#\n"); } /* Don't let phy go to suspend mode, which * will cause FS/LS devices enum failed in host mode. */ set_sus_phy(otg, 0); retval = device_create_file(otg->dev, &dev_attr_otg_id); if (retval < 0) { otg_dbg(otg, "Can't register sysfs attribute: %d\n", retval); return -ENOMEM; } otg_dbg(otg, "\n"); otg_write(otg, OEVTEN, 0); otg_write(otg, OCTL, 0); dwc3_switch_mode(otg, GCTL_PRT_CAP_DIR_OTG); return 0; }
/*Internal function of isr */ static void process_port_intr(struct usb_hcd *hcd) { hprt_t hprt; /* by ss1, clear_hprt; */ struct sec_otghost *otghost = hcd_to_sec_otghost(hcd); hprt.d32 = read_reg_32(HPRT); otg_dbg(OTG_DBG_ISR, "Port Interrupt() : HPRT = 0x%x\n", hprt.d32); if (hprt.b.prtconndet) { otg_dbg(true, "detect connection"); otghost->port_flag.b.port_connect_status_change = 1; if (hprt.b.prtconnsts) otghost->port_flag.b.port_connect_status = 1; /* wake_lock(&otghost->wake_lock); */ } if (hprt.b.prtenchng) { otg_dbg(true, "port enable/disable changed\n"); otghost->port_flag.b.port_enable_change = 1; // kevinh - it seems the hw implicitly disables the interface on unplug, so mark that we are unplugged if(!hprt.b.prtconnsts) { otghost->port_flag.b.port_connect_status_change = 1; otghost->port_flag.b.port_connect_status = 0; } } if (hprt.b.prtovrcurrchng) { otg_dbg(true, "over current condition is changed\n"); if (hprt.b.prtovrcurract) { otg_dbg(true, "port_over_current_change = 1\n"); otghost->port_flag.b.port_over_current_change = 1; } else { otghost->port_flag.b.port_over_current_change = 0; } /* defer otg power control into a kernel thread */ queue_work(otghost->wq, &otghost->work); } hprt.b.prtena = 0; /* prtena를 writeclear시키면 안됨. */ /* hprt.b.prtpwr = 0; */ hprt.b.prtrst = 0; hprt.b.prtconnsts = 0; write_reg_32(HPRT, hprt.d32); }
static enum dwc_otg_state do_charging(struct dwc_otg2 *otg) { int ret; u32 otg_events = 0; u32 user_events = 0; u32 otg_mask = 0; u32 user_mask = 0; otg_mask = OEVT_A_DEV_SESS_END_DET_EVNT; if (dwc3_otg_pdata->do_charging) dwc3_otg_pdata->do_charging(otg); ret = sleep_until_event(otg, otg_mask, user_mask, &otg_events, &user_events, 0); if (ret < 0) return DWC_STATE_EXIT; if (otg_events & OEVT_A_DEV_SESS_END_DET_EVNT) { otg_dbg(otg, "OEVT_A_DEV_SESS_END_DET_EVNT\n"); dwc_otg_notify_charger_type(otg, POWER_SUPPLY_CHARGER_EVENT_DISCONNECT); return DWC_STATE_B_IDLE; } return DWC_STATE_INVALID; }
static int insert_ed_to_ready_q(struct ed *insert_ed, bool is_first) { otg_dbg(OTG_DBG_SCHEDULE_ED, "ed_id %d, td_id %d, %d\n", insert_ed->ed_id, insert_ed->num_td, is_first); if (insert_ed->ed_desc.endpoint_type == BULK_TRANSFER || insert_ed->ed_desc.endpoint_type == CONTROL_TRANSFER) { if (is_first) { otg_list_push_next(&insert_ed->readyq_list, &nonperiodic_trans_ready_q.entity_list); } else { otg_list_push_prev(&insert_ed->readyq_list, &nonperiodic_trans_ready_q.entity_list); } nonperiodic_trans_ready_q.entity_num++; } else { if (is_first) { otg_list_push_next(&insert_ed->readyq_list, &periodic_trans_ready_q.entity_list); } else { otg_list_push_prev(&insert_ed->readyq_list, &periodic_trans_ready_q.entity_list); } periodic_trans_ready_q.entity_num++; } return USB_ERR_SUCCESS; }
static void start_main_thread(struct dwc_otg2 *otg) { enum dwc3_otg_mode mode = dwc3_otg_pdata->mode; bool children_ready = false; mutex_lock(&lock); if ((mode == DWC3_DEVICE_ONLY) && otg->otg.gadget) children_ready = true; if ((mode == DWC3_HOST_ONLY) && otg->otg.host) children_ready = true; if ((mode == DWC3_DRD) && otg->otg.host && otg->otg.gadget) children_ready = true; if (!otg->main_thread && children_ready) { otg_dbg(otg, "Starting OTG main thread\n"); otg->main_thread = kthread_create(otg_main_thread, otg, "otg"); wake_up_process(otg->main_thread); } mutex_unlock(&lock); }
/** * int reset_and_enable_port(const u8 port) * * @brief Reset port and make enable status the specific port * * @param [IN] port : port number * * @return USB_ERR_SUCCESS : If success \n * USB_ERR_FAIL : If call fail \n * * @remark * */ int reset_and_enable_port(const u8 port) { hprt_t hprt; u32 count = 0; u32 max_error_count = 1000; mdelay(50); hprt.d32 = read_reg_32(HPRT); if(!hprt.b.prtena) { hprt.b.prtrst = 1; // drive reset write_reg_32(HPRT, hprt.d32); mdelay(80); hprt.b.prtrst = 0; write_reg_32(HPRT, hprt.d32); mdelay(60); do { hprt.d32 = read_reg_32(HPRT); udelay(10); if(count > max_error_count) { otg_dbg(OTG_DBG_ROOTHUB,"Port Reset Fail : HPRT : 0x%x\n",(u16)read_reg_32(HPRT)); return USB_ERR_FAIL; } count++; }while(!hprt.b.prtena); } return USB_ERR_SUCCESS; }
static enum dwc_otg_state do_wait_vbus_fall(struct dwc_otg2 *otg) { int ret; u32 otg_events = 0; u32 user_events = 0; u32 otg_mask = 0; u32 user_mask = 0; otg_mask = OEVT_A_DEV_SESS_END_DET_EVNT; ret = sleep_until_event(otg, otg_mask, user_mask, &otg_events, &user_events, VBUS_TIMEOUT); if (ret < 0) return DWC_STATE_EXIT; if (otg_events & OEVT_A_DEV_SESS_END_DET_EVNT) { otg_dbg(otg, "OEVT_A_DEV_SESS_END_DET_EVNT\n"); if (otg->charging_cap.chrg_type == POWER_SUPPLY_CHARGER_TYPE_ACA_DOCK) dwc_otg_notify_charger_type(otg, POWER_SUPPLY_CHARGER_EVENT_DISCONNECT); return DWC_STATE_B_IDLE; } /* timeout*/ if (!ret) { otg_err(otg, "Haven't get VBus drop event! Maybe something wrong\n"); return DWC_STATE_B_IDLE; } return DWC_STATE_INVALID; }
static int dwc3_intel_byt_handle_notification(struct notifier_block *nb, unsigned long event, void *data) { struct dwc_otg2 *otg = dwc3_get_otg(); int state, val; unsigned long flags; if (!otg) return NOTIFY_BAD; val = *(int *)data; spin_lock_irqsave(&otg->lock, flags); switch (event) { case USB_EVENT_VBUS: if (val) { otg->otg_events |= OEVT_B_DEV_SES_VLD_DET_EVNT; otg->otg_events &= ~OEVT_A_DEV_SESS_END_DET_EVNT; } else { otg->otg_events |= OEVT_A_DEV_SESS_END_DET_EVNT; otg->otg_events &= ~OEVT_B_DEV_SES_VLD_DET_EVNT; } state = NOTIFY_OK; break; default: otg_dbg(otg, "DWC OTG Notify unknow notify message\n"); state = NOTIFY_DONE; } dwc3_wakeup_otg_thread(otg); spin_unlock_irqrestore(&otg->lock, flags); return state; }
static enum dwc_otg_state do_wait_vbus_raise(struct dwc_otg2 *otg) { int ret; u32 otg_events = 0; u32 user_events = 0; u32 otg_mask = 0; u32 user_mask = 0; otg_mask = OEVT_B_DEV_SES_VLD_DET_EVNT; ret = sleep_until_event(otg, otg_mask, user_mask, &otg_events, &user_events, VBUS_TIMEOUT); if (ret < 0) return DWC_STATE_EXIT; if (otg_events & OEVT_B_DEV_SES_VLD_DET_EVNT) { otg_dbg(otg, "OEVT_B_SES_VLD_EVT\n"); return DWC_STATE_CHARGER_DETECTION; } /* timeout*/ if (!ret) return DWC_STATE_A_HOST; return DWC_STATE_B_IDLE; }
static int dwc3_check_gpio_id(struct dwc_otg2 *otg2) { struct dwc_otg2 *otg = dwc3_get_otg(); struct intel_dwc_otg_pdata *data; int id = 0; int next = 0; int count = 0; unsigned long timeout; otg_dbg(otg, "start check gpio id\n"); data = (struct intel_dwc_otg_pdata *)otg->otg_data; /* Polling ID GPIO PIN value for SW debounce as HW debouce chip * is not connected on BYT CR board */ if (data && data->gpio_id) { id = gpio_get_value(data->gpio_id); /* If get 20 of the same value in a row by GPIO read, * then end SW debouce and return the ID value. * the total length of debouce time is 80ms~100ms for * 20 times GPIO read on BYT CR, which is longer than * normal debounce time done by HW chip. * Also set 200ms timeout value to avoid impact from * pin unstable cases */ timeout = jiffies + msecs_to_jiffies(200); while ((count < 20) && (!time_after(jiffies, timeout))) { next = gpio_get_value(data->gpio_id); otg_dbg(otg, "id value pin %d = %d\n", data->gpio_id, next); if (next < 0) return -EINVAL; else if (id == next) count++; else { id = next; count = 0; } } if (count >= 20) { otg_dbg(otg, "id debounce done = %d\n", id); return id; } } return -ENODEV; }
/* Caller must hold otg->lock */ void dwc3_wakeup_otg_thread(struct dwc_otg2 *otg) { if (!otg->main_thread) return; otg_dbg(otg, "\n"); /* Tell the main thread that something has happened */ otg->main_wakeup_needed = 1; wake_up_interruptible(&otg->main_wq); }
static void stop_main_thread(struct dwc_otg2 *otg) { mutex_lock(&lock); if (otg->main_thread) { otg_dbg(otg, "Stopping OTG main thread\n"); otg->state = DWC_STATE_EXIT; dwc3_wakeup_otg_thread(otg); } mutex_unlock(&lock); }
static ssize_t store_otg_id(struct device *_dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long flags; struct dwc_otg2 *otg = dwc3_get_otg(); if (!otg) return 0; if (count != 2) { otg_err(otg, "return EINVAL\n"); return -EINVAL; } if (count > 0 && buf[count-1] == '\n') ((char *) buf)[count-1] = 0; switch (buf[0]) { case 'a': case 'A': otg_dbg(otg, "Change ID to A\n"); otg->user_events |= USER_ID_A_CHANGE_EVENT; spin_lock_irqsave(&otg->lock, flags); dwc3_wakeup_otg_thread(otg); otg_id = 0; spin_unlock_irqrestore(&otg->lock, flags); return count; case 'b': case 'B': otg_dbg(otg, "Change ID to B\n"); otg->user_events |= USER_ID_B_CHANGE_EVENT; spin_lock_irqsave(&otg->lock, flags); dwc3_wakeup_otg_thread(otg); otg_id = 1; spin_unlock_irqrestore(&otg->lock, flags); return count; default: otg_err(otg, "Just support change ID to A!\n"); return -EINVAL; } return count; }
/** * int get_otg_port_status(const u8 port, char* status) * * @brief Get port change bitmap information * * @param [IN] port : port number * [OUT] status : buffer to store bitmap information * * @returnUSB_ERR_SUCCESS : If success \n * USB_ERR_FAIL : If call fail \n * * @remark * */ __inline__ int get_otg_port_status(const u8 port, char *status) { //return root_hub_feature(port, GetPortStatus, NULL, status); status[port] = 0; status[port] |= (port_flag.b.port_connect_status_change || port_flag.b.port_reset_change || port_flag.b.port_enable_change || port_flag.b.port_suspend_change || port_flag.b.port_over_current_change) << 1; if (status[port]) { otg_dbg(OTG_DBG_ROOTHUB, " Root port status changed\n"); otg_dbg(OTG_DBG_ROOTHUB, " port_connect_status_change: %d\n", port_flag.b.port_connect_status_change); otg_dbg(OTG_DBG_ROOTHUB, " port_reset_change: %d\n", port_flag.b.port_reset_change); otg_dbg(OTG_DBG_ROOTHUB, " port_enable_change: %d\n", port_flag.b.port_enable_change); otg_dbg(OTG_DBG_ROOTHUB, " port_suspend_change: %d\n", port_flag.b.port_suspend_change); otg_dbg(OTG_DBG_ROOTHUB, " port_over_current_change: %d\n", port_flag.b.port_over_current_change); } return (status[port] !=0); }
static int sleep_main_thread_timeout(struct dwc_otg2 *otg, int msecs) { signed long jiffies; int rc = msecs; if (otg->state == DWC_STATE_EXIT) { otg_dbg(otg, "Main thread exiting\n"); rc = -EINTR; goto done; } if (signal_pending(current)) { otg_dbg(otg, "Main thread signal pending\n"); rc = -EINTR; goto done; } if (otg->main_wakeup_needed) { otg_dbg(otg, "Main thread wakeup needed\n"); rc = msecs; goto done; } jiffies = msecs_to_jiffies(msecs); rc = wait_event_freezable_timeout(otg->main_wq, otg->main_wakeup_needed, jiffies); if (otg->state == DWC_STATE_EXIT) { otg_dbg(otg, "Main thread exiting\n"); rc = -EINTR; goto done; } if (rc > 0) rc = jiffies_to_msecs(rc); done: otg->main_wakeup_needed = 0; return rc; }
int dwc3_intel_byt_after_stop_peripheral(struct dwc_otg2 *otg) { struct intel_dwc_otg_pdata *data; data = (struct intel_dwc_otg_pdata *)otg->otg_data; if (!data) return -EINVAL; otg_dbg(otg, "cancel discon work\n"); __cancel_delayed_work(&data->suspend_discon_work); return 0; }
static int dwc_otg2_set_host(struct usb_otg *x, struct usb_bus *host) { struct dwc_otg2 *otg; if (!x) { otg_dbg(otg, "otg is NULL!\n"); return -ENODEV; } otg = xceiv_to_dwc_otg2(x); otg_dbg(otg, "\n"); if (!host) { otg->otg.host = NULL; stop_main_thread(otg); return -ENODEV; } otg->otg.host = host; start_main_thread(otg); return 0; }
static void dwc_otg_suspend_discon_work(struct work_struct *work) { struct dwc_otg2 *otg = dwc3_get_otg(); unsigned long flags; otg_dbg(otg, "start suspend_disconn work\n"); spin_lock_irqsave(&otg->lock, flags); otg->otg_events |= OEVT_A_DEV_SESS_END_DET_EVNT; otg->otg_events &= ~OEVT_B_DEV_SES_VLD_DET_EVNT; dwc3_wakeup_otg_thread(otg); spin_unlock_irqrestore(&otg->lock, flags); }
/** * static int __init s3c6410_otg_module_init(void) * * @brief module_init function * * @return it returns result of platform_driver_register * @remark * This function is called when the s3c6410_otg_driver is installed with the * insmod command. It registers the s3c6410_otg_driver structure with the * appropriate bus driver. This will cause the s3c6410_otg_driver_probe function * to be called. In addition, the bus driver will automatically expose * attributes defined for the device and driver in the special sysfs file * system. */ static int __init s3c6410_otg_module_init(void) { int ret_val = 0; otg_dbg(OTG_DBG_OTGHCDI_DRIVER, "s3c_otg_module_init \n"); ret_val = platform_driver_register(&s3c6410_otg_driver); if (ret_val < 0) { otg_err(OTG_DBG_OTGHCDI_DRIVER, "platform_driver_register \n"); } return ret_val; }
static void oci_set_global_interrupt(bool set) { gahbcfg_t ahbcfg; otg_dbg(OTG_DBG_OCI, "oci_set_global_interrupt\n"); ahbcfg.d32 = 0; ahbcfg.b.glblintrmsk = 1; if (set) update_reg_32(GAHBCFG, ahbcfg.d32); else clear_reg_32(GAHBCFG, ahbcfg.d32); }
/** * int bus_resume(void) * * @brief Make resume status when this platform support PM Mode * * @param None * * @return USB_ERR_SUCCESS : If success \n * USB_ERR_FAIL : If call fail \n * * @remark * */ int bus_resume(void) { /* hprt_t hprt; pcgcctl_t pcgcctl; hprt.d32 = 0; pcgcctl.d32 = 0; pcgcctl.b.stoppclk = 1; clear_reg_32(PCGCCTL,pcgcctl.d32); udelay(1); pcgcctl.b.pwrclmp = 1; clear_reg_32(PCGCCTL,pcgcctl.d32); udelay(1); pcgcctl.b.rstpdwnmodule = 1; clear_reg_32(PCGCCTL,pcgcctl.d32); udelay(1); hprt.b.prtres = 1; update_reg_32(HPRT, hprt.d32); mdelay(20); clear_reg_32(HPRT, hprt.d32); */ otg_dbg(OTG_DBG_OTGHCDI_HCD, "bus_resume()...... \n"); if(oci_init() == USB_ERR_SUCCESS) { if(oci_start() == USB_ERR_SUCCESS) { otg_dbg(OTG_DBG_OTGHCDI_HCD, "OTG Init Success...... \n"); return USB_ERR_SUCCESS; } } return USB_ERR_FAIL; }
static void init_transfer_ready_q(void) { otg_dbg(OTG_DBG_SCHEDULE, "start init_transfer_ready_q\n"); otg_list_init(&periodic_trans_ready_q.entity_list); periodic_trans_ready_q.is_periodic = true; periodic_trans_ready_q.entity_num = 0; periodic_trans_ready_q.total_alloc_chnum = 0; periodic_trans_ready_q.total_perio_bus_bandwidth = 0; otg_list_init(&nonperiodic_trans_ready_q.entity_list); nonperiodic_trans_ready_q.is_periodic = false; nonperiodic_trans_ready_q.entity_num = 0; nonperiodic_trans_ready_q.total_alloc_chnum = 0; nonperiodic_trans_ready_q.total_perio_bus_bandwidth = 0; }
static int stop_host(struct dwc_otg2 *otg) { int ret = -1; struct usb_hcd *hcd = NULL; otg_dbg(otg, "\n"); hcd = container_of(otg->otg.host, struct usb_hcd, self); if (otg->otg.host) ret = otg->stop_host(hcd); if (dwc3_otg_pdata->after_stop_host) ret = dwc3_otg_pdata->after_stop_host(otg); return ret; }
static int remove_ed_from_ready_q(struct ed *remove_ed) { otg_dbg(OTG_DBG_SCHEDULE_ED, "ed_id %d, td_id %d\n", remove_ed->ed_id, remove_ed->num_td); otg_list_pop(&remove_ed->readyq_list); if (remove_ed->ed_desc.endpoint_type == BULK_TRANSFER || remove_ed->ed_desc.endpoint_type == CONTROL_TRANSFER) { nonperiodic_trans_ready_q.entity_num--; } else periodic_trans_ready_q.entity_num--; return USB_ERR_SUCCESS; }
static int s5pc110_stop_otg(void) { struct sec_otghost *otghost = NULL; struct sec_otghost_data *otgdata = NULL; pr_info("+++++ OTG STOP\n"); otg_dbg(OTG_DBG_OTGHCDI_DRIVER, "s5pc110_stop_otg\n"); otghost = hcd_to_sec_otghost(g_pUsbHcd); #ifdef CONFIG_USB_HOST_NOTIFY host_notify_dev_unregister(&g_pUsbHcd->ndev); #endif otg_hcd_deinit_modules(otghost); destroy_workqueue(otghost->wq); wake_unlock(&otghost->wake_lock); wake_lock_destroy(&otghost->wake_lock); usb_remove_hcd(g_pUsbHcd); #if 1 if (g_pUDCBase == S3C_VA_HSOTG) { pr_info("otg release_mem_region\n"); release_mem_region(g_pUsbHcd->rsrc_start, g_pUsbHcd->rsrc_len); } #endif usb_put_hcd(g_pUsbHcd); otgdata = otghost->otg_data; if (otgdata && otgdata->phy_exit && otgdata->pdev) { pr_info("otg phy_off\n"); otgdata->phy_exit(0); } return 0; }