[RFC] clk: exynos5420: Make sure MDMA0 clock is enabled during suspend

From: Javier Martinez Canillas
Date: Mon Mar 30 2015 - 11:11:40 EST


Commit ae43b3289186 ("ARM: 8202/1: dmaengine: pl330: Add runtime Power
Management support v12") added pm support for the pl330 dma driver but
it makes the clock for the Exynos5420 MDMA0 DMA controller to be gated
during suspend and this clock needs to remain enabled in order to make
the system resume from a system suspend state.

To make sure that the clock is enabled during suspend, enable it prior
to entering a suspend state and disable it once the system has resumed.

Thanks to Abhilash Kesavan for figuring out that this was the issue.

Fixes: ae43b32 ("ARM: 8202/1: dmaengine: pl330: Add runtime Power Management support v12")
Signed-off-by: Javier Martinez Canillas <javier.martinez@xxxxxxxxxxxxxxx>
---
drivers/clk/samsung/clk-exynos5420.c | 44 ++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)

diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 8b49e8b3b548..02029cf9fcb8 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -155,6 +155,7 @@ static enum exynos5x_soc exynos5x_soc;
#ifdef CONFIG_PM_SLEEP
static struct samsung_clk_reg_dump *exynos5x_save;
static struct samsung_clk_reg_dump *exynos5800_save;
+static struct clk **exynos5x_clks;

/*
* list of controller registers to be saved and restored during a
@@ -275,8 +276,17 @@ static const struct samsung_clk_reg_dump exynos5420_set_clksrc[] = {
{ .offset = GATE_IP_PERIC, .value = 0xffffffff, },
};

+/*
+ * list of clocks that have to be kept enabled during suspend/resume cycle.
+ */
+static const char *exynos5x_clk_pm[] __initdata = {
+ "mdma0",
+};
+
static int exynos5420_clk_suspend(void)
{
+ int i;
+
samsung_clk_save(reg_base, exynos5x_save,
ARRAY_SIZE(exynos5x_clk_regs));

@@ -287,11 +297,19 @@ static int exynos5420_clk_suspend(void)
samsung_clk_restore(reg_base, exynos5420_set_clksrc,
ARRAY_SIZE(exynos5420_set_clksrc));

+ for (i = 0; i < ARRAY_SIZE(exynos5x_clk_pm); i++)
+ clk_prepare_enable(exynos5x_clks[i]);
+
return 0;
}

static void exynos5420_clk_resume(void)
{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(exynos5x_clk_pm); i++)
+ clk_disable_unprepare(exynos5x_clks[i]);
+
samsung_clk_restore(reg_base, exynos5x_save,
ARRAY_SIZE(exynos5x_clk_regs));

@@ -307,6 +325,9 @@ static struct syscore_ops exynos5420_clk_syscore_ops = {

static void exynos5420_clk_sleep_init(void)
{
+ int i;
+ int clk_len = ARRAY_SIZE(exynos5x_clk_pm);
+
exynos5x_save = samsung_clk_alloc_reg_dump(exynos5x_clk_regs,
ARRAY_SIZE(exynos5x_clk_regs));
if (!exynos5x_save) {
@@ -323,8 +344,31 @@ static void exynos5420_clk_sleep_init(void)
goto err_soc;
}

+ exynos5x_clks = kzalloc(sizeof(struct clk *) * clk_len, GFP_KERNEL);
+ if (!exynos5x_clks)
+ goto err_clks;
+
+ for (i = 0; i < clk_len; i++) {
+ exynos5x_clks[i] = clk_get(NULL, exynos5x_clk_pm[i]);
+ if (IS_ERR(exynos5x_clks[i])) {
+ pr_warn("Failed to get %s clk (%ld)\n",
+ exynos5x_clk_pm[i], PTR_ERR(exynos5x_clks[i]));
+
+ while (i--)
+ clk_put(exynos5x_clks[i]);
+
+ goto err_clkget;
+ }
+ }
+
register_syscore_ops(&exynos5420_clk_syscore_ops);
return;
+err_clkget:
+ kfree(exynos5x_clks);
+err_clks:
+ kfree(exynos5800_save);
+ pr_warn("%s: failed to allocate suspend clocks, no sleep support!\n",
+ __func__);
err_soc:
kfree(exynos5x_save);
pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/