Here's a another 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
- model PLLs, their dividers and the resulting SYSCLKs
- add concept of clock parents
- drop 'div_by_*' in favor of using PLL dividers
- misc. other minor cleanups
- move clock definitions into chip-specific code
- start using clk_get_rate() to get rates (UART, timers)

TODO:
- implement the programmable dividers
- seek-and-destroy hardcoded clock rates

Signed-off-by: Kevin Hilman <[email protected]>
---
 arch/arm/mach-davinci/board-dm355-evm.c     |    3 +-
 arch/arm/mach-davinci/board-dm644x-evm.c    |    2 +-
 arch/arm/mach-davinci/board-dm646x-evm.c    |    5 +-
 arch/arm/mach-davinci/board-sffsdr.c        |    2 +-
 arch/arm/mach-davinci/clock.c               |  370 +++++++--------------------
 arch/arm/mach-davinci/clock.h               |   51 ++++-
 arch/arm/mach-davinci/dm355.c               |  227 ++++++++++++++++
 arch/arm/mach-davinci/dm644x.c              |  195 ++++++++++++++
 arch/arm/mach-davinci/dm646x.c              |  154 +++++++++++
 arch/arm/mach-davinci/include/mach/clock.h  |    2 +-
 arch/arm/mach-davinci/include/mach/common.h |    1 -
 arch/arm/mach-davinci/include/mach/dm355.h  |   18 ++
 arch/arm/mach-davinci/include/mach/dm644x.h |    2 +
 arch/arm/mach-davinci/include/mach/dm646x.h |   18 ++
 arch/arm/mach-davinci/io.c                  |    6 -
 arch/arm/mach-davinci/serial.c              |    6 +-
 arch/arm/mach-davinci/time.c                |   16 +-
 17 files changed, 771 insertions(+), 307 deletions(-)
 create mode 100644 arch/arm/mach-davinci/dm355.c
 create mode 100644 arch/arm/mach-davinci/dm644x.c
 create mode 100644 arch/arm/mach-davinci/dm646x.c
 create mode 100644 arch/arm/mach-davinci/include/mach/dm355.h
 create mode 100644 arch/arm/mach-davinci/include/mach/dm646x.h

diff --git a/arch/arm/mach-davinci/board-dm355-evm.c 
b/arch/arm/mach-davinci/board-dm355-evm.c
index d62d19a..1821d3d 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -28,6 +28,7 @@
 #include <asm/mach/flash.h>
 
 #include <mach/hardware.h>
+#include <mach/dm355.h>
 #include <mach/psc.h>
 #include <mach/common.h>
 #include <mach/board.h>
@@ -177,6 +178,7 @@ static struct davinci_board_config_kernel 
davinci_evm_config[] __initdata = {
 static void __init dm355_evm_map_io(void)
 {
        davinci_map_common_io();
+       dm355_init();
 }
 
 static int dm355evm_mmc_get_cd(int module)
@@ -238,7 +240,6 @@ static __init void dm355_evm_init(void)
 
 static __init void dm355_evm_irq_init(void)
 {
-       davinci_init_common_hw();
        davinci_irq_init();
 }
 
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c 
b/arch/arm/mach-davinci/board-dm644x-evm.c
index 359b754..113ae3b 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -594,6 +594,7 @@ static void __init
 davinci_evm_map_io(void)
 {
        davinci_map_common_io();
+       dm644x_init();
 }
 
 static int davinci_phy_fixup(struct phy_device *phydev)
@@ -640,7 +641,6 @@ static __init void davinci_evm_init(void)
 
 static __init void davinci_evm_irq_init(void)
 {
-       davinci_init_common_hw();
        davinci_irq_init();
 }
 
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c 
b/arch/arm/mach-davinci/board-dm646x-evm.c
index 6b1f323..8b7ef25 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -33,9 +33,10 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
+
+#include <mach/dm646x.h>
 #include <mach/board.h>
 #include <mach/common.h>
-#include <mach/hardware.h>
 #include <mach/psc.h>
 #include <mach/serial.h>
 #include <mach/i2c.h>
@@ -120,6 +121,7 @@ static void __init evm_init_i2c(void)
 static void __init davinci_map_io(void)
 {
        davinci_map_common_io();
+       dm646x_init();
 }
 
 static __init void evm_init(void)
@@ -133,7 +135,6 @@ static __init void evm_init(void)
 
 static __init void davinci_dm646x_evm_irq_init(void)
 {
-       davinci_init_common_hw();
        davinci_irq_init();
 }
 
diff --git a/arch/arm/mach-davinci/board-sffsdr.c 
b/arch/arm/mach-davinci/board-sffsdr.c
index 9dab21d..e6db2e2 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -152,6 +152,7 @@ static struct davinci_board_config_kernel 
davinci_sffsdr_config[] __initdata = {
 static void __init davinci_sffsdr_map_io(void)
 {
        davinci_map_common_io();
+       dm644x_init();
 }
 
 static __init void davinci_sffsdr_init(void)
@@ -187,7 +188,6 @@ __setup("eth=", davinci_cpmac_eth_setup);
 
 static __init void davinci_sffsdr_irq_init(void)
 {
-       davinci_init_common_hw();
        davinci_irq_init();
 }
 
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 67ab35d..68a0fc9 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -25,22 +25,10 @@
 #include <mach/cpu.h>
 #include "clock.h"
 
-#define DAVINCI_PLL_CNTRL0_BASE 0x01C40800
-
-/* PLL/Reset register offsets */
-#define PLLM           0x110
-
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clockfw_lock);
 
-static unsigned int commonrate;
-static unsigned int div_by_four;
-static unsigned int div_by_six;
-static unsigned int div_by_eight;
-static unsigned int armrate;
-static unsigned int fixedrate = 27000000;      /* 27 MHZ */
-
 extern void davinci_psc_config(unsigned int domain, unsigned int id, char 
enable);
 
 /*
@@ -147,6 +135,7 @@ struct clk *clk_get(struct device *dev, const char *id)
 found:
        mutex_unlock(&clocks_mutex);
 
+       WARN_ON(clk == ERR_PTR(-ENOENT));
        return clk;
 }
 EXPORT_SYMBOL(clk_get);
@@ -213,7 +202,7 @@ unsigned long clk_get_rate(struct clk *clk)
        if (clk == NULL || IS_ERR(clk))
                return -EINVAL;
 
-       return *(clk->rate);
+       return clk->rate;
 }
 EXPORT_SYMBOL(clk_get_rate);
 
@@ -222,7 +211,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
        if (clk == NULL || IS_ERR(clk))
                return -EINVAL;
 
-       return *(clk->rate);
+       return clk->rate;
 }
 EXPORT_SYMBOL(clk_round_rate);
 
@@ -245,6 +234,17 @@ int clk_register(struct clk *clk)
        list_add(&clk->node, &clocks);
        mutex_unlock(&clocks_mutex);
 
+       /* If rate passed in, use it */
+       if (clk->rate)
+               return 0;
+
+       /* Otherwise, use parent rate and any divider */
+       BUG_ON(!clk->parent);
+       BUG_ON(!clk->parent->rate);
+       clk->rate = clk->parent->rate;
+       if (clk->fixed_divisor > 1)
+               clk->rate /= clk->fixed_divisor;
+
        return 0;
 }
 EXPORT_SYMBOL(clk_register);
@@ -260,227 +260,6 @@ void clk_unregister(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_unregister);
 
-static struct clk davinci_clks[] = {
-       {
-               .name = "ARMCLK",
-               .rate = &armrate,
-               .lpsc = -1,
-               .flags = ALWAYS_ENABLED,
-       },
-       {
-               .name = "UART0",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_UART0,
-       },
-       {
-               .name = "UART1",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_UART1,
-       },
-       {
-               .name = "UART2",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_UART2,
-       },
-       {
-               .name = "EMACCLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
-       },
-       {
-               .name = "I2CCLK",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_I2C,
-       },
-       {
-               .name = "IDECLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_ATA,
-       },
-       {
-               .name = "McBSPCLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_McBSP,
-       },
-       {
-               .name = "MMCSDCLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_MMC_SD,
-       },
-       {
-               .name = "SPICLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_SPI,
-       },
-       {
-               .name = "gpio",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_GPIO,
-       },
-       {
-               .name = "USBCLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_USB,
-       },
-       {
-               .name = "VLYNQCLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_VLYNQ,
-       },
-       {
-               .name = "AEMIFCLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_AEMIF,
-               .usecount = 1,
-       }
-};
-static struct clk davinci_dm646x_clks[] = {
-       {
-               .name = "ARMCLK",
-               .rate = &armrate,
-               .lpsc = -1,
-               .flags = ALWAYS_ENABLED,
-       },
-       {
-               .name = "UART0",
-               .rate = &fixedrate,
-               .lpsc = DM646X_LPSC_UART0,
-       },
-       {
-               .name = "UART1",
-               .rate = &fixedrate,
-               .lpsc = DM646X_LPSC_UART1,
-       },
-       {
-               .name = "UART2",
-               .rate = &fixedrate,
-               .lpsc = DM646X_LPSC_UART2,
-       },
-       {
-               .name = "I2CCLK",
-               .rate = &div_by_four,
-               .lpsc = DM646X_LPSC_I2C,
-       },
-       {
-               .name = "gpio",
-               .rate = &commonrate,
-               .lpsc = DM646X_LPSC_GPIO,
-       },
-       {
-               .name = "AEMIFCLK",
-               .rate = &div_by_four,
-               .lpsc = DM646X_LPSC_AEMIF,
-               .usecount = 1,
-       },
-       {
-               .name = "EMACCLK",
-               .rate = &div_by_four,
-               .lpsc = DM646X_LPSC_EMAC,
-       },
-};
-static struct clk davinci_dm355_clks[] = {
-       {
-               .name = "ARMCLK",
-               .rate = &armrate,
-               .lpsc = -1,
-               .flags = ALWAYS_ENABLED,
-       },
-       {
-               .name = "UART0",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_UART0,
-               .usecount = 1,
-       },
-       {
-               .name = "UART1",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_UART1,
-               .usecount = 1,
-       },
-       {
-               .name = "UART2",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_UART2,
-               .usecount = 1,
-       },
-       {
-               .name = "I2CCLK",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_I2C,
-       },
-       {
-               .name = "McBSPCLK0",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_McBSP,
-       },
-       {
-               .name = "McBSPCLK1",
-               .rate = &commonrate,
-               .lpsc = DM355_LPSC_McBSP1,
-       },
-       {
-               .name = "MMCSDCLK0",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_MMC_SD,
-       },
-       {
-               .name = "MMCSDCLK1",
-               .rate = &commonrate,
-               .lpsc = DM355_LPSC_MMC_SD1,
-       },
-       {
-               .name = "SPICLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_SPI,
-       },
-       {
-               .name = "SPICLK1",
-               .rate = &commonrate,
-               .lpsc = DM355_LPSC_SPI1,
-       },
-       {
-               .name = "SPICLK2",
-               .rate = &commonrate,
-               .lpsc = DM355_LPSC_SPI2,
-       },
-       {
-               .name = "gpio",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_GPIO,
-       },
-       {
-               .name = "AEMIFCLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_AEMIF,
-               .usecount = 1,
-       },
-       {
-               .name = "PWM0_CLK",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_PWM0,
-       },
-       {
-               .name = "PWM1_CLK",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_PWM1,
-       },
-       {
-               .name = "PWM2_CLK",
-               .rate = &fixedrate,
-               .lpsc = DAVINCI_LPSC_PWM2,
-       },
-       {
-               .name = "PWM3_CLK",
-               .rate = &fixedrate,
-               .lpsc = DM355_LPSC_PWM3,
-       },
-       {
-               .name = "USBCLK",
-               .rate = &commonrate,
-               .lpsc = DAVINCI_LPSC_USB,
-       },
-};
-
 #ifdef CONFIG_DAVINCI_RESET_CLOCKS
 /*
  * Disable any unused clocks left on by the bootloader
@@ -505,51 +284,90 @@ static int __init clk_disable_unused(void)
 late_initcall(clk_disable_unused);
 #endif
 
-int __init davinci_clk_init(void)
+static void __init clk_pll_init(struct clk *clk)
 {
-       struct clk *clkp;
-       static struct clk *board_clks;
-       int count = 0, num_clks;
-       u32 pll_mult;
-
-       pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
-       commonrate = ((pll_mult + 1) * DM646X_OSC_FREQ) / 6;
-       armrate = ((pll_mult + 1) * DM646X_OSC_FREQ) / 2;
-
-       if (cpu_is_davinci_dm646x()) {
-               fixedrate = 24000000;
-               div_by_four = ((pll_mult + 1) * DM646X_OSC_FREQ) / 4;
-               div_by_six = ((pll_mult + 1) * DM646X_OSC_FREQ) / 6;
-               div_by_eight = ((pll_mult + 1) * DM646X_OSC_FREQ) / 8;
-               armrate = ((pll_mult + 1) * DM646X_OSC_FREQ) / 2;
-
-               board_clks = davinci_dm646x_clks;
-               num_clks = ARRAY_SIZE(davinci_dm646x_clks);
-       } else if (cpu_is_davinci_dm355()) {
-               unsigned long postdiv;
-
-               postdiv = (davinci_readl(DAVINCI_PLL_CNTRL0_BASE + 0x128)
-                          & 0x1f) + 1;
-
-               fixedrate = 24000000;
-               armrate = (pll_mult + 1) * (fixedrate / (16 * postdiv));
-               commonrate = armrate / 2;
-               board_clks = davinci_dm355_clks;
-               num_clks = ARRAY_SIZE(davinci_dm355_clks);
-       } else {
-               fixedrate = DM646X_OSC_FREQ;
-               armrate = (pll_mult + 1) * (fixedrate / 2);
-               commonrate = armrate / 3;
-
-               board_clks = davinci_clks;
-               num_clks = ARRAY_SIZE(davinci_clks);
+       u32 i, ctrl, plldiv, mult = 1, prediv = 1, postdiv = 1;
+       u8 bypass;
+       void __iomem *base;
+
+       base = IO_ADDRESS(clk->pll_data->phys_base);
+       ctrl = __raw_readl(base + PLLCTL);
+       clk->rate = clk->parent->rate;
+
+       if (ctrl & PLLCTL_PLLEN) {
+               bypass = 0;
+               mult = __raw_readl(base + PLLM) & PLLM_PLLM_MASK;
+               mult += 1;
+       } else
+               bypass = 1;
+
+       if (clk->pll_data->flags & PLL_HAS_PREDIV) {
+               prediv = __raw_readl(base + PREDIV);
+               if (prediv & PLLDIV_EN)
+                       prediv = (prediv & PLLDIV_RATIO_MASK) + 1;
+       }
+
+       if (clk->pll_data->flags & PLL_HAS_POSTDIV) {
+               postdiv = __raw_readl(base + POSTDIV);
+               if (postdiv & PLLDIV_EN)
+                       postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1;
+       }
+
+       if (!bypass) {
+               clk->rate /= prediv;
+               clk->rate *= mult;
+               clk->rate /= postdiv;
        }
 
-       for (clkp = board_clks; count < num_clks; count++, clkp++) {
+       printk(KERN_INFO "PLL%d: input = %lu MHz [ ",
+              clk->pll_data->num, 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", clk->rate / 1000000);
+
+       for (i = 0; i < MAX_PLL_DIVISORS; i++) {
+               u32 v, div_reg = clk->pll_data->div_regs[i];
+
+               plldiv = 0;
+               if (div_reg) {
+                       v = __raw_readl(base + div_reg);
+                       if (v & PLLDIV_EN)
+                               plldiv = (v & PLLDIV_RATIO_MASK) + 1;
+               }
+
+               if (plldiv)
+                       printk(KERN_INFO
+                              "  SYSCLK%d [ / %d ] = %lu MHz\n",
+                              i + 1, plldiv,
+                              clk->rate / plldiv / 1000000);
+       }
+       plldiv = __raw_readl(base + BPDIV);
+       if (plldiv & PLLDIV_EN) {
+               plldiv = (plldiv & PLLDIV_RATIO_MASK) + 1;
+               printk(KERN_INFO "  SYSCLKBP [ / %d ] = %lu MHz\n",
+                      plldiv, clk->rate / plldiv / 1000000);
+       }
+}
+
+int __init davinci_clk_init(struct clk *clocks[])
+{
+       struct clk *clkp;
+       int i = 0;
+
+       while ((clkp = clocks[i++])) {
                clk_register(clkp);
 
-               /* Turn on clocks that have been enabled in the
-                * table above */
+               if (clkp->pll_data)
+                       clk_pll_init(clkp);
+
+               /* FIXME: is this really needed?  why ? */
+               /* Turn on clocks that have been force enabled */
                if (clkp->usecount)
                        clk_enable(clkp);
        }
@@ -581,7 +399,7 @@ static int davinci_ck_show(struct seq_file *m, void *v)
        struct clk *cp;
 
        list_for_each_entry(cp, &clocks, node)
-               seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
+               seq_printf(m, "%s %lu %d\n", cp->name, cp->rate, cp->usecount);
 
        return 0;
 }
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index b7f111d..44bdee3 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -11,15 +11,58 @@
 #ifndef __ARCH_ARM_DAVINCI_CLOCK_H
 #define __ARCH_ARM_DAVINCI_CLOCK_H
 
+#include <linux/list.h>
+
+#define DAVINCI_PLL1_BASE 0x01c40800
+#define DAVINCI_PLL2_BASE 0x01c40c00
+#define MAX_PLL 2
+
+#define MAX_PLL_DIVISORS 9
+
+/* 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 PLLDIV4         0x160
+#define PLLDIV5         0x164
+#define PLLDIV6         0x168
+#define PLLDIV8         0x170
+#define PLLDIV9         0x174
+#define PLLDIV_EN       BIT(15)
+#define PLLDIV_RATIO_MASK 0x1f
+
+struct pll_data {
+       u32 phys_base;
+       u32 num;
+       u32 flags;
+
+       u32 div_regs[MAX_PLL_DIVISORS];
+};
+#define PLL_HAS_PREDIV          0x01
+#define PLL_HAS_POSTDIV         0x02
+
 struct clk {
        struct list_head        node;
        struct module           *owner;
        const char              *name;
-       unsigned int            *rate;
+       unsigned long           rate;
        int                     id;
        __s8                    usecount;
        __u8                    flags;
        __u8                    lpsc;
+       __u8                    fixed_divisor;
+       struct clk              *parent;
+       struct pll_data         *pll_data;
 };
 
 /* Clock flags */
@@ -30,12 +73,6 @@ struct clk {
 #define ALWAYS_ENABLED         16
 #define ENABLE_REG_32BIT       32
 
-/* various clock frequencies */
-#define DM646X_OSC_FREQ        27000000
-#define DM646X_AUX_OSC_FREQ    24000000
-#define DM646X_CLOCK_TICK_RATE 148500000
-#define DM355_CLOCK_TICK_RATE  24000000
-
 int davinci_clk_associate(struct device *dev, const char *logical_clockname,
                const char *physical_clockname);
 
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
new file mode 100644
index 0000000..9d2559b
--- /dev/null
+++ b/arch/arm/mach-davinci/dm355.c
@@ -0,0 +1,227 @@
+/*
+ * TI DaVinci DM355 chip specific setup
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <mach/dm644x.h>
+#include <mach/clock.h>
+#include <mach/psc.h>
+#include <mach/mux.h>
+
+#include "clock.h"
+
+#define DM355_REF_FREQ         24000000
+
+static struct pll_data pll1_data = {
+       .num       = 1,
+       .phys_base = DAVINCI_PLL1_BASE,
+       .div_regs  = {PLLDIV1, PLLDIV2, PLLDIV3, PLLDIV4},
+};
+
+static struct pll_data pll2_data = {
+       .num       = 2,
+       .phys_base = DAVINCI_PLL2_BASE,
+       .div_regs  = {PLLDIV1},
+};
+
+static struct clk ref_clk = {
+       .name = "ref_clk",
+       .rate = DM355_REF_FREQ,
+       .flags = ALWAYS_ENABLED,
+};
+
+static struct clk pll1_clk = {
+       .name = "pll1",
+       .parent = &ref_clk,
+       .pll_data = &pll1_data,
+};
+
+static struct clk pll2_clk = {
+       .name = "pll2",
+       .parent = &ref_clk,
+       .pll_data = &pll2_data,
+};
+
+static struct clk aux_clk = {
+       .name = "aux_clk",
+       .parent = &ref_clk,
+       .fixed_divisor = 1,
+};
+
+static struct clk sysclk1_clk = {
+       .name = "SYSCLK1",
+       .parent = &pll1_clk,
+       .fixed_divisor = 2,
+};
+
+static struct clk sysclk2_clk = {
+       .name = "SYSCLK2",
+       .parent = &pll1_clk,
+       .fixed_divisor = 4,
+};
+
+static struct clk sysclk5_clk = {
+       .name = "SYSCLK5",
+       .parent = &pll1_clk,
+       .fixed_divisor = 6,
+};
+
+static struct clk arm_clk = {
+       .name = "ARMCLK",
+       .parent = &sysclk1_clk,
+       .lpsc = -1,
+       .flags = ALWAYS_ENABLED,
+};
+
+static struct clk uart0_clk = {
+       .name = "UART0",
+       .parent = &aux_clk,
+       .lpsc = DAVINCI_LPSC_UART0,
+};
+
+static struct clk uart1_clk = {
+       .name = "UART1",
+       .parent = &aux_clk,
+       .lpsc = DAVINCI_LPSC_UART1,
+};
+
+static struct clk uart2_clk = {
+       .name = "UART2",
+       .parent = &sysclk2_clk,
+       .lpsc = DAVINCI_LPSC_UART2,
+};
+
+static struct clk i2c_clk = {
+       .name = "I2CCLK",
+       .parent = &aux_clk,
+       .lpsc = DAVINCI_LPSC_I2C,
+};
+
+static struct clk asp0_clk = {
+       .name = "asp0_clk",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_McBSP,
+};
+
+static struct clk asp1_clk = {
+       .name = "asp1_clk",
+       .parent = &sysclk5_clk,
+       .lpsc = DM355_LPSC_McBSP1,
+};
+
+static struct clk mmcsd0_clk = {
+       .name = "MMCSDCLK0",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_MMC_SD,
+};
+
+static struct clk mmcsd1_clk = {
+       .name = "MMCSDCLK1",
+       .parent = &sysclk5_clk,
+       .lpsc = DM355_LPSC_MMC_SD1,
+};
+
+static struct clk spi0_clk = {
+       .name = "SPICLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_SPI,
+};
+
+static struct clk spi1_clk = {
+       .name = "SPICLK1",
+       .parent = &sysclk5_clk,
+       .lpsc = DM355_LPSC_SPI1,
+};
+
+static struct clk spi2_clk = {
+       .name = "SPICLK2",
+       .parent = &sysclk5_clk,
+       .lpsc = DM355_LPSC_SPI2,
+};
+static struct clk gpio_clk = {
+       .name = "gpio",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_GPIO,
+};
+
+static struct clk aemif_clk = {
+       .name = "AEMIFCLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_AEMIF,
+       .usecount = 1,
+};
+
+static struct clk pwm0_clk = {
+       .name = "PWM0_CLK",
+       .parent = &ref_clk,
+       .lpsc = DAVINCI_LPSC_PWM0,
+};
+
+static struct clk pwm1_clk = {
+       .name = "PWM1_CLK",
+       .parent = &ref_clk,
+       .lpsc = DAVINCI_LPSC_PWM1,
+};
+
+static struct clk pwm2_clk = {
+       .name = "PWM2_CLK",
+       .parent = &ref_clk,
+       .lpsc = DAVINCI_LPSC_PWM2,
+};
+
+static struct clk pwm3_clk = {
+       .name = "PWM3_CLK",
+       .parent = &ref_clk,
+       .lpsc = DM355_LPSC_PWM3,
+};
+
+static struct clk usb_clk = {
+       .name = "USBCLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_USB,
+};
+
+static struct clk *dm355_clks[] __initdata = {
+       &ref_clk,
+       &pll1_clk,
+       &pll2_clk,
+       &aux_clk,
+       &sysclk1_clk,
+       &sysclk2_clk,
+       &sysclk5_clk,
+       &arm_clk,
+       &uart0_clk,
+       &uart1_clk,
+       &uart2_clk,
+       &i2c_clk,
+       &asp0_clk,
+       &asp1_clk,
+       &mmcsd0_clk,
+       &mmcsd1_clk,
+       &spi0_clk,
+       &spi1_clk,
+       &spi2_clk,
+       &gpio_clk,
+       &aemif_clk,
+       &pwm0_clk,
+       &pwm1_clk,
+       &pwm2_clk,
+       &pwm3_clk,
+       &usb_clk,
+       NULL,
+};
+
+void __init dm355_init(void)
+{
+       davinci_clk_init(dm355_clks);
+       davinci_mux_init();
+}
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
new file mode 100644
index 0000000..54947bb
--- /dev/null
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -0,0 +1,195 @@
+/*
+ * TI DaVinci DM644x chip specific setup
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <mach/dm644x.h>
+#include <mach/clock.h>
+#include <mach/psc.h>
+#include <mach/mux.h>
+
+#include "clock.h"
+
+#define DM644X_REF_FREQ        27000000
+
+static struct pll_data pll1_data = {
+       .num       = 1,
+       .phys_base = DAVINCI_PLL1_BASE,
+       .div_regs  = {PLLDIV1, PLLDIV2, PLLDIV3, PLLDIV4, PLLDIV5},
+};
+
+static struct pll_data pll2_data = {
+       .num       = 2,
+       .phys_base = DAVINCI_PLL2_BASE,
+       .div_regs  = {PLLDIV1, PLLDIV2},
+};
+
+static struct clk ref_clk = {
+       .name = "ref_clk",
+       .rate = DM644X_REF_FREQ,
+       .flags = ALWAYS_ENABLED,
+};
+
+static struct clk pll1_clk = {
+       .name = "pll1",
+       .parent = &ref_clk,
+       .pll_data = &pll1_data,
+};
+
+static struct clk pll2_clk = {
+       .name = "pll2",
+       .parent = &ref_clk,
+       .pll_data = &pll2_data,
+};
+
+static struct clk sysclk1_clk = {
+       .name = "SYSCLK1",
+       .parent = &pll1_clk,
+       .fixed_divisor = 1,
+};
+
+static struct clk sysclk2_clk = {
+       .name = "SYSCLK2",
+       .parent = &pll1_clk,
+       .fixed_divisor = 2,
+};
+
+static struct clk sysclk3_clk = {
+       .name = "SYSCLK3",
+       .parent = &pll1_clk,
+       .fixed_divisor = 3,
+};
+
+static struct clk sysclk5_clk = {
+       .name = "SYSCLK5",
+       .parent = &pll1_clk,
+       .fixed_divisor = 6,
+};
+
+static struct clk arm_clk = {
+       .name = "ARMCLK",
+       .parent = &sysclk2_clk,
+       .lpsc = -1,
+       .flags = ALWAYS_ENABLED,
+};
+
+static struct clk uart0_clk = {
+       .name = "UART0",
+       .parent = &ref_clk,
+       .lpsc = DAVINCI_LPSC_UART0,
+};
+
+static struct clk uart1_clk = {
+       .name = "UART1",
+       .parent = &ref_clk,
+       .lpsc = DAVINCI_LPSC_UART1,
+};
+
+static struct clk uart2_clk = {
+       .name = "UART2",
+       .parent = &ref_clk,
+       .lpsc = DAVINCI_LPSC_UART2,
+};
+
+static struct clk emac_clk = {
+       .name = "EMACCLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
+};
+
+static struct clk i2c_clk = {
+       .name = "I2CCLK",
+       .parent = &ref_clk,
+       .fixed_divisor = 1,
+       .lpsc = DAVINCI_LPSC_I2C,
+};
+
+static struct clk ide_clk = {
+       .name = "IDECLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_ATA,
+};
+
+static struct clk asp_clk = {
+       .name = "ASPCLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_McBSP,
+};
+
+static struct clk mmcsd_clk = {
+       .name = "MMCSDCLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_MMC_SD,
+};
+
+static struct clk spi_clk = {
+       .name = "SPICLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_SPI,
+};
+
+static struct clk gpio_clk = {
+       .name = "gpio",
+       .parent = &sysclk5_clk,
+       .fixed_divisor = 6,
+       .lpsc = DAVINCI_LPSC_GPIO,
+};
+
+static struct clk usb_clk = {
+       .name = "USBCLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_USB,
+};
+
+static struct clk vlynq_clk = {
+       .name = "VLYNQCLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_VLYNQ,
+};
+
+static struct clk aemif_clk = {
+       .name = "AEMIFCLK",
+       .parent = &sysclk5_clk,
+       .lpsc = DAVINCI_LPSC_AEMIF,
+       .usecount = 1,
+};
+
+static struct clk *dm644x_clks[] __initdata = {
+       &ref_clk,
+       &pll1_clk,
+       &pll2_clk,
+       &sysclk1_clk,
+       &sysclk2_clk,
+       &sysclk3_clk,
+       &sysclk5_clk,
+       &arm_clk,
+       &uart0_clk,
+       &uart1_clk,
+       &uart2_clk,
+       &emac_clk,
+       &i2c_clk,
+       &ide_clk,
+       &asp_clk,
+       &mmcsd_clk,
+       &spi_clk,
+       &gpio_clk,
+       &usb_clk,
+       &vlynq_clk,
+       &aemif_clk,
+       NULL,
+};
+
+void __init dm644x_init(void)
+{
+       davinci_clk_init(dm644x_clks);
+       davinci_mux_init();
+}
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
new file mode 100644
index 0000000..36c2cce
--- /dev/null
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -0,0 +1,154 @@
+/*
+ * TI DaVinci DM644x chip specific setup
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <mach/dm644x.h>
+#include <mach/clock.h>
+#include <mach/psc.h>
+#include <mach/mux.h>
+
+#include "clock.h"
+
+/* various clock frequencies */
+#define DM646X_REF_FREQ                27000000
+#define DM646X_AUX_FREQ                24000000
+/* #define DM646X_CLOCK_TICK_RATE      148500000 */
+
+static struct pll_data pll1_data = {
+       .num       = 1,
+       .phys_base = DAVINCI_PLL1_BASE,
+       .div_regs  = {PLLDIV1, PLLDIV2, PLLDIV3, PLLDIV4, PLLDIV5,
+                     PLLDIV6, 0,       PLLDIV8, PLLDIV9},
+};
+
+static struct pll_data pll2_data = {
+       .num       = 2,
+       .phys_base = DAVINCI_PLL2_BASE,
+       .div_regs  = {PLLDIV1},
+};
+
+static struct clk ref_clk = {
+       .name = "ref_clk",
+       .rate = DM646X_REF_FREQ,
+       .flags = ALWAYS_ENABLED,
+};
+
+static struct clk aux_clk = {
+       .name = "aux_clk",
+       .rate = DM646X_AUX_FREQ,
+       .flags = ALWAYS_ENABLED,
+};
+
+static struct clk pll1_clk = {
+       .name = "pll1",
+       .parent = &ref_clk,
+       .pll_data = &pll1_data,
+};
+
+static struct clk pll2_clk = {
+       .name = "pll2",
+       .parent = &ref_clk,
+       .pll_data = &pll2_data,
+};
+
+static struct clk sysclk1_clk = {
+       .name = "SYSCLK1",
+       .parent = &pll1_clk,
+       .fixed_divisor = 1,
+};
+
+static struct clk sysclk2_clk = {
+       .name = "SYSCLK2",
+       .parent = &pll1_clk,
+       .fixed_divisor = 2,
+};
+
+static struct clk sysclk3_clk = {
+       .name = "SYSCLK3",
+       .parent = &pll1_clk,
+       .fixed_divisor = 4,
+};
+
+static struct clk arm_clk = {
+       .name = "ARMCLK",
+       .parent = &sysclk2_clk,
+       .lpsc = -1,
+       .flags = ALWAYS_ENABLED,
+};
+
+static struct clk uart0_clk = {
+       .name = "UART0",
+       .parent = &aux_clk,
+       .lpsc = DM646X_LPSC_UART0,
+};
+
+static struct clk uart1_clk = {
+       .name = "UART1",
+       .parent = &aux_clk,
+       .lpsc = DM646X_LPSC_UART1,
+};
+
+static struct clk uart2_clk = {
+       .name = "UART2",
+       .parent = &aux_clk,
+       .lpsc = DM646X_LPSC_UART2,
+};
+
+static struct clk i2c_clk = {
+       .name = "I2CCLK",
+       .parent = &sysclk3_clk,
+       .lpsc = DM646X_LPSC_I2C,
+};
+
+static struct clk gpio_clk = {
+       .name = "gpio",
+       .parent = &sysclk3_clk,
+       .lpsc = DM646X_LPSC_GPIO,
+};
+
+static struct clk aemif_clk = {
+       .name = "AEMIFCLK",
+       .parent = &sysclk3_clk,
+       .lpsc = DM646X_LPSC_AEMIF,
+       .usecount = 1,
+};
+
+static struct clk emac_clk = {
+       .name = "EMACCLK",
+       .parent = &sysclk3_clk,
+       .lpsc = DM646X_LPSC_EMAC,
+};
+
+static struct clk *dm646x_clks[] __initdata = {
+       &ref_clk,
+       &pll1_clk,
+       &pll2_clk,
+       &sysclk1_clk,
+       &sysclk2_clk,
+       &sysclk3_clk,
+       &arm_clk,
+       &uart0_clk,
+       &uart1_clk,
+       &uart2_clk,
+       &i2c_clk,
+       &gpio_clk,
+       &aemif_clk,
+       &emac_clk,
+       NULL,
+};
+
+void __init dm646x_init(void)
+{
+       davinci_clk_init(dm646x_clks);
+       davinci_mux_init();
+}
diff --git a/arch/arm/mach-davinci/include/mach/clock.h 
b/arch/arm/mach-davinci/include/mach/clock.h
index 38bdd49..78cfb35 100644
--- a/arch/arm/mach-davinci/include/mach/clock.h
+++ b/arch/arm/mach-davinci/include/mach/clock.h
@@ -17,6 +17,6 @@ struct clk;
 
 extern int clk_register(struct clk *clk);
 extern void clk_unregister(struct clk *clk);
-extern int davinci_clk_init(void);
+extern int davinci_clk_init(struct clk *clocks[]);
 
 #endif
diff --git a/arch/arm/mach-davinci/include/mach/common.h 
b/arch/arm/mach-davinci/include/mach/common.h
index ef55274..1917709 100644
--- a/arch/arm/mach-davinci/include/mach/common.h
+++ b/arch/arm/mach-davinci/include/mach/common.h
@@ -17,7 +17,6 @@ struct sys_timer;
 extern struct sys_timer davinci_timer;
 
 extern void davinci_irq_init(void);
-extern void davinci_init_common_hw(void);
 extern void davinci_map_common_io(void);
 
 /* parameters describe VBUS sourcing for host mode */
diff --git a/arch/arm/mach-davinci/include/mach/dm355.h 
b/arch/arm/mach-davinci/include/mach/dm355.h
new file mode 100644
index 0000000..dbdfaa4
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/dm355.h
@@ -0,0 +1,18 @@
+/*
+ * Chip specific defines for DM355 SoC
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_DM355_H
+#define __ASM_ARCH_DM355_H
+
+#include <mach/hardware.h>
+
+void __init dm355_init(void);
+
+#endif /* __ASM_ARCH_DM355_H */
diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h 
b/arch/arm/mach-davinci/include/mach/dm644x.h
index 7d016a4..5b3d512 100644
--- a/arch/arm/mach-davinci/include/mach/dm644x.h
+++ b/arch/arm/mach-davinci/include/mach/dm644x.h
@@ -24,4 +24,6 @@
 
 #include <mach/hardware.h>
 
+void __init dm644x_init(void);
+
 #endif /* __ASM_ARCH_DM644X_H */
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h 
b/arch/arm/mach-davinci/include/mach/dm646x.h
new file mode 100644
index 0000000..d917939
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/dm646x.h
@@ -0,0 +1,18 @@
+/*
+ * Chip specific defines for DM646x SoC
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_DM646X_H
+#define __ASM_ARCH_DM646X_H
+
+#include <mach/hardware.h>
+
+void __init dm646x_init(void);
+
+#endif /* __ASM_ARCH_DM646X_H */
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c
index c493889..fdd51ea 100644
--- a/arch/arm/mach-davinci/io.c
+++ b/arch/arm/mach-davinci/io.c
@@ -51,9 +51,3 @@ void __init davinci_map_common_io(void)
         */
        davinci_check_revision();
 }
-
-void __init davinci_init_common_hw(void)
-{
-       davinci_mux_init();
-       davinci_clk_init();
-}
diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c
index b6020c0..ff759c4 100644
--- a/arch/arm/mach-davinci/serial.c
+++ b/arch/arm/mach-davinci/serial.c
@@ -58,7 +58,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
-               .uartclk        = 27000000,
        },
        {
                .membase        = (char *)IO_ADDRESS(DAVINCI_UART1_BASE),
@@ -67,7 +66,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
-               .uartclk        = 27000000,
        },
        {
                .membase        = (char *)IO_ADDRESS(DAVINCI_UART2_BASE),
@@ -76,7 +74,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
                .iotype         = UPIO_MEM,
                .regshift       = 2,
-               .uartclk        = 27000000,
        },
        {
                .flags          = 0
@@ -133,12 +130,10 @@ void __init davinci_serial_init(void)
                struct plat_serial8250_port *p = serial_platform_data + i;
 
                if (cpu_is_davinci_dm646x()) {
-                       p->uartclk = DM646X_AUX_OSC_FREQ;
                        p->iotype = UPIO_MEM32;
                }
 
                if (cpu_is_davinci_dm355()) {
-                       p->uartclk = 24000000;
                        if (i == 2) {
                                p->membase = (char *)
                                        IO_ADDRESS(DM355_UART2_BASE);
@@ -155,6 +150,7 @@ void __init davinci_serial_init(void)
 
                sprintf(name, "UART%d", i);
                uart_clk = clk_get(dev, name);
+               p->uartclk = clk_get_rate(uart_clk);
                if (IS_ERR(uart_clk))
                        printk(KERN_ERR "%s:%d: failed to get UART%d clock\n",
                                        __func__, __LINE__, i);
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 62d95ad..b298d9b 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -16,6 +16,7 @@
 #include <linux/clockchips.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 #include <mach/hardware.h>
 #include <asm/system.h>
@@ -304,18 +305,21 @@ static struct clock_event_device clockevent_davinci = {
 
 static void __init davinci_timer_init(void)
 {
+       struct clk *timer_clk;
+
        static char err[] __initdata = KERN_ERR
                "%s: can't register clocksource!\n";
 
        /* init timer hw */
        timer_init();
 
-       if (cpu_is_davinci_dm644x())
-               davinci_clock_tick_rate = DM646X_OSC_FREQ;
-       else if (cpu_is_davinci_dm646x())
-               davinci_clock_tick_rate = DM646X_CLOCK_TICK_RATE;
-       else if (cpu_is_davinci_dm355())
-               davinci_clock_tick_rate = DM355_CLOCK_TICK_RATE;
+       if (cpu_is_davinci_dm646x())
+               timer_clk = clk_get(NULL, "SYSCLK3");
+       else
+               timer_clk = clk_get(NULL, "ref_clk");
+
+       davinci_clock_tick_rate = clk_get_rate(timer_clk);
+       clk_put(timer_clk);
 
        /* setup clocksource */
        clocksource_davinci.mult =
-- 
1.6.1


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

Reply via email to