From: Jammy Zhou Date: Wed, 22 Jul 2015 01:54:16 +0000 (+0800) Subject: drm/amd/powerplay: add Carrizo smu support X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=4630f0faae80;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git 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 Signed-off-by: Jammy Zhou Reviewed-by: Alex Deucher --- 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 273616ab43db..000000000000 --- 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 d758d07b6a31..000000000000 --- 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 5c9cc3c0bbfa..000000000000 --- 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 f8ba071f39c8..000000000000 --- 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 000000000000..273616ab43db --- /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 000000000000..d758d07b6a31 --- /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 000000000000..5c9cc3c0bbfa --- /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 000000000000..f8ba071f39c8 --- /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 61bfb2afd5c1..9219940a7a8f 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 000000000000..e74023bd4e0d --- /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 +#include +#include +#include +#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 000000000000..883818039248 --- /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 1a117140e475..9ff5d3381666 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 */