aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/ti
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2014-12-16 11:20:46 -0500
committerMichael Turquette <mturquette@linaro.org>2015-01-30 13:50:09 -0500
commitc82f8957b48c628a74bf5dd8ee64e33fc70d7b8f (patch)
tree2ec5d570bab1ede44c632d928efd4e03b6e9629d /drivers/clk/ti
parent97bf6af1f928216fd6c5a66e8a57bfa95a659672 (diff)
clk: ti: add core support for initializing legacy clocks
Legacy clock data for OMAP3 is being moved under clock driver, thus base support for this is needed. This patch adds basic definitions for clock init descriptors and core infrastructure for initialization, which will be called from the OMAP3 clock init. Signed-off-by: Tero Kristo <t-kristo@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Michael Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk/ti')
-rw-r--r--drivers/clk/ti/clk.c110
-rw-r--r--drivers/clk/ti/clock.h160
2 files changed, 270 insertions, 0 deletions
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 337abe5909e1..a8958f1ba8a3 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -22,6 +22,8 @@
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23#include <linux/list.h> 23#include <linux/list.h>
24 24
25#include "clock.h"
26
25#undef pr_fmt 27#undef pr_fmt
26#define pr_fmt(fmt) "%s: " fmt, __func__ 28#define pr_fmt(fmt) "%s: " fmt, __func__
27 29
@@ -183,3 +185,111 @@ void ti_dt_clk_init_retry_clks(void)
183 retries--; 185 retries--;
184 } 186 }
185} 187}
188
189void __init ti_clk_patch_legacy_clks(struct ti_clk **patch)
190{
191 while (*patch) {
192 memcpy((*patch)->patch, *patch, sizeof(**patch));
193 patch++;
194 }
195}
196
197struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
198{
199 struct clk *clk;
200 struct ti_clk_fixed *fixed;
201 struct ti_clk_fixed_factor *fixed_factor;
202 struct clk_hw *clk_hw;
203
204 if (setup->clk)
205 return setup->clk;
206
207 switch (setup->type) {
208 case TI_CLK_FIXED:
209 fixed = setup->data;
210
211 clk = clk_register_fixed_rate(NULL, setup->name, NULL,
212 CLK_IS_ROOT, fixed->frequency);
213 break;
214 case TI_CLK_FIXED_FACTOR:
215 fixed_factor = setup->data;
216
217 clk = clk_register_fixed_factor(NULL, setup->name,
218 fixed_factor->parent,
219 0, fixed_factor->mult,
220 fixed_factor->div);
221 break;
222 default:
223 pr_err("bad type for %s!\n", setup->name);
224 clk = ERR_PTR(-EINVAL);
225 }
226
227 if (!IS_ERR(clk)) {
228 setup->clk = clk;
229 if (setup->clkdm_name) {
230 if (__clk_get_flags(clk) & CLK_IS_BASIC) {
231 pr_warn("can't setup clkdm for basic clk %s\n",
232 setup->name);
233 } else {
234 clk_hw = __clk_get_hw(clk);
235 to_clk_hw_omap(clk_hw)->clkdm_name =
236 setup->clkdm_name;
237 omap2_init_clk_clkdm(clk_hw);
238 }
239 }
240 }
241
242 return clk;
243}
244
245int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks)
246{
247 struct clk *clk;
248 bool retry;
249 struct ti_clk_alias *retry_clk;
250 struct ti_clk_alias *tmp;
251
252 while (clks->clk) {
253 clk = ti_clk_register_clk(clks->clk);
254 if (IS_ERR(clk)) {
255 if (PTR_ERR(clk) == -EAGAIN) {
256 list_add(&clks->link, &retry_list);
257 } else {
258 pr_err("register for %s failed: %ld\n",
259 clks->clk->name, PTR_ERR(clk));
260 return PTR_ERR(clk);
261 }
262 } else {
263 clks->lk.clk = clk;
264 clkdev_add(&clks->lk);
265 }
266 clks++;
267 }
268
269 retry = true;
270
271 while (!list_empty(&retry_list) && retry) {
272 retry = false;
273 list_for_each_entry_safe(retry_clk, tmp, &retry_list, link) {
274 pr_debug("retry-init: %s\n", retry_clk->clk->name);
275 clk = ti_clk_register_clk(retry_clk->clk);
276 if (IS_ERR(clk)) {
277 if (PTR_ERR(clk) == -EAGAIN) {
278 continue;
279 } else {
280 pr_err("register for %s failed: %ld\n",
281 retry_clk->clk->name,
282 PTR_ERR(clk));
283 return PTR_ERR(clk);
284 }
285 } else {
286 retry = true;
287 retry_clk->lk.clk = clk;
288 clkdev_add(&retry_clk->lk);
289 list_del(&retry_clk->link);
290 }
291 }
292 }
293
294 return 0;
295}
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
new file mode 100644
index 000000000000..6ee6c6e43ede
--- /dev/null
+++ b/drivers/clk/ti/clock.h
@@ -0,0 +1,160 @@
1/*
2 * TI Clock driver internal definitions
3 *
4 * Copyright (C) 2014 Texas Instruments, Inc
5 * Tero Kristo (t-kristo@ti.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation version 2.
10 *
11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12 * kind, whether express or implied; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16#ifndef __DRIVERS_CLK_TI_CLOCK__
17#define __DRIVERS_CLK_TI_CLOCK__
18
19enum {
20 TI_CLK_FIXED,
21 TI_CLK_MUX,
22 TI_CLK_DIVIDER,
23 TI_CLK_COMPOSITE,
24 TI_CLK_FIXED_FACTOR,
25 TI_CLK_GATE,
26 TI_CLK_DPLL,
27};
28
29/* Global flags */
30#define CLKF_INDEX_POWER_OF_TWO (1 << 0)
31#define CLKF_INDEX_STARTS_AT_ONE (1 << 1)
32#define CLKF_SET_RATE_PARENT (1 << 2)
33#define CLKF_OMAP3 (1 << 3)
34#define CLKF_AM35XX (1 << 4)
35
36/* Gate flags */
37#define CLKF_SET_BIT_TO_DISABLE (1 << 5)
38#define CLKF_INTERFACE (1 << 6)
39#define CLKF_SSI (1 << 7)
40#define CLKF_DSS (1 << 8)
41#define CLKF_HSOTGUSB (1 << 9)
42#define CLKF_WAIT (1 << 10)
43#define CLKF_NO_WAIT (1 << 11)
44#define CLKF_HSDIV (1 << 12)
45#define CLKF_CLKDM (1 << 13)
46
47/* DPLL flags */
48#define CLKF_LOW_POWER_STOP (1 << 5)
49#define CLKF_LOCK (1 << 6)
50#define CLKF_LOW_POWER_BYPASS (1 << 7)
51#define CLKF_PER (1 << 8)
52#define CLKF_CORE (1 << 9)
53#define CLKF_J_TYPE (1 << 10)
54
55#define CLK(dev, con, ck) \
56 { \
57 .lk = { \
58 .dev_id = dev, \
59 .con_id = con, \
60 }, \
61 .clk = ck, \
62 }
63
64struct ti_clk {
65 const char *name;
66 const char *clkdm_name;
67 int type;
68 void *data;
69 struct ti_clk *patch;
70 struct clk *clk;
71};
72
73struct ti_clk_alias {
74 struct ti_clk *clk;
75 struct clk_lookup lk;
76 struct list_head link;
77};
78
79struct ti_clk_fixed {
80 u32 frequency;
81 u16 flags;
82};
83
84struct ti_clk_mux {
85 u8 bit_shift;
86 int num_parents;
87 u16 reg;
88 u8 module;
89 const char **parents;
90 u16 flags;
91};
92
93struct ti_clk_divider {
94 const char *parent;
95 u8 bit_shift;
96 u16 max_div;
97 u16 reg;
98 u8 module;
99 int *dividers;
100 int num_dividers;
101 u16 flags;
102};
103
104struct ti_clk_fixed_factor {
105 const char *parent;
106 u16 div;
107 u16 mult;
108 u16 flags;
109};
110
111struct ti_clk_gate {
112 const char *parent;
113 u8 bit_shift;
114 u16 reg;
115 u8 module;
116 u16 flags;
117};
118
119struct ti_clk_composite {
120 struct ti_clk_divider *divider;
121 struct ti_clk_mux *mux;
122 struct ti_clk_gate *gate;
123 u16 flags;
124};
125
126struct ti_clk_clkdm_gate {
127 const char *parent;
128 u16 flags;
129};
130
131struct ti_clk_dpll {
132 int num_parents;
133 u16 control_reg;
134 u16 idlest_reg;
135 u16 autoidle_reg;
136 u16 mult_div1_reg;
137 u8 module;
138 const char **parents;
139 u16 flags;
140 u8 modes;
141 u32 mult_mask;
142 u32 div1_mask;
143 u32 enable_mask;
144 u32 autoidle_mask;
145 u32 freqsel_mask;
146 u32 idlest_mask;
147 u32 dco_mask;
148 u32 sddiv_mask;
149 u16 max_multiplier;
150 u16 max_divider;
151 u8 auto_recal_bit;
152 u8 recal_en_bit;
153 u8 recal_st_bit;
154};
155
156void ti_clk_patch_legacy_clks(struct ti_clk **patch);
157struct clk *ti_clk_register_clk(struct ti_clk *setup);
158int ti_clk_register_legacy_clks(struct ti_clk_alias *clks);
159
160#endif