]>
Commit | Line | Data |
---|---|---|
68b921ad RN |
1 | /* |
2 | * OMAP4 clockdomain control | |
3 | * | |
4 | * Copyright (C) 2008-2010 Texas Instruments, Inc. | |
5 | * Copyright (C) 2008-2010 Nokia Corporation | |
6 | * | |
7 | * Derived from mach-omap2/clockdomain.c written by Paul Walmsley | |
8 | * Rajendra Nayak <rnayak@ti.com> | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License version 2 as | |
12 | * published by the Free Software Foundation. | |
13 | */ | |
14 | ||
15b08d93 | 15 | #include <linux/kernel.h> |
68b921ad RN |
16 | #include "clockdomain.h" |
17 | #include "cminst44xx.h" | |
15b08d93 RN |
18 | #include "cm44xx.h" |
19 | ||
20 | static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1, | |
21 | struct clockdomain *clkdm2) | |
22 | { | |
23 | omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit), | |
24 | clkdm1->prcm_partition, | |
25 | clkdm1->cm_inst, clkdm1->clkdm_offs + | |
26 | OMAP4_CM_STATICDEP); | |
27 | return 0; | |
28 | } | |
29 | ||
30 | static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1, | |
31 | struct clockdomain *clkdm2) | |
32 | { | |
33 | omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit), | |
34 | clkdm1->prcm_partition, | |
35 | clkdm1->cm_inst, clkdm1->clkdm_offs + | |
36 | OMAP4_CM_STATICDEP); | |
37 | return 0; | |
38 | } | |
39 | ||
40 | static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1, | |
41 | struct clockdomain *clkdm2) | |
42 | { | |
43 | return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition, | |
44 | clkdm1->cm_inst, clkdm1->clkdm_offs + | |
45 | OMAP4_CM_STATICDEP, | |
46 | (1 << clkdm2->dep_bit)); | |
47 | } | |
48 | ||
49 | static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm) | |
50 | { | |
51 | struct clkdm_dep *cd; | |
52 | u32 mask = 0; | |
53 | ||
6ba5a69e PW |
54 | if (!clkdm->prcm_partition) |
55 | return 0; | |
56 | ||
15b08d93 | 57 | for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) { |
15b08d93 RN |
58 | if (!cd->clkdm) |
59 | continue; /* only happens if data is erroneous */ | |
60 | ||
61 | mask |= 1 << cd->clkdm->dep_bit; | |
62 | atomic_set(&cd->wkdep_usecount, 0); | |
63 | } | |
64 | ||
65 | omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition, | |
66 | clkdm->cm_inst, clkdm->clkdm_offs + | |
67 | OMAP4_CM_STATICDEP); | |
68 | return 0; | |
69 | } | |
68b921ad RN |
70 | |
71 | static int omap4_clkdm_sleep(struct clockdomain *clkdm) | |
72 | { | |
65aa94b2 | 73 | omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, |
68b921ad RN |
74 | clkdm->cm_inst, clkdm->clkdm_offs); |
75 | return 0; | |
76 | } | |
77 | ||
78 | static int omap4_clkdm_wakeup(struct clockdomain *clkdm) | |
79 | { | |
80 | omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition, | |
81 | clkdm->cm_inst, clkdm->clkdm_offs); | |
82 | return 0; | |
83 | } | |
84 | ||
5cd1937b RN |
85 | static void omap4_clkdm_allow_idle(struct clockdomain *clkdm) |
86 | { | |
87 | omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition, | |
88 | clkdm->cm_inst, clkdm->clkdm_offs); | |
89 | } | |
90 | ||
91 | static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) | |
92 | { | |
65aa94b2 JH |
93 | if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) |
94 | omap4_clkdm_wakeup(clkdm); | |
95 | else | |
96 | omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition, | |
97 | clkdm->cm_inst, | |
98 | clkdm->clkdm_offs); | |
5cd1937b RN |
99 | } |
100 | ||
4da71ae6 RN |
101 | static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) |
102 | { | |
555e74ea RN |
103 | if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP) |
104 | return omap4_clkdm_wakeup(clkdm); | |
4da71ae6 RN |
105 | |
106 | return 0; | |
107 | } | |
108 | ||
109 | static int omap4_clkdm_clk_disable(struct clockdomain *clkdm) | |
110 | { | |
111 | bool hwsup = false; | |
112 | ||
6ba5a69e PW |
113 | if (!clkdm->prcm_partition) |
114 | return 0; | |
115 | ||
4da71ae6 RN |
116 | hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, |
117 | clkdm->cm_inst, clkdm->clkdm_offs); | |
118 | ||
555e74ea RN |
119 | if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) |
120 | omap4_clkdm_sleep(clkdm); | |
4da71ae6 RN |
121 | |
122 | return 0; | |
123 | } | |
124 | ||
68b921ad | 125 | struct clkdm_ops omap4_clkdm_operations = { |
15b08d93 RN |
126 | .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep, |
127 | .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep, | |
128 | .clkdm_read_wkdep = omap4_clkdm_read_wkup_sleep_dep, | |
129 | .clkdm_clear_all_wkdeps = omap4_clkdm_clear_all_wkup_sleep_deps, | |
130 | .clkdm_add_sleepdep = omap4_clkdm_add_wkup_sleep_dep, | |
131 | .clkdm_del_sleepdep = omap4_clkdm_del_wkup_sleep_dep, | |
132 | .clkdm_read_sleepdep = omap4_clkdm_read_wkup_sleep_dep, | |
133 | .clkdm_clear_all_sleepdeps = omap4_clkdm_clear_all_wkup_sleep_deps, | |
68b921ad RN |
134 | .clkdm_sleep = omap4_clkdm_sleep, |
135 | .clkdm_wakeup = omap4_clkdm_wakeup, | |
5cd1937b RN |
136 | .clkdm_allow_idle = omap4_clkdm_allow_idle, |
137 | .clkdm_deny_idle = omap4_clkdm_deny_idle, | |
4da71ae6 RN |
138 | .clkdm_clk_enable = omap4_clkdm_clk_enable, |
139 | .clkdm_clk_disable = omap4_clkdm_clk_disable, | |
68b921ad | 140 | }; |