1
0
Fork 0

dmaengine: imx-sdma: support allocate memory from iram

Allocate memory from SoC internal SRAM so that we can turn off
voltage of external DDR to save power if 'iram' property in dts.

Signed-off-by: Robin Gong <yibin.gong@nxp.com>
5.4-rM2-2.2.x-imx-squashed
Nicolin Chen 2013-11-05 19:19:07 +08:00 committed by Dong Aisheng
parent 2d1e5b8f23
commit ff3799c817
1 changed files with 45 additions and 15 deletions

View File

@ -24,6 +24,7 @@
#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/genalloc.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/slab.h>
@ -451,6 +452,7 @@ struct sdma_engine {
struct sdma_buffer_descriptor *bd0;
/* clock ratio for AHB:SDMA core. 1:1 is 1, 2:1 is 0*/
bool clk_ratio;
struct gen_pool *iram_pool;
};
static int sdma_config_write(struct dma_chan *chan,
@ -736,10 +738,13 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
int ret;
unsigned long flags;
buf_virt = dma_alloc_coherent(sdma->dev, size, &buf_phys, GFP_KERNEL);
if (!buf_virt) {
if (sdma->iram_pool)
buf_virt = gen_pool_dma_alloc(sdma->iram_pool, size, &buf_phys);
else
buf_virt = dma_alloc_coherent(sdma->dev, size, &buf_phys,
GFP_KERNEL);
if (!buf_virt)
return -ENOMEM;
}
spin_lock_irqsave(&sdma->channel_0_lock, flags);
@ -755,7 +760,10 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
dma_free_coherent(sdma->dev, size, buf_virt, buf_phys);
if (sdma->iram_pool)
gen_pool_free(sdma->iram_pool, (unsigned long)buf_virt, size);
else
dma_free_coherent(sdma->dev, size, buf_virt, buf_phys);
return ret;
}
@ -1250,8 +1258,12 @@ static int sdma_request_channel0(struct sdma_engine *sdma)
{
int ret = -EBUSY;
sdma->bd0 = dma_alloc_coherent(sdma->dev, PAGE_SIZE, &sdma->bd0_phys,
GFP_NOWAIT);
if (sdma->iram_pool)
sdma->bd0 = gen_pool_dma_alloc(sdma->iram_pool, PAGE_SIZE,
&sdma->bd0_phys);
else
sdma->bd0 = dma_alloc_coherent(sdma->dev, PAGE_SIZE,
&sdma->bd0_phys, GFP_NOWAIT);
if (!sdma->bd0) {
ret = -ENOMEM;
goto out;
@ -1271,10 +1283,15 @@ out:
static int sdma_alloc_bd(struct sdma_desc *desc)
{
u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
struct sdma_engine *sdma = desc->sdmac->sdma;
int ret = 0;
desc->bd = dma_alloc_coherent(desc->sdmac->sdma->dev, bd_size,
&desc->bd_phys, GFP_NOWAIT);
if (sdma->iram_pool)
desc->bd = gen_pool_dma_alloc(sdma->iram_pool, PAGE_SIZE,
&desc->bd_phys);
else
desc->bd = dma_alloc_coherent(sdma->dev, bd_size,
&desc->bd_phys, GFP_NOWAIT);
if (!desc->bd) {
ret = -ENOMEM;
goto out;
@ -1286,9 +1303,14 @@ out:
static void sdma_free_bd(struct sdma_desc *desc)
{
u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
struct sdma_engine *sdma = desc->sdmac->sdma;
dma_free_coherent(desc->sdmac->sdma->dev, bd_size, desc->bd,
desc->bd_phys);
if (sdma->iram_pool)
gen_pool_free(sdma->iram_pool, (unsigned long)desc->bd,
PAGE_SIZE);
else
dma_free_coherent(desc->sdmac->sdma->dev, bd_size, desc->bd,
desc->bd_phys);
}
static void sdma_desc_free(struct virt_dma_desc *vd)
@ -1904,7 +1926,7 @@ static int sdma_get_firmware(struct sdma_engine *sdma,
static int sdma_init(struct sdma_engine *sdma)
{
int i, ret;
int i, ret, ccbsize;
dma_addr_t ccb_phys;
ret = clk_enable(sdma->clk_ipg);
@ -1921,11 +1943,15 @@ static int sdma_init(struct sdma_engine *sdma)
/* Be sure SDMA has not started yet */
writel_relaxed(0, sdma->regs + SDMA_H_C0PTR);
sdma->channel_control = dma_alloc_coherent(sdma->dev,
MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) +
sizeof(struct sdma_context_data),
&ccb_phys, GFP_KERNEL);
ccbsize = MAX_DMA_CHANNELS * sizeof(struct sdma_channel_control)
+ sizeof(struct sdma_context_data);
if (sdma->iram_pool)
sdma->channel_control = gen_pool_dma_alloc(sdma->iram_pool,
ccbsize, &ccb_phys);
else
sdma->channel_control = dma_alloc_coherent(sdma->dev, ccbsize,
&ccb_phys, GFP_KERNEL);
if (!sdma->channel_control) {
ret = -ENOMEM;
goto err_dma_alloc;
@ -2179,6 +2205,10 @@ static int sdma_probe(struct platform_device *pdev)
sdma->spba_end_addr = spba_res.end;
}
of_node_put(spba_bus);
sdma->iram_pool = of_gen_pool_get(np, "iram", 0);
if (sdma->iram_pool)
dev_info(&pdev->dev, "alloc bd from iram. \n");
}
/*