• Emil Lundmark's avatar
    clk: imx: improve precision of AV PLL to 1 Hz · c5a8045a
    Emil Lundmark authored
    The audio and video PLLs are designed to have a precision of 1 Hz if some
    conditions are met. The current implementation only allows a precision that
    depends on the rate of the parent clock. E.g., if the parent clock is 24
    MHz, the precision will be 24 Hz; or more generally the precision will be
    
        p / 10^6 Hz
    
    where p is the parent clock rate. This comes down to how the register
    values for the PLL's fractional loop divider are chosen.
    
    The clock rate calculation for the PLL is
    
        PLL output frequency = Fref * (DIV_SELECT + NUM / DENOM)
    
    or with a shorter notation
    
        r = p * (d + a / b)
    
    In addition to all variables being integers, we also have the following
    conditions:
    
        27 <= d <= 54
    
        -2^29 <= a <= 2^29-1
         0    <  b <= 2^30-1
        |a| < b
    
    Here, d, a and b are register values for the fractional loop divider. We
    want to chose d, a and b such that f(p, r) = p, i.e. f is our round_rate
    function. Currently, d and b are chosen as
    
        d = r / p
        b = 10^6
    
    hence we get the poor precision. And a is defined in terms of r, d, p and
    b:
    
        a = (r - d * p) * b / p
    
    I propose that if p <= 2^30-1 (i.e., the max value for b), we chose b as
    
        b = p
    
    We can do this since
    
        |a| < b
    
        |(r - d * p) * b / p| < b
    
        |r - d * p| < p
    
    Which have two solutions, one of them is when p < 0, so we can skip that
    one. The other is when p > 0 and
    
        p * (d - 1) < r < p * (d + 1)
    
    Substitute d = r / p:
    
        (r - p) < r < (r + p)  <=>  p > 0
    
    So, as long as p > 0, we can chose b = p. This is a good choise for b since
    
        a = (r - d * p) * b / p
          = (r - d * p) * p / p
          = r - d * p
    
        r = p * (d + a / b)
          = p * d + p * a / b
          = p * d + p * a / p
          = p * d + a
    
    and if d = r / p:
    
        a = r - d * p
          = r - r / p * p
          = 0
    
        r = p * d + a
          = p * d + 0
          = p * r / p
          = r
    
    I reckon this is the intention by the design of the clock rate formula.
    Signed-off-by: default avatarEmil Lundmark <emil@limesaudio.com>
    Reviewed-by: default avatarFabio Estevam <fabio.estevam@nxp.com>
    Acked-by: default avatarShawn Guo <shawnguo@kernel.org>
    Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
    c5a8045a
clk-pllv3.c 8.78 KB