1 /* 2 * Copyright (C) 2016 NVIDIA Corporation 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9 #include <linux/clk-provider.h> 10 #include <linux/device.h> 11 #include <linux/seq_buf.h> 12 #include <linux/slab.h> 13 14 #include <soc/tegra/bpmp.h> 15 #include <soc/tegra/bpmp-abi.h> 16 17 #define TEGRA_BPMP_DUMP_CLOCK_INFO 0 18 19 #define TEGRA_BPMP_CLK_HAS_MUX BIT(0) 20 #define TEGRA_BPMP_CLK_HAS_SET_RATE BIT(1) 21 #define TEGRA_BPMP_CLK_IS_ROOT BIT(2) 22 23 struct tegra_bpmp_clk_info { 24 unsigned int id; 25 char name[MRQ_CLK_NAME_MAXLEN]; 26 unsigned int parents[MRQ_CLK_MAX_PARENTS]; 27 unsigned int num_parents; 28 unsigned long flags; 29 }; 30 31 struct tegra_bpmp_clk { 32 struct clk_hw hw; 33 34 struct tegra_bpmp *bpmp; 35 unsigned int id; 36 37 unsigned int num_parents; 38 unsigned int *parents; 39 }; 40 41 static inline struct tegra_bpmp_clk *to_tegra_bpmp_clk(struct clk_hw *hw) 42 { 43 return container_of(hw, struct tegra_bpmp_clk, hw); 44 } 45 46 struct tegra_bpmp_clk_message { 47 unsigned int cmd; 48 unsigned int id; 49 50 struct { 51 const void *data; 52 size_t size; 53 } tx; 54 55 struct { 56 void *data; 57 size_t size; 58 } rx; 59 }; 60 61 static int tegra_bpmp_clk_transfer(struct tegra_bpmp *bpmp, 62 const struct tegra_bpmp_clk_message *clk) 63 { 64 struct mrq_clk_request request; 65 struct tegra_bpmp_message msg; 66 void *req = &request; 67 68 memset(&request, 0, sizeof(request)); 69 request.cmd_and_id = (clk->cmd << 24) | clk->id; 70 71 /* 72 * The mrq_clk_request structure has an anonymous union at offset 4 73 * that contains all possible sub-command structures. Copy the data 74 * to that union. Ideally we'd be able to refer to it by name, but 75 * doing so would require changing the ABI header and increase the 76 * maintenance burden. 77 */ 78 memcpy(req + 4, clk->tx.data, clk->tx.size); 79 80 memset(&msg, 0, sizeof(msg)); 81 msg.mrq = MRQ_CLK; 82 msg.tx.data = &request; 83 msg.tx.size = sizeof(request); 84 msg.rx.data = clk->rx.data; 85 msg.rx.size = clk->rx.size; 86 87 return tegra_bpmp_transfer(bpmp, &msg); 88 } 89 90 static int tegra_bpmp_clk_prepare(struct clk_hw *hw) 91 { 92 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw); 93 struct tegra_bpmp_clk_message msg; 94 95 memset(&msg, 0, sizeof(msg)); 96 msg.cmd = CMD_CLK_ENABLE; 97 msg.id = clk->id; 98 99 return tegra_bpmp_clk_transfer(clk->bpmp, &msg); 100 } 101 102 static void tegra_bpmp_clk_unprepare(struct clk_hw *hw) 103 { 104 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw); 105 struct tegra_bpmp_clk_message msg; 106 int err; 107 108 memset(&msg, 0, sizeof(msg)); 109 msg.cmd = CMD_CLK_DISABLE; 110 msg.id = clk->id; 111 112 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg); 113 if (err < 0) 114 dev_err(clk->bpmp->dev, "failed to disable clock %s: %d\n", 115 clk_hw_get_name(hw), err); 116 } 117 118 static int tegra_bpmp_clk_is_prepared(struct clk_hw *hw) 119 { 120 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw); 121 struct cmd_clk_is_enabled_response response; 122 struct tegra_bpmp_clk_message msg; 123 int err; 124 125 memset(&msg, 0, sizeof(msg)); 126 msg.cmd = CMD_CLK_IS_ENABLED; 127 msg.id = clk->id; 128 msg.rx.data = &response; 129 msg.rx.size = sizeof(response); 130 131 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg); 132 if (err < 0) 133 return err; 134 135 return response.state; 136 } 137 138 static unsigned long tegra_bpmp_clk_recalc_rate(struct clk_hw *hw, 139 unsigned long parent_rate) 140 { 141 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw); 142 struct cmd_clk_get_rate_response response; 143 struct cmd_clk_get_rate_request request; 144 struct tegra_bpmp_clk_message msg; 145 int err; 146 147 memset(&msg, 0, sizeof(msg)); 148 msg.cmd = CMD_CLK_GET_RATE; 149 msg.id = clk->id; 150 msg.tx.data = &request; 151 msg.tx.size = sizeof(request); 152 msg.rx.data = &response; 153 msg.rx.size = sizeof(response); 154 155 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg); 156 if (err < 0) 157 return err; 158 159 return response.rate; 160 } 161 162 static long tegra_bpmp_clk_round_rate(struct clk_hw *hw, unsigned long rate, 163 unsigned long *parent_rate) 164 { 165 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw); 166 struct cmd_clk_round_rate_response response; 167 struct cmd_clk_round_rate_request request; 168 struct tegra_bpmp_clk_message msg; 169 int err; 170 171 memset(&request, 0, sizeof(request)); 172 request.rate = rate; 173 174 memset(&msg, 0, sizeof(msg)); 175 msg.cmd = CMD_CLK_ROUND_RATE; 176 msg.id = clk->id; 177 msg.tx.data = &request; 178 msg.tx.size = sizeof(request); 179 msg.rx.data = &response; 180 msg.rx.size = sizeof(response); 181 182 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg); 183 if (err < 0) 184 return err; 185 186 return response.rate; 187 } 188 189 static int tegra_bpmp_clk_set_parent(struct clk_hw *hw, u8 index) 190 { 191 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw); 192 struct cmd_clk_set_parent_response response; 193 struct cmd_clk_set_parent_request request; 194 struct tegra_bpmp_clk_message msg; 195 int err; 196 197 memset(&request, 0, sizeof(request)); 198 request.parent_id = clk->parents[index]; 199 200 memset(&msg, 0, sizeof(msg)); 201 msg.cmd = CMD_CLK_SET_PARENT; 202 msg.id = clk->id; 203 msg.tx.data = &request; 204 msg.tx.size = sizeof(request); 205 msg.rx.data = &response; 206 msg.rx.size = sizeof(response); 207 208 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg); 209 if (err < 0) 210 return err; 211 212 /* XXX check parent ID in response */ 213 214 return 0; 215 } 216 217 static u8 tegra_bpmp_clk_get_parent(struct clk_hw *hw) 218 { 219 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw); 220 struct cmd_clk_get_parent_response response; 221 struct tegra_bpmp_clk_message msg; 222 unsigned int i; 223 int err; 224 225 memset(&msg, 0, sizeof(msg)); 226 msg.cmd = CMD_CLK_GET_PARENT; 227 msg.id = clk->id; 228 msg.rx.data = &response; 229 msg.rx.size = sizeof(response); 230 231 err = tegra_bpmp_clk_transfer(clk->bpmp, &msg); 232 if (err < 0) { 233 dev_err(clk->bpmp->dev, "failed to get parent for %s: %d\n", 234 clk_hw_get_name(hw), err); 235 return U8_MAX; 236 } 237 238 for (i = 0; i < clk->num_parents; i++) 239 if (clk->parents[i] == response.parent_id) 240 return i; 241 242 return U8_MAX; 243 } 244 245 static int tegra_bpmp_clk_set_rate(struct clk_hw *hw, unsigned long rate, 246 unsigned long parent_rate) 247 { 248 struct tegra_bpmp_clk *clk = to_tegra_bpmp_clk(hw); 249 struct cmd_clk_set_rate_response response; 250 struct cmd_clk_set_rate_request request; 251 struct tegra_bpmp_clk_message msg; 252 253 memset(&request, 0, sizeof(request)); 254 request.rate = rate; 255 256 memset(&msg, 0, sizeof(msg)); 257 msg.cmd = CMD_CLK_SET_RATE; 258 msg.id = clk->id; 259 msg.tx.data = &request; 260 msg.tx.size = sizeof(request); 261 msg.rx.data = &response; 262 msg.rx.size = sizeof(response); 263 264 return tegra_bpmp_clk_transfer(clk->bpmp, &msg); 265 } 266 267 static const struct clk_ops tegra_bpmp_clk_gate_ops = { 268 .prepare = tegra_bpmp_clk_prepare, 269 .unprepare = tegra_bpmp_clk_unprepare, 270 .is_prepared = tegra_bpmp_clk_is_prepared, 271 .recalc_rate = tegra_bpmp_clk_recalc_rate, 272 }; 273 274 static const struct clk_ops tegra_bpmp_clk_mux_ops = { 275 .prepare = tegra_bpmp_clk_prepare, 276 .unprepare = tegra_bpmp_clk_unprepare, 277 .is_prepared = tegra_bpmp_clk_is_prepared, 278 .recalc_rate = tegra_bpmp_clk_recalc_rate, 279 .set_parent = tegra_bpmp_clk_set_parent, 280 .get_parent = tegra_bpmp_clk_get_parent, 281 }; 282 283 static const struct clk_ops tegra_bpmp_clk_rate_ops = { 284 .prepare = tegra_bpmp_clk_prepare, 285 .unprepare = tegra_bpmp_clk_unprepare, 286 .is_prepared = tegra_bpmp_clk_is_prepared, 287 .recalc_rate = tegra_bpmp_clk_recalc_rate, 288 .round_rate = tegra_bpmp_clk_round_rate, 289 .set_rate = tegra_bpmp_clk_set_rate, 290 }; 291 292 static const struct clk_ops tegra_bpmp_clk_mux_rate_ops = { 293 .prepare = tegra_bpmp_clk_prepare, 294 .unprepare = tegra_bpmp_clk_unprepare, 295 .is_prepared = tegra_bpmp_clk_is_prepared, 296 .recalc_rate = tegra_bpmp_clk_recalc_rate, 297 .round_rate = tegra_bpmp_clk_round_rate, 298 .set_parent = tegra_bpmp_clk_set_parent, 299 .get_parent = tegra_bpmp_clk_get_parent, 300 .set_rate = tegra_bpmp_clk_set_rate, 301 }; 302 303 static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp *bpmp) 304 { 305 struct cmd_clk_get_max_clk_id_response response; 306 struct tegra_bpmp_clk_message msg; 307 int err; 308 309 memset(&msg, 0, sizeof(msg)); 310 msg.cmd = CMD_CLK_GET_MAX_CLK_ID; 311 msg.rx.data = &response; 312 msg.rx.size = sizeof(response); 313 314 err = tegra_bpmp_clk_transfer(bpmp, &msg); 315 if (err < 0) 316 return err; 317 318 if (response.max_id > INT_MAX) 319 return -E2BIG; 320 321 return response.max_id; 322 } 323 324 static int tegra_bpmp_clk_get_info(struct tegra_bpmp *bpmp, unsigned int id, 325 struct tegra_bpmp_clk_info *info) 326 { 327 struct cmd_clk_get_all_info_response response; 328 struct tegra_bpmp_clk_message msg; 329 unsigned int i; 330 int err; 331 332 memset(&msg, 0, sizeof(msg)); 333 msg.cmd = CMD_CLK_GET_ALL_INFO; 334 msg.id = id; 335 msg.rx.data = &response; 336 msg.rx.size = sizeof(response); 337 338 err = tegra_bpmp_clk_transfer(bpmp, &msg); 339 if (err < 0) 340 return err; 341 342 strlcpy(info->name, response.name, MRQ_CLK_NAME_MAXLEN); 343 info->num_parents = response.num_parents; 344 345 for (i = 0; i < info->num_parents; i++) 346 info->parents[i] = response.parents[i]; 347 348 info->flags = response.flags; 349 350 return 0; 351 } 352 353 static void tegra_bpmp_clk_info_dump(struct tegra_bpmp *bpmp, 354 const char *level, 355 const struct tegra_bpmp_clk_info *info) 356 { 357 const char *prefix = ""; 358 struct seq_buf buf; 359 unsigned int i; 360 char flags[64]; 361 362 seq_buf_init(&buf, flags, sizeof(flags)); 363 364 if (info->flags) 365 seq_buf_printf(&buf, "("); 366 367 if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) { 368 seq_buf_printf(&buf, "%smux", prefix); 369 prefix = ", "; 370 } 371 372 if ((info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE) == 0) { 373 seq_buf_printf(&buf, "%sfixed", prefix); 374 prefix = ", "; 375 } 376 377 if (info->flags & TEGRA_BPMP_CLK_IS_ROOT) { 378 seq_buf_printf(&buf, "%sroot", prefix); 379 prefix = ", "; 380 } 381 382 if (info->flags) 383 seq_buf_printf(&buf, ")"); 384 385 dev_printk(level, bpmp->dev, "%03u: %s\n", info->id, info->name); 386 dev_printk(level, bpmp->dev, " flags: %lx %s\n", info->flags, flags); 387 dev_printk(level, bpmp->dev, " parents: %u\n", info->num_parents); 388 389 for (i = 0; i < info->num_parents; i++) 390 dev_printk(level, bpmp->dev, " %03u\n", info->parents[i]); 391 } 392 393 static int tegra_bpmp_probe_clocks(struct tegra_bpmp *bpmp, 394 struct tegra_bpmp_clk_info **clocksp) 395 { 396 struct tegra_bpmp_clk_info *clocks; 397 unsigned int max_id, id, count = 0; 398 unsigned int holes = 0; 399 int err; 400 401 err = tegra_bpmp_clk_get_max_id(bpmp); 402 if (err < 0) 403 return err; 404 405 max_id = err; 406 407 dev_dbg(bpmp->dev, "maximum clock ID: %u\n", max_id); 408 409 clocks = kcalloc(max_id + 1, sizeof(*clocks), GFP_KERNEL); 410 if (!clocks) 411 return -ENOMEM; 412 413 for (id = 0; id <= max_id; id++) { 414 struct tegra_bpmp_clk_info *info = &clocks[count]; 415 416 err = tegra_bpmp_clk_get_info(bpmp, id, info); 417 if (err < 0) { 418 dev_err(bpmp->dev, "failed to query clock %u: %d\n", 419 id, err); 420 continue; 421 } 422 423 if (info->num_parents >= U8_MAX) { 424 dev_err(bpmp->dev, 425 "clock %u has too many parents (%u, max: %u)\n", 426 id, info->num_parents, U8_MAX); 427 continue; 428 } 429 430 /* clock not exposed by BPMP */ 431 if (info->name[0] == '\0') { 432 holes++; 433 continue; 434 } 435 436 info->id = id; 437 count++; 438 439 if (TEGRA_BPMP_DUMP_CLOCK_INFO) 440 tegra_bpmp_clk_info_dump(bpmp, KERN_DEBUG, info); 441 } 442 443 dev_dbg(bpmp->dev, "holes: %u\n", holes); 444 *clocksp = clocks; 445 446 return count; 447 } 448 449 static const struct tegra_bpmp_clk_info * 450 tegra_bpmp_clk_find(const struct tegra_bpmp_clk_info *clocks, 451 unsigned int num_clocks, unsigned int id) 452 { 453 unsigned int i; 454 455 for (i = 0; i < num_clocks; i++) 456 if (clocks[i].id == id) 457 return &clocks[i]; 458 459 return NULL; 460 } 461 462 static struct tegra_bpmp_clk * 463 tegra_bpmp_clk_register(struct tegra_bpmp *bpmp, 464 const struct tegra_bpmp_clk_info *info, 465 const struct tegra_bpmp_clk_info *clocks, 466 unsigned int num_clocks) 467 { 468 struct tegra_bpmp_clk *clk; 469 struct clk_init_data init; 470 const char **parents; 471 unsigned int i; 472 int err; 473 474 clk = devm_kzalloc(bpmp->dev, sizeof(*clk), GFP_KERNEL); 475 if (!clk) 476 return ERR_PTR(-ENOMEM); 477 478 clk->id = info->id; 479 clk->bpmp = bpmp; 480 481 clk->parents = devm_kcalloc(bpmp->dev, info->num_parents, 482 sizeof(*clk->parents), GFP_KERNEL); 483 if (!clk->parents) 484 return ERR_PTR(-ENOMEM); 485 486 clk->num_parents = info->num_parents; 487 488 /* hardware clock initialization */ 489 memset(&init, 0, sizeof(init)); 490 init.name = info->name; 491 clk->hw.init = &init; 492 493 if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) { 494 if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE) 495 init.ops = &tegra_bpmp_clk_mux_rate_ops; 496 else 497 init.ops = &tegra_bpmp_clk_mux_ops; 498 } else { 499 if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE) 500 init.ops = &tegra_bpmp_clk_rate_ops; 501 else 502 init.ops = &tegra_bpmp_clk_gate_ops; 503 } 504 505 init.num_parents = info->num_parents; 506 507 parents = kcalloc(info->num_parents, sizeof(*parents), GFP_KERNEL); 508 if (!parents) 509 return ERR_PTR(-ENOMEM); 510 511 for (i = 0; i < info->num_parents; i++) { 512 const struct tegra_bpmp_clk_info *parent; 513 514 /* keep a private copy of the ID to parent index map */ 515 clk->parents[i] = info->parents[i]; 516 517 parent = tegra_bpmp_clk_find(clocks, num_clocks, 518 info->parents[i]); 519 if (!parent) { 520 dev_err(bpmp->dev, "no parent %u found for %u\n", 521 info->parents[i], info->id); 522 continue; 523 } 524 525 parents[i] = parent->name; 526 } 527 528 init.parent_names = parents; 529 530 err = devm_clk_hw_register(bpmp->dev, &clk->hw); 531 532 kfree(parents); 533 534 if (err < 0) 535 return ERR_PTR(err); 536 537 return clk; 538 } 539 540 static int tegra_bpmp_register_clocks(struct tegra_bpmp *bpmp, 541 struct tegra_bpmp_clk_info *infos, 542 unsigned int count) 543 { 544 struct tegra_bpmp_clk *clk; 545 unsigned int i; 546 547 bpmp->num_clocks = count; 548 549 bpmp->clocks = devm_kcalloc(bpmp->dev, count, sizeof(clk), GFP_KERNEL); 550 if (!bpmp->clocks) 551 return -ENOMEM; 552 553 for (i = 0; i < count; i++) { 554 struct tegra_bpmp_clk_info *info = &infos[i]; 555 556 clk = tegra_bpmp_clk_register(bpmp, info, infos, count); 557 if (IS_ERR(clk)) { 558 dev_err(bpmp->dev, 559 "failed to register clock %u (%s): %ld\n", 560 info->id, info->name, PTR_ERR(clk)); 561 continue; 562 } 563 564 bpmp->clocks[i] = clk; 565 } 566 567 return 0; 568 } 569 570 static void tegra_bpmp_unregister_clocks(struct tegra_bpmp *bpmp) 571 { 572 unsigned int i; 573 574 for (i = 0; i < bpmp->num_clocks; i++) 575 clk_hw_unregister(&bpmp->clocks[i]->hw); 576 } 577 578 static struct clk_hw *tegra_bpmp_clk_of_xlate(struct of_phandle_args *clkspec, 579 void *data) 580 { 581 unsigned int id = clkspec->args[0], i; 582 struct tegra_bpmp *bpmp = data; 583 584 for (i = 0; i < bpmp->num_clocks; i++) 585 if (bpmp->clocks[i]->id == id) 586 return &bpmp->clocks[i]->hw; 587 588 return NULL; 589 } 590 591 int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp) 592 { 593 struct tegra_bpmp_clk_info *clocks; 594 unsigned int count; 595 int err; 596 597 err = tegra_bpmp_probe_clocks(bpmp, &clocks); 598 if (err < 0) 599 return err; 600 601 count = err; 602 603 dev_dbg(bpmp->dev, "%u clocks probed\n", count); 604 605 err = tegra_bpmp_register_clocks(bpmp, clocks, count); 606 if (err < 0) 607 goto free; 608 609 err = of_clk_add_hw_provider(bpmp->dev->of_node, 610 tegra_bpmp_clk_of_xlate, 611 bpmp); 612 if (err < 0) { 613 tegra_bpmp_unregister_clocks(bpmp); 614 goto free; 615 } 616 617 free: 618 kfree(clocks); 619 return err; 620 } 621