* [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs
@ 2013-06-08 17:34 Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct Yadwinder Singh Brar
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
To: linux-arm-kernel
This patch series does the following:
1) Unifies the clk strutures and registration function used for PLL35xx &
PLL36xx, to factor out possible common code.
2) Defines a common rate_table which will contain recommended p, m, s and k
values for supported rates that needs to be changed for changing
corresponding PLL's rate
3) Adds set_rate() and round_rate() clk_ops for PLL35xx and PLL36xx
changes since v4:
- Defined common samsung samsung_clk_register_pll() to register a list
of PLL and used a struct samsung_pll_clock for passing intialisation
data instead of passing as arguments. Now passing LOCK as well as CON0
offset as intialisation data.
- Calculated length of rate table while registering PLL instead of
getting it as intialisation data.
changes since v3:
- Used __clk_lookup() instead of adding alias for mout_vpllsrc
- Added check for changing only M value in samsung_pll36xx_set_rate()
- Modified samsung_pll35xx_mp_change() & samsung_pll35xx_set_rate()
to improve readabilty.
- Made the input rate_table as __init_data which is to be provided while
registering PLL and made a copy of that table while registering, so
that if multiple tables are their, they can be freed after getting the
P, M, S, K setting values from required one.
changes since v2:
- Added new patch to reorder the MUX registration for mout_vpllsrc MUX
before the PLL registrations. And to add the alias for the mout_vpllsrc MUX.
- Added a check to confirm parent rate while registrating the PLL
rate tables.
changes since v1:
- removed sorting and bsearch
- modified the definition of struct "samsung_pll_rate_table"
- added generic round_rate()
- rectified the ops assignment for "rate table passed as NULL"
during PLL registration
Is rebased on branch kgene's "for-next"
https://git.kernel.org/cgit/linux/kernel/git/kgene/linux-samsung.git/log/?h=for-next
Vikas Sajjan (2):
clk: samsung: Add set_rate() clk_ops for PLL36xx
clk: samsung: Reorder MUX registration for mout_vpllsrc
Yadwinder Singh Brar (5):
clk: samsung: Introduce a common samsung_clk_pll struct.
clk: samsung: Define a common samsung_clk_register_pll().
clk: samsung: Add support to register rate_table for PLL3xxx
clk: samsung: Add set_rate() clk_ops for PLL35xx
clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC
drivers/clk/samsung/clk-exynos4.c | 40 +++--
drivers/clk/samsung/clk-exynos5250.c | 101 +++++++++--
drivers/clk/samsung/clk-pll.c | 330 ++++++++++++++++++++++++++--------
drivers/clk/samsung/clk-pll.h | 36 ++++-
drivers/clk/samsung/clk.h | 54 ++++++
5 files changed, 449 insertions(+), 112 deletions(-)
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct.
2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 2/7] clk: samsung: Define a common samsung_clk_register_pll() Yadwinder Singh Brar
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
To: linux-arm-kernel
This patch unifies clk strutures used for PLL35xx & PLL36xx and
adding an extra member lock_reg, so that common code can be factored out.
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
drivers/clk/samsung/clk-pll.c | 30 ++++++++++++------------------
1 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 89135f6..8224bde 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -13,6 +13,14 @@
#include "clk.h"
#include "clk-pll.h"
+struct samsung_clk_pll {
+ struct clk_hw hw;
+ void __iomem *lock_reg;
+ void __iomem *con_reg;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
/*
* PLL35xx Clock Type
*/
@@ -24,17 +32,10 @@
#define PLL35XX_PDIV_SHIFT (8)
#define PLL35XX_SDIV_SHIFT (0)
-struct samsung_clk_pll35xx {
- struct clk_hw hw;
- const void __iomem *con_reg;
-};
-
-#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
-
static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, pll_con;
u64 fvco = parent_rate;
@@ -56,7 +57,7 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
struct clk * __init samsung_clk_register_pll35xx(const char *name,
const char *pname, const void __iomem *con_reg)
{
- struct samsung_clk_pll35xx *pll;
+ struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
@@ -100,17 +101,10 @@ struct clk * __init samsung_clk_register_pll35xx(const char *name,
#define PLL36XX_PDIV_SHIFT (8)
#define PLL36XX_SDIV_SHIFT (0)
-struct samsung_clk_pll36xx {
- struct clk_hw hw;
- const void __iomem *con_reg;
-};
-
-#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
-
static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
u64 fvco = parent_rate;
@@ -135,7 +129,7 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
struct clk * __init samsung_clk_register_pll36xx(const char *name,
const char *pname, const void __iomem *con_reg)
{
- struct samsung_clk_pll36xx *pll;
+ struct samsung_clk_pll *pll;
struct clk *clk;
struct clk_init_data init;
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 2/7] clk: samsung: Define a common samsung_clk_register_pll().
2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 3/7] clk: samsung: Add support to register rate_table for PLL3xxx Yadwinder Singh Brar
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
To: linux-arm-kernel
This patch defines a common samsung_clk_register_pll() and its migrating the
PLL35xx & PLL36xx to use it. Other samsung PLL can also be migrated to it.
This patch also adds exynos5250 PLLs in unique id list of exynos5250 clocks.
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
drivers/clk/samsung/clk-exynos4.c | 40 +++++++----
drivers/clk/samsung/clk-exynos5250.c | 60 +++++++++++-----
drivers/clk/samsung/clk-pll.c | 128 +++++++++++++++------------------
drivers/clk/samsung/clk-pll.h | 9 ++-
drivers/clk/samsung/clk.h | 48 +++++++++++++
5 files changed, 178 insertions(+), 107 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index addc738..ba25a1b 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -17,7 +17,6 @@
#include <linux/of_address.h>
#include "clk.h"
-#include "clk-pll.h"
/* Exynos4 clock controller register offsets */
#define SRC_LEFTBUS 0x4200
@@ -97,12 +96,14 @@
#define GATE_IP_PERIL 0xc950
#define E4210_GATE_IP_PERIR 0xc960
#define GATE_BLOCK 0xc970
+#define E4X12_MPLL_LOCK 0x10008
#define E4X12_MPLL_CON0 0x10108
#define SRC_DMC 0x10200
#define SRC_MASK_DMC 0x10300
#define DIV_DMC0 0x10500
#define DIV_DMC1 0x10504
#define GATE_IP_DMC 0x10900
+#define APLL_LOCK 0x14000
#define APLL_CON0 0x14100
#define E4210_MPLL_CON0 0x14108
#define SRC_CPU 0x14200
@@ -121,6 +122,12 @@ enum exynos4_soc {
EXYNOS4X12,
};
+/* list of PLLs to be registered */
+enum exynos4_plls {
+ apll, mpll, epll, vpll,
+ nr_plls /* number of PLLs */
+};
+
/*
* Let each supported clock get a unique id. This id is used to lookup the clock
* for device tree based platforms. The clocks are categorized into three
@@ -988,6 +995,17 @@ static __initdata struct of_device_id ext_clk_match[] = {
{},
};
+struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
+ [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+ APLL_CON0, "fout_apll"),
+ [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll",
+ E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll"),
+ [epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+ EPLL_CON0, "fout_epll"),
+ [vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
+ VPLL_CON0, "fout_vpll"),
+};
+
/* register exynos4 clocks */
void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom)
{
@@ -1024,22 +1042,16 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
reg_base + EPLL_CON0, pll_4600);
vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc",
reg_base + VPLL_CON0, pll_4650c);
+
+ samsung_clk_add_lookup(apll, fout_apll);
+ samsung_clk_add_lookup(mpll, fout_mpll);
+ samsung_clk_add_lookup(epll, fout_epll);
+ samsung_clk_add_lookup(vpll, fout_vpll);
} else {
- apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
- reg_base + APLL_CON0);
- mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
- reg_base + E4X12_MPLL_CON0);
- epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
- reg_base + EPLL_CON0);
- vpll = samsung_clk_register_pll36xx("fout_vpll", "fin_pll",
- reg_base + VPLL_CON0);
+ samsung_clk_register_pll(exynos4_plls,
+ ARRAY_SIZE(exynos4_plls), reg_base);
}
- samsung_clk_add_lookup(apll, fout_apll);
- samsung_clk_add_lookup(mpll, fout_mpll);
- samsung_clk_add_lookup(epll, fout_epll);
- samsung_clk_add_lookup(vpll, fout_vpll);
-
samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
ARRAY_SIZE(exynos4_fixed_rate_clks));
samsung_clk_register_mux(exynos4_mux_clks,
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 5c97e75..0418cc1 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -17,11 +17,22 @@
#include <linux/of_address.h>
#include "clk.h"
-#include "clk-pll.h"
+#define APLL_LOCK 0x0
+#define APLL_CON0 0x100
#define SRC_CPU 0x200
#define DIV_CPU0 0x500
+#define MPLL_LOCK 0x4000
+#define MPLL_CON0 0x4100
#define SRC_CORE1 0x4204
+#define CPLL_LOCK 0x10020
+#define EPLL_LOCK 0x10030
+#define VPLL_LOCK 0x10040
+#define GPLL_LOCK 0x10050
+#define CPLL_CON0 0x10120
+#define EPLL_CON0 0x10130
+#define VPLL_CON0 0x10140
+#define GPLL_CON0 0x10150
#define SRC_TOP0 0x10210
#define SRC_TOP2 0x10218
#define SRC_GSCL 0x10220
@@ -59,10 +70,18 @@
#define GATE_IP_FSYS 0x10944
#define GATE_IP_PERIC 0x10950
#define GATE_IP_PERIS 0x10960
+#define BPLL_LOCK 0x20010
+#define BPLL_CON0 0x20110
#define SRC_CDREX 0x20200
#define PLL_DIV2_SEL 0x20a24
#define GATE_IP_DISP1 0x10928
+/* list of PLLs to be registered */
+enum exynos5250_plls {
+ apll, mpll, bpll, gpll, cpll, epll, vpll,
+ nr_plls /* number of PLLs */
+};
+
/*
* Let each supported clock get a unique id. This id is used to lookup the clock
* for device tree based platforms. The clocks are categorized into three
@@ -79,7 +98,8 @@ enum exynos5250_clks {
none,
/* core clocks */
- fin_pll,
+ fin_pll, fout_apll, fout_mpll, fout_bpll, fout_gpll, fout_cpll,
+ fout_epll, fout_vpll,
/* gate for special clocks (sclk) */
sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb,
@@ -469,11 +489,27 @@ static __initdata struct of_device_id ext_clk_match[] = {
{ },
};
+struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
+ [apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
+ APLL_CON0, "fout_apll"),
+ [mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
+ MPLL_CON0, "fout_mpll"),
+ [bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
+ BPLL_CON0),
+ [gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", GPLL_LOCK,
+ GPLL_CON0),
+ [cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK,
+ CPLL_CON0),
+ [epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
+ EPLL_CON0),
+ [vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
+ VPLL_CON0),
+};
+
/* register exynox5250 clocks */
void __init exynos5250_clk_init(struct device_node *np)
{
void __iomem *reg_base;
- struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
if (np) {
reg_base = of_iomap(np, 0);
@@ -489,22 +525,8 @@ void __init exynos5250_clk_init(struct device_node *np)
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
-
- apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
- reg_base + 0x100);
- mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
- reg_base + 0x4100);
- bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
- reg_base + 0x20110);
- gpll = samsung_clk_register_pll35xx("fout_gpll", "fin_pll",
- reg_base + 0x10150);
- cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
- reg_base + 0x10120);
- epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
- reg_base + 0x10130);
- vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc",
- reg_base + 0x10140);
-
+ samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
+ reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
ARRAY_SIZE(exynos5250_fixed_rate_clks));
samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 8224bde..b83900c 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -17,6 +17,7 @@ struct samsung_clk_pll {
struct clk_hw hw;
void __iomem *lock_reg;
void __iomem *con_reg;
+ enum samsung_pll_type type;
};
#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
@@ -54,41 +55,6 @@ static const struct clk_ops samsung_pll35xx_clk_ops = {
.recalc_rate = samsung_pll35xx_recalc_rate,
};
-struct clk * __init samsung_clk_register_pll35xx(const char *name,
- const char *pname, const void __iomem *con_reg)
-{
- struct samsung_clk_pll *pll;
- struct clk *clk;
- struct clk_init_data init;
-
- pll = kzalloc(sizeof(*pll), GFP_KERNEL);
- if (!pll) {
- pr_err("%s: could not allocate pll clk %s\n", __func__, name);
- return NULL;
- }
-
- init.name = name;
- init.ops = &samsung_pll35xx_clk_ops;
- init.flags = CLK_GET_RATE_NOCACHE;
- init.parent_names = &pname;
- init.num_parents = 1;
-
- pll->hw.init = &init;
- pll->con_reg = con_reg;
-
- clk = clk_register(NULL, &pll->hw);
- if (IS_ERR(clk)) {
- pr_err("%s: failed to register pll clock %s\n", __func__,
- name);
- kfree(pll);
- }
-
- if (clk_register_clkdev(clk, name, NULL))
- pr_err("%s: failed to register lookup for %s", __func__, name);
-
- return clk;
-}
-
/*
* PLL36xx Clock Type
*/
@@ -126,41 +92,6 @@ static const struct clk_ops samsung_pll36xx_clk_ops = {
.recalc_rate = samsung_pll36xx_recalc_rate,
};
-struct clk * __init samsung_clk_register_pll36xx(const char *name,
- const char *pname, const void __iomem *con_reg)
-{
- struct samsung_clk_pll *pll;
- struct clk *clk;
- struct clk_init_data init;
-
- pll = kzalloc(sizeof(*pll), GFP_KERNEL);
- if (!pll) {
- pr_err("%s: could not allocate pll clk %s\n", __func__, name);
- return NULL;
- }
-
- init.name = name;
- init.ops = &samsung_pll36xx_clk_ops;
- init.flags = CLK_GET_RATE_NOCACHE;
- init.parent_names = &pname;
- init.num_parents = 1;
-
- pll->hw.init = &init;
- pll->con_reg = con_reg;
-
- clk = clk_register(NULL, &pll->hw);
- if (IS_ERR(clk)) {
- pr_err("%s: failed to register pll clock %s\n", __func__,
- name);
- kfree(pll);
- }
-
- if (clk_register_clkdev(clk, name, NULL))
- pr_err("%s: failed to register lookup for %s", __func__, name);
-
- return clk;
-}
-
/*
* PLL45xx Clock Type
*/
@@ -411,3 +342,60 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
return clk;
}
+
+void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
+ unsigned int nr_pll, void __iomem *base)
+{
+ struct samsung_clk_pll *pll;
+ struct clk *clk;
+ struct clk_init_data init;
+ struct samsung_pll_clock *list = clk_list;
+ int cnt;
+
+ for (cnt = 0; cnt < nr_pll; cnt++, list++) {
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll) {
+ pr_err("%s: could not allocate pll clk %s\n",
+ __func__, list->name);
+ continue;
+ }
+
+ init.name = list->name;
+ init.flags = list->flags;
+ init.parent_names = &list->parent_name;
+ init.num_parents = 1;
+
+ switch (list->type) {
+ case pll_35xx:
+ init.ops = &samsung_pll35xx_clk_ops;
+ break;
+ case pll_36xx:
+ init.ops = &samsung_pll36xx_clk_ops;
+ break;
+ default:
+ pr_warn("%s: Unknown pll type for pll clk %s\n",
+ __func__, list->name);
+ }
+
+ pll->hw.init = &init;
+ pll->type = list->type;
+ pll->lock_reg = base + list->lock_offset;
+ pll->con_reg = base + list->con_offset;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register pll clock %s\n",
+ __func__, list->name);
+ kfree(pll);
+ continue;
+ }
+
+ samsung_clk_add_lookup(clk, list->id);
+
+ if (list->alias)
+ if (clk_register_clkdev(clk, list->alias,
+ list->dev_name))
+ pr_err("%s: failed to register lookup for %s",
+ __func__, list->name);
+ }
+}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index f33786e..58810fe 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -12,6 +12,11 @@
#ifndef __SAMSUNG_CLK_PLL_H
#define __SAMSUNG_CLK_PLL_H
+enum samsung_pll_type {
+ pll_35xx,
+ pll_36xx,
+};
+
enum pll45xx_type {
pll_4500,
pll_4502,
@@ -24,10 +29,6 @@ enum pll46xx_type {
pll_4650c,
};
-extern struct clk * __init samsung_clk_register_pll35xx(const char *name,
- const char *pname, const void __iomem *con_reg);
-extern struct clk * __init samsung_clk_register_pll36xx(const char *name,
- const char *pname, const void __iomem *con_reg);
extern struct clk * __init samsung_clk_register_pll45xx(const char *name,
const char *pname, const void __iomem *con_reg,
enum pll45xx_type type);
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index e4ad6ea..51f60ca 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -19,6 +19,7 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include "clk-pll.h"
/**
* struct samsung_clock_alias: information about mux clock
@@ -258,6 +259,51 @@ struct samsung_clk_reg_dump {
u32 value;
};
+/**
+ * struct samsung_pll_clock: information about pll clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this pll clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @con_offset: offset of the register for configuring the PLL.
+ * @lock_offset: offset of the register for locking the PLL.
+ * @type: Type of PLL to be registered.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_pll_clock {
+ unsigned int id;
+ const char *dev_name;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ const int con_offset;
+ const int lock_offset;
+ enum samsung_pll_type type;
+ const char *alias;
+};
+
+#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, _alias) \
+ { \
+ .id = _id, \
+ .type = _typ, \
+ .dev_name = _dname, \
+ .name = _name, \
+ .parent_name = _pname, \
+ .flags = CLK_GET_RATE_NOCACHE, \
+ .con_offset = _con, \
+ .lock_offset = _lock, \
+ .alias = _alias, \
+ }
+
+#define PLL(_typ, _id, _name, _pname, _lock, _con) \
+ __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
+ _lock, _con, NULL)
+
+#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias) \
+ __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
+ _lock, _con, _alias)
+
extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
unsigned long nr_clks, unsigned long *rdump,
unsigned long nr_rdump, unsigned long *soc_rdump,
@@ -281,6 +327,8 @@ extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
unsigned int nr_clk);
extern void __init samsung_clk_register_gate(
struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+extern void __init samsung_clk_register_pll(struct samsung_pll_clock *list,
+ unsigned int nr_clk, void __iomem *base);
extern unsigned long _get_rate(const char *clk_name);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 3/7] clk: samsung: Add support to register rate_table for PLL3xxx
2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 2/7] clk: samsung: Define a common samsung_clk_register_pll() Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx Yadwinder Singh Brar
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
To: linux-arm-kernel
This patch defines a common rate_table which will contain recommended p, m, s,
k values for supported rates that needs to be changed for changing
corresponding PLL's rate.
Reviewed-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
drivers/clk/samsung/clk-exynos4.c | 8 ++++----
drivers/clk/samsung/clk-exynos5250.c | 14 +++++++-------
drivers/clk/samsung/clk-pll.c | 22 ++++++++++++++++++++--
drivers/clk/samsung/clk-pll.h | 27 +++++++++++++++++++++++++++
drivers/clk/samsung/clk.h | 14 +++++++++-----
5 files changed, 67 insertions(+), 18 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index ba25a1b..ceee66c 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -997,13 +997,13 @@ static __initdata struct of_device_id ext_clk_match[] = {
struct __initdata samsung_pll_clock exynos4_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
- APLL_CON0, "fout_apll"),
+ APLL_CON0, "fout_apll", NULL),
[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll",
- E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll"),
+ E4X12_MPLL_LOCK, E4X12_MPLL_CON0, "fout_mpll", NULL),
[epll] = PLL_A(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
- EPLL_CON0, "fout_epll"),
+ EPLL_CON0, "fout_epll", NULL),
[vpll] = PLL_A(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
- VPLL_CON0, "fout_vpll"),
+ VPLL_CON0, "fout_vpll", NULL),
};
/* register exynos4 clocks */
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 0418cc1..a025269 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -491,19 +491,19 @@ static __initdata struct of_device_id ext_clk_match[] = {
struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
- APLL_CON0, "fout_apll"),
+ APLL_CON0, "fout_apll", NULL),
[mpll] = PLL_A(pll_35xx, fout_mpll, "fout_mpll", "fin_pll", MPLL_LOCK,
- MPLL_CON0, "fout_mpll"),
+ MPLL_CON0, "fout_mpll", NULL),
[bpll] = PLL(pll_35xx, fout_bpll, "fout_bpll", "fin_pll", BPLL_LOCK,
- BPLL_CON0),
+ BPLL_CON0, NULL),
[gpll] = PLL(pll_35xx, fout_gpll, "fout_gpll", "fin_pll", GPLL_LOCK,
- GPLL_CON0),
+ GPLL_CON0, NULL),
[cpll] = PLL(pll_35xx, fout_cpll, "fout_cpll", "fin_pll", CPLL_LOCK,
- CPLL_CON0),
+ CPLL_CON0, NULL),
[epll] = PLL(pll_36xx, fout_epll, "fout_epll", "fin_pll", EPLL_LOCK,
- EPLL_CON0),
+ EPLL_CON0, NULL),
[vpll] = PLL(pll_36xx, fout_vpll, "fout_vpll", "fin_pll", VPLL_LOCK,
- VPLL_CON0),
+ VPLL_CON0, NULL),
};
/* register exynox5250 clocks */
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index b83900c..f753c5e 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -18,6 +18,8 @@ struct samsung_clk_pll {
void __iomem *lock_reg;
void __iomem *con_reg;
enum samsung_pll_type type;
+ unsigned int rate_count;
+ const struct samsung_pll_rate_table *rate_table;
};
#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
@@ -350,7 +352,7 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
struct clk *clk;
struct clk_init_data init;
struct samsung_pll_clock *list = clk_list;
- int cnt;
+ int cnt, len;
for (cnt = 0; cnt < nr_pll; cnt++, list++) {
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
@@ -365,6 +367,21 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
init.parent_names = &list->parent_name;
init.num_parents = 1;
+ if (list->rate_table) {
+ /* find count of rates in rate_table */
+ for (len = 0; list->rate_table[len].rate != 0; )
+ len++;
+
+ pll->rate_count = len;
+ pll->rate_table = kmemdup(list->rate_table,
+ list->rate_count *
+ sizeof(struct samsung_pll_rate_table),
+ GFP_KERNEL);
+ WARN(!pll->rate_table,
+ "%s: could not allocate rate table for %s\n",
+ __func__, list->name);
+ }
+
switch (list->type) {
case pll_35xx:
init.ops = &samsung_pll35xx_clk_ops;
@@ -392,10 +409,11 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
samsung_clk_add_lookup(clk, list->id);
- if (list->alias)
+ if (list->alias) {
if (clk_register_clkdev(clk, list->alias,
list->dev_name))
pr_err("%s: failed to register lookup for %s",
__func__, list->name);
+ }
}
}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index 58810fe..fb42252 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -17,6 +17,33 @@ enum samsung_pll_type {
pll_36xx,
};
+#define PLL_35XX_RATE(_rate, _m, _p, _s) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ }
+
+#define PLL_36XX_RATE(_rate, _m, _p, _s, _k) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ .kdiv = (_k), \
+ }
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+
+struct samsung_pll_rate_table {
+ unsigned int rate;
+ unsigned int pdiv;
+ unsigned int mdiv;
+ unsigned int sdiv;
+ unsigned int kdiv;
+};
+
enum pll45xx_type {
pll_4500,
pll_4502,
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 51f60ca..3e6501c 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -280,10 +280,13 @@ struct samsung_pll_clock {
const int con_offset;
const int lock_offset;
enum samsung_pll_type type;
+ const struct samsung_pll_rate_table *rate_table;
+ unsigned int rate_count;
const char *alias;
};
-#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, _alias) \
+#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, \
+ _rtable, _alias) \
{ \
.id = _id, \
.type = _typ, \
@@ -293,16 +296,17 @@ struct samsung_pll_clock {
.flags = CLK_GET_RATE_NOCACHE, \
.con_offset = _con, \
.lock_offset = _lock, \
+ .rate_table = _rtable, \
.alias = _alias, \
}
-#define PLL(_typ, _id, _name, _pname, _lock, _con) \
+#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
- _lock, _con, NULL)
+ _lock, _con, _rtable, _name)
-#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias) \
+#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
- _lock, _con, _alias)
+ _lock, _con, _rtable, _alias)
extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
unsigned long nr_clks, unsigned long *rdump,
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx
2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
` (2 preceding siblings ...)
2013-06-08 17:34 ` [PATCH v5 3/7] clk: samsung: Add support to register rate_table for PLL3xxx Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx Yadwinder Singh Brar
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
To: linux-arm-kernel
This patch add set_rate() and round_rate() for PLL35xx
Reviewed-by: Doug Anderson <dianders@chromium.org>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
drivers/clk/samsung/clk-pll.c | 104 ++++++++++++++++++++++++++++++++++++++++-
1 files changed, 103 insertions(+), 1 deletions(-)
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index f753c5e..df419aa 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -24,16 +24,51 @@ struct samsung_clk_pll {
#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+static const struct samsung_pll_rate_table *samsung_get_pll_settings(
+ struct samsung_clk_pll *pll, unsigned long rate)
+{
+ const struct samsung_pll_rate_table *rate_table = pll->rate_table;
+ int i;
+
+ for (i = 0; i < pll->rate_count; i++) {
+ if (rate == rate_table[i].rate)
+ return &rate_table[i];
+ }
+
+ return NULL;
+}
+
+static long samsung_pll_round_rate(struct clk_hw *hw,
+ unsigned long drate, unsigned long *prate)
+{
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
+ const struct samsung_pll_rate_table *rate_table = pll->rate_table;
+ int i;
+
+ /* Assumming rate_table is in descending order */
+ for (i = 0; i < pll->rate_count; i++) {
+ if (drate >= rate_table[i].rate)
+ return rate_table[i].rate;
+ }
+
+ /* return minimum supported value */
+ return rate_table[i - 1].rate;
+}
+
/*
* PLL35xx Clock Type
*/
+/* Maximum lock time can be 270 * PDIV cycles */
+#define PLL35XX_LOCK_FACTOR (270)
#define PLL35XX_MDIV_MASK (0x3FF)
#define PLL35XX_PDIV_MASK (0x3F)
#define PLL35XX_SDIV_MASK (0x7)
+#define PLL35XX_LOCK_STAT_MASK (0x1)
#define PLL35XX_MDIV_SHIFT (16)
#define PLL35XX_PDIV_SHIFT (8)
#define PLL35XX_SDIV_SHIFT (0)
+#define PLL35XX_LOCK_STAT_SHIFT (29)
static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -53,8 +88,72 @@ static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
return (unsigned long)fvco;
}
+static inline bool samsung_pll35xx_mp_change(
+ const struct samsung_pll_rate_table *rate, u32 pll_con)
+{
+ u32 old_mdiv, old_pdiv;
+
+ old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+ old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+
+ return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
+}
+
+static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
+ const struct samsung_pll_rate_table *rate;
+ u32 tmp;
+
+ /* Get required rate settings from table */
+ rate = samsung_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, __clk_get_name(hw->clk));
+ return -EINVAL;
+ }
+
+ tmp = __raw_readl(pll->con_reg);
+
+ if (!(samsung_pll35xx_mp_change(rate, tmp))) {
+ /* If only s change, change just s value only*/
+ tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
+ tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
+ __raw_writel(tmp, pll->con_reg);
+ return 0;
+ }
+
+ /* Set PLL lock time. */
+ __raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR,
+ pll->lock_reg);
+
+ /* Change PLL PMS values */
+ tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
+ (PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
+ (PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
+ tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
+ (rate->pdiv << PLL35XX_PDIV_SHIFT) |
+ (rate->sdiv << PLL35XX_SDIV_SHIFT);
+ __raw_writel(tmp, pll->con_reg);
+
+ /* wait_lock_time */
+ do {
+ cpu_relax();
+ tmp = __raw_readl(pll->con_reg);
+ } while (!(tmp & (PLL35XX_LOCK_STAT_MASK
+ << PLL35XX_LOCK_STAT_SHIFT)));
+ return 0;
+}
+
static const struct clk_ops samsung_pll35xx_clk_ops = {
.recalc_rate = samsung_pll35xx_recalc_rate,
+ .round_rate = samsung_pll_round_rate,
+ .set_rate = samsung_pll35xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll35xx_clk_min_ops = {
+ .recalc_rate = samsung_pll35xx_recalc_rate,
};
/*
@@ -384,7 +483,10 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
switch (list->type) {
case pll_35xx:
- init.ops = &samsung_pll35xx_clk_ops;
+ if (!pll->rate_table)
+ init.ops = &samsung_pll35xx_clk_min_ops;
+ else
+ init.ops = &samsung_pll35xx_clk_ops;
break;
case pll_36xx:
init.ops = &samsung_pll36xx_clk_ops;
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx
2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
` (3 preceding siblings ...)
2013-06-08 17:34 ` [PATCH v5 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar
6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
To: linux-arm-kernel
From: Vikas Sajjan <vikas.sajjan@linaro.org>
This patch adds set_rate and round_rate clk_ops for PLL36xx
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Reviewed-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Vikas Sajjan <vikas.sajjan@linaro.org>
---
drivers/clk/samsung/clk-pll.c | 78 ++++++++++++++++++++++++++++++++++++++++-
1 files changed, 77 insertions(+), 1 deletions(-)
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index df419aa..2adf761 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -159,6 +159,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
/*
* PLL36xx Clock Type
*/
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR (3000)
#define PLL36XX_KDIV_MASK (0xFFFF)
#define PLL36XX_MDIV_MASK (0x1FF)
@@ -167,6 +169,8 @@ static const struct clk_ops samsung_pll35xx_clk_min_ops = {
#define PLL36XX_MDIV_SHIFT (16)
#define PLL36XX_PDIV_SHIFT (8)
#define PLL36XX_SDIV_SHIFT (0)
+#define PLL36XX_KDIV_SHIFT (0)
+#define PLL36XX_LOCK_STAT_SHIFT (29)
static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
@@ -189,8 +193,77 @@ static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
return (unsigned long)fvco;
}
+static inline bool samsung_pll36xx_mpk_change(
+ const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
+{
+ u32 old_mdiv, old_pdiv, old_kdiv;
+
+ old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+ old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+ old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
+
+ return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+ rate->kdiv != old_kdiv);
+}
+
+static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long parent_rate)
+{
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
+ u32 tmp, pll_con0, pll_con1;
+ const struct samsung_pll_rate_table *rate;
+
+ rate = samsung_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, __clk_get_name(hw->clk));
+ return -EINVAL;
+ }
+
+ pll_con0 = __raw_readl(pll->con_reg);
+ pll_con1 = __raw_readl(pll->con_reg + 4);
+
+ if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
+ /* If only s change, change just s value only*/
+ pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
+ pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
+ __raw_writel(pll_con0, pll->con_reg);
+ return 0;
+ }
+
+ /* Set PLL lock time. */
+ __raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
+
+ /* Change PLL PMS values */
+ pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
+ (PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
+ (PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
+ pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
+ (rate->pdiv << PLL36XX_PDIV_SHIFT) |
+ (rate->sdiv << PLL36XX_SDIV_SHIFT);
+ __raw_writel(pll_con0, pll->con_reg);
+
+ pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
+ pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
+ __raw_writel(pll_con1, pll->con_reg + 4);
+
+ /* wait_lock_time */
+ do {
+ cpu_relax();
+ tmp = __raw_readl(pll->con_reg);
+ } while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
+
+ return 0;
+}
+
static const struct clk_ops samsung_pll36xx_clk_ops = {
.recalc_rate = samsung_pll36xx_recalc_rate,
+ .set_rate = samsung_pll36xx_set_rate,
+ .round_rate = samsung_pll_round_rate,
+};
+
+static const struct clk_ops samsung_pll36xx_clk_min_ops = {
+ .recalc_rate = samsung_pll36xx_recalc_rate,
};
/*
@@ -489,7 +562,10 @@ void __init samsung_clk_register_pll(struct samsung_pll_clock *clk_list,
init.ops = &samsung_pll35xx_clk_ops;
break;
case pll_36xx:
- init.ops = &samsung_pll36xx_clk_ops;
+ if (!pll->rate_table)
+ init.ops = &samsung_pll36xx_clk_min_ops;
+ else
+ init.ops = &samsung_pll36xx_clk_ops;
break;
default:
pr_warn("%s: Unknown pll type for pll clk %s\n",
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc
2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
` (4 preceding siblings ...)
2013-06-08 17:34 ` [PATCH v5 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar
6 siblings, 0 replies; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
To: linux-arm-kernel
From: Vikas Sajjan <vikas.sajjan@linaro.org>
While trying to get rate of "mout_vpllsrc" MUX (parent) for registering the
"fout_vpll" (child), we found get rate was failing.
So this patch moves the mout_vpllsrc MUX out of the existing common list
and registers the mout_vpllsrc MUX before the PLL registrations.
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Vikas Sajjan <vikas.sajjan@linaro.org>
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
drivers/clk/samsung/clk-exynos5250.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index a025269..09da356 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -227,6 +227,10 @@ struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
};
+struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+ MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
+};
+
struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
MUX(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
@@ -234,7 +238,6 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1),
MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
- MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
MUX(none, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
MUX(none, "sclk_epll", mout_epll_p, SRC_TOP2, 12, 1),
MUX(none, "sclk_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
@@ -525,6 +528,8 @@ void __init exynos5250_clk_init(struct device_node *np)
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
ext_clk_match);
+ samsung_clk_register_mux(exynos5250_pll_pmux_clks,
+ ARRAY_SIZE(exynos5250_pll_pmux_clks));
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC
2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
` (5 preceding siblings ...)
2013-06-08 17:34 ` [PATCH v5 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc Yadwinder Singh Brar
@ 2013-06-08 17:34 ` Yadwinder Singh Brar
2013-06-17 20:08 ` Andrew Bresticker
6 siblings, 1 reply; 10+ messages in thread
From: Yadwinder Singh Brar @ 2013-06-08 17:34 UTC (permalink / raw)
To: linux-arm-kernel
Adds the EPLL and VPLL freq table for exynos5250 SoC.
Signed-off-by: Vikas Sajjan <vikas.sajjan@linaro.org>
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
drivers/clk/samsung/clk-exynos5250.c | 38 ++++++++++++++++++++++++++++++++++
drivers/clk/samsung/clk.h | 2 +
2 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 09da356..d2743f9 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -492,6 +492,29 @@ static __initdata struct of_device_id ext_clk_match[] = {
{ },
};
+static __initdata struct samsung_pll_rate_table vpll_24mhz_tbl[] = {
+ /* sorted in descending order */
+ /* PLL_36XX_RATE(rate, m, p, s, k) */
+ PLL_36XX_RATE(266000000, 266, 3, 3, 0),
+ /* Not in UM, but need for eDP on snow */
+ PLL_36XX_RATE(70500000, 94, 2, 4, 0),
+ { },
+};
+
+static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
+ /* sorted in descending order */
+ /* PLL_36XX_RATE(rate, m, p, s, k) */
+ PLL_36XX_RATE(192000000, 48, 3, 1, 0),
+ PLL_36XX_RATE(180633600, 45, 3, 1, 10381),
+ PLL_36XX_RATE(180000000, 45, 3, 1, 0),
+ PLL_36XX_RATE(73728000, 73, 3, 3, 47710),
+ PLL_36XX_RATE(67737600, 90, 4, 3, 20762),
+ PLL_36XX_RATE(49152000, 49, 3, 3, 9962),
+ PLL_36XX_RATE(45158400, 45, 3, 3, 10381),
+ PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+ { },
+};
+
struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
[apll] = PLL_A(pll_35xx, fout_apll, "fout_apll", "fin_pll", APLL_LOCK,
APLL_CON0, "fout_apll", NULL),
@@ -513,6 +536,8 @@ struct __initdata samsung_pll_clock exynos5250_plls[nr_plls] = {
void __init exynos5250_clk_init(struct device_node *np)
{
void __iomem *reg_base;
+ struct clk *vpllsrc;
+ unsigned long fin_pll_rate, mout_vpllsrc_rate = 0;
if (np) {
reg_base = of_iomap(np, 0);
@@ -530,6 +555,19 @@ void __init exynos5250_clk_init(struct device_node *np)
ext_clk_match);
samsung_clk_register_mux(exynos5250_pll_pmux_clks,
ARRAY_SIZE(exynos5250_pll_pmux_clks));
+
+ fin_pll_rate = _get_rate("fin_pll");
+
+ if (fin_pll_rate == (24 * MHZ))
+ exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
+
+ vpllsrc = __clk_lookup("mout_vpllsrc");
+ if (vpllsrc)
+ mout_vpllsrc_rate = clk_get_rate(vpllsrc);
+
+ if (mout_vpllsrc_rate == (24 * MHZ))
+ exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl;
+
samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls),
reg_base);
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 3e6501c..378bf98 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -40,6 +40,8 @@ struct samsung_clock_alias {
.alias = a, \
}
+#define MHZ (1000*1000)
+
/**
* struct samsung_fixed_rate_clock: information about fixed-rate clock
* @id: platform specific id of the clock.
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC
2013-06-08 17:34 ` [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar
@ 2013-06-17 20:08 ` Andrew Bresticker
2013-06-18 7:10 ` Vikas Sajjan
0 siblings, 1 reply; 10+ messages in thread
From: Andrew Bresticker @ 2013-06-17 20:08 UTC (permalink / raw)
To: linux-arm-kernel
> +static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
> + /* sorted in descending order */
> + /* PLL_36XX_RATE(rate, m, p, s, k) */
> + PLL_36XX_RATE(192000000, 48, 3, 1, 0),
> + PLL_36XX_RATE(180633600, 45, 3, 1, 10381),
> + PLL_36XX_RATE(180000000, 45, 3, 1, 0),
> + PLL_36XX_RATE(73728000, 73, 3, 3, 47710),
> + PLL_36XX_RATE(67737600, 90, 4, 3, 20762),
> + PLL_36XX_RATE(49152000, 49, 3, 3, 9962),
> + PLL_36XX_RATE(45158400, 45, 3, 3, 10381),
> + PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
> + { },
> +};
I believe the UM says that 64 <= m <= 511. Although the above seems
to work on 5250 and 5420, it might be better to use a table that
conforms to the constraint on m:
PLL_36XX_RATE(192000000, 64, 2, 2, 0),
PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
PLL_36XX_RATE(180000000, 90, 3, 2, 0),
PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
PLL_36XX_RATE(32768000, 131, 3, 5, 4719)
Thanks,
Andrew
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC
2013-06-17 20:08 ` Andrew Bresticker
@ 2013-06-18 7:10 ` Vikas Sajjan
0 siblings, 0 replies; 10+ messages in thread
From: Vikas Sajjan @ 2013-06-18 7:10 UTC (permalink / raw)
To: linux-arm-kernel
Hi Andrew,
On 18 June 2013 01:38, Andrew Bresticker <abrestic@chromium.org> wrote:
>> +static __initdata struct samsung_pll_rate_table epll_24mhz_tbl[] = {
>> + /* sorted in descending order */
>> + /* PLL_36XX_RATE(rate, m, p, s, k) */
>> + PLL_36XX_RATE(192000000, 48, 3, 1, 0),
>> + PLL_36XX_RATE(180633600, 45, 3, 1, 10381),
>> + PLL_36XX_RATE(180000000, 45, 3, 1, 0),
>> + PLL_36XX_RATE(73728000, 73, 3, 3, 47710),
>> + PLL_36XX_RATE(67737600, 90, 4, 3, 20762),
>> + PLL_36XX_RATE(49152000, 49, 3, 3, 9962),
>> + PLL_36XX_RATE(45158400, 45, 3, 3, 10381),
>> + PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
>> + { },
>> +};
>
> I believe the UM says that 64 <= m <= 511. Although the above seems
> to work on 5250 and 5420, it might be better to use a table that
> conforms to the constraint on m:
>
OK, will test with the below table and resend.
> PLL_36XX_RATE(192000000, 64, 2, 2, 0),
> PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
> PLL_36XX_RATE(180000000, 90, 3, 2, 0),
> PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
> PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
> PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
> PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
> PLL_36XX_RATE(32768000, 131, 3, 5, 4719)
>
> Thanks,
> Andrew
--
Thanks and Regards
Vikas Sajjan
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-06-18 7:10 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-08 17:34 [PATCH v5 0/7] Add generic set_rate clk_ops for PLL35xx and PLL36xx for samsung SoCs Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 1/7] clk: samsung: Introduce a common samsung_clk_pll struct Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 2/7] clk: samsung: Define a common samsung_clk_register_pll() Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 3/7] clk: samsung: Add support to register rate_table for PLL3xxx Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 4/7] clk: samsung: Add set_rate() clk_ops for PLL35xx Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 5/7] clk: samsung: Add set_rate() clk_ops for PLL36xx Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 6/7] clk: samsung: Reorder MUX registration for mout_vpllsrc Yadwinder Singh Brar
2013-06-08 17:34 ` [PATCH v5 7/7] clk: samsung: Add EPLL and VPLL freq table for exynos5250 SoC Yadwinder Singh Brar
2013-06-17 20:08 ` Andrew Bresticker
2013-06-18 7:10 ` Vikas Sajjan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).