/*! * otg_pci_isr() - interrupt service handler */ irqreturn_t otg_pci_isr(int irq, void *data, struct pt_regs *r) { struct pci_dev *pci_dev = data; struct otg_dev *otg_dev = pci_get_drvdata(pci_dev); int i; /* XXX spinlock */ RETURN_IRQ_HANDLED_UNLESS(otg_dev); TRACE_MSG0(otg_dev->PCI, "---------------------------------------- Start"); for (i = OTG_DRIVER_TCD; i < OTG_DRIVER_TYPES; i++) { struct otg_driver *otg_driver; otg_driver = otg_dev->otg_pci_driver->drivers[i]; CONTINUE_UNLESS(otg_driver); TRACE_MSG2(otg_dev->PCI, "try %s %d", otg_driver->name, i); CONTINUE_UNLESS(otg_driver->isr); RETURN_IRQ_HANDLED_IF_IRQ_HANDLED (otg_driver->isr(otg_dev, data)); TRACE_MSG2(otg_dev->PCI, "not handled by %s %d", otg_driver->name, i); } TRACE_MSG2(otg_dev->PCI, "try %s %d", otg_dev->otg_pci_driver->name, i); if (otg_dev->otg_pci_driver->isr) RETURN_IRQ_HANDLED_IF_IRQ_HANDLED (otg_dev->otg_pci_driver->isr(otg_dev, data)); /* XXX spinlock */ TRACE_MSG0(otg_dev->PCI, "---------------------------------------- IRQ_NONE ----"); return IRQ_NONE; }
/*! * ocd_ctrl_int_hndlr - Control and I2C interrupt * Process USBOTG related interrupts. * @param irq * @param dev_id * @param regs */ static irqreturn_t ocd_ctrl_int_hndlr(int irq, void *dev_id) { u32 sys_ctrl = fs_rl(OTG_SYS_CTRL); // C.f. 23.8 USB Control Register u32 cint_stat = fs_rl(OTG_CORE_CINT_STAT); // C.f. 23.9.2 USBOTG Module Interrupt Status Register u32 hint_stat = fs_rl(OTG_CORE_HINT_STAT); // C.f. 23.9.12 HNP Interrupt Status Register u32 hnp_cstat = fs_rl(OTG_CORE_HNP_CSTAT); static u32 ocd_interrupts = 0; /* N.B. OTG_CORE_CINT_STAT interrupts are self clearing when interrupt * sources have been cleared. */ RETURN_IRQ_HANDLED_UNLESS(cint_stat || hint_stat); //if (sys_ctrl & (SYS_CTRL_HOST_WU_INT_STAT | SYS_CTRL_FNT_WU_INT_STAT)) // TRACE_MSG1(OCD, "SYS_CTRL: HOST/FUNC %08x", sys_ctrl); //TRACE_MSG4(OCD, "CLK: %08x sys: %08x cint: %08x hint: %08x", fs_rl(OTG_CORE_CLK_CTRL), sys_ctrl, cint_stat, hint_stat); if (hint_stat) { //if (hint_stat & HNP_I2COTGINT) // TRACE_MSG1(OCD, "OTG_CORE_HINT_STAT HNP_I2COTGINT %08x ignored (periodic?)", hint_stat); fs_wl(OTG_CORE_HINT_STAT, hint_stat); printk(KERN_INFO"%s: HINT_STAT: %08x HNP_CSTAT: %08x\n", __FUNCTION__, hint_stat, hnp_cstat); } if (cint_stat & MODULE_ASHNPINT) { // asynchronous HNP interrupt, enable Main clock u32 hnp_cstat = fs_rl(OTG_CORE_HNP_CSTAT); u32 hint_stat = fs_rl(OTG_CORE_HINT_STAT); //TRACE_MSG1(OCD, "MODULE_ASHNPINT %08x", hint_stat); mxc_main_clock_on(); // turn on Main Clock //if (hnp_cstat & MODULE_ISBDEV) // TRACE_MSG0(OCD, "ISBDEV"); //if (hnp_cstat & MODULE_ISADEV) // TRACE_MSG0(OCD, "ISADEV"); //fs_wl_set(OCD, OTG_CORE_HINT_STAT, hint_stat); fs_wl(OTG_CORE_HINT_STAT, hint_stat); ocd_hnp_int_hndlr(irq, dev_id); } if (cint_stat & MODULE_ASFCINT) { // Asynchronous Function interrupt, enable Func clock //TRACE_MSG1(OCD, "MODULE_ASFCINT %08x", cint_stat); // XXX otg_queue_event(ocd_instance->otg, B_SESS_VLD | A_SESS_VLD, PCD, "MX2ADS ASFCINT"); mxc_func_clock_on(); // turn on Function Clock } if (cint_stat & MODULE_ASHCINT) { // Asynchronous Host interrupt, enable Host clock //TRACE_MSG1(OCD, "MODULE_ASHCINT %08x", cint_stat); mxc_host_clock_on(); // turn on Host Clock } if ((cint_stat & MODULE_HNPINT) || hint_stat) // HNP interrupt ocd_hnp_int_hndlr(irq, dev_id); if (cint_stat & MODULE_FCINT) mxc_pcd_int_hndlr(); if (cint_stat & MODULE_HCINT) { //TRACE_MSG1(OCD, "MODULE_HCINT %08x", cint_stat); mxc_hcd_hw_int_hndlr(irq, NULL); } return IRQ_HANDLED; }