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
10 #include <linux/clk-provider.h>
11 #include <linux/clk-private.h>
12 #include <linux/mfd/dbx500-prcmu.h>
13 #include <linux/slab.h>
15 #include <linux/err.h>
18 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
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__
,
42 static int clk_prcmu_enable(struct clk_hw
*hw
)
44 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
49 static void clk_prcmu_disable(struct clk_hw
*hw
)
51 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
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
)
89 err
= prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP
,
96 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP
,
102 static int clk_prcmu_opp_prepare(struct clk_hw
*hw
)
105 struct clk_prcmu
*clk
= to_clk_prcmu(hw
);
107 err
= request_ape_opp100(true);
109 pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n",
110 __func__
, hw
->init
->name
);
114 err
= prcmu_request_clock(clk
->cg_sel
, true);
116 request_ape_opp100(false);
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))
127 if (request_ape_opp100(false))
132 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__
,
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
,
175 struct clk_ops
*clk_prcmu_ops
)
177 struct clk_prcmu
*clk
;
178 struct clk_init_data clk_prcmu_init
;
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
);
188 pr_err("clk_prcmu: %s could not allocate clk\n", __func__
);
189 return ERR_PTR(-ENOMEM
);
192 clk
->cg_sel
= cg_sel
;
194 /* "rate" can be used for changing the initial frequency */
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
))
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
,
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
,
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
,
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
,
250 return clk_reg_prcmu(name
, parent_name
, cg_sel
, 0, flags
,
251 &clk_prcmu_opp_gate_ops
);