Commit 28c7a19d authored by Narayanan G's avatar Narayanan G Committed by Vinod Koul
Browse files

dmaengine/ste_dma40: Add support to use lcla area from esram



This patch provides an option of having the lcla (link address)
in ESRAM instead of allocating it. The bool value (use_esram_lcla)
in the stedma40_platform_data if set to true, then the lcla
address would be taken from platform resources. Also, the
corresponding esram regulator is managed in the
suspend/resume functions.

Signed-off-by: default avatarNarayanan G <narayanan.gopalakrishnan@stericsson.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@linux.intel.com>
parent d5613947
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ struct stedma40_platform_data {
	struct stedma40_chan_cfg	*memcpy_conf_phy;
	struct stedma40_chan_cfg	*memcpy_conf_log;
	int				 disabled_channels[STEDMA40_MAX_PHYS];
	bool				 use_esram_lcla;
};

#ifdef CONFIG_STE_DMA40
+85 −10
Original line number Diff line number Diff line
@@ -304,6 +304,7 @@ struct d40_chan {
 * to phy_chans entries.
 * @plat_data: Pointer to provided platform_data which is the driver
 * configuration.
 * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla.
 * @phy_res: Vector containing all physical channels.
 * @lcla_pool: lcla pool settings and data.
 * @lcpa_base: The virtual mapped address of LCPA.
@@ -338,6 +339,7 @@ struct d40_base {
	struct d40_chan			**lookup_log_chans;
	struct d40_chan			**lookup_phy_chans;
	struct stedma40_platform_data	 *plat_data;
	struct regulator		 *lcpa_regulator;
	/* Physical half channels */
	struct d40_phy_res		 *phy_res;
	struct d40_lcla_pool		  lcla_pool;
@@ -605,6 +607,7 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
	bool cyclic = desc->cyclic;
	int curr_lcla = -EINVAL;
	int first_lcla = 0;
	bool use_esram_lcla = chan->base->plat_data->use_esram_lcla;
	bool linkback;

	/*
@@ -677,11 +680,16 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
				       &lli->src[lli_current],
				       next_lcla, flags);

		/*
		 * Cache maintenance is not needed if lcla is
		 * mapped in esram
		 */
		if (!use_esram_lcla) {
			dma_sync_single_range_for_device(chan->base->dev,
						pool->dma_addr, lcla_offset,
						2 * sizeof(struct d40_log_lli),
						DMA_TO_DEVICE);

		}
		curr_lcla = next_lcla;

		if (curr_lcla == -EINVAL || curr_lcla == first_lcla) {
@@ -2668,10 +2676,15 @@ failure1:
#ifdef CONFIG_PM
static int dma40_pm_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct d40_base *base = platform_get_drvdata(pdev);
	int ret = 0;
	if (!pm_runtime_suspended(dev))
		return -EBUSY;

	return 0;
	if (base->lcpa_regulator)
		ret = regulator_disable(base->lcpa_regulator);
	return ret;
}

static int dma40_runtime_suspend(struct device *dev)
@@ -2702,11 +2715,23 @@ static int dma40_runtime_resume(struct device *dev)
	return 0;
}

static int dma40_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct d40_base *base = platform_get_drvdata(pdev);
	int ret = 0;

	if (base->lcpa_regulator)
		ret = regulator_enable(base->lcpa_regulator);

	return ret;
}

static const struct dev_pm_ops dma40_pm_ops = {
	.suspend		= dma40_pm_suspend,
	.runtime_suspend	= dma40_runtime_suspend,
	.runtime_resume		= dma40_runtime_resume,
	.resume			= dma40_resume,
};
#define DMA40_PM_OPS	(&dma40_pm_ops)
#else
@@ -3165,12 +3190,32 @@ static int __init d40_probe(struct platform_device *pdev)
		d40_err(&pdev->dev, "Failed to ioremap LCPA region\n");
		goto failure;
	}
	/* If lcla has to be located in ESRAM we don't need to allocate */
	if (base->plat_data->use_esram_lcla) {
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
							"lcla_esram");
		if (!res) {
			ret = -ENOENT;
			d40_err(&pdev->dev,
				"No \"lcla_esram\" memory resource\n");
			goto failure;
		}
		base->lcla_pool.base = ioremap(res->start,
						resource_size(res));
		if (!base->lcla_pool.base) {
			ret = -ENOMEM;
			d40_err(&pdev->dev, "Failed to ioremap LCLA region\n");
			goto failure;
		}
		writel(res->start, base->virtbase + D40_DREG_LCLA);

	} else {
		ret = d40_lcla_allocate(base);
		if (ret) {
			d40_err(&pdev->dev, "Failed to allocate LCLA area\n");
			goto failure;
		}
	}

	spin_lock_init(&base->lcla_pool.lock);

@@ -3187,6 +3232,26 @@ static int __init d40_probe(struct platform_device *pdev)
	pm_runtime_use_autosuspend(base->dev);
	pm_runtime_enable(base->dev);
	pm_runtime_resume(base->dev);

	if (base->plat_data->use_esram_lcla) {

		base->lcpa_regulator = regulator_get(base->dev, "lcla_esram");
		if (IS_ERR(base->lcpa_regulator)) {
			d40_err(&pdev->dev, "Failed to get lcpa_regulator\n");
			base->lcpa_regulator = NULL;
			goto failure;
		}

		ret = regulator_enable(base->lcpa_regulator);
		if (ret) {
			d40_err(&pdev->dev,
				"Failed to enable lcpa_regulator\n");
			regulator_put(base->lcpa_regulator);
			base->lcpa_regulator = NULL;
			goto failure;
		}
	}

	base->initialized = true;
	err = d40_dmaengine_init(base, num_reserved_chans);
	if (err)
@@ -3204,6 +3269,11 @@ failure:
		if (base->virtbase)
			iounmap(base->virtbase);

		if (base->lcla_pool.base && base->plat_data->use_esram_lcla) {
			iounmap(base->lcla_pool.base);
			base->lcla_pool.base = NULL;
		}

		if (base->lcla_pool.dma_addr)
			dma_unmap_single(base->dev, base->lcla_pool.dma_addr,
					 SZ_1K * base->num_phy_chans,
@@ -3226,6 +3296,11 @@ failure:
			clk_put(base->clk);
		}

		if (base->lcpa_regulator) {
			regulator_disable(base->lcpa_regulator);
			regulator_put(base->lcpa_regulator);
		}

		kfree(base->lcla_pool.alloc_map);
		kfree(base->lookup_log_chans);
		kfree(base->lookup_phy_chans);