diff options
author | Prashant Gaikwad <pgaikwad@nvidia.com> | 2012-08-06 11:57:42 +0530 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2012-09-06 11:47:20 -0600 |
commit | 96a1bd1e11ade7be969d275edd4c06749684cdba (patch) | |
tree | d76dde0eb30d5dab8cb81ad8d27fc5554e0cbe03 /arch/arm/mach-tegra/clock.c | |
parent | 23fc5b246119f665cfa075ce7567f31a017b11b8 (diff) | |
download | linux-rt-96a1bd1e11ade7be969d275edd4c06749684cdba.tar.gz |
ARM: tegra: Add clk_tegra structure and helper functions
Add Tegra platform specific clock structure clk_tegra and
some helper functions for generic clock framework.
struct clk_tegra is the single strcture used for all types of
clocks. reset and cfg_ex ops moved to clk_tegra from clk_ops.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/clock.c')
-rw-r--r-- | arch/arm/mach-tegra/clock.c | 126 |
1 files changed, 125 insertions, 1 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 58f981c0819c..ef9b494f961a 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -1,6 +1,7 @@ /* * * Copyright (C) 2010 Google, Inc. + * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved. * * Author: * Colin Cross <ccross@google.com> @@ -62,6 +63,7 @@ static DEFINE_MUTEX(clock_list_lock); static LIST_HEAD(clocks); +#ifndef CONFIG_COMMON_CLK struct clk *tegra_get_clock_by_name(const char *name) { struct clk *c; @@ -668,5 +670,127 @@ err_out: debugfs_remove_recursive(clk_debugfs_root); return err; } - #endif +#else + +void tegra_clk_add(struct clk *clk) +{ + struct clk_tegra *c = to_clk_tegra(__clk_get_hw(clk)); + + mutex_lock(&clock_list_lock); + list_add(&c->node, &clocks); + mutex_unlock(&clock_list_lock); +} + +struct clk *tegra_get_clock_by_name(const char *name) +{ + struct clk_tegra *c; + struct clk *ret = NULL; + mutex_lock(&clock_list_lock); + list_for_each_entry(c, &clocks, node) { + if (strcmp(__clk_get_name(c->hw.clk), name) == 0) { + ret = c->hw.clk; + break; + } + } + mutex_unlock(&clock_list_lock); + return ret; +} + +static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) +{ + struct clk *c; + struct clk *p; + struct clk *parent; + + int ret = 0; + + c = tegra_get_clock_by_name(table->name); + + if (!c) { + pr_warn("Unable to initialize clock %s\n", + table->name); + return -ENODEV; + } + + parent = clk_get_parent(c); + + if (table->parent) { + p = tegra_get_clock_by_name(table->parent); + if (!p) { + pr_warn("Unable to find parent %s of clock %s\n", + table->parent, table->name); + return -ENODEV; + } + + if (parent != p) { + ret = clk_set_parent(c, p); + if (ret) { + pr_warn("Unable to set parent %s of clock %s: %d\n", + table->parent, table->name, ret); + return -EINVAL; + } + } + } + + if (table->rate && table->rate != clk_get_rate(c)) { + ret = clk_set_rate(c, table->rate); + if (ret) { + pr_warn("Unable to set clock %s to rate %lu: %d\n", + table->name, table->rate, ret); + return -EINVAL; + } + } + + if (table->enabled) { + ret = clk_prepare_enable(c); + if (ret) { + pr_warn("Unable to enable clock %s: %d\n", + table->name, ret); + return -EINVAL; + } + } + + return 0; +} + +void tegra_clk_init_from_table(struct tegra_clk_init_table *table) +{ + for (; table->name; table++) + tegra_clk_init_one_from_table(table); +} + +void tegra_periph_reset_deassert(struct clk *c) +{ + struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c)); + BUG_ON(!clk->reset); + clk->reset(__clk_get_hw(c), false); +} +EXPORT_SYMBOL(tegra_periph_reset_deassert); + +void tegra_periph_reset_assert(struct clk *c) +{ + struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c)); + BUG_ON(!clk->reset); + clk->reset(__clk_get_hw(c), true); +} +EXPORT_SYMBOL(tegra_periph_reset_assert); + +/* Several extended clock configuration bits (e.g., clock routing, clock + * phase control) are included in PLL and peripheral clock source + * registers. */ +int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting) +{ + int ret = 0; + struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c)); + + if (!clk->clk_cfg_ex) { + ret = -ENOSYS; + goto out; + } + ret = clk->clk_cfg_ex(__clk_get_hw(c), p, setting); + +out: + return ret; +} +#endif /* !CONFIG_COMMON_CLK */ |