linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420
@ 2014-05-22 17:21 Abhilash Kesavan
  2014-05-22 17:21 ` [PATCH RFC v2 1/7] clk: exynos5250: add aliases for clocks used by devfreq Abhilash Kesavan
                   ` (7 more replies)
  0 siblings, 8 replies; 12+ messages in thread
From: Abhilash Kesavan @ 2014-05-22 17:21 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset adds devfreq support on Exynos5250 and Exynos5420.
The patches add the missing INT clock support for exynos5250 and
also add a new 5420 driver. We also have patches which add the
PPMU node and fix a typo in the exynos5250 driver.

Changes since RFC v1:
	- Exynos5420 support has been added to the existent Exynos5250
	  driver itself.
	- Rebased on Chanwoo Choi's devfreq consolidation patchset.
	- Removed unused clocks from the clock list
	- Used the PPMU nodes with different compatible strings to
	  differentiate between exynos5250 and exynos5420.

The patches have been tested on Exynos5250 based Snow board and Exynos5420
based Peach-Pit boards. They have been prepared on linux-next(20140521) with
the devfreq for-next branch merged. Also applied is the "devfreq resource
management" series from Chanwoo Choi[1].
[1] https://lkml.org/lkml/2014/4/25/826

Abhilash Kesavan (3):
  ARM: dts: Add PPMU device tree support for Exynos5250
  ARM: dts: Add PPMU device tree support for Exynos5420
  PM / devfreq: exynos: Fix typo in macro

Andrew Bresticker (2):
  clk: exynos5250: add aliases for clocks used by devfreq
  PM / devfreq: exynos5250: migrate to common-clock

Arjun.K.V (2):
  clk: exynos5420: Add aliases for clocks used by devfreq
  PM / devfreq: Add devfreq driver for Exynos5420

 .../bindings/arm/exynos/ppmu-exynos5.txt           |   27 +
 arch/arm/boot/dts/exynos5250.dtsi                  |    8 +
 arch/arm/boot/dts/exynos5420.dtsi                  |    7 +
 drivers/clk/samsung/clk-exynos5250.c               |   25 +-
 drivers/clk/samsung/clk-exynos5420.c               |   73 ++-
 drivers/devfreq/Kconfig                            |   10 +-
 drivers/devfreq/exynos/exynos5_bus.c               |  665 +++++++++++++++++---
 drivers/devfreq/exynos/exynos_ppmu.h               |    2 +-
 8 files changed, 703 insertions(+), 114 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/exynos/ppmu-exynos5.txt

-- 
1.7.9.5

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

* [PATCH RFC v2 1/7] clk: exynos5250: add aliases for clocks used by devfreq
  2014-05-22 17:21 [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Abhilash Kesavan
@ 2014-05-22 17:21 ` Abhilash Kesavan
  2014-05-22 17:21 ` [PATCH RFC v2 2/7] clk: exynos5420: Add " Abhilash Kesavan
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Abhilash Kesavan @ 2014-05-22 17:21 UTC (permalink / raw)
  To: linux-arm-kernel

From: Andrew Bresticker <abrestic@chromium.org>

Devfreq does not support DT-based lookup of these peripheral clocks,
so add aliases for them.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/clk/samsung/clk-exynos5250.c |   25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 8848859..be2d7d8 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -202,6 +202,11 @@ PNAME(mout_aclk400_p)	= { "mout_aclk400_g3d_mid", "mout_gpll" };
 PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" };
 PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" };
 PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" };
+PNAME(mout_aclk300_disp1_p) = { "mout_aclk300_disp1_mid",
+				"mout_aclk300_disp1_mid1" };
+PNAME(mout_aclk300_gscl_p) = { "mout_aclk300_gscl_mid",
+				"mout_aclk300_gscl_mid1" };
+PNAME(mout_aclk300_gscl_mid1_p) = { "mout_vpll", "mout_cpll" };
 PNAME(mout_hdmi_p)	= { "div_hdmi_pixel", "sclk_hdmiphy" };
 PNAME(mout_usb3_p)	= { "mout_mpll_user", "mout_cpll" };
 PNAME(mout_group1_p)	= { "fin_pll", "fin_pll", "sclk_hdmi27m",
@@ -278,9 +283,17 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
 	 */
 	MUX(0, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1),
 	MUX(0, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1),
+	MUX(0, "mout_aclk300_disp1_mid", mout_aclk200_p, SRC_TOP0, 14, 1),
+	MUX(0, "mout_aclk300_disp1", mout_aclk300_disp1_p, SRC_TOP0, 15, 1),
 	MUX(0, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1),
 	MUX(0, "mout_aclk400_g3d_mid", mout_aclk200_p, SRC_TOP0, 20, 1),
+	MUX(0, "mout_aclk300_gscl_mid", mout_aclk200_p, SRC_TOP0, 24, 1),
+	MUX(0, "mout_aclk300_gscl", mout_aclk300_gscl_p, SRC_TOP0, 25, 2),
 
+	MUX(0, "mout_aclk300_disp1_mid1", mout_aclk300_gscl_mid1_p,
+					SRC_TOP1, 8, 1),
+	MUX(0, "mout_aclk300_gscl_mid1", mout_aclk300_gscl_mid1_p,
+					SRC_TOP1, 12, 1),
 	MUX(0, "mout_aclk400_g3d", mout_aclk400_p, SRC_TOP1, 28, 1),
 
 	MUX(0, "mout_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
@@ -357,13 +370,17 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
 	 * CMU_TOP
 	 */
 	DIV(0, "div_aclk66", "div_aclk66_pre", DIV_TOP0, 0, 3),
-	DIV(0, "div_aclk166", "mout_aclk166", DIV_TOP0, 8, 3),
-	DIV(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
-	DIV(0, "div_aclk266", "mout_mpll_user", DIV_TOP0, 16, 3),
-	DIV(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3),
+	DIV_A(0, "div_aclk166", "mout_aclk166", DIV_TOP0, 8, 3, "aclk166_d"),
+	DIV_A(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3, "aclk200_d"),
+	DIV_A(0, "div_aclk266", "mout_mpll_user", DIV_TOP0, 16, 3, "aclk266_d"),
+	DIV_A(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3, "aclk333_d"),
 	DIV(0, "div_aclk400_g3d", "mout_aclk400_g3d", DIV_TOP0,
 							24, 3),
+	DIV_A(0, "div_aclk300_disp1", "mout_aclk300_disp1",
+					DIV_TOP0, 28, 3, "aclk300_disp1_d"),
 
+	DIV_A(0, "div_aclk300_gscl", "mout_aclk300_gscl",
+					DIV_TOP1, 12, 3, "aclk300_gscl_d"),
 	DIV(0, "div_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3),
 
 	DIV(0, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4),
-- 
1.7.9.5

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

* [PATCH RFC v2 2/7] clk: exynos5420: Add aliases for clocks used by devfreq
  2014-05-22 17:21 [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Abhilash Kesavan
  2014-05-22 17:21 ` [PATCH RFC v2 1/7] clk: exynos5250: add aliases for clocks used by devfreq Abhilash Kesavan
@ 2014-05-22 17:21 ` Abhilash Kesavan
  2014-05-22 17:21 ` [PATCH RFC v2 3/7] ARM: dts: Add PPMU device tree support for Exynos5250 Abhilash Kesavan
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Abhilash Kesavan @ 2014-05-22 17:21 UTC (permalink / raw)
  To: linux-arm-kernel

From: "Arjun.K.V" <arjun.kv@samsung.com>

Devfreq does not support DT-based lookup of these peripheral clocks,
so add aliases for them.

Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Arjun.K.V <arjun.kv@samsung.com>
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/clk/samsung/clk-exynos5420.c |   73 ++++++++++++++++++++--------------
 1 file changed, 44 insertions(+), 29 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 9d7d7ee..93b9422 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -554,21 +554,25 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
 	MUX(0, "mout_aclk400_isp", mout_group1_p, SRC_TOP0, 0, 2),
 	MUX_A(0, "mout_aclk400_mscl", mout_group1_p,
 				SRC_TOP0, 4, 2, "aclk400_mscl"),
-	MUX(0, "mout_aclk400_wcore", mout_group1_p, SRC_TOP0, 16, 2),
-	MUX(0, "mout_aclk100_noc", mout_group1_p, SRC_TOP0, 20, 2),
-
+	MUX_A(0, "mout_aclk400_wcore", mout_group1_p,
+				SRC_TOP0, 16, 2, "aclk400_wcore"),
+	MUX_A(0, "mout_aclk100_noc", mout_group1_p,
+				SRC_TOP0, 20, 2, "aclk100_noc"),
 	MUX(0, "mout_aclk333_432_gscl", mout_group4_p, SRC_TOP1, 0, 2),
 	MUX(0, "mout_aclk333_432_isp", mout_group4_p,
 				SRC_TOP1, 4, 2),
 	MUX(0, "mout_aclk333_432_isp0", mout_group4_p, SRC_TOP1, 12, 2),
-	MUX(0, "mout_aclk266", mout_group1_p, SRC_TOP1, 20, 2),
+	MUX_A(0, "mout_aclk266", mout_group1_p, SRC_TOP1, 20, 2, "aclk266"),
 	MUX(0, "mout_aclk333", mout_group1_p, SRC_TOP1, 28, 2),
 
-	MUX(0, "mout_aclk400_disp1", mout_group1_p, SRC_TOP2, 4, 2),
+	MUX_A(0, "mout_aclk400_disp1", mout_group1_p,
+				SRC_TOP2, 4, 2, "aclk400_disp1"),
 	MUX(0, "mout_aclk333_g2d", mout_group1_p, SRC_TOP2, 8, 2),
 	MUX(0, "mout_aclk266_g2d", mout_group1_p, SRC_TOP2, 12, 2),
-	MUX(0, "mout_aclk300_jpeg", mout_group1_p, SRC_TOP2, 20, 2),
-	MUX(0, "mout_aclk300_disp1", mout_group1_p, SRC_TOP2, 24, 2),
+	MUX_A(0, "mout_aclk300_jpeg", mout_group1_p,
+				SRC_TOP2, 20, 2, "aclk300_jpeg"),
+	MUX_A(0, "mout_aclk300_disp1", mout_group1_p,
+				SRC_TOP2, 24, 2, "aclk300_disp1"),
 	MUX(0, "mout_aclk300_gscl", mout_group1_p, SRC_TOP2, 28, 2),
 
 	MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2),
@@ -577,8 +581,8 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
 };
 
 struct samsung_div_clock exynos5420_div_clks[] __initdata = {
-	DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll",
-			DIV_TOP0, 16, 3),
+	DIV_A(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll",
+			DIV_TOP0, 16, 3, "aclk400_wcore_d"),
 };
 
 static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
@@ -593,12 +597,15 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
 	MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
 
 	MUX(0, "mout_aclk200", mout_group1_p, SRC_TOP0, 8, 2),
-	MUX(0, "mout_aclk200_fsys2", mout_group1_p, SRC_TOP0, 12, 2),
-	MUX(0, "mout_pclk200_fsys", mout_group1_p, SRC_TOP0, 24, 2),
-	MUX(0, "mout_aclk200_fsys", mout_group1_p, SRC_TOP0, 28, 2),
+	MUX_A(0, "mout_aclk200_fsys2", mout_group1_p,
+		SRC_TOP0, 12, 2, "aclk200_fsys2"),
+	MUX_A(0, "mout_pclk200_fsys", mout_group1_p,
+		SRC_TOP0, 24, 2, "pclk200_fsys"),
+	MUX_A(0, "mout_aclk200_fsys", mout_group1_p,
+		SRC_TOP0, 28, 2, "aclk200_fsys"),
 
-	MUX(0, "mout_aclk66", mout_group1_p, SRC_TOP1, 8, 2),
-	MUX(0, "mout_aclk166", mout_group1_p, SRC_TOP1, 24, 2),
+	MUX_A(0, "mout_aclk66", mout_group1_p, SRC_TOP1, 8, 2, "aclk66"),
+	MUX_A(0, "mout_aclk166", mout_group1_p, SRC_TOP1, 24, 2, "aclk166"),
 
 	MUX(0, "mout_aclk_g3d", mout_group5_p, SRC_TOP2, 16, 1),
 
@@ -650,14 +657,14 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
 	MUX(0, "mout_user_aclk300_gscl", mout_user_aclk300_gscl_p,
 			SRC_TOP5, 28, 1),
 
-	MUX(0, "mout_sclk_mpll", mout_mpll_p, SRC_TOP6, 0, 1),
+	MUX_A(0, "mout_sclk_mpll", mout_mpll_p, SRC_TOP6, 0, 1, "mout_mpll"),
 	MUX(CLK_MOUT_VPLL, "mout_sclk_vpll", mout_vpll_p, SRC_TOP6, 4, 1),
 	MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1),
-	MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1),
+	MUX_A(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1, "mout_ipll"),
 	MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1),
 	MUX(0, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1),
-	MUX(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1),
-	MUX(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1),
+	MUX_A(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1, "mout_dpll"),
+	MUX_A(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1, "mout_cpll"),
 
 	MUX(0, "mout_sw_aclk400_isp", mout_sw_aclk400_isp_p,
 			SRC_TOP10, 0, 1),
@@ -751,29 +758,36 @@ static struct samsung_div_clock exynos5x_div_clks[] __initdata = {
 	DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3),
 
 	DIV(0, "dout_aclk400_isp", "mout_aclk400_isp", DIV_TOP0, 0, 3),
-	DIV(0, "dout_aclk400_mscl", "mout_aclk400_mscl", DIV_TOP0, 4, 3),
+	DIV_A(0, "dout_aclk400_mscl", "mout_aclk400_mscl",
+			DIV_TOP0, 4, 3, "aclk400_mscl_d"),
 	DIV(0, "dout_aclk200", "mout_aclk200", DIV_TOP0, 8, 3),
-	DIV(0, "dout_aclk200_fsys2", "mout_aclk200_fsys2", DIV_TOP0, 12, 3),
-	DIV(0, "dout_aclk100_noc", "mout_aclk100_noc", DIV_TOP0, 20, 3),
-	DIV(0, "dout_pclk200_fsys", "mout_pclk200_fsys", DIV_TOP0, 24, 3),
-	DIV(0, "dout_aclk200_fsys", "mout_aclk200_fsys", DIV_TOP0, 28, 3),
+	DIV_A(0, "dout_aclk200_fsys2", "mout_aclk200_fsys2",
+			DIV_TOP0, 12, 3, "aclk200_fsys2_d"),
+	DIV_A(0, "dout_aclk100_noc", "mout_aclk100_noc",
+			DIV_TOP0, 20, 3, "aclk100_noc_d"),
+	DIV_A(0, "dout_pclk200_fsys", "mout_pclk200_fsys",
+			DIV_TOP0, 24, 3, "pclk200_fsys_d"),
+	DIV_A(0, "dout_aclk200_fsys", "mout_aclk200_fsys",
+			DIV_TOP0, 28, 3, "aclk200_fsys_d"),
 
 	DIV(0, "dout_aclk333_432_gscl", "mout_aclk333_432_gscl",
 			DIV_TOP1, 0, 3),
 	DIV(0, "dout_aclk333_432_isp", "mout_aclk333_432_isp",
 			DIV_TOP1, 4, 3),
-	DIV(0, "dout_aclk66", "mout_aclk66", DIV_TOP1, 8, 6),
+	DIV_A(0, "dout_aclk66", "mout_aclk66", DIV_TOP1, 8, 6, "aclk66_d"),
 	DIV(0, "dout_aclk333_432_isp0", "mout_aclk333_432_isp0",
 			DIV_TOP1, 16, 3),
-	DIV(0, "dout_aclk266", "mout_aclk266", DIV_TOP1, 20, 3),
-	DIV(0, "dout_aclk166", "mout_aclk166", DIV_TOP1, 24, 3),
+	DIV_A(0, "dout_aclk266", "mout_aclk266", DIV_TOP1, 20, 3, "aclk266_d"),
+	DIV_A(0, "dout_aclk166", "mout_aclk166", DIV_TOP1, 24, 3, "aclk166_d"),
 	DIV(0, "dout_aclk333", "mout_aclk333", DIV_TOP1, 28, 3),
 
 	DIV(0, "dout_aclk333_g2d", "mout_aclk333_g2d", DIV_TOP2, 8, 3),
 	DIV(0, "dout_aclk266_g2d", "mout_aclk266_g2d", DIV_TOP2, 12, 3),
 	DIV(0, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, 16, 3),
-	DIV(0, "dout_aclk300_jpeg", "mout_aclk300_jpeg", DIV_TOP2, 20, 3),
-	DIV(0, "dout_aclk300_disp1", "mout_aclk300_disp1", DIV_TOP2, 24, 3),
+	DIV_A(0, "dout_aclk300_jpeg", "mout_aclk300_jpeg",
+			DIV_TOP2, 20, 3, "aclk300_jpeg_d"),
+	DIV_A(0, "dout_aclk300_disp1", "mout_aclk300_disp1",
+			DIV_TOP2, 24, 3, "aclk300_disp1_d"),
 	DIV(0, "dout_aclk300_gscl", "mout_aclk300_gscl", DIV_TOP2, 28, 3),
 
 	/* DISP1 Block */
@@ -782,7 +796,8 @@ static struct samsung_div_clock exynos5x_div_clks[] __initdata = {
 	DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4),
 	DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4),
 	DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2),
-	DIV(0, "dout_aclk400_disp1", "mout_aclk400_disp1", DIV_TOP2, 4, 3),
+	DIV_A(0, "dout_aclk400_disp1", "mout_aclk400_disp1",
+			DIV_TOP2, 4, 3, "aclk400_disp1_d"),
 
 	/* Audio Block */
 	DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4),
-- 
1.7.9.5

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

* [PATCH RFC v2 3/7] ARM: dts: Add PPMU device tree support for Exynos5250
  2014-05-22 17:21 [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Abhilash Kesavan
  2014-05-22 17:21 ` [PATCH RFC v2 1/7] clk: exynos5250: add aliases for clocks used by devfreq Abhilash Kesavan
  2014-05-22 17:21 ` [PATCH RFC v2 2/7] clk: exynos5420: Add " Abhilash Kesavan
@ 2014-05-22 17:21 ` Abhilash Kesavan
  2014-05-22 17:21 ` [PATCH RFC v2 4/7] ARM: dts: Add PPMU device tree support for Exynos5420 Abhilash Kesavan
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Abhilash Kesavan @ 2014-05-22 17:21 UTC (permalink / raw)
  To: linux-arm-kernel

PPMU is required by the exynos5250 devfreq driver. Add a device
tree node for it.

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 .../bindings/arm/exynos/ppmu-exynos5.txt           |   27 ++++++++++++++++++++
 arch/arm/boot/dts/exynos5250.dtsi                  |    8 ++++++
 2 files changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/exynos/ppmu-exynos5.txt

diff --git a/Documentation/devicetree/bindings/arm/exynos/ppmu-exynos5.txt b/Documentation/devicetree/bindings/arm/exynos/ppmu-exynos5.txt
new file mode 100644
index 0000000..08a4aaf
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/exynos/ppmu-exynos5.txt
@@ -0,0 +1,27 @@
+Exynos PPMU driver
+-------------------
+
+Performance events are primitive values used to get performance data. These
+events provide information about the behavior of the SoC that can be used
+when analyzing system performance. These events are made visible using the
+PPMU logic.
+Exynos PPMU driver is used by the exynos5 devfreq drivers to control the
+bus frequency/voltage.
+
+Required properties:
+- compatible: "samsung,exynos5250-int-busfreq", "samsung,exynos5420-int-busfreq"
+- reg:
+	* physical base address of the PPMUs (e.g DDR, Right Bus, Left bus etc)
+	and length of memory mapped region.
+
+Example:
+--------
+
+	ppmu {
+		compatible = "samsung,exynos5250-int-busfreq";
+		reg = <0x10C40000 0x2000
+		       0x10C50000 0x2000
+		       0x10C60000 0x2000
+		       0x10CB0000 0x2000
+		       0x13660000 0x2000>;
+	};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 68a3e6f..f20355a 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -750,4 +750,12 @@
 		clocks = <&clock 348>;
 		clock-names = "secss";
 	};
+
+	ppmu {
+		compatible = "samsung,exynos5250-int-busfreq";
+	            reg = <0x10C40000 0x2000	/* PPMU_DDR_C */
+			   0x10C50000 0x2000	/* PPMU_DDR_L */
+			   0x10CB0000 0x2000	/* PPMU_DDR_R */
+			   0x13660000 0x2000>;	/* PPMU_RIGHT */
+	};
 };
-- 
1.7.9.5

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

* [PATCH RFC v2 4/7] ARM: dts: Add PPMU device tree support for Exynos5420
  2014-05-22 17:21 [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Abhilash Kesavan
                   ` (2 preceding siblings ...)
  2014-05-22 17:21 ` [PATCH RFC v2 3/7] ARM: dts: Add PPMU device tree support for Exynos5250 Abhilash Kesavan
@ 2014-05-22 17:21 ` Abhilash Kesavan
  2014-05-22 17:50   ` Sergei Shtylyov
  2014-05-22 17:22 ` [PATCH RFC v2 5/7] PM / devfreq: exynos5250: migrate to common-clock Abhilash Kesavan
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 12+ messages in thread
From: Abhilash Kesavan @ 2014-05-22 17:21 UTC (permalink / raw)
  To: linux-arm-kernel

PPMU is required by the exynos5420 devfreq driver. Add a device
tree node for it.

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 arch/arm/boot/dts/exynos5420.dtsi |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 8e7e35c..6ab7b03 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -833,4 +833,11 @@
 		samsung,pmu-syscon = <&pmu_system_controller>;
 		#phy-cells = <1>;
 	};
+
+	ppmu {
+		compatible = "samsung,exynos5420-int-busfreq";
+		reg = <0x10D00000 0x2000	/* PPMU_DMC_0_0 */
+		       0x10D10000 0x2000	/* PPMU_DMC_0_1 */
+		       0x10D60000 0x2000>;	/* PPMU_DMC_1_0 */
+	};
 };
-- 
1.7.9.5

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

* [PATCH RFC v2 5/7] PM / devfreq: exynos5250: migrate to common-clock
  2014-05-22 17:21 [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Abhilash Kesavan
                   ` (3 preceding siblings ...)
  2014-05-22 17:21 ` [PATCH RFC v2 4/7] ARM: dts: Add PPMU device tree support for Exynos5420 Abhilash Kesavan
@ 2014-05-22 17:22 ` Abhilash Kesavan
  2014-05-22 17:22 ` [PATCH RFC v2 6/7] PM / devfreq: exynos: Fix typo in macro Abhilash Kesavan
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 12+ messages in thread
From: Abhilash Kesavan @ 2014-05-22 17:22 UTC (permalink / raw)
  To: linux-arm-kernel

From: Andrew Bresticker <abrestic@chromium.org>

Use the common-clock framework to scale frequencies for the various
peripheral clocks on the Exynos5250.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/devfreq/exynos/exynos5_bus.c |  131 ++++++++++++++++++++++++++++++----
 1 file changed, 119 insertions(+), 12 deletions(-)

diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c
index 6cd0392..1196653 100644
--- a/drivers/devfreq/exynos/exynos5_bus.c
+++ b/drivers/devfreq/exynos/exynos5_bus.c
@@ -57,7 +57,6 @@ struct busfreq_data_int {
 	struct notifier_block pm_notifier;
 	struct mutex lock;
 	struct pm_qos_request int_req;
-	struct clk *int_clk;
 };
 
 struct int_bus_opp_table {
@@ -66,6 +65,17 @@ struct int_bus_opp_table {
 	unsigned long volt;
 };
 
+struct int_clk_table {
+	unsigned int idx;
+	unsigned long freq;
+};
+
+struct int_clk {
+	const char *clk_name;
+	struct clk *clk;
+	struct int_clk_table *freq_table;
+};
+
 static struct int_bus_opp_table exynos5_int_opp_table[] = {
 	{LV_0, 266000, 1025000},
 	{LV_1, 200000, 1025000},
@@ -75,6 +85,98 @@ static struct int_bus_opp_table exynos5_int_opp_table[] = {
 	{0, 0, 0},
 };
 
+static struct int_clk_table aclk_166[] = {
+	{LV_0, 167000},
+	{LV_1, 111000},
+	{LV_2,  84000},
+	{LV_3,  84000},
+	{LV_4,  42000},
+};
+
+static struct int_clk_table aclk_200[] = {
+	{LV_0, 200000},
+	{LV_1, 160000},
+	{LV_2, 160000},
+	{LV_3, 134000},
+	{LV_4, 100000},
+};
+
+static struct int_clk_table aclk_266[] = {
+	{LV_0, 267000},
+	{LV_1, 200000},
+	{LV_2, 160000},
+	{LV_3, 134000},
+	{LV_4, 100000},
+};
+
+static struct int_clk_table aclk_333[] = {
+	{LV_0, 333000},
+	{LV_1, 167000},
+	{LV_2, 111000},
+	{LV_3, 111000},
+	{LV_4,  42000},
+};
+
+static struct int_clk_table aclk_300_disp1[] = {
+	{LV_0, 267000},
+	{LV_1, 267000},
+	{LV_2, 267000},
+	{LV_3, 267000},
+	{LV_4, 200000},
+};
+
+static struct int_clk_table aclk_300_gscl[] = {
+	{LV_0, 267000},
+	{LV_1, 267000},
+	{LV_2, 267000},
+	{LV_3, 200000},
+	{LV_4, 100000},
+};
+
+#define EXYNOS5_INT_CLK(name, tbl) {		\
+	.clk_name = name,			\
+	.freq_table = tbl,			\
+}
+
+static struct int_clk exynos5_int_clks[] = {
+	EXYNOS5_INT_CLK("aclk166_d", aclk_166),
+	EXYNOS5_INT_CLK("aclk200_d", aclk_200),
+	EXYNOS5_INT_CLK("aclk266_d", aclk_266),
+	EXYNOS5_INT_CLK("aclk333_d", aclk_333),
+	EXYNOS5_INT_CLK("aclk300_disp1_d", aclk_300_disp1),
+	EXYNOS5_INT_CLK("aclk300_gscl_d", aclk_300_gscl),
+};
+
+static int exynos5_int_set_rate(struct busfreq_data_int *data,
+				unsigned long rate)
+{
+	int index, i;
+
+	for (index = 0; index < ARRAY_SIZE(exynos5_int_opp_table); index++) {
+		if (exynos5_int_opp_table[index].clk == rate)
+			break;
+	}
+
+	if (index >= _LV_END)
+		return -EINVAL;
+
+	/* Change the system clock divider values */
+	for (i = 0; i < ARRAY_SIZE(exynos5_int_clks); i++) {
+		struct int_clk *clk_info = &exynos5_int_clks[i];
+		int ret;
+
+		ret = clk_set_rate(clk_info->clk,
+				clk_info->freq_table[index].freq * 1000);
+		if (ret) {
+			dev_err(data->dev, "Failed to set %s rate: %d\n",
+				clk_info->clk_name, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int exynos5_int_setvolt(struct busfreq_data_int *data,
 				unsigned long volt)
 {
@@ -126,7 +228,7 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
 	if (err)
 		goto out;
 
-	err = clk_set_rate(data->int_clk, freq * 1000);
+	err = exynos5_int_set_rate(data, freq);
 
 	if (err)
 		goto out;
@@ -220,7 +322,7 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
 		if (err)
 			goto unlock;
 
-		err = clk_set_rate(data->int_clk, freq * 1000);
+		err = exynos5_int_set_rate(data, freq);
 
 		if (err)
 			goto unlock;
@@ -300,10 +402,15 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 		return PTR_ERR(data->vdd_int);
 	}
 
-	data->int_clk = devm_clk_get(dev, "int_clk");
-	if (IS_ERR(data->int_clk)) {
-		dev_err(dev, "Cannot get clock \"int_clk\"\n");
-		return PTR_ERR(data->int_clk);
+	for (i = 0; i < ARRAY_SIZE(exynos5_int_clks); i++) {
+		struct int_clk *clk_info = &exynos5_int_clks[i];
+
+		clk_info->clk = devm_clk_get(dev, clk_info->clk_name);
+		if (IS_ERR(clk_info->clk)) {
+			dev_err(dev, "Failed to get clock %s\n",
+				clk_info->clk_name);
+			return PTR_ERR(clk_info->clk);
+		}
 	}
 
 	rcu_read_lock();
@@ -320,16 +427,16 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 	rcu_read_unlock();
 	data->curr_freq = initial_freq;
 
-	err = clk_set_rate(data->int_clk, initial_freq * 1000);
+	err = exynos5_int_setvolt(data, initial_volt);
+	if (err)
+		return err;
+
+	err = exynos5_int_set_rate(data, initial_freq);
 	if (err) {
 		dev_err(dev, "Failed to set initial frequency\n");
 		return err;
 	}
 
-	err = exynos5_int_setvolt(data, initial_volt);
-	if (err)
-		return err;
-
 	platform_set_drvdata(pdev, data);
 
 	busfreq_mon_reset(ppmu_data);
-- 
1.7.9.5

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

* [PATCH RFC v2 6/7] PM / devfreq: exynos: Fix typo in macro
  2014-05-22 17:21 [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Abhilash Kesavan
                   ` (4 preceding siblings ...)
  2014-05-22 17:22 ` [PATCH RFC v2 5/7] PM / devfreq: exynos5250: migrate to common-clock Abhilash Kesavan
@ 2014-05-22 17:22 ` Abhilash Kesavan
  2014-05-22 17:22 ` [PATCH RFC v2 7/7] PM / devfreq: Add devfreq driver for Exynos5420 Abhilash Kesavan
  2014-05-23  5:08 ` [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Chanwoo Choi
  7 siblings, 0 replies; 12+ messages in thread
From: Abhilash Kesavan @ 2014-05-22 17:22 UTC (permalink / raw)
  To: linux-arm-kernel

Fix PPMU_BEVTSEL macro being used in the PPMU driver.

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/devfreq/exynos/exynos_ppmu.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/devfreq/exynos/exynos_ppmu.h b/drivers/devfreq/exynos/exynos_ppmu.h
index 71f17ba..d5c14eb 100644
--- a/drivers/devfreq/exynos/exynos_ppmu.h
+++ b/drivers/devfreq/exynos/exynos_ppmu.h
@@ -37,7 +37,7 @@
 
 #define PPMU_BEVT0SEL		0x1000
 #define PPMU_BEVTSEL_OFFSET	0x100
-#define PPMU_BEVTSEL(x)		(PPMU_BEVT0SEL + (ch * PPMU_BEVTSEL_OFFSET))
+#define PPMU_BEVTSEL(ch)	(PPMU_BEVT0SEL + (ch * PPMU_BEVTSEL_OFFSET))
 
 /* For Event Selection */
 #define RD_DATA_COUNT		0x5
-- 
1.7.9.5

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

* [PATCH RFC v2 7/7] PM / devfreq: Add devfreq driver for Exynos5420
  2014-05-22 17:21 [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Abhilash Kesavan
                   ` (5 preceding siblings ...)
  2014-05-22 17:22 ` [PATCH RFC v2 6/7] PM / devfreq: exynos: Fix typo in macro Abhilash Kesavan
@ 2014-05-22 17:22 ` Abhilash Kesavan
  2014-05-23  5:08 ` [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Chanwoo Choi
  7 siblings, 0 replies; 12+ messages in thread
From: Abhilash Kesavan @ 2014-05-22 17:22 UTC (permalink / raw)
  To: linux-arm-kernel

From: "Arjun.K.V" <arjun.kv@samsung.com>

Exynos5420 bus device devfreq driver monitors PPMU counters and
adjusts INT domain operating frequencies and voltages. Support
for 5420 has been added to the extant 5250 support.

Signed-off-by: Arjun.K.V <arjun.kv@samsung.com>
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/devfreq/Kconfig              |   10 +-
 drivers/devfreq/exynos/exynos5_bus.c |  598 ++++++++++++++++++++++++++++------
 2 files changed, 508 insertions(+), 100 deletions(-)

diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index c023c57..4e84615 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -80,14 +80,14 @@ config ARM_EXYNOS4_BUS_DEVFREQ
 	  (CONFIG_EXYNOS_ASV).
 
 config ARM_EXYNOS5_BUS_DEVFREQ
-	bool "ARM Exynos5250 Bus DEVFREQ Driver"
-	depends on SOC_EXYNOS5250
+	bool "ARM Exynos5 Bus DEVFREQ Driver"
+	depends on (SOC_EXYNOS5250 || SOC_EXYNOS5420)
 	select ARCH_HAS_OPP
 	select DEVFREQ_GOV_SIMPLE_ONDEMAND
 	select PM_OPP
 	help
-	  This adds the DEVFREQ driver for Exynos5250 bus interface (vdd_int).
-	  It reads PPMU counters of memory controllers and adjusts the
-	  operating frequencies and voltages with OPP support.
+	  This adds the DEVFREQ driver for Exynos5250/5420 bus interface
+	  (vdd_int). It reads PPMU counters of memory controllers and adjusts
+	  the operating frequencies and voltages with OPP support.
 
 endif # PM_DEVFREQ
diff --git a/drivers/devfreq/exynos/exynos5_bus.c b/drivers/devfreq/exynos/exynos5_bus.c
index 1196653..7ce5b76 100644
--- a/drivers/devfreq/exynos/exynos5_bus.c
+++ b/drivers/devfreq/exynos/exynos5_bus.c
@@ -1,10 +1,10 @@
 /*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012-14 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com/
  *
  * EXYNOS5 INT clock frequency scaling support using DEVFREQ framework
  * Based on work done by Jonghwan Choi <jhbird.choi@samsung.com>
- * Support for only EXYNOS5250 is present.
+ * Support for EXYNOS5250 and Exynos5420 is present.
  *
  * 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
@@ -14,23 +14,28 @@
 
 #include <linux/module.h>
 #include <linux/devfreq.h>
-#include <linux/io.h>
 #include <linux/pm_opp.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
 #include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/platform_device.h>
-#include <linux/pm_qos.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of_address.h>
-#include <linux/of_platform.h>
 
 #include "exynos_ppmu.h"
 
-#define MAX_SAFEVOLT			1100000 /* 1.10V */
-/* Assume that the bus is saturated if the utilization is 25% */
-#define INT_BUS_SATURATION_RATIO	25
+/* Assume that we need to bump up the level if the utilization is 10% */
+#define INT_BUS_SATURATION_RATIO	10
+#define INT_VOLT_STEP_UV		12500
+
+struct exynos5_busfreq_drv_data {
+	int busf_type;
+};
+
+enum exynos5_busf_type {
+	TYPE_BUSF_EXYNOS5250,
+	TYPE_BUSF_EXYNOS5420,
+};
 
 enum int_level_idx {
 	LV_0,
@@ -41,12 +46,31 @@ enum int_level_idx {
 	_LV_END
 };
 
-enum exynos_ppmu_list {
+enum exynos5250_ppmu_list {
+	PPMU_DDR_C,
+	PPMU_DDR_L,
+	PPMU_DDR_R,
 	PPMU_RIGHT,
-	PPMU_END,
+	PPMU_END_5250,
+};
+
+enum exynos5420_ppmu_list {
+	PPMU_DMC_0_1,
+	PPMU_DMC_1_0,
+	PPMU_DMC_1_1,
+	PPMU_END_5420,
+};
+
+enum int_bus_pll {
+	C_PLL = 0,
+	D_PLL,
+	M_PLL,
+	I_PLL,
 };
 
 struct busfreq_data_int {
+	enum exynos5_busf_type type;
+	struct list_head list;
 	struct device *dev;
 	struct devfreq *devfreq;
 	struct regulator *vdd_int;
@@ -56,7 +80,11 @@ struct busfreq_data_int {
 
 	struct notifier_block pm_notifier;
 	struct mutex lock;
-	struct pm_qos_request int_req;
+
+	struct clk *mout_mpll;
+	struct clk *mout_dpll;
+	struct clk *mout_cpll;
+	struct clk *mout_ipll;
 };
 
 struct int_bus_opp_table {
@@ -70,13 +98,29 @@ struct int_clk_table {
 	unsigned long freq;
 };
 
-struct int_clk {
+struct int_simple_clk {
 	const char *clk_name;
 	struct clk *clk;
 	struct int_clk_table *freq_table;
 };
 
-static struct int_bus_opp_table exynos5_int_opp_table[] = {
+struct int_clk_info {
+	unsigned int idx;
+	unsigned long target_freq;
+	enum int_bus_pll src_pll;
+};
+
+struct int_comp_clks {
+	struct list_head node;
+	const char *mux_clk_name;   /* The parent of the div clock */
+	struct clk *mux_clk;
+	const char *div_clk_name;
+	struct clk *div_clk;
+	struct int_clk_info *clk_info;
+};
+
+static struct int_bus_opp_table *exynos5_int_opp_table;
+static struct int_bus_opp_table exynos5250_int_opp_table[] = {
 	{LV_0, 266000, 1025000},
 	{LV_1, 200000, 1025000},
 	{LV_2, 160000, 1025000},
@@ -85,7 +129,16 @@ static struct int_bus_opp_table exynos5_int_opp_table[] = {
 	{0, 0, 0},
 };
 
-static struct int_clk_table aclk_166[] = {
+static struct int_bus_opp_table exynos5420_int_opp_table[] = {
+	{LV_0, 400000, 1100000},
+	{LV_1, 333000, 1100000},
+	{LV_2, 222000, 1100000},
+	{LV_3, 111000, 1100000},
+	{LV_4,  83000, 1100000},
+	{0, 0, 0},
+};
+
+static struct int_clk_table exynos5250_aclk_166[] = {
 	{LV_0, 167000},
 	{LV_1, 111000},
 	{LV_2,  84000},
@@ -93,7 +146,7 @@ static struct int_clk_table aclk_166[] = {
 	{LV_4,  42000},
 };
 
-static struct int_clk_table aclk_200[] = {
+static struct int_clk_table exynos5250_aclk_200[] = {
 	{LV_0, 200000},
 	{LV_1, 160000},
 	{LV_2, 160000},
@@ -101,7 +154,7 @@ static struct int_clk_table aclk_200[] = {
 	{LV_4, 100000},
 };
 
-static struct int_clk_table aclk_266[] = {
+static struct int_clk_table exynos5250_aclk_266[] = {
 	{LV_0, 267000},
 	{LV_1, 200000},
 	{LV_2, 160000},
@@ -109,7 +162,7 @@ static struct int_clk_table aclk_266[] = {
 	{LV_4, 100000},
 };
 
-static struct int_clk_table aclk_333[] = {
+static struct int_clk_table exynos5250_aclk_333[] = {
 	{LV_0, 333000},
 	{LV_1, 167000},
 	{LV_2, 111000},
@@ -117,7 +170,7 @@ static struct int_clk_table aclk_333[] = {
 	{LV_4,  42000},
 };
 
-static struct int_clk_table aclk_300_disp1[] = {
+static struct int_clk_table exynos5250_aclk_300_disp1[] = {
 	{LV_0, 267000},
 	{LV_1, 267000},
 	{LV_2, 267000},
@@ -125,7 +178,7 @@ static struct int_clk_table aclk_300_disp1[] = {
 	{LV_4, 200000},
 };
 
-static struct int_clk_table aclk_300_gscl[] = {
+static struct int_clk_table exynos5250_aclk_300_gscl[] = {
 	{LV_0, 267000},
 	{LV_1, 267000},
 	{LV_2, 267000},
@@ -133,27 +186,183 @@ static struct int_clk_table aclk_300_gscl[] = {
 	{LV_4, 100000},
 };
 
-#define EXYNOS5_INT_CLK(name, tbl) {		\
+#define EXYNOS5250_INT_CLK(name, tbl) {		\
 	.clk_name = name,			\
 	.freq_table = tbl,			\
 }
 
-static struct int_clk exynos5_int_clks[] = {
-	EXYNOS5_INT_CLK("aclk166_d", aclk_166),
-	EXYNOS5_INT_CLK("aclk200_d", aclk_200),
-	EXYNOS5_INT_CLK("aclk266_d", aclk_266),
-	EXYNOS5_INT_CLK("aclk333_d", aclk_333),
-	EXYNOS5_INT_CLK("aclk300_disp1_d", aclk_300_disp1),
-	EXYNOS5_INT_CLK("aclk300_gscl_d", aclk_300_gscl),
+static struct int_simple_clk exynos5250_int_clks[] = {
+	EXYNOS5250_INT_CLK("aclk166_d", exynos5250_aclk_166),
+	EXYNOS5250_INT_CLK("aclk200_d", exynos5250_aclk_200),
+	EXYNOS5250_INT_CLK("aclk266_d", exynos5250_aclk_266),
+	EXYNOS5250_INT_CLK("aclk333_d", exynos5250_aclk_333),
+	EXYNOS5250_INT_CLK("aclk300_disp1_d", exynos5250_aclk_300_disp1),
+	EXYNOS5250_INT_CLK("aclk300_gscl_d", exynos5250_aclk_300_gscl),
+};
+
+static struct int_clk_info exynos5420_aclk_200_fsys[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 200000, D_PLL},
+	{LV_1, 200000, D_PLL},
+	{LV_2, 150000, D_PLL},
+	{LV_3, 100000, D_PLL},
+	{LV_4, 100000, D_PLL},
+};
+
+static struct int_clk_info exynos5420_pclk_200_fsys[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 200000, D_PLL},
+	{LV_1, 150000, D_PLL},
+	{LV_2, 150000, D_PLL},
+	{LV_3, 100000, D_PLL},
+	{LV_4, 100000, D_PLL},
+};
+
+static struct int_clk_info exynos5420_aclk_100_noc[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 100000, D_PLL},
+	{LV_1,  86000, D_PLL},
+	{LV_2,  75000, D_PLL},
+	{LV_3,  75000, D_PLL},
+	{LV_4,  75000, D_PLL},
 };
 
-static int exynos5_int_set_rate(struct busfreq_data_int *data,
+static struct int_clk_info exynos5420_aclk_400_wcore[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 400000, M_PLL},
+	{LV_1, 333000, C_PLL},
+	{LV_2, 333000, C_PLL},
+	{LV_3, 333000, C_PLL},
+	{LV_4, 333000, C_PLL},
+};
+
+static struct int_clk_info exynos5420_aclk_200_fsys2[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 200000, D_PLL},
+	{LV_1, 200000, D_PLL},
+	{LV_2, 150000, D_PLL},
+	{LV_3, 100000, D_PLL},
+	{LV_4, 100000, D_PLL},
+};
+
+static struct int_clk_info exynos5420_aclk_400_mscl[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 400000, M_PLL},
+	{LV_1, 333000, C_PLL},
+	{LV_2, 222000, C_PLL},
+	{LV_3, 167000, C_PLL},
+	{LV_4,  84000, C_PLL},
+};
+
+static struct int_clk_info exynos5420_aclk_166[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 167000, C_PLL},
+	{LV_1, 134000, C_PLL},
+	{LV_2, 111000, C_PLL},
+	{LV_3,  84000, C_PLL},
+	{LV_4,  84000, C_PLL},
+};
+
+static struct int_clk_info exynos5420_aclk_266[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 267000, M_PLL},
+	{LV_1, 160000, M_PLL},
+	{LV_2, 134000, M_PLL},
+	{LV_3, 134000, M_PLL},
+	{LV_4,  86000, D_PLL},
+};
+
+static struct int_clk_info exynos5420_aclk_66[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0,  67000, C_PLL},
+	{LV_1,  67000, C_PLL},
+	{LV_2,  67000, C_PLL},
+	{LV_3,  67000, C_PLL},
+	{LV_4,  67000, C_PLL},
+};
+
+static struct int_clk_info exynos5420_aclk_300_disp1[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 200000, D_PLL},
+	{LV_1, 200000, D_PLL},
+	{LV_2, 200000, D_PLL},
+	{LV_3, 200000, D_PLL},
+	{LV_4, 120000, D_PLL},
+};
+
+static struct int_clk_info exynos5420_aclk_400_disp1[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 300000, D_PLL},
+	{LV_1, 300000, D_PLL},
+	{LV_2, 200000, D_PLL},
+	{LV_3, 200000, D_PLL},
+	{LV_4, 120000, D_PLL},
+};
+
+static struct int_clk_info exynos5420_aclk_300_jpeg[] = {
+	/* Level, Freq, Parent_Pll */
+	{LV_0, 300000, D_PLL},
+	{LV_1, 300000, D_PLL},
+	{LV_2, 200000, D_PLL},
+	{LV_3, 150000, D_PLL},
+	{LV_4,  75000, D_PLL},
+};
+
+#define EXYNOS5420_INT_PM_CLK(NAME, CLK, PCLK, CLK_INFO)	\
+static struct int_comp_clks int_pm_clks_##NAME = {	\
+	.mux_clk_name = CLK,				\
+	.div_clk_name = PCLK,				\
+	.clk_info = CLK_INFO,				\
+}
+
+EXYNOS5420_INT_PM_CLK(aclk_200_fsys, "aclk200_fsys",
+			"aclk200_fsys_d", exynos5420_aclk_200_fsys);
+EXYNOS5420_INT_PM_CLK(pclk_200_fsys, "pclk200_fsys",
+			"pclk200_fsys_d", exynos5420_pclk_200_fsys);
+EXYNOS5420_INT_PM_CLK(aclk_100_noc, "aclk100_noc",
+			"aclk100_noc_d", exynos5420_aclk_100_noc);
+EXYNOS5420_INT_PM_CLK(aclk_400_wcore, "aclk400_wcore",
+			"aclk400_wcore_d", exynos5420_aclk_400_wcore);
+EXYNOS5420_INT_PM_CLK(aclk_200_fsys2, "aclk200_fsys2",
+			"aclk200_fsys2_d", exynos5420_aclk_200_fsys2);
+EXYNOS5420_INT_PM_CLK(aclk_400_mscl, "aclk400_mscl",
+			"aclk400_mscl_d", exynos5420_aclk_400_mscl);
+EXYNOS5420_INT_PM_CLK(aclk_166, "aclk166",
+			"aclk166_d", exynos5420_aclk_166);
+EXYNOS5420_INT_PM_CLK(aclk_266, "aclk266",
+			"aclk266_d", exynos5420_aclk_266);
+EXYNOS5420_INT_PM_CLK(aclk_66, "aclk66",
+			"aclk66_d", exynos5420_aclk_66);
+EXYNOS5420_INT_PM_CLK(aclk_300_disp1, "aclk300_disp1",
+			"aclk300_disp1_d", exynos5420_aclk_300_disp1);
+EXYNOS5420_INT_PM_CLK(aclk_300_jpeg, "aclk300_jpeg",
+			"aclk300_jpeg_d", exynos5420_aclk_300_jpeg);
+EXYNOS5420_INT_PM_CLK(aclk_400_disp1, "aclk400_disp1",
+			"aclk400_disp1_d", exynos5420_aclk_400_disp1);
+
+static struct int_comp_clks *exynos5420_int_pm_clks[] = {
+	&int_pm_clks_aclk_200_fsys,
+	&int_pm_clks_pclk_200_fsys,
+	&int_pm_clks_aclk_100_noc,
+	&int_pm_clks_aclk_400_wcore,
+	&int_pm_clks_aclk_200_fsys2,
+	&int_pm_clks_aclk_400_mscl,
+	&int_pm_clks_aclk_166,
+	&int_pm_clks_aclk_266,
+	&int_pm_clks_aclk_66,
+	&int_pm_clks_aclk_300_disp1,
+	&int_pm_clks_aclk_300_jpeg,
+	&int_pm_clks_aclk_400_disp1,
+	NULL,
+};
+
+static int exynos5250_int_set_rate(struct busfreq_data_int *data,
 				unsigned long rate)
 {
 	int index, i;
 
-	for (index = 0; index < ARRAY_SIZE(exynos5_int_opp_table); index++) {
-		if (exynos5_int_opp_table[index].clk == rate)
+	for (index = 0; index < ARRAY_SIZE(exynos5250_int_opp_table); index++) {
+		if (exynos5250_int_opp_table[index].clk == rate)
 			break;
 	}
 
@@ -161,8 +370,8 @@ static int exynos5_int_set_rate(struct busfreq_data_int *data,
 		return -EINVAL;
 
 	/* Change the system clock divider values */
-	for (i = 0; i < ARRAY_SIZE(exynos5_int_clks); i++) {
-		struct int_clk *clk_info = &exynos5_int_clks[i];
+	for (i = 0; i < ARRAY_SIZE(exynos5250_int_clks); i++) {
+		struct int_simple_clk *clk_info = &exynos5250_int_clks[i];
 		int ret;
 
 		ret = clk_set_rate(clk_info->clk,
@@ -177,10 +386,111 @@ static int exynos5_int_set_rate(struct busfreq_data_int *data,
 	return 0;
 }
 
+static struct clk *exynos5420_find_pll(struct busfreq_data_int *data,
+				    enum int_bus_pll target_pll)
+{
+	struct clk *target_src_clk = NULL;
+
+	switch (target_pll) {
+	case C_PLL:
+		target_src_clk = data->mout_cpll;
+		break;
+	case M_PLL:
+		target_src_clk = data->mout_mpll;
+		break;
+	case D_PLL:
+		target_src_clk = data->mout_dpll;
+		break;
+	case I_PLL:
+		target_src_clk = data->mout_ipll;
+		break;
+	default:
+		break;
+	}
+
+	return target_src_clk;
+}
+
+static int exynos5420_int_set_rate(struct busfreq_data_int *data,
+		unsigned long target_freq, unsigned long pre_freq)
+{
+	unsigned int i;
+	unsigned long tar_rate;
+	int target_idx = -EINVAL;
+	int pre_idx = -EINVAL;
+	struct int_comp_clks *int_clk;
+	struct clk *new_src_pll;
+	struct clk *old_src_pll;
+	unsigned long old_src_rate, new_src_rate;
+	unsigned long rate1, rate2, rate3, rate4;
+
+	/* Find the levels for target and previous frequencies */
+	for (i = 0; i < _LV_END; i++) {
+		if (exynos5420_int_opp_table[i].clk == target_freq)
+			target_idx = exynos5420_int_opp_table[i].idx;
+		if (exynos5420_int_opp_table[i].clk == pre_freq)
+			pre_idx = exynos5420_int_opp_table[i].idx;
+	}
+
+	list_for_each_entry(int_clk, &data->list, node) {
+		tar_rate = int_clk->clk_info[target_idx].target_freq * 1000;
+
+		old_src_pll = clk_get_parent(int_clk->mux_clk);
+		new_src_pll = exynos5420_find_pll(data,
+				int_clk->clk_info[target_idx].src_pll);
+
+		if (old_src_pll == new_src_pll) {
+			/* No need to change pll */
+			clk_set_rate(int_clk->div_clk, tar_rate);
+			pr_debug("%s: %s now %lu (%lu)\n", __func__,
+				 int_clk->mux_clk_name,
+				 clk_get_rate(int_clk->div_clk), tar_rate);
+			continue;
+		}
+
+		old_src_rate = clk_get_rate(old_src_pll);
+		new_src_rate = clk_get_rate(new_src_pll);
+		rate1 = clk_get_rate(int_clk->div_clk);
+
+		/*
+		 * If we're switching to a faster PLL we should bump up the
+		 * divider before switching.
+		 */
+		if (new_src_rate > old_src_rate) {
+			int new_div;
+			unsigned long tmp_rate;
+
+			new_div = DIV_ROUND_UP(new_src_rate, tar_rate);
+			tmp_rate = DIV_ROUND_UP(old_src_rate, new_div);
+			clk_set_rate(int_clk->div_clk, tmp_rate);
+		}
+		rate2 = clk_get_rate(int_clk->div_clk);
+
+		/* We can safely change the mux now */
+		clk_set_parent(int_clk->mux_clk, new_src_pll);
+		rate3 = clk_get_rate(int_clk->div_clk);
+
+		/*
+		 * Give us a proper divider; technically not needed in the case
+		 * where we pre-calculated the divider above (the new_src_rate >
+		 * old_src_rate case), but let's be formal about it.
+		 */
+		clk_set_rate(int_clk->div_clk, tar_rate);
+		rate4 = clk_get_rate(int_clk->div_clk);
+
+		pr_debug("%s: %s => PLL %d; %lu=>%lu=>%lu=>%lu (%lu)\n",
+			 __func__, int_clk->mux_clk_name,
+			 int_clk->clk_info[target_idx].src_pll,
+			 rate1, rate2, rate3, rate4, tar_rate);
+	}
+	return 0;
+}
+
 static int exynos5_int_setvolt(struct busfreq_data_int *data,
 				unsigned long volt)
 {
-	return regulator_set_voltage(data->vdd_int, volt, MAX_SAFEVOLT);
+	return regulator_set_voltage(data->vdd_int, volt,
+				volt + INT_VOLT_STEP_UV);
 }
 
 static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
@@ -218,18 +528,15 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
 	if (data->disabled)
 		goto out;
 
-	if (freq > exynos5_int_opp_table[0].clk)
-		pm_qos_update_request(&data->int_req, freq * 16 / 1000);
-	else
-		pm_qos_update_request(&data->int_req, -1);
-
 	if (old_freq < freq)
 		err = exynos5_int_setvolt(data, volt);
 	if (err)
 		goto out;
 
-	err = exynos5_int_set_rate(data, freq);
-
+	if (data->type == TYPE_BUSF_EXYNOS5250)
+		err = exynos5250_int_set_rate(data, freq);
+	else
+		err = exynos5420_int_set_rate(data, freq, old_freq);
 	if (err)
 		goto out;
 
@@ -267,16 +574,20 @@ static int exynos5_int_get_dev_status(struct device *dev,
 }
 
 static struct devfreq_dev_profile exynos5_devfreq_int_profile = {
-	.initial_freq		= 160000,
-	.polling_ms		= 100,
+	.polling_ms		= 10,
 	.target			= exynos5_busfreq_int_target,
 	.get_dev_status		= exynos5_int_get_dev_status,
 };
 
-static int exynos5250_init_int_tables(struct busfreq_data_int *data)
+static int exynos5_init_int_tables(struct busfreq_data_int *data)
 {
 	int i, err = 0;
 
+	if (data->type == TYPE_BUSF_EXYNOS5250)
+		exynos5_int_opp_table = exynos5250_int_opp_table;
+	else
+		exynos5_int_opp_table = exynos5420_int_opp_table;
+
 	for (i = LV_0; i < _LV_END; i++) {
 		err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk,
 				exynos5_int_opp_table[i].volt);
@@ -297,6 +608,7 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
 	struct dev_pm_opp *opp;
 	unsigned long maxfreq = ULONG_MAX;
 	unsigned long freq;
+	unsigned long old_freq;
 	unsigned long volt;
 	int err = 0;
 
@@ -322,8 +634,14 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
 		if (err)
 			goto unlock;
 
-		err = exynos5_int_set_rate(data, freq);
+		old_freq = data->curr_freq;
 
+		if (data->type == TYPE_BUSF_EXYNOS5250)
+			err = exynos5250_int_set_rate(data, freq);
+		else if (data->type == TYPE_BUSF_EXYNOS5420)
+			err = exynos5420_int_set_rate(data, freq, old_freq);
+		else
+			err = -EINVAL;
 		if (err)
 			goto unlock;
 
@@ -345,16 +663,38 @@ unlock:
 	return NOTIFY_DONE;
 }
 
+static const struct of_device_id exynos5_busfreq_dt_match[];
+
+static inline int exynos5_busfreq_get_driver_data(struct platform_device *pdev)
+{
+#ifdef CONFIG_OF
+	struct exynos5_busfreq_drv_data *data;
+
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+
+		match = of_match_node(exynos5_busfreq_dt_match,
+					pdev->dev.of_node);
+		data = (struct exynos5_busfreq_drv_data *) match->data;
+		return data->busf_type;
+	}
+#endif
+	return platform_get_device_id(pdev)->driver_data;
+}
+
 static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 {
 	struct busfreq_data_int *data;
 	struct busfreq_ppmu_data *ppmu_data;
+	struct device_node *np = pdev->dev.of_node;
 	struct dev_pm_opp *opp;
 	struct device *dev = &pdev->dev;
-	struct device_node *np;
 	unsigned long initial_freq;
 	unsigned long initial_volt;
+	struct clk *mux_clk, *div_clk;
+	struct int_comp_clks *int_pm_clk;
 	int err = 0;
+	int nr_clk;
 	int i;
 
 	data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data_int),
@@ -364,22 +704,27 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	INIT_LIST_HEAD(&data->list);
+	data->type = exynos5_busfreq_get_driver_data(pdev);
+
 	ppmu_data = &data->ppmu_data;
-	ppmu_data->ppmu_end = PPMU_END;
+	if (data->type == TYPE_BUSF_EXYNOS5250) {
+		ppmu_data->ppmu_end = PPMU_END_5250;
+	} else if (data->type == TYPE_BUSF_EXYNOS5420) {
+		ppmu_data->ppmu_end = PPMU_END_5420;
+	} else {
+		dev_err(dev, "Cannot determine the device id %d\n", data->type);
+		return -EINVAL;
+	}
+
 	ppmu_data->ppmu = devm_kzalloc(dev,
-				       sizeof(struct exynos_ppmu) * PPMU_END,
-				       GFP_KERNEL);
+			sizeof(struct exynos_ppmu) * (ppmu_data->ppmu_end),
+			GFP_KERNEL);
 	if (!ppmu_data->ppmu) {
 		dev_err(dev, "Failed to allocate memory for exynos_ppmu\n");
 		return -ENOMEM;
 	}
 
-	np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu");
-	if (np == NULL) {
-		pr_err("Unable to find PPMU node\n");
-		return -ENOENT;
-	}
-
 	for (i = 0; i < ppmu_data->ppmu_end; i++) {
 		/* map PPMU memory region */
 		ppmu_data->ppmu[i].hw_base = of_iomap(np, i);
@@ -388,13 +733,17 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 			return -ENOMEM;
 		}
 	}
+
 	data->pm_notifier.notifier_call = exynos5_busfreq_int_pm_notifier_event;
 	data->dev = dev;
 	mutex_init(&data->lock);
 
-	err = exynos5250_init_int_tables(data);
-	if (err)
+	err = exynos5_init_int_tables(data);
+	if (err) {
+		dev_err(dev, "Cannot initialize busfreq table %d\n",
+			     data->type);
 		return err;
+	}
 
 	data->vdd_int = devm_regulator_get(dev, "vdd_int");
 	if (IS_ERR(data->vdd_int)) {
@@ -402,18 +751,70 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 		return PTR_ERR(data->vdd_int);
 	}
 
-	for (i = 0; i < ARRAY_SIZE(exynos5_int_clks); i++) {
-		struct int_clk *clk_info = &exynos5_int_clks[i];
+	if (data->type == TYPE_BUSF_EXYNOS5250) {
+		for (i = 0; i < ARRAY_SIZE(exynos5250_int_clks); i++) {
+			struct int_simple_clk *clk_info =
+				&exynos5250_int_clks[i];
+
+			clk_info->clk = devm_clk_get(dev, clk_info->clk_name);
+			if (IS_ERR(clk_info->clk)) {
+				dev_err(dev, "Failed to get clock %s\n",
+					clk_info->clk_name);
+				return PTR_ERR(clk_info->clk);
+			}
+		}
+	} else {
+		data->mout_ipll = devm_clk_get(dev, "mout_ipll");
+		if (IS_ERR(data->mout_ipll)) {
+			dev_err(dev, "Cannot get clock \"mout_ipll\"\n");
+			return PTR_ERR(data->mout_ipll);
+		}
 
-		clk_info->clk = devm_clk_get(dev, clk_info->clk_name);
-		if (IS_ERR(clk_info->clk)) {
-			dev_err(dev, "Failed to get clock %s\n",
-				clk_info->clk_name);
-			return PTR_ERR(clk_info->clk);
+		data->mout_mpll = devm_clk_get(dev, "mout_mpll");
+		if (IS_ERR(data->mout_mpll)) {
+			dev_err(dev, "Cannot get clock \"mout_mpll\"\n");
+			return PTR_ERR(data->mout_mpll);
+		}
+
+		data->mout_dpll = devm_clk_get(dev, "mout_dpll");
+		if (IS_ERR(data->mout_dpll)) {
+			dev_err(dev, "Cannot get clock \"mout_dpll\"\n");
+			return PTR_ERR(data->mout_dpll);
+		}
+
+		data->mout_cpll = devm_clk_get(dev, "mout_cpll");
+		if (IS_ERR(data->mout_cpll)) {
+			dev_err(dev, "Cannot get clock \"mout_cpll\"\n");
+			return PTR_ERR(data->mout_cpll);
+		}
+
+		for (nr_clk = 0; exynos5420_int_pm_clks[nr_clk] != NULL;
+								nr_clk++) {
+			int_pm_clk = exynos5420_int_pm_clks[nr_clk];
+			mux_clk = devm_clk_get(dev, int_pm_clk->mux_clk_name);
+			if (IS_ERR(mux_clk)) {
+				dev_err(dev, "Cannot get mux clock: %s\n",
+						int_pm_clk->mux_clk_name);
+				return PTR_ERR(mux_clk);
+			}
+			div_clk = devm_clk_get(dev, int_pm_clk->div_clk_name);
+			if (IS_ERR(div_clk)) {
+				dev_err(dev, "Cannot get div clock: %s\n",
+						int_pm_clk->div_clk_name);
+				return PTR_ERR(div_clk);
+			}
+			int_pm_clk->mux_clk = mux_clk;
+			int_pm_clk->div_clk = div_clk;
+			list_add_tail(&int_pm_clk->node, &data->list);
 		}
 	}
 
 	rcu_read_lock();
+	if (data->type == TYPE_BUSF_EXYNOS5250)
+		exynos5_devfreq_int_profile.initial_freq = 160000;
+	else
+		exynos5_devfreq_int_profile.initial_freq = 333000;
+
 	opp = dev_pm_opp_find_freq_floor(dev,
 			&exynos5_devfreq_int_profile.initial_freq);
 	if (IS_ERR(opp)) {
@@ -428,10 +829,15 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 	data->curr_freq = initial_freq;
 
 	err = exynos5_int_setvolt(data, initial_volt);
-	if (err)
+	if (err) {
+		dev_err(dev, "Failed to set initial voltage\n");
 		return err;
+	}
 
-	err = exynos5_int_set_rate(data, initial_freq);
+	if (data->type == TYPE_BUSF_EXYNOS5250)
+		err = exynos5250_int_set_rate(data, initial_freq);
+	else
+		err = exynos5420_int_set_rate(data, initial_freq, initial_freq);
 	if (err) {
 		dev_err(dev, "Failed to set initial frequency\n");
 		return err;
@@ -439,28 +845,31 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, data);
 
-	busfreq_mon_reset(ppmu_data);
-
-	data->devfreq = devm_devfreq_add_device(dev, &exynos5_devfreq_int_profile,
-					   "simple_ondemand", NULL);
+	data->devfreq = devm_devfreq_add_device(dev,
+		&exynos5_devfreq_int_profile, "simple_ondemand", NULL);
 	if (IS_ERR(data->devfreq))
 		return PTR_ERR(data->devfreq);
 
+	/*
+	 * Start PPMU (Performance Profiling Monitoring Unit) to check
+	 * utilization of each IP in the Exynos4 SoC.
+	 */
+	busfreq_mon_reset(ppmu_data);
+
+	/* Register opp_notifier for Exynos5 busfreq */
 	err = devm_devfreq_register_opp_notifier(dev, data->devfreq);
 	if (err < 0) {
 		dev_err(dev, "Failed to register opp notifier\n");
 		return err;
 	}
 
+	/* Register pm_notifier for Exynos5 busfreq */
 	err = register_pm_notifier(&data->pm_notifier);
 	if (err) {
 		dev_err(dev, "Failed to setup pm notifier\n");
 		return err;
 	}
 
-	/* TODO: Add a new QOS class for int/mif bus */
-	pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1);
-
 	return 0;
 }
 
@@ -468,7 +877,7 @@ static int exynos5_busfreq_int_remove(struct platform_device *pdev)
 {
 	struct busfreq_data_int *data = platform_get_drvdata(pdev);
 
-	pm_qos_remove_request(&data->int_req);
+	/* Unregister all of notifier chain */
 	unregister_pm_notifier(&data->pm_notifier);
 
 	return 0;
@@ -492,8 +901,24 @@ static const struct dev_pm_ops exynos5_busfreq_int_pm = {
 static SIMPLE_DEV_PM_OPS(exynos5_busfreq_int_pm_ops, NULL,
 			 exynos5_busfreq_int_resume);
 
-/* platform device pointer for exynos5 devfreq device. */
-static struct platform_device *exynos5_devfreq_pdev;
+#ifdef CONFIG_OF
+static struct exynos5_busfreq_drv_data exynos_busfreq_data_array[] = {
+	[TYPE_BUSF_EXYNOS5250] = { TYPE_BUSF_EXYNOS5250 },
+	[TYPE_BUSF_EXYNOS5420] = { TYPE_BUSF_EXYNOS5420 },
+};
+
+static const struct of_device_id exynos5_busfreq_dt_match[] = {
+	{
+		.compatible = "samsung,exynos5250-int-busfreq",
+		.data = &exynos_busfreq_data_array[TYPE_BUSF_EXYNOS5250],
+	}, {
+		.compatible = "samsung,exynos5420-int-busfreq",
+		.data = &exynos_busfreq_data_array[TYPE_BUSF_EXYNOS5420],
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos5_busfreq_dt_match);
+#endif
 
 static struct platform_driver exynos5_busfreq_int_driver = {
 	.probe		= exynos5_busfreq_int_probe,
@@ -502,35 +927,18 @@ static struct platform_driver exynos5_busfreq_int_driver = {
 		.name		= "exynos5-bus-int",
 		.owner		= THIS_MODULE,
 		.pm		= &exynos5_busfreq_int_pm_ops,
+		.of_match_table	= of_match_ptr(exynos5_busfreq_dt_match),
 	},
 };
 
 static int __init exynos5_busfreq_int_init(void)
 {
-	int ret;
-
-	ret = platform_driver_register(&exynos5_busfreq_int_driver);
-	if (ret < 0)
-		goto out;
-
-	exynos5_devfreq_pdev =
-		platform_device_register_simple("exynos5-bus-int", -1, NULL, 0);
-	if (IS_ERR(exynos5_devfreq_pdev)) {
-		ret = PTR_ERR(exynos5_devfreq_pdev);
-		goto out1;
-	}
-
-	return 0;
-out1:
-	platform_driver_unregister(&exynos5_busfreq_int_driver);
-out:
-	return ret;
+	return platform_driver_register(&exynos5_busfreq_int_driver);
 }
 late_initcall(exynos5_busfreq_int_init);
 
 static void __exit exynos5_busfreq_int_exit(void)
 {
-	platform_device_unregister(exynos5_devfreq_pdev);
 	platform_driver_unregister(&exynos5_busfreq_int_driver);
 }
 module_exit(exynos5_busfreq_int_exit);
-- 
1.7.9.5

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

* [PATCH RFC v2 4/7] ARM: dts: Add PPMU device tree support for Exynos5420
  2014-05-22 17:21 ` [PATCH RFC v2 4/7] ARM: dts: Add PPMU device tree support for Exynos5420 Abhilash Kesavan
@ 2014-05-22 17:50   ` Sergei Shtylyov
  2014-06-16  7:01     ` Abhilash Kesavan
  0 siblings, 1 reply; 12+ messages in thread
From: Sergei Shtylyov @ 2014-05-22 17:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/22/2014 09:21 PM, Abhilash Kesavan wrote:

> PPMU is required by the exynos5420 devfreq driver. Add a device
> tree node for it.

> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> ---
>   arch/arm/boot/dts/exynos5420.dtsi |    7 +++++++
>   1 file changed, 7 insertions(+)

> diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
> index 8e7e35c..6ab7b03 100644
> --- a/arch/arm/boot/dts/exynos5420.dtsi
> +++ b/arch/arm/boot/dts/exynos5420.dtsi
> @@ -833,4 +833,11 @@
>   		samsung,pmu-syscon = <&pmu_system_controller>;
>   		#phy-cells = <1>;
>   	};
> +
> +	ppmu {

    Shouldn't it have the unit-address part, like "ppmu at 10d00000"?

> +		compatible = "samsung,exynos5420-int-busfreq";
> +		reg = <0x10D00000 0x2000	/* PPMU_DMC_0_0 */
> +		       0x10D10000 0x2000	/* PPMU_DMC_0_1 */
> +		       0x10D60000 0x2000>;	/* PPMU_DMC_1_0 */
> +	};
>   };

WBR, Sergei

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

* [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420
  2014-05-22 17:21 [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Abhilash Kesavan
                   ` (6 preceding siblings ...)
  2014-05-22 17:22 ` [PATCH RFC v2 7/7] PM / devfreq: Add devfreq driver for Exynos5420 Abhilash Kesavan
@ 2014-05-23  5:08 ` Chanwoo Choi
  2014-06-16  6:59   ` Abhilash Kesavan
  7 siblings, 1 reply; 12+ messages in thread
From: Chanwoo Choi @ 2014-05-23  5:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 05/23/2014 02:21 AM, Abhilash Kesavan wrote:
> This patchset adds devfreq support on Exynos5250 and Exynos5420.
> The patches add the missing INT clock support for exynos5250 and
> also add a new 5420 driver. We also have patches which add the
> PPMU node and fix a typo in the exynos5250 driver.
> 
> Changes since RFC v1:
> 	- Exynos5420 support has been added to the existent Exynos5250
> 	  driver itself.
> 	- Rebased on Chanwoo Choi's devfreq consolidation patchset.
> 	- Removed unused clocks from the clock list
> 	- Used the PPMU nodes with different compatible strings to
> 	  differentiate between exynos5250 and exynos5420.
> 
> The patches have been tested on Exynos5250 based Snow board and Exynos5420
> based Peach-Pit boards. They have been prepared on linux-next(20140521) with
> the devfreq for-next branch merged. Also applied is the "devfreq resource
> management" series from Chanwoo Choi[1].
> [1] https://lkml.org/lkml/2014/4/25/826

I sent v2 patchset as following after fixed minor issue:
[PATCHv2 0/5] devfreq: Support resource management functions and code clean
- https://lkml.org/lkml/2014/5/9/74

Best Regards,
Chanwoo Choi

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

* [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420
  2014-05-23  5:08 ` [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Chanwoo Choi
@ 2014-06-16  6:59   ` Abhilash Kesavan
  0 siblings, 0 replies; 12+ messages in thread
From: Abhilash Kesavan @ 2014-06-16  6:59 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Chanwoo,

On Fri, May 23, 2014 at 10:38 AM, Chanwoo Choi <cw00.choi@samsung.com> wrote:
> Hi,
>
> On 05/23/2014 02:21 AM, Abhilash Kesavan wrote:
>> This patchset adds devfreq support on Exynos5250 and Exynos5420.
>> The patches add the missing INT clock support for exynos5250 and
>> also add a new 5420 driver. We also have patches which add the
>> PPMU node and fix a typo in the exynos5250 driver.
>>
>> Changes since RFC v1:
>>       - Exynos5420 support has been added to the existent Exynos5250
>>         driver itself.
>>       - Rebased on Chanwoo Choi's devfreq consolidation patchset.
>>       - Removed unused clocks from the clock list
>>       - Used the PPMU nodes with different compatible strings to
>>         differentiate between exynos5250 and exynos5420.
>>
>> The patches have been tested on Exynos5250 based Snow board and Exynos5420
>> based Peach-Pit boards. They have been prepared on linux-next(20140521) with
>> the devfreq for-next branch merged. Also applied is the "devfreq resource
>> management" series from Chanwoo Choi[1].
>> [1] https://lkml.org/lkml/2014/4/25/826
>
> I sent v2 patchset as following after fixed minor issue:
> [PATCHv2 0/5] devfreq: Support resource management functions and code clean
> - https://lkml.org/lkml/2014/5/9/74
Sorry for the delayed response, I was not in office for the last
couple of weeks. I have got the link wrong here, my patchset was in
fact based on your v2 patchset.

Myungjoo and Chanwoo, do you have any other comments on this patchset
or should I re-base this on the latest devfreq tree and re-send ?

Regards,
Abhilash
>
> Best Regards,
> Chanwoo Choi

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

* [PATCH RFC v2 4/7] ARM: dts: Add PPMU device tree support for Exynos5420
  2014-05-22 17:50   ` Sergei Shtylyov
@ 2014-06-16  7:01     ` Abhilash Kesavan
  0 siblings, 0 replies; 12+ messages in thread
From: Abhilash Kesavan @ 2014-06-16  7:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sergei,

On Thu, May 22, 2014 at 11:20 PM, Sergei Shtylyov
<sergei.shtylyov@cogentembedded.com> wrote:
> On 05/22/2014 09:21 PM, Abhilash Kesavan wrote:
>
>> PPMU is required by the exynos5420 devfreq driver. Add a device
>> tree node for it.
>
>
>> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
>> ---
>>   arch/arm/boot/dts/exynos5420.dtsi |    7 +++++++
>>   1 file changed, 7 insertions(+)
>
>
>> diff --git a/arch/arm/boot/dts/exynos5420.dtsi
>> b/arch/arm/boot/dts/exynos5420.dtsi
>> index 8e7e35c..6ab7b03 100644
>> --- a/arch/arm/boot/dts/exynos5420.dtsi
>> +++ b/arch/arm/boot/dts/exynos5420.dtsi
>> @@ -833,4 +833,11 @@
>>                 samsung,pmu-syscon = <&pmu_system_controller>;
>>                 #phy-cells = <1>;
>>         };
>> +
>> +       ppmu {
>
>
>    Shouldn't it have the unit-address part, like "ppmu at 10d00000"?
Will fix.

Regards,
Abhilash
>
>
>> +               compatible = "samsung,exynos5420-int-busfreq";
>> +               reg = <0x10D00000 0x2000        /* PPMU_DMC_0_0 */
>> +                      0x10D10000 0x2000        /* PPMU_DMC_0_1 */
>> +                      0x10D60000 0x2000>;      /* PPMU_DMC_1_0 */
>> +       };
>>   };
>
>
> WBR, Sergei
>

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

end of thread, other threads:[~2014-06-16  7:01 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-22 17:21 [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Abhilash Kesavan
2014-05-22 17:21 ` [PATCH RFC v2 1/7] clk: exynos5250: add aliases for clocks used by devfreq Abhilash Kesavan
2014-05-22 17:21 ` [PATCH RFC v2 2/7] clk: exynos5420: Add " Abhilash Kesavan
2014-05-22 17:21 ` [PATCH RFC v2 3/7] ARM: dts: Add PPMU device tree support for Exynos5250 Abhilash Kesavan
2014-05-22 17:21 ` [PATCH RFC v2 4/7] ARM: dts: Add PPMU device tree support for Exynos5420 Abhilash Kesavan
2014-05-22 17:50   ` Sergei Shtylyov
2014-06-16  7:01     ` Abhilash Kesavan
2014-05-22 17:22 ` [PATCH RFC v2 5/7] PM / devfreq: exynos5250: migrate to common-clock Abhilash Kesavan
2014-05-22 17:22 ` [PATCH RFC v2 6/7] PM / devfreq: exynos: Fix typo in macro Abhilash Kesavan
2014-05-22 17:22 ` [PATCH RFC v2 7/7] PM / devfreq: Add devfreq driver for Exynos5420 Abhilash Kesavan
2014-05-23  5:08 ` [PATCH RFC v2 0/7] Devfreq support for Exynos5250/5420 Chanwoo Choi
2014-06-16  6:59   ` Abhilash Kesavan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).