0001
0002
0003
0004
0005
0006 #include <linux/clk-provider.h>
0007 #include <linux/device.h>
0008 #include <linux/seq_buf.h>
0009 #include <linux/slab.h>
0010
0011 #include <soc/tegra/bpmp.h>
0012 #include <soc/tegra/bpmp-abi.h>
0013
0014 #define TEGRA_BPMP_DUMP_CLOCK_INFO 0
0015
0016 #define TEGRA_BPMP_CLK_HAS_MUX BIT(0)
0017 #define TEGRA_BPMP_CLK_HAS_SET_RATE BIT(1)
0018 #define TEGRA_BPMP_CLK_IS_ROOT BIT(2)
0019
0020 struct tegra_bpmp_clk_info {
0021 unsigned int id;
0022 char name[MRQ_CLK_NAME_MAXLEN];
0023 unsigned int parents[MRQ_CLK_MAX_PARENTS];
0024 unsigned int num_parents;
0025 unsigned long flags;
0026 };
0027
0028 struct tegra_bpmp_clk {
0029 struct clk_hw hw;
0030
0031 struct tegra_bpmp *bpmp;
0032 unsigned int id;
0033
0034 unsigned int num_parents;
0035 unsigned int *parents;
0036 };
0037
0038 static inline struct tegra_bpmp_clk *to_tegra_bpmp_clk(struct clk_hw *hw)
0039 {
0040 return container_of(hw, struct tegra_bpmp_clk, hw);
0041 }
0042
0043 struct tegra_bpmp_clk_message {
0044 unsigned int cmd;
0045 unsigned int id;
0046
0047 struct {
0048 const void *data;
0049 size_t size;
0050 } tx;
0051
0052 struct {
0053 void *data;
0054 size_t size;
0055 int ret;
0056 } rx;
0057 };
0058
0059 static int tegra_bpmp_clk_transfer(struct tegra_bpmp *bpmp,
0060 const struct tegra_bpmp_clk_message *clk)
0061 {
0062 struct mrq_clk_request request;
0063 struct tegra_bpmp_message msg;
0064 void *req = &request;
0065 int err;
0066
0067 memset(&request, 0, sizeof(request));
0068 request.cmd_and_id = (clk->cmd << 24) | clk->id;
0069
0070
0071
0072
0073
0074
0075
0076
0077 memcpy(req + 4, clk->tx.data, clk->tx.size);
0078
0079 memset(&msg, 0, sizeof(msg));
0080 msg.mrq = MRQ_CLK;
0081 msg.tx.data = &request;
0082 msg.tx.size = sizeof(request);
0083 msg.rx.data = clk->rx.data;
0084 msg.rx.size = clk->rx.size;
0085
0086 err = tegra_bpmp_transfer(bpmp, &msg);
0087 if (err < 0)
0088 return err;
0089 else if (msg.rx.ret < 0)
0090 return -EINVAL;
0091
0092 return 0;
0093 }
0094
0095 static int tegra_bpmp_clk_prepare(struct clk_hw *hw)
0096 {
0097 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
0098 struct tegra_bpmp_clk_message msg;
0099
0100 memset(&msg, 0, sizeof(msg));
0101 msg.cmd = CMD_CLK_ENABLE;
0102 msg.id = clk->id;
0103
0104 return tegra_bpmp_clk_transfer(clk->bpmp, &msg);
0105 }
0106
0107 static void tegra_bpmp_clk_unprepare(struct clk_hw *hw)
0108 {
0109 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
0110 struct tegra_bpmp_clk_message msg;
0111 int err;
0112
0113 memset(&msg, 0, sizeof(msg));
0114 msg.cmd = CMD_CLK_DISABLE;
0115 msg.id = clk->id;
0116
0117 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
0118 if (err < 0)
0119 dev_err(clk->bpmp->dev, "failed to disable clock %s: %d\n",
0120 clk_hw_get_name(hw), err);
0121 }
0122
0123 static int tegra_bpmp_clk_is_prepared(struct clk_hw *hw)
0124 {
0125 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
0126 struct cmd_clk_is_enabled_response response;
0127 struct tegra_bpmp_clk_message msg;
0128 int err;
0129
0130 memset(&msg, 0, sizeof(msg));
0131 msg.cmd = CMD_CLK_IS_ENABLED;
0132 msg.id = clk->id;
0133 msg.rx.data = &response;
0134 msg.rx.size = sizeof(response);
0135
0136 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
0137 if (err < 0)
0138 return err;
0139
0140 return response.state;
0141 }
0142
0143 static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw *hw,
0144 unsigned long parent_rate)
0145 {
0146 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
0147 struct cmd_clk_get_rate_response response;
0148 struct cmd_clk_get_rate_request request;
0149 struct tegra_bpmp_clk_message msg;
0150 int err;
0151
0152 memset(&msg, 0, sizeof(msg));
0153 msg.cmd = CMD_CLK_GET_RATE;
0154 msg.id = clk->id;
0155 msg.tx.data = &request;
0156 msg.tx.size = sizeof(request);
0157 msg.rx.data = &response;
0158 msg.rx.size = sizeof(response);
0159
0160 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
0161 if (err < 0)
0162 return err;
0163
0164 return response.rate;
0165 }
0166
0167 static int tegra_bpmp_clk_determine_rate(struct clk_hw *hw,
0168 struct clk_rate_request *rate_req)
0169 {
0170 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
0171 struct cmd_clk_round_rate_response response;
0172 struct cmd_clk_round_rate_request request;
0173 struct tegra_bpmp_clk_message msg;
0174 unsigned long rate;
0175 int err;
0176
0177 rate = min(max(rate_req->rate, rate_req->min_rate), rate_req->max_rate);
0178
0179 memset(&request, 0, sizeof(request));
0180 request.rate = min_t(u64, rate, S64_MAX);
0181
0182 memset(&msg, 0, sizeof(msg));
0183 msg.cmd = CMD_CLK_ROUND_RATE;
0184 msg.id = clk->id;
0185 msg.tx.data = &request;
0186 msg.tx.size = sizeof(request);
0187 msg.rx.data = &response;
0188 msg.rx.size = sizeof(response);
0189
0190 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
0191 if (err < 0)
0192 return err;
0193
0194 rate_req->rate = (unsigned long)response.rate;
0195
0196 return 0;
0197 }
0198
0199 static int tegra_bpmp_clk_set_parent(struct clk_hw *hw, u8 index)
0200 {
0201 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
0202 struct cmd_clk_set_parent_response response;
0203 struct cmd_clk_set_parent_request request;
0204 struct tegra_bpmp_clk_message msg;
0205 int err;
0206
0207 memset(&request, 0, sizeof(request));
0208 request.parent_id = clk->parents[index];
0209
0210 memset(&msg, 0, sizeof(msg));
0211 msg.cmd = CMD_CLK_SET_PARENT;
0212 msg.id = clk->id;
0213 msg.tx.data = &request;
0214 msg.tx.size = sizeof(request);
0215 msg.rx.data = &response;
0216 msg.rx.size = sizeof(response);
0217
0218 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
0219 if (err < 0)
0220 return err;
0221
0222
0223
0224 return 0;
0225 }
0226
0227 static u8 tegra_bpmp_clk_get_parent(struct clk_hw *hw)
0228 {
0229 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
0230 struct cmd_clk_get_parent_response response;
0231 struct tegra_bpmp_clk_message msg;
0232 unsigned int i;
0233 int err;
0234
0235 memset(&msg, 0, sizeof(msg));
0236 msg.cmd = CMD_CLK_GET_PARENT;
0237 msg.id = clk->id;
0238 msg.rx.data = &response;
0239 msg.rx.size = sizeof(response);
0240
0241 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
0242 if (err < 0) {
0243 dev_err(clk->bpmp->dev, "failed to get parent for %s: %d\n",
0244 clk_hw_get_name(hw), err);
0245 return U8_MAX;
0246 }
0247
0248 for (i = 0; i < clk->num_parents; i++)
0249 if (clk->parents[i] == response.parent_id)
0250 return i;
0251
0252 return U8_MAX;
0253 }
0254
0255 static int tegra_bpmp_clk_set_rate(struct clk_hw *hw, unsigned long rate,
0256 unsigned long parent_rate)
0257 {
0258 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw);
0259 struct cmd_clk_set_rate_response response;
0260 struct cmd_clk_set_rate_request request;
0261 struct tegra_bpmp_clk_message msg;
0262
0263 memset(&request, 0, sizeof(request));
0264 request.rate = min_t(u64, rate, S64_MAX);
0265
0266 memset(&msg, 0, sizeof(msg));
0267 msg.cmd = CMD_CLK_SET_RATE;
0268 msg.id = clk->id;
0269 msg.tx.data = &request;
0270 msg.tx.size = sizeof(request);
0271 msg.rx.data = &response;
0272 msg.rx.size = sizeof(response);
0273
0274 return tegra_bpmp_clk_transfer(clk->bpmp, &msg);
0275 }
0276
0277 static const struct clk_ops tegra_bpmp_clk_gate_ops = {
0278 .prepare = tegra_bpmp_clk_prepare,
0279 .unprepare = tegra_bpmp_clk_unprepare,
0280 .is_prepared = tegra_bpmp_clk_is_prepared,
0281 .recalc_rate = tegra_bpmp_clk_recalc_rate,
0282 };
0283
0284 static const struct clk_ops tegra_bpmp_clk_mux_ops = {
0285 .prepare = tegra_bpmp_clk_prepare,
0286 .unprepare = tegra_bpmp_clk_unprepare,
0287 .is_prepared = tegra_bpmp_clk_is_prepared,
0288 .recalc_rate = tegra_bpmp_clk_recalc_rate,
0289 .set_parent = tegra_bpmp_clk_set_parent,
0290 .get_parent = tegra_bpmp_clk_get_parent,
0291 };
0292
0293 static const struct clk_ops tegra_bpmp_clk_rate_ops = {
0294 .prepare = tegra_bpmp_clk_prepare,
0295 .unprepare = tegra_bpmp_clk_unprepare,
0296 .is_prepared = tegra_bpmp_clk_is_prepared,
0297 .recalc_rate = tegra_bpmp_clk_recalc_rate,
0298 .determine_rate = tegra_bpmp_clk_determine_rate,
0299 .set_rate = tegra_bpmp_clk_set_rate,
0300 };
0301
0302 static const struct clk_ops tegra_bpmp_clk_mux_rate_ops = {
0303 .prepare = tegra_bpmp_clk_prepare,
0304 .unprepare = tegra_bpmp_clk_unprepare,
0305 .is_prepared = tegra_bpmp_clk_is_prepared,
0306 .recalc_rate = tegra_bpmp_clk_recalc_rate,
0307 .determine_rate = tegra_bpmp_clk_determine_rate,
0308 .set_parent = tegra_bpmp_clk_set_parent,
0309 .get_parent = tegra_bpmp_clk_get_parent,
0310 .set_rate = tegra_bpmp_clk_set_rate,
0311 };
0312
0313 static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp *bpmp)
0314 {
0315 struct cmd_clk_get_max_clk_id_response response;
0316 struct tegra_bpmp_clk_message msg;
0317 int err;
0318
0319 memset(&msg, 0, sizeof(msg));
0320 msg.cmd = CMD_CLK_GET_MAX_CLK_ID;
0321 msg.rx.data = &response;
0322 msg.rx.size = sizeof(response);
0323
0324 err = tegra_bpmp_clk_transfer(bpmp, &msg);
0325 if (err < 0)
0326 return err;
0327
0328 if (response.max_id > INT_MAX)
0329 return -E2BIG;
0330
0331 return response.max_id;
0332 }
0333
0334 static int tegra_bpmp_clk_get_info(struct tegra_bpmp *bpmp, unsigned int id,
0335 struct tegra_bpmp_clk_info *info)
0336 {
0337 struct cmd_clk_get_all_info_response response;
0338 struct tegra_bpmp_clk_message msg;
0339 unsigned int i;
0340 int err;
0341
0342 memset(&msg, 0, sizeof(msg));
0343 msg.cmd = CMD_CLK_GET_ALL_INFO;
0344 msg.id = id;
0345 msg.rx.data = &response;
0346 msg.rx.size = sizeof(response);
0347
0348 err = tegra_bpmp_clk_transfer(bpmp, &msg);
0349 if (err < 0)
0350 return err;
0351
0352 strlcpy(info->name, response.name, MRQ_CLK_NAME_MAXLEN);
0353 info->num_parents = response.num_parents;
0354
0355 for (i = 0; i < info->num_parents; i++)
0356 info->parents[i] = response.parents[i];
0357
0358 info->flags = response.flags;
0359
0360 return 0;
0361 }
0362
0363 static void tegra_bpmp_clk_info_dump(struct tegra_bpmp *bpmp,
0364 const char *level,
0365 const struct tegra_bpmp_clk_info *info)
0366 {
0367 const char *prefix = "";
0368 struct seq_buf buf;
0369 unsigned int i;
0370 char flags[64];
0371
0372 seq_buf_init(&buf, flags, sizeof(flags));
0373
0374 if (info->flags)
0375 seq_buf_printf(&buf, "(");
0376
0377 if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
0378 seq_buf_printf(&buf, "%smux", prefix);
0379 prefix = ", ";
0380 }
0381
0382 if ((info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE) == 0) {
0383 seq_buf_printf(&buf, "%sfixed", prefix);
0384 prefix = ", ";
0385 }
0386
0387 if (info->flags & TEGRA_BPMP_CLK_IS_ROOT) {
0388 seq_buf_printf(&buf, "%sroot", prefix);
0389 prefix = ", ";
0390 }
0391
0392 if (info->flags)
0393 seq_buf_printf(&buf, ")");
0394
0395 dev_printk(level, bpmp->dev, "%03u: %s\n", info->id, info->name);
0396 dev_printk(level, bpmp->dev, " flags: %lx %s\n", info->flags, flags);
0397 dev_printk(level, bpmp->dev, " parents: %u\n", info->num_parents);
0398
0399 for (i = 0; i < info->num_parents; i++)
0400 dev_printk(level, bpmp->dev, " %03u\n", info->parents[i]);
0401 }
0402
0403 static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp,
0404 struct tegra_bpmp_clk_info **clocksp)
0405 {
0406 struct tegra_bpmp_clk_info *clocks;
0407 unsigned int max_id, id, count = 0;
0408 unsigned int holes = 0;
0409 int err;
0410
0411 err = tegra_bpmp_clk_get_max_id(bpmp);
0412 if (err < 0)
0413 return err;
0414
0415 max_id = err;
0416
0417 dev_dbg(bpmp->dev, "maximum clock ID: %u\n", max_id);
0418
0419 clocks = kcalloc(max_id + 1, sizeof(*clocks), GFP_KERNEL);
0420 if (!clocks)
0421 return -ENOMEM;
0422
0423 for (id = 0; id <= max_id; id++) {
0424 struct tegra_bpmp_clk_info *info = &clocks[count];
0425
0426 err = tegra_bpmp_clk_get_info(bpmp, id, info);
0427 if (err < 0)
0428 continue;
0429
0430 if (info->num_parents >= U8_MAX) {
0431 dev_err(bpmp->dev,
0432 "clock %u has too many parents (%u, max: %u)\n",
0433 id, info->num_parents, U8_MAX);
0434 continue;
0435 }
0436
0437
0438 if (info->name[0] == '\0') {
0439 holes++;
0440 continue;
0441 }
0442
0443 info->id = id;
0444 count++;
0445
0446 if (TEGRA_BPMP_DUMP_CLOCK_INFO)
0447 tegra_bpmp_clk_info_dump(bpmp, KERN_DEBUG, info);
0448 }
0449
0450 dev_dbg(bpmp->dev, "holes: %u\n", holes);
0451 *clocksp = clocks;
0452
0453 return count;
0454 }
0455
0456 static unsigned int
0457 tegra_bpmp_clk_id_to_index(const struct tegra_bpmp_clk_info *clocks,
0458 unsigned int num_clocks, unsigned int id)
0459 {
0460 unsigned int i;
0461
0462 for (i = 0; i < num_clocks; i++)
0463 if (clocks[i].id == id)
0464 return i;
0465
0466 return UINT_MAX;
0467 }
0468
0469 static const struct tegra_bpmp_clk_info *
0470 tegra_bpmp_clk_find(const struct tegra_bpmp_clk_info *clocks,
0471 unsigned int num_clocks, unsigned int id)
0472 {
0473 unsigned int i;
0474
0475 i = tegra_bpmp_clk_id_to_index(clocks, num_clocks, id);
0476
0477 if (i < num_clocks)
0478 return &clocks[i];
0479
0480 return NULL;
0481 }
0482
0483 static struct tegra_bpmp_clk *
0484 tegra_bpmp_clk_register(struct tegra_bpmp *bpmp,
0485 const struct tegra_bpmp_clk_info *info,
0486 const struct tegra_bpmp_clk_info *clocks,
0487 unsigned int num_clocks)
0488 {
0489 struct tegra_bpmp_clk *clk;
0490 struct clk_init_data init;
0491 const char **parents;
0492 unsigned int i;
0493 int err;
0494
0495 clk = devm_kzalloc(bpmp->dev, sizeof(*clk), GFP_KERNEL);
0496 if (!clk)
0497 return ERR_PTR(-ENOMEM);
0498
0499 clk->id = info->id;
0500 clk->bpmp = bpmp;
0501
0502 clk->parents = devm_kcalloc(bpmp->dev, info->num_parents,
0503 sizeof(*clk->parents), GFP_KERNEL);
0504 if (!clk->parents)
0505 return ERR_PTR(-ENOMEM);
0506
0507 clk->num_parents = info->num_parents;
0508
0509
0510 memset(&init, 0, sizeof(init));
0511 init.name = info->name;
0512 clk->hw.init = &init;
0513
0514 if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
0515 if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE)
0516 init.ops = &tegra_bpmp_clk_mux_rate_ops;
0517 else
0518 init.ops = &tegra_bpmp_clk_mux_ops;
0519 } else {
0520 if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE)
0521 init.ops = &tegra_bpmp_clk_rate_ops;
0522 else
0523 init.ops = &tegra_bpmp_clk_gate_ops;
0524 }
0525
0526 init.num_parents = info->num_parents;
0527
0528 parents = kcalloc(info->num_parents, sizeof(*parents), GFP_KERNEL);
0529 if (!parents)
0530 return ERR_PTR(-ENOMEM);
0531
0532 for (i = 0; i < info->num_parents; i++) {
0533 const struct tegra_bpmp_clk_info *parent;
0534
0535
0536 clk->parents[i] = info->parents[i];
0537
0538 parent = tegra_bpmp_clk_find(clocks, num_clocks,
0539 info->parents[i]);
0540 if (!parent) {
0541 dev_err(bpmp->dev, "no parent %u found for %u\n",
0542 info->parents[i], info->id);
0543 continue;
0544 }
0545
0546 parents[i] = parent->name;
0547 }
0548
0549 init.parent_names = parents;
0550
0551 err = devm_clk_hw_register(bpmp->dev, &clk->hw);
0552
0553 kfree(parents);
0554
0555 if (err < 0)
0556 return ERR_PTR(err);
0557
0558 return clk;
0559 }
0560
0561 static void tegra_bpmp_register_clocks_one(struct tegra_bpmp *bpmp,
0562 struct tegra_bpmp_clk_info *infos,
0563 unsigned int i,
0564 unsigned int count)
0565 {
0566 unsigned int j;
0567 struct tegra_bpmp_clk_info *info;
0568 struct tegra_bpmp_clk *clk;
0569
0570 if (bpmp->clocks[i]) {
0571
0572 return;
0573 }
0574
0575 info = &infos[i];
0576 for (j = 0; j < info->num_parents; ++j) {
0577 unsigned int p_id = info->parents[j];
0578 unsigned int p_i = tegra_bpmp_clk_id_to_index(infos, count,
0579 p_id);
0580 if (p_i < count)
0581 tegra_bpmp_register_clocks_one(bpmp, infos, p_i, count);
0582 }
0583
0584 clk = tegra_bpmp_clk_register(bpmp, info, infos, count);
0585 if (IS_ERR(clk)) {
0586 dev_err(bpmp->dev,
0587 "failed to register clock %u (%s): %ld\n",
0588 info->id, info->name, PTR_ERR(clk));
0589
0590
0591
0592
0593 }
0594
0595 bpmp->clocks[i] = clk;
0596 }
0597
0598 static int tegra_bpmp_register_clocks(struct tegra_bpmp *bpmp,
0599 struct tegra_bpmp_clk_info *infos,
0600 unsigned int count)
0601 {
0602 unsigned int i;
0603
0604 bpmp->num_clocks = count;
0605
0606 bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(struct tegra_bpmp_clk), GFP_KERNEL);
0607 if (!bpmp->clocks)
0608 return -ENOMEM;
0609
0610 for (i = 0; i < count; i++) {
0611 tegra_bpmp_register_clocks_one(bpmp, infos, i, count);
0612 }
0613
0614 return 0;
0615 }
0616
0617 static void tegra_bpmp_unregister_clocks(struct tegra_bpmp *bpmp)
0618 {
0619 unsigned int i;
0620
0621 for (i = 0; i < bpmp->num_clocks; i++)
0622 clk_hw_unregister(&bpmp->clocks[i]->hw);
0623 }
0624
0625 static struct clk_hw *tegra_bpmp_clk_of_xlate(struct of_phandle_args *clkspec,
0626 void *data)
0627 {
0628 unsigned int id = clkspec->args[0], i;
0629 struct tegra_bpmp *bpmp = data;
0630
0631 for (i = 0; i < bpmp->num_clocks; i++) {
0632 struct tegra_bpmp_clk *clk = bpmp->clocks[i];
0633
0634 if (!clk)
0635 continue;
0636
0637 if (clk->id == id)
0638 return &clk->hw;
0639 }
0640
0641 return NULL;
0642 }
0643
0644 int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp)
0645 {
0646 struct tegra_bpmp_clk_info *clocks;
0647 unsigned int count;
0648 int err;
0649
0650 err = tegra_bpmp_probe_clocks(bpmp, &clocks);
0651 if (err < 0)
0652 return err;
0653
0654 count = err;
0655
0656 dev_dbg(bpmp->dev, "%u clocks probed\n", count);
0657
0658 err = tegra_bpmp_register_clocks(bpmp, clocks, count);
0659 if (err < 0)
0660 goto free;
0661
0662 err = of_clk_add_hw_provider(bpmp->dev->of_node,
0663 tegra_bpmp_clk_of_xlate,
0664 bpmp);
0665 if (err < 0) {
0666 tegra_bpmp_unregister_clocks(bpmp);
0667 goto free;
0668 }
0669
0670 free:
0671 kfree(clocks);
0672 return err;
0673 }