Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e71eb392 authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Greg Kroah-Hartman
Browse files

usb: musb: convert musb to new style bind



udc-core checks for valid callbacks so there is no need for the driver
to do so. Also "can-be-bound-once" is verified by udc-core. The pull-up
callback is called by udc-core afterwords.

[ balbi@ti.com : keep holding gadget_driver pointer for now
		 remove the stupid check for gadget_driver otherwise
		  we don't handle IRQs ]

Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 352c2dc8
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
@@ -899,7 +899,6 @@ void musb_start(struct musb *musb)

	/* put into basic highspeed mode and start session */
	musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
						| MUSB_POWER_SOFTCONN
						| MUSB_POWER_HSENAB
						/* ENSUSPEND wedges tusb */
						/* | MUSB_POWER_ENSUSPEND */
@@ -1526,12 +1525,6 @@ irqreturn_t musb_interrupt(struct musb *musb)
		(devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
		musb->int_usb, musb->int_tx, musb->int_rx);

	if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
		if (!musb->gadget_driver) {
			dev_dbg(musb->controller, "No gadget driver loaded\n");
			return IRQ_HANDLED;
		}

	/* the core can interrupt us for multiple reasons; docs have
	 * a generic interrupt flowchart to follow
	 */
+17 −74
Original line number Diff line number Diff line
@@ -1657,8 +1657,8 @@ static void musb_pullup(struct musb *musb, int is_on)

	/* FIXME if on, HdrcStart; if off, HdrcStop */

	dev_dbg(musb->controller, "gadget %s D+ pullup %s\n",
		musb->gadget_driver->function, is_on ? "on" : "off");
	dev_dbg(musb->controller, "gadget D+ pullup %s\n",
		is_on ? "on" : "off");
	musb_writeb(musb->mregs, MUSB_POWER, power);
}

@@ -1704,9 +1704,10 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
	return 0;
}

static int musb_gadget_start(struct usb_gadget_driver *driver,
		int (*bind)(struct usb_gadget *));
static int musb_gadget_stop(struct usb_gadget_driver *driver);
static int musb_gadget_start(struct usb_gadget *g,
		struct usb_gadget_driver *driver);
static int musb_gadget_stop(struct usb_gadget *g,
		struct usb_gadget_driver *driver);

static const struct usb_gadget_ops musb_gadget_operations = {
	.get_frame		= musb_gadget_get_frame,
@@ -1715,8 +1716,8 @@ static const struct usb_gadget_ops musb_gadget_operations = {
	/* .vbus_session		= musb_gadget_vbus_session, */
	.vbus_draw		= musb_gadget_vbus_draw,
	.pullup			= musb_gadget_pullup,
	.start			= musb_gadget_start,
	.stop			= musb_gadget_stop,
	.udc_start		= musb_gadget_start,
	.udc_stop		= musb_gadget_stop,
};

/* ----------------------------------------------------------------------- */
@@ -1727,7 +1728,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
 * about there being only one external upstream port.  It assumes
 * all peripheral ports are external...
 */
static struct musb *the_gadget;

static void musb_gadget_release(struct device *dev)
{
@@ -1814,9 +1814,6 @@ int __init musb_gadget_setup(struct musb *musb)
	 * musb peripherals at the same time, only the bus lock
	 * is probably held.
	 */
	if (the_gadget)
		return -EBUSY;
	the_gadget = musb;

	musb->g.ops = &musb_gadget_operations;
	musb->g.is_dualspeed = 1;
@@ -1840,7 +1837,6 @@ int __init musb_gadget_setup(struct musb *musb)
	status = device_register(&musb->g.dev);
	if (status != 0) {
		put_device(&musb->g.dev);
		the_gadget = NULL;
		return status;
	}
	status = usb_add_gadget_udc(musb->controller, &musb->g);
@@ -1850,18 +1846,13 @@ int __init musb_gadget_setup(struct musb *musb)
	return 0;
err:
	device_unregister(&musb->g.dev);
	the_gadget = NULL;
	return status;
}

void musb_gadget_cleanup(struct musb *musb)
{
	if (musb != the_gadget)
		return;

	usb_del_gadget_udc(&musb->g);
	device_unregister(&musb->g.dev);
	the_gadget = NULL;
}

/*
@@ -1873,59 +1864,30 @@ void musb_gadget_cleanup(struct musb *musb)
 * -ENOMEM no memory to perform the operation
 *
 * @param driver the gadget driver
 * @param bind the driver's bind function
 * @return <0 if error, 0 if everything is fine
 */
static int musb_gadget_start(struct usb_gadget_driver *driver,
		int (*bind)(struct usb_gadget *))
static int musb_gadget_start(struct usb_gadget *g,
		struct usb_gadget_driver *driver)
{
	struct musb		*musb = the_gadget;
	struct musb		*musb = gadget_to_musb(g);
	unsigned long		flags;
	int			retval = -EINVAL;

	if (!driver
			|| driver->speed != USB_SPEED_HIGH
			|| !bind || !driver->setup)
	if (driver->speed != USB_SPEED_HIGH)
		goto err0;

	/* driver must be initialized to support peripheral mode */
	if (!musb) {
		dev_dbg(musb->controller, "no dev??\n");
		retval = -ENODEV;
		goto err0;
	}

	pm_runtime_get_sync(musb->controller);

	dev_dbg(musb->controller, "registering driver %s\n", driver->function);

	if (musb->gadget_driver) {
		dev_dbg(musb->controller, "%s is already bound to %s\n",
				musb_driver_name,
				musb->gadget_driver->driver.name);
		retval = -EBUSY;
		goto err0;
	}

	spin_lock_irqsave(&musb->lock, flags);
	musb->softconnect = 0;
	musb->gadget_driver = driver;
	musb->g.dev.driver = &driver->driver;
	driver->driver.bus = NULL;
	musb->softconnect = 1;
	spin_unlock_irqrestore(&musb->lock, flags);

	retval = bind(&musb->g);
	if (retval) {
		dev_dbg(musb->controller, "bind to driver %s failed --> %d\n",
				driver->driver.name, retval);
		goto err1;
	}

	spin_lock_irqsave(&musb->lock, flags);
	musb->is_active = 1;

	otg_set_peripheral(musb->xceiv, &musb->g);
	musb->xceiv->state = OTG_STATE_B_IDLE;
	musb->is_active = 1;

	/*
	 * FIXME this ignores the softconnect flag.  Drivers are
@@ -1937,8 +1899,6 @@ static int musb_gadget_start(struct usb_gadget_driver *driver,
	if (!is_otg_enabled(musb))
		musb_start(musb);

	otg_set_peripheral(musb->xceiv, &musb->g);

	spin_unlock_irqrestore(&musb->lock, flags);

	if (is_otg_enabled(musb)) {
@@ -1970,11 +1930,6 @@ static int musb_gadget_start(struct usb_gadget_driver *driver,
err2:
	if (!is_otg_enabled(musb))
		musb_stop(musb);

err1:
	musb->gadget_driver = NULL;
	musb->g.dev.driver = NULL;

err0:
	return retval;
}
@@ -2027,17 +1982,12 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
 *
 * @param driver the gadget driver to unregister
 */
static int musb_gadget_stop(struct usb_gadget_driver *driver)
static int musb_gadget_stop(struct usb_gadget *g,
		struct usb_gadget_driver *driver)
{
	struct musb	*musb = the_gadget;
	struct musb	*musb = gadget_to_musb(g);
	unsigned long	flags;

	if (!driver || !driver->unbind || !musb)
		return -EINVAL;

	if (!musb->gadget_driver)
		return -EINVAL;

	if (musb->xceiv->last_event == USB_EVENT_NONE)
		pm_runtime_get_sync(musb->controller);

@@ -2058,13 +2008,6 @@ static int musb_gadget_stop(struct usb_gadget_driver *driver)

	dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);

	spin_unlock_irqrestore(&musb->lock, flags);
	driver->unbind(&musb->g);
	spin_lock_irqsave(&musb->lock, flags);

	musb->gadget_driver = NULL;
	musb->g.dev.driver = NULL;

	musb->is_active = 0;
	musb_platform_try_idle(musb, 0);
	spin_unlock_irqrestore(&musb->lock, flags);