u8 ctrl_buff[8];
struct usb_gadget gadget;
+ unsigned int connected:1;
unsigned int setup;
unsigned long last_rst;
struct s3c_hsotg_ep *eps;
extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2);
extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg);
+extern void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2);
#else
static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2)
{ return 0; }
{ return 0; }
static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2) {}
static inline void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
+static inline void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
#endif
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
dwc2_op_state_str(hsotg));
gotgctl = readl(hsotg->regs + GOTGCTL);
+ if (dwc2_is_device_mode(hsotg))
+ s3c_hsotg_disconnect(hsotg);
+
if (hsotg->op_state == OTG_STATE_B_HOST) {
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
} else {
/* Clear interrupt */
writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
+
+ /*
+ * Report disconnect if there is any previous session established
+ */
+ if (dwc2_is_device_mode(hsotg))
+ s3c_hsotg_disconnect(hsotg);
}
/*
}
static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg);
-static void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg);
/**
* s3c_hsotg_stall_ep0 - stall ep0
if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
switch (ctrl->bRequest) {
case USB_REQ_SET_ADDRESS:
- s3c_hsotg_disconnect(hsotg);
dcfg = readl(hsotg->regs + DCFG);
dcfg &= ~DCFG_DEVADDR_MASK;
dcfg |= (le16_to_cpu(ctrl->wValue) <<
* transactions and signal the gadget driver that this
* has happened.
*/
-static void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg)
+void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg)
{
unsigned ep;
+ if (!hsotg->connected)
+ return;
+
+ hsotg->connected = 0;
for (ep = 0; ep < hsotg->num_of_eps; ep++)
kill_all_requests(hsotg, &hsotg->eps[ep], -ESHUTDOWN, true);
call_gadget(hsotg, disconnect);
}
+EXPORT_SYMBOL_GPL(s3c_hsotg_disconnect);
/**
* s3c_hsotg_irq_fifoempty - TX FIFO empty interrupt handler
writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
s3c_hsotg_irq_enumdone(hsotg);
+ hsotg->connected = 1;
}
if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {