in controllers/omap_ssi_port.c [805:861]
static void ssi_error(struct hsi_port *port)
{
struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
struct hsi_msg *msg;
unsigned int i;
u32 err;
u32 val;
u32 tmp;
/* ACK error */
err = readl(omap_port->ssr_base + SSI_SSR_ERROR_REG);
dev_err(&port->device, "SSI error: 0x%02x\n", err);
if (!err) {
dev_dbg(&port->device, "spurious SSI error ignored!\n");
return;
}
spin_lock(&omap_ssi->lock);
/* Cancel all GDD read transfers */
for (i = 0, val = 0; i < SSI_MAX_GDD_LCH; i++) {
msg = omap_ssi->gdd_trn[i].msg;
if ((msg) && (msg->ttype == HSI_MSG_READ)) {
writew_relaxed(0, omap_ssi->gdd + SSI_GDD_CCR_REG(i));
val |= (1 << i);
omap_ssi->gdd_trn[i].msg = NULL;
}
}
tmp = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
tmp &= ~val;
writel_relaxed(tmp, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
spin_unlock(&omap_ssi->lock);
/* Cancel all PIO read transfers */
spin_lock(&omap_port->lock);
tmp = readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
tmp &= 0xfeff00ff; /* Disable error & all dataavailable interrupts */
writel_relaxed(tmp, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
/* ACK error */
writel_relaxed(err, omap_port->ssr_base + SSI_SSR_ERRORACK_REG);
writel_relaxed(SSI_ERROROCCURED,
omap_ssi->sys + SSI_MPU_STATUS_REG(port->num, 0));
/* Signal the error all current pending read requests */
for (i = 0; i < omap_port->channels; i++) {
if (list_empty(&omap_port->rxqueue[i]))
continue;
msg = list_first_entry(&omap_port->rxqueue[i], struct hsi_msg,
link);
list_del(&msg->link);
msg->status = HSI_STATUS_ERROR;
spin_unlock(&omap_port->lock);
msg->complete(msg);
/* Now restart queued reads if any */
ssi_transfer(omap_port, &omap_port->rxqueue[i]);
spin_lock(&omap_port->lock);
}
spin_unlock(&omap_port->lock);
}