Linux Samsung SOC development
 help / color / mirror / Atom feed
* [PATCH 0/7] ARM: S5PV310: Add support CPUFREQ driver
@ 2010-12-23  5:49 Kukjin Kim
  2010-12-23  5:49 ` [PATCH 1/7] ARM: S5PV310: Update CMU registers for CPUFREQ Kukjin Kim
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: Kukjin Kim @ 2010-12-23  5:49 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: ben-linux

This patch adds support CPUFREQ for S5PV310(S5PC210) SoC.

Following 1st, 3rd, 4th, and 7th patches have been submitted several month ago
and already has been merged in my tree at that time, but I dropped because of
dependency of ARM localtimer and APLL.

Now, submitted MCT(Multi-Core Timer) which can prevent its problem and also other
localtimer patch for avoding same problem. Anyway so, I think, this can support
CPUFREQ of S5PV310(S5PC210).

Basically, I re-based old CPUFREQ driver and recent new CPUFREQ patch which has
been submitted by Mr. Kim, Sangbeom.

[PATCH 1/7] ARM: S5PV310: Update CMU registers for CPUFREQ
[PATCH V3 2/7] ARM: S5PV310: Define missing CMU register for CPUFREQ
[PATCH 3/7] ARM: S5PV310: Add DMC registers and map_desc
[PATCH 4/7] ARM: S5PV310: Add support CPUFREQ
[PATCH V3 5/7] ARM: S5PV310: Update CPUFREQ
[PATCH V3 6/7] ARM: S5PV310: Add FOUT APLL get rate function
[PATCH 7/7] ARM: S5PV310: Update Kconfig and Makefile for supporting CPUFREQ

Merry Christmas :-)
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] 8+ messages in thread

* [PATCH 1/7] ARM: S5PV310: Update CMU registers for CPUFREQ
  2010-12-23  5:49 [PATCH 0/7] ARM: S5PV310: Add support CPUFREQ driver Kukjin Kim
@ 2010-12-23  5:49 ` Kukjin Kim
  2010-12-23  5:49 ` [PATCH V3 2/7] ARM: S5PV310: Define missing CMU register " Kukjin Kim
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kukjin Kim @ 2010-12-23  5:49 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: ben-linux, Sunyoung Kang, Kukjin Kim

From: Sunyoung Kang <sy0816.kang@samsung.com>

This patch adds CMU(Clock Management Unit) registers for S5PV310/S5PC210
CPUFREQ driver and modifies some register names according to datasheet.

Signed-off-by: Sunyoung Kang <sy0816.kang@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/clock.c                   |   12 ++--
 arch/arm/mach-s5pv310/include/mach/regs-clock.h |   77 ++++++++++++++++++++++-
 2 files changed, 81 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
index 58c9d33..fdce2b4 100644
--- a/arch/arm/mach-s5pv310/clock.c
+++ b/arch/arm/mach-s5pv310/clock.c
@@ -244,7 +244,7 @@ static struct clksrc_clk clk_mout_corebus = {
 		.id		= -1,
 	},
 	.sources	= &clkset_mout_corebus,
-	.reg_src	= { .reg = S5P_CLKSRC_CORE, .shift = 4, .size = 1 },
+	.reg_src	= { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
 };
 
 static struct clksrc_clk clk_sclk_dmc = {
@@ -253,7 +253,7 @@ static struct clksrc_clk clk_sclk_dmc = {
 		.id		= -1,
 		.parent		= &clk_mout_corebus.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 12, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
 };
 
 static struct clksrc_clk clk_aclk_cored = {
@@ -262,7 +262,7 @@ static struct clksrc_clk clk_aclk_cored = {
 		.id		= -1,
 		.parent		= &clk_sclk_dmc.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 16, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
 };
 
 static struct clksrc_clk clk_aclk_corep = {
@@ -271,7 +271,7 @@ static struct clksrc_clk clk_aclk_corep = {
 		.id		= -1,
 		.parent		= &clk_aclk_cored.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 20, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
 };
 
 static struct clksrc_clk clk_aclk_acp = {
@@ -280,7 +280,7 @@ static struct clksrc_clk clk_aclk_acp = {
 		.id		= -1,
 		.parent		= &clk_mout_corebus.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 0, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
 };
 
 static struct clksrc_clk clk_pclk_acp = {
@@ -289,7 +289,7 @@ static struct clksrc_clk clk_pclk_acp = {
 		.id		= -1,
 		.parent		= &clk_aclk_acp.clk,
 	},
-	.reg_div	= { .reg = S5P_CLKDIV_CORE0, .shift = 4, .size = 3 },
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
 };
 
 /* Core list of CMU_TOP side */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
index f1028ca..9e9e44c 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -19,6 +19,12 @@
 
 #define S5P_INFORM0			S5P_CLKREG(0x800)
 
+#define S5P_CLKDIV_LEFTBUS		S5P_CLKREG(0x04500)
+#define S5P_CLKDIV_STAT_LEFTBUS		S5P_CLKREG(0x04600)
+
+#define S5P_CLKDIV_RIGHTBUS		S5P_CLKREG(0x08500)
+#define S5P_CLKDIV_STAT_RIGHTBUS	S5P_CLKREG(0x08600)
+
 #define S5P_EPLL_CON0			S5P_CLKREG(0x0C110)
 #define S5P_EPLL_CON1			S5P_CLKREG(0x0C114)
 #define S5P_VPLL_CON0			S5P_CLKREG(0x0C120)
@@ -58,6 +64,8 @@
 #define S5P_CLKSRC_MASK_PERIL0		S5P_CLKREG(0x0C350)
 #define S5P_CLKSRC_MASK_PERIL1		S5P_CLKREG(0x0C354)
 
+#define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
+
 #define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
 #define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
 #define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
@@ -66,8 +74,9 @@
 #define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x0C950)
 #define S5P_CLKGATE_IP_PERIR		S5P_CLKREG(0x0C960)
 
-#define S5P_CLKSRC_CORE			S5P_CLKREG(0x10200)
-#define S5P_CLKDIV_CORE0		S5P_CLKREG(0x10500)
+#define S5P_CLKSRC_DMC			S5P_CLKREG(0x10200)
+#define S5P_CLKDIV_DMC0			S5P_CLKREG(0x10500)
+#define S5P_CLKDIV_STAT_DMC0		S5P_CLKREG(0x10600)
 
 #define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
 #define S5P_MPLL_LOCK			S5P_CLKREG(0x14004)
@@ -84,6 +93,70 @@
 
 #define S5P_CLKGATE_SCLKCPU		S5P_CLKREG(0x14800)
 
+/* APLL_LOCK */
+#define S5P_APLL_LOCKTIME		(0x1C20)	/* 300us */
+
+/* APLL_CON0 */
+#define S5P_APLLCON0_ENABLE_SHIFT	(31)
+#define S5P_APLLCON0_LOCKED_SHIFT	(29)
+#define S5P_APLL_VAL_1000		((250 << 16) | (6 << 8) | 1)
+
+/* CLK_SRC_CPU */
+#define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
+#define S5P_CLKMUX_STATCPU_MUXCORE_MASK	(0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
+
+/* CLKDIV_CPU0 */
+#define S5P_CLKDIV_CPU0_CORE_SHIFT	(0)
+#define S5P_CLKDIV_CPU0_CORE_MASK	(0x7 << S5P_CLKDIV_CPU0_CORE_SHIFT)
+#define S5P_CLKDIV_CPU0_COREM0_SHIFT	(4)
+#define S5P_CLKDIV_CPU0_COREM0_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM0_SHIFT)
+#define S5P_CLKDIV_CPU0_COREM1_SHIFT	(8)
+#define S5P_CLKDIV_CPU0_COREM1_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM1_SHIFT)
+#define S5P_CLKDIV_CPU0_PERIPH_SHIFT	(12)
+#define S5P_CLKDIV_CPU0_PERIPH_MASK	(0x7 << S5P_CLKDIV_CPU0_PERIPH_SHIFT)
+#define S5P_CLKDIV_CPU0_ATB_SHIFT	(16)
+#define S5P_CLKDIV_CPU0_ATB_MASK	(0x7 << S5P_CLKDIV_CPU0_ATB_SHIFT)
+#define S5P_CLKDIV_CPU0_PCLKDBG_SHIFT	(20)
+#define S5P_CLKDIV_CPU0_PCLKDBG_MASK	(0x7 << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT)
+#define S5P_CLKDIV_CPU0_APLL_SHIFT	(24)
+#define S5P_CLKDIV_CPU0_APLL_MASK	(0x7 << S5P_CLKDIV_CPU0_APLL_SHIFT)
+
+/* CLKDIV_DMC0 */
+#define S5P_CLKDIV_DMC0_ACP_SHIFT	(0)
+#define S5P_CLKDIV_DMC0_ACP_MASK	(0x7 << S5P_CLKDIV_DMC0_ACP_SHIFT)
+#define S5P_CLKDIV_DMC0_ACPPCLK_SHIFT	(4)
+#define S5P_CLKDIV_DMC0_ACPPCLK_MASK	(0x7 << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT)
+#define S5P_CLKDIV_DMC0_DPHY_SHIFT	(8)
+#define S5P_CLKDIV_DMC0_DPHY_MASK	(0x7 << S5P_CLKDIV_DMC0_DPHY_SHIFT)
+#define S5P_CLKDIV_DMC0_DMC_SHIFT	(12)
+#define S5P_CLKDIV_DMC0_DMC_MASK	(0x7 << S5P_CLKDIV_DMC0_DMC_SHIFT)
+#define S5P_CLKDIV_DMC0_DMCD_SHIFT	(16)
+#define S5P_CLKDIV_DMC0_DMCD_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCD_SHIFT)
+#define S5P_CLKDIV_DMC0_DMCP_SHIFT	(20)
+#define S5P_CLKDIV_DMC0_DMCP_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCP_SHIFT)
+#define S5P_CLKDIV_DMC0_COPY2_SHIFT	(24)
+#define S5P_CLKDIV_DMC0_COPY2_MASK	(0x7 << S5P_CLKDIV_DMC0_COPY2_SHIFT)
+#define S5P_CLKDIV_DMC0_CORETI_SHIFT	(28)
+#define S5P_CLKDIV_DMC0_CORETI_MASK	(0x7 << S5P_CLKDIV_DMC0_CORETI_SHIFT)
+
+/* CLKDIV_TOP */
+#define S5P_CLKDIV_TOP_ACLK200_SHIFT	(0)
+#define S5P_CLKDIV_TOP_ACLK200_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK200_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK100_SHIFT	(4)
+#define S5P_CLKDIV_TOP_ACLK100_MASK	(0xf << S5P_CLKDIV_TOP_ACLK100_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK160_SHIFT	(8)
+#define S5P_CLKDIV_TOP_ACLK160_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK160_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK133_SHIFT	(12)
+#define S5P_CLKDIV_TOP_ACLK133_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK133_SHIFT)
+#define S5P_CLKDIV_TOP_ONENAND_SHIFT	(16)
+#define S5P_CLKDIV_TOP_ONENAND_MASK	(0x7 << S5P_CLKDIV_TOP_ONENAND_SHIFT)
+
+/* CLKDIV_LEFTBUS / CLKDIV_RIGHTBUS*/
+#define S5P_CLKDIV_BUS_GDLR_SHIFT	(0)
+#define S5P_CLKDIV_BUS_GDLR_MASK	(0x7 << S5P_CLKDIV_BUS_GDLR_SHIFT)
+#define S5P_CLKDIV_BUS_GPLR_SHIFT	(4)
+#define S5P_CLKDIV_BUS_GPLR_MASK	(0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
+
 /* Compatibility defines */
 
 #define S5P_EPLL_CON			S5P_EPLL_CON0
-- 
1.6.2.5

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

* [PATCH V3 2/7] ARM: S5PV310: Define missing CMU register for CPUFREQ
  2010-12-23  5:49 [PATCH 0/7] ARM: S5PV310: Add support CPUFREQ driver Kukjin Kim
  2010-12-23  5:49 ` [PATCH 1/7] ARM: S5PV310: Update CMU registers for CPUFREQ Kukjin Kim
@ 2010-12-23  5:49 ` Kukjin Kim
  2010-12-23  5:49 ` [PATCH 3/7] ARM: S5PV310: Add DMC registers and map_desc Kukjin Kim
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kukjin Kim @ 2010-12-23  5:49 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: ben-linux, Sangwook Ju, Sangbeom Kim, Kukjin Kim

From: Sangwook Ju <sw.ju@samsung.com>

This patch adds missing CMU(Clock Management Unit) registers for
updated S5PV310 CPUFREQ driver.

Signed-off-by: Sangwook Ju <sw.ju@samsung.com>
Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/include/mach/regs-clock.h |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
index 9e9e44c..b5c4ada 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -89,7 +89,9 @@
 #define S5P_CLKMUX_STATCPU		S5P_CLKREG(0x14400)
 
 #define S5P_CLKDIV_CPU			S5P_CLKREG(0x14500)
+#define S5P_CLKDIV_CPU1			S5P_CLKREG(0x14504)
 #define S5P_CLKDIV_STATCPU		S5P_CLKREG(0x14600)
+#define S5P_CLKDIV_STATCPU1		S5P_CLKREG(0x14604)
 
 #define S5P_CLKGATE_SCLKCPU		S5P_CLKREG(0x14800)
 
@@ -100,6 +102,7 @@
 #define S5P_APLLCON0_ENABLE_SHIFT	(31)
 #define S5P_APLLCON0_LOCKED_SHIFT	(29)
 #define S5P_APLL_VAL_1000		((250 << 16) | (6 << 8) | 1)
+#define S5P_APLL_VAL_800		((200 << 16) | (6 << 8) | 1)
 
 /* CLK_SRC_CPU */
 #define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
-- 
1.6.2.5

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

* [PATCH 3/7] ARM: S5PV310: Add DMC registers and map_desc
  2010-12-23  5:49 [PATCH 0/7] ARM: S5PV310: Add support CPUFREQ driver Kukjin Kim
  2010-12-23  5:49 ` [PATCH 1/7] ARM: S5PV310: Update CMU registers for CPUFREQ Kukjin Kim
  2010-12-23  5:49 ` [PATCH V3 2/7] ARM: S5PV310: Define missing CMU register " Kukjin Kim
@ 2010-12-23  5:49 ` Kukjin Kim
  2010-12-23  5:49 ` [PATCH 4/7] ARM: S5PV310: Add support CPUFREQ Kukjin Kim
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kukjin Kim @ 2010-12-23  5:49 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: ben-linux, Sunyoung Kang, Kukjin Kim

From: Sunyoung Kang <sy0816.kang@samsung.com>

This patch adds DMC io mapping for access it and adds registers.
This is used in checking DRAM memory type.

Signed-off-by: Sunyoung Kang <sy0816.kang@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/cpu.c                   |    5 +++++
 arch/arm/mach-s5pv310/include/mach/map.h      |    2 ++
 arch/arm/mach-s5pv310/include/mach/regs-mem.h |   23 +++++++++++++++++++++++
 3 files changed, 30 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/include/mach/regs-mem.h

diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
index 82ce4aa..283dd75 100644
--- a/arch/arm/mach-s5pv310/cpu.c
+++ b/arch/arm/mach-s5pv310/cpu.c
@@ -73,6 +73,11 @@ static struct map_desc s5pv310_iodesc[] __initdata = {
 		.length		= SZ_256,
 		.type		= MT_DEVICE,
 	}, {
+		.virtual	= (unsigned long)S5P_VA_DMC0,
+		.pfn		= __phys_to_pfn(S5PV310_PA_DMC0),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
 		.virtual	= (unsigned long)S3C_VA_UART,
 		.pfn		= __phys_to_pfn(S3C_PA_UART),
 		.length		= SZ_512K,
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
index 7acf4e7..37294f1 100644
--- a/arch/arm/mach-s5pv310/include/mach/map.h
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -44,6 +44,8 @@
 #define S5PV310_PA_WATCHDOG		(0x10060000)
 #define S5PV310_PA_RTC			(0x10070000)
 
+#define S5PV310_PA_DMC0			(0x10400000)
+
 #define S5PV310_PA_COMBINER		(0x10448000)
 
 #define S5PV310_PA_COREPERI		(0x10500000)
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-mem.h b/arch/arm/mach-s5pv310/include/mach/regs-mem.h
new file mode 100644
index 0000000..8342271
--- /dev/null
+++ b/arch/arm/mach-s5pv310/include/mach/regs-mem.h
@@ -0,0 +1,23 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/regs-mem.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5PV310 - SROMC and DMC register definitions
+ *
+ * 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.
+*/
+
+#ifndef __ASM_ARCH_REGS_MEM_H
+#define __ASM_ARCH_REGS_MEM_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_DMC0_MEMCON_OFFSET		0x04
+
+#define S5P_DMC0_MEMTYPE_SHIFT		8
+#define S5P_DMC0_MEMTYPE_MASK		0xF
+
+#endif /* __ASM_ARCH_REGS_MEM_H */
-- 
1.6.2.5

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

* [PATCH 4/7] ARM: S5PV310: Add support CPUFREQ
  2010-12-23  5:49 [PATCH 0/7] ARM: S5PV310: Add support CPUFREQ driver Kukjin Kim
                   ` (2 preceding siblings ...)
  2010-12-23  5:49 ` [PATCH 3/7] ARM: S5PV310: Add DMC registers and map_desc Kukjin Kim
@ 2010-12-23  5:49 ` Kukjin Kim
  2010-12-23  5:49 ` [PATCH V3 5/7] ARM: S5PV310: Update CPUFREQ Kukjin Kim
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: Kukjin Kim @ 2010-12-23  5:49 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: ben-linux, Sunyoung Kang, Kukjin Kim

From: Sunyoung Kang <sy0816.kang@samsung.com>

This patch adds support CPUFREQ driver for S5PV310 and S5PC210. This can
support DVFS(Dynamic Voltage and Frequency Scaling). The voltage scaling
depends on existence of regulator.

Sigend-off-by: Sunyoung Kang <sy0816.kang@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/cpufreq.c |  561 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 561 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/cpufreq.c

diff --git a/arch/arm/mach-s5pv310/cpufreq.c b/arch/arm/mach-s5pv310/cpufreq.c
new file mode 100644
index 0000000..bcd4ebf
--- /dev/null
+++ b/arch/arm/mach-s5pv310/cpufreq.c
@@ -0,0 +1,561 @@
+/* linux/arch/arm/mach-s5pv310/cpufreq.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * S5PV310 - CPU frequency scaling 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.
+*/
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/cpufreq.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-mem.h>
+
+#include <plat/clock.h>
+
+static struct clk *cpu_clk;
+static struct clk *moutcore;
+static struct clk *mout_mpll;
+static struct clk *mout_apll;
+
+#ifdef CONFIG_REGULATOR
+static struct regulator *arm_regulator;
+static struct regulator *int_regulator;
+#endif
+
+static struct cpufreq_freqs freqs;
+static unsigned int armclk_use_apll;
+static unsigned int memtype;
+
+enum s5pv310_memory_type {
+	DDR2 = 4,
+	LPDDR2,
+	DDR3,
+};
+
+enum cpufreq_level_index {
+	L0, L1, L2, L3, L4, CPUFREQ_LEVEL_END,
+};
+
+static struct cpufreq_frequency_table s5pv310_freq_table[] = {
+	{L0, 1000*1000},
+	{L1, 800*1000},
+	{L2, 400*1000},
+	{L3, 200*1000},
+	{L4, 100*1000},
+	{0, CPUFREQ_TABLE_END},
+};
+
+static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END + 1][7] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
+	 *		DIVATB, DIVPCLK_DBG, DIVAPLL }
+	 */
+
+	/* ARM L0: 1000MHz */
+	{ 0, 3, 7, 3, 3, 0, 0 },
+
+	/* ARM L1: 800MHz */
+	{ 0, 3, 7, 3, 3, 0, 0 },
+
+	/* ARM L2: 400MHz */
+	{ 1, 1, 3, 1, 1, 0, 0 },
+
+	/* ARM L3: 200MHz */
+	{ 3, 0, 1, 0, 0, 0, 0 },
+
+	/* ARM L4A: 100MHz, for DDR2/3 */
+	{ 7, 0, 1, 0, 0, 0, 0 },
+
+	/* ARM L4B: 100MHz, for LPDDR2 (SMDKV310 has LPDDR2) */
+	{ 7, 0, 1, 0, 0, 0, 0 },
+};
+
+static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END + 1][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: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L3: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L4A: 400MHz, for DDR2/3 */
+	{ 7, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L4B: 200MHz, for LPDDR2 */
+	{ 7, 1, 1, 3, 1, 1, 3, 1 },
+};
+
+static unsigned int clkdiv_top[CPUFREQ_LEVEL_END + 1][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: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L3: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L4A: 100MHz */
+	{ 7, 7, 7, 7, 1 },
+
+	/* ACLK200 L4B: 100MHz */
+	{ 7, 7, 7, 7, 1 },
+};
+
+static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END + 1][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: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L3: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L4A: 100MHz */
+	{ 7, 1 },
+
+	/* ACLK_GDL/R L4B: 100MHz */
+	{ 7, 1 },
+};
+
+struct cpufreq_voltage_table {
+	unsigned int	index;		/* any */
+	unsigned int	arm_volt;	/* uV */
+	unsigned int	int_volt;
+};
+
+static struct cpufreq_voltage_table s5pv310_volt_table[] = {
+	{
+		.index		= L0,
+		.arm_volt	= 1200000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L1,
+		.arm_volt	= 1100000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L2,
+		.arm_volt	= 1050000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L3,
+		.arm_volt	= 1050000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L4,
+		.arm_volt	= 1000000,
+		.int_volt	= 1000000,
+	},
+};
+
+int s5pv310_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, s5pv310_freq_table);
+}
+
+unsigned int s5pv310_getspeed(unsigned int cpu)
+{
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+void s5pv310_set_clkdiv(unsigned int div_index)
+{
+	unsigned int tmp;
+
+	/* 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));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU);
+	} while (tmp & 0x1111111);
+
+	/* 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 int s5pv310_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq,
+			  unsigned int relation)
+{
+	unsigned int index, div_index, tmp;
+	unsigned int arm_volt, int_volt;
+	unsigned int need_apll = 0;
+
+	freqs.old = s5pv310_getspeed(policy->cpu);
+
+	if (cpufreq_frequency_table_target(policy, s5pv310_freq_table,
+					   target_freq, relation, &index))
+		return -EINVAL;
+
+	freqs.new = s5pv310_freq_table[index].frequency;
+	freqs.cpu = policy->cpu;
+
+	if (freqs.new == freqs.old)
+		return 0;
+
+	/*
+	 * If freqs.new is higher than 800MHz
+	 * cpufreq driver should turn on apll
+	 */
+	if (index < L1)
+		need_apll = 1;
+
+	/* If the memory type is LPDDR2, use L4-B instead of L4-A */
+	if ((index == L4) && (memtype == LPDDR2))
+		div_index = index + 1;
+	else
+		div_index = index;
+
+	/* get the voltage value */
+	arm_volt = s5pv310_volt_table[index].arm_volt;
+	int_volt = s5pv310_volt_table[index].int_volt;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* control regulator */
+	if (freqs.new > freqs.old) {
+		/* Voltage up */
+#ifdef CONFIG_REGULATOR
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+#endif
+	}
+
+	/* Clock Configuration Procedure */
+
+	/* 1. Change the system clock divider values */
+	s5pv310_set_clkdiv(div_index);
+
+	/* 2. Change the divider values for special clocks in CMU_TOP */
+	/* currently nothing */
+
+	/* 3. Change the XPLL values or Select the parent XPLL */
+	if (need_apll) {
+		if (!armclk_use_apll) {
+			/*
+			 * If the parent clock of armclk isn't apll
+			 * here need to set apll (include m,p,s value)
+			 */
+
+			/* a. MUX_CORE_SEL = MPLL,
+			 * ARMCLK uses MPLL for lock time */
+			clk_set_parent(moutcore, mout_mpll);
+
+			do {
+				tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
+					>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
+				tmp &= 0x7;
+			} while (tmp != 0x2);
+
+			/* b. Set APLL Lock time */
+			__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
+
+			/* c. Change PLL PMS values */
+			__raw_writel(S5P_APLL_VAL_1000, S5P_APLL_CON0);
+
+			/* d. Turn on a PLL */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp |= (0x1 << S5P_APLLCON0_ENABLE_SHIFT);
+			__raw_writel(tmp, S5P_APLL_CON0);
+
+			/* e. wait_lock_time */
+			do {
+				tmp = __raw_readl(S5P_APLL_CON0);
+			} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
+
+			armclk_use_apll = 1;
+
+		}
+
+		/* MUX_CORE_SEL = APLL */
+		clk_set_parent(moutcore, mout_apll);
+
+		do {
+			tmp = __raw_readl(S5P_CLKMUX_STATCPU);
+			tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
+		} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
+
+	} else {
+		if (clk_get_parent(moutcore) != mout_mpll) {
+			clk_set_parent(moutcore, mout_mpll);
+
+			do {
+				tmp = __raw_readl(S5P_CLKMUX_STATCPU);
+				tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
+			} while (tmp != (0x2 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
+		}
+	}
+
+	/* control regulator */
+	if (freqs.new < freqs.old) {
+		/* Voltage down */
+#ifdef CONFIG_REGULATOR
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+#endif
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int s5pv310_cpufreq_suspend(struct cpufreq_policy *policy,
+				   pm_message_t pmsg)
+{
+	return 0;
+}
+
+static int s5pv310_cpufreq_resume(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+#endif
+
+static int s5pv310_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	policy->cur = policy->min = policy->max = s5pv310_getspeed(policy->cpu);
+
+	cpufreq_frequency_table_get_attr(s5pv310_freq_table, policy->cpu);
+
+	/* set the transition latency value */
+	policy->cpuinfo.transition_latency = 100000;
+
+	/*
+	 * S5PV310 multi-core processors has 2 cores
+	 * that the frequency cannot be set independently.
+	 * Each cpu is bound to the same speed.
+	 * So the affected cpu is all of the cpus.
+	 */
+	cpumask_setall(policy->cpus);
+
+	return cpufreq_frequency_table_cpuinfo(policy, s5pv310_freq_table);
+}
+
+static struct cpufreq_driver s5pv310_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= s5pv310_verify_speed,
+	.target		= s5pv310_target,
+	.get		= s5pv310_getspeed,
+	.init		= s5pv310_cpufreq_cpu_init,
+	.name		= "s5pv310_cpufreq",
+#ifdef CONFIG_PM
+	.suspend	= s5pv310_cpufreq_suspend,
+	.resume		= s5pv310_cpufreq_resume,
+#endif
+};
+
+static int __init s5pv310_cpufreq_init(void)
+{
+	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;
+
+	mout_mpll = clk_get(NULL, "mout_mpll");
+	if (IS_ERR(mout_mpll))
+		goto out;
+
+	mout_apll = clk_get(NULL, "mout_apll");
+	if (IS_ERR(mout_apll))
+		goto out;
+
+#ifdef CONFIG_REGULATOR
+	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;
+	}
+
+	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;
+	}
+#endif
+
+	/* check parent clock of armclk */
+	tmp = __raw_readl(S5P_CLKSRC_CPU);
+	if (tmp & S5P_CLKSRC_CPU_MUXCORE_SHIFT)
+		armclk_use_apll = 0;
+	else
+		armclk_use_apll = 1;
+
+	/*
+	 * 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(&s5pv310_driver);
+
+out:
+	if (!IS_ERR(cpu_clk))
+		clk_put(cpu_clk);
+
+	if (!IS_ERR(moutcore))
+		clk_put(moutcore);
+
+	if (!IS_ERR(mout_mpll))
+		clk_put(mout_mpll);
+
+	if (!IS_ERR(mout_apll))
+		clk_put(mout_apll);
+
+#ifdef CONFIG_REGULATOR
+	if (!IS_ERR(arm_regulator))
+		regulator_put(arm_regulator);
+
+	if (!IS_ERR(int_regulator))
+		regulator_put(int_regulator);
+#endif
+
+	printk(KERN_ERR "%s: failed initialization\n", __func__);
+
+	return -EINVAL;
+}
+late_initcall(s5pv310_cpufreq_init);
-- 
1.6.2.5

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

* [PATCH V3 5/7] ARM: S5PV310: Update CPUFREQ
  2010-12-23  5:49 [PATCH 0/7] ARM: S5PV310: Add support CPUFREQ driver Kukjin Kim
                   ` (3 preceding siblings ...)
  2010-12-23  5:49 ` [PATCH 4/7] ARM: S5PV310: Add support CPUFREQ Kukjin Kim
@ 2010-12-23  5:49 ` Kukjin Kim
  2010-12-23  5:49 ` [PATCH V3 6/7] ARM: S5PV310: Add FOUT APLL get rate function Kukjin Kim
  2010-12-23  5:49 ` [PATCH 7/7] ARM: S5PV310: Update Kconfig and Makefile for supporting CPUFREQ Kukjin Kim
  6 siblings, 0 replies; 8+ messages in thread
From: Kukjin Kim @ 2010-12-23  5:49 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: ben-linux, Sangwook Ju, Sangbeom Kim, Kukjin Kim

From: Sangwook Ju <sw.ju@samsung.com>

This patch updates following of CPUFREQ.

- Updated DVFS table and divider value
- Added common function
- Added some function for changing APLL and setting

Signed-off-by: Sangwook Ju <sw.ju@samsung.com>
Reviewed-by: Jaecheol Lee <jc.lee@samsung.com>
Signed-off-by: Sangbeom Kim <sbkim73@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/cpufreq.c |  301 +++++++++++++++++++++------------------
 1 files changed, 160 insertions(+), 141 deletions(-)

diff --git a/arch/arm/mach-s5pv310/cpufreq.c b/arch/arm/mach-s5pv310/cpufreq.c
index bcd4ebf..b04cbc7 100644
--- a/arch/arm/mach-s5pv310/cpufreq.c
+++ b/arch/arm/mach-s5pv310/cpufreq.c
@@ -24,6 +24,7 @@
 #include <mach/regs-mem.h>
 
 #include <plat/clock.h>
+#include <plat/pm.h>
 
 static struct clk *cpu_clk;
 static struct clk *moutcore;
@@ -36,7 +37,6 @@ static struct regulator *int_regulator;
 #endif
 
 static struct cpufreq_freqs freqs;
-static unsigned int armclk_use_apll;
 static unsigned int memtype;
 
 enum s5pv310_memory_type {
@@ -46,19 +46,18 @@ enum s5pv310_memory_type {
 };
 
 enum cpufreq_level_index {
-	L0, L1, L2, L3, L4, CPUFREQ_LEVEL_END,
+	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
 };
 
 static struct cpufreq_frequency_table s5pv310_freq_table[] = {
 	{L0, 1000*1000},
 	{L1, 800*1000},
 	{L2, 400*1000},
-	{L3, 200*1000},
-	{L4, 100*1000},
+	{L3, 100*1000},
 	{0, CPUFREQ_TABLE_END},
 };
 
-static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END + 1][7] = {
+static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
 	/*
 	 * Clock divider value for following
 	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
@@ -66,25 +65,38 @@ static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END + 1][7] = {
 	 */
 
 	/* ARM L0: 1000MHz */
-	{ 0, 3, 7, 3, 3, 0, 0 },
+	{ 0, 3, 7, 3, 3, 0, 1 },
 
 	/* ARM L1: 800MHz */
-	{ 0, 3, 7, 3, 3, 0, 0 },
+	{ 0, 3, 7, 3, 3, 0, 1 },
 
 	/* ARM L2: 400MHz */
-	{ 1, 1, 3, 1, 1, 0, 0 },
+	{ 0, 1, 3, 1, 3, 0, 1 },
 
-	/* ARM L3: 200MHz */
-	{ 3, 0, 1, 0, 0, 0, 0 },
+	/* ARM L3: 100MHz */
+	{ 0, 0, 1, 0, 3, 1, 1 },
+};
 
-	/* ARM L4A: 100MHz, for DDR2/3 */
-	{ 7, 0, 1, 0, 0, 0, 0 },
+static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCOPY, DIVHPM }
+	 */
+
+	 /* ARM L0: 1000MHz */
+	{ 3, 0 },
+
+	/* ARM L1: 800MHz */
+	{ 3, 0 },
 
-	/* ARM L4B: 100MHz, for LPDDR2 (SMDKV310 has LPDDR2) */
-	{ 7, 0, 1, 0, 0, 0, 0 },
+	/* ARM L2: 400MHz */
+	{ 3, 0 },
+
+	/* ARM L3: 100MHz */
+	{ 3, 0 },
 };
 
-static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END + 1][8] = {
+static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
 	/*
 	 * Clock divider value for following
 	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
@@ -97,20 +109,14 @@ static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END + 1][8] = {
 	/* DMC L1: 400MHz */
 	{ 3, 1, 1, 1, 1, 1, 3, 1 },
 
-	/* DMC L2: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L3: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L4A: 400MHz, for DDR2/3 */
-	{ 7, 1, 1, 1, 1, 1, 3, 1 },
+	/* DMC L2: 266.7MHz */
+	{ 7, 1, 1, 2, 1, 1, 3, 1 },
 
-	/* DMC L4B: 200MHz, for LPDDR2 */
+	/* DMC L3: 200MHz */
 	{ 7, 1, 1, 3, 1, 1, 3, 1 },
 };
 
-static unsigned int clkdiv_top[CPUFREQ_LEVEL_END + 1][5] = {
+static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
 	/*
 	 * Clock divider value for following
 	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
@@ -122,20 +128,14 @@ static unsigned int clkdiv_top[CPUFREQ_LEVEL_END + 1][5] = {
 	/* ACLK200 L1: 200MHz */
 	{ 3, 7, 4, 5, 1 },
 
-	/* ACLK200 L2: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L3: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L4A: 100MHz */
-	{ 7, 7, 7, 7, 1 },
+	/* ACLK200 L2: 160MHz */
+	{ 4, 7, 5, 7, 1 },
 
-	/* ACLK200 L4B: 100MHz */
-	{ 7, 7, 7, 7, 1 },
+	/* ACLK200 L3: 133.3MHz */
+	{ 5, 7, 7, 7, 1 },
 };
 
-static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END + 1][2] = {
+static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
 	/*
 	 * Clock divider value for following
 	 * { DIVGDL/R, DIVGPL/R }
@@ -147,17 +147,11 @@ static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END + 1][2] = {
 	/* ACLK_GDL/R L1: 200MHz */
 	{ 3, 1 },
 
-	/* ACLK_GDL/R L2: 200MHz */
-	{ 3, 1 },
-
-	/* ACLK_GDL/R L3: 200MHz */
-	{ 3, 1 },
+	/* ACLK_GDL/R L2: 160MHz */
+	{ 4, 1 },
 
-	/* ACLK_GDL/R L4A: 100MHz */
-	{ 7, 1 },
-
-	/* ACLK_GDL/R L4B: 100MHz */
-	{ 7, 1 },
+	/* ACLK_GDL/R L3: 133.3MHz */
+	{ 5, 1 },
 };
 
 struct cpufreq_voltage_table {
@@ -166,7 +160,7 @@ struct cpufreq_voltage_table {
 	unsigned int	int_volt;
 };
 
-static struct cpufreq_voltage_table s5pv310_volt_table[] = {
+static struct cpufreq_voltage_table s5pv310_volt_table[CPUFREQ_LEVEL_END] = {
 	{
 		.index		= L0,
 		.arm_volt	= 1200000,
@@ -177,19 +171,29 @@ static struct cpufreq_voltage_table s5pv310_volt_table[] = {
 		.int_volt	= 1100000,
 	}, {
 		.index		= L2,
-		.arm_volt	= 1050000,
-		.int_volt	= 1100000,
+		.arm_volt	= 1000000,
+		.int_volt	= 1000000,
 	}, {
 		.index		= L3,
-		.arm_volt	= 1050000,
-		.int_volt	= 1100000,
-	}, {
-		.index		= L4,
-		.arm_volt	= 1000000,
+		.arm_volt	= 900000,
 		.int_volt	= 1000000,
 	},
 };
 
+static unsigned int s5pv310_apll_pms_table[CPUFREQ_LEVEL_END] = {
+	/* APLL FOUT L0: 1000MHz */
+	((250 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L1: 800MHz */
+	((200 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L2 : 400MHz */
+	((200 << 16) | (6 << 8) | 2),
+
+	/* APLL FOUT L3: 100MHz */
+	((200 << 16) | (6 << 8) | 4),
+};
+
 int s5pv310_verify_speed(struct cpufreq_policy *policy)
 {
 	return cpufreq_frequency_table_verify(policy, s5pv310_freq_table);
@@ -227,6 +231,21 @@ void s5pv310_set_clkdiv(unsigned int div_index)
 		tmp = __raw_readl(S5P_CLKDIV_STATCPU);
 	} while (tmp & 0x1111111);
 
+	/* Change Divider - CPU1 */
+
+	tmp = __raw_readl(S5P_CLKDIV_CPU1);
+
+	tmp &= ~((0x7 << 4) | 0x7);
+
+	tmp |= ((clkdiv_cpu1[div_index][0] << 4) |
+		(clkdiv_cpu1[div_index][1] << 0));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU1);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
+	} while (tmp & 0x11);
+
 	/* Change Divider - DMC0 */
 
 	tmp = __raw_readl(S5P_CLKDIV_DMC0);
@@ -302,17 +321,101 @@ void s5pv310_set_clkdiv(unsigned int div_index)
 	} while (tmp & 0x11);
 }
 
+static void s5pv310_set_apll(unsigned int index)
+{
+	unsigned int tmp;
+
+	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
+	clk_set_parent(moutcore, mout_mpll);
+
+	do {
+		tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
+			>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
+		tmp &= 0x7;
+	} while (tmp != 0x2);
+
+	/* 2. Set APLL Lock time */
+	__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
+
+	/* 3. Change PLL PMS values */
+	tmp = __raw_readl(S5P_APLL_CON0);
+	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
+	tmp |= s5pv310_apll_pms_table[index];
+	__raw_writel(tmp, S5P_APLL_CON0);
+
+	/* 4. wait_lock_time */
+	do {
+		tmp = __raw_readl(S5P_APLL_CON0);
+	} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
+
+	/* 5. MUX_CORE_SEL = APLL */
+	clk_set_parent(moutcore, mout_apll);
+
+	do {
+		tmp = __raw_readl(S5P_CLKMUX_STATCPU);
+		tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
+	} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
+}
+
+static void s5pv310_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 == s5pv310_freq_table[L0].frequency) {
+			/* 1. Change the system clock divider values */
+			s5pv310_set_clkdiv(new_index);
+
+			/* 2. Change the apll m,p,s value */
+			s5pv310_set_apll(new_index);
+		} else {
+			/* 1. Change the system clock divider values */
+			s5pv310_set_clkdiv(new_index);
+
+			/* 2. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (s5pv310_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 == s5pv310_freq_table[L0].frequency) {
+			/* 1. Change the apll m,p,s value */
+			s5pv310_set_apll(new_index);
+
+			/* 2. Change the system clock divider values */
+			s5pv310_set_clkdiv(new_index);
+		} else {
+			/* 1. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (s5pv310_apll_pms_table[new_index] & 0x7);
+			__raw_writel(tmp, S5P_APLL_CON0);
+
+			/* 2. Change the system clock divider values */
+			s5pv310_set_clkdiv(new_index);
+		}
+	}
+}
+
 static int s5pv310_target(struct cpufreq_policy *policy,
 			  unsigned int target_freq,
 			  unsigned int relation)
 {
-	unsigned int index, div_index, tmp;
+	unsigned int index, old_index;
 	unsigned int arm_volt, int_volt;
-	unsigned int need_apll = 0;
 
 	freqs.old = s5pv310_getspeed(policy->cpu);
 
 	if (cpufreq_frequency_table_target(policy, s5pv310_freq_table,
+					   freqs.old, relation, &old_index))
+		return -EINVAL;
+
+	if (cpufreq_frequency_table_target(policy, s5pv310_freq_table,
 					   target_freq, relation, &index))
 		return -EINVAL;
 
@@ -322,19 +425,6 @@ static int s5pv310_target(struct cpufreq_policy *policy,
 	if (freqs.new == freqs.old)
 		return 0;
 
-	/*
-	 * If freqs.new is higher than 800MHz
-	 * cpufreq driver should turn on apll
-	 */
-	if (index < L1)
-		need_apll = 1;
-
-	/* If the memory type is LPDDR2, use L4-B instead of L4-A */
-	if ((index == L4) && (memtype == LPDDR2))
-		div_index = index + 1;
-	else
-		div_index = index;
-
 	/* get the voltage value */
 	arm_volt = s5pv310_volt_table[index].arm_volt;
 	int_volt = s5pv310_volt_table[index].int_volt;
@@ -351,69 +441,7 @@ static int s5pv310_target(struct cpufreq_policy *policy,
 	}
 
 	/* Clock Configuration Procedure */
-
-	/* 1. Change the system clock divider values */
-	s5pv310_set_clkdiv(div_index);
-
-	/* 2. Change the divider values for special clocks in CMU_TOP */
-	/* currently nothing */
-
-	/* 3. Change the XPLL values or Select the parent XPLL */
-	if (need_apll) {
-		if (!armclk_use_apll) {
-			/*
-			 * If the parent clock of armclk isn't apll
-			 * here need to set apll (include m,p,s value)
-			 */
-
-			/* a. MUX_CORE_SEL = MPLL,
-			 * ARMCLK uses MPLL for lock time */
-			clk_set_parent(moutcore, mout_mpll);
-
-			do {
-				tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
-					>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
-				tmp &= 0x7;
-			} while (tmp != 0x2);
-
-			/* b. Set APLL Lock time */
-			__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
-
-			/* c. Change PLL PMS values */
-			__raw_writel(S5P_APLL_VAL_1000, S5P_APLL_CON0);
-
-			/* d. Turn on a PLL */
-			tmp = __raw_readl(S5P_APLL_CON0);
-			tmp |= (0x1 << S5P_APLLCON0_ENABLE_SHIFT);
-			__raw_writel(tmp, S5P_APLL_CON0);
-
-			/* e. wait_lock_time */
-			do {
-				tmp = __raw_readl(S5P_APLL_CON0);
-			} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
-
-			armclk_use_apll = 1;
-
-		}
-
-		/* MUX_CORE_SEL = APLL */
-		clk_set_parent(moutcore, mout_apll);
-
-		do {
-			tmp = __raw_readl(S5P_CLKMUX_STATCPU);
-			tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
-		} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
-
-	} else {
-		if (clk_get_parent(moutcore) != mout_mpll) {
-			clk_set_parent(moutcore, mout_mpll);
-
-			do {
-				tmp = __raw_readl(S5P_CLKMUX_STATCPU);
-				tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
-			} while (tmp != (0x2 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
-		}
-	}
+	s5pv310_set_frequency(old_index, index);
 
 	/* control regulator */
 	if (freqs.new < freqs.old) {
@@ -477,8 +505,6 @@ static struct cpufreq_driver s5pv310_driver = {
 
 static int __init s5pv310_cpufreq_init(void)
 {
-	unsigned int tmp;
-
 	cpu_clk = clk_get(NULL, "armclk");
 	if (IS_ERR(cpu_clk))
 		return PTR_ERR(cpu_clk);
@@ -509,13 +535,6 @@ static int __init s5pv310_cpufreq_init(void)
 	}
 #endif
 
-	/* check parent clock of armclk */
-	tmp = __raw_readl(S5P_CLKSRC_CPU);
-	if (tmp & S5P_CLKSRC_CPU_MUXCORE_SHIFT)
-		armclk_use_apll = 0;
-	else
-		armclk_use_apll = 1;
-
 	/*
 	 * Check DRAM type.
 	 * Because DVFS level is different according to DRAM type.
-- 
1.6.2.5

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

* [PATCH V3 6/7] ARM: S5PV310: Add FOUT APLL get rate function
  2010-12-23  5:49 [PATCH 0/7] ARM: S5PV310: Add support CPUFREQ driver Kukjin Kim
                   ` (4 preceding siblings ...)
  2010-12-23  5:49 ` [PATCH V3 5/7] ARM: S5PV310: Update CPUFREQ Kukjin Kim
@ 2010-12-23  5:49 ` Kukjin Kim
  2010-12-23  5:49 ` [PATCH 7/7] ARM: S5PV310: Update Kconfig and Makefile for supporting CPUFREQ Kukjin Kim
  6 siblings, 0 replies; 8+ messages in thread
From: Kukjin Kim @ 2010-12-23  5:49 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: ben-linux, Jaecheol Lee, Sangwook Ju, Kukjin Kim

From: Jaecheol Lee <jc.lee@samsung.com>

FOUT APLL clock is used as a source of ARM core clock. So we need that the
clock source can be changed dynamically by using CPUFREQ driver. This patch
can give correct frequency when calling clk_get_rate() function.

Signed-off-by: Jaecheol Lee <jc.lee@samsung.com>
Signed-off-by: Sangwook Ju <sw.ju@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/mach-s5pv310/clock.c |   16 +++++++++++++++-
 1 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
index fdce2b4..752a07e 100644
--- a/arch/arm/mach-s5pv310/clock.c
+++ b/arch/arm/mach-s5pv310/clock.c
@@ -990,6 +990,17 @@ static struct clksrc_clk *sysclks[] = {
 	&clk_dout_mmc4,
 };
 
+static int xtal_rate;
+
+static unsigned long s5pv310_fout_apll_get_rate(struct clk *clk)
+{
+	return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508);
+}
+
+static struct clk_ops s5pv310_fout_apll_ops = {
+	.get_rate = s5pv310_fout_apll_get_rate,
+};
+
 void __init_or_cpufreq s5pv310_setup_clocks(void)
 {
 	struct clk *xtal_clk;
@@ -1013,6 +1024,9 @@ void __init_or_cpufreq s5pv310_setup_clocks(void)
 	BUG_ON(IS_ERR(xtal_clk));
 
 	xtal = clk_get_rate(xtal_clk);
+
+	xtal_rate = xtal;
+
 	clk_put(xtal_clk);
 
 	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
@@ -1026,7 +1040,7 @@ void __init_or_cpufreq s5pv310_setup_clocks(void)
 	vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
 				__raw_readl(S5P_VPLL_CON1), pll_4650);
 
-	clk_fout_apll.rate = apll;
+	clk_fout_apll.ops = &s5pv310_fout_apll_ops;
 	clk_fout_mpll.rate = mpll;
 	clk_fout_epll.rate = epll;
 	clk_fout_vpll.rate = vpll;
-- 
1.6.2.5

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

* [PATCH 7/7] ARM: S5PV310: Update Kconfig and Makefile for supporting CPUFREQ
  2010-12-23  5:49 [PATCH 0/7] ARM: S5PV310: Add support CPUFREQ driver Kukjin Kim
                   ` (5 preceding siblings ...)
  2010-12-23  5:49 ` [PATCH V3 6/7] ARM: S5PV310: Add FOUT APLL get rate function Kukjin Kim
@ 2010-12-23  5:49 ` Kukjin Kim
  6 siblings, 0 replies; 8+ messages in thread
From: Kukjin Kim @ 2010-12-23  5:49 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: ben-linux, Sunyoung Kang, Kukjin Kim

From: Sunyoung Kang <sy0816.kang@samsung.com>

This patch adds ARCH_HAS_CPUFREQ in Kconfig of ARCH_S5PV310 and updates
Makefile for supporting build S5PV310 CPUFREQ driver.

Signed-off-by: Sunyoung Kang <sy0816.kang@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
 arch/arm/Kconfig               |    1 +
 arch/arm/mach-s5pv310/Makefile |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d56d21c..5ecaec6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -738,6 +738,7 @@ config ARCH_S5PV310
 	select ARCH_SPARSEMEM_ENABLE
 	select GENERIC_GPIO
 	select HAVE_CLK
+	select ARCH_HAS_CPUFREQ
 	select GENERIC_CLOCKEVENTS
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_I2C if I2C
diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
index 84afc64..6a8a1ef 100644
--- a/arch/arm/mach-s5pv310/Makefile
+++ b/arch/arm/mach-s5pv310/Makefile
@@ -14,6 +14,7 @@ obj-				:=
 
 obj-$(CONFIG_CPU_S5PV310)	+= cpu.o init.o clock.o irq-combiner.o
 obj-$(CONFIG_CPU_S5PV310)	+= setup-i2c0.o time.o gpiolib.o irq-eint.o
+obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
 
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
-- 
1.6.2.5

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

end of thread, other threads:[~2010-12-23  6:07 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-23  5:49 [PATCH 0/7] ARM: S5PV310: Add support CPUFREQ driver Kukjin Kim
2010-12-23  5:49 ` [PATCH 1/7] ARM: S5PV310: Update CMU registers for CPUFREQ Kukjin Kim
2010-12-23  5:49 ` [PATCH V3 2/7] ARM: S5PV310: Define missing CMU register " Kukjin Kim
2010-12-23  5:49 ` [PATCH 3/7] ARM: S5PV310: Add DMC registers and map_desc Kukjin Kim
2010-12-23  5:49 ` [PATCH 4/7] ARM: S5PV310: Add support CPUFREQ Kukjin Kim
2010-12-23  5:49 ` [PATCH V3 5/7] ARM: S5PV310: Update CPUFREQ Kukjin Kim
2010-12-23  5:49 ` [PATCH V3 6/7] ARM: S5PV310: Add FOUT APLL get rate function Kukjin Kim
2010-12-23  5:49 ` [PATCH 7/7] ARM: S5PV310: Update Kconfig and Makefile for supporting CPUFREQ Kukjin Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox