diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0045-drm-amd-powerplay-add-Carrizo-smu-support.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0045-drm-amd-powerplay-add-Carrizo-smu-support.patch | 2159 |
1 files changed, 2159 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0045-drm-amd-powerplay-add-Carrizo-smu-support.patch b/common/recipes-kernel/linux/files/0045-drm-amd-powerplay-add-Carrizo-smu-support.patch new file mode 100644 index 00000000..a73f3163 --- /dev/null +++ b/common/recipes-kernel/linux/files/0045-drm-amd-powerplay-add-Carrizo-smu-support.patch @@ -0,0 +1,2159 @@ +From 7e947a91bd0ea6cecf185060d03f2dfd9756673f Mon Sep 17 00:00:00 2001 +From: Jammy Zhou <Jammy.Zhou@amd.com> +Date: Wed, 22 Jul 2015 09:54:16 +0800 +Subject: [PATCH 0045/1110] drm/amd/powerplay: add Carrizo smu support + +This implements the SMU firmware manager interface for CZ. +Some header files are moved from amdgpu folder to powerplay as well. + +v3: delete peci sub-module. +v2: use cgs interface directly + add load_mec_firmware function + +Signed-off-by: Rex Zhu <Rex.Zhu@amd.com> +Signed-off-by: Jammy Zhou <Jammy.Zhou@amd.com> +Reviewed-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h | 185 ----- + drivers/gpu/drm/amd/amdgpu/smu8.h | 72 -- + drivers/gpu/drm/amd/amdgpu/smu8_fusion.h | 127 --- + drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_cz.h | 147 ---- + drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h | 185 +++++ + drivers/gpu/drm/amd/powerplay/inc/smu8.h | 72 ++ + drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h | 127 +++ + .../gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h | 147 ++++ + drivers/gpu/drm/amd/powerplay/smumgr/Makefile | 2 +- + drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c | 858 +++++++++++++++++++++ + drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h | 102 +++ + drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 3 +- + 12 files changed, 1494 insertions(+), 533 deletions(-) + delete mode 100644 drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h + delete mode 100644 drivers/gpu/drm/amd/amdgpu/smu8.h + delete mode 100644 drivers/gpu/drm/amd/amdgpu/smu8_fusion.h + delete mode 100644 drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_cz.h + create mode 100644 drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h + create mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu8.h + create mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h + create mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h + create mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c + create mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h + +diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h b/drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h +deleted file mode 100644 +index 273616a..0000000 +--- a/drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h ++++ /dev/null +@@ -1,185 +0,0 @@ +-/* +- * Copyright 2014 Advanced Micro Devices, Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- */ +- +-#ifndef CZ_PP_SMC_H +-#define CZ_PP_SMC_H +- +-#pragma pack(push, 1) +- +-/* Fan control algorithm:*/ +-#define FDO_MODE_HARDWARE 0 +-#define FDO_MODE_PIECE_WISE_LINEAR 1 +- +-enum FAN_CONTROL { +- FAN_CONTROL_FUZZY, +- FAN_CONTROL_TABLE +-}; +- +-enum DPM_ARRAY { +- DPM_ARRAY_HARD_MAX, +- DPM_ARRAY_HARD_MIN, +- DPM_ARRAY_SOFT_MAX, +- DPM_ARRAY_SOFT_MIN +-}; +- +-/* +- * Return codes for driver to SMC communication. +- * Leave these #define-s, enums might not be exactly 8-bits on the microcontroller. +- */ +-#define PPSMC_Result_OK ((uint16_t)0x01) +-#define PPSMC_Result_NoMore ((uint16_t)0x02) +-#define PPSMC_Result_NotNow ((uint16_t)0x03) +-#define PPSMC_Result_Failed ((uint16_t)0xFF) +-#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) +-#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) +- +-#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) +- +-/* +- * Supported driver messages +- */ +-#define PPSMC_MSG_Test ((uint16_t) 0x1) +-#define PPSMC_MSG_GetFeatureStatus ((uint16_t) 0x2) +-#define PPSMC_MSG_EnableAllSmuFeatures ((uint16_t) 0x3) +-#define PPSMC_MSG_DisableAllSmuFeatures ((uint16_t) 0x4) +-#define PPSMC_MSG_OptimizeBattery ((uint16_t) 0x5) +-#define PPSMC_MSG_MaximizePerf ((uint16_t) 0x6) +-#define PPSMC_MSG_UVDPowerOFF ((uint16_t) 0x7) +-#define PPSMC_MSG_UVDPowerON ((uint16_t) 0x8) +-#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x9) +-#define PPSMC_MSG_VCEPowerON ((uint16_t) 0xA) +-#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0xB) +-#define PPSMC_MSG_ACPPowerON ((uint16_t) 0xC) +-#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0xD) +-#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0xE) +-#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0xF) +-#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x10) +-#define PPSMC_MSG_SetMinDeepSleepSclk ((uint16_t) 0x11) +-#define PPSMC_MSG_SetSclkSoftMin ((uint16_t) 0x12) +-#define PPSMC_MSG_SetSclkSoftMax ((uint16_t) 0x13) +-#define PPSMC_MSG_SetSclkHardMin ((uint16_t) 0x14) +-#define PPSMC_MSG_SetSclkHardMax ((uint16_t) 0x15) +-#define PPSMC_MSG_SetLclkSoftMin ((uint16_t) 0x16) +-#define PPSMC_MSG_SetLclkSoftMax ((uint16_t) 0x17) +-#define PPSMC_MSG_SetLclkHardMin ((uint16_t) 0x18) +-#define PPSMC_MSG_SetLclkHardMax ((uint16_t) 0x19) +-#define PPSMC_MSG_SetUvdSoftMin ((uint16_t) 0x1A) +-#define PPSMC_MSG_SetUvdSoftMax ((uint16_t) 0x1B) +-#define PPSMC_MSG_SetUvdHardMin ((uint16_t) 0x1C) +-#define PPSMC_MSG_SetUvdHardMax ((uint16_t) 0x1D) +-#define PPSMC_MSG_SetEclkSoftMin ((uint16_t) 0x1E) +-#define PPSMC_MSG_SetEclkSoftMax ((uint16_t) 0x1F) +-#define PPSMC_MSG_SetEclkHardMin ((uint16_t) 0x20) +-#define PPSMC_MSG_SetEclkHardMax ((uint16_t) 0x21) +-#define PPSMC_MSG_SetAclkSoftMin ((uint16_t) 0x22) +-#define PPSMC_MSG_SetAclkSoftMax ((uint16_t) 0x23) +-#define PPSMC_MSG_SetAclkHardMin ((uint16_t) 0x24) +-#define PPSMC_MSG_SetAclkHardMax ((uint16_t) 0x25) +-#define PPSMC_MSG_SetNclkSoftMin ((uint16_t) 0x26) +-#define PPSMC_MSG_SetNclkSoftMax ((uint16_t) 0x27) +-#define PPSMC_MSG_SetNclkHardMin ((uint16_t) 0x28) +-#define PPSMC_MSG_SetNclkHardMax ((uint16_t) 0x29) +-#define PPSMC_MSG_SetPstateSoftMin ((uint16_t) 0x2A) +-#define PPSMC_MSG_SetPstateSoftMax ((uint16_t) 0x2B) +-#define PPSMC_MSG_SetPstateHardMin ((uint16_t) 0x2C) +-#define PPSMC_MSG_SetPstateHardMax ((uint16_t) 0x2D) +-#define PPSMC_MSG_DisableLowMemoryPstate ((uint16_t) 0x2E) +-#define PPSMC_MSG_EnableLowMemoryPstate ((uint16_t) 0x2F) +-#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x30) +-#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x31) +-#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x32) +-#define PPSMC_MSG_DriverDramAddrHi ((uint16_t) 0x33) +-#define PPSMC_MSG_DriverDramAddrLo ((uint16_t) 0x34) +-#define PPSMC_MSG_CondExecDramAddrHi ((uint16_t) 0x35) +-#define PPSMC_MSG_CondExecDramAddrLo ((uint16_t) 0x36) +-#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x37) +-#define PPSMC_MSG_DriverResetMode ((uint16_t) 0x38) +-#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x39) +-#define PPSMC_MSG_SetDisplayPhyConfig ((uint16_t) 0x3A) +-#define PPSMC_MSG_GetMaxSclkLevel ((uint16_t) 0x3B) +-#define PPSMC_MSG_GetMaxLclkLevel ((uint16_t) 0x3C) +-#define PPSMC_MSG_GetMaxUvdLevel ((uint16_t) 0x3D) +-#define PPSMC_MSG_GetMaxEclkLevel ((uint16_t) 0x3E) +-#define PPSMC_MSG_GetMaxAclkLevel ((uint16_t) 0x3F) +-#define PPSMC_MSG_GetMaxNclkLevel ((uint16_t) 0x40) +-#define PPSMC_MSG_GetMaxPstate ((uint16_t) 0x41) +-#define PPSMC_MSG_DramAddrHiVirtual ((uint16_t) 0x42) +-#define PPSMC_MSG_DramAddrLoVirtual ((uint16_t) 0x43) +-#define PPSMC_MSG_DramAddrHiPhysical ((uint16_t) 0x44) +-#define PPSMC_MSG_DramAddrLoPhysical ((uint16_t) 0x45) +-#define PPSMC_MSG_DramBufferSize ((uint16_t) 0x46) +-#define PPSMC_MSG_SetMmPwrLogDramAddrHi ((uint16_t) 0x47) +-#define PPSMC_MSG_SetMmPwrLogDramAddrLo ((uint16_t) 0x48) +-#define PPSMC_MSG_SetClkTableAddrHi ((uint16_t) 0x49) +-#define PPSMC_MSG_SetClkTableAddrLo ((uint16_t) 0x4A) +-#define PPSMC_MSG_GetConservativePowerLimit ((uint16_t) 0x4B) +- +-#define PPSMC_MSG_InitJobs ((uint16_t) 0x252) +-#define PPSMC_MSG_ExecuteJob ((uint16_t) 0x254) +- +-#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) +-#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) +- +-#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) +-#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) +- +-#define PPSMC_MSG_PmStatusLogStart ((uint16_t) 0x170) +-#define PPSMC_MSG_PmStatusLogSample ((uint16_t) 0x171) +- +-#define PPSMC_MSG_AllowLowSclkInterrupt ((uint16_t) 0x184) +-#define PPSMC_MSG_MmPowerMonitorStart ((uint16_t) 0x18F) +-#define PPSMC_MSG_MmPowerMonitorStop ((uint16_t) 0x190) +-#define PPSMC_MSG_MmPowerMonitorRestart ((uint16_t) 0x191) +- +-#define PPSMC_MSG_SetClockGateMask ((uint16_t) 0x260) +-#define PPSMC_MSG_SetFpsThresholdLo ((uint16_t) 0x264) +-#define PPSMC_MSG_SetFpsThresholdHi ((uint16_t) 0x265) +-#define PPSMC_MSG_SetLowSclkIntrThreshold ((uint16_t) 0x266) +- +-#define PPSMC_MSG_ClkTableXferToDram ((uint16_t) 0x267) +-#define PPSMC_MSG_ClkTableXferToSmu ((uint16_t) 0x268) +-#define PPSMC_MSG_GetAverageGraphicsActivity ((uint16_t) 0x269) +-#define PPSMC_MSG_GetAverageGioActivity ((uint16_t) 0x26A) +-#define PPSMC_MSG_SetLoggerBufferSize ((uint16_t) 0x26B) +-#define PPSMC_MSG_SetLoggerAddressHigh ((uint16_t) 0x26C) +-#define PPSMC_MSG_SetLoggerAddressLow ((uint16_t) 0x26D) +-#define PPSMC_MSG_SetWatermarkFrequency ((uint16_t) 0x26E) +- +-/* REMOVE LATER*/ +-#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) +- +-/* Feature Enable Masks*/ +-#define NB_DPM_MASK 0x00000800 +-#define VDDGFX_MASK 0x00800000 +-#define VCE_DPM_MASK 0x00400000 +-#define ACP_DPM_MASK 0x00040000 +-#define UVD_DPM_MASK 0x00010000 +-#define GFX_CU_PG_MASK 0x00004000 +-#define SCLK_DPM_MASK 0x00080000 +- +-#if !defined(SMC_MICROCODE) +-#pragma pack(pop) +- +-#endif +- +-#endif +diff --git a/drivers/gpu/drm/amd/amdgpu/smu8.h b/drivers/gpu/drm/amd/amdgpu/smu8.h +deleted file mode 100644 +index d758d07..0000000 +--- a/drivers/gpu/drm/amd/amdgpu/smu8.h ++++ /dev/null +@@ -1,72 +0,0 @@ +-/* +- * Copyright 2014 Advanced Micro Devices, Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- */ +- +-#ifndef SMU8_H +-#define SMU8_H +- +-#pragma pack(push, 1) +- +-#define ENABLE_DEBUG_FEATURES +- +-struct SMU8_Firmware_Header { +- uint32_t Version; +- uint32_t ImageSize; +- uint32_t CodeSize; +- uint32_t HeaderSize; +- uint32_t EntryPoint; +- uint32_t Rtos; +- uint32_t UcodeLoadStatus; +- uint32_t DpmTable; +- uint32_t FanTable; +- uint32_t PmFuseTable; +- uint32_t Globals; +- uint32_t Reserved[20]; +- uint32_t Signature; +-}; +- +-struct SMU8_MultimediaPowerLogData { +- uint32_t avgTotalPower; +- uint32_t avgGpuPower; +- uint32_t avgUvdPower; +- uint32_t avgVcePower; +- +- uint32_t avgSclk; +- uint32_t avgDclk; +- uint32_t avgVclk; +- uint32_t avgEclk; +- +- uint32_t startTimeHi; +- uint32_t startTimeLo; +- +- uint32_t endTimeHi; +- uint32_t endTimeLo; +-}; +- +-#define SMU8_FIRMWARE_HEADER_LOCATION 0x1FF80 +-#define SMU8_UNBCSR_START_ADDR 0xC0100000 +- +-#define SMN_MP1_SRAM_START_ADDR 0x10000000 +- +-#pragma pack(pop) +- +-#endif +diff --git a/drivers/gpu/drm/amd/amdgpu/smu8_fusion.h b/drivers/gpu/drm/amd/amdgpu/smu8_fusion.h +deleted file mode 100644 +index 5c9cc3c..0000000 +--- a/drivers/gpu/drm/amd/amdgpu/smu8_fusion.h ++++ /dev/null +@@ -1,127 +0,0 @@ +-/* +- * Copyright 2014 Advanced Micro Devices, Inc. +- * +- * Permission is hereby granted, free of charge, to any person obtaining a +- * copy of this software and associated documentation files (the "Software"), +- * to deal in the Software without restriction, including without limitation +- * the rights to use, copy, modify, merge, publish, distribute, sublicense, +- * and/or sell copies of the Software, and to permit persons to whom the +- * Software is furnished to do so, subject to the following conditions: +- * +- * The above copyright notice and this permission notice shall be included in +- * all copies or substantial portions of the Software. +- * +- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +- * OTHER DEALINGS IN THE SOFTWARE. +- * +- */ +- +-#ifndef SMU8_FUSION_H +-#define SMU8_FUSION_H +- +-#include "smu8.h" +- +-#pragma pack(push, 1) +- +-#define SMU8_MAX_CUS 2 +-#define SMU8_PSMS_PER_CU 4 +-#define SMU8_CACS_PER_CU 4 +- +-struct SMU8_GfxCuPgScoreboard { +- uint8_t Enabled; +- uint8_t spare[3]; +-}; +- +-struct SMU8_Port80MonitorTable { +- uint32_t MmioAddress; +- uint32_t MemoryBaseHi; +- uint32_t MemoryBaseLo; +- uint16_t MemoryBufferSize; +- uint16_t MemoryPosition; +- uint16_t PollingInterval; +- uint8_t EnableCsrShadow; +- uint8_t EnableDramShadow; +-}; +- +-/* Clock Table Definitions */ +-#define NUM_SCLK_LEVELS 8 +-#define NUM_LCLK_LEVELS 8 +-#define NUM_UVD_LEVELS 8 +-#define NUM_ECLK_LEVELS 8 +-#define NUM_ACLK_LEVELS 8 +- +-struct SMU8_Fusion_ClkLevel { +- uint8_t GnbVid; +- uint8_t GfxVid; +- uint8_t DfsDid; +- uint8_t DeepSleepDid; +- uint32_t DfsBypass; +- uint32_t Frequency; +-}; +- +-struct SMU8_Fusion_SclkBreakdownTable { +- struct SMU8_Fusion_ClkLevel ClkLevel[NUM_SCLK_LEVELS]; +- struct SMU8_Fusion_ClkLevel DpmOffLevel; +- /* SMU8_Fusion_ClkLevel PwrOffLevel; */ +- uint32_t SclkValidMask; +- uint32_t MaxSclkIndex; +-}; +- +-struct SMU8_Fusion_LclkBreakdownTable { +- struct SMU8_Fusion_ClkLevel ClkLevel[NUM_LCLK_LEVELS]; +- struct SMU8_Fusion_ClkLevel DpmOffLevel; +- /* SMU8_Fusion_ClkLevel PwrOffLevel; */ +- uint32_t LclkValidMask; +- uint32_t MaxLclkIndex; +-}; +- +-struct SMU8_Fusion_EclkBreakdownTable { +- struct SMU8_Fusion_ClkLevel ClkLevel[NUM_ECLK_LEVELS]; +- struct SMU8_Fusion_ClkLevel DpmOffLevel; +- struct SMU8_Fusion_ClkLevel PwrOffLevel; +- uint32_t EclkValidMask; +- uint32_t MaxEclkIndex; +-}; +- +-struct SMU8_Fusion_VclkBreakdownTable { +- struct SMU8_Fusion_ClkLevel ClkLevel[NUM_UVD_LEVELS]; +- struct SMU8_Fusion_ClkLevel DpmOffLevel; +- struct SMU8_Fusion_ClkLevel PwrOffLevel; +- uint32_t VclkValidMask; +- uint32_t MaxVclkIndex; +-}; +- +-struct SMU8_Fusion_DclkBreakdownTable { +- struct SMU8_Fusion_ClkLevel ClkLevel[NUM_UVD_LEVELS]; +- struct SMU8_Fusion_ClkLevel DpmOffLevel; +- struct SMU8_Fusion_ClkLevel PwrOffLevel; +- uint32_t DclkValidMask; +- uint32_t MaxDclkIndex; +-}; +- +-struct SMU8_Fusion_AclkBreakdownTable { +- struct SMU8_Fusion_ClkLevel ClkLevel[NUM_ACLK_LEVELS]; +- struct SMU8_Fusion_ClkLevel DpmOffLevel; +- struct SMU8_Fusion_ClkLevel PwrOffLevel; +- uint32_t AclkValidMask; +- uint32_t MaxAclkIndex; +-}; +- +- +-struct SMU8_Fusion_ClkTable { +- struct SMU8_Fusion_SclkBreakdownTable SclkBreakdownTable; +- struct SMU8_Fusion_LclkBreakdownTable LclkBreakdownTable; +- struct SMU8_Fusion_EclkBreakdownTable EclkBreakdownTable; +- struct SMU8_Fusion_VclkBreakdownTable VclkBreakdownTable; +- struct SMU8_Fusion_DclkBreakdownTable DclkBreakdownTable; +- struct SMU8_Fusion_AclkBreakdownTable AclkBreakdownTable; +-}; +- +-#pragma pack(pop) +- +-#endif +diff --git a/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_cz.h b/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_cz.h +deleted file mode 100644 +index f8ba071..0000000 +--- a/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_cz.h ++++ /dev/null +@@ -1,147 +0,0 @@ +-// CZ Ucode Loading Definitions +-#ifndef SMU_UCODE_XFER_CZ_H +-#define SMU_UCODE_XFER_CZ_H +- +-#define NUM_JOBLIST_ENTRIES 32 +- +-#define TASK_TYPE_NO_ACTION 0 +-#define TASK_TYPE_UCODE_LOAD 1 +-#define TASK_TYPE_UCODE_SAVE 2 +-#define TASK_TYPE_REG_LOAD 3 +-#define TASK_TYPE_REG_SAVE 4 +-#define TASK_TYPE_INITIALIZE 5 +- +-#define TASK_ARG_REG_SMCIND 0 +-#define TASK_ARG_REG_MMIO 1 +-#define TASK_ARG_REG_FCH 2 +-#define TASK_ARG_REG_UNB 3 +- +-#define TASK_ARG_INIT_MM_PWR_LOG 0 +-#define TASK_ARG_INIT_CLK_TABLE 1 +- +-#define JOB_GFX_SAVE 0 +-#define JOB_GFX_RESTORE 1 +-#define JOB_FCH_SAVE 2 +-#define JOB_FCH_RESTORE 3 +-#define JOB_UNB_SAVE 4 +-#define JOB_UNB_RESTORE 5 +-#define JOB_GMC_SAVE 6 +-#define JOB_GMC_RESTORE 7 +-#define JOB_GNB_SAVE 8 +-#define JOB_GNB_RESTORE 9 +- +-#define IGNORE_JOB 0xff +-#define END_OF_TASK_LIST (uint16_t)0xffff +- +-// Size of DRAM regions (in bytes) requested by SMU: +-#define SMU_DRAM_REQ_MM_PWR_LOG 48 +- +-#define UCODE_ID_SDMA0 0 +-#define UCODE_ID_SDMA1 1 +-#define UCODE_ID_CP_CE 2 +-#define UCODE_ID_CP_PFP 3 +-#define UCODE_ID_CP_ME 4 +-#define UCODE_ID_CP_MEC_JT1 5 +-#define UCODE_ID_CP_MEC_JT2 6 +-#define UCODE_ID_GMCON_RENG 7 +-#define UCODE_ID_RLC_G 8 +-#define UCODE_ID_RLC_SCRATCH 9 +-#define UCODE_ID_RLC_SRM_ARAM 10 +-#define UCODE_ID_RLC_SRM_DRAM 11 +-#define UCODE_ID_DMCU_ERAM 12 +-#define UCODE_ID_DMCU_IRAM 13 +- +-#define UCODE_ID_SDMA0_MASK 0x00000001 +-#define UCODE_ID_SDMA1_MASK 0x00000002 +-#define UCODE_ID_CP_CE_MASK 0x00000004 +-#define UCODE_ID_CP_PFP_MASK 0x00000008 +-#define UCODE_ID_CP_ME_MASK 0x00000010 +-#define UCODE_ID_CP_MEC_JT1_MASK 0x00000020 +-#define UCODE_ID_CP_MEC_JT2_MASK 0x00000040 +-#define UCODE_ID_GMCON_RENG_MASK 0x00000080 +-#define UCODE_ID_RLC_G_MASK 0x00000100 +-#define UCODE_ID_RLC_SCRATCH_MASK 0x00000200 +-#define UCODE_ID_RLC_SRM_ARAM_MASK 0x00000400 +-#define UCODE_ID_RLC_SRM_DRAM_MASK 0x00000800 +-#define UCODE_ID_DMCU_ERAM_MASK 0x00001000 +-#define UCODE_ID_DMCU_IRAM_MASK 0x00002000 +- +-#define UCODE_ID_SDMA0_SIZE_BYTE 10368 +-#define UCODE_ID_SDMA1_SIZE_BYTE 10368 +-#define UCODE_ID_CP_CE_SIZE_BYTE 8576 +-#define UCODE_ID_CP_PFP_SIZE_BYTE 16768 +-#define UCODE_ID_CP_ME_SIZE_BYTE 16768 +-#define UCODE_ID_CP_MEC_JT1_SIZE_BYTE 384 +-#define UCODE_ID_CP_MEC_JT2_SIZE_BYTE 384 +-#define UCODE_ID_GMCON_RENG_SIZE_BYTE 4096 +-#define UCODE_ID_RLC_G_SIZE_BYTE 2048 +-#define UCODE_ID_RLC_SCRATCH_SIZE_BYTE 132 +-#define UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE 8192 +-#define UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE 4096 +-#define UCODE_ID_DMCU_ERAM_SIZE_BYTE 24576 +-#define UCODE_ID_DMCU_IRAM_SIZE_BYTE 1024 +- +-#define NUM_UCODES 14 +- +-typedef struct { +- uint32_t high; +- uint32_t low; +-} data_64_t; +- +-struct SMU_Task { +- uint8_t type; +- uint8_t arg; +- uint16_t next; +- data_64_t addr; +- uint32_t size_bytes; +-}; +-typedef struct SMU_Task SMU_Task; +- +-struct TOC { +- uint8_t JobList[NUM_JOBLIST_ENTRIES]; +- SMU_Task tasks[1]; +-}; +- +-// META DATA COMMAND Definitions +-#define METADATA_CMD_MODE0 0x00000103 +-#define METADATA_CMD_MODE1 0x00000113 +-#define METADATA_CMD_MODE2 0x00000123 +-#define METADATA_CMD_MODE3 0x00000133 +-#define METADATA_CMD_DELAY 0x00000203 +-#define METADATA_CMD_CHNG_REGSPACE 0x00000303 +-#define METADATA_PERFORM_ON_SAVE 0x00001000 +-#define METADATA_PERFORM_ON_LOAD 0x00002000 +-#define METADATA_CMD_ARG_MASK 0xFFFF0000 +-#define METADATA_CMD_ARG_SHIFT 16 +- +-// Simple register addr/data fields +-struct SMU_MetaData_Mode0 { +- uint32_t register_address; +- uint32_t register_data; +-}; +-typedef struct SMU_MetaData_Mode0 SMU_MetaData_Mode0; +- +-// Register addr/data with mask +-struct SMU_MetaData_Mode1 { +- uint32_t register_address; +- uint32_t register_mask; +- uint32_t register_data; +-}; +-typedef struct SMU_MetaData_Mode1 SMU_MetaData_Mode1; +- +-struct SMU_MetaData_Mode2 { +- uint32_t register_address; +- uint32_t register_mask; +- uint32_t target_value; +-}; +-typedef struct SMU_MetaData_Mode2 SMU_MetaData_Mode2; +- +-// Always write data (even on a save operation) +-struct SMU_MetaData_Mode3 { +- uint32_t register_address; +- uint32_t register_mask; +- uint32_t register_data; +-}; +-typedef struct SMU_MetaData_Mode3 SMU_MetaData_Mode3; +- +-#endif +diff --git a/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h +new file mode 100644 +index 0000000..273616a +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h +@@ -0,0 +1,185 @@ ++/* ++ * Copyright 2014 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++ ++#ifndef CZ_PP_SMC_H ++#define CZ_PP_SMC_H ++ ++#pragma pack(push, 1) ++ ++/* Fan control algorithm:*/ ++#define FDO_MODE_HARDWARE 0 ++#define FDO_MODE_PIECE_WISE_LINEAR 1 ++ ++enum FAN_CONTROL { ++ FAN_CONTROL_FUZZY, ++ FAN_CONTROL_TABLE ++}; ++ ++enum DPM_ARRAY { ++ DPM_ARRAY_HARD_MAX, ++ DPM_ARRAY_HARD_MIN, ++ DPM_ARRAY_SOFT_MAX, ++ DPM_ARRAY_SOFT_MIN ++}; ++ ++/* ++ * Return codes for driver to SMC communication. ++ * Leave these #define-s, enums might not be exactly 8-bits on the microcontroller. ++ */ ++#define PPSMC_Result_OK ((uint16_t)0x01) ++#define PPSMC_Result_NoMore ((uint16_t)0x02) ++#define PPSMC_Result_NotNow ((uint16_t)0x03) ++#define PPSMC_Result_Failed ((uint16_t)0xFF) ++#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) ++#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) ++ ++#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) ++ ++/* ++ * Supported driver messages ++ */ ++#define PPSMC_MSG_Test ((uint16_t) 0x1) ++#define PPSMC_MSG_GetFeatureStatus ((uint16_t) 0x2) ++#define PPSMC_MSG_EnableAllSmuFeatures ((uint16_t) 0x3) ++#define PPSMC_MSG_DisableAllSmuFeatures ((uint16_t) 0x4) ++#define PPSMC_MSG_OptimizeBattery ((uint16_t) 0x5) ++#define PPSMC_MSG_MaximizePerf ((uint16_t) 0x6) ++#define PPSMC_MSG_UVDPowerOFF ((uint16_t) 0x7) ++#define PPSMC_MSG_UVDPowerON ((uint16_t) 0x8) ++#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x9) ++#define PPSMC_MSG_VCEPowerON ((uint16_t) 0xA) ++#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0xB) ++#define PPSMC_MSG_ACPPowerON ((uint16_t) 0xC) ++#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0xD) ++#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0xE) ++#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0xF) ++#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x10) ++#define PPSMC_MSG_SetMinDeepSleepSclk ((uint16_t) 0x11) ++#define PPSMC_MSG_SetSclkSoftMin ((uint16_t) 0x12) ++#define PPSMC_MSG_SetSclkSoftMax ((uint16_t) 0x13) ++#define PPSMC_MSG_SetSclkHardMin ((uint16_t) 0x14) ++#define PPSMC_MSG_SetSclkHardMax ((uint16_t) 0x15) ++#define PPSMC_MSG_SetLclkSoftMin ((uint16_t) 0x16) ++#define PPSMC_MSG_SetLclkSoftMax ((uint16_t) 0x17) ++#define PPSMC_MSG_SetLclkHardMin ((uint16_t) 0x18) ++#define PPSMC_MSG_SetLclkHardMax ((uint16_t) 0x19) ++#define PPSMC_MSG_SetUvdSoftMin ((uint16_t) 0x1A) ++#define PPSMC_MSG_SetUvdSoftMax ((uint16_t) 0x1B) ++#define PPSMC_MSG_SetUvdHardMin ((uint16_t) 0x1C) ++#define PPSMC_MSG_SetUvdHardMax ((uint16_t) 0x1D) ++#define PPSMC_MSG_SetEclkSoftMin ((uint16_t) 0x1E) ++#define PPSMC_MSG_SetEclkSoftMax ((uint16_t) 0x1F) ++#define PPSMC_MSG_SetEclkHardMin ((uint16_t) 0x20) ++#define PPSMC_MSG_SetEclkHardMax ((uint16_t) 0x21) ++#define PPSMC_MSG_SetAclkSoftMin ((uint16_t) 0x22) ++#define PPSMC_MSG_SetAclkSoftMax ((uint16_t) 0x23) ++#define PPSMC_MSG_SetAclkHardMin ((uint16_t) 0x24) ++#define PPSMC_MSG_SetAclkHardMax ((uint16_t) 0x25) ++#define PPSMC_MSG_SetNclkSoftMin ((uint16_t) 0x26) ++#define PPSMC_MSG_SetNclkSoftMax ((uint16_t) 0x27) ++#define PPSMC_MSG_SetNclkHardMin ((uint16_t) 0x28) ++#define PPSMC_MSG_SetNclkHardMax ((uint16_t) 0x29) ++#define PPSMC_MSG_SetPstateSoftMin ((uint16_t) 0x2A) ++#define PPSMC_MSG_SetPstateSoftMax ((uint16_t) 0x2B) ++#define PPSMC_MSG_SetPstateHardMin ((uint16_t) 0x2C) ++#define PPSMC_MSG_SetPstateHardMax ((uint16_t) 0x2D) ++#define PPSMC_MSG_DisableLowMemoryPstate ((uint16_t) 0x2E) ++#define PPSMC_MSG_EnableLowMemoryPstate ((uint16_t) 0x2F) ++#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x30) ++#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x31) ++#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x32) ++#define PPSMC_MSG_DriverDramAddrHi ((uint16_t) 0x33) ++#define PPSMC_MSG_DriverDramAddrLo ((uint16_t) 0x34) ++#define PPSMC_MSG_CondExecDramAddrHi ((uint16_t) 0x35) ++#define PPSMC_MSG_CondExecDramAddrLo ((uint16_t) 0x36) ++#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x37) ++#define PPSMC_MSG_DriverResetMode ((uint16_t) 0x38) ++#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x39) ++#define PPSMC_MSG_SetDisplayPhyConfig ((uint16_t) 0x3A) ++#define PPSMC_MSG_GetMaxSclkLevel ((uint16_t) 0x3B) ++#define PPSMC_MSG_GetMaxLclkLevel ((uint16_t) 0x3C) ++#define PPSMC_MSG_GetMaxUvdLevel ((uint16_t) 0x3D) ++#define PPSMC_MSG_GetMaxEclkLevel ((uint16_t) 0x3E) ++#define PPSMC_MSG_GetMaxAclkLevel ((uint16_t) 0x3F) ++#define PPSMC_MSG_GetMaxNclkLevel ((uint16_t) 0x40) ++#define PPSMC_MSG_GetMaxPstate ((uint16_t) 0x41) ++#define PPSMC_MSG_DramAddrHiVirtual ((uint16_t) 0x42) ++#define PPSMC_MSG_DramAddrLoVirtual ((uint16_t) 0x43) ++#define PPSMC_MSG_DramAddrHiPhysical ((uint16_t) 0x44) ++#define PPSMC_MSG_DramAddrLoPhysical ((uint16_t) 0x45) ++#define PPSMC_MSG_DramBufferSize ((uint16_t) 0x46) ++#define PPSMC_MSG_SetMmPwrLogDramAddrHi ((uint16_t) 0x47) ++#define PPSMC_MSG_SetMmPwrLogDramAddrLo ((uint16_t) 0x48) ++#define PPSMC_MSG_SetClkTableAddrHi ((uint16_t) 0x49) ++#define PPSMC_MSG_SetClkTableAddrLo ((uint16_t) 0x4A) ++#define PPSMC_MSG_GetConservativePowerLimit ((uint16_t) 0x4B) ++ ++#define PPSMC_MSG_InitJobs ((uint16_t) 0x252) ++#define PPSMC_MSG_ExecuteJob ((uint16_t) 0x254) ++ ++#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) ++#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) ++ ++#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) ++#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) ++ ++#define PPSMC_MSG_PmStatusLogStart ((uint16_t) 0x170) ++#define PPSMC_MSG_PmStatusLogSample ((uint16_t) 0x171) ++ ++#define PPSMC_MSG_AllowLowSclkInterrupt ((uint16_t) 0x184) ++#define PPSMC_MSG_MmPowerMonitorStart ((uint16_t) 0x18F) ++#define PPSMC_MSG_MmPowerMonitorStop ((uint16_t) 0x190) ++#define PPSMC_MSG_MmPowerMonitorRestart ((uint16_t) 0x191) ++ ++#define PPSMC_MSG_SetClockGateMask ((uint16_t) 0x260) ++#define PPSMC_MSG_SetFpsThresholdLo ((uint16_t) 0x264) ++#define PPSMC_MSG_SetFpsThresholdHi ((uint16_t) 0x265) ++#define PPSMC_MSG_SetLowSclkIntrThreshold ((uint16_t) 0x266) ++ ++#define PPSMC_MSG_ClkTableXferToDram ((uint16_t) 0x267) ++#define PPSMC_MSG_ClkTableXferToSmu ((uint16_t) 0x268) ++#define PPSMC_MSG_GetAverageGraphicsActivity ((uint16_t) 0x269) ++#define PPSMC_MSG_GetAverageGioActivity ((uint16_t) 0x26A) ++#define PPSMC_MSG_SetLoggerBufferSize ((uint16_t) 0x26B) ++#define PPSMC_MSG_SetLoggerAddressHigh ((uint16_t) 0x26C) ++#define PPSMC_MSG_SetLoggerAddressLow ((uint16_t) 0x26D) ++#define PPSMC_MSG_SetWatermarkFrequency ((uint16_t) 0x26E) ++ ++/* REMOVE LATER*/ ++#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) ++ ++/* Feature Enable Masks*/ ++#define NB_DPM_MASK 0x00000800 ++#define VDDGFX_MASK 0x00800000 ++#define VCE_DPM_MASK 0x00400000 ++#define ACP_DPM_MASK 0x00040000 ++#define UVD_DPM_MASK 0x00010000 ++#define GFX_CU_PG_MASK 0x00004000 ++#define SCLK_DPM_MASK 0x00080000 ++ ++#if !defined(SMC_MICROCODE) ++#pragma pack(pop) ++ ++#endif ++ ++#endif +diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu8.h b/drivers/gpu/drm/amd/powerplay/inc/smu8.h +new file mode 100644 +index 0000000..d758d07 +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/inc/smu8.h +@@ -0,0 +1,72 @@ ++/* ++ * Copyright 2014 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++ ++#ifndef SMU8_H ++#define SMU8_H ++ ++#pragma pack(push, 1) ++ ++#define ENABLE_DEBUG_FEATURES ++ ++struct SMU8_Firmware_Header { ++ uint32_t Version; ++ uint32_t ImageSize; ++ uint32_t CodeSize; ++ uint32_t HeaderSize; ++ uint32_t EntryPoint; ++ uint32_t Rtos; ++ uint32_t UcodeLoadStatus; ++ uint32_t DpmTable; ++ uint32_t FanTable; ++ uint32_t PmFuseTable; ++ uint32_t Globals; ++ uint32_t Reserved[20]; ++ uint32_t Signature; ++}; ++ ++struct SMU8_MultimediaPowerLogData { ++ uint32_t avgTotalPower; ++ uint32_t avgGpuPower; ++ uint32_t avgUvdPower; ++ uint32_t avgVcePower; ++ ++ uint32_t avgSclk; ++ uint32_t avgDclk; ++ uint32_t avgVclk; ++ uint32_t avgEclk; ++ ++ uint32_t startTimeHi; ++ uint32_t startTimeLo; ++ ++ uint32_t endTimeHi; ++ uint32_t endTimeLo; ++}; ++ ++#define SMU8_FIRMWARE_HEADER_LOCATION 0x1FF80 ++#define SMU8_UNBCSR_START_ADDR 0xC0100000 ++ ++#define SMN_MP1_SRAM_START_ADDR 0x10000000 ++ ++#pragma pack(pop) ++ ++#endif +diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h b/drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h +new file mode 100644 +index 0000000..5c9cc3c +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h +@@ -0,0 +1,127 @@ ++/* ++ * Copyright 2014 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++ ++#ifndef SMU8_FUSION_H ++#define SMU8_FUSION_H ++ ++#include "smu8.h" ++ ++#pragma pack(push, 1) ++ ++#define SMU8_MAX_CUS 2 ++#define SMU8_PSMS_PER_CU 4 ++#define SMU8_CACS_PER_CU 4 ++ ++struct SMU8_GfxCuPgScoreboard { ++ uint8_t Enabled; ++ uint8_t spare[3]; ++}; ++ ++struct SMU8_Port80MonitorTable { ++ uint32_t MmioAddress; ++ uint32_t MemoryBaseHi; ++ uint32_t MemoryBaseLo; ++ uint16_t MemoryBufferSize; ++ uint16_t MemoryPosition; ++ uint16_t PollingInterval; ++ uint8_t EnableCsrShadow; ++ uint8_t EnableDramShadow; ++}; ++ ++/* Clock Table Definitions */ ++#define NUM_SCLK_LEVELS 8 ++#define NUM_LCLK_LEVELS 8 ++#define NUM_UVD_LEVELS 8 ++#define NUM_ECLK_LEVELS 8 ++#define NUM_ACLK_LEVELS 8 ++ ++struct SMU8_Fusion_ClkLevel { ++ uint8_t GnbVid; ++ uint8_t GfxVid; ++ uint8_t DfsDid; ++ uint8_t DeepSleepDid; ++ uint32_t DfsBypass; ++ uint32_t Frequency; ++}; ++ ++struct SMU8_Fusion_SclkBreakdownTable { ++ struct SMU8_Fusion_ClkLevel ClkLevel[NUM_SCLK_LEVELS]; ++ struct SMU8_Fusion_ClkLevel DpmOffLevel; ++ /* SMU8_Fusion_ClkLevel PwrOffLevel; */ ++ uint32_t SclkValidMask; ++ uint32_t MaxSclkIndex; ++}; ++ ++struct SMU8_Fusion_LclkBreakdownTable { ++ struct SMU8_Fusion_ClkLevel ClkLevel[NUM_LCLK_LEVELS]; ++ struct SMU8_Fusion_ClkLevel DpmOffLevel; ++ /* SMU8_Fusion_ClkLevel PwrOffLevel; */ ++ uint32_t LclkValidMask; ++ uint32_t MaxLclkIndex; ++}; ++ ++struct SMU8_Fusion_EclkBreakdownTable { ++ struct SMU8_Fusion_ClkLevel ClkLevel[NUM_ECLK_LEVELS]; ++ struct SMU8_Fusion_ClkLevel DpmOffLevel; ++ struct SMU8_Fusion_ClkLevel PwrOffLevel; ++ uint32_t EclkValidMask; ++ uint32_t MaxEclkIndex; ++}; ++ ++struct SMU8_Fusion_VclkBreakdownTable { ++ struct SMU8_Fusion_ClkLevel ClkLevel[NUM_UVD_LEVELS]; ++ struct SMU8_Fusion_ClkLevel DpmOffLevel; ++ struct SMU8_Fusion_ClkLevel PwrOffLevel; ++ uint32_t VclkValidMask; ++ uint32_t MaxVclkIndex; ++}; ++ ++struct SMU8_Fusion_DclkBreakdownTable { ++ struct SMU8_Fusion_ClkLevel ClkLevel[NUM_UVD_LEVELS]; ++ struct SMU8_Fusion_ClkLevel DpmOffLevel; ++ struct SMU8_Fusion_ClkLevel PwrOffLevel; ++ uint32_t DclkValidMask; ++ uint32_t MaxDclkIndex; ++}; ++ ++struct SMU8_Fusion_AclkBreakdownTable { ++ struct SMU8_Fusion_ClkLevel ClkLevel[NUM_ACLK_LEVELS]; ++ struct SMU8_Fusion_ClkLevel DpmOffLevel; ++ struct SMU8_Fusion_ClkLevel PwrOffLevel; ++ uint32_t AclkValidMask; ++ uint32_t MaxAclkIndex; ++}; ++ ++ ++struct SMU8_Fusion_ClkTable { ++ struct SMU8_Fusion_SclkBreakdownTable SclkBreakdownTable; ++ struct SMU8_Fusion_LclkBreakdownTable LclkBreakdownTable; ++ struct SMU8_Fusion_EclkBreakdownTable EclkBreakdownTable; ++ struct SMU8_Fusion_VclkBreakdownTable VclkBreakdownTable; ++ struct SMU8_Fusion_DclkBreakdownTable DclkBreakdownTable; ++ struct SMU8_Fusion_AclkBreakdownTable AclkBreakdownTable; ++}; ++ ++#pragma pack(pop) ++ ++#endif +diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h b/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h +new file mode 100644 +index 0000000..f8ba071 +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h +@@ -0,0 +1,147 @@ ++// CZ Ucode Loading Definitions ++#ifndef SMU_UCODE_XFER_CZ_H ++#define SMU_UCODE_XFER_CZ_H ++ ++#define NUM_JOBLIST_ENTRIES 32 ++ ++#define TASK_TYPE_NO_ACTION 0 ++#define TASK_TYPE_UCODE_LOAD 1 ++#define TASK_TYPE_UCODE_SAVE 2 ++#define TASK_TYPE_REG_LOAD 3 ++#define TASK_TYPE_REG_SAVE 4 ++#define TASK_TYPE_INITIALIZE 5 ++ ++#define TASK_ARG_REG_SMCIND 0 ++#define TASK_ARG_REG_MMIO 1 ++#define TASK_ARG_REG_FCH 2 ++#define TASK_ARG_REG_UNB 3 ++ ++#define TASK_ARG_INIT_MM_PWR_LOG 0 ++#define TASK_ARG_INIT_CLK_TABLE 1 ++ ++#define JOB_GFX_SAVE 0 ++#define JOB_GFX_RESTORE 1 ++#define JOB_FCH_SAVE 2 ++#define JOB_FCH_RESTORE 3 ++#define JOB_UNB_SAVE 4 ++#define JOB_UNB_RESTORE 5 ++#define JOB_GMC_SAVE 6 ++#define JOB_GMC_RESTORE 7 ++#define JOB_GNB_SAVE 8 ++#define JOB_GNB_RESTORE 9 ++ ++#define IGNORE_JOB 0xff ++#define END_OF_TASK_LIST (uint16_t)0xffff ++ ++// Size of DRAM regions (in bytes) requested by SMU: ++#define SMU_DRAM_REQ_MM_PWR_LOG 48 ++ ++#define UCODE_ID_SDMA0 0 ++#define UCODE_ID_SDMA1 1 ++#define UCODE_ID_CP_CE 2 ++#define UCODE_ID_CP_PFP 3 ++#define UCODE_ID_CP_ME 4 ++#define UCODE_ID_CP_MEC_JT1 5 ++#define UCODE_ID_CP_MEC_JT2 6 ++#define UCODE_ID_GMCON_RENG 7 ++#define UCODE_ID_RLC_G 8 ++#define UCODE_ID_RLC_SCRATCH 9 ++#define UCODE_ID_RLC_SRM_ARAM 10 ++#define UCODE_ID_RLC_SRM_DRAM 11 ++#define UCODE_ID_DMCU_ERAM 12 ++#define UCODE_ID_DMCU_IRAM 13 ++ ++#define UCODE_ID_SDMA0_MASK 0x00000001 ++#define UCODE_ID_SDMA1_MASK 0x00000002 ++#define UCODE_ID_CP_CE_MASK 0x00000004 ++#define UCODE_ID_CP_PFP_MASK 0x00000008 ++#define UCODE_ID_CP_ME_MASK 0x00000010 ++#define UCODE_ID_CP_MEC_JT1_MASK 0x00000020 ++#define UCODE_ID_CP_MEC_JT2_MASK 0x00000040 ++#define UCODE_ID_GMCON_RENG_MASK 0x00000080 ++#define UCODE_ID_RLC_G_MASK 0x00000100 ++#define UCODE_ID_RLC_SCRATCH_MASK 0x00000200 ++#define UCODE_ID_RLC_SRM_ARAM_MASK 0x00000400 ++#define UCODE_ID_RLC_SRM_DRAM_MASK 0x00000800 ++#define UCODE_ID_DMCU_ERAM_MASK 0x00001000 ++#define UCODE_ID_DMCU_IRAM_MASK 0x00002000 ++ ++#define UCODE_ID_SDMA0_SIZE_BYTE 10368 ++#define UCODE_ID_SDMA1_SIZE_BYTE 10368 ++#define UCODE_ID_CP_CE_SIZE_BYTE 8576 ++#define UCODE_ID_CP_PFP_SIZE_BYTE 16768 ++#define UCODE_ID_CP_ME_SIZE_BYTE 16768 ++#define UCODE_ID_CP_MEC_JT1_SIZE_BYTE 384 ++#define UCODE_ID_CP_MEC_JT2_SIZE_BYTE 384 ++#define UCODE_ID_GMCON_RENG_SIZE_BYTE 4096 ++#define UCODE_ID_RLC_G_SIZE_BYTE 2048 ++#define UCODE_ID_RLC_SCRATCH_SIZE_BYTE 132 ++#define UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE 8192 ++#define UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE 4096 ++#define UCODE_ID_DMCU_ERAM_SIZE_BYTE 24576 ++#define UCODE_ID_DMCU_IRAM_SIZE_BYTE 1024 ++ ++#define NUM_UCODES 14 ++ ++typedef struct { ++ uint32_t high; ++ uint32_t low; ++} data_64_t; ++ ++struct SMU_Task { ++ uint8_t type; ++ uint8_t arg; ++ uint16_t next; ++ data_64_t addr; ++ uint32_t size_bytes; ++}; ++typedef struct SMU_Task SMU_Task; ++ ++struct TOC { ++ uint8_t JobList[NUM_JOBLIST_ENTRIES]; ++ SMU_Task tasks[1]; ++}; ++ ++// META DATA COMMAND Definitions ++#define METADATA_CMD_MODE0 0x00000103 ++#define METADATA_CMD_MODE1 0x00000113 ++#define METADATA_CMD_MODE2 0x00000123 ++#define METADATA_CMD_MODE3 0x00000133 ++#define METADATA_CMD_DELAY 0x00000203 ++#define METADATA_CMD_CHNG_REGSPACE 0x00000303 ++#define METADATA_PERFORM_ON_SAVE 0x00001000 ++#define METADATA_PERFORM_ON_LOAD 0x00002000 ++#define METADATA_CMD_ARG_MASK 0xFFFF0000 ++#define METADATA_CMD_ARG_SHIFT 16 ++ ++// Simple register addr/data fields ++struct SMU_MetaData_Mode0 { ++ uint32_t register_address; ++ uint32_t register_data; ++}; ++typedef struct SMU_MetaData_Mode0 SMU_MetaData_Mode0; ++ ++// Register addr/data with mask ++struct SMU_MetaData_Mode1 { ++ uint32_t register_address; ++ uint32_t register_mask; ++ uint32_t register_data; ++}; ++typedef struct SMU_MetaData_Mode1 SMU_MetaData_Mode1; ++ ++struct SMU_MetaData_Mode2 { ++ uint32_t register_address; ++ uint32_t register_mask; ++ uint32_t target_value; ++}; ++typedef struct SMU_MetaData_Mode2 SMU_MetaData_Mode2; ++ ++// Always write data (even on a save operation) ++struct SMU_MetaData_Mode3 { ++ uint32_t register_address; ++ uint32_t register_mask; ++ uint32_t register_data; ++}; ++typedef struct SMU_MetaData_Mode3 SMU_MetaData_Mode3; ++ ++#endif +diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile +index 61bfb2a..9219940 100644 +--- a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile ++++ b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile +@@ -2,7 +2,7 @@ + # Makefile for the 'smu manager' sub-component of powerplay. + # It provides the smu management services for the driver. + +-SMU_MGR = smumgr.o ++SMU_MGR = smumgr.o cz_smumgr.o + + AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR)) + +diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c +new file mode 100644 +index 0000000..e74023b +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c +@@ -0,0 +1,858 @@ ++/* ++ * Copyright 2015 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/gfp.h> ++#include "linux/delay.h" ++#include "cgs_common.h" ++#include "smu/smu_8_0_d.h" ++#include "smu/smu_8_0_sh_mask.h" ++#include "smu8.h" ++#include "smu8_fusion.h" ++#include "cz_smumgr.h" ++#include "cz_ppsmc.h" ++#include "smu_ucode_xfer_cz.h" ++#include "gca/gfx_8_0_d.h" ++#include "gca/gfx_8_0_sh_mask.h" ++#include "smumgr.h" ++ ++#define SIZE_ALIGN_32(x) (((x) + 31) / 32 * 32) ++ ++static enum cz_scratch_entry firmware_list[] = { ++ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, ++ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, ++}; ++ ++static int cz_smum_get_argument(struct pp_smumgr *smumgr) ++{ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ return cgs_read_register(smumgr->device, ++ mmSMU_MP1_SRBM2P_ARG_0); ++} ++ ++static int cz_send_msg_to_smc_async(struct pp_smumgr *smumgr, ++ uint16_t msg) ++{ ++ int result = 0; ++ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ result = SMUM_WAIT_FIELD_UNEQUAL(smumgr, ++ SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); ++ if (result != 0) { ++ printk(KERN_ERR "[ powerplay ] cz_send_msg_to_smc_async failed\n"); ++ return result; ++ } ++ ++ cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0); ++ cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg); ++ ++ return 0; ++} ++ ++/* Send a message to the SMC, and wait for its response.*/ ++static int cz_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) ++{ ++ int result = 0; ++ ++ result = cz_send_msg_to_smc_async(smumgr, msg); ++ if (result != 0) ++ return result; ++ ++ result = SMUM_WAIT_FIELD_UNEQUAL(smumgr, ++ SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); ++ ++ if (result != 0) ++ return result; ++ ++ return 0; ++} ++ ++static int cz_set_smc_sram_address(struct pp_smumgr *smumgr, ++ uint32_t smc_address, uint32_t limit) ++{ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ if (0 != (3 & smc_address)) { ++ printk(KERN_ERR "[ powerplay ] SMC address must be 4 byte aligned\n"); ++ return -1; ++ } ++ ++ if (limit <= (smc_address + 3)) { ++ printk(KERN_ERR "[ powerplay ] SMC address beyond the SMC RAM area\n"); ++ return -1; ++ } ++ ++ cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX_0, ++ SMN_MP1_SRAM_START_ADDR + smc_address); ++ ++ return 0; ++} ++ ++static int cz_write_smc_sram_dword(struct pp_smumgr *smumgr, ++ uint32_t smc_address, uint32_t value, uint32_t limit) ++{ ++ int result; ++ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ result = cz_set_smc_sram_address(smumgr, smc_address, limit); ++ cgs_write_register(smumgr->device, mmMP0PUB_IND_DATA_0, value); ++ ++ return 0; ++} ++ ++static int cz_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, ++ uint16_t msg, uint32_t parameter) ++{ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter); ++ ++ return cz_send_msg_to_smc(smumgr, msg); ++} ++ ++static int cz_request_smu_load_fw(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)(smumgr->backend); ++ int result = 0; ++ uint32_t smc_address; ++ ++ if (!smumgr->reload_fw) { ++ printk(KERN_INFO "[ powerplay ] skip reloading...\n"); ++ return 0; ++ } ++ ++ smc_address = SMU8_FIRMWARE_HEADER_LOCATION + ++ offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); ++ ++ cz_write_smc_sram_dword(smumgr, smc_address, 0, smc_address+4); ++ ++ cz_send_msg_to_smc_with_parameter(smumgr, ++ PPSMC_MSG_DriverDramAddrHi, ++ cz_smu->toc_buffer.mc_addr_high); ++ ++ cz_send_msg_to_smc_with_parameter(smumgr, ++ PPSMC_MSG_DriverDramAddrLo, ++ cz_smu->toc_buffer.mc_addr_low); ++ ++ cz_send_msg_to_smc(smumgr, PPSMC_MSG_InitJobs); ++ ++ cz_send_msg_to_smc_with_parameter(smumgr, ++ PPSMC_MSG_ExecuteJob, ++ cz_smu->toc_entry_aram); ++ cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, ++ cz_smu->toc_entry_power_profiling_index); ++ ++ result = cz_send_msg_to_smc_with_parameter(smumgr, ++ PPSMC_MSG_ExecuteJob, ++ cz_smu->toc_entry_initialize_index); ++ ++ return result; ++} ++ ++static int cz_check_fw_load_finish(struct pp_smumgr *smumgr, ++ uint32_t firmware) ++{ ++ int i; ++ uint32_t index = SMN_MP1_SRAM_START_ADDR + ++ SMU8_FIRMWARE_HEADER_LOCATION + ++ offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); ++ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ return cgs_read_register(smumgr->device, ++ mmSMU_MP1_SRBM2P_ARG_0); ++ ++ cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX, index); ++ ++ for (i = 0; i < smumgr->usec_timeout; i++) { ++ if (firmware == ++ (cgs_read_register(smumgr->device, mmMP0PUB_IND_DATA) & firmware)) ++ break; ++ udelay(1); ++ } ++ ++ if (i >= smumgr->usec_timeout) { ++ printk(KERN_ERR "[ powerplay ] SMU check loaded firmware failed.\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int cz_load_mec_firmware(struct pp_smumgr *smumgr) ++{ ++ uint32_t reg_data; ++ uint32_t tmp; ++ int ret = 0; ++ struct cgs_firmware_info info = {0}; ++ struct cz_smumgr *cz_smu; ++ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ cz_smu = (struct cz_smumgr *)smumgr->backend; ++ ret = cgs_get_firmware_info(smumgr->device, ++ CGS_UCODE_ID_CP_MEC, &info); ++ ++ if (ret) ++ return -EINVAL; ++ ++ /* Disable MEC parsing/prefetching */ ++ tmp = cgs_read_register(smumgr->device, ++ mmCP_MEC_CNTL); ++ tmp = SMUM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1); ++ tmp = SMUM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1); ++ cgs_write_register(smumgr->device, mmCP_MEC_CNTL, tmp); ++ ++ tmp = cgs_read_register(smumgr->device, ++ mmCP_CPC_IC_BASE_CNTL); ++ ++ tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0); ++ tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0); ++ tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); ++ tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1); ++ cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_CNTL, tmp); ++ ++ reg_data = smu_lower_32_bits(info.mc_addr) & ++ SMUM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO); ++ cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_LO, reg_data); ++ ++ reg_data = smu_upper_32_bits(info.mc_addr) & ++ SMUM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI); ++ cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_HI, reg_data); ++ ++ return 0; ++} ++ ++static int cz_start_smu(struct pp_smumgr *smumgr) ++{ ++ int ret = 0; ++ uint32_t fw_to_check = UCODE_ID_RLC_G_MASK | ++ UCODE_ID_SDMA0_MASK | ++ UCODE_ID_SDMA1_MASK | ++ UCODE_ID_CP_CE_MASK | ++ UCODE_ID_CP_ME_MASK | ++ UCODE_ID_CP_PFP_MASK | ++ UCODE_ID_CP_MEC_JT1_MASK | ++ UCODE_ID_CP_MEC_JT2_MASK; ++ ++ cz_request_smu_load_fw(smumgr); ++ cz_check_fw_load_finish(smumgr, fw_to_check); ++ ++ ret = cz_load_mec_firmware(smumgr); ++ if (ret) ++ printk(KERN_ERR "[ powerplay ] Mec Firmware load failed\n"); ++ ++ return ret; ++} ++ ++static uint8_t cz_translate_firmware_enum_to_arg( ++ enum cz_scratch_entry firmware_enum) ++{ ++ uint8_t ret = 0; ++ ++ switch (firmware_enum) { ++ case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0: ++ ret = UCODE_ID_SDMA0; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1: ++ ret = UCODE_ID_SDMA1; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE: ++ ret = UCODE_ID_CP_CE; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP: ++ ret = UCODE_ID_CP_PFP; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME: ++ ret = UCODE_ID_CP_ME; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1: ++ ret = UCODE_ID_CP_MEC_JT1; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2: ++ ret = UCODE_ID_CP_MEC_JT2; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG: ++ ret = UCODE_ID_GMCON_RENG; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G: ++ ret = UCODE_ID_RLC_G; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH: ++ ret = UCODE_ID_RLC_SCRATCH; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM: ++ ret = UCODE_ID_RLC_SRM_ARAM; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM: ++ ret = UCODE_ID_RLC_SRM_DRAM; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM: ++ ret = UCODE_ID_DMCU_ERAM; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM: ++ ret = UCODE_ID_DMCU_IRAM; ++ break; ++ case CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING: ++ ret = TASK_ARG_INIT_MM_PWR_LOG; ++ break; ++ case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT: ++ case CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING: ++ case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS: ++ case CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT: ++ case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START: ++ case CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS: ++ ret = TASK_ARG_REG_MMIO; ++ break; ++ case CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE: ++ ret = TASK_ARG_INIT_CLK_TABLE; ++ break; ++ } ++ ++ return ret; ++} ++ ++static enum cgs_ucode_id cz_convert_fw_type_to_cgs(uint32_t fw_type) ++{ ++ enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM; ++ ++ switch (fw_type) { ++ case UCODE_ID_SDMA0: ++ result = CGS_UCODE_ID_SDMA0; ++ break; ++ case UCODE_ID_SDMA1: ++ result = CGS_UCODE_ID_SDMA1; ++ break; ++ case UCODE_ID_CP_CE: ++ result = CGS_UCODE_ID_CP_CE; ++ break; ++ case UCODE_ID_CP_PFP: ++ result = CGS_UCODE_ID_CP_PFP; ++ break; ++ case UCODE_ID_CP_ME: ++ result = CGS_UCODE_ID_CP_ME; ++ break; ++ case UCODE_ID_CP_MEC_JT1: ++ result = CGS_UCODE_ID_CP_MEC_JT1; ++ break; ++ case UCODE_ID_CP_MEC_JT2: ++ result = CGS_UCODE_ID_CP_MEC_JT2; ++ break; ++ case UCODE_ID_RLC_G: ++ result = CGS_UCODE_ID_RLC_G; ++ break; ++ default: ++ break; ++ } ++ ++ return result; ++} ++ ++static int cz_smu_populate_single_scratch_task( ++ struct pp_smumgr *smumgr, ++ enum cz_scratch_entry fw_enum, ++ uint8_t type, bool is_last) ++{ ++ uint8_t i; ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; ++ struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++]; ++ ++ task->type = type; ++ task->arg = cz_translate_firmware_enum_to_arg(fw_enum); ++ task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count; ++ ++ for (i = 0; i < cz_smu->scratch_buffer_length; i++) ++ if (cz_smu->scratch_buffer[i].firmware_ID == fw_enum) ++ break; ++ ++ if (i >= cz_smu->scratch_buffer_length) { ++ printk(KERN_ERR "[ powerplay ] Invalid Firmware Type\n"); ++ return -EINVAL; ++ } ++ ++ task->addr.low = cz_smu->scratch_buffer[i].mc_addr_low; ++ task->addr.high = cz_smu->scratch_buffer[i].mc_addr_high; ++ task->size_bytes = cz_smu->scratch_buffer[i].data_size; ++ ++ if (CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) { ++ struct cz_ih_meta_data *pIHReg_restore = ++ (struct cz_ih_meta_data *)cz_smu->scratch_buffer[i].kaddr; ++ pIHReg_restore->command = ++ METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD; ++ } ++ ++ return 0; ++} ++ ++static int cz_smu_populate_single_ucode_load_task( ++ struct pp_smumgr *smumgr, ++ enum cz_scratch_entry fw_enum, ++ bool is_last) ++{ ++ uint8_t i; ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; ++ struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++]; ++ ++ task->type = TASK_TYPE_UCODE_LOAD; ++ task->arg = cz_translate_firmware_enum_to_arg(fw_enum); ++ task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count; ++ ++ for (i = 0; i < cz_smu->driver_buffer_length; i++) ++ if (cz_smu->driver_buffer[i].firmware_ID == fw_enum) ++ break; ++ ++ if (i >= cz_smu->driver_buffer_length) { ++ printk(KERN_ERR "[ powerplay ] Invalid Firmware Type\n"); ++ return -EINVAL; ++ } ++ ++ task->addr.low = cz_smu->driver_buffer[i].mc_addr_low; ++ task->addr.high = cz_smu->driver_buffer[i].mc_addr_high; ++ task->size_bytes = cz_smu->driver_buffer[i].data_size; ++ ++ return 0; ++} ++ ++static int cz_smu_construct_toc_for_rlc_aram_save(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ ++ cz_smu->toc_entry_aram = cz_smu->toc_entry_used_count; ++ cz_smu_populate_single_scratch_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, ++ TASK_TYPE_UCODE_SAVE, true); ++ ++ return 0; ++} ++ ++static int cz_smu_initialize_toc_empty_job_list(struct pp_smumgr *smumgr) ++{ ++ int i; ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; ++ ++ for (i = 0; i < NUM_JOBLIST_ENTRIES; i++) ++ toc->JobList[i] = (uint8_t)IGNORE_JOB; ++ ++ return 0; ++} ++ ++static int cz_smu_construct_toc_for_vddgfx_enter(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; ++ ++ toc->JobList[JOB_GFX_SAVE] = (uint8_t)cz_smu->toc_entry_used_count; ++ cz_smu_populate_single_scratch_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, ++ TASK_TYPE_UCODE_SAVE, false); ++ ++ cz_smu_populate_single_scratch_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, ++ TASK_TYPE_UCODE_SAVE, true); ++ ++ return 0; ++} ++ ++ ++static int cz_smu_construct_toc_for_vddgfx_exit(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; ++ ++ toc->JobList[JOB_GFX_RESTORE] = (uint8_t)cz_smu->toc_entry_used_count; ++ ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, false); ++ ++ /* populate scratch */ ++ cz_smu_populate_single_scratch_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, ++ TASK_TYPE_UCODE_LOAD, false); ++ ++ cz_smu_populate_single_scratch_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, ++ TASK_TYPE_UCODE_LOAD, false); ++ ++ cz_smu_populate_single_scratch_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, ++ TASK_TYPE_UCODE_LOAD, true); ++ ++ return 0; ++} ++ ++static int cz_smu_construct_toc_for_power_profiling( ++ struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ ++ cz_smu->toc_entry_power_profiling_index = cz_smu->toc_entry_used_count; ++ ++ cz_smu_populate_single_scratch_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, ++ TASK_TYPE_INITIALIZE, true); ++ return 0; ++} ++ ++static int cz_smu_construct_toc_for_bootup(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ ++ cz_smu->toc_entry_initialize_index = cz_smu->toc_entry_used_count; ++ ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); ++ cz_smu_populate_single_ucode_load_task(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, true); ++ ++ return 0; ++} ++ ++static int cz_smu_construct_toc_for_clock_table(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ ++ cz_smu->toc_entry_clock_table = cz_smu->toc_entry_used_count; ++ ++ cz_smu_populate_single_scratch_task(smumgr, ++ CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, ++ TASK_TYPE_INITIALIZE, true); ++ ++ return 0; ++} ++ ++static int cz_smu_construct_toc(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ ++ cz_smu->toc_entry_used_count = 0; ++ ++ cz_smu_initialize_toc_empty_job_list(smumgr); ++ ++ cz_smu_construct_toc_for_rlc_aram_save(smumgr); ++ ++ cz_smu_construct_toc_for_vddgfx_enter(smumgr); ++ ++ cz_smu_construct_toc_for_vddgfx_exit(smumgr); ++ ++ cz_smu_construct_toc_for_power_profiling(smumgr); ++ ++ cz_smu_construct_toc_for_bootup(smumgr); ++ ++ cz_smu_construct_toc_for_clock_table(smumgr); ++ ++ return 0; ++} ++ ++static int cz_smu_populate_firmware_entries(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ uint32_t firmware_type; ++ uint32_t i; ++ int ret; ++ enum cgs_ucode_id ucode_id; ++ struct cgs_firmware_info info = {0}; ++ ++ cz_smu->driver_buffer_length = 0; ++ ++ for (i = 0; i < sizeof(firmware_list)/sizeof(*firmware_list); i++) { ++ ++ firmware_type = cz_translate_firmware_enum_to_arg( ++ firmware_list[i]); ++ ++ ucode_id = cz_convert_fw_type_to_cgs(firmware_type); ++ ++ ret = cgs_get_firmware_info(smumgr->device, ++ ucode_id, &info); ++ ++ if (ret == 0) { ++ cz_smu->driver_buffer[i].mc_addr_high = ++ smu_upper_32_bits(info.mc_addr); ++ ++ cz_smu->driver_buffer[i].mc_addr_low = ++ smu_lower_32_bits(info.mc_addr); ++ ++ cz_smu->driver_buffer[i].data_size = info.image_size; ++ ++ cz_smu->driver_buffer[i].firmware_ID = firmware_list[i]; ++ cz_smu->driver_buffer_length++; ++ } ++ } ++ ++ return 0; ++} ++ ++static int cz_smu_populate_single_scratch_entry( ++ struct pp_smumgr *smumgr, ++ enum cz_scratch_entry scratch_type, ++ uint32_t ulsize_byte, ++ struct cz_buffer_entry *entry) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ long long mc_addr = ++ ((long long)(cz_smu->smu_buffer.mc_addr_high) << 32) ++ | cz_smu->smu_buffer.mc_addr_low; ++ ++ uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte); ++ ++ mc_addr += cz_smu->smu_buffer_used_bytes; ++ ++ entry->data_size = ulsize_byte; ++ entry->kaddr = (char *) cz_smu->smu_buffer.kaddr + ++ cz_smu->smu_buffer_used_bytes; ++ entry->mc_addr_low = smu_lower_32_bits(mc_addr); ++ entry->mc_addr_high = smu_upper_32_bits(mc_addr); ++ entry->firmware_ID = scratch_type; ++ ++ cz_smu->smu_buffer_used_bytes += ulsize_aligned; ++ ++ return 0; ++} ++ ++static int cz_download_pptable_settings(struct pp_smumgr *smumgr, void **table) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ unsigned long i; ++ ++ for (i = 0; i < cz_smu->scratch_buffer_length; i++) { ++ if (cz_smu->scratch_buffer[i].firmware_ID ++ == CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) ++ break; ++ } ++ ++ *table = (struct SMU8_Fusion_ClkTable *)cz_smu->scratch_buffer[i].kaddr; ++ ++ cz_send_msg_to_smc_with_parameter(smumgr, ++ PPSMC_MSG_SetClkTableAddrHi, ++ cz_smu->scratch_buffer[i].mc_addr_high); ++ ++ cz_send_msg_to_smc_with_parameter(smumgr, ++ PPSMC_MSG_SetClkTableAddrLo, ++ cz_smu->scratch_buffer[i].mc_addr_low); ++ ++ cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, ++ cz_smu->toc_entry_clock_table); ++ ++ cz_send_msg_to_smc(smumgr, PPSMC_MSG_ClkTableXferToDram); ++ ++ return 0; ++} ++ ++static int cz_upload_pptable_settings(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ unsigned long i; ++ ++ for (i = 0; i < cz_smu->scratch_buffer_length; i++) { ++ if (cz_smu->scratch_buffer[i].firmware_ID ++ == CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) ++ break; ++ } ++ ++ cz_send_msg_to_smc_with_parameter(smumgr, ++ PPSMC_MSG_SetClkTableAddrHi, ++ cz_smu->scratch_buffer[i].mc_addr_high); ++ ++ cz_send_msg_to_smc_with_parameter(smumgr, ++ PPSMC_MSG_SetClkTableAddrLo, ++ cz_smu->scratch_buffer[i].mc_addr_low); ++ ++ cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, ++ cz_smu->toc_entry_clock_table); ++ ++ cz_send_msg_to_smc(smumgr, PPSMC_MSG_ClkTableXferToSmu); ++ ++ return 0; ++} ++ ++static int cz_smu_init(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; ++ uint64_t mc_addr = 0; ++ int ret = 0; ++ ++ cz_smu->toc_buffer.data_size = 4096; ++ cz_smu->smu_buffer.data_size = ++ ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) + ++ ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) + ++ ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) + ++ ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) + ++ ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32); ++ ++ ret = smu_allocate_memory(smumgr->device, ++ cz_smu->toc_buffer.data_size, ++ CGS_GPU_MEM_TYPE__GART_CACHEABLE, ++ PAGE_SIZE, ++ &mc_addr, ++ &cz_smu->toc_buffer.kaddr, ++ &cz_smu->toc_buffer.handle); ++ if (ret != 0) ++ return -1; ++ ++ cz_smu->toc_buffer.mc_addr_high = smu_upper_32_bits(mc_addr); ++ cz_smu->toc_buffer.mc_addr_low = smu_lower_32_bits(mc_addr); ++ ++ ret = smu_allocate_memory(smumgr->device, ++ cz_smu->smu_buffer.data_size, ++ CGS_GPU_MEM_TYPE__GART_CACHEABLE, ++ PAGE_SIZE, ++ &mc_addr, ++ &cz_smu->smu_buffer.kaddr, ++ &cz_smu->smu_buffer.handle); ++ if (ret != 0) ++ return -1; ++ ++ cz_smu->smu_buffer.mc_addr_high = smu_upper_32_bits(mc_addr); ++ cz_smu->smu_buffer.mc_addr_low = smu_lower_32_bits(mc_addr); ++ ++ cz_smu_populate_firmware_entries(smumgr); ++ if (0 != cz_smu_populate_single_scratch_entry(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, ++ UCODE_ID_RLC_SCRATCH_SIZE_BYTE, ++ &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { ++ printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); ++ return -1; ++ } ++ ++ if (0 != cz_smu_populate_single_scratch_entry(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, ++ UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, ++ &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { ++ printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); ++ return -1; ++ } ++ if (0 != cz_smu_populate_single_scratch_entry(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, ++ UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, ++ &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { ++ printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); ++ return -1; ++ } ++ ++ if (0 != cz_smu_populate_single_scratch_entry(smumgr, ++ CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, ++ sizeof(struct SMU8_MultimediaPowerLogData), ++ &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { ++ printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); ++ return -1; ++ } ++ ++ if (0 != cz_smu_populate_single_scratch_entry(smumgr, ++ CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, ++ sizeof(struct SMU8_Fusion_ClkTable), ++ &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { ++ printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); ++ return -1; ++ } ++ cz_smu_construct_toc(smumgr); ++ ++ return 0; ++} ++ ++static int cz_smu_fini(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu; ++ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ cz_smu = (struct cz_smumgr *)smumgr->backend; ++ if (!cz_smu) { ++ cgs_free_gpu_mem(smumgr->device, ++ cz_smu->toc_buffer.handle); ++ cgs_free_gpu_mem(smumgr->device, ++ cz_smu->smu_buffer.handle); ++ kfree(cz_smu); ++ kfree(smumgr); ++ } ++ ++ return 0; ++} ++ ++static const struct pp_smumgr_func cz_smu_funcs = { ++ .smu_init = cz_smu_init, ++ .smu_fini = cz_smu_fini, ++ .start_smu = cz_start_smu, ++ .check_fw_load_finish = cz_check_fw_load_finish, ++ .request_smu_load_fw = NULL, ++ .request_smu_load_specific_fw = NULL, ++ .get_argument = cz_smum_get_argument, ++ .send_msg_to_smc = cz_send_msg_to_smc, ++ .send_msg_to_smc_with_parameter = cz_send_msg_to_smc_with_parameter, ++ .download_pptable_settings = cz_download_pptable_settings, ++ .upload_pptable_settings = cz_upload_pptable_settings, ++}; ++ ++int cz_smum_init(struct pp_smumgr *smumgr) ++{ ++ struct cz_smumgr *cz_smu; ++ ++ cz_smu = kzalloc(sizeof(struct cz_smumgr), GFP_KERNEL); ++ if (cz_smu == NULL) ++ return -ENOMEM; ++ ++ smumgr->backend = cz_smu; ++ smumgr->smumgr_funcs = &cz_smu_funcs; ++ return 0; ++} +diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h +new file mode 100644 +index 0000000..8838180 +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h +@@ -0,0 +1,102 @@ ++/* ++ * Copyright 2015 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#ifndef _CZ_SMUMGR_H_ ++#define _CZ_SMUMGR_H_ ++ ++ ++#define MAX_NUM_FIRMWARE 8 ++#define MAX_NUM_SCRATCH 11 ++#define CZ_SCRATCH_SIZE_NONGFX_CLOCKGATING 1024 ++#define CZ_SCRATCH_SIZE_NONGFX_GOLDENSETTING 2048 ++#define CZ_SCRATCH_SIZE_SDMA_METADATA 1024 ++#define CZ_SCRATCH_SIZE_IH ((2*256+1)*4) ++ ++enum cz_scratch_entry { ++ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0 = 0, ++ CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, ++ CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, ++ CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, ++ CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, ++ CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM, ++ CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM, ++ CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, ++ CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT, ++ CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING, ++ CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS, ++ CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT, ++ CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START, ++ CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS, ++ CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE ++}; ++ ++struct cz_buffer_entry { ++ uint32_t data_size; ++ uint32_t mc_addr_low; ++ uint32_t mc_addr_high; ++ void *kaddr; ++ enum cz_scratch_entry firmware_ID; ++ unsigned long handle; /* as bo handle used when release bo */ ++}; ++ ++struct cz_register_index_data_pair { ++ uint32_t offset; ++ uint32_t value; ++}; ++ ++struct cz_ih_meta_data { ++ uint32_t command; ++ struct cz_register_index_data_pair register_index_value_pair[1]; ++}; ++ ++struct cz_smumgr { ++ uint8_t driver_buffer_length; ++ uint8_t scratch_buffer_length; ++ uint16_t toc_entry_used_count; ++ uint16_t toc_entry_initialize_index; ++ uint16_t toc_entry_power_profiling_index; ++ uint16_t toc_entry_aram; ++ uint16_t toc_entry_ih_register_restore_task_index; ++ uint16_t toc_entry_clock_table; ++ uint16_t ih_register_restore_task_size; ++ uint16_t smu_buffer_used_bytes; ++ ++ struct cz_buffer_entry toc_buffer; ++ struct cz_buffer_entry smu_buffer; ++ struct cz_buffer_entry firmware_buffer; ++ struct cz_buffer_entry driver_buffer[MAX_NUM_FIRMWARE]; ++ struct cz_buffer_entry meta_data_buffer[MAX_NUM_FIRMWARE]; ++ struct cz_buffer_entry scratch_buffer[MAX_NUM_SCRATCH]; ++}; ++ ++struct pp_smumgr; ++ ++extern int cz_smum_init(struct pp_smumgr *smumgr); ++ ++#endif +diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +index 1a11714..9ff5d33 100644 +--- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c ++++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +@@ -27,6 +27,7 @@ + #include "smumgr.h" + #include "cgs_common.h" + #include "linux/delay.h" ++#include "cz_smumgr.h" + + int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle) + { +@@ -49,7 +50,7 @@ int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle) + + switch (smumgr->chip_family) { + case AMD_FAMILY_CZ: +- /* TODO */ ++ cz_smum_init(smumgr); + break; + case AMD_FAMILY_VI: + /* TODO */ +-- +2.7.4 + |