Hi Hugo,

Thank you for your review.

On Tue, Nov 11, 2025 11:41 PM, Hugo Villeneuve wrote:
> > +/* Required division ratio for MIPI D-PHY clock depending on number of 
> > lanes and bpp. */
> >+static unsigned int dsi_div_ab_desired;
>
> giving a maximum of 24 * 2 / 1 = 48
>
> So change type to u8?

Done.

I also changed the API function:

-void rzg2l_cpg_dsi_div_set_divider(unsigned int divider, int target);
+void rzg2l_cpg_dsi_div_set_divider(u8 divider, int target);

But, I kept "target" as int because it is an enum.
Any comment on changing that to "u8" as well???


> > +rzg2l_cpg_get_foutpostdiv_rate(struct rzg2l_cpg_priv *priv,
> > +                          struct rzg2l_pll5_param *params,
> >                            unsigned long rate)
> >  {
> >     unsigned long foutpostdiv_rate, foutvco_rate;
> > +   unsigned long hsclk;
> > +   unsigned int a, b, odd;
> > +   unsigned int dsi_div_ab_calc;
> > +
>
> Based on my tests, it seems we can arrive at this point with a 
> non-initialized dsi_div_ab_desired (0). Since valid
> values are from 1 to 128, add a check for this before using it.

I think at first, we need to understand how that is happening and fix that code 
path.
If this function is being called before the dsi_div_ab_desired is set to a 
valid value, then the code might make bad calculations and decisions.


> > +           /* Determine the correct clock source based on even/odd of the 
> > divider */
> > +           odd = dsi_div_ab_desired & 1;
> > +           if (odd) {
> > +                   /* divider is odd */
>
> You can drop this comment, as your "odd" variable is self-explanatory.
>
> > +                   priv->mux_dsi_div_params.clksrc = 0;    /* FOUTPOSTDIV 
> > */
> > +                   dsi_div_ab_calc = dsi_div_ab_desired;
> > +           } else {
> > +                   /* divider is even */
>
> ditto.

Done.


> > +
> > +                   /* FOUTPOSTDIV: DIV_DSI_A must always be 1/1 */
> > +                   if (odd && a != 0)
> > +                           continue;
>
> Use break instead of continue?

Done.
Changed to break;

> > +
> > +                   for (b = 0; b < 16; b++) {
> > +                           /* FOUTPOSTDIV: DIV_DSI_B must always be odd 
> > divider 1/(b+1) */
> > +                           if (odd && b & 1)
> > +                                   continue;
> > +
> > +                           if ((b + 1) << a == dsi_div_ab_calc) {
>
>
> It took me a while to decipher this :)
>
> Use an inline function to compute div_ab to improve readability, and you can 
> reuse this function elsewhere instead of hardcoding the div_ab value (to for 
> example):
>
> static inline u8 rzg2l_cpg_div_ab(u8 a, u8 b) {
>       return (b + 1) << a;
> }
>
> and then:
>
>     ...
>     if (rzg2l_cpg_div_ab(a, b) == dsi_div_ab_calc) {
>     ...
>

OK. I can live with that.

During the reviews, the code kept getting more and more optimized and trimmed 
down, which then became harder to follow.


> > +   if (dsi_div_target == PLL5_TARGET_DPI) {
> > +           /* Fixed settings for DPI */
> > +           priv->mux_dsi_div_params.clksrc = 0;
> > +           priv->mux_dsi_div_params.dsi_div_a = 3; /* Divided by 8 */
> > +           priv->mux_dsi_div_params.dsi_div_b = 0; /* Divided by 1 */
> > +           dsi_div_ab_desired = 8;                 /* (1 << a) * (b + 1) */
> > +   }
>
> Here this block could be combined as an if/else-if:
>
>     if (dsi_div_target == PLL5_TARGET_DPI) {
>         ...
>     } else if (dsi_div_target == PLL5_TARGET_DSI) {
>         ...

Done.


> > +                           if (params->pl5_intin < PLL5_INTIN_MIN ||
> > +                               params->pl5_intin > PLL5_INTIN_MAX)
> > +                                   continue;
>
> Insert line for readability

Done.




> > -   foutpostdiv_rate = DIV_ROUND_CLOSEST_ULL(foutvco_rate,
> > -                                            params->pl5_postdiv1 * 
> > params->pl5_postdiv2);
> > +
> > +   foutpostdiv_rate = DIV_ROUND_CLOSEST(foutvco_rate,
> > +                                        params->pl5_postdiv1 * 
> > params->pl5_postdiv2);
> >  
> >     return foutpostdiv_rate;
>
> You can drop foutpostdiv_rate intermediate variable and return directly, all 
> on one line:
>
>     return DIV_ROUND_CLOSEST(foutvco_rate, params->pl5_postdiv1 * 
> params->pl5_postdiv2);

Done.


> >     vclk_rate = rzg2l_cpg_get_vclk_rate(hw, rate);
> >     sipll5->foutpostdiv_rate =
> > -           rzg2l_cpg_get_foutpostdiv_rate(&params, vclk_rate);
> > +           rzg2l_cpg_get_foutpostdiv_rate(priv, &params, vclk_rate);
>
> Before this patch, rzg2l_cpg_get_foutpostdiv_rate() seemed to always return a 
> valid rate. Therefore, no validation was done of the computed rate.
>
> Now with your patch it may return "0" if the rate is invalid. Therefore you 
> need to check for this here and return a corresponding error code.

I saw for some clock drivers, if they could not get the correct rate, they just 
return '0' as the rate.

But, I do see in some other drivers, they return -EINVAL, so I can do that as 
well.

 
> > -   priv->mux_dsi_div_params.clksrc = 1; /* Use clk src 1 for DSI */
> > -   priv->mux_dsi_div_params.dsi_div_a = 1; /* Divided by 2 */
> > -   priv->mux_dsi_div_params.dsi_div_b = 2; /* Divided by 3 */
> > +   /* Default settings for DPI */
> > +   priv->mux_dsi_div_params.clksrc = 0;
> > +   priv->mux_dsi_div_params.dsi_div_a = 3; /* Divided by 8 */
> > +   priv->mux_dsi_div_params.dsi_div_b = 0; /* Divided by 1 */
> > +   dsi_div_ab_desired = 8;                 /* (1 << a) * (b + 1) */
>
> Use inline function rzg2l_cpg_div_ab() previously suggested.

I plan on getting rid of this code block anyway.
It's not needed.



Cheers

Chris

Reply via email to