aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2015-07-28 14:58:26 -0400
committerStephen Boyd <sboyd@codeaurora.org>2015-07-28 14:58:26 -0400
commit4d341056202a4725777ed99897f6456405819cd4 (patch)
tree45fb9d229bacf995aabcad282937568e5201b5a7
parente306479ac252928b84cc563c6e790f9b7e7ae427 (diff)
parent989feafb84118a840ff21250a1e5f516f43e3dbb (diff)
Merge branch 'for-4.2/ti-clk-move' of https://github.com/t-kristo/linux-pm into clk-next
From Tero Kristo: "This pull request contains the TI clock driver set to move the clock implementations under clock driver. Some small portions of the clock driver code still remain under mach-omap2 after this, it should be decided whether this code is now obsolete and should be deleted or should someone try to fix it." Slight merge conflicts with determine_rate prototype changes.
-rw-r--r--arch/arm/mach-omap2/Makefile22
-rw-r--r--arch/arm/mach-omap2/clkt34xx_dpll3m2.c7
-rw-r--r--arch/arm/mach-omap2/clkt_clksel.c466
-rw-r--r--arch/arm/mach-omap2/clkt_iclk.c68
-rw-r--r--arch/arm/mach-omap2/clock.c675
-rw-r--r--arch/arm/mach-omap2/clock.h205
-rw-r--r--arch/arm/mach-omap2/clock2430.c57
-rw-r--r--arch/arm/mach-omap2/clock2xxx.c57
-rw-r--r--arch/arm/mach-omap2/clock34xx.c138
-rw-r--r--arch/arm/mach-omap2/clock34xx.h18
-rw-r--r--arch/arm/mach-omap2/clock3517.c118
-rw-r--r--arch/arm/mach-omap2/clock3517.h14
-rw-r--r--arch/arm/mach-omap2/clock36xx.c69
-rw-r--r--arch/arm/mach-omap2/clock36xx.h13
-rw-r--r--arch/arm/mach-omap2/clock3xxx.c135
-rw-r--r--arch/arm/mach-omap2/clock44xx.h20
-rw-r--r--arch/arm/mach-omap2/clock_common_data.c115
-rw-r--r--arch/arm/mach-omap2/io.c3
-rw-r--r--drivers/clk/ti/Makefile17
-rw-r--r--drivers/clk/ti/apll.c2
-rw-r--r--drivers/clk/ti/autoidle.c121
-rw-r--r--drivers/clk/ti/clk-2xxx.c2
-rw-r--r--drivers/clk/ti/clk-33xx.c2
-rw-r--r--drivers/clk/ti/clk-3xxx.c244
-rw-r--r--drivers/clk/ti/clk-43xx.c2
-rw-r--r--drivers/clk/ti/clk-44xx.c2
-rw-r--r--drivers/clk/ti/clk-54xx.c2
-rw-r--r--drivers/clk/ti/clk-7xx.c3
-rw-r--r--drivers/clk/ti/clk-816x.c2
-rw-r--r--drivers/clk/ti/clk.c145
-rw-r--r--drivers/clk/ti/clkt_dflt.c316
-rw-r--r--drivers/clk/ti/clkt_dpll.c (renamed from arch/arm/mach-omap2/clkt_dpll.c)27
-rw-r--r--drivers/clk/ti/clkt_iclk.c101
-rw-r--r--drivers/clk/ti/clock.h105
-rw-r--r--drivers/clk/ti/clockdomain.c78
-rw-r--r--drivers/clk/ti/dpll3xxx.c (renamed from arch/arm/mach-omap2/dpll3xxx.c)157
-rw-r--r--drivers/clk/ti/dpll44xx.c (renamed from arch/arm/mach-omap2/dpll44xx.c)23
-rw-r--r--drivers/clk/ti/fixed-factor.c2
-rw-r--r--include/linux/clk/ti.h149
39 files changed, 1320 insertions, 2382 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 903c85be2897..7892c7d3b6f4 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -12,8 +12,7 @@ obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o timer.o pm.o \
12 12
13hwmod-common = omap_hwmod.o omap_hwmod_reset.o \ 13hwmod-common = omap_hwmod.o omap_hwmod_reset.o \
14 omap_hwmod_common_data.o 14 omap_hwmod_common_data.o
15clock-common = clock.o clock_common_data.o \ 15clock-common = clock.o
16 clkt_dpll.o clkt_clksel.o
17secure-common = omap-smc.o omap-secure.o 16secure-common = omap-smc.o omap-secure.o
18 17
19obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) 18obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
@@ -182,24 +181,17 @@ obj-$(CONFIG_SOC_DRA7XX) += $(clockdomain-common)
182obj-$(CONFIG_SOC_DRA7XX) += clockdomains7xx_data.o 181obj-$(CONFIG_SOC_DRA7XX) += clockdomains7xx_data.o
183 182
184# Clock framework 183# Clock framework
185obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o 184obj-$(CONFIG_ARCH_OMAP2) += $(clock-common)
186obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpllcore.o 185obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpllcore.o
187obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_virt_prcm_set.o 186obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_virt_prcm_set.o
188obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o clkt_iclk.o 187obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o
189obj-$(CONFIG_SOC_OMAP2430) += clock2430.o 188obj-$(CONFIG_ARCH_OMAP3) += $(clock-common)
190obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o 189obj-$(CONFIG_ARCH_OMAP3) += clkt34xx_dpll3m2.o
191obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o clkt34xx_dpll3m2.o
192obj-$(CONFIG_ARCH_OMAP3) += clock3517.o clock36xx.o
193obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o
194obj-$(CONFIG_ARCH_OMAP3) += clkt_iclk.o
195obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) 190obj-$(CONFIG_ARCH_OMAP4) += $(clock-common)
196obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o 191obj-$(CONFIG_SOC_AM33XX) += $(clock-common)
197obj-$(CONFIG_SOC_AM33XX) += $(clock-common) dpll3xxx.o
198obj-$(CONFIG_SOC_OMAP5) += $(clock-common) 192obj-$(CONFIG_SOC_OMAP5) += $(clock-common)
199obj-$(CONFIG_SOC_OMAP5) += dpll3xxx.o dpll44xx.o
200obj-$(CONFIG_SOC_DRA7XX) += $(clock-common) 193obj-$(CONFIG_SOC_DRA7XX) += $(clock-common)
201obj-$(CONFIG_SOC_DRA7XX) += dpll3xxx.o dpll44xx.o 194obj-$(CONFIG_SOC_AM43XX) += $(clock-common)
202obj-$(CONFIG_SOC_AM43XX) += $(clock-common) dpll3xxx.o
203 195
204# OMAP2 clock rate set data (old "OPP" data) 196# OMAP2 clock rate set data (old "OPP" data)
205obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o 197obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o
diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
index eb69acf21014..07e1956a26ce 100644
--- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
+++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
@@ -23,12 +23,13 @@
23 23
24#include "clock.h" 24#include "clock.h"
25#include "clock3xxx.h" 25#include "clock3xxx.h"
26#include "clock34xx.h"
27#include "sdrc.h" 26#include "sdrc.h"
28#include "sram.h" 27#include "sram.h"
29 28
30#define CYCLES_PER_MHZ 1000000 29#define CYCLES_PER_MHZ 1000000
31 30
31struct clk *sdrc_ick_p, *arm_fck_p;
32
32/* 33/*
33 * CORE DPLL (DPLL3) M2 divider rate programming functions 34 * CORE DPLL (DPLL3) M2 divider rate programming functions
34 * 35 *
@@ -60,7 +61,9 @@ int omap3_core_dpll_m2_set_rate(struct clk_hw *hw, unsigned long rate,
60 if (!clk || !rate) 61 if (!clk || !rate)
61 return -EINVAL; 62 return -EINVAL;
62 63
63 validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); 64 new_div = DIV_ROUND_UP(parent_rate, rate);
65 validrate = parent_rate / new_div;
66
64 if (validrate != rate) 67 if (validrate != rate)
65 return -EINVAL; 68 return -EINVAL;
66 69
diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
deleted file mode 100644
index 7ee26108ac0d..000000000000
--- a/arch/arm/mach-omap2/clkt_clksel.c
+++ /dev/null
@@ -1,466 +0,0 @@
1/*
2 * clkt_clksel.c - OMAP2/3/4 clksel clock functions
3 *
4 * Copyright (C) 2005-2008 Texas Instruments, Inc.
5 * Copyright (C) 2004-2010 Nokia Corporation
6 *
7 * Contacts:
8 * Richard Woodruff <r-woodruff2@ti.com>
9 * Paul Walmsley
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 *
16 * clksel clocks are clocks that do not have a fixed parent, or that
17 * can divide their parent's rate, or possibly both at the same time, based
18 * on the contents of a hardware register bitfield.
19 *
20 * All of the various mux and divider settings can be encoded into
21 * struct clksel* data structures, and then these can be autogenerated
22 * from some hardware database for each new chip generation. This
23 * should avoid the need to write, review, and validate a lot of new
24 * clock code for each new chip, since it can be exported from the SoC
25 * design flow. This is now done on OMAP4.
26 *
27 * The fusion of mux and divider clocks is a software creation. In
28 * hardware reality, the multiplexer (parent selection) and the
29 * divider exist separately. XXX At some point these clksel clocks
30 * should be split into "divider" clocks and "mux" clocks to better
31 * match the hardware.
32 *
33 * (The name "clksel" comes from the name of the corresponding
34 * register field in the OMAP2/3 family of SoCs.)
35 *
36 * XXX Currently these clocks are only used in the OMAP2/3/4 code, but
37 * many of the OMAP1 clocks should be convertible to use this
38 * mechanism.
39 */
40#undef DEBUG
41
42#include <linux/kernel.h>
43#include <linux/errno.h>
44#include <linux/clk-provider.h>
45#include <linux/io.h>
46#include <linux/bug.h>
47
48#include "clock.h"
49
50/* Private functions */
51
52/**
53 * _get_clksel_by_parent() - return clksel struct for a given clk & parent
54 * @clk: OMAP struct clk ptr to inspect
55 * @src_clk: OMAP struct clk ptr of the parent clk to search for
56 *
57 * Scan the struct clksel array associated with the clock to find
58 * the element associated with the supplied parent clock address.
59 * Returns a pointer to the struct clksel on success or NULL on error.
60 */
61static const struct clksel *_get_clksel_by_parent(struct clk_hw_omap *clk,
62 struct clk *src_clk)
63{
64 const struct clksel *clks;
65
66 if (!src_clk)
67 return NULL;
68
69 for (clks = clk->clksel; clks->parent; clks++)
70 if (clks->parent == src_clk)
71 break; /* Found the requested parent */
72
73 if (!clks->parent) {
74 /* This indicates a data problem */
75 WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
76 __clk_get_name(clk->hw.clk), __clk_get_name(src_clk));
77 return NULL;
78 }
79
80 return clks;
81}
82
83/**
84 * _write_clksel_reg() - program a clock's clksel register in hardware
85 * @clk: struct clk * to program
86 * @v: clksel bitfield value to program (with LSB at bit 0)
87 *
88 * Shift the clksel register bitfield value @v to its appropriate
89 * location in the clksel register and write it in. This function
90 * will ensure that the write to the clksel_reg reaches its
91 * destination before returning -- important since PRM and CM register
92 * accesses can be quite slow compared to ARM cycles -- but does not
93 * take into account any time the hardware might take to switch the
94 * clock source.
95 */
96static void _write_clksel_reg(struct clk_hw_omap *clk, u32 field_val)
97{
98 u32 v;
99
100 v = omap2_clk_readl(clk, clk->clksel_reg);
101 v &= ~clk->clksel_mask;
102 v |= field_val << __ffs(clk->clksel_mask);
103 omap2_clk_writel(v, clk, clk->clksel_reg);
104
105 v = omap2_clk_readl(clk, clk->clksel_reg); /* OCP barrier */
106}
107
108/**
109 * _clksel_to_divisor() - turn clksel field value into integer divider
110 * @clk: OMAP struct clk to use
111 * @field_val: register field value to find
112 *
113 * Given a struct clk of a rate-selectable clksel clock, and a register field
114 * value to search for, find the corresponding clock divisor. The register
115 * field value should be pre-masked and shifted down so the LSB is at bit 0
116 * before calling. Returns 0 on error or returns the actual integer divisor
117 * upon success.
118 */
119static u32 _clksel_to_divisor(struct clk_hw_omap *clk, u32 field_val)
120{
121 const struct clksel *clks;
122 const struct clksel_rate *clkr;
123 struct clk *parent;
124
125 parent = __clk_get_parent(clk->hw.clk);
126
127 clks = _get_clksel_by_parent(clk, parent);
128 if (!clks)
129 return 0;
130
131 for (clkr = clks->rates; clkr->div; clkr++) {
132 if (!(clkr->flags & cpu_mask))
133 continue;
134
135 if (clkr->val == field_val)
136 break;
137 }
138
139 if (!clkr->div) {
140 /* This indicates a data error */
141 WARN(1, "clock: %s: could not find fieldval %d for parent %s\n",
142 __clk_get_name(clk->hw.clk), field_val,
143 __clk_get_name(parent));
144 return 0;
145 }
146
147 return clkr->div;
148}
149
150/**
151 * _divisor_to_clksel() - turn clksel integer divisor into a field value
152 * @clk: OMAP struct clk to use
153 * @div: integer divisor to search for
154 *
155 * Given a struct clk of a rate-selectable clksel clock, and a clock
156 * divisor, find the corresponding register field value. Returns the
157 * register field value _before_ left-shifting (i.e., LSB is at bit
158 * 0); or returns 0xFFFFFFFF (~0) upon error.
159 */
160static u32 _divisor_to_clksel(struct clk_hw_omap *clk, u32 div)
161{
162 const struct clksel *clks;
163 const struct clksel_rate *clkr;
164 struct clk *parent;
165
166 /* should never happen */
167 WARN_ON(div == 0);
168
169 parent = __clk_get_parent(clk->hw.clk);
170 clks = _get_clksel_by_parent(clk, parent);
171 if (!clks)
172 return ~0;
173
174 for (clkr = clks->rates; clkr->div; clkr++) {
175 if (!(clkr->flags & cpu_mask))
176 continue;
177
178 if (clkr->div == div)
179 break;
180 }
181
182 if (!clkr->div) {
183 pr_err("clock: %s: could not find divisor %d for parent %s\n",
184 __clk_get_name(clk->hw.clk), div,
185 __clk_get_name(parent));
186 return ~0;
187 }
188
189 return clkr->val;
190}
191
192/**
193 * _read_divisor() - get current divisor applied to parent clock (from hdwr)
194 * @clk: OMAP struct clk to use.
195 *
196 * Read the current divisor register value for @clk that is programmed
197 * into the hardware, convert it into the actual divisor value, and
198 * return it; or return 0 on error.
199 */
200static u32 _read_divisor(struct clk_hw_omap *clk)
201{
202 u32 v;
203
204 if (!clk->clksel || !clk->clksel_mask)
205 return 0;
206
207 v = omap2_clk_readl(clk, clk->clksel_reg);
208 v &= clk->clksel_mask;
209 v >>= __ffs(clk->clksel_mask);
210
211 return _clksel_to_divisor(clk, v);
212}
213
214/* Public functions */
215
216/**
217 * omap2_clksel_round_rate_div() - find divisor for the given clock and rate
218 * @clk: OMAP struct clk to use
219 * @target_rate: desired clock rate
220 * @new_div: ptr to where we should store the divisor
221 *
222 * Finds 'best' divider value in an array based on the source and target
223 * rates. The divider array must be sorted with smallest divider first.
224 * This function is also used by the DPLL3 M2 divider code.
225 *
226 * Returns the rounded clock rate or returns 0xffffffff on error.
227 */
228u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
229 unsigned long target_rate,
230 u32 *new_div)
231{
232 unsigned long test_rate;
233 const struct clksel *clks;
234 const struct clksel_rate *clkr;
235 u32 last_div = 0;
236 struct clk *parent;
237 unsigned long parent_rate;
238 const char *clk_name;
239
240 parent = __clk_get_parent(clk->hw.clk);
241 clk_name = __clk_get_name(clk->hw.clk);
242 parent_rate = __clk_get_rate(parent);
243
244 if (!clk->clksel || !clk->clksel_mask)
245 return ~0;
246
247 pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
248 clk_name, target_rate);
249
250 *new_div = 1;
251
252 clks = _get_clksel_by_parent(clk, parent);
253 if (!clks)
254 return ~0;
255
256 for (clkr = clks->rates; clkr->div; clkr++) {
257 if (!(clkr->flags & cpu_mask))
258 continue;
259
260 /* Sanity check */
261 if (clkr->div <= last_div)
262 pr_err("clock: %s: clksel_rate table not sorted\n",
263 clk_name);
264
265 last_div = clkr->div;
266
267 test_rate = parent_rate / clkr->div;
268
269 if (test_rate <= target_rate)
270 break; /* found it */
271 }
272
273 if (!clkr->div) {
274 pr_err("clock: %s: could not find divisor for target rate %ld for parent %s\n",
275 clk_name, target_rate, __clk_get_name(parent));
276 return ~0;
277 }
278
279 *new_div = clkr->div;
280
281 pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
282 (parent_rate / clkr->div));
283
284 return parent_rate / clkr->div;
285}
286
287/*
288 * Clocktype interface functions to the OMAP clock code
289 * (i.e., those used in struct clk field function pointers, etc.)
290 */
291
292/**
293 * omap2_clksel_find_parent_index() - return the array index of the current
294 * hardware parent of @hw
295 * @hw: struct clk_hw * to find the current hardware parent of
296 *
297 * Given a struct clk_hw pointer @hw to the 'hw' member of a struct
298 * clk_hw_omap record representing a source-selectable hardware clock,
299 * read the hardware register and determine what its parent is
300 * currently set to. Intended to be called only by the common clock
301 * framework struct clk_hw_ops.get_parent function pointer. Return
302 * the array index of this parent clock upon success -- there is no
303 * way to return an error, so if we encounter an error, just WARN()
304 * and pretend that we know that we're doing.
305 */
306u8 omap2_clksel_find_parent_index(struct clk_hw *hw)
307{
308 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
309 const struct clksel *clks;
310 const struct clksel_rate *clkr;
311 u32 r, found = 0;
312 struct clk *parent;
313 const char *clk_name;
314 int ret = 0, f = 0;
315
316 parent = __clk_get_parent(hw->clk);
317 clk_name = __clk_get_name(hw->clk);
318
319 /* XXX should be able to return an error */
320 WARN((!clk->clksel || !clk->clksel_mask),
321 "clock: %s: attempt to call on a non-clksel clock", clk_name);
322
323 r = omap2_clk_readl(clk, clk->clksel_reg) & clk->clksel_mask;
324 r >>= __ffs(clk->clksel_mask);
325
326 for (clks = clk->clksel; clks->parent && !found; clks++) {
327 for (clkr = clks->rates; clkr->div && !found; clkr++) {
328 if (!(clkr->flags & cpu_mask))
329 continue;
330
331 if (clkr->val == r) {
332 found = 1;
333 ret = f;
334 }
335 }
336 f++;
337 }
338
339 /* This indicates a data error */
340 WARN(!found, "clock: %s: init parent: could not find regval %0x\n",
341 clk_name, r);
342
343 return ret;
344}
345
346
347/**
348 * omap2_clksel_recalc() - function ptr to pass via struct clk .recalc field
349 * @clk: struct clk *
350 *
351 * This function is intended to be called only by the clock framework.
352 * Each clksel clock should have its struct clk .recalc field set to this
353 * function. Returns the clock's current rate, based on its parent's rate
354 * and its current divisor setting in the hardware.
355 */
356unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate)
357{
358 unsigned long rate;
359 u32 div = 0;
360 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
361
362 if (!parent_rate)
363 return 0;
364
365 div = _read_divisor(clk);
366 if (!div)
367 rate = parent_rate;
368 else
369 rate = parent_rate / div;
370
371 pr_debug("%s: recalc'd %s's rate to %lu (div %d)\n", __func__,
372 __clk_get_name(hw->clk), rate, div);
373
374 return rate;
375}
376
377/**
378 * omap2_clksel_round_rate() - find rounded rate for the given clock and rate
379 * @clk: OMAP struct clk to use
380 * @target_rate: desired clock rate
381 *
382 * This function is intended to be called only by the clock framework.
383 * Finds best target rate based on the source clock and possible dividers.
384 * rates. The divider array must be sorted with smallest divider first.
385 *
386 * Returns the rounded clock rate or returns 0xffffffff on error.
387 */
388long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
389 unsigned long *parent_rate)
390{
391 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
392 u32 new_div;
393
394 return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
395}
396
397/**
398 * omap2_clksel_set_rate() - program clock rate in hardware
399 * @clk: struct clk * to program rate
400 * @rate: target rate to program
401 *
402 * This function is intended to be called only by the clock framework.
403 * Program @clk's rate to @rate in the hardware. The clock can be
404 * either enabled or disabled when this happens, although if the clock
405 * is enabled, some downstream devices may glitch or behave
406 * unpredictably when the clock rate is changed - this depends on the
407 * hardware. This function does not currently check the usecount of
408 * the clock, so if multiple drivers are using the clock, and the rate
409 * is changed, they will all be affected without any notification.
410 * Returns -EINVAL upon error, or 0 upon success.
411 */
412int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
413 unsigned long parent_rate)
414{
415 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
416 u32 field_val, validrate, new_div = 0;
417
418 if (!clk->clksel || !clk->clksel_mask)
419 return -EINVAL;
420
421 validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
422 if (validrate != rate)
423 return -EINVAL;
424
425 field_val = _divisor_to_clksel(clk, new_div);
426 if (field_val == ~0)
427 return -EINVAL;
428
429 _write_clksel_reg(clk, field_val);
430
431 pr_debug("clock: %s: set rate to %ld\n", __clk_get_name(hw->clk),
432 __clk_get_rate(hw->clk));
433
434 return 0;
435}
436
437/*
438 * Clksel parent setting function - not passed in struct clk function
439 * pointer - instead, the OMAP clock code currently assumes that any
440 * parent-setting clock is a clksel clock, and calls
441 * omap2_clksel_set_parent() by default
442 */
443
444/**
445 * omap2_clksel_set_parent() - change a clock's parent clock
446 * @clk: struct clk * of the child clock
447 * @new_parent: struct clk * of the new parent clock
448 *
449 * This function is intended to be called only by the clock framework.
450 * Change the parent clock of clock @clk to @new_parent. This is
451 * intended to be used while @clk is disabled. This function does not
452 * currently check the usecount of the clock, so if multiple drivers
453 * are using the clock, and the parent is changed, they will all be
454 * affected without any notification. Returns -EINVAL upon error, or
455 * 0 upon success.
456 */
457int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val)
458{
459 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
460
461 if (!clk->clksel || !clk->clksel_mask)
462 return -EINVAL;
463
464 _write_clksel_reg(clk, field_val);
465 return 0;
466}
diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
deleted file mode 100644
index 55eb579aeae1..000000000000
--- a/arch/arm/mach-omap2/clkt_iclk.c
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 * OMAP2/3 interface clock control
3 *
4 * Copyright (C) 2011 Nokia Corporation
5 * Paul Walmsley
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#undef DEBUG
12
13#include <linux/kernel.h>
14#include <linux/clk-provider.h>
15#include <linux/io.h>
16
17#include "clock.h"
18
19/* Register offsets */
20#define CM_AUTOIDLE 0x30
21#define CM_ICLKEN 0x10
22
23/* Private functions */
24
25/* XXX */
26void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
27{
28 u32 v;
29 void __iomem *r;
30
31 r = (__force void __iomem *)
32 ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
33
34 v = omap2_clk_readl(clk, r);
35 v |= (1 << clk->enable_bit);
36 omap2_clk_writel(v, clk, r);
37}
38
39/* XXX */
40void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
41{
42 u32 v;
43 void __iomem *r;
44
45 r = (__force void __iomem *)
46 ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
47
48 v = omap2_clk_readl(clk, r);
49 v &= ~(1 << clk->enable_bit);
50 omap2_clk_writel(v, clk, r);
51}
52
53/* Public data */
54
55const struct clk_hw_omap_ops clkhwops_iclk = {
56 .allow_idle = omap2_clkt_iclk_allow_idle,
57 .deny_idle = omap2_clkt_iclk_deny_idle,
58};
59
60const struct clk_hw_omap_ops clkhwops_iclk_wait = {
61 .allow_idle = omap2_clkt_iclk_allow_idle,
62 .deny_idle = omap2_clkt_iclk_deny_idle,
63 .find_idlest = omap2_clk_dflt_find_idlest,
64 .find_companion = omap2_clk_dflt_find_companion,
65};
66
67
68
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index a699d7169307..4340ba6524d1 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -23,9 +23,7 @@
23#include <linux/clk-provider.h> 23#include <linux/clk-provider.h>
24#include <linux/io.h> 24#include <linux/io.h>
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26#include <linux/regmap.h>
27#include <linux/of_address.h> 26#include <linux/of_address.h>
28#include <linux/bootmem.h>
29#include <asm/cpu.h> 27#include <asm/cpu.h>
30 28
31#include <trace/events/power.h> 29#include <trace/events/power.h>
@@ -40,19 +38,8 @@
40#include "cm-regbits-34xx.h" 38#include "cm-regbits-34xx.h"
41#include "common.h" 39#include "common.h"
42 40
43/*
44 * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait
45 * for a module to indicate that it is no longer in idle
46 */
47#define MAX_MODULE_ENABLE_WAIT 100000
48
49u16 cpu_mask; 41u16 cpu_mask;
50 42
51/*
52 * Clock features setup. Used instead of CPU type checks.
53 */
54struct ti_clk_features ti_clk_features;
55
56/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */ 43/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
57#define OMAP3430_DPLL_FINT_BAND1_MIN 750000 44#define OMAP3430_DPLL_FINT_BAND1_MIN 750000
58#define OMAP3430_DPLL_FINT_BAND1_MAX 2100000 45#define OMAP3430_DPLL_FINT_BAND1_MAX 2100000
@@ -66,119 +53,24 @@ struct ti_clk_features ti_clk_features;
66#define OMAP3PLUS_DPLL_FINT_MIN 32000 53#define OMAP3PLUS_DPLL_FINT_MIN 32000
67#define OMAP3PLUS_DPLL_FINT_MAX 52000000 54#define OMAP3PLUS_DPLL_FINT_MAX 52000000
68 55
69/*
70 * clkdm_control: if true, then when a clock is enabled in the
71 * hardware, its clockdomain will first be enabled; and when a clock
72 * is disabled in the hardware, its clockdomain will be disabled
73 * afterwards.
74 */
75static bool clkdm_control = true;
76
77static LIST_HEAD(clk_hw_omap_clocks);
78
79struct clk_iomap {
80 struct regmap *regmap;
81 void __iomem *mem;
82};
83
84static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
85
86static void clk_memmap_writel(u32 val, void __iomem *reg)
87{
88 struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
89 struct clk_iomap *io = clk_memmaps[r->index];
90
91 if (io->regmap)
92 regmap_write(io->regmap, r->offset, val);
93 else
94 writel_relaxed(val, io->mem + r->offset);
95}
96
97static u32 clk_memmap_readl(void __iomem *reg)
98{
99 u32 val;
100 struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
101 struct clk_iomap *io = clk_memmaps[r->index];
102
103 if (io->regmap)
104 regmap_read(io->regmap, r->offset, &val);
105 else
106 val = readl_relaxed(io->mem + r->offset);
107
108 return val;
109}
110
111void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg)
112{
113 if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
114 writel_relaxed(val, reg);
115 else
116 clk_memmap_writel(val, reg);
117}
118
119u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg)
120{
121 if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
122 return readl_relaxed(reg);
123 else
124 return clk_memmap_readl(reg);
125}
126
127static struct ti_clk_ll_ops omap_clk_ll_ops = { 56static struct ti_clk_ll_ops omap_clk_ll_ops = {
128 .clk_readl = clk_memmap_readl, 57 .clkdm_clk_enable = clkdm_clk_enable,
129 .clk_writel = clk_memmap_writel, 58 .clkdm_clk_disable = clkdm_clk_disable,
59 .cm_wait_module_ready = omap_cm_wait_module_ready,
60 .cm_split_idlest_reg = cm_split_idlest_reg,
130}; 61};
131 62
132/** 63/**
133 * omap2_clk_provider_init - initialize a clock provider 64 * omap2_clk_setup_ll_ops - setup clock driver low-level ops
134 * @match_table: DT device table to match for devices to init
135 * @np: device node pointer for the this clock provider
136 * @index: index for the clock provider
137 + @syscon: syscon regmap pointer
138 * @mem: iomem pointer for the clock provider memory area, only used if
139 * syscon is not provided
140 * 65 *
141 * Initializes a clock provider module (CM/PRM etc.), registering 66 * Sets up clock driver low-level platform ops. These are needed
142 * the memory mapping at specified index and initializing the 67 * for register accesses and various other misc platform operations.
143 * low level driver infrastructure. Returns 0 in success. 68 * Returns 0 on success, -EBUSY if low level ops have been registered
69 * already.
144 */ 70 */
145int __init omap2_clk_provider_init(struct device_node *np, int index, 71int __init omap2_clk_setup_ll_ops(void)
146 struct regmap *syscon, void __iomem *mem)
147{ 72{
148 struct clk_iomap *io; 73 return ti_clk_setup_ll_ops(&omap_clk_ll_ops);
149
150 ti_clk_ll_ops = &omap_clk_ll_ops;
151
152 io = kzalloc(sizeof(*io), GFP_KERNEL);
153
154 io->regmap = syscon;
155 io->mem = mem;
156
157 clk_memmaps[index] = io;
158
159 ti_dt_clk_init_provider(np, index);
160
161 return 0;
162}
163
164/**
165 * omap2_clk_legacy_provider_init - initialize a legacy clock provider
166 * @index: index for the clock provider
167 * @mem: iomem pointer for the clock provider memory area
168 *
169 * Initializes a legacy clock provider memory mapping.
170 */
171void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
172{
173 struct clk_iomap *io;
174
175 ti_clk_ll_ops = &omap_clk_ll_ops;
176
177 io = memblock_virt_alloc(sizeof(*io), 0);
178
179 io->mem = mem;
180
181 clk_memmaps[index] = io;
182} 74}
183 75
184/* 76/*
@@ -187,77 +79,6 @@ void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
187 79
188/* Private functions */ 80/* Private functions */
189 81
190
191/**
192 * _wait_idlest_generic - wait for a module to leave the idle state
193 * @clk: module clock to wait for (needed for register offsets)
194 * @reg: virtual address of module IDLEST register
195 * @mask: value to mask against to determine if the module is active
196 * @idlest: idle state indicator (0 or 1) for the clock
197 * @name: name of the clock (for printk)
198 *
199 * Wait for a module to leave idle, where its idle-status register is
200 * not inside the CM module. Returns 1 if the module left idle
201 * promptly, or 0 if the module did not leave idle before the timeout
202 * elapsed. XXX Deprecated - should be moved into drivers for the
203 * individual IP block that the IDLEST register exists in.
204 */
205static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
206 u32 mask, u8 idlest, const char *name)
207{
208 int i = 0, ena = 0;
209
210 ena = (idlest) ? 0 : mask;
211
212 omap_test_timeout(((omap2_clk_readl(clk, reg) & mask) == ena),
213 MAX_MODULE_ENABLE_WAIT, i);
214
215 if (i < MAX_MODULE_ENABLE_WAIT)
216 pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
217 name, i);
218 else
219 pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
220 name, MAX_MODULE_ENABLE_WAIT);
221
222 return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
223};
224
225/**
226 * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
227 * @clk: struct clk * belonging to the module
228 *
229 * If the necessary clocks for the OMAP hardware IP block that
230 * corresponds to clock @clk are enabled, then wait for the module to
231 * indicate readiness (i.e., to leave IDLE). This code does not
232 * belong in the clock code and will be moved in the medium term to
233 * module-dependent code. No return value.
234 */
235static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
236{
237 void __iomem *companion_reg, *idlest_reg;
238 u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
239 s16 prcm_mod;
240 int r;
241
242 /* Not all modules have multiple clocks that their IDLEST depends on */
243 if (clk->ops->find_companion) {
244 clk->ops->find_companion(clk, &companion_reg, &other_bit);
245 if (!(omap2_clk_readl(clk, companion_reg) & (1 << other_bit)))
246 return;
247 }
248
249 clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
250 r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
251 if (r) {
252 /* IDLEST register not in the CM module */
253 _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
254 idlest_val, __clk_get_name(clk->hw.clk));
255 } else {
256 omap_cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
257 idlest_bit);
258 };
259}
260
261/* Public functions */ 82/* Public functions */
262 83
263/** 84/**
@@ -290,279 +111,6 @@ void omap2_init_clk_clkdm(struct clk_hw *hw)
290 } 111 }
291} 112}
292 113
293/**
294 * omap2_clk_disable_clkdm_control - disable clkdm control on clk enable/disable
295 *
296 * Prevent the OMAP clock code from calling into the clockdomain code
297 * when a hardware clock in that clockdomain is enabled or disabled.
298 * Intended to be called at init time from omap*_clk_init(). No
299 * return value.
300 */
301void __init omap2_clk_disable_clkdm_control(void)
302{
303 clkdm_control = false;
304}
305
306/**
307 * omap2_clk_dflt_find_companion - find companion clock to @clk
308 * @clk: struct clk * to find the companion clock of
309 * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
310 * @other_bit: u8 ** to return the companion clock bit shift in
311 *
312 * Note: We don't need special code here for INVERT_ENABLE for the
313 * time being since INVERT_ENABLE only applies to clocks enabled by
314 * CM_CLKEN_PLL
315 *
316 * Convert CM_ICLKEN* <-> CM_FCLKEN*. This conversion assumes it's
317 * just a matter of XORing the bits.
318 *
319 * Some clocks don't have companion clocks. For example, modules with
320 * only an interface clock (such as MAILBOXES) don't have a companion
321 * clock. Right now, this code relies on the hardware exporting a bit
322 * in the correct companion register that indicates that the
323 * nonexistent 'companion clock' is active. Future patches will
324 * associate this type of code with per-module data structures to
325 * avoid this issue, and remove the casts. No return value.
326 */
327void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
328 void __iomem **other_reg, u8 *other_bit)
329{
330 u32 r;
331
332 /*
333 * Convert CM_ICLKEN* <-> CM_FCLKEN*. This conversion assumes
334 * it's just a matter of XORing the bits.
335 */
336 r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
337
338 *other_reg = (__force void __iomem *)r;
339 *other_bit = clk->enable_bit;
340}
341
342/**
343 * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
344 * @clk: struct clk * to find IDLEST info for
345 * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
346 * @idlest_bit: u8 * to return the CM_IDLEST bit shift in
347 * @idlest_val: u8 * to return the idle status indicator
348 *
349 * Return the CM_IDLEST register address and bit shift corresponding
350 * to the module that "owns" this clock. This default code assumes
351 * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
352 * the IDLEST register address ID corresponds to the CM_*CLKEN
353 * register address ID (e.g., that CM_FCLKEN2 corresponds to
354 * CM_IDLEST2). This is not true for all modules. No return value.
355 */
356void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
357 void __iomem **idlest_reg, u8 *idlest_bit, u8 *idlest_val)
358{
359 u32 r;
360
361 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
362 *idlest_reg = (__force void __iomem *)r;
363 *idlest_bit = clk->enable_bit;
364
365 /*
366 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
367 * 34xx reverses this, just to keep us on our toes
368 * AM35xx uses both, depending on the module.
369 */
370 *idlest_val = ti_clk_features.cm_idlest_val;
371}
372
373/**
374 * omap2_dflt_clk_enable - enable a clock in the hardware
375 * @hw: struct clk_hw * of the clock to enable
376 *
377 * Enable the clock @hw in the hardware. We first call into the OMAP
378 * clockdomain code to "enable" the corresponding clockdomain if this
379 * is the first enabled user of the clockdomain. Then program the
380 * hardware to enable the clock. Then wait for the IP block that uses
381 * this clock to leave idle (if applicable). Returns the error value
382 * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
383 * if @hw has a null clock enable_reg, or zero upon success.
384 */
385int omap2_dflt_clk_enable(struct clk_hw *hw)
386{
387 struct clk_hw_omap *clk;
388 u32 v;
389 int ret = 0;
390
391 clk = to_clk_hw_omap(hw);
392
393 if (clkdm_control && clk->clkdm) {
394 ret = clkdm_clk_enable(clk->clkdm, hw->clk);
395 if (ret) {
396 WARN(1, "%s: could not enable %s's clockdomain %s: %d\n",
397 __func__, __clk_get_name(hw->clk),
398 clk->clkdm->name, ret);
399 return ret;
400 }
401 }
402
403 if (unlikely(clk->enable_reg == NULL)) {
404 pr_err("%s: %s missing enable_reg\n", __func__,
405 __clk_get_name(hw->clk));
406 ret = -EINVAL;
407 goto err;
408 }
409
410 /* FIXME should not have INVERT_ENABLE bit here */
411 v = omap2_clk_readl(clk, clk->enable_reg);
412 if (clk->flags & INVERT_ENABLE)
413 v &= ~(1 << clk->enable_bit);
414 else
415 v |= (1 << clk->enable_bit);
416 omap2_clk_writel(v, clk, clk->enable_reg);
417 v = omap2_clk_readl(clk, clk->enable_reg); /* OCP barrier */
418
419 if (clk->ops && clk->ops->find_idlest)
420 _omap2_module_wait_ready(clk);
421
422 return 0;
423
424err:
425 if (clkdm_control && clk->clkdm)
426 clkdm_clk_disable(clk->clkdm, hw->clk);
427 return ret;
428}
429
430/**
431 * omap2_dflt_clk_disable - disable a clock in the hardware
432 * @hw: struct clk_hw * of the clock to disable
433 *
434 * Disable the clock @hw in the hardware, and call into the OMAP
435 * clockdomain code to "disable" the corresponding clockdomain if all
436 * clocks/hwmods in that clockdomain are now disabled. No return
437 * value.
438 */
439void omap2_dflt_clk_disable(struct clk_hw *hw)
440{
441 struct clk_hw_omap *clk;
442 u32 v;
443
444 clk = to_clk_hw_omap(hw);
445 if (!clk->enable_reg) {
446 /*
447 * 'independent' here refers to a clock which is not
448 * controlled by its parent.
449 */
450 pr_err("%s: independent clock %s has no enable_reg\n",
451 __func__, __clk_get_name(hw->clk));
452 return;
453 }
454
455 v = omap2_clk_readl(clk, clk->enable_reg);
456 if (clk->flags & INVERT_ENABLE)
457 v |= (1 << clk->enable_bit);
458 else
459 v &= ~(1 << clk->enable_bit);
460 omap2_clk_writel(v, clk, clk->enable_reg);
461 /* No OCP barrier needed here since it is a disable operation */
462
463 if (clkdm_control && clk->clkdm)
464 clkdm_clk_disable(clk->clkdm, hw->clk);
465}
466
467/**
468 * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
469 * @hw: struct clk_hw * of the clock being enabled
470 *
471 * Increment the usecount of the clockdomain of the clock pointed to
472 * by @hw; if the usecount is 1, the clockdomain will be "enabled."
473 * Only needed for clocks that don't use omap2_dflt_clk_enable() as
474 * their enable function pointer. Passes along the return value of
475 * clkdm_clk_enable(), -EINVAL if @hw is not associated with a
476 * clockdomain, or 0 if clock framework-based clockdomain control is
477 * not implemented.
478 */
479int omap2_clkops_enable_clkdm(struct clk_hw *hw)
480{
481 struct clk_hw_omap *clk;
482 int ret = 0;
483
484 clk = to_clk_hw_omap(hw);
485
486 if (unlikely(!clk->clkdm)) {
487 pr_err("%s: %s: no clkdm set ?!\n", __func__,
488 __clk_get_name(hw->clk));
489 return -EINVAL;
490 }
491
492 if (unlikely(clk->enable_reg))
493 pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
494 __clk_get_name(hw->clk));
495
496 if (!clkdm_control) {
497 pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
498 __func__, __clk_get_name(hw->clk));
499 return 0;
500 }
501
502 ret = clkdm_clk_enable(clk->clkdm, hw->clk);
503 WARN(ret, "%s: could not enable %s's clockdomain %s: %d\n",
504 __func__, __clk_get_name(hw->clk), clk->clkdm->name, ret);
505
506 return ret;
507}
508
509/**
510 * omap2_clkops_disable_clkdm - decrement usecount on clkdm of @hw
511 * @hw: struct clk_hw * of the clock being disabled
512 *
513 * Decrement the usecount of the clockdomain of the clock pointed to
514 * by @hw; if the usecount is 0, the clockdomain will be "disabled."
515 * Only needed for clocks that don't use omap2_dflt_clk_disable() as their
516 * disable function pointer. No return value.
517 */
518void omap2_clkops_disable_clkdm(struct clk_hw *hw)
519{
520 struct clk_hw_omap *clk;
521
522 clk = to_clk_hw_omap(hw);
523
524 if (unlikely(!clk->clkdm)) {
525 pr_err("%s: %s: no clkdm set ?!\n", __func__,
526 __clk_get_name(hw->clk));
527 return;
528 }
529
530 if (unlikely(clk->enable_reg))
531 pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
532 __clk_get_name(hw->clk));
533
534 if (!clkdm_control) {
535 pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
536 __func__, __clk_get_name(hw->clk));
537 return;
538 }
539
540 clkdm_clk_disable(clk->clkdm, hw->clk);
541}
542
543/**
544 * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
545 * @hw: struct clk_hw * to check
546 *
547 * Return 1 if the clock represented by @hw is enabled in the
548 * hardware, or 0 otherwise. Intended for use in the struct
549 * clk_ops.is_enabled function pointer.
550 */
551int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
552{
553 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
554 u32 v;
555
556 v = omap2_clk_readl(clk, clk->enable_reg);
557
558 if (clk->flags & INVERT_ENABLE)
559 v ^= BIT(clk->enable_bit);
560
561 v &= BIT(clk->enable_bit);
562
563 return v ? 1 : 0;
564}
565
566static int __initdata mpurate; 114static int __initdata mpurate;
567 115
568/* 116/*
@@ -584,178 +132,6 @@ static int __init omap_clk_setup(char *str)
584__setup("mpurate=", omap_clk_setup); 132__setup("mpurate=", omap_clk_setup);
585 133
586/** 134/**
587 * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
588 * @clk: struct clk * to initialize
589 *
590 * Add an OMAP clock @clk to the internal list of OMAP clocks. Used
591 * temporarily for autoidle handling, until this support can be
592 * integrated into the common clock framework code in some way. No
593 * return value.
594 */
595void omap2_init_clk_hw_omap_clocks(struct clk *clk)
596{
597 struct clk_hw_omap *c;
598
599 if (__clk_get_flags(clk) & CLK_IS_BASIC)
600 return;
601
602 c = to_clk_hw_omap(__clk_get_hw(clk));
603 list_add(&c->node, &clk_hw_omap_clocks);
604}
605
606/**
607 * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
608 * support it
609 *
610 * Enable clock autoidle on all OMAP clocks that have allow_idle
611 * function pointers associated with them. This function is intended
612 * to be temporary until support for this is added to the common clock
613 * code. Returns 0.
614 */
615int omap2_clk_enable_autoidle_all(void)
616{
617 struct clk_hw_omap *c;
618
619 list_for_each_entry(c, &clk_hw_omap_clocks, node)
620 if (c->ops && c->ops->allow_idle)
621 c->ops->allow_idle(c);
622
623 of_ti_clk_allow_autoidle_all();
624
625 return 0;
626}
627
628/**
629 * omap2_clk_disable_autoidle_all - disable autoidle on all OMAP clocks that
630 * support it
631 *
632 * Disable clock autoidle on all OMAP clocks that have allow_idle
633 * function pointers associated with them. This function is intended
634 * to be temporary until support for this is added to the common clock
635 * code. Returns 0.
636 */
637int omap2_clk_disable_autoidle_all(void)
638{
639 struct clk_hw_omap *c;
640
641 list_for_each_entry(c, &clk_hw_omap_clocks, node)
642 if (c->ops && c->ops->deny_idle)
643 c->ops->deny_idle(c);
644
645 of_ti_clk_deny_autoidle_all();
646
647 return 0;
648}
649
650/**
651 * omap2_clk_deny_idle - disable autoidle on an OMAP clock
652 * @clk: struct clk * to disable autoidle for
653 *
654 * Disable autoidle on an OMAP clock.
655 */
656int omap2_clk_deny_idle(struct clk *clk)
657{
658 struct clk_hw_omap *c;
659
660 if (__clk_get_flags(clk) & CLK_IS_BASIC)
661 return -EINVAL;
662
663 c = to_clk_hw_omap(__clk_get_hw(clk));
664 if (c->ops && c->ops->deny_idle)
665 c->ops->deny_idle(c);
666 return 0;
667}
668
669/**
670 * omap2_clk_allow_idle - enable autoidle on an OMAP clock
671 * @clk: struct clk * to enable autoidle for
672 *
673 * Enable autoidle on an OMAP clock.
674 */
675int omap2_clk_allow_idle(struct clk *clk)
676{
677 struct clk_hw_omap *c;
678
679 if (__clk_get_flags(clk) & CLK_IS_BASIC)
680 return -EINVAL;
681
682 c = to_clk_hw_omap(__clk_get_hw(clk));
683 if (c->ops && c->ops->allow_idle)
684 c->ops->allow_idle(c);
685 return 0;
686}
687
688/**
689 * omap2_clk_enable_init_clocks - prepare & enable a list of clocks
690 * @clk_names: ptr to an array of strings of clock names to enable
691 * @num_clocks: number of clock names in @clk_names
692 *
693 * Prepare and enable a list of clocks, named by @clk_names. No
694 * return value. XXX Deprecated; only needed until these clocks are
695 * properly claimed and enabled by the drivers or core code that uses
696 * them. XXX What code disables & calls clk_put on these clocks?
697 */
698void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
699{
700 struct clk *init_clk;
701 int i;
702
703 for (i = 0; i < num_clocks; i++) {
704 init_clk = clk_get(NULL, clk_names[i]);
705 if (WARN(IS_ERR(init_clk), "could not find init clock %s\n",
706 clk_names[i]))
707 continue;
708 clk_prepare_enable(init_clk);
709 }
710}
711
712const struct clk_hw_omap_ops clkhwops_wait = {
713 .find_idlest = omap2_clk_dflt_find_idlest,
714 .find_companion = omap2_clk_dflt_find_companion,
715};
716
717/**
718 * omap2_clk_switch_mpurate_at_boot - switch ARM MPU rate by boot-time argument
719 * @mpurate_ck_name: clk name of the clock to change rate
720 *
721 * Change the ARM MPU clock rate to the rate specified on the command
722 * line, if one was specified. @mpurate_ck_name should be
723 * "virt_prcm_set" on OMAP2xxx and "dpll1_ck" on OMAP34xx/OMAP36xx.
724 * XXX Does not handle voltage scaling - on OMAP2xxx this is currently
725 * handled by the virt_prcm_set clock, but this should be handled by
726 * the OPP layer. XXX This is intended to be handled by the OPP layer
727 * code in the near future and should be removed from the clock code.
728 * Returns -EINVAL if 'mpurate' is zero or if clk_set_rate() rejects
729 * the rate, -ENOENT if the struct clk referred to by @mpurate_ck_name
730 * cannot be found, or 0 upon success.
731 */
732int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
733{
734 struct clk *mpurate_ck;
735 int r;
736
737 if (!mpurate)
738 return -EINVAL;
739
740 mpurate_ck = clk_get(NULL, mpurate_ck_name);
741 if (WARN(IS_ERR(mpurate_ck), "Failed to get %s.\n", mpurate_ck_name))
742 return -ENOENT;
743
744 r = clk_set_rate(mpurate_ck, mpurate);
745 if (r < 0) {
746 WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
747 mpurate_ck_name, mpurate, r);
748 clk_put(mpurate_ck);
749 return -EINVAL;
750 }
751
752 calibrate_delay();
753 clk_put(mpurate_ck);
754
755 return 0;
756}
757
758/**
759 * omap2_clk_print_new_rates - print summary of current clock tree rates 135 * omap2_clk_print_new_rates - print summary of current clock tree rates
760 * @hfclkin_ck_name: clk name for the off-chip HF oscillator 136 * @hfclkin_ck_name: clk name for the off-chip HF oscillator
761 * @core_ck_name: clk name for the on-chip CORE_CLK 137 * @core_ck_name: clk name for the on-chip CORE_CLK
@@ -801,29 +177,30 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
801 */ 177 */
802void __init ti_clk_init_features(void) 178void __init ti_clk_init_features(void)
803{ 179{
180 struct ti_clk_features features = { 0 };
804 /* Fint setup for DPLLs */ 181 /* Fint setup for DPLLs */
805 if (cpu_is_omap3430()) { 182 if (cpu_is_omap3430()) {
806 ti_clk_features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN; 183 features.fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
807 ti_clk_features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX; 184 features.fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
808 ti_clk_features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX; 185 features.fint_band1_max = OMAP3430_DPLL_FINT_BAND1_MAX;
809 ti_clk_features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN; 186 features.fint_band2_min = OMAP3430_DPLL_FINT_BAND2_MIN;
810 } else { 187 } else {
811 ti_clk_features.fint_min = OMAP3PLUS_DPLL_FINT_MIN; 188 features.fint_min = OMAP3PLUS_DPLL_FINT_MIN;
812 ti_clk_features.fint_max = OMAP3PLUS_DPLL_FINT_MAX; 189 features.fint_max = OMAP3PLUS_DPLL_FINT_MAX;
813 } 190 }
814 191
815 /* Bypass value setup for DPLLs */ 192 /* Bypass value setup for DPLLs */
816 if (cpu_is_omap24xx()) { 193 if (cpu_is_omap24xx()) {
817 ti_clk_features.dpll_bypass_vals |= 194 features.dpll_bypass_vals |=
818 (1 << OMAP2XXX_EN_DPLL_LPBYPASS) | 195 (1 << OMAP2XXX_EN_DPLL_LPBYPASS) |
819 (1 << OMAP2XXX_EN_DPLL_FRBYPASS); 196 (1 << OMAP2XXX_EN_DPLL_FRBYPASS);
820 } else if (cpu_is_omap34xx()) { 197 } else if (cpu_is_omap34xx()) {
821 ti_clk_features.dpll_bypass_vals |= 198 features.dpll_bypass_vals |=
822 (1 << OMAP3XXX_EN_DPLL_LPBYPASS) | 199 (1 << OMAP3XXX_EN_DPLL_LPBYPASS) |
823 (1 << OMAP3XXX_EN_DPLL_FRBYPASS); 200 (1 << OMAP3XXX_EN_DPLL_FRBYPASS);
824 } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx() || 201 } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx() ||
825 soc_is_omap54xx() || soc_is_dra7xx()) { 202 soc_is_omap54xx() || soc_is_dra7xx()) {
826 ti_clk_features.dpll_bypass_vals |= 203 features.dpll_bypass_vals |=
827 (1 << OMAP4XXX_EN_DPLL_LPBYPASS) | 204 (1 << OMAP4XXX_EN_DPLL_LPBYPASS) |
828 (1 << OMAP4XXX_EN_DPLL_FRBYPASS) | 205 (1 << OMAP4XXX_EN_DPLL_FRBYPASS) |
829 (1 << OMAP4XXX_EN_DPLL_MNBYPASS); 206 (1 << OMAP4XXX_EN_DPLL_MNBYPASS);
@@ -831,7 +208,7 @@ void __init ti_clk_init_features(void)
831 208
832 /* Jitter correction only available on OMAP343X */ 209 /* Jitter correction only available on OMAP343X */
833 if (cpu_is_omap343x()) 210 if (cpu_is_omap343x())
834 ti_clk_features.flags |= TI_CLK_DPLL_HAS_FREQSEL; 211 features.flags |= TI_CLK_DPLL_HAS_FREQSEL;
835 212
836 /* Idlest value for interface clocks. 213 /* Idlest value for interface clocks.
837 * 24xx uses 0 to indicate not ready, and 1 to indicate ready. 214 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
@@ -839,11 +216,13 @@ void __init ti_clk_init_features(void)
839 * AM35xx uses both, depending on the module. 216 * AM35xx uses both, depending on the module.
840 */ 217 */
841 if (cpu_is_omap24xx()) 218 if (cpu_is_omap24xx())
842 ti_clk_features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL; 219 features.cm_idlest_val = OMAP24XX_CM_IDLEST_VAL;
843 else if (cpu_is_omap34xx()) 220 else if (cpu_is_omap34xx())
844 ti_clk_features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL; 221 features.cm_idlest_val = OMAP34XX_CM_IDLEST_VAL;
845 222
846 /* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */ 223 /* On OMAP3430 ES1.0, DPLL4 can't be re-programmed */
847 if (omap_rev() == OMAP3430_REV_ES1_0) 224 if (omap_rev() == OMAP3430_REV_ES1_0)
848 ti_clk_features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM; 225 features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
226
227 ti_clk_setup_features(&features);
849} 228}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 652ed0ab86ec..67da640ba1c7 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -23,90 +23,6 @@
23#include <linux/clk-provider.h> 23#include <linux/clk-provider.h>
24#include <linux/clk/ti.h> 24#include <linux/clk/ti.h>
25 25
26struct omap_clk {
27 u16 cpu;
28 struct clk_lookup lk;
29};
30
31#define CLK(dev, con, ck) \
32 { \
33 .lk = { \
34 .dev_id = dev, \
35 .con_id = con, \
36 .clk = ck, \
37 }, \
38 }
39
40struct clockdomain;
41
42#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name) \
43 static struct clk_core _name##_core = { \
44 .name = #_name, \
45 .hw = &_name##_hw.hw, \
46 .parent_names = _parent_array_name, \
47 .num_parents = ARRAY_SIZE(_parent_array_name), \
48 .ops = &_clkops_name, \
49 }; \
50 static struct clk _name = { \
51 .core = &_name##_core, \
52 };
53
54#define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name, \
55 _clkops_name, _flags) \
56 static struct clk_core _name##_core = { \
57 .name = #_name, \
58 .hw = &_name##_hw.hw, \
59 .parent_names = _parent_array_name, \
60 .num_parents = ARRAY_SIZE(_parent_array_name), \
61 .ops = &_clkops_name, \
62 .flags = _flags, \
63 }; \
64 static struct clk _name = { \
65 .core = &_name##_core, \
66 };
67
68#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name) \
69 static struct clk_hw_omap _name##_hw = { \
70 .hw = { \
71 .clk = &_name, \
72 }, \
73 .clkdm_name = _clkdm_name, \
74 };
75
76#define DEFINE_CLK_OMAP_MUX(_name, _clkdm_name, _clksel, \
77 _clksel_reg, _clksel_mask, \
78 _parent_names, _ops) \
79 static struct clk _name; \
80 static struct clk_hw_omap _name##_hw = { \
81 .hw = { \
82 .clk = &_name, \
83 }, \
84 .clksel = _clksel, \
85 .clksel_reg = _clksel_reg, \
86 .clksel_mask = _clksel_mask, \
87 .clkdm_name = _clkdm_name, \
88 }; \
89 DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
90
91#define DEFINE_CLK_OMAP_MUX_GATE(_name, _clkdm_name, _clksel, \
92 _clksel_reg, _clksel_mask, \
93 _enable_reg, _enable_bit, \
94 _hwops, _parent_names, _ops) \
95 static struct clk _name; \
96 static struct clk_hw_omap _name##_hw = { \
97 .hw = { \
98 .clk = &_name, \
99 }, \
100 .ops = _hwops, \
101 .enable_reg = _enable_reg, \
102 .enable_bit = _enable_bit, \
103 .clksel = _clksel, \
104 .clksel_reg = _clksel_reg, \
105 .clksel_mask = _clksel_mask, \
106 .clkdm_name = _clkdm_name, \
107 }; \
108 DEFINE_STRUCT_CLK(_name, _parent_names, _ops);
109
110/* struct clksel_rate.flags possibilities */ 26/* struct clksel_rate.flags possibilities */
111#define RATE_IN_242X (1 << 0) 27#define RATE_IN_242X (1 << 0)
112#define RATE_IN_243X (1 << 1) 28#define RATE_IN_243X (1 << 1)
@@ -127,38 +43,6 @@ struct clockdomain;
127/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */ 43/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
128#define RATE_IN_3430ES2PLUS_36XX (RATE_IN_3430ES2PLUS | RATE_IN_36XX) 44#define RATE_IN_3430ES2PLUS_36XX (RATE_IN_3430ES2PLUS | RATE_IN_36XX)
129 45
130
131/**
132 * struct clksel_rate - register bitfield values corresponding to clk divisors
133 * @val: register bitfield value (shifted to bit 0)
134 * @div: clock divisor corresponding to @val
135 * @flags: (see "struct clksel_rate.flags possibilities" above)
136 *
137 * @val should match the value of a read from struct clk.clksel_reg
138 * AND'ed with struct clk.clksel_mask, shifted right to bit 0.
139 *
140 * @div is the divisor that should be applied to the parent clock's rate
141 * to produce the current clock's rate.
142 */
143struct clksel_rate {
144 u32 val;
145 u8 div;
146 u16 flags;
147};
148
149/**
150 * struct clksel - available parent clocks, and a pointer to their divisors
151 * @parent: struct clk * to a possible parent clock
152 * @rates: available divisors for this parent clock
153 *
154 * A struct clksel is always associated with one or more struct clks
155 * and one or more struct clksel_rates.
156 */
157struct clksel {
158 struct clk *parent;
159 const struct clksel_rate *rates;
160};
161
162/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */ 46/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
163#define CORE_CLK_SRC_32K 0x0 47#define CORE_CLK_SRC_32K 0x0
164#define CORE_CLK_SRC_DPLL 0x1 48#define CORE_CLK_SRC_DPLL 0x1
@@ -180,105 +64,18 @@ struct clksel {
180#define OMAP4XXX_EN_DPLL_FRBYPASS 0x6 64#define OMAP4XXX_EN_DPLL_FRBYPASS 0x6
181#define OMAP4XXX_EN_DPLL_LOCKED 0x7 65#define OMAP4XXX_EN_DPLL_LOCKED 0x7
182 66
183u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
184void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
185void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
186void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk);
187void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk);
188
189void __init omap2_clk_disable_clkdm_control(void);
190
191/* clkt_clksel.c public functions */
192u32 omap2_clksel_round_rate_div(struct clk_hw_omap *clk,
193 unsigned long target_rate,
194 u32 *new_div);
195u8 omap2_clksel_find_parent_index(struct clk_hw *hw);
196unsigned long omap2_clksel_recalc(struct clk_hw *hw, unsigned long parent_rate);
197long omap2_clksel_round_rate(struct clk_hw *hw, unsigned long target_rate,
198 unsigned long *parent_rate);
199int omap2_clksel_set_rate(struct clk_hw *hw, unsigned long rate,
200 unsigned long parent_rate);
201int omap2_clksel_set_parent(struct clk_hw *hw, u8 field_val);
202
203/* clkt_iclk.c public functions */
204extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
205extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
206
207unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
208
209void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
210 void __iomem **other_reg,
211 u8 *other_bit);
212void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
213 void __iomem **idlest_reg,
214 u8 *idlest_bit, u8 *idlest_val);
215int omap2_clk_enable_autoidle_all(void);
216int omap2_clk_allow_idle(struct clk *clk);
217int omap2_clk_deny_idle(struct clk *clk);
218int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
219void omap2_clk_print_new_rates(const char *hfclkin_ck_name, 67void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
220 const char *core_ck_name, 68 const char *core_ck_name,
221 const char *mpu_ck_name); 69 const char *mpu_ck_name);
222 70
223u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg);
224void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg);
225
226extern u16 cpu_mask; 71extern u16 cpu_mask;
227 72
228/*
229 * Clock features setup. Used instead of CPU type checks.
230 */
231struct ti_clk_features {
232 u32 flags;
233 long fint_min;
234 long fint_max;
235 long fint_band1_max;
236 long fint_band2_min;
237 u8 dpll_bypass_vals;
238 u8 cm_idlest_val;
239};
240
241#define TI_CLK_DPLL_HAS_FREQSEL (1 << 0)
242#define TI_CLK_DPLL4_DENY_REPROGRAM (1 << 1)
243
244extern struct ti_clk_features ti_clk_features;
245
246extern const struct clkops clkops_omap2_dflt_wait; 73extern const struct clkops clkops_omap2_dflt_wait;
247extern const struct clkops clkops_omap2_dflt; 74extern const struct clkops clkops_omap2_dflt;
248 75
249extern struct clk_functions omap2_clk_functions; 76extern struct clk_functions omap2_clk_functions;
250 77
251extern const struct clksel_rate gpt_32k_rates[]; 78int __init omap2_clk_setup_ll_ops(void);
252extern const struct clksel_rate gpt_sys_rates[];
253extern const struct clksel_rate gfx_l3_rates[];
254extern const struct clksel_rate dsp_ick_rates[];
255
256extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
257extern const struct clk_hw_omap_ops clkhwops_wait;
258extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait;
259extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
260extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
261extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
262extern const struct clk_hw_omap_ops clkhwops_apll54;
263extern const struct clk_hw_omap_ops clkhwops_apll96;
264
265/* clksel_rate blocks shared between OMAP44xx and AM33xx */
266extern const struct clksel_rate div_1_0_rates[];
267extern const struct clksel_rate div3_1to4_rates[];
268extern const struct clksel_rate div_1_1_rates[];
269extern const struct clksel_rate div_1_2_rates[];
270extern const struct clksel_rate div_1_3_rates[];
271extern const struct clksel_rate div_1_4_rates[];
272extern const struct clksel_rate div31_1to31_rates[];
273
274extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
275extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
276
277struct regmap;
278
279int __init omap2_clk_provider_init(struct device_node *np, int index,
280 struct regmap *syscon, void __iomem *mem);
281void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem);
282 79
283void __init ti_clk_init_features(void); 80void __init ti_clk_init_features(void);
284#endif 81#endif
diff --git a/arch/arm/mach-omap2/clock2430.c b/arch/arm/mach-omap2/clock2430.c
deleted file mode 100644
index cef0c8d1de52..000000000000
--- a/arch/arm/mach-omap2/clock2430.c
+++ /dev/null
@@ -1,57 +0,0 @@
1/*
2 * clock2430.c - OMAP2430-specific clock integration code
3 *
4 * Copyright (C) 2005-2008 Texas Instruments, Inc.
5 * Copyright (C) 2004-2010 Nokia Corporation
6 *
7 * Contacts:
8 * Richard Woodruff <r-woodruff2@ti.com>
9 * Paul Walmsley
10 *
11 * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
12 * Gordon McNutt and RidgeRun, Inc.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18#undef DEBUG
19
20#include <linux/kernel.h>
21#include <linux/clk.h>
22#include <linux/io.h>
23
24#include "soc.h"
25#include "iomap.h"
26#include "clock.h"
27#include "clock2xxx.h"
28#include "cm2xxx.h"
29#include "cm-regbits-24xx.h"
30
31/**
32 * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
33 * @clk: struct clk * being enabled
34 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
35 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
36 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
37 *
38 * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
39 * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE. This custom function
40 * passes back the correct CM_IDLEST register address for I2CHS
41 * modules. No return value.
42 */
43static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
44 void __iomem **idlest_reg,
45 u8 *idlest_bit,
46 u8 *idlest_val)
47{
48 *idlest_reg = OMAP2430_CM_REGADDR(CORE_MOD, CM_IDLEST);
49 *idlest_bit = clk->enable_bit;
50 *idlest_val = OMAP24XX_CM_IDLEST_VAL;
51}
52
53/* 2430 I2CHS has non-standard IDLEST register */
54const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
55 .find_idlest = omap2430_clk_i2chs_find_idlest,
56 .find_companion = omap2_clk_dflt_find_companion,
57};
diff --git a/arch/arm/mach-omap2/clock2xxx.c b/arch/arm/mach-omap2/clock2xxx.c
deleted file mode 100644
index b870f6a9e283..000000000000
--- a/arch/arm/mach-omap2/clock2xxx.c
+++ /dev/null
@@ -1,57 +0,0 @@
1/*
2 * clock2xxx.c - OMAP2xxx-specific clock integration code
3 *
4 * Copyright (C) 2005-2008 Texas Instruments, Inc.
5 * Copyright (C) 2004-2010 Nokia Corporation
6 *
7 * Contacts:
8 * Richard Woodruff <r-woodruff2@ti.com>
9 * Paul Walmsley
10 *
11 * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
12 * Gordon McNutt and RidgeRun, Inc.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18#undef DEBUG
19
20#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/clk.h>
23#include <linux/io.h>
24
25#include "soc.h"
26#include "clock.h"
27#include "clock2xxx.h"
28#include "cm.h"
29#include "cm-regbits-24xx.h"
30
31struct clk_hw *dclk_hw;
32/*
33 * Omap24xx specific clock functions
34 */
35
36/*
37 * Switch the MPU rate if specified on cmdline. We cannot do this
38 * early until cmdline is parsed. XXX This should be removed from the
39 * clock code and handled by the OPP layer code in the near future.
40 */
41static int __init omap2xxx_clk_arch_init(void)
42{
43 int ret;
44
45 if (!cpu_is_omap24xx())
46 return 0;
47
48 ret = omap2_clk_switch_mpurate_at_boot("virt_prcm_set");
49 if (!ret)
50 omap2_clk_print_new_rates("sys_ck", "dpll_ck", "mpu_ck");
51
52 return ret;
53}
54
55omap_arch_initcall(omap2xxx_clk_arch_init);
56
57
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
deleted file mode 100644
index 4596468e50ab..000000000000
--- a/arch/arm/mach-omap2/clock34xx.c
+++ /dev/null
@@ -1,138 +0,0 @@
1/*
2 * OMAP3-specific clock framework functions
3 *
4 * Copyright (C) 2007-2008 Texas Instruments, Inc.
5 * Copyright (C) 2007-2011 Nokia Corporation
6 *
7 * Paul Walmsley
8 * Jouni Högander
9 *
10 * Parts of this code are based on code written by
11 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
12 * Russell King
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18#undef DEBUG
19
20#include <linux/kernel.h>
21#include <linux/clk.h>
22#include <linux/io.h>
23
24#include "clock.h"
25#include "clock34xx.h"
26#include "cm3xxx.h"
27#include "cm-regbits-34xx.h"
28
29/**
30 * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
31 * @clk: struct clk * being enabled
32 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
33 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
34 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
35 *
36 * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
37 * from the CM_{I,F}CLKEN bit. Pass back the correct info via
38 * @idlest_reg and @idlest_bit. No return value.
39 */
40static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
41 void __iomem **idlest_reg,
42 u8 *idlest_bit,
43 u8 *idlest_val)
44{
45 u32 r;
46
47 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
48 *idlest_reg = (__force void __iomem *)r;
49 *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
50 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
51}
52const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait = {
53 .find_idlest = omap3430es2_clk_ssi_find_idlest,
54 .find_companion = omap2_clk_dflt_find_companion,
55};
56
57const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
58 .allow_idle = omap2_clkt_iclk_allow_idle,
59 .deny_idle = omap2_clkt_iclk_deny_idle,
60 .find_idlest = omap3430es2_clk_ssi_find_idlest,
61 .find_companion = omap2_clk_dflt_find_companion,
62};
63
64/**
65 * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
66 * @clk: struct clk * being enabled
67 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
68 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
69 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
70 *
71 * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
72 * target IDLEST bits. For our purposes, we are concerned with the
73 * target IDLEST bits, which exist at a different bit position than
74 * the *CLKEN bit position for these modules (DSS and USBHOST) (The
75 * default find_idlest code assumes that they are at the same
76 * position.) No return value.
77 */
78static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
79 void __iomem **idlest_reg,
80 u8 *idlest_bit,
81 u8 *idlest_val)
82{
83 u32 r;
84
85 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
86 *idlest_reg = (__force void __iomem *)r;
87 /* USBHOST_IDLE has same shift */
88 *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
89 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
90}
91
92const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
93 .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
94 .find_companion = omap2_clk_dflt_find_companion,
95};
96
97const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
98 .allow_idle = omap2_clkt_iclk_allow_idle,
99 .deny_idle = omap2_clkt_iclk_deny_idle,
100 .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
101 .find_companion = omap2_clk_dflt_find_companion,
102};
103
104/**
105 * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
106 * @clk: struct clk * being enabled
107 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
108 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
109 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
110 *
111 * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
112 * shift from the CM_{I,F}CLKEN bit. Pass back the correct info via
113 * @idlest_reg and @idlest_bit. No return value.
114 */
115static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
116 void __iomem **idlest_reg,
117 u8 *idlest_bit,
118 u8 *idlest_val)
119{
120 u32 r;
121
122 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
123 *idlest_reg = (__force void __iomem *)r;
124 *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
125 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
126}
127
128const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
129 .allow_idle = omap2_clkt_iclk_allow_idle,
130 .deny_idle = omap2_clkt_iclk_deny_idle,
131 .find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
132 .find_companion = omap2_clk_dflt_find_companion,
133};
134
135const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait = {
136 .find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
137 .find_companion = omap2_clk_dflt_find_companion,
138};
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
deleted file mode 100644
index 084ba71b2b31..000000000000
--- a/arch/arm/mach-omap2/clock34xx.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * OMAP34xx clock function prototypes and macros
3 *
4 * Copyright (C) 2007-2010 Texas Instruments, Inc.
5 * Copyright (C) 2007-2011 Nokia Corporation
6 */
7
8#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
9#define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
10
11extern const struct clkops clkops_omap3430es2_ssi_wait;
12extern const struct clkops clkops_omap3430es2_iclk_ssi_wait;
13extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
14extern const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait;
15extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
16extern const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait;
17
18#endif
diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c
deleted file mode 100644
index 4d79ae2c0241..000000000000
--- a/arch/arm/mach-omap2/clock3517.c
+++ /dev/null
@@ -1,118 +0,0 @@
1/*
2 * OMAP3517/3505-specific clock framework functions
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc.
5 * Copyright (C) 2011 Nokia Corporation
6 *
7 * Ranjith Lohithakshan
8 * Paul Walmsley
9 *
10 * Parts of this code are based on code written by
11 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
12 * Russell King
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18#undef DEBUG
19
20#include <linux/kernel.h>
21#include <linux/clk.h>
22#include <linux/io.h>
23
24#include "clock.h"
25#include "clock3517.h"
26#include "cm3xxx.h"
27#include "cm-regbits-34xx.h"
28
29/*
30 * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
31 * in the same register at a bit offset of 0x8. The EN_ACK for ICK is
32 * at an offset of 4 from ICK enable bit.
33 */
34#define AM35XX_IPSS_ICK_MASK 0xF
35#define AM35XX_IPSS_ICK_EN_ACK_OFFSET 0x4
36#define AM35XX_IPSS_ICK_FCK_OFFSET 0x8
37#define AM35XX_IPSS_CLK_IDLEST_VAL 0
38
39/**
40 * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
41 * @clk: struct clk * being enabled
42 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
43 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
44 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
45 *
46 * The interface clocks on AM35xx IPSS reflects the clock idle status
47 * in the enable register itsel at a bit offset of 4 from the enable
48 * bit. A value of 1 indicates that clock is enabled.
49 */
50static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
51 void __iomem **idlest_reg,
52 u8 *idlest_bit,
53 u8 *idlest_val)
54{
55 *idlest_reg = (__force void __iomem *)(clk->enable_reg);
56 *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
57 *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
58}
59
60/**
61 * am35xx_clk_find_companion - find companion clock to @clk
62 * @clk: struct clk * to find the companion clock of
63 * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
64 * @other_bit: u8 ** to return the companion clock bit shift in
65 *
66 * Some clocks don't have companion clocks. For example, modules with
67 * only an interface clock (such as HECC) don't have a companion
68 * clock. Right now, this code relies on the hardware exporting a bit
69 * in the correct companion register that indicates that the
70 * nonexistent 'companion clock' is active. Future patches will
71 * associate this type of code with per-module data structures to
72 * avoid this issue, and remove the casts. No return value.
73 */
74static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
75 void __iomem **other_reg,
76 u8 *other_bit)
77{
78 *other_reg = (__force void __iomem *)(clk->enable_reg);
79 if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
80 *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
81 else
82 *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
83}
84const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
85 .find_idlest = am35xx_clk_find_idlest,
86 .find_companion = am35xx_clk_find_companion,
87};
88
89/**
90 * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
91 * @clk: struct clk * being enabled
92 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
93 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
94 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
95 *
96 * The IPSS target CM_IDLEST bit is at a different shift from the
97 * CM_{I,F}CLKEN bit. Pass back the correct info via @idlest_reg
98 * and @idlest_bit. No return value.
99 */
100static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
101 void __iomem **idlest_reg,
102 u8 *idlest_bit,
103 u8 *idlest_val)
104{
105 u32 r;
106
107 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
108 *idlest_reg = (__force void __iomem *)r;
109 *idlest_bit = AM35XX_ST_IPSS_SHIFT;
110 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
111}
112
113const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
114 .allow_idle = omap2_clkt_iclk_allow_idle,
115 .deny_idle = omap2_clkt_iclk_deny_idle,
116 .find_idlest = am35xx_clk_ipss_find_idlest,
117 .find_companion = omap2_clk_dflt_find_companion,
118};
diff --git a/arch/arm/mach-omap2/clock3517.h b/arch/arm/mach-omap2/clock3517.h
deleted file mode 100644
index ca5e5a64c2e2..000000000000
--- a/arch/arm/mach-omap2/clock3517.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/*
2 * OMAP3517/3505 clock function prototypes and macros
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc.
5 * Copyright (C) 2010 Nokia Corporation
6 */
7
8#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK3517_H
9#define __ARCH_ARM_MACH_OMAP2_CLOCK3517_H
10
11extern const struct clkops clkops_am35xx_ipss_module_wait;
12extern const struct clkops clkops_am35xx_ipss_wait;
13
14#endif
diff --git a/arch/arm/mach-omap2/clock36xx.c b/arch/arm/mach-omap2/clock36xx.c
deleted file mode 100644
index 91ccb962e09e..000000000000
--- a/arch/arm/mach-omap2/clock36xx.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/*
2 * OMAP36xx-specific clkops
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc.
5 * Copyright (C) 2010 Nokia Corporation
6 *
7 * Mike Turquette
8 * Vijaykumar GN
9 * Paul Walmsley
10 *
11 * Parts of this code are based on code written by
12 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu,
13 * Russell King
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation.
18 */
19#undef DEBUG
20
21#include <linux/kernel.h>
22#include <linux/clk.h>
23#include <linux/clk-provider.h>
24#include <linux/io.h>
25
26#include "clock.h"
27#include "clock36xx.h"
28#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
29
30/**
31 * omap36xx_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering
32 * from HSDivider PWRDN problem Implements Errata ID: i556.
33 * @clk: DPLL output struct clk
34 *
35 * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck,
36 * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset
37 * valueafter their respective PWRDN bits are set. Any dummy write
38 * (Any other value different from the Read value) to the
39 * corresponding CM_CLKSEL register will refresh the dividers.
40 */
41int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *clk)
42{
43 struct clk_divider *parent;
44 struct clk_hw *parent_hw;
45 u32 dummy_v, orig_v;
46 struct clk_hw_omap *omap_clk = to_clk_hw_omap(clk);
47 int ret;
48
49 /* Clear PWRDN bit of HSDIVIDER */
50 ret = omap2_dflt_clk_enable(clk);
51
52 parent_hw = __clk_get_hw(__clk_get_parent(clk->clk));
53 parent = to_clk_divider(parent_hw);
54
55 /* Restore the dividers */
56 if (!ret) {
57 orig_v = omap2_clk_readl(omap_clk, parent->reg);
58 dummy_v = orig_v;
59
60 /* Write any other value different from the Read value */
61 dummy_v ^= (1 << parent->shift);
62 omap2_clk_writel(dummy_v, omap_clk, parent->reg);
63
64 /* Write the original divider */
65 omap2_clk_writel(orig_v, omap_clk, parent->reg);
66 }
67
68 return ret;
69}
diff --git a/arch/arm/mach-omap2/clock36xx.h b/arch/arm/mach-omap2/clock36xx.h
deleted file mode 100644
index 945bb7f083e9..000000000000
--- a/arch/arm/mach-omap2/clock36xx.h
+++ /dev/null
@@ -1,13 +0,0 @@
1/*
2 * OMAP36xx clock function prototypes and macros
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc.
5 * Copyright (C) 2010 Nokia Corporation
6 */
7
8#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
9#define __ARCH_ARM_MACH_OMAP2_CLOCK36XX_H
10
11extern int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk_hw *hw);
12
13#endif
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
deleted file mode 100644
index a9e86db5daf9..000000000000
--- a/arch/arm/mach-omap2/clock3xxx.c
+++ /dev/null
@@ -1,135 +0,0 @@
1/*
2 * OMAP3-specific clock framework functions
3 *
4 * Copyright (C) 2007-2008 Texas Instruments, Inc.
5 * Copyright (C) 2007-2010 Nokia Corporation
6 *
7 * Paul Walmsley
8 * Jouni Högander
9 *
10 * Parts of this code are based on code written by
11 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17#undef DEBUG
18
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/clk.h>
22#include <linux/io.h>
23
24#include "soc.h"
25#include "clock.h"
26#include "clock3xxx.h"
27#include "prm2xxx_3xxx.h"
28#include "prm-regbits-34xx.h"
29#include "cm2xxx_3xxx.h"
30#include "cm-regbits-34xx.h"
31
32/*
33 * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
34 * that are sourced by DPLL5, and both of these require this clock
35 * to be at 120 MHz for proper operation.
36 */
37#define DPLL5_FREQ_FOR_USBHOST 120000000
38
39/* needed by omap3_core_dpll_m2_set_rate() */
40struct clk *sdrc_ick_p, *arm_fck_p;
41
42/**
43 * omap3_dpll4_set_rate - set rate for omap3 per-dpll
44 * @hw: clock to change
45 * @rate: target rate for clock
46 * @parent_rate: rate of the parent clock
47 *
48 * Check if the current SoC supports the per-dpll reprogram operation
49 * or not, and then do the rate change if supported. Returns -EINVAL
50 * if not supported, 0 for success, and potential error codes from the
51 * clock rate change.
52 */
53int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
54 unsigned long parent_rate)
55{
56 /*
57 * According to the 12-5 CDP code from TI, "Limitation 2.5"
58 * on 3430ES1 prevents us from changing DPLL multipliers or dividers
59 * on DPLL4.
60 */
61 if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
62 pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
63 return -EINVAL;
64 }
65
66 return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
67}
68
69/**
70 * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
71 * @hw: clock to change
72 * @rate: target rate for clock
73 * @parent_rate: rate of the parent clock
74 * @index: parent index, 0 - reference clock, 1 - bypass clock
75 *
76 * Check if the current SoC support the per-dpll reprogram operation
77 * or not, and then do the rate + parent change if supported. Returns
78 * -EINVAL if not supported, 0 for success, and potential error codes
79 * from the clock rate change.
80 */
81int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
82 unsigned long parent_rate, u8 index)
83{
84 if (ti_clk_features.flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
85 pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
86 return -EINVAL;
87 }
88
89 return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
90 index);
91}
92
93void __init omap3_clk_lock_dpll5(void)
94{
95 struct clk *dpll5_clk;
96 struct clk *dpll5_m2_clk;
97
98 dpll5_clk = clk_get(NULL, "dpll5_ck");
99 clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
100 clk_prepare_enable(dpll5_clk);
101
102 /* Program dpll5_m2_clk divider for no division */
103 dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
104 clk_prepare_enable(dpll5_m2_clk);
105 clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
106
107 clk_disable_unprepare(dpll5_m2_clk);
108 clk_disable_unprepare(dpll5_clk);
109 return;
110}
111
112/* Common clock code */
113
114/*
115 * Switch the MPU rate if specified on cmdline. We cannot do this
116 * early until cmdline is parsed. XXX This should be removed from the
117 * clock code and handled by the OPP layer code in the near future.
118 */
119static int __init omap3xxx_clk_arch_init(void)
120{
121 int ret;
122
123 if (!cpu_is_omap34xx())
124 return 0;
125
126 ret = omap2_clk_switch_mpurate_at_boot("dpll1_ck");
127 if (!ret)
128 omap2_clk_print_new_rates("osc_sys_ck", "core_ck", "arm_fck");
129
130 return ret;
131}
132
133omap_arch_initcall(omap3xxx_clk_arch_init);
134
135
diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h
deleted file mode 100644
index 287a46f78d97..000000000000
--- a/arch/arm/mach-omap2/clock44xx.h
+++ /dev/null
@@ -1,20 +0,0 @@
1/*
2 * OMAP4 clock function prototypes and macros
3 *
4 * Copyright (C) 2009 Texas Instruments, Inc.
5 * Copyright (C) 2010 Nokia Corporation
6 */
7
8#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
9#define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
10
11/*
12 * OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is
13 * set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM
14 * vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters")
15 */
16#define OMAP4430_REGM4XEN_MULT 4
17
18int omap4xxx_clk_init(void);
19
20#endif
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
deleted file mode 100644
index 61b60dfb14ce..000000000000
--- a/arch/arm/mach-omap2/clock_common_data.c
+++ /dev/null
@@ -1,115 +0,0 @@
1/*
2 * linux/arch/arm/mach-omap2/clock_common_data.c
3 *
4 * Copyright (C) 2005-2009 Texas Instruments, Inc.
5 * Copyright (C) 2004-2009 Nokia Corporation
6 *
7 * Contacts:
8 * Richard Woodruff <r-woodruff2@ti.com>
9 * Paul Walmsley
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * This file contains clock data that is common to both the OMAP2xxx and
16 * OMAP3xxx clock definition files.
17 */
18
19#include "clock.h"
20
21/* clksel_rate data common to 24xx/343x */
22const struct clksel_rate gpt_32k_rates[] = {
23 { .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_3XXX },
24 { .div = 0 }
25};
26
27const struct clksel_rate gpt_sys_rates[] = {
28 { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_3XXX },
29 { .div = 0 }
30};
31
32const struct clksel_rate gfx_l3_rates[] = {
33 { .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_3XXX },
34 { .div = 2, .val = 2, .flags = RATE_IN_24XX | RATE_IN_3XXX },
35 { .div = 3, .val = 3, .flags = RATE_IN_243X | RATE_IN_3XXX },
36 { .div = 4, .val = 4, .flags = RATE_IN_243X | RATE_IN_3XXX },
37 { .div = 0 }
38};
39
40const struct clksel_rate dsp_ick_rates[] = {
41 { .div = 1, .val = 1, .flags = RATE_IN_24XX },
42 { .div = 2, .val = 2, .flags = RATE_IN_24XX },
43 { .div = 3, .val = 3, .flags = RATE_IN_243X },
44 { .div = 0 },
45};
46
47
48/* clksel_rate blocks shared between OMAP44xx and AM33xx */
49
50const struct clksel_rate div_1_0_rates[] = {
51 { .div = 1, .val = 0, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
52 { .div = 0 },
53};
54
55const struct clksel_rate div3_1to4_rates[] = {
56 { .div = 1, .val = 0, .flags = RATE_IN_4430 },
57 { .div = 2, .val = 1, .flags = RATE_IN_4430 },
58 { .div = 4, .val = 2, .flags = RATE_IN_4430 },
59 { .div = 0 },
60};
61
62const struct clksel_rate div_1_1_rates[] = {
63 { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
64 { .div = 0 },
65};
66
67const struct clksel_rate div_1_2_rates[] = {
68 { .div = 1, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
69 { .div = 0 },
70};
71
72const struct clksel_rate div_1_3_rates[] = {
73 { .div = 1, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
74 { .div = 0 },
75};
76
77const struct clksel_rate div_1_4_rates[] = {
78 { .div = 1, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
79 { .div = 0 },
80};
81
82const struct clksel_rate div31_1to31_rates[] = {
83 { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
84 { .div = 2, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
85 { .div = 3, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
86 { .div = 4, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
87 { .div = 5, .val = 5, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
88 { .div = 6, .val = 6, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
89 { .div = 7, .val = 7, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
90 { .div = 8, .val = 8, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
91 { .div = 9, .val = 9, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
92 { .div = 10, .val = 10, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
93 { .div = 11, .val = 11, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
94 { .div = 12, .val = 12, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
95 { .div = 13, .val = 13, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
96 { .div = 14, .val = 14, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
97 { .div = 15, .val = 15, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
98 { .div = 16, .val = 16, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
99 { .div = 17, .val = 17, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
100 { .div = 18, .val = 18, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
101 { .div = 19, .val = 19, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
102 { .div = 20, .val = 20, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
103 { .div = 21, .val = 21, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
104 { .div = 22, .val = 22, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
105 { .div = 23, .val = 23, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
106 { .div = 24, .val = 24, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
107 { .div = 25, .val = 25, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
108 { .div = 26, .val = 26, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
109 { .div = 27, .val = 27, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
110 { .div = 28, .val = 28, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
111 { .div = 29, .val = 29, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
112 { .div = 30, .val = 30, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
113 { .div = 31, .val = 31, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
114 { .div = 0 },
115};
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 820dde8b5b04..a253aafbb9a2 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -37,7 +37,6 @@
37#include "clock.h" 37#include "clock.h"
38#include "clock2xxx.h" 38#include "clock2xxx.h"
39#include "clock3xxx.h" 39#include "clock3xxx.h"
40#include "clock44xx.h"
41#include "omap-pm.h" 40#include "omap-pm.h"
42#include "sdrc.h" 41#include "sdrc.h"
43#include "control.h" 42#include "control.h"
@@ -723,6 +722,8 @@ int __init omap_clk_init(void)
723 722
724 ti_clk_init_features(); 723 ti_clk_init_features();
725 724
725 omap2_clk_setup_ll_ops();
726
726 if (of_have_populated_dt()) { 727 if (of_have_populated_dt()) {
727 ret = omap_control_init(); 728 ret = omap_control_init();
728 if (ret) 729 if (ret)
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 105ffd0f5e79..9b93e6904359 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -1,16 +1,19 @@
1obj-y += clk.o autoidle.o clockdomain.o 1obj-y += clk.o autoidle.o clockdomain.o
2clk-common = dpll.o composite.o divider.o gate.o \ 2clk-common = dpll.o composite.o divider.o gate.o \
3 fixed-factor.o mux.o apll.o 3 fixed-factor.o mux.o apll.o \
4obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o 4 clkt_dpll.o clkt_iclk.o clkt_dflt.o
5obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o dpll3xxx.o
5obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-816x.o 6obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-816x.o
6obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o 7obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
7obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o \ 8obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o \
8 clk-3xxx.o 9 clk-3xxx.o dpll3xxx.o
9obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o 10obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o \
10obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o 11 dpll3xxx.o dpll44xx.o
12obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o \
13 dpll3xxx.o dpll44xx.o
11obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o \ 14obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o \
12 clk-dra7-atl.o 15 clk-dra7-atl.o dpll3xxx.o dpll44xx.o
13obj-$(CONFIG_SOC_AM43XX) += $(clk-common) clk-43xx.o 16obj-$(CONFIG_SOC_AM43XX) += $(clk-common) dpll3xxx.o clk-43xx.o
14 17
15ifdef CONFIG_ATAGS 18ifdef CONFIG_ATAGS
16obj-$(CONFIG_ARCH_OMAP3) += clk-3xxx-legacy.o 19obj-$(CONFIG_ARCH_OMAP3) += clk-3xxx-legacy.o
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
index 49baf3831546..594b759f02ee 100644
--- a/drivers/clk/ti/apll.c
+++ b/drivers/clk/ti/apll.c
@@ -27,6 +27,8 @@
27#include <linux/clk/ti.h> 27#include <linux/clk/ti.h>
28#include <linux/delay.h> 28#include <linux/delay.h>
29 29
30#include "clock.h"
31
30#define APLL_FORCE_LOCK 0x1 32#define APLL_FORCE_LOCK 0x1
31#define APLL_AUTO_IDLE 0x2 33#define APLL_AUTO_IDLE 0x2
32#define MAX_APLL_WAIT_TRIES 1000000 34#define MAX_APLL_WAIT_TRIES 1000000
diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c
index e75c64c9e81c..94f0dcd94181 100644
--- a/drivers/clk/ti/autoidle.c
+++ b/drivers/clk/ti/autoidle.c
@@ -22,6 +22,8 @@
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23#include <linux/clk/ti.h> 23#include <linux/clk/ti.h>
24 24
25#include "clock.h"
26
25struct clk_ti_autoidle { 27struct clk_ti_autoidle {
26 void __iomem *reg; 28 void __iomem *reg;
27 u8 shift; 29 u8 shift;
@@ -33,8 +35,47 @@ struct clk_ti_autoidle {
33#define AUTOIDLE_LOW 0x1 35#define AUTOIDLE_LOW 0x1
34 36
35static LIST_HEAD(autoidle_clks); 37static LIST_HEAD(autoidle_clks);
38static LIST_HEAD(clk_hw_omap_clocks);
36 39
37static void ti_allow_autoidle(struct clk_ti_autoidle *clk) 40/**
41 * omap2_clk_deny_idle - disable autoidle on an OMAP clock
42 * @clk: struct clk * to disable autoidle for
43 *
44 * Disable autoidle on an OMAP clock.
45 */
46int omap2_clk_deny_idle(struct clk *clk)
47{
48 struct clk_hw_omap *c;
49
50 if (__clk_get_flags(clk) & CLK_IS_BASIC)
51 return -EINVAL;
52
53 c = to_clk_hw_omap(__clk_get_hw(clk));
54 if (c->ops && c->ops->deny_idle)
55 c->ops->deny_idle(c);
56 return 0;
57}
58
59/**
60 * omap2_clk_allow_idle - enable autoidle on an OMAP clock
61 * @clk: struct clk * to enable autoidle for
62 *
63 * Enable autoidle on an OMAP clock.
64 */
65int omap2_clk_allow_idle(struct clk *clk)
66{
67 struct clk_hw_omap *c;
68
69 if (__clk_get_flags(clk) & CLK_IS_BASIC)
70 return -EINVAL;
71
72 c = to_clk_hw_omap(__clk_get_hw(clk));
73 if (c->ops && c->ops->allow_idle)
74 c->ops->allow_idle(c);
75 return 0;
76}
77
78static void _allow_autoidle(struct clk_ti_autoidle *clk)
38{ 79{
39 u32 val; 80 u32 val;
40 81
@@ -48,7 +89,7 @@ static void ti_allow_autoidle(struct clk_ti_autoidle *clk)
48 ti_clk_ll_ops->clk_writel(val, clk->reg); 89 ti_clk_ll_ops->clk_writel(val, clk->reg);
49} 90}
50 91
51static void ti_deny_autoidle(struct clk_ti_autoidle *clk) 92static void _deny_autoidle(struct clk_ti_autoidle *clk)
52{ 93{
53 u32 val; 94 u32 val;
54 95
@@ -63,31 +104,31 @@ static void ti_deny_autoidle(struct clk_ti_autoidle *clk)
63} 104}
64 105
65/** 106/**
66 * of_ti_clk_allow_autoidle_all - enable autoidle for all clocks 107 * _clk_generic_allow_autoidle_all - enable autoidle for all clocks
67 * 108 *
68 * Enables hardware autoidle for all registered DT clocks, which have 109 * Enables hardware autoidle for all registered DT clocks, which have
69 * the feature. 110 * the feature.
70 */ 111 */
71void of_ti_clk_allow_autoidle_all(void) 112static void _clk_generic_allow_autoidle_all(void)
72{ 113{
73 struct clk_ti_autoidle *c; 114 struct clk_ti_autoidle *c;
74 115
75 list_for_each_entry(c, &autoidle_clks, node) 116 list_for_each_entry(c, &autoidle_clks, node)
76 ti_allow_autoidle(c); 117 _allow_autoidle(c);
77} 118}
78 119
79/** 120/**
80 * of_ti_clk_deny_autoidle_all - disable autoidle for all clocks 121 * _clk_generic_deny_autoidle_all - disable autoidle for all clocks
81 * 122 *
82 * Disables hardware autoidle for all registered DT clocks, which have 123 * Disables hardware autoidle for all registered DT clocks, which have
83 * the feature. 124 * the feature.
84 */ 125 */
85void of_ti_clk_deny_autoidle_all(void) 126static void _clk_generic_deny_autoidle_all(void)
86{ 127{
87 struct clk_ti_autoidle *c; 128 struct clk_ti_autoidle *c;
88 129
89 list_for_each_entry(c, &autoidle_clks, node) 130 list_for_each_entry(c, &autoidle_clks, node)
90 ti_deny_autoidle(c); 131 _deny_autoidle(c);
91} 132}
92 133
93/** 134/**
@@ -131,3 +172,67 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
131 172
132 return 0; 173 return 0;
133} 174}
175
176/**
177 * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
178 * @clk: struct clk * to initialize
179 *
180 * Add an OMAP clock @clk to the internal list of OMAP clocks. Used
181 * temporarily for autoidle handling, until this support can be
182 * integrated into the common clock framework code in some way. No
183 * return value.
184 */
185void omap2_init_clk_hw_omap_clocks(struct clk *clk)
186{
187 struct clk_hw_omap *c;
188
189 if (__clk_get_flags(clk) & CLK_IS_BASIC)
190 return;
191
192 c = to_clk_hw_omap(__clk_get_hw(clk));
193 list_add(&c->node, &clk_hw_omap_clocks);
194}
195
196/**
197 * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
198 * support it
199 *
200 * Enable clock autoidle on all OMAP clocks that have allow_idle
201 * function pointers associated with them. This function is intended
202 * to be temporary until support for this is added to the common clock
203 * code. Returns 0.
204 */
205int omap2_clk_enable_autoidle_all(void)
206{
207 struct clk_hw_omap *c;
208
209 list_for_each_entry(c, &clk_hw_omap_clocks, node)
210 if (c->ops && c->ops->allow_idle)
211 c->ops->allow_idle(c);
212
213 _clk_generic_allow_autoidle_all();
214
215 return 0;
216}
217
218/**
219 * omap2_clk_disable_autoidle_all - disable autoidle on all OMAP clocks that
220 * support it
221 *
222 * Disable clock autoidle on all OMAP clocks that have allow_idle
223 * function pointers associated with them. This function is intended
224 * to be temporary until support for this is added to the common clock
225 * code. Returns 0.
226 */
227int omap2_clk_disable_autoidle_all(void)
228{
229 struct clk_hw_omap *c;
230
231 list_for_each_entry(c, &clk_hw_omap_clocks, node)
232 if (c->ops && c->ops->deny_idle)
233 c->ops->deny_idle(c);
234
235 _clk_generic_deny_autoidle_all();
236
237 return 0;
238}
diff --git a/drivers/clk/ti/clk-2xxx.c b/drivers/clk/ti/clk-2xxx.c
index c808ab3d2bb2..bd8790be2ab1 100644
--- a/drivers/clk/ti/clk-2xxx.c
+++ b/drivers/clk/ti/clk-2xxx.c
@@ -19,6 +19,8 @@
19#include <linux/clk-provider.h> 19#include <linux/clk-provider.h>
20#include <linux/clk/ti.h> 20#include <linux/clk/ti.h>
21 21
22#include "clock.h"
23
22static struct ti_dt_clk omap2xxx_clks[] = { 24static struct ti_dt_clk omap2xxx_clks[] = {
23 DT_CLK(NULL, "func_32k_ck", "func_32k_ck"), 25 DT_CLK(NULL, "func_32k_ck", "func_32k_ck"),
24 DT_CLK(NULL, "secure_32k_ck", "secure_32k_ck"), 26 DT_CLK(NULL, "secure_32k_ck", "secure_32k_ck"),
diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c
index 028b33783d38..733f9d374d0f 100644
--- a/drivers/clk/ti/clk-33xx.c
+++ b/drivers/clk/ti/clk-33xx.c
@@ -19,6 +19,8 @@
19#include <linux/clk-provider.h> 19#include <linux/clk-provider.h>
20#include <linux/clk/ti.h> 20#include <linux/clk/ti.h>
21 21
22#include "clock.h"
23
22static struct ti_dt_clk am33xx_clks[] = { 24static struct ti_dt_clk am33xx_clks[] = {
23 DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"), 25 DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"),
24 DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"), 26 DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"),
diff --git a/drivers/clk/ti/clk-3xxx.c b/drivers/clk/ti/clk-3xxx.c
index 757636d166cf..6e33332b6b34 100644
--- a/drivers/clk/ti/clk-3xxx.c
+++ b/drivers/clk/ti/clk-3xxx.c
@@ -19,6 +19,226 @@
19#include <linux/clk-provider.h> 19#include <linux/clk-provider.h>
20#include <linux/clk/ti.h> 20#include <linux/clk/ti.h>
21 21
22#include "clock.h"
23
24/*
25 * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
26 * that are sourced by DPLL5, and both of these require this clock
27 * to be at 120 MHz for proper operation.
28 */
29#define DPLL5_FREQ_FOR_USBHOST 120000000
30
31#define OMAP3430ES2_ST_DSS_IDLE_SHIFT 1
32#define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT 5
33#define OMAP3430ES2_ST_SSI_IDLE_SHIFT 8
34
35#define OMAP34XX_CM_IDLEST_VAL 1
36
37/*
38 * In AM35xx IPSS, the {ICK,FCK} enable bits for modules are exported
39 * in the same register at a bit offset of 0x8. The EN_ACK for ICK is
40 * at an offset of 4 from ICK enable bit.
41 */
42#define AM35XX_IPSS_ICK_MASK 0xF
43#define AM35XX_IPSS_ICK_EN_ACK_OFFSET 0x4
44#define AM35XX_IPSS_ICK_FCK_OFFSET 0x8
45#define AM35XX_IPSS_CLK_IDLEST_VAL 0
46
47#define AM35XX_ST_IPSS_SHIFT 5
48
49/**
50 * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
51 * @clk: struct clk * being enabled
52 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
53 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
54 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
55 *
56 * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
57 * from the CM_{I,F}CLKEN bit. Pass back the correct info via
58 * @idlest_reg and @idlest_bit. No return value.
59 */
60static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
61 void __iomem **idlest_reg,
62 u8 *idlest_bit,
63 u8 *idlest_val)
64{
65 u32 r;
66
67 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
68 *idlest_reg = (__force void __iomem *)r;
69 *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
70 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
71}
72
73const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait = {
74 .find_idlest = omap3430es2_clk_ssi_find_idlest,
75 .find_companion = omap2_clk_dflt_find_companion,
76};
77
78const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
79 .allow_idle = omap2_clkt_iclk_allow_idle,
80 .deny_idle = omap2_clkt_iclk_deny_idle,
81 .find_idlest = omap3430es2_clk_ssi_find_idlest,
82 .find_companion = omap2_clk_dflt_find_companion,
83};
84
85/**
86 * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
87 * @clk: struct clk * being enabled
88 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
89 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
90 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
91 *
92 * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
93 * target IDLEST bits. For our purposes, we are concerned with the
94 * target IDLEST bits, which exist at a different bit position than
95 * the *CLKEN bit position for these modules (DSS and USBHOST) (The
96 * default find_idlest code assumes that they are at the same
97 * position.) No return value.
98 */
99static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
100 void __iomem **idlest_reg,
101 u8 *idlest_bit,
102 u8 *idlest_val)
103{
104 u32 r;
105
106 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
107 *idlest_reg = (__force void __iomem *)r;
108 /* USBHOST_IDLE has same shift */
109 *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
110 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
111}
112
113const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait = {
114 .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
115 .find_companion = omap2_clk_dflt_find_companion,
116};
117
118const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
119 .allow_idle = omap2_clkt_iclk_allow_idle,
120 .deny_idle = omap2_clkt_iclk_deny_idle,
121 .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
122 .find_companion = omap2_clk_dflt_find_companion,
123};
124
125/**
126 * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
127 * @clk: struct clk * being enabled
128 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
129 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
130 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
131 *
132 * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
133 * shift from the CM_{I,F}CLKEN bit. Pass back the correct info via
134 * @idlest_reg and @idlest_bit. No return value.
135 */
136static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
137 void __iomem **idlest_reg,
138 u8 *idlest_bit,
139 u8 *idlest_val)
140{
141 u32 r;
142
143 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
144 *idlest_reg = (__force void __iomem *)r;
145 *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
146 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
147}
148
149const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
150 .allow_idle = omap2_clkt_iclk_allow_idle,
151 .deny_idle = omap2_clkt_iclk_deny_idle,
152 .find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
153 .find_companion = omap2_clk_dflt_find_companion,
154};
155
156const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait = {
157 .find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
158 .find_companion = omap2_clk_dflt_find_companion,
159};
160
161/**
162 * am35xx_clk_find_idlest - return clock ACK info for AM35XX IPSS
163 * @clk: struct clk * being enabled
164 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
165 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
166 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
167 *
168 * The interface clocks on AM35xx IPSS reflects the clock idle status
169 * in the enable register itsel at a bit offset of 4 from the enable
170 * bit. A value of 1 indicates that clock is enabled.
171 */
172static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
173 void __iomem **idlest_reg,
174 u8 *idlest_bit,
175 u8 *idlest_val)
176{
177 *idlest_reg = (__force void __iomem *)(clk->enable_reg);
178 *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
179 *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
180}
181
182/**
183 * am35xx_clk_find_companion - find companion clock to @clk
184 * @clk: struct clk * to find the companion clock of
185 * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
186 * @other_bit: u8 ** to return the companion clock bit shift in
187 *
188 * Some clocks don't have companion clocks. For example, modules with
189 * only an interface clock (such as HECC) don't have a companion
190 * clock. Right now, this code relies on the hardware exporting a bit
191 * in the correct companion register that indicates that the
192 * nonexistent 'companion clock' is active. Future patches will
193 * associate this type of code with per-module data structures to
194 * avoid this issue, and remove the casts. No return value.
195 */
196static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
197 void __iomem **other_reg,
198 u8 *other_bit)
199{
200 *other_reg = (__force void __iomem *)(clk->enable_reg);
201 if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
202 *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
203 else
204 *other_bit = clk->enable_bit - AM35XX_IPSS_ICK_FCK_OFFSET;
205}
206
207const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
208 .find_idlest = am35xx_clk_find_idlest,
209 .find_companion = am35xx_clk_find_companion,
210};
211
212/**
213 * am35xx_clk_ipss_find_idlest - return CM_IDLEST info for IPSS
214 * @clk: struct clk * being enabled
215 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
216 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
217 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
218 *
219 * The IPSS target CM_IDLEST bit is at a different shift from the
220 * CM_{I,F}CLKEN bit. Pass back the correct info via @idlest_reg
221 * and @idlest_bit. No return value.
222 */
223static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
224 void __iomem **idlest_reg,
225 u8 *idlest_bit,
226 u8 *idlest_val)
227{
228 u32 r;
229
230 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
231 *idlest_reg = (__force void __iomem *)r;
232 *idlest_bit = AM35XX_ST_IPSS_SHIFT;
233 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
234}
235
236const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait = {
237 .allow_idle = omap2_clkt_iclk_allow_idle,
238 .deny_idle = omap2_clkt_iclk_deny_idle,
239 .find_idlest = am35xx_clk_ipss_find_idlest,
240 .find_companion = omap2_clk_dflt_find_companion,
241};
22 242
23static struct ti_dt_clk omap3xxx_clks[] = { 243static struct ti_dt_clk omap3xxx_clks[] = {
24 DT_CLK(NULL, "apb_pclk", "dummy_apb_pclk"), 244 DT_CLK(NULL, "apb_pclk", "dummy_apb_pclk"),
@@ -324,6 +544,30 @@ enum {
324 OMAP3_SOC_OMAP3630, 544 OMAP3_SOC_OMAP3630,
325}; 545};
326 546
547/**
548 * omap3_clk_lock_dpll5 - locks DPLL5
549 *
550 * Locks DPLL5 to a pre-defined frequency. This is required for proper
551 * operation of USB.
552 */
553void __init omap3_clk_lock_dpll5(void)
554{
555 struct clk *dpll5_clk;
556 struct clk *dpll5_m2_clk;
557
558 dpll5_clk = clk_get(NULL, "dpll5_ck");
559 clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
560 clk_prepare_enable(dpll5_clk);
561
562 /* Program dpll5_m2_clk divider for no division */
563 dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
564 clk_prepare_enable(dpll5_m2_clk);
565 clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
566
567 clk_disable_unprepare(dpll5_m2_clk);
568 clk_disable_unprepare(dpll5_clk);
569}
570
327static int __init omap3xxx_dt_clk_init(int soc_type) 571static int __init omap3xxx_dt_clk_init(int soc_type)
328{ 572{
329 if (soc_type == OMAP3_SOC_AM35XX || soc_type == OMAP3_SOC_OMAP3630 || 573 if (soc_type == OMAP3_SOC_AM35XX || soc_type == OMAP3_SOC_OMAP3630 ||
diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c
index 3795fce8a830..894316738459 100644
--- a/drivers/clk/ti/clk-43xx.c
+++ b/drivers/clk/ti/clk-43xx.c
@@ -19,6 +19,8 @@
19#include <linux/clk-provider.h> 19#include <linux/clk-provider.h>
20#include <linux/clk/ti.h> 20#include <linux/clk/ti.h>
21 21
22#include "clock.h"
23
22static struct ti_dt_clk am43xx_clks[] = { 24static struct ti_dt_clk am43xx_clks[] = {
23 DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"), 25 DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"),
24 DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"), 26 DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"),
diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c
index 581db7711f51..7a8b51b35f9f 100644
--- a/drivers/clk/ti/clk-44xx.c
+++ b/drivers/clk/ti/clk-44xx.c
@@ -16,6 +16,8 @@
16#include <linux/clkdev.h> 16#include <linux/clkdev.h>
17#include <linux/clk/ti.h> 17#include <linux/clk/ti.h>
18 18
19#include "clock.h"
20
19/* 21/*
20 * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section 22 * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section
21 * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK 23 * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK
diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c
index 96c69a335975..59ce2fa2c104 100644
--- a/drivers/clk/ti/clk-54xx.c
+++ b/drivers/clk/ti/clk-54xx.c
@@ -17,6 +17,8 @@
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/clk/ti.h> 18#include <linux/clk/ti.h>
19 19
20#include "clock.h"
21
20#define OMAP5_DPLL_ABE_DEFFREQ 98304000 22#define OMAP5_DPLL_ABE_DEFFREQ 98304000
21 23
22/* 24/*
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c
index 63b8323df918..9b5b289e6334 100644
--- a/drivers/clk/ti/clk-7xx.c
+++ b/drivers/clk/ti/clk-7xx.c
@@ -16,11 +16,12 @@
16#include <linux/clkdev.h> 16#include <linux/clkdev.h>
17#include <linux/clk/ti.h> 17#include <linux/clk/ti.h>
18 18
19#include "clock.h"
20
19#define DRA7_DPLL_ABE_DEFFREQ 180633600 21#define DRA7_DPLL_ABE_DEFFREQ 180633600
20#define DRA7_DPLL_GMAC_DEFFREQ 1000000000 22#define DRA7_DPLL_GMAC_DEFFREQ 1000000000
21#define DRA7_DPLL_USB_DEFFREQ 960000000 23#define DRA7_DPLL_USB_DEFFREQ 960000000
22 24
23
24static struct ti_dt_clk dra7xx_clks[] = { 25static struct ti_dt_clk dra7xx_clks[] = {
25 DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"), 26 DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"),
26 DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"), 27 DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"),
diff --git a/drivers/clk/ti/clk-816x.c b/drivers/clk/ti/clk-816x.c
index 9451e651a1ff..c69352b24dba 100644
--- a/drivers/clk/ti/clk-816x.c
+++ b/drivers/clk/ti/clk-816x.c
@@ -14,6 +14,8 @@
14#include <linux/clk-provider.h> 14#include <linux/clk-provider.h>
15#include <linux/clk/ti.h> 15#include <linux/clk/ti.h>
16 16
17#include "clock.h"
18
17static struct ti_dt_clk dm816x_clks[] = { 19static struct ti_dt_clk dm816x_clks[] = {
18 DT_CLK(NULL, "sys_clkin", "sys_clkin_ck"), 20 DT_CLK(NULL, "sys_clkin", "sys_clkin_ck"),
19 DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"), 21 DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"),
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 64bb5e8a3b8c..3343bde47fe4 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -21,6 +21,8 @@
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/regmap.h>
25#include <linux/bootmem.h>
24 26
25#include "clock.h" 27#include "clock.h"
26 28
@@ -30,6 +32,63 @@
30struct ti_clk_ll_ops *ti_clk_ll_ops; 32struct ti_clk_ll_ops *ti_clk_ll_ops;
31static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS]; 33static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
32 34
35struct ti_clk_features ti_clk_features;
36
37struct clk_iomap {
38 struct regmap *regmap;
39 void __iomem *mem;
40};
41
42static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
43
44static void clk_memmap_writel(u32 val, void __iomem *reg)
45{
46 struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
47 struct clk_iomap *io = clk_memmaps[r->index];
48
49 if (io->regmap)
50 regmap_write(io->regmap, r->offset, val);
51 else
52 writel_relaxed(val, io->mem + r->offset);
53}
54
55static u32 clk_memmap_readl(void __iomem *reg)
56{
57 u32 val;
58 struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
59 struct clk_iomap *io = clk_memmaps[r->index];
60
61 if (io->regmap)
62 regmap_read(io->regmap, r->offset, &val);
63 else
64 val = readl_relaxed(io->mem + r->offset);
65
66 return val;
67}
68
69/**
70 * ti_clk_setup_ll_ops - setup low level clock operations
71 * @ops: low level clock ops descriptor
72 *
73 * Sets up low level clock operations for TI clock driver. This is used
74 * to provide various callbacks for the clock driver towards platform
75 * specific code. Returns 0 on success, -EBUSY if ll_ops have been
76 * registered already.
77 */
78int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
79{
80 if (ti_clk_ll_ops) {
81 pr_err("Attempt to register ll_ops multiple times.\n");
82 return -EBUSY;
83 }
84
85 ti_clk_ll_ops = ops;
86 ops->clk_readl = clk_memmap_readl;
87 ops->clk_writel = clk_memmap_writel;
88
89 return 0;
90}
91
33/** 92/**
34 * ti_dt_clocks_register - register DT alias clocks during boot 93 * ti_dt_clocks_register - register DT alias clocks during boot
35 * @oclks: list of clocks to register 94 * @oclks: list of clocks to register
@@ -138,28 +197,61 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
138} 197}
139 198
140/** 199/**
141 * ti_dt_clk_init_provider - init master clock provider 200 * omap2_clk_provider_init - init master clock provider
142 * @parent: master node 201 * @parent: master node
143 * @index: internal index for clk_reg_ops 202 * @index: internal index for clk_reg_ops
203 * @syscon: syscon regmap pointer for accessing clock registers
204 * @mem: iomem pointer for the clock provider memory area, only used if
205 * syscon is not provided
144 * 206 *
145 * Initializes a master clock IP block. This basically sets up the 207 * Initializes a master clock IP block. This basically sets up the
146 * mapping from clocks node to the memory map index. All the clocks 208 * mapping from clocks node to the memory map index. All the clocks
147 * are then initialized through the common of_clk_init call, and the 209 * are then initialized through the common of_clk_init call, and the
148 * clocks will access their memory maps based on the node layout. 210 * clocks will access their memory maps based on the node layout.
211 * Returns 0 in success.
149 */ 212 */
150void ti_dt_clk_init_provider(struct device_node *parent, int index) 213int __init omap2_clk_provider_init(struct device_node *parent, int index,
214 struct regmap *syscon, void __iomem *mem)
151{ 215{
152 struct device_node *clocks; 216 struct device_node *clocks;
217 struct clk_iomap *io;
153 218
154 /* get clocks for this parent */ 219 /* get clocks for this parent */
155 clocks = of_get_child_by_name(parent, "clocks"); 220 clocks = of_get_child_by_name(parent, "clocks");
156 if (!clocks) { 221 if (!clocks) {
157 pr_err("%s missing 'clocks' child node.\n", parent->name); 222 pr_err("%s missing 'clocks' child node.\n", parent->name);
158 return; 223 return -EINVAL;
159 } 224 }
160 225
161 /* add clocks node info */ 226 /* add clocks node info */
162 clocks_node_ptr[index] = clocks; 227 clocks_node_ptr[index] = clocks;
228
229 io = kzalloc(sizeof(*io), GFP_KERNEL);
230
231 io->regmap = syscon;
232 io->mem = mem;
233
234 clk_memmaps[index] = io;
235
236 return 0;
237}
238
239/**
240 * omap2_clk_legacy_provider_init - initialize a legacy clock provider
241 * @index: index for the clock provider
242 * @mem: iomem pointer for the clock provider memory area
243 *
244 * Initializes a legacy clock provider memory mapping.
245 */
246void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
247{
248 struct clk_iomap *io;
249
250 io = memblock_virt_alloc(sizeof(*io), 0);
251
252 io->mem = mem;
253
254 clk_memmaps[index] = io;
163} 255}
164 256
165/** 257/**
@@ -311,3 +403,50 @@ int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks)
311 return 0; 403 return 0;
312} 404}
313#endif 405#endif
406
407/**
408 * ti_clk_setup_features - setup clock features flags
409 * @features: features definition to use
410 *
411 * Initializes the clock driver features flags based on platform
412 * provided data. No return value.
413 */
414void __init ti_clk_setup_features(struct ti_clk_features *features)
415{
416 memcpy(&ti_clk_features, features, sizeof(*features));
417}
418
419/**
420 * ti_clk_get_features - get clock driver features flags
421 *
422 * Get TI clock driver features description. Returns a pointer
423 * to the current feature setup.
424 */
425const struct ti_clk_features *ti_clk_get_features(void)
426{
427 return &ti_clk_features;
428}
429
430/**
431 * omap2_clk_enable_init_clocks - prepare & enable a list of clocks
432 * @clk_names: ptr to an array of strings of clock names to enable
433 * @num_clocks: number of clock names in @clk_names
434 *
435 * Prepare and enable a list of clocks, named by @clk_names. No
436 * return value. XXX Deprecated; only needed until these clocks are
437 * properly claimed and enabled by the drivers or core code that uses
438 * them. XXX What code disables & calls clk_put on these clocks?
439 */
440void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
441{
442 struct clk *init_clk;
443 int i;
444
445 for (i = 0; i < num_clocks; i++) {
446 init_clk = clk_get(NULL, clk_names[i]);
447 if (WARN(IS_ERR(init_clk), "could not find init clock %s\n",
448 clk_names[i]))
449 continue;
450 clk_prepare_enable(init_clk);
451 }
452}
diff --git a/drivers/clk/ti/clkt_dflt.c b/drivers/clk/ti/clkt_dflt.c
new file mode 100644
index 000000000000..a176b8ac8dd0
--- /dev/null
+++ b/drivers/clk/ti/clkt_dflt.c
@@ -0,0 +1,316 @@
1/*
2 * Default clock type
3 *
4 * Copyright (C) 2005-2008, 2015 Texas Instruments, Inc.
5 * Copyright (C) 2004-2010 Nokia Corporation
6 *
7 * Contacts:
8 * Richard Woodruff <r-woodruff2@ti.com>
9 * Paul Walmsley
10 * Tero Kristo <t-kristo@ti.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
17 * kind, whether express or implied; without even the implied warranty
18 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
21
22#include <linux/kernel.h>
23#include <linux/errno.h>
24#include <linux/clk-provider.h>
25#include <linux/io.h>
26#include <linux/clk/ti.h>
27#include <linux/delay.h>
28
29#include "clock.h"
30
31/*
32 * MAX_MODULE_ENABLE_WAIT: maximum of number of microseconds to wait
33 * for a module to indicate that it is no longer in idle
34 */
35#define MAX_MODULE_ENABLE_WAIT 100000
36
37/*
38 * CM module register offsets, used for calculating the companion
39 * register addresses.
40 */
41#define CM_FCLKEN 0x0000
42#define CM_ICLKEN 0x0010
43
44/**
45 * _wait_idlest_generic - wait for a module to leave the idle state
46 * @clk: module clock to wait for (needed for register offsets)
47 * @reg: virtual address of module IDLEST register
48 * @mask: value to mask against to determine if the module is active
49 * @idlest: idle state indicator (0 or 1) for the clock
50 * @name: name of the clock (for printk)
51 *
52 * Wait for a module to leave idle, where its idle-status register is
53 * not inside the CM module. Returns 1 if the module left idle
54 * promptly, or 0 if the module did not leave idle before the timeout
55 * elapsed. XXX Deprecated - should be moved into drivers for the
56 * individual IP block that the IDLEST register exists in.
57 */
58static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
59 u32 mask, u8 idlest, const char *name)
60{
61 int i = 0, ena = 0;
62
63 ena = (idlest) ? 0 : mask;
64
65 /* Wait until module enters enabled state */
66 for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) {
67 if ((ti_clk_ll_ops->clk_readl(reg) & mask) == ena)
68 break;
69 udelay(1);
70 }
71
72 if (i < MAX_MODULE_ENABLE_WAIT)
73 pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
74 name, i);
75 else
76 pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
77 name, MAX_MODULE_ENABLE_WAIT);
78
79 return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
80}
81
82/**
83 * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
84 * @clk: struct clk * belonging to the module
85 *
86 * If the necessary clocks for the OMAP hardware IP block that
87 * corresponds to clock @clk are enabled, then wait for the module to
88 * indicate readiness (i.e., to leave IDLE). This code does not
89 * belong in the clock code and will be moved in the medium term to
90 * module-dependent code. No return value.
91 */
92static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
93{
94 void __iomem *companion_reg, *idlest_reg;
95 u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
96 s16 prcm_mod;
97 int r;
98
99 /* Not all modules have multiple clocks that their IDLEST depends on */
100 if (clk->ops->find_companion) {
101 clk->ops->find_companion(clk, &companion_reg, &other_bit);
102 if (!(ti_clk_ll_ops->clk_readl(companion_reg) &
103 (1 << other_bit)))
104 return;
105 }
106
107 clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
108 r = ti_clk_ll_ops->cm_split_idlest_reg(idlest_reg, &prcm_mod,
109 &idlest_reg_id);
110 if (r) {
111 /* IDLEST register not in the CM module */
112 _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
113 idlest_val, __clk_get_name(clk->hw.clk));
114 } else {
115 ti_clk_ll_ops->cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
116 idlest_bit);
117 }
118}
119
120/**
121 * omap2_clk_dflt_find_companion - find companion clock to @clk
122 * @clk: struct clk * to find the companion clock of
123 * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
124 * @other_bit: u8 ** to return the companion clock bit shift in
125 *
126 * Note: We don't need special code here for INVERT_ENABLE for the
127 * time being since INVERT_ENABLE only applies to clocks enabled by
128 * CM_CLKEN_PLL
129 *
130 * Convert CM_ICLKEN* <-> CM_FCLKEN*. This conversion assumes it's
131 * just a matter of XORing the bits.
132 *
133 * Some clocks don't have companion clocks. For example, modules with
134 * only an interface clock (such as MAILBOXES) don't have a companion
135 * clock. Right now, this code relies on the hardware exporting a bit
136 * in the correct companion register that indicates that the
137 * nonexistent 'companion clock' is active. Future patches will
138 * associate this type of code with per-module data structures to
139 * avoid this issue, and remove the casts. No return value.
140 */
141void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
142 void __iomem **other_reg, u8 *other_bit)
143{
144 u32 r;
145
146 /*
147 * Convert CM_ICLKEN* <-> CM_FCLKEN*. This conversion assumes
148 * it's just a matter of XORing the bits.
149 */
150 r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
151
152 *other_reg = (__force void __iomem *)r;
153 *other_bit = clk->enable_bit;
154}
155
156/**
157 * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
158 * @clk: struct clk * to find IDLEST info for
159 * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
160 * @idlest_bit: u8 * to return the CM_IDLEST bit shift in
161 * @idlest_val: u8 * to return the idle status indicator
162 *
163 * Return the CM_IDLEST register address and bit shift corresponding
164 * to the module that "owns" this clock. This default code assumes
165 * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
166 * the IDLEST register address ID corresponds to the CM_*CLKEN
167 * register address ID (e.g., that CM_FCLKEN2 corresponds to
168 * CM_IDLEST2). This is not true for all modules. No return value.
169 */
170void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
171 void __iomem **idlest_reg, u8 *idlest_bit,
172 u8 *idlest_val)
173{
174 u32 r;
175
176 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
177 *idlest_reg = (__force void __iomem *)r;
178 *idlest_bit = clk->enable_bit;
179
180 /*
181 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
182 * 34xx reverses this, just to keep us on our toes
183 * AM35xx uses both, depending on the module.
184 */
185 *idlest_val = ti_clk_get_features()->cm_idlest_val;
186}
187
188/**
189 * omap2_dflt_clk_enable - enable a clock in the hardware
190 * @hw: struct clk_hw * of the clock to enable
191 *
192 * Enable the clock @hw in the hardware. We first call into the OMAP
193 * clockdomain code to "enable" the corresponding clockdomain if this
194 * is the first enabled user of the clockdomain. Then program the
195 * hardware to enable the clock. Then wait for the IP block that uses
196 * this clock to leave idle (if applicable). Returns the error value
197 * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
198 * if @hw has a null clock enable_reg, or zero upon success.
199 */
200int omap2_dflt_clk_enable(struct clk_hw *hw)
201{
202 struct clk_hw_omap *clk;
203 u32 v;
204 int ret = 0;
205 bool clkdm_control;
206
207 if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL)
208 clkdm_control = false;
209 else
210 clkdm_control = true;
211
212 clk = to_clk_hw_omap(hw);
213
214 if (clkdm_control && clk->clkdm) {
215 ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
216 if (ret) {
217 WARN(1,
218 "%s: could not enable %s's clockdomain %s: %d\n",
219 __func__, __clk_get_name(hw->clk),
220 clk->clkdm_name, ret);
221 return ret;
222 }
223 }
224
225 if (unlikely(!clk->enable_reg)) {
226 pr_err("%s: %s missing enable_reg\n", __func__,
227 __clk_get_name(hw->clk));
228 ret = -EINVAL;
229 goto err;
230 }
231
232 /* FIXME should not have INVERT_ENABLE bit here */
233 v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
234 if (clk->flags & INVERT_ENABLE)
235 v &= ~(1 << clk->enable_bit);
236 else
237 v |= (1 << clk->enable_bit);
238 ti_clk_ll_ops->clk_writel(v, clk->enable_reg);
239 v = ti_clk_ll_ops->clk_readl(clk->enable_reg); /* OCP barrier */
240
241 if (clk->ops && clk->ops->find_idlest)
242 _omap2_module_wait_ready(clk);
243
244 return 0;
245
246err:
247 if (clkdm_control && clk->clkdm)
248 ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
249 return ret;
250}
251
252/**
253 * omap2_dflt_clk_disable - disable a clock in the hardware
254 * @hw: struct clk_hw * of the clock to disable
255 *
256 * Disable the clock @hw in the hardware, and call into the OMAP
257 * clockdomain code to "disable" the corresponding clockdomain if all
258 * clocks/hwmods in that clockdomain are now disabled. No return
259 * value.
260 */
261void omap2_dflt_clk_disable(struct clk_hw *hw)
262{
263 struct clk_hw_omap *clk;
264 u32 v;
265
266 clk = to_clk_hw_omap(hw);
267 if (!clk->enable_reg) {
268 /*
269 * 'independent' here refers to a clock which is not
270 * controlled by its parent.
271 */
272 pr_err("%s: independent clock %s has no enable_reg\n",
273 __func__, __clk_get_name(hw->clk));
274 return;
275 }
276
277 v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
278 if (clk->flags & INVERT_ENABLE)
279 v |= (1 << clk->enable_bit);
280 else
281 v &= ~(1 << clk->enable_bit);
282 ti_clk_ll_ops->clk_writel(v, clk->enable_reg);
283 /* No OCP barrier needed here since it is a disable operation */
284
285 if (!(ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) &&
286 clk->clkdm)
287 ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
288}
289
290/**
291 * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
292 * @hw: struct clk_hw * to check
293 *
294 * Return 1 if the clock represented by @hw is enabled in the
295 * hardware, or 0 otherwise. Intended for use in the struct
296 * clk_ops.is_enabled function pointer.
297 */
298int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
299{
300 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
301 u32 v;
302
303 v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
304
305 if (clk->flags & INVERT_ENABLE)
306 v ^= BIT(clk->enable_bit);
307
308 v &= BIT(clk->enable_bit);
309
310 return v ? 1 : 0;
311}
312
313const struct clk_hw_omap_ops clkhwops_wait = {
314 .find_idlest = omap2_clk_dflt_find_idlest,
315 .find_companion = omap2_clk_dflt_find_companion,
316};
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/drivers/clk/ti/clkt_dpll.c
index f251a14cbf16..a01fc7f305c1 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/drivers/clk/ti/clkt_dpll.c
@@ -18,6 +18,7 @@
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/clk-provider.h> 19#include <linux/clk-provider.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/clk/ti.h>
21 22
22#include <asm/div64.h> 23#include <asm/div64.h>
23 24
@@ -80,8 +81,8 @@ static int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n)
80 fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN; 81 fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
81 fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX; 82 fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
82 } else { 83 } else {
83 fint_min = ti_clk_features.fint_min; 84 fint_min = ti_clk_get_features()->fint_min;
84 fint_max = ti_clk_features.fint_max; 85 fint_max = ti_clk_get_features()->fint_max;
85 } 86 }
86 87
87 if (!fint_min || !fint_max) { 88 if (!fint_min || !fint_max) {
@@ -89,18 +90,18 @@ static int _dpll_test_fint(struct clk_hw_omap *clk, unsigned int n)
89 return DPLL_FINT_INVALID; 90 return DPLL_FINT_INVALID;
90 } 91 }
91 92
92 if (fint < ti_clk_features.fint_min) { 93 if (fint < ti_clk_get_features()->fint_min) {
93 pr_debug("rejecting n=%d due to Fint failure, lowering max_divider\n", 94 pr_debug("rejecting n=%d due to Fint failure, lowering max_divider\n",
94 n); 95 n);
95 dd->max_divider = n; 96 dd->max_divider = n;
96 ret = DPLL_FINT_UNDERFLOW; 97 ret = DPLL_FINT_UNDERFLOW;
97 } else if (fint > ti_clk_features.fint_max) { 98 } else if (fint > ti_clk_get_features()->fint_max) {
98 pr_debug("rejecting n=%d due to Fint failure, boosting min_divider\n", 99 pr_debug("rejecting n=%d due to Fint failure, boosting min_divider\n",
99 n); 100 n);
100 dd->min_divider = n; 101 dd->min_divider = n;
101 ret = DPLL_FINT_INVALID; 102 ret = DPLL_FINT_INVALID;
102 } else if (fint > ti_clk_features.fint_band1_max && 103 } else if (fint > ti_clk_get_features()->fint_band1_max &&
103 fint < ti_clk_features.fint_band2_min) { 104 fint < ti_clk_get_features()->fint_band2_min) {
104 pr_debug("rejecting n=%d due to Fint failure\n", n); 105 pr_debug("rejecting n=%d due to Fint failure\n", n);
105 ret = DPLL_FINT_INVALID; 106 ret = DPLL_FINT_INVALID;
106 } 107 }
@@ -183,7 +184,7 @@ static int _omap2_dpll_is_in_bypass(u32 v)
183{ 184{
184 u8 mask, val; 185 u8 mask, val;
185 186
186 mask = ti_clk_features.dpll_bypass_vals; 187 mask = ti_clk_get_features()->dpll_bypass_vals;
187 188
188 /* 189 /*
189 * Each set bit in the mask corresponds to a bypass value equal 190 * Each set bit in the mask corresponds to a bypass value equal
@@ -211,7 +212,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
211 if (!dd) 212 if (!dd)
212 return -EINVAL; 213 return -EINVAL;
213 214
214 v = omap2_clk_readl(clk, dd->control_reg); 215 v = ti_clk_ll_ops->clk_readl(dd->control_reg);
215 v &= dd->enable_mask; 216 v &= dd->enable_mask;
216 v >>= __ffs(dd->enable_mask); 217 v >>= __ffs(dd->enable_mask);
217 218
@@ -247,20 +248,20 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
247 return 0; 248 return 0;
248 249
249 /* Return bypass rate if DPLL is bypassed */ 250 /* Return bypass rate if DPLL is bypassed */
250 v = omap2_clk_readl(clk, dd->control_reg); 251 v = ti_clk_ll_ops->clk_readl(dd->control_reg);
251 v &= dd->enable_mask; 252 v &= dd->enable_mask;
252 v >>= __ffs(dd->enable_mask); 253 v >>= __ffs(dd->enable_mask);
253 254
254 if (_omap2_dpll_is_in_bypass(v)) 255 if (_omap2_dpll_is_in_bypass(v))
255 return __clk_get_rate(dd->clk_bypass); 256 return __clk_get_rate(dd->clk_bypass);
256 257
257 v = omap2_clk_readl(clk, dd->mult_div1_reg); 258 v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg);
258 dpll_mult = v & dd->mult_mask; 259 dpll_mult = v & dd->mult_mask;
259 dpll_mult >>= __ffs(dd->mult_mask); 260 dpll_mult >>= __ffs(dd->mult_mask);
260 dpll_div = v & dd->div1_mask; 261 dpll_div = v & dd->div1_mask;
261 dpll_div >>= __ffs(dd->div1_mask); 262 dpll_div >>= __ffs(dd->div1_mask);
262 263
263 dpll_clk = (long long) __clk_get_rate(dd->clk_ref) * dpll_mult; 264 dpll_clk = (long long)__clk_get_rate(dd->clk_ref) * dpll_mult;
264 do_div(dpll_clk, dpll_div + 1); 265 do_div(dpll_clk, dpll_div + 1);
265 266
266 return dpll_clk; 267 return dpll_clk;
@@ -281,7 +282,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
281 * be rounded, or the rounded rate upon success. 282 * be rounded, or the rounded rate upon success.
282 */ 283 */
283long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, 284long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
284 unsigned long *parent_rate) 285 unsigned long *parent_rate)
285{ 286{
286 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 287 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
287 int m, n, r, scaled_max_m; 288 int m, n, r, scaled_max_m;
@@ -310,7 +311,6 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
310 dd->last_rounded_rate = 0; 311 dd->last_rounded_rate = 0;
311 312
312 for (n = dd->min_divider; n <= dd->max_divider; n++) { 313 for (n = dd->min_divider; n <= dd->max_divider; n++) {
313
314 /* Is the (input clk, divider) pair valid for the DPLL? */ 314 /* Is the (input clk, divider) pair valid for the DPLL? */
315 r = _dpll_test_fint(clk, n); 315 r = _dpll_test_fint(clk, n);
316 if (r == DPLL_FINT_UNDERFLOW) 316 if (r == DPLL_FINT_UNDERFLOW)
@@ -367,4 +367,3 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
367 367
368 return dd->last_rounded_rate; 368 return dd->last_rounded_rate;
369} 369}
370
diff --git a/drivers/clk/ti/clkt_iclk.c b/drivers/clk/ti/clkt_iclk.c
new file mode 100644
index 000000000000..38c36908cf88
--- /dev/null
+++ b/drivers/clk/ti/clkt_iclk.c
@@ -0,0 +1,101 @@
1/*
2 * OMAP2/3 interface clock control
3 *
4 * Copyright (C) 2011 Nokia Corporation
5 * Paul Walmsley
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#undef DEBUG
12
13#include <linux/kernel.h>
14#include <linux/clk-provider.h>
15#include <linux/io.h>
16#include <linux/clk/ti.h>
17
18#include "clock.h"
19
20/* Register offsets */
21#define OMAP24XX_CM_FCLKEN2 0x04
22#define CM_AUTOIDLE 0x30
23#define CM_ICLKEN 0x10
24#define CM_IDLEST 0x20
25
26#define OMAP24XX_CM_IDLEST_VAL 0
27
28/* Private functions */
29
30/* XXX */
31void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
32{
33 u32 v;
34 void __iomem *r;
35
36 r = (__force void __iomem *)
37 ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
38
39 v = ti_clk_ll_ops->clk_readl(r);
40 v |= (1 << clk->enable_bit);
41 ti_clk_ll_ops->clk_writel(v, r);
42}
43
44/* XXX */
45void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
46{
47 u32 v;
48 void __iomem *r;
49
50 r = (__force void __iomem *)
51 ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
52
53 v = ti_clk_ll_ops->clk_readl(r);
54 v &= ~(1 << clk->enable_bit);
55 ti_clk_ll_ops->clk_writel(v, r);
56}
57
58/**
59 * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
60 * @clk: struct clk * being enabled
61 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
62 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
63 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
64 *
65 * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
66 * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE. This custom function
67 * passes back the correct CM_IDLEST register address for I2CHS
68 * modules. No return value.
69 */
70static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
71 void __iomem **idlest_reg,
72 u8 *idlest_bit,
73 u8 *idlest_val)
74{
75 u32 r;
76
77 r = ((__force u32)clk->enable_reg ^ (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST));
78 *idlest_reg = (__force void __iomem *)r;
79 *idlest_bit = clk->enable_bit;
80 *idlest_val = OMAP24XX_CM_IDLEST_VAL;
81}
82
83/* Public data */
84
85const struct clk_hw_omap_ops clkhwops_iclk = {
86 .allow_idle = omap2_clkt_iclk_allow_idle,
87 .deny_idle = omap2_clkt_iclk_deny_idle,
88};
89
90const struct clk_hw_omap_ops clkhwops_iclk_wait = {
91 .allow_idle = omap2_clkt_iclk_allow_idle,
92 .deny_idle = omap2_clkt_iclk_deny_idle,
93 .find_idlest = omap2_clk_dflt_find_idlest,
94 .find_companion = omap2_clk_dflt_find_companion,
95};
96
97/* 2430 I2CHS has non-standard IDLEST register */
98const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait = {
99 .find_idlest = omap2430_clk_i2chs_find_idlest,
100 .find_companion = omap2_clk_dflt_find_companion,
101};
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 404158d2d7f8..d8aafd333058 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -154,6 +154,35 @@ struct ti_clk_dpll {
154 u8 recal_st_bit; 154 u8 recal_st_bit;
155}; 155};
156 156
157/* Composite clock component types */
158enum {
159 CLK_COMPONENT_TYPE_GATE = 0,
160 CLK_COMPONENT_TYPE_DIVIDER,
161 CLK_COMPONENT_TYPE_MUX,
162 CLK_COMPONENT_TYPE_MAX,
163};
164
165/**
166 * struct ti_dt_clk - OMAP DT clock alias declarations
167 * @lk: clock lookup definition
168 * @node_name: clock DT node to map to
169 */
170struct ti_dt_clk {
171 struct clk_lookup lk;
172 char *node_name;
173};
174
175#define DT_CLK(dev, con, name) \
176 { \
177 .lk = { \
178 .dev_id = dev, \
179 .con_id = con, \
180 }, \
181 .node_name = name, \
182 }
183
184typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
185
157struct clk *ti_clk_register_gate(struct ti_clk *setup); 186struct clk *ti_clk_register_gate(struct ti_clk *setup);
158struct clk *ti_clk_register_interface(struct ti_clk *setup); 187struct clk *ti_clk_register_interface(struct ti_clk *setup);
159struct clk *ti_clk_register_mux(struct ti_clk *setup); 188struct clk *ti_clk_register_mux(struct ti_clk *setup);
@@ -169,4 +198,80 @@ void ti_clk_patch_legacy_clks(struct ti_clk **patch);
169struct clk *ti_clk_register_clk(struct ti_clk *setup); 198struct clk *ti_clk_register_clk(struct ti_clk *setup);
170int ti_clk_register_legacy_clks(struct ti_clk_alias *clks); 199int ti_clk_register_legacy_clks(struct ti_clk_alias *clks);
171 200
201void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
202void ti_dt_clocks_register(struct ti_dt_clk *oclks);
203int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
204 ti_of_clk_init_cb_t func);
205int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
206
207void omap2_init_clk_hw_omap_clocks(struct clk *clk);
208int of_ti_clk_autoidle_setup(struct device_node *node);
209void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
210
211extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
212extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
213extern const struct clk_hw_omap_ops clkhwops_wait;
214extern const struct clk_hw_omap_ops clkhwops_iclk;
215extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
216extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
217extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
218extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
219extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
220extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
221extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
222extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
223
224extern const struct clk_ops ti_clk_divider_ops;
225extern const struct clk_ops ti_clk_mux_ops;
226
227int omap2_clkops_enable_clkdm(struct clk_hw *hw);
228void omap2_clkops_disable_clkdm(struct clk_hw *hw);
229
230int omap2_dflt_clk_enable(struct clk_hw *hw);
231void omap2_dflt_clk_disable(struct clk_hw *hw);
232int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
233void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
234 void __iomem **other_reg,
235 u8 *other_bit);
236void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
237 void __iomem **idlest_reg,
238 u8 *idlest_bit, u8 *idlest_val);
239
240void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
241void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
242
243u8 omap2_init_dpll_parent(struct clk_hw *hw);
244int omap3_noncore_dpll_enable(struct clk_hw *hw);
245void omap3_noncore_dpll_disable(struct clk_hw *hw);
246int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index);
247int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
248 unsigned long parent_rate);
249int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
250 unsigned long rate,
251 unsigned long parent_rate,
252 u8 index);
253int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
254 struct clk_rate_request *req);
255long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
256 unsigned long *parent_rate);
257unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
258 unsigned long parent_rate);
259
260unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
261int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
262 unsigned long parent_rate);
263int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
264 unsigned long parent_rate, u8 index);
265void omap3_clk_lock_dpll5(void);
266
267unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
268 unsigned long parent_rate);
269long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
270 unsigned long target_rate,
271 unsigned long *parent_rate);
272int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
273 struct clk_rate_request *req);
274
275extern struct ti_clk_ll_ops *ti_clk_ll_ops;
276
172#endif 277#endif
diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
index b82ef07f3403..fc517453321b 100644
--- a/drivers/clk/ti/clockdomain.c
+++ b/drivers/clk/ti/clockdomain.c
@@ -21,9 +21,87 @@
21#include <linux/of_address.h> 21#include <linux/of_address.h>
22#include <linux/clk/ti.h> 22#include <linux/clk/ti.h>
23 23
24#include "clock.h"
25
24#undef pr_fmt 26#undef pr_fmt
25#define pr_fmt(fmt) "%s: " fmt, __func__ 27#define pr_fmt(fmt) "%s: " fmt, __func__
26 28
29/**
30 * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
31 * @hw: struct clk_hw * of the clock being enabled
32 *
33 * Increment the usecount of the clockdomain of the clock pointed to
34 * by @hw; if the usecount is 1, the clockdomain will be "enabled."
35 * Only needed for clocks that don't use omap2_dflt_clk_enable() as
36 * their enable function pointer. Passes along the return value of
37 * clkdm_clk_enable(), -EINVAL if @hw is not associated with a
38 * clockdomain, or 0 if clock framework-based clockdomain control is
39 * not implemented.
40 */
41int omap2_clkops_enable_clkdm(struct clk_hw *hw)
42{
43 struct clk_hw_omap *clk;
44 int ret = 0;
45
46 clk = to_clk_hw_omap(hw);
47
48 if (unlikely(!clk->clkdm)) {
49 pr_err("%s: %s: no clkdm set ?!\n", __func__,
50 __clk_get_name(hw->clk));
51 return -EINVAL;
52 }
53
54 if (unlikely(clk->enable_reg))
55 pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
56 __clk_get_name(hw->clk));
57
58 if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
59 pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
60 __func__, __clk_get_name(hw->clk));
61 return 0;
62 }
63
64 ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
65 WARN(ret, "%s: could not enable %s's clockdomain %s: %d\n",
66 __func__, __clk_get_name(hw->clk), clk->clkdm_name, ret);
67
68 return ret;
69}
70
71/**
72 * omap2_clkops_disable_clkdm - decrement usecount on clkdm of @hw
73 * @hw: struct clk_hw * of the clock being disabled
74 *
75 * Decrement the usecount of the clockdomain of the clock pointed to
76 * by @hw; if the usecount is 0, the clockdomain will be "disabled."
77 * Only needed for clocks that don't use omap2_dflt_clk_disable() as their
78 * disable function pointer. No return value.
79 */
80void omap2_clkops_disable_clkdm(struct clk_hw *hw)
81{
82 struct clk_hw_omap *clk;
83
84 clk = to_clk_hw_omap(hw);
85
86 if (unlikely(!clk->clkdm)) {
87 pr_err("%s: %s: no clkdm set ?!\n", __func__,
88 __clk_get_name(hw->clk));
89 return;
90 }
91
92 if (unlikely(clk->enable_reg))
93 pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
94 __clk_get_name(hw->clk));
95
96 if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
97 pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
98 __func__, __clk_get_name(hw->clk));
99 return;
100 }
101
102 ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
103}
104
27static void __init of_ti_clockdomain_setup(struct device_node *node) 105static void __init of_ti_clockdomain_setup(struct device_node *node)
28{ 106{
29 struct clk *clk; 107 struct clk *clk;
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c
index 8c57ace30421..b0aa87b35f24 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/drivers/clk/ti/dpll3xxx.c
@@ -27,8 +27,8 @@
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/bitops.h> 28#include <linux/bitops.h>
29#include <linux/clkdev.h> 29#include <linux/clkdev.h>
30#include <linux/clk/ti.h>
30 31
31#include "clockdomain.h"
32#include "clock.h" 32#include "clock.h"
33 33
34/* CM_AUTOIDLE_PLL*.AUTO_* bit values */ 34/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
@@ -37,6 +37,13 @@
37 37
38#define MAX_DPLL_WAIT_TRIES 1000000 38#define MAX_DPLL_WAIT_TRIES 1000000
39 39
40#define OMAP3XXX_EN_DPLL_LOCKED 0x7
41
42/* Forward declarations */
43static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk);
44static void omap3_dpll_deny_idle(struct clk_hw_omap *clk);
45static void omap3_dpll_allow_idle(struct clk_hw_omap *clk);
46
40/* Private functions */ 47/* Private functions */
41 48
42/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */ 49/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
@@ -47,10 +54,10 @@ static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
47 54
48 dd = clk->dpll_data; 55 dd = clk->dpll_data;
49 56
50 v = omap2_clk_readl(clk, dd->control_reg); 57 v = ti_clk_ll_ops->clk_readl(dd->control_reg);
51 v &= ~dd->enable_mask; 58 v &= ~dd->enable_mask;
52 v |= clken_bits << __ffs(dd->enable_mask); 59 v |= clken_bits << __ffs(dd->enable_mask);
53 omap2_clk_writel(v, clk, dd->control_reg); 60 ti_clk_ll_ops->clk_writel(v, dd->control_reg);
54} 61}
55 62
56/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */ 63/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
@@ -66,14 +73,14 @@ static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
66 73
67 state <<= __ffs(dd->idlest_mask); 74 state <<= __ffs(dd->idlest_mask);
68 75
69 while (((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask) 76 while (((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask)
70 != state) && i < MAX_DPLL_WAIT_TRIES) { 77 != state) && i < MAX_DPLL_WAIT_TRIES) {
71 i++; 78 i++;
72 udelay(1); 79 udelay(1);
73 } 80 }
74 81
75 if (i == MAX_DPLL_WAIT_TRIES) { 82 if (i == MAX_DPLL_WAIT_TRIES) {
76 printk(KERN_ERR "clock: %s failed transition to '%s'\n", 83 pr_err("clock: %s failed transition to '%s'\n",
77 clk_name, (state) ? "locked" : "bypassed"); 84 clk_name, (state) ? "locked" : "bypassed");
78 } else { 85 } else {
79 pr_debug("clock: %s transition to '%s' in %d loops\n", 86 pr_debug("clock: %s transition to '%s' in %d loops\n",
@@ -144,7 +151,8 @@ static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
144 state <<= __ffs(dd->idlest_mask); 151 state <<= __ffs(dd->idlest_mask);
145 152
146 /* Check if already locked */ 153 /* Check if already locked */
147 if ((omap2_clk_readl(clk, dd->idlest_reg) & dd->idlest_mask) == state) 154 if ((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask) ==
155 state)
148 goto done; 156 goto done;
149 157
150 ai = omap3_dpll_autoidle_read(clk); 158 ai = omap3_dpll_autoidle_read(clk);
@@ -307,15 +315,15 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
307 * Set jitter correction. Jitter correction applicable for OMAP343X 315 * Set jitter correction. Jitter correction applicable for OMAP343X
308 * only since freqsel field is no longer present on other devices. 316 * only since freqsel field is no longer present on other devices.
309 */ 317 */
310 if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) { 318 if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
311 v = omap2_clk_readl(clk, dd->control_reg); 319 v = ti_clk_ll_ops->clk_readl(dd->control_reg);
312 v &= ~dd->freqsel_mask; 320 v &= ~dd->freqsel_mask;
313 v |= freqsel << __ffs(dd->freqsel_mask); 321 v |= freqsel << __ffs(dd->freqsel_mask);
314 omap2_clk_writel(v, clk, dd->control_reg); 322 ti_clk_ll_ops->clk_writel(v, dd->control_reg);
315 } 323 }
316 324
317 /* Set DPLL multiplier, divider */ 325 /* Set DPLL multiplier, divider */
318 v = omap2_clk_readl(clk, dd->mult_div1_reg); 326 v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg);
319 327
320 /* Handle Duty Cycle Correction */ 328 /* Handle Duty Cycle Correction */
321 if (dd->dcc_mask) { 329 if (dd->dcc_mask) {
@@ -342,11 +350,11 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
342 v |= sd_div << __ffs(dd->sddiv_mask); 350 v |= sd_div << __ffs(dd->sddiv_mask);
343 } 351 }
344 352
345 omap2_clk_writel(v, clk, dd->mult_div1_reg); 353 ti_clk_ll_ops->clk_writel(v, dd->mult_div1_reg);
346 354
347 /* Set 4X multiplier and low-power mode */ 355 /* Set 4X multiplier and low-power mode */
348 if (dd->m4xen_mask || dd->lpmode_mask) { 356 if (dd->m4xen_mask || dd->lpmode_mask) {
349 v = omap2_clk_readl(clk, dd->control_reg); 357 v = ti_clk_ll_ops->clk_readl(dd->control_reg);
350 358
351 if (dd->m4xen_mask) { 359 if (dd->m4xen_mask) {
352 if (dd->last_rounded_m4xen) 360 if (dd->last_rounded_m4xen)
@@ -362,7 +370,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
362 v &= ~dd->lpmode_mask; 370 v &= ~dd->lpmode_mask;
363 } 371 }
364 372
365 omap2_clk_writel(v, clk, dd->control_reg); 373 ti_clk_ll_ops->clk_writel(v, dd->control_reg);
366 } 374 }
367 375
368 /* We let the clock framework set the other output dividers later */ 376 /* We let the clock framework set the other output dividers later */
@@ -417,12 +425,12 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
417 return -EINVAL; 425 return -EINVAL;
418 426
419 if (clk->clkdm) { 427 if (clk->clkdm) {
420 r = clkdm_clk_enable(clk->clkdm, hw->clk); 428 r = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
421 if (r) { 429 if (r) {
422 WARN(1, 430 WARN(1,
423 "%s: could not enable %s's clockdomain %s: %d\n", 431 "%s: could not enable %s's clockdomain %s: %d\n",
424 __func__, __clk_get_name(hw->clk), 432 __func__, __clk_get_name(hw->clk),
425 clk->clkdm->name, r); 433 clk->clkdm_name, r);
426 return r; 434 return r;
427 } 435 }
428 } 436 }
@@ -453,10 +461,9 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
453 461
454 _omap3_noncore_dpll_stop(clk); 462 _omap3_noncore_dpll_stop(clk);
455 if (clk->clkdm) 463 if (clk->clkdm)
456 clkdm_clk_disable(clk->clkdm, hw->clk); 464 ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
457} 465}
458 466
459
460/* Non-CORE DPLL rate set code */ 467/* Non-CORE DPLL rate set code */
461 468
462/** 469/**
@@ -554,7 +561,7 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
554 return -EINVAL; 561 return -EINVAL;
555 562
556 /* Freqsel is available only on OMAP343X devices */ 563 /* Freqsel is available only on OMAP343X devices */
557 if (ti_clk_features.flags & TI_CLK_DPLL_HAS_FREQSEL) { 564 if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
558 freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n); 565 freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
559 WARN_ON(!freqsel); 566 WARN_ON(!freqsel);
560 } 567 }
@@ -613,7 +620,7 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
613 * -EINVAL if passed a null pointer or if the struct clk does not 620 * -EINVAL if passed a null pointer or if the struct clk does not
614 * appear to refer to a DPLL. 621 * appear to refer to a DPLL.
615 */ 622 */
616u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk) 623static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
617{ 624{
618 const struct dpll_data *dd; 625 const struct dpll_data *dd;
619 u32 v; 626 u32 v;
@@ -626,7 +633,7 @@ u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
626 if (!dd->autoidle_reg) 633 if (!dd->autoidle_reg)
627 return -EINVAL; 634 return -EINVAL;
628 635
629 v = omap2_clk_readl(clk, dd->autoidle_reg); 636 v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
630 v &= dd->autoidle_mask; 637 v &= dd->autoidle_mask;
631 v >>= __ffs(dd->autoidle_mask); 638 v >>= __ffs(dd->autoidle_mask);
632 639
@@ -642,7 +649,7 @@ u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
642 * OMAP3430. The DPLL will enter low-power stop when its downstream 649 * OMAP3430. The DPLL will enter low-power stop when its downstream
643 * clocks are gated. No return value. 650 * clocks are gated. No return value.
644 */ 651 */
645void omap3_dpll_allow_idle(struct clk_hw_omap *clk) 652static void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
646{ 653{
647 const struct dpll_data *dd; 654 const struct dpll_data *dd;
648 u32 v; 655 u32 v;
@@ -660,11 +667,10 @@ void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
660 * by writing 0x5 instead of 0x1. Add some mechanism to 667 * by writing 0x5 instead of 0x1. Add some mechanism to
661 * optionally enter this mode. 668 * optionally enter this mode.
662 */ 669 */
663 v = omap2_clk_readl(clk, dd->autoidle_reg); 670 v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
664 v &= ~dd->autoidle_mask; 671 v &= ~dd->autoidle_mask;
665 v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask); 672 v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
666 omap2_clk_writel(v, clk, dd->autoidle_reg); 673 ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
667
668} 674}
669 675
670/** 676/**
@@ -673,7 +679,7 @@ void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
673 * 679 *
674 * Disable DPLL automatic idle control. No return value. 680 * Disable DPLL automatic idle control. No return value.
675 */ 681 */
676void omap3_dpll_deny_idle(struct clk_hw_omap *clk) 682static void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
677{ 683{
678 const struct dpll_data *dd; 684 const struct dpll_data *dd;
679 u32 v; 685 u32 v;
@@ -686,11 +692,10 @@ void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
686 if (!dd->autoidle_reg) 692 if (!dd->autoidle_reg)
687 return; 693 return;
688 694
689 v = omap2_clk_readl(clk, dd->autoidle_reg); 695 v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
690 v &= ~dd->autoidle_mask; 696 v &= ~dd->autoidle_mask;
691 v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask); 697 v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
692 omap2_clk_writel(v, clk, dd->autoidle_reg); 698 ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
693
694} 699}
695 700
696/* Clock control for DPLL outputs */ 701/* Clock control for DPLL outputs */
@@ -748,7 +753,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
748 753
749 WARN_ON(!dd->enable_mask); 754 WARN_ON(!dd->enable_mask);
750 755
751 v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask; 756 v = ti_clk_ll_ops->clk_readl(dd->control_reg) & dd->enable_mask;
752 v >>= __ffs(dd->enable_mask); 757 v >>= __ffs(dd->enable_mask);
753 if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE)) 758 if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
754 rate = parent_rate; 759 rate = parent_rate;
@@ -757,57 +762,59 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
757 return rate; 762 return rate;
758} 763}
759 764
760int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate, 765/* OMAP3/4 non-CORE DPLL clkops */
761 unsigned long parent_rate) 766const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
762{ 767 .allow_idle = omap3_dpll_allow_idle,
763 return 0; 768 .deny_idle = omap3_dpll_deny_idle,
764} 769};
765 770
766long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate, 771/**
767 unsigned long *prate) 772 * omap3_dpll4_set_rate - set rate for omap3 per-dpll
773 * @hw: clock to change
774 * @rate: target rate for clock
775 * @parent_rate: rate of the parent clock
776 *
777 * Check if the current SoC supports the per-dpll reprogram operation
778 * or not, and then do the rate change if supported. Returns -EINVAL
779 * if not supported, 0 for success, and potential error codes from the
780 * clock rate change.
781 */
782int omap3_dpll4_set_rate(struct clk_hw *hw, unsigned long rate,
783 unsigned long parent_rate)
768{ 784{
769 const struct dpll_data *dd; 785 /*
770 u32 v; 786 * According to the 12-5 CDP code from TI, "Limitation 2.5"
771 struct clk_hw_omap *pclk = NULL; 787 * on 3430ES1 prevents us from changing DPLL multipliers or dividers
772 788 * on DPLL4.
773 if (!*prate) 789 */
774 return 0; 790 if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
775 791 pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
776 pclk = omap3_find_clkoutx2_dpll(hw); 792 return -EINVAL;
777
778 if (!pclk)
779 return 0;
780
781 dd = pclk->dpll_data;
782
783 /* TYPE J does not have a clkoutx2 */
784 if (dd->flags & DPLL_J_TYPE) {
785 *prate = __clk_round_rate(__clk_get_parent(pclk->hw.clk), rate);
786 return *prate;
787 } 793 }
788 794
789 WARN_ON(!dd->enable_mask); 795 return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
790 796}
791 v = omap2_clk_readl(pclk, dd->control_reg) & dd->enable_mask;
792 v >>= __ffs(dd->enable_mask);
793
794 /* If in bypass, the rate is fixed to the bypass rate*/
795 if (v != OMAP3XXX_EN_DPLL_LOCKED)
796 return *prate;
797
798 if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
799 unsigned long best_parent;
800 797
801 best_parent = (rate / 2); 798/**
802 *prate = __clk_round_rate(__clk_get_parent(hw->clk), 799 * omap3_dpll4_set_rate_and_parent - set rate and parent for omap3 per-dpll
803 best_parent); 800 * @hw: clock to change
801 * @rate: target rate for clock
802 * @parent_rate: rate of the parent clock
803 * @index: parent index, 0 - reference clock, 1 - bypass clock
804 *
805 * Check if the current SoC support the per-dpll reprogram operation
806 * or not, and then do the rate + parent change if supported. Returns
807 * -EINVAL if not supported, 0 for success, and potential error codes
808 * from the clock rate change.
809 */
810int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
811 unsigned long parent_rate, u8 index)
812{
813 if (ti_clk_get_features()->flags & TI_CLK_DPLL4_DENY_REPROGRAM) {
814 pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
815 return -EINVAL;
804 } 816 }
805 817
806 return *prate * 2; 818 return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
819 index);
807} 820}
808
809/* OMAP3/4 non-CORE DPLL clkops */
810const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
811 .allow_idle = omap3_dpll_allow_idle,
812 .deny_idle = omap3_dpll_deny_idle,
813};
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/drivers/clk/ti/dpll44xx.c
index 446a4e0d5a6a..73af77a90586 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/drivers/clk/ti/dpll44xx.c
@@ -14,6 +14,7 @@
14#include <linux/clk.h> 14#include <linux/clk.h>
15#include <linux/io.h> 15#include <linux/io.h>
16#include <linux/bitops.h> 16#include <linux/bitops.h>
17#include <linux/clk/ti.h>
17 18
18#include "clock.h" 19#include "clock.h"
19 20
@@ -29,14 +30,14 @@
29/* 30/*
30 * Bitfield declarations 31 * Bitfield declarations
31 */ 32 */
32#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK (1 << 8) 33#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK BIT(8)
33#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK (1 << 10) 34#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK BIT(10)
34#define OMAP4430_DPLL_REGM4XEN_MASK (1 << 11) 35#define OMAP4430_DPLL_REGM4XEN_MASK BIT(11)
35 36
36/* Static rate multiplier for OMAP4 REGM4XEN clocks */ 37/* Static rate multiplier for OMAP4 REGM4XEN clocks */
37#define OMAP4430_REGM4XEN_MULT 4 38#define OMAP4430_REGM4XEN_MULT 4
38 39
39void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk) 40static void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
40{ 41{
41 u32 v; 42 u32 v;
42 u32 mask; 43 u32 mask;
@@ -48,13 +49,13 @@ void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
48 OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : 49 OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
49 OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; 50 OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
50 51
51 v = omap2_clk_readl(clk, clk->clksel_reg); 52 v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
52 /* Clear the bit to allow gatectrl */ 53 /* Clear the bit to allow gatectrl */
53 v &= ~mask; 54 v &= ~mask;
54 omap2_clk_writel(v, clk, clk->clksel_reg); 55 ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
55} 56}
56 57
57void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk) 58static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
58{ 59{
59 u32 v; 60 u32 v;
60 u32 mask; 61 u32 mask;
@@ -66,10 +67,10 @@ void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
66 OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : 67 OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
67 OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; 68 OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
68 69
69 v = omap2_clk_readl(clk, clk->clksel_reg); 70 v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
70 /* Set the bit to deny gatectrl */ 71 /* Set the bit to deny gatectrl */
71 v |= mask; 72 v |= mask;
72 omap2_clk_writel(v, clk, clk->clksel_reg); 73 ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
73} 74}
74 75
75const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = { 76const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
@@ -112,7 +113,7 @@ static void omap4_dpll_lpmode_recalc(struct dpll_data *dd)
112 * upon success, or 0 upon error. 113 * upon success, or 0 upon error.
113 */ 114 */
114unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, 115unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
115 unsigned long parent_rate) 116 unsigned long parent_rate)
116{ 117{
117 struct clk_hw_omap *clk = to_clk_hw_omap(hw); 118 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
118 u32 v; 119 u32 v;
@@ -127,7 +128,7 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
127 rate = omap2_get_dpll_rate(clk); 128 rate = omap2_get_dpll_rate(clk);
128 129
129 /* regm4xen adds a multiplier of 4 to DPLL calculations */ 130 /* regm4xen adds a multiplier of 4 to DPLL calculations */
130 v = omap2_clk_readl(clk, dd->control_reg); 131 v = ti_clk_ll_ops->clk_readl(dd->control_reg);
131 if (v & OMAP4430_DPLL_REGM4XEN_MASK) 132 if (v & OMAP4430_DPLL_REGM4XEN_MASK)
132 rate *= OMAP4430_REGM4XEN_MULT; 133 rate *= OMAP4430_REGM4XEN_MULT;
133 134
diff --git a/drivers/clk/ti/fixed-factor.c b/drivers/clk/ti/fixed-factor.c
index c2c8a287408c..3cd406768909 100644
--- a/drivers/clk/ti/fixed-factor.c
+++ b/drivers/clk/ti/fixed-factor.c
@@ -22,6 +22,8 @@
22#include <linux/of_address.h> 22#include <linux/of_address.h>
23#include <linux/clk/ti.h> 23#include <linux/clk/ti.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
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 448b4f87b9eb..9299222d680d 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -188,33 +188,6 @@ struct clk_hw_omap {
188/* DPLL Type and DCO Selection Flags */ 188/* DPLL Type and DCO Selection Flags */
189#define DPLL_J_TYPE 0x1 189#define DPLL_J_TYPE 0x1
190 190
191/* Composite clock component types */
192enum {
193 CLK_COMPONENT_TYPE_GATE = 0,
194 CLK_COMPONENT_TYPE_DIVIDER,
195 CLK_COMPONENT_TYPE_MUX,
196 CLK_COMPONENT_TYPE_MAX,
197};
198
199/**
200 * struct ti_dt_clk - OMAP DT clock alias declarations
201 * @lk: clock lookup definition
202 * @node_name: clock DT node to map to
203 */
204struct ti_dt_clk {
205 struct clk_lookup lk;
206 char *node_name;
207};
208
209#define DT_CLK(dev, con, name) \
210 { \
211 .lk = { \
212 .dev_id = dev, \
213 .con_id = con, \
214 }, \
215 .node_name = name, \
216 }
217
218/* Static memmap indices */ 191/* Static memmap indices */
219enum { 192enum {
220 TI_CLKM_CM = 0, 193 TI_CLKM_CM = 0,
@@ -225,8 +198,6 @@ enum {
225 CLK_MAX_MEMMAPS 198 CLK_MAX_MEMMAPS
226}; 199};
227 200
228typedef void (*ti_of_clk_init_cb_t)(struct clk_hw *, struct device_node *);
229
230/** 201/**
231 * struct clk_omap_reg - OMAP register declaration 202 * struct clk_omap_reg - OMAP register declaration
232 * @offset: offset from the master IP module base address 203 * @offset: offset from the master IP module base address
@@ -238,85 +209,56 @@ struct clk_omap_reg {
238}; 209};
239 210
240/** 211/**
241 * struct ti_clk_ll_ops - low-level register access ops for a clock 212 * struct ti_clk_ll_ops - low-level ops for clocks
242 * @clk_readl: pointer to register read function 213 * @clk_readl: pointer to register read function
243 * @clk_writel: pointer to register write function 214 * @clk_writel: pointer to register write function
215 * @clkdm_clk_enable: pointer to clockdomain enable function
216 * @clkdm_clk_disable: pointer to clockdomain disable function
217 * @cm_wait_module_ready: pointer to CM module wait ready function
218 * @cm_split_idlest_reg: pointer to CM module function to split idlest reg
244 * 219 *
245 * Low-level register access ops are generally used by the basic clock types 220 * Low-level ops are generally used by the basic clock types (clk-gate,
246 * (clk-gate, clk-mux, clk-divider etc.) to provide support for various 221 * clk-mux, clk-divider etc.) to provide support for various low-level
247 * low-level hardware interfaces (direct MMIO, regmap etc.), but can also be 222 * hadrware interfaces (direct MMIO, regmap etc.), and is initialized
248 * used by other hardware-specific clock drivers if needed. 223 * by board code. Low-level ops also contain some other platform specific
224 * operations not provided directly by clock drivers.
249 */ 225 */
250struct ti_clk_ll_ops { 226struct ti_clk_ll_ops {
251 u32 (*clk_readl)(void __iomem *reg); 227 u32 (*clk_readl)(void __iomem *reg);
252 void (*clk_writel)(u32 val, void __iomem *reg); 228 void (*clk_writel)(u32 val, void __iomem *reg);
229 int (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk);
230 int (*clkdm_clk_disable)(struct clockdomain *clkdm,
231 struct clk *clk);
232 int (*cm_wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg,
233 u8 idlest_shift);
234 int (*cm_split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
235 u8 *idlest_reg_id);
253}; 236};
254 237
255extern struct ti_clk_ll_ops *ti_clk_ll_ops;
256
257extern const struct clk_ops ti_clk_divider_ops;
258extern const struct clk_ops ti_clk_mux_ops;
259
260#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw) 238#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
261 239
262void omap2_init_clk_hw_omap_clocks(struct clk *clk);
263int omap3_noncore_dpll_enable(struct clk_hw *hw);
264void omap3_noncore_dpll_disable(struct clk_hw *hw);
265int omap3_noncore_dpll_set_parent(struct clk_hw *hw, u8 index);
266int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
267 unsigned long parent_rate);
268int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
269 unsigned long rate,
270 unsigned long parent_rate,
271 u8 index);
272int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
273 struct clk_rate_request *req);
274unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
275 unsigned long parent_rate);
276long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
277 unsigned long target_rate,
278 unsigned long *parent_rate);
279int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
280 struct clk_rate_request *req);
281u8 omap2_init_dpll_parent(struct clk_hw *hw);
282unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
283long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
284 unsigned long *parent_rate);
285void omap2_init_clk_clkdm(struct clk_hw *clk); 240void omap2_init_clk_clkdm(struct clk_hw *clk);
286unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
287 unsigned long parent_rate);
288int omap3_clkoutx2_set_rate(struct clk_hw *hw, unsigned long rate,
289 unsigned long parent_rate);
290long omap3_clkoutx2_round_rate(struct clk_hw *hw, unsigned long rate,
291 unsigned long *prate);
292int omap2_clkops_enable_clkdm(struct clk_hw *hw);
293void omap2_clkops_disable_clkdm(struct clk_hw *hw);
294int omap2_clk_disable_autoidle_all(void); 241int omap2_clk_disable_autoidle_all(void);
295void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks); 242int omap2_clk_enable_autoidle_all(void);
296int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate, 243int omap2_clk_allow_idle(struct clk *clk);
297 unsigned long parent_rate); 244int omap2_clk_deny_idle(struct clk *clk);
298int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
299 unsigned long parent_rate, u8 index);
300int omap2_dflt_clk_enable(struct clk_hw *hw);
301void omap2_dflt_clk_disable(struct clk_hw *hw);
302int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
303void omap3_clk_lock_dpll5(void);
304unsigned long omap2_dpllcore_recalc(struct clk_hw *hw, 245unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
305 unsigned long parent_rate); 246 unsigned long parent_rate);
306int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate, 247int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
307 unsigned long parent_rate); 248 unsigned long parent_rate);
308void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw); 249void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
309void omap2xxx_clkt_vps_init(void); 250void omap2xxx_clkt_vps_init(void);
251unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk);
310 252
311void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
312void ti_dt_clocks_register(struct ti_dt_clk *oclks);
313void ti_dt_clk_init_provider(struct device_node *np, int index);
314void ti_dt_clk_init_retry_clks(void); 253void ti_dt_clk_init_retry_clks(void);
315void ti_dt_clockdomains_setup(void); 254void ti_dt_clockdomains_setup(void);
316int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw, 255int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops);
317 ti_of_clk_init_cb_t func); 256
318int of_ti_clk_autoidle_setup(struct device_node *node); 257struct regmap;
319int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type); 258
259int omap2_clk_provider_init(struct device_node *parent, int index,
260 struct regmap *syscon, void __iomem *mem);
261void omap2_clk_legacy_provider_init(int index, void __iomem *mem);
320 262
321int omap3430_dt_clk_init(void); 263int omap3430_dt_clk_init(void);
322int omap3630_dt_clk_init(void); 264int omap3630_dt_clk_init(void);
@@ -330,27 +272,24 @@ int am43xx_dt_clk_init(void);
330int omap2420_dt_clk_init(void); 272int omap2420_dt_clk_init(void);
331int omap2430_dt_clk_init(void); 273int omap2430_dt_clk_init(void);
332 274
333#ifdef CONFIG_OF 275struct ti_clk_features {
334void of_ti_clk_allow_autoidle_all(void); 276 u32 flags;
335void of_ti_clk_deny_autoidle_all(void); 277 long fint_min;
336#else 278 long fint_max;
337static inline void of_ti_clk_allow_autoidle_all(void) { } 279 long fint_band1_max;
338static inline void of_ti_clk_deny_autoidle_all(void) { } 280 long fint_band2_min;
339#endif 281 u8 dpll_bypass_vals;
282 u8 cm_idlest_val;
283};
284
285#define TI_CLK_DPLL_HAS_FREQSEL BIT(0)
286#define TI_CLK_DPLL4_DENY_REPROGRAM BIT(1)
287#define TI_CLK_DISABLE_CLKDM_CONTROL BIT(2)
288
289void ti_clk_setup_features(struct ti_clk_features *features);
290const struct ti_clk_features *ti_clk_get_features(void);
340 291
341extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll; 292extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
342extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
343extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
344extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
345extern const struct clk_hw_omap_ops clkhwops_wait;
346extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
347extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
348extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
349extern const struct clk_hw_omap_ops clkhwops_iclk;
350extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
351extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait;
352extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait;
353extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait;
354 293
355#ifdef CONFIG_ATAGS 294#ifdef CONFIG_ATAGS
356int omap3430_clk_legacy_init(void); 295int omap3430_clk_legacy_init(void);