diff options
Diffstat (limited to 'drivers/usb/gadget/udc/omap_udc.c')
| -rw-r--r-- | drivers/usb/gadget/udc/omap_udc.c | 88 |
1 files changed, 31 insertions, 57 deletions
diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 3a16431da321..fcf13ef33b31 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c | |||
| @@ -2033,6 +2033,7 @@ static inline int machine_without_vbus_sense(void) | |||
| 2033 | { | 2033 | { |
| 2034 | return machine_is_omap_innovator() | 2034 | return machine_is_omap_innovator() |
| 2035 | || machine_is_omap_osk() | 2035 | || machine_is_omap_osk() |
| 2036 | || machine_is_omap_palmte() | ||
| 2036 | || machine_is_sx1() | 2037 | || machine_is_sx1() |
| 2037 | /* No known omap7xx boards with vbus sense */ | 2038 | /* No known omap7xx boards with vbus sense */ |
| 2038 | || cpu_is_omap7xx(); | 2039 | || cpu_is_omap7xx(); |
| @@ -2041,7 +2042,7 @@ static inline int machine_without_vbus_sense(void) | |||
| 2041 | static int omap_udc_start(struct usb_gadget *g, | 2042 | static int omap_udc_start(struct usb_gadget *g, |
| 2042 | struct usb_gadget_driver *driver) | 2043 | struct usb_gadget_driver *driver) |
| 2043 | { | 2044 | { |
| 2044 | int status = -ENODEV; | 2045 | int status; |
| 2045 | struct omap_ep *ep; | 2046 | struct omap_ep *ep; |
| 2046 | unsigned long flags; | 2047 | unsigned long flags; |
| 2047 | 2048 | ||
| @@ -2079,6 +2080,7 @@ static int omap_udc_start(struct usb_gadget *g, | |||
| 2079 | goto done; | 2080 | goto done; |
| 2080 | } | 2081 | } |
| 2081 | } else { | 2082 | } else { |
| 2083 | status = 0; | ||
| 2082 | if (can_pullup(udc)) | 2084 | if (can_pullup(udc)) |
| 2083 | pullup_enable(udc); | 2085 | pullup_enable(udc); |
| 2084 | else | 2086 | else |
| @@ -2593,9 +2595,22 @@ omap_ep_setup(char *name, u8 addr, u8 type, | |||
| 2593 | 2595 | ||
| 2594 | static void omap_udc_release(struct device *dev) | 2596 | static void omap_udc_release(struct device *dev) |
| 2595 | { | 2597 | { |
| 2596 | complete(udc->done); | 2598 | pullup_disable(udc); |
| 2599 | if (!IS_ERR_OR_NULL(udc->transceiver)) { | ||
| 2600 | usb_put_phy(udc->transceiver); | ||
| 2601 | udc->transceiver = NULL; | ||
| 2602 | } | ||
| 2603 | omap_writew(0, UDC_SYSCON1); | ||
| 2604 | remove_proc_file(); | ||
| 2605 | if (udc->dc_clk) { | ||
| 2606 | if (udc->clk_requested) | ||
| 2607 | omap_udc_enable_clock(0); | ||
| 2608 | clk_put(udc->hhc_clk); | ||
| 2609 | clk_put(udc->dc_clk); | ||
| 2610 | } | ||
| 2611 | if (udc->done) | ||
| 2612 | complete(udc->done); | ||
| 2597 | kfree(udc); | 2613 | kfree(udc); |
| 2598 | udc = NULL; | ||
| 2599 | } | 2614 | } |
| 2600 | 2615 | ||
| 2601 | static int | 2616 | static int |
| @@ -2627,6 +2642,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) | |||
| 2627 | udc->gadget.speed = USB_SPEED_UNKNOWN; | 2642 | udc->gadget.speed = USB_SPEED_UNKNOWN; |
| 2628 | udc->gadget.max_speed = USB_SPEED_FULL; | 2643 | udc->gadget.max_speed = USB_SPEED_FULL; |
| 2629 | udc->gadget.name = driver_name; | 2644 | udc->gadget.name = driver_name; |
| 2645 | udc->gadget.quirk_ep_out_aligned_size = 1; | ||
| 2630 | udc->transceiver = xceiv; | 2646 | udc->transceiver = xceiv; |
| 2631 | 2647 | ||
| 2632 | /* ep0 is special; put it right after the SETUP buffer */ | 2648 | /* ep0 is special; put it right after the SETUP buffer */ |
| @@ -2867,8 +2883,8 @@ bad_on_1710: | |||
| 2867 | udc->clr_halt = UDC_RESET_EP; | 2883 | udc->clr_halt = UDC_RESET_EP; |
| 2868 | 2884 | ||
| 2869 | /* USB general purpose IRQ: ep0, state changes, dma, etc */ | 2885 | /* USB general purpose IRQ: ep0, state changes, dma, etc */ |
| 2870 | status = request_irq(pdev->resource[1].start, omap_udc_irq, | 2886 | status = devm_request_irq(&pdev->dev, pdev->resource[1].start, |
| 2871 | 0, driver_name, udc); | 2887 | omap_udc_irq, 0, driver_name, udc); |
| 2872 | if (status != 0) { | 2888 | if (status != 0) { |
| 2873 | ERR("can't get irq %d, err %d\n", | 2889 | ERR("can't get irq %d, err %d\n", |
| 2874 | (int) pdev->resource[1].start, status); | 2890 | (int) pdev->resource[1].start, status); |
| @@ -2876,20 +2892,20 @@ bad_on_1710: | |||
| 2876 | } | 2892 | } |
| 2877 | 2893 | ||
| 2878 | /* USB "non-iso" IRQ (PIO for all but ep0) */ | 2894 | /* USB "non-iso" IRQ (PIO for all but ep0) */ |
| 2879 | status = request_irq(pdev->resource[2].start, omap_udc_pio_irq, | 2895 | status = devm_request_irq(&pdev->dev, pdev->resource[2].start, |
| 2880 | 0, "omap_udc pio", udc); | 2896 | omap_udc_pio_irq, 0, "omap_udc pio", udc); |
| 2881 | if (status != 0) { | 2897 | if (status != 0) { |
| 2882 | ERR("can't get irq %d, err %d\n", | 2898 | ERR("can't get irq %d, err %d\n", |
| 2883 | (int) pdev->resource[2].start, status); | 2899 | (int) pdev->resource[2].start, status); |
| 2884 | goto cleanup2; | 2900 | goto cleanup1; |
| 2885 | } | 2901 | } |
| 2886 | #ifdef USE_ISO | 2902 | #ifdef USE_ISO |
| 2887 | status = request_irq(pdev->resource[3].start, omap_udc_iso_irq, | 2903 | status = devm_request_irq(&pdev->dev, pdev->resource[3].start, |
| 2888 | 0, "omap_udc iso", udc); | 2904 | omap_udc_iso_irq, 0, "omap_udc iso", udc); |
| 2889 | if (status != 0) { | 2905 | if (status != 0) { |
| 2890 | ERR("can't get irq %d, err %d\n", | 2906 | ERR("can't get irq %d, err %d\n", |
| 2891 | (int) pdev->resource[3].start, status); | 2907 | (int) pdev->resource[3].start, status); |
| 2892 | goto cleanup3; | 2908 | goto cleanup1; |
| 2893 | } | 2909 | } |
| 2894 | #endif | 2910 | #endif |
| 2895 | if (cpu_is_omap16xx() || cpu_is_omap7xx()) { | 2911 | if (cpu_is_omap16xx() || cpu_is_omap7xx()) { |
| @@ -2900,23 +2916,8 @@ bad_on_1710: | |||
| 2900 | } | 2916 | } |
| 2901 | 2917 | ||
| 2902 | create_proc_file(); | 2918 | create_proc_file(); |
| 2903 | status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, | 2919 | return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, |
| 2904 | omap_udc_release); | 2920 | omap_udc_release); |
| 2905 | if (status) | ||
| 2906 | goto cleanup4; | ||
| 2907 | |||
| 2908 | return 0; | ||
| 2909 | |||
| 2910 | cleanup4: | ||
| 2911 | remove_proc_file(); | ||
| 2912 | |||
| 2913 | #ifdef USE_ISO | ||
| 2914 | cleanup3: | ||
| 2915 | free_irq(pdev->resource[2].start, udc); | ||
| 2916 | #endif | ||
| 2917 | |||
| 2918 | cleanup2: | ||
| 2919 | free_irq(pdev->resource[1].start, udc); | ||
| 2920 | 2921 | ||
| 2921 | cleanup1: | 2922 | cleanup1: |
| 2922 | kfree(udc); | 2923 | kfree(udc); |
| @@ -2943,42 +2944,15 @@ static int omap_udc_remove(struct platform_device *pdev) | |||
| 2943 | { | 2944 | { |
| 2944 | DECLARE_COMPLETION_ONSTACK(done); | 2945 | DECLARE_COMPLETION_ONSTACK(done); |
| 2945 | 2946 | ||
| 2946 | if (!udc) | ||
| 2947 | return -ENODEV; | ||
| 2948 | |||
| 2949 | usb_del_gadget_udc(&udc->gadget); | ||
| 2950 | if (udc->driver) | ||
| 2951 | return -EBUSY; | ||
| 2952 | |||
| 2953 | udc->done = &done; | 2947 | udc->done = &done; |
| 2954 | 2948 | ||
| 2955 | pullup_disable(udc); | 2949 | usb_del_gadget_udc(&udc->gadget); |
| 2956 | if (!IS_ERR_OR_NULL(udc->transceiver)) { | ||
| 2957 | usb_put_phy(udc->transceiver); | ||
| 2958 | udc->transceiver = NULL; | ||
| 2959 | } | ||
| 2960 | omap_writew(0, UDC_SYSCON1); | ||
| 2961 | |||
| 2962 | remove_proc_file(); | ||
| 2963 | |||
| 2964 | #ifdef USE_ISO | ||
| 2965 | free_irq(pdev->resource[3].start, udc); | ||
| 2966 | #endif | ||
| 2967 | free_irq(pdev->resource[2].start, udc); | ||
| 2968 | free_irq(pdev->resource[1].start, udc); | ||
| 2969 | 2950 | ||
| 2970 | if (udc->dc_clk) { | 2951 | wait_for_completion(&done); |
| 2971 | if (udc->clk_requested) | ||
| 2972 | omap_udc_enable_clock(0); | ||
| 2973 | clk_put(udc->hhc_clk); | ||
| 2974 | clk_put(udc->dc_clk); | ||
| 2975 | } | ||
| 2976 | 2952 | ||
| 2977 | release_mem_region(pdev->resource[0].start, | 2953 | release_mem_region(pdev->resource[0].start, |
| 2978 | pdev->resource[0].end - pdev->resource[0].start + 1); | 2954 | pdev->resource[0].end - pdev->resource[0].start + 1); |
| 2979 | 2955 | ||
| 2980 | wait_for_completion(&done); | ||
| 2981 | |||
| 2982 | return 0; | 2956 | return 0; |
| 2983 | } | 2957 | } |
| 2984 | 2958 | ||
