summaryrefslogtreecommitdiffstats
path: root/drivers/clk/renesas/r8a7795-cpg-mssr.c
diff options
context:
space:
mode:
authorGeert Uytterhoeven <geert+renesas@glider.be>2016-05-04 14:32:56 +0200
committerGeert Uytterhoeven <geert+renesas@glider.be>2016-06-06 11:58:31 +0200
commit5b1defde7054e66da5c0f6cba8b35cef29edede0 (patch)
treec3f4f475b8f73ebeea57b8a334a32f54b56285f5 /drivers/clk/renesas/r8a7795-cpg-mssr.c
parent972610fb23b08dd54879102a9d5be695d53b728b (diff)
downloadblackbird-obmc-linux-5b1defde7054e66da5c0f6cba8b35cef29edede0.tar.gz
blackbird-obmc-linux-5b1defde7054e66da5c0f6cba8b35cef29edede0.zip
clk: renesas: cpg-mssr: Extract common R-Car Gen3 support code
Extract the code to support parts common to all members of the R-Car Gen3 SoC family into a separate file, to ease sharing among SoC-specific drivers. Note that while the cpg_pll_configs[] arrays and the selection of the config based on the MODE bits are identical on R-Car H3 and R-Car M3-W, they are not common, and may be different on other R-Car Gen3 SoCs. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Tested-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'drivers/clk/renesas/r8a7795-cpg-mssr.c')
-rw-r--r--drivers/clk/renesas/r8a7795-cpg-mssr.c360
1 files changed, 5 insertions, 355 deletions
diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c
index ca5519c583d4..e53aff5b23ad 100644
--- a/drivers/clk/renesas/r8a7795-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c
@@ -12,22 +12,14 @@
* 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,
};
OpenPOWER on IntegriCloud