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