diff options
Diffstat (limited to 'drivers/clk/qcom/clk-regmap-divider.c')
| -rw-r--r-- | drivers/clk/qcom/clk-regmap-divider.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c index 53484912301e..4f5395f0ab6d 100644 --- a/drivers/clk/qcom/clk-regmap-divider.c +++ b/drivers/clk/qcom/clk-regmap-divider.c @@ -1,14 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2014, The Linux Foundation. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/kernel.h> @@ -23,13 +15,35 @@ static inline struct clk_regmap_div *to_clk_regmap_div(struct clk_hw *hw) return container_of(to_clk_regmap(hw), struct clk_regmap_div, clkr); } -static long div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) +static int div_ro_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_regmap_div *divider = to_clk_regmap_div(hw); + struct clk_regmap *clkr = ÷r->clkr; + u32 val; + + regmap_read(clkr->regmap, divider->reg, &val); + val >>= divider->shift; + val &= BIT(divider->width) - 1; + + req->rate = divider_ro_round_rate(hw, req->rate, + &req->best_parent_rate, NULL, + divider->width, + CLK_DIVIDER_ROUND_CLOSEST, val); + + return 0; +} + +static int div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + struct clk_regmap_div *divider = to_clk_regmap_div(hw); + + req->rate = divider_round_rate(hw, req->rate, &req->best_parent_rate, + NULL, + divider->width, + CLK_DIVIDER_ROUND_CLOSEST); - return divider_round_rate(hw, rate, prate, NULL, divider->width, - CLK_DIVIDER_ROUND_CLOSEST); + return 0; } static int div_set_rate(struct clk_hw *hw, unsigned long rate, @@ -59,12 +73,18 @@ static unsigned long div_recalc_rate(struct clk_hw *hw, div &= BIT(divider->width) - 1; return divider_recalc_rate(hw, parent_rate, div, NULL, - CLK_DIVIDER_ROUND_CLOSEST); + CLK_DIVIDER_ROUND_CLOSEST, divider->width); } const struct clk_ops clk_regmap_div_ops = { - .round_rate = div_round_rate, + .determine_rate = div_determine_rate, .set_rate = div_set_rate, .recalc_rate = div_recalc_rate, }; EXPORT_SYMBOL_GPL(clk_regmap_div_ops); + +const struct clk_ops clk_regmap_div_ro_ops = { + .determine_rate = div_ro_determine_rate, + .recalc_rate = div_recalc_rate, +}; +EXPORT_SYMBOL_GPL(clk_regmap_div_ro_ops); |
