Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fcf47e2 authored by Tomasz Figa's avatar Tomasz Figa Committed by Kukjin Kim
Browse files

clk: samsung: exynos4: Add remaining suspend/resume handling



As of now, part of Exynos4 clock suspend/resume handling is located
in mach-exynos/pm.c, which is not where code accessing CMU registers
should reside.

This patch implements all the necessary suspend/resume handling code
in Exynos4 clock driver to allow dropping that old code.

Signed-off-by: default avatarTomasz Figa <t.figa@samsung.com>
Acked-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: default avatarThomas Abraham <thomas.ab@samsung.com>
Reviewed-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKukjin Kim <kgene.kim@samsung.com>
parent 3efb2511
Loading
Loading
Loading
Loading
+68 −8
Original line number Original line Diff line number Diff line
@@ -140,6 +140,7 @@ static enum exynos4_soc exynos4_soc;
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM_SLEEP
static struct samsung_clk_reg_dump *exynos4_save_common;
static struct samsung_clk_reg_dump *exynos4_save_common;
static struct samsung_clk_reg_dump *exynos4_save_soc;
static struct samsung_clk_reg_dump *exynos4_save_soc;
static struct samsung_clk_reg_dump *exynos4_save_pll;


/*
/*
 * list of controller registers to be saved and restored during a
 * list of controller registers to be saved and restored during a
@@ -165,6 +166,17 @@ static unsigned long exynos4x12_clk_save[] __initdata = {
	E4X12_MPLL_CON0,
	E4X12_MPLL_CON0,
};
};


static unsigned long exynos4_clk_pll_regs[] __initdata = {
	EPLL_LOCK,
	VPLL_LOCK,
	EPLL_CON0,
	EPLL_CON1,
	EPLL_CON2,
	VPLL_CON0,
	VPLL_CON1,
	VPLL_CON2,
};

static unsigned long exynos4_clk_regs[] __initdata = {
static unsigned long exynos4_clk_regs[] __initdata = {
	SRC_LEFTBUS,
	SRC_LEFTBUS,
	DIV_LEFTBUS,
	DIV_LEFTBUS,
@@ -172,12 +184,6 @@ static unsigned long exynos4_clk_regs[] __initdata = {
	SRC_RIGHTBUS,
	SRC_RIGHTBUS,
	DIV_RIGHTBUS,
	DIV_RIGHTBUS,
	GATE_IP_RIGHTBUS,
	GATE_IP_RIGHTBUS,
	EPLL_CON0,
	EPLL_CON1,
	EPLL_CON2,
	VPLL_CON0,
	VPLL_CON1,
	VPLL_CON2,
	SRC_TOP0,
	SRC_TOP0,
	SRC_TOP1,
	SRC_TOP1,
	SRC_CAM,
	SRC_CAM,
@@ -238,23 +244,70 @@ static unsigned long exynos4_clk_regs[] __initdata = {
	GATE_IP_CPU,
	GATE_IP_CPU,
};
};


static const struct samsung_clk_reg_dump src_mask_suspend[] = {
	{ .offset = SRC_MASK_TOP,		.value = 0x00000001, },
	{ .offset = SRC_MASK_CAM,		.value = 0x11111111, },
	{ .offset = SRC_MASK_TV,		.value = 0x00000111, },
	{ .offset = SRC_MASK_LCD0,		.value = 0x00001111, },
	{ .offset = SRC_MASK_MAUDIO,		.value = 0x00000001, },
	{ .offset = SRC_MASK_FSYS,		.value = 0x01011111, },
	{ .offset = SRC_MASK_PERIL0,		.value = 0x01111111, },
	{ .offset = SRC_MASK_PERIL1,		.value = 0x01110111, },
	{ .offset = SRC_MASK_DMC,		.value = 0x00010000, },
};

static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = {
	{ .offset = E4210_SRC_MASK_LCD1,	.value = 0x00001111, },
};

#define PLL_ENABLED	(1 << 31)
#define PLL_LOCKED	(1 << 29)

static void exynos4_clk_wait_for_pll(u32 reg)
{
	u32 pll_con;

	pll_con = readl(reg_base + reg);
	if (!(pll_con & PLL_ENABLED))
		return;

	while (!(pll_con & PLL_LOCKED)) {
		cpu_relax();
		pll_con = readl(reg_base + reg);
	}
}

static int exynos4_clk_suspend(void)
static int exynos4_clk_suspend(void)
{
{
	samsung_clk_save(reg_base, exynos4_save_common,
	samsung_clk_save(reg_base, exynos4_save_common,
				ARRAY_SIZE(exynos4_clk_regs));
				ARRAY_SIZE(exynos4_clk_regs));
	samsung_clk_save(reg_base, exynos4_save_pll,
				ARRAY_SIZE(exynos4_clk_pll_regs));


	if (exynos4_soc == EXYNOS4210)
	if (exynos4_soc == EXYNOS4210) {
		samsung_clk_save(reg_base, exynos4_save_soc,
		samsung_clk_save(reg_base, exynos4_save_soc,
					ARRAY_SIZE(exynos4210_clk_save));
					ARRAY_SIZE(exynos4210_clk_save));
	else
		samsung_clk_restore(reg_base, src_mask_suspend_e4210,
					ARRAY_SIZE(src_mask_suspend_e4210));
	} else {
		samsung_clk_save(reg_base, exynos4_save_soc,
		samsung_clk_save(reg_base, exynos4_save_soc,
					ARRAY_SIZE(exynos4x12_clk_save));
					ARRAY_SIZE(exynos4x12_clk_save));
	}

	samsung_clk_restore(reg_base, src_mask_suspend,
					ARRAY_SIZE(src_mask_suspend));


	return 0;
	return 0;
}
}


static void exynos4_clk_resume(void)
static void exynos4_clk_resume(void)
{
{
	samsung_clk_restore(reg_base, exynos4_save_pll,
				ARRAY_SIZE(exynos4_clk_pll_regs));

	exynos4_clk_wait_for_pll(EPLL_CON0);
	exynos4_clk_wait_for_pll(VPLL_CON0);

	samsung_clk_restore(reg_base, exynos4_save_common,
	samsung_clk_restore(reg_base, exynos4_save_common,
				ARRAY_SIZE(exynos4_clk_regs));
				ARRAY_SIZE(exynos4_clk_regs));


@@ -289,9 +342,16 @@ static void exynos4_clk_sleep_init(void)
	if (!exynos4_save_soc)
	if (!exynos4_save_soc)
		goto err_common;
		goto err_common;


	exynos4_save_pll = samsung_clk_alloc_reg_dump(exynos4_clk_pll_regs,
					ARRAY_SIZE(exynos4_clk_pll_regs));
	if (!exynos4_save_pll)
		goto err_soc;

	register_syscore_ops(&exynos4_clk_syscore_ops);
	register_syscore_ops(&exynos4_clk_syscore_ops);
	return;
	return;


err_soc:
	kfree(exynos4_save_soc);
err_common:
err_common:
	kfree(exynos4_save_common);
	kfree(exynos4_save_common);
err_warn:
err_warn: