mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-02 18:46:41 +07:00
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>
This commit is contained in:
parent
4ef85e0f69
commit
3b87218829
@ -44,6 +44,7 @@ struct usbhsg_uep {
|
|||||||
struct usbhsg_gpriv {
|
struct usbhsg_gpriv {
|
||||||
struct usb_gadget gadget;
|
struct usb_gadget gadget;
|
||||||
struct usbhs_mod mod;
|
struct usbhs_mod mod;
|
||||||
|
struct list_head link;
|
||||||
|
|
||||||
struct usbhsg_uep *uep;
|
struct usbhsg_uep *uep;
|
||||||
int uep_size;
|
int uep_size;
|
||||||
@ -113,6 +114,16 @@ struct usbhsg_recip_handle {
|
|||||||
#define usbhsg_status_clr(gp, b) (gp->status &= ~b)
|
#define usbhsg_status_clr(gp, b) (gp->status &= ~b)
|
||||||
#define usbhsg_status_has(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
|
* queue push/pop
|
||||||
*/
|
*/
|
||||||
@ -732,11 +743,10 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
|
|||||||
* linux usb function
|
* linux usb function
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct usbhsg_gpriv *the_controller;
|
|
||||||
static int usbhsg_gadget_start(struct usb_gadget_driver *driver,
|
static int usbhsg_gadget_start(struct usb_gadget_driver *driver,
|
||||||
int (*bind)(struct usb_gadget *))
|
int (*bind)(struct usb_gadget *))
|
||||||
{
|
{
|
||||||
struct usbhsg_gpriv *gpriv = the_controller;
|
struct usbhsg_gpriv *gpriv;
|
||||||
struct usbhs_priv *priv;
|
struct usbhs_priv *priv;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
int ret;
|
int ret;
|
||||||
@ -746,10 +756,17 @@ static int usbhsg_gadget_start(struct usb_gadget_driver *driver,
|
|||||||
!driver->setup ||
|
!driver->setup ||
|
||||||
driver->speed != USB_SPEED_HIGH)
|
driver->speed != USB_SPEED_HIGH)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!gpriv)
|
|
||||||
return -ENODEV;
|
/*
|
||||||
if (gpriv->driver)
|
* find unused controller
|
||||||
return -EBUSY;
|
*/
|
||||||
|
usbhsg_for_each_controller(gpriv) {
|
||||||
|
if (!gpriv->driver)
|
||||||
|
goto find_unused_controller;
|
||||||
|
}
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
find_unused_controller:
|
||||||
|
|
||||||
dev = usbhsg_gpriv_to_dev(gpriv);
|
dev = usbhsg_gpriv_to_dev(gpriv);
|
||||||
priv = usbhsg_gpriv_to_priv(gpriv);
|
priv = usbhsg_gpriv_to_priv(gpriv);
|
||||||
@ -786,18 +803,25 @@ static int usbhsg_gadget_start(struct usb_gadget_driver *driver,
|
|||||||
|
|
||||||
static int usbhsg_gadget_stop(struct usb_gadget_driver *driver)
|
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 usbhs_priv *priv;
|
||||||
struct device *dev = usbhsg_gpriv_to_dev(gpriv);
|
struct device *dev;
|
||||||
|
|
||||||
if (!gpriv)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (!driver ||
|
if (!driver ||
|
||||||
!driver->unbind ||
|
!driver->unbind)
|
||||||
driver != gpriv->driver)
|
|
||||||
return -EINVAL;
|
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);
|
dev = usbhsg_gpriv_to_dev(gpriv);
|
||||||
priv = usbhsg_gpriv_to_priv(gpriv);
|
priv = usbhsg_gpriv_to_priv(gpriv);
|
||||||
|
|
||||||
@ -919,7 +943,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
the_controller = gpriv;
|
usbhsg_controller_register(gpriv);
|
||||||
|
|
||||||
ret = usb_add_gadget_udc(dev, &gpriv->gadget);
|
ret = usb_add_gadget_udc(dev, &gpriv->gadget);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -943,6 +967,9 @@ void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv)
|
|||||||
struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
|
struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
|
||||||
|
|
||||||
usb_del_gadget_udc(&gpriv->gadget);
|
usb_del_gadget_udc(&gpriv->gadget);
|
||||||
|
|
||||||
|
usbhsg_controller_unregister(gpriv);
|
||||||
|
|
||||||
kfree(gpriv->uep);
|
kfree(gpriv->uep);
|
||||||
kfree(gpriv);
|
kfree(gpriv);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user