Exemplo n.º 1
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));*/
		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);
		}
	}
}
Exemplo n.º 2
0
/* 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);
		}
	}

}
Exemplo n.º 3
0
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);
	}
}
Exemplo n.º 4
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;

	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;
}
Exemplo n.º 6
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;

	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);
		}
	}
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 12
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;

	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);

}
Exemplo n.º 13
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;
	}

	//&*&*&*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);
			}
		}
	}
}
Exemplo n.º 14
0
Arquivo: otg.c Projeto: 19Dan01/linux
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);
}
Exemplo n.º 15
0
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);
}
Exemplo n.º 16
0
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);
	}
}
Exemplo n.º 18
0
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
}
Exemplo n.º 19
0
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);
}
Exemplo n.º 20
0
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);
}
Exemplo n.º 22
0
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");
	}
}
Exemplo n.º 23
0
/* 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;
}
Exemplo n.º 24
0
Arquivo: otg.c Projeto: qkdang/m462
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;
}
Exemplo n.º 25
0
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
}
Exemplo n.º 26
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 (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);
		}
	}
}
Exemplo n.º 27
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;
}
Exemplo n.º 28
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;
}
Exemplo n.º 29
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;
}
Exemplo n.º 30
0
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;
	}
}