Commit 04a5def3 authored by Takeshi Kihara's avatar Takeshi Kihara Committed by Felipe Balbi

usb: renesas_usbhs: gadget: fix the behavior of pullup

This patch fixes an issue that this driver always enable the D+ pullup
after it detected the VBUS connection even though this usb controller
can control the D+ pullup timing by software. So, this driver should
enable the D+ pullup after a gadget driver called usb_gadget_connect().
Signed-off-by: default avatarTakeshi Kihara <takeshi.kihara.df@renesas.com>
Signed-off-by: default avatarKazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
Signed-off-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 11432050
...@@ -126,13 +126,15 @@ void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable) ...@@ -126,13 +126,15 @@ void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable)
void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable) void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
{ {
u16 mask = DCFM | DRPD | DPRPU | HSE | USBE; u16 mask = DCFM | DRPD | DPRPU | HSE | USBE;
u16 val = DPRPU | HSE | USBE; u16 val = HSE | USBE;
/* /*
* if enable * if enable
* *
* - select Function mode * - select Function mode
* - D+ Line Pull-up * - D+ Line Pull-up is disabled
* When D+ Line Pull-up is enabled,
* calling usbhs_sys_function_pullup(,1)
*/ */
usbhs_bset(priv, SYSCFG, mask, enable ? val : 0); usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
} }
......
...@@ -56,6 +56,7 @@ struct usbhsg_gpriv { ...@@ -56,6 +56,7 @@ struct usbhsg_gpriv {
#define USBHSG_STATUS_REGISTERD (1 << 1) #define USBHSG_STATUS_REGISTERD (1 << 1)
#define USBHSG_STATUS_WEDGE (1 << 2) #define USBHSG_STATUS_WEDGE (1 << 2)
#define USBHSG_STATUS_SELF_POWERED (1 << 3) #define USBHSG_STATUS_SELF_POWERED (1 << 3)
#define USBHSG_STATUS_SOFT_CONNECT (1 << 4)
}; };
struct usbhsg_recip_handle { struct usbhsg_recip_handle {
...@@ -725,6 +726,25 @@ static struct usb_ep_ops usbhsg_ep_ops = { ...@@ -725,6 +726,25 @@ static struct usb_ep_ops usbhsg_ep_ops = {
.set_wedge = usbhsg_ep_set_wedge, .set_wedge = usbhsg_ep_set_wedge,
}; };
/*
* pullup control
*/
static int usbhsg_can_pullup(struct usbhs_priv *priv)
{
struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
return gpriv->driver &&
usbhsg_status_has(gpriv, USBHSG_STATUS_SOFT_CONNECT);
}
static void usbhsg_update_pullup(struct usbhs_priv *priv)
{
if (usbhsg_can_pullup(priv))
usbhs_sys_function_pullup(priv, 1);
else
usbhs_sys_function_pullup(priv, 0);
}
/* /*
* usb module start/end * usb module start/end
*/ */
...@@ -775,6 +795,7 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) ...@@ -775,6 +795,7 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status)
* - usb module * - usb module
*/ */
usbhs_sys_function_ctrl(priv, 1); usbhs_sys_function_ctrl(priv, 1);
usbhsg_update_pullup(priv);
/* /*
* enable irq callback * enable irq callback
...@@ -880,8 +901,15 @@ static int usbhsg_pullup(struct usb_gadget *gadget, int is_on) ...@@ -880,8 +901,15 @@ static int usbhsg_pullup(struct usb_gadget *gadget, int is_on)
{ {
struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
unsigned long flags;
usbhs_sys_function_pullup(priv, is_on); usbhs_lock(priv, flags);
if (is_on)
usbhsg_status_set(gpriv, USBHSG_STATUS_SOFT_CONNECT);
else
usbhsg_status_clr(gpriv, USBHSG_STATUS_SOFT_CONNECT);
usbhsg_update_pullup(priv);
usbhs_unlock(priv, flags);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment