From 3ff6e0d8d64d594a551b5c4904e4b617bf7eee22 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Tue, 11 Jun 2013 15:01:12 +0530 Subject: [PATCH] clk: samsung: Add support to register rate_table for samsung plls 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 Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mike Turquette --- 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 9de7a39..68f9a4a 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -986,13 +986,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 b9a5f2a..46a1636 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -493,19 +493,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 3dbe7a3..ca352695 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -729,27 +729,27 @@ static 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 dd948f2..8394231 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -18,6 +18,8 @@ struct samsung_clk_pll { void __iomem *lock_reg; void __iomem *con_reg; enum samsung_pll_type type; + unsigned int rate_count; + const struct samsung_pll_rate_table *rate_table; }; #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw) @@ -350,7 +352,7 @@ 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) { @@ -364,6 +366,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 4e83e52..b3f2532 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -283,10 +283,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, \ @@ -296,16 +298,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, -- 2.7.4