Hi Geert, On Thu, Jun 16, 2016 at 11:43 PM, Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> wrote: > On Fri, Jun 17, 2016 at 1:40 AM, Hoan Tran <hotran@xxxxxxx> wrote: >> This patch adds fractional scale clock support. >> Fractional scale clock is implemented for a single register field. >> Output rate = parent_rate * scale / denominator >> For example, for 1 / 8 fractional scale, denominator will be 8 and scale >> will be computed and programmed accordingly. >> >> Signed-off-by: Hoan Tran <hotran@xxxxxxx> >> Signed-off-by: Loc Ho <lho@xxxxxxx> > >> --- /dev/null >> +++ b/drivers/clk/clk-fractional-scale.c > >> +static long clk_fs_round_rate(struct clk_hw *hw, unsigned long rate, >> + unsigned long *parent_rate) >> +{ >> + struct clk_fractional_scale *fd = to_clk_sf(hw); >> + u64 ret, scale; >> + >> + if (!rate || rate >= *parent_rate) >> + return *parent_rate; >> + >> + /* freq = parent_rate * scaler / denom */ >> + ret = rate * fd->denom; > > Can this overflow? No, because fd->denom is u64. > But if fd->denom is changed to u32, it needs a cast to u64 here. > >> + scale = ret / *parent_rate; > > As detected by the kbuild test robot, this should use do_div(). Yes, my mistake. I'll fix it. > >> + >> + ret = (u64) *parent_rate * scale; >> + do_div(ret, fd->denom); >> + >> + return ret; >> +} >> + >> +static int clk_fs_set_rate(struct clk_hw *hw, unsigned long rate, >> + unsigned long parent_rate) >> +{ >> + struct clk_fractional_scale *fd = to_clk_sf(hw); >> + unsigned long flags = 0; >> + u64 scale, ret; >> + u32 val; >> + >> + /* >> + * Compute the scaler: >> + * >> + * freq = parent_rate * scaler / denom, or >> + * scaler = freq * denom / parent_rate >> + */ >> + ret = rate * fd->denom; > > Can this overflow? No, because fd->denom is u64. > But if fd->denom is changed to u32, it needs a cast to u64 here. > >> + scale = ret / (u64)parent_rate; > > Don't cast the divider to u64, as this will turn a 64-by-32 division into a > 64-by-64 division. > As detected by the kbuild test robot, this should use do_div(). Will fix it. Thanks Hoan > >> --- a/include/linux/clk-provider.h >> +++ b/include/linux/clk-provider.h > >> +struct clk_fractional_scale { >> + struct clk_hw hw; >> + void __iomem *reg; >> + u8 shift; >> + u32 mask; >> + u64 denom; > > u64 sounds overkill to me, but it looks like that was done to avoid overflow in > the multiplications? > >> + u32 flags; >> + spinlock_t *lock; >> +}; > > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx > > In personal conversations with technical people, I call myself a hacker. But > when I'm talking to journalists I just say "programmer" or something like that. > -- Linus Torvalds -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html