aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/ux500/clk-prcmu.c55
-rw-r--r--drivers/clk/ux500/clk.h6
2 files changed, 61 insertions, 0 deletions
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index 930cdfeb47ab..04577ca6a308 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -133,6 +133,40 @@ out_error:
133 hw->init->name); 133 hw->init->name);
134} 134}
135 135
136static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
137{
138 int err;
139 struct clk_prcmu *clk = to_clk_prcmu(hw);
140
141 err = prcmu_request_ape_opp_100_voltage(true);
142 if (err) {
143 pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n",
144 __func__, hw->init->name);
145 return err;
146 }
147
148 err = prcmu_request_clock(clk->cg_sel, true);
149 if (err)
150 prcmu_request_ape_opp_100_voltage(false);
151
152 return err;
153}
154
155static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
156{
157 struct clk_prcmu *clk = to_clk_prcmu(hw);
158
159 if (prcmu_request_clock(clk->cg_sel, false))
160 goto out_error;
161 if (prcmu_request_ape_opp_100_voltage(false))
162 goto out_error;
163 return;
164
165out_error:
166 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
167 hw->init->name);
168}
169
136static struct clk_ops clk_prcmu_scalable_ops = { 170static struct clk_ops clk_prcmu_scalable_ops = {
137 .prepare = clk_prcmu_prepare, 171 .prepare = clk_prcmu_prepare,
138 .unprepare = clk_prcmu_unprepare, 172 .unprepare = clk_prcmu_unprepare,
@@ -167,6 +201,17 @@ static struct clk_ops clk_prcmu_opp_gate_ops = {
167 .recalc_rate = clk_prcmu_recalc_rate, 201 .recalc_rate = clk_prcmu_recalc_rate,
168}; 202};
169 203
204static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
205 .prepare = clk_prcmu_opp_volt_prepare,
206 .unprepare = clk_prcmu_opp_volt_unprepare,
207 .enable = clk_prcmu_enable,
208 .disable = clk_prcmu_disable,
209 .is_enabled = clk_prcmu_is_enabled,
210 .recalc_rate = clk_prcmu_recalc_rate,
211 .round_rate = clk_prcmu_round_rate,
212 .set_rate = clk_prcmu_set_rate,
213};
214
170static struct clk *clk_reg_prcmu(const char *name, 215static struct clk *clk_reg_prcmu(const char *name,
171 const char *parent_name, 216 const char *parent_name,
172 u8 cg_sel, 217 u8 cg_sel,
@@ -250,3 +295,13 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
250 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags, 295 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
251 &clk_prcmu_opp_gate_ops); 296 &clk_prcmu_opp_gate_ops);
252} 297}
298
299struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
300 const char *parent_name,
301 u8 cg_sel,
302 unsigned long rate,
303 unsigned long flags)
304{
305 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
306 &clk_prcmu_opp_volt_scalable_ops);
307}
diff --git a/drivers/clk/ux500/clk.h b/drivers/clk/ux500/clk.h
index 836d7d16751e..f36eeedca493 100644
--- a/drivers/clk/ux500/clk.h
+++ b/drivers/clk/ux500/clk.h
@@ -45,4 +45,10 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
45 u8 cg_sel, 45 u8 cg_sel,
46 unsigned long flags); 46 unsigned long flags);
47 47
48struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
49 const char *parent_name,
50 u8 cg_sel,
51 unsigned long rate,
52 unsigned long flags);
53
48#endif /* __UX500_CLK_H */ 54#endif /* __UX500_CLK_H */