Skip to contentSkip to conversation

Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs

PATCH Superseded Yadwinder Singh Brar 3 participants 17 messages Jun 10, 2013 – Jun 19, 2013

Subsystems (3)

v6 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

v6 cover Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs

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 v5:
- Corrected to use rate table as specified in UM for exynos5250 epll.
- Took care of exynos5420 as well, as new exynos5420 clk driver came in while rebasing on latest Kgene's for-next.

Since we spilted 1st patch into 2 different patches, can we expect "reviewed-by" again for the same?

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 samsung plls
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-exynos5420.c |   86 ++++++---
 drivers/clk/samsung/clk-pll.c        |  332 ++++++++++++++++++++++++++--------
 drivers/clk/samsung/clk-pll.h        |   38 ++++-
 drivers/clk/samsung/clk.h            |   54 ++++++
 6 files changed, 513 insertions(+), 138 deletions(-)
#1 lore raw

PATCH v6 1/7 clk: samsung: Introduce a common samsung_clk_pll struct

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

---
 drivers/clk/samsung/clk-pll.c |   30 ++++++++++++------------------
 1 files changed, 12 insertions(+), 18 deletions(-)
drivers/clk/samsung/clk-pll.c +12 -18
index 89135f6..8224bde 100644
@@ -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;
 
Signature · 1 line
1.7.0.4
#2 lore raw

PATCH v6 1/7 clk: samsung: Introduce a common samsung_clk_pll struct

Quoted 77 lines · On Monday 10 of June 2013 18:54:13 Yadwinder Singh Brar wrote:

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

---
 drivers/clk/samsung/clk-pll.c |   30 ++++++++++++------------------
 1 files changed, 12 insertions(+), 18 deletions(-)
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-pll.c index 89135f6..8224bde 100644

drivers/clk/samsung/clk-pll.c +8 -6
@@ -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,

drivers/clk/samsung/clk-pll.c +2 -2
 				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)

drivers/clk/samsung/clk-pll.c +0 -6
-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,

drivers/clk/samsung/clk-pll.c +1 -1
 				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;

drivers/clk/samsung/clk-pll.c static const struct clk_ops samsung_pll36xx_clk_ops · line 134

Quoted 7 lines
drivers/clk/samsung/clk-pll.c +1 -1
@@ -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;

Looks good to me.

Best regards,
Tomasz

#3 lore raw

PATCH v6 2/7 clk: samsung: Define a common samsung_clk_register_pll()

In reply to Yadwinder Singh Brar

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. It also adds exynos5250 & exynos5420 PLLs to unique id list of clocks. Since pll2550 & pll35xx and pll2650 & pll36xx have exactly same clk ops implementation, added pll2550 and pll2650 also.

---
 drivers/clk/samsung/clk-exynos4.c    |   40 +++++++----
 drivers/clk/samsung/clk-exynos5250.c |   60 +++++++++++-----
 drivers/clk/samsung/clk-exynos5420.c |   86 +++++++++++++++-------
 drivers/clk/samsung/clk-pll.c        |  132 ++++++++++++++++------------------
 drivers/clk/samsung/clk-pll.h        |   11 ++-
 drivers/clk/samsung/clk.h            |   48 ++++++++++++
 6 files changed, 242 insertions(+), 135 deletions(-)
drivers/clk/samsung/clk-exynos4.c +26 -14
index addc738..ba25a1b 100644
@@ -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,
drivers/clk/samsung/clk-exynos5250.c +41 -19

102 lines not on this page · raw message

drivers/clk/samsung/clk-exynos5420.c +58 -28

130 lines not on this page · raw message

drivers/clk/samsung/clk-pll.c +62 -70

153 lines not on this page · raw message

drivers/clk/samsung/clk-pll.h +7 -4
index f33786e..1536f27 100644
@@ -12,6 +12,13 @@
 #ifndef __SAMSUNG_CLK_PLL_H
 #define __SAMSUNG_CLK_PLL_H
 
+enum samsung_pll_type {
+	pll_35xx,
+	pll_36xx,
+	pll_2550,
+	pll_2650,
+};
+
 enum pll45xx_type {
 	pll_4500,
 	pll_4502,
@@ -24,10 +31,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);
drivers/clk/samsung/clk.h +48 -0

66 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#4 lore raw

PATCH v6 2/7 clk: samsung: Define a common samsung_clk_register_pll()

Hi Yadwinder,

Generally looks really good, but some comments inline.

Quoted 61 lines · On Monday 10 of June 2013 18:54:14 Yadwinder Singh Brar wrote:

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. It also adds exynos5250 & exynos5420 PLLs to unique id list of clocks. Since pll2550 & pll35xx and pll2650 & pll36xx have exactly same clk ops implementation, added pll2550 and pll2650 also.

---
 drivers/clk/samsung/clk-exynos4.c    |   40 +++++++----
 drivers/clk/samsung/clk-exynos5250.c |   60 +++++++++++-----
 drivers/clk/samsung/clk-exynos5420.c |   86 +++++++++++++++-------
 drivers/clk/samsung/clk-pll.c        |  132
++++++++++++++++------------------ drivers/clk/samsung/clk-pll.h       
|   11 ++-
 drivers/clk/samsung/clk.h            |   48 ++++++++++++
 6 files changed, 242 insertions(+), 135 deletions(-)
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-exynos4.c index addc738..ba25a1b 100644

drivers/clk/samsung/clk-exynos4.c +8 -1
@@ -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[] = { {},
};

drivers/clk/samsung/clk-exynos4.c

Quoted 2 lines
drivers/clk/samsung/clk-exynos4.c +2 -0
+struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
+	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", 

APLL_LOCK,

drivers/clk/samsung/clk-exynos4.c static __initdata struct of_device_id ext_clk_match[] = {

Quoted 4 lines
drivers/clk/samsung/clk-exynos4.c +4 -0
+		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,

drivers/clk/samsung/clk-exynos4.c

Quoted 2 lines
drivers/clk/samsung/clk-exynos4.c +2 -0
+		EPLL_CON0, "fout_epll"),
+	[vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", 

VPLL_LOCK,

drivers/clk/samsung/clk-exynos4.c void __init exynos4_clk_init(struct device_node · line 1043

Quoted 9 lines
drivers/clk/samsung/clk-exynos4.c +3 -0
+		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) {

drivers/clk/samsung/clk-exynos4.c +0 -0
@@ -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",

drivers/clk/samsung/clk-exynos4.c void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so

Quoted 8 lines
drivers/clk/samsung/clk-exynos4.c +5 -1
 					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",

drivers/clk/samsung/clk-exynos4.c void __init exynos4_clk_init(struct device_node · line 1030

Quoted 2 lines
drivers/clk/samsung/clk-exynos4.c +0 -2
-					reg_base + APLL_CON0);
-		mpll = samsung_clk_register_pll35xx("fout_mpll", 

"fin_pll",

drivers/clk/samsung/clk-exynos4.c void __init exynos4_clk_init(struct device_node · line 1032

Quoted 2 lines
drivers/clk/samsung/clk-exynos4.c +0 -2
-					reg_base + E4X12_MPLL_CON0);
-		epll = samsung_clk_register_pll36xx("fout_epll", 

"fin_pll",

drivers/clk/samsung/clk-exynos4.c void __init exynos4_clk_init(struct device_node · line 1034

Quoted 2 lines
drivers/clk/samsung/clk-exynos4.c +0 -2
-					reg_base + EPLL_CON0);
-		vpll = samsung_clk_register_pll36xx("fout_vpll", 

"fin_pll",

drivers/clk/samsung/clk-exynos4.c void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so

Quoted 3 lines
drivers/clk/samsung/clk-exynos4.c +2 -1
-					reg_base + VPLL_CON0);
+		samsung_clk_register_pll(exynos4_plls,
+					ARRAY_SIZE(exynos4_plls), 

reg_base);

Quoted 71 lines
drivers/clk/samsung/clk-exynos4.c +0 -5
 	}
 
-	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,
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-exynos5250.c index 7c68850..dc6a700 100644

drivers/clk/samsung/clk-exynos5250.c +20 -1
@@ -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 {

drivers/clk/samsung/clk-exynos5250.c +2 -1
 	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, @@ -470,11 +490,27 @@ static __initdata struct of_device_id ext_clk_match[] = { { },
};

drivers/clk/samsung/clk-exynos5250.c

Quoted 2 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
+struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
+	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", 

APLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c

Quoted 2 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
+		APLL_CON0, "fout_apll"),
+	[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", 

MPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c

Quoted 2 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
+		MPLL_CON0, "fout_mpll"),
+	[bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", 

BPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c

Quoted 2 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
+		BPLL_CON0),
+	[gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", 

GPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c

Quoted 2 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
+		GPLL_CON0),
+	[cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", 

CPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c

Quoted 2 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
+		CPLL_CON0),
+	[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", 

EPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c

Quoted 2 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
+		EPLL_CON0),
+	[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", 

VPLL_LOCK,

Quoted 22 lines
drivers/clk/samsung/clk-exynos5250.c +3 -8
+		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);
@@ -490,22 +526,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);

drivers/clk/samsung/clk-exynos5250.c void __init exynos5250_clk_init(struct device_node · line 529

Quoted 10 lines
drivers/clk/samsung/clk-exynos5250.c +1 -9
-	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),

Quoted 70 lines
drivers/clk/samsung/clk-exynos5250.c +1 -0
+					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,
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-exynos5420.c index 68a96cb..3ea6b4f 100644

drivers/clk/samsung/clk-exynos5420.c +31 -2
@@ -17,13 +17,30 @@
 #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 DIV_CPU1		0x504
 #define GATE_BUS_CPU		0x700
 #define GATE_SCLK_CPU		0x800
+#define CPLL_LOCK		0x10020
+#define DPLL_LOCK		0x10030
+#define EPLL_LOCK		0x10040
+#define RPLL_LOCK		0x10050
+#define IPLL_LOCK		0x10060
+#define SPLL_LOCK		0x10070
+#define VPLL_LOCK		0x10070
+#define MPLL_LOCK		0x10090
+#define CPLL_CON0		0x10120
+#define DPLL_CON0		0x10128
+#define EPLL_CON0		0x10130
+#define RPLL_CON0		0x10140
+#define IPLL_CON0		0x10150
+#define SPLL_CON0		0x10160
+#define VPLL_CON0		0x10170
+#define MPLL_CON0		0x10180
 #define SRC_TOP0		0x10200
 #define SRC_TOP1		0x10204
 #define SRC_TOP2		0x10208
@@ -75,15 +92,27 @@
 #define GATE_TOP_SCLK_MAU	0x1083c
 #define GATE_TOP_SCLK_FSYS	0x10840
 #define GATE_TOP_SCLK_PERIC	0x10850
+#define BPLL_LOCK		0x20010
+#define BPLL_CON0		0x20110
 #define SRC_CDREX		0x20200
+#define KPLL_LOCK		0x28000
+#define KPLL_CON0		0x28100
 #define SRC_KFC			0x28200
 #define DIV_KFC0		0x28500
 
+/* list of PLLs */
+enum exynos5420_plls {
+	apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll,
+	bpll, kpll,
+	nr_plls			/* number of PLLs */
+};
+
 enum exynos5420_clks {
 	none,
 
 	/* core clocks */
-	fin_pll,
+	fin_pll,  fout_apll, fout_cpll, fout_dpll, fout_epll, fout_rpll,
+	fout_ipll, fout_spll, fout_vpll, fout_mpll, fout_bpll, fout_kpll,
 
 	/* gate for special clocks (sclk) */
 	sclk_uart0 = 128, sclk_uart1, sclk_uart2, sclk_uart3, sclk_mmc0,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 731

Quoted 5 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
@@ -698,6 +727,31 @@ struct samsung_gate_clock exynos5420_gate_clks[]
 __initdata = { GATE(smmu_mscl2, "smmu_mscl2", "aclk400_mscl",
 GATE_IP_MSCL, 10, 0, 0), };
 
+struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = {
+	[apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", 

APLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 733

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		APLL_CON0),
+	[cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", 

MPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 735

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		MPLL_CON0),
+	[dpll] = PLL(pll_2550, fout_dpll, "fout_dpll", "fin_pll", 

DPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 737

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		DPLL_CON0),
+	[epll] = PLL(pll_2650, fout_epll, "fout_epll", "fin_pll", 

EPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 739

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		EPLL_CON0),
+	[rpll] = PLL(pll_2650, fout_rpll, "fout_rpll", "fin_pll", 

RPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 741

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		RPLL_CON0),
+	[ipll] = PLL(pll_2550, fout_ipll, "fout_ipll", "fin_pll", 

IPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 743

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		IPLL_CON0),
+	[spll] = PLL(pll_2550, fout_spll, "fout_spll", "fin_pll", 

SPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 745

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		SPLL_CON0),
+	[vpll] = PLL(pll_2550, fout_vpll, "fout_vpll", "fin_pll", 

VPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 747

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		VPLL_CON0),
+	[mpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", 

MPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 749

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		MPLL_CON0),
+	[bpll] = PLL(pll_2550, fout_bpll, "fout_bpll", "fin_pll", 

BPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 751

Quoted 2 lines
drivers/clk/samsung/clk-exynos5420.c +2 -0
+		BPLL_CON0),
+	[kpll] = PLL(pll_2550, fout_kpll, "fout_kpll", "fin_pll", 

KPLL_LOCK,

Quoted 35 lines
drivers/clk/samsung/clk-exynos5420.c +3 -0
+		KPLL_CON0),
+};
+
 static __initdata struct of_device_id ext_clk_match[] = {
 	{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
 	{ },
@@ -707,8 +761,6 @@ static __initdata struct of_device_id

ext_clk_match[] = { void __init exynos5420_clk_init(struct device_node *np)
{

drivers/clk/samsung/clk-exynos5420.c +0 -17
 	void __iomem *reg_base;
-	struct clk *apll, *bpll, *cpll, *dpll, *epll, *ipll, *kpll, *mpll;
-	struct clk *rpll, *spll, *vpll;
 
 	if (np) {
 		reg_base = of_iomap(np, 0);
@@ -724,30 +776,8 @@ void __init exynos5420_clk_init(struct device_node
 *np) samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks,
 ARRAY_SIZE(exynos5420_fixed_rate_ext_clks),
 			ext_clk_match);
-
-	apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
-			reg_base + 0x100);
-	bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
-			reg_base + 0x20110);
-	cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
-			reg_base + 0x10120);
-	dpll = samsung_clk_register_pll35xx("fout_dpll", "fin_pll",
-			reg_base + 0x10128);
-	epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
-			reg_base + 0x10130);
-	ipll = samsung_clk_register_pll35xx("fout_ipll", "fin_pll",
-			reg_base + 0x10150);
-	kpll = samsung_clk_register_pll35xx("fout_kpll", "fin_pll",
-			reg_base + 0x28100);

drivers/clk/samsung/clk-exynos5420.c void __init exynos5420_clk_init(struct device_node · line 779

Quoted 10 lines
drivers/clk/samsung/clk-exynos5420.c +1 -9
-	mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
-			reg_base + 0x10180);
-	rpll = samsung_clk_register_pll36xx("fout_rpll", "fin_pll",
-			reg_base + 0x10140);
-	spll = samsung_clk_register_pll35xx("fout_spll", "fin_pll",
-			reg_base + 0x10160);
-	vpll = samsung_clk_register_pll35xx("fout_vpll", "fin_pll",
-			reg_base + 0x10170);
-
+	samsung_clk_register_pll(exynos5420_plls, 

ARRAY_SIZE(exynos5420_plls),

Quoted 20 lines
drivers/clk/samsung/clk-exynos5420.c +1 -0
+					reg_base);
 	samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks,
 			ARRAY_SIZE(exynos5420_fixed_rate_clks));
 	samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks,
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-pll.c index 8224bde..f132353 100644

drivers/clk/samsung/clk-pll.c +1 -0
@@ -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,
 };
 

drivers/clk/samsung/clk-pll.c static const struct clk_ops samsung_pll35xx_clk_ops = · line 66

Quoted 10 lines
drivers/clk/samsung/clk-pll.c +0 -10
-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);

Quoted 11 lines
drivers/clk/samsung/clk-pll.c +0 -11
-		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;

drivers/clk/samsung/clk-pll.c static const struct clk_ops samsung_pll35xx_clk_ops = {

Quoted 10 lines
drivers/clk/samsung/clk-pll.c +0 -10
-
-	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);

Quoted 11 lines
drivers/clk/samsung/clk-pll.c +0 -4
-
-	return clk;
-}
-
 /*
  * PLL36xx Clock Type
  */
@@ -126,41 +92,6 @@ static const struct clk_ops samsung_pll36xx_clk_ops
 = { .recalc_rate = samsung_pll36xx_recalc_rate,
 };
 

drivers/clk/samsung/clk-pll.c static const struct clk_ops samsung_pll36xx_clk_ops · line 138

Quoted 10 lines
drivers/clk/samsung/clk-pll.c +0 -10
-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);

Quoted 11 lines
drivers/clk/samsung/clk-pll.c +0 -11
-		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;

drivers/clk/samsung/clk-pll.c static const struct clk_ops samsung_pll36xx_clk_ops = {

Quoted 10 lines
drivers/clk/samsung/clk-pll.c +0 -10
-
-	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);

Quoted 14 lines
drivers/clk/samsung/clk-pll.c +2 -4
-
-	return clk;
-}
-
 /*
  * PLL45xx Clock Type
  */
@@ -411,3 +342,64 @@ struct clk * __init
 samsung_clk_register_pll2550x(const char *name,
 
 	return clk;
 }
+
+void __init samsung_clk_register_pll(struct samsung_pll_clock
Quoted 1 line

*clk_list, + unsigned int nr_pll, void __iomem

*base)

drivers/clk/samsung/clk-pll.c struct clk * __init samsung_clk_register_pll2550x(const char *name, · line 355

Quoted 8 lines
drivers/clk/samsung/clk-pll.c +8 -0
+{
+	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++) {

I'd suggest moving contents of this loop to a function like following?

static int __init _samsung_clk_register_pll(struct samsung_pll_clock *pll,
void __iomem *base)

This will make the code less indented and so more readable.

Quoted 36 lines
drivers/clk/samsung/clk-pll.c +36 -0
+		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) {
+		/* clk_ops for 35xx and 2550 are similar */
+		case pll_35xx:
+		case pll_2550:
+			init.ops = &samsung_pll35xx_clk_ops;
+			break;
+		/* clk_ops for 36xx and 2650 are similar */
+		case pll_36xx:
+		case pll_2650:
+			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",

drivers/clk/samsung/clk-pll.c struct clk * __init samsung_clk_register_pll2550x(const char *name, · line 401

Quoted 10 lines
drivers/clk/samsung/clk-pll.c +10 -0
+				__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))

What about

		if (!list->alias)
			return;

		ret = clk_register_clkdev(clk, list->alias, list-
Quoted 1 line

dev_name);

		if (ret)
			pr_err("%s: failed to register lookup for %s",
						__func__, list->name);

drivers/clk/samsung/clk-pll.c

Quoted 1 line
drivers/clk/samsung/clk-pll.c +1 -0
+				pr_err("%s: failed to register lookup for 

%s",

Quoted 22 lines
drivers/clk/samsung/clk-pll.c +3 -0
+					__func__, list->name);
+	}
+}
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-pll.h index f33786e..1536f27 100644

drivers/clk/samsung/clk-pll.h +7 -0
@@ -12,6 +12,13 @@
 #ifndef __SAMSUNG_CLK_PLL_H
 #define __SAMSUNG_CLK_PLL_H
 
+enum samsung_pll_type {
+	pll_35xx,
+	pll_36xx,
+	pll_2550,
+	pll_2650,
+};
+
 enum pll45xx_type {
 	pll_4500,
 	pll_4502,

drivers/clk/samsung/clk-pll.h enum pll46xx_type { · line 34

Quoted 5 lines
drivers/clk/samsung/clk-pll.h +0 -1
@@ -24,10 +31,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);

drivers/clk/samsung/clk-pll.h enum pll46xx_type { · line 35

Quoted 2 lines
drivers/clk/samsung/clk-pll.h +0 -1
-extern struct clk * __init samsung_clk_register_pll36xx(const char
 *name, -			const char *pname, const void __iomem 

*con_reg);

Quoted 29 lines
drivers/clk/samsung/clk-pll.h +0 -0
 extern struct clk * __init samsung_clk_register_pll45xx(const char

*name, const char *pname, const void __iomem *con_reg,

drivers/clk/samsung/clk-pll.h +0 -0
 			enum pll45xx_type type);
drivers/clk/samsung/clk.h +11 -0
index e4ad6ea..51f60ca 100644
@@ -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.

drivers/clk/samsung/clk.h struct samsung_clk_reg_dump { · line 281

Quoted 10 lines
drivers/clk/samsung/clk.h +10 -0
+ * @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;

I don't see any point of having all those const qualifiers of non- pointers. This makes the struct useless for creating and initializing at runtime.

drivers/clk/samsung/clk.h struct samsung_clk_reg_dump { · line 282

Quoted 1 line
drivers/clk/samsung/clk.h +1 -0
+	enum			samsung_pll_type type;

IMHO the enum keyword shouldn't be separated from enum name like this.

Otherwise the patch looks fine. Maybe it's a bit too big - things could be done a bit more gradually, like:
1) first add required structs and functions,
2) then move existing clock drivers to use the new API, possibly one patch per driver,
3) remove the old API.

This would make the whole change easier to review and, in case of any regressions, easier to track down the problem.

Best regards,
Tomasz

drivers/clk/samsung/clk.h struct samsung_clk_reg_dump {

Quoted 5 lines
drivers/clk/samsung/clk.h +4 -0
+	const char              *alias;
+};
+
+#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con,
 _alias) \ +	{								

\

Quoted 30 lines
drivers/clk/samsung/clk.h +20 -0
+		.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);
#5 lore raw

PATCH v6 2/7 clk: samsung: Define a common samsung_clk_register_pll()

Quoted 25 lines · Tomasz Figa

Hi Yadwinder,

Generally looks really good, but some comments inline.

Quoted 8 lines · On Monday 10 of June 2013 18:54:14 Yadwinder Singh Brar wrote:

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. It also adds exynos5250 & exynos5420 PLLs to unique id list of clocks. Since pll2550 & pll35xx and pll2650 & pll36xx have exactly same clk ops implementation, added pll2550 and pll2650 also.

+void __init samsung_clk_register_pll(struct samsung_pll_clock
*clk_list, + unsigned int nr_pll, void __iomem

*base)

drivers/clk/samsung/clk-pll.c struct clk * __init samsung_clk_register_pll2550x(const char *name, · line 355

Quoted 8 lines
drivers/clk/samsung/clk-pll.c +8 -0
+{
+     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++) {

I'd suggest moving contents of this loop to a function like following?

Quoted 5 lines

static int __init _samsung_clk_register_pll(struct samsung_pll_clock *pll,
void __iomem *base)

This will make the code less indented and so more readable.

Yes, will do it.

Quoted 49 lines
Quoted 36 lines
drivers/clk/samsung/clk-pll.c +36 -0
+             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) {
+             /* clk_ops for 35xx and 2550 are similar */
+             case pll_35xx:
+             case pll_2550:
+                     init.ops = &samsung_pll35xx_clk_ops;
+                     break;
+             /* clk_ops for 36xx and 2650 are similar */
+             case pll_36xx:
+             case pll_2650:
+                     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",

drivers/clk/samsung/clk-pll.c struct clk * __init samsung_clk_register_pll2550x(const char *name, · line 401

Quoted 10 lines
drivers/clk/samsung/clk-pll.c +10 -0
+                             __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))

What about

Quoted 9 lines
                if (!list->alias)
                        return;

                ret = clk_register_clkdev(clk, list->alias, list-
Quoted 1 line

dev_name);

if (ret)
pr_err("%s: failed to register lookup for %s",
__func__, list->name);

its ok, but to me it looks more clear and precise inside if(){ }, as its length and indentation is not much deep.
If you really insist we can do it ?

Quoted 15 lines
Quoted 1 line

+ pr_err("%s: failed to register lookup for

%s",

drivers/clk/samsung/clk.h struct samsung_clk_reg_dump { · line 281

Quoted 12 lines
drivers/clk/samsung/clk.h +11 -0
+                                     __func__, list->name);
+     }
+}
 
+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;
Quoted 4 lines

I don't see any point of having all those const qualifiers of non- pointers. This makes the struct useless for creating and initializing at runtime.

OK, will remove it.

Quoted 4 lines
Quoted 1 line

+ enum samsung_pll_type type;

IMHO the enum keyword shouldn't be separated from enum name like this.

Any specific reason? Just to keep indentation same for all members, I used tabs :).

Quoted 10 lines

Otherwise the patch looks fine. Maybe it's a bit too big - things could be done a bit more gradually, like:
1) first add required structs and functions,
2) then move existing clock drivers to use the new API, possibly one patch per driver,
3) remove the old API.

This would make the whole change easier to review and, in case of any regressions, easier to track down the problem.

OK, I will split it.

Thanks,
Yadwinder

#6 lore raw

PATCH v6 2/7 clk: samsung: Define a common samsung_clk_register_pll()

Quoted 1 line · On Wednesday 19 of June 2013 23:44:47 Yadwinder Singh Brar wrote:

On Wed, Jun 19, 2013 at 10:24 PM, Tomasz Figa <[email protected]>

Quoted 97 lines · wrote:
Quoted 29 lines

Hi Yadwinder,

Generally looks really good, but some comments inline.

Quoted 10 lines · On Monday 10 of June 2013 18:54:14 Yadwinder Singh Brar wrote:

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. It also adds exynos5250 & exynos5420 PLLs to unique id list of clocks. Since pll2550 & pll35xx and pll2650 & pll36xx have exactly same clk ops implementation, added pll2550 and pll2650 also.

+void __init samsung_clk_register_pll(struct samsung_pll_clock
*clk_list, + unsigned int nr_pll, void
__iomem

*base)

drivers/clk/samsung/clk-pll.c struct clk * __init samsung_clk_register_pll2550x(const char *name, · line 355

Quoted 8 lines
drivers/clk/samsung/clk-pll.c +8 -0
+{
+     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++) {

I'd suggest moving contents of this loop to a function like following?

Quoted 5 lines

static int __init _samsung_clk_register_pll(struct samsung_pll_clock *pll,>
void __iomem *base)

This will make the code less indented and so more readable.

Yes, will do it.

Quoted 60 lines
Quoted 37 lines
drivers/clk/samsung/clk-pll.c +25 -0
+             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) {
+             /* clk_ops for 35xx and 2550 are similar */
+             case pll_35xx:
+             case pll_2550:
+                     init.ops = &samsung_pll35xx_clk_ops;
+                     break;
+             /* clk_ops for 36xx and 2650 are similar */
+             case pll_36xx:
+             case pll_2650:
+                     init.ops = &samsung_pll36xx_clk_ops;
+                     break;
+             default:
+                     pr_warn("%s: Unknown pll type for pll clk

%s\n",

drivers/clk/samsung/clk-pll.c +11 -0
+                             __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",

drivers/clk/samsung/clk-pll.c struct clk * __init samsung_clk_register_pll2550x(const char *name, · line 401

Quoted 10 lines
drivers/clk/samsung/clk-pll.c +10 -0
+                             __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))

What about

                if (!list->alias)
                
                        return;
                
                ret = clk_register_clkdev(clk, list->alias, list-
Quoted 3 lines

dev_name);

if (ret)

Quoted 7 lines
Quoted 3 lines

pr_err("%s: failed to register lookup for %s",

__func__, list->name);

its ok, but to me it looks more clear and precise inside if(){ }, as its length and indentation is not much deep.
If you really insist we can do it ?

Well, you can read the code as the CPU does - if you are not interested in the alias you can see instantly that you don't have to read this function any more, because it returns if alias is NULL.

And it's always good to have lower indentation level. :)

Quoted 22 lines
Quoted 9 lines
Quoted 2 lines

+ pr_err("%s: failed to register lookup
for

%s",

Quoted 4 lines
drivers/clk/samsung/clk-pll.c +3 -0
+                                     __func__, list->name);
+     }
+}
Quoted 12 lines

drivers/clk/samsung/clk.h struct samsung_clk_reg_dump { · line 281

Quoted 8 lines
drivers/clk/samsung/clk.h +8 -0
+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;

I don't see any point of having all those const qualifiers of non- pointers. This makes the struct useless for creating and initializing at runtime.

Quoted 8 lines

OK, will remove it.

Quoted 3 lines
Quoted 1 line

+ enum samsung_pll_type type;

IMHO the enum keyword shouldn't be separated from enum name like this.

Any specific reason? Just to keep indentation same for all members, I used tabs :).

Well, "enum samsung_pll_type" is the type name, not "enum" and "type" is name of the member, not "samsung_pll_type type".

Just imagine "unsigned long x" separated to "unsigned" "long x". Isn't it a bit awkward?

Anyway, thanks for your good work on improving this patch series continuously. :)

Best regards,
Tomasz

Quoted 14 lines
Quoted 9 lines

Otherwise the patch looks fine. Maybe it's a bit too big - things could be done a bit more gradually, like:
1) first add required structs and functions,
2) then move existing clock drivers to use the new API, possibly one patch per driver,
3) remove the old API.

This would make the whole change easier to review and, in case of any regressions, easier to track down the problem.

OK, I will split it.

Thanks,
Yadwinder

#7 lore raw

PATCH v6 3/7 clk: samsung: Add support to register rate_table for samsung plls

In reply to Yadwinder Singh Brar

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.

---
 drivers/clk/samsung/clk-exynos4.c    |    8 ++++----
 drivers/clk/samsung/clk-exynos5250.c |   14 +++++++-------
 drivers/clk/samsung/clk-exynos5420.c |   22 +++++++++++-----------
 drivers/clk/samsung/clk-pll.c        |   22 ++++++++++++++++++++--
 drivers/clk/samsung/clk-pll.h        |   27 +++++++++++++++++++++++++++
 drivers/clk/samsung/clk.h            |   14 +++++++++-----
 6 files changed, 78 insertions(+), 29 deletions(-)
drivers/clk/samsung/clk-exynos4.c +4 -4
index ba25a1b..ceee66c 100644
@@ -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 */
drivers/clk/samsung/clk-exynos5250.c +7 -7
index dc6a700..21f5491 100644
@@ -492,19 +492,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 */
drivers/clk/samsung/clk-exynos5420.c +11 -11
index 3ea6b4f..86dfc64 100644
@@ -729,27 +729,27 @@ struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {
 
 struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = {
 	[apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
-		APLL_CON0),
+		APLL_CON0, NULL),
 	[cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
-		MPLL_CON0),
+		MPLL_CON0, NULL),
 	[dpll] = PLL(pll_2550, fout_dpll, "fout_dpll", "fin_pll", DPLL_LOCK,
-		DPLL_CON0),
+		DPLL_CON0, NULL),
 	[epll] = PLL(pll_2650, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
-		EPLL_CON0),
+		EPLL_CON0, NULL),
 	[rpll] = PLL(pll_2650, fout_rpll, "fout_rpll", "fin_pll", RPLL_LOCK,
-		RPLL_CON0),
+		RPLL_CON0, NULL),
 	[ipll] = PLL(pll_2550, fout_ipll, "fout_ipll", "fin_pll", IPLL_LOCK,
-		IPLL_CON0),
+		IPLL_CON0, NULL),
 	[spll] = PLL(pll_2550, fout_spll, "fout_spll", "fin_pll", SPLL_LOCK,
-		SPLL_CON0),
+		SPLL_CON0, NULL),
 	[vpll] = PLL(pll_2550, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
-		VPLL_CON0),
+		VPLL_CON0, NULL),
 	[mpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
-		MPLL_CON0),
+		MPLL_CON0, NULL),
 	[bpll] = PLL(pll_2550, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
-		BPLL_CON0),
+		BPLL_CON0, NULL),
 	[kpll] = PLL(pll_2550, fout_kpll, "fout_kpll", "fin_pll", KPLL_LOCK,
-		KPLL_CON0),
+		KPLL_CON0, NULL),
 };
 
 static __initdata struct of_device_id ext_clk_match[] = {
drivers/clk/samsung/clk-pll.c +20 -2
index f132353..b2088dd 100644
@@ -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) {
 		/* clk_ops for 35xx and 2550 are similar */
 		case pll_35xx:
@@ -396,10 +413,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);
+		}
 	}
 }
drivers/clk/samsung/clk-pll.h +27 -0
index 1536f27..95ae23d 100644
@@ -19,6 +19,33 @@ enum samsung_pll_type {
 	pll_2650,
 };
 
+#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,
drivers/clk/samsung/clk.h +9 -5
index 51f60ca..3e6501c 100644
@@ -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,
Signature · 1 line
1.7.0.4
#8 lore raw

PATCH v6 3/7 clk: samsung: Add support to register rate_table for samsung plls

Quoted 20 lines · On Monday 10 of June 2013 18:54:15 Yadwinder Singh Brar wrote:

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.

---
 drivers/clk/samsung/clk-exynos4.c    |    8 ++++----
 drivers/clk/samsung/clk-exynos5250.c |   14 +++++++-------
 drivers/clk/samsung/clk-exynos5420.c |   22 +++++++++++-----------
 drivers/clk/samsung/clk-pll.c        |   22 ++++++++++++++++++++--
 drivers/clk/samsung/clk-pll.h        |   27 +++++++++++++++++++++++++++
drivers/clk/samsung/clk.h            |   14 +++++++++-----
 6 files changed, 78 insertions(+), 29 deletions(-)
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-exynos4.c index ba25a1b..ceee66c 100644

drivers/clk/samsung/clk-exynos4.c static __initdata struct of_device_id · line 1000

Quoted 4 lines
drivers/clk/samsung/clk-exynos4.c +0 -0
@@ -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,

drivers/clk/samsung/clk-exynos4.c static __initdata struct of_device_id ext_clk_match[] = {

Quoted 6 lines
drivers/clk/samsung/clk-exynos4.c +2 -2
-		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,

drivers/clk/samsung/clk-exynos4.c static __initdata struct of_device_id ext_clk_match[] = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos4.c +1 -1
-		EPLL_CON0, "fout_epll"),
+		EPLL_CON0, "fout_epll", NULL),
 	[vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", 

VPLL_LOCK,

Quoted 10 lines
drivers/clk/samsung/clk-exynos4.c +1 -1
-		VPLL_CON0, "fout_vpll"),
+		VPLL_CON0, "fout_vpll", NULL),
 };
 

/* register exynos4 clocks */

(quoted diff) +0 -0

b/drivers/clk/samsung/clk-exynos5250.c index dc6a700..21f5491 100644

drivers/clk/samsung/clk-exynos5250.c static __initdata struct of_device_id · line 495

Quoted 4 lines
drivers/clk/samsung/clk-exynos5250.c +0 -0
@@ -492,19 +492,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,

drivers/clk/samsung/clk-exynos5250.c static __initdata struct of_device_id · line 497

Quoted 3 lines
drivers/clk/samsung/clk-exynos5250.c +1 -1
-		APLL_CON0, "fout_apll"),
+		APLL_CON0, "fout_apll", NULL),
 	[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", 

MPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c static __initdata struct of_device_id ext_clk_match[] = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5250.c +1 -1
-		MPLL_CON0, "fout_mpll"),
+		MPLL_CON0, "fout_mpll", NULL),
 	[bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", 

BPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c static __initdata struct of_device_id ext_clk_match[] = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5250.c +1 -1
-		BPLL_CON0),
+		BPLL_CON0, NULL),
 	[gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", 

GPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c static __initdata struct of_device_id ext_clk_match[] = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5250.c +1 -1
-		GPLL_CON0),
+		GPLL_CON0, NULL),
 	[cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", 

CPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c static __initdata struct of_device_id ext_clk_match[] = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5250.c +1 -1
-		CPLL_CON0),
+		CPLL_CON0, NULL),
 	[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", 

EPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c static __initdata struct of_device_id ext_clk_match[] = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5250.c +1 -1
-		EPLL_CON0),
+		EPLL_CON0, NULL),
 	[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", 

VPLL_LOCK,

Quoted 10 lines
drivers/clk/samsung/clk-exynos5250.c +1 -1
-		VPLL_CON0),
+		VPLL_CON0, NULL),
 };
 

/* register exynox5250 clocks */

(quoted diff) +0 -0

b/drivers/clk/samsung/clk-exynos5420.c index 3ea6b4f..86dfc64 100644

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 732

Quoted 4 lines
drivers/clk/samsung/clk-exynos5420.c +0 -0
@@ -729,27 +729,27 @@ struct samsung_gate_clock exynos5420_gate_clks[]
 __initdata = {
 
 struct __initdata samsung_pll_clock exynos5420_plls[nr_plls] = {
 	[apll] = PLL(pll_2550, fout_apll, "fout_apll", "fin_pll", 

APLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		APLL_CON0),
+		APLL_CON0, NULL),
 	[cpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", 

MPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		MPLL_CON0),
+		MPLL_CON0, NULL),
 	[dpll] = PLL(pll_2550, fout_dpll, "fout_dpll", "fin_pll", 

DPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		DPLL_CON0),
+		DPLL_CON0, NULL),
 	[epll] = PLL(pll_2650, fout_epll, "fout_epll", "fin_pll", 

EPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 740

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		EPLL_CON0),
+		EPLL_CON0, NULL),
 	[rpll] = PLL(pll_2650, fout_rpll, "fout_rpll", "fin_pll", 

RPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		RPLL_CON0),
+		RPLL_CON0, NULL),
 	[ipll] = PLL(pll_2550, fout_ipll, "fout_ipll", "fin_pll", 

IPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		IPLL_CON0),
+		IPLL_CON0, NULL),
 	[spll] = PLL(pll_2550, fout_spll, "fout_spll", "fin_pll", 

SPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		SPLL_CON0),
+		SPLL_CON0, NULL),
 	[vpll] = PLL(pll_2550, fout_vpll, "fout_vpll", "fin_pll", 

VPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 748

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		VPLL_CON0),
+		VPLL_CON0, NULL),
 	[mpll] = PLL(pll_2550, fout_mpll, "fout_mpll", "fin_pll", 

MPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] __initdata = {

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		MPLL_CON0),
+		MPLL_CON0, NULL),
 	[bpll] = PLL(pll_2550, fout_bpll, "fout_bpll", "fin_pll", 

BPLL_LOCK,

drivers/clk/samsung/clk-exynos5420.c struct samsung_gate_clock exynos5420_gate_clks[] · line 752

Quoted 3 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		BPLL_CON0),
+		BPLL_CON0, NULL),
 	[kpll] = PLL(pll_2550, fout_kpll, "fout_kpll", "fin_pll", 

KPLL_LOCK,

Quoted 30 lines
drivers/clk/samsung/clk-exynos5420.c +1 -1
-		KPLL_CON0),
+		KPLL_CON0, NULL),
 };
 

static __initdata struct of_device_id ext_clk_match[] = {

(quoted diff) +0 -0

b/drivers/clk/samsung/clk-pll.c index f132353..b2088dd 100644

drivers/clk/samsung/clk-pll.c +3 -1
@@ -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;

drivers/clk/samsung/clk-pll.c void __init samsung_clk_register_pll(struct · line 378

Quoted 10 lines
drivers/clk/samsung/clk-pll.c +9 -0
 
+		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),

drivers/clk/samsung/clk-pll.c void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,

Quoted 3 lines
drivers/clk/samsung/clk-pll.c +3 -0
+					GFP_KERNEL);
+			WARN(!pll->rate_table,
+				"%s: could not allocate rate table for 

%s\n",

drivers/clk/samsung/clk-pll.c void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list, · line 382

Quoted 1 line
drivers/clk/samsung/clk-pll.c +1 -0
+				__func__, list->name);

This warning is not needed, because kmalloc() already prints a warning when allocation fails.

drivers/clk/samsung/clk-pll.c void __init samsung_clk_register_pll(struct · line 417

Quoted 12 lines
drivers/clk/samsung/clk-pll.c +3 -1
+		}
+
 		switch (list->type) {
 		/* clk_ops for 35xx and 2550 are similar */
 		case pll_35xx:
@@ -396,10 +413,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) {

What about

		if (!list->alias)
			return;

		ret = clk_register_clkdev(clk, list->alias, list-

drivers/clk/samsung/clk-pll.c void __init samsung_clk_register_pll(struct · line 418

Quoted 1 line
drivers/clk/samsung/clk-pll.c +0 -0
 dev_name);

if (ret)
pr_err("%s: failed to register lookup for %s",

This will make the code a bit nicer to read.

Otherwise looks good.

Best regards,
Tomasz

drivers/clk/samsung/clk-pll.c void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,

Quoted 3 lines
drivers/clk/samsung/clk-pll.c +0 -0
 			if (clk_register_clkdev(clk, list->alias,
 				list->dev_name))
 				pr_err("%s: failed to register lookup for 

%s",

Quoted 48 lines
drivers/clk/samsung/clk-pll.c +1 -0
 					__func__, list->name);
+		}
drivers/clk/samsung/clk-pll.c +0 -0
 	}
 }
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-pll.h index 1536f27..95ae23d 100644

drivers/clk/samsung/clk-pll.h +27 -0
@@ -19,6 +19,33 @@ enum samsung_pll_type {
 	pll_2650,
 };
 
+#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,
drivers/clk/samsung/clk.h +0 -0
index 51f60ca..3e6501c 100644
@@ -280,10 +280,13 @@ struct samsung_pll_clock {
 	const int		con_offset;

drivers/clk/samsung/clk.h struct samsung_pll_clock { · line 289

Quoted 10 lines
drivers/clk/samsung/clk.h +2 -1
 	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)				
	\
Quoted 19 lines
drivers/clk/samsung/clk.h +4 -3
 	{								\
 		.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) \
Quoted 1 line

__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ -

_lock,

Quoted 5 lines

_con, _alias)

drivers/clk/samsung/clk.h +1 -0
+		_lock, _con, _rtable, _alias)
 
 extern void __init samsung_clk_init(struct device_node *np, void

__iomem *base, unsigned long nr_clks, unsigned long *rdump,

#9 lore raw

PATCH v6 4/7 clk: samsung: Add set_rate() clk_ops for PLL35xx

In reply to Yadwinder Singh Brar

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

---
 drivers/clk/samsung/clk-pll.c |  105 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 104 insertions(+), 1 deletions(-)
drivers/clk/samsung/clk-pll.c +104 -1
index b2088dd..e3e7f0c 100644
@@ -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,73 @@ 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,
 };
 
 /*
@@ -386,7 +486,10 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
 		/* clk_ops for 35xx and 2550 are similar */
 		case pll_35xx:
 		case pll_2550:
-			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;
 		/* clk_ops for 36xx and 2650 are similar */
 		case pll_36xx:
Signature · 1 line
1.7.0.4
#10 lore raw

PATCH v6 4/7 clk: samsung: Add set_rate() clk_ops for PLL35xx

Quoted 15 lines · On Monday 10 of June 2013 18:54:16 Yadwinder Singh Brar wrote:

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

---
 drivers/clk/samsung/clk-pll.c |  105

++++++++++++++++++++++++++++++++++++++++- 1 files changed, 104 insertions(+), 1 deletions(-)

(quoted diff) +0 -0

b/drivers/clk/samsung/clk-pll.c index b2088dd..e3e7f0c 100644

drivers/clk/samsung/clk-pll.c struct samsung_clk_pll { · line 28

Quoted 5 lines
drivers/clk/samsung/clk-pll.c +2 -0
@@ -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)

Quoted 65 lines
drivers/clk/samsung/clk-pll.c +33 -0
+{
+	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,
drivers/clk/samsung/clk-pll.c +0 -0
 				unsigned long parent_rate)
@@ -53,8 +88,73 @@ static unsigned long

samsung_pll35xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco;
}

drivers/clk/samsung/clk-pll.c +12 -0
+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)

drivers/clk/samsung/clk-pll.c static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,

Quoted 9 lines
drivers/clk/samsung/clk-pll.c +9 -0
+{
+	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__,

Quoted 51 lines
drivers/clk/samsung/clk-pll.c +43 -0
+			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,
 };
 
 /*
@@ -386,7 +486,10 @@ void __init samsung_clk_register_pll(struct

samsung_pll_clock *clk_list, /* clk_ops for 35xx and 2550 are similar */

drivers/clk/samsung/clk-pll.c void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list, · line 495

Quoted 10 lines
drivers/clk/samsung/clk-pll.c +4 -1
 		case pll_35xx:
 		case pll_2550:
-			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;
 		/* clk_ops for 36xx and 2650 are similar */
 		case pll_36xx:

Looks good.

Best regards,
Tomasz

#11 lore raw

PATCH v6 5/7 clk: samsung: Add set_rate() clk_ops for PLL36xx

In reply to Yadwinder Singh Brar

From: Vikas Sajjan <[email protected]>

This patch adds set_rate and round_rate clk_ops for PLL36xx

---
 drivers/clk/samsung/clk-pll.c |   79 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 78 insertions(+), 1 deletions(-)
drivers/clk/samsung/clk-pll.c +78 -1
index e3e7f0c..2197004 100644
@@ -160,6 +160,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)
@@ -168,6 +170,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)
@@ -190,8 +194,78 @@ 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,
 };
 
 /*
@@ -494,7 +568,10 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
 		/* clk_ops for 36xx and 2650 are similar */
 		case pll_36xx:
 		case pll_2650:
-			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",
Signature · 1 line
1.7.0.4
#12 lore raw

PATCH v6 5/7 clk: samsung: Add set_rate() clk_ops for PLL36xx

Quoted 39 lines · On Monday 10 of June 2013 18:54:17 Yadwinder Singh Brar wrote:

From: Vikas Sajjan <[email protected]>

This patch adds set_rate and round_rate clk_ops for PLL36xx

---
 drivers/clk/samsung/clk-pll.c |   79

++++++++++++++++++++++++++++++++++++++++- 1 files changed, 78 insertions(+), 1 deletions(-)

(quoted diff) +0 -0

b/drivers/clk/samsung/clk-pll.c index e3e7f0c..2197004 100644

drivers/clk/samsung/clk-pll.c +0 -0
@@ -160,6 +160,8 @@ static const struct clk_ops

samsung_pll35xx_clk_min_ops = { /*
* PLL36xx Clock Type
*/

drivers/clk/samsung/clk-pll.c +4 -0
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR    (3000)
 
 #define PLL36XX_KDIV_MASK	(0xFFFF)
 #define PLL36XX_MDIV_MASK	(0x1FF)
@@ -168,6 +170,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)
@@ -190,8 +194,78 @@ static unsigned long

samsung_pll36xx_recalc_rate(struct clk_hw *hw, return (unsigned long)fvco;
}

drivers/clk/samsung/clk-pll.c

Quoted 2 lines
drivers/clk/samsung/clk-pll.c +2 -0
+static inline bool samsung_pll36xx_mpk_change(
+	const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 

pll_con1)

Quoted 13 lines
drivers/clk/samsung/clk-pll.c +12 -0
+{
+	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)

drivers/clk/samsung/clk-pll.c static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,

Quoted 8 lines
drivers/clk/samsung/clk-pll.c +8 -0
+{
+	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__,

drivers/clk/samsung/clk-pll.c static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, · line 225

Quoted 6 lines
drivers/clk/samsung/clk-pll.c +6 -0
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	pll_con0 = __raw_readl(pll->con_reg);
+	pll_con1 = __raw_readl(pll->con_reg + 4);

Please define offset constants for these two registers.

Otherwise looks good.

Best regards,
Tomasz

Quoted 59 lines
drivers/clk/samsung/clk-pll.c +41 -0
+
+	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,
 };
 
 /*
@@ -494,7 +568,10 @@ void __init samsung_clk_register_pll(struct

samsung_pll_clock *clk_list, /* clk_ops for 36xx and 2650 are similar */

drivers/clk/samsung/clk-pll.c +4 -1
 		case pll_36xx:
 		case pll_2650:
-			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",
#13 lore raw

PATCH v6 6/7 clk: samsung: Reorder MUX registration for mout_vpllsrc

In reply to Yadwinder Singh Brar

From: Vikas Sajjan <[email protected]>

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.

---
 drivers/clk/samsung/clk-exynos5250.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)
drivers/clk/samsung/clk-exynos5250.c +6 -1
index 21f5491..6881810 100644
@@ -228,6 +228,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),
@@ -235,7 +239,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),
@@ -526,6 +529,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,
Signature · 1 line
1.7.0.4
#14 lore raw

PATCH v6 6/7 clk: samsung: Reorder MUX registration for mout_vpllsrc

Quoted 40 lines · On Monday 10 of June 2013 18:54:18 Yadwinder Singh Brar wrote:

From: Vikas Sajjan <[email protected]>

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.

---
 drivers/clk/samsung/clk-exynos5250.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-exynos5250.c index 21f5491..6881810 100644

drivers/clk/samsung/clk-exynos5250.c +4 -0
@@ -228,6 +228,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),
drivers/clk/samsung/clk-exynos5250.c +0 -1
 	MUX(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
@@ -235,7 +239,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),

drivers/clk/samsung/clk-exynos5250.c void __init exynos5250_clk_init(struct device_node · line 534

Quoted 6 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
@@ -526,6 +529,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),

drivers/clk/samsung/clk-exynos5250.c void __init exynos5250_clk_init(struct device_node *np) · line 536

Quoted 2 lines
drivers/clk/samsung/clk-exynos5250.c +0 -0
 reg_base);
 	samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,

Best regards,
Tomasz

#15 lore raw

PATCH v6 7/7 clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

In reply to Yadwinder Singh Brar

Adds the EPLL and VPLL freq table for exynos5250 SoC.

---
 drivers/clk/samsung/clk-exynos5250.c |   42 ++++++++++++++++++++++++++++++++-
 drivers/clk/samsung/clk.h            |    2 +
 2 files changed, 42 insertions(+), 2 deletions(-)
drivers/clk/samsung/clk-exynos5250.c +40 -2
index 6881810..13e293e 100644
@@ -493,6 +493,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, 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)
+	{ },
+};
+
 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),
@@ -506,14 +529,16 @@ struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
 		CPLL_CON0, NULL),
 	[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
 		EPLL_CON0, NULL),
-	[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
-		VPLL_CON0, NULL),
+	[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "mout_vpllsrc",
+		VPLL_LOCK, VPLL_CON0, NULL),
 };
 
 /* register exynox5250 clocks */
 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);
@@ -531,6 +556,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,
drivers/clk/samsung/clk.h +2 -0
index 3e6501c..378bf98 100644
@@ -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.
Signature · 1 line
1.7.0.4
#16 lore raw

PATCH v6 7/7 clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC

Quoted 33 lines · On Monday 10 of June 2013 18:54:19 Yadwinder Singh Brar wrote:

Adds the EPLL and VPLL freq table for exynos5250 SoC.

---
 drivers/clk/samsung/clk-exynos5250.c |   42
++++++++++++++++++++++++++++++++- drivers/clk/samsung/clk.h           
|    2 +
 2 files changed, 42 insertions(+), 2 deletions(-)
(quoted diff) +0 -0

b/drivers/clk/samsung/clk-exynos5250.c index 6881810..13e293e 100644

drivers/clk/samsung/clk-exynos5250.c +15 -0
@@ -493,6 +493,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, 64, 2, 2, 0),
+	PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
+	PLL_36XX_RATE(180000000, 90, 3, 2, 0),

drivers/clk/samsung/clk-exynos5250.c static __initdata struct of_device_id · line 520

Quoted 10 lines
drivers/clk/samsung/clk-exynos5250.c +8 -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)
+	{ },
+};
+
 struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
 	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", 

APLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c struct __initdata samsung_pll_clock · line 530

Quoted 4 lines
drivers/clk/samsung/clk-exynos5250.c +0 -0
 APLL_CON0, "fout_apll", NULL),
@@ -506,14 +529,16 @@ struct __initdata samsung_pll_clock
 exynos5250_plls[nr_plls] = { CPLL_CON0, NULL),
 	[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", 

EPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c struct __initdata samsung_pll_clock · line 509

Quoted 2 lines
drivers/clk/samsung/clk-exynos5250.c +0 -1
 		EPLL_CON0, NULL),
-	[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", 

VPLL_LOCK,

drivers/clk/samsung/clk-exynos5250.c struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = { · line 533

Quoted 3 lines
drivers/clk/samsung/clk-exynos5250.c +2 -1
-		VPLL_CON0, NULL),
+	[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "mout_vpllsrc",
+		VPLL_LOCK, VPLL_CON0, NULL),

IMHO the parent should be fixed in separate patch, as this doesn't seem to be related strictly to adding rate table.

Quoted 12 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
 };
 
 /* register exynox5250 clocks */
 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);

drivers/clk/samsung/clk-exynos5250.c void __init exynos5250_clk_init(struct device_node · line 562

Quoted 7 lines
drivers/clk/samsung/clk-exynos5250.c +4 -0
@@ -531,6 +556,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))

Nit: Unnecessary parentheses around 24 * MHZ.

drivers/clk/samsung/clk-exynos5250.c void __init exynos5250_clk_init(struct device_node *np) · line 569

Quoted 7 lines
drivers/clk/samsung/clk-exynos5250.c +7 -0
+		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))

Ditto.

drivers/clk/samsung/clk-exynos5250.c void __init exynos5250_clk_init(struct device_node *np)

Quoted 3 lines
drivers/clk/samsung/clk-exynos5250.c +2 -0
+		exynos5250_plls[vpll].rate_table =  vpll_24mhz_tbl;
+
 	samsung_clk_register_pll(exynos5250_plls, 

ARRAY_SIZE(exynos5250_plls),

drivers/clk/samsung/clk.h struct samsung_clock_alias { · line 43

Quoted 11 lines
drivers/clk/samsung/clk-exynos5250.c +0 -0
 reg_base);
 	samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
drivers/clk/samsung/clk.h +1 -0
index 3e6501c..378bf98 100644
@@ -40,6 +40,8 @@ struct samsung_clock_alias {
 		.alias		= a,				\
 	}
 
+#define MHZ (1000*1000)

Nit: (1000 * 1000)

Best regards,
Tomasz

Quoted 4 lines
drivers/clk/samsung/clk.h +1 -0
+
 /**
  * struct samsung_fixed_rate_clock: information about fixed-rate clock
  * @id: platform specific id of the clock.