All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] EXYNOS4210: Update exynos4210-cpufreq.c
@ 2011-07-05  8:06 Kukjin Kim
  2011-07-05  8:06 ` [PATCH 1/4] [CPUFREQ] EXYNOS4210: Remove regarding busfreq codes Kukjin Kim
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Kukjin Kim @ 2011-07-05  8:06 UTC (permalink / raw)
  To: linux-samsung-soc, cpufreq; +Cc: davej

This patch updates CPU table and divider to support 1.2GHz in stable and
removes unused codes like regarding bus freq codes.

[PATCH 1/4] [CPUFREQ] EXYNOS4210: Remove regarding busfreq codes
[PATCH 2/4] [CPUFREQ] EXYNOS4210: Change CPU table and divider
[PATCH 3/4] [CPUFREQ] EXYNOS4210: Cleanup sequence and unused codes
[PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] [CPUFREQ] EXYNOS4210: Remove regarding busfreq codes
  2011-07-05  8:06 [PATCH 0/4] EXYNOS4210: Update exynos4210-cpufreq.c Kukjin Kim
@ 2011-07-05  8:06 ` Kukjin Kim
  2011-07-05  8:06 ` [PATCH 2/4] EXYNOS4210: Change CPU table and divider Kukjin Kim
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Kukjin Kim @ 2011-07-05  8:06 UTC (permalink / raw)
  To: linux-samsung-soc, cpufreq; +Cc: davej, Jongpill Lee, SangWook Ju, Kukjin Kim

From: Jongpill Lee <boyko.lee@samsung.com>

Since busfreq codes can be handlend on busfreq driver,
this patch removes regarding busfreq codes on cpufreq.

Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
Signed-off-by: SangWook Ju <sw.ju@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 drivers/cpufreq/exynos4210-cpufreq.c |  180 +---------------------------------
 1 files changed, 3 insertions(+), 177 deletions(-)

diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index 54025fc..28b3d53 100644
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -31,16 +31,8 @@ static struct clk *mout_mpll;
 static struct clk *mout_apll;
 
 static struct regulator *arm_regulator;
-static struct regulator *int_regulator;
 
 static struct cpufreq_freqs freqs;
-static unsigned int memtype;
-
-enum exynos4_memory_type {
-	DDR2 = 4,
-	LPDDR2,
-	DDR3,
-};
 
 enum cpufreq_level_index {
 	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
@@ -93,87 +85,24 @@ static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
 	{ 3, 0 },
 };
 
-static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
-	 *		DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
-	 */
-
-	/* DMC L0: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L1: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L2: 266.7MHz */
-	{ 7, 1, 1, 2, 1, 1, 3, 1 },
-
-	/* DMC L3: 200MHz */
-	{ 7, 1, 1, 3, 1, 1, 3, 1 },
-};
-
-static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
-	 */
-
-	/* ACLK200 L0: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L1: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L2: 160MHz */
-	{ 4, 7, 5, 7, 1 },
-
-	/* ACLK200 L3: 133.3MHz */
-	{ 5, 7, 7, 7, 1 },
-};
-
-static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVGDL/R, DIVGPL/R }
-	 */
-
-	/* ACLK_GDL/R L0: 200MHz */
-	{ 3, 1 },
-
-	/* ACLK_GDL/R L1: 200MHz */
-	{ 3, 1 },
-
-	/* ACLK_GDL/R L2: 160MHz */
-	{ 4, 1 },
-
-	/* ACLK_GDL/R L3: 133.3MHz */
-	{ 5, 1 },
-};
-
 struct cpufreq_voltage_table {
 	unsigned int	index;		/* any */
 	unsigned int	arm_volt;	/* uV */
-	unsigned int	int_volt;
 };
 
 static struct cpufreq_voltage_table exynos4_volt_table[CPUFREQ_LEVEL_END] = {
 	{
 		.index		= L0,
 		.arm_volt	= 1200000,
-		.int_volt	= 1100000,
 	}, {
 		.index		= L1,
 		.arm_volt	= 1100000,
-		.int_volt	= 1100000,
 	}, {
 		.index		= L2,
 		.arm_volt	= 1000000,
-		.int_volt	= 1000000,
 	}, {
 		.index		= L3,
 		.arm_volt	= 900000,
-		.int_volt	= 1000000,
 	},
 };
 
@@ -242,80 +171,6 @@ void exynos4_set_clkdiv(unsigned int div_index)
 	do {
 		tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
 	} while (tmp & 0x11);
-
-	/* Change Divider - DMC0 */
-
-	tmp = __raw_readl(S5P_CLKDIV_DMC0);
-
-	tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
-		S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
-		S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
-		S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
-
-	tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
-		(clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
-		(clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
-		(clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
-		(clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
-		(clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
-		(clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
-		(clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_DMC0);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
-	} while (tmp & 0x11111111);
-
-	/* Change Divider - TOP */
-
-	tmp = __raw_readl(S5P_CLKDIV_TOP);
-
-	tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
-		S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
-		S5P_CLKDIV_TOP_ONENAND_MASK);
-
-	tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
-		(clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
-		(clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
-		(clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
-		(clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_TOP);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
-	} while (tmp & 0x11111);
-
-	/* Change Divider - LEFTBUS */
-
-	tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
-
-	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
-		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
-	} while (tmp & 0x11);
-
-	/* Change Divider - RIGHTBUS */
-
-	tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
-
-	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
-		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
-	} while (tmp & 0x11);
 }
 
 static void exynos4_set_apll(unsigned int index)
@@ -404,7 +259,7 @@ static int exynos4_target(struct cpufreq_policy *policy,
 			  unsigned int relation)
 {
 	unsigned int index, old_index;
-	unsigned int arm_volt, int_volt;
+	unsigned int arm_volt;
 
 	freqs.old = exynos4_getspeed(policy->cpu);
 
@@ -424,26 +279,21 @@ static int exynos4_target(struct cpufreq_policy *policy,
 
 	/* get the voltage value */
 	arm_volt = exynos4_volt_table[index].arm_volt;
-	int_volt = exynos4_volt_table[index].int_volt;
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
 	/* control regulator */
-	if (freqs.new > freqs.old) {
+	if (freqs.new > freqs.old)
 		/* Voltage up */
 		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
-		regulator_set_voltage(int_regulator, int_volt, int_volt);
-	}
 
 	/* Clock Configuration Procedure */
 	exynos4_set_frequency(old_index, index);
 
 	/* control regulator */
-	if (freqs.new < freqs.old) {
+	if (freqs.new < freqs.old)
 		/* Voltage down */
 		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
-		regulator_set_voltage(int_regulator, int_volt, int_volt);
-	}
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
@@ -519,27 +369,6 @@ static int __init exynos4_cpufreq_init(void)
 		goto out;
 	}
 
-	int_regulator = regulator_get(NULL, "vdd_int");
-	if (IS_ERR(int_regulator)) {
-		printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
-		goto out;
-	}
-
-	/*
-	 * Check DRAM type.
-	 * Because DVFS level is different according to DRAM type.
-	 */
-	memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
-	memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
-	memtype &= S5P_DMC0_MEMTYPE_MASK;
-
-	if ((memtype < DDR2) && (memtype > DDR3)) {
-		printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
-		goto out;
-	} else {
-		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
-	}
-
 	return cpufreq_register_driver(&exynos4_driver);
 
 out:
@@ -558,9 +387,6 @@ out:
 	if (!IS_ERR(arm_regulator))
 		regulator_put(arm_regulator);
 
-	if (!IS_ERR(int_regulator))
-		regulator_put(int_regulator);
-
 	printk(KERN_ERR "%s: failed initialization\n", __func__);
 
 	return -EINVAL;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] EXYNOS4210: Change CPU table and divider
  2011-07-05  8:06 [PATCH 0/4] EXYNOS4210: Update exynos4210-cpufreq.c Kukjin Kim
  2011-07-05  8:06 ` [PATCH 1/4] [CPUFREQ] EXYNOS4210: Remove regarding busfreq codes Kukjin Kim
@ 2011-07-05  8:06 ` Kukjin Kim
  2011-07-05  8:06 ` [PATCH 3/4] [CPUFREQ] EXYNOS4210: Cleanup sequence and unused codes Kukjin Kim
  2011-07-05  8:06 ` [PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock Kukjin Kim
  3 siblings, 0 replies; 10+ messages in thread
From: Kukjin Kim @ 2011-07-05  8:06 UTC (permalink / raw)
  To: linux-samsung-soc, cpufreq; +Cc: davej, Jongpill Lee, SangWook Ju, Kukjin Kim

From: Jongpill Lee <boyko.lee@samsung.com>

This patch adds support 1.2GHz CPU frequency and changes
CPU table and divider for stable working.

Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
Signed-off-by: SangWook Ju <sw.ju@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 drivers/cpufreq/exynos4210-cpufreq.c |   69 ++++++++++++++++++++--------------
 1 files changed, 41 insertions(+), 28 deletions(-)

diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index 28b3d53..0a9ef1a 100644
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -35,14 +35,15 @@ static struct regulator *arm_regulator;
 static struct cpufreq_freqs freqs;
 
 enum cpufreq_level_index {
-	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
+	L0, L1, L2, L3, L4, CPUFREQ_LEVEL_END,
 };
 
 static struct cpufreq_frequency_table exynos4_freq_table[] = {
-	{L0, 1000*1000},
-	{L1, 800*1000},
-	{L2, 400*1000},
-	{L3, 100*1000},
+	{L0, 1200*1000},
+	{L1, 1000*1000},
+	{L2, 800*1000},
+	{L3, 500*1000},
+	{L4, 200*1000},
 	{0, CPUFREQ_TABLE_END},
 };
 
@@ -53,17 +54,20 @@ static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
 	 *		DIVATB, DIVPCLK_DBG, DIVAPLL }
 	 */
 
-	/* ARM L0: 1000MHz */
-	{ 0, 3, 7, 3, 3, 0, 1 },
+	/* ARM L0: 1200MHz */
+	{ 0, 3, 7, 3, 4, 1, 7 },
 
-	/* ARM L1: 800MHz */
-	{ 0, 3, 7, 3, 3, 0, 1 },
+	/* ARM L1: 1000MHz */
+	{ 0, 3, 7, 3, 4, 1, 7 },
 
-	/* ARM L2: 400MHz */
-	{ 0, 1, 3, 1, 3, 0, 1 },
+	/* ARM L2: 800MHz */
+	{ 0, 3, 7, 3, 3, 1, 7 },
 
-	/* ARM L3: 100MHz */
-	{ 0, 0, 1, 0, 3, 1, 1 },
+	/* ARM L3: 500MHz */
+	{ 0, 3, 7, 3, 3, 1, 7 },
+
+	/* ARM L4: 200MHz */
+	{ 0, 1, 3, 1, 3, 1, 0 },
 };
 
 static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
@@ -72,16 +76,19 @@ static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
 	 * { DIVCOPY, DIVHPM }
 	 */
 
-	 /* ARM L0: 1000MHz */
-	{ 3, 0 },
+	 /* ARM L0: 1200MHz */
+	{ 5, 0 },
+
+	/* ARM L1: 1000MHz */
+	{ 4, 0 },
 
-	/* ARM L1: 800MHz */
+	/* ARM L2: 800MHz */
 	{ 3, 0 },
 
-	/* ARM L2: 400MHz */
+	/* ARM L3: 500MHz */
 	{ 3, 0 },
 
-	/* ARM L3: 100MHz */
+	/* ARM L4: 200MHz */
 	{ 3, 0 },
 };
 
@@ -93,31 +100,37 @@ struct cpufreq_voltage_table {
 static struct cpufreq_voltage_table exynos4_volt_table[CPUFREQ_LEVEL_END] = {
 	{
 		.index		= L0,
-		.arm_volt	= 1200000,
+		.arm_volt	= 1350000,
 	}, {
 		.index		= L1,
-		.arm_volt	= 1100000,
+		.arm_volt	= 1300000,
 	}, {
 		.index		= L2,
-		.arm_volt	= 1000000,
+		.arm_volt	= 1200000,
 	}, {
 		.index		= L3,
-		.arm_volt	= 900000,
+		.arm_volt	= 1100000,
+	}, {
+		.index		= L4,
+		.arm_volt	= 1050000,
 	},
 };
 
 static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = {
-	/* APLL FOUT L0: 1000MHz */
+	/* APLL FOUT L0: 1200MHz */
+	((150 << 16) | (3 << 8) | 1),
+
+	/* APLL FOUT L1: 1000MHz */
 	((250 << 16) | (6 << 8) | 1),
 
-	/* APLL FOUT L1: 800MHz */
+	/* APLL FOUT L2: 800MHz */
 	((200 << 16) | (6 << 8) | 1),
 
-	/* APLL FOUT L2 : 400MHz */
-	((200 << 16) | (6 << 8) | 2),
+	/* APLL FOUT L3: 500MHz */
+	((250 << 16) | (6 << 8) | 2),
 
-	/* APLL FOUT L3: 100MHz */
-	((200 << 16) | (6 << 8) | 4),
+	/* APLL FOUT L4: 200MHz */
+	((200 << 16) | (6 << 8) | 3),
 };
 
 int exynos4_verify_speed(struct cpufreq_policy *policy)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] [CPUFREQ] EXYNOS4210: Cleanup sequence and unused codes
  2011-07-05  8:06 [PATCH 0/4] EXYNOS4210: Update exynos4210-cpufreq.c Kukjin Kim
  2011-07-05  8:06 ` [PATCH 1/4] [CPUFREQ] EXYNOS4210: Remove regarding busfreq codes Kukjin Kim
  2011-07-05  8:06 ` [PATCH 2/4] EXYNOS4210: Change CPU table and divider Kukjin Kim
@ 2011-07-05  8:06 ` Kukjin Kim
  2011-07-05  8:06 ` [PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock Kukjin Kim
  3 siblings, 0 replies; 10+ messages in thread
From: Kukjin Kim @ 2011-07-05  8:06 UTC (permalink / raw)
  To: linux-samsung-soc, cpufreq
  Cc: davej, Jongpill Lee, SangWook Ju, Jonghwan Choi, Kukjin Kim

From: Jongpill Lee <boyko.lee@samsung.com>

This patch modifies following.
1. Remove unused register access
2. Change sequence of changing frequency
3. Minor optimization

Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
Signed-off-by: SangWook Ju <sw.ju@samsung.com>
Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 drivers/cpufreq/exynos4210-cpufreq.c |  138 +++++++++++++++++++++------------
 1 files changed, 88 insertions(+), 50 deletions(-)

diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index 0a9ef1a..2e04e01 100644
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -34,10 +34,16 @@ static struct regulator *arm_regulator;
 
 static struct cpufreq_freqs freqs;
 
+struct cpufreq_clkdiv {
+	unsigned int clkdiv;
+};
+
 enum cpufreq_level_index {
 	L0, L1, L2, L3, L4, CPUFREQ_LEVEL_END,
 };
 
+static struct cpufreq_clkdiv exynos4_clkdiv_table[CPUFREQ_LEVEL_END];
+
 static struct cpufreq_frequency_table exynos4_freq_table[] = {
 	{L0, 1200*1000},
 	{L1, 1000*1000},
@@ -149,20 +155,7 @@ void exynos4_set_clkdiv(unsigned int div_index)
 
 	/* Change Divider - CPU0 */
 
-	tmp = __raw_readl(S5P_CLKDIV_CPU);
-
-	tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
-		S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
-		S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
-		S5P_CLKDIV_CPU0_APLL_MASK);
-
-	tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
-		(clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
-		(clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
-		(clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
-		(clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
-		(clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
-		(clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+	tmp = exynos4_clkdiv_table[div_index].clkdiv;
 
 	__raw_writel(tmp, S5P_CLKDIV_CPU);
 
@@ -227,14 +220,12 @@ static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index
 	unsigned int tmp;
 
 	if (old_index > new_index) {
-		/* The frequency changing to L0 needs to change apll */
-		if (freqs.new == exynos4_freq_table[L0].frequency) {
-			/* 1. Change the system clock divider values */
-			exynos4_set_clkdiv(new_index);
-
-			/* 2. Change the apll m,p,s value */
-			exynos4_set_apll(new_index);
-		} else {
+		/*
+		 * L1/L3, L2/L4 Level change require
+		 * to only change s divider value
+		 */
+		if (((old_index == L3) && (new_index == L1)) ||
+				((old_index == L4) && (new_index == L2))) {
 			/* 1. Change the system clock divider values */
 			exynos4_set_clkdiv(new_index);
 
@@ -243,18 +234,20 @@ static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index
 			tmp &= ~(0x7 << 0);
 			tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
 			__raw_writel(tmp, S5P_APLL_CON0);
-		}
-	}
-
-	else if (old_index < new_index) {
-		/* The frequency changing from L0 needs to change apll */
-		if (freqs.old == exynos4_freq_table[L0].frequency) {
-			/* 1. Change the apll m,p,s value */
-			exynos4_set_apll(new_index);
-
-			/* 2. Change the system clock divider values */
-			exynos4_set_clkdiv(new_index);
 		} else {
+			/* Clock Configuration Procedure */
+			/* 1. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+			/* 2. Change the apll m,p,s value */
+			exynos4_set_apll(new_index);
+		}
+	} else if (old_index < new_index) {
+		/*
+		 * L1/L3, L2/L4 Level change require
+		 * to only change s divider value
+		 */
+		if (((old_index == L1) && (new_index == L3)) ||
+				((old_index == L2) && (new_index == L4))) {
 			/* 1. Change just s value in apll m,p,s value */
 			tmp = __raw_readl(S5P_APLL_CON0);
 			tmp &= ~(0x7 << 0);
@@ -263,6 +256,12 @@ static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index
 
 			/* 2. Change the system clock divider values */
 			exynos4_set_clkdiv(new_index);
+		} else {
+			/* Clock Configuration Procedure */
+			/* 1. Change the apll m,p,s value */
+			exynos4_set_apll(new_index);
+			/* 2. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
 		}
 	}
 }
@@ -303,12 +302,13 @@ static int exynos4_target(struct cpufreq_policy *policy,
 	/* Clock Configuration Procedure */
 	exynos4_set_frequency(old_index, index);
 
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
 	/* control regulator */
 	if (freqs.new < freqs.old)
 		/* Voltage down */
 		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 	return 0;
 }
@@ -340,7 +340,12 @@ static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	 * Each cpu is bound to the same speed.
 	 * So the affected cpu is all of the cpus.
 	 */
-	cpumask_setall(policy->cpus);
+	if (!cpu_online(1)) {
+		cpumask_copy(policy->related_cpus, cpu_possible_mask);
+		cpumask_copy(policy->cpus, cpu_online_mask);
+	} else {
+		cpumask_setall(policy->cpus);
+	}
 
 	return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
 }
@@ -360,47 +365,80 @@ static struct cpufreq_driver exynos4_driver = {
 
 static int __init exynos4_cpufreq_init(void)
 {
+	int i;
+	unsigned int tmp;
+
 	cpu_clk = clk_get(NULL, "armclk");
 	if (IS_ERR(cpu_clk))
 		return PTR_ERR(cpu_clk);
 
 	moutcore = clk_get(NULL, "moutcore");
 	if (IS_ERR(moutcore))
-		goto out;
+		goto err_moutcore;
 
 	mout_mpll = clk_get(NULL, "mout_mpll");
 	if (IS_ERR(mout_mpll))
-		goto out;
+		goto err_mout_mpll;
 
 	mout_apll = clk_get(NULL, "mout_apll");
 	if (IS_ERR(mout_apll))
-		goto out;
+		goto err_mout_apll;
 
 	arm_regulator = regulator_get(NULL, "vdd_arm");
 	if (IS_ERR(arm_regulator)) {
 		printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
-		goto out;
+		goto err_vdd_arm;
 	}
 
-	return cpufreq_register_driver(&exynos4_driver);
+	tmp = __raw_readl(S5P_CLKDIV_CPU);
 
-out:
-	if (!IS_ERR(cpu_clk))
-		clk_put(cpu_clk);
+	for (i = L0; i <  CPUFREQ_LEVEL_END; i++) {
+		tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK |
+			 S5P_CLKDIV_CPU0_COREM0_MASK |
+			 S5P_CLKDIV_CPU0_COREM1_MASK |
+			 S5P_CLKDIV_CPU0_PERIPH_MASK |
+			 S5P_CLKDIV_CPU0_ATB_MASK |
+			 S5P_CLKDIV_CPU0_PCLKDBG_MASK |
+			 S5P_CLKDIV_CPU0_APLL_MASK);
+
+		tmp |= ((clkdiv_cpu0[i][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
+			(clkdiv_cpu0[i][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
+			(clkdiv_cpu0[i][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
+			(clkdiv_cpu0[i][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
+			(clkdiv_cpu0[i][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
+			(clkdiv_cpu0[i][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
+			(clkdiv_cpu0[i][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+
+		exynos4_clkdiv_table[i].clkdiv = tmp;
+	}
 
-	if (!IS_ERR(moutcore))
-		clk_put(moutcore);
+	if (cpufreq_register_driver(&exynos4_driver)) {
+		pr_err("failed to register cpufreq driver\n");
+		goto err_cpufreq;
+	}
 
-	if (!IS_ERR(mout_mpll))
-		clk_put(mout_mpll);
+	return 0;
+err_cpufreq:
+	if (!IS_ERR(arm_regulator))
+		regulator_put(arm_regulator);
 
+err_vdd_arm:
 	if (!IS_ERR(mout_apll))
 		clk_put(mout_apll);
 
-	if (!IS_ERR(arm_regulator))
-		regulator_put(arm_regulator);
+err_mout_apll:
+	if (!IS_ERR(mout_mpll))
+		clk_put(mout_mpll);
+
+err_mout_mpll:
+	if (!IS_ERR(moutcore))
+		clk_put(moutcore);
+
+err_moutcore:
+	if (!IS_ERR(cpu_clk))
+		clk_put(cpu_clk);
 
-	printk(KERN_ERR "%s: failed initialization\n", __func__);
+	pr_debug("%s: failed initialization\n", __func__);
 
 	return -EINVAL;
 }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock
  2011-07-05  8:06 [PATCH 0/4] EXYNOS4210: Update exynos4210-cpufreq.c Kukjin Kim
                   ` (2 preceding siblings ...)
  2011-07-05  8:06 ` [PATCH 3/4] [CPUFREQ] EXYNOS4210: Cleanup sequence and unused codes Kukjin Kim
@ 2011-07-05  8:06 ` Kukjin Kim
  2011-07-05  8:49   ` Kyungmin Park
  2011-07-09  3:48   ` Mark Brown
  3 siblings, 2 replies; 10+ messages in thread
From: Kukjin Kim @ 2011-07-05  8:06 UTC (permalink / raw)
  To: linux-samsung-soc, cpufreq
  Cc: davej, Jongpill Lee, SangWook Ju, Jonghwan Choi, Kukjin Kim

From: Jongpill Lee <boyko.lee@samsung.com>

Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
Signed-off-by: SangWook Ju <sw.ju@samsung.com>
Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-exynos4/include/mach/cpufreq.h |   39 ++++++
 drivers/cpufreq/exynos4210-cpufreq.c         |  167 +++++++++++++++++++++++++-
 2 files changed, 200 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/mach-exynos4/include/mach/cpufreq.h

diff --git a/arch/arm/mach-exynos4/include/mach/cpufreq.h b/arch/arm/mach-exynos4/include/mach/cpufreq.h
new file mode 100644
index 0000000..7e00931
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/cpufreq.h
@@ -0,0 +1,39 @@
+/* linux/arch/arm/mach-exynos4/include/mach/cpufreq.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - CPUFreq support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * CPU frequency level index for using cpufreq lock API
+ * This should be same with cpufreq_frequency_table
+ */
+enum cpufreq_level_request {
+	CPU_L0,		/* 1200MHz */
+	CPU_L1,		/* 1000MHz */
+	CPU_L2,		/* 800MHz */
+	CPU_L3,		/* 500MHz */
+	CPU_L4,		/* 200MHz */
+	CPU_LEVEL_END,
+};
+
+enum cpufreq_lock_ID {
+	DVFS_LOCK_ID_G2D,	/* G2D */
+	DVFS_LOCK_ID_TV,	/* TV */
+	DVFS_LOCK_ID_MFC,	/* MFC */
+	DVFS_LOCK_ID_USB,	/* USB */
+	DVFS_LOCK_ID_CAM,	/* CAM */
+	DVFS_LOCK_ID_PM,	/* PM */
+	DVFS_LOCK_ID_USER,	/* USER */
+	DVFS_LOCK_ID_END,
+};
+
+int exynos4_cpufreq_lock(unsigned int nId,
+			enum cpufreq_level_request cpufreq_level);
+void exynos4_cpufreq_lock_free(unsigned int nId);
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index 2e04e01..1d2b7da 100644
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -17,14 +17,21 @@
 #include <linux/slab.h>
 #include <linux/regulator/consumer.h>
 #include <linux/cpufreq.h>
+#include <linux/suspend.h>
+#include <linux/reboot.h>
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-mem.h>
+#include <mach/cpufreq.h>
 
 #include <plat/clock.h>
 #include <plat/pm.h>
 
+static bool exynos4_cpufreq_init_done;
+static DEFINE_MUTEX(set_freq_lock);
+static DEFINE_MUTEX(set_cpu_freq_lock);
+
 static struct clk *cpu_clk;
 static struct clk *moutcore;
 static struct clk *mout_mpll;
@@ -53,6 +60,12 @@ static struct cpufreq_frequency_table exynos4_freq_table[] = {
 	{0, CPUFREQ_TABLE_END},
 };
 
+/* This defines are for cpufreq lock */
+#define CPUFREQ_MIN_LEVEL	(CPUFREQ_LEVEL_END - 1)
+unsigned int cpufreq_lock_id;
+unsigned int cpufreq_lock_val[DVFS_LOCK_ID_END];
+unsigned int cpufreq_lock_level = CPUFREQ_MIN_LEVEL;
+
 static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
 	/*
 	 * Clock divider value for following
@@ -272,22 +285,31 @@ static int exynos4_target(struct cpufreq_policy *policy,
 {
 	unsigned int index, old_index;
 	unsigned int arm_volt;
+	int ret = 0;
+
+	mutex_lock(&set_freq_lock);
 
 	freqs.old = exynos4_getspeed(policy->cpu);
 
 	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
-					   freqs.old, relation, &old_index))
-		return -EINVAL;
+					   freqs.old, relation, &old_index)) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
-					   target_freq, relation, &index))
-		return -EINVAL;
+					   target_freq, relation, &index)) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	freqs.new = exynos4_freq_table[index].frequency;
 	freqs.cpu = policy->cpu;
 
-	if (freqs.new == freqs.old)
-		return 0;
+	if (freqs.new == freqs.old) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	/* get the voltage value */
 	arm_volt = exynos4_volt_table[index].arm_volt;
@@ -309,9 +331,98 @@ static int exynos4_target(struct cpufreq_policy *policy,
 		/* Voltage down */
 		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
 
+out:
+	mutex_unlock(&set_freq_lock);
+
+	return ret;
+}
+
+atomic_t exynos4_cpufreq_lock_count;
+
+int exynos4_cpufreq_lock(unsigned int id,
+		enum cpufreq_level_request cpufreq_level)
+{
+	int i, old_idx = 0;
+	unsigned int freq_old, freq_new, arm_volt;
+
+	if (!exynos4_cpufreq_init_done)
+		return 0;
+
+	if (cpufreq_lock_id & (1 << id)) {
+		printk(KERN_ERR "%s:Device [%d] already locked cpufreq\n",
+				__func__,  id);
+		return 0;
+	}
+	mutex_lock(&set_cpu_freq_lock);
+	cpufreq_lock_id |= (1 << id);
+	cpufreq_lock_val[id] = cpufreq_level;
+
+	/* If the requested cpufreq is higher than current min frequency */
+	if (cpufreq_level < cpufreq_lock_level)
+		cpufreq_lock_level = cpufreq_level;
+
+	mutex_unlock(&set_cpu_freq_lock);
+
+	/*
+	 * If current frequency is lower than requested freq,
+	 * it needs to update
+	 */
+	mutex_lock(&set_freq_lock);
+	freq_old = exynos4_getspeed(0);
+	freq_new = exynos4_freq_table[cpufreq_level].frequency;
+	if (freq_old < freq_new) {
+		/* Find out current level index */
+		for (i = 0 ; i < CPUFREQ_LEVEL_END ; i++) {
+			if (freq_old == exynos4_freq_table[i].frequency) {
+				old_idx = exynos4_freq_table[i].index;
+				break;
+			} else if (i == (CPUFREQ_LEVEL_END - 1)) {
+				printk(KERN_ERR "%s: Level not found\n",
+						__func__);
+				mutex_unlock(&set_freq_lock);
+				return -EINVAL;
+			} else {
+				continue;
+			}
+		}
+		freqs.old = freq_old;
+		freqs.new = freq_new;
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+		/* get the voltage value */
+		arm_volt = exynos4_volt_table[cpufreq_level].arm_volt;
+		regulator_set_voltage(arm_regulator, arm_volt,
+				arm_volt);
+
+		exynos4_set_frequency(old_idx, cpufreq_level);
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
+	mutex_unlock(&set_freq_lock);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(exynos4_cpufreq_lock);
+
+void exynos4_cpufreq_lock_free(unsigned int id)
+{
+	int i;
+
+	if (!exynos4_cpufreq_init_done)
+		return;
+
+	mutex_lock(&set_cpu_freq_lock);
+	cpufreq_lock_id &= ~(1 << id);
+	cpufreq_lock_val[id] = CPUFREQ_MIN_LEVEL;
+	cpufreq_lock_level = CPUFREQ_MIN_LEVEL;
+	if (cpufreq_lock_id) {
+		for (i = 0; i < DVFS_LOCK_ID_END; i++) {
+			if (cpufreq_lock_val[i] < cpufreq_lock_level)
+				cpufreq_lock_level = cpufreq_lock_val[i];
+		}
+	}
+	mutex_unlock(&set_cpu_freq_lock);
+}
+EXPORT_SYMBOL_GPL(exynos4_cpufreq_lock_free);
 
 #ifdef CONFIG_PM
 static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
@@ -325,6 +436,28 @@ static int exynos4_cpufreq_resume(struct cpufreq_policy *policy)
 }
 #endif
 
+static int exynos4_cpufreq_notifier_event(struct notifier_block *this,
+		unsigned long event, void *ptr)
+{
+	switch (event) {
+	case PM_SUSPEND_PREPARE:
+		if (exynos4_cpufreq_lock(DVFS_LOCK_ID_PM, CPU_L0))
+			return NOTIFY_BAD;
+		pr_debug("PM_SUSPEND_PREPARE for CPUFREQ\n");
+		return NOTIFY_OK;
+	case PM_POST_RESTORE:
+	case PM_POST_SUSPEND:
+		pr_debug("PM_POST_SUSPEND for CPUFREQ\n");
+		exynos4_cpufreq_lock_free(DVFS_LOCK_ID_PM);
+		return NOTIFY_OK;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block exynos4_cpufreq_notifier = {
+	.notifier_call = exynos4_cpufreq_notifier_event,
+};
+
 static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
 	policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
@@ -350,6 +483,20 @@ static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
 	return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
 }
 
+static int exynos4_cpufreq_reboot_notifier_call(struct notifier_block *this,
+		unsigned long code, void *_cmd)
+{
+	if (exynos4_cpufreq_lock(DVFS_LOCK_ID_PM, CPU_L0))
+		return NOTIFY_BAD;
+
+	printk(KERN_INFO "REBOOT Notifier for CPUFREQ\n");
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block exynos4_cpufreq_reboot_notifier = {
+	.notifier_call = exynos4_cpufreq_reboot_notifier_call,
+};
+
 static struct cpufreq_driver exynos4_driver = {
 	.flags		= CPUFREQ_STICKY,
 	.verify		= exynos4_verify_speed,
@@ -390,6 +537,11 @@ static int __init exynos4_cpufreq_init(void)
 		goto err_vdd_arm;
 	}
 
+	register_pm_notifier(&exynos4_cpufreq_notifier);
+	register_reboot_notifier(&exynos4_cpufreq_reboot_notifier);
+
+	exynos4_cpufreq_init_done = true;
+
 	tmp = __raw_readl(S5P_CLKDIV_CPU);
 
 	for (i = L0; i <  CPUFREQ_LEVEL_END; i++) {
@@ -419,6 +571,9 @@ static int __init exynos4_cpufreq_init(void)
 
 	return 0;
 err_cpufreq:
+	unregister_reboot_notifier(&exynos4_cpufreq_reboot_notifier);
+	unregister_pm_notifier(&exynos4_cpufreq_notifier);
+
 	if (!IS_ERR(arm_regulator))
 		regulator_put(arm_regulator);
 
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock
  2011-07-05  8:06 ` [PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock Kukjin Kim
@ 2011-07-05  8:49   ` Kyungmin Park
  2011-07-08  6:22     ` [PATCH 4/4] " Kukjin Kim
  2011-07-09  3:48   ` Mark Brown
  1 sibling, 1 reply; 10+ messages in thread
From: Kyungmin Park @ 2011-07-05  8:49 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: linux-samsung-soc, cpufreq, davej, Jongpill Lee, SangWook Ju,
	Jonghwan Choi, 함명주

On Tue, Jul 5, 2011 at 5:06 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> From: Jongpill Lee <boyko.lee@samsung.com>
>
> Signed-off-by: Jongpill Lee <boyko.lee@samsung.com>
> Signed-off-by: SangWook Ju <sw.ju@samsung.com>
> Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
>  arch/arm/mach-exynos4/include/mach/cpufreq.h |   39 ++++++
>  drivers/cpufreq/exynos4210-cpufreq.c         |  167 +++++++++++++++++++++++++-
>  2 files changed, 200 insertions(+), 6 deletions(-)
>  create mode 100644 arch/arm/mach-exynos4/include/mach/cpufreq.h
>
> diff --git a/arch/arm/mach-exynos4/include/mach/cpufreq.h b/arch/arm/mach-exynos4/include/mach/cpufreq.h
> new file mode 100644
> index 0000000..7e00931
> --- /dev/null
> +++ b/arch/arm/mach-exynos4/include/mach/cpufreq.h
> @@ -0,0 +1,39 @@
> +/* linux/arch/arm/mach-exynos4/include/mach/cpufreq.h
> + *
> + * Copyright (c) 2011 Samsung Electronics Co., Ltd.
> + *             http://www.samsung.com
> + *
> + * EXYNOS4 - CPUFreq support
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +/*
> + * CPU frequency level index for using cpufreq lock API
> + * This should be same with cpufreq_frequency_table
> + */
> +enum cpufreq_level_request {
> +       CPU_L0,         /* 1200MHz */
> +       CPU_L1,         /* 1000MHz */
> +       CPU_L2,         /* 800MHz */
> +       CPU_L3,         /* 500MHz */
> +       CPU_L4,         /* 200MHz */
> +       CPU_LEVEL_END,
> +};
> +
> +enum cpufreq_lock_ID {
> +       DVFS_LOCK_ID_G2D,       /* G2D */
> +       DVFS_LOCK_ID_TV,        /* TV */
> +       DVFS_LOCK_ID_MFC,       /* MFC */
> +       DVFS_LOCK_ID_USB,       /* USB */
> +       DVFS_LOCK_ID_CAM,       /* CAM */
> +       DVFS_LOCK_ID_PM,        /* PM */
> +       DVFS_LOCK_ID_USER,      /* USER */
> +       DVFS_LOCK_ID_END,
> +};
> +
> +int exynos4_cpufreq_lock(unsigned int nId,
> +                       enum cpufreq_level_request cpufreq_level);
> +void exynos4_cpufreq_lock_free(unsigned int nId);
> diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
> index 2e04e01..1d2b7da 100644
> --- a/drivers/cpufreq/exynos4210-cpufreq.c
> +++ b/drivers/cpufreq/exynos4210-cpufreq.c
> @@ -17,14 +17,21 @@
>  #include <linux/slab.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/cpufreq.h>
> +#include <linux/suspend.h>
> +#include <linux/reboot.h>
>
>  #include <mach/map.h>
>  #include <mach/regs-clock.h>
>  #include <mach/regs-mem.h>
> +#include <mach/cpufreq.h>
>
>  #include <plat/clock.h>
>  #include <plat/pm.h>
>
> +static bool exynos4_cpufreq_init_done;
> +static DEFINE_MUTEX(set_freq_lock);
> +static DEFINE_MUTEX(set_cpu_freq_lock);
> +
>  static struct clk *cpu_clk;
>  static struct clk *moutcore;
>  static struct clk *mout_mpll;
> @@ -53,6 +60,12 @@ static struct cpufreq_frequency_table exynos4_freq_table[] = {
>        {0, CPUFREQ_TABLE_END},
>  };
>
> +/* This defines are for cpufreq lock */
> +#define CPUFREQ_MIN_LEVEL      (CPUFREQ_LEVEL_END - 1)
> +unsigned int cpufreq_lock_id;
> +unsigned int cpufreq_lock_val[DVFS_LOCK_ID_END];
> +unsigned int cpufreq_lock_level = CPUFREQ_MIN_LEVEL;
> +
>  static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
>        /*
>         * Clock divider value for following
> @@ -272,22 +285,31 @@ static int exynos4_target(struct cpufreq_policy *policy,
>  {
>        unsigned int index, old_index;
>        unsigned int arm_volt;
> +       int ret = 0;
> +
> +       mutex_lock(&set_freq_lock);
>
>        freqs.old = exynos4_getspeed(policy->cpu);
>
>        if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
> -                                          freqs.old, relation, &old_index))
> -               return -EINVAL;
> +                                          freqs.old, relation, &old_index)) {
> +               ret = -EINVAL;
> +               goto out;
> +       }
>
>        if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
> -                                          target_freq, relation, &index))
> -               return -EINVAL;
> +                                          target_freq, relation, &index)) {
> +               ret = -EINVAL;
> +               goto out;
> +       }
>
>        freqs.new = exynos4_freq_table[index].frequency;
>        freqs.cpu = policy->cpu;
>
> -       if (freqs.new == freqs.old)
> -               return 0;
> +       if (freqs.new == freqs.old) {
> +               ret = -EINVAL;
> +               goto out;
> +       }
>
>        /* get the voltage value */
>        arm_volt = exynos4_volt_table[index].arm_volt;
> @@ -309,9 +331,98 @@ static int exynos4_target(struct cpufreq_policy *policy,
>                /* Voltage down */
>                regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
>
> +out:
> +       mutex_unlock(&set_freq_lock);
> +
> +       return ret;
> +}
> +
> +atomic_t exynos4_cpufreq_lock_count;
> +
> +int exynos4_cpufreq_lock(unsigned int id,
> +               enum cpufreq_level_request cpufreq_level)
> +{
> +       int i, old_idx = 0;
> +       unsigned int freq_old, freq_new, arm_volt;
> +
> +       if (!exynos4_cpufreq_init_done)
> +               return 0;
> +
> +       if (cpufreq_lock_id & (1 << id)) {
> +               printk(KERN_ERR "%s:Device [%d] already locked cpufreq\n",
> +                               __func__,  id);
> +               return 0;
> +       }
> +       mutex_lock(&set_cpu_freq_lock);
> +       cpufreq_lock_id |= (1 << id);
> +       cpufreq_lock_val[id] = cpufreq_level;
> +
> +       /* If the requested cpufreq is higher than current min frequency */
> +       if (cpufreq_level < cpufreq_lock_level)
> +               cpufreq_lock_level = cpufreq_level;
> +
> +       mutex_unlock(&set_cpu_freq_lock);
> +
> +       /*
> +        * If current frequency is lower than requested freq,
> +        * it needs to update
> +        */
> +       mutex_lock(&set_freq_lock);
> +       freq_old = exynos4_getspeed(0);
> +       freq_new = exynos4_freq_table[cpufreq_level].frequency;
> +       if (freq_old < freq_new) {
> +               /* Find out current level index */
> +               for (i = 0 ; i < CPUFREQ_LEVEL_END ; i++) {
> +                       if (freq_old == exynos4_freq_table[i].frequency) {
> +                               old_idx = exynos4_freq_table[i].index;
> +                               break;
> +                       } else if (i == (CPUFREQ_LEVEL_END - 1)) {
> +                               printk(KERN_ERR "%s: Level not found\n",
> +                                               __func__);
> +                               mutex_unlock(&set_freq_lock);
> +                               return -EINVAL;
> +                       } else {
> +                               continue;
> +                       }
> +               }
> +               freqs.old = freq_old;
> +               freqs.new = freq_new;
> +               cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
> +
> +               /* get the voltage value */
> +               arm_volt = exynos4_volt_table[cpufreq_level].arm_volt;
> +               regulator_set_voltage(arm_regulator, arm_volt,
> +                               arm_volt);
> +
> +               exynos4_set_frequency(old_idx, cpufreq_level);
> +               cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
> +       }
> +       mutex_unlock(&set_freq_lock);
>
>        return 0;
>  }
> +EXPORT_SYMBOL_GPL(exynos4_cpufreq_lock);
> +
> +void exynos4_cpufreq_lock_free(unsigned int id)
> +{
> +       int i;
> +
> +       if (!exynos4_cpufreq_init_done)
> +               return;
> +
> +       mutex_lock(&set_cpu_freq_lock);
> +       cpufreq_lock_id &= ~(1 << id);
> +       cpufreq_lock_val[id] = CPUFREQ_MIN_LEVEL;
> +       cpufreq_lock_level = CPUFREQ_MIN_LEVEL;
> +       if (cpufreq_lock_id) {
> +               for (i = 0; i < DVFS_LOCK_ID_END; i++) {
> +                       if (cpufreq_lock_val[i] < cpufreq_lock_level)
> +                               cpufreq_lock_level = cpufreq_lock_val[i];
> +               }
> +       }
> +       mutex_unlock(&set_cpu_freq_lock);
> +}
> +EXPORT_SYMBOL_GPL(exynos4_cpufreq_lock_free);
>
>  #ifdef CONFIG_PM
>  static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
> @@ -325,6 +436,28 @@ static int exynos4_cpufreq_resume(struct cpufreq_policy *policy)
>  }
>  #endif
>
> +static int exynos4_cpufreq_notifier_event(struct notifier_block *this,
> +               unsigned long event, void *ptr)
> +{
> +       switch (event) {
> +       case PM_SUSPEND_PREPARE:
> +               if (exynos4_cpufreq_lock(DVFS_LOCK_ID_PM, CPU_L0))
Really do you want to set L0, 1.2GHz for suspend?
> +                       return NOTIFY_BAD;
> +               pr_debug("PM_SUSPEND_PREPARE for CPUFREQ\n");
> +               return NOTIFY_OK;
> +       case PM_POST_RESTORE:
> +       case PM_POST_SUSPEND:
> +               pr_debug("PM_POST_SUSPEND for CPUFREQ\n");
> +               exynos4_cpufreq_lock_free(DVFS_LOCK_ID_PM);
> +               return NOTIFY_OK;
> +       }
> +       return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block exynos4_cpufreq_notifier = {
> +       .notifier_call = exynos4_cpufreq_notifier_event,
> +};
> +
>  static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
>  {
>        policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
> @@ -350,6 +483,20 @@ static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
>        return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
>  }
>
> +static int exynos4_cpufreq_reboot_notifier_call(struct notifier_block *this,
> +               unsigned long code, void *_cmd)
> +{
> +       if (exynos4_cpufreq_lock(DVFS_LOCK_ID_PM, CPU_L0))
ditto at reboot
> +               return NOTIFY_BAD;
> +
> +       printk(KERN_INFO "REBOOT Notifier for CPUFREQ\n");
> +       return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block exynos4_cpufreq_reboot_notifier = {
> +       .notifier_call = exynos4_cpufreq_reboot_notifier_call,
> +};
> +
>  static struct cpufreq_driver exynos4_driver = {
>        .flags          = CPUFREQ_STICKY,
>        .verify         = exynos4_verify_speed,
> @@ -390,6 +537,11 @@ static int __init exynos4_cpufreq_init(void)
>                goto err_vdd_arm;
>        }
>
> +       register_pm_notifier(&exynos4_cpufreq_notifier);
> +       register_reboot_notifier(&exynos4_cpufreq_reboot_notifier);
> +
> +       exynos4_cpufreq_init_done = true;
> +
>        tmp = __raw_readl(S5P_CLKDIV_CPU);
>
>        for (i = L0; i <  CPUFREQ_LEVEL_END; i++) {
> @@ -419,6 +571,9 @@ static int __init exynos4_cpufreq_init(void)
>
>        return 0;
>  err_cpufreq:
> +       unregister_reboot_notifier(&exynos4_cpufreq_reboot_notifier);
> +       unregister_pm_notifier(&exynos4_cpufreq_notifier);
> +
>        if (!IS_ERR(arm_regulator))
>                regulator_put(arm_regulator);
>
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 4/4] EXYNOS4210: Add Support for DVS Lock
  2011-07-05  8:49   ` Kyungmin Park
@ 2011-07-08  6:22     ` Kukjin Kim
  0 siblings, 0 replies; 10+ messages in thread
From: Kukjin Kim @ 2011-07-08  6:22 UTC (permalink / raw)
  To: 'Kyungmin Park'
  Cc: linux-samsung-soc, cpufreq, davej, 'Jongpill Lee',
	'SangWook Ju', 'Jonghwan Choi',
	'함명주'

Kyungmin Park wrote:
> 
> On Tue, Jul 5, 2011 at 5:06 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:

(snip)

> >
> > +static int exynos4_cpufreq_notifier_event(struct notifier_block *this,
> > +               unsigned long event, void *ptr)
> > +{
> > +       switch (event) {
> > +       case PM_SUSPEND_PREPARE:
> > +               if (exynos4_cpufreq_lock(DVFS_LOCK_ID_PM, CPU_L0))
> Really do you want to set L0, 1.2GHz for suspend?

(snip)

> > +static int exynos4_cpufreq_reboot_notifier_call(struct notifier_block *this,
> > +               unsigned long code, void *_cmd)
> > +{
> > +       if (exynos4_cpufreq_lock(DVFS_LOCK_ID_PM, CPU_L0))
> ditto at reboot

Yes, this is needed to work regardless of boot-loader clock configuration.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] EXYNOS4210: Add Support for DVS Lock
  2011-07-05  8:06 ` [PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock Kukjin Kim
  2011-07-05  8:49   ` Kyungmin Park
@ 2011-07-09  3:48   ` Mark Brown
  2011-07-18  7:08     ` [PATCH 4/4] [CPUFREQ] " Kukjin Kim
  1 sibling, 1 reply; 10+ messages in thread
From: Mark Brown @ 2011-07-09  3:48 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: linux-samsung-soc, cpufreq, davej, Jongpill Lee, SangWook Ju,
	Jonghwan Choi

On Tue, Jul 05, 2011 at 05:06:19PM +0900, Kukjin Kim wrote:

> +int exynos4_cpufreq_lock(unsigned int nId,
> +			enum cpufreq_level_request cpufreq_level);
> +void exynos4_cpufreq_lock_free(unsigned int nId);

This feels like something cpufreq should support to at least some extent
in the core, especially the thing with forcing a particular mode on
suspend.  Not that I have any particularly bright ideas for how
immediately.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock
  2011-07-09  3:48   ` Mark Brown
@ 2011-07-18  7:08     ` Kukjin Kim
  2011-07-19 15:03       ` Mark Brown
  0 siblings, 1 reply; 10+ messages in thread
From: Kukjin Kim @ 2011-07-18  7:08 UTC (permalink / raw)
  To: 'Mark Brown'
  Cc: linux-samsung-soc, cpufreq, davej, 'Jongpill Lee',
	'SangWook Ju', 'Jonghwan Choi'

Mark Brown wrote:
> 
> On Tue, Jul 05, 2011 at 05:06:19PM +0900, Kukjin Kim wrote:
> 
> > +int exynos4_cpufreq_lock(unsigned int nId,
> > +			enum cpufreq_level_request cpufreq_level);
> > +void exynos4_cpufreq_lock_free(unsigned int nId);
> 
> This feels like something cpufreq should support to at least some extent
> in the core, especially the thing with forcing a particular mode on
> suspend.  Not that I have any particularly bright ideas for how
> immediately.

Basically, I agreed, but I also have no idea yet :(
How about to use this for now then let us think the way?

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock
  2011-07-18  7:08     ` [PATCH 4/4] [CPUFREQ] " Kukjin Kim
@ 2011-07-19 15:03       ` Mark Brown
  0 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2011-07-19 15:03 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: linux-samsung-soc, cpufreq, davej, 'Jongpill Lee',
	'SangWook Ju', 'Jonghwan Choi'

On Mon, Jul 18, 2011 at 04:08:53PM +0900, Kukjin Kim wrote:

> > This feels like something cpufreq should support to at least some extent
> > in the core, especially the thing with forcing a particular mode on
> > suspend.  Not that I have any particularly bright ideas for how
> > immediately.

> Basically, I agreed, but I also have no idea yet :(
> How about to use this for now then let us think the way?

Probably just as well.  For the suspend stuff we should be able to
implement a generic override the governor callback for use in suspend
entry easily enough but for other things I'm drawing a blank right now.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-07-19 15:03 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-05  8:06 [PATCH 0/4] EXYNOS4210: Update exynos4210-cpufreq.c Kukjin Kim
2011-07-05  8:06 ` [PATCH 1/4] [CPUFREQ] EXYNOS4210: Remove regarding busfreq codes Kukjin Kim
2011-07-05  8:06 ` [PATCH 2/4] EXYNOS4210: Change CPU table and divider Kukjin Kim
2011-07-05  8:06 ` [PATCH 3/4] [CPUFREQ] EXYNOS4210: Cleanup sequence and unused codes Kukjin Kim
2011-07-05  8:06 ` [PATCH 4/4] [CPUFREQ] EXYNOS4210: Add Support for DVS Lock Kukjin Kim
2011-07-05  8:49   ` Kyungmin Park
2011-07-08  6:22     ` [PATCH 4/4] " Kukjin Kim
2011-07-09  3:48   ` Mark Brown
2011-07-18  7:08     ` [PATCH 4/4] [CPUFREQ] " Kukjin Kim
2011-07-19 15:03       ` Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.