[linux-sunxi] [PATCH 1/3] clk: sunxi: Add a driver for the CCU
Jean-Francois Moine
moinejf at free.fr
Wed Jun 29 09:55:28 PDT 2016
On Wed, 29 Jun 2016 17:30:51 +0200
Ondřej Jirman <megi at xff.cz> wrote:
> >>> + reg = readl(ccu->base + ccu->reg);
> >>> + m_val = reg & m_mask;
> >>> + p_val = reg & p_mask;
> >>> +
> >>> + spin_lock(&ccu_lock);
> >>> +
> >>> + /* increase p, then m */
> >>> + if (ccu->p_width && p_val < (val & p_mask)) {
> >>> + reg &= ~p_mask;
> >>> + reg |= val & p_mask;
> >>> + writel(reg, ccu->base + ccu->reg);
> >>> + udelay(10);
> >>> + }
> >>> + if (ccu->m_width && m_val < (val & m_mask)) {
> >>> + reg &= ~m_mask;
> >>> + reg |= val & m_mask;
> >>> + writel(reg, ccu->base + ccu->reg);
> >>> + udelay(10);
> >>> + }
> >>> +
> >>> + /* set other factors */
> >>> + reg &= ~(mask & ~(p_mask | m_mask));
> >>> + reg |= val & ~(p_mask | m_mask);
> >>> + writel(reg, ccu->base + ccu->reg);
> >>> +
> >>> + /* decrease m */
> >>> + if (ccu->m_width && m_val > (val & m_mask)) {
> >>> + reg &= ~m_mask;
> >>> + reg |= val & m_mask;
> >>> + writel(reg, ccu->base + ccu->reg);
> >>> + udelay(10);
> >>> + }
> >>> +
> >>> + /* wait for PLL stable */
> >>> + if (ccu->lock_reg) {
> >>> + u32 lock;
> >>> +
> >>> + lock = BIT(ccu->lock_bit);
> >>> + WARN_ON(readl_relaxed_poll_timeout(ccu->base + ccu->lock_reg,
> >>> + reg, !(reg & lock),
> >>> + 100, 70000));
> >>> + }
> > [snip]
> >>
> >> Any reason why you're waiting for the lock after decreasing m and not
> >> before? PLL output may till run too fast before reducing the postdivider
> >> potentially causing a crash. But I might be misunderstanding what m is
> >> exactly.
> >
> > I just followed what is done in the function
> > sunxi_clk_factors_set_flat_facotrs() from Allwinnertech:
> >
> > 1).try to increase factor p first
> > 2).try to increase factor m first
> > 3. write factor n & k
> > 4. do pair things for 2). decease factor m
> > 5. wait for PLL state stable
> > 6.do pair things for 1). decease factor p
> >
> > As this is written, it seems m is a pre-divider.
> >
>
> Interesting. :) I've reverse engineered their arisc code, and there the
> order for setting up/changing PLL1 is:
>
> 1. try to increase factor p first
> 2. try to increase factor m first
> 3. write factor n & k
> 4. wait for PLL state stable
> 5. do pair things for 2). decease factor m
> 6. do pair things for 1). decease factor p
>
> That's why I asked.
>
> So all this depends on the design of this clock source. It may be
> different for different PLLs.
>From the SDK of the sun8i/9i families, this way to change the PLL
clocks is needed only for the PLL CPU of the SoCs sun8i7w (H3) and
sun8iw8 (other name unknown).
> Hard to know what to believe. Perhaps it would be possible to create a
> PLL stress tester that would try both approaches and see whether one of
> them is more stable/leads to creashes?
Not easy to do...
--
Ken ar c'hentañ | ** Breizh ha Linux atav! **
Jef | http://moinejf.free.fr/
More information about the linux-arm-kernel
mailing list