#include <asm/unaligned.h>
#include <asm/dma.h>
-#ifdef CONFIG_USB_XUSBPS_OTG
#include <linux/usb/xilinx_usbps_otg.h>
-#endif
#define DRIVER_DESC "Xilinx PS USB Device Controller driver"
#define DRIVER_AUTHOR "Xilinx, Inc."
xusbps_writel(temp, &dr_regs->usbintr);
+ /*
+ * Enable disconnect notification using B session end interrupt.
+ * This is a SW workaround for USB disconnect detection as mentioned
+ * in AR# 47538
+ */
+ if (!gadget_is_otg(&udc->gadget)) {
+ temp = xusbps_readl(&dr_regs->otgsc);
+ temp |= OTGSC_BSEIE;
+ xusbps_writel(temp, &dr_regs->otgsc);
+ }
+
/* Clear stopped bit */
udc->stopped = 0;
static irqreturn_t xusbps_udc_irq(int irq, void *_udc)
{
struct xusbps_udc *udc = _udc;
- u32 irq_src;
+ u32 irq_src, otg_sts;
irqreturn_t status = IRQ_NONE;
unsigned long flags;
#ifdef CONFIG_USB_XUSBPS_OTG
/* Clear notification bits */
xusbps_writel(irq_src, &dr_regs->usbsts);
+ /*
+ * Check disconnect event from B session end interrupt.
+ * This is a SW workaround for USB disconnect detection as mentioned
+ * in AR# 47538
+ */
+ if (!gadget_is_otg(&udc->gadget)) {
+ otg_sts = xusbps_readl(&dr_regs->otgsc);
+ if (otg_sts & OTGSC_BSEIS) {
+ xusbps_writel(otg_sts, &dr_regs->otgsc);
+ reset_queues(udc);
+ status = IRQ_HANDLED;
+ }
+ }
+
/* VDBG("irq_src [0x%8x]", irq_src); */
/* Need to resume? */