1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * PS3 repository routines. 4 * 5 * Copyright (C) 2006 Sony Computer Entertainment Inc. 6 * Copyright 2006 Sony Corp. 7 */ 8 9 #include <linux/minmax.h> 10 11 #include <asm/lv1call.h> 12 13 #include "platform.h" 14 15 enum ps3_vendor_id { 16 PS3_VENDOR_ID_NONE = 0, 17 PS3_VENDOR_ID_SONY = 0x8000000000000000UL, 18 }; 19 20 enum ps3_lpar_id { 21 PS3_LPAR_ID_CURRENT = 0, 22 PS3_LPAR_ID_PME = 1, 23 }; 24 25 #define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__) 26 static void _dump_field(const char *hdr, u64 n, const char *func, int line) 27 { 28 #if defined(DEBUG) 29 char s[16]; 30 const char *const in = (const char *)&n; 31 unsigned int i; 32 33 for (i = 0; i < 8; i++) 34 s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.'; 35 s[i] = 0; 36 37 pr_devel("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s); 38 #endif 39 } 40 41 #define dump_node_name(_a, _b, _c, _d, _e) \ 42 _dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__) 43 static void _dump_node_name(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, 44 u64 n4, const char *func, int line) 45 { 46 pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id); 47 _dump_field("n1: ", n1, func, line); 48 _dump_field("n2: ", n2, func, line); 49 _dump_field("n3: ", n3, func, line); 50 _dump_field("n4: ", n4, func, line); 51 } 52 53 #define dump_node(_a, _b, _c, _d, _e, _f, _g) \ 54 _dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) 55 static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, 56 u64 v1, u64 v2, const char *func, int line) 57 { 58 pr_devel("%s:%d: lpar: %u\n", func, line, lpar_id); 59 _dump_field("n1: ", n1, func, line); 60 _dump_field("n2: ", n2, func, line); 61 _dump_field("n3: ", n3, func, line); 62 _dump_field("n4: ", n4, func, line); 63 pr_devel("%s:%d: v1: %016llx\n", func, line, v1); 64 pr_devel("%s:%d: v2: %016llx\n", func, line, v2); 65 } 66 67 /** 68 * make_first_field - Make the first field of a repository node name. 69 * @text: Text portion of the field. 70 * @index: Numeric index portion of the field. Use zero for 'don't care'. 71 * 72 * This routine sets the vendor id to zero (non-vendor specific). 73 * Returns field value. 74 */ 75 76 static u64 make_first_field(const char *text, u64 index) 77 { 78 u64 n = 0; 79 size_t len = min(strlen(text), sizeof(n)); 80 81 memcpy(&n, text, len); 82 return PS3_VENDOR_ID_NONE + (n >> 32) + index; 83 } 84 85 /** 86 * make_field - Make subsequent fields of a repository node name. 87 * @text: Text portion of the field. Use "" for 'don't care'. 88 * @index: Numeric index portion of the field. Use zero for 'don't care'. 89 * 90 * Returns field value. 91 */ 92 93 static u64 make_field(const char *text, u64 index) 94 { 95 u64 n = 0; 96 97 memcpy((char *)&n, text, strnlen(text, sizeof(n))); 98 return n + index; 99 } 100 101 /** 102 * read_node - Read a repository node from raw fields. 103 * @n1: First field of node name. 104 * @n2: Second field of node name. Use zero for 'don't care'. 105 * @n3: Third field of node name. Use zero for 'don't care'. 106 * @n4: Fourth field of node name. Use zero for 'don't care'. 107 * @v1: First repository value (high word). 108 * @v2: Second repository value (low word). Optional parameter, use zero 109 * for 'don't care'. 110 */ 111 112 static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, 113 u64 *_v1, u64 *_v2) 114 { 115 int result; 116 u64 v1; 117 u64 v2; 118 119 if (lpar_id == PS3_LPAR_ID_CURRENT) { 120 u64 id; 121 lv1_get_logical_partition_id(&id); 122 lpar_id = id; 123 } 124 125 result = lv1_read_repository_node(lpar_id, n1, n2, n3, n4, &v1, 126 &v2); 127 128 if (result) { 129 pr_warn("%s:%d: lv1_read_repository_node failed: %s\n", 130 __func__, __LINE__, ps3_result(result)); 131 dump_node_name(lpar_id, n1, n2, n3, n4); 132 return -ENOENT; 133 } 134 135 dump_node(lpar_id, n1, n2, n3, n4, v1, v2); 136 137 if (_v1) 138 *_v1 = v1; 139 if (_v2) 140 *_v2 = v2; 141 142 if (v1 && !_v1) 143 pr_devel("%s:%d: warning: discarding non-zero v1: %016llx\n", 144 __func__, __LINE__, v1); 145 if (v2 && !_v2) 146 pr_devel("%s:%d: warning: discarding non-zero v2: %016llx\n", 147 __func__, __LINE__, v2); 148 149 return 0; 150 } 151 152 int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, 153 u64 *value) 154 { 155 return read_node(PS3_LPAR_ID_PME, 156 make_first_field("bus", bus_index), 157 make_field(bus_str, 0), 158 0, 0, 159 value, NULL); 160 } 161 162 int ps3_repository_read_bus_id(unsigned int bus_index, u64 *bus_id) 163 { 164 return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), 165 make_field("id", 0), 0, 0, bus_id, NULL); 166 } 167 168 int ps3_repository_read_bus_type(unsigned int bus_index, 169 enum ps3_bus_type *bus_type) 170 { 171 int result; 172 u64 v1 = 0; 173 174 result = read_node(PS3_LPAR_ID_PME, 175 make_first_field("bus", bus_index), 176 make_field("type", 0), 177 0, 0, 178 &v1, NULL); 179 *bus_type = v1; 180 return result; 181 } 182 183 int ps3_repository_read_bus_num_dev(unsigned int bus_index, 184 unsigned int *num_dev) 185 { 186 int result; 187 u64 v1 = 0; 188 189 result = read_node(PS3_LPAR_ID_PME, 190 make_first_field("bus", bus_index), 191 make_field("num_dev", 0), 192 0, 0, 193 &v1, NULL); 194 *num_dev = v1; 195 return result; 196 } 197 198 int ps3_repository_read_dev_str(unsigned int bus_index, 199 unsigned int dev_index, const char *dev_str, u64 *value) 200 { 201 return read_node(PS3_LPAR_ID_PME, 202 make_first_field("bus", bus_index), 203 make_field("dev", dev_index), 204 make_field(dev_str, 0), 205 0, 206 value, NULL); 207 } 208 209 int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index, 210 u64 *dev_id) 211 { 212 return read_node(PS3_LPAR_ID_PME, make_first_field("bus", bus_index), 213 make_field("dev", dev_index), make_field("id", 0), 0, 214 dev_id, NULL); 215 } 216 217 int ps3_repository_read_dev_type(unsigned int bus_index, 218 unsigned int dev_index, enum ps3_dev_type *dev_type) 219 { 220 int result; 221 u64 v1 = 0; 222 223 result = read_node(PS3_LPAR_ID_PME, 224 make_first_field("bus", bus_index), 225 make_field("dev", dev_index), 226 make_field("type", 0), 227 0, 228 &v1, NULL); 229 *dev_type = v1; 230 return result; 231 } 232 233 int ps3_repository_read_dev_intr(unsigned int bus_index, 234 unsigned int dev_index, unsigned int intr_index, 235 enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id) 236 { 237 int result; 238 u64 v1 = 0; 239 u64 v2 = 0; 240 241 result = read_node(PS3_LPAR_ID_PME, 242 make_first_field("bus", bus_index), 243 make_field("dev", dev_index), 244 make_field("intr", intr_index), 245 0, 246 &v1, &v2); 247 *intr_type = v1; 248 *interrupt_id = v2; 249 return result; 250 } 251 252 int ps3_repository_read_dev_reg_type(unsigned int bus_index, 253 unsigned int dev_index, unsigned int reg_index, 254 enum ps3_reg_type *reg_type) 255 { 256 int result; 257 u64 v1 = 0; 258 259 result = read_node(PS3_LPAR_ID_PME, 260 make_first_field("bus", bus_index), 261 make_field("dev", dev_index), 262 make_field("reg", reg_index), 263 make_field("type", 0), 264 &v1, NULL); 265 *reg_type = v1; 266 return result; 267 } 268 269 int ps3_repository_read_dev_reg_addr(unsigned int bus_index, 270 unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len) 271 { 272 return read_node(PS3_LPAR_ID_PME, 273 make_first_field("bus", bus_index), 274 make_field("dev", dev_index), 275 make_field("reg", reg_index), 276 make_field("data", 0), 277 bus_addr, len); 278 } 279 280 int ps3_repository_read_dev_reg(unsigned int bus_index, 281 unsigned int dev_index, unsigned int reg_index, 282 enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len) 283 { 284 int result = ps3_repository_read_dev_reg_type(bus_index, dev_index, 285 reg_index, reg_type); 286 return result ? result 287 : ps3_repository_read_dev_reg_addr(bus_index, dev_index, 288 reg_index, bus_addr, len); 289 } 290 291 292 293 int ps3_repository_find_device(struct ps3_repository_device *repo) 294 { 295 int result; 296 struct ps3_repository_device tmp = *repo; 297 unsigned int num_dev; 298 299 BUG_ON(repo->bus_index > 10); 300 BUG_ON(repo->dev_index > 10); 301 302 result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); 303 304 if (result) { 305 pr_devel("%s:%d read_bus_num_dev failed\n", __func__, __LINE__); 306 return result; 307 } 308 309 pr_devel("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n", 310 __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, 311 num_dev); 312 313 if (tmp.dev_index >= num_dev) { 314 pr_devel("%s:%d: no device found\n", __func__, __LINE__); 315 return -ENODEV; 316 } 317 318 result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, 319 &tmp.dev_type); 320 321 if (result) { 322 pr_devel("%s:%d read_dev_type failed\n", __func__, __LINE__); 323 return result; 324 } 325 326 result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, 327 &tmp.dev_id); 328 329 if (result) { 330 pr_devel("%s:%d ps3_repository_read_dev_id failed\n", __func__, 331 __LINE__); 332 return result; 333 } 334 335 pr_devel("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n", 336 __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); 337 338 *repo = tmp; 339 return 0; 340 } 341 342 int ps3_repository_find_device_by_id(struct ps3_repository_device *repo, 343 u64 bus_id, u64 dev_id) 344 { 345 int result = -ENODEV; 346 struct ps3_repository_device tmp; 347 unsigned int num_dev; 348 349 pr_devel(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__, 350 bus_id, dev_id); 351 352 for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) { 353 result = ps3_repository_read_bus_id(tmp.bus_index, 354 &tmp.bus_id); 355 if (result) { 356 pr_devel("%s:%u read_bus_id(%u) failed\n", __func__, 357 __LINE__, tmp.bus_index); 358 return result; 359 } 360 361 if (tmp.bus_id == bus_id) 362 goto found_bus; 363 364 pr_devel("%s:%u: skip, bus_id %llu\n", __func__, __LINE__, 365 tmp.bus_id); 366 } 367 pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__); 368 return result; 369 370 found_bus: 371 result = ps3_repository_read_bus_type(tmp.bus_index, &tmp.bus_type); 372 if (result) { 373 pr_devel("%s:%u read_bus_type(%u) failed\n", __func__, 374 __LINE__, tmp.bus_index); 375 return result; 376 } 377 378 result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); 379 if (result) { 380 pr_devel("%s:%u read_bus_num_dev failed\n", __func__, 381 __LINE__); 382 return result; 383 } 384 385 for (tmp.dev_index = 0; tmp.dev_index < num_dev; tmp.dev_index++) { 386 result = ps3_repository_read_dev_id(tmp.bus_index, 387 tmp.dev_index, 388 &tmp.dev_id); 389 if (result) { 390 pr_devel("%s:%u read_dev_id(%u:%u) failed\n", __func__, 391 __LINE__, tmp.bus_index, tmp.dev_index); 392 return result; 393 } 394 395 if (tmp.dev_id == dev_id) 396 goto found_dev; 397 398 pr_devel("%s:%u: skip, dev_id %llu\n", __func__, __LINE__, 399 tmp.dev_id); 400 } 401 pr_devel(" <- %s:%u: dev not found\n", __func__, __LINE__); 402 return result; 403 404 found_dev: 405 result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, 406 &tmp.dev_type); 407 if (result) { 408 pr_devel("%s:%u read_dev_type failed\n", __func__, __LINE__); 409 return result; 410 } 411 412 pr_devel(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n", 413 __func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index, 414 tmp.dev_index, tmp.bus_id, tmp.dev_id); 415 *repo = tmp; 416 return 0; 417 } 418 419 int __init ps3_repository_find_devices(enum ps3_bus_type bus_type, 420 int (*callback)(const struct ps3_repository_device *repo)) 421 { 422 int result = 0; 423 struct ps3_repository_device repo; 424 425 pr_devel(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); 426 427 repo.bus_type = bus_type; 428 result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index); 429 if (result) { 430 pr_devel(" <- %s:%u: bus not found\n", __func__, __LINE__); 431 return result; 432 } 433 434 result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id); 435 if (result) { 436 pr_devel("%s:%d read_bus_id(%u) failed\n", __func__, __LINE__, 437 repo.bus_index); 438 return result; 439 } 440 441 for (repo.dev_index = 0; ; repo.dev_index++) { 442 result = ps3_repository_find_device(&repo); 443 if (result == -ENODEV) { 444 result = 0; 445 break; 446 } else if (result) 447 break; 448 449 result = callback(&repo); 450 if (result) { 451 pr_devel("%s:%d: abort at callback\n", __func__, 452 __LINE__); 453 break; 454 } 455 } 456 457 pr_devel(" <- %s:%d\n", __func__, __LINE__); 458 return result; 459 } 460 461 int __init ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, 462 unsigned int *bus_index) 463 { 464 unsigned int i; 465 enum ps3_bus_type type; 466 int error; 467 468 for (i = from; i < 10; i++) { 469 error = ps3_repository_read_bus_type(i, &type); 470 if (error) { 471 pr_devel("%s:%d read_bus_type failed\n", 472 __func__, __LINE__); 473 *bus_index = UINT_MAX; 474 return error; 475 } 476 if (type == bus_type) { 477 *bus_index = i; 478 return 0; 479 } 480 } 481 *bus_index = UINT_MAX; 482 return -ENODEV; 483 } 484 485 int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, 486 enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) 487 { 488 int result = 0; 489 unsigned int res_index; 490 491 pr_devel("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type); 492 493 *interrupt_id = UINT_MAX; 494 495 for (res_index = 0; res_index < 10; res_index++) { 496 enum ps3_interrupt_type t; 497 unsigned int id; 498 499 result = ps3_repository_read_dev_intr(repo->bus_index, 500 repo->dev_index, res_index, &t, &id); 501 502 if (result) { 503 pr_devel("%s:%d read_dev_intr failed\n", 504 __func__, __LINE__); 505 return result; 506 } 507 508 if (t == intr_type) { 509 *interrupt_id = id; 510 break; 511 } 512 } 513 514 if (res_index == 10) 515 return -ENODEV; 516 517 pr_devel("%s:%d: found intr_type %u at res_index %u\n", 518 __func__, __LINE__, intr_type, res_index); 519 520 return result; 521 } 522 523 int ps3_repository_find_reg(const struct ps3_repository_device *repo, 524 enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len) 525 { 526 int result = 0; 527 unsigned int res_index; 528 529 pr_devel("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type); 530 531 *bus_addr = *len = 0; 532 533 for (res_index = 0; res_index < 10; res_index++) { 534 enum ps3_reg_type t; 535 u64 a; 536 u64 l; 537 538 result = ps3_repository_read_dev_reg(repo->bus_index, 539 repo->dev_index, res_index, &t, &a, &l); 540 541 if (result) { 542 pr_devel("%s:%d read_dev_reg failed\n", 543 __func__, __LINE__); 544 return result; 545 } 546 547 if (t == reg_type) { 548 *bus_addr = a; 549 *len = l; 550 break; 551 } 552 } 553 554 if (res_index == 10) 555 return -ENODEV; 556 557 pr_devel("%s:%d: found reg_type %u at res_index %u\n", 558 __func__, __LINE__, reg_type, res_index); 559 560 return result; 561 } 562 563 int ps3_repository_read_stor_dev_port(unsigned int bus_index, 564 unsigned int dev_index, u64 *port) 565 { 566 return read_node(PS3_LPAR_ID_PME, 567 make_first_field("bus", bus_index), 568 make_field("dev", dev_index), 569 make_field("port", 0), 570 0, port, NULL); 571 } 572 573 int ps3_repository_read_stor_dev_blk_size(unsigned int bus_index, 574 unsigned int dev_index, u64 *blk_size) 575 { 576 return read_node(PS3_LPAR_ID_PME, 577 make_first_field("bus", bus_index), 578 make_field("dev", dev_index), 579 make_field("blk_size", 0), 580 0, blk_size, NULL); 581 } 582 583 int ps3_repository_read_stor_dev_num_blocks(unsigned int bus_index, 584 unsigned int dev_index, u64 *num_blocks) 585 { 586 return read_node(PS3_LPAR_ID_PME, 587 make_first_field("bus", bus_index), 588 make_field("dev", dev_index), 589 make_field("n_blocks", 0), 590 0, num_blocks, NULL); 591 } 592 593 int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index, 594 unsigned int dev_index, unsigned int *num_regions) 595 { 596 int result; 597 u64 v1 = 0; 598 599 result = read_node(PS3_LPAR_ID_PME, 600 make_first_field("bus", bus_index), 601 make_field("dev", dev_index), 602 make_field("n_regs", 0), 603 0, &v1, NULL); 604 *num_regions = v1; 605 return result; 606 } 607 608 int ps3_repository_read_stor_dev_region_id(unsigned int bus_index, 609 unsigned int dev_index, unsigned int region_index, 610 unsigned int *region_id) 611 { 612 int result; 613 u64 v1 = 0; 614 615 result = read_node(PS3_LPAR_ID_PME, 616 make_first_field("bus", bus_index), 617 make_field("dev", dev_index), 618 make_field("region", region_index), 619 make_field("id", 0), 620 &v1, NULL); 621 *region_id = v1; 622 return result; 623 } 624 625 int ps3_repository_read_stor_dev_region_size(unsigned int bus_index, 626 unsigned int dev_index, unsigned int region_index, u64 *region_size) 627 { 628 return read_node(PS3_LPAR_ID_PME, 629 make_first_field("bus", bus_index), 630 make_field("dev", dev_index), 631 make_field("region", region_index), 632 make_field("size", 0), 633 region_size, NULL); 634 } 635 636 int ps3_repository_read_stor_dev_region_start(unsigned int bus_index, 637 unsigned int dev_index, unsigned int region_index, u64 *region_start) 638 { 639 return read_node(PS3_LPAR_ID_PME, 640 make_first_field("bus", bus_index), 641 make_field("dev", dev_index), 642 make_field("region", region_index), 643 make_field("start", 0), 644 region_start, NULL); 645 } 646 647 int ps3_repository_read_stor_dev_info(unsigned int bus_index, 648 unsigned int dev_index, u64 *port, u64 *blk_size, 649 u64 *num_blocks, unsigned int *num_regions) 650 { 651 int result; 652 653 result = ps3_repository_read_stor_dev_port(bus_index, dev_index, port); 654 if (result) 655 return result; 656 657 result = ps3_repository_read_stor_dev_blk_size(bus_index, dev_index, 658 blk_size); 659 if (result) 660 return result; 661 662 result = ps3_repository_read_stor_dev_num_blocks(bus_index, dev_index, 663 num_blocks); 664 if (result) 665 return result; 666 667 result = ps3_repository_read_stor_dev_num_regions(bus_index, dev_index, 668 num_regions); 669 return result; 670 } 671 672 int ps3_repository_read_stor_dev_region(unsigned int bus_index, 673 unsigned int dev_index, unsigned int region_index, 674 unsigned int *region_id, u64 *region_start, u64 *region_size) 675 { 676 int result; 677 678 result = ps3_repository_read_stor_dev_region_id(bus_index, dev_index, 679 region_index, region_id); 680 if (result) 681 return result; 682 683 result = ps3_repository_read_stor_dev_region_start(bus_index, dev_index, 684 region_index, region_start); 685 if (result) 686 return result; 687 688 result = ps3_repository_read_stor_dev_region_size(bus_index, dev_index, 689 region_index, region_size); 690 return result; 691 } 692 693 /** 694 * ps3_repository_read_num_pu - Number of logical PU processors for this lpar. 695 */ 696 697 int ps3_repository_read_num_pu(u64 *num_pu) 698 { 699 *num_pu = 0; 700 return read_node(PS3_LPAR_ID_CURRENT, 701 make_first_field("bi", 0), 702 make_field("pun", 0), 703 0, 0, 704 num_pu, NULL); 705 } 706 707 /** 708 * ps3_repository_read_pu_id - Read the logical PU id. 709 * @pu_index: Zero based index. 710 * @pu_id: The logical PU id. 711 */ 712 713 int ps3_repository_read_pu_id(unsigned int pu_index, u64 *pu_id) 714 { 715 return read_node(PS3_LPAR_ID_CURRENT, 716 make_first_field("bi", 0), 717 make_field("pu", pu_index), 718 0, 0, 719 pu_id, NULL); 720 } 721 722 int ps3_repository_read_rm_size(unsigned int ppe_id, u64 *rm_size) 723 { 724 return read_node(PS3_LPAR_ID_CURRENT, 725 make_first_field("bi", 0), 726 make_field("pu", 0), 727 ppe_id, 728 make_field("rm_size", 0), 729 rm_size, NULL); 730 } 731 732 int ps3_repository_read_region_total(u64 *region_total) 733 { 734 return read_node(PS3_LPAR_ID_CURRENT, 735 make_first_field("bi", 0), 736 make_field("rgntotal", 0), 737 0, 0, 738 region_total, NULL); 739 } 740 741 /** 742 * ps3_repository_read_mm_info - Read mm info for single pu system. 743 * @rm_base: Real mode memory base address. 744 * @rm_size: Real mode memory size. 745 * @region_total: Maximum memory region size. 746 */ 747 748 int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total) 749 { 750 int result; 751 u64 ppe_id; 752 753 lv1_get_logical_ppe_id(&ppe_id); 754 *rm_base = 0; 755 result = ps3_repository_read_rm_size(ppe_id, rm_size); 756 return result ? result 757 : ps3_repository_read_region_total(region_total); 758 } 759 760 /** 761 * ps3_repository_read_highmem_region_count - Read the number of highmem regions 762 * 763 * Bootloaders must arrange the repository nodes such that regions are indexed 764 * with a region_index from 0 to region_count-1. 765 */ 766 767 int ps3_repository_read_highmem_region_count(unsigned int *region_count) 768 { 769 int result; 770 u64 v1 = 0; 771 772 result = read_node(PS3_LPAR_ID_CURRENT, 773 make_first_field("highmem", 0), 774 make_field("region", 0), 775 make_field("count", 0), 776 0, 777 &v1, NULL); 778 *region_count = v1; 779 return result; 780 } 781 782 783 int ps3_repository_read_highmem_base(unsigned int region_index, 784 u64 *highmem_base) 785 { 786 return read_node(PS3_LPAR_ID_CURRENT, 787 make_first_field("highmem", 0), 788 make_field("region", region_index), 789 make_field("base", 0), 790 0, 791 highmem_base, NULL); 792 } 793 794 int ps3_repository_read_highmem_size(unsigned int region_index, 795 u64 *highmem_size) 796 { 797 return read_node(PS3_LPAR_ID_CURRENT, 798 make_first_field("highmem", 0), 799 make_field("region", region_index), 800 make_field("size", 0), 801 0, 802 highmem_size, NULL); 803 } 804 805 /** 806 * ps3_repository_read_highmem_info - Read high memory region info 807 * @region_index: Region index, {0,..,region_count-1}. 808 * @highmem_base: High memory base address. 809 * @highmem_size: High memory size. 810 * 811 * Bootloaders that preallocate highmem regions must place the 812 * region info into the repository at these well known nodes. 813 */ 814 815 int ps3_repository_read_highmem_info(unsigned int region_index, 816 u64 *highmem_base, u64 *highmem_size) 817 { 818 int result; 819 820 *highmem_base = 0; 821 result = ps3_repository_read_highmem_base(region_index, highmem_base); 822 return result ? result 823 : ps3_repository_read_highmem_size(region_index, highmem_size); 824 } 825 826 /** 827 * ps3_repository_read_num_spu_reserved - Number of physical spus reserved. 828 * @num_spu: Number of physical spus. 829 */ 830 831 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved) 832 { 833 int result; 834 u64 v1 = 0; 835 836 result = read_node(PS3_LPAR_ID_CURRENT, 837 make_first_field("bi", 0), 838 make_field("spun", 0), 839 0, 0, 840 &v1, NULL); 841 *num_spu_reserved = v1; 842 return result; 843 } 844 845 /** 846 * ps3_repository_read_num_spu_resource_id - Number of spu resource reservations. 847 * @num_resource_id: Number of spu resource ids. 848 */ 849 850 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id) 851 { 852 int result; 853 u64 v1 = 0; 854 855 result = read_node(PS3_LPAR_ID_CURRENT, 856 make_first_field("bi", 0), 857 make_field("spursvn", 0), 858 0, 0, 859 &v1, NULL); 860 *num_resource_id = v1; 861 return result; 862 } 863 864 /** 865 * ps3_repository_read_spu_resource_id - spu resource reservation id value. 866 * @res_index: Resource reservation index. 867 * @resource_type: Resource reservation type. 868 * @resource_id: Resource reservation id. 869 */ 870 871 int ps3_repository_read_spu_resource_id(unsigned int res_index, 872 enum ps3_spu_resource_type *resource_type, unsigned int *resource_id) 873 { 874 int result; 875 u64 v1 = 0; 876 u64 v2 = 0; 877 878 result = read_node(PS3_LPAR_ID_CURRENT, 879 make_first_field("bi", 0), 880 make_field("spursv", 0), 881 res_index, 882 0, 883 &v1, &v2); 884 *resource_type = v1; 885 *resource_id = v2; 886 return result; 887 } 888 889 static int ps3_repository_read_boot_dat_address(u64 *address) 890 { 891 return read_node(PS3_LPAR_ID_CURRENT, 892 make_first_field("bi", 0), 893 make_field("boot_dat", 0), 894 make_field("address", 0), 895 0, 896 address, NULL); 897 } 898 899 int ps3_repository_read_boot_dat_size(unsigned int *size) 900 { 901 int result; 902 u64 v1 = 0; 903 904 result = read_node(PS3_LPAR_ID_CURRENT, 905 make_first_field("bi", 0), 906 make_field("boot_dat", 0), 907 make_field("size", 0), 908 0, 909 &v1, NULL); 910 *size = v1; 911 return result; 912 } 913 914 int __init ps3_repository_read_vuart_av_port(unsigned int *port) 915 { 916 int result; 917 u64 v1 = 0; 918 919 result = read_node(PS3_LPAR_ID_CURRENT, 920 make_first_field("bi", 0), 921 make_field("vir_uart", 0), 922 make_field("port", 0), 923 make_field("avset", 0), 924 &v1, NULL); 925 *port = v1; 926 return result; 927 } 928 929 int __init ps3_repository_read_vuart_sysmgr_port(unsigned int *port) 930 { 931 int result; 932 u64 v1 = 0; 933 934 result = read_node(PS3_LPAR_ID_CURRENT, 935 make_first_field("bi", 0), 936 make_field("vir_uart", 0), 937 make_field("port", 0), 938 make_field("sysmgr", 0), 939 &v1, NULL); 940 *port = v1; 941 return result; 942 } 943 944 /** 945 * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. 946 * @lpar_addr: lpar address of cell_ext_os_area 947 * @size: size of cell_ext_os_area 948 */ 949 950 int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size) 951 { 952 int result; 953 954 *size = 0; 955 result = ps3_repository_read_boot_dat_address(lpar_addr); 956 return result ? result 957 : ps3_repository_read_boot_dat_size(size); 958 } 959 960 /** 961 * ps3_repository_read_num_be - Number of physical BE processors in the system. 962 */ 963 964 int ps3_repository_read_num_be(unsigned int *num_be) 965 { 966 int result; 967 u64 v1 = 0; 968 969 result = read_node(PS3_LPAR_ID_PME, 970 make_first_field("ben", 0), 971 0, 972 0, 973 0, 974 &v1, NULL); 975 *num_be = v1; 976 return result; 977 } 978 979 /** 980 * ps3_repository_read_be_node_id - Read the physical BE processor node id. 981 * @be_index: Zero based index. 982 * @node_id: The BE processor node id. 983 */ 984 985 int ps3_repository_read_be_node_id(unsigned int be_index, u64 *node_id) 986 { 987 return read_node(PS3_LPAR_ID_PME, 988 make_first_field("be", be_index), 989 0, 990 0, 991 0, 992 node_id, NULL); 993 } 994 995 /** 996 * ps3_repository_read_be_id - Read the physical BE processor id. 997 * @node_id: The BE processor node id. 998 * @be_id: The BE processor id. 999 */ 1000 1001 int ps3_repository_read_be_id(u64 node_id, u64 *be_id) 1002 { 1003 return read_node(PS3_LPAR_ID_PME, 1004 make_first_field("be", 0), 1005 node_id, 1006 0, 1007 0, 1008 be_id, NULL); 1009 } 1010 1011 int __init ps3_repository_read_tb_freq(u64 node_id, u64 *tb_freq) 1012 { 1013 return read_node(PS3_LPAR_ID_PME, 1014 make_first_field("be", 0), 1015 node_id, 1016 make_field("clock", 0), 1017 0, 1018 tb_freq, NULL); 1019 } 1020 1021 int __init ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) 1022 { 1023 int result; 1024 u64 node_id; 1025 1026 *tb_freq = 0; 1027 result = ps3_repository_read_be_node_id(be_index, &node_id); 1028 return result ? result 1029 : ps3_repository_read_tb_freq(node_id, tb_freq); 1030 } 1031 1032 int ps3_repository_read_lpm_privileges(unsigned int be_index, u64 *lpar, 1033 u64 *rights) 1034 { 1035 int result; 1036 u64 node_id; 1037 1038 *lpar = 0; 1039 *rights = 0; 1040 result = ps3_repository_read_be_node_id(be_index, &node_id); 1041 return result ? result 1042 : read_node(PS3_LPAR_ID_PME, 1043 make_first_field("be", 0), 1044 node_id, 1045 make_field("lpm", 0), 1046 make_field("priv", 0), 1047 lpar, rights); 1048 } 1049 1050 #if defined(CONFIG_PS3_REPOSITORY_WRITE) 1051 1052 static int create_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2) 1053 { 1054 int result; 1055 1056 dump_node(0, n1, n2, n3, n4, v1, v2); 1057 1058 result = lv1_create_repository_node(n1, n2, n3, n4, v1, v2); 1059 1060 if (result) { 1061 pr_devel("%s:%d: lv1_create_repository_node failed: %s\n", 1062 __func__, __LINE__, ps3_result(result)); 1063 return -ENOENT; 1064 } 1065 1066 return 0; 1067 } 1068 1069 static int delete_node(u64 n1, u64 n2, u64 n3, u64 n4) 1070 { 1071 int result; 1072 1073 dump_node(0, n1, n2, n3, n4, 0, 0); 1074 1075 result = lv1_delete_repository_node(n1, n2, n3, n4); 1076 1077 if (result) { 1078 pr_devel("%s:%d: lv1_delete_repository_node failed: %s\n", 1079 __func__, __LINE__, ps3_result(result)); 1080 return -ENOENT; 1081 } 1082 1083 return 0; 1084 } 1085 1086 static int write_node(u64 n1, u64 n2, u64 n3, u64 n4, u64 v1, u64 v2) 1087 { 1088 int result; 1089 1090 result = create_node(n1, n2, n3, n4, v1, v2); 1091 1092 if (!result) 1093 return 0; 1094 1095 result = lv1_write_repository_node(n1, n2, n3, n4, v1, v2); 1096 1097 if (result) { 1098 pr_devel("%s:%d: lv1_write_repository_node failed: %s\n", 1099 __func__, __LINE__, ps3_result(result)); 1100 return -ENOENT; 1101 } 1102 1103 return 0; 1104 } 1105 1106 int ps3_repository_write_highmem_region_count(unsigned int region_count) 1107 { 1108 int result; 1109 u64 v1 = (u64)region_count; 1110 1111 result = write_node( 1112 make_first_field("highmem", 0), 1113 make_field("region", 0), 1114 make_field("count", 0), 1115 0, 1116 v1, 0); 1117 return result; 1118 } 1119 1120 int ps3_repository_write_highmem_base(unsigned int region_index, 1121 u64 highmem_base) 1122 { 1123 return write_node( 1124 make_first_field("highmem", 0), 1125 make_field("region", region_index), 1126 make_field("base", 0), 1127 0, 1128 highmem_base, 0); 1129 } 1130 1131 int ps3_repository_write_highmem_size(unsigned int region_index, 1132 u64 highmem_size) 1133 { 1134 return write_node( 1135 make_first_field("highmem", 0), 1136 make_field("region", region_index), 1137 make_field("size", 0), 1138 0, 1139 highmem_size, 0); 1140 } 1141 1142 int ps3_repository_write_highmem_info(unsigned int region_index, 1143 u64 highmem_base, u64 highmem_size) 1144 { 1145 int result; 1146 1147 result = ps3_repository_write_highmem_base(region_index, highmem_base); 1148 return result ? result 1149 : ps3_repository_write_highmem_size(region_index, highmem_size); 1150 } 1151 1152 static int ps3_repository_delete_highmem_base(unsigned int region_index) 1153 { 1154 return delete_node( 1155 make_first_field("highmem", 0), 1156 make_field("region", region_index), 1157 make_field("base", 0), 1158 0); 1159 } 1160 1161 static int ps3_repository_delete_highmem_size(unsigned int region_index) 1162 { 1163 return delete_node( 1164 make_first_field("highmem", 0), 1165 make_field("region", region_index), 1166 make_field("size", 0), 1167 0); 1168 } 1169 1170 int ps3_repository_delete_highmem_info(unsigned int region_index) 1171 { 1172 int result; 1173 1174 result = ps3_repository_delete_highmem_base(region_index); 1175 result += ps3_repository_delete_highmem_size(region_index); 1176 1177 return result ? -1 : 0; 1178 } 1179 1180 #endif /* defined(CONFIG_PS3_REPOSITORY_WRITE) */ 1181 1182 #if defined(DEBUG) 1183 1184 int __init ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) 1185 { 1186 int result = 0; 1187 unsigned int res_index; 1188 1189 pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, 1190 repo->bus_index, repo->dev_index); 1191 1192 for (res_index = 0; res_index < 10; res_index++) { 1193 enum ps3_interrupt_type intr_type; 1194 unsigned int interrupt_id; 1195 1196 result = ps3_repository_read_dev_intr(repo->bus_index, 1197 repo->dev_index, res_index, &intr_type, &interrupt_id); 1198 1199 if (result) { 1200 if (result != LV1_NO_ENTRY) 1201 pr_devel("%s:%d ps3_repository_read_dev_intr" 1202 " (%u:%u) failed\n", __func__, __LINE__, 1203 repo->bus_index, repo->dev_index); 1204 break; 1205 } 1206 1207 pr_devel("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", 1208 __func__, __LINE__, repo->bus_index, repo->dev_index, 1209 intr_type, interrupt_id); 1210 } 1211 1212 for (res_index = 0; res_index < 10; res_index++) { 1213 enum ps3_reg_type reg_type; 1214 u64 bus_addr; 1215 u64 len; 1216 1217 result = ps3_repository_read_dev_reg(repo->bus_index, 1218 repo->dev_index, res_index, ®_type, &bus_addr, &len); 1219 1220 if (result) { 1221 if (result != LV1_NO_ENTRY) 1222 pr_devel("%s:%d ps3_repository_read_dev_reg" 1223 " (%u:%u) failed\n", __func__, __LINE__, 1224 repo->bus_index, repo->dev_index); 1225 break; 1226 } 1227 1228 pr_devel("%s:%d (%u:%u) reg_type %u, bus_addr %llxh, len %llxh\n", 1229 __func__, __LINE__, repo->bus_index, repo->dev_index, 1230 reg_type, bus_addr, len); 1231 } 1232 1233 pr_devel(" <- %s:%d\n", __func__, __LINE__); 1234 return result; 1235 } 1236 1237 static int __init dump_stor_dev_info(struct ps3_repository_device *repo) 1238 { 1239 int result = 0; 1240 unsigned int num_regions, region_index; 1241 u64 port, blk_size, num_blocks; 1242 1243 pr_devel(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, 1244 repo->bus_index, repo->dev_index); 1245 1246 result = ps3_repository_read_stor_dev_info(repo->bus_index, 1247 repo->dev_index, &port, &blk_size, &num_blocks, &num_regions); 1248 if (result) { 1249 pr_devel("%s:%d ps3_repository_read_stor_dev_info" 1250 " (%u:%u) failed\n", __func__, __LINE__, 1251 repo->bus_index, repo->dev_index); 1252 goto out; 1253 } 1254 1255 pr_devel("%s:%d (%u:%u): port %llu, blk_size %llu, num_blocks " 1256 "%llu, num_regions %u\n", 1257 __func__, __LINE__, repo->bus_index, repo->dev_index, 1258 port, blk_size, num_blocks, num_regions); 1259 1260 for (region_index = 0; region_index < num_regions; region_index++) { 1261 unsigned int region_id; 1262 u64 region_start, region_size; 1263 1264 result = ps3_repository_read_stor_dev_region(repo->bus_index, 1265 repo->dev_index, region_index, ®ion_id, 1266 ®ion_start, ®ion_size); 1267 if (result) { 1268 pr_devel("%s:%d ps3_repository_read_stor_dev_region" 1269 " (%u:%u) failed\n", __func__, __LINE__, 1270 repo->bus_index, repo->dev_index); 1271 break; 1272 } 1273 1274 pr_devel("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", 1275 __func__, __LINE__, repo->bus_index, repo->dev_index, 1276 region_id, (unsigned long)region_start, 1277 (unsigned long)region_size); 1278 } 1279 1280 out: 1281 pr_devel(" <- %s:%d\n", __func__, __LINE__); 1282 return result; 1283 } 1284 1285 static int __init dump_device_info(struct ps3_repository_device *repo, 1286 unsigned int num_dev) 1287 { 1288 int result = 0; 1289 1290 pr_devel(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index); 1291 1292 for (repo->dev_index = 0; repo->dev_index < num_dev; 1293 repo->dev_index++) { 1294 1295 result = ps3_repository_read_dev_type(repo->bus_index, 1296 repo->dev_index, &repo->dev_type); 1297 1298 if (result) { 1299 pr_devel("%s:%d ps3_repository_read_dev_type" 1300 " (%u:%u) failed\n", __func__, __LINE__, 1301 repo->bus_index, repo->dev_index); 1302 break; 1303 } 1304 1305 result = ps3_repository_read_dev_id(repo->bus_index, 1306 repo->dev_index, &repo->dev_id); 1307 1308 if (result) { 1309 pr_devel("%s:%d ps3_repository_read_dev_id" 1310 " (%u:%u) failed\n", __func__, __LINE__, 1311 repo->bus_index, repo->dev_index); 1312 continue; 1313 } 1314 1315 pr_devel("%s:%d (%u:%u): dev_type %u, dev_id %lu\n", __func__, 1316 __LINE__, repo->bus_index, repo->dev_index, 1317 repo->dev_type, (unsigned long)repo->dev_id); 1318 1319 ps3_repository_dump_resource_info(repo); 1320 1321 if (repo->bus_type == PS3_BUS_TYPE_STORAGE) 1322 dump_stor_dev_info(repo); 1323 } 1324 1325 pr_devel(" <- %s:%d\n", __func__, __LINE__); 1326 return result; 1327 } 1328 1329 int __init ps3_repository_dump_bus_info(void) 1330 { 1331 int result = 0; 1332 struct ps3_repository_device repo; 1333 1334 pr_devel(" -> %s:%d\n", __func__, __LINE__); 1335 1336 memset(&repo, 0, sizeof(repo)); 1337 1338 for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { 1339 unsigned int num_dev; 1340 1341 result = ps3_repository_read_bus_type(repo.bus_index, 1342 &repo.bus_type); 1343 1344 if (result) { 1345 pr_devel("%s:%d read_bus_type(%u) failed\n", 1346 __func__, __LINE__, repo.bus_index); 1347 break; 1348 } 1349 1350 result = ps3_repository_read_bus_id(repo.bus_index, 1351 &repo.bus_id); 1352 1353 if (result) { 1354 pr_devel("%s:%d read_bus_id(%u) failed\n", 1355 __func__, __LINE__, repo.bus_index); 1356 continue; 1357 } 1358 1359 if (repo.bus_index != repo.bus_id) 1360 pr_devel("%s:%d bus_index != bus_id\n", 1361 __func__, __LINE__); 1362 1363 result = ps3_repository_read_bus_num_dev(repo.bus_index, 1364 &num_dev); 1365 1366 if (result) { 1367 pr_devel("%s:%d read_bus_num_dev(%u) failed\n", 1368 __func__, __LINE__, repo.bus_index); 1369 continue; 1370 } 1371 1372 pr_devel("%s:%d bus_%u: bus_type %u, bus_id %lu, num_dev %u\n", 1373 __func__, __LINE__, repo.bus_index, repo.bus_type, 1374 (unsigned long)repo.bus_id, num_dev); 1375 1376 dump_device_info(&repo, num_dev); 1377 } 1378 1379 pr_devel(" <- %s:%d\n", __func__, __LINE__); 1380 return result; 1381 } 1382 1383 #endif /* defined(DEBUG) */ 1384