0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk-provider.h>
0012 #include <linux/regmap.h>
0013
0014 #include "owl-divider.h"
0015
0016 long owl_divider_helper_round_rate(struct owl_clk_common *common,
0017 const struct owl_divider_hw *div_hw,
0018 unsigned long rate,
0019 unsigned long *parent_rate)
0020 {
0021 return divider_round_rate(&common->hw, rate, parent_rate,
0022 div_hw->table, div_hw->width,
0023 div_hw->div_flags);
0024 }
0025
0026 static long owl_divider_round_rate(struct clk_hw *hw, unsigned long rate,
0027 unsigned long *parent_rate)
0028 {
0029 struct owl_divider *div = hw_to_owl_divider(hw);
0030
0031 return owl_divider_helper_round_rate(&div->common, &div->div_hw,
0032 rate, parent_rate);
0033 }
0034
0035 unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common,
0036 const struct owl_divider_hw *div_hw,
0037 unsigned long parent_rate)
0038 {
0039 unsigned long val;
0040 unsigned int reg;
0041
0042 regmap_read(common->regmap, div_hw->reg, ®);
0043 val = reg >> div_hw->shift;
0044 val &= (1 << div_hw->width) - 1;
0045
0046 return divider_recalc_rate(&common->hw, parent_rate,
0047 val, div_hw->table,
0048 div_hw->div_flags,
0049 div_hw->width);
0050 }
0051
0052 static unsigned long owl_divider_recalc_rate(struct clk_hw *hw,
0053 unsigned long parent_rate)
0054 {
0055 struct owl_divider *div = hw_to_owl_divider(hw);
0056
0057 return owl_divider_helper_recalc_rate(&div->common,
0058 &div->div_hw, parent_rate);
0059 }
0060
0061 int owl_divider_helper_set_rate(const struct owl_clk_common *common,
0062 const struct owl_divider_hw *div_hw,
0063 unsigned long rate,
0064 unsigned long parent_rate)
0065 {
0066 unsigned long val;
0067 unsigned int reg;
0068
0069 val = divider_get_val(rate, parent_rate, div_hw->table,
0070 div_hw->width, 0);
0071
0072 regmap_read(common->regmap, div_hw->reg, ®);
0073 reg &= ~GENMASK(div_hw->width + div_hw->shift - 1, div_hw->shift);
0074
0075 regmap_write(common->regmap, div_hw->reg,
0076 reg | (val << div_hw->shift));
0077
0078 return 0;
0079 }
0080
0081 static int owl_divider_set_rate(struct clk_hw *hw, unsigned long rate,
0082 unsigned long parent_rate)
0083 {
0084 struct owl_divider *div = hw_to_owl_divider(hw);
0085
0086 return owl_divider_helper_set_rate(&div->common, &div->div_hw,
0087 rate, parent_rate);
0088 }
0089
0090 const struct clk_ops owl_divider_ops = {
0091 .recalc_rate = owl_divider_recalc_rate,
0092 .round_rate = owl_divider_round_rate,
0093 .set_rate = owl_divider_set_rate,
0094 };