static int ssi_start_dma()

in controllers/omap_ssi_port.c [207:284]


static int ssi_start_dma(struct hsi_msg *msg, int lch)
{
	struct hsi_port *port = hsi_get_port(msg->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);
	void __iomem *gdd = omap_ssi->gdd;
	int err;
	u16 csdp;
	u16 ccr;
	u32 s_addr;
	u32 d_addr;
	u32 tmp;

	/* Hold clocks during the transfer */
	pm_runtime_get(omap_port->pdev);

	if (!pm_runtime_active(omap_port->pdev)) {
		dev_warn(&port->device, "ssi_start_dma called without runtime PM!\n");
		pm_runtime_put_autosuspend(omap_port->pdev);
		return -EREMOTEIO;
	}

	if (msg->ttype == HSI_MSG_READ) {
		err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents,
							DMA_FROM_DEVICE);
		if (err < 0) {
			dev_dbg(&ssi->device, "DMA map SG failed !\n");
			pm_runtime_put_autosuspend(omap_port->pdev);
			return err;
		}
		csdp = SSI_DST_BURST_4x32_BIT | SSI_DST_MEMORY_PORT |
			SSI_SRC_SINGLE_ACCESS0 | SSI_SRC_PERIPHERAL_PORT |
			SSI_DATA_TYPE_S32;
		ccr = msg->channel + 0x10 + (port->num * 8); /* Sync */
		ccr |= SSI_DST_AMODE_POSTINC | SSI_SRC_AMODE_CONST |
			SSI_CCR_ENABLE;
		s_addr = omap_port->ssr_dma +
					SSI_SSR_BUFFER_CH_REG(msg->channel);
		d_addr = sg_dma_address(msg->sgt.sgl);
	} else {
		err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents,
							DMA_TO_DEVICE);
		if (err < 0) {
			dev_dbg(&ssi->device, "DMA map SG failed !\n");
			pm_runtime_put_autosuspend(omap_port->pdev);
			return err;
		}
		csdp = SSI_SRC_BURST_4x32_BIT | SSI_SRC_MEMORY_PORT |
			SSI_DST_SINGLE_ACCESS0 | SSI_DST_PERIPHERAL_PORT |
			SSI_DATA_TYPE_S32;
		ccr = (msg->channel + 1 + (port->num * 8)) & 0xf; /* Sync */
		ccr |= SSI_SRC_AMODE_POSTINC | SSI_DST_AMODE_CONST |
			SSI_CCR_ENABLE;
		s_addr = sg_dma_address(msg->sgt.sgl);
		d_addr = omap_port->sst_dma +
					SSI_SST_BUFFER_CH_REG(msg->channel);
	}
	dev_dbg(&ssi->device, "lch %d cdsp %08x ccr %04x s_addr %08x d_addr %08x\n",
		lch, csdp, ccr, s_addr, d_addr);

	writew_relaxed(csdp, gdd + SSI_GDD_CSDP_REG(lch));
	writew_relaxed(SSI_BLOCK_IE | SSI_TOUT_IE, gdd + SSI_GDD_CICR_REG(lch));
	writel_relaxed(d_addr, gdd + SSI_GDD_CDSA_REG(lch));
	writel_relaxed(s_addr, gdd + SSI_GDD_CSSA_REG(lch));
	writew_relaxed(SSI_BYTES_TO_FRAMES(msg->sgt.sgl->length),
						gdd + SSI_GDD_CEN_REG(lch));

	spin_lock_bh(&omap_ssi->lock);
	tmp = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
	tmp |= SSI_GDD_LCH(lch);
	writel_relaxed(tmp, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
	spin_unlock_bh(&omap_ssi->lock);
	writew(ccr, gdd + SSI_GDD_CCR_REG(lch));
	msg->status = HSI_STATUS_PROCEEDING;

	return 0;
}