aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrashant Gaikwad <pgaikwad@nvidia.com>2012-08-06 02:27:42 -0400
committerStephen Warren <swarren@nvidia.com>2012-09-06 13:47:20 -0400
commit96a1bd1e11ade7be969d275edd4c06749684cdba (patch)
treed76dde0eb30d5dab8cb81ad8d27fc5554e0cbe03
parent23fc5b246119f665cfa075ce7567f31a017b11b8 (diff)
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>
-rw-r--r--arch/arm/mach-tegra/clock.c126
-rw-r--r--arch/arm/mach-tegra/clock.h90
-rw-r--r--arch/arm/mach-tegra/common.c2
-rw-r--r--arch/arm/mach-tegra/include/mach/clk.h3
4 files changed, 210 insertions, 11 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 @@
1/* 1/*
2 * 2 *
3 * Copyright (C) 2010 Google, Inc. 3 * Copyright (C) 2010 Google, Inc.
4 * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved.
4 * 5 *
5 * Author: 6 * Author:
6 * Colin Cross <ccross@google.com> 7 * Colin Cross <ccross@google.com>
@@ -62,6 +63,7 @@
62static DEFINE_MUTEX(clock_list_lock); 63static DEFINE_MUTEX(clock_list_lock);
63static LIST_HEAD(clocks); 64static LIST_HEAD(clocks);
64 65
66#ifndef CONFIG_COMMON_CLK
65struct clk *tegra_get_clock_by_name(const char *name) 67struct clk *tegra_get_clock_by_name(const char *name)
66{ 68{
67 struct clk *c; 69 struct clk *c;
@@ -668,5 +670,127 @@ err_out:
668 debugfs_remove_recursive(clk_debugfs_root); 670 debugfs_remove_recursive(clk_debugfs_root);
669 return err; 671 return err;
670} 672}
671
672#endif 673#endif
674#else
675
676void tegra_clk_add(struct clk *clk)
677{
678 struct clk_tegra *c = to_clk_tegra(__clk_get_hw(clk));
679
680 mutex_lock(&clock_list_lock);
681 list_add(&c->node, &clocks);
682 mutex_unlock(&clock_list_lock);
683}
684
685struct clk *tegra_get_clock_by_name(const char *name)
686{
687 struct clk_tegra *c;
688 struct clk *ret = NULL;
689 mutex_lock(&clock_list_lock);
690 list_for_each_entry(c, &clocks, node) {
691 if (strcmp(__clk_get_name(c->hw.clk), name) == 0) {
692 ret = c->hw.clk;
693 break;
694 }
695 }
696 mutex_unlock(&clock_list_lock);
697 return ret;
698}
699
700static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
701{
702 struct clk *c;
703 struct clk *p;
704 struct clk *parent;
705
706 int ret = 0;
707
708 c = tegra_get_clock_by_name(table->name);
709
710 if (!c) {
711 pr_warn("Unable to initialize clock %s\n",
712 table->name);
713 return -ENODEV;
714 }
715
716 parent = clk_get_parent(c);
717
718 if (table->parent) {
719 p = tegra_get_clock_by_name(table->parent);
720 if (!p) {
721 pr_warn("Unable to find parent %s of clock %s\n",
722 table->parent, table->name);
723 return -ENODEV;
724 }
725
726 if (parent != p) {
727 ret = clk_set_parent(c, p);
728 if (ret) {
729 pr_warn("Unable to set parent %s of clock %s: %d\n",
730 table->parent, table->name, ret);
731 return -EINVAL;
732 }
733 }
734 }
735
736 if (table->rate && table->rate != clk_get_rate(c)) {
737 ret = clk_set_rate(c, table->rate);
738 if (ret) {
739 pr_warn("Unable to set clock %s to rate %lu: %d\n",
740 table->name, table->rate, ret);
741 return -EINVAL;
742 }
743 }
744
745 if (table->enabled) {
746 ret = clk_prepare_enable(c);
747 if (ret) {
748 pr_warn("Unable to enable clock %s: %d\n",
749 table->name, ret);
750 return -EINVAL;
751 }
752 }
753
754 return 0;
755}
756
757void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
758{
759 for (; table->name; table++)
760 tegra_clk_init_one_from_table(table);
761}
762
763void tegra_periph_reset_deassert(struct clk *c)
764{
765 struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
766 BUG_ON(!clk->reset);
767 clk->reset(__clk_get_hw(c), false);
768}
769EXPORT_SYMBOL(tegra_periph_reset_deassert);
770
771void tegra_periph_reset_assert(struct clk *c)
772{
773 struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
774 BUG_ON(!clk->reset);
775 clk->reset(__clk_get_hw(c), true);
776}
777EXPORT_SYMBOL(tegra_periph_reset_assert);
778
779/* Several extended clock configuration bits (e.g., clock routing, clock
780 * phase control) are included in PLL and peripheral clock source
781 * registers. */
782int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
783{
784 int ret = 0;
785 struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
786
787 if (!clk->clk_cfg_ex) {
788 ret = -ENOSYS;
789 goto out;
790 }
791 ret = clk->clk_cfg_ex(__clk_get_hw(c), p, setting);
792
793out:
794 return ret;
795}
796#endif /* !CONFIG_COMMON_CLK */
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index bc300657deba..f4d32ba56027 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -2,6 +2,7 @@
2 * arch/arm/mach-tegra/include/mach/clock.h 2 * arch/arm/mach-tegra/include/mach/clock.h
3 * 3 *
4 * Copyright (C) 2010 Google, Inc. 4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (c) 2012 NVIDIA CORPORATION. All rights reserved.
5 * 6 *
6 * Author: 7 * Author:
7 * Colin Cross <ccross@google.com> 8 * Colin Cross <ccross@google.com>
@@ -20,6 +21,7 @@
20#ifndef __MACH_TEGRA_CLOCK_H 21#ifndef __MACH_TEGRA_CLOCK_H
21#define __MACH_TEGRA_CLOCK_H 22#define __MACH_TEGRA_CLOCK_H
22 23
24#include <linux/clk-provider.h>
23#include <linux/clkdev.h> 25#include <linux/clkdev.h>
24#include <linux/list.h> 26#include <linux/list.h>
25#include <linux/spinlock.h> 27#include <linux/spinlock.h>
@@ -54,6 +56,11 @@
54 56
55struct clk; 57struct clk;
56 58
59#ifdef CONFIG_COMMON_CLK
60struct clk_tegra;
61#define to_clk_tegra(_hw) container_of(_hw, struct clk_tegra, hw)
62#endif
63
57struct clk_mux_sel { 64struct clk_mux_sel {
58 struct clk *input; 65 struct clk *input;
59 u32 value; 66 u32 value;
@@ -68,6 +75,13 @@ struct clk_pll_freq_table {
68 u8 cpcon; 75 u8 cpcon;
69}; 76};
70 77
78enum clk_state {
79 UNINITIALIZED = 0,
80 ON,
81 OFF,
82};
83
84#ifndef CONFIG_COMMON_CLK
71struct clk_ops { 85struct clk_ops {
72 void (*init)(struct clk *); 86 void (*init)(struct clk *);
73 int (*enable)(struct clk *); 87 int (*enable)(struct clk *);
@@ -80,12 +94,6 @@ struct clk_ops {
80 enum tegra_clk_ex_param, u32); 94 enum tegra_clk_ex_param, u32);
81}; 95};
82 96
83enum clk_state {
84 UNINITIALIZED = 0,
85 ON,
86 OFF,
87};
88
89struct clk { 97struct clk {
90 /* node for master clocks list */ 98 /* node for master clocks list */
91 struct list_head node; /* node for list of all clocks */ 99 struct list_head node; /* node for list of all clocks */
@@ -147,6 +155,65 @@ struct clk {
147 spinlock_t spinlock; 155 spinlock_t spinlock;
148}; 156};
149 157
158#else
159
160struct clk_tegra {
161 /* node for master clocks list */
162 struct list_head node; /* node for list of all clocks */
163 struct clk_lookup lookup;
164 struct clk_hw hw;
165
166 bool set;
167 unsigned long fixed_rate;
168 unsigned long max_rate;
169 unsigned long min_rate;
170 u32 flags;
171 const char *name;
172
173 enum clk_state state;
174 u32 div;
175 u32 mul;
176
177 u32 reg;
178 u32 reg_shift;
179
180 struct list_head shared_bus_list;
181
182 union {
183 struct {
184 unsigned int clk_num;
185 } periph;
186 struct {
187 unsigned long input_min;
188 unsigned long input_max;
189 unsigned long cf_min;
190 unsigned long cf_max;
191 unsigned long vco_min;
192 unsigned long vco_max;
193 const struct clk_pll_freq_table *freq_table;
194 int lock_delay;
195 unsigned long fixed_rate;
196 } pll;
197 struct {
198 u32 sel;
199 u32 reg_mask;
200 } mux;
201 struct {
202 struct clk *main;
203 struct clk *backup;
204 } cpu;
205 struct {
206 struct list_head node;
207 bool enabled;
208 unsigned long rate;
209 } shared_bus_user;
210 } u;
211
212 void (*reset)(struct clk_hw *, bool);
213 int (*clk_cfg_ex)(struct clk_hw *, enum tegra_clk_ex_param, u32);
214};
215#endif /* !CONFIG_COMMON_CLK */
216
150struct clk_duplicate { 217struct clk_duplicate {
151 const char *name; 218 const char *name;
152 struct clk_lookup lookup; 219 struct clk_lookup lookup;
@@ -159,13 +226,16 @@ struct tegra_clk_init_table {
159 bool enabled; 226 bool enabled;
160}; 227};
161 228
229#ifndef CONFIG_COMMON_CLK
230void clk_init(struct clk *clk);
231unsigned long clk_get_rate_locked(struct clk *c);
232int clk_set_rate_locked(struct clk *c, unsigned long rate);
233int clk_reparent(struct clk *c, struct clk *parent);
234#endif /* !CONFIG_COMMON_CLK */
235
162void tegra2_init_clocks(void); 236void tegra2_init_clocks(void);
163void tegra30_init_clocks(void); 237void tegra30_init_clocks(void);
164void clk_init(struct clk *clk);
165struct clk *tegra_get_clock_by_name(const char *name); 238struct clk *tegra_get_clock_by_name(const char *name);
166int clk_reparent(struct clk *c, struct clk *parent);
167void tegra_clk_init_from_table(struct tegra_clk_init_table *table); 239void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
168unsigned long clk_get_rate_locked(struct clk *c);
169int clk_set_rate_locked(struct clk *c, unsigned long rate);
170 240
171#endif 241#endif
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 96fef6bcc651..ef7d6f3cff82 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -152,6 +152,8 @@ void __init tegra30_init_early(void)
152 152
153void __init tegra_init_late(void) 153void __init tegra_init_late(void)
154{ 154{
155#ifndef CONFIG_COMMON_CLK
155 tegra_clk_debugfs_init(); 156 tegra_clk_debugfs_init();
157#endif
156 tegra_powergate_debugfs_init(); 158 tegra_powergate_debugfs_init();
157} 159}
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
index d97e403303a0..95f3a547c770 100644
--- a/arch/arm/mach-tegra/include/mach/clk.h
+++ b/arch/arm/mach-tegra/include/mach/clk.h
@@ -34,7 +34,10 @@ enum tegra_clk_ex_param {
34void tegra_periph_reset_deassert(struct clk *c); 34void tegra_periph_reset_deassert(struct clk *c);
35void tegra_periph_reset_assert(struct clk *c); 35void tegra_periph_reset_assert(struct clk *c);
36 36
37#ifndef CONFIG_COMMON_CLK
37unsigned long clk_get_rate_all_locked(struct clk *c); 38unsigned long clk_get_rate_all_locked(struct clk *c);
39#endif
40
38void tegra2_sdmmc_tap_delay(struct clk *c, int delay); 41void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
39int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting); 42int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting);
40 43