> -----Original Message-----
> From: [email protected]
> [mailto:[email protected]] On Behalf
> Of Kevin Hilman
> Sent: Saturday, January 10, 2009 1:42 PM
> To: [email protected]
> Subject: [PATCH/RFT] clock: update PLL/clock handling, with goal of DVFS
> capable clock tree
>
> Here's a first pass at better modeling of clocks and PLLs.  The longer
> term goal being the ability model the clock tree well enough to do
> DVFS on parts that support it.
>
> - generalize PLLs
> - add concept of clock parents
> - drop 'div_by_*' in favor of 'fixed_divider' attribute of clock
> - misc. other minor cleanups
>
> TODO:
> - add PLL2 which can have programmable dividers.
>
> Known problems:
> - doesn't boot on dm646x, and can't see why because DEBUG_LL doesn't work
> either
>
> Basic boot testing on dm6446 and dm355.
> ---
>  arch/arm/mach-davinci/clock.c |  273 +++++++++++++++++++++++++++++-------
> -----
>  arch/arm/mach-davinci/clock.h |   17 +++-
>  2 files changed, 211 insertions(+), 79 deletions(-)
>
> diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
> index 67ab35d..aeee633 100644
> --- a/arch/arm/mach-davinci/clock.c
> +++ b/arch/arm/mach-davinci/clock.c
> @@ -25,22 +25,31 @@
>  #include <mach/cpu.h>
>  #include "clock.h"
>
> -#define DAVINCI_PLL_CNTRL0_BASE 0x01C40800
> +#define DAVINCI_PLL1_BASE 0x01c40800
> +#define DAVINCI_PLL2_BASE 0x01c40c00
> +#define MAX_PLL 2
>
>  /* PLL/Reset register offsets */
> +#define PLLCTL          0x100
> +#define PLLCTL_PLLEN    BIT(0)
> +#define PLLCTL_CLKMODE  BIT(8)
> +
>  #define PLLM         0x110
> +#define PLLM_PLLM_MASK  0x1f
> +
> +#define PREDIV          0x114
> +#define PLLDIV1         0x118
> +#define PLLDIV2         0x11c
> +#define PLLDIV3         0x120
> +#define POSTDIV         0x128
> +#define BPDIV           0x12c
> +#define PLLDIV_EN       BIT(15)
> +#define PLLDIV_RATIO_MASK 0xf
>
>  static LIST_HEAD(clocks);
>  static DEFINE_MUTEX(clocks_mutex);
>  static DEFINE_SPINLOCK(clockfw_lock);

>  [...]


> +static void __init davinci_pll_init(void)
> +{
> +     int i;
> +
> +     if (cpu_is_davinci_dm646x()) {
> +             osc_clk.rate = DM646X_OSC_FREQ;
> +             aux_clk.rate = DM646X_AUX_OSC_FREQ;
> +     } else if (cpu_is_davinci_dm355())
> +             osc_clk.rate = DM355_OSC_FREQ;
> +     else
> +             osc_clk.rate = DM644X_OSC_FREQ;
> +     clk_register(&osc_clk);
> +     clk_register(&aux_clk);
> +
> +     for(i = 0; i < MAX_PLL; i++) {
> +             u32 ctrl, mult, prediv = 1, postdiv = 1;
> +             u8 bypass;
> +             void __iomem *base;
> +             struct clk *pll_clk = pll_list[i];
> +
> +             if (!pll_clk)
> +                     continue;
> +
> +             base = IO_ADDRESS(pll_clk->pll_data->phys_base);
> +             ctrl = __raw_readl(base + PLLCTL);
> +             bypass = !(ctrl & PLLCTL_PLLEN);
> +             pll_clk->rate = pll_clk->parent->rate;
> +
> +             mult = __raw_readl(base + PLLM) & PLLM_PLLM_MASK;
> +             mult += 1;
> +
> +             postdiv = __raw_readl(base + POSTDIV);
> +             if (postdiv & PLLDIV_EN)
> +                     postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1;
> +
> +             if (!cpu_is_davinci_dm644x()) {
> +                     prediv = __raw_readl(base + PREDIV);
> +                     if (prediv & PLLDIV_EN)
> +                             prediv = (prediv & PLLDIV_RATIO_MASK) + 1;
> +             }

The PREDIV and POSTDIV registers are not relevant for DM646x. A read
of these registers results in zero and the clock rate is not set due to divide 
by zero 
error. Additional cpu_is_dmxxx( ) macros to read the PLL registers will solve 
the booting issue on DM646x.

> +
> +             if (!bypass) {
> +                     pll_clk->rate /= prediv;
> +                     pll_clk->rate *= mult;
> +                     pll_clk->rate /= postdiv;
> +             }
> +
> +             printk(KERN_INFO "PLL%d: input = %lu MHz [ ",
> +                    i + 1, pll_clk->parent->rate / 1000000);
> +             if (bypass)
> +                     printk("bypass ");
> +             if (prediv > 1)
> +                     printk("/ %d ", prediv);
> +             if (mult > 1)
> +                     printk("* %d ", mult);
> +             if (postdiv > 1)
> +                     printk("/ %d ", postdiv);
> +             printk("] --> %lu MHz output.\n", pll_clk->rate / 1000000);
> +     }
> +}
> +

-Chaithrika_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to