[PATCH v7 07/11] clk: samsung: Add support to register rate_table for samsung plls

Yadwinder Singh Brar yadi.brar at samsung.com
Tue Jun 11 05:31:12 EDT 2013


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

Reviewed-by: Doug Anderson <dianders at chromium.org>
Signed-off-by: Yadwinder Singh Brar <yadi.brar at samsung.com>
---
 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        |   19 ++++++++++++++++++-
 drivers/clk/samsung/clk-pll.h        |   27 +++++++++++++++++++++++++++
 drivers/clk/samsung/clk.h            |   13 ++++++++-----
 6 files changed, 75 insertions(+), 28 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index f2c2156..c270eb0 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -999,13 +999,13 @@ static __initdata struct of_device_id ext_clk_match[] = {
 
 struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
 	[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
-		APLL_CON0, "fout_apll"),
+		APLL_CON0, "fout_apll", NULL),
 	[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll",
-		E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll"),
+		E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll", NULL),
 	[epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
-		EPLL_CON0, "fout_epll"),
+		EPLL_CON0, "fout_epll", NULL),
 	[vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
-		VPLL_CON0, "fout_vpll"),
+		VPLL_CON0, "fout_vpll", NULL),
 };
 
 /* register exynos4 clocks */
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 4027c69..623ae44 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -497,19 +497,19 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
 
 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", "mout_vpllsrc",
-		VPLL_LOCK, VPLL_CON0),
+		VPLL_LOCK, VPLL_CON0, NULL),
 };
 
 static __initdata struct of_device_id ext_clk_match[] = {
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 3ea6b4f..86dfc64 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -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[] = {
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 7d5bea8..adc0659 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -18,6 +18,8 @@ struct samsung_clk_pll {
 	void __iomem		*lock_reg;
 	void __iomem		*con_reg;
 	enum samsung_pll_type	type;
+	unsigned int		rate_count;
+	const struct samsung_pll_rate_table *rate_table;
 };
 
 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
@@ -349,7 +351,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
 	struct samsung_clk_pll *pll;
 	struct clk *clk;
 	struct clk_init_data init;
-	int ret;
+	int ret, len;
 
 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 	if (!pll) {
@@ -363,6 +365,21 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk,
 	init.parent_names = &pll_clk->parent_name;
 	init.num_parents = 1;
 
+	if (pll_clk->rate_table) {
+		/* find count of rates in rate_table */
+		for (len = 0; pll_clk->rate_table[len].rate != 0; )
+			len++;
+
+		pll->rate_count = len;
+		pll->rate_table = kmemdup(pll_clk->rate_table,
+					pll->rate_count *
+					sizeof(struct samsung_pll_rate_table),
+					GFP_KERNEL);
+		WARN(!pll->rate_table,
+			"%s: could not allocate rate table for %s\n",
+			__func__, pll_clk->name);
+	}
+
 	switch (pll_clk->type) {
 	/* clk_ops for 35xx and 2550 are similar */
 	case pll_35xx:
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 1536f27..95ae23d 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -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,
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index d834395..4a003d7 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -280,10 +280,12 @@ struct samsung_pll_clock {
 	int			con_offset;
 	int			lock_offset;
 	enum samsung_pll_type	type;
+	const struct samsung_pll_rate_table *rate_table;
 	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 +295,17 @@ struct samsung_pll_clock {
 		.flags		= CLK_GET_RATE_NOCACHE,			\
 		.con_offset	= _con,					\
 		.lock_offset	= _lock,				\
+		.rate_table	= _rtable,				\
 		.alias		= _alias,				\
 	}
 
-#define PLL(_typ, _id, _name, _pname, _lock, _con)			\
+#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable)	\
 	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
-		_lock, _con, NULL)
+		_lock, _con, _rtable, _name)
 
-#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias)		\
+#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
 	__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE,	\
-		_lock, _con, _alias)
+		_lock, _con, _rtable, _alias)
 
 extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
 		unsigned long nr_clks, unsigned long *rdump,
-- 
1.7.0.4




More information about the linux-arm-kernel mailing list