diff options
author | Narayanan G <narayanan.gopalakrishnan@stericsson.com> | 2011-11-22 03:26:55 -0500 |
---|---|---|
committer | Vinod Koul <vinod.koul@linux.intel.com> | 2011-11-27 22:30:08 -0500 |
commit | 28c7a19d230228ab9ae61c300c5003a2400fadd3 (patch) | |
tree | d66f1e8a74528afc4226df129dcaf5f3abb97f1d /drivers/dma/ste_dma40.c | |
parent | d5613947addb1e1096a3be29dfe817905e385469 (diff) |
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: Narayanan G <narayanan.gopalakrishnan@stericsson.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Diffstat (limited to 'drivers/dma/ste_dma40.c')
-rw-r--r-- | drivers/dma/ste_dma40.c | 95 |
1 files changed, 85 insertions, 10 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index c2cf8cfaf7d4..aff128a39a4b 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
@@ -304,6 +304,7 @@ struct d40_chan { | |||
304 | * to phy_chans entries. | 304 | * to phy_chans entries. |
305 | * @plat_data: Pointer to provided platform_data which is the driver | 305 | * @plat_data: Pointer to provided platform_data which is the driver |
306 | * configuration. | 306 | * configuration. |
307 | * @lcpa_regulator: Pointer to hold the regulator for the esram bank for lcla. | ||
307 | * @phy_res: Vector containing all physical channels. | 308 | * @phy_res: Vector containing all physical channels. |
308 | * @lcla_pool: lcla pool settings and data. | 309 | * @lcla_pool: lcla pool settings and data. |
309 | * @lcpa_base: The virtual mapped address of LCPA. | 310 | * @lcpa_base: The virtual mapped address of LCPA. |
@@ -338,6 +339,7 @@ struct d40_base { | |||
338 | struct d40_chan **lookup_log_chans; | 339 | struct d40_chan **lookup_log_chans; |
339 | struct d40_chan **lookup_phy_chans; | 340 | struct d40_chan **lookup_phy_chans; |
340 | struct stedma40_platform_data *plat_data; | 341 | struct stedma40_platform_data *plat_data; |
342 | struct regulator *lcpa_regulator; | ||
341 | /* Physical half channels */ | 343 | /* Physical half channels */ |
342 | struct d40_phy_res *phy_res; | 344 | struct d40_phy_res *phy_res; |
343 | struct d40_lcla_pool lcla_pool; | 345 | 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) | |||
605 | bool cyclic = desc->cyclic; | 607 | bool cyclic = desc->cyclic; |
606 | int curr_lcla = -EINVAL; | 608 | int curr_lcla = -EINVAL; |
607 | int first_lcla = 0; | 609 | int first_lcla = 0; |
610 | bool use_esram_lcla = chan->base->plat_data->use_esram_lcla; | ||
608 | bool linkback; | 611 | bool linkback; |
609 | 612 | ||
610 | /* | 613 | /* |
@@ -677,11 +680,16 @@ static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc) | |||
677 | &lli->src[lli_current], | 680 | &lli->src[lli_current], |
678 | next_lcla, flags); | 681 | next_lcla, flags); |
679 | 682 | ||
680 | dma_sync_single_range_for_device(chan->base->dev, | 683 | /* |
681 | pool->dma_addr, lcla_offset, | 684 | * Cache maintenance is not needed if lcla is |
682 | 2 * sizeof(struct d40_log_lli), | 685 | * mapped in esram |
683 | DMA_TO_DEVICE); | 686 | */ |
684 | 687 | if (!use_esram_lcla) { | |
688 | dma_sync_single_range_for_device(chan->base->dev, | ||
689 | pool->dma_addr, lcla_offset, | ||
690 | 2 * sizeof(struct d40_log_lli), | ||
691 | DMA_TO_DEVICE); | ||
692 | } | ||
685 | curr_lcla = next_lcla; | 693 | curr_lcla = next_lcla; |
686 | 694 | ||
687 | if (curr_lcla == -EINVAL || curr_lcla == first_lcla) { | 695 | if (curr_lcla == -EINVAL || curr_lcla == first_lcla) { |
@@ -2668,10 +2676,15 @@ failure1: | |||
2668 | #ifdef CONFIG_PM | 2676 | #ifdef CONFIG_PM |
2669 | static int dma40_pm_suspend(struct device *dev) | 2677 | static int dma40_pm_suspend(struct device *dev) |
2670 | { | 2678 | { |
2679 | struct platform_device *pdev = to_platform_device(dev); | ||
2680 | struct d40_base *base = platform_get_drvdata(pdev); | ||
2681 | int ret = 0; | ||
2671 | if (!pm_runtime_suspended(dev)) | 2682 | if (!pm_runtime_suspended(dev)) |
2672 | return -EBUSY; | 2683 | return -EBUSY; |
2673 | 2684 | ||
2674 | return 0; | 2685 | if (base->lcpa_regulator) |
2686 | ret = regulator_disable(base->lcpa_regulator); | ||
2687 | return ret; | ||
2675 | } | 2688 | } |
2676 | 2689 | ||
2677 | static int dma40_runtime_suspend(struct device *dev) | 2690 | static int dma40_runtime_suspend(struct device *dev) |
@@ -2702,11 +2715,23 @@ static int dma40_runtime_resume(struct device *dev) | |||
2702 | return 0; | 2715 | return 0; |
2703 | } | 2716 | } |
2704 | 2717 | ||
2718 | static int dma40_resume(struct device *dev) | ||
2719 | { | ||
2720 | struct platform_device *pdev = to_platform_device(dev); | ||
2721 | struct d40_base *base = platform_get_drvdata(pdev); | ||
2722 | int ret = 0; | ||
2723 | |||
2724 | if (base->lcpa_regulator) | ||
2725 | ret = regulator_enable(base->lcpa_regulator); | ||
2726 | |||
2727 | return ret; | ||
2728 | } | ||
2705 | 2729 | ||
2706 | static const struct dev_pm_ops dma40_pm_ops = { | 2730 | static const struct dev_pm_ops dma40_pm_ops = { |
2707 | .suspend = dma40_pm_suspend, | 2731 | .suspend = dma40_pm_suspend, |
2708 | .runtime_suspend = dma40_runtime_suspend, | 2732 | .runtime_suspend = dma40_runtime_suspend, |
2709 | .runtime_resume = dma40_runtime_resume, | 2733 | .runtime_resume = dma40_runtime_resume, |
2734 | .resume = dma40_resume, | ||
2710 | }; | 2735 | }; |
2711 | #define DMA40_PM_OPS (&dma40_pm_ops) | 2736 | #define DMA40_PM_OPS (&dma40_pm_ops) |
2712 | #else | 2737 | #else |
@@ -3165,11 +3190,31 @@ static int __init d40_probe(struct platform_device *pdev) | |||
3165 | d40_err(&pdev->dev, "Failed to ioremap LCPA region\n"); | 3190 | d40_err(&pdev->dev, "Failed to ioremap LCPA region\n"); |
3166 | goto failure; | 3191 | goto failure; |
3167 | } | 3192 | } |
3193 | /* If lcla has to be located in ESRAM we don't need to allocate */ | ||
3194 | if (base->plat_data->use_esram_lcla) { | ||
3195 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
3196 | "lcla_esram"); | ||
3197 | if (!res) { | ||
3198 | ret = -ENOENT; | ||
3199 | d40_err(&pdev->dev, | ||
3200 | "No \"lcla_esram\" memory resource\n"); | ||
3201 | goto failure; | ||
3202 | } | ||
3203 | base->lcla_pool.base = ioremap(res->start, | ||
3204 | resource_size(res)); | ||
3205 | if (!base->lcla_pool.base) { | ||
3206 | ret = -ENOMEM; | ||
3207 | d40_err(&pdev->dev, "Failed to ioremap LCLA region\n"); | ||
3208 | goto failure; | ||
3209 | } | ||
3210 | writel(res->start, base->virtbase + D40_DREG_LCLA); | ||
3168 | 3211 | ||
3169 | ret = d40_lcla_allocate(base); | 3212 | } else { |
3170 | if (ret) { | 3213 | ret = d40_lcla_allocate(base); |
3171 | d40_err(&pdev->dev, "Failed to allocate LCLA area\n"); | 3214 | if (ret) { |
3172 | goto failure; | 3215 | d40_err(&pdev->dev, "Failed to allocate LCLA area\n"); |
3216 | goto failure; | ||
3217 | } | ||
3173 | } | 3218 | } |
3174 | 3219 | ||
3175 | spin_lock_init(&base->lcla_pool.lock); | 3220 | spin_lock_init(&base->lcla_pool.lock); |
@@ -3187,6 +3232,26 @@ static int __init d40_probe(struct platform_device *pdev) | |||
3187 | pm_runtime_use_autosuspend(base->dev); | 3232 | pm_runtime_use_autosuspend(base->dev); |
3188 | pm_runtime_enable(base->dev); | 3233 | pm_runtime_enable(base->dev); |
3189 | pm_runtime_resume(base->dev); | 3234 | pm_runtime_resume(base->dev); |
3235 | |||
3236 | if (base->plat_data->use_esram_lcla) { | ||
3237 | |||
3238 | base->lcpa_regulator = regulator_get(base->dev, "lcla_esram"); | ||
3239 | if (IS_ERR(base->lcpa_regulator)) { | ||
3240 | d40_err(&pdev->dev, "Failed to get lcpa_regulator\n"); | ||
3241 | base->lcpa_regulator = NULL; | ||
3242 | goto failure; | ||
3243 | } | ||
3244 | |||
3245 | ret = regulator_enable(base->lcpa_regulator); | ||
3246 | if (ret) { | ||
3247 | d40_err(&pdev->dev, | ||
3248 | "Failed to enable lcpa_regulator\n"); | ||
3249 | regulator_put(base->lcpa_regulator); | ||
3250 | base->lcpa_regulator = NULL; | ||
3251 | goto failure; | ||
3252 | } | ||
3253 | } | ||
3254 | |||
3190 | base->initialized = true; | 3255 | base->initialized = true; |
3191 | err = d40_dmaengine_init(base, num_reserved_chans); | 3256 | err = d40_dmaengine_init(base, num_reserved_chans); |
3192 | if (err) | 3257 | if (err) |
@@ -3204,6 +3269,11 @@ failure: | |||
3204 | if (base->virtbase) | 3269 | if (base->virtbase) |
3205 | iounmap(base->virtbase); | 3270 | iounmap(base->virtbase); |
3206 | 3271 | ||
3272 | if (base->lcla_pool.base && base->plat_data->use_esram_lcla) { | ||
3273 | iounmap(base->lcla_pool.base); | ||
3274 | base->lcla_pool.base = NULL; | ||
3275 | } | ||
3276 | |||
3207 | if (base->lcla_pool.dma_addr) | 3277 | if (base->lcla_pool.dma_addr) |
3208 | dma_unmap_single(base->dev, base->lcla_pool.dma_addr, | 3278 | dma_unmap_single(base->dev, base->lcla_pool.dma_addr, |
3209 | SZ_1K * base->num_phy_chans, | 3279 | SZ_1K * base->num_phy_chans, |
@@ -3226,6 +3296,11 @@ failure: | |||
3226 | clk_put(base->clk); | 3296 | clk_put(base->clk); |
3227 | } | 3297 | } |
3228 | 3298 | ||
3299 | if (base->lcpa_regulator) { | ||
3300 | regulator_disable(base->lcpa_regulator); | ||
3301 | regulator_put(base->lcpa_regulator); | ||
3302 | } | ||
3303 | |||
3229 | kfree(base->lcla_pool.alloc_map); | 3304 | kfree(base->lcla_pool.alloc_map); |
3230 | kfree(base->lookup_log_chans); | 3305 | kfree(base->lookup_log_chans); |
3231 | kfree(base->lookup_phy_chans); | 3306 | kfree(base->lookup_phy_chans); |