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;
}