/** * 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; }
/** * 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; }
/** * dwc3_otg_start_host - helper function for starting/stoping the host controller driver. * * @otg: Pointer to the otg_transceiver structure. * @on: start / stop the host controller driver. * * Returns 0 on success otherwise negative errno. */ static int dwc3_otg_start_host(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; int ret = 0; if (!dwc->xhci) return -EINVAL; if (!dotg->vbus_otg) { dotg->vbus_otg = devm_regulator_get(dwc->dev->parent, "vbus_dwc3"); if (IS_ERR(dotg->vbus_otg)) { dev_err(dwc->dev, "Failed to get vbus regulator\n"); ret = PTR_ERR(dotg->vbus_otg); dotg->vbus_otg = 0; return ret; } } if (on) { dev_dbg(otg->phy->dev, "%s: turn on host\n", __func__); dwc3_otg_notify_host_mode(otg, on); ret = regulator_enable(dotg->vbus_otg); if (ret) { dev_err(otg->phy->dev, "unable to enable vbus_otg\n"); dwc3_otg_notify_host_mode(otg, 0); return ret; } /* * This should be revisited for more testing post-silicon. * In worst case we may need to disconnect the root hub * before stopping the controller so that it does not * interfere with runtime pm/system pm. * We can also consider registering and unregistering xhci * platform device. It is almost similar to add_hcd and * remove_hcd, But we may not use standard set_host method * anymore. */ dwc3_otg_set_hsphy_auto_suspend(dotg, true); dwc3_otg_set_host_regs(dotg); /* * FIXME If micro A cable is disconnected during system suspend, * xhci platform device will be removed before runtime pm is * enabled for xhci device. Due to this, disable_depth becomes * greater than one and runtimepm is not enabled for next microA * connect. Fix this by calling pm_runtime_init for xhci device. */ pm_runtime_init(&dwc->xhci->dev); ret = platform_device_add(dwc->xhci); if (ret) { dev_err(otg->phy->dev, "%s: failed to add XHCI pdev ret=%d\n", __func__, ret); regulator_disable(dotg->vbus_otg); dwc3_otg_notify_host_mode(otg, 0); return ret; } /* re-init OTG EVTEN register as XHCI reset clears it */ if (ext_xceiv && !ext_xceiv->otg_capability) dwc3_otg_reset(dotg); } else { dev_dbg(otg->phy->dev, "%s: turn off host\n", __func__); ret = regulator_disable(dotg->vbus_otg); if (ret) { dev_err(otg->phy->dev, "unable to disable vbus_otg\n"); return ret; } dwc3_otg_notify_host_mode(otg, on); platform_device_del(dwc->xhci); /* * Perform USB hardware RESET (both core reset and DBM reset) * when moving from host to peripheral. This is required for * peripheral mode to work. */ if (ext_xceiv && ext_xceiv->otg_capability && ext_xceiv->ext_block_reset) ext_xceiv->ext_block_reset(ext_xceiv, true); dwc3_otg_set_hsphy_auto_suspend(dotg, false); dwc3_otg_set_peripheral_regs(dotg); /* 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); } return 0; }
static int dwc3_otg_start_host(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; int ret = 0; #ifdef CONFIG_PANTECH_QUALCOMM_OTG_MODE_OVP_BUG //xsemiyas_debug int value; #endif #if defined(CONFIG_PANTECH_USB_SMB_OTG_DISABLE_LOW_BATTERY) || defined(CONFIG_PANTECH_USB_TI_OTG_DISABLE_LOW_BATTERY) int level; #endif if (!dwc->xhci) return -EINVAL; #ifdef FEATURE_PANTECH_USB_CHARGER_INIT_ERROR if(!charger_ready_status()) return -ENODEV; #endif #if !defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) && !defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) && !defined(CONFIG_PANTECH_PMIC_CHARGER_BQ2419X) if (!dotg->vbus_otg) { dotg->vbus_otg = devm_regulator_get(dwc->dev->parent, "vbus_dwc3"); if (IS_ERR(dotg->vbus_otg)) { dev_err(dwc->dev, "Failed to get vbus regulator\n"); ret = PTR_ERR(dotg->vbus_otg); dotg->vbus_otg = 0; return ret; } } #endif /* !defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) && !defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) && !defined(CONFIG_PANTECH_CHARGER_BQ2419X) */ #if defined(CONFIG_PANTECH_USB_SMB_OTG_DISABLE_LOW_BATTERY) && defined(CONFIG_PANTECH_PMIC_OTG_UVLO) level = max17058_get_soc_for_otg(); #elif defined(CONFIG_PANTECH_USB_TI_OTG_DISABLE_LOW_BATTERY) && defined(CONFIG_PANTECH_EF63_PMIC_FUELGAUGE_MAX17058) level = max17058_get_soc_for_led(); #else level = 50; #endif if (on) { dev_dbg(otg->phy->dev, "%s: turn on host\n", __func__); #if defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) || defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) //xsemiyas_debug:warmup_time smb349_otg_power(1); usleep_range(60, 100); #ifdef CONFIG_PANTECH_PMIC_OTG smb349_otg_power_current(3); #endif /* CONFIG_PANTECH_PMIC_OTG */ smb349_otg_power(0); #endif /* defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) || defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) */ /* * This should be revisited for more testing post-silicon. * In worst case we may need to disconnect the root hub * before stopping the controller so that it does not * interfere with runtime pm/system pm. * We can also consider registering and unregistering xhci * platform device. It is almost similar to add_hcd and * remove_hcd, But we may not use standard set_host method * anymore. */ dwc3_otg_set_hsphy_auto_suspend(dotg, true); dwc3_otg_set_host_regs(dotg); /* * FIXME If micro A cable is disconnected during system suspend, * xhci platform device will be removed before runtime pm is * enabled for xhci device. Due to this, disable_depth becomes * greater than one and runtimepm is not enabled for next microA * connect. Fix this by calling pm_runtime_init for xhci device. */ pm_runtime_init(&dwc->xhci->dev); ret = platform_device_add(dwc->xhci); if (ret) { dev_err(otg->phy->dev, "%s: failed to add XHCI pdev ret=%d\n", __func__, ret); return ret; } dwc3_otg_notify_host_mode(otg, on); #ifdef CONFIG_PANTECH_QUALCOMM_OTG_MODE_OVP_BUG //xsemiyas_debug while((value = get_pantech_chg_otg_mode()) != 1){ if(value == -1){ set_pantech_chg_otg_mode(0); dev_err(otg->phy->dev, "unable to enable qpnp_otg_mode\n"); return -ENXIO; } msleep(10); } #endif #if defined(CONFIG_PANTECH_USB_SMB_OTG_DISABLE_LOW_BATTERY) if (level < 30) { dev_err(dwc->dev, "Low Battery!!, OTG power not set!\n"); #ifdef CONFIG_ANDROID_PANTECH_USB_OTG_INTENT set_otg_dev_state(2); #endif return 0; } #elif defined(CONFIG_PANTECH_USB_TI_OTG_DISABLE_LOW_BATTERY) if (level < 10) { dev_err(dwc->dev, "Battery is not enough!, OTG power remove!\n"); #ifdef CONFIG_ANDROID_PANTECH_USB_OTG_INTENT set_otg_dev_state(2); #endif #if defined(CONFIG_PANTECH_PMIC_CHARGER_BQ2419X) //chg_force_switching_scope(1); //otg power remove dwc3_otg_notify_host_mode(otg, 0); //otg power remove #endif return 0; } #endif #ifdef CONFIG_PANTECH_USB_TUNE_SIGNALING_PARAM pantech_set_otg_signaling_param(on); #endif #if defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) || defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) smb349_otg_power(on); #ifdef CONFIG_PANTECH_PMIC_OTG usleep_range(60, 100);//xsemiyas_debug: change 60uS smb349_otg_power_current(3); //750mA current setting #endif /* CONFIG_PANTECH_PMIC_OTG */ #elif !defined(CONFIG_PANTECH_PMIC_CHARGER_BQ2419X) ret = regulator_enable(dotg->vbus_otg); if (ret) { dev_err(otg->phy->dev, "unable to enable vbus_otg\n"); platform_device_del(dwc->xhci); return ret; } #endif /* defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) || defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) */ /* re-init OTG EVTEN register as XHCI reset clears it */ if (ext_xceiv && !ext_xceiv->otg_capability) dwc3_otg_reset(dotg); #if defined(CONFIG_PANTECH_USB_SMB_OTG_DISABLE_LOW_BATTERY) || defined(CONFIG_PANTECH_USB_TI_OTG_DISABLE_LOW_BATTERY) is_otg_enabled = 1; #endif } else { dev_dbg(otg->phy->dev, "%s: turn off host\n", __func__); #ifdef CONFIG_PANTECH_USB_SMB_OTG_DISABLE_LOW_BATTERY if (level >= 30) { #endif #if defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) || defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) smb349_otg_power(on); #ifdef CONFIG_PANTECH_PMIC_OTG smb349_otg_power_current(1); //250mA current setting #endif /* CONFIG_PANTECH_PMIC_OTG */ #ifdef CONFIG_PANTECH_USB_SMB_OTG_DISABLE_LOW_BATTERY } #endif #elif !defined(CONFIG_PANTECH_PMIC_CHARGER_BQ2419X) ret = regulator_disable(dotg->vbus_otg); if (ret) { dev_err(otg->phy->dev, "unable to disable vbus_otg\n"); return ret; } #endif /* defined(CONFIG_PANTECH_PMIC_CHARGER_SMB347) || defined(CONFIG_PANTECH_PMIC_CHARGER_SMB349) */ #ifdef CONFIG_PANTECH_USB_TUNE_SIGNALING_PARAM pantech_set_otg_signaling_param(on); #endif #if defined(CONFIG_PANTECH_USB_SMB_OTG_DISABLE_LOW_BATTERY) || defined(CONFIG_PANTECH_USB_TI_OTG_DISABLE_LOW_BATTERY) is_otg_enabled = 0; #endif dwc3_otg_notify_host_mode(otg, on); #ifdef CONFIG_PANTECH_SIO_BUG_FIX /* FIXME : Sometimes sm_work is executed twice in abnormal state. * So platform_device_del is executed twice. * And this code is occurred NULL pointer exception at seconds procedure. * We are fixed below code only executed one. * from LS4-USB tarial */ if (dwc->xhci) platform_device_del(dwc->xhci); #else platform_device_del(dwc->xhci); #endif /* * Perform USB hardware RESET (both core reset and DBM reset) * when moving from host to peripheral. This is required for * peripheral mode to work. */ if (ext_xceiv && ext_xceiv->otg_capability && ext_xceiv->ext_block_reset) ext_xceiv->ext_block_reset(ext_xceiv, true); dwc3_otg_set_hsphy_auto_suspend(dotg, false); dwc3_otg_set_peripheral_regs(dotg); /* 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); } return 0; }