clk: renesas: cpg-mssr: Extract common R-Car Gen3 support code
[linux-2.6-block.git] / drivers / clk / renesas / r8a7795-cpg-mssr.c
index ca5519c583d4bf57d1c948abc4bf76ee4b8e60c7..e53aff5b23ad4967291def960db7a5331f443362 100644 (file)
  * the Free Software Foundation; version 2 of the License.
  */
 
-#include <linux/bug.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
 #include <linux/device.h>
-#include <linux/err.h>
 #include <linux/init.h>
-#include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/of.h>
-#include <linux/slab.h>
 
 #include <dt-bindings/clock/r8a7795-cpg-mssr.h>
 
 #include "renesas-cpg-mssr.h"
-
-#define CPG_RCKCR      0x240
+#include "rcar-gen3-cpg.h"
 
 enum clk_ids {
        /* Core Clock Outputs exported to DT */
@@ -58,20 +50,6 @@ enum clk_ids {
        MOD_CLK_BASE
 };
 
-enum r8a7795_clk_types {
-       CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM,
-       CLK_TYPE_GEN3_PLL0,
-       CLK_TYPE_GEN3_PLL1,
-       CLK_TYPE_GEN3_PLL2,
-       CLK_TYPE_GEN3_PLL3,
-       CLK_TYPE_GEN3_PLL4,
-       CLK_TYPE_GEN3_SD,
-       CLK_TYPE_GEN3_R,
-};
-
-#define DEF_GEN3_SD(_name, _id, _parent, _offset)      \
-       DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
-
 static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
        /* External Clock Inputs */
        DEF_INPUT("extal",  CLK_EXTAL),
@@ -262,225 +240,6 @@ static const unsigned int r8a7795_crit_mod_clks[] __initconst = {
        MOD_CLK_ID(408),        /* INTC-AP (GIC) */
 };
 
-/* -----------------------------------------------------------------------------
- * SDn Clock
- *
- */
-#define CPG_SD_STP_HCK         BIT(9)
-#define CPG_SD_STP_CK          BIT(8)
-
-#define CPG_SD_STP_MASK                (CPG_SD_STP_HCK | CPG_SD_STP_CK)
-#define CPG_SD_FC_MASK         (0x7 << 2 | 0x3 << 0)
-
-#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \
-{ \
-       .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \
-              ((stp_ck) ? CPG_SD_STP_CK : 0) | \
-              ((sd_srcfc) << 2) | \
-              ((sd_fc) << 0), \
-       .div = (sd_div), \
-}
-
-struct sd_div_table {
-       u32 val;
-       unsigned int div;
-};
-
-struct sd_clock {
-       struct clk_hw hw;
-       void __iomem *reg;
-       const struct sd_div_table *div_table;
-       unsigned int div_num;
-       unsigned int div_min;
-       unsigned int div_max;
-};
-
-/* SDn divider
- *                     sd_srcfc   sd_fc   div
- * stp_hck   stp_ck    (div)      (div)     = sd_srcfc x sd_fc
- *-------------------------------------------------------------------
- *  0         0         0 (1)      1 (4)      4
- *  0         0         1 (2)      1 (4)      8
- *  1         0         2 (4)      1 (4)     16
- *  1         0         3 (8)      1 (4)     32
- *  1         0         4 (16)     1 (4)     64
- *  0         0         0 (1)      0 (2)      2
- *  0         0         1 (2)      0 (2)      4
- *  1         0         2 (4)      0 (2)      8
- *  1         0         3 (8)      0 (2)     16
- *  1         0         4 (16)     0 (2)     32
- */
-static const struct sd_div_table cpg_sd_div_table[] = {
-/*     CPG_SD_DIV_TABLE_DATA(stp_hck,  stp_ck,   sd_srcfc,   sd_fc,  sd_div) */
-       CPG_SD_DIV_TABLE_DATA(0,        0,        0,          1,        4),
-       CPG_SD_DIV_TABLE_DATA(0,        0,        1,          1,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        2,          1,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        3,          1,       32),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        4,          1,       64),
-       CPG_SD_DIV_TABLE_DATA(0,        0,        0,          0,        2),
-       CPG_SD_DIV_TABLE_DATA(0,        0,        1,          0,        4),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        2,          0,        8),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        3,          0,       16),
-       CPG_SD_DIV_TABLE_DATA(1,        0,        4,          0,       32),
-};
-
-#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw)
-
-static int cpg_sd_clock_enable(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       u32 val, sd_fc;
-       unsigned int i;
-
-       val = clk_readl(clock->reg);
-
-       sd_fc = val & CPG_SD_FC_MASK;
-       for (i = 0; i < clock->div_num; i++)
-               if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
-                       break;
-
-       if (i >= clock->div_num)
-               return -EINVAL;
-
-       val &= ~(CPG_SD_STP_MASK);
-       val |= clock->div_table[i].val & CPG_SD_STP_MASK;
-
-       clk_writel(val, clock->reg);
-
-       return 0;
-}
-
-static void cpg_sd_clock_disable(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg);
-}
-
-static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-
-       return !(clk_readl(clock->reg) & CPG_SD_STP_MASK);
-}
-
-static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
-                                               unsigned long parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned long rate = parent_rate;
-       u32 val, sd_fc;
-       unsigned int i;
-
-       val = clk_readl(clock->reg);
-
-       sd_fc = val & CPG_SD_FC_MASK;
-       for (i = 0; i < clock->div_num; i++)
-               if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK))
-                       break;
-
-       if (i >= clock->div_num)
-               return -EINVAL;
-
-       return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div);
-}
-
-static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock,
-                                         unsigned long rate,
-                                         unsigned long parent_rate)
-{
-       unsigned int div;
-
-       if (!rate)
-               rate = 1;
-
-       div = DIV_ROUND_CLOSEST(parent_rate, rate);
-
-       return clamp_t(unsigned int, div, clock->div_min, clock->div_max);
-}
-
-static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate,
-                                     unsigned long *parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate);
-
-       return DIV_ROUND_CLOSEST(*parent_rate, div);
-}
-
-static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
-                                  unsigned long parent_rate)
-{
-       struct sd_clock *clock = to_sd_clock(hw);
-       unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate);
-       u32 val;
-       unsigned int i;
-
-       for (i = 0; i < clock->div_num; i++)
-               if (div == clock->div_table[i].div)
-                       break;
-
-       if (i >= clock->div_num)
-               return -EINVAL;
-
-       val = clk_readl(clock->reg);
-       val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
-       val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
-       clk_writel(val, clock->reg);
-
-       return 0;
-}
-
-static const struct clk_ops cpg_sd_clock_ops = {
-       .enable = cpg_sd_clock_enable,
-       .disable = cpg_sd_clock_disable,
-       .is_enabled = cpg_sd_clock_is_enabled,
-       .recalc_rate = cpg_sd_clock_recalc_rate,
-       .round_rate = cpg_sd_clock_round_rate,
-       .set_rate = cpg_sd_clock_set_rate,
-};
-
-static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
-                                              void __iomem *base,
-                                              const char *parent_name)
-{
-       struct clk_init_data init;
-       struct sd_clock *clock;
-       struct clk *clk;
-       unsigned int i;
-
-       clock = kzalloc(sizeof(*clock), GFP_KERNEL);
-       if (!clock)
-               return ERR_PTR(-ENOMEM);
-
-       init.name = core->name;
-       init.ops = &cpg_sd_clock_ops;
-       init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
-       init.parent_names = &parent_name;
-       init.num_parents = 1;
-
-       clock->reg = base + core->offset;
-       clock->hw.init = &init;
-       clock->div_table = cpg_sd_div_table;
-       clock->div_num = ARRAY_SIZE(cpg_sd_div_table);
-
-       clock->div_max = clock->div_table[0].div;
-       clock->div_min = clock->div_max;
-       for (i = 1; i < clock->div_num; i++) {
-               clock->div_max = max(clock->div_max, clock->div_table[i].div);
-               clock->div_min = min(clock->div_min, clock->div_table[i].div);
-       }
-
-       clk = clk_register(NULL, &clock->hw);
-       if (IS_ERR(clk))
-               kfree(clock);
-
-       return clk;
-}
-
-#define CPG_PLL0CR     0x00d8
-#define CPG_PLL2CR     0x002c
-#define CPG_PLL4CR     0x01f4
 
 /*
  * CPG Clock Data
@@ -512,13 +271,7 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
                                         (((md) & BIT(19)) >> 18) | \
                                         (((md) & BIT(17)) >> 17))
 
-struct cpg_pll_config {
-       unsigned int extal_div;
-       unsigned int pll1_mult;
-       unsigned int pll3_mult;
-};
-
-static const struct cpg_pll_config cpg_pll_configs[16] __initconst = {
+static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
        /* EXTAL div    PLL1 mult       PLL3 mult */
        { 1,            192,            192,    },
        { 1,            192,            128,    },
@@ -538,112 +291,9 @@ static const struct cpg_pll_config cpg_pll_configs[16] __initconst = {
        { 2,            192,            192,    },
 };
 
-static const struct cpg_pll_config *cpg_pll_config __initdata;
-
-static
-struct clk * __init r8a7795_cpg_clk_register(struct device *dev,
-                                            const struct cpg_core_clk *core,
-                                            const struct cpg_mssr_info *info,
-                                            struct clk **clks,
-                                            void __iomem *base)
-{
-       const struct clk *parent;
-       unsigned int mult = 1;
-       unsigned int div = 1;
-       u32 value;
-
-       parent = clks[core->parent];
-       if (IS_ERR(parent))
-               return ERR_CAST(parent);
-
-       switch (core->type) {
-       case CLK_TYPE_GEN3_MAIN:
-               div = cpg_pll_config->extal_div;
-               break;
-
-       case CLK_TYPE_GEN3_PLL0:
-               /*
-                * PLL0 is a configurable multiplier clock. Register it as a
-                * fixed factor clock for now as there's no generic multiplier
-                * clock implementation and we currently have no need to change
-                * the multiplier value.
-                */
-               value = readl(base + CPG_PLL0CR);
-               mult = (((value >> 24) & 0x7f) + 1) * 2;
-               break;
-
-       case CLK_TYPE_GEN3_PLL1:
-               mult = cpg_pll_config->pll1_mult;
-               break;
-
-       case CLK_TYPE_GEN3_PLL2:
-               /*
-                * PLL2 is a configurable multiplier clock. Register it as a
-                * fixed factor clock for now as there's no generic multiplier
-                * clock implementation and we currently have no need to change
-                * the multiplier value.
-                */
-               value = readl(base + CPG_PLL2CR);
-               mult = (((value >> 24) & 0x7f) + 1) * 2;
-               break;
-
-       case CLK_TYPE_GEN3_PLL3:
-               mult = cpg_pll_config->pll3_mult;
-               break;
-
-       case CLK_TYPE_GEN3_PLL4:
-               /*
-                * PLL4 is a configurable multiplier clock. Register it as a
-                * fixed factor clock for now as there's no generic multiplier
-                * clock implementation and we currently have no need to change
-                * the multiplier value.
-                */
-               value = readl(base + CPG_PLL4CR);
-               mult = (((value >> 24) & 0x7f) + 1) * 2;
-               break;
-
-       case CLK_TYPE_GEN3_SD:
-               return cpg_sd_clk_register(core, base, __clk_get_name(parent));
-
-       case CLK_TYPE_GEN3_R:
-               /* RINT is default. Only if EXTALR is populated, we switch to it */
-               value = readl(base + CPG_RCKCR) & 0x3f;
-
-               if (clk_get_rate(clks[CLK_EXTALR])) {
-                       parent = clks[CLK_EXTALR];
-                       value |= BIT(15);
-               }
-
-               writel(value, base + CPG_RCKCR);
-               break;
-
-       default:
-               return ERR_PTR(-EINVAL);
-       }
-
-       return clk_register_fixed_factor(NULL, core->name,
-                                        __clk_get_name(parent), 0, mult, div);
-}
-
-/*
- * Reset register definitions.
- */
-#define MODEMR 0xe6160060
-
-static u32 rcar_gen3_read_mode_pins(void)
-{
-       void __iomem *modemr = ioremap_nocache(MODEMR, 4);
-       u32 mode;
-
-       BUG_ON(!modemr);
-       mode = ioread32(modemr);
-       iounmap(modemr);
-
-       return mode;
-}
-
 static int __init r8a7795_cpg_mssr_init(struct device *dev)
 {
+       const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
        u32 cpg_mode = rcar_gen3_read_mode_pins();
 
        cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
@@ -652,7 +302,7 @@ static int __init r8a7795_cpg_mssr_init(struct device *dev)
                return -EINVAL;
        }
 
-       return 0;
+       return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR);
 }
 
 const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = {
@@ -673,5 +323,5 @@ const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = {
 
        /* Callbacks */
        .init = r8a7795_cpg_mssr_init,
-       .cpg_clk_register = r8a7795_cpg_clk_register,
+       .cpg_clk_register = rcar_gen3_cpg_clk_register,
 };