in controllers/omap_ssi_port.c [666:725]
static void ssi_cleanup_queues(struct hsi_client *cl)
{
struct hsi_port *port = hsi_get_port(cl);
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 rxbufstate = 0;
u32 txbufstate = 0;
u32 status = SSI_ERROROCCURED;
u32 tmp;
ssi_flush_queue(&omap_port->brkqueue, cl);
if (list_empty(&omap_port->brkqueue))
status |= SSI_BREAKDETECTED;
for (i = 0; i < omap_port->channels; i++) {
if (list_empty(&omap_port->txqueue[i]))
continue;
msg = list_first_entry(&omap_port->txqueue[i], struct hsi_msg,
link);
if ((msg->cl == cl) && (msg->status == HSI_STATUS_PROCEEDING)) {
txbufstate |= (1 << i);
status |= SSI_DATAACCEPT(i);
/* Release the clocks writes, also GDD ones */
pm_runtime_mark_last_busy(omap_port->pdev);
pm_runtime_put_autosuspend(omap_port->pdev);
}
ssi_flush_queue(&omap_port->txqueue[i], cl);
}
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);
if ((msg->cl == cl) && (msg->status == HSI_STATUS_PROCEEDING)) {
rxbufstate |= (1 << i);
status |= SSI_DATAAVAILABLE(i);
}
ssi_flush_queue(&omap_port->rxqueue[i], cl);
/* Check if we keep the error detection interrupt armed */
if (!list_empty(&omap_port->rxqueue[i]))
status &= ~SSI_ERROROCCURED;
}
/* Cleanup write buffers */
tmp = readl(omap_port->sst_base + SSI_SST_BUFSTATE_REG);
tmp &= ~txbufstate;
writel_relaxed(tmp, omap_port->sst_base + SSI_SST_BUFSTATE_REG);
/* Cleanup read buffers */
tmp = readl(omap_port->ssr_base + SSI_SSR_BUFSTATE_REG);
tmp &= ~rxbufstate;
writel_relaxed(tmp, omap_port->ssr_base + SSI_SSR_BUFSTATE_REG);
/* Disarm and ack pending interrupts */
tmp = readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
tmp &= ~status;
writel_relaxed(tmp, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
writel_relaxed(status, omap_ssi->sys +
SSI_MPU_STATUS_REG(port->num, 0));
}