aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2015-03-03 08:28:53 -0500
committerTero Kristo <t-kristo@ti.com>2015-06-02 05:31:22 -0400
commit9f37e90efaf0772b8f98bc347b9db77a3f0c27eb (patch)
tree7a3b08e65e085952b5dd45442a22635718501c19
parent046b7c31668311942a2e431e7983d8ab9874d845 (diff)
clk: ti: dflt: move support for default gate clock to clock driver
With the legacy support gone, OMAP2+ default gate clock can be moved under clock driver. Create a new file for the purpose, and clean-up the header exports a bit as some clock APIs are no longer needed outside clock driver itself. Signed-off-by: Tero Kristo <t-kristo@ti.com>
-rw-r--r--arch/arm/mach-omap2/clock.c273
-rw-r--r--drivers/clk/ti/Makefile2
-rw-r--r--drivers/clk/ti/clkt_dflt.c316
-rw-r--r--drivers/clk/ti/clock.h5
-rw-r--r--include/linux/clk/ti.h4
5 files changed, 322 insertions, 278 deletions
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 6c17adf40e6f..38a336b4c42b 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -40,12 +40,6 @@
40#include "cm-regbits-34xx.h" 40#include "cm-regbits-34xx.h"
41#include "common.h" 41#include "common.h"
42 42
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; 43u16 cpu_mask;
50 44
51/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */ 45/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
@@ -176,77 +170,6 @@ void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
176 170
177/* Private functions */ 171/* Private functions */
178 172
179
180/**
181 * _wait_idlest_generic - wait for a module to leave the idle state
182 * @clk: module clock to wait for (needed for register offsets)
183 * @reg: virtual address of module IDLEST register
184 * @mask: value to mask against to determine if the module is active
185 * @idlest: idle state indicator (0 or 1) for the clock
186 * @name: name of the clock (for printk)
187 *
188 * Wait for a module to leave idle, where its idle-status register is
189 * not inside the CM module. Returns 1 if the module left idle
190 * promptly, or 0 if the module did not leave idle before the timeout
191 * elapsed. XXX Deprecated - should be moved into drivers for the
192 * individual IP block that the IDLEST register exists in.
193 */
194static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
195 u32 mask, u8 idlest, const char *name)
196{
197 int i = 0, ena = 0;
198
199 ena = (idlest) ? 0 : mask;
200
201 omap_test_timeout(((omap2_clk_readl(clk, reg) & mask) == ena),
202 MAX_MODULE_ENABLE_WAIT, i);
203
204 if (i < MAX_MODULE_ENABLE_WAIT)
205 pr_debug("omap clock: module associated with clock %s ready after %d loops\n",
206 name, i);
207 else
208 pr_err("omap clock: module associated with clock %s didn't enable in %d tries\n",
209 name, MAX_MODULE_ENABLE_WAIT);
210
211 return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
212};
213
214/**
215 * _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
216 * @clk: struct clk * belonging to the module
217 *
218 * If the necessary clocks for the OMAP hardware IP block that
219 * corresponds to clock @clk are enabled, then wait for the module to
220 * indicate readiness (i.e., to leave IDLE). This code does not
221 * belong in the clock code and will be moved in the medium term to
222 * module-dependent code. No return value.
223 */
224static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
225{
226 void __iomem *companion_reg, *idlest_reg;
227 u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
228 s16 prcm_mod;
229 int r;
230
231 /* Not all modules have multiple clocks that their IDLEST depends on */
232 if (clk->ops->find_companion) {
233 clk->ops->find_companion(clk, &companion_reg, &other_bit);
234 if (!(omap2_clk_readl(clk, companion_reg) & (1 << other_bit)))
235 return;
236 }
237
238 clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
239 r = cm_split_idlest_reg(idlest_reg, &prcm_mod, &idlest_reg_id);
240 if (r) {
241 /* IDLEST register not in the CM module */
242 _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
243 idlest_val, __clk_get_name(clk->hw.clk));
244 } else {
245 omap_cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
246 idlest_bit);
247 };
248}
249
250/* Public functions */ 173/* Public functions */
251 174
252/** 175/**
@@ -280,174 +203,6 @@ void omap2_init_clk_clkdm(struct clk_hw *hw)
280} 203}
281 204
282/** 205/**
283 * omap2_clk_dflt_find_companion - find companion clock to @clk
284 * @clk: struct clk * to find the companion clock of
285 * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
286 * @other_bit: u8 ** to return the companion clock bit shift in
287 *
288 * Note: We don't need special code here for INVERT_ENABLE for the
289 * time being since INVERT_ENABLE only applies to clocks enabled by
290 * CM_CLKEN_PLL
291 *
292 * Convert CM_ICLKEN* <-> CM_FCLKEN*. This conversion assumes it's
293 * just a matter of XORing the bits.
294 *
295 * Some clocks don't have companion clocks. For example, modules with
296 * only an interface clock (such as MAILBOXES) don't have a companion
297 * clock. Right now, this code relies on the hardware exporting a bit
298 * in the correct companion register that indicates that the
299 * nonexistent 'companion clock' is active. Future patches will
300 * associate this type of code with per-module data structures to
301 * avoid this issue, and remove the casts. No return value.
302 */
303void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
304 void __iomem **other_reg, u8 *other_bit)
305{
306 u32 r;
307
308 /*
309 * Convert CM_ICLKEN* <-> CM_FCLKEN*. This conversion assumes
310 * it's just a matter of XORing the bits.
311 */
312 r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
313
314 *other_reg = (__force void __iomem *)r;
315 *other_bit = clk->enable_bit;
316}
317
318/**
319 * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
320 * @clk: struct clk * to find IDLEST info for
321 * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
322 * @idlest_bit: u8 * to return the CM_IDLEST bit shift in
323 * @idlest_val: u8 * to return the idle status indicator
324 *
325 * Return the CM_IDLEST register address and bit shift corresponding
326 * to the module that "owns" this clock. This default code assumes
327 * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
328 * the IDLEST register address ID corresponds to the CM_*CLKEN
329 * register address ID (e.g., that CM_FCLKEN2 corresponds to
330 * CM_IDLEST2). This is not true for all modules. No return value.
331 */
332void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
333 void __iomem **idlest_reg, u8 *idlest_bit, u8 *idlest_val)
334{
335 u32 r;
336
337 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
338 *idlest_reg = (__force void __iomem *)r;
339 *idlest_bit = clk->enable_bit;
340
341 /*
342 * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
343 * 34xx reverses this, just to keep us on our toes
344 * AM35xx uses both, depending on the module.
345 */
346 *idlest_val = ti_clk_get_features()->cm_idlest_val;
347}
348
349/**
350 * omap2_dflt_clk_enable - enable a clock in the hardware
351 * @hw: struct clk_hw * of the clock to enable
352 *
353 * Enable the clock @hw in the hardware. We first call into the OMAP
354 * clockdomain code to "enable" the corresponding clockdomain if this
355 * is the first enabled user of the clockdomain. Then program the
356 * hardware to enable the clock. Then wait for the IP block that uses
357 * this clock to leave idle (if applicable). Returns the error value
358 * from clkdm_clk_enable() if it terminated with an error, or -EINVAL
359 * if @hw has a null clock enable_reg, or zero upon success.
360 */
361int omap2_dflt_clk_enable(struct clk_hw *hw)
362{
363 struct clk_hw_omap *clk;
364 u32 v;
365 int ret = 0;
366 bool clkdm_control;
367
368 if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL)
369 clkdm_control = false;
370 else
371 clkdm_control = true;
372
373 clk = to_clk_hw_omap(hw);
374
375 if (clkdm_control && clk->clkdm) {
376 ret = clkdm_clk_enable(clk->clkdm, hw->clk);
377 if (ret) {
378 WARN(1, "%s: could not enable %s's clockdomain %s: %d\n",
379 __func__, __clk_get_name(hw->clk),
380 clk->clkdm->name, ret);
381 return ret;
382 }
383 }
384
385 if (unlikely(clk->enable_reg == NULL)) {
386 pr_err("%s: %s missing enable_reg\n", __func__,
387 __clk_get_name(hw->clk));
388 ret = -EINVAL;
389 goto err;
390 }
391
392 /* FIXME should not have INVERT_ENABLE bit here */
393 v = omap2_clk_readl(clk, clk->enable_reg);
394 if (clk->flags & INVERT_ENABLE)
395 v &= ~(1 << clk->enable_bit);
396 else
397 v |= (1 << clk->enable_bit);
398 omap2_clk_writel(v, clk, clk->enable_reg);
399 v = omap2_clk_readl(clk, clk->enable_reg); /* OCP barrier */
400
401 if (clk->ops && clk->ops->find_idlest)
402 _omap2_module_wait_ready(clk);
403
404 return 0;
405
406err:
407 if (clkdm_control && clk->clkdm)
408 clkdm_clk_disable(clk->clkdm, hw->clk);
409 return ret;
410}
411
412/**
413 * omap2_dflt_clk_disable - disable a clock in the hardware
414 * @hw: struct clk_hw * of the clock to disable
415 *
416 * Disable the clock @hw in the hardware, and call into the OMAP
417 * clockdomain code to "disable" the corresponding clockdomain if all
418 * clocks/hwmods in that clockdomain are now disabled. No return
419 * value.
420 */
421void omap2_dflt_clk_disable(struct clk_hw *hw)
422{
423 struct clk_hw_omap *clk;
424 u32 v;
425
426 clk = to_clk_hw_omap(hw);
427 if (!clk->enable_reg) {
428 /*
429 * 'independent' here refers to a clock which is not
430 * controlled by its parent.
431 */
432 pr_err("%s: independent clock %s has no enable_reg\n",
433 __func__, __clk_get_name(hw->clk));
434 return;
435 }
436
437 v = omap2_clk_readl(clk, clk->enable_reg);
438 if (clk->flags & INVERT_ENABLE)
439 v |= (1 << clk->enable_bit);
440 else
441 v &= ~(1 << clk->enable_bit);
442 omap2_clk_writel(v, clk, clk->enable_reg);
443 /* No OCP barrier needed here since it is a disable operation */
444
445 if (!(ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) &&
446 clk->clkdm)
447 clkdm_clk_disable(clk->clkdm, hw->clk);
448}
449
450/**
451 * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw 206 * omap2_clkops_enable_clkdm - increment usecount on clkdm of @hw
452 * @hw: struct clk_hw * of the clock being enabled 207 * @hw: struct clk_hw * of the clock being enabled
453 * 208 *
@@ -523,29 +278,6 @@ void omap2_clkops_disable_clkdm(struct clk_hw *hw)
523 clkdm_clk_disable(clk->clkdm, hw->clk); 278 clkdm_clk_disable(clk->clkdm, hw->clk);
524} 279}
525 280
526/**
527 * omap2_dflt_clk_is_enabled - is clock enabled in the hardware?
528 * @hw: struct clk_hw * to check
529 *
530 * Return 1 if the clock represented by @hw is enabled in the
531 * hardware, or 0 otherwise. Intended for use in the struct
532 * clk_ops.is_enabled function pointer.
533 */
534int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
535{
536 struct clk_hw_omap *clk = to_clk_hw_omap(hw);
537 u32 v;
538
539 v = omap2_clk_readl(clk, clk->enable_reg);
540
541 if (clk->flags & INVERT_ENABLE)
542 v ^= BIT(clk->enable_bit);
543
544 v &= BIT(clk->enable_bit);
545
546 return v ? 1 : 0;
547}
548
549static int __initdata mpurate; 281static int __initdata mpurate;
550 282
551/* 283/*
@@ -566,11 +298,6 @@ static int __init omap_clk_setup(char *str)
566} 298}
567__setup("mpurate=", omap_clk_setup); 299__setup("mpurate=", omap_clk_setup);
568 300
569const struct clk_hw_omap_ops clkhwops_wait = {
570 .find_idlest = omap2_clk_dflt_find_idlest,
571 .find_companion = omap2_clk_dflt_find_companion,
572};
573
574/** 301/**
575 * omap2_clk_print_new_rates - print summary of current clock tree rates 302 * omap2_clk_print_new_rates - print summary of current clock tree rates
576 * @hfclkin_ck_name: clk name for the off-chip HF oscillator 303 * @hfclkin_ck_name: clk name for the off-chip HF oscillator
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile
index 05a0294aba10..9b93e6904359 100644
--- a/drivers/clk/ti/Makefile
+++ b/drivers/clk/ti/Makefile
@@ -1,7 +1,7 @@
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 \
4 clkt_dpll.o clkt_iclk.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_AM33XX) += $(clk-common) clk-33xx.o dpll3xxx.o
6obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-816x.o 6obj-$(CONFIG_SOC_TI81XX) += $(clk-common) fapll.o clk-816x.o
7obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o 7obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o
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/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 688d9e47b2c8..f21538364588 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -175,9 +175,14 @@ void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
175 175
176extern const struct clk_hw_omap_ops clkhwops_omap3_dpll; 176extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
177extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx; 177extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
178extern const struct clk_hw_omap_ops clkhwops_wait;
178extern const struct clk_hw_omap_ops clkhwops_iclk; 179extern const struct clk_hw_omap_ops clkhwops_iclk;
179extern const struct clk_hw_omap_ops clkhwops_iclk_wait; 180extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
180 181
182int omap2_dflt_clk_enable(struct clk_hw *hw);
183void omap2_dflt_clk_disable(struct clk_hw *hw);
184int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
185
181u8 omap2_init_dpll_parent(struct clk_hw *hw); 186u8 omap2_init_dpll_parent(struct clk_hw *hw);
182int omap3_noncore_dpll_enable(struct clk_hw *hw); 187int omap3_noncore_dpll_enable(struct clk_hw *hw);
183void omap3_noncore_dpll_disable(struct clk_hw *hw); 188void omap3_noncore_dpll_disable(struct clk_hw *hw);
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index fbb65e401d13..81a913edffa7 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -278,9 +278,6 @@ int omap2_clk_disable_autoidle_all(void);
278int omap2_clk_enable_autoidle_all(void); 278int omap2_clk_enable_autoidle_all(void);
279int omap2_clk_allow_idle(struct clk *clk); 279int omap2_clk_allow_idle(struct clk *clk);
280int omap2_clk_deny_idle(struct clk *clk); 280int omap2_clk_deny_idle(struct clk *clk);
281int omap2_dflt_clk_enable(struct clk_hw *hw);
282void omap2_dflt_clk_disable(struct clk_hw *hw);
283int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
284void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk); 281void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
285void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk); 282void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk);
286void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk, 283void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
@@ -337,7 +334,6 @@ const struct ti_clk_features *ti_clk_get_features(void);
337 334
338extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll; 335extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
339extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait; 336extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
340extern const struct clk_hw_omap_ops clkhwops_wait;
341extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait; 337extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait;
342extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait; 338extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
343extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait; 339extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;