コード例 #1
0
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, __FUNCTION__);

	/* 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
}
コード例 #2
0
/* add or disable the host device+driver */
static int
isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
{
	struct isp1301	*isp = container_of(otg, struct isp1301, otg);

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

	if (!host) {
		omap_writew(0, OTG_IRQ_EN);
		power_down(isp);
		isp->otg.host = NULL;
		return 0;
	}

#ifdef	CONFIG_USB_OTG
	isp->otg.host = host;
	dev_dbg(&isp->client->dev, "registered host\n");
	host_suspend(isp);
	if (isp->otg.gadget)
		return isp1301_otg_enable(isp);
	return 0;

#elif	!defined(CONFIG_USB_GADGET_OMAP)
	// FIXME update its refcount
	isp->otg.host = host;

	power_up(isp);

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

	dev_info(&isp->client->dev, "A-Host sessions ok\n");
	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
		INTR_ID_GND);
	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
		INTR_ID_GND);

	/* If this has a Mini-AB connector, this mode is highly
	 * nonstandard ... but can be handy for testing, especially with
	 * the Mini-A end of an OTG cable.  (Or something nonstandard
	 * like MiniB-to-StandardB, maybe built with a gender mender.)
	 */
	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV);

	dump_regs(isp, __func__);

	return 0;

#else
	dev_dbg(&isp->client->dev, "host sessions not allowed\n");
	return -EINVAL;
#endif

}
コード例 #3
0
static int isp1301_otg_enable(struct isp1301 *isp)
{
	power_up(isp);
	otg_init(isp);

	/* NOTE:  since we don't change this, this provides
	 * a few more interrupts than are strictly needed.
	 */
	isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING,
		INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);
	isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
		INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND);

	dev_info(&isp->client->dev, "ready for dual-role USB ...\n");

	return 0;
}
コード例 #4
0
static void power_up(struct isp1301 *isp)
{
	// isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);

	/* do this only when cpu is driving transceiver,
	 * so host won't see a low speed device...
	 */
	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
}
コード例 #5
0
static void power_down(struct isp1301 *isp)
{
	isp->otg.state = OTG_STATE_UNDEFINED;

	// isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN);
	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND);

	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_ID_PULLDOWN);
	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0);
}
コード例 #6
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
}
コード例 #7
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
}
コード例 #8
0
static void isp_update_otg(struct isp1301 *isp, u8 stat)
{
	u8			isp_stat, isp_bstat;
	enum usb_otg_state	state = isp->otg.state;

	if (stat & INTR_BDIS_ACON)
		pr_debug("OTG:  BDIS_ACON, %s\n", state_name(isp));

	/* start certain state transitions right away */
	isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE);
	if (isp_stat & INTR_ID_GND) {
		if (isp->otg.default_a) {
			switch (state) {
			case OTG_STATE_B_IDLE:
				a_idle(isp, "idle");
				/* FALLTHROUGH */
			case OTG_STATE_A_IDLE:
				enable_vbus_source(isp);
				/* FALLTHROUGH */
			case OTG_STATE_A_WAIT_VRISE:
				/* we skip over OTG_STATE_A_WAIT_BCON, since
				 * the HC will transition to A_HOST (or
				 * A_SUSPEND!) without our noticing except
				 * when HNP is used.
				 */
				if (isp_stat & INTR_VBUS_VLD)
					isp->otg.state = OTG_STATE_A_HOST;
				break;
			case OTG_STATE_A_WAIT_VFALL:
				if (!(isp_stat & INTR_SESS_VLD))
					a_idle(isp, "vfell");
				break;
			default:
				if (!(isp_stat & INTR_VBUS_VLD))
					isp->otg.state = OTG_STATE_A_VBUS_ERR;
				break;
			}
			isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);
		} else {
			switch (state) {
			case OTG_STATE_B_PERIPHERAL:
			case OTG_STATE_B_HOST:
			case OTG_STATE_B_WAIT_ACON:
				usb_gadget_vbus_disconnect(isp->otg.gadget);
				break;
			default:
				break;
			}
			if (state != OTG_STATE_A_IDLE)
				a_idle(isp, "id");
			if (isp->otg.host && state == OTG_STATE_A_IDLE)
				isp1301_defer_work(isp, WORK_HOST_RESUME);
			isp_bstat = 0;
		}
	} else {
		u32 l;

		/* if user unplugged mini-A end of cable,
		 * don't bypass A_WAIT_VFALL.
		 */
		if (isp->otg.default_a) {
			switch (state) {
			default:
				isp->otg.state = OTG_STATE_A_WAIT_VFALL;
				break;
			case OTG_STATE_A_WAIT_VFALL:
				state = OTG_STATE_A_IDLE;
				/* khubd may take a while to notice and
				 * handle this disconnect, so don't go
				 * to B_IDLE quite yet.
				 */
				break;
			case OTG_STATE_A_IDLE:
				host_suspend(isp);
				isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1,
						MC1_BDIS_ACON_EN);
				isp->otg.state = OTG_STATE_B_IDLE;
				l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
				l &= ~OTG_CTRL_BITS;
				omap_writel(l, OTG_CTRL);
				break;
			case OTG_STATE_B_IDLE:
				break;
			}
		}
		isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS);

		switch (isp->otg.state) {
		case OTG_STATE_B_PERIPHERAL:
		case OTG_STATE_B_WAIT_ACON:
		case OTG_STATE_B_HOST:
			if (likely(isp_bstat & OTG_B_SESS_VLD))
				break;
			enable_vbus_draw(isp, 0);
#ifndef	CONFIG_USB_OTG
			/* UDC driver will clear OTG_BSESSVLD */
			isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
						OTG1_DP_PULLDOWN);
			isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
						OTG1_DP_PULLUP);
			dump_regs(isp, __func__);
#endif
			/* FALLTHROUGH */
		case OTG_STATE_B_SRP_INIT:
			b_idle(isp, __func__);
			l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS;
			omap_writel(l, OTG_CTRL);
			/* FALLTHROUGH */
		case OTG_STATE_B_IDLE:
			if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) {
#ifdef	CONFIG_USB_OTG
				update_otg1(isp, isp_stat);
				update_otg2(isp, isp_bstat);
#endif
				b_peripheral(isp);
			} else if (!(isp_stat & (INTR_VBUS_VLD|INTR_SESS_VLD)))
				isp_bstat |= OTG_B_SESS_END;
			break;
		case OTG_STATE_A_WAIT_VFALL:
			break;
		default:
			pr_debug("otg: unsupported b-device %s\n",
				state_name(isp));
			break;
		}
	}

	if (state != isp->otg.state)
		pr_debug("  isp, %s -> %s\n",
				state_string(state), state_name(isp));

#ifdef	CONFIG_USB_OTG
	/* update the OTG controller state to match the isp1301; may
	 * trigger OPRT_CHG irqs for changes going to the isp1301.
	 */
	update_otg1(isp, isp_stat);
	update_otg2(isp, isp_bstat);
	check_state(isp, __func__);
#endif

	dump_regs(isp, "isp1301->otg");
}
コード例 #9
0
/* inputs going to ISP1301 */
static void otg_update_isp(struct isp1301 *isp)
{
	u32	otg_ctrl, otg_change;
	u8	set = OTG1_DM_PULLDOWN, clr = OTG1_DM_PULLUP;

	otg_ctrl = omap_readl(OTG_CTRL);
	otg_change = otg_ctrl ^ isp->last_otg_ctrl;
	isp->last_otg_ctrl = otg_ctrl;
	otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS;

	switch (isp->otg.state) {
	case OTG_STATE_B_IDLE:
	case OTG_STATE_B_PERIPHERAL:
	case OTG_STATE_B_SRP_INIT:
		if (!(otg_ctrl & OTG_PULLUP)) {
			// if (otg_ctrl & OTG_B_HNPEN) {
			if (isp->otg.gadget->b_hnp_enable) {
				isp->otg.state = OTG_STATE_B_WAIT_ACON;
				pr_debug("  --> b_wait_acon\n");
			}
			goto pulldown;
		}
pullup:
		set |= OTG1_DP_PULLUP;
		clr |= OTG1_DP_PULLDOWN;
		break;
	case OTG_STATE_A_SUSPEND:
	case OTG_STATE_A_PERIPHERAL:
		if (otg_ctrl & OTG_PULLUP)
			goto pullup;
		/* FALLTHROUGH */
	// case OTG_STATE_B_WAIT_ACON:
	default:
pulldown:
		set |= OTG1_DP_PULLDOWN;
		clr |= OTG1_DP_PULLUP;
		break;
	}

#	define toggle(OTG,ISP) do { \
		if (otg_ctrl & OTG) set |= ISP; \
		else clr |= ISP; \
		} while (0)

	if (!(isp->otg.host))
		otg_ctrl &= ~OTG_DRV_VBUS;

	switch (isp->otg.state) {
	case OTG_STATE_A_SUSPEND:
		if (otg_ctrl & OTG_DRV_VBUS) {
			set |= OTG1_VBUS_DRV;
			break;
		}
		/* HNP failed for some reason (A_AIDL_BDIS timeout) */
		notresponding(isp);

		/* FALLTHROUGH */
	case OTG_STATE_A_VBUS_ERR:
		isp->otg.state = OTG_STATE_A_WAIT_VFALL;
		pr_debug("  --> a_wait_vfall\n");
		/* FALLTHROUGH */
	case OTG_STATE_A_WAIT_VFALL:
		/* FIXME usbcore thinks port power is still on ... */
		clr |= OTG1_VBUS_DRV;
		break;
	case OTG_STATE_A_IDLE:
		if (otg_ctrl & OTG_DRV_VBUS) {
			isp->otg.state = OTG_STATE_A_WAIT_VRISE;
			pr_debug("  --> a_wait_vrise\n");
		}
		/* FALLTHROUGH */
	default:
		toggle(OTG_DRV_VBUS, OTG1_VBUS_DRV);
	}

	toggle(OTG_PU_VBUS, OTG1_VBUS_CHRG);
	toggle(OTG_PD_VBUS, OTG1_VBUS_DISCHRG);

#	undef toggle

	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, set);
	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, clr);

	/* HNP switch to host or peripheral; and SRP */
	if (otg_change & OTG_PULLUP) {
		u32 l;

		switch (isp->otg.state) {
		case OTG_STATE_B_IDLE:
			if (clr & OTG1_DP_PULLUP)
				break;
			isp->otg.state = OTG_STATE_B_PERIPHERAL;
			pr_debug("  --> b_peripheral\n");
			break;
		case OTG_STATE_A_SUSPEND:
			if (clr & OTG1_DP_PULLUP)
				break;
			isp->otg.state = OTG_STATE_A_PERIPHERAL;
			pr_debug("  --> a_peripheral\n");
			break;
		default:
			break;
		}
		l = omap_readl(OTG_CTRL);
		l |= OTG_PULLUP;
		omap_writel(l, OTG_CTRL);
	}

	check_state(isp, __func__);
	dump_regs(isp, "otg->isp1301");
}
コード例 #10
0
static int __init
isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
	int			status;
	struct isp1301		*isp;

	if (the_transceiver)
		return 0;

	isp = kzalloc(sizeof *isp, GFP_KERNEL);
	if (!isp)
		return 0;

	INIT_WORK(&isp->work, isp1301_work);
	init_timer(&isp->timer);
	isp->timer.function = isp1301_timer;
	isp->timer.data = (unsigned long) isp;

	i2c_set_clientdata(i2c, isp);
	isp->client = i2c;

	/* verify the chip (shouldn't be necesary) */
	status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
	if (status != I2C_VENDOR_ID_PHILIPS) {
		dev_dbg(&i2c->dev, "not philips id: %d\n", status);
		goto fail;
	}
	status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
	if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
		dev_dbg(&i2c->dev, "not isp1301, %d\n", status);
		goto fail;
	}
	isp->i2c_release = i2c->dev.release;
	i2c->dev.release = isp1301_release;

	/* initial development used chiprev 2.00 */
	status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE);
	dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n",
		status >> 8, status & 0xff);

	/* make like power-on reset */
	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK);

	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI);
	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI);

	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
				OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
				~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));

	isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0);
	isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
	isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);

#ifdef	CONFIG_USB_OTG
	status = otg_bind(isp);
	if (status < 0) {
		dev_dbg(&i2c->dev, "can't bind OTG\n");
		goto fail;
	}
#endif

	if (machine_is_omap_h2()) {
		/* full speed signaling by default */
		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
			MC1_SPEED);
		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
			MC2_SPD_SUSP_CTRL);

		/* IRQ wired at M14 */
		omap_cfg_reg(M14_1510_GPIO2);
		if (gpio_request(2, "isp1301") == 0)
			gpio_direction_input(2);
		isp->irq_type = IRQF_TRIGGER_FALLING;
	}

	isp->irq_type |= IRQF_SAMPLE_RANDOM;
	status = request_irq(i2c->irq, isp1301_irq,
			isp->irq_type, DRIVER_NAME, isp);
	if (status < 0) {
		dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
				i2c->irq, status);
		goto fail;
	}

	isp->otg.dev = &i2c->dev;
	isp->otg.label = DRIVER_NAME;

	isp->otg.set_host = isp1301_set_host,
	isp->otg.set_peripheral = isp1301_set_peripheral,
	isp->otg.set_power = isp1301_set_power,
	isp->otg.start_srp = isp1301_start_srp,
	isp->otg.start_hnp = isp1301_start_hnp,

	enable_vbus_draw(isp, 0);
	power_down(isp);
	the_transceiver = isp;

#ifdef	CONFIG_USB_OTG
	update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
#endif

	dump_regs(isp, __func__);

#ifdef	VERBOSE
	mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
	dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
#endif

	status = otg_set_transceiver(&isp->otg);
	if (status < 0)
		dev_err(&i2c->dev, "can't register transceiver, %d\n",
			status);

	return 0;

fail:
	kfree(isp);
	return -ENODEV;
}
コード例 #11
0
/* no error returns, they'd just make bus scanning stop */
static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
{
	int			status;
	struct isp1301		*isp;
	struct i2c_client	*i2c;

	if (the_transceiver)
		return 0;

	isp = kzalloc(sizeof *isp, GFP_KERNEL);
	if (!isp)
		return 0;

	INIT_WORK(&isp->work, isp1301_work, isp);
	init_timer(&isp->timer);
	isp->timer.function = isp1301_timer;
	isp->timer.data = (unsigned long) isp;

	isp->irq = -1;
	isp->client.addr = address;
	i2c_set_clientdata(&isp->client, isp);
	isp->client.adapter = bus;
	isp->client.driver = &isp1301_driver;
	strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE);
	i2c = &isp->client;

	/* if this is a true probe, verify the chip ... */
	if (kind < 0) {
		status = isp1301_get_u16(isp, ISP1301_VENDOR_ID);
		if (status != I2C_VENDOR_ID_PHILIPS) {
			dev_dbg(&bus->dev, "addr %d not philips id: %d\n",
				address, status);
			goto fail1;
		}
		status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID);
		if (status != I2C_PRODUCT_ID_PHILIPS_1301) {
			dev_dbg(&bus->dev, "%d not isp1301, %d\n",
				address, status);
			goto fail1;
		}
	}

	status = i2c_attach_client(i2c);
	if (status < 0) {
		dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
				DRIVER_NAME, address, status);
fail1:
		kfree(isp);
		return 0;
	}
	isp->i2c_release = i2c->dev.release;
	i2c->dev.release = isp1301_release;

	/* initial development used chiprev 2.00 */
	status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE);
	dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n",
		status >> 8, status & 0xff);

	/* make like power-on reset */
	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK);

	isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI);
	isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI);

	isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1,
				OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN);
	isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
				~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN));

	isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0);
	isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0);
	isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0);

#ifdef	CONFIG_USB_OTG
	status = otg_bind(isp);
	if (status < 0) {
		dev_dbg(&i2c->dev, "can't bind OTG\n");
		goto fail2;
	}
#endif

	if (machine_is_omap_h2()) {
		/* full speed signaling by default */
		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1,
			MC1_SPEED_REG);
		isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2,
			MC2_SPD_SUSP_CTRL);

		/* IRQ wired at M14 */
		omap_cfg_reg(M14_1510_GPIO2);
		isp->irq = OMAP_GPIO_IRQ(2);
		omap_request_gpio(2);
		omap_set_gpio_direction(2, 1);
		omap_set_gpio_edge_ctrl(2, OMAP_GPIO_FALLING_EDGE);
	}

	status = request_irq(isp->irq, isp1301_irq,
			IRQF_SAMPLE_RANDOM, DRIVER_NAME, isp);
	if (status < 0) {
		dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n",
				isp->irq, status);
#ifdef	CONFIG_USB_OTG
fail2:
#endif
		i2c_detach_client(i2c);
		goto fail1;
	}

	isp->otg.dev = &isp->client.dev;
	isp->otg.label = DRIVER_NAME;

	isp->otg.set_host = isp1301_set_host,
	isp->otg.set_peripheral = isp1301_set_peripheral,
	isp->otg.set_power = isp1301_set_power,
	isp->otg.start_srp = isp1301_start_srp,
	isp->otg.start_hnp = isp1301_start_hnp,

	enable_vbus_draw(isp, 0);
	power_down(isp);
	the_transceiver = isp;

#ifdef	CONFIG_USB_OTG
	update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
	update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
#endif

	dump_regs(isp, __FUNCTION__);

#ifdef	VERBOSE
	mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);
	dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
#endif

	status = otg_set_transceiver(&isp->otg);
	if (status < 0)
		dev_err(&i2c->dev, "can't register transceiver, %d\n",
			status);

	return 0;
}
コード例 #12
0
static int
isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
{
	struct isp1301	*isp = container_of(otg->phy, struct isp1301, phy);

	if (isp != the_transceiver)
		return -ENODEV;

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

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

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

	{
		u32 l;

		l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK;
		l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS);
		l |= OTG_ID;
		omap_writel(l, OTG_CTRL);
	}

	power_up(isp);
	isp->phy.otg->state = OTG_STATE_B_IDLE;

	if (machine_is_omap_h2() || machine_is_omap_h3())
		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
}