Skip to content

Commit 897117e

Browse files
ziyao233bebarino
authored andcommitted
clk: loongson2: Support scale clocks with an alternative mode
LS2K0300 and LS2K1500 ship scale clocks with an alternative mode. There's one mode bit in clock configuration register indicating the operation mode. When mode bit is unset, the scale clock acts the same as previous generation of scale clocks. When it's set, a different equation for calculating result frequency, Fout = Fin / (scale + 1), is used. This patch adds frequency calculation support for the scale clock variant. A helper macro, CLK_SCALE_MODE, is added to simplify definitions. Signed-off-by: Yao Zi <ziyao@disroot.org> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
1 parent 499f818 commit 897117e

1 file changed

Lines changed: 23 additions & 3 deletions

File tree

drivers/clk/clk-loongson2.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct loongson2_clk_data {
4242
u8 div_width;
4343
u8 mult_shift;
4444
u8 mult_width;
45+
u8 bit_idx;
4546
};
4647

4748
struct loongson2_clk_board_info {
@@ -96,6 +97,19 @@ struct loongson2_clk_board_info {
9697
.div_width = _dwidth, \
9798
}
9899

100+
#define CLK_SCALE_MODE(_id, _name, _pname, _offset, \
101+
_dshift, _dwidth, _midx) \
102+
{ \
103+
.id = _id, \
104+
.type = CLK_TYPE_SCALE, \
105+
.name = _name, \
106+
.parent_name = _pname, \
107+
.reg_offset = _offset, \
108+
.div_shift = _dshift, \
109+
.div_width = _dwidth, \
110+
.bit_idx = _midx + 1, \
111+
}
112+
99113
#define CLK_GATE(_id, _name, _pname, _offset, _bidx) \
100114
{ \
101115
.id = _id, \
@@ -243,13 +257,18 @@ static const struct clk_ops loongson2_pll_recalc_ops = {
243257
static unsigned long loongson2_freqscale_recalc_rate(struct clk_hw *hw,
244258
unsigned long parent_rate)
245259
{
246-
u64 val, mult;
260+
u64 val, scale;
261+
u32 mode = 0;
247262
struct loongson2_clk_data *clk = to_loongson2_clk(hw);
248263

249264
val = readq(clk->reg);
250-
mult = loongson2_rate_part(val, clk->div_shift, clk->div_width) + 1;
265+
scale = loongson2_rate_part(val, clk->div_shift, clk->div_width) + 1;
266+
267+
if (clk->bit_idx)
268+
mode = val & BIT(clk->bit_idx - 1);
251269

252-
return div_u64((u64)parent_rate * mult, 8);
270+
return mode == 0 ? div_u64((u64)parent_rate * scale, 8) :
271+
div_u64((u64)parent_rate, scale);
253272
}
254273

255274
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,
284303
clk->div_width = cld->div_width;
285304
clk->mult_shift = cld->mult_shift;
286305
clk->mult_width = cld->mult_width;
306+
clk->bit_idx = cld->bit_idx;
287307
clk->hw.init = &init;
288308

289309
hw = &clk->hw;

0 commit comments

Comments
 (0)