in controllers/omap_ssi_port.c [996:1033]
static irqreturn_t ssi_wake_thread(int irq __maybe_unused, void *ssi_port)
{
struct hsi_port *port = (struct hsi_port *)ssi_port;
struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
if (ssi_wakein(port)) {
/**
* We can have a quick High-Low-High transition in the line.
* In such a case if we have long interrupt latencies,
* we can miss the low event or get twice a high event.
* This workaround will avoid breaking the clock reference
* count when such a situation ocurrs.
*/
if (!test_and_set_bit(SSI_WAKE_EN, &omap_port->flags))
pm_runtime_get_sync(omap_port->pdev);
dev_dbg(&ssi->device, "Wake in high\n");
if (omap_port->wktest) { /* FIXME: HACK ! To be removed */
writel(SSI_WAKE(0),
omap_ssi->sys + SSI_SET_WAKE_REG(port->num));
}
hsi_event(port, HSI_EVENT_START_RX);
} else {
dev_dbg(&ssi->device, "Wake in low\n");
if (omap_port->wktest) { /* FIXME: HACK ! To be removed */
writel(SSI_WAKE(0),
omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num));
}
hsi_event(port, HSI_EVENT_STOP_RX);
if (test_and_clear_bit(SSI_WAKE_EN, &omap_port->flags)) {
pm_runtime_mark_last_busy(omap_port->pdev);
pm_runtime_put_autosuspend(omap_port->pdev);
}
}
return IRQ_HANDLED;
}