On Tue, Dec 12, 2023 at 10:22:28AM +0800, Chen Wang wrote: > On 2023/12/9 0:47, Conor Dooley wrote: > > On Fri, Dec 08, 2023 at 09:14:32AM +0800, Chen Wang wrote: > > > +#define ENCODE_PLL_CTRL(fbdiv, p1, p2, refdiv) \ > > > + (((fbdiv & 0xfff) << 16) | ((p2 & 0x7) << 12) | ((p1 & 0x7) << 8) | (refdiv & 0x3f)) > > IMO this should be a function not a macro. > Would like to listen why it should be a function instead of a macro? Any > experiences you can share with me? Readability. A function, which could be inlined allows you to break this up and make it easier to read. > > > +/* > > > + * Based on input rate/prate/fbdiv/refdiv, look up the postdiv1_2 table > > > + * to get the closest postdiiv combination. > > > + * @rate: FOUTPOSTDIV > > > + * @prate: parent rate, i.e. FREF > > > + * @fbdiv: FBDIV > > > + * @refdiv: REFDIV > > > + * @postdiv1: POSTDIV1, output > > > + * @postdiv2: POSTDIV2, output > > > + * See TRM: > > > + * FOUTPOSTDIV = FREF * FBDIV / REFDIV / (POSTDIV1 * POSTDIV2) > > > + * So we get following formula to get POSTDIV1 and POSTDIV2: > > > + * POSTDIV = (prate/REFDIV) x FBDIV/rate > > > + * above POSTDIV = POSTDIV1*POSTDIV2 > > > + */ > > > +static int __sg2042_pll_get_postdiv_1_2( > > > + unsigned long rate, > > > + unsigned long prate, > > > + unsigned int fbdiv, > > > + unsigned int refdiv, > > > + unsigned int *postdiv1, > > > + unsigned int *postdiv2) > > This is not the coding style btw. > Agree, will fix this. > > > +{ > > > + int index = 0; > > > + int ret = 0; > > > + u64 tmp0; > > > + > > > + /* prate/REFDIV and result save to tmp0 */ > > > + tmp0 = prate; > > > + do_div(tmp0, refdiv); > > > + > > > + /* ((prate/REFDIV) x FBDIV) and result save to tmp0 */ > > > + tmp0 *= fbdiv; > > > + > > > + /* ((prate/REFDIV) x FBDIV)/rate and result save to tmp0 */ > > > + do_div(tmp0, rate); > > > + > > > + /* tmp0 is POSTDIV1*POSTDIV2, now we calculate div1 and div2 value */ > > > + if (tmp0 <= 7) { > > > + /* (div1 * div2) <= 7, no need to use array search */ > > > + *postdiv1 = tmp0; > > > + *postdiv2 = 1; > > > + } else { > > > + /* (div1 * div2) > 7, use array search */ > > > + for (index = 0; index < ARRAY_SIZE(postdiv1_2); index++) { > > > + if (tmp0 > postdiv1_2[index][POSTDIV_RESULT_INDEX]) { > > > + continue; > > > + } else { > > > + /* found it */ > > > + break; > > > + } > > > + } > > > + if (index < ARRAY_SIZE(postdiv1_2)) { > > > + *postdiv1 = postdiv1_2[index][1]; > > > + *postdiv2 = postdiv1_2[index][0]; > > > + } else { > > > + pr_debug("%s can not find in postdiv array!\n", __func__); > > > + ret = -EINVAL; > > > + } > > > + } > > > + > > > + return ret; > > > +} > > Reading this function it makes me wonder if (and I am far from the best > > person to comment, someone like Stephen is vastly more qualified) you > > should model this as several "stages", each implemented by the > > "standard" clocks - like clk_divider etc. The code here is quite > > complicated IMO as it seems to be trying to implement several stages of > > division in one go. > > The objective of __sg2042_pll_get_postdiv_1_2() is straightforward: based on > the formula defined by the TRM, with input rate/prate/fbdiv/refdiv, we can > get the possiblle combination of POSTDIV1 and POSTDIV2 by looking up the > table of postdiv1_2. We will later use it to setup the clock register. > > Though the codes looks a bit complicated, but accually it is calculate with > the formula : POSTDIV = (prate/REFDIV) x FBDIV/rate, I just separate it into > several steps to make it easy to understand, I have listed the formula in > the comment on top of the function. I understand what you are doing, I did something similar myself previously. My suggestion/question was about using the "standard" types of clock that the core provides to represent as many of the clocks in this driver as is feasible. > > There's quite a lot in the driver and I will admit that I have not read > > it all my any means (I skimmed from here onwards), but in general my > > advice would be to try and reuse the generic code as much as possible. > Agree, I will double check and try to optimize the code in next revision.
Attachment:
signature.asc
Description: PGP signature