Commit 5f6901eb3c38a3c8e8896830270a05a5904ace3a
Committed by
Sekhar Nori
1 parent
ee89bcd3f1
Exists in
ti-linux-3.14.y
and in
2 other branches
usb: dwc3: gadget: Adapt gadget to drd library
Adapt the dwc3 gadget to use drd library functions. In preparation to support DRD on dwc3. Signed-off-by: George Cherian <george.cherian@ti.com> [nsekhar@ti.com: fix sparse warnings] Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Showing 1 changed file with 101 additions and 28 deletions Side-by-side Diff
drivers/usb/dwc3/gadget.c
... | ... | @@ -29,6 +29,7 @@ |
29 | 29 | |
30 | 30 | #include <linux/usb/ch9.h> |
31 | 31 | #include <linux/usb/gadget.h> |
32 | +#include <linux/usb/drd.h> | |
32 | 33 | |
33 | 34 | #include "core.h" |
34 | 35 | #include "gadget.h" |
... | ... | @@ -2754,6 +2755,89 @@ |
2754 | 2755 | return ret; |
2755 | 2756 | } |
2756 | 2757 | |
2758 | +static void dwc3_gadget_release(struct device *dev) | |
2759 | +{ | |
2760 | + struct usb_gadget *gadget = container_of(dev, struct usb_gadget, dev); | |
2761 | + struct dwc3_gadget *dwc_gadget = gadget_to_dwc_gadget(gadget); | |
2762 | + struct dwc3 *dwc = dwc_gadget->dwc; | |
2763 | + | |
2764 | + dev_dbg(dev, "releasing '%s'\n", dev_name(dev)); | |
2765 | + dwc3_gadget_free_endpoints(dwc); | |
2766 | + dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE, | |
2767 | + dwc->ep0_bounce, dwc->ep0_bounce_addr); | |
2768 | + kfree(dwc->setup_buf); | |
2769 | + dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), | |
2770 | + dwc->ep0_trb, dwc->ep0_trb_addr); | |
2771 | + dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), | |
2772 | + dwc->ctrl_req, dwc->ctrl_req_addr); | |
2773 | + usb_drd_unregister_udc(dwc->dev); | |
2774 | + kfree(dwc_gadget); | |
2775 | +} | |
2776 | + | |
2777 | +static int dwc3_gadget_setup(void *data) | |
2778 | +{ | |
2779 | + struct dwc3 *dwc = data; | |
2780 | + struct dwc3_gadget *dwc_gadget; | |
2781 | + struct usb_drd_gadget *drd_gadget; | |
2782 | + struct usb_drd_setup *gadget_setup; | |
2783 | + int ret; | |
2784 | + | |
2785 | + drd_gadget = kzalloc(sizeof(*drd_gadget), GFP_KERNEL); | |
2786 | + if (!drd_gadget) { | |
2787 | + ret = -ENOMEM; | |
2788 | + goto err1; | |
2789 | + } | |
2790 | + | |
2791 | + gadget_setup = kzalloc(sizeof(*gadget_setup), GFP_KERNEL); | |
2792 | + if (!gadget_setup) { | |
2793 | + ret = -ENOMEM; | |
2794 | + goto err2; | |
2795 | + } | |
2796 | + | |
2797 | + dwc_gadget = kzalloc(sizeof(*dwc_gadget), GFP_KERNEL); | |
2798 | + if (!dwc_gadget) { | |
2799 | + ret = -ENOMEM; | |
2800 | + goto err3; | |
2801 | + } | |
2802 | + | |
2803 | + drd_gadget->g_driver = dwc->gadget_driver; | |
2804 | + | |
2805 | + /* | |
2806 | + * Pass the DWC3 specific routines for | |
2807 | + * switching roles to the drd library | |
2808 | + */ | |
2809 | + gadget_setup->ll_start = NULL; | |
2810 | + gadget_setup->ll_stop = NULL; | |
2811 | + gadget_setup->ll_release = dwc3_gadget_release; | |
2812 | + gadget_setup->data = (void *)dwc; | |
2813 | + drd_gadget->gadget_setup = gadget_setup; | |
2814 | + | |
2815 | + dwc_gadget->gadget.ops = &dwc3_gadget_ops; | |
2816 | + dwc_gadget->gadget.max_speed = USB_SPEED_SUPER; | |
2817 | + dwc_gadget->gadget.speed = USB_SPEED_UNKNOWN; | |
2818 | + dwc_gadget->gadget.sg_supported = true; | |
2819 | + dwc_gadget->gadget.name = "dwc3-gadget"; | |
2820 | + dwc_gadget->dwc = dwc; | |
2821 | + drd_gadget->gadget = &dwc_gadget->gadget; | |
2822 | + | |
2823 | + /* | |
2824 | + * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize | |
2825 | + * on ep out. | |
2826 | + */ | |
2827 | + dwc_gadget->gadget.quirk_ep_out_aligned_size = true; | |
2828 | + dwc->dwc_gadget = dwc_gadget; | |
2829 | + usb_drd_register_udc(dwc->dev, drd_gadget); | |
2830 | + | |
2831 | + return 0; | |
2832 | + | |
2833 | +err3: | |
2834 | + kfree(gadget_setup); | |
2835 | +err2: | |
2836 | + kfree(drd_gadget); | |
2837 | +err1: | |
2838 | + return ret; | |
2839 | +} | |
2840 | + | |
2757 | 2841 | /** |
2758 | 2842 | * dwc3_gadget_init - Initializes gadget related registers |
2759 | 2843 | * @dwc: pointer to our controller context structure |
... | ... | @@ -2763,7 +2847,6 @@ |
2763 | 2847 | int dwc3_gadget_init(struct dwc3 *dwc) |
2764 | 2848 | { |
2765 | 2849 | int ret; |
2766 | - struct dwc3_gadget *dwc_gadget; | |
2767 | 2850 | |
2768 | 2851 | dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), |
2769 | 2852 | &dwc->ctrl_req_addr, GFP_KERNEL); |
2770 | 2853 | |
2771 | 2854 | |
2772 | 2855 | |
... | ... | @@ -2797,26 +2880,11 @@ |
2797 | 2880 | goto err3; |
2798 | 2881 | } |
2799 | 2882 | |
2800 | - dwc_gadget = kzalloc(sizeof(*dwc_gadget), GFP_KERNEL); | |
2801 | - if (!dwc_gadget) { | |
2802 | - ret = -ENOMEM; | |
2883 | + ret = dwc3_gadget_setup(dwc); | |
2884 | + if (ret) | |
2803 | 2885 | goto err3; |
2804 | - } | |
2805 | 2886 | |
2806 | - dwc_gadget->gadget.ops = &dwc3_gadget_ops; | |
2807 | - dwc_gadget->gadget.max_speed = USB_SPEED_SUPER; | |
2808 | - dwc_gadget->gadget.speed = USB_SPEED_UNKNOWN; | |
2809 | - dwc_gadget->gadget.sg_supported = true; | |
2810 | - dwc_gadget->gadget.name = "dwc3-gadget"; | |
2811 | - dwc_gadget->dwc = dwc; | |
2812 | - | |
2813 | 2887 | /* |
2814 | - * Per databook, DWC3 needs buffer size to be aligned to MaxPacketSize | |
2815 | - * on ep out. | |
2816 | - */ | |
2817 | - dwc_gadget->gadget.quirk_ep_out_aligned_size = true; | |
2818 | - | |
2819 | - /* | |
2820 | 2888 | * REVISIT: Here we should clear all pending IRQs to be |
2821 | 2889 | * sure we're starting from a well known location. |
2822 | 2890 | */ |
... | ... | @@ -2825,7 +2893,8 @@ |
2825 | 2893 | if (ret) |
2826 | 2894 | goto err4; |
2827 | 2895 | |
2828 | - ret = usb_add_gadget_udc(dwc->dev, &dwc_gadget->gadget); | |
2896 | + ret = usb_add_gadget_udc_release(dwc->dev, &dwc->dwc_gadget->gadget, | |
2897 | + dwc3_gadget_release); | |
2829 | 2898 | if (ret) { |
2830 | 2899 | dev_err(dwc->dev, "failed to register udc\n"); |
2831 | 2900 | goto err4; |
... | ... | @@ -2834,6 +2903,7 @@ |
2834 | 2903 | return 0; |
2835 | 2904 | |
2836 | 2905 | err4: |
2906 | + usb_drd_unregister_udc(dwc->dev); | |
2837 | 2907 | dwc3_gadget_free_endpoints(dwc); |
2838 | 2908 | dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE, |
2839 | 2909 | dwc->ep0_bounce, dwc->ep0_bounce_addr); |
2840 | 2910 | |
2841 | 2911 | |
2842 | 2912 | |
2843 | 2913 | |
2844 | 2914 | |
... | ... | @@ -2859,20 +2929,23 @@ |
2859 | 2929 | { |
2860 | 2930 | struct dwc3_gadget *dwc_gadget = dwc->dwc_gadget; |
2861 | 2931 | |
2862 | - usb_del_gadget_udc(&dwc_gadget->gadget); | |
2863 | 2932 | |
2864 | - dwc3_gadget_free_endpoints(dwc); | |
2933 | + if (usb_drd_get_state(dwc->dev) & DRD_DEVICE_REGISTERED) { | |
2934 | + usb_del_gadget_udc(&dwc_gadget->gadget); | |
2865 | 2935 | |
2866 | - dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE, | |
2867 | - dwc->ep0_bounce, dwc->ep0_bounce_addr); | |
2936 | + dwc3_gadget_free_endpoints(dwc); | |
2868 | 2937 | |
2869 | - kfree(dwc->setup_buf); | |
2938 | + dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE, | |
2939 | + dwc->ep0_bounce, dwc->ep0_bounce_addr); | |
2870 | 2940 | |
2871 | - dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), | |
2872 | - dwc->ep0_trb, dwc->ep0_trb_addr); | |
2941 | + kfree(dwc->setup_buf); | |
2873 | 2942 | |
2874 | - dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), | |
2875 | - dwc->ctrl_req, dwc->ctrl_req_addr); | |
2943 | + dma_free_coherent(dwc->dev, sizeof(*dwc->ep0_trb), | |
2944 | + dwc->ep0_trb, dwc->ep0_trb_addr); | |
2945 | + | |
2946 | + dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), | |
2947 | + dwc->ctrl_req, dwc->ctrl_req_addr); | |
2948 | + } | |
2876 | 2949 | } |
2877 | 2950 | |
2878 | 2951 | int dwc3_gadget_suspend(struct dwc3 *dwc) |