clk: qcom: Add support for clock dependency

Add clock ops for taking care of a dependent clock when the actual
clock requests are made.

Change-Id: I52691ef9f183da035ddf9c05fb73811f48fef74c
Signed-off-by: Taniya Das <tdas@codeaurora.org>
Signed-off-by: David Collins <collinsd@codeaurora.org>
This commit is contained in:
Taniya Das 2018-12-28 16:20:33 +05:30 • committed by David Collins
commit 228b95aa74
3 changed files with 104 additions and 2 deletions

View file

@ -171,6 +171,7 @@ extern const struct clk_ops clk_pixel_ops;
extern const struct clk_ops clk_gfx3d_ops;
extern const struct clk_ops clk_rcg2_shared_ops;
extern const struct clk_ops clk_dp_ops;
extern const struct clk_ops clk_rcg2_dependent_ops;
struct clk_rcg_dfs_data {
struct clk_rcg2 *rcg;

View file

@ -1411,3 +1411,102 @@ int qcom_cc_register_rcg_dfs(struct regmap *regmap,
return 0;
}
EXPORT_SYMBOL_GPL(qcom_cc_register_rcg_dfs);
static int clk_rcg2_dependent_enable(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
int ret;
ret = clk_rcg2_enable(hw);
if (ret < 0)
return ret;
return clk_enable(rcg->clkr.dependent_hw->clk);
}
static void clk_rcg2_dependent_disable(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
clk_rcg2_disable(hw);
clk_disable(rcg->clkr.dependent_hw->clk);
}
static int clk_rcg2_dependent_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
struct clk_hw *p_hw;
int ret;
ret = clk_rcg2_set_parent(hw, index);
if (ret < 0)
return ret;
p_hw = clk_hw_get_parent_by_index(rcg->clkr.dependent_hw, index);
return clk_set_parent(rcg->clkr.dependent_hw->clk, p_hw->clk);
}
static int clk_rcg2_dependent_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
__clk_determine_rate(rcg->clkr.dependent_hw, req);
return clk_rcg2_determine_rate(hw, req);
}
static int clk_rcg2_dependent_set_rate(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate)
{
int ret;
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
ret = clk_rcg2_set_rate(hw, rate, parent_rate);
if (ret < 0)
return ret;
return clk_set_rate(rcg->clkr.dependent_hw->clk, rate);
}
static int clk_rcg2_dependent_set_rate_and_parent(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate, u8 index)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
int ret;
ret = clk_rcg2_set_rate_and_parent(hw, rate, parent_rate, index);
if (ret < 0)
return ret;
return clk_set_rate(rcg->clkr.dependent_hw->clk, rate);
}
static int clk_rcg2_dependent_prepare(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
return clk_prepare(rcg->clkr.dependent_hw->clk);
}
static void clk_rcg2_dependent_unprepare(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
clk_unprepare(rcg->clkr.dependent_hw->clk);
}
const struct clk_ops clk_rcg2_dependent_ops = {
.is_enabled = clk_rcg2_is_enabled,
.prepare = clk_rcg2_dependent_prepare,
.unprepare = clk_rcg2_dependent_unprepare,
.enable = clk_rcg2_dependent_enable,
.disable = clk_rcg2_dependent_disable,
.get_parent = clk_rcg2_get_parent,
.set_parent = clk_rcg2_dependent_set_parent,
.recalc_rate = clk_rcg2_recalc_rate,
.determine_rate = clk_rcg2_dependent_determine_rate,
.set_rate = clk_rcg2_dependent_set_rate,
.set_rate_and_parent = clk_rcg2_dependent_set_rate_and_parent,
};
EXPORT_SYMBOL(clk_rcg2_dependent_ops);

View file

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2014, The Linux Foundation. All rights reserved. */
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2014, 2016-2018, The Linux Foundation. All rights reserved. */
#ifndef __QCOM_CLK_REGMAP_H__
#define __QCOM_CLK_REGMAP_H__
@ -11,6 +11,7 @@ struct regmap;
/**
* struct clk_regmap - regmap supporting clock
* @hw: handle between common and hardware-specific interfaces
* @dependent_hw: dependent clocks clock hw
* @regmap: regmap to use for regmap helpers and/or by providers
* @enable_reg: register when using regmap enable/disable ops
* @enable_mask: mask when using regmap enable/disable ops
@ -19,6 +20,7 @@ struct regmap;
*/
struct clk_regmap {
struct clk_hw hw;
struct clk_hw *dependent_hw;
struct regmap *regmap;
unsigned int enable_reg;
unsigned int enable_mask;