diff options
| -rw-r--r-- | drivers/clk/clk-loongson2.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c index cc3fb13e770f..bba97270376c 100644 --- a/drivers/clk/clk-loongson2.c +++ b/drivers/clk/clk-loongson2.c @@ -42,6 +42,7 @@ struct loongson2_clk_data { u8 div_width; u8 mult_shift; u8 mult_width; + u8 bit_idx; }; struct loongson2_clk_board_info { @@ -96,6 +97,19 @@ struct loongson2_clk_board_info { .div_width = _dwidth, \ } +#define CLK_SCALE_MODE(_id, _name, _pname, _offset, \ + _dshift, _dwidth, _midx) \ + { \ + .id = _id, \ + .type = CLK_TYPE_SCALE, \ + .name = _name, \ + .parent_name = _pname, \ + .reg_offset = _offset, \ + .div_shift = _dshift, \ + .div_width = _dwidth, \ + .bit_idx = _midx + 1, \ + } + #define CLK_GATE(_id, _name, _pname, _offset, _bidx) \ { \ .id = _id, \ @@ -243,13 +257,18 @@ static const struct clk_ops loongson2_pll_recalc_ops = { static unsigned long loongson2_freqscale_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - u64 val, mult; + u64 val, scale; + u32 mode = 0; struct loongson2_clk_data *clk = to_loongson2_clk(hw); val = readq(clk->reg); - mult = loongson2_rate_part(val, clk->div_shift, clk->div_width) + 1; + scale = loongson2_rate_part(val, clk->div_shift, clk->div_width) + 1; + + if (clk->bit_idx) + mode = val & BIT(clk->bit_idx - 1); - return div_u64((u64)parent_rate * mult, 8); + return mode == 0 ? div_u64((u64)parent_rate * scale, 8) : + div_u64((u64)parent_rate, scale); } static const struct clk_ops loongson2_freqscale_recalc_ops = { @@ -284,6 +303,7 @@ static struct clk_hw *loongson2_clk_register(struct loongson2_clk_provider *clp, clk->div_width = cld->div_width; clk->mult_shift = cld->mult_shift; clk->mult_width = cld->mult_width; + clk->bit_idx = cld->bit_idx; clk->hw.init = &init; hw = &clk->hw; |
