diff options
Diffstat (limited to 'drivers/clk/renesas/rcar-cpg-lib.c')
| -rw-r--r-- | drivers/clk/renesas/rcar-cpg-lib.c | 83 | 
1 files changed, 83 insertions, 0 deletions
| diff --git a/drivers/clk/renesas/rcar-cpg-lib.c b/drivers/clk/renesas/rcar-cpg-lib.c index 5678768ee1f2..e93f0011eb07 100644 --- a/drivers/clk/renesas/rcar-cpg-lib.c +++ b/drivers/clk/renesas/rcar-cpg-lib.c @@ -267,4 +267,87 @@ free_clock:  	return clk;  } +struct rpc_clock { +	struct clk_divider div; +	struct clk_gate gate; +	/* +	 * One notifier covers both RPC and RPCD2 clocks as they are both +	 * controlled by the same RPCCKCR register... +	 */ +	struct cpg_simple_notifier csn; +}; + +static const struct clk_div_table cpg_rpc_div_table[] = { +	{ 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 }, +}; + +struct clk * __init cpg_rpc_clk_register(const char *name, +	void __iomem *rpcckcr, const char *parent_name, +	struct raw_notifier_head *notifiers) +{ +	struct rpc_clock *rpc; +	struct clk *clk; + +	rpc = kzalloc(sizeof(*rpc), GFP_KERNEL); +	if (!rpc) +		return ERR_PTR(-ENOMEM); + +	rpc->div.reg = rpcckcr; +	rpc->div.width = 3; +	rpc->div.table = cpg_rpc_div_table; +	rpc->div.lock = &cpg_lock; + +	rpc->gate.reg = rpcckcr; +	rpc->gate.bit_idx = 8; +	rpc->gate.flags = CLK_GATE_SET_TO_DISABLE; +	rpc->gate.lock = &cpg_lock; + +	rpc->csn.reg = rpcckcr; + +	clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, +				     &rpc->div.hw,  &clk_divider_ops, +				     &rpc->gate.hw, &clk_gate_ops, +				     CLK_SET_RATE_PARENT); +	if (IS_ERR(clk)) { +		kfree(rpc); +		return clk; +	} + +	cpg_simple_notifier_register(notifiers, &rpc->csn); +	return clk; +} + +struct rpcd2_clock { +	struct clk_fixed_factor fixed; +	struct clk_gate gate; +}; + +struct clk * __init cpg_rpcd2_clk_register(const char *name, +					   void __iomem *rpcckcr, +					   const char *parent_name) +{ +	struct rpcd2_clock *rpcd2; +	struct clk *clk; + +	rpcd2 = kzalloc(sizeof(*rpcd2), GFP_KERNEL); +	if (!rpcd2) +		return ERR_PTR(-ENOMEM); + +	rpcd2->fixed.mult = 1; +	rpcd2->fixed.div = 2; + +	rpcd2->gate.reg = rpcckcr; +	rpcd2->gate.bit_idx = 9; +	rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE; +	rpcd2->gate.lock = &cpg_lock; + +	clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, +				     &rpcd2->fixed.hw, &clk_fixed_factor_ops, +				     &rpcd2->gate.hw, &clk_gate_ops, +				     CLK_SET_RATE_PARENT); +	if (IS_ERR(clk)) +		kfree(rpcd2); + +	return clk; +} |