From 8e88bc5ff96131cec9a8154e862247dac5194460 Mon Sep 17 00:00:00 2001 From: Deepak Katragadda Date: Thu, 29 Sep 2016 13:28:59 +0530 Subject: [PATCH] clk: qcom: Add support for hardware control branch clocks Add new ops to allow clock clients to enable/disable hardware dynamic gating of the clock branch. Change-Id: I14abed3827de8cefc31f3deb3c1e589136c32b8d Signed-off-by: Taniya Das Signed-off-by: Deepak Katragadda Signed-off-by: David Dai Signed-off-by: David Collins --- drivers/clk/qcom/clk-branch.c | 56 +++++++++++++++++++++++++++++++++-- drivers/clk/qcom/clk-branch.h | 5 ++-- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index f869fc6aaed6..43ad05b584d7 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -1,6 +1,6 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved. */ #include @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -152,6 +153,57 @@ const struct clk_ops clk_branch2_aon_ops = { }; EXPORT_SYMBOL_GPL(clk_branch2_aon_ops); +static unsigned long clk_branch2_hw_ctl_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate; +} + +static int clk_branch2_hw_ctl_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_hw *clkp; + + clkp = clk_hw_get_parent(hw); + if (!clkp) + return -EINVAL; + + req->best_parent_hw = clkp; + req->best_parent_rate = clk_round_rate(clkp->clk, req->rate); + + return 0; +} + +static int clk_branch2_hw_ctl_enable(struct clk_hw *hw) +{ + struct clk_hw *parent = clk_hw_get_parent(hw); + + /* The parent branch clock should have been prepared prior to this. */ + if (!parent || (parent && !clk_hw_is_prepared(parent))) + return -EINVAL; + + return clk_enable_regmap(hw); +} + +static void clk_branch2_hw_ctl_disable(struct clk_hw *hw) +{ + struct clk_hw *parent = clk_hw_get_parent(hw); + + if (!parent) + return; + + clk_disable_regmap(hw); +} + +const struct clk_ops clk_branch2_hw_ctl_ops = { + .enable = clk_branch2_hw_ctl_enable, + .disable = clk_branch2_hw_ctl_disable, + .is_enabled = clk_is_enabled_regmap, + .recalc_rate = clk_branch2_hw_ctl_recalc_rate, + .determine_rate = clk_branch2_hw_ctl_determine_rate, +}; +EXPORT_SYMBOL(clk_branch2_hw_ctl_ops); + const struct clk_ops clk_branch_simple_ops = { .enable = clk_enable_regmap, .disable = clk_disable_regmap, diff --git a/drivers/clk/qcom/clk-branch.h b/drivers/clk/qcom/clk-branch.h index 17a58119165e..8f71551b2aea 100644 --- a/drivers/clk/qcom/clk-branch.h +++ b/drivers/clk/qcom/clk-branch.h @@ -1,5 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (c) 2013, The Linux Foundation. All rights reserved. */ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2013, 2016, The Linux Foundation. All rights reserved. */ #ifndef __QCOM_CLK_BRANCH_H__ #define __QCOM_CLK_BRANCH_H__ @@ -39,6 +39,7 @@ struct clk_branch { extern const struct clk_ops clk_branch_ops; extern const struct clk_ops clk_branch2_ops; +extern const struct clk_ops clk_branch2_hw_ctl_ops; extern const struct clk_ops clk_branch_simple_ops; extern const struct clk_ops clk_branch2_aon_ops;