[PATCH v8 2/3] clk: canaan: Add clock driver for Canaan K230
Vivian Wang
wangruikang at iscas.ac.cn
Tue Sep 9 00:02:55 PDT 2025
On 9/8/25 22:13, Xukai Wang wrote:
>>> [...]
>>>
>>> +
>>> +static int k230_clk_set_rate_mul_div(struct clk_hw *hw, unsigned long rate,
>>> + unsigned long parent_rate)
>>> +{
>>> + struct k230_clk_rate *clk = hw_to_k230_clk_rate(hw);
>>> + struct k230_clk_rate_self *rate_self = &clk->clk;
>>> + u32 div, mul, div_reg, mul_reg;
>>> +
>>> + if (rate > parent_rate)
>>> + return -EINVAL;
>>> +
>>> + if (rate_self->read_only)
>>> + return 0;
>>> +
>>> + if (k230_clk_find_approximate_mul_div(rate_self->mul_min, rate_self->mul_max,
>>> + rate_self->div_min, rate_self->div_max,
>>> + rate, parent_rate, &div, &mul))
>>> + return -EINVAL;
>>> +
>>> + guard(spinlock)(rate_self->lock);
>>> +
>>> + div_reg = readl(rate_self->reg + clk->div_reg_off);
>>> + div_reg |= ((div - 1) & rate_self->div_mask) << (rate_self->div_shift);
>>> + div_reg |= BIT(rate_self->write_enable_bit);
>>> + writel(div_reg, rate_self->reg + clk->div_reg_off);
>>> +
>>> + mul_reg = readl(rate_self->reg + clk->mul_reg_off);
>>> + mul_reg |= ((mul - 1) & rate_self->mul_mask) << (rate_self->mul_shift);
>>> + mul_reg |= BIT(rate_self->write_enable_bit);
>>> + writel(mul_reg, rate_self->reg + clk->mul_reg_off);
>>> +
>>> + return 0;
>>> +}
>> There are three variants of rate clocks, mul-only, div-only and mul-div
>> ones, which are similar to clk-multiplier, clk-divider,
>> clk-fractional-divider.
>>
>> The only difference is to setup new parameters for K230's rate clocks,
>> a register bit, described as k230_clk_rate_self.write_enable_bit, must
>> be set first.
> Actually, I think the differences are not limited to just the
> write_enable_bit. There are also distinct mul_min, mul_max, div_min, and
> div_max values, which are not typically just 1 and (1 << bit_width) as
> in standard clock divider or multiplier structures.
So the part I have been thinking about is, consider just checking the
{mul,div}_{min,max} values to determine which kind it is? As is this is
just redundant information, since you can infer whether there is a
configurable multiplier by checking if mul_{min,max} are equal. Same for
div_{min,max}.
Vivian "dramforever" Wang
> For example, the div_min for hs_sd_card_src_rate is 2, not 1. This
> affects the calculation of the approximate divider, and cannot be fully
> represented if we only use the clk_divider structure.
>
> Another example is ls_codec_adc_rate, where mul_min is 0x10, mul_max is
> 0x1B9, div_min is 0xC35, and div_max is 0x3D09. These specific ranges
> cannot be described using the normal clk_fractional_divider structure.
>
More information about the linux-riscv
mailing list