0001
0002
0003
0004
0005
0006
0007 #include <linux/clk-provider.h>
0008 #include <linux/module.h>
0009
0010 #include "clk-regmap.h"
0011 #include "clk-cpu-dyndiv.h"
0012
0013 static inline struct meson_clk_cpu_dyndiv_data *
0014 meson_clk_cpu_dyndiv_data(struct clk_regmap *clk)
0015 {
0016 return (struct meson_clk_cpu_dyndiv_data *)clk->data;
0017 }
0018
0019 static unsigned long meson_clk_cpu_dyndiv_recalc_rate(struct clk_hw *hw,
0020 unsigned long prate)
0021 {
0022 struct clk_regmap *clk = to_clk_regmap(hw);
0023 struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
0024
0025 return divider_recalc_rate(hw, prate,
0026 meson_parm_read(clk->map, &data->div),
0027 NULL, 0, data->div.width);
0028 }
0029
0030 static long meson_clk_cpu_dyndiv_round_rate(struct clk_hw *hw,
0031 unsigned long rate,
0032 unsigned long *prate)
0033 {
0034 struct clk_regmap *clk = to_clk_regmap(hw);
0035 struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
0036
0037 return divider_round_rate(hw, rate, prate, NULL, data->div.width, 0);
0038 }
0039
0040 static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw *hw, unsigned long rate,
0041 unsigned long parent_rate)
0042 {
0043 struct clk_regmap *clk = to_clk_regmap(hw);
0044 struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
0045 unsigned int val;
0046 int ret;
0047
0048 ret = divider_get_val(rate, parent_rate, NULL, data->div.width, 0);
0049 if (ret < 0)
0050 return ret;
0051
0052 val = (unsigned int)ret << data->div.shift;
0053
0054
0055 meson_parm_write(clk->map, &data->dyn, 1);
0056
0057
0058 return regmap_update_bits(clk->map, data->div.reg_off,
0059 SETPMASK(data->div.width, data->div.shift) |
0060 SETPMASK(data->dyn.width, data->dyn.shift),
0061 val);
0062 };
0063
0064 const struct clk_ops meson_clk_cpu_dyndiv_ops = {
0065 .recalc_rate = meson_clk_cpu_dyndiv_recalc_rate,
0066 .round_rate = meson_clk_cpu_dyndiv_round_rate,
0067 .set_rate = meson_clk_cpu_dyndiv_set_rate,
0068 };
0069 EXPORT_SYMBOL_GPL(meson_clk_cpu_dyndiv_ops);
0070
0071 MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider");
0072 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
0073 MODULE_LICENSE("GPL v2");