0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk-provider.h>
0010 #include <linux/mfd/dbx500-prcmu.h>
0011 #include <linux/slab.h>
0012 #include <linux/io.h>
0013 #include <linux/err.h>
0014 #include "clk.h"
0015
0016 #define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
0017 #define to_clk_prcmu_clkout(_hw) container_of(_hw, struct clk_prcmu_clkout, hw)
0018
0019 struct clk_prcmu {
0020 struct clk_hw hw;
0021 u8 cg_sel;
0022 int opp_requested;
0023 };
0024
0025 struct clk_prcmu_clkout {
0026 struct clk_hw hw;
0027 u8 clkout_id;
0028 u8 source;
0029 u8 divider;
0030 };
0031
0032
0033
0034 static int clk_prcmu_prepare(struct clk_hw *hw)
0035 {
0036 struct clk_prcmu *clk = to_clk_prcmu(hw);
0037
0038 return prcmu_request_clock(clk->cg_sel, true);
0039 }
0040
0041 static void clk_prcmu_unprepare(struct clk_hw *hw)
0042 {
0043 struct clk_prcmu *clk = to_clk_prcmu(hw);
0044 if (prcmu_request_clock(clk->cg_sel, false))
0045 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
0046 clk_hw_get_name(hw));
0047 }
0048
0049 static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw,
0050 unsigned long parent_rate)
0051 {
0052 struct clk_prcmu *clk = to_clk_prcmu(hw);
0053 return prcmu_clock_rate(clk->cg_sel);
0054 }
0055
0056 static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate,
0057 unsigned long *parent_rate)
0058 {
0059 struct clk_prcmu *clk = to_clk_prcmu(hw);
0060 return prcmu_round_clock_rate(clk->cg_sel, rate);
0061 }
0062
0063 static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
0064 unsigned long parent_rate)
0065 {
0066 struct clk_prcmu *clk = to_clk_prcmu(hw);
0067 return prcmu_set_clock_rate(clk->cg_sel, rate);
0068 }
0069
0070 static int clk_prcmu_opp_prepare(struct clk_hw *hw)
0071 {
0072 int err;
0073 struct clk_prcmu *clk = to_clk_prcmu(hw);
0074
0075 if (!clk->opp_requested) {
0076 err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
0077 (char *)clk_hw_get_name(hw),
0078 100);
0079 if (err) {
0080 pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
0081 __func__, clk_hw_get_name(hw));
0082 return err;
0083 }
0084 clk->opp_requested = 1;
0085 }
0086
0087 err = prcmu_request_clock(clk->cg_sel, true);
0088 if (err) {
0089 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
0090 (char *)clk_hw_get_name(hw));
0091 clk->opp_requested = 0;
0092 return err;
0093 }
0094
0095 return 0;
0096 }
0097
0098 static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
0099 {
0100 struct clk_prcmu *clk = to_clk_prcmu(hw);
0101
0102 if (prcmu_request_clock(clk->cg_sel, false)) {
0103 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
0104 clk_hw_get_name(hw));
0105 return;
0106 }
0107
0108 if (clk->opp_requested) {
0109 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
0110 (char *)clk_hw_get_name(hw));
0111 clk->opp_requested = 0;
0112 }
0113 }
0114
0115 static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
0116 {
0117 int err;
0118 struct clk_prcmu *clk = to_clk_prcmu(hw);
0119
0120 if (!clk->opp_requested) {
0121 err = prcmu_request_ape_opp_100_voltage(true);
0122 if (err) {
0123 pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
0124 __func__, clk_hw_get_name(hw));
0125 return err;
0126 }
0127 clk->opp_requested = 1;
0128 }
0129
0130 err = prcmu_request_clock(clk->cg_sel, true);
0131 if (err) {
0132 prcmu_request_ape_opp_100_voltage(false);
0133 clk->opp_requested = 0;
0134 return err;
0135 }
0136
0137 return 0;
0138 }
0139
0140 static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
0141 {
0142 struct clk_prcmu *clk = to_clk_prcmu(hw);
0143
0144 if (prcmu_request_clock(clk->cg_sel, false)) {
0145 pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
0146 clk_hw_get_name(hw));
0147 return;
0148 }
0149
0150 if (clk->opp_requested) {
0151 prcmu_request_ape_opp_100_voltage(false);
0152 clk->opp_requested = 0;
0153 }
0154 }
0155
0156 static const struct clk_ops clk_prcmu_scalable_ops = {
0157 .prepare = clk_prcmu_prepare,
0158 .unprepare = clk_prcmu_unprepare,
0159 .recalc_rate = clk_prcmu_recalc_rate,
0160 .round_rate = clk_prcmu_round_rate,
0161 .set_rate = clk_prcmu_set_rate,
0162 };
0163
0164 static const struct clk_ops clk_prcmu_gate_ops = {
0165 .prepare = clk_prcmu_prepare,
0166 .unprepare = clk_prcmu_unprepare,
0167 .recalc_rate = clk_prcmu_recalc_rate,
0168 };
0169
0170 static const struct clk_ops clk_prcmu_scalable_rate_ops = {
0171 .recalc_rate = clk_prcmu_recalc_rate,
0172 .round_rate = clk_prcmu_round_rate,
0173 .set_rate = clk_prcmu_set_rate,
0174 };
0175
0176 static const struct clk_ops clk_prcmu_rate_ops = {
0177 .recalc_rate = clk_prcmu_recalc_rate,
0178 };
0179
0180 static const struct clk_ops clk_prcmu_opp_gate_ops = {
0181 .prepare = clk_prcmu_opp_prepare,
0182 .unprepare = clk_prcmu_opp_unprepare,
0183 .recalc_rate = clk_prcmu_recalc_rate,
0184 };
0185
0186 static const struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
0187 .prepare = clk_prcmu_opp_volt_prepare,
0188 .unprepare = clk_prcmu_opp_volt_unprepare,
0189 .recalc_rate = clk_prcmu_recalc_rate,
0190 .round_rate = clk_prcmu_round_rate,
0191 .set_rate = clk_prcmu_set_rate,
0192 };
0193
0194 static struct clk_hw *clk_reg_prcmu(const char *name,
0195 const char *parent_name,
0196 u8 cg_sel,
0197 unsigned long rate,
0198 unsigned long flags,
0199 const struct clk_ops *clk_prcmu_ops)
0200 {
0201 struct clk_prcmu *clk;
0202 struct clk_init_data clk_prcmu_init;
0203 int ret;
0204
0205 if (!name) {
0206 pr_err("clk_prcmu: %s invalid arguments passed\n", __func__);
0207 return ERR_PTR(-EINVAL);
0208 }
0209
0210 clk = kzalloc(sizeof(*clk), GFP_KERNEL);
0211 if (!clk)
0212 return ERR_PTR(-ENOMEM);
0213
0214 clk->cg_sel = cg_sel;
0215 clk->opp_requested = 0;
0216
0217 if (rate)
0218 prcmu_set_clock_rate(cg_sel, rate);
0219
0220 clk_prcmu_init.name = name;
0221 clk_prcmu_init.ops = clk_prcmu_ops;
0222 clk_prcmu_init.flags = flags;
0223 clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL);
0224 clk_prcmu_init.num_parents = (parent_name ? 1 : 0);
0225 clk->hw.init = &clk_prcmu_init;
0226
0227 ret = clk_hw_register(NULL, &clk->hw);
0228 if (ret)
0229 goto free_clk;
0230
0231 return &clk->hw;
0232
0233 free_clk:
0234 kfree(clk);
0235 pr_err("clk_prcmu: %s failed to register clk\n", __func__);
0236 return ERR_PTR(-ENOMEM);
0237 }
0238
0239 struct clk_hw *clk_reg_prcmu_scalable(const char *name,
0240 const char *parent_name,
0241 u8 cg_sel,
0242 unsigned long rate,
0243 unsigned long flags)
0244 {
0245 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
0246 &clk_prcmu_scalable_ops);
0247 }
0248
0249 struct clk_hw *clk_reg_prcmu_gate(const char *name,
0250 const char *parent_name,
0251 u8 cg_sel,
0252 unsigned long flags)
0253 {
0254 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
0255 &clk_prcmu_gate_ops);
0256 }
0257
0258 struct clk_hw *clk_reg_prcmu_scalable_rate(const char *name,
0259 const char *parent_name,
0260 u8 cg_sel,
0261 unsigned long rate,
0262 unsigned long flags)
0263 {
0264 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
0265 &clk_prcmu_scalable_rate_ops);
0266 }
0267
0268 struct clk_hw *clk_reg_prcmu_rate(const char *name,
0269 const char *parent_name,
0270 u8 cg_sel,
0271 unsigned long flags)
0272 {
0273 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
0274 &clk_prcmu_rate_ops);
0275 }
0276
0277 struct clk_hw *clk_reg_prcmu_opp_gate(const char *name,
0278 const char *parent_name,
0279 u8 cg_sel,
0280 unsigned long flags)
0281 {
0282 return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
0283 &clk_prcmu_opp_gate_ops);
0284 }
0285
0286 struct clk_hw *clk_reg_prcmu_opp_volt_scalable(const char *name,
0287 const char *parent_name,
0288 u8 cg_sel,
0289 unsigned long rate,
0290 unsigned long flags)
0291 {
0292 return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
0293 &clk_prcmu_opp_volt_scalable_ops);
0294 }
0295
0296
0297
0298 static int clk_prcmu_clkout_prepare(struct clk_hw *hw)
0299 {
0300 struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw);
0301
0302 return prcmu_config_clkout(clk->clkout_id, clk->source, clk->divider);
0303 }
0304
0305 static void clk_prcmu_clkout_unprepare(struct clk_hw *hw)
0306 {
0307 struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw);
0308 int ret;
0309
0310
0311 ret = prcmu_config_clkout(clk->clkout_id, clk->source, 0);
0312 if (ret)
0313 pr_err("clk_prcmu: %s failed to disable %s\n", __func__,
0314 clk_hw_get_name(hw));
0315 }
0316
0317 static unsigned long clk_prcmu_clkout_recalc_rate(struct clk_hw *hw,
0318 unsigned long parent_rate)
0319 {
0320 struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw);
0321
0322 return (parent_rate / clk->divider);
0323 }
0324
0325 static u8 clk_prcmu_clkout_get_parent(struct clk_hw *hw)
0326 {
0327 struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw);
0328
0329 return clk->source;
0330 }
0331
0332 static int clk_prcmu_clkout_set_parent(struct clk_hw *hw, u8 index)
0333 {
0334 struct clk_prcmu_clkout *clk = to_clk_prcmu_clkout(hw);
0335
0336 clk->source = index;
0337
0338 if (clk_hw_is_prepared(hw))
0339 return clk_prcmu_clkout_prepare(hw);
0340 return 0;
0341 }
0342
0343 static const struct clk_ops clk_prcmu_clkout_ops = {
0344 .prepare = clk_prcmu_clkout_prepare,
0345 .unprepare = clk_prcmu_clkout_unprepare,
0346 .recalc_rate = clk_prcmu_clkout_recalc_rate,
0347 .get_parent = clk_prcmu_clkout_get_parent,
0348 .set_parent = clk_prcmu_clkout_set_parent,
0349 };
0350
0351 struct clk_hw *clk_reg_prcmu_clkout(const char *name,
0352 const char * const *parent_names,
0353 int num_parents,
0354 u8 source, u8 divider)
0355
0356 {
0357 struct clk_prcmu_clkout *clk;
0358 struct clk_init_data clk_prcmu_clkout_init;
0359 u8 clkout_id;
0360 int ret;
0361
0362 if (!name) {
0363 pr_err("clk_prcmu_clkout: %s invalid arguments passed\n", __func__);
0364 return ERR_PTR(-EINVAL);
0365 }
0366
0367 if (!strcmp(name, "clkout1"))
0368 clkout_id = 0;
0369 else if (!strcmp(name, "clkout2"))
0370 clkout_id = 1;
0371 else {
0372 pr_err("clk_prcmu_clkout: %s bad clock name\n", __func__);
0373 return ERR_PTR(-EINVAL);
0374 }
0375
0376 clk = kzalloc(sizeof(*clk), GFP_KERNEL);
0377 if (!clk)
0378 return ERR_PTR(-ENOMEM);
0379
0380 clk->clkout_id = clkout_id;
0381 clk->source = source;
0382 clk->divider = divider;
0383
0384 clk_prcmu_clkout_init.name = name;
0385 clk_prcmu_clkout_init.ops = &clk_prcmu_clkout_ops;
0386 clk_prcmu_clkout_init.flags = CLK_GET_RATE_NOCACHE;
0387 clk_prcmu_clkout_init.parent_names = parent_names;
0388 clk_prcmu_clkout_init.num_parents = num_parents;
0389 clk->hw.init = &clk_prcmu_clkout_init;
0390
0391 ret = clk_hw_register(NULL, &clk->hw);
0392 if (ret)
0393 goto free_clkout;
0394
0395 return &clk->hw;
0396 free_clkout:
0397 kfree(clk);
0398 pr_err("clk_prcmu_clkout: %s failed to register clk\n", __func__);
0399 return ERR_PTR(-ENOMEM);
0400 }