diff options
Diffstat (limited to 'drivers/usb/renesas_usbhs/mod_gadget.c')
-rw-r--r-- | drivers/usb/renesas_usbhs/mod_gadget.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 2d17c10a0428..8697e6efcabf 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -56,6 +56,7 @@ struct usbhsg_gpriv { | |||
56 | #define USBHSG_STATUS_REGISTERD (1 << 1) | 56 | #define USBHSG_STATUS_REGISTERD (1 << 1) |
57 | #define USBHSG_STATUS_WEDGE (1 << 2) | 57 | #define USBHSG_STATUS_WEDGE (1 << 2) |
58 | #define USBHSG_STATUS_SELF_POWERED (1 << 3) | 58 | #define USBHSG_STATUS_SELF_POWERED (1 << 3) |
59 | #define USBHSG_STATUS_SOFT_CONNECT (1 << 4) | ||
59 | }; | 60 | }; |
60 | 61 | ||
61 | struct usbhsg_recip_handle { | 62 | struct usbhsg_recip_handle { |
@@ -484,6 +485,9 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv, | |||
484 | case NODATA_STATUS_STAGE: | 485 | case NODATA_STATUS_STAGE: |
485 | pipe->handler = &usbhs_ctrl_stage_end_handler; | 486 | pipe->handler = &usbhs_ctrl_stage_end_handler; |
486 | break; | 487 | break; |
488 | case READ_STATUS_STAGE: | ||
489 | case WRITE_STATUS_STAGE: | ||
490 | usbhs_dcp_control_transfer_done(pipe); | ||
487 | default: | 491 | default: |
488 | return ret; | 492 | return ret; |
489 | } | 493 | } |
@@ -602,6 +606,9 @@ static int usbhsg_ep_disable(struct usb_ep *ep) | |||
602 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | 606 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); |
603 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); | 607 | struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); |
604 | 608 | ||
609 | if (!pipe) | ||
610 | return -EINVAL; | ||
611 | |||
605 | usbhsg_pipe_disable(uep); | 612 | usbhsg_pipe_disable(uep); |
606 | usbhs_pipe_free(pipe); | 613 | usbhs_pipe_free(pipe); |
607 | 614 | ||
@@ -723,6 +730,25 @@ static struct usb_ep_ops usbhsg_ep_ops = { | |||
723 | }; | 730 | }; |
724 | 731 | ||
725 | /* | 732 | /* |
733 | * pullup control | ||
734 | */ | ||
735 | static int usbhsg_can_pullup(struct usbhs_priv *priv) | ||
736 | { | ||
737 | struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); | ||
738 | |||
739 | return gpriv->driver && | ||
740 | usbhsg_status_has(gpriv, USBHSG_STATUS_SOFT_CONNECT); | ||
741 | } | ||
742 | |||
743 | static void usbhsg_update_pullup(struct usbhs_priv *priv) | ||
744 | { | ||
745 | if (usbhsg_can_pullup(priv)) | ||
746 | usbhs_sys_function_pullup(priv, 1); | ||
747 | else | ||
748 | usbhs_sys_function_pullup(priv, 0); | ||
749 | } | ||
750 | |||
751 | /* | ||
726 | * usb module start/end | 752 | * usb module start/end |
727 | */ | 753 | */ |
728 | static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | 754 | static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) |
@@ -756,9 +782,9 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
756 | /* | 782 | /* |
757 | * pipe initialize and enable DCP | 783 | * pipe initialize and enable DCP |
758 | */ | 784 | */ |
785 | usbhs_fifo_init(priv); | ||
759 | usbhs_pipe_init(priv, | 786 | usbhs_pipe_init(priv, |
760 | usbhsg_dma_map_ctrl); | 787 | usbhsg_dma_map_ctrl); |
761 | usbhs_fifo_init(priv); | ||
762 | 788 | ||
763 | /* dcp init instead of usbhsg_ep_enable() */ | 789 | /* dcp init instead of usbhsg_ep_enable() */ |
764 | dcp->pipe = usbhs_dcp_malloc(priv); | 790 | dcp->pipe = usbhs_dcp_malloc(priv); |
@@ -772,6 +798,7 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
772 | * - usb module | 798 | * - usb module |
773 | */ | 799 | */ |
774 | usbhs_sys_function_ctrl(priv, 1); | 800 | usbhs_sys_function_ctrl(priv, 1); |
801 | usbhsg_update_pullup(priv); | ||
775 | 802 | ||
776 | /* | 803 | /* |
777 | * enable irq callback | 804 | * enable irq callback |
@@ -851,8 +878,7 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget, | |||
851 | return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); | 878 | return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); |
852 | } | 879 | } |
853 | 880 | ||
854 | static int usbhsg_gadget_stop(struct usb_gadget *gadget, | 881 | static int usbhsg_gadget_stop(struct usb_gadget *gadget) |
855 | struct usb_gadget_driver *driver) | ||
856 | { | 882 | { |
857 | struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); | 883 | struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); |
858 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | 884 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); |
@@ -878,8 +904,15 @@ static int usbhsg_pullup(struct usb_gadget *gadget, int is_on) | |||
878 | { | 904 | { |
879 | struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); | 905 | struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); |
880 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); | 906 | struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); |
907 | unsigned long flags; | ||
881 | 908 | ||
882 | usbhs_sys_function_pullup(priv, is_on); | 909 | usbhs_lock(priv, flags); |
910 | if (is_on) | ||
911 | usbhsg_status_set(gpriv, USBHSG_STATUS_SOFT_CONNECT); | ||
912 | else | ||
913 | usbhsg_status_clr(gpriv, USBHSG_STATUS_SOFT_CONNECT); | ||
914 | usbhsg_update_pullup(priv); | ||
915 | usbhs_unlock(priv, flags); | ||
883 | 916 | ||
884 | return 0; | 917 | return 0; |
885 | } | 918 | } |