in qcom.c [493:608]
static irqreturn_t qcom_swrm_irq_handler(int irq, void *dev_id)
{
struct qcom_swrm_ctrl *swrm = dev_id;
u32 value, intr_sts, intr_sts_masked, slave_status;
u32 i;
int devnum;
int ret = IRQ_HANDLED;
swrm->reg_read(swrm, SWRM_INTERRUPT_STATUS, &intr_sts);
intr_sts_masked = intr_sts & swrm->intr_mask;
do {
for (i = 0; i < SWRM_INTERRUPT_MAX; i++) {
value = intr_sts_masked & BIT(i);
if (!value)
continue;
switch (value) {
case SWRM_INTERRUPT_STATUS_SLAVE_PEND_IRQ:
devnum = qcom_swrm_get_alert_slave_dev_num(swrm);
if (devnum < 0) {
dev_err_ratelimited(swrm->dev,
"no slave alert found.spurious interrupt\n");
} else {
sdw_handle_slave_status(&swrm->bus, swrm->status);
}
break;
case SWRM_INTERRUPT_STATUS_NEW_SLAVE_ATTACHED:
case SWRM_INTERRUPT_STATUS_CHANGE_ENUM_SLAVE_STATUS:
dev_err_ratelimited(swrm->dev, "%s: SWR new slave attached\n",
__func__);
swrm->reg_read(swrm, SWRM_MCP_SLV_STATUS, &slave_status);
if (swrm->slave_status == slave_status) {
dev_err(swrm->dev, "Slave status not changed %x\n",
slave_status);
} else {
qcom_swrm_get_device_status(swrm);
qcom_swrm_enumerate(&swrm->bus);
sdw_handle_slave_status(&swrm->bus, swrm->status);
}
break;
case SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET:
dev_err_ratelimited(swrm->dev,
"%s: SWR bus clsh detected\n",
__func__);
swrm->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;
swrm->reg_write(swrm, SWRM_INTERRUPT_CPU_EN, swrm->intr_mask);
break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
dev_err_ratelimited(swrm->dev,
"%s: SWR read FIFO overflow fifo status 0x%x\n",
__func__, value);
break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW:
swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
dev_err_ratelimited(swrm->dev,
"%s: SWR read FIFO underflow fifo status 0x%x\n",
__func__, value);
break;
case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
dev_err(swrm->dev,
"%s: SWR write FIFO overflow fifo status %x\n",
__func__, value);
swrm->reg_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
break;
case SWRM_INTERRUPT_STATUS_CMD_ERROR:
swrm->reg_read(swrm, SWRM_CMD_FIFO_STATUS, &value);
dev_err_ratelimited(swrm->dev,
"%s: SWR CMD error, fifo status 0x%x, flushing fifo\n",
__func__, value);
swrm->reg_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
break;
case SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION:
dev_err_ratelimited(swrm->dev,
"%s: SWR Port collision detected\n",
__func__);
swrm->intr_mask &= ~SWRM_INTERRUPT_STATUS_DOUT_PORT_COLLISION;
swrm->reg_write(swrm,
SWRM_INTERRUPT_CPU_EN, swrm->intr_mask);
break;
case SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH:
dev_err_ratelimited(swrm->dev,
"%s: SWR read enable valid mismatch\n",
__func__);
swrm->intr_mask &=
~SWRM_INTERRUPT_STATUS_READ_EN_RD_VALID_MISMATCH;
swrm->reg_write(swrm,
SWRM_INTERRUPT_CPU_EN, swrm->intr_mask);
break;
case SWRM_INTERRUPT_STATUS_SPECIAL_CMD_ID_FINISHED:
complete(&swrm->broadcast);
break;
case SWRM_INTERRUPT_STATUS_BUS_RESET_FINISHED_V2:
break;
case SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED_V2:
break;
case SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP:
break;
default:
dev_err_ratelimited(swrm->dev,
"%s: SWR unknown interrupt value: %d\n",
__func__, value);
ret = IRQ_NONE;
break;
}
}
swrm->reg_write(swrm, SWRM_INTERRUPT_CLEAR, intr_sts);
swrm->reg_read(swrm, SWRM_INTERRUPT_STATUS, &intr_sts);
intr_sts_masked = intr_sts & swrm->intr_mask;
} while (intr_sts_masked);
return ret;
}