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>
This commit is contained in:
Wolfram Sang 2016-03-30 16:58:18 +02:00 committed by Geert Uytterhoeven
parent ba8c1a81d4
commit 5d3927f655
2 changed files with 15 additions and 6 deletions

View file

@ -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, if (core->type == CLK_TYPE_DIV6_RO)
parent_name, 0, /* Multiply with the DIV6 register value */
core->mult, core->div); div *= (readl(priv->base + core->offset) & 0x3f) + 1;
} else {
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;

View file

@ -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