| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 |
|
| 8 | #include <linux/clk-provider.h>
|
| 9 |
|
| 10 | #include "div.h"
|
| 11 |
|
| 12 | static int sprd_div_determine_rate(struct clk_hw *hw,
|
| 13 | struct clk_rate_request *req)
|
| 14 | {
|
| 15 | struct sprd_div *cd = hw_to_sprd_div(hw);
|
| 16 |
|
| 17 | return divider_determine_rate(&cd->common.hw, req, NULL, cd->div.width, 0);
|
| 18 | }
|
| 19 |
|
| 20 | unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
|
| 21 | const struct sprd_div_internal *div,
|
| 22 | unsigned long parent_rate)
|
| 23 | {
|
| 24 | unsigned long val;
|
| 25 | unsigned int reg;
|
| 26 |
|
| 27 | regmap_read(common->regmap, common->reg + div->offset, ®);
|
| 28 | val = reg >> div->shift;
|
| 29 | val &= (1 << div->width) - 1;
|
| 30 |
|
| 31 | return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0,
|
| 32 | div->width);
|
| 33 | }
|
| 34 | EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate);
|
| 35 |
|
| 36 | static unsigned long sprd_div_recalc_rate(struct clk_hw *hw,
|
| 37 | unsigned long parent_rate)
|
| 38 | {
|
| 39 | struct sprd_div *cd = hw_to_sprd_div(hw);
|
| 40 |
|
| 41 | return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate);
|
| 42 | }
|
| 43 |
|
| 44 | int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
|
| 45 | const struct sprd_div_internal *div,
|
| 46 | unsigned long rate,
|
| 47 | unsigned long parent_rate)
|
| 48 | {
|
| 49 | unsigned long val;
|
| 50 | unsigned int reg;
|
| 51 |
|
| 52 | val = divider_get_val(rate, parent_rate, NULL,
|
| 53 | div->width, 0);
|
| 54 |
|
| 55 | regmap_read(common->regmap, common->reg + div->offset, ®);
|
| 56 | reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
|
| 57 |
|
| 58 | regmap_write(common->regmap, common->reg + div->offset,
|
| 59 | reg | (val << div->shift));
|
| 60 |
|
| 61 | return 0;
|
| 62 |
|
| 63 | }
|
| 64 | EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate);
|
| 65 |
|
| 66 | static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate,
|
| 67 | unsigned long parent_rate)
|
| 68 | {
|
| 69 | struct sprd_div *cd = hw_to_sprd_div(hw);
|
| 70 |
|
| 71 | return sprd_div_helper_set_rate(&cd->common, &cd->div,
|
| 72 | rate, parent_rate);
|
| 73 | }
|
| 74 |
|
| 75 | const struct clk_ops sprd_div_ops = {
|
| 76 | .recalc_rate = sprd_div_recalc_rate,
|
| 77 | .determine_rate = sprd_div_determine_rate,
|
| 78 | .set_rate = sprd_div_set_rate,
|
| 79 | };
|
| 80 | EXPORT_SYMBOL_GPL(sprd_div_ops);
|