Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/pp: Move helper functions to smu_help.c

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Evan Quan <evan.quan@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Rex Zhu and committed by
Alex Deucher
8e686279 c4256885

+722 -662
+1 -1
drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
··· 31 31 smu7_clockpowergating.o \ 32 32 vega10_processpptables.o vega10_hwmgr.o vega10_powertune.o \ 33 33 vega10_thermal.o smu10_hwmgr.o pp_psm.o\ 34 - pp_overdriver.o 34 + pp_overdriver.o smu_helper.o 35 35 36 36 AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR)) 37 37
+4 -509
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
··· 30 30 #include <drm/amdgpu_drm.h> 31 31 #include "power_state.h" 32 32 #include "hwmgr.h" 33 - #include "pppcielanes.h" 34 - #include "ppatomctrl.h" 35 33 #include "ppsmc.h" 36 34 #include "amd_acpi.h" 37 35 #include "pp_psm.h" ··· 43 45 extern const struct pp_smumgr_func vega10_smu_funcs; 44 46 extern const struct pp_smumgr_func smu10_smu_funcs; 45 47 48 + extern int smu7_init_function_pointers(struct pp_hwmgr *hwmgr); 46 49 extern int cz_init_function_pointers(struct pp_hwmgr *hwmgr); 50 + extern int vega10_hwmgr_init(struct pp_hwmgr *hwmgr); 51 + extern int smu10_init_function_pointers(struct pp_hwmgr *hwmgr); 52 + 47 53 static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr); 48 54 static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr); 49 55 static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr); ··· 55 53 static int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr); 56 54 static int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr); 57 55 static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr); 58 - 59 - uint8_t convert_to_vid(uint16_t vddc) 60 - { 61 - return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); 62 - } 63 - 64 - uint16_t convert_to_vddc(uint8_t vid) 65 - { 66 - return (uint16_t) ((6200 - (vid * 25)) / VOLTAGE_SCALE); 67 - } 68 - 69 - uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size) 70 - { 71 - u32 mask = 0; 72 - u32 shift = 0; 73 - 74 - shift = (offset % 4) << 3; 75 - if (size == sizeof(uint8_t)) 76 - mask = 0xFF << shift; 77 - else if (size == sizeof(uint16_t)) 78 - mask = 0xFFFF << shift; 79 - 80 - original_data &= ~mask; 81 - original_data |= (field << shift); 82 - return original_data; 83 - } 84 56 85 57 static int phm_thermal_l2h_irq(void *private_data, 86 58 unsigned src_id, const uint32_t *iv_entry) ··· 408 432 } 409 433 return ret; 410 434 } 411 - /** 412 - * Returns once the part of the register indicated by the mask has 413 - * reached the given value. 414 - */ 415 - int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, 416 - uint32_t value, uint32_t mask) 417 - { 418 - uint32_t i; 419 - uint32_t cur_value; 420 - 421 - if (hwmgr == NULL || hwmgr->device == NULL) { 422 - pr_err("Invalid Hardware Manager!"); 423 - return -EINVAL; 424 - } 425 - 426 - for (i = 0; i < hwmgr->usec_timeout; i++) { 427 - cur_value = cgs_read_register(hwmgr->device, index); 428 - if ((cur_value & mask) == (value & mask)) 429 - break; 430 - udelay(1); 431 - } 432 - 433 - /* timeout means wrong logic*/ 434 - if (i == hwmgr->usec_timeout) 435 - return -1; 436 - return 0; 437 - } 438 - 439 - 440 - /** 441 - * Returns once the part of the register indicated by the mask has 442 - * reached the given value.The indirect space is described by giving 443 - * the memory-mapped index of the indirect index register. 444 - */ 445 - int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, 446 - uint32_t indirect_port, 447 - uint32_t index, 448 - uint32_t value, 449 - uint32_t mask) 450 - { 451 - if (hwmgr == NULL || hwmgr->device == NULL) { 452 - pr_err("Invalid Hardware Manager!"); 453 - return -EINVAL; 454 - } 455 - 456 - cgs_write_register(hwmgr->device, indirect_port, index); 457 - return phm_wait_on_register(hwmgr, indirect_port + 1, mask, value); 458 - } 459 - 460 - int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, 461 - uint32_t index, 462 - uint32_t value, uint32_t mask) 463 - { 464 - uint32_t i; 465 - uint32_t cur_value; 466 - 467 - if (hwmgr == NULL || hwmgr->device == NULL) 468 - return -EINVAL; 469 - 470 - for (i = 0; i < hwmgr->usec_timeout; i++) { 471 - cur_value = cgs_read_register(hwmgr->device, 472 - index); 473 - if ((cur_value & mask) != (value & mask)) 474 - break; 475 - udelay(1); 476 - } 477 - 478 - /* timeout means wrong logic */ 479 - if (i == hwmgr->usec_timeout) 480 - return -ETIME; 481 - return 0; 482 - } 483 - 484 - int phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr, 485 - uint32_t indirect_port, 486 - uint32_t index, 487 - uint32_t value, 488 - uint32_t mask) 489 - { 490 - if (hwmgr == NULL || hwmgr->device == NULL) 491 - return -EINVAL; 492 - 493 - cgs_write_register(hwmgr->device, indirect_port, index); 494 - return phm_wait_for_register_unequal(hwmgr, indirect_port + 1, 495 - value, mask); 496 - } 497 - 498 - bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr) 499 - { 500 - return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating); 501 - } 502 - 503 - bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr) 504 - { 505 - return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating); 506 - } 507 - 508 - 509 - int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table) 510 - { 511 - uint32_t i, j; 512 - uint16_t vvalue; 513 - bool found = false; 514 - struct pp_atomctrl_voltage_table *table; 515 - 516 - PP_ASSERT_WITH_CODE((NULL != vol_table), 517 - "Voltage Table empty.", return -EINVAL); 518 - 519 - table = kzalloc(sizeof(struct pp_atomctrl_voltage_table), 520 - GFP_KERNEL); 521 - 522 - if (NULL == table) 523 - return -EINVAL; 524 - 525 - table->mask_low = vol_table->mask_low; 526 - table->phase_delay = vol_table->phase_delay; 527 - 528 - for (i = 0; i < vol_table->count; i++) { 529 - vvalue = vol_table->entries[i].value; 530 - found = false; 531 - 532 - for (j = 0; j < table->count; j++) { 533 - if (vvalue == table->entries[j].value) { 534 - found = true; 535 - break; 536 - } 537 - } 538 - 539 - if (!found) { 540 - table->entries[table->count].value = vvalue; 541 - table->entries[table->count].smio_low = 542 - vol_table->entries[i].smio_low; 543 - table->count++; 544 - } 545 - } 546 - 547 - memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table)); 548 - kfree(table); 549 - table = NULL; 550 - return 0; 551 - } 552 - 553 - int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, 554 - phm_ppt_v1_clock_voltage_dependency_table *dep_table) 555 - { 556 - uint32_t i; 557 - int result; 558 - 559 - PP_ASSERT_WITH_CODE((0 != dep_table->count), 560 - "Voltage Dependency Table empty.", return -EINVAL); 561 - 562 - PP_ASSERT_WITH_CODE((NULL != vol_table), 563 - "vol_table empty.", return -EINVAL); 564 - 565 - vol_table->mask_low = 0; 566 - vol_table->phase_delay = 0; 567 - vol_table->count = dep_table->count; 568 - 569 - for (i = 0; i < dep_table->count; i++) { 570 - vol_table->entries[i].value = dep_table->entries[i].mvdd; 571 - vol_table->entries[i].smio_low = 0; 572 - } 573 - 574 - result = phm_trim_voltage_table(vol_table); 575 - PP_ASSERT_WITH_CODE((0 == result), 576 - "Failed to trim MVDD table.", return result); 577 - 578 - return 0; 579 - } 580 - 581 - int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, 582 - phm_ppt_v1_clock_voltage_dependency_table *dep_table) 583 - { 584 - uint32_t i; 585 - int result; 586 - 587 - PP_ASSERT_WITH_CODE((0 != dep_table->count), 588 - "Voltage Dependency Table empty.", return -EINVAL); 589 - 590 - PP_ASSERT_WITH_CODE((NULL != vol_table), 591 - "vol_table empty.", return -EINVAL); 592 - 593 - vol_table->mask_low = 0; 594 - vol_table->phase_delay = 0; 595 - vol_table->count = dep_table->count; 596 - 597 - for (i = 0; i < dep_table->count; i++) { 598 - vol_table->entries[i].value = dep_table->entries[i].vddci; 599 - vol_table->entries[i].smio_low = 0; 600 - } 601 - 602 - result = phm_trim_voltage_table(vol_table); 603 - PP_ASSERT_WITH_CODE((0 == result), 604 - "Failed to trim VDDCI table.", return result); 605 - 606 - return 0; 607 - } 608 - 609 - int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, 610 - phm_ppt_v1_voltage_lookup_table *lookup_table) 611 - { 612 - int i = 0; 613 - 614 - PP_ASSERT_WITH_CODE((0 != lookup_table->count), 615 - "Voltage Lookup Table empty.", return -EINVAL); 616 - 617 - PP_ASSERT_WITH_CODE((NULL != vol_table), 618 - "vol_table empty.", return -EINVAL); 619 - 620 - vol_table->mask_low = 0; 621 - vol_table->phase_delay = 0; 622 - 623 - vol_table->count = lookup_table->count; 624 - 625 - for (i = 0; i < vol_table->count; i++) { 626 - vol_table->entries[i].value = lookup_table->entries[i].us_vdd; 627 - vol_table->entries[i].smio_low = 0; 628 - } 629 - 630 - return 0; 631 - } 632 - 633 - void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, 634 - struct pp_atomctrl_voltage_table *vol_table) 635 - { 636 - unsigned int i, diff; 637 - 638 - if (vol_table->count <= max_vol_steps) 639 - return; 640 - 641 - diff = vol_table->count - max_vol_steps; 642 - 643 - for (i = 0; i < max_vol_steps; i++) 644 - vol_table->entries[i] = vol_table->entries[i + diff]; 645 - 646 - vol_table->count = max_vol_steps; 647 - 648 - return; 649 - } 650 - 651 - int phm_reset_single_dpm_table(void *table, 652 - uint32_t count, int max) 653 - { 654 - int i; 655 - 656 - struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; 657 - 658 - dpm_table->count = count > max ? max : count; 659 - 660 - for (i = 0; i < dpm_table->count; i++) 661 - dpm_table->dpm_level[i].enabled = false; 662 - 663 - return 0; 664 - } 665 - 666 - void phm_setup_pcie_table_entry( 667 - void *table, 668 - uint32_t index, uint32_t pcie_gen, 669 - uint32_t pcie_lanes) 670 - { 671 - struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; 672 - dpm_table->dpm_level[index].value = pcie_gen; 673 - dpm_table->dpm_level[index].param1 = pcie_lanes; 674 - dpm_table->dpm_level[index].enabled = 1; 675 - } 676 - 677 - int32_t phm_get_dpm_level_enable_mask_value(void *table) 678 - { 679 - int32_t i; 680 - int32_t mask = 0; 681 - struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; 682 - 683 - for (i = dpm_table->count; i > 0; i--) { 684 - mask = mask << 1; 685 - if (dpm_table->dpm_level[i - 1].enabled) 686 - mask |= 0x1; 687 - else 688 - mask &= 0xFFFFFFFE; 689 - } 690 - 691 - return mask; 692 - } 693 - 694 - uint8_t phm_get_voltage_index( 695 - struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage) 696 - { 697 - uint8_t count = (uint8_t) (lookup_table->count); 698 - uint8_t i; 699 - 700 - PP_ASSERT_WITH_CODE((NULL != lookup_table), 701 - "Lookup Table empty.", return 0); 702 - PP_ASSERT_WITH_CODE((0 != count), 703 - "Lookup Table empty.", return 0); 704 - 705 - for (i = 0; i < lookup_table->count; i++) { 706 - /* find first voltage equal or bigger than requested */ 707 - if (lookup_table->entries[i].us_vdd >= voltage) 708 - return i; 709 - } 710 - /* voltage is bigger than max voltage in the table */ 711 - return i - 1; 712 - } 713 - 714 - uint8_t phm_get_voltage_id(pp_atomctrl_voltage_table *voltage_table, 715 - uint32_t voltage) 716 - { 717 - uint8_t count = (uint8_t) (voltage_table->count); 718 - uint8_t i = 0; 719 - 720 - PP_ASSERT_WITH_CODE((NULL != voltage_table), 721 - "Voltage Table empty.", return 0;); 722 - PP_ASSERT_WITH_CODE((0 != count), 723 - "Voltage Table empty.", return 0;); 724 - 725 - for (i = 0; i < count; i++) { 726 - /* find first voltage bigger than requested */ 727 - if (voltage_table->entries[i].value >= voltage) 728 - return i; 729 - } 730 - 731 - /* voltage is bigger than max voltage in the table */ 732 - return i - 1; 733 - } 734 - 735 - uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci) 736 - { 737 - uint32_t i; 738 - 739 - for (i = 0; i < vddci_table->count; i++) { 740 - if (vddci_table->entries[i].value >= vddci) 741 - return vddci_table->entries[i].value; 742 - } 743 - 744 - pr_debug("vddci is larger than max value in vddci_table\n"); 745 - return vddci_table->entries[i-1].value; 746 - } 747 - 748 - int phm_find_boot_level(void *table, 749 - uint32_t value, uint32_t *boot_level) 750 - { 751 - int result = -EINVAL; 752 - uint32_t i; 753 - struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; 754 - 755 - for (i = 0; i < dpm_table->count; i++) { 756 - if (value == dpm_table->dpm_level[i].value) { 757 - *boot_level = i; 758 - result = 0; 759 - } 760 - } 761 - 762 - return result; 763 - } 764 - 765 - int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, 766 - phm_ppt_v1_voltage_lookup_table *lookup_table, 767 - uint16_t virtual_voltage_id, int32_t *sclk) 768 - { 769 - uint8_t entry_id; 770 - uint8_t voltage_id; 771 - struct phm_ppt_v1_information *table_info = 772 - (struct phm_ppt_v1_information *)(hwmgr->pptable); 773 - 774 - PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL); 775 - 776 - /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */ 777 - for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) { 778 - voltage_id = table_info->vdd_dep_on_sclk->entries[entry_id].vddInd; 779 - if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id) 780 - break; 781 - } 782 - 783 - if (entry_id >= table_info->vdd_dep_on_sclk->count) { 784 - pr_debug("Can't find requested voltage id in vdd_dep_on_sclk table\n"); 785 - return -EINVAL; 786 - } 787 - 788 - *sclk = table_info->vdd_dep_on_sclk->entries[entry_id].clk; 789 - 790 - return 0; 791 - } 792 - 793 - /** 794 - * Initialize Dynamic State Adjustment Rule Settings 795 - * 796 - * @param hwmgr the address of the powerplay hardware manager. 797 - */ 798 - int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr) 799 - { 800 - uint32_t table_size; 801 - struct phm_clock_voltage_dependency_table *table_clk_vlt; 802 - struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); 803 - 804 - /* initialize vddc_dep_on_dal_pwrl table */ 805 - table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record); 806 - table_clk_vlt = kzalloc(table_size, GFP_KERNEL); 807 - 808 - if (NULL == table_clk_vlt) { 809 - pr_err("Can not allocate space for vddc_dep_on_dal_pwrl! \n"); 810 - return -ENOMEM; 811 - } else { 812 - table_clk_vlt->count = 4; 813 - table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW; 814 - table_clk_vlt->entries[0].v = 0; 815 - table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW; 816 - table_clk_vlt->entries[1].v = 720; 817 - table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL; 818 - table_clk_vlt->entries[2].v = 810; 819 - table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE; 820 - table_clk_vlt->entries[3].v = 900; 821 - if (pptable_info != NULL) 822 - pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt; 823 - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; 824 - } 825 - 826 - return 0; 827 - } 828 - 829 - uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask) 830 - { 831 - uint32_t level = 0; 832 - 833 - while (0 == (mask & (1 << level))) 834 - level++; 835 - 836 - return level; 837 - } 838 - 839 - void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr) 840 - { 841 - struct phm_ppt_v1_information *table_info = 842 - (struct phm_ppt_v1_information *)hwmgr->pptable; 843 - struct phm_clock_voltage_dependency_table *table = 844 - table_info->vddc_dep_on_dal_pwrl; 845 - struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table; 846 - enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level; 847 - uint32_t req_vddc = 0, req_volt, i; 848 - 849 - if (!table || table->count <= 0 850 - || dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW 851 - || dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE) 852 - return; 853 - 854 - for (i = 0; i < table->count; i++) { 855 - if (dal_power_level == table->entries[i].clk) { 856 - req_vddc = table->entries[i].v; 857 - break; 858 - } 859 - } 860 - 861 - vddc_table = table_info->vdd_dep_on_sclk; 862 - for (i = 0; i < vddc_table->count; i++) { 863 - if (req_vddc <= vddc_table->entries[i].vddc) { 864 - req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE); 865 - smum_send_msg_to_smc_with_parameter(hwmgr, 866 - PPSMC_MSG_VddC_Request, req_volt); 867 - return; 868 - } 869 - } 870 - pr_err("DAL requested level can not" 871 - " found a available voltage in VDDC DPM Table \n"); 872 - } 873 435 874 436 void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr) 875 437 { ··· 466 952 hwmgr->od_enabled = true; 467 953 468 954 return 0; 469 - } 470 - 471 - int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, 472 - uint32_t sclk, uint16_t id, uint16_t *voltage) 473 - { 474 - uint32_t vol; 475 - int ret = 0; 476 - 477 - if (hwmgr->chip_id < CHIP_TONGA) { 478 - ret = atomctrl_get_voltage_evv(hwmgr, id, voltage); 479 - } else if (hwmgr->chip_id < CHIP_POLARIS10) { 480 - ret = atomctrl_get_voltage_evv_on_sclk(hwmgr, voltage_type, sclk, id, voltage); 481 - if (*voltage >= 2000 || *voltage == 0) 482 - *voltage = 1150; 483 - } else { 484 - ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol); 485 - *voltage = (uint16_t)(vol/100); 486 - } 487 - return ret; 488 955 } 489 956 490 957 int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
+536
drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
··· 1 + /* 2 + * Copyright 2018 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #include "hwmgr.h" 24 + #include "pp_debug.h" 25 + #include "ppatomctrl.h" 26 + #include "ppsmc.h" 27 + 28 + uint8_t convert_to_vid(uint16_t vddc) 29 + { 30 + return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); 31 + } 32 + 33 + uint16_t convert_to_vddc(uint8_t vid) 34 + { 35 + return (uint16_t) ((6200 - (vid * 25)) / VOLTAGE_SCALE); 36 + } 37 + 38 + uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size) 39 + { 40 + u32 mask = 0; 41 + u32 shift = 0; 42 + 43 + shift = (offset % 4) << 3; 44 + if (size == sizeof(uint8_t)) 45 + mask = 0xFF << shift; 46 + else if (size == sizeof(uint16_t)) 47 + mask = 0xFFFF << shift; 48 + 49 + original_data &= ~mask; 50 + original_data |= (field << shift); 51 + return original_data; 52 + } 53 + 54 + /** 55 + * Returns once the part of the register indicated by the mask has 56 + * reached the given value. 57 + */ 58 + int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, 59 + uint32_t value, uint32_t mask) 60 + { 61 + uint32_t i; 62 + uint32_t cur_value; 63 + 64 + if (hwmgr == NULL || hwmgr->device == NULL) { 65 + pr_err("Invalid Hardware Manager!"); 66 + return -EINVAL; 67 + } 68 + 69 + for (i = 0; i < hwmgr->usec_timeout; i++) { 70 + cur_value = cgs_read_register(hwmgr->device, index); 71 + if ((cur_value & mask) == (value & mask)) 72 + break; 73 + udelay(1); 74 + } 75 + 76 + /* timeout means wrong logic*/ 77 + if (i == hwmgr->usec_timeout) 78 + return -1; 79 + return 0; 80 + } 81 + 82 + 83 + /** 84 + * Returns once the part of the register indicated by the mask has 85 + * reached the given value.The indirect space is described by giving 86 + * the memory-mapped index of the indirect index register. 87 + */ 88 + int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, 89 + uint32_t indirect_port, 90 + uint32_t index, 91 + uint32_t value, 92 + uint32_t mask) 93 + { 94 + if (hwmgr == NULL || hwmgr->device == NULL) { 95 + pr_err("Invalid Hardware Manager!"); 96 + return -EINVAL; 97 + } 98 + 99 + cgs_write_register(hwmgr->device, indirect_port, index); 100 + return phm_wait_on_register(hwmgr, indirect_port + 1, mask, value); 101 + } 102 + 103 + int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, 104 + uint32_t index, 105 + uint32_t value, uint32_t mask) 106 + { 107 + uint32_t i; 108 + uint32_t cur_value; 109 + 110 + if (hwmgr == NULL || hwmgr->device == NULL) 111 + return -EINVAL; 112 + 113 + for (i = 0; i < hwmgr->usec_timeout; i++) { 114 + cur_value = cgs_read_register(hwmgr->device, 115 + index); 116 + if ((cur_value & mask) != (value & mask)) 117 + break; 118 + udelay(1); 119 + } 120 + 121 + /* timeout means wrong logic */ 122 + if (i == hwmgr->usec_timeout) 123 + return -ETIME; 124 + return 0; 125 + } 126 + 127 + int phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr, 128 + uint32_t indirect_port, 129 + uint32_t index, 130 + uint32_t value, 131 + uint32_t mask) 132 + { 133 + if (hwmgr == NULL || hwmgr->device == NULL) 134 + return -EINVAL; 135 + 136 + cgs_write_register(hwmgr->device, indirect_port, index); 137 + return phm_wait_for_register_unequal(hwmgr, indirect_port + 1, 138 + value, mask); 139 + } 140 + 141 + bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr) 142 + { 143 + return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating); 144 + } 145 + 146 + bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr) 147 + { 148 + return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating); 149 + } 150 + 151 + 152 + int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table) 153 + { 154 + uint32_t i, j; 155 + uint16_t vvalue; 156 + bool found = false; 157 + struct pp_atomctrl_voltage_table *table; 158 + 159 + PP_ASSERT_WITH_CODE((NULL != vol_table), 160 + "Voltage Table empty.", return -EINVAL); 161 + 162 + table = kzalloc(sizeof(struct pp_atomctrl_voltage_table), 163 + GFP_KERNEL); 164 + 165 + if (NULL == table) 166 + return -EINVAL; 167 + 168 + table->mask_low = vol_table->mask_low; 169 + table->phase_delay = vol_table->phase_delay; 170 + 171 + for (i = 0; i < vol_table->count; i++) { 172 + vvalue = vol_table->entries[i].value; 173 + found = false; 174 + 175 + for (j = 0; j < table->count; j++) { 176 + if (vvalue == table->entries[j].value) { 177 + found = true; 178 + break; 179 + } 180 + } 181 + 182 + if (!found) { 183 + table->entries[table->count].value = vvalue; 184 + table->entries[table->count].smio_low = 185 + vol_table->entries[i].smio_low; 186 + table->count++; 187 + } 188 + } 189 + 190 + memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table)); 191 + kfree(table); 192 + table = NULL; 193 + return 0; 194 + } 195 + 196 + int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, 197 + phm_ppt_v1_clock_voltage_dependency_table *dep_table) 198 + { 199 + uint32_t i; 200 + int result; 201 + 202 + PP_ASSERT_WITH_CODE((0 != dep_table->count), 203 + "Voltage Dependency Table empty.", return -EINVAL); 204 + 205 + PP_ASSERT_WITH_CODE((NULL != vol_table), 206 + "vol_table empty.", return -EINVAL); 207 + 208 + vol_table->mask_low = 0; 209 + vol_table->phase_delay = 0; 210 + vol_table->count = dep_table->count; 211 + 212 + for (i = 0; i < dep_table->count; i++) { 213 + vol_table->entries[i].value = dep_table->entries[i].mvdd; 214 + vol_table->entries[i].smio_low = 0; 215 + } 216 + 217 + result = phm_trim_voltage_table(vol_table); 218 + PP_ASSERT_WITH_CODE((0 == result), 219 + "Failed to trim MVDD table.", return result); 220 + 221 + return 0; 222 + } 223 + 224 + int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, 225 + phm_ppt_v1_clock_voltage_dependency_table *dep_table) 226 + { 227 + uint32_t i; 228 + int result; 229 + 230 + PP_ASSERT_WITH_CODE((0 != dep_table->count), 231 + "Voltage Dependency Table empty.", return -EINVAL); 232 + 233 + PP_ASSERT_WITH_CODE((NULL != vol_table), 234 + "vol_table empty.", return -EINVAL); 235 + 236 + vol_table->mask_low = 0; 237 + vol_table->phase_delay = 0; 238 + vol_table->count = dep_table->count; 239 + 240 + for (i = 0; i < dep_table->count; i++) { 241 + vol_table->entries[i].value = dep_table->entries[i].vddci; 242 + vol_table->entries[i].smio_low = 0; 243 + } 244 + 245 + result = phm_trim_voltage_table(vol_table); 246 + PP_ASSERT_WITH_CODE((0 == result), 247 + "Failed to trim VDDCI table.", return result); 248 + 249 + return 0; 250 + } 251 + 252 + int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, 253 + phm_ppt_v1_voltage_lookup_table *lookup_table) 254 + { 255 + int i = 0; 256 + 257 + PP_ASSERT_WITH_CODE((0 != lookup_table->count), 258 + "Voltage Lookup Table empty.", return -EINVAL); 259 + 260 + PP_ASSERT_WITH_CODE((NULL != vol_table), 261 + "vol_table empty.", return -EINVAL); 262 + 263 + vol_table->mask_low = 0; 264 + vol_table->phase_delay = 0; 265 + 266 + vol_table->count = lookup_table->count; 267 + 268 + for (i = 0; i < vol_table->count; i++) { 269 + vol_table->entries[i].value = lookup_table->entries[i].us_vdd; 270 + vol_table->entries[i].smio_low = 0; 271 + } 272 + 273 + return 0; 274 + } 275 + 276 + void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, 277 + struct pp_atomctrl_voltage_table *vol_table) 278 + { 279 + unsigned int i, diff; 280 + 281 + if (vol_table->count <= max_vol_steps) 282 + return; 283 + 284 + diff = vol_table->count - max_vol_steps; 285 + 286 + for (i = 0; i < max_vol_steps; i++) 287 + vol_table->entries[i] = vol_table->entries[i + diff]; 288 + 289 + vol_table->count = max_vol_steps; 290 + 291 + return; 292 + } 293 + 294 + int phm_reset_single_dpm_table(void *table, 295 + uint32_t count, int max) 296 + { 297 + int i; 298 + 299 + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; 300 + 301 + dpm_table->count = count > max ? max : count; 302 + 303 + for (i = 0; i < dpm_table->count; i++) 304 + dpm_table->dpm_level[i].enabled = false; 305 + 306 + return 0; 307 + } 308 + 309 + void phm_setup_pcie_table_entry( 310 + void *table, 311 + uint32_t index, uint32_t pcie_gen, 312 + uint32_t pcie_lanes) 313 + { 314 + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; 315 + dpm_table->dpm_level[index].value = pcie_gen; 316 + dpm_table->dpm_level[index].param1 = pcie_lanes; 317 + dpm_table->dpm_level[index].enabled = 1; 318 + } 319 + 320 + int32_t phm_get_dpm_level_enable_mask_value(void *table) 321 + { 322 + int32_t i; 323 + int32_t mask = 0; 324 + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; 325 + 326 + for (i = dpm_table->count; i > 0; i--) { 327 + mask = mask << 1; 328 + if (dpm_table->dpm_level[i - 1].enabled) 329 + mask |= 0x1; 330 + else 331 + mask &= 0xFFFFFFFE; 332 + } 333 + 334 + return mask; 335 + } 336 + 337 + uint8_t phm_get_voltage_index( 338 + struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage) 339 + { 340 + uint8_t count = (uint8_t) (lookup_table->count); 341 + uint8_t i; 342 + 343 + PP_ASSERT_WITH_CODE((NULL != lookup_table), 344 + "Lookup Table empty.", return 0); 345 + PP_ASSERT_WITH_CODE((0 != count), 346 + "Lookup Table empty.", return 0); 347 + 348 + for (i = 0; i < lookup_table->count; i++) { 349 + /* find first voltage equal or bigger than requested */ 350 + if (lookup_table->entries[i].us_vdd >= voltage) 351 + return i; 352 + } 353 + /* voltage is bigger than max voltage in the table */ 354 + return i - 1; 355 + } 356 + 357 + uint8_t phm_get_voltage_id(pp_atomctrl_voltage_table *voltage_table, 358 + uint32_t voltage) 359 + { 360 + uint8_t count = (uint8_t) (voltage_table->count); 361 + uint8_t i = 0; 362 + 363 + PP_ASSERT_WITH_CODE((NULL != voltage_table), 364 + "Voltage Table empty.", return 0;); 365 + PP_ASSERT_WITH_CODE((0 != count), 366 + "Voltage Table empty.", return 0;); 367 + 368 + for (i = 0; i < count; i++) { 369 + /* find first voltage bigger than requested */ 370 + if (voltage_table->entries[i].value >= voltage) 371 + return i; 372 + } 373 + 374 + /* voltage is bigger than max voltage in the table */ 375 + return i - 1; 376 + } 377 + 378 + uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci) 379 + { 380 + uint32_t i; 381 + 382 + for (i = 0; i < vddci_table->count; i++) { 383 + if (vddci_table->entries[i].value >= vddci) 384 + return vddci_table->entries[i].value; 385 + } 386 + 387 + pr_debug("vddci is larger than max value in vddci_table\n"); 388 + return vddci_table->entries[i-1].value; 389 + } 390 + 391 + int phm_find_boot_level(void *table, 392 + uint32_t value, uint32_t *boot_level) 393 + { 394 + int result = -EINVAL; 395 + uint32_t i; 396 + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; 397 + 398 + for (i = 0; i < dpm_table->count; i++) { 399 + if (value == dpm_table->dpm_level[i].value) { 400 + *boot_level = i; 401 + result = 0; 402 + } 403 + } 404 + 405 + return result; 406 + } 407 + 408 + int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, 409 + phm_ppt_v1_voltage_lookup_table *lookup_table, 410 + uint16_t virtual_voltage_id, int32_t *sclk) 411 + { 412 + uint8_t entry_id; 413 + uint8_t voltage_id; 414 + struct phm_ppt_v1_information *table_info = 415 + (struct phm_ppt_v1_information *)(hwmgr->pptable); 416 + 417 + PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL); 418 + 419 + /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */ 420 + for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) { 421 + voltage_id = table_info->vdd_dep_on_sclk->entries[entry_id].vddInd; 422 + if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id) 423 + break; 424 + } 425 + 426 + if (entry_id >= table_info->vdd_dep_on_sclk->count) { 427 + pr_debug("Can't find requested voltage id in vdd_dep_on_sclk table\n"); 428 + return -EINVAL; 429 + } 430 + 431 + *sclk = table_info->vdd_dep_on_sclk->entries[entry_id].clk; 432 + 433 + return 0; 434 + } 435 + 436 + /** 437 + * Initialize Dynamic State Adjustment Rule Settings 438 + * 439 + * @param hwmgr the address of the powerplay hardware manager. 440 + */ 441 + int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr) 442 + { 443 + uint32_t table_size; 444 + struct phm_clock_voltage_dependency_table *table_clk_vlt; 445 + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); 446 + 447 + /* initialize vddc_dep_on_dal_pwrl table */ 448 + table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record); 449 + table_clk_vlt = kzalloc(table_size, GFP_KERNEL); 450 + 451 + if (NULL == table_clk_vlt) { 452 + pr_err("Can not allocate space for vddc_dep_on_dal_pwrl! \n"); 453 + return -ENOMEM; 454 + } else { 455 + table_clk_vlt->count = 4; 456 + table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW; 457 + table_clk_vlt->entries[0].v = 0; 458 + table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW; 459 + table_clk_vlt->entries[1].v = 720; 460 + table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL; 461 + table_clk_vlt->entries[2].v = 810; 462 + table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE; 463 + table_clk_vlt->entries[3].v = 900; 464 + if (pptable_info != NULL) 465 + pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt; 466 + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; 467 + } 468 + 469 + return 0; 470 + } 471 + 472 + uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask) 473 + { 474 + uint32_t level = 0; 475 + 476 + while (0 == (mask & (1 << level))) 477 + level++; 478 + 479 + return level; 480 + } 481 + 482 + void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr) 483 + { 484 + struct phm_ppt_v1_information *table_info = 485 + (struct phm_ppt_v1_information *)hwmgr->pptable; 486 + struct phm_clock_voltage_dependency_table *table = 487 + table_info->vddc_dep_on_dal_pwrl; 488 + struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table; 489 + enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level; 490 + uint32_t req_vddc = 0, req_volt, i; 491 + 492 + if (!table || table->count <= 0 493 + || dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW 494 + || dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE) 495 + return; 496 + 497 + for (i = 0; i < table->count; i++) { 498 + if (dal_power_level == table->entries[i].clk) { 499 + req_vddc = table->entries[i].v; 500 + break; 501 + } 502 + } 503 + 504 + vddc_table = table_info->vdd_dep_on_sclk; 505 + for (i = 0; i < vddc_table->count; i++) { 506 + if (req_vddc <= vddc_table->entries[i].vddc) { 507 + req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE); 508 + smum_send_msg_to_smc_with_parameter(hwmgr, 509 + PPSMC_MSG_VddC_Request, req_volt); 510 + return; 511 + } 512 + } 513 + pr_err("DAL requested level can not" 514 + " found a available voltage in VDDC DPM Table \n"); 515 + } 516 + 517 + int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, 518 + uint32_t sclk, uint16_t id, uint16_t *voltage) 519 + { 520 + uint32_t vol; 521 + int ret = 0; 522 + 523 + if (hwmgr->chip_id < CHIP_TONGA) { 524 + ret = atomctrl_get_voltage_evv(hwmgr, id, voltage); 525 + } else if (hwmgr->chip_id < CHIP_POLARIS10) { 526 + ret = atomctrl_get_voltage_evv_on_sclk(hwmgr, voltage_type, sclk, id, voltage); 527 + if (*voltage >= 2000 || *voltage == 0) 528 + *voltage = 1150; 529 + } else { 530 + ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol); 531 + *voltage = (uint16_t)(vol/100); 532 + } 533 + return ret; 534 + } 535 + 536 +
+180
drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h
··· 1 + /* 2 + * Copyright 2018 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #ifndef _SMU_HELPER_H_ 24 + #define _SMU_HELPER_H_ 25 + 26 + struct pp_atomctrl_voltage_table; 27 + struct pp_hwmgr; 28 + struct phm_ppt_v1_voltage_lookup_table; 29 + 30 + extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, 31 + uint32_t index, 32 + uint32_t value, uint32_t mask); 33 + extern int phm_wait_for_indirect_register_unequal( 34 + struct pp_hwmgr *hwmgr, 35 + uint32_t indirect_port, uint32_t index, 36 + uint32_t value, uint32_t mask); 37 + 38 + 39 + extern bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr); 40 + extern bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr); 41 + extern bool phm_cf_want_microcode_fan_ctrl(struct pp_hwmgr *hwmgr); 42 + 43 + extern int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table); 44 + extern int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); 45 + extern int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); 46 + extern int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_voltage_lookup_table *lookup_table); 47 + extern void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table); 48 + extern int phm_reset_single_dpm_table(void *table, uint32_t count, int max); 49 + extern void phm_setup_pcie_table_entry(void *table, uint32_t index, uint32_t pcie_gen, uint32_t pcie_lanes); 50 + extern int32_t phm_get_dpm_level_enable_mask_value(void *table); 51 + extern uint8_t phm_get_voltage_id(struct pp_atomctrl_voltage_table *voltage_table, 52 + uint32_t voltage); 53 + extern uint8_t phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage); 54 + extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci); 55 + extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level); 56 + extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table, 57 + uint16_t virtual_voltage_id, int32_t *sclk); 58 + extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr); 59 + extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask); 60 + extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr); 61 + 62 + extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, 63 + uint32_t sclk, uint16_t id, uint16_t *voltage); 64 + 65 + extern uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size); 66 + 67 + extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, 68 + uint32_t value, uint32_t mask); 69 + 70 + extern int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, 71 + uint32_t indirect_port, 72 + uint32_t index, 73 + uint32_t value, 74 + uint32_t mask); 75 + 76 + #define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT 77 + #define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK 78 + 79 + #define PHM_SET_FIELD(origval, reg, field, fieldval) \ 80 + (((origval) & ~PHM_FIELD_MASK(reg, field)) | \ 81 + (PHM_FIELD_MASK(reg, field) & ((fieldval) << PHM_FIELD_SHIFT(reg, field)))) 82 + 83 + #define PHM_GET_FIELD(value, reg, field) \ 84 + (((value) & PHM_FIELD_MASK(reg, field)) >> \ 85 + PHM_FIELD_SHIFT(reg, field)) 86 + 87 + 88 + /* Operations on named fields. */ 89 + 90 + #define PHM_READ_FIELD(device, reg, field) \ 91 + PHM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) 92 + 93 + #define PHM_READ_INDIRECT_FIELD(device, port, reg, field) \ 94 + PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 95 + reg, field) 96 + 97 + #define PHM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ 98 + PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 99 + reg, field) 100 + 101 + #define PHM_WRITE_FIELD(device, reg, field, fieldval) \ 102 + cgs_write_register(device, mm##reg, PHM_SET_FIELD( \ 103 + cgs_read_register(device, mm##reg), reg, field, fieldval)) 104 + 105 + #define PHM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \ 106 + cgs_write_ind_register(device, port, ix##reg, \ 107 + PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 108 + reg, field, fieldval)) 109 + 110 + #define PHM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \ 111 + cgs_write_ind_register(device, port, ix##reg, \ 112 + PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 113 + reg, field, fieldval)) 114 + 115 + #define PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \ 116 + phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX, index, value, mask) 117 + 118 + 119 + #define PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ 120 + PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 121 + 122 + #define PHM_WAIT_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ 123 + PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \ 124 + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) 125 + 126 + #define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \ 127 + phm_wait_for_indirect_register_unequal(hwmgr, \ 128 + mm##port##_INDEX, index, value, mask) 129 + 130 + #define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ 131 + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 132 + 133 + #define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ 134 + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ 135 + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ 136 + PHM_FIELD_MASK(reg, field) ) 137 + 138 + 139 + #define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ 140 + port, index, value, mask) \ 141 + phm_wait_for_indirect_register_unequal(hwmgr, \ 142 + mm##port##_INDEX_11, index, value, mask) 143 + 144 + #define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ 145 + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 146 + 147 + #define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ 148 + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ 149 + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ 150 + PHM_FIELD_MASK(reg, field)) 151 + 152 + 153 + #define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, \ 154 + port, index, value, mask) \ 155 + phm_wait_on_indirect_register(hwmgr, \ 156 + mm##port##_INDEX_11, index, value, mask) 157 + 158 + #define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ 159 + PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 160 + 161 + #define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ 162 + PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, \ 163 + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ 164 + PHM_FIELD_MASK(reg, field)) 165 + 166 + #define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ 167 + index, value, mask) \ 168 + phm_wait_for_register_unequal(hwmgr, \ 169 + index, value, mask) 170 + 171 + #define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask) \ 172 + PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ 173 + mm##reg, value, mask) 174 + 175 + #define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval) \ 176 + PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, \ 177 + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ 178 + PHM_FIELD_MASK(reg, field)) 179 + 180 + #endif /* _SMU_HELPER_H_ */
+1 -152
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
··· 32 32 #include "ppatomctrl.h" 33 33 #include "hwmgr_ppt.h" 34 34 #include "power_state.h" 35 - #include "cgs_linux.h" 35 + #include "smu_helper.h" 36 36 37 37 struct pp_instance; 38 38 struct pp_hwmgr; ··· 777 777 extern int hwmgr_handle_task(struct pp_instance *handle, 778 778 enum amd_pp_task task_id, 779 779 enum amd_pm_state_type *user_state); 780 - extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, 781 - uint32_t value, uint32_t mask); 782 780 783 - extern int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, 784 - uint32_t indirect_port, 785 - uint32_t index, 786 - uint32_t value, 787 - uint32_t mask); 788 - 789 - extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, 790 - uint32_t index, 791 - uint32_t value, uint32_t mask); 792 - extern int phm_wait_for_indirect_register_unequal( 793 - struct pp_hwmgr *hwmgr, 794 - uint32_t indirect_port, uint32_t index, 795 - uint32_t value, uint32_t mask); 796 - 797 - 798 - extern bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr); 799 - extern bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr); 800 - extern bool phm_cf_want_microcode_fan_ctrl(struct pp_hwmgr *hwmgr); 801 - 802 - extern int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table); 803 - extern int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); 804 - extern int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); 805 - extern int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_voltage_lookup_table *lookup_table); 806 - extern void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table); 807 - extern int phm_reset_single_dpm_table(void *table, uint32_t count, int max); 808 - extern void phm_setup_pcie_table_entry(void *table, uint32_t index, uint32_t pcie_gen, uint32_t pcie_lanes); 809 - extern int32_t phm_get_dpm_level_enable_mask_value(void *table); 810 - extern uint8_t phm_get_voltage_id(struct pp_atomctrl_voltage_table *voltage_table, 811 - uint32_t voltage); 812 - extern uint8_t phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage); 813 - extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci); 814 - extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level); 815 - extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table, 816 - uint16_t virtual_voltage_id, int32_t *sclk); 817 - extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr); 818 - extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask); 819 - extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr); 820 - 821 - extern int smu7_init_function_pointers(struct pp_hwmgr *hwmgr); 822 - extern int vega10_hwmgr_init(struct pp_hwmgr *hwmgr); 823 - extern int smu10_init_function_pointers(struct pp_hwmgr *hwmgr); 824 - 825 - extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, 826 - uint32_t sclk, uint16_t id, uint16_t *voltage); 827 - 828 - extern uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size); 829 781 830 782 #define PHM_ENTIRE_REGISTER_MASK 0xFFFFFFFFU 831 783 832 - #define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT 833 - #define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK 834 - 835 - #define PHM_SET_FIELD(origval, reg, field, fieldval) \ 836 - (((origval) & ~PHM_FIELD_MASK(reg, field)) | \ 837 - (PHM_FIELD_MASK(reg, field) & ((fieldval) << PHM_FIELD_SHIFT(reg, field)))) 838 - 839 - #define PHM_GET_FIELD(value, reg, field) \ 840 - (((value) & PHM_FIELD_MASK(reg, field)) >> \ 841 - PHM_FIELD_SHIFT(reg, field)) 842 - 843 - 844 - /* Operations on named fields. */ 845 - 846 - #define PHM_READ_FIELD(device, reg, field) \ 847 - PHM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) 848 - 849 - #define PHM_READ_INDIRECT_FIELD(device, port, reg, field) \ 850 - PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 851 - reg, field) 852 - 853 - #define PHM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ 854 - PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 855 - reg, field) 856 - 857 - #define PHM_WRITE_FIELD(device, reg, field, fieldval) \ 858 - cgs_write_register(device, mm##reg, PHM_SET_FIELD( \ 859 - cgs_read_register(device, mm##reg), reg, field, fieldval)) 860 - 861 - #define PHM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \ 862 - cgs_write_ind_register(device, port, ix##reg, \ 863 - PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 864 - reg, field, fieldval)) 865 - 866 - #define PHM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \ 867 - cgs_write_ind_register(device, port, ix##reg, \ 868 - PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 869 - reg, field, fieldval)) 870 - 871 - #define PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \ 872 - phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX, index, value, mask) 873 - 874 - 875 - #define PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ 876 - PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 877 - 878 - #define PHM_WAIT_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ 879 - PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \ 880 - << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) 881 - 882 - #define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \ 883 - phm_wait_for_indirect_register_unequal(hwmgr, \ 884 - mm##port##_INDEX, index, value, mask) 885 - 886 - #define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ 887 - PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 888 - 889 - #define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ 890 - PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ 891 - (fieldval) << PHM_FIELD_SHIFT(reg, field), \ 892 - PHM_FIELD_MASK(reg, field) ) 893 - 894 - 895 - #define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ 896 - port, index, value, mask) \ 897 - phm_wait_for_indirect_register_unequal(hwmgr, \ 898 - mm##port##_INDEX_11, index, value, mask) 899 - 900 - #define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ 901 - PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 902 - 903 - #define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ 904 - PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ 905 - (fieldval) << PHM_FIELD_SHIFT(reg, field), \ 906 - PHM_FIELD_MASK(reg, field)) 907 - 908 - 909 - #define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, \ 910 - port, index, value, mask) \ 911 - phm_wait_on_indirect_register(hwmgr, \ 912 - mm##port##_INDEX_11, index, value, mask) 913 - 914 - #define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ 915 - PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 916 - 917 - #define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ 918 - PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, \ 919 - (fieldval) << PHM_FIELD_SHIFT(reg, field), \ 920 - PHM_FIELD_MASK(reg, field)) 921 - 922 - #define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ 923 - index, value, mask) \ 924 - phm_wait_for_register_unequal(hwmgr, \ 925 - index, value, mask) 926 - 927 - #define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask) \ 928 - PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ 929 - mm##reg, value, mask) 930 - 931 - #define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval) \ 932 - PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, \ 933 - (fieldval) << PHM_FIELD_SHIFT(reg, field), \ 934 - PHM_FIELD_MASK(reg, field)) 935 784 936 785 #endif /* _HWMGR_H_ */