diff options
| author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2011-07-03 20:42:35 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-07-08 18:08:19 -0400 |
| commit | 3b87218829a4182850cc62f8c0c28abcecfdf8e6 (patch) | |
| tree | 3f498555db80b40f9982b036dd9fbfc71b97e51d | |
| parent | 4ef85e0f697051829179c4fdeda1bd3f4166dc17 (diff) | |
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>
| -rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index cc3ad634d4f7..ba79dbf5adbc 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
| @@ -44,6 +44,7 @@ struct usbhsg_uep { | |||
| 44 | struct usbhsg_gpriv { | 44 | struct usbhsg_gpriv { |
| 45 | struct usb_gadget gadget; | 45 | struct usb_gadget gadget; |
| 46 | struct usbhs_mod mod; | 46 | struct usbhs_mod mod; |
| 47 | struct list_head link; | ||
| 47 | 48 | ||
| 48 | struct usbhsg_uep *uep; | 49 | struct usbhsg_uep *uep; |
| 49 | int uep_size; | 50 | int uep_size; |
| @@ -113,6 +114,16 @@ struct usbhsg_recip_handle { | |||
| 113 | #define usbhsg_status_clr(gp, b) (gp->status &= ~b) | 114 | #define usbhsg_status_clr(gp, b) (gp->status &= ~b) |
| 114 | #define usbhsg_status_has(gp, b) (gp->status & b) | 115 | #define usbhsg_status_has(gp, b) (gp->status & b) |
| 115 | 116 | ||
| 117 | /* controller */ | ||
| 118 | LIST_HEAD(the_controller_link); | ||
| 119 | |||
| 120 | #define usbhsg_for_each_controller(gpriv)\ | ||
| 121 | list_for_each_entry(gpriv, &the_controller_link, link) | ||
| 122 | #define usbhsg_controller_register(gpriv)\ | ||
| 123 | list_add_tail(&(gpriv)->link, &the_controller_link) | ||
| 124 | #define usbhsg_controller_unregister(gpriv)\ | ||
| 125 | list_del_init(&(gpriv)->link) | ||
| 126 | |||
| 116 | /* | 127 | /* |
| 117 | * queue push/pop | 128 | * queue push/pop |
| 118 | */ | 129 | */ |
| @@ -732,11 +743,10 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
| 732 | * linux usb function | 743 | * linux usb function |
| 733 | * | 744 | * |
| 734 | */ | 745 | */ |
| 735 | struct usbhsg_gpriv *the_controller; | ||
| 736 | static int usbhsg_gadget_start(struct usb_gadget_driver *driver, | 746 | static int usbhsg_gadget_start(struct usb_gadget_driver *driver, |
| 737 | int (*bind)(struct usb_gadget *)) | 747 | int (*bind)(struct usb_gadget *)) |
| 738 | { | 748 | { |
| 739 | struct usbhsg_gpriv *gpriv = the_controller; | 749 | struct usbhsg_gpriv *gpriv; |
| 740 | struct usbhs_priv *priv; | 750 | struct usbhs_priv *priv; |
| 741 | struct device *dev; | 751 | struct device *dev; |
| 742 | int ret; | 752 | int ret; |
| @@ -746,10 +756,17 @@ static int usbhsg_gadget_start(struct usb_gadget_driver *driver, | |||
| 746 | !driver->setup || | 756 | !driver->setup || |
| 747 | driver->speed != USB_SPEED_HIGH) | 757 | driver->speed != USB_SPEED_HIGH) |
| 748 | return -EINVAL; | 758 | return -EINVAL; |
| 749 | if (!gpriv) | 759 | |
| 750 | return -ENODEV; | 760 | /* |
| 751 | if (gpriv->driver) | 761 | * find unused controller |
| 752 | return -EBUSY; | 762 | */ |
| 763 | usbhsg_for_each_controller(gpriv) { | ||
| 764 | if (!gpriv->driver) | ||
| 765 | goto find_unused_controller; | ||
| 766 | } | ||
| 767 | return -ENODEV; | ||
| 768 | |||
| 769 | find_unused_controller: | ||
| 753 | 770 | ||
| 754 | dev = usbhsg_gpriv_to_dev(gpriv); | 771 | dev = usbhsg_gpriv_to_dev(gpriv); |
| 755 | priv = usbhsg_gpriv_to_priv(gpriv); | 772 | priv = usbhsg_gpriv_to_priv(gpriv); |
| @@ -786,18 +803,25 @@ add_fail: | |||
| 786 | 803 | ||
| 787 | static int usbhsg_gadget_stop(struct usb_gadget_driver *driver) | 804 | static int usbhsg_gadget_stop(struct usb_gadget_driver *driver) |
| 788 | { | 805 | { |
| 789 | struct usbhsg_gpriv *gpriv = the_controller; | 806 | struct usbhsg_gpriv *gpriv; |
| 790 | struct usbhs_priv *priv; | 807 | struct usbhs_priv *priv; |
| 791 | struct device *dev = usbhsg_gpriv_to_dev(gpriv); | 808 | struct device *dev; |
| 792 | |||
| 793 | if (!gpriv) | ||
| 794 | return -ENODEV; | ||
| 795 | 809 | ||
| 796 | if (!driver || | 810 | if (!driver || |
| 797 | !driver->unbind || | 811 | !driver->unbind) |
| 798 | driver != gpriv->driver) | ||
| 799 | return -EINVAL; | 812 | return -EINVAL; |
| 800 | 813 | ||
| 814 | /* | ||
| 815 | * find controller | ||
| 816 | */ | ||
| 817 | usbhsg_for_each_controller(gpriv) { | ||
| 818 | if (gpriv->driver == driver) | ||
| 819 | goto find_matching_controller; | ||
| 820 | } | ||
| 821 | return -ENODEV; | ||
| 822 | |||
| 823 | find_matching_controller: | ||
| 824 | |||
| 801 | dev = usbhsg_gpriv_to_dev(gpriv); | 825 | dev = usbhsg_gpriv_to_dev(gpriv); |
| 802 | priv = usbhsg_gpriv_to_priv(gpriv); | 826 | priv = usbhsg_gpriv_to_priv(gpriv); |
| 803 | 827 | ||
| @@ -919,7 +943,7 @@ int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
| 919 | } | 943 | } |
| 920 | } | 944 | } |
| 921 | 945 | ||
| 922 | the_controller = gpriv; | 946 | usbhsg_controller_register(gpriv); |
| 923 | 947 | ||
| 924 | ret = usb_add_gadget_udc(dev, &gpriv->gadget); | 948 | ret = usb_add_gadget_udc(dev, &gpriv->gadget); |
| 925 | if (ret) | 949 | if (ret) |
| @@ -943,6 +967,9 @@ void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) | |||
| 943 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | 967 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); |
| 944 | 968 | ||
| 945 | usb_del_gadget_udc(&gpriv->gadget); | 969 | usb_del_gadget_udc(&gpriv->gadget); |
| 970 | |||
| 971 | usbhsg_controller_unregister(gpriv); | ||
| 972 | |||
| 946 | kfree(gpriv->uep); | 973 | kfree(gpriv->uep); |
| 947 | kfree(gpriv); | 974 | kfree(gpriv); |
| 948 | } | 975 | } |
