Browse Source

clk: renesas: cpg-mssr: add generic support for read-only DIV6 clocks

Gen3 has two clocks (OSC and R) which look like a DIV6 clock but their
divider value is read-only and depends on MD pins at bootup. Add support
for such clocks by reading the value and adding a fixed clock.

Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Wolfram Sang 9 years ago
parent
commit
5d3927f655
2 changed files with 15 additions and 6 deletions
  1. 12 6
      drivers/clk/renesas/renesas-cpg-mssr.c
  2. 3 0
      drivers/clk/renesas/renesas-cpg-mssr.h

+ 12 - 6
drivers/clk/renesas/renesas-cpg-mssr.c

@@ -253,7 +253,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
 {
 {
 	struct clk *clk = NULL, *parent;
 	struct clk *clk = NULL, *parent;
 	struct device *dev = priv->dev;
 	struct device *dev = priv->dev;
-	unsigned int id = core->id;
+	unsigned int id = core->id, div = core->div;
 	const char *parent_name;
 	const char *parent_name;
 
 
 	WARN_DEBUG(id >= priv->num_core_clks);
 	WARN_DEBUG(id >= priv->num_core_clks);
@@ -266,6 +266,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
 
 
 	case CLK_TYPE_FF:
 	case CLK_TYPE_FF:
 	case CLK_TYPE_DIV6P1:
 	case CLK_TYPE_DIV6P1:
+	case CLK_TYPE_DIV6_RO:
 		WARN_DEBUG(core->parent >= priv->num_core_clks);
 		WARN_DEBUG(core->parent >= priv->num_core_clks);
 		parent = priv->clks[core->parent];
 		parent = priv->clks[core->parent];
 		if (IS_ERR(parent)) {
 		if (IS_ERR(parent)) {
@@ -274,13 +275,18 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
 		}
 		}
 
 
 		parent_name = __clk_get_name(parent);
 		parent_name = __clk_get_name(parent);
-		if (core->type == CLK_TYPE_FF) {
-			clk = clk_register_fixed_factor(NULL, core->name,
-							parent_name, 0,
-							core->mult, core->div);
-		} else {
+
+		if (core->type == CLK_TYPE_DIV6_RO)
+			/* Multiply with the DIV6 register value */
+			div *= (readl(priv->base + core->offset) & 0x3f) + 1;
+
+		if (core->type == CLK_TYPE_DIV6P1) {
 			clk = cpg_div6_register(core->name, 1, &parent_name,
 			clk = cpg_div6_register(core->name, 1, &parent_name,
 						priv->base + core->offset);
 						priv->base + core->offset);
+		} else {
+			clk = clk_register_fixed_factor(NULL, core->name,
+							parent_name, 0,
+							core->mult, div);
 		}
 		}
 		break;
 		break;
 
 

+ 3 - 0
drivers/clk/renesas/renesas-cpg-mssr.h

@@ -37,6 +37,7 @@ enum clk_types {
 	CLK_TYPE_IN,		/* External Clock Input */
 	CLK_TYPE_IN,		/* External Clock Input */
 	CLK_TYPE_FF,		/* Fixed Factor Clock */
 	CLK_TYPE_FF,		/* Fixed Factor Clock */
 	CLK_TYPE_DIV6P1,	/* DIV6 Clock with 1 parent clock */
 	CLK_TYPE_DIV6P1,	/* DIV6 Clock with 1 parent clock */
+	CLK_TYPE_DIV6_RO,	/* DIV6 Clock read only with extra divisor */
 
 
 	/* Custom definitions start here */
 	/* Custom definitions start here */
 	CLK_TYPE_CUSTOM,
 	CLK_TYPE_CUSTOM,
@@ -53,6 +54,8 @@ enum clk_types {
 	DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
 	DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
 #define DEF_DIV6P1(_name, _id, _parent, _offset)	\
 #define DEF_DIV6P1(_name, _id, _parent, _offset)	\
 	DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset)
 	DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset)
+#define DEF_DIV6_RO(_name, _id, _parent, _offset, _div)	\
+	DEF_BASE(_name, _id, CLK_TYPE_DIV6_RO, _parent, .offset = _offset, .div = _div, .mult = 1)
 
 
     /*
     /*
      * Definitions of Module Clocks
      * Definitions of Module Clocks