> -----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