Commit 1322188f authored by Kevin Hilman's avatar Kevin Hilman

clock: rework PLL/clock handling, with goal of DVFS capable clock tree

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 devices that support it.

  - generalize PLL control and clock distribution
  - model PLLs, their dividers and the resulting PLL-derived clocks
  - add clock parent/child relationships
  - 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)
  - drop DM*_CLOCK_TICK_RATE

Updates from last version

  - multiple updates and fixes from David Brownell (Thanks!)
  - use of divider registers instead of 'fixed_divisor' field
    to better model PLL-derived clocks based on divider regs.
  - drop some hard-coded LPSC init in favor of enabling with
    relevant clock.

TODO:
- seek-and-destroy hardcoded clock rates
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 5d0acbd9
......@@ -9,6 +9,11 @@ obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \
obj-$(CONFIG_DAVINCI_MUX) += mux.o mux_cfg.o
# Chip specific
obj-$(CONFIG_ARCH_DAVINCI_DM644x) += dm644x.o
obj-$(CONFIG_ARCH_DAVINCI_DM646x) += dm646x.o
obj-$(CONFIG_ARCH_DAVINCI_DM355) += dm355.o
# Board specific
obj-$(CONFIG_MACH_DAVINCI_EVM) += board-dm644x-evm.o
obj-$(CONFIG_MACH_DAVINCI_DM646X_EVM) += board-dm646x-evm.o
......
......@@ -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/emac.h>
......@@ -173,6 +174,7 @@ static struct davinci_uart_config uart_config __initdata = {
static void __init dm355_evm_map_io(void)
{
davinci_map_common_io();
dm355_init();
}
static int dm355evm_mmc_get_cd(int module)
......@@ -210,8 +212,6 @@ static struct davinci_mmc_config dm355evm_mmc_config = {
static __init void dm355_evm_init(void)
{
davinci_psc_init();
gpio_request(1, "dm9000");
gpio_direction_input(1);
dm355evm_dm9000_rsrc[2].start = gpio_to_irq(1);
......@@ -232,7 +232,6 @@ static __init void dm355_evm_init(void)
static __init void dm355_evm_irq_init(void)
{
davinci_init_common_hw();
davinci_irq_init();
}
......
......@@ -590,6 +590,7 @@ static void __init
davinci_evm_map_io(void)
{
davinci_map_common_io();
dm644x_init();
}
static int davinci_phy_fixup(struct phy_device *phydev)
......@@ -607,8 +608,6 @@ static int davinci_phy_fixup(struct phy_device *phydev)
static __init void davinci_evm_init(void)
{
davinci_psc_init();
#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
#if defined(CONFIG_MTD_PHYSMAP) || \
......@@ -634,7 +633,6 @@ static __init void davinci_evm_init(void)
static __init void davinci_evm_irq_init(void)
{
davinci_init_common_hw();
davinci_irq_init();
}
......
......@@ -33,8 +33,8 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
#include <mach/dm646x.h>
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/psc.h>
#include <mach/serial.h>
#include <mach/i2c.h>
......@@ -116,18 +116,17 @@ 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)
{
davinci_psc_init();
evm_init_i2c();
davinci_serial_init(&uart_config);
}
static __init void davinci_dm646x_evm_irq_init(void)
{
davinci_init_common_hw();
davinci_irq_init();
}
......
......@@ -147,6 +147,7 @@ static struct davinci_uart_config uart_config __initdata = {
static void __init davinci_sffsdr_map_io(void)
{
davinci_map_common_io();
dm644x_init();
}
static __init void davinci_sffsdr_init(void)
......@@ -180,7 +181,6 @@ __setup("eth=", davinci_cpmac_eth_setup);
static __init void davinci_sffsdr_irq_init(void)
{
davinci_init_common_hw();
davinci_irq_init();
}
......
/*
* TI DaVinci clock config file
* Clock and PLL control for DaVinci devices
*
* Copyright (C) 2006 Texas Instruments.
* Copyright (C) 2006-2007 Texas Instruments.
* Copyright (C) 2008-2009 Deep Root Systems, LLC
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -25,22 +26,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);
/*
......@@ -107,13 +96,10 @@ done:
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
int idno;
struct clk_mapping *mapping;
if (dev == NULL || dev->bus != &platform_bus_type)
idno = -1;
else
idno = to_platform_device(dev)->id;
if (!id)
return ERR_PTR(-EINVAL);
mutex_lock(&clocks_mutex);
......@@ -129,14 +115,6 @@ struct clk *clk_get(struct device *dev, const char *id)
}
}
list_for_each_entry(p, &clocks, node) {
if (p->id == idno &&
strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
goto found;
}
}
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
......@@ -147,6 +125,8 @@ struct clk *clk_get(struct device *dev, const char *id)
found:
mutex_unlock(&clocks_mutex);
WARN(IS_ERR(clk), "CLK: can't find %s/%s\n",
dev ? dev_name(dev) : "nodev", id);
return clk;
}
EXPORT_SYMBOL(clk_get);
......@@ -158,38 +138,36 @@ void clk_put(struct clk *clk)
}
EXPORT_SYMBOL(clk_put);
static int __clk_enable(struct clk *clk)
static void __clk_enable(struct clk *clk)
{
if (clk->flags & ALWAYS_ENABLED)
return 0;
davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
return 0;
if (clk->parent)
__clk_enable(clk->parent);
if (clk->usecount++ == 0 && !(clk->flags & CLK_PLL))
davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
}
static void __clk_disable(struct clk *clk)
{
if (clk->usecount)
if (WARN_ON(clk->usecount == 0))
return;
davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
if (--clk->usecount == 0 && !(clk->flags & CLK_PLL))
davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
if (clk->parent)
__clk_disable(clk->parent);
}
int clk_enable(struct clk *clk)
{
unsigned long flags;
int ret = 0;
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
if (clk->usecount++ == 0) {
spin_lock_irqsave(&clockfw_lock, flags);
ret = __clk_enable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
spin_lock_irqsave(&clockfw_lock, flags);
__clk_enable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
return ret;
return 0;
}
EXPORT_SYMBOL(clk_enable);
......@@ -200,11 +178,9 @@ void clk_disable(struct clk *clk)
if (clk == NULL || IS_ERR(clk))
return;
if (clk->usecount > 0 && !(--clk->usecount)) {
spin_lock_irqsave(&clockfw_lock, flags);
__clk_disable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
spin_lock_irqsave(&clockfw_lock, flags);
__clk_disable(clk);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
......@@ -213,7 +189,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 +198,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);
......@@ -241,10 +217,23 @@ int clk_register(struct clk *clk)
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
if (WARN(clk->parent && !clk->parent->rate,
"CLK: %s parent %s has no rate!\n",
clk->name, clk->parent->name))
return -EINVAL;
mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
list_add_tail(&clk->node, &clocks);
mutex_unlock(&clocks_mutex);
/* If rate is already set, use it */
if (clk->rate)
return 0;
/* Otherwise, use parent rate and any divider */
if (clk->parent)
clk->rate = clk->parent->rate;
return 0;
}
EXPORT_SYMBOL(clk_register);
......@@ -260,227 +249,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
......@@ -491,7 +259,7 @@ static int __init clk_disable_unused(void)
unsigned long flags;
list_for_each_entry(ck, &clocks, node) {
if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED))
if (ck->usecount > 0)
continue;
printk(KERN_INFO "Clocks: disable unused %s\n", ck->name);
......@@ -505,52 +273,107 @@ static int __init clk_disable_unused(void)
late_initcall(clk_disable_unused);
#endif
int __init davinci_clk_init(void)
static void clk_sysclk_recalc(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 v, plldiv;
struct pll_data *pll;
/* Immediate parent must be PLL */
if (WARN_ON(!clk->parent || !clk->parent->pll_data))
return;
pll = clk->parent->pll_data;
clk->rate = clk->parent->rate;
/* If bypass divider (BPDIV) use input reference clock */
if (clk->div_reg == BPDIV)
clk->rate = pll->input_rate;
v = __raw_readl(pll->base + clk->div_reg);
if (v & PLLDIV_EN) {
plldiv = (v & PLLDIV_RATIO_MASK) + 1;
if (plldiv)
clk->rate /= plldiv;
}
}
static void __init clk_pll_init(struct clk *clk)
{
u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
u8 bypass;
struct pll_data *pll = clk->pll_data;
pll->base = IO_ADDRESS(pll->phys_base);
ctrl = __raw_readl(pll->base + PLLCTL);
clk->rate = pll->input_rate = clk->parent->rate;
if (ctrl & PLLCTL_PLLEN) {
bypass = 0;
mult = __raw_readl(pll->base + PLLM);
mult = (mult & PLLM_PLLM_MASK) + 1;
} else
bypass = 1;
if (pll->flags & PLL_HAS_PREDIV) {
prediv = __raw_readl(pll->base + PREDIV);
if (prediv & PLLDIV_EN)
prediv = (prediv & PLLDIV_RATIO_MASK) + 1;
else
prediv = 1;
}
/* pre-divider is fixed, but (some?) chips won't report that */
if (cpu_is_davinci_dm355() && pll->num == 1)
prediv = 8;
if (pll->flags & PLL_HAS_POSTDIV) {
postdiv = __raw_readl(pll->base + POSTDIV);
if (postdiv & PLLDIV_EN)
postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1;
else
postdiv = 1;
}
if (!bypass) {
clk->rate /= prediv;
clk->rate *= mult;
clk->rate /= postdiv;
}
for (clkp = board_clks; count < num_clks; count++, clkp++) {
pr_debug("PLL%d: input = %lu MHz [ ",
pll->num, clk->parent->rate / 1000000);
if (bypass)
pr_debug("bypass ");
if (prediv > 1)
pr_debug("/ %d ", prediv);
if (mult > 1)
pr_debug("* %d ", mult);
if (postdiv > 1)
pr_debug("/ %d ", postdiv);
pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000);
}
int __init davinci_clk_init(struct clk *clocks[])
{
struct clk *clkp;
int i = 0;
davinci_psc_init();
while ((clkp = clocks[i++])) {
if (clkp->pll_data)
clk_pll_init(clkp);
clk_register(clkp);
/* Turn on clocks that have been enabled in the
* table above */
if (clkp->usecount)
/* Calculate rates for PLL-derived clocks */
if (clkp->div_reg)
clk_sysclk_recalc(clkp);
/* FIXME: remove equivalent special-cased code from
* davinci_psc_init() once cpus list *all* clocks.
*/
/* Turn on clocks that Linux doesn't otherwise manage */
if (clkp->flags & ALWAYS_ENABLED)
clk_enable(clkp);
}
......@@ -576,12 +399,47 @@ static void davinci_ck_stop(struct seq_file *m, void *v)
{
}
static int davinci_ck_show(struct seq_file *m, void *v)
#define CLKNAME_MAX 10 /* longest clock name */
#define NEST_DELTA 2
#define NEST_MAX 4
static void
dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
{
struct clk *cp;
char *state;
char buf[CLKNAME_MAX + NEST_DELTA * NEST_MAX];
struct clk *clk;
unsigned i;
state = (parent->flags & CLK_PLL) ? "pll" : "psc";
/* <nest spaces> name <pad to end> */
memset(buf, ' ', sizeof(buf) - 1);
buf[sizeof(buf) - 1] = 0;
i = strlen(parent->name);
memcpy(buf + nest, parent->name,
min(i, (unsigned)(sizeof(buf) - 1 - nest)));
seq_printf(s, "%s users=%2d %-3s %9ld Hz\n",
buf, parent->usecount, state, clk_get_rate(parent));
/* REVISIT show device associations too */
/* cost is now small, but not linear... */
list_for_each_entry(clk, &clocks, node) {
if (clk->parent == parent)
dump_clock(s, nest + NEST_DELTA, clk);
}
}
list_for_each_entry(cp, &clocks, node)
seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
static int davinci_ck_show(struct seq_file *m, void *v)
{
/* Show clock tree; we know the main oscillator is first.
* We trust nonzero usecounts equate to PSC enables...
*/
mutex_lock(&clocks_mutex);
if (!list_empty(&clocks))
dump_clock(m, 0, list_first_entry(&clocks, struct clk, node));
mutex_unlock(&clocks_mutex);
return 0;
}
......
......@@ -11,32 +11,69 @@
#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
/* PLL/Reset register offsets */
#define PLLCTL 0x100
#define PLLCTL_PLLEN BIT(0)
#define PLLCTL_CLKMODE BIT(8)
#define PLLM 0x110
#define PLLM_PLLM_MASK 0xff
#define PREDIV 0x114
#define PLLDIV1 0x118
#define PLLDIV2 0x11c
#define PLLDIV3 0x120
#define POSTDIV 0x128
#define BPDIV 0x12c
#define PLLCMD 0x138
#define PLLSTAT 0x13c
#define PLLALNCTL 0x140
#define PLLDCHANGE 0x144
#define PLLCKEN 0x148
#define PLLCKSTAT 0x14c
#define PLLSYSTAT 0x150
#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;
void __iomem *base;
u32 num;
u32 flags;
u32 input_rate;
};
#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;
int id;
__s8 usecount;
__u8 flags;
__u8 lpsc;
unsigned long rate;
u8 usecount;
u8 flags;
u8 lpsc;
struct clk *parent;
struct pll_data *pll_data;
u32 div_reg;
};
/* Clock flags */
#define RATE_CKCTL 1
#define RATE_FIXED 2
#define RATE_PROPAGATES 4
#define VIRTUAL_CLOCK 8
#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
#define ALWAYS_ENABLED BIT(1)
#define CLK_PLL BIT(2)
int davinci_clk_associate(struct device *dev, const char *logical_clockname,
const char *physical_clockname);
const char *physical_clockname);
#endif
/*
* 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/dm355.h>
#include <mach/clock.h>
#include <mach/psc.h>
#include <mach/mux.h>
#include "clock.h"
#define DM355_REF_FREQ 24000000 /* 24 or 36 MHz */
static struct pll_data pll1_data = {
.num = 1,
.phys_base = DAVINCI_PLL1_BASE,
.flags = PLL_HAS_PREDIV | PLL_HAS_POSTDIV,
};
static struct pll_data pll2_data = {
.num = 2,
.phys_base = DAVINCI_PLL2_BASE,
.flags = PLL_HAS_PREDIV,
};
static struct clk ref_clk = {
.name = "ref_clk",
/* FIXME -- crystal rate is board-specific */
.rate = DM355_REF_FREQ,
.flags = CLK_PLL,
};
static struct clk pll1_clk = {
.name = "pll1",
.parent = &ref_clk,
.flags = CLK_PLL,
.pll_data = &pll1_data,
};
static struct clk pll2_clk = {
.name = "pll2",
.parent = &ref_clk,
.flags = CLK_PLL,
.pll_data = &pll2_data,
};
static struct clk aux_clk = {
.name = "aux_clk",
.parent = &ref_clk,
.flags = CLK_PLL,
};
static struct clk sysclk1_clk = {
.name = "SYSCLK1",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV1,
};
static struct clk sysclk2_clk = {
.name = "SYSCLK2",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV2,
};
static struct clk vpbe_clk = { /* a.k.a. PLL1.SYSCLK3 */
.name = "vpbe",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV3,
};
static struct clk vpss_clk = { /* a.k.a. PLL1.SYCLK4 */
.name = "vpss",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV4,
};
static struct clk clkout1_clk = {
.name = "clkout1",
.parent = &aux_clk,
.flags = CLK_PLL,
/* NOTE: clkout1 can be externally gated by muxing GPIO-18 */
};
static struct clk clkout2_clk = { /* a.k.a. PLL1.SYSCLKBP */
.name = "clkout2",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = BPDIV,
};
static struct clk clkout3_clk = {
.name = "clkout3",
.parent = &pll2_clk,
.flags = CLK_PLL,
.div_reg = BPDIV,
/* NOTE: clkout3 can be externally gated by muxing GPIO-16 */
};
static struct clk arm_clk = {
.name = "ARMCLK",
.parent = &sysclk1_clk,
.flags = ALWAYS_ENABLED | CLK_PLL,
};
/*
* NOT LISTED below, but turned on by PSC init:
* - in SyncReset state by default
* .lpsc = DAVINCI_LPSC_VPSSMSTR, .parent = &vpss_clk,
* .lpsc = DAVINCI_LPSC_VPSSSLV, .parent = &vpss_clk,
* .lpsc = DAVINCI_LPSC_TPCC,
* .lpsc = DAVINCI_LPSC_TPTC0,
* .lpsc = DAVINCI_LPSC_TPTC1,
*
* NOT LISTED below, and not touched by Linux
* - in SyncReset state by default
* .lpsc = DAVINCI_LPSC_DDR_EMIF, .parent = &sysclk2_clk,
* .lpsc = DM355_LPSC_RT0, .parent = &aux_clk,
* .lpsc = DAVINCI_LPSC_MEMSTICK,
* .lpsc = 41, .parent = &vpss_clk, // VPSS DAC
* - in Enabled state by default
* .lpsc = DAVINCI_LPSC_SYSTEM_SUBSYS,
* .lpsc = DAVINCI_LPSC_SCR2, // "bus"
* .lpsc = DAVINCI_LPSC_SCR3, // "bus"
* .lpsc = DAVINCI_LPSC_SCR4, // "bus"
* .lpsc = DAVINCI_LPSC_CROSSBAR, // "emulation"
* .lpsc = DAVINCI_LPSC_CFG27, // "test"
* .lpsc = DAVINCI_LPSC_CFG3, // "test"
* .lpsc = DAVINCI_LPSC_CFG5, // "test"
*/
static struct clk mjcp_clk = {
.name = "mjcp",
.parent = &sysclk1_clk,
.lpsc = DAVINCI_LPSC_IMCOP,
};
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 = &sysclk2_clk,
.lpsc = DAVINCI_LPSC_McBSP,
};
static struct clk asp1_clk = {
.name = "asp1_clk",
.parent = &sysclk2_clk,
.lpsc = DM355_LPSC_McBSP1,
};
static struct clk mmcsd0_clk = {
.name = "MMCSDCLK0",
.parent = &sysclk2_clk,
.lpsc = DAVINCI_LPSC_MMC_SD,
};
static struct clk mmcsd1_clk = {
.name = "MMCSDCLK1",
.parent = &sysclk2_clk,
.lpsc = DM355_LPSC_MMC_SD1,
};
static struct clk spi0_clk = {
.name = "SPICLK",
.parent = &sysclk2_clk,
.lpsc = DAVINCI_LPSC_SPI,
};
static struct clk spi1_clk = {
.name = "SPICLK1",
.parent = &sysclk2_clk,
.lpsc = DM355_LPSC_SPI1,
};
static struct clk spi2_clk = {
.name = "SPICLK2",
.parent = &sysclk2_clk,
.lpsc = DM355_LPSC_SPI2,
};
static struct clk gpio_clk = {
.name = "gpio",
.parent = &sysclk2_clk,
.lpsc = DAVINCI_LPSC_GPIO,
};
static struct clk aemif_clk = {
.name = "AEMIFCLK",
.parent = &sysclk2_clk,
.lpsc = DAVINCI_LPSC_AEMIF,
.usecount = 1,
};
static struct clk pwm0_clk = {
.name = "PWM0_CLK",
.parent = &aux_clk,
.lpsc = DAVINCI_LPSC_PWM0,
};
static struct clk pwm1_clk = {
.name = "PWM1_CLK",
.parent = &aux_clk,
.lpsc = DAVINCI_LPSC_PWM1,
};
static struct clk pwm2_clk = {
.name = "PWM2_CLK",
.parent = &aux_clk,
.lpsc = DAVINCI_LPSC_PWM2,
};
static struct clk pwm3_clk = {
.name = "PWM3_CLK",
.parent = &aux_clk,
.lpsc = DM355_LPSC_PWM3,
};
static struct clk timer0_clk = {
.name = "timer0",
.parent = &aux_clk,
.lpsc = DAVINCI_LPSC_TIMER0,
};
static struct clk timer1_clk = {
.name = "timer1",
.parent = &aux_clk,
.lpsc = DAVINCI_LPSC_TIMER1,
};
static struct clk timer2_clk = {
.name = "timer2",
.parent = &aux_clk,
.lpsc = DAVINCI_LPSC_TIMER2,
};
static struct clk timer3_clk = {
.name = "timer3",
.parent = &aux_clk,
.lpsc = DM355_LPSC_TIMER3,
};
static struct clk usb_clk = {
.name = "USBCLK",
.parent = &sysclk2_clk,
.lpsc = DAVINCI_LPSC_USB,
};
static struct clk *dm355_clks[] __initdata = {
&ref_clk,
&pll1_clk,
&aux_clk,
&sysclk1_clk,
&sysclk2_clk,
&vpbe_clk,
&vpss_clk,
&clkout1_clk,
&clkout2_clk,
&pll2_clk,
&clkout3_clk,
&arm_clk,
&mjcp_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,
&timer0_clk,
&timer1_clk,
&timer2_clk,
&timer3_clk,
&usb_clk,
NULL,
};
void __init dm355_init(void)
{
davinci_clk_init(dm355_clks);
davinci_mux_init();
}
/*
* 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,
};
static struct pll_data pll2_data = {
.num = 2,
.phys_base = DAVINCI_PLL2_BASE,
};
static struct clk ref_clk = {
.name = "ref_clk",
.rate = DM644X_REF_FREQ,
.flags = CLK_PLL,
};
static struct clk pll1_clk = {
.name = "pll1",
.parent = &ref_clk,
.pll_data = &pll1_data,
.flags = CLK_PLL,
};
static struct clk pll2_clk = {
.name = "pll2",
.parent = &ref_clk,
.pll_data = &pll2_data,
.flags = CLK_PLL,
};
static struct clk sysclk1_clk = {
.name = "SYSCLK1",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV1,
};
static struct clk sysclk2_clk = {
.name = "SYSCLK2",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV2,
};
static struct clk sysclk3_clk = {
.name = "SYSCLK3",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV3,
};
static struct clk sysclk5_clk = {
.name = "SYSCLK5",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV5,
};
static struct clk arm_clk = {
.name = "ARMCLK",
.parent = &sysclk2_clk,
.lpsc = DAVINCI_LPSC_NONE,
.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,
.lpsc = DAVINCI_LPSC_I2C,
};
static struct clk ide_clk = {
.name = "IDECLK",
.parent = &sysclk5_clk,
.lpsc = DAVINCI_LPSC_ATA,
};
static struct clk asp_clk = {
.name = "asp0_clk",
.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,
.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,
.flags = ALWAYS_ENABLED,
};
static struct clk timer0_clk = {
.name = "timer0",
.parent = &ref_clk,
.lpsc = DAVINCI_LPSC_TIMER0,
};
static struct clk timer1_clk = {
.name = "timer1",
.parent = &ref_clk,
.lpsc = DAVINCI_LPSC_TIMER1,
};
static struct clk timer2_clk = {
.name = "timer2",
.parent = &ref_clk,
.lpsc = DAVINCI_LPSC_TIMER2,
};
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,
&timer0_clk,
&timer1_clk,
&timer2_clk,
NULL,
};
void __init dm644x_init(void)
{
davinci_clk_init(dm644x_clks);
davinci_mux_init();
}
/*
* 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
static struct pll_data pll1_data = {
.num = 1,
.phys_base = DAVINCI_PLL1_BASE,
};
static struct pll_data pll2_data = {
.num = 2,
.phys_base = DAVINCI_PLL2_BASE,
};
static struct clk ref_clk = {
.name = "ref_clk",
.rate = DM646X_REF_FREQ,
.flags = CLK_PLL,
};
static struct clk aux_clk = {
.name = "aux_clk",
.rate = DM646X_AUX_FREQ,
.flags = CLK_PLL,
};
static struct clk pll1_clk = {
.name = "pll1",
.parent = &ref_clk,
.pll_data = &pll1_data,
.flags = CLK_PLL,
};
static struct clk pll2_clk = {
.name = "pll2",
.parent = &ref_clk,
.pll_data = &pll2_data,
.flags = CLK_PLL,
};
static struct clk sysclk1_clk = {
.name = "SYSCLK1",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV1,
};
static struct clk sysclk2_clk = {
.name = "SYSCLK2",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV2,
};
static struct clk sysclk3_clk = {
.name = "SYSCLK3",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV3,
};
static struct clk sysclk4_clk = {
.name = "SYSCLK4",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV4,
};
static struct clk sysclk5_clk = {
.name = "SYSCLK5",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV5,
};
static struct clk sysclk6_clk = {
.name = "SYSCLK6",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV6,
};
static struct clk sysclk8_clk = {
.name = "SYSCLK8",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV8,
};
static struct clk sysclk9_clk = {
.name = "SYSCLK9",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = PLLDIV9,
};
static struct clk sysclkbp_clk = {
.name = "SYSCLKBP",
.parent = &pll1_clk,
.flags = CLK_PLL,
.div_reg = BPDIV,
};
static struct clk arm_clk = {
.name = "ARMCLK",
.parent = &sysclk2_clk,
.lpsc = DAVINCI_LPSC_NONE,
.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,
.flags = ALWAYS_ENABLED,
};
static struct clk emac_clk = {
.name = "EMACCLK",
.parent = &sysclk3_clk,
.lpsc = DM646X_LPSC_EMAC,
};
static struct clk timer0_clk = {
.name = "timer0",
.parent = &sysclk3_clk,
.lpsc = DM646X_LPSC_TIMER0,
};
static struct clk timer1_clk = {
.name = "timer1",
.parent = &sysclk3_clk,
.lpsc = DM646X_LPSC_TIMER1,
};
static struct clk *dm646x_clks[] __initdata = {
&ref_clk,
&pll1_clk,
&sysclk1_clk,
&sysclk2_clk,
&sysclk3_clk,
&sysclk4_clk,
&sysclk5_clk,
&sysclk6_clk,
&sysclk8_clk,
&sysclk9_clk,
&sysclkbp_clk,
&pll2_clk,
&arm_clk,
&uart0_clk,
&uart1_clk,
&uart2_clk,
&i2c_clk,
&gpio_clk,
&aemif_clk,
&emac_clk,
&timer0_clk,
&timer1_clk,
NULL,
};
void __init dm646x_init(void)
{
davinci_clk_init(dm646x_clks);
davinci_mux_init();
}
......@@ -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
......@@ -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 */
......
/*
* 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 */
......@@ -24,4 +24,6 @@
#include <mach/hardware.h>
void __init dm644x_init(void);
#endif /* __ASM_ARCH_DM644X_H */
/*
* 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 */
......@@ -31,6 +31,8 @@
#define DAVINCI_GPSC_ARMDOMAIN 0
#define DAVINCI_GPSC_DSPDOMAIN 1
#define DAVINCI_LPSC_NONE 0xff
#define DAVINCI_LPSC_VPSSMSTR 0
#define DAVINCI_LPSC_VPSSSLV 1
#define DAVINCI_LPSC_TPCC 2
......
......@@ -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();
}
......@@ -124,6 +124,9 @@ void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
{
u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
if (id == DAVINCI_LPSC_NONE)
return;
mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
if (enable)
mdctl |= 0x00000003; /* Enable Module */
......@@ -199,12 +202,5 @@ void __init davinci_psc_init(void)
DAVINCI_LPSC_TPTC0, 1);
davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN,
DAVINCI_LPSC_TPTC1, 1);
/* Turn on WatchDog timer LPSC. Needed for RESET to work */
davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN,
DAVINCI_LPSC_TIMER2, 1);
} else if (cpu_is_davinci_dm646x()) {
davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN,
DM646X_LPSC_AEMIF, 1);
}
}
......@@ -57,7 +57,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),
......@@ -66,7 +65,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),
......@@ -75,7 +73,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
......@@ -125,12 +122,10 @@ void __init davinci_serial_init(struct davinci_uart_config *info)
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);
......@@ -144,8 +139,9 @@ void __init davinci_serial_init(struct davinci_uart_config *info)
continue;
}
sprintf(name, "UART%d", i);
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);
......
......@@ -16,6 +16,8 @@
#include <linux/clockchips.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <mach/hardware.h>
#include <asm/system.h>
......@@ -304,18 +306,26 @@ static struct clock_event_device clockevent_davinci = {
static void __init davinci_timer_init(void)
{
struct clk *timer_clk, *wd_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;
timer_clk = clk_get(NULL, "timer0");
BUG_ON(IS_ERR(timer_clk));
clk_enable(timer_clk);
if (cpu_is_davinci_dm644x() || cpu_is_davinci_dm355()) {
wd_clk = clk_get(NULL, "timer2");
BUG_ON(IS_ERR(wd_clk));
clk_enable(wd_clk);
}
davinci_clock_tick_rate = clk_get_rate(timer_clk);
clk_put(timer_clk);
/* setup clocksource */
clocksource_davinci.mult =
......
......@@ -401,7 +401,7 @@ static int davinci_i2s_probe(struct platform_device *pdev,
struct resource *mem, *ioarea;
struct evm_snd_platform_data *pdata;
int ret;
static const char *clocks[] = { "McBSPCLK", "McBSPCLK1", };
static const char *clocks[] = { "asp0_clk", "asp1_clk", };
if (pdev->id < 0 || pdev->id > ARRAY_SIZE(clocks))
return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment