All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Add CPU clock support for Exynos7
@ 2014-11-26 11:17 ` Abhilash Kesavan
  0 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel, tomasz.figa, s.nawrocki, mturquette
  Cc: linux-samsung-soc, kesavan.abhilash

These patches add the atlas clocks on Exynos7. It also modifies the
existing cpu clock infrastructure to handle exynos7 differences. These
patches are a pre-requisite for enabling CPUFreq on Exynos7.

Following are the dependencies:
1) arch: arm64: Enable support for Samsung Exynos7 SoC
http://www.spinics.net/lists/linux-samsung-soc/msg38734.html
2) cpufreq: use generic cpufreq drivers for exynos platforms
http://www.spinics.net/lists/linux-samsung-soc/msg39332.html

For testing I have applied the following:
1) mfd: sec: add S2MPS15 PMIC support
https://lkml.org/lkml/2014/10/14/50
2) regulator: s2mps11: add support for S2MPS15 regulators
https://lkml.org/lkml/2014/10/14/52
3) Regulators dt nodes were added in the espresso dts file and I2C channel 4
which has the PMIC on it was tested.

Abhilash Kesavan (4):
  clk: samsung: exynos7: add clocks for CPU block
  clk: samsung: retrieve the clock provider information from
    samsung_cmu_register_one
  clk: samsung: add cpu clock support for Exynos7
  clk: samsung: add cpu clock configuration data and instantiate cpu
    clock

 .../devicetree/bindings/clock/exynos7-clock.txt    |    6 +
 drivers/clk/samsung/clk-cpu.c                      |  130 ++++++++++++++++-
 drivers/clk/samsung/clk-cpu.h                      |   38 ++++-
 drivers/clk/samsung/clk-exynos4.c                  |    2 +-
 drivers/clk/samsung/clk-exynos5250.c               |    2 +-
 drivers/clk/samsung/clk-exynos5420.c               |    4 +-
 drivers/clk/samsung/clk-exynos7.c                  |  147 ++++++++++++++++++++
 drivers/clk/samsung/clk.c                          |    6 +-
 drivers/clk/samsung/clk.h                          |    4 +-
 include/dt-bindings/clock/exynos7-clk.h            |   21 ++-
 10 files changed, 347 insertions(+), 13 deletions(-)

-- 
1.7.9.5

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

* [PATCH 0/4] Add CPU clock support for Exynos7
@ 2014-11-26 11:17 ` Abhilash Kesavan
  0 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

These patches add the atlas clocks on Exynos7. It also modifies the
existing cpu clock infrastructure to handle exynos7 differences. These
patches are a pre-requisite for enabling CPUFreq on Exynos7.

Following are the dependencies:
1) arch: arm64: Enable support for Samsung Exynos7 SoC
http://www.spinics.net/lists/linux-samsung-soc/msg38734.html
2) cpufreq: use generic cpufreq drivers for exynos platforms
http://www.spinics.net/lists/linux-samsung-soc/msg39332.html

For testing I have applied the following:
1) mfd: sec: add S2MPS15 PMIC support
https://lkml.org/lkml/2014/10/14/50
2) regulator: s2mps11: add support for S2MPS15 regulators
https://lkml.org/lkml/2014/10/14/52
3) Regulators dt nodes were added in the espresso dts file and I2C channel 4
which has the PMIC on it was tested.

Abhilash Kesavan (4):
  clk: samsung: exynos7: add clocks for CPU block
  clk: samsung: retrieve the clock provider information from
    samsung_cmu_register_one
  clk: samsung: add cpu clock support for Exynos7
  clk: samsung: add cpu clock configuration data and instantiate cpu
    clock

 .../devicetree/bindings/clock/exynos7-clock.txt    |    6 +
 drivers/clk/samsung/clk-cpu.c                      |  130 ++++++++++++++++-
 drivers/clk/samsung/clk-cpu.h                      |   38 ++++-
 drivers/clk/samsung/clk-exynos4.c                  |    2 +-
 drivers/clk/samsung/clk-exynos5250.c               |    2 +-
 drivers/clk/samsung/clk-exynos5420.c               |    4 +-
 drivers/clk/samsung/clk-exynos7.c                  |  147 ++++++++++++++++++++
 drivers/clk/samsung/clk.c                          |    6 +-
 drivers/clk/samsung/clk.h                          |    4 +-
 include/dt-bindings/clock/exynos7-clk.h            |   21 ++-
 10 files changed, 347 insertions(+), 13 deletions(-)

-- 
1.7.9.5

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

* [PATCH 1/4] clk: samsung: exynos7: add clocks for CPU block
  2014-11-26 11:17 ` Abhilash Kesavan
@ 2014-11-26 11:17   ` Abhilash Kesavan
  -1 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel, tomasz.figa, s.nawrocki, mturquette
  Cc: linux-samsung-soc, kesavan.abhilash

Add clock support for the Atlas CPU block in Exynos7.

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 .../devicetree/bindings/clock/exynos7-clock.txt    |    6 +
 drivers/clk/samsung/clk-exynos7.c                  |  121 ++++++++++++++++++++
 include/dt-bindings/clock/exynos7-clk.h            |   20 +++-
 3 files changed, 146 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/exynos7-clock.txt b/Documentation/devicetree/bindings/clock/exynos7-clock.txt
index 6d3d5f8..0b4ba7f 100644
--- a/Documentation/devicetree/bindings/clock/exynos7-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos7-clock.txt
@@ -28,6 +28,7 @@ Required Properties for Clock Controller:
 	- "samsung,exynos7-clock-topc"
 	- "samsung,exynos7-clock-top0"
 	- "samsung,exynos7-clock-top1"
+	- "samsung,exynos7-clock-atlas"
 	- "samsung,exynos7-clock-ccore"
 	- "samsung,exynos7-clock-peric0"
 	- "samsung,exynos7-clock-peric1"
@@ -61,6 +62,11 @@ Input clocks for top1 clock controller:
 	- dout_sclk_cc_pll
 	- dout_sclk_mfc_pll
 
+Input clocks for atlas clock controller:
+	- fin_pll
+	- fout_atlas_pll
+	- mout_sclk_bus0_pll_atlas
+
 Input clocks for ccore clock controller:
 	- fin_pll
 	- dout_aclk_ccore_133
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index a79bf23..78f66b4 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -35,6 +35,34 @@
 #define DIV_TOPC1		0x0604
 #define DIV_TOPC3		0x060C
 
+static const struct samsung_pll_rate_table pll1450x_24mhz_tbl[] = {
+	/* rate, m, p, s */
+	PLL_35XX_RATE(2496000000, 208, 2, 0),
+	PLL_35XX_RATE(2400000000, 200, 2, 0),
+	PLL_35XX_RATE(2304000000, 288, 3, 0),
+	PLL_35XX_RATE(2200000000, 275, 3, 0),
+	PLL_35XX_RATE(2100000000, 175, 2, 0),
+	PLL_35XX_RATE(2000000000, 250, 3, 0),
+	PLL_35XX_RATE(1896000000, 158, 2, 0),
+	PLL_35XX_RATE(1800000000, 150, 2, 0),
+	PLL_35XX_RATE(1704000000, 142, 2, 0),
+	PLL_35XX_RATE(1600000000, 200, 3, 0),
+	PLL_35XX_RATE(1500000000, 250, 2, 1),
+	PLL_35XX_RATE(1400000000, 350, 3, 1),
+	PLL_35XX_RATE(1300000000, 325, 3, 1),
+	PLL_35XX_RATE(1200000000, 200, 2, 1),
+	PLL_35XX_RATE(1100000000, 275, 3, 1),
+	PLL_35XX_RATE(1000000000, 250, 3, 1),
+	PLL_35XX_RATE(900000000, 150, 2, 1),
+	PLL_35XX_RATE(800000000, 200, 3, 1),
+	PLL_35XX_RATE(700000000, 350, 3, 2),
+	PLL_35XX_RATE(600000000, 200, 2, 2),
+	PLL_35XX_RATE(500000000, 250, 3, 2),
+	PLL_35XX_RATE(400000000, 200, 3, 2),
+	PLL_35XX_RATE(300000000, 200, 2, 3),
+	PLL_35XX_RATE(200000000, 200, 3, 3),
+};
+
 static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
 	FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_bus0_pll_ctrl", 1, 2, 0),
 	FFACTOR(0, "ffac_topc_bus0_pll_div4",
@@ -50,6 +78,8 @@ PNAME(mout_bus1_pll_ctrl_p)	= { "fin_pll", "fout_bus1_pll" };
 PNAME(mout_cc_pll_ctrl_p)	= { "fin_pll", "fout_cc_pll" };
 PNAME(mout_mfc_pll_ctrl_p)	= { "fin_pll", "fout_mfc_pll" };
 
+PNAME(mout_topc_group1)	= { "mout_bus0_pll_ctrl", "ffac_topc_bus0_pll_div2",
+	 "mout_bus1_pll_ctrl", "mout_cci_pll" };
 PNAME(mout_topc_group2) = { "mout_sclk_bus0_pll_cmuc",
 	"mout_sclk_bus1_pll_cmuc", "mout_sclk_cc_pll_cmuc",
 	"mout_sclk_mfc_pll_cmuc" };
@@ -104,6 +134,8 @@ static struct samsung_mux_clock topc_mux_clks[] __initdata = {
 
 	MUX(0, "mout_sclk_bus0_pll_out", mout_sclk_bus0_pll_out_p,
 		MUX_SEL_TOPC1, 16, 1),
+	MUX(MOUT_SCLK_BUS0_PLL_ATLAS, "mout_sclk_bus0_pll_atlas",
+		mout_topc_group1, MUX_SEL_TOPC1, 4, 2),
 
 	MUX(0, "mout_aclk_ccore_133", mout_topc_group2,	MUX_SEL_TOPC2, 4, 2),
 
@@ -402,6 +434,95 @@ static void __init exynos7_clk_top1_init(struct device_node *np)
 CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1",
 	exynos7_clk_top1_init);
 
+/* Register Offset definitions for CMU_ATLAS (0x11800000) */
+#define	ATLAS_PLL_LOCK			0x0000
+#define	ATLAS_PLL_CON0			0x0100
+#define	MUX_SEL_ATLAS0			0x0200
+#define	MUX_SEL_ATLAS1			0x0204
+#define	MUX_SEL_ATLAS2			0x0208
+#define	DIV_ATLAS0			0x0600
+#define	DIV_ATLAS1			0x0604
+#define	ENABLE_IP_ATLAS0		0x0B00
+
+/* List of parent clocks for Muxes in CMU_ATLAS */
+PNAME(mout_atlas_pll_ctrl_p) = { "fin_pll", "fout_atlas_pll" };
+PNAME(mout_bus_pll_atlas_p) = { "fin_pll", "mout_sclk_bus0_pll_atlas" };
+PNAME(mout_atlas_p) = { "mout_atlas_pll_ctrl", "mout_bus_pll_atlas" };
+
+static unsigned long atlas_clk_regs[] __initdata = {
+	ATLAS_PLL_LOCK,
+	ATLAS_PLL_CON0,
+	MUX_SEL_ATLAS0,
+	MUX_SEL_ATLAS1,
+	MUX_SEL_ATLAS2,
+	DIV_ATLAS0,
+	DIV_ATLAS1,
+	ENABLE_IP_ATLAS0,
+};
+
+static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
+	MUX_F(MOUT_ATLAS_PLL_CTRL, "mout_atlas_pll_ctrl", mout_atlas_pll_ctrl_p,
+		MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0),
+	MUX_F(MOUT_BUS_PLL_ATLAS, "mout_bus_pll_atlas", mout_bus_pll_atlas_p,
+		MUX_SEL_ATLAS1, 0, 1, CLK_SET_RATE_PARENT, 0),
+	MUX_F(MOUT_ATLAS, "mout_atlas", mout_atlas_p,
+		MUX_SEL_ATLAS2, 0, 1, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct samsung_div_clock atlas_div_clks[] __initdata = {
+	DIV(DOUT_PCLK_DBG_CLK_ATLAS, "dout_pclk_dbg_clk_atlas", "dout_atlas2",
+		DIV_ATLAS0, 26, 6),
+	DIV(DOUT_ATCLK_ATLAS, "dout_atclk_atlas", "dout_atlas2",
+		DIV_ATLAS0, 20, 6),
+	DIV(DOUT_PCLK_ATLAS, "dout_pclk_atlas", "dout_atlas2",
+		DIV_ATLAS0, 12, 6),
+	DIV(DOUT_ACLK_ATLAS, "dout_aclk_atlas", "dout_atlas2",
+		DIV_ATLAS0, 8, 3),
+	DIV(DOUT_ATLAS2, "dout_atlas2", "dout_atlas1",
+		DIV_ATLAS0, 4, 3),
+	DIV(DOUT_ATLAS1, "dout_atlas1", "mout_atlas",
+		DIV_ATLAS0, 0, 3),
+
+	DIV(DOUT_CNTCLK_ATLAS, "dout_cntclk_atlas", "dout_atlas2",
+		DIV_ATLAS1, 8, 4),
+	DIV(DOUT_SCLK_HPM_ATLAS, "dout_sclk_hpm_atlas", "mout_atlas",
+		DIV_ATLAS1, 4, 3),
+	DIV(DOUT_ATLAS_PLL, "dout_atlas_pll", "mout_atlas",
+		DIV_ATLAS1, 0, 3),
+};
+
+static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
+	GATE(CLK_ATLAS, "atlas", "dout_sclk_atlas_pll",
+		ENABLE_IP_ATLAS0, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_pll_clock atlas_pll_clks[] __initdata = {
+	PLL(pll_1450x, FOUT_ATLAS_PLL, "fout_atlas_pll", "fin_pll",
+		ATLAS_PLL_LOCK, ATLAS_PLL_CON0,
+		pll1450x_24mhz_tbl),
+};
+
+static struct samsung_cmu_info atlas_cmu_info __initdata = {
+	.pll_clks		= atlas_pll_clks,
+	.nr_pll_clks		= ARRAY_SIZE(atlas_pll_clks),
+	.mux_clks		= atlas_mux_clks,
+	.nr_mux_clks		= ARRAY_SIZE(atlas_mux_clks),
+	.div_clks		= atlas_div_clks,
+	.nr_div_clks		= ARRAY_SIZE(atlas_div_clks),
+	.gate_clks		= atlas_gate_clks,
+	.nr_gate_clks		= ARRAY_SIZE(atlas_gate_clks),
+	.nr_clk_ids		= ATLAS_NR_CLK,
+	.clk_regs		= atlas_clk_regs,
+	.nr_clk_regs		= ARRAY_SIZE(atlas_clk_regs),
+};
+
+static void __init exynos7_clk_atlas_init(struct device_node *np)
+{
+	samsung_cmu_register_one(np, &atlas_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos7_clk_atlas, "samsung,exynos7-clock-atlas",
+		exynos7_clk_atlas_init);
 /* Register Offset definitions for CMU_CCORE (0x105B0000) */
 #define MUX_SEL_CCORE			0x0200
 #define DIV_CCORE			0x0600
diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h
index e0bad38..93c78f9 100644
--- a/include/dt-bindings/clock/exynos7-clk.h
+++ b/include/dt-bindings/clock/exynos7-clk.h
@@ -17,7 +17,8 @@
 #define DOUT_SCLK_CC_PLL		4
 #define DOUT_SCLK_MFC_PLL		5
 #define DOUT_ACLK_CCORE_133		6
-#define TOPC_NR_CLK			7
+#define MOUT_SCLK_BUS0_PLL_ATLAS	7
+#define TOPC_NR_CLK			8
 
 /* TOP0 */
 #define DOUT_ACLK_PERIC1		1
@@ -39,6 +40,23 @@
 #define CLK_SCLK_MMC0			8
 #define TOP1_NR_CLK			9
 
+/* ATLAS */
+#define FOUT_ATLAS_PLL			1
+#define MOUT_ATLAS_PLL_CTRL		2
+#define MOUT_BUS_PLL_ATLAS		3
+#define MOUT_ATLAS			4
+#define DOUT_PCLK_DBG_CLK_ATLAS		5
+#define DOUT_ATCLK_ATLAS		6
+#define DOUT_PCLK_ATLAS			7
+#define DOUT_ACLK_ATLAS			8
+#define DOUT_ATLAS2			9
+#define DOUT_ATLAS1			10
+#define DOUT_CNTCLK_ATLAS		11
+#define CLK_ATLAS			12
+#define DOUT_SCLK_HPM_ATLAS		13
+#define DOUT_ATLAS_PLL			14
+#define ATLAS_NR_CLK			15
+
 /* CCORE */
 #define PCLK_RTC			1
 #define CCORE_NR_CLK			2
-- 
1.7.9.5

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

* [PATCH 1/4] clk: samsung: exynos7: add clocks for CPU block
@ 2014-11-26 11:17   ` Abhilash Kesavan
  0 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

Add clock support for the Atlas CPU block in Exynos7.

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 .../devicetree/bindings/clock/exynos7-clock.txt    |    6 +
 drivers/clk/samsung/clk-exynos7.c                  |  121 ++++++++++++++++++++
 include/dt-bindings/clock/exynos7-clk.h            |   20 +++-
 3 files changed, 146 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/exynos7-clock.txt b/Documentation/devicetree/bindings/clock/exynos7-clock.txt
index 6d3d5f8..0b4ba7f 100644
--- a/Documentation/devicetree/bindings/clock/exynos7-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos7-clock.txt
@@ -28,6 +28,7 @@ Required Properties for Clock Controller:
 	- "samsung,exynos7-clock-topc"
 	- "samsung,exynos7-clock-top0"
 	- "samsung,exynos7-clock-top1"
+	- "samsung,exynos7-clock-atlas"
 	- "samsung,exynos7-clock-ccore"
 	- "samsung,exynos7-clock-peric0"
 	- "samsung,exynos7-clock-peric1"
@@ -61,6 +62,11 @@ Input clocks for top1 clock controller:
 	- dout_sclk_cc_pll
 	- dout_sclk_mfc_pll
 
+Input clocks for atlas clock controller:
+	- fin_pll
+	- fout_atlas_pll
+	- mout_sclk_bus0_pll_atlas
+
 Input clocks for ccore clock controller:
 	- fin_pll
 	- dout_aclk_ccore_133
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index a79bf23..78f66b4 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -35,6 +35,34 @@
 #define DIV_TOPC1		0x0604
 #define DIV_TOPC3		0x060C
 
+static const struct samsung_pll_rate_table pll1450x_24mhz_tbl[] = {
+	/* rate, m, p, s */
+	PLL_35XX_RATE(2496000000, 208, 2, 0),
+	PLL_35XX_RATE(2400000000, 200, 2, 0),
+	PLL_35XX_RATE(2304000000, 288, 3, 0),
+	PLL_35XX_RATE(2200000000, 275, 3, 0),
+	PLL_35XX_RATE(2100000000, 175, 2, 0),
+	PLL_35XX_RATE(2000000000, 250, 3, 0),
+	PLL_35XX_RATE(1896000000, 158, 2, 0),
+	PLL_35XX_RATE(1800000000, 150, 2, 0),
+	PLL_35XX_RATE(1704000000, 142, 2, 0),
+	PLL_35XX_RATE(1600000000, 200, 3, 0),
+	PLL_35XX_RATE(1500000000, 250, 2, 1),
+	PLL_35XX_RATE(1400000000, 350, 3, 1),
+	PLL_35XX_RATE(1300000000, 325, 3, 1),
+	PLL_35XX_RATE(1200000000, 200, 2, 1),
+	PLL_35XX_RATE(1100000000, 275, 3, 1),
+	PLL_35XX_RATE(1000000000, 250, 3, 1),
+	PLL_35XX_RATE(900000000, 150, 2, 1),
+	PLL_35XX_RATE(800000000, 200, 3, 1),
+	PLL_35XX_RATE(700000000, 350, 3, 2),
+	PLL_35XX_RATE(600000000, 200, 2, 2),
+	PLL_35XX_RATE(500000000, 250, 3, 2),
+	PLL_35XX_RATE(400000000, 200, 3, 2),
+	PLL_35XX_RATE(300000000, 200, 2, 3),
+	PLL_35XX_RATE(200000000, 200, 3, 3),
+};
+
 static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
 	FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_bus0_pll_ctrl", 1, 2, 0),
 	FFACTOR(0, "ffac_topc_bus0_pll_div4",
@@ -50,6 +78,8 @@ PNAME(mout_bus1_pll_ctrl_p)	= { "fin_pll", "fout_bus1_pll" };
 PNAME(mout_cc_pll_ctrl_p)	= { "fin_pll", "fout_cc_pll" };
 PNAME(mout_mfc_pll_ctrl_p)	= { "fin_pll", "fout_mfc_pll" };
 
+PNAME(mout_topc_group1)	= { "mout_bus0_pll_ctrl", "ffac_topc_bus0_pll_div2",
+	 "mout_bus1_pll_ctrl", "mout_cci_pll" };
 PNAME(mout_topc_group2) = { "mout_sclk_bus0_pll_cmuc",
 	"mout_sclk_bus1_pll_cmuc", "mout_sclk_cc_pll_cmuc",
 	"mout_sclk_mfc_pll_cmuc" };
@@ -104,6 +134,8 @@ static struct samsung_mux_clock topc_mux_clks[] __initdata = {
 
 	MUX(0, "mout_sclk_bus0_pll_out", mout_sclk_bus0_pll_out_p,
 		MUX_SEL_TOPC1, 16, 1),
+	MUX(MOUT_SCLK_BUS0_PLL_ATLAS, "mout_sclk_bus0_pll_atlas",
+		mout_topc_group1, MUX_SEL_TOPC1, 4, 2),
 
 	MUX(0, "mout_aclk_ccore_133", mout_topc_group2,	MUX_SEL_TOPC2, 4, 2),
 
@@ -402,6 +434,95 @@ static void __init exynos7_clk_top1_init(struct device_node *np)
 CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1",
 	exynos7_clk_top1_init);
 
+/* Register Offset definitions for CMU_ATLAS (0x11800000) */
+#define	ATLAS_PLL_LOCK			0x0000
+#define	ATLAS_PLL_CON0			0x0100
+#define	MUX_SEL_ATLAS0			0x0200
+#define	MUX_SEL_ATLAS1			0x0204
+#define	MUX_SEL_ATLAS2			0x0208
+#define	DIV_ATLAS0			0x0600
+#define	DIV_ATLAS1			0x0604
+#define	ENABLE_IP_ATLAS0		0x0B00
+
+/* List of parent clocks for Muxes in CMU_ATLAS */
+PNAME(mout_atlas_pll_ctrl_p) = { "fin_pll", "fout_atlas_pll" };
+PNAME(mout_bus_pll_atlas_p) = { "fin_pll", "mout_sclk_bus0_pll_atlas" };
+PNAME(mout_atlas_p) = { "mout_atlas_pll_ctrl", "mout_bus_pll_atlas" };
+
+static unsigned long atlas_clk_regs[] __initdata = {
+	ATLAS_PLL_LOCK,
+	ATLAS_PLL_CON0,
+	MUX_SEL_ATLAS0,
+	MUX_SEL_ATLAS1,
+	MUX_SEL_ATLAS2,
+	DIV_ATLAS0,
+	DIV_ATLAS1,
+	ENABLE_IP_ATLAS0,
+};
+
+static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
+	MUX_F(MOUT_ATLAS_PLL_CTRL, "mout_atlas_pll_ctrl", mout_atlas_pll_ctrl_p,
+		MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0),
+	MUX_F(MOUT_BUS_PLL_ATLAS, "mout_bus_pll_atlas", mout_bus_pll_atlas_p,
+		MUX_SEL_ATLAS1, 0, 1, CLK_SET_RATE_PARENT, 0),
+	MUX_F(MOUT_ATLAS, "mout_atlas", mout_atlas_p,
+		MUX_SEL_ATLAS2, 0, 1, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct samsung_div_clock atlas_div_clks[] __initdata = {
+	DIV(DOUT_PCLK_DBG_CLK_ATLAS, "dout_pclk_dbg_clk_atlas", "dout_atlas2",
+		DIV_ATLAS0, 26, 6),
+	DIV(DOUT_ATCLK_ATLAS, "dout_atclk_atlas", "dout_atlas2",
+		DIV_ATLAS0, 20, 6),
+	DIV(DOUT_PCLK_ATLAS, "dout_pclk_atlas", "dout_atlas2",
+		DIV_ATLAS0, 12, 6),
+	DIV(DOUT_ACLK_ATLAS, "dout_aclk_atlas", "dout_atlas2",
+		DIV_ATLAS0, 8, 3),
+	DIV(DOUT_ATLAS2, "dout_atlas2", "dout_atlas1",
+		DIV_ATLAS0, 4, 3),
+	DIV(DOUT_ATLAS1, "dout_atlas1", "mout_atlas",
+		DIV_ATLAS0, 0, 3),
+
+	DIV(DOUT_CNTCLK_ATLAS, "dout_cntclk_atlas", "dout_atlas2",
+		DIV_ATLAS1, 8, 4),
+	DIV(DOUT_SCLK_HPM_ATLAS, "dout_sclk_hpm_atlas", "mout_atlas",
+		DIV_ATLAS1, 4, 3),
+	DIV(DOUT_ATLAS_PLL, "dout_atlas_pll", "mout_atlas",
+		DIV_ATLAS1, 0, 3),
+};
+
+static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
+	GATE(CLK_ATLAS, "atlas", "dout_sclk_atlas_pll",
+		ENABLE_IP_ATLAS0, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+static struct samsung_pll_clock atlas_pll_clks[] __initdata = {
+	PLL(pll_1450x, FOUT_ATLAS_PLL, "fout_atlas_pll", "fin_pll",
+		ATLAS_PLL_LOCK, ATLAS_PLL_CON0,
+		pll1450x_24mhz_tbl),
+};
+
+static struct samsung_cmu_info atlas_cmu_info __initdata = {
+	.pll_clks		= atlas_pll_clks,
+	.nr_pll_clks		= ARRAY_SIZE(atlas_pll_clks),
+	.mux_clks		= atlas_mux_clks,
+	.nr_mux_clks		= ARRAY_SIZE(atlas_mux_clks),
+	.div_clks		= atlas_div_clks,
+	.nr_div_clks		= ARRAY_SIZE(atlas_div_clks),
+	.gate_clks		= atlas_gate_clks,
+	.nr_gate_clks		= ARRAY_SIZE(atlas_gate_clks),
+	.nr_clk_ids		= ATLAS_NR_CLK,
+	.clk_regs		= atlas_clk_regs,
+	.nr_clk_regs		= ARRAY_SIZE(atlas_clk_regs),
+};
+
+static void __init exynos7_clk_atlas_init(struct device_node *np)
+{
+	samsung_cmu_register_one(np, &atlas_cmu_info);
+}
+
+CLK_OF_DECLARE(exynos7_clk_atlas, "samsung,exynos7-clock-atlas",
+		exynos7_clk_atlas_init);
 /* Register Offset definitions for CMU_CCORE (0x105B0000) */
 #define MUX_SEL_CCORE			0x0200
 #define DIV_CCORE			0x0600
diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h
index e0bad38..93c78f9 100644
--- a/include/dt-bindings/clock/exynos7-clk.h
+++ b/include/dt-bindings/clock/exynos7-clk.h
@@ -17,7 +17,8 @@
 #define DOUT_SCLK_CC_PLL		4
 #define DOUT_SCLK_MFC_PLL		5
 #define DOUT_ACLK_CCORE_133		6
-#define TOPC_NR_CLK			7
+#define MOUT_SCLK_BUS0_PLL_ATLAS	7
+#define TOPC_NR_CLK			8
 
 /* TOP0 */
 #define DOUT_ACLK_PERIC1		1
@@ -39,6 +40,23 @@
 #define CLK_SCLK_MMC0			8
 #define TOP1_NR_CLK			9
 
+/* ATLAS */
+#define FOUT_ATLAS_PLL			1
+#define MOUT_ATLAS_PLL_CTRL		2
+#define MOUT_BUS_PLL_ATLAS		3
+#define MOUT_ATLAS			4
+#define DOUT_PCLK_DBG_CLK_ATLAS		5
+#define DOUT_ATCLK_ATLAS		6
+#define DOUT_PCLK_ATLAS			7
+#define DOUT_ACLK_ATLAS			8
+#define DOUT_ATLAS2			9
+#define DOUT_ATLAS1			10
+#define DOUT_CNTCLK_ATLAS		11
+#define CLK_ATLAS			12
+#define DOUT_SCLK_HPM_ATLAS		13
+#define DOUT_ATLAS_PLL			14
+#define ATLAS_NR_CLK			15
+
 /* CCORE */
 #define PCLK_RTC			1
 #define CCORE_NR_CLK			2
-- 
1.7.9.5

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

* [PATCH 2/4] clk: samsung: retrieve the clock provider information from samsung_cmu_register_one
  2014-11-26 11:17 ` Abhilash Kesavan
@ 2014-11-26 11:17   ` Abhilash Kesavan
  -1 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel, tomasz.figa, s.nawrocki, mturquette
  Cc: linux-samsung-soc, kesavan.abhilash

In case of SoCs with multiple CMUs like Exynos7 and Exynos5260 we are
making use of a common samsung_cmu_register_one function for pll, div,
mux registration. To register the cpu domain clock (for cpufreq) we need
a reference to this clock provider information in the cpu cmu block. Make
this information accessible by returning it from samsung_cmu_register_one().

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/clk/samsung/clk.c |    6 ++++--
 drivers/clk/samsung/clk.h |    4 ++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index dd1f7c9..4a653fe 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -374,8 +374,8 @@ static void samsung_clk_sleep_init(void __iomem *reg_base,
  * Common function which registers plls, muxes, dividers and gates
  * for each CMU. It also add CMU register list to register cache.
  */
-void __init samsung_cmu_register_one(struct device_node *np,
-			struct samsung_cmu_info *cmu)
+struct samsung_clk_provider * __init samsung_cmu_register_one(
+		struct device_node *np, struct samsung_cmu_info *cmu)
 {
 	void __iomem *reg_base;
 	struct samsung_clk_provider *ctx;
@@ -410,4 +410,6 @@ void __init samsung_cmu_register_one(struct device_node *np,
 			cmu->nr_clk_regs);
 
 	samsung_clk_of_add_provider(np, ctx);
+
+	return ctx;
 }
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 3f471e9..24ae23c 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -396,8 +396,8 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
 			struct samsung_pll_clock *pll_list,
 			unsigned int nr_clk, void __iomem *base);
 
-extern void __init samsung_cmu_register_one(struct device_node *,
-			struct samsung_cmu_info *);
+extern struct samsung_clk_provider * __init
+samsung_cmu_register_one(struct device_node *, struct samsung_cmu_info *);
 
 extern unsigned long _get_rate(const char *clk_name);
 
-- 
1.7.9.5

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

* [PATCH 2/4] clk: samsung: retrieve the clock provider information from samsung_cmu_register_one
@ 2014-11-26 11:17   ` Abhilash Kesavan
  0 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

In case of SoCs with multiple CMUs like Exynos7 and Exynos5260 we are
making use of a common samsung_cmu_register_one function for pll, div,
mux registration. To register the cpu domain clock (for cpufreq) we need
a reference to this clock provider information in the cpu cmu block. Make
this information accessible by returning it from samsung_cmu_register_one().

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/clk/samsung/clk.c |    6 ++++--
 drivers/clk/samsung/clk.h |    4 ++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index dd1f7c9..4a653fe 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -374,8 +374,8 @@ static void samsung_clk_sleep_init(void __iomem *reg_base,
  * Common function which registers plls, muxes, dividers and gates
  * for each CMU. It also add CMU register list to register cache.
  */
-void __init samsung_cmu_register_one(struct device_node *np,
-			struct samsung_cmu_info *cmu)
+struct samsung_clk_provider * __init samsung_cmu_register_one(
+		struct device_node *np, struct samsung_cmu_info *cmu)
 {
 	void __iomem *reg_base;
 	struct samsung_clk_provider *ctx;
@@ -410,4 +410,6 @@ void __init samsung_cmu_register_one(struct device_node *np,
 			cmu->nr_clk_regs);
 
 	samsung_clk_of_add_provider(np, ctx);
+
+	return ctx;
 }
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 3f471e9..24ae23c 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -396,8 +396,8 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
 			struct samsung_pll_clock *pll_list,
 			unsigned int nr_clk, void __iomem *base);
 
-extern void __init samsung_cmu_register_one(struct device_node *,
-			struct samsung_cmu_info *);
+extern struct samsung_clk_provider * __init
+samsung_cmu_register_one(struct device_node *, struct samsung_cmu_info *);
 
 extern unsigned long _get_rate(const char *clk_name);
 
-- 
1.7.9.5

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

* [PATCH 3/4] clk: samsung: add cpu clock support for Exynos7
  2014-11-26 11:17 ` Abhilash Kesavan
@ 2014-11-26 11:17   ` Abhilash Kesavan
  -1 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel, tomasz.figa, s.nawrocki, mturquette
  Cc: linux-samsung-soc, kesavan.abhilash

The divider and mux register offsets and bits are different on
Exynos7 from the older SoCs. Add new pre/post rate change callbacks
for Exynos7 to handle these differences. To do this:
	- Add a new exynos_cpuclk_soc_data structure that will hold
	the SoC-specific pre/post rate change call-backs
	- Modify exynos_register_cpu_clock() prototype to include a
	node pointer

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/clk/samsung/clk-cpu.c        |  130 +++++++++++++++++++++++++++++++++-
 drivers/clk/samsung/clk-cpu.h        |   33 ++++++++-
 drivers/clk/samsung/clk-exynos4.c    |    2 +-
 drivers/clk/samsung/clk-exynos5250.c |    2 +-
 drivers/clk/samsung/clk-exynos5420.c |    4 +-
 5 files changed, 163 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
index 009a21b..6c00802 100644
--- a/drivers/clk/samsung/clk-cpu.c
+++ b/drivers/clk/samsung/clk-cpu.c
@@ -51,6 +51,13 @@
 #define DIV_MASK_ALL		0xffffffff
 #define MUX_MASK		7
 
+#define EXYNOS7_SRC_CPU		0x208
+#define EXYNOS7_STAT_CPU	0x408
+#define EXYNOS7_DIV_CPU0	0x600
+#define EXYNOS7_DIV_CPU1	0x604
+#define EXYNOS7_DIV_STAT_CPU0	0x700
+#define EXYNOS7_DIV_STAT_CPU1	0x704
+
 /*
  * Helper function to wait until divider(s) have stabilized after the divider
  * value has changed.
@@ -128,6 +135,88 @@ static void exynos_set_safe_div(void __iomem *base, unsigned long div,
 	wait_until_divider_stable(base + E4210_DIV_STAT_CPU0, mask);
 }
 
+static void exynos7_set_safe_div(void __iomem *base, unsigned long div,
+					unsigned long mask)
+{
+	unsigned long div0;
+
+	div0 = readl(base + EXYNOS7_DIV_CPU0);
+	div0 = (div0 & ~mask) | (div & mask);
+	writel(div0, base + EXYNOS7_DIV_CPU0);
+	wait_until_divider_stable(base + EXYNOS7_DIV_STAT_CPU0, mask);
+}
+
+/* Exynos7 handler for pre-rate change notification from parent clock */
+static int exynos7_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
+			struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+	const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
+	unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent);
+	unsigned long alt_div = 0, alt_div_mask = DIV_MASK;
+	unsigned long div0, div1 = 0, mux_reg;
+
+	/* find out the divider values to use for clock data */
+	while ((cfg_data->prate * 1000) != ndata->new_rate) {
+		if (cfg_data->prate == 0)
+			return -EINVAL;
+		cfg_data++;
+	}
+
+	spin_lock(cpuclk->lock);
+
+	/*
+	 * If the new and old parent clock speed is less than the clock speed
+	 * of the alternate parent, then it should be ensured that at no point
+	 * the armclk speed is more than the old_prate until the dividers are
+	 * set.
+	 */
+	div0 = cfg_data->div0;
+	if (alt_prate > ndata->old_rate) {
+		alt_div =  DIV_ROUND_UP(alt_prate, ndata->old_rate) - 1;
+		WARN_ON(alt_div >= MAX_DIV);
+
+		exynos7_set_safe_div(base, alt_div, alt_div_mask);
+		div0 |= alt_div;
+	}
+
+	/* select mout_bus0_pll_atlas as the alternate parent */
+	mux_reg = readl(base + EXYNOS7_SRC_CPU);
+	writel(mux_reg | (1 << 0), base + EXYNOS7_SRC_CPU);
+	wait_until_mux_stable(base + EXYNOS7_STAT_CPU, 0, 1);
+
+	/* alternate parent is active now. set the dividers */
+	writel(div0, base + EXYNOS7_DIV_CPU0);
+	wait_until_divider_stable(base + EXYNOS7_DIV_STAT_CPU0, DIV_MASK_ALL);
+
+	if (test_bit(CLK_CPU_HAS_DIV1, &cpuclk->flags)) {
+		writel(div1, base + EXYNOS7_DIV_CPU1);
+		wait_until_divider_stable(base + EXYNOS7_DIV_STAT_CPU1,
+				DIV_MASK_ALL);
+	}
+
+	spin_unlock(cpuclk->lock);
+	return 0;
+}
+
+/* Exynos7 handler for post-rate change notification from parent clock */
+static int exynos7_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
+			struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+	unsigned long div = 0, div_mask = DIV_MASK;
+	unsigned long mux_reg;
+
+	spin_lock(cpuclk->lock);
+
+	/* select mout_atlas_pll as the alternate parent */
+	mux_reg = readl(base + EXYNOS7_SRC_CPU);
+	writel(mux_reg & ~(1 << 0), base + EXYNOS7_SRC_CPU);
+	wait_until_mux_stable(base + EXYNOS7_STAT_CPU, 0, 0);
+
+	exynos7_set_safe_div(base, div, div_mask);
+	spin_unlock(cpuclk->lock);
+	return 0;
+}
+
 /* handler for pre-rate change notification from parent clock */
 static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
 			struct exynos_cpuclk *cpuclk, void __iomem *base)
@@ -248,25 +337,58 @@ static int exynos_cpuclk_notifier_cb(struct notifier_block *nb,
 	base = cpuclk->ctrl_base;
 
 	if (event == PRE_RATE_CHANGE)
-		err = exynos_cpuclk_pre_rate_change(ndata, cpuclk, base);
+		err = cpuclk->pre_rate_cb(ndata, cpuclk, base);
 	else if (event == POST_RATE_CHANGE)
-		err = exynos_cpuclk_post_rate_change(ndata, cpuclk, base);
+		err = cpuclk->post_rate_cb(ndata, cpuclk, base);
 
 	return notifier_from_errno(err);
 }
 
+static const struct exynos_cpuclk_soc_data e4210_clk_soc_data __initconst = {
+	.pre_rate_cb = exynos_cpuclk_pre_rate_change,
+	.post_rate_cb = exynos_cpuclk_post_rate_change,
+};
+
+static const struct exynos_cpuclk_soc_data e7_clk_soc_data __initconst = {
+	.pre_rate_cb = exynos7_cpuclk_pre_rate_change,
+	.post_rate_cb = exynos7_cpuclk_post_rate_change,
+};
+
+static const struct of_device_id exynos_cpuclk_ids[] __initconst = {
+	{ .compatible = "samsung,exynos4210-clock",
+			.data = &e4210_clk_soc_data, },
+	{ .compatible = "samsung,exynos5250-clock",
+			.data = &e4210_clk_soc_data, },
+	{ .compatible = "samsung,exynos5420-clock",
+			.data = &e4210_clk_soc_data, },
+	{ .compatible = "samsung,exynos7-clock-atlas",
+			.data = &e7_clk_soc_data, },
+	{ },
+};
+
 /* helper function to register a CPU clock */
 int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 		unsigned int lookup_id, const char *name, const char *parent,
 		const char *alt_parent, unsigned long offset,
 		const struct exynos_cpuclk_cfg_data *cfg,
-		unsigned long num_cfgs, unsigned long flags)
+		unsigned long num_cfgs, unsigned long flags,
+		struct device_node *np)
 {
+	const struct of_device_id *match;
+	const struct exynos_cpuclk_soc_data *data = NULL;
 	struct exynos_cpuclk *cpuclk;
 	struct clk_init_data init;
 	struct clk *clk;
 	int ret = 0;
 
+	if (!np)
+		return -EINVAL;
+
+	match = of_match_node(exynos_cpuclk_ids, np);
+	if (!match)
+		return -EINVAL;
+	data = match->data;
+
 	cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
 	if (!cpuclk)
 		return -ENOMEM;
@@ -281,6 +403,8 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 	cpuclk->ctrl_base = ctx->reg_base + offset;
 	cpuclk->lock = &ctx->lock;
 	cpuclk->flags = flags;
+	cpuclk->pre_rate_cb = data->pre_rate_cb;
+	cpuclk->post_rate_cb = data->post_rate_cb;
 	cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb;
 
 	cpuclk->alt_parent = __clk_lookup(alt_parent);
diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h
index 42e1905..24e844e 100644
--- a/drivers/clk/samsung/clk-cpu.h
+++ b/drivers/clk/samsung/clk-cpu.h
@@ -60,6 +60,10 @@ struct exynos_cpuclk_cfg_data {
  * @num_cfgs: number of array elements in @cfg array.
  * @clk_nb: clock notifier registered for changes in clock speed of the
  *	primary parent clock.
+ * @pre_rate_cb: callback function to handle PRE_RATE_CHANGE notification
+ *	of the primary parent clock.
+ * @post_rate_cb: callback function to handle POST_RATE_CHANGE notification
+ *	of the primary parent clock.
  * @flags: configuration flags for the CPU clock.
  *
  * This structure holds information required for programming the CPU clock for
@@ -73,6 +77,12 @@ struct exynos_cpuclk {
 	const struct exynos_cpuclk_cfg_data	*cfg;
 	const unsigned long			num_cfgs;
 	struct notifier_block			clk_nb;
+	int			(*pre_rate_cb)(struct clk_notifier_data *,
+					struct exynos_cpuclk *,
+					void __iomem *base);
+	int			(*post_rate_cb)(struct clk_notifier_data *,
+					struct exynos_cpuclk *,
+					void __iomem *base);
 	unsigned long				flags;
 
 /* The CPU clock registers has DIV1 configuration register */
@@ -81,11 +91,32 @@ struct exynos_cpuclk {
 #define CLK_CPU_NEEDS_DEBUG_ALT_DIV	(1 << 1)
 };
 
+/**
+ * struct exynos_cpuclk_soc_data: soc specific data for cpu clocks.
+ * @pre_rate_cb: callback function to handle PRE_RATE_CHANGE notification
+ *	of the primary parent clock.
+ * @post_rate_cb: callback function to handle POST_RATE_CHANGE notification
+ *	of the primary parent clock.
+ *
+ * This structure provides SoC specific data for CPU clocks. Based on
+ * the compatible value of the clock controller node, the value of the
+ * fields in this structure can be populated.
+ */
+struct exynos_cpuclk_soc_data {
+	int			(*pre_rate_cb)(struct clk_notifier_data *,
+					struct exynos_cpuclk *,
+					void __iomem *base);
+	int			(*post_rate_cb)(struct clk_notifier_data *,
+					struct exynos_cpuclk *,
+					void __iomem *base);
+};
+
 extern int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 			unsigned int lookup_id, const char *name,
 			const char *parent, const char *alt_parent,
 			unsigned long offset,
 			const struct exynos_cpuclk_cfg_data *cfg,
-			unsigned long num_cfgs, unsigned long flags);
+			unsigned long num_cfgs, unsigned long flags,
+			struct device_node *np);
 
 #endif /* __SAMSUNG_CLK_CPU_H */
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 3731fc7..a057a24 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1473,7 +1473,7 @@ static void __init exynos4_clk_init(struct device_node *np,
 		exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
 			mout_core_p4210[0], mout_core_p4210[1], 0x14200,
 			e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d),
-			CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
+			CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, np);
 	} else {
 		samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
 			ARRAY_SIZE(exynos4x12_mux_clks));
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 1d958f1..56b4147b 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -824,7 +824,7 @@ static void __init exynos5250_clk_init(struct device_node *np)
 	exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
 			mout_cpu_p[0], mout_cpu_p[1], 0x200,
 			exynos5250_armclk_d, ARRAY_SIZE(exynos5250_armclk_d),
-			CLK_CPU_HAS_DIV1);
+			CLK_CPU_HAS_DIV1, np);
 
 	/*
 	 * Enable arm clock down (in idle) and set arm divider
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index fcf365d..a8c668d 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -1358,10 +1358,10 @@ static void __init exynos5x_clk_init(struct device_node *np,
 
 	exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
 		mout_cpu_p[0], mout_cpu_p[1], 0x200,
-		exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
+		exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0, np);
 	exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk",
 		mout_kfc_p[0], mout_kfc_p[1], 0x28200,
-		exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
+		exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0, np);
 
 	exynos5420_clk_sleep_init();
 
-- 
1.7.9.5

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

* [PATCH 3/4] clk: samsung: add cpu clock support for Exynos7
@ 2014-11-26 11:17   ` Abhilash Kesavan
  0 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

The divider and mux register offsets and bits are different on
Exynos7 from the older SoCs. Add new pre/post rate change callbacks
for Exynos7 to handle these differences. To do this:
	- Add a new exynos_cpuclk_soc_data structure that will hold
	the SoC-specific pre/post rate change call-backs
	- Modify exynos_register_cpu_clock() prototype to include a
	node pointer

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/clk/samsung/clk-cpu.c        |  130 +++++++++++++++++++++++++++++++++-
 drivers/clk/samsung/clk-cpu.h        |   33 ++++++++-
 drivers/clk/samsung/clk-exynos4.c    |    2 +-
 drivers/clk/samsung/clk-exynos5250.c |    2 +-
 drivers/clk/samsung/clk-exynos5420.c |    4 +-
 5 files changed, 163 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
index 009a21b..6c00802 100644
--- a/drivers/clk/samsung/clk-cpu.c
+++ b/drivers/clk/samsung/clk-cpu.c
@@ -51,6 +51,13 @@
 #define DIV_MASK_ALL		0xffffffff
 #define MUX_MASK		7
 
+#define EXYNOS7_SRC_CPU		0x208
+#define EXYNOS7_STAT_CPU	0x408
+#define EXYNOS7_DIV_CPU0	0x600
+#define EXYNOS7_DIV_CPU1	0x604
+#define EXYNOS7_DIV_STAT_CPU0	0x700
+#define EXYNOS7_DIV_STAT_CPU1	0x704
+
 /*
  * Helper function to wait until divider(s) have stabilized after the divider
  * value has changed.
@@ -128,6 +135,88 @@ static void exynos_set_safe_div(void __iomem *base, unsigned long div,
 	wait_until_divider_stable(base + E4210_DIV_STAT_CPU0, mask);
 }
 
+static void exynos7_set_safe_div(void __iomem *base, unsigned long div,
+					unsigned long mask)
+{
+	unsigned long div0;
+
+	div0 = readl(base + EXYNOS7_DIV_CPU0);
+	div0 = (div0 & ~mask) | (div & mask);
+	writel(div0, base + EXYNOS7_DIV_CPU0);
+	wait_until_divider_stable(base + EXYNOS7_DIV_STAT_CPU0, mask);
+}
+
+/* Exynos7 handler for pre-rate change notification from parent clock */
+static int exynos7_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
+			struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+	const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
+	unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent);
+	unsigned long alt_div = 0, alt_div_mask = DIV_MASK;
+	unsigned long div0, div1 = 0, mux_reg;
+
+	/* find out the divider values to use for clock data */
+	while ((cfg_data->prate * 1000) != ndata->new_rate) {
+		if (cfg_data->prate == 0)
+			return -EINVAL;
+		cfg_data++;
+	}
+
+	spin_lock(cpuclk->lock);
+
+	/*
+	 * If the new and old parent clock speed is less than the clock speed
+	 * of the alternate parent, then it should be ensured that at no point
+	 * the armclk speed is more than the old_prate until the dividers are
+	 * set.
+	 */
+	div0 = cfg_data->div0;
+	if (alt_prate > ndata->old_rate) {
+		alt_div =  DIV_ROUND_UP(alt_prate, ndata->old_rate) - 1;
+		WARN_ON(alt_div >= MAX_DIV);
+
+		exynos7_set_safe_div(base, alt_div, alt_div_mask);
+		div0 |= alt_div;
+	}
+
+	/* select mout_bus0_pll_atlas as the alternate parent */
+	mux_reg = readl(base + EXYNOS7_SRC_CPU);
+	writel(mux_reg | (1 << 0), base + EXYNOS7_SRC_CPU);
+	wait_until_mux_stable(base + EXYNOS7_STAT_CPU, 0, 1);
+
+	/* alternate parent is active now. set the dividers */
+	writel(div0, base + EXYNOS7_DIV_CPU0);
+	wait_until_divider_stable(base + EXYNOS7_DIV_STAT_CPU0, DIV_MASK_ALL);
+
+	if (test_bit(CLK_CPU_HAS_DIV1, &cpuclk->flags)) {
+		writel(div1, base + EXYNOS7_DIV_CPU1);
+		wait_until_divider_stable(base + EXYNOS7_DIV_STAT_CPU1,
+				DIV_MASK_ALL);
+	}
+
+	spin_unlock(cpuclk->lock);
+	return 0;
+}
+
+/* Exynos7 handler for post-rate change notification from parent clock */
+static int exynos7_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
+			struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+	unsigned long div = 0, div_mask = DIV_MASK;
+	unsigned long mux_reg;
+
+	spin_lock(cpuclk->lock);
+
+	/* select mout_atlas_pll as the alternate parent */
+	mux_reg = readl(base + EXYNOS7_SRC_CPU);
+	writel(mux_reg & ~(1 << 0), base + EXYNOS7_SRC_CPU);
+	wait_until_mux_stable(base + EXYNOS7_STAT_CPU, 0, 0);
+
+	exynos7_set_safe_div(base, div, div_mask);
+	spin_unlock(cpuclk->lock);
+	return 0;
+}
+
 /* handler for pre-rate change notification from parent clock */
 static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
 			struct exynos_cpuclk *cpuclk, void __iomem *base)
@@ -248,25 +337,58 @@ static int exynos_cpuclk_notifier_cb(struct notifier_block *nb,
 	base = cpuclk->ctrl_base;
 
 	if (event == PRE_RATE_CHANGE)
-		err = exynos_cpuclk_pre_rate_change(ndata, cpuclk, base);
+		err = cpuclk->pre_rate_cb(ndata, cpuclk, base);
 	else if (event == POST_RATE_CHANGE)
-		err = exynos_cpuclk_post_rate_change(ndata, cpuclk, base);
+		err = cpuclk->post_rate_cb(ndata, cpuclk, base);
 
 	return notifier_from_errno(err);
 }
 
+static const struct exynos_cpuclk_soc_data e4210_clk_soc_data __initconst = {
+	.pre_rate_cb = exynos_cpuclk_pre_rate_change,
+	.post_rate_cb = exynos_cpuclk_post_rate_change,
+};
+
+static const struct exynos_cpuclk_soc_data e7_clk_soc_data __initconst = {
+	.pre_rate_cb = exynos7_cpuclk_pre_rate_change,
+	.post_rate_cb = exynos7_cpuclk_post_rate_change,
+};
+
+static const struct of_device_id exynos_cpuclk_ids[] __initconst = {
+	{ .compatible = "samsung,exynos4210-clock",
+			.data = &e4210_clk_soc_data, },
+	{ .compatible = "samsung,exynos5250-clock",
+			.data = &e4210_clk_soc_data, },
+	{ .compatible = "samsung,exynos5420-clock",
+			.data = &e4210_clk_soc_data, },
+	{ .compatible = "samsung,exynos7-clock-atlas",
+			.data = &e7_clk_soc_data, },
+	{ },
+};
+
 /* helper function to register a CPU clock */
 int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 		unsigned int lookup_id, const char *name, const char *parent,
 		const char *alt_parent, unsigned long offset,
 		const struct exynos_cpuclk_cfg_data *cfg,
-		unsigned long num_cfgs, unsigned long flags)
+		unsigned long num_cfgs, unsigned long flags,
+		struct device_node *np)
 {
+	const struct of_device_id *match;
+	const struct exynos_cpuclk_soc_data *data = NULL;
 	struct exynos_cpuclk *cpuclk;
 	struct clk_init_data init;
 	struct clk *clk;
 	int ret = 0;
 
+	if (!np)
+		return -EINVAL;
+
+	match = of_match_node(exynos_cpuclk_ids, np);
+	if (!match)
+		return -EINVAL;
+	data = match->data;
+
 	cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
 	if (!cpuclk)
 		return -ENOMEM;
@@ -281,6 +403,8 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 	cpuclk->ctrl_base = ctx->reg_base + offset;
 	cpuclk->lock = &ctx->lock;
 	cpuclk->flags = flags;
+	cpuclk->pre_rate_cb = data->pre_rate_cb;
+	cpuclk->post_rate_cb = data->post_rate_cb;
 	cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb;
 
 	cpuclk->alt_parent = __clk_lookup(alt_parent);
diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h
index 42e1905..24e844e 100644
--- a/drivers/clk/samsung/clk-cpu.h
+++ b/drivers/clk/samsung/clk-cpu.h
@@ -60,6 +60,10 @@ struct exynos_cpuclk_cfg_data {
  * @num_cfgs: number of array elements in @cfg array.
  * @clk_nb: clock notifier registered for changes in clock speed of the
  *	primary parent clock.
+ * @pre_rate_cb: callback function to handle PRE_RATE_CHANGE notification
+ *	of the primary parent clock.
+ * @post_rate_cb: callback function to handle POST_RATE_CHANGE notification
+ *	of the primary parent clock.
  * @flags: configuration flags for the CPU clock.
  *
  * This structure holds information required for programming the CPU clock for
@@ -73,6 +77,12 @@ struct exynos_cpuclk {
 	const struct exynos_cpuclk_cfg_data	*cfg;
 	const unsigned long			num_cfgs;
 	struct notifier_block			clk_nb;
+	int			(*pre_rate_cb)(struct clk_notifier_data *,
+					struct exynos_cpuclk *,
+					void __iomem *base);
+	int			(*post_rate_cb)(struct clk_notifier_data *,
+					struct exynos_cpuclk *,
+					void __iomem *base);
 	unsigned long				flags;
 
 /* The CPU clock registers has DIV1 configuration register */
@@ -81,11 +91,32 @@ struct exynos_cpuclk {
 #define CLK_CPU_NEEDS_DEBUG_ALT_DIV	(1 << 1)
 };
 
+/**
+ * struct exynos_cpuclk_soc_data: soc specific data for cpu clocks.
+ * @pre_rate_cb: callback function to handle PRE_RATE_CHANGE notification
+ *	of the primary parent clock.
+ * @post_rate_cb: callback function to handle POST_RATE_CHANGE notification
+ *	of the primary parent clock.
+ *
+ * This structure provides SoC specific data for CPU clocks. Based on
+ * the compatible value of the clock controller node, the value of the
+ * fields in this structure can be populated.
+ */
+struct exynos_cpuclk_soc_data {
+	int			(*pre_rate_cb)(struct clk_notifier_data *,
+					struct exynos_cpuclk *,
+					void __iomem *base);
+	int			(*post_rate_cb)(struct clk_notifier_data *,
+					struct exynos_cpuclk *,
+					void __iomem *base);
+};
+
 extern int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
 			unsigned int lookup_id, const char *name,
 			const char *parent, const char *alt_parent,
 			unsigned long offset,
 			const struct exynos_cpuclk_cfg_data *cfg,
-			unsigned long num_cfgs, unsigned long flags);
+			unsigned long num_cfgs, unsigned long flags,
+			struct device_node *np);
 
 #endif /* __SAMSUNG_CLK_CPU_H */
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 3731fc7..a057a24 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1473,7 +1473,7 @@ static void __init exynos4_clk_init(struct device_node *np,
 		exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
 			mout_core_p4210[0], mout_core_p4210[1], 0x14200,
 			e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d),
-			CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
+			CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1, np);
 	} else {
 		samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
 			ARRAY_SIZE(exynos4x12_mux_clks));
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 1d958f1..56b4147b 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -824,7 +824,7 @@ static void __init exynos5250_clk_init(struct device_node *np)
 	exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
 			mout_cpu_p[0], mout_cpu_p[1], 0x200,
 			exynos5250_armclk_d, ARRAY_SIZE(exynos5250_armclk_d),
-			CLK_CPU_HAS_DIV1);
+			CLK_CPU_HAS_DIV1, np);
 
 	/*
 	 * Enable arm clock down (in idle) and set arm divider
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index fcf365d..a8c668d 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -1358,10 +1358,10 @@ static void __init exynos5x_clk_init(struct device_node *np,
 
 	exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
 		mout_cpu_p[0], mout_cpu_p[1], 0x200,
-		exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
+		exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0, np);
 	exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk",
 		mout_kfc_p[0], mout_kfc_p[1], 0x28200,
-		exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
+		exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0, np);
 
 	exynos5420_clk_sleep_init();
 
-- 
1.7.9.5

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

* [PATCH 4/4] clk: samsung: add cpu clock configuration data and instantiate cpu clock
  2014-11-26 11:17 ` Abhilash Kesavan
@ 2014-11-26 11:17   ` Abhilash Kesavan
  -1 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel, tomasz.figa, s.nawrocki, mturquette
  Cc: linux-samsung-soc, kesavan.abhilash

Add the Atlas CPU clock configuration data and instantiate the CPU clock
type for Exynos7.

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/clk/samsung/clk-cpu.h           |    5 +++++
 drivers/clk/samsung/clk-exynos7.c       |   28 +++++++++++++++++++++++++++-
 include/dt-bindings/clock/exynos7-clk.h |    3 ++-
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h
index 24e844e..1fd7f51 100644
--- a/drivers/clk/samsung/clk-cpu.h
+++ b/drivers/clk/samsung/clk-cpu.h
@@ -31,6 +31,11 @@
 #define E5420_KFC_DIV(kpll, pclk, aclk)					\
 		((((kpll) << 24) | ((pclk) << 20) | ((aclk) << 4)))
 
+#define EXYNOS7_ATL_DIV0(aclk, pclk, atclk, pclk_dbg) \
+		((aclk << 8) | (pclk << 12) | (atclk << 20) | (pclk_dbg << 26))
+#define EXYNOS7_ATL_DIV1(pll, hpm, cntclk) \
+		((pll << 0) | (hpm << 4) | (cntclk << 8))
+
 /**
  * struct exynos_cpuclk_data: config data to setup cpu clocks.
  * @prate: frequency of the primary parent clock (in KHz).
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index 78f66b4..dc9b7fb 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -14,6 +14,7 @@
 #include <linux/of.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 #include <dt-bindings/clock/exynos7-clk.h>
 
 /* Register Offset definitions for CMU_TOPC (0x10570000) */
@@ -63,6 +64,25 @@ static const struct samsung_pll_rate_table pll1450x_24mhz_tbl[] = {
 	PLL_35XX_RATE(200000000, 200, 3, 3),
 };
 
+static const struct exynos_cpuclk_cfg_data exynos7_atlclk_d[] __initconst = {
+	{ 1600000, EXYNOS7_ATL_DIV0(2, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1500000, EXYNOS7_ATL_DIV0(2, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1400000, EXYNOS7_ATL_DIV0(2, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1300000, EXYNOS7_ATL_DIV0(2, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1200000, EXYNOS7_ATL_DIV0(1, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1100000, EXYNOS7_ATL_DIV0(1, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1000000, EXYNOS7_ATL_DIV0(1, 6, 6, 6), EXYNOS7_ATL_DIV1(1, 2, 6), },
+	{  900000, EXYNOS7_ATL_DIV0(1, 6, 6, 6), EXYNOS7_ATL_DIV1(1, 2, 6), },
+	{  800000, EXYNOS7_ATL_DIV0(1, 5, 5, 5), EXYNOS7_ATL_DIV1(1, 2, 5), },
+	{  700000, EXYNOS7_ATL_DIV0(1, 5, 5, 5), EXYNOS7_ATL_DIV1(1, 2, 5), },
+	{  600000, EXYNOS7_ATL_DIV0(1, 4, 4, 4), EXYNOS7_ATL_DIV1(1, 2, 4), },
+	{  500000, EXYNOS7_ATL_DIV0(1, 3, 3, 3), EXYNOS7_ATL_DIV1(1, 2, 3), },
+	{  400000, EXYNOS7_ATL_DIV0(1, 3, 3, 3), EXYNOS7_ATL_DIV1(1, 2, 3), },
+	{  300000, EXYNOS7_ATL_DIV0(1, 3, 3, 3), EXYNOS7_ATL_DIV1(1, 2, 3), },
+	{  200000, EXYNOS7_ATL_DIV0(1, 3, 3, 3), EXYNOS7_ATL_DIV1(1, 2, 3), },
+	{  0 },
+};
+
 static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
 	FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_bus0_pll_ctrl", 1, 2, 0),
 	FFACTOR(0, "ffac_topc_bus0_pll_div4",
@@ -518,7 +538,13 @@ static struct samsung_cmu_info atlas_cmu_info __initdata = {
 
 static void __init exynos7_clk_atlas_init(struct device_node *np)
 {
-	samsung_cmu_register_one(np, &atlas_cmu_info);
+	struct samsung_clk_provider *ctx;
+
+	ctx = samsung_cmu_register_one(np, &atlas_cmu_info);
+	exynos_register_cpu_clock(ctx, CLK_ATLAS_CLK, "atlclk",
+		mout_atlas_p[0], mout_atlas_p[1], 0x0,
+		exynos7_atlclk_d, ARRAY_SIZE(exynos7_atlclk_d),
+		CLK_CPU_HAS_DIV1, np);
 }
 
 CLK_OF_DECLARE(exynos7_clk_atlas, "samsung,exynos7-clock-atlas",
diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h
index 93c78f9..33bc166 100644
--- a/include/dt-bindings/clock/exynos7-clk.h
+++ b/include/dt-bindings/clock/exynos7-clk.h
@@ -55,7 +55,8 @@
 #define CLK_ATLAS			12
 #define DOUT_SCLK_HPM_ATLAS		13
 #define DOUT_ATLAS_PLL			14
-#define ATLAS_NR_CLK			15
+#define CLK_ATLAS_CLK			15
+#define ATLAS_NR_CLK			16
 
 /* CCORE */
 #define PCLK_RTC			1
-- 
1.7.9.5

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

* [PATCH 4/4] clk: samsung: add cpu clock configuration data and instantiate cpu clock
@ 2014-11-26 11:17   ` Abhilash Kesavan
  0 siblings, 0 replies; 10+ messages in thread
From: Abhilash Kesavan @ 2014-11-26 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

Add the Atlas CPU clock configuration data and instantiate the CPU clock
type for Exynos7.

Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
---
 drivers/clk/samsung/clk-cpu.h           |    5 +++++
 drivers/clk/samsung/clk-exynos7.c       |   28 +++++++++++++++++++++++++++-
 include/dt-bindings/clock/exynos7-clk.h |    3 ++-
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h
index 24e844e..1fd7f51 100644
--- a/drivers/clk/samsung/clk-cpu.h
+++ b/drivers/clk/samsung/clk-cpu.h
@@ -31,6 +31,11 @@
 #define E5420_KFC_DIV(kpll, pclk, aclk)					\
 		((((kpll) << 24) | ((pclk) << 20) | ((aclk) << 4)))
 
+#define EXYNOS7_ATL_DIV0(aclk, pclk, atclk, pclk_dbg) \
+		((aclk << 8) | (pclk << 12) | (atclk << 20) | (pclk_dbg << 26))
+#define EXYNOS7_ATL_DIV1(pll, hpm, cntclk) \
+		((pll << 0) | (hpm << 4) | (cntclk << 8))
+
 /**
  * struct exynos_cpuclk_data: config data to setup cpu clocks.
  * @prate: frequency of the primary parent clock (in KHz).
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index 78f66b4..dc9b7fb 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -14,6 +14,7 @@
 #include <linux/of.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 #include <dt-bindings/clock/exynos7-clk.h>
 
 /* Register Offset definitions for CMU_TOPC (0x10570000) */
@@ -63,6 +64,25 @@ static const struct samsung_pll_rate_table pll1450x_24mhz_tbl[] = {
 	PLL_35XX_RATE(200000000, 200, 3, 3),
 };
 
+static const struct exynos_cpuclk_cfg_data exynos7_atlclk_d[] __initconst = {
+	{ 1600000, EXYNOS7_ATL_DIV0(2, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1500000, EXYNOS7_ATL_DIV0(2, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1400000, EXYNOS7_ATL_DIV0(2, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1300000, EXYNOS7_ATL_DIV0(2, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1200000, EXYNOS7_ATL_DIV0(1, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1100000, EXYNOS7_ATL_DIV0(1, 7, 7, 7), EXYNOS7_ATL_DIV1(1, 2, 7), },
+	{ 1000000, EXYNOS7_ATL_DIV0(1, 6, 6, 6), EXYNOS7_ATL_DIV1(1, 2, 6), },
+	{  900000, EXYNOS7_ATL_DIV0(1, 6, 6, 6), EXYNOS7_ATL_DIV1(1, 2, 6), },
+	{  800000, EXYNOS7_ATL_DIV0(1, 5, 5, 5), EXYNOS7_ATL_DIV1(1, 2, 5), },
+	{  700000, EXYNOS7_ATL_DIV0(1, 5, 5, 5), EXYNOS7_ATL_DIV1(1, 2, 5), },
+	{  600000, EXYNOS7_ATL_DIV0(1, 4, 4, 4), EXYNOS7_ATL_DIV1(1, 2, 4), },
+	{  500000, EXYNOS7_ATL_DIV0(1, 3, 3, 3), EXYNOS7_ATL_DIV1(1, 2, 3), },
+	{  400000, EXYNOS7_ATL_DIV0(1, 3, 3, 3), EXYNOS7_ATL_DIV1(1, 2, 3), },
+	{  300000, EXYNOS7_ATL_DIV0(1, 3, 3, 3), EXYNOS7_ATL_DIV1(1, 2, 3), },
+	{  200000, EXYNOS7_ATL_DIV0(1, 3, 3, 3), EXYNOS7_ATL_DIV1(1, 2, 3), },
+	{  0 },
+};
+
 static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
 	FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_bus0_pll_ctrl", 1, 2, 0),
 	FFACTOR(0, "ffac_topc_bus0_pll_div4",
@@ -518,7 +538,13 @@ static struct samsung_cmu_info atlas_cmu_info __initdata = {
 
 static void __init exynos7_clk_atlas_init(struct device_node *np)
 {
-	samsung_cmu_register_one(np, &atlas_cmu_info);
+	struct samsung_clk_provider *ctx;
+
+	ctx = samsung_cmu_register_one(np, &atlas_cmu_info);
+	exynos_register_cpu_clock(ctx, CLK_ATLAS_CLK, "atlclk",
+		mout_atlas_p[0], mout_atlas_p[1], 0x0,
+		exynos7_atlclk_d, ARRAY_SIZE(exynos7_atlclk_d),
+		CLK_CPU_HAS_DIV1, np);
 }
 
 CLK_OF_DECLARE(exynos7_clk_atlas, "samsung,exynos7-clock-atlas",
diff --git a/include/dt-bindings/clock/exynos7-clk.h b/include/dt-bindings/clock/exynos7-clk.h
index 93c78f9..33bc166 100644
--- a/include/dt-bindings/clock/exynos7-clk.h
+++ b/include/dt-bindings/clock/exynos7-clk.h
@@ -55,7 +55,8 @@
 #define CLK_ATLAS			12
 #define DOUT_SCLK_HPM_ATLAS		13
 #define DOUT_ATLAS_PLL			14
-#define ATLAS_NR_CLK			15
+#define CLK_ATLAS_CLK			15
+#define ATLAS_NR_CLK			16
 
 /* CCORE */
 #define PCLK_RTC			1
-- 
1.7.9.5

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

end of thread, other threads:[~2014-11-26 11:19 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-26 11:17 [PATCH 0/4] Add CPU clock support for Exynos7 Abhilash Kesavan
2014-11-26 11:17 ` Abhilash Kesavan
2014-11-26 11:17 ` [PATCH 1/4] clk: samsung: exynos7: add clocks for CPU block Abhilash Kesavan
2014-11-26 11:17   ` Abhilash Kesavan
2014-11-26 11:17 ` [PATCH 2/4] clk: samsung: retrieve the clock provider information from samsung_cmu_register_one Abhilash Kesavan
2014-11-26 11:17   ` Abhilash Kesavan
2014-11-26 11:17 ` [PATCH 3/4] clk: samsung: add cpu clock support for Exynos7 Abhilash Kesavan
2014-11-26 11:17   ` Abhilash Kesavan
2014-11-26 11:17 ` [PATCH 4/4] clk: samsung: add cpu clock configuration data and instantiate cpu clock Abhilash Kesavan
2014-11-26 11:17   ` Abhilash Kesavan

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