* [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.