linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs
@ 2013-06-08 17:34 Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct Yadwinder Singh Brar
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series does the following:

 1) Unifies the clk strutures  and registration function used for PLL35xx &
    PLL36xx, to factor out possible common code.

 2) Defines a common rate_table which will contain recommended p, m, s and k
    values for supported rates that needs to be changed for changing
    corresponding PLL's rate

 3) Adds set_rate() and round_rate() clk_ops for PLL35xx and PLL36xx

changes since v4:
	- Defined common samsung samsung_clk_register_pll() to register a list
	of PLL and used a struct samsung_pll_clock for passing intialisation
	data instead of passing as arguments. Now passing LOCK as well as CON0
	offset as intialisation data.
	- Calculated length of rate table while registering PLL instead of
	getting it as intialisation data.

changes since v3:
	- Used __clk_lookup() instead of adding alias for mout_vpllsrc
	- Added check for changing only M value in samsung_pll36xx_set_rate()
	- Modified samsung_pll35xx_mp_change() & samsung_pll35xx_set_rate()
	to improve readabilty.
	- Made the input rate_table as __init_data which is to be provided while
	registering PLL and made a copy of that table while registering, so
	that if multiple tables are their, they can be freed after getting the
	P, M, S, K setting values from required one.

changes since v2:
	- Added new patch to reorder the MUX registration for mout_vpllsrc MUX
	before the PLL registrations. And to add the alias for the mout_vpllsrc MUX.
        - Added a check to confirm parent rate while registrating the PLL
	rate tables.

changes since v1:
	- removed sorting and bsearch
	- modified the definition of struct "samsung_pll_rate_table"
	- added generic round_rate()
	- rectified the ops assignment for "rate table passed as NULL"
	  during PLL registration

Is rebased on branch kgene's "for-next"
https://git.kernel.org/cgit/linux/kernel/git/kgene/linux-samsung.git/log/?h=for-next

Vikas Sajjan (2):
  clk: samsung: Add set_rate() clk_ops for PLL36xx
  clk: samsung: Reorder MUX registration for mout_vpllsrc

Yadwinder Singh Brar (5):
  clk: samsung: Introduce a common samsung_clk_pll struct.
  clk: samsung: Define a common samsung_clk_register_pll().
  clk: samsung: Add support to register rate_table for PLL3xxx
  clk: samsung: Add set_rate() clk_ops for PLL35xx
  clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

 drivers/clk/samsung/clk-exynos4.c    |   40 +++--
 drivers/clk/samsung/clk-exynos5250.c |  101 +++++++++--
 drivers/clk/samsung/clk-pll.c        |  330 ++++++++++++++++++++++++++--------
 drivers/clk/samsung/clk-pll.h        |   36 ++++-
 drivers/clk/samsung/clk.h            |   54 ++++++
 5 files changed, 449 insertions(+), 112 deletions(-)

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

* [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct.
  2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 2/7] clk: samsung: Define a common samsung_clk_register_pll() Yadwinder Singh Brar
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

This patch unifies clk strutures used for PLL35xx & PLL36xx and
adding an extra member lock_reg, so that common code can be factored out.

Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
 drivers/clk/samsung/clk-pll.c |   30 ++++++++++++------------------
 1 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 89135f6..8224bde 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -13,6 +13,14 @@
 #include "clk.h"
 #include "clk-pll.h"
 
+struct samsung_clk_pll {
+	struct clk_hw		hw;
+	void __iomem		*lock_reg;
+	void __iomem		*con_reg;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
 /*
  * PLL35xx Clock Type
  */
@@ -24,17 +32,10 @@
 #define PLL35XX_PDIV_SHIFT      (8)
 #define PLL35XX_SDIV_SHIFT      (0)
 
-struct samsung_clk_pll35xx {
-	struct clk_hw		hw;
-	const void __iomem	*con_reg;
-};
-
-#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
-
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
 				unsigned long parent_rate)
 {
-	struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
 	u32 mdiv, pdiv, sdiv, pll_con;
 	u64 fvco = parent_rate;
 
@@ -56,7 +57,7 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
 struct clk * __init samsung_clk_register_pll35xx(const char *name,
 			const char *pname, const void __iomem *con_reg)
 {
-	struct samsung_clk_pll35xx *pll;
+	struct samsung_clk_pll *pll;
 	struct clk *clk;
 	struct clk_init_data init;
 
@@ -100,17 +101,10 @@ struct clk * __init samsung_clk_register_pll35xx(const char *name,
 #define PLL36XX_PDIV_SHIFT	(8)
 #define PLL36XX_SDIV_SHIFT	(0)
 
-struct samsung_clk_pll36xx {
-	struct clk_hw		hw;
-	const void __iomem	*con_reg;
-};
-
-#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
-
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
 				unsigned long parent_rate)
 {
-	struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
 	u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
 	u64 fvco = parent_rate;
 
@@ -135,7 +129,7 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
 struct clk * __init samsung_clk_register_pll36xx(const char *name,
 			const char *pname, const void __iomem *con_reg)
 {
-	struct samsung_clk_pll36xx *pll;
+	struct samsung_clk_pll *pll;
 	struct clk *clk;
 	struct clk_init_data init;
 
-- 
1.7.0.4

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

* [PATCH v5 2/7] clk: samsung: Define a common samsung_clk_register_pll().
  2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 3/7] clk: samsung: Add support to register rate_table for PLL3xxx Yadwinder Singh Brar
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

This patch defines a common samsung_clk_register_pll() and its migrating the
PLL35xx & PLL36xx to use it. Other samsung PLL can also be migrated to it.
This patch also adds exynos5250 PLLs in unique id list of exynos5250 clocks.

Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
 drivers/clk/samsung/clk-exynos4.c    |   40 +++++++----
 drivers/clk/samsung/clk-exynos5250.c |   60 +++++++++++-----
 drivers/clk/samsung/clk-pll.c        |  128 +++++++++++++++------------------
 drivers/clk/samsung/clk-pll.h        |    9 ++-
 drivers/clk/samsung/clk.h            |   48 +++++++++++++
 5 files changed, 178 insertions(+), 107 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index addc738..ba25a1b 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -17,7 +17,6 @@
 #include <linux/of_address.h>
 
 #include "clk.h"
-#include "clk-pll.h"
 
 /* Exynos4 clock controller register offsets */
 #define SRC_LEFTBUS		0x4200
@@ -97,12 +96,14 @@
 #define GATE_IP_PERIL		0xc950
 #define E4210_GATE_IP_PERIR	0xc960
 #define GATE_BLOCK		0xc970
+#define E4X12_MPLL_LOCK		0x10008
 #define E4X12_MPLL_CON0		0x10108
 #define SRC_DMC			0x10200
 #define SRC_MASK_DMC		0x10300
 #define DIV_DMC0		0x10500
 #define DIV_DMC1		0x10504
 #define GATE_IP_DMC		0x10900
+#define APLL_LOCK		0x14000
 #define APLL_CON0		0x14100
 #define E4210_MPLL_CON0		0x14108
 #define SRC_CPU			0x14200
@@ -121,6 +122,12 @@ enum exynos4_soc {
 	EXYNOS4X12,
 };
 
+/* list of PLLs to be registered */
+enum exynos4_plls {
+	apll, mpll, epll, vpll,
+	nr_plls			/* number of PLLs */
+};
+
 /*
  * Let each supported clock get a unique id. This id is used to lookup the clock
  * for device tree based platforms. The clocks are categorized into three
@@ -988,6 +995,17 @@ static __initdata struct of_device_id ext_clk_match[] = {
 	{},
 };
 
+struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
+	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+		APLL_CON0, "fout_apll"),
+	[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll",
+		E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll"),
+	[epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+		EPLL_CON0, "fout_epll"),
+	[vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
+		VPLL_CON0, "fout_vpll"),
+};
+
 /* register exynos4 clocks */
 void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom)
 {
@@ -1024,22 +1042,16 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
 					reg_base + EPLL_CON0, pll_4600);
 		vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc",
 					reg_base + VPLL_CON0, pll_4650c);
+
+		samsung_clk_add_lookup(apll, fout_apll);
+		samsung_clk_add_lookup(mpll, fout_mpll);
+		samsung_clk_add_lookup(epll, fout_epll);
+		samsung_clk_add_lookup(vpll, fout_vpll);
 	} else {
-		apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
-					reg_base + APLL_CON0);
-		mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
-					reg_base + E4X12_MPLL_CON0);
-		epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
-					reg_base + EPLL_CON0);
-		vpll = samsung_clk_register_pll36xx("fout_vpll", "fin_pll",
-					reg_base + VPLL_CON0);
+		samsung_clk_register_pll(exynos4_plls,
+					ARRAY_SIZE(exynos4_plls), reg_base);
 	}
 
-	samsung_clk_add_lookup(apll, fout_apll);
-	samsung_clk_add_lookup(mpll, fout_mpll);
-	samsung_clk_add_lookup(epll, fout_epll);
-	samsung_clk_add_lookup(vpll, fout_vpll);
-
 	samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
 			ARRAY_SIZE(exynos4_fixed_rate_clks));
 	samsung_clk_register_mux(exynos4_mux_clks,
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 5c97e75..0418cc1 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -17,11 +17,22 @@
 #include <linux/of_address.h>
 
 #include "clk.h"
-#include "clk-pll.h"
 
+#define APLL_LOCK		0x0
+#define APLL_CON0		0x100
 #define SRC_CPU			0x200
 #define DIV_CPU0		0x500
+#define MPLL_LOCK		0x4000
+#define MPLL_CON0		0x4100
 #define SRC_CORE1		0x4204
+#define CPLL_LOCK		0x10020
+#define EPLL_LOCK		0x10030
+#define VPLL_LOCK		0x10040
+#define GPLL_LOCK		0x10050
+#define CPLL_CON0		0x10120
+#define EPLL_CON0		0x10130
+#define VPLL_CON0		0x10140
+#define GPLL_CON0		0x10150
 #define SRC_TOP0		0x10210
 #define SRC_TOP2		0x10218
 #define SRC_GSCL		0x10220
@@ -59,10 +70,18 @@
 #define GATE_IP_FSYS		0x10944
 #define GATE_IP_PERIC		0x10950
 #define GATE_IP_PERIS		0x10960
+#define BPLL_LOCK		0x20010
+#define BPLL_CON0		0x20110
 #define SRC_CDREX		0x20200
 #define PLL_DIV2_SEL		0x20a24
 #define GATE_IP_DISP1		0x10928
 
+/* list of PLLs to be registered */
+enum exynos5250_plls {
+	apll, mpll, bpll, gpll, cpll, epll, vpll,
+	nr_plls			/* number of PLLs */
+};
+
 /*
  * Let each supported clock get a unique id. This id is used to lookup the clock
  * for device tree based platforms. The clocks are categorized into three
@@ -79,7 +98,8 @@ enum exynos5250_clks {
 	none,
 
 	/* core clocks */
-	fin_pll,
+	fin_pll, fout_apll, fout_mpll, fout_bpll, fout_gpll, fout_cpll,
+	fout_epll, fout_vpll,
 
 	/* gate for special clocks (sclk) */
 	sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb,
@@ -469,11 +489,27 @@ static __initdata struct of_device_id ext_clk_match[] = {
 	{ },
 };
 
+struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
+	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+		APLL_CON0, "fout_apll"),
+	[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
+		MPLL_CON0, "fout_mpll"),
+	[bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
+		BPLL_CON0),
+	[gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", GPLL_LOCK,
+		GPLL_CON0),
+	[cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK,
+		CPLL_CON0),
+	[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+		EPLL_CON0),
+	[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
+		VPLL_CON0),
+};
+
 /* register exynox5250 clocks */
 void __init exynos5250_clk_init(struct device_node *np)
 {
 	void __iomem *reg_base;
-	struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
 
 	if (np) {
 		reg_base = of_iomap(np, 0);
@@ -489,22 +525,8 @@ void __init exynos5250_clk_init(struct device_node *np)
 	samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
 			ext_clk_match);
-
-	apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
-			reg_base + 0x100);
-	mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
-			reg_base + 0x4100);
-	bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
-			reg_base + 0x20110);
-	gpll = samsung_clk_register_pll35xx("fout_gpll", "fin_pll",
-			reg_base + 0x10150);
-	cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
-			reg_base + 0x10120);
-	epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
-			reg_base + 0x10130);
-	vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc",
-			reg_base + 0x10140);
-
+	samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
+					reg_base);
 	samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
 			ARRAY_SIZE(exynos5250_fixed_rate_clks));
 	samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 8224bde..b83900c 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -17,6 +17,7 @@ struct samsung_clk_pll {
 	struct clk_hw		hw;
 	void __iomem		*lock_reg;
 	void __iomem		*con_reg;
+	enum samsung_pll_type	type;
 };
 
 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
@@ -54,41 +55,6 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
 	.recalc_rate = samsung_pll35xx_recalc_rate,
 };
 
-struct clk * __init samsung_clk_register_pll35xx(const char *name,
-			const char *pname, const void __iomem *con_reg)
-{
-	struct samsung_clk_pll *pll;
-	struct clk *clk;
-	struct clk_init_data init;
-
-	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-	if (!pll) {
-		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
-		return NULL;
-	}
-
-	init.name = name;
-	init.ops = &samsung_pll35xx_clk_ops;
-	init.flags = CLK_GET_RATE_NOCACHE;
-	init.parent_names = &pname;
-	init.num_parents = 1;
-
-	pll->hw.init = &init;
-	pll->con_reg = con_reg;
-
-	clk = clk_register(NULL, &pll->hw);
-	if (IS_ERR(clk)) {
-		pr_err("%s: failed to register pll clock %s\n", __func__,
-				name);
-		kfree(pll);
-	}
-
-	if (clk_register_clkdev(clk, name, NULL))
-		pr_err("%s: failed to register lookup for %s", __func__, name);
-
-	return clk;
-}
-
 /*
  * PLL36xx Clock Type
  */
@@ -126,41 +92,6 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
 	.recalc_rate = samsung_pll36xx_recalc_rate,
 };
 
-struct clk * __init samsung_clk_register_pll36xx(const char *name,
-			const char *pname, const void __iomem *con_reg)
-{
-	struct samsung_clk_pll *pll;
-	struct clk *clk;
-	struct clk_init_data init;
-
-	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-	if (!pll) {
-		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
-		return NULL;
-	}
-
-	init.name = name;
-	init.ops = &samsung_pll36xx_clk_ops;
-	init.flags = CLK_GET_RATE_NOCACHE;
-	init.parent_names = &pname;
-	init.num_parents = 1;
-
-	pll->hw.init = &init;
-	pll->con_reg = con_reg;
-
-	clk = clk_register(NULL, &pll->hw);
-	if (IS_ERR(clk)) {
-		pr_err("%s: failed to register pll clock %s\n", __func__,
-				name);
-		kfree(pll);
-	}
-
-	if (clk_register_clkdev(clk, name, NULL))
-		pr_err("%s: failed to register lookup for %s", __func__, name);
-
-	return clk;
-}
-
 /*
  * PLL45xx Clock Type
  */
@@ -411,3 +342,60 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
 
 	return clk;
 }
+
+void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
+				unsigned int nr_pll, void __iomem *base)
+{
+	struct samsung_clk_pll *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+	struct samsung_pll_clock *list = clk_list;
+	int cnt;
+
+	for (cnt = 0; cnt < nr_pll; cnt++, list++) {
+		pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+		if (!pll) {
+			pr_err("%s: could not allocate pll clk %s\n",
+				__func__, list->name);
+			continue;
+		}
+
+		init.name = list->name;
+		init.flags = list->flags;
+		init.parent_names = &list->parent_name;
+		init.num_parents = 1;
+
+		switch (list->type) {
+		case pll_35xx:
+			init.ops = &samsung_pll35xx_clk_ops;
+			break;
+		case pll_36xx:
+			init.ops = &samsung_pll36xx_clk_ops;
+			break;
+		default:
+			pr_warn("%s: Unknown pll type for pll clk %s\n",
+				__func__, list->name);
+		}
+
+		pll->hw.init = &init;
+		pll->type = list->type;
+		pll->lock_reg = base + list->lock_offset;
+		pll->con_reg = base + list->con_offset;
+
+		clk = clk_register(NULL, &pll->hw);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register pll clock %s\n",
+				__func__, list->name);
+			kfree(pll);
+			continue;
+		}
+
+		samsung_clk_add_lookup(clk, list->id);
+
+		if (list->alias)
+			if (clk_register_clkdev(clk, list->alias,
+				list->dev_name))
+				pr_err("%s: failed to register lookup for %s",
+					__func__, list->name);
+	}
+}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index f33786e..58810fe 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -12,6 +12,11 @@
 #ifndef __SAMSUNG_CLK_PLL_H
 #define __SAMSUNG_CLK_PLL_H
 
+enum samsung_pll_type {
+	pll_35xx,
+	pll_36xx,
+};
+
 enum pll45xx_type {
 	pll_4500,
 	pll_4502,
@@ -24,10 +29,6 @@ enum pll46xx_type {
 	pll_4650c,
 };
 
-extern struct clk * __init samsung_clk_register_pll35xx(const char *name,
-			const char *pname, const void __iomem *con_reg);
-extern struct clk * __init samsung_clk_register_pll36xx(const char *name,
-			const char *pname, const void __iomem *con_reg);
 extern struct clk * __init samsung_clk_register_pll45xx(const char *name,
 			const char *pname, const void __iomem *con_reg,
 			enum pll45xx_type type);
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index e4ad6ea..51f60ca 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -19,6 +19,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include "clk-pll.h"
 
 /**
  * struct samsung_clock_alias: information about mux clock
@@ -258,6 +259,51 @@ struct samsung_clk_reg_dump {
 	u32	value;
 };
 
+/**
+ * struct samsung_pll_clock: information about pll clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this pll clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @con_offset: offset of the register for configuring the PLL.
+ * @lock_offset: offset of the register for locking the PLL.
+ * @type: Type of PLL to be registered.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_pll_clock {
+	unsigned int		id;
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	const int		con_offset;
+	const int		lock_offset;
+	enum			samsung_pll_type type;
+	const char              *alias;
+};
+
+#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, _alias) \
+	{								\
+		.id		= _id,					\
+		.type		= _typ,					\
+		.dev_name	= _dname,				\
+		.name		= _name,				\
+		.parent_name	= _pname,				\
+		.flags		= CLK_GET_RATE_NOCACHE,			\
+		.con_offset	= _con,					\
+		.lock_offset	= _lock,				\
+		.alias		= _alias,				\
+	}
+
+#define PLL(_typ, _id, _name, _pname, _lock, _con)			\
+	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
+		_lock, _con, NULL)
+
+#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias)		\
+	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
+		_lock, _con, _alias)
+
 extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
 		unsigned long nr_clks, unsigned long *rdump,
 		unsigned long nr_rdump, unsigned long *soc_rdump,
@@ -281,6 +327,8 @@ extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
 		unsigned int nr_clk);
 extern void __init samsung_clk_register_gate(
 		struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+extern void __init samsung_clk_register_pll(struct samsung_pll_clock *list,
+		unsigned int nr_clk, void __iomem *base);
 
 extern unsigned long _get_rate(const char *clk_name);
 
-- 
1.7.0.4

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

* [PATCH v5 3/7] clk: samsung: Add support to register rate_table for PLL3xxx
  2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 2/7] clk: samsung: Define a common samsung_clk_register_pll() Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx Yadwinder Singh Brar
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

This patch defines a common rate_table which will contain recommended p, m, s,
k values for supported rates that needs to be changed for changing
corresponding PLL's rate.

Reviewed-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
 drivers/clk/samsung/clk-exynos4.c    |    8 ++++----
 drivers/clk/samsung/clk-exynos5250.c |   14 +++++++-------
 drivers/clk/samsung/clk-pll.c        |   22 ++++++++++++++++++++--
 drivers/clk/samsung/clk-pll.h        |   27 +++++++++++++++++++++++++++
 drivers/clk/samsung/clk.h            |   14 +++++++++-----
 5 files changed, 67 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index ba25a1b..ceee66c 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -997,13 +997,13 @@ static __initdata struct of_device_id ext_clk_match[] = {
 
 struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
 	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
-		APLL_CON0, "fout_apll"),
+		APLL_CON0, "fout_apll", NULL),
 	[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll",
-		E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll"),
+		E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll", NULL),
 	[epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
-		EPLL_CON0, "fout_epll"),
+		EPLL_CON0, "fout_epll", NULL),
 	[vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
-		VPLL_CON0, "fout_vpll"),
+		VPLL_CON0, "fout_vpll", NULL),
 };
 
 /* register exynos4 clocks */
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 0418cc1..a025269 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -491,19 +491,19 @@ static __initdata struct of_device_id ext_clk_match[] = {
 
 struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
 	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
-		APLL_CON0, "fout_apll"),
+		APLL_CON0, "fout_apll", NULL),
 	[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
-		MPLL_CON0, "fout_mpll"),
+		MPLL_CON0, "fout_mpll", NULL),
 	[bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
-		BPLL_CON0),
+		BPLL_CON0, NULL),
 	[gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", GPLL_LOCK,
-		GPLL_CON0),
+		GPLL_CON0, NULL),
 	[cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK,
-		CPLL_CON0),
+		CPLL_CON0, NULL),
 	[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
-		EPLL_CON0),
+		EPLL_CON0, NULL),
 	[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
-		VPLL_CON0),
+		VPLL_CON0, NULL),
 };
 
 /* register exynox5250 clocks */
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index b83900c..f753c5e 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -18,6 +18,8 @@ struct samsung_clk_pll {
 	void __iomem		*lock_reg;
 	void __iomem		*con_reg;
 	enum samsung_pll_type	type;
+	unsigned int		rate_count;
+	const struct samsung_pll_rate_table *rate_table;
 };
 
 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
@@ -350,7 +352,7 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
 	struct clk *clk;
 	struct clk_init_data init;
 	struct samsung_pll_clock *list = clk_list;
-	int cnt;
+	int cnt, len;
 
 	for (cnt = 0; cnt < nr_pll; cnt++, list++) {
 		pll = kzalloc(sizeof(*pll), GFP_KERNEL);
@@ -365,6 +367,21 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
 		init.parent_names = &list->parent_name;
 		init.num_parents = 1;
 
+		if (list->rate_table) {
+			/* find count of rates in rate_table */
+			for (len = 0; list->rate_table[len].rate != 0; )
+				len++;
+
+			pll->rate_count = len;
+			pll->rate_table = kmemdup(list->rate_table,
+					list->rate_count *
+					sizeof(struct samsung_pll_rate_table),
+					GFP_KERNEL);
+			WARN(!pll->rate_table,
+				"%s: could not allocate rate table for %s\n",
+				__func__, list->name);
+		}
+
 		switch (list->type) {
 		case pll_35xx:
 			init.ops = &samsung_pll35xx_clk_ops;
@@ -392,10 +409,11 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
 
 		samsung_clk_add_lookup(clk, list->id);
 
-		if (list->alias)
+		if (list->alias) {
 			if (clk_register_clkdev(clk, list->alias,
 				list->dev_name))
 				pr_err("%s: failed to register lookup for %s",
 					__func__, list->name);
+		}
 	}
 }
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 58810fe..fb42252 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -17,6 +17,33 @@ enum samsung_pll_type {
 	pll_36xx,
 };
 
+#define PLL_35XX_RATE(_rate, _m, _p, _s)			\
+	{							\
+		.rate	=	(_rate),				\
+		.mdiv	=	(_m),				\
+		.pdiv	=	(_p),				\
+		.sdiv	=	(_s),				\
+	}
+
+#define PLL_36XX_RATE(_rate, _m, _p, _s, _k)			\
+	{							\
+		.rate	=	(_rate),				\
+		.mdiv	=	(_m),				\
+		.pdiv	=	(_p),				\
+		.sdiv	=	(_s),				\
+		.kdiv	=	(_k),				\
+	}
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+
+struct samsung_pll_rate_table {
+	unsigned int rate;
+	unsigned int pdiv;
+	unsigned int mdiv;
+	unsigned int sdiv;
+	unsigned int kdiv;
+};
+
 enum pll45xx_type {
 	pll_4500,
 	pll_4502,
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 51f60ca..3e6501c 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -280,10 +280,13 @@ struct samsung_pll_clock {
 	const int		con_offset;
 	const int		lock_offset;
 	enum			samsung_pll_type type;
+	const struct samsung_pll_rate_table *rate_table;
+	unsigned int		rate_count;
 	const char              *alias;
 };
 
-#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, _alias) \
+#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con,	\
+		_rtable, _alias)					\
 	{								\
 		.id		= _id,					\
 		.type		= _typ,					\
@@ -293,16 +296,17 @@ struct samsung_pll_clock {
 		.flags		= CLK_GET_RATE_NOCACHE,			\
 		.con_offset	= _con,					\
 		.lock_offset	= _lock,				\
+		.rate_table	= _rtable,				\
 		.alias		= _alias,				\
 	}
 
-#define PLL(_typ, _id, _name, _pname, _lock, _con)			\
+#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable)	\
 	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
-		_lock, _con, NULL)
+		_lock, _con, _rtable, _name)
 
-#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias)		\
+#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
 	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
-		_lock, _con, _alias)
+		_lock, _con, _rtable, _alias)
 
 extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
 		unsigned long nr_clks, unsigned long *rdump,
-- 
1.7.0.4

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

* [PATCH v5 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx
  2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
                   ` (2 preceding siblings ...)
  2013-06-08 17:34 ` [PATCH v5 3/7] clk: samsung: Add support to register rate_table for PLL3xxx Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx Yadwinder Singh Brar
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

This patch add set_rate() and round_rate() for PLL35xx

Reviewed-by: Doug Anderson <dianders@chromium.org>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
 drivers/clk/samsung/clk-pll.c |  104 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 103 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index f753c5e..df419aa 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -24,16 +24,51 @@ struct samsung_clk_pll {
 
 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
 
+static const struct samsung_pll_rate_table *samsung_get_pll_settings(
+				struct samsung_clk_pll *pll, unsigned long rate)
+{
+	const struct samsung_pll_rate_table  *rate_table = pll->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++) {
+		if (rate == rate_table[i].rate)
+			return &rate_table[i];
+	}
+
+	return NULL;
+}
+
+static long samsung_pll_round_rate(struct clk_hw *hw,
+			unsigned long drate, unsigned long *prate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	const struct samsung_pll_rate_table *rate_table = pll->rate_table;
+	int i;
+
+	/* Assumming rate_table is in descending order */
+	for (i = 0; i < pll->rate_count; i++) {
+		if (drate >= rate_table[i].rate)
+			return rate_table[i].rate;
+	}
+
+	/* return minimum supported value */
+	return rate_table[i - 1].rate;
+}
+
 /*
  * PLL35xx Clock Type
  */
+/* Maximum lock time can be 270 * PDIV cycles */
+#define PLL35XX_LOCK_FACTOR	(270)
 
 #define PLL35XX_MDIV_MASK       (0x3FF)
 #define PLL35XX_PDIV_MASK       (0x3F)
 #define PLL35XX_SDIV_MASK       (0x7)
+#define PLL35XX_LOCK_STAT_MASK	(0x1)
 #define PLL35XX_MDIV_SHIFT      (16)
 #define PLL35XX_PDIV_SHIFT      (8)
 #define PLL35XX_SDIV_SHIFT      (0)
+#define PLL35XX_LOCK_STAT_SHIFT	(29)
 
 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
 				unsigned long parent_rate)
@@ -53,8 +88,72 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
 	return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll35xx_mp_change(
+		const struct samsung_pll_rate_table *rate, u32 pll_con)
+{
+	u32 old_mdiv, old_pdiv;
+
+	old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+	old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+
+	return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
+}
+
+static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long prate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	const struct samsung_pll_rate_table *rate;
+	u32 tmp;
+
+	/* Get required rate settings from table */
+	rate = samsung_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	tmp = __raw_readl(pll->con_reg);
+
+	if (!(samsung_pll35xx_mp_change(rate, tmp))) {
+		/* If only s change, change just s value only*/
+		tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
+		tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
+		__raw_writel(tmp, pll->con_reg);
+		return 0;
+	}
+
+	/* Set PLL lock time. */
+	__raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR,
+			pll->lock_reg);
+
+	/* Change PLL PMS values */
+	tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
+			(PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
+			(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
+	tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
+			(rate->pdiv << PLL35XX_PDIV_SHIFT) |
+			(rate->sdiv << PLL35XX_SDIV_SHIFT);
+	__raw_writel(tmp, pll->con_reg);
+
+	/* wait_lock_time */
+	do {
+		cpu_relax();
+		tmp = __raw_readl(pll->con_reg);
+	} while (!(tmp & (PLL35XX_LOCK_STAT_MASK
+				<< PLL35XX_LOCK_STAT_SHIFT)));
+	return 0;
+}
+
 static const struct clk_ops samsung_pll35xx_clk_ops = {
 	.recalc_rate = samsung_pll35xx_recalc_rate,
+	.round_rate = samsung_pll_round_rate,
+	.set_rate = samsung_pll35xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll35xx_clk_min_ops = {
+	.recalc_rate = samsung_pll35xx_recalc_rate,
 };
 
 /*
@@ -384,7 +483,10 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
 
 		switch (list->type) {
 		case pll_35xx:
-			init.ops = &samsung_pll35xx_clk_ops;
+			if (!pll->rate_table)
+				init.ops = &samsung_pll35xx_clk_min_ops;
+			else
+				init.ops = &samsung_pll35xx_clk_ops;
 			break;
 		case pll_36xx:
 			init.ops = &samsung_pll36xx_clk_ops;
-- 
1.7.0.4

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

* [PATCH v5 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx
  2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
                   ` (3 preceding siblings ...)
  2013-06-08 17:34 ` [PATCH v5 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar
  6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vikas Sajjan <vikas.sajjan@linaro.org>

This patch adds set_rate and round_rate clk_ops for PLL36xx

Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Reviewed-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Vikas Sajjan <vikas.sajjan@linaro.org>
---
 drivers/clk/samsung/clk-pll.c |   78 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 77 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index df419aa..2adf761 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -159,6 +159,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 /*
  * PLL36xx Clock Type
  */
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR    (3000)
 
 #define PLL36XX_KDIV_MASK	(0xFFFF)
 #define PLL36XX_MDIV_MASK	(0x1FF)
@@ -167,6 +169,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
 #define PLL36XX_MDIV_SHIFT	(16)
 #define PLL36XX_PDIV_SHIFT	(8)
 #define PLL36XX_SDIV_SHIFT	(0)
+#define PLL36XX_KDIV_SHIFT	(0)
+#define PLL36XX_LOCK_STAT_SHIFT	(29)
 
 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
 				unsigned long parent_rate)
@@ -189,8 +193,77 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
 	return (unsigned long)fvco;
 }
 
+static inline bool samsung_pll36xx_mpk_change(
+	const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
+{
+	u32 old_mdiv, old_pdiv, old_kdiv;
+
+	old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+	old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+	old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
+
+	return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+		rate->kdiv != old_kdiv);
+}
+
+static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long parent_rate)
+{
+	struct samsung_clk_pll *pll = to_clk_pll(hw);
+	u32 tmp, pll_con0, pll_con1;
+	const struct samsung_pll_rate_table *rate;
+
+	rate = samsung_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	pll_con0 = __raw_readl(pll->con_reg);
+	pll_con1 = __raw_readl(pll->con_reg + 4);
+
+	if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
+		/* If only s change, change just s value only*/
+		pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
+		pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
+		__raw_writel(pll_con0, pll->con_reg);
+		return 0;
+	}
+
+	/* Set PLL lock time. */
+	__raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
+
+	 /* Change PLL PMS values */
+	pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
+			(PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
+			(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
+	pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
+			(rate->pdiv << PLL36XX_PDIV_SHIFT) |
+			(rate->sdiv << PLL36XX_SDIV_SHIFT);
+	__raw_writel(pll_con0, pll->con_reg);
+
+	pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
+	pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
+	__raw_writel(pll_con1, pll->con_reg + 4);
+
+	/* wait_lock_time */
+	do {
+		cpu_relax();
+		tmp = __raw_readl(pll->con_reg);
+	} while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
+
+	return 0;
+}
+
 static const struct clk_ops samsung_pll36xx_clk_ops = {
 	.recalc_rate = samsung_pll36xx_recalc_rate,
+	.set_rate = samsung_pll36xx_set_rate,
+	.round_rate = samsung_pll_round_rate,
+};
+
+static const struct clk_ops samsung_pll36xx_clk_min_ops = {
+	.recalc_rate = samsung_pll36xx_recalc_rate,
 };
 
 /*
@@ -489,7 +562,10 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
 				init.ops = &samsung_pll35xx_clk_ops;
 			break;
 		case pll_36xx:
-			init.ops = &samsung_pll36xx_clk_ops;
+			if (!pll->rate_table)
+				init.ops = &samsung_pll36xx_clk_min_ops;
+			else
+				init.ops = &samsung_pll36xx_clk_ops;
 			break;
 		default:
 			pr_warn("%s: Unknown pll type for pll clk %s\n",
-- 
1.7.0.4

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

* [PATCH v5 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc
  2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
                   ` (4 preceding siblings ...)
  2013-06-08 17:34 ` [PATCH v5 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
  2013-06-08 17:34 ` [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar
  6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

From: Vikas Sajjan <vikas.sajjan@linaro.org>

While trying to get rate of "mout_vpllsrc" MUX (parent) for registering the
"fout_vpll" (child), we found get rate was failing.

So this patch moves the mout_vpllsrc MUX out of the existing common list
and registers the mout_vpllsrc MUX before the PLL registrations.

Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Vikas Sajjan <vikas.sajjan@linaro.org>
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
 drivers/clk/samsung/clk-exynos5250.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index a025269..09da356 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -227,6 +227,10 @@ struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
 	FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
 };
 
+struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+	MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
+};
+
 struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
 	MUX(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
 	MUX(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
@@ -234,7 +238,6 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
 	MUX(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1),
 	MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
 	MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
-	MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
 	MUX(none, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
 	MUX(none, "sclk_epll", mout_epll_p, SRC_TOP2, 12, 1),
 	MUX(none, "sclk_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
@@ -525,6 +528,8 @@ void __init exynos5250_clk_init(struct device_node *np)
 	samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
 			ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
 			ext_clk_match);
+	samsung_clk_register_mux(exynos5250_pll_pmux_clks,
+				ARRAY_SIZE(exynos5250_pll_pmux_clks));
 	samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
 					reg_base);
 	samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
-- 
1.7.0.4

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

* [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC
  2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
                   ` (5 preceding siblings ...)
  2013-06-08 17:34 ` [PATCH v5 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
  2013-06-17 20:08   ` Andrew Bresticker
  6 siblings, 1 reply; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
  To: linux-arm-kernel

Adds the EPLL and VPLL freq table for exynos5250 SoC.

Signed-off-by: Vikas Sajjan <vikas.sajjan@linaro.org>
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
 drivers/clk/samsung/clk-exynos5250.c |   38 ++++++++++++++++++++++++++++++++++
 drivers/clk/samsung/clk.h            |    2 +
 2 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 09da356..d2743f9 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -492,6 +492,29 @@ static __initdata struct of_device_id ext_clk_match[] = {
 	{ },
 };
 
+static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = {
+	/* sorted in descending order */
+	/* PLL_36XX_RATE(rate, m, p, s, k) */
+	PLL_36XX_RATE(266000000, 266, 3, 3, 0),
+	/* Not in UM, but need for eDP on snow */
+	PLL_36XX_RATE(70500000, 94, 2, 4, 0),
+	{ },
+};
+
+static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
+	/* sorted in descending order */
+	/* PLL_36XX_RATE(rate, m, p, s, k) */
+	PLL_36XX_RATE(192000000, 48, 3, 1, 0),
+	PLL_36XX_RATE(180633600, 45, 3, 1, 10381),
+	PLL_36XX_RATE(180000000, 45, 3, 1, 0),
+	PLL_36XX_RATE(73728000, 73, 3, 3, 47710),
+	PLL_36XX_RATE(67737600, 90, 4, 3, 20762),
+	PLL_36XX_RATE(49152000, 49, 3, 3, 9962),
+	PLL_36XX_RATE(45158400, 45, 3, 3, 10381),
+	PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+	{ },
+};
+
 struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
 	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
 		APLL_CON0, "fout_apll", NULL),
@@ -513,6 +536,8 @@ struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
 void __init exynos5250_clk_init(struct device_node *np)
 {
 	void __iomem *reg_base;
+	struct clk *vpllsrc;
+	unsigned long fin_pll_rate, mout_vpllsrc_rate = 0;
 
 	if (np) {
 		reg_base = of_iomap(np, 0);
@@ -530,6 +555,19 @@ void __init exynos5250_clk_init(struct device_node *np)
 			ext_clk_match);
 	samsung_clk_register_mux(exynos5250_pll_pmux_clks,
 				ARRAY_SIZE(exynos5250_pll_pmux_clks));
+
+	fin_pll_rate = _get_rate("fin_pll");
+
+	if (fin_pll_rate == (24 * MHZ))
+		exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
+
+	vpllsrc = __clk_lookup("mout_vpllsrc");
+	if (vpllsrc)
+		mout_vpllsrc_rate = clk_get_rate(vpllsrc);
+
+	if (mout_vpllsrc_rate == (24 * MHZ))
+		exynos5250_plls[vpll].rate_table =  vpll_24mhz_tbl;
+
 	samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
 					reg_base);
 	samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 3e6501c..378bf98 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -40,6 +40,8 @@ struct samsung_clock_alias {
 		.alias		= a,				\
 	}
 
+#define MHZ (1000*1000)
+
 /**
  * struct samsung_fixed_rate_clock: information about fixed-rate clock
  * @id: platform specific id of the clock.
-- 
1.7.0.4

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

* [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC
  2013-06-08 17:34 ` [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar
@ 2013-06-17 20:08   ` Andrew Bresticker
  2013-06-18  7:10     ` Vikas Sajjan
  0 siblings, 1 reply; 10+ messages in thread
From: Andrew Bresticker @ 2013-06-17 20:08 UTC (permalink / raw)
  To: linux-arm-kernel

> +static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
> +       /* sorted in descending order */
> +       /* PLL_36XX_RATE(rate, m, p, s, k) */
> +       PLL_36XX_RATE(192000000, 48, 3, 1, 0),
> +       PLL_36XX_RATE(180633600, 45, 3, 1, 10381),
> +       PLL_36XX_RATE(180000000, 45, 3, 1, 0),
> +       PLL_36XX_RATE(73728000, 73, 3, 3, 47710),
> +       PLL_36XX_RATE(67737600, 90, 4, 3, 20762),
> +       PLL_36XX_RATE(49152000, 49, 3, 3, 9962),
> +       PLL_36XX_RATE(45158400, 45, 3, 3, 10381),
> +       PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
> +       { },
> +};

I believe the UM says that 64 <= m <= 511.  Although the above seems
to work on 5250 and 5420, it might be better to use a table that
conforms to the constraint on m:

PLL_36XX_RATE(192000000, 64, 2, 2, 0),
PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
PLL_36XX_RATE(180000000, 90, 3, 2, 0),
PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
PLL_36XX_RATE(32768000, 131, 3, 5, 4719)

Thanks,
Andrew

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

* [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC
  2013-06-17 20:08   ` Andrew Bresticker
@ 2013-06-18  7:10     ` Vikas Sajjan
  0 siblings, 0 replies; 10+ messages in thread
From: Vikas Sajjan @ 2013-06-18  7:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Andrew,

On 18 June 2013 01:38, Andrew Bresticker <abrestic@chromium.org> wrote:
>> +static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
>> +       /* sorted in descending order */
>> +       /* PLL_36XX_RATE(rate, m, p, s, k) */
>> +       PLL_36XX_RATE(192000000, 48, 3, 1, 0),
>> +       PLL_36XX_RATE(180633600, 45, 3, 1, 10381),
>> +       PLL_36XX_RATE(180000000, 45, 3, 1, 0),
>> +       PLL_36XX_RATE(73728000, 73, 3, 3, 47710),
>> +       PLL_36XX_RATE(67737600, 90, 4, 3, 20762),
>> +       PLL_36XX_RATE(49152000, 49, 3, 3, 9962),
>> +       PLL_36XX_RATE(45158400, 45, 3, 3, 10381),
>> +       PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
>> +       { },
>> +};
>
> I believe the UM says that 64 <= m <= 511.  Although the above seems
> to work on 5250 and 5420, it might be better to use a table that
> conforms to the constraint on m:
>

OK, will test with the below table and resend.


> PLL_36XX_RATE(192000000, 64, 2, 2, 0),
> PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
> PLL_36XX_RATE(180000000, 90, 3, 2, 0),
> PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
> PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
> PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
> PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
> PLL_36XX_RATE(32768000, 131, 3, 5, 4719)
>
> Thanks,
> Andrew



--
Thanks and Regards
 Vikas Sajjan

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

end of thread, other threads:[~2013-06-18  7:10 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 2/7] clk: samsung: Define a common samsung_clk_register_pll() Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 3/7] clk: samsung: Add support to register rate_table for PLL3xxx Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar
2013-06-17 20:08   ` Andrew Bresticker
2013-06-18  7:10     ` Vikas Sajjan

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).