mirror of https://gitee.com/openkylin/linux.git
dmaengine: pl08x: Split device_control
Split the device_control callback of the AMBA PL08x DMA driver to make use of the newly introduced callbacks, that will eventually be used to retrieve slave capabilities. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
This commit is contained in:
parent
cb8cea513c
commit
bcd1b0b901
|
@ -1386,32 +1386,6 @@ static u32 pl08x_get_cctl(struct pl08x_dma_chan *plchan,
|
||||||
return pl08x_cctl(cctl);
|
return pl08x_cctl(cctl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dma_set_runtime_config(struct dma_chan *chan,
|
|
||||||
struct dma_slave_config *config)
|
|
||||||
{
|
|
||||||
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
|
|
||||||
struct pl08x_driver_data *pl08x = plchan->host;
|
|
||||||
|
|
||||||
if (!plchan->slave)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* Reject definitely invalid configurations */
|
|
||||||
if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
|
|
||||||
config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (config->device_fc && pl08x->vd->pl080s) {
|
|
||||||
dev_err(&pl08x->adev->dev,
|
|
||||||
"%s: PL080S does not support peripheral flow control\n",
|
|
||||||
__func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
plchan->cfg = *config;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Slave transactions callback to the slave device to allow
|
* Slave transactions callback to the slave device to allow
|
||||||
* synchronization of slave DMA signals with the DMAC enable
|
* synchronization of slave DMA signals with the DMAC enable
|
||||||
|
@ -1693,20 +1667,71 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_cyclic(
|
||||||
return vchan_tx_prep(&plchan->vc, &txd->vd, flags);
|
return vchan_tx_prep(&plchan->vc, &txd->vd, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
|
static int pl08x_config(struct dma_chan *chan,
|
||||||
unsigned long arg)
|
struct dma_slave_config *config)
|
||||||
|
{
|
||||||
|
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
|
||||||
|
struct pl08x_driver_data *pl08x = plchan->host;
|
||||||
|
|
||||||
|
if (!plchan->slave)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Reject definitely invalid configurations */
|
||||||
|
if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
|
||||||
|
config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (config->device_fc && pl08x->vd->pl080s) {
|
||||||
|
dev_err(&pl08x->adev->dev,
|
||||||
|
"%s: PL080S does not support peripheral flow control\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
plchan->cfg = *config;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pl08x_terminate_all(struct dma_chan *chan)
|
||||||
{
|
{
|
||||||
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
|
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
|
||||||
struct pl08x_driver_data *pl08x = plchan->host;
|
struct pl08x_driver_data *pl08x = plchan->host;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
/* Controls applicable to inactive channels */
|
spin_lock_irqsave(&plchan->vc.lock, flags);
|
||||||
if (cmd == DMA_SLAVE_CONFIG) {
|
if (!plchan->phychan && !plchan->at) {
|
||||||
return dma_set_runtime_config(chan,
|
spin_unlock_irqrestore(&plchan->vc.lock, flags);
|
||||||
(struct dma_slave_config *)arg);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plchan->state = PL08X_CHAN_IDLE;
|
||||||
|
|
||||||
|
if (plchan->phychan) {
|
||||||
|
/*
|
||||||
|
* Mark physical channel as free and free any slave
|
||||||
|
* signal
|
||||||
|
*/
|
||||||
|
pl08x_phy_free(plchan);
|
||||||
|
}
|
||||||
|
/* Dequeue jobs and free LLIs */
|
||||||
|
if (plchan->at) {
|
||||||
|
pl08x_desc_free(&plchan->at->vd);
|
||||||
|
plchan->at = NULL;
|
||||||
|
}
|
||||||
|
/* Dequeue jobs not yet fired as well */
|
||||||
|
pl08x_free_txd_list(pl08x, plchan);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&plchan->vc.lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pl08x_pause(struct dma_chan *chan)
|
||||||
|
{
|
||||||
|
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Anything succeeds on channels with no physical allocation and
|
* Anything succeeds on channels with no physical allocation and
|
||||||
* no queued transfers.
|
* no queued transfers.
|
||||||
|
@ -1717,42 +1742,35 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
pl08x_pause_phy_chan(plchan->phychan);
|
||||||
case DMA_TERMINATE_ALL:
|
plchan->state = PL08X_CHAN_PAUSED;
|
||||||
plchan->state = PL08X_CHAN_IDLE;
|
|
||||||
|
|
||||||
if (plchan->phychan) {
|
|
||||||
/*
|
|
||||||
* Mark physical channel as free and free any slave
|
|
||||||
* signal
|
|
||||||
*/
|
|
||||||
pl08x_phy_free(plchan);
|
|
||||||
}
|
|
||||||
/* Dequeue jobs and free LLIs */
|
|
||||||
if (plchan->at) {
|
|
||||||
pl08x_desc_free(&plchan->at->vd);
|
|
||||||
plchan->at = NULL;
|
|
||||||
}
|
|
||||||
/* Dequeue jobs not yet fired as well */
|
|
||||||
pl08x_free_txd_list(pl08x, plchan);
|
|
||||||
break;
|
|
||||||
case DMA_PAUSE:
|
|
||||||
pl08x_pause_phy_chan(plchan->phychan);
|
|
||||||
plchan->state = PL08X_CHAN_PAUSED;
|
|
||||||
break;
|
|
||||||
case DMA_RESUME:
|
|
||||||
pl08x_resume_phy_chan(plchan->phychan);
|
|
||||||
plchan->state = PL08X_CHAN_RUNNING;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Unknown command */
|
|
||||||
ret = -ENXIO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&plchan->vc.lock, flags);
|
spin_unlock_irqrestore(&plchan->vc.lock, flags);
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pl08x_resume(struct dma_chan *chan)
|
||||||
|
{
|
||||||
|
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Anything succeeds on channels with no physical allocation and
|
||||||
|
* no queued transfers.
|
||||||
|
*/
|
||||||
|
spin_lock_irqsave(&plchan->vc.lock, flags);
|
||||||
|
if (!plchan->phychan && !plchan->at) {
|
||||||
|
spin_unlock_irqrestore(&plchan->vc.lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl08x_resume_phy_chan(plchan->phychan);
|
||||||
|
plchan->state = PL08X_CHAN_RUNNING;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&plchan->vc.lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
|
bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
|
||||||
|
@ -2048,7 +2066,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
|
||||||
pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
|
pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
|
||||||
pl08x->memcpy.device_tx_status = pl08x_dma_tx_status;
|
pl08x->memcpy.device_tx_status = pl08x_dma_tx_status;
|
||||||
pl08x->memcpy.device_issue_pending = pl08x_issue_pending;
|
pl08x->memcpy.device_issue_pending = pl08x_issue_pending;
|
||||||
pl08x->memcpy.device_control = pl08x_control;
|
pl08x->memcpy.device_config = pl08x_config;
|
||||||
|
pl08x->memcpy.device_pause = pl08x_pause;
|
||||||
|
pl08x->memcpy.device_resume = pl08x_resume;
|
||||||
|
pl08x->memcpy.device_terminate_all = pl08x_terminate_all;
|
||||||
|
|
||||||
/* Initialize slave engine */
|
/* Initialize slave engine */
|
||||||
dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
|
dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
|
||||||
|
@ -2061,7 +2082,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
|
||||||
pl08x->slave.device_issue_pending = pl08x_issue_pending;
|
pl08x->slave.device_issue_pending = pl08x_issue_pending;
|
||||||
pl08x->slave.device_prep_slave_sg = pl08x_prep_slave_sg;
|
pl08x->slave.device_prep_slave_sg = pl08x_prep_slave_sg;
|
||||||
pl08x->slave.device_prep_dma_cyclic = pl08x_prep_dma_cyclic;
|
pl08x->slave.device_prep_dma_cyclic = pl08x_prep_dma_cyclic;
|
||||||
pl08x->slave.device_control = pl08x_control;
|
pl08x->slave.device_config = pl08x_config;
|
||||||
|
pl08x->slave.device_pause = pl08x_pause;
|
||||||
|
pl08x->slave.device_resume = pl08x_resume;
|
||||||
|
pl08x->slave.device_terminate_all = pl08x_terminate_all;
|
||||||
|
|
||||||
/* Get the platform data */
|
/* Get the platform data */
|
||||||
pl08x->pd = dev_get_platdata(&adev->dev);
|
pl08x->pd = dev_get_platdata(&adev->dev);
|
||||||
|
|
Loading…
Reference in New Issue