static void ssi_pio_complete()

in controllers/omap_ssi_port.c [893:955]


static void ssi_pio_complete(struct hsi_port *port, struct list_head *queue)
{
	struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
	struct hsi_msg *msg;
	u32 *buf;
	u32 reg;
	u32 val;

	spin_lock_bh(&omap_port->lock);
	msg = list_first_entry(queue, struct hsi_msg, link);
	if ((!msg->sgt.nents) || (!msg->sgt.sgl->length)) {
		msg->actual_len = 0;
		msg->status = HSI_STATUS_PENDING;
	}
	if (msg->ttype == HSI_MSG_WRITE)
		val = SSI_DATAACCEPT(msg->channel);
	else
		val = SSI_DATAAVAILABLE(msg->channel);
	if (msg->status == HSI_STATUS_PROCEEDING) {
		buf = sg_virt(msg->sgt.sgl) + msg->actual_len;
		if (msg->ttype == HSI_MSG_WRITE)
			writel(*buf, omap_port->sst_base +
					SSI_SST_BUFFER_CH_REG(msg->channel));
		 else
			*buf = readl(omap_port->ssr_base +
					SSI_SSR_BUFFER_CH_REG(msg->channel));
		dev_dbg(&port->device, "ch %d ttype %d 0x%08x\n", msg->channel,
							msg->ttype, *buf);
		msg->actual_len += sizeof(*buf);
		if (msg->actual_len >= msg->sgt.sgl->length)
			msg->status = HSI_STATUS_COMPLETED;
		/*
		 * Wait for the last written frame to be really sent before
		 * we call the complete callback
		 */
		if ((msg->status == HSI_STATUS_PROCEEDING) ||
				((msg->status == HSI_STATUS_COMPLETED) &&
					(msg->ttype == HSI_MSG_WRITE))) {
			writel(val, omap_ssi->sys +
					SSI_MPU_STATUS_REG(port->num, 0));
			spin_unlock_bh(&omap_port->lock);

			return;
		}

	}
	/* Transfer completed at this point */
	reg = readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
	if (msg->ttype == HSI_MSG_WRITE) {
		/* Release clocks for write transfer */
		pm_runtime_mark_last_busy(omap_port->pdev);
		pm_runtime_put_autosuspend(omap_port->pdev);
	}
	reg &= ~val;
	writel_relaxed(reg, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
	writel_relaxed(val, omap_ssi->sys + SSI_MPU_STATUS_REG(port->num, 0));
	list_del(&msg->link);
	spin_unlock_bh(&omap_port->lock);
	msg->complete(msg);
	ssi_transfer(omap_port, queue);
}