netprio_cgroup: simplify write_priomap()
[linux-2.6/libata-dev.git] / drivers / clk / ux500 / clk-prcmu.c
blob930cdfeb47ab451659843446b3f8ebdcdee01776
1 /*
2 * PRCMU clock implementation for ux500 platform.
4 * Copyright (C) 2012 ST-Ericsson SA
5 * Author: Ulf Hansson <ulf.hansson@linaro.org>
7 * License terms: GNU General Public License (GPL) version 2
8 */
10 #include <linux/clk-provider.h>
11 #include <linux/clk-private.h>
12 #include <linux/mfd/dbx500-prcmu.h>
13 #include <linux/slab.h>
14 #include <linux/io.h>
15 #include <linux/err.h>
16 #include "clk.h"
18 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
20 struct clk_prcmu {
21 struct clk_hw hw;
22 u8 cg_sel;
23 int is_enabled;
26 /* PRCMU clock operations. */
28 static int clk_prcmu_prepare(struct clk_hw *hw)
30 struct clk_prcmu *clk = to_clk_prcmu(hw);
31 return prcmu_request_clock(clk->cg_sel, true);
34 static void clk_prcmu_unprepare(struct clk_hw *hw)
36 struct clk_prcmu *clk = to_clk_prcmu(hw);
37 if (prcmu_request_clock(clk->cg_sel, false))
38 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
39 hw->init->name);
42 static int clk_prcmu_enable(struct clk_hw *hw)
44 struct clk_prcmu *clk = to_clk_prcmu(hw);
45 clk->is_enabled = 1;
46 return 0;
49 static void clk_prcmu_disable(struct clk_hw *hw)
51 struct clk_prcmu *clk = to_clk_prcmu(hw);
52 clk->is_enabled = 0;
55 static int clk_prcmu_is_enabled(struct clk_hw *hw)
57 struct clk_prcmu *clk = to_clk_prcmu(hw);
58 return clk->is_enabled;
61 static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw,
62 unsigned long parent_rate)
64 struct clk_prcmu *clk = to_clk_prcmu(hw);
65 return prcmu_clock_rate(clk->cg_sel);
68 static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate,
69 unsigned long *parent_rate)
71 struct clk_prcmu *clk = to_clk_prcmu(hw);
72 return prcmu_round_clock_rate(clk->cg_sel, rate);
75 static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
76 unsigned long parent_rate)
78 struct clk_prcmu *clk = to_clk_prcmu(hw);
79 return prcmu_set_clock_rate(clk->cg_sel, rate);
82 static int request_ape_opp100(bool enable)
84 static int reqs;
85 int err = 0;
87 if (enable) {
88 if (!reqs)
89 err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
90 "clock", 100);
91 if (!err)
92 reqs++;
93 } else {
94 reqs--;
95 if (!reqs)
96 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
97 "clock");
99 return err;
102 static int clk_prcmu_opp_prepare(struct clk_hw *hw)
104 int err;
105 struct clk_prcmu *clk = to_clk_prcmu(hw);
107 err = request_ape_opp100(true);
108 if (err) {
109 pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n",
110 __func__, hw->init->name);
111 return err;
114 err = prcmu_request_clock(clk->cg_sel, true);
115 if (err)
116 request_ape_opp100(false);
118 return err;
121 static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
123 struct clk_prcmu *clk = to_clk_prcmu(hw);
125 if (prcmu_request_clock(clk->cg_sel, false))
126 goto out_error;
127 if (request_ape_opp100(false))
128 goto out_error;
129 return;
131 out_error:
132 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
133 hw->init->name);
136 static struct clk_ops clk_prcmu_scalable_ops = {
137 .prepare = clk_prcmu_prepare,
138 .unprepare = clk_prcmu_unprepare,
139 .enable = clk_prcmu_enable,
140 .disable = clk_prcmu_disable,
141 .is_enabled = clk_prcmu_is_enabled,
142 .recalc_rate = clk_prcmu_recalc_rate,
143 .round_rate = clk_prcmu_round_rate,
144 .set_rate = clk_prcmu_set_rate,
147 static struct clk_ops clk_prcmu_gate_ops = {
148 .prepare = clk_prcmu_prepare,
149 .unprepare = clk_prcmu_unprepare,
150 .enable = clk_prcmu_enable,
151 .disable = clk_prcmu_disable,
152 .is_enabled = clk_prcmu_is_enabled,
153 .recalc_rate = clk_prcmu_recalc_rate,
156 static struct clk_ops clk_prcmu_rate_ops = {
157 .is_enabled = clk_prcmu_is_enabled,
158 .recalc_rate = clk_prcmu_recalc_rate,
161 static struct clk_ops clk_prcmu_opp_gate_ops = {
162 .prepare = clk_prcmu_opp_prepare,
163 .unprepare = clk_prcmu_opp_unprepare,
164 .enable = clk_prcmu_enable,
165 .disable = clk_prcmu_disable,
166 .is_enabled = clk_prcmu_is_enabled,
167 .recalc_rate = clk_prcmu_recalc_rate,
170 static struct clk *clk_reg_prcmu(const char *name,
171 const char *parent_name,
172 u8 cg_sel,
173 unsigned long rate,
174 unsigned long flags,
175 struct clk_ops *clk_prcmu_ops)
177 struct clk_prcmu *clk;
178 struct clk_init_data clk_prcmu_init;
179 struct clk *clk_reg;
181 if (!name) {
182 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__);
183 return ERR_PTR(-EINVAL);
186 clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL);
187 if (!clk) {
188 pr_err("clk_prcmu: %s could not allocate clk\n", __func__);
189 return ERR_PTR(-ENOMEM);
192 clk->cg_sel = cg_sel;
193 clk->is_enabled = 1;
194 /* "rate" can be used for changing the initial frequency */
195 if (rate)
196 prcmu_set_clock_rate(cg_sel, rate);
198 clk_prcmu_init.name = name;
199 clk_prcmu_init.ops = clk_prcmu_ops;
200 clk_prcmu_init.flags = flags;
201 clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL);
202 clk_prcmu_init.num_parents = (parent_name ? 1 : 0);
203 clk->hw.init = &clk_prcmu_init;
205 clk_reg = clk_register(NULL, &clk->hw);
206 if (IS_ERR_OR_NULL(clk_reg))
207 goto free_clk;
209 return clk_reg;
211 free_clk:
212 kfree(clk);
213 pr_err("clk_prcmu: %s failed to register clk\n", __func__);
214 return ERR_PTR(-ENOMEM);
217 struct clk *clk_reg_prcmu_scalable(const char *name,
218 const char *parent_name,
219 u8 cg_sel,
220 unsigned long rate,
221 unsigned long flags)
223 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
224 &clk_prcmu_scalable_ops);
227 struct clk *clk_reg_prcmu_gate(const char *name,
228 const char *parent_name,
229 u8 cg_sel,
230 unsigned long flags)
232 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
233 &clk_prcmu_gate_ops);
236 struct clk *clk_reg_prcmu_rate(const char *name,
237 const char *parent_name,
238 u8 cg_sel,
239 unsigned long flags)
241 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
242 &clk_prcmu_rate_ops);
245 struct clk *clk_reg_prcmu_opp_gate(const char *name,
246 const char *parent_name,
247 u8 cg_sel,
248 unsigned long flags)
250 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
251 &clk_prcmu_opp_gate_ops);