usb: renesas_usbhs: support multi driver

Some SuperH/board has multi USBHS on it.
This patch supports multi register for renesas_usbhs

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index cc3ad63..ba79dbf 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -44,6 +44,7 @@
 struct usbhsg_gpriv {
 	struct usb_gadget	 gadget;
 	struct usbhs_mod	 mod;
+	struct list_head	 link;
 
 	struct usbhsg_uep	*uep;
 	int			 uep_size;
@@ -113,6 +114,16 @@
 #define usbhsg_status_clr(gp, b) (gp->status &= ~b)
 #define usbhsg_status_has(gp, b) (gp->status &   b)
 
+/* controller */
+LIST_HEAD(the_controller_link);
+
+#define usbhsg_for_each_controller(gpriv)\
+	list_for_each_entry(gpriv, &the_controller_link, link)
+#define usbhsg_controller_register(gpriv)\
+	list_add_tail(&(gpriv)->link, &the_controller_link)
+#define usbhsg_controller_unregister(gpriv)\
+	list_del_init(&(gpriv)->link)
+
 /*
  *		queue push/pop
  */
@@ -732,11 +743,10 @@
  *		linux usb function
  *
  */
-struct usbhsg_gpriv *the_controller;
 static int usbhsg_gadget_start(struct usb_gadget_driver *driver,
 			    int (*bind)(struct usb_gadget *))
 {
-	struct usbhsg_gpriv *gpriv = the_controller;
+	struct usbhsg_gpriv *gpriv;
 	struct usbhs_priv *priv;
 	struct device *dev;
 	int ret;
@@ -746,10 +756,17 @@
 	    !driver->setup	||
 	    driver->speed != USB_SPEED_HIGH)
 		return -EINVAL;
-	if (!gpriv)
-		return -ENODEV;
-	if (gpriv->driver)
-		return -EBUSY;
+
+	/*
+	 * find unused controller
+	 */
+	usbhsg_for_each_controller(gpriv) {
+		if (!gpriv->driver)
+			goto find_unused_controller;
+	}
+	return -ENODEV;
+
+find_unused_controller:
 
 	dev  = usbhsg_gpriv_to_dev(gpriv);
 	priv = usbhsg_gpriv_to_priv(gpriv);
@@ -786,18 +803,25 @@
 
 static int usbhsg_gadget_stop(struct usb_gadget_driver *driver)
 {
-	struct usbhsg_gpriv *gpriv = the_controller;
+	struct usbhsg_gpriv *gpriv;
 	struct usbhs_priv *priv;
-	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
-
-	if (!gpriv)
-		return -ENODEV;
+	struct device *dev;
 
 	if (!driver		||
-	    !driver->unbind	||
-	    driver != gpriv->driver)
+	    !driver->unbind)
 		return -EINVAL;
 
+	/*
+	 * find controller
+	 */
+	usbhsg_for_each_controller(gpriv) {
+		if (gpriv->driver == driver)
+			goto find_matching_controller;
+	}
+	return -ENODEV;
+
+find_matching_controller:
+
 	dev  = usbhsg_gpriv_to_dev(gpriv);
 	priv = usbhsg_gpriv_to_priv(gpriv);
 
@@ -919,7 +943,7 @@
 		}
 	}
 
-	the_controller = gpriv;
+	usbhsg_controller_register(gpriv);
 
 	ret = usb_add_gadget_udc(dev, &gpriv->gadget);
 	if (ret)
@@ -943,6 +967,9 @@
 	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
 
 	usb_del_gadget_udc(&gpriv->gadget);
+
+	usbhsg_controller_unregister(gpriv);
+
 	kfree(gpriv->uep);
 	kfree(gpriv);
 }