示例#1
0
文件: tahvo-usb.c 项目: mozyg/kernel
static void tahvo_usb_vbus_interrupt(unsigned long arg)
{
	struct tahvo_usb *tu = (struct tahvo_usb *) arg;

	tahvo_ack_irq(TAHVO_INT_VBUSON);
	/* Seems we need this to acknowledge the interrupt */
	tahvo_read_reg(TAHVO_REG_IDSR);
	schedule_work(&tu->irq_work);
}
示例#2
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");
}
示例#3
0
文件: tahvo-usb.c 项目: mozyg/kernel
static int tahvo_usb_set_suspend(struct otg_transceiver *dev, int suspend)
{
	struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg);
	u16 w;

	dev_dbg(&tu->pt_dev->dev, "set_suspend\n");

	w = tahvo_read_reg(TAHVO_REG_USBR);
	if (suspend)
		w &= ~USBR_NSUSPEND;
	else
		w |= USBR_NSUSPEND;
	tahvo_write_reg(TAHVO_REG_USBR, w);

	return 0;
}
示例#4
0
文件: tahvo-usb.c 项目: mozyg/kernel
static int tahvo_usb_probe(struct device *dev)
{
	struct tahvo_usb *tu;
	int ret;

	dev_dbg(dev, "probe\n");

	/* Create driver data */
	tu = kmalloc(sizeof(*tu), GFP_KERNEL);
	if (!tu)
		return -ENOMEM;
	memset(tu, 0, sizeof(*tu));
	tu->pt_dev = container_of(dev, struct platform_device, dev);
#ifdef CONFIG_USB_OTG
	/* Default mode */
#ifdef CONFIG_CBUS_TAHVO_USB_HOST_BY_DEFAULT
	tu->tahvo_mode = TAHVO_MODE_HOST;
#else
	tu->tahvo_mode = TAHVO_MODE_PERIPHERAL;
#endif
#endif

	INIT_WORK(&tu->irq_work, tahvo_usb_irq_work);
	mutex_init(&tu->serialize);

	/* Set initial state, so that we generate kevents only on
	 * state changes */
	tu->vbus_state = tahvo_read_reg(TAHVO_REG_IDSR) & 0x01;

	/* We cannot enable interrupt until omap_udc is initialized */
	ret = tahvo_request_irq(TAHVO_INT_VBUSON, tahvo_usb_vbus_interrupt,
				(unsigned long) tu, "vbus_interrupt");
	if (ret != 0) {
		kfree(tu);
		printk(KERN_ERR "Could not register Tahvo interrupt for VBUS\n");
		return ret;
	}

	/* Attributes */
	ret = device_create_file(dev, &dev_attr_vbus_state);
#ifdef CONFIG_USB_OTG
	ret |= device_create_file(dev, &dev_attr_otg_mode);
#endif
	if (ret)
		printk(KERN_ERR "attribute creation failed: %d\n", ret);

	/* Create OTG interface */
	tahvo_usb_power_off(tu);
	tu->otg.state = OTG_STATE_UNDEFINED;
	tu->otg.label = DRIVER_NAME;
	tu->otg.set_host = tahvo_usb_set_host;
	tu->otg.set_peripheral = tahvo_usb_set_peripheral;
	tu->otg.set_power = tahvo_usb_set_power;
	tu->otg.set_suspend = tahvo_usb_set_suspend;
	tu->otg.start_srp = tahvo_usb_start_srp;
	tu->otg.start_hnp = tahvo_usb_start_hnp;

	ret = otg_set_transceiver(&tu->otg);
	if (ret < 0) {
		printk(KERN_ERR "Cannot register USB transceiver\n");
		kfree(tu);
		tahvo_free_irq(TAHVO_INT_VBUSON);
		return ret;
	}

	dev->driver_data = tu;

	/* Act upon current vbus state once at startup. A vbus state irq may or
	 * may not be generated in addition to this. */
	schedule_work(&tu->irq_work);
	return 0;
}
示例#5
0
文件: tahvo-usb.c 项目: tmlind/linux
static int __init tahvo_usb_probe(struct platform_device *pdev)
{
	struct tahvo_usb *tu;
	struct device *dev = &pdev->dev;
	int ret;
	int irq;

	dev_dbg(dev, "probe\n");

	/* Create driver data */
	tu = kzalloc(sizeof(*tu), GFP_KERNEL);
	if (!tu)
		return -ENOMEM;
	tahvo_usb_device = tu;

	tu->dev = dev;
	tu->pt_dev = pdev;
#ifdef CONFIG_USB_OTG
	/* Default mode */
#ifdef CONFIG_CBUS_TAHVO_USB_HOST_BY_DEFAULT
	tu->tahvo_mode = TAHVO_MODE_HOST;
#else
	tu->tahvo_mode = TAHVO_MODE_PERIPHERAL;
#endif
#endif

	mutex_init(&tu->serialize);

	tu->ick = clk_get(NULL, "usb_l4_ick");
	if (IS_ERR(tu->ick)) {
		dev_err(dev, "Failed to get usb_l4_ick\n");
		ret = PTR_ERR(tu->ick);
		goto err_free_tu;
	}
	clk_enable(tu->ick);

	/* Set initial state, so that we generate kevents only on
	 * state changes */
	tu->vbus_state = tahvo_read_reg(tu->dev, TAHVO_REG_IDSR) & 0x01;

	irq = platform_get_irq(pdev, 0);
	tu->irq = irq;

	/* We cannot enable interrupt until omap_udc is initialized */
	ret = request_threaded_irq(irq, NULL, tahvo_usb_vbus_interrupt,
			IRQF_ONESHOT, "tahvo-vbus", tu);
	if (ret != 0) {
		printk(KERN_ERR "Could not register Tahvo interrupt for VBUS\n");
		goto err_release_clk;
	}

	/* Attributes */
	ret = device_create_file(dev, &dev_attr_vbus_state);
#ifdef CONFIG_USB_OTG
	ret |= device_create_file(dev, &dev_attr_otg_mode);
#endif
	if (ret)
		printk(KERN_ERR "attribute creation failed: %d\n", ret);

	/* Create OTG interface */
	tahvo_usb_power_off(tu);
	tu->otg.state = OTG_STATE_UNDEFINED;
	tu->otg.label = DRIVER_NAME;
	tu->otg.set_host = tahvo_usb_set_host;
	tu->otg.set_peripheral = tahvo_usb_set_peripheral;
	tu->otg.set_power = tahvo_usb_set_power;
	tu->otg.set_suspend = tahvo_usb_set_suspend;
	tu->otg.start_srp = tahvo_usb_start_srp;
	tu->otg.start_hnp = tahvo_usb_start_hnp;

	ret = otg_set_transceiver(&tu->otg);
	if (ret < 0) {
		printk(KERN_ERR "Cannot register USB transceiver\n");
		goto err_free_irq;
	}

	dev_set_drvdata(dev, tu);

	return 0;

err_free_irq:
	free_irq(tu->irq, tu);
err_release_clk:
	clk_disable(tu->ick);
	clk_put(tu->ick);
err_free_tu:
	kfree(tu);
	tahvo_usb_device = NULL;

	return ret;
}