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
