0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/slab.h>
0018 #include <linux/clk.h>
0019 #include <linux/clk-provider.h>
0020 #include <linux/io.h>
0021 #include <linux/mfd/syscon.h>
0022 #include <linux/regmap.h>
0023 #include <linux/reboot.h>
0024 #include <linux/rational.h>
0025
0026 #include "../clk-fractional-divider.h"
0027 #include "clk.h"
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 static struct clk *rockchip_clk_register_branch(const char *name,
0040 const char *const *parent_names, u8 num_parents,
0041 void __iomem *base,
0042 int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
0043 int div_offset, u8 div_shift, u8 div_width, u8 div_flags,
0044 struct clk_div_table *div_table, int gate_offset,
0045 u8 gate_shift, u8 gate_flags, unsigned long flags,
0046 spinlock_t *lock)
0047 {
0048 struct clk_hw *hw;
0049 struct clk_mux *mux = NULL;
0050 struct clk_gate *gate = NULL;
0051 struct clk_divider *div = NULL;
0052 const struct clk_ops *mux_ops = NULL, *div_ops = NULL,
0053 *gate_ops = NULL;
0054 int ret;
0055
0056 if (num_parents > 1) {
0057 mux = kzalloc(sizeof(*mux), GFP_KERNEL);
0058 if (!mux)
0059 return ERR_PTR(-ENOMEM);
0060
0061 mux->reg = base + muxdiv_offset;
0062 mux->shift = mux_shift;
0063 mux->mask = BIT(mux_width) - 1;
0064 mux->flags = mux_flags;
0065 mux->lock = lock;
0066 mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops
0067 : &clk_mux_ops;
0068 }
0069
0070 if (gate_offset >= 0) {
0071 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
0072 if (!gate) {
0073 ret = -ENOMEM;
0074 goto err_gate;
0075 }
0076
0077 gate->flags = gate_flags;
0078 gate->reg = base + gate_offset;
0079 gate->bit_idx = gate_shift;
0080 gate->lock = lock;
0081 gate_ops = &clk_gate_ops;
0082 }
0083
0084 if (div_width > 0) {
0085 div = kzalloc(sizeof(*div), GFP_KERNEL);
0086 if (!div) {
0087 ret = -ENOMEM;
0088 goto err_div;
0089 }
0090
0091 div->flags = div_flags;
0092 if (div_offset)
0093 div->reg = base + div_offset;
0094 else
0095 div->reg = base + muxdiv_offset;
0096 div->shift = div_shift;
0097 div->width = div_width;
0098 div->lock = lock;
0099 div->table = div_table;
0100 div_ops = (div_flags & CLK_DIVIDER_READ_ONLY)
0101 ? &clk_divider_ro_ops
0102 : &clk_divider_ops;
0103 }
0104
0105 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
0106 mux ? &mux->hw : NULL, mux_ops,
0107 div ? &div->hw : NULL, div_ops,
0108 gate ? &gate->hw : NULL, gate_ops,
0109 flags);
0110 if (IS_ERR(hw)) {
0111 kfree(div);
0112 kfree(gate);
0113 return ERR_CAST(hw);
0114 }
0115
0116 return hw->clk;
0117 err_div:
0118 kfree(gate);
0119 err_gate:
0120 kfree(mux);
0121 return ERR_PTR(ret);
0122 }
0123
0124 struct rockchip_clk_frac {
0125 struct notifier_block clk_nb;
0126 struct clk_fractional_divider div;
0127 struct clk_gate gate;
0128
0129 struct clk_mux mux;
0130 const struct clk_ops *mux_ops;
0131 int mux_frac_idx;
0132
0133 bool rate_change_remuxed;
0134 int rate_change_idx;
0135 };
0136
0137 #define to_rockchip_clk_frac_nb(nb) \
0138 container_of(nb, struct rockchip_clk_frac, clk_nb)
0139
0140 static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
0141 unsigned long event, void *data)
0142 {
0143 struct clk_notifier_data *ndata = data;
0144 struct rockchip_clk_frac *frac = to_rockchip_clk_frac_nb(nb);
0145 struct clk_mux *frac_mux = &frac->mux;
0146 int ret = 0;
0147
0148 pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
0149 __func__, event, ndata->old_rate, ndata->new_rate);
0150 if (event == PRE_RATE_CHANGE) {
0151 frac->rate_change_idx =
0152 frac->mux_ops->get_parent(&frac_mux->hw);
0153 if (frac->rate_change_idx != frac->mux_frac_idx) {
0154 frac->mux_ops->set_parent(&frac_mux->hw,
0155 frac->mux_frac_idx);
0156 frac->rate_change_remuxed = 1;
0157 }
0158 } else if (event == POST_RATE_CHANGE) {
0159
0160
0161
0162
0163
0164
0165 if (frac->rate_change_remuxed) {
0166 frac->mux_ops->set_parent(&frac_mux->hw,
0167 frac->rate_change_idx);
0168 frac->rate_change_remuxed = 0;
0169 }
0170 }
0171
0172 return notifier_from_errno(ret);
0173 }
0174
0175
0176
0177
0178
0179 static void rockchip_fractional_approximation(struct clk_hw *hw,
0180 unsigned long rate, unsigned long *parent_rate,
0181 unsigned long *m, unsigned long *n)
0182 {
0183 struct clk_fractional_divider *fd = to_clk_fd(hw);
0184 unsigned long p_rate, p_parent_rate;
0185 struct clk_hw *p_parent;
0186
0187 p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
0188 if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
0189 p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
0190 p_parent_rate = clk_hw_get_rate(p_parent);
0191 *parent_rate = p_parent_rate;
0192 }
0193
0194 fd->flags |= CLK_FRAC_DIVIDER_POWER_OF_TWO_PS;
0195
0196 clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n);
0197 }
0198
0199 static struct clk *rockchip_clk_register_frac_branch(
0200 struct rockchip_clk_provider *ctx, const char *name,
0201 const char *const *parent_names, u8 num_parents,
0202 void __iomem *base, int muxdiv_offset, u8 div_flags,
0203 int gate_offset, u8 gate_shift, u8 gate_flags,
0204 unsigned long flags, struct rockchip_clk_branch *child,
0205 spinlock_t *lock)
0206 {
0207 struct clk_hw *hw;
0208 struct rockchip_clk_frac *frac;
0209 struct clk_gate *gate = NULL;
0210 struct clk_fractional_divider *div = NULL;
0211 const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
0212
0213 if (muxdiv_offset < 0)
0214 return ERR_PTR(-EINVAL);
0215
0216 if (child && child->branch_type != branch_mux) {
0217 pr_err("%s: fractional child clock for %s can only be a mux\n",
0218 __func__, name);
0219 return ERR_PTR(-EINVAL);
0220 }
0221
0222 frac = kzalloc(sizeof(*frac), GFP_KERNEL);
0223 if (!frac)
0224 return ERR_PTR(-ENOMEM);
0225
0226 if (gate_offset >= 0) {
0227 gate = &frac->gate;
0228 gate->flags = gate_flags;
0229 gate->reg = base + gate_offset;
0230 gate->bit_idx = gate_shift;
0231 gate->lock = lock;
0232 gate_ops = &clk_gate_ops;
0233 }
0234
0235 div = &frac->div;
0236 div->flags = div_flags;
0237 div->reg = base + muxdiv_offset;
0238 div->mshift = 16;
0239 div->mwidth = 16;
0240 div->mmask = GENMASK(div->mwidth - 1, 0) << div->mshift;
0241 div->nshift = 0;
0242 div->nwidth = 16;
0243 div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
0244 div->lock = lock;
0245 div->approximation = rockchip_fractional_approximation;
0246 div_ops = &clk_fractional_divider_ops;
0247
0248 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
0249 NULL, NULL,
0250 &div->hw, div_ops,
0251 gate ? &gate->hw : NULL, gate_ops,
0252 flags | CLK_SET_RATE_UNGATE);
0253 if (IS_ERR(hw)) {
0254 kfree(frac);
0255 return ERR_CAST(hw);
0256 }
0257
0258 if (child) {
0259 struct clk_mux *frac_mux = &frac->mux;
0260 struct clk_init_data init;
0261 struct clk *mux_clk;
0262 int ret;
0263
0264 frac->mux_frac_idx = match_string(child->parent_names,
0265 child->num_parents, name);
0266 frac->mux_ops = &clk_mux_ops;
0267 frac->clk_nb.notifier_call = rockchip_clk_frac_notifier_cb;
0268
0269 frac_mux->reg = base + child->muxdiv_offset;
0270 frac_mux->shift = child->mux_shift;
0271 frac_mux->mask = BIT(child->mux_width) - 1;
0272 frac_mux->flags = child->mux_flags;
0273 frac_mux->lock = lock;
0274 frac_mux->hw.init = &init;
0275
0276 init.name = child->name;
0277 init.flags = child->flags | CLK_SET_RATE_PARENT;
0278 init.ops = frac->mux_ops;
0279 init.parent_names = child->parent_names;
0280 init.num_parents = child->num_parents;
0281
0282 mux_clk = clk_register(NULL, &frac_mux->hw);
0283 if (IS_ERR(mux_clk)) {
0284 kfree(frac);
0285 return mux_clk;
0286 }
0287
0288 rockchip_clk_add_lookup(ctx, mux_clk, child->id);
0289
0290
0291 if (frac->mux_frac_idx >= 0) {
0292 pr_debug("%s: found fractional parent in mux at pos %d\n",
0293 __func__, frac->mux_frac_idx);
0294 ret = clk_notifier_register(hw->clk, &frac->clk_nb);
0295 if (ret)
0296 pr_err("%s: failed to register clock notifier for %s\n",
0297 __func__, name);
0298 } else {
0299 pr_warn("%s: could not find %s as parent of %s, rate changes may not work\n",
0300 __func__, name, child->name);
0301 }
0302 }
0303
0304 return hw->clk;
0305 }
0306
0307 static struct clk *rockchip_clk_register_factor_branch(const char *name,
0308 const char *const *parent_names, u8 num_parents,
0309 void __iomem *base, unsigned int mult, unsigned int div,
0310 int gate_offset, u8 gate_shift, u8 gate_flags,
0311 unsigned long flags, spinlock_t *lock)
0312 {
0313 struct clk_hw *hw;
0314 struct clk_gate *gate = NULL;
0315 struct clk_fixed_factor *fix = NULL;
0316
0317
0318 if (gate_offset == 0) {
0319 return clk_register_fixed_factor(NULL, name,
0320 parent_names[0], flags, mult,
0321 div);
0322 }
0323
0324 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
0325 if (!gate)
0326 return ERR_PTR(-ENOMEM);
0327
0328 gate->flags = gate_flags;
0329 gate->reg = base + gate_offset;
0330 gate->bit_idx = gate_shift;
0331 gate->lock = lock;
0332
0333 fix = kzalloc(sizeof(*fix), GFP_KERNEL);
0334 if (!fix) {
0335 kfree(gate);
0336 return ERR_PTR(-ENOMEM);
0337 }
0338
0339 fix->mult = mult;
0340 fix->div = div;
0341
0342 hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
0343 NULL, NULL,
0344 &fix->hw, &clk_fixed_factor_ops,
0345 &gate->hw, &clk_gate_ops, flags);
0346 if (IS_ERR(hw)) {
0347 kfree(fix);
0348 kfree(gate);
0349 return ERR_CAST(hw);
0350 }
0351
0352 return hw->clk;
0353 }
0354
0355 struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
0356 void __iomem *base,
0357 unsigned long nr_clks)
0358 {
0359 struct rockchip_clk_provider *ctx;
0360 struct clk **clk_table;
0361 int i;
0362
0363 ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL);
0364 if (!ctx)
0365 return ERR_PTR(-ENOMEM);
0366
0367 clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
0368 if (!clk_table)
0369 goto err_free;
0370
0371 for (i = 0; i < nr_clks; ++i)
0372 clk_table[i] = ERR_PTR(-ENOENT);
0373
0374 ctx->reg_base = base;
0375 ctx->clk_data.clks = clk_table;
0376 ctx->clk_data.clk_num = nr_clks;
0377 ctx->cru_node = np;
0378 spin_lock_init(&ctx->lock);
0379
0380 ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
0381 "rockchip,grf");
0382
0383 return ctx;
0384
0385 err_free:
0386 kfree(ctx);
0387 return ERR_PTR(-ENOMEM);
0388 }
0389 EXPORT_SYMBOL_GPL(rockchip_clk_init);
0390
0391 void rockchip_clk_of_add_provider(struct device_node *np,
0392 struct rockchip_clk_provider *ctx)
0393 {
0394 if (of_clk_add_provider(np, of_clk_src_onecell_get,
0395 &ctx->clk_data))
0396 pr_err("%s: could not register clk provider\n", __func__);
0397 }
0398 EXPORT_SYMBOL_GPL(rockchip_clk_of_add_provider);
0399
0400 void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
0401 struct clk *clk, unsigned int id)
0402 {
0403 if (ctx->clk_data.clks && id)
0404 ctx->clk_data.clks[id] = clk;
0405 }
0406 EXPORT_SYMBOL_GPL(rockchip_clk_add_lookup);
0407
0408 void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
0409 struct rockchip_pll_clock *list,
0410 unsigned int nr_pll, int grf_lock_offset)
0411 {
0412 struct clk *clk;
0413 int idx;
0414
0415 for (idx = 0; idx < nr_pll; idx++, list++) {
0416 clk = rockchip_clk_register_pll(ctx, list->type, list->name,
0417 list->parent_names, list->num_parents,
0418 list->con_offset, grf_lock_offset,
0419 list->lock_shift, list->mode_offset,
0420 list->mode_shift, list->rate_table,
0421 list->flags, list->pll_flags);
0422 if (IS_ERR(clk)) {
0423 pr_err("%s: failed to register clock %s\n", __func__,
0424 list->name);
0425 continue;
0426 }
0427
0428 rockchip_clk_add_lookup(ctx, clk, list->id);
0429 }
0430 }
0431 EXPORT_SYMBOL_GPL(rockchip_clk_register_plls);
0432
0433 void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
0434 struct rockchip_clk_branch *list,
0435 unsigned int nr_clk)
0436 {
0437 struct clk *clk = NULL;
0438 unsigned int idx;
0439 unsigned long flags;
0440
0441 for (idx = 0; idx < nr_clk; idx++, list++) {
0442 flags = list->flags;
0443
0444
0445 switch (list->branch_type) {
0446 case branch_mux:
0447 clk = clk_register_mux(NULL, list->name,
0448 list->parent_names, list->num_parents,
0449 flags, ctx->reg_base + list->muxdiv_offset,
0450 list->mux_shift, list->mux_width,
0451 list->mux_flags, &ctx->lock);
0452 break;
0453 case branch_muxgrf:
0454 clk = rockchip_clk_register_muxgrf(list->name,
0455 list->parent_names, list->num_parents,
0456 flags, ctx->grf, list->muxdiv_offset,
0457 list->mux_shift, list->mux_width,
0458 list->mux_flags);
0459 break;
0460 case branch_divider:
0461 if (list->div_table)
0462 clk = clk_register_divider_table(NULL,
0463 list->name, list->parent_names[0],
0464 flags,
0465 ctx->reg_base + list->muxdiv_offset,
0466 list->div_shift, list->div_width,
0467 list->div_flags, list->div_table,
0468 &ctx->lock);
0469 else
0470 clk = clk_register_divider(NULL, list->name,
0471 list->parent_names[0], flags,
0472 ctx->reg_base + list->muxdiv_offset,
0473 list->div_shift, list->div_width,
0474 list->div_flags, &ctx->lock);
0475 break;
0476 case branch_fraction_divider:
0477 clk = rockchip_clk_register_frac_branch(ctx, list->name,
0478 list->parent_names, list->num_parents,
0479 ctx->reg_base, list->muxdiv_offset,
0480 list->div_flags,
0481 list->gate_offset, list->gate_shift,
0482 list->gate_flags, flags, list->child,
0483 &ctx->lock);
0484 break;
0485 case branch_half_divider:
0486 clk = rockchip_clk_register_halfdiv(list->name,
0487 list->parent_names, list->num_parents,
0488 ctx->reg_base, list->muxdiv_offset,
0489 list->mux_shift, list->mux_width,
0490 list->mux_flags, list->div_shift,
0491 list->div_width, list->div_flags,
0492 list->gate_offset, list->gate_shift,
0493 list->gate_flags, flags, &ctx->lock);
0494 break;
0495 case branch_gate:
0496 flags |= CLK_SET_RATE_PARENT;
0497
0498 clk = clk_register_gate(NULL, list->name,
0499 list->parent_names[0], flags,
0500 ctx->reg_base + list->gate_offset,
0501 list->gate_shift, list->gate_flags, &ctx->lock);
0502 break;
0503 case branch_composite:
0504 clk = rockchip_clk_register_branch(list->name,
0505 list->parent_names, list->num_parents,
0506 ctx->reg_base, list->muxdiv_offset,
0507 list->mux_shift,
0508 list->mux_width, list->mux_flags,
0509 list->div_offset, list->div_shift, list->div_width,
0510 list->div_flags, list->div_table,
0511 list->gate_offset, list->gate_shift,
0512 list->gate_flags, flags, &ctx->lock);
0513 break;
0514 case branch_mmc:
0515 clk = rockchip_clk_register_mmc(
0516 list->name,
0517 list->parent_names, list->num_parents,
0518 ctx->reg_base + list->muxdiv_offset,
0519 list->div_shift
0520 );
0521 break;
0522 case branch_inverter:
0523 clk = rockchip_clk_register_inverter(
0524 list->name, list->parent_names,
0525 list->num_parents,
0526 ctx->reg_base + list->muxdiv_offset,
0527 list->div_shift, list->div_flags, &ctx->lock);
0528 break;
0529 case branch_factor:
0530 clk = rockchip_clk_register_factor_branch(
0531 list->name, list->parent_names,
0532 list->num_parents, ctx->reg_base,
0533 list->div_shift, list->div_width,
0534 list->gate_offset, list->gate_shift,
0535 list->gate_flags, flags, &ctx->lock);
0536 break;
0537 case branch_ddrclk:
0538 clk = rockchip_clk_register_ddrclk(
0539 list->name, list->flags,
0540 list->parent_names, list->num_parents,
0541 list->muxdiv_offset, list->mux_shift,
0542 list->mux_width, list->div_shift,
0543 list->div_width, list->div_flags,
0544 ctx->reg_base, &ctx->lock);
0545 break;
0546 }
0547
0548
0549 if (!clk) {
0550 pr_err("%s: unknown clock type %d\n",
0551 __func__, list->branch_type);
0552 continue;
0553 }
0554
0555 if (IS_ERR(clk)) {
0556 pr_err("%s: failed to register clock %s: %ld\n",
0557 __func__, list->name, PTR_ERR(clk));
0558 continue;
0559 }
0560
0561 rockchip_clk_add_lookup(ctx, clk, list->id);
0562 }
0563 }
0564 EXPORT_SYMBOL_GPL(rockchip_clk_register_branches);
0565
0566 void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
0567 unsigned int lookup_id,
0568 const char *name, const char *const *parent_names,
0569 u8 num_parents,
0570 const struct rockchip_cpuclk_reg_data *reg_data,
0571 const struct rockchip_cpuclk_rate_table *rates,
0572 int nrates)
0573 {
0574 struct clk *clk;
0575
0576 clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents,
0577 reg_data, rates, nrates,
0578 ctx->reg_base, &ctx->lock);
0579 if (IS_ERR(clk)) {
0580 pr_err("%s: failed to register clock %s: %ld\n",
0581 __func__, name, PTR_ERR(clk));
0582 return;
0583 }
0584
0585 rockchip_clk_add_lookup(ctx, clk, lookup_id);
0586 }
0587 EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk);
0588
0589 void rockchip_clk_protect_critical(const char *const clocks[],
0590 int nclocks)
0591 {
0592 int i;
0593
0594
0595 for (i = 0; i < nclocks; i++) {
0596 struct clk *clk = __clk_lookup(clocks[i]);
0597
0598 clk_prepare_enable(clk);
0599 }
0600 }
0601 EXPORT_SYMBOL_GPL(rockchip_clk_protect_critical);
0602
0603 static void __iomem *rst_base;
0604 static unsigned int reg_restart;
0605 static void (*cb_restart)(void);
0606 static int rockchip_restart_notify(struct notifier_block *this,
0607 unsigned long mode, void *cmd)
0608 {
0609 if (cb_restart)
0610 cb_restart();
0611
0612 writel(0xfdb9, rst_base + reg_restart);
0613 return NOTIFY_DONE;
0614 }
0615
0616 static struct notifier_block rockchip_restart_handler = {
0617 .notifier_call = rockchip_restart_notify,
0618 .priority = 128,
0619 };
0620
0621 void
0622 rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
0623 unsigned int reg,
0624 void (*cb)(void))
0625 {
0626 int ret;
0627
0628 rst_base = ctx->reg_base;
0629 reg_restart = reg;
0630 cb_restart = cb;
0631 ret = register_restart_handler(&rockchip_restart_handler);
0632 if (ret)
0633 pr_err("%s: cannot register restart handler, %d\n",
0634 __func__, ret);
0635 }
0636 EXPORT_SYMBOL_GPL(rockchip_register_restart_notifier);