12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- // SPDX-License-Identifier: GPL-2.0
- //
- // Spreadtrum divider clock driver
- //
- // Copyright (C) 2017 Spreadtrum, Inc.
- // Author: Chunyan Zhang <[email protected]>
- #include <linux/clk-provider.h>
- #include "div.h"
- long sprd_div_helper_round_rate(struct sprd_clk_common *common,
- const struct sprd_div_internal *div,
- unsigned long rate,
- unsigned long *parent_rate)
- {
- return divider_round_rate(&common->hw, rate, parent_rate,
- NULL, div->width, 0);
- }
- EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate);
- static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
- {
- struct sprd_div *cd = hw_to_sprd_div(hw);
- return sprd_div_helper_round_rate(&cd->common, &cd->div,
- rate, parent_rate);
- }
- unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
- const struct sprd_div_internal *div,
- unsigned long parent_rate)
- {
- unsigned long val;
- unsigned int reg;
- regmap_read(common->regmap, common->reg, ®);
- val = reg >> div->shift;
- val &= (1 << div->width) - 1;
- return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0,
- div->width);
- }
- EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate);
- static unsigned long sprd_div_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
- {
- struct sprd_div *cd = hw_to_sprd_div(hw);
- return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate);
- }
- int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
- const struct sprd_div_internal *div,
- unsigned long rate,
- unsigned long parent_rate)
- {
- unsigned long val;
- unsigned int reg;
- val = divider_get_val(rate, parent_rate, NULL,
- div->width, 0);
- regmap_read(common->regmap, common->reg, ®);
- reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
- regmap_write(common->regmap, common->reg,
- reg | (val << div->shift));
- return 0;
- }
- EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate);
- static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
- {
- struct sprd_div *cd = hw_to_sprd_div(hw);
- return sprd_div_helper_set_rate(&cd->common, &cd->div,
- rate, parent_rate);
- }
- const struct clk_ops sprd_div_ops = {
- .recalc_rate = sprd_div_recalc_rate,
- .round_rate = sprd_div_round_rate,
- .set_rate = sprd_div_set_rate,
- };
- EXPORT_SYMBOL_GPL(sprd_div_ops);
|