Merge branch 'fix/edma' into fixes
This commit is contained in:
Коммит
956e6c8e18
|
@ -1238,6 +1238,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
|
||||||
struct edma_desc *edesc;
|
struct edma_desc *edesc;
|
||||||
dma_addr_t src_addr, dst_addr;
|
dma_addr_t src_addr, dst_addr;
|
||||||
enum dma_slave_buswidth dev_width;
|
enum dma_slave_buswidth dev_width;
|
||||||
|
bool use_intermediate = false;
|
||||||
u32 burst;
|
u32 burst;
|
||||||
int i, ret, nslots;
|
int i, ret, nslots;
|
||||||
|
|
||||||
|
@ -1279,8 +1280,21 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
|
||||||
* but the synchronization is difficult to achieve with Cyclic and
|
* but the synchronization is difficult to achieve with Cyclic and
|
||||||
* cannot be guaranteed, so we error out early.
|
* cannot be guaranteed, so we error out early.
|
||||||
*/
|
*/
|
||||||
if (nslots > MAX_NR_SG)
|
if (nslots > MAX_NR_SG) {
|
||||||
return NULL;
|
/*
|
||||||
|
* If the burst and period sizes are the same, we can put
|
||||||
|
* the full buffer into a single period and activate
|
||||||
|
* intermediate interrupts. This will produce interrupts
|
||||||
|
* after each burst, which is also after each desired period.
|
||||||
|
*/
|
||||||
|
if (burst == period_len) {
|
||||||
|
period_len = buf_len;
|
||||||
|
nslots = 2;
|
||||||
|
use_intermediate = true;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]),
|
edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]),
|
||||||
GFP_ATOMIC);
|
GFP_ATOMIC);
|
||||||
|
@ -1358,8 +1372,13 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
|
||||||
/*
|
/*
|
||||||
* Enable period interrupt only if it is requested
|
* Enable period interrupt only if it is requested
|
||||||
*/
|
*/
|
||||||
if (tx_flags & DMA_PREP_INTERRUPT)
|
if (tx_flags & DMA_PREP_INTERRUPT) {
|
||||||
edesc->pset[i].param.opt |= TCINTEN;
|
edesc->pset[i].param.opt |= TCINTEN;
|
||||||
|
|
||||||
|
/* Also enable intermediate interrupts if necessary */
|
||||||
|
if (use_intermediate)
|
||||||
|
edesc->pset[i].param.opt |= ITCINTEN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Place the cyclic channel to highest priority queue */
|
/* Place the cyclic channel to highest priority queue */
|
||||||
|
@ -1570,32 +1589,6 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void edma_tc_set_pm_state(struct edma_tc *tc, bool enable)
|
|
||||||
{
|
|
||||||
struct platform_device *tc_pdev;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_OF) || !tc)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tc_pdev = of_find_device_by_node(tc->node);
|
|
||||||
if (!tc_pdev) {
|
|
||||||
pr_err("%s: TPTC device is not found\n", __func__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!pm_runtime_enabled(&tc_pdev->dev))
|
|
||||||
pm_runtime_enable(&tc_pdev->dev);
|
|
||||||
|
|
||||||
if (enable)
|
|
||||||
ret = pm_runtime_get_sync(&tc_pdev->dev);
|
|
||||||
else
|
|
||||||
ret = pm_runtime_put_sync(&tc_pdev->dev);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
pr_err("%s: pm_runtime_%s_sync() failed for %s\n", __func__,
|
|
||||||
enable ? "get" : "put", dev_name(&tc_pdev->dev));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Alloc channel resources */
|
/* Alloc channel resources */
|
||||||
static int edma_alloc_chan_resources(struct dma_chan *chan)
|
static int edma_alloc_chan_resources(struct dma_chan *chan)
|
||||||
{
|
{
|
||||||
|
@ -1632,8 +1625,6 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
|
||||||
EDMA_CHAN_SLOT(echan->ch_num), chan->chan_id,
|
EDMA_CHAN_SLOT(echan->ch_num), chan->chan_id,
|
||||||
echan->hw_triggered ? "HW" : "SW");
|
echan->hw_triggered ? "HW" : "SW");
|
||||||
|
|
||||||
edma_tc_set_pm_state(echan->tc, true);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_slot:
|
err_slot:
|
||||||
|
@ -1670,7 +1661,6 @@ static void edma_free_chan_resources(struct dma_chan *chan)
|
||||||
echan->alloced = false;
|
echan->alloced = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
edma_tc_set_pm_state(echan->tc, false);
|
|
||||||
echan->tc = NULL;
|
echan->tc = NULL;
|
||||||
echan->hw_triggered = false;
|
echan->hw_triggered = false;
|
||||||
|
|
||||||
|
@ -2417,10 +2407,8 @@ static int edma_pm_suspend(struct device *dev)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ecc->num_channels; i++) {
|
for (i = 0; i < ecc->num_channels; i++) {
|
||||||
if (echan[i].alloced) {
|
if (echan[i].alloced)
|
||||||
edma_setup_interrupt(&echan[i], false);
|
edma_setup_interrupt(&echan[i], false);
|
||||||
edma_tc_set_pm_state(echan[i].tc, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2450,8 +2438,6 @@ static int edma_pm_resume(struct device *dev)
|
||||||
|
|
||||||
/* Set up channel -> slot mapping for the entry slot */
|
/* Set up channel -> slot mapping for the entry slot */
|
||||||
edma_set_chmap(&echan[i], echan[i].slot[0]);
|
edma_set_chmap(&echan[i], echan[i].slot[0]);
|
||||||
|
|
||||||
edma_tc_set_pm_state(echan[i].tc, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2475,7 +2461,8 @@ static struct platform_driver edma_driver = {
|
||||||
|
|
||||||
static int edma_tptc_probe(struct platform_device *pdev)
|
static int edma_tptc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
return 0;
|
pm_runtime_enable(&pdev->dev);
|
||||||
|
return pm_runtime_get_sync(&pdev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver edma_tptc_driver = {
|
static struct platform_driver edma_tptc_driver = {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче