irqreturn_t msm_slim_port_irq_handler(struct msm_slim_ctrl *dev, u32 pstat) { int i; u32 int_en = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_EN_EEn, dev->ver)); if ((pstat & int_en) == 0) return IRQ_HANDLED; for (i = dev->port_b; i < MSM_SLIM_NPORTS; i++) { if (pstat & (1 << i)) { u32 val = readl_relaxed(PGD_PORT(PGD_PORT_STATn, i, dev->ver)); if (val & MSM_PORT_OVERFLOW) { dev->ctrl.ports[i-dev->port_b].err = SLIM_P_OVERFLOW; } else if (val & MSM_PORT_UNDERFLOW) { dev->ctrl.ports[i-dev->port_b].err = SLIM_P_UNDERFLOW; } } } writel_relaxed((int_en & (~pstat)), PGD_THIS_EE(PGD_PORT_INT_EN_EEn, dev->ver)); writel_relaxed(pstat, PGD_THIS_EE(PGD_PORT_INT_CL_EEn, dev->ver)); SLIM_INFO(dev, "disabled overflow/underflow for port 0x%x", pstat); mb(); return IRQ_HANDLED; }
irqreturn_t msm_slim_port_irq_handler(struct msm_slim_ctrl *dev, u32 pstat) { int i; u32 int_en = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_EN_EEn, dev->ver)); /* * different port-interrupt than what we enabled, ignore. * This may happen if overflow/underflow is reported, but * was disabled due to unavailability of buffers provided by * client. */ if ((pstat & int_en) == 0) return IRQ_HANDLED; for (i = 0; i < dev->port_nums; i++) { struct msm_slim_endp *endpoint = &dev->pipes[i]; if (pstat & (1 << endpoint->port_b)) { u32 val = readl_relaxed(PGD_PORT(PGD_PORT_STATn, endpoint->port_b, dev->ver)); if (val & MSM_PORT_OVERFLOW) { dev->ctrl.ports[i].err = SLIM_P_OVERFLOW; } else if (val & MSM_PORT_UNDERFLOW) { dev->ctrl.ports[i].err = SLIM_P_UNDERFLOW; } } } /* * Disable port interrupt here. Re-enable when more * buffers are provided for this port. */ writel_relaxed((int_en & (~pstat)), PGD_THIS_EE(PGD_PORT_INT_EN_EEn, dev->ver)); /* clear port interrupts */ writel_relaxed(pstat, PGD_THIS_EE(PGD_PORT_INT_CL_EEn, dev->ver)); SLIM_INFO(dev, "disabled overflow/underflow for port 0x%x", pstat); /* * Guarantee that port interrupt bit(s) clearing writes go * through before exiting ISR */ mb(); return IRQ_HANDLED; }