Thread (64 messages) 64 messages, 4 authors, 2016-06-03

[PATCH 07/16] clk: sunxi-ng: Add phase clock support

From: Maxime Ripard <hidden>
Date: 2016-05-23 17:01:29
Also in: linux-clk

Hi,

On Sun, May 22, 2016 at 12:43:48AM +0800, Chen-Yu Tsai wrote:
quoted
+static int ccu_phase_set_phase(struct clk_hw *hw, int degrees)
+{
+       struct ccu_phase *phase = hw_to_ccu_phase(hw);
+       struct clk_hw *parent, *pparent;
+       unsigned int parent_rate, pparent_rate;
grandparent(_rate) would be easier to understand.
Ack.
quoted
+       unsigned long flags;
+       u32 reg;
+       u8 delay;
+
+       /* Get our parent clock, it's the one that can adjust its rate */
+       parent = clk_hw_get_parent(hw);
+       if (!parent)
+               return -EINVAL;
+
+       /* And its rate */
+       parent_rate = clk_hw_get_rate(parent);
+       if (!parent_rate)
+               return -EINVAL;
+
+       /* Now, get our parent's parent (most likely some PLL) */
+       pparent = clk_hw_get_parent(parent);
+       if (!pparent)
+               return -EINVAL;
+
+       /* And its rate */
+       pparent_rate = clk_hw_get_rate(pparent);
+       if (!pparent_rate)
+               return -EINVAL;
+
+       if (degrees != 180) {
+               u16 step, parent_div;
+
+               /* Get our parent divider */
+               parent_div = pparent_rate / parent_rate;
+
+               /*
+                * We can only outphase the clocks by multiple of the
+                * PLL's period.
+                *
+                * Since our parent clock is only a divider, and the
+                * formula to get the outphasing in degrees is deg =
+                * 360 * delta / period
+                *
+                * If we simplify this formula, we can see that the
+                * only thing that we're concerned about is the number
+                * of period we want to outphase our clock from, and
+                * the divider set by our parent clock.
+                */
+               step = DIV_ROUND_CLOSEST(360, parent_div);
+               delay = DIV_ROUND_CLOSEST(degrees, step);
Doesn't this mean some delay values are impossible to set?

For instance, for PLL = 600 MHz and this clock = 50 MHz, div would be 12,
and a step would be 30 degrees. This means we can't ask for a delay of 6,
which is 180 degrees.

For PLL = 600 MHz, clock = 100 MHz, div would be 6, and a step is 60
degrees. Therefor we can't ask for a delay of 3.
You don't ask for a delay, you ask for an outphasing in degrees. In
the hardware, in the register 0 means an outphasing of 180 degrees
(and this has been confirmed by Allwinner a while back). In the two
cases you point out, we would have two ways of achieving the same
thing, we prefer one over another, but I don't see how it's
problematic.

It's also a direct copy of the current code we have, which didn't
raise any objection, or had any known bugs.
quoted
+struct ccu_phase {
+       u8                      shift;
+       u8                      width;
Not sure why you used struct ccu_factor in the divider table clock,
but separate fields directly in ccu_phase here.
Because this is not meant for the same thing. ccu_factor is probably
going to go away anyway because of the dividers consolidation.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160523/2ae847cb/attachment-0001.sig>
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help