clk: samsung: Add support to register rate_table for samsung plls
authorYadwinder Singh Brar <yadi.brar@samsung.com>
Tue, 11 Jun 2013 09:31:12 +0000 (15:01 +0530)
committerMike Turquette <mturquette@linaro.org>
Fri, 2 Aug 2013 20:22:09 +0000 (13:22 -0700)
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>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
drivers/clk/samsung/clk-exynos4.c
drivers/clk/samsung/clk-exynos5250.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/samsung/clk-pll.c
drivers/clk/samsung/clk-pll.h
drivers/clk/samsung/clk.h

index 9de7a39..68f9a4a 100644 (file)
@@ -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 */
index b9a5f2a..46a1636 100644 (file)
@@ -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[] = {
index 3dbe7a3..ca35269 100644 (file)
@@ -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[] = {
index dd948f2..8394231 100644 (file)
@@ -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:
index 1536f27..95ae23d 100644 (file)
@@ -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,
index 4e83e52..b3f2532 100644 (file)
@@ -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,