[PATCH 8/8] clk/qcom: fix rcg divider value

Sumit Garg sumit.garg at linaro.org
Fri Oct 27 14:18:13 CEST 2023


On Wed, 25 Oct 2023 at 19:14, Caleb Connolly <caleb.connolly at linaro.org> wrote:
>
>
>
> On 24/10/2023 21:23, Caleb Connolly wrote:
> > The RCG divider field takes a value of (2*h - 1) where h is the divisor.
> > This allows fractional dividers to be supported by calculating them at
> > compile time using a macro.
> >
> > However, the clk_rcg_set_rate_mnd() function was also performing the
> > calculation. Clean this all up and consistently use the F() macro to
> > calculate these at compile time and properly support fractional divisors.
> >
> > Additionally, improve clk_bcr_update() to timeout with a warning rather
> > than hanging the board, and make the freq_tbl struct and helpers common
> > so that they can be reused by future platforms.
> >
> > Signed-off-by: Caleb Connolly <caleb.connolly at linaro.org>
>
> [...]
> >
> >  #define CFG_MODE_DUAL_EDGE (0x2 << 12) /* Counter mode */
> >
> > -#define CFG_MASK 0x3FFF
> > +// Disable the HW_CLK_CONTROL bit
> > +#define CFG_MASK (0x3FFF | (1 << 20))
>
> There seems to be a bug in this patch that causes the actual clock rate
> to be wrong in some cases, most obvious with db845c UART. I had
> initially thought it to be a board issue but upon further investigation
> I think I'm wrong.
>
> The UART clock frequency table in clock-sdm845.c is taken from Linux,
> the 115200 baud rate corresponds to the lowest frequency (7372800Hz).
> However, with the implementation changes here, the RCG configuration
> actually results in a measured clock rate of 9085208Hz.
>
> If the entry is changed as follows
> -       F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625)
> +       F(7372800, CFG_CLK_SRC_GPLL0, 0.5, 192, 15625)
>

I would suggest we keep the frequency table aligned to the Linux tree.
We should try to fix the mismatch in the computation to support
fractional divisors.

-Sumit

> Then the resultant clock rate is 7372604Hz (within the tolerance)...
>
> I will resolve this for v2.
> >
> >  #define CFG_DIVIDER_MASK 0x1F
> >
> > -/* root set rate for clocks with half integer and MND divider */
> > +/*
> > + * root set rate for clocks with half integer and MND divider
> > + * div should be pre-calculated ((div * 2) - 1)
> > + */
> >  void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
> >                         int div, int m, int n, int source, u8 mnd_width)
> >  {
> > @@ -99,17 +125,15 @@ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
> >       /* Program MND values */
> >       setbits_le32(base + regs->M, m_val & mask);
> >       setbits_le32(base + regs->N, n_val & mask);
> > -     setbits_le32(base + regs->D, d_val & mask);
> > +     setbits_le32(base + regs->D, (d_val & mask) == mask ? 0 : (d_val & mask));
> >
> >       /* setup src select and divider */
> >       cfg  = readl(base + regs->cfg_rcgr);
> >       cfg &= ~CFG_MASK;
> >       cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */
> >
> > -     /* Set the divider; HW permits fraction dividers (+0.5), but
> > -        for simplicity, we will support integers only */
> >       if (div)
> > -             cfg |= (2 * div - 1) & CFG_DIVIDER_MASK;
> > +             cfg |= div & CFG_DIVIDER_MASK;
> >
> >       if (n_val)
> >               cfg |= CFG_MODE_DUAL_EDGE;
>
> --
> // Caleb (they/them)


More information about the U-Boot mailing list