Exemple #1
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;
}
static int
isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
{
	struct isp1301	*isp = container_of(otg, struct isp1301, otg);

	if (!otg || isp != the_transceiver)
		return -ENODEV;

	if (!gadget) {
		OTG_IRQ_EN_REG = 0;
		if (!isp->otg.default_a)
			enable_vbus_draw(isp, 0);
		usb_gadget_vbus_disconnect(isp->otg.gadget);
		isp->otg.gadget = 0;
		power_down(isp);
		return 0;
	}

#ifdef	CONFIG_USB_OTG
	isp->otg.gadget = gadget;
	dev_dbg(&isp->client.dev, "registered gadget\n");
	/* gadget driver may be suspended until vbus_connect () */
	if (isp->otg.host)
		return isp1301_otg_enable(isp);
	return 0;

#elif	!defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE)
	isp->otg.gadget = gadget;
	// FIXME update its refcount

	OTG_CTRL_REG = (OTG_CTRL_REG & OTG_CTRL_MASK
				& ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS))
			| OTG_ID;
	power_up(isp);
	isp->otg.state = OTG_STATE_B_IDLE;

	if (machine_is_omap_h2())
		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);

	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
		INTR_SESS_VLD);
	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
		INTR_VBUS_VLD);
	dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
	dump_regs(isp, __func__);

	/* If this has a Mini-AB connector, this mode is highly
	 * nonstandard ... but can be handy for testing, so long
	 * as you don't plug a Mini-A cable into the jack.
	 */
	if (isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE) & INTR_VBUS_VLD)
		b_peripheral(isp);

	return 0;

#else
	dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n");
	return -EINVAL;
#endif
}
Exemple #3
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 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;
}
Exemple #5
0
static void tahvo_usb_power_off(struct tahvo_usb *tu)
{
	u32 l;
	int id;

	/* Disable gadget controller if any */
	if (tu->otg.gadget)
		usb_gadget_vbus_disconnect(tu->otg.gadget);

	/* Disable OTG and interrupts */
	if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL)
		id = OTG_ID;
	else
		id = 0;
	l = omap_readl(OTG_CTRL);
	l &= ~(OTG_CTRL_XCVR_MASK | OTG_CTRL_SYS_MASK | OTG_BSESSVLD);
	l |= id | OTG_BSESSEND;
	omap_writel(l, OTG_CTRL);
	omap_writew(0, OTG_IRQ_EN);

	l = omap_readl(OTG_SYSCON_2);
	l &= ~OTG_EN;
	omap_writel(l, OTG_SYSCON_2);

	l = omap_readl(OTG_SYSCON_1);
	l |= OTG_IDLE_EN;
	omap_writel(l, OTG_SYSCON_1);

	/* Power off transceiver */
	tahvo_write_reg(tu->dev, TAHVO_REG_USBR, 0);
	tu->otg.state = OTG_STATE_UNDEFINED;
}
Exemple #6
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);
		}
	}

}
/**
 * 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;
}
Exemple #8
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;
}
/**
 * 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;
}
Exemple #10
0
static void tahvo_usb_power_off(struct tahvo_usb *tu)
{
	u32 l;
	int id;

	/* Disable gadget controller if any */
	if (tu->otg.gadget)
		usb_gadget_vbus_disconnect(tu->otg.gadget);

	host_suspend(tu);

	/* Disable OTG and interrupts */
	if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL)
		id = OTG_ID;
	else
		id = 0;
	l = OTG_CTRL_REG;
	l &= ~(OTG_CTRL_XCVR_MASK | OTG_CTRL_SYS_MASK | OTG_BSESSVLD);
	l |= id | OTG_BSESSEND;
	OTG_CTRL_REG = l;
	OTG_IRQ_EN_REG = 0;

	OTG_SYSCON_2_REG &= ~OTG_EN;

	OTG_SYSCON_1_REG |= OTG_IDLE_EN;

	/* Power off transceiver */
	tahvo_write_reg(TAHVO_REG_USBR, 0);
	tu->otg.state = OTG_STATE_UNDEFINED;
}
static int gadget_suspend(struct isp1301 *isp)
{
	isp->otg.gadget->b_hnp_enable = 0;
	isp->otg.gadget->a_hnp_support = 0;
	isp->otg.gadget->a_alt_hnp_support = 0;
	return usb_gadget_vbus_disconnect(isp->otg.gadget);
}
Exemple #12
0
static ssize_t u1_switch_store_usb_lock(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t count)
{
	int lock;
	struct s3c_udc *udc = platform_get_drvdata(&s3c_device_usbgadget);

	if (!strncmp(buf, "0", 1))
		lock = 0;
	else if (!strncmp(buf, "1", 1))
		lock = 1;
	else {
		pr_warn("%s: Wrong command\n", __func__);
		return count;
	}

	if (IS_ERR_OR_NULL(udc))
		return count;

	pr_info("%s: lock=%d\n", __func__, lock);

	if (lock != is_usb_locked) {
		is_usb_locked = lock;

		if (lock) {
			if (udc->udc_enabled)
				usb_gadget_vbus_disconnect(&udc->gadget);
		}
	}

	return count;
}
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 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;
}
Exemple #15
0
static void tahvo_usb_stop_peripheral(struct tahvo_usb *tu)
{
	OTG_CTRL_REG = (OTG_CTRL_REG & ~OTG_BSESSVLD) | OTG_BSESSEND;
	if (tu->otg.gadget)
		usb_gadget_vbus_disconnect(tu->otg.gadget);
	tu->otg.state = OTG_STATE_B_IDLE;

}
Exemple #16
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);

}
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);
			}
		}
	}
}
Exemple #18
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);
}
Exemple #19
0
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);
}
Exemple #20
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);
	}
}
Exemple #22
0
static void tahvo_usb_power_off(struct tahvo_usb *tu)
{
	struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);

	/* Disable gadget controller if any */
	if (tu->phy.otg->gadget)
		usb_gadget_vbus_disconnect(tu->phy.otg->gadget);

	/* Power off transceiver */
	retu_write(rdev, TAHVO_REG_USBR, 0);
	tu->phy.state = OTG_STATE_UNDEFINED;
}
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);
		}
	}
}
Exemple #24
0
static void tahvo_usb_stop_peripheral(struct tahvo_usb *tu)
{
	u32 l;

	l = omap_readl(OTG_CTRL);
	l &= ~OTG_BSESSVLD;
	l |= OTG_BSESSEND;
	omap_writel(l, OTG_CTRL);

	if (tu->otg.gadget)
		usb_gadget_vbus_disconnect(tu->otg.gadget);
	tu->otg.state = OTG_STATE_B_IDLE;

}
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 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);
}
Exemple #27
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");
	}
}
/* 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;
}
Exemple #29
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 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;
}
Exemple #30
0
static int tegra_otg_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct tegra_otg_data *tegra_otg = platform_get_drvdata(pdev);
	struct otg_transceiver *otg = &tegra_otg->otg;
	enum usb_otg_state from = otg->state;
	/* store the interupt enable for cable ID and VBUS */
	clk_enable(tegra_otg->clk);
	tegra_otg->intr_reg_data = readl(tegra_otg->regs + USB_PHY_WAKEUP);
	clk_disable(tegra_otg->clk);

	if (from == OTG_STATE_B_PERIPHERAL && otg->gadget)
		usb_gadget_vbus_disconnect(otg->gadget);

	tegra_otg_disable_clk();
	return 0;
}