void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
{
u16 mask = DCFM | DRPD | DPRPU | HSE | USBE;
- u16 val = DPRPU | HSE | USBE;
+ u16 val = HSE | USBE;
/*
* if enable
*
* - 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);
}
#define USBHSG_STATUS_REGISTERD (1 << 1)
#define USBHSG_STATUS_WEDGE (1 << 2)
#define USBHSG_STATUS_SELF_POWERED (1 << 3)
+#define USBHSG_STATUS_SOFT_CONNECT (1 << 4)
};
struct usbhsg_recip_handle {
.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
*/
usbhs_sys_function_ctrl(priv, 1);
+ usbhsg_update_pullup(priv);
/*
* enable irq callback
{
struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
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;
}