diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-01 13:05:40 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-01 13:05:40 -0800 |
commit | 13dda80e48439b446d0bc9bab34b91484bc8f533 (patch) | |
tree | e8037122d65fe2a5dd8f633a7648b2597640a2ce /arch/arm/mach-davinci/clock.c | |
parent | 379e3a820da171cb1d97e8dccd736a69cebfb7c0 (diff) | |
parent | 5f19daa16ffca55db5b0253eba2bd0f71ee7f7f4 (diff) |
Merge branch 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci
* 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci: (40 commits)
DaVinci DM365: Adding support for SPI EEPROM
DaVinci DM365: Adding DM365 SPI support
DaVinci DM355: Modifications to DM355 SPI support
DaVinci: SPI: Adding header file for SPI support.
davinci: dm646x: CDCE clocks: davinci_clk converted to clk_lookup
davinci: clkdev cleanup: remove clk_lookup wrapper, use clkdev_add_table()
DaVinci: DM365: Voice codec support for the DM365 SoC
davinci: clock: let clk->set_rate function sleep
Add SDA and SCL pin numbers to i2c platform data
davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138
davinci: build list of unused EDMA events dynamically
davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case
davinci: Keep count of channel controllers on a platform
davinci: Correct return value of edma_alloc_channel api
davinci: add CDCE949 support on DM6467 EVM
davinci: add support for CDCE949 clock synthesizer
davinci: da850/omap-l138 EVM: register for suspend support
davinci: da850/omap-l138: add support for SoC suspend
davinci: add power management support
DaVinci: DM365: Changing default queue for DM365.
...
Diffstat (limited to 'arch/arm/mach-davinci/clock.c')
-rw-r--r-- | arch/arm/mach-davinci/clock.c | 93 |
1 files changed, 39 insertions, 54 deletions
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index baece65cb9c0..bf6218ee94e1 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -49,7 +49,8 @@ static void __clk_disable(struct clk *clk) { if (WARN_ON(clk->usecount == 0)) return; - if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) + if (--clk->usecount == 0 && !(clk->flags & CLK_PLL) && + (clk->flags & CLK_PSC)) davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0); if (clk->parent) __clk_disable(clk->parent); @@ -124,9 +125,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk == NULL || IS_ERR(clk)) return ret; - spin_lock_irqsave(&clockfw_lock, flags); if (clk->set_rate) ret = clk->set_rate(clk, rate); + + spin_lock_irqsave(&clockfw_lock, flags); if (ret == 0) { if (clk->recalc) clk->rate = clk->recalc(clk); @@ -363,6 +365,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, { u32 ctrl; unsigned int locktime; + unsigned long flags; if (pll->base == NULL) return -EINVAL; @@ -376,25 +379,23 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, locktime = ((2000 * prediv) / 100); prediv = (prediv - 1) | PLLDIV_EN; } else { - locktime = 20; + locktime = PLL_LOCK_TIME; } if (postdiv) postdiv = (postdiv - 1) | PLLDIV_EN; if (mult) mult = mult - 1; + /* Protect against simultaneous calls to PLL setting seqeunce */ + spin_lock_irqsave(&clockfw_lock, flags); + ctrl = __raw_readl(pll->base + PLLCTL); /* Switch the PLL to bypass mode */ ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN); __raw_writel(ctrl, pll->base + PLLCTL); - /* - * Wait for 4 OSCIN/CLKIN cycles to ensure that the PLLC has switched - * to bypass mode. Delay of 1us ensures we are good for all > 4MHz - * OSCIN/CLKIN inputs. Typically the input is ~25MHz. - */ - udelay(1); + udelay(PLL_BYPASS_TIME); /* Reset and enable PLL */ ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS); @@ -408,11 +409,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, if (pll->flags & PLL_HAS_POSTDIV) __raw_writel(postdiv, pll->base + POSTDIV); - /* - * Wait for PLL to reset properly, OMAP-L138 datasheet says - * 'min' time = 125ns - */ - udelay(1); + udelay(PLL_RESET_TIME); /* Bring PLL out of reset */ ctrl |= PLLCTL_PLLRST; @@ -424,17 +421,20 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, ctrl |= PLLCTL_PLLEN; __raw_writel(ctrl, pll->base + PLLCTL); + spin_unlock_irqrestore(&clockfw_lock, flags); + return 0; } EXPORT_SYMBOL(davinci_set_pllrate); -int __init davinci_clk_init(struct davinci_clk *clocks) +int __init davinci_clk_init(struct clk_lookup *clocks) { - struct davinci_clk *c; + struct clk_lookup *c; struct clk *clk; + size_t num_clocks = 0; - for (c = clocks; c->lk.clk; c++) { - clk = c->lk.clk; + for (c = clocks; c->clk; c++) { + clk = c->clk; if (!clk->recalc) { @@ -457,35 +457,23 @@ int __init davinci_clk_init(struct davinci_clk *clocks) if (clk->lpsc) clk->flags |= CLK_PSC; - clkdev_add(&c->lk); clk_register(clk); + num_clocks++; /* Turn on clocks that Linux doesn't otherwise manage */ if (clk->flags & ALWAYS_ENABLED) clk_enable(clk); } - return 0; -} - -#ifdef CONFIG_PROC_FS -#include <linux/proc_fs.h> -#include <linux/seq_file.h> + clkdev_add_table(clocks, num_clocks); -static void *davinci_ck_start(struct seq_file *m, loff_t *pos) -{ - return *pos < 1 ? (void *)1 : NULL; + return 0; } -static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++*pos; - return NULL; -} +#ifdef CONFIG_DEBUG_FS -static void davinci_ck_stop(struct seq_file *m, void *v) -{ -} +#include <linux/debugfs.h> +#include <linux/seq_file.h> #define CLKNAME_MAX 10 /* longest clock name */ #define NEST_DELTA 2 @@ -525,41 +513,38 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent) 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... + struct clk *clk; + + /* + * Show clock tree; 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)); + list_for_each_entry(clk, &clocks, node) + if (!clk->parent) + dump_clock(m, 0, clk); mutex_unlock(&clocks_mutex); return 0; } -static const struct seq_operations davinci_ck_op = { - .start = davinci_ck_start, - .next = davinci_ck_next, - .stop = davinci_ck_stop, - .show = davinci_ck_show -}; - static int davinci_ck_open(struct inode *inode, struct file *file) { - return seq_open(file, &davinci_ck_op); + return single_open(file, davinci_ck_show, NULL); } -static const struct file_operations proc_davinci_ck_operations = { +static const struct file_operations davinci_ck_operations = { .open = davinci_ck_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; -static int __init davinci_ck_proc_init(void) +static int __init davinci_clk_debugfs_init(void) { - proc_create("davinci_clocks", 0, NULL, &proc_davinci_ck_operations); + debugfs_create_file("davinci_clocks", S_IFREG | S_IRUGO, NULL, NULL, + &davinci_ck_operations); return 0; } -__initcall(davinci_ck_proc_init); -#endif /* CONFIG_DEBUG_PROC_FS */ +device_initcall(davinci_clk_debugfs_init); +#endif /* CONFIG_DEBUG_FS */ |