|
@@ -24,81 +24,14 @@
|
|
|
#include <linux/debugfs.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/seq_file.h>
|
|
|
-#include <linux/regulator/consumer.h>
|
|
|
#include <linux/clkdev.h>
|
|
|
|
|
|
-#include "clock.h"
|
|
|
#include "board.h"
|
|
|
-#include "fuse.h"
|
|
|
+#include "clock.h"
|
|
|
|
|
|
static LIST_HEAD(clocks);
|
|
|
|
|
|
static DEFINE_SPINLOCK(clock_lock);
|
|
|
-static DEFINE_MUTEX(dvfs_lock);
|
|
|
-
|
|
|
-static int clk_is_dvfs(struct clk *c)
|
|
|
-{
|
|
|
- return (c->dvfs != NULL);
|
|
|
-};
|
|
|
-
|
|
|
-static int dvfs_set_rate(struct dvfs *d, unsigned long rate)
|
|
|
-{
|
|
|
- struct dvfs_table *t;
|
|
|
-
|
|
|
- if (d->table == NULL)
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- for (t = d->table; t->rate != 0; t++) {
|
|
|
- if (rate <= t->rate) {
|
|
|
- if (!d->reg)
|
|
|
- return 0;
|
|
|
-
|
|
|
- return regulator_set_voltage(d->reg,
|
|
|
- t->millivolts * 1000,
|
|
|
- d->max_millivolts * 1000);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return -EINVAL;
|
|
|
-}
|
|
|
-
|
|
|
-static void dvfs_init(struct clk *c)
|
|
|
-{
|
|
|
- int process_id;
|
|
|
- int i;
|
|
|
- struct dvfs_table *table;
|
|
|
-
|
|
|
- process_id = c->dvfs->cpu ? tegra_core_process_id() :
|
|
|
- tegra_cpu_process_id();
|
|
|
-
|
|
|
- for (i = 0; i < c->dvfs->process_id_table_length; i++)
|
|
|
- if (process_id == c->dvfs->process_id_table[i].process_id)
|
|
|
- c->dvfs->table = c->dvfs->process_id_table[i].table;
|
|
|
-
|
|
|
- if (c->dvfs->table == NULL) {
|
|
|
- pr_err("Failed to find dvfs table for clock %s process %d\n",
|
|
|
- c->name, process_id);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- c->dvfs->max_millivolts = 0;
|
|
|
- for (table = c->dvfs->table; table->rate != 0; table++)
|
|
|
- if (c->dvfs->max_millivolts < table->millivolts)
|
|
|
- c->dvfs->max_millivolts = table->millivolts;
|
|
|
-
|
|
|
- c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id);
|
|
|
-
|
|
|
- if (IS_ERR(c->dvfs->reg)) {
|
|
|
- pr_err("Failed to get regulator %s for clock %s\n",
|
|
|
- c->dvfs->reg_id, c->name);
|
|
|
- c->dvfs->reg = NULL;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (c->refcnt > 0)
|
|
|
- dvfs_set_rate(c->dvfs, c->rate);
|
|
|
-}
|
|
|
-
|
|
|
struct clk *tegra_get_clock_by_name(const char *name)
|
|
|
{
|
|
|
struct clk *c;
|
|
@@ -214,34 +147,11 @@ int clk_enable_locked(struct clk *c)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int clk_enable_cansleep(struct clk *c)
|
|
|
-{
|
|
|
- int ret;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- mutex_lock(&dvfs_lock);
|
|
|
-
|
|
|
- if (clk_is_dvfs(c) && c->refcnt > 0)
|
|
|
- dvfs_set_rate(c->dvfs, c->rate);
|
|
|
-
|
|
|
- spin_lock_irqsave(&clock_lock, flags);
|
|
|
- ret = clk_enable_locked(c);
|
|
|
- spin_unlock_irqrestore(&clock_lock, flags);
|
|
|
-
|
|
|
- mutex_unlock(&dvfs_lock);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(clk_enable_cansleep);
|
|
|
-
|
|
|
int clk_enable(struct clk *c)
|
|
|
{
|
|
|
int ret;
|
|
|
unsigned long flags;
|
|
|
|
|
|
- if (clk_is_dvfs(c))
|
|
|
- BUG();
|
|
|
-
|
|
|
spin_lock_irqsave(&clock_lock, flags);
|
|
|
ret = clk_enable_locked(c);
|
|
|
spin_unlock_irqrestore(&clock_lock, flags);
|
|
@@ -268,30 +178,10 @@ void clk_disable_locked(struct clk *c)
|
|
|
c->refcnt--;
|
|
|
}
|
|
|
|
|
|
-void clk_disable_cansleep(struct clk *c)
|
|
|
-{
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- mutex_lock(&dvfs_lock);
|
|
|
-
|
|
|
- spin_lock_irqsave(&clock_lock, flags);
|
|
|
- clk_disable_locked(c);
|
|
|
- spin_unlock_irqrestore(&clock_lock, flags);
|
|
|
-
|
|
|
- if (clk_is_dvfs(c) && c->refcnt == 0)
|
|
|
- dvfs_set_rate(c->dvfs, c->rate);
|
|
|
-
|
|
|
- mutex_unlock(&dvfs_lock);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(clk_disable_cansleep);
|
|
|
-
|
|
|
void clk_disable(struct clk *c)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
|
|
|
- if (clk_is_dvfs(c))
|
|
|
- BUG();
|
|
|
-
|
|
|
spin_lock_irqsave(&clock_lock, flags);
|
|
|
clk_disable_locked(c);
|
|
|
spin_unlock_irqrestore(&clock_lock, flags);
|
|
@@ -356,41 +246,11 @@ int clk_set_rate_locked(struct clk *c, unsigned long rate)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int clk_set_rate_cansleep(struct clk *c, unsigned long rate)
|
|
|
-{
|
|
|
- int ret = 0;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- mutex_lock(&dvfs_lock);
|
|
|
-
|
|
|
- if (rate > c->rate)
|
|
|
- ret = dvfs_set_rate(c->dvfs, rate);
|
|
|
- if (ret)
|
|
|
- goto out;
|
|
|
-
|
|
|
- spin_lock_irqsave(&clock_lock, flags);
|
|
|
- ret = clk_set_rate_locked(c, rate);
|
|
|
- spin_unlock_irqrestore(&clock_lock, flags);
|
|
|
-
|
|
|
- if (ret)
|
|
|
- goto out;
|
|
|
-
|
|
|
- ret = dvfs_set_rate(c->dvfs, rate);
|
|
|
-
|
|
|
-out:
|
|
|
- mutex_unlock(&dvfs_lock);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(clk_set_rate_cansleep);
|
|
|
-
|
|
|
int clk_set_rate(struct clk *c, unsigned long rate)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
unsigned long flags;
|
|
|
|
|
|
- if (clk_is_dvfs(c))
|
|
|
- BUG();
|
|
|
-
|
|
|
spin_lock_irqsave(&clock_lock, flags);
|
|
|
ret = clk_set_rate_locked(c, rate);
|
|
|
spin_unlock_irqrestore(&clock_lock, flags);
|
|
@@ -503,23 +363,6 @@ void __init tegra_init_clock(void)
|
|
|
tegra2_init_clocks();
|
|
|
}
|
|
|
|
|
|
-int __init tegra_init_dvfs(void)
|
|
|
-{
|
|
|
- struct clk *c, *safe;
|
|
|
-
|
|
|
- mutex_lock(&dvfs_lock);
|
|
|
-
|
|
|
- list_for_each_entry_safe(c, safe, &clocks, node)
|
|
|
- if (c->dvfs)
|
|
|
- dvfs_init(c);
|
|
|
-
|
|
|
- mutex_unlock(&dvfs_lock);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-late_initcall(tegra_init_dvfs);
|
|
|
-
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
|
static struct dentry *clk_debugfs_root;
|
|
|
|