static void tegra_change_otg_state(struct tegra_otg_data *tegra, enum usb_otg_state to) { struct otg_transceiver *otg = &tegra->otg; enum usb_otg_state from = otg->state; if(!tegra->interrupt_mode){ DBG("OTG: Vbus detection is disabled"); return; } DBG("%s(%d) requested otg state %s-->%s\n", __func__, __LINE__, tegra_state_name(from), tegra_state_name(to)); if (to != OTG_STATE_UNDEFINED && from != to) { otg->state = to; /*dev_info(tegra->otg.dev, "%s --> %s\n", tegra_state_name(from), tegra_state_name(to));*/ USBH_INFO("%s --> %s\n", tegra_state_name(from), tegra_state_name(to)); if (from == OTG_STATE_A_SUSPEND) { if (to == OTG_STATE_B_PERIPHERAL && otg->gadget) { usb_gadget_vbus_connect(otg->gadget); #ifdef CONFIG_USB_ANDROID_PROJECTOR if (check_htc_mode_status() != NOT_ON_AUTOBOT) { htc_mode_enable(0); android_switch_default(); } #endif } else if (to == OTG_STATE_A_HOST) { tegra_start_host(tegra); dump_otg_state(); } } else if (from == OTG_STATE_A_HOST) { if (to == OTG_STATE_A_SUSPEND) tegra_stop_host(tegra); } else if (from == OTG_STATE_B_PERIPHERAL && otg->gadget) { if (to == OTG_STATE_A_SUSPEND) usb_gadget_vbus_disconnect(otg->gadget); } } else if (to != OTG_STATE_UNDEFINED && from == to) { USBH_INFO("%s --> %s (%d)\n", tegra_state_name(from), tegra_state_name(to), USB_disabled); if (USB_disabled) { usb_gadget_disconnect(otg->gadget); } else if (to == OTG_STATE_B_PERIPHERAL) { usb_gadget_vbus_connect(otg->gadget); usb_gadget_connect(otg->gadget); } else { usb_gadget_connect(otg->gadget); } } }
/* usb cable call back function */ static void muic_usb_cb(u8 usb_mode) { struct usb_gadget *gadget = platform_get_drvdata(&s3c_device_usbgadget); pr_info("%s:%s MUIC usb_cb:%d\n", MUIC_DEV_NAME, __func__, usb_mode); if (gadget) { switch (usb_mode) { case USB_CABLE_DETACHED: pr_info("usb: muic: USB_CABLE_DETACHED(%d)\n", usb_mode); usb_gadget_vbus_disconnect(gadget); break; case USB_CABLE_ATTACHED: pr_info("usb: muic: USB_CABLE_ATTACHED(%d)\n", usb_mode); usb_gadget_vbus_connect(gadget); break; default: pr_info("usb: muic: invalid mode%d\n", usb_mode); } } }
void usb_composite_force_reset(struct usb_composite_dev *cdev) { unsigned long flags; spin_lock_irqsave(&cdev->lock, flags); /* force reenumeration */ if (cdev && cdev->gadget && cdev->gadget->speed != USB_SPEED_UNKNOWN) { /* * Another USB disconnect event is reported from * controller before "disconnected" switch event is sent out. * This does happen. When force_reset is executed, * two reset interrupt occur - one for get descriptor, * one for bus enumeration. * To avoid unnecessary switch event ignited, * we set the flag "mute_switch" to 2. * This is a "hard" assumption that two * "disconnect" event will be reported */ cdev->mute_switch = 2; /* avoid sending a disconnect switch event until after we disconnect */ spin_unlock_irqrestore(&cdev->lock, flags); usb_gadget_disconnect(cdev->gadget); msleep(10); usb_gadget_connect(cdev->gadget); usb_gadget_vbus_connect(cdev->gadget); } else { spin_unlock_irqrestore(&cdev->lock, flags); } }
/** * dwc3_otg_start_peripheral - bind/unbind the peripheral controller. * * @otg: Pointer to the otg_transceiver structure. * @gadget: pointer to the usb_gadget structure. * * Returns 0 on success otherwise negative errno. */ static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on) { struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv; if (!otg->gadget) return -EINVAL; if (on) { dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n", __func__, otg->gadget->name); usb_phy_notify_connect(dotg->dwc->usb2_phy, USB_SPEED_HIGH); usb_phy_notify_connect(dotg->dwc->usb3_phy, USB_SPEED_SUPER); /* Core reset is not required during start peripheral. Only * DBM reset is required, hence perform only DBM reset here */ if (ext_xceiv && ext_xceiv->ext_block_reset) ext_xceiv->ext_block_reset(ext_xceiv, false); dwc3_set_mode(dotg->dwc, DWC3_GCTL_PRTCAP_DEVICE); usb_gadget_vbus_connect(otg->gadget); } else { dev_dbg(otg->phy->dev, "%s: turn off gadget %s\n", __func__, otg->gadget->name); usb_gadget_vbus_disconnect(otg->gadget); usb_phy_notify_disconnect(dotg->dwc->usb2_phy, USB_SPEED_HIGH); usb_phy_notify_disconnect(dotg->dwc->usb3_phy, USB_SPEED_SUPER); dwc3_gadget_usb3_phy_suspend(dotg->dwc, false); } return 0; }
static int dwc3_otg_start_gadget(struct otg_fsm *fsm, int on) { struct usb_otg *otg = fsm->otg; struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); struct device *dev = dotg->dwc->dev; int ret; if (!otg->gadget) return -EINVAL; dev_err(dev, "Turn %s gadget %s\n", on ? "on" : "off", otg->gadget->name); if (on) { wake_lock(&dotg->wakelock); pm_runtime_get_sync(dev); dwc3_otg_set_peripheral_mode(dotg); ret = usb_gadget_vbus_connect(otg->gadget); } else { /* * Delay VBus OFF signal delivery to not miss Disconnect * interrupt (80ms is minimum; ascertained by experiment) */ msleep(200); ret = usb_gadget_vbus_disconnect(otg->gadget); pm_runtime_put_sync(dev); wake_unlock(&dotg->wakelock); } return ret; }
/** * dwc3_otg_start_peripheral - bind/unbind the peripheral controller. * * @otg: Pointer to the otg_transceiver structure. * @gadget: pointer to the usb_gadget structure. * * Returns 0 on success otherwise negative errno. */ static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on) { struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv; if (!otg->gadget) return -EINVAL; if (on) { dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n", __func__, otg->gadget->name); /* Core reset is not required during start peripheral. Only * DBM reset is required, hence perform only DBM reset here */ if (ext_xceiv && ext_xceiv->otg_capability && ext_xceiv->ext_block_reset) ext_xceiv->ext_block_reset(ext_xceiv, false); dwc3_otg_set_hsphy_auto_suspend(dotg, true); dwc3_otg_set_peripheral_regs(dotg); usb_gadget_vbus_connect(otg->gadget); } else { dev_dbg(otg->phy->dev, "%s: turn off gadget %s\n", __func__, otg->gadget->name); usb_gadget_vbus_disconnect(otg->gadget); dwc3_otg_set_hsphy_auto_suspend(dotg, false); } return 0; }
static void tegra_change_otg_state(struct tegra_otg_data *tegra, enum usb_otg_state to) { struct otg_transceiver *otg = &tegra->otg; enum usb_otg_state from = otg->state; if(!tegra->interrupt_mode){ DBG("OTG: Vbus detection is disabled"); return; } DBG("%s(%d) requested otg state %s-->%s\n", __func__, __LINE__, tegra_state_name(from), tegra_state_name(to)); if (to != OTG_STATE_UNDEFINED && from != to) { otg->state = to; dev_info(tegra->otg.dev, "%s --> %s\n", tegra_state_name(from), tegra_state_name(to)); if (from == OTG_STATE_A_SUSPEND) { if (to == OTG_STATE_B_PERIPHERAL && otg->gadget) usb_gadget_vbus_connect(otg->gadget); else if (to == OTG_STATE_A_HOST) tegra_start_host(tegra); } else if (from == OTG_STATE_A_HOST) { if (to == OTG_STATE_A_SUSPEND) tegra_stop_host(tegra); } else if (from == OTG_STATE_B_PERIPHERAL && otg->gadget) { if (to == OTG_STATE_A_SUSPEND) usb_gadget_vbus_disconnect(otg->gadget); } } }
static irqreturn_t nop_gpio_vbus_thread(int irq, void *data) { struct usb_phy_generic *nop = data; struct usb_otg *otg = nop->phy.otg; int vbus, status; vbus = gpiod_get_value(nop->gpiod_vbus); if ((vbus ^ nop->vbus) == 0) return IRQ_HANDLED; nop->vbus = vbus; if (vbus) { status = USB_EVENT_VBUS; otg->state = OTG_STATE_B_PERIPHERAL; nop->phy.last_event = status; usb_gadget_vbus_connect(otg->gadget); /* drawing a "unit load" is *always* OK, except for OTG */ nop_set_vbus_draw(nop, 100); atomic_notifier_call_chain(&nop->phy.notifier, status, otg->gadget); } else { nop_set_vbus_draw(nop, 0); usb_gadget_vbus_disconnect(otg->gadget); status = USB_EVENT_NONE; otg->state = OTG_STATE_B_IDLE; nop->phy.last_event = status; atomic_notifier_call_chain(&nop->phy.notifier, status, otg->gadget); } return IRQ_HANDLED; }
/** * exynos_drd_switch_start_peripheral - bind/unbind the peripheral controller. * * @otg: Pointer to the usb_otg structure. * @on: start / stop the gadget controller driver. * * Returns 0 on success otherwise negative errno. */ static int exynos_drd_switch_start_peripheral(struct usb_otg *otg, int on) { int ret; if (!otg->gadget) return -EINVAL; dev_dbg(otg->phy->dev, "Turn %s gadget %s\n", on ? "on" : "off", otg->gadget->name); if (on) { /* Start device only if host is off */ if (!exynos_drd_switch_is_host_off(otg)) { /* * REVISIT: if host is not suspended shall we check * runtime_error flag and clear it, if it is set? * It will give an additional chance to the host * to be suspended if runtime error happened. */ dev_vdbg(otg->phy->dev, "%s: host is still active\n", __func__); return -EAGAIN; } ret = usb_gadget_vbus_connect(otg->gadget); } else { ret = usb_gadget_vbus_disconnect(otg->gadget); /* Currently always return 0 */ } return ret; }
static void msm_otg_start_peripheral(struct usb_phy *phy, int on) { struct msm_otg *motg = container_of(phy, struct msm_otg, phy); struct msm_otg_platform_data *pdata = motg->pdata; if (!phy->otg->gadget) return; if (on) { dev_dbg(phy->dev, "gadget on\n"); /* * Some boards have a switch cotrolled by gpio * to enable/disable internal HUB. Disable internal * HUB before kicking the gadget. */ if (pdata->setup_gpio) pdata->setup_gpio(OTG_STATE_B_PERIPHERAL); usb_gadget_vbus_connect(phy->otg->gadget); } else { dev_dbg(phy->dev, "gadget off\n"); usb_gadget_vbus_disconnect(phy->otg->gadget); if (pdata->setup_gpio) pdata->setup_gpio(OTG_STATE_UNDEFINED); } }
static int sec_bat_check_cable_callback(void) { struct usb_gadget *gadget = platform_get_drvdata(&s3c_device_usbgadget); bool attach = true; int adc_1, adc_2, avg_adc; if (!charger_supply) { charger_supply = power_supply_get_by_name("sec-charger"); if (!charger_supply) pr_err("%s: failed to get power supplies\n", __func__); } /* ADC check margin (300~500ms) */ msleep(150); usb_switch_lock(); usb_switch_set_path(USB_PATH_ADCCHECK); adc_1 = stmpe811_get_adc_data(6); adc_2 = stmpe811_get_adc_data(6); avg_adc = (adc_1 + adc_2)/2; usb_switch_clr_path(USB_PATH_ADCCHECK); usb_switch_unlock(); pr_info("[BAT] %s: Adc value (%d)\n", __func__, avg_adc); attach = !gpio_get_value(GPIO_TA_nCONNECTED) ? true : false; if(attach) { if(avg_adc > TA_ADC_LOW) current_cable_type = POWER_SUPPLY_TYPE_MAINS; else current_cable_type = POWER_SUPPLY_TYPE_USB; } else current_cable_type = POWER_SUPPLY_TYPE_BATTERY; /* temp code : only set vbus enable when usb attaced */ if (gadget) { if (attach) usb_gadget_vbus_connect(gadget); else usb_gadget_vbus_disconnect(gadget); } #if 0 pr_info("%s: Cable type(%s), Attach(%d), Adc(%d)\n", __func__, current_cable_type == POWER_SUPPLY_TYPE_BATTERY ? "Battery" : current_cable_type == POWER_SUPPLY_TYPE_USB ? "USB" : "TA", attach, adc); #endif return current_cable_type; }
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; clk_enable(tegra->clk); spin_lock_irqsave(&tegra->lock, flags); status = tegra->int_status; 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 (to == OTG_STATE_A_SUSPEND) { if (from == OTG_STATE_A_HOST) tegra_stop_host(tegra); else if (from == OTG_STATE_B_PERIPHERAL && otg->gadget) usb_gadget_vbus_disconnect(otg->gadget); } else if (to == OTG_STATE_B_PERIPHERAL && otg->gadget) { if (from == OTG_STATE_A_SUSPEND) usb_gadget_vbus_connect(otg->gadget); } else if (to == OTG_STATE_A_HOST) { if (from == OTG_STATE_A_SUSPEND) tegra_start_host(tegra); } } clk_disable(tegra->clk); }
static void tegra_change_otg_state(struct tegra_otg_data *tegra, enum usb_otg_state to) { struct otg_transceiver *otg = &tegra->otg; enum usb_otg_state from = otg->state; if(!tegra->interrupt_mode){ DBG("OTG: Vbus detection is disabled"); return; } //&*&*&*AL1_20121121 skip tegra_stop_host api to avoid device hang on suspend handle if (from == OTG_STATE_A_HOST && to == OTG_STATE_A_SUSPEND) { if (tegra->pdev->dev.power.is_suspended) { DBG("OTG: host is suspended\n"); //&*&*&*AL1_20121126 tegra_otg_notify_event(otg, USB_EVENT_NONE); //&*&*&*AL2_20121126 return; } } //&*&*&*AL2_20121121 skip tegra_stop_host api to avoid device hang on suspend handle DBG("%s(%d) requested otg state %s-->%s\n", __func__, __LINE__, tegra_state_name(from), tegra_state_name(to)); if (to != OTG_STATE_UNDEFINED && from != to) { otg->state = to; dev_info(tegra->otg.dev, "%s --> %s\n", tegra_state_name(from), tegra_state_name(to)); #if 1 //CL2N+ if (tegra->charger_cb) tegra->charger_cb(to, from, tegra->charger_cb_data); #endif //CL2N- if (from == OTG_STATE_A_SUSPEND) { if (to == OTG_STATE_B_PERIPHERAL && otg->gadget) { usb_gadget_vbus_connect(otg->gadget); tegra_otg_notify_event(otg, USB_EVENT_VBUS); } else if (to == OTG_STATE_A_HOST) { tegra_start_host(tegra); tegra_otg_notify_event(otg, USB_EVENT_ID); } } else if (from == OTG_STATE_A_HOST) { if (to == OTG_STATE_A_SUSPEND) { tegra_stop_host(tegra); tegra_otg_notify_event(otg, USB_EVENT_NONE); } } else if (from == OTG_STATE_B_PERIPHERAL && otg->gadget) { if (to == OTG_STATE_A_SUSPEND) { usb_gadget_vbus_disconnect(otg->gadget); tegra_otg_notify_event(otg, USB_EVENT_NONE); } } } }
void ci_handle_vbus_change(struct ci_hdrc *ci) { if (!ci->is_otg) return; if (hw_read_otgsc(ci, OTGSC_BSV)) usb_gadget_vbus_connect(&ci->gadget); else usb_gadget_vbus_disconnect(&ci->gadget); }
static void msm_otg_start_peripheral(struct otg_transceiver *xceiv, int on) { if (!xceiv->gadget) return; if (on) usb_gadget_vbus_connect(xceiv->gadget); else usb_gadget_vbus_disconnect(xceiv->gadget); }
static void check_vbus_state(struct tahvo_usb *tu) { int reg, prev_state; reg = tahvo_read_reg(TAHVO_REG_IDSR); if (reg & 0x01) { u32 l; vbus_active = 1; switch (tu->otg.state) { case OTG_STATE_B_IDLE: /* Enable the gadget driver */ if (tu->otg.gadget) usb_gadget_vbus_connect(tu->otg.gadget); /* Set B-session valid and not B-sessio ended to indicate * Vbus to be ok. */ l = omap_readl(OTG_CTRL); l &= ~OTG_BSESSEND; l |= OTG_BSESSVLD; omap_writel(l, OTG_CTRL); tu->otg.state = OTG_STATE_B_PERIPHERAL; break; case OTG_STATE_A_IDLE: /* Session is now valid assuming the USB hub is driving Vbus */ tu->otg.state = OTG_STATE_A_HOST; host_resume(tu); break; default: break; } printk("USB cable connected\n"); } else { switch (tu->otg.state) { case OTG_STATE_B_PERIPHERAL: if (tu->otg.gadget) usb_gadget_vbus_disconnect(tu->otg.gadget); tu->otg.state = OTG_STATE_B_IDLE; break; case OTG_STATE_A_HOST: tu->otg.state = OTG_STATE_A_IDLE; break; default: break; } printk("USB cable disconnected\n"); vbus_active = 0; } prev_state = tu->vbus_state; tu->vbus_state = reg & 0x01; if (prev_state != tu->vbus_state) sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state"); }
static void gpio_vbus_work(struct work_struct *work) { struct gpio_vbus_data *gpio_vbus = container_of(work, struct gpio_vbus_data, work.work); struct gpio_vbus_mach_info *pdata = dev_get_platdata(gpio_vbus->dev); int gpio, status, vbus; if (!gpio_vbus->phy.otg->gadget) return; vbus = is_vbus_powered(pdata); if ((vbus ^ gpio_vbus->vbus) == 0) return; gpio_vbus->vbus = vbus; /* Peripheral controllers which manage the pullup themselves won't have * gpio_pullup configured here. If it's configured here, we'll do what * isp1301_omap::b_peripheral() does and enable the pullup here... although * that may complicate usb_gadget_{,dis}connect() support. */ gpio = pdata->gpio_pullup; if (vbus) { status = USB_EVENT_VBUS; gpio_vbus->phy.otg->state = OTG_STATE_B_PERIPHERAL; gpio_vbus->phy.last_event = status; usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget); /* drawing a "unit load" is *always* OK, except for OTG */ set_vbus_draw(gpio_vbus, 100); /* optionally enable D+ pullup */ if (gpio_is_valid(gpio)) gpio_set_value(gpio, !pdata->gpio_pullup_inverted); atomic_notifier_call_chain(&gpio_vbus->phy.notifier, status, gpio_vbus->phy.otg->gadget); } else { /* optionally disable D+ pullup */ if (gpio_is_valid(gpio)) gpio_set_value(gpio, pdata->gpio_pullup_inverted); set_vbus_draw(gpio_vbus, 0); usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget); status = USB_EVENT_NONE; gpio_vbus->phy.otg->state = OTG_STATE_B_IDLE; gpio_vbus->phy.last_event = status; atomic_notifier_call_chain(&gpio_vbus->phy.notifier, status, gpio_vbus->phy.otg->gadget); } }
static int isp1301_start_hnp(struct otg_transceiver *dev) { #ifdef CONFIG_USB_OTG struct isp1301 *isp = container_of(dev, struct isp1301, otg); u32 l; if (!dev || isp != the_transceiver) return -ENODEV; if (isp->otg.default_a && (isp->otg.host == NULL || !isp->otg.host->b_hnp_enable)) return -ENOTCONN; if (!isp->otg.default_a && (isp->otg.gadget == NULL || !isp->otg.gadget->b_hnp_enable)) return -ENOTCONN; /* We want hardware to manage most HNP protocol timings. * So do this part as early as possible... */ switch (isp->otg.state) { case OTG_STATE_B_HOST: isp->otg.state = OTG_STATE_B_PERIPHERAL; /* caller will suspend next */ break; case OTG_STATE_A_HOST: #if 0 /* autoconnect mode avoids irq latency bugs */ isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_BDIS_ACON_EN); #endif /* caller must suspend then clear A_BUSREQ */ usb_gadget_vbus_connect(isp->otg.gadget); l = omap_readl(OTG_CTRL); l |= OTG_A_SETB_HNPEN; omap_writel(l, OTG_CTRL); break; case OTG_STATE_A_PERIPHERAL: /* initiated by B-Host suspend */ break; default: return -EILSEQ; } pr_debug("otg: HNP %s, %06x ...\n", state_name(isp), omap_readl(OTG_CTRL)); check_state(isp, __func__); return 0; #else /* srp-only */ return -EINVAL; #endif }
void ci_handle_vbus_connected(struct ci_hdrc *ci) { /* * TODO: if the platform does not supply 5v to udc, or use other way * to supply 5v, it needs to use other conditions to call * usb_gadget_vbus_connect. */ if (!ci->is_otg) return; if (hw_read_otgsc(ci, OTGSC_BSV) && !ci_is_vbus_glitch(ci)) usb_gadget_vbus_connect(&ci->gadget); }
static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) { struct usb_otg *otg = mvotg->phy.otg; if (!otg->gadget) return; dev_info(mvotg->phy.dev, "gadget %s\n", on ? "on" : "off"); if (on) usb_gadget_vbus_connect(otg->gadget); else usb_gadget_vbus_disconnect(otg->gadget); }
static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) { struct otg_transceiver *otg = &mvotg->otg; if (!otg->gadget) return; dev_info(otg->dev, "gadget %s\n", on ? "on" : "off"); if (on) usb_gadget_vbus_connect(otg->gadget); else usb_gadget_vbus_disconnect(otg->gadget); }
static void check_vbus_state(struct tahvo_usb *tu) { struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent); int reg, prev_state; reg = retu_read(rdev, TAHVO_REG_IDSR); if (reg & TAHVO_STAT_VBUS) { switch (tu->phy.state) { case OTG_STATE_B_IDLE: /* Enable the gadget driver */ if (tu->phy.otg->gadget) usb_gadget_vbus_connect(tu->phy.otg->gadget); tu->phy.state = OTG_STATE_B_PERIPHERAL; break; case OTG_STATE_A_IDLE: /* * Session is now valid assuming the USB hub is driving * Vbus. */ tu->phy.state = OTG_STATE_A_HOST; break; default: break; } dev_info(&tu->pt_dev->dev, "USB cable connected\n"); } else { switch (tu->phy.state) { case OTG_STATE_B_PERIPHERAL: if (tu->phy.otg->gadget) usb_gadget_vbus_disconnect(tu->phy.otg->gadget); tu->phy.state = OTG_STATE_B_IDLE; break; case OTG_STATE_A_HOST: tu->phy.state = OTG_STATE_A_IDLE; break; default: break; } dev_info(&tu->pt_dev->dev, "USB cable disconnected\n"); } prev_state = tu->vbus_state; tu->vbus_state = reg & TAHVO_STAT_VBUS; if (prev_state != tu->vbus_state) { extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state); sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state"); } }
/* VBUS change IRQ handler */ static irqreturn_t gpio_vbus_irq(int irq, void *data) { struct platform_device *pdev = data; struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); int gpio, vbus; vbus = gpio_get_value(pdata->gpio_vbus); if (pdata->gpio_vbus_inverted) vbus = !vbus; dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", vbus ? "supplied" : "inactive", gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); if (!gpio_vbus->otg.gadget) return IRQ_HANDLED; /* Peripheral controllers which manage the pullup themselves won't have * gpio_pullup configured here. If it's configured here, we'll do what * isp1301_omap::b_peripheral() does and enable the pullup here... although * that may complicate usb_gadget_{,dis}connect() support. */ gpio = pdata->gpio_pullup; if (vbus) { gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL; usb_gadget_vbus_connect(gpio_vbus->otg.gadget); /* drawing a "unit load" is *always* OK, except for OTG */ set_vbus_draw(gpio_vbus, 100); /* optionally enable D+ pullup */ if (gpio_is_valid(gpio)) gpio_set_value(gpio, !pdata->gpio_pullup_inverted); } else { /* optionally disable D+ pullup */ if (gpio_is_valid(gpio)) gpio_set_value(gpio, pdata->gpio_pullup_inverted); set_vbus_draw(gpio_vbus, 0); usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget); gpio_vbus->otg.state = OTG_STATE_B_IDLE; } return IRQ_HANDLED; }
static int dwc3_otg_start_gadget(struct otg_fsm *fsm, int on) { struct usb_otg *otg = fsm->otg; struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); struct dwc3 *dwc = dotg->dwc; struct device *dev = dotg->dwc->dev; int ret = 0; if (!otg->gadget) return -EINVAL; dev_err(dev, "Turn %s gadget %s\n", on ? "on" : "off", otg->gadget->name); /* sync usb3 phy state with usb2 phy */ dwc->usb3_phy->state = dwc->usb2_phy->state; if (on) { pm_runtime_get_sync(dev); ret = dwc3_core_init(dwc); if (ret) { dev_err(dwc->dev, "%s: failed to reinitialize core\n", __func__); goto err1; } dwc3_otg_set_peripheral_mode(dotg); ret = usb_gadget_vbus_connect(otg->gadget); if (ret) { dev_err(dwc->dev, "%s: vbus connect failed\n", __func__); goto err2; } } else { /* avoid missing disconnect interrupt */ wait_for_completion_timeout(&dwc->disconnect, msecs_to_jiffies(200)); ret = usb_gadget_vbus_disconnect(otg->gadget); if (ret) dev_err(dwc->dev, "%s: vbus disconnect failed\n", __func__); err2: dwc3_core_exit(dwc); err1: pm_runtime_put_sync(dev); } return ret; }
static void b_peripheral(struct isp1301 *isp) { OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; usb_gadget_vbus_connect(isp->otg.gadget); #ifdef CONFIG_USB_OTG enable_vbus_draw(isp, 8); otg_update_isp(isp); #else enable_vbus_draw(isp, 100); /* UDC driver just set OTG_BSESSVLD */ isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN); isp->otg.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); dump_regs(isp, "2periph"); #endif }
static void tegra_change_otg_state(struct tegra_otg_data *tegra, enum usb_otg_state to) { struct otg_transceiver *otg = &tegra->otg; enum usb_otg_state from = otg->state; if(!tegra->interrupt_mode){ DBG("OTG: Vbus detection is disabled"); return; } DBG("%s(%d) requested otg state %s-->%s\n", __func__, __LINE__, tegra_state_name(from), tegra_state_name(to)); if (to != OTG_STATE_UNDEFINED && from != to) { 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 (from == OTG_STATE_A_SUSPEND) { if (to == OTG_STATE_B_PERIPHERAL && otg->gadget) usb_gadget_vbus_connect(otg->gadget); else if (to == OTG_STATE_A_HOST) tegra_start_host(tegra); } else if (from == OTG_STATE_A_HOST) { if (to == OTG_STATE_A_SUSPEND) { tegra_stop_host(tegra); #ifdef CONFIG_MHL_SII8334 if(zte_get_board_id() > 1) CBUS_ID_Opened_AfterPlugedout(); #endif } } else if (from == OTG_STATE_B_PERIPHERAL && otg->gadget) { if (to == OTG_STATE_A_SUSPEND) usb_gadget_vbus_disconnect(otg->gadget); } } }
/** * dwc3_otg_start_peripheral - bind/unbind the peripheral controller. * * @otg: Pointer to the otg_transceiver structure. * @gadget: pointer to the usb_gadget structure. * * Returns 0 on success otherwise negative errno. */ static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on) { struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); if (!otg->gadget) return -EINVAL; if (on) { dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n", __func__, otg->gadget->name); dwc3_otg_set_peripheral_regs(dotg); usb_gadget_vbus_connect(otg->gadget); } else { dev_dbg(otg->phy->dev, "%s: turn off gadget %s\n", __func__, otg->gadget->name); usb_gadget_vbus_disconnect(otg->gadget); } return 0; }
/** * dwc3_otg_start_peripheral - bind/unbind the peripheral controller. * * @otg: Pointer to the otg_transceiver structure. * @gadget: pointer to the usb_gadget structure. * * Returns 0 on success otherwise negative errno. */ static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on) { struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv; struct dwc3 *dwc = dotg->dwc; if (!otg->gadget) return -EINVAL; if (on) { dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n", __func__, otg->gadget->name); /* * Hardware reset is required to support below scenarios: * 1. Host <-> peripheral switching * 2. Once an endpoint is configured in DBM (BAM) mode, it * can be unconfigured only after RESET */ if (ext_xceiv && ext_xceiv->otg_capability && ext_xceiv->ext_block_reset) ext_xceiv->ext_block_reset(); /* re-init core and OTG registers as block reset clears these */ dwc3_post_host_reset_core_init(dwc); if (ext_xceiv && !ext_xceiv->otg_capability) dwc3_otg_reset(dotg); dwc3_otg_set_peripheral_regs(dotg); usb_gadget_vbus_connect(otg->gadget); } else { dev_dbg(otg->phy->dev, "%s: turn off gadget %s\n", __func__, otg->gadget->name); usb_gadget_vbus_disconnect(otg->gadget); } return 0; }
static ssize_t usb_lock_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct tegra_otg_data *tegra_otg = dev_get_drvdata(dev); struct otg_transceiver *otg = &tegra_otg->otg; unsigned long status; int value; if (sscanf(buf, "%d", &value) != 1) { pr_err("%s : Invalid value\n", __func__); return -EINVAL; } if ((value < 0) || (value > 1)) { pr_err("%s : Invalid value\n", __func__); return -EINVAL; } status = tegra_otg->int_status; if (value != usb_access_lock) { usb_access_lock = value; if (value == 1) { pr_err("%s : Set USB Block!!\n", __func__); usb_gadget_vbus_disconnect(otg->gadget); } else { pr_err("%s : Release USB Block!!\n", __func__); if (status & USB_VBUS_STATUS) { pr_err("%s : status: 0x%x\n", __func__, status); usb_gadget_vbus_connect(otg->gadget); } } } return size; }
static void gpio_vbus_work(struct work_struct *work) { struct gpio_vbus_data *gpio_vbus = container_of(work, struct gpio_vbus_data, work); struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; int gpio; if (!gpio_vbus->otg.gadget) return; /* Peripheral controllers which manage the pullup themselves won't have * gpio_pullup configured here. If it's configured here, we'll do what * isp1301_omap::b_peripheral() does and enable the pullup here... although * that may complicate usb_gadget_{,dis}connect() support. */ gpio = pdata->gpio_pullup; if (is_vbus_powered(pdata)) { gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL; usb_gadget_vbus_connect(gpio_vbus->otg.gadget); /* drawing a "unit load" is *always* OK, except for OTG */ set_vbus_draw(gpio_vbus, 100); /* optionally enable D+ pullup */ if (gpio_is_valid(gpio)) gpio_set_value(gpio, !pdata->gpio_pullup_inverted); } else { /* optionally disable D+ pullup */ if (gpio_is_valid(gpio)) gpio_set_value(gpio, pdata->gpio_pullup_inverted); set_vbus_draw(gpio_vbus, 0); usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget); gpio_vbus->otg.state = OTG_STATE_B_IDLE; } }