diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0373-drm-amdgpu-Add-Fiji-support-to-SMC-and-DPM-v2.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0373-drm-amdgpu-Add-Fiji-support-to-SMC-and-DPM-v2.patch | 1356 |
1 files changed, 0 insertions, 1356 deletions
diff --git a/common/recipes-kernel/linux/files/0373-drm-amdgpu-Add-Fiji-support-to-SMC-and-DPM-v2.patch b/common/recipes-kernel/linux/files/0373-drm-amdgpu-Add-Fiji-support-to-SMC-and-DPM-v2.patch deleted file mode 100644 index 8c7e1a1e..00000000 --- a/common/recipes-kernel/linux/files/0373-drm-amdgpu-Add-Fiji-support-to-SMC-and-DPM-v2.patch +++ /dev/null @@ -1,1356 +0,0 @@ -From 8e711e1a1ad3a95883ae15deead593d22e57c3f1 Mon Sep 17 00:00:00 2001 -From: David Zhang <david1.zhang@amd.com> -Date: Wed, 8 Jul 2015 01:23:25 +0800 -Subject: [PATCH 0373/1050] drm/amdgpu: Add Fiji support to SMC and DPM (v2) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -v2: agd5f: prepare for release - -Signed-off-by: David Zhang <david1.zhang@amd.com> -Reviewed-by: Alex Deucher <alexander.deucher@amd.com> -Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com> -Reviewed-by: Christian König <christian.koenig@amd.com> ---- - drivers/gpu/drm/amd/amdgpu/Makefile | 1 + - drivers/gpu/drm/amd/amdgpu/fiji_dpm.c | 181 +++++++ - drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h | 182 +++++++ - drivers/gpu/drm/amd/amdgpu/fiji_smc.c | 853 +++++++++++++++++++++++++++++++ - drivers/gpu/drm/amd/amdgpu/fiji_smumgr.h | 42 ++ - drivers/gpu/drm/amd/amdgpu/vi.c | 7 + - drivers/gpu/drm/amd/amdgpu/vi_dpm.h | 2 +- - 7 files changed, 1267 insertions(+), 1 deletion(-) - create mode 100644 drivers/gpu/drm/amd/amdgpu/fiji_dpm.c - create mode 100644 drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h - create mode 100644 drivers/gpu/drm/amd/amdgpu/fiji_smc.c - create mode 100644 drivers/gpu/drm/amd/amdgpu/fiji_smumgr.h - -diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile -index 4e1c07d..4c75e1c 100644 ---- a/drivers/gpu/drm/amd/amdgpu/Makefile -+++ b/drivers/gpu/drm/amd/amdgpu/Makefile -@@ -45,6 +45,7 @@ amdgpu-y += \ - amdgpu_dpm.o \ - cz_smc.o cz_dpm.o \ - tonga_smc.o tonga_dpm.o \ -+ fiji_smc.o fiji_dpm.o \ - iceland_smc.o iceland_dpm.o - - # add DCE block -diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c b/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c -new file mode 100644 -index 0000000..8f9845d ---- /dev/null -+++ b/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c -@@ -0,0 +1,181 @@ -+/* -+ * 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. -+ * -+ */ -+ -+#include <linux/firmware.h> -+#include "drmP.h" -+#include "amdgpu.h" -+#include "fiji_smumgr.h" -+ -+MODULE_FIRMWARE("amdgpu/fiji_smc.bin"); -+ -+static void fiji_dpm_set_funcs(struct amdgpu_device *adev); -+ -+static int fiji_dpm_early_init(void *handle) -+{ -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ -+ fiji_dpm_set_funcs(adev); -+ -+ return 0; -+} -+ -+static int fiji_dpm_init_microcode(struct amdgpu_device *adev) -+{ -+ char fw_name[30] = "amdgpu/fiji_smc.bin"; -+ int err; -+ -+ err = request_firmware(&adev->pm.fw, fw_name, adev->dev); -+ if (err) -+ goto out; -+ err = amdgpu_ucode_validate(adev->pm.fw); -+ -+out: -+ if (err) { -+ DRM_ERROR("Failed to load firmware \"%s\"", fw_name); -+ release_firmware(adev->pm.fw); -+ adev->pm.fw = NULL; -+ } -+ return err; -+} -+ -+static int fiji_dpm_sw_init(void *handle) -+{ -+ int ret; -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ -+ ret = fiji_dpm_init_microcode(adev); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int fiji_dpm_sw_fini(void *handle) -+{ -+ return 0; -+} -+ -+static int fiji_dpm_hw_init(void *handle) -+{ -+ int ret; -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ -+ mutex_lock(&adev->pm.mutex); -+ -+ ret = fiji_smu_init(adev); -+ if (ret) { -+ DRM_ERROR("SMU initialization failed\n"); -+ goto fail; -+ } -+ -+ ret = fiji_smu_start(adev); -+ if (ret) { -+ DRM_ERROR("SMU start failed\n"); -+ goto fail; -+ } -+ -+ mutex_unlock(&adev->pm.mutex); -+ return 0; -+ -+fail: -+ adev->firmware.smu_load = false; -+ mutex_unlock(&adev->pm.mutex); -+ return -EINVAL; -+} -+ -+static int fiji_dpm_hw_fini(void *handle) -+{ -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ mutex_lock(&adev->pm.mutex); -+ fiji_smu_fini(adev); -+ mutex_unlock(&adev->pm.mutex); -+ return 0; -+} -+ -+static int fiji_dpm_suspend(void *handle) -+{ -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ -+ fiji_dpm_hw_fini(adev); -+ -+ return 0; -+} -+ -+static int fiji_dpm_resume(void *handle) -+{ -+ struct amdgpu_device *adev = (struct amdgpu_device *)handle; -+ -+ fiji_dpm_hw_init(adev); -+ -+ return 0; -+} -+ -+static int fiji_dpm_set_clockgating_state(void *handle, -+ enum amd_clockgating_state state) -+{ -+ return 0; -+} -+ -+static int fiji_dpm_set_powergating_state(void *handle, -+ enum amd_powergating_state state) -+{ -+ return 0; -+} -+ -+const struct amd_ip_funcs fiji_dpm_ip_funcs = { -+ .early_init = fiji_dpm_early_init, -+ .late_init = NULL, -+ .sw_init = fiji_dpm_sw_init, -+ .sw_fini = fiji_dpm_sw_fini, -+ .hw_init = fiji_dpm_hw_init, -+ .hw_fini = fiji_dpm_hw_fini, -+ .suspend = fiji_dpm_suspend, -+ .resume = fiji_dpm_resume, -+ .is_idle = NULL, -+ .wait_for_idle = NULL, -+ .soft_reset = NULL, -+ .print_status = NULL, -+ .set_clockgating_state = fiji_dpm_set_clockgating_state, -+ .set_powergating_state = fiji_dpm_set_powergating_state, -+}; -+ -+static const struct amdgpu_dpm_funcs fiji_dpm_funcs = { -+ .get_temperature = NULL, -+ .pre_set_power_state = NULL, -+ .set_power_state = NULL, -+ .post_set_power_state = NULL, -+ .display_configuration_changed = NULL, -+ .get_sclk = NULL, -+ .get_mclk = NULL, -+ .print_power_state = NULL, -+ .debugfs_print_current_performance_level = NULL, -+ .force_performance_level = NULL, -+ .vblank_too_short = NULL, -+ .powergate_uvd = NULL, -+}; -+ -+static void fiji_dpm_set_funcs(struct amdgpu_device *adev) -+{ -+ if (NULL == adev->pm.funcs) -+ adev->pm.funcs = &fiji_dpm_funcs; -+} -diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h b/drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h -new file mode 100644 -index 0000000..3c48240 ---- /dev/null -+++ b/drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h -@@ -0,0 +1,182 @@ -+/* -+ * 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 FIJI_PP_SMC_H -+#define FIJI_PP_SMC_H -+ -+#pragma pack(push, 1) -+ -+#define PPSMC_SWSTATE_FLAG_DC 0x01 -+#define PPSMC_SWSTATE_FLAG_UVD 0x02 -+#define PPSMC_SWSTATE_FLAG_VCE 0x04 -+ -+#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 -+#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 -+#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff -+ -+#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 -+#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 -+#define PPSMC_SYSTEMFLAG_GDDR5 0x04 -+ -+#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 -+ -+#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 -+#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 -+ -+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 -+#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 -+ -+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 -+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 -+ -+#define PPSMC_DPM2FLAGS_TDPCLMP 0x01 -+#define PPSMC_DPM2FLAGS_PWRSHFT 0x02 -+#define PPSMC_DPM2FLAGS_OCP 0x04 -+ -+#define PPSMC_DISPLAY_WATERMARK_LOW 0 -+#define PPSMC_DISPLAY_WATERMARK_HIGH 1 -+ -+#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 -+#define PPSMC_STATEFLAG_POWERBOOST 0x02 -+#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04 -+#define PPSMC_STATEFLAG_POWERSHIFT 0x08 -+#define PPSMC_STATEFLAG_SLOW_READ_MARGIN 0x10 -+#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 -+#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 -+ -+#define FDO_MODE_HARDWARE 0 -+#define FDO_MODE_PIECE_WISE_LINEAR 1 -+ -+enum FAN_CONTROL { -+ FAN_CONTROL_FUZZY, -+ FAN_CONTROL_TABLE -+}; -+ -+//Gemini Modes -+#define PPSMC_GeminiModeNone 0 //Single GPU board -+#define PPSMC_GeminiModeMaster 1 //Master GPU on a Gemini board -+#define PPSMC_GeminiModeSlave 2 //Slave GPU on a Gemini board -+ -+#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) -+ -+typedef uint16_t PPSMC_Result; -+ -+#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) -+ -+#define PPSMC_MSG_Halt ((uint16_t)0x10) -+#define PPSMC_MSG_Resume ((uint16_t)0x11) -+#define PPSMC_MSG_EnableDPMLevel ((uint16_t)0x12) -+#define PPSMC_MSG_ZeroLevelsDisabled ((uint16_t)0x13) -+#define PPSMC_MSG_OneLevelsDisabled ((uint16_t)0x14) -+#define PPSMC_MSG_TwoLevelsDisabled ((uint16_t)0x15) -+#define PPSMC_MSG_EnableThermalInterrupt ((uint16_t)0x16) -+#define PPSMC_MSG_RunningOnAC ((uint16_t)0x17) -+#define PPSMC_MSG_LevelUp ((uint16_t)0x18) -+#define PPSMC_MSG_LevelDown ((uint16_t)0x19) -+#define PPSMC_MSG_ResetDPMCounters ((uint16_t)0x1a) -+#define PPSMC_MSG_SwitchToSwState ((uint16_t)0x20) -+#define PPSMC_MSG_SwitchToSwStateLast ((uint16_t)0x3f) -+#define PPSMC_MSG_SwitchToInitialState ((uint16_t)0x40) -+#define PPSMC_MSG_NoForcedLevel ((uint16_t)0x41) -+#define PPSMC_MSG_ForceHigh ((uint16_t)0x42) -+#define PPSMC_MSG_ForceMediumOrHigh ((uint16_t)0x43) -+#define PPSMC_MSG_SwitchToMinimumPower ((uint16_t)0x51) -+#define PPSMC_MSG_ResumeFromMinimumPower ((uint16_t)0x52) -+#define PPSMC_MSG_EnableCac ((uint16_t)0x53) -+#define PPSMC_MSG_DisableCac ((uint16_t)0x54) -+#define PPSMC_DPMStateHistoryStart ((uint16_t)0x55) -+#define PPSMC_DPMStateHistoryStop ((uint16_t)0x56) -+#define PPSMC_CACHistoryStart ((uint16_t)0x57) -+#define PPSMC_CACHistoryStop ((uint16_t)0x58) -+#define PPSMC_TDPClampingActive ((uint16_t)0x59) -+#define PPSMC_TDPClampingInactive ((uint16_t)0x5A) -+#define PPSMC_StartFanControl ((uint16_t)0x5B) -+#define PPSMC_StopFanControl ((uint16_t)0x5C) -+#define PPSMC_NoDisplay ((uint16_t)0x5D) -+#define PPSMC_HasDisplay ((uint16_t)0x5E) -+#define PPSMC_MSG_UVDPowerOFF ((uint16_t)0x60) -+#define PPSMC_MSG_UVDPowerON ((uint16_t)0x61) -+#define PPSMC_MSG_EnableULV ((uint16_t)0x62) -+#define PPSMC_MSG_DisableULV ((uint16_t)0x63) -+#define PPSMC_MSG_EnterULV ((uint16_t)0x64) -+#define PPSMC_MSG_ExitULV ((uint16_t)0x65) -+#define PPSMC_PowerShiftActive ((uint16_t)0x6A) -+#define PPSMC_PowerShiftInactive ((uint16_t)0x6B) -+#define PPSMC_OCPActive ((uint16_t)0x6C) -+#define PPSMC_OCPInactive ((uint16_t)0x6D) -+#define PPSMC_CACLongTermAvgEnable ((uint16_t)0x6E) -+#define PPSMC_CACLongTermAvgDisable ((uint16_t)0x6F) -+#define PPSMC_MSG_InferredStateSweep_Start ((uint16_t)0x70) -+#define PPSMC_MSG_InferredStateSweep_Stop ((uint16_t)0x71) -+#define PPSMC_MSG_SwitchToLowestInfState ((uint16_t)0x72) -+#define PPSMC_MSG_SwitchToNonInfState ((uint16_t)0x73) -+#define PPSMC_MSG_AllStateSweep_Start ((uint16_t)0x74) -+#define PPSMC_MSG_AllStateSweep_Stop ((uint16_t)0x75) -+#define PPSMC_MSG_SwitchNextLowerInfState ((uint16_t)0x76) -+#define PPSMC_MSG_SwitchNextHigherInfState ((uint16_t)0x77) -+#define PPSMC_MSG_MclkRetrainingTest ((uint16_t)0x78) -+#define PPSMC_MSG_ForceTDPClamping ((uint16_t)0x79) -+#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint16_t)0x7A) -+#define PPSMC_MSG_CollectCAC_WeightCalib ((uint16_t)0x7B) -+#define PPSMC_MSG_CollectCAC_SQonly ((uint16_t)0x7C) -+#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D) -+#define PPSMC_MSG_ExtremitiesTest_Start ((uint16_t)0x7E) -+#define PPSMC_MSG_ExtremitiesTest_Stop ((uint16_t)0x7F) -+#define PPSMC_FlushDataCache ((uint16_t)0x80) -+#define PPSMC_FlushInstrCache ((uint16_t)0x81) -+#define PPSMC_MSG_SetEnabledLevels ((uint16_t)0x82) -+#define PPSMC_MSG_SetForcedLevels ((uint16_t)0x83) -+#define PPSMC_MSG_ResetToDefaults ((uint16_t)0x84) -+#define PPSMC_MSG_SetForcedLevelsAndJump ((uint16_t)0x85) -+#define PPSMC_MSG_SetCACHistoryMode ((uint16_t)0x86) -+#define PPSMC_MSG_EnableDTE ((uint16_t)0x87) -+#define PPSMC_MSG_DisableDTE ((uint16_t)0x88) -+#define PPSMC_MSG_SmcSpaceSetAddress ((uint16_t)0x89) -+#define PPSMC_MSG_SmcSpaceWriteDWordInc ((uint16_t)0x8A) -+#define PPSMC_MSG_SmcSpaceWriteWordInc ((uint16_t)0x8B) -+#define PPSMC_MSG_SmcSpaceWriteByteInc ((uint16_t)0x8C) -+ -+#define PPSMC_MSG_BREAK ((uint16_t)0xF8) -+ -+#define PPSMC_MSG_Test ((uint16_t)0x100) -+#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t)0x250) -+#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t)0x251) -+#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t)0x252) -+#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t)0x253) -+#define PPSMC_MSG_LoadUcodes ((uint16_t)0x254) -+ -+typedef uint16_t PPSMC_Msg; -+ -+#define PPSMC_EVENT_STATUS_THERMAL 0x00000001 -+#define PPSMC_EVENT_STATUS_REGULATORHOT 0x00000002 -+#define PPSMC_EVENT_STATUS_DC 0x00000004 -+#define PPSMC_EVENT_STATUS_GPIO17 0x00000008 -+ -+#pragma pack(pop) -+ -+#endif -diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_smc.c b/drivers/gpu/drm/amd/amdgpu/fiji_smc.c -new file mode 100644 -index 0000000..493c8c9 ---- /dev/null -+++ b/drivers/gpu/drm/amd/amdgpu/fiji_smc.c -@@ -0,0 +1,853 @@ -+/* -+ * 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. -+ * -+ */ -+ -+#include <linux/firmware.h> -+#include "drmP.h" -+#include "amdgpu.h" -+#include "fiji_ppsmc.h" -+#include "fiji_smumgr.h" -+#include "smu_ucode_xfer_vi.h" -+#include "amdgpu_ucode.h" -+ -+#include "smu/smu_7_1_3_d.h" -+#include "smu/smu_7_1_3_sh_mask.h" -+ -+#define FIJI_SMC_SIZE 0x20000 -+ -+static int fiji_set_smc_sram_address(struct amdgpu_device *adev, uint32_t smc_address, uint32_t limit) -+{ -+ uint32_t val; -+ -+ if (smc_address & 3) -+ return -EINVAL; -+ -+ if ((smc_address + 3) > limit) -+ return -EINVAL; -+ -+ WREG32(mmSMC_IND_INDEX_0, smc_address); -+ -+ val = RREG32(mmSMC_IND_ACCESS_CNTL); -+ val = REG_SET_FIELD(val, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); -+ WREG32(mmSMC_IND_ACCESS_CNTL, val); -+ -+ return 0; -+} -+ -+static int fiji_copy_bytes_to_smc(struct amdgpu_device *adev, uint32_t smc_start_address, const uint8_t *src, uint32_t byte_count, uint32_t limit) -+{ -+ uint32_t addr; -+ uint32_t data, orig_data; -+ int result = 0; -+ uint32_t extra_shift; -+ unsigned long flags; -+ -+ if (smc_start_address & 3) -+ return -EINVAL; -+ -+ if ((smc_start_address + byte_count) > limit) -+ return -EINVAL; -+ -+ addr = smc_start_address; -+ -+ spin_lock_irqsave(&adev->smc_idx_lock, flags); -+ while (byte_count >= 4) { -+ /* Bytes are written into the SMC addres space with the MSB first */ -+ data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3]; -+ -+ result = fiji_set_smc_sram_address(adev, addr, limit); -+ -+ if (result) -+ goto out; -+ -+ WREG32(mmSMC_IND_DATA_0, data); -+ -+ src += 4; -+ byte_count -= 4; -+ addr += 4; -+ } -+ -+ if (0 != byte_count) { -+ /* Now write odd bytes left, do a read modify write cycle */ -+ data = 0; -+ -+ result = fiji_set_smc_sram_address(adev, addr, limit); -+ if (result) -+ goto out; -+ -+ orig_data = RREG32(mmSMC_IND_DATA_0); -+ extra_shift = 8 * (4 - byte_count); -+ -+ while (byte_count > 0) { -+ data = (data << 8) + *src++; -+ byte_count--; -+ } -+ -+ data <<= extra_shift; -+ data |= (orig_data & ~((~0UL) << extra_shift)); -+ -+ result = fiji_set_smc_sram_address(adev, addr, limit); -+ if (result) -+ goto out; -+ -+ WREG32(mmSMC_IND_DATA_0, data); -+ } -+ -+out: -+ spin_unlock_irqrestore(&adev->smc_idx_lock, flags); -+ return result; -+} -+ -+static int fiji_program_jump_on_start(struct amdgpu_device *adev) -+{ -+ static unsigned char data[] = {0xE0, 0x00, 0x80, 0x40}; -+ fiji_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1); -+ -+ return 0; -+} -+ -+static bool fiji_is_smc_ram_running(struct amdgpu_device *adev) -+{ -+ uint32_t val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0); -+ val = REG_GET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, ck_disable); -+ -+ return ((0 == val) && (0x20100 <= RREG32_SMC(ixSMC_PC_C))); -+} -+ -+static int wait_smu_response(struct amdgpu_device *adev) -+{ -+ int i; -+ uint32_t val; -+ -+ for (i = 0; i < adev->usec_timeout; i++) { -+ val = RREG32(mmSMC_RESP_0); -+ if (REG_GET_FIELD(val, SMC_RESP_0, SMC_RESP)) -+ break; -+ udelay(1); -+ } -+ -+ if (i == adev->usec_timeout) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int fiji_send_msg_to_smc_offset(struct amdgpu_device *adev) -+{ -+ if (wait_smu_response(adev)) { -+ DRM_ERROR("Failed to send previous message\n"); -+ return -EINVAL; -+ } -+ -+ WREG32(mmSMC_MSG_ARG_0, 0x20000); -+ WREG32(mmSMC_MESSAGE_0, PPSMC_MSG_Test); -+ -+ if (wait_smu_response(adev)) { -+ DRM_ERROR("Failed to send message\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int fiji_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg) -+{ -+ if (!fiji_is_smc_ram_running(adev)) -+ { -+ return -EINVAL;; -+ } -+ -+ if (wait_smu_response(adev)) { -+ DRM_ERROR("Failed to send previous message\n"); -+ return -EINVAL; -+ } -+ -+ WREG32(mmSMC_MESSAGE_0, msg); -+ -+ if (wait_smu_response(adev)) { -+ DRM_ERROR("Failed to send message\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int fiji_send_msg_to_smc_without_waiting(struct amdgpu_device *adev, -+ PPSMC_Msg msg) -+{ -+ if (wait_smu_response(adev)) { -+ DRM_ERROR("Failed to send previous message\n"); -+ return -EINVAL; -+ } -+ -+ WREG32(mmSMC_MESSAGE_0, msg); -+ -+ return 0; -+} -+ -+static int fiji_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, -+ PPSMC_Msg msg, -+ uint32_t parameter) -+{ -+ if (!fiji_is_smc_ram_running(adev)) -+ return -EINVAL; -+ -+ if (wait_smu_response(adev)) { -+ DRM_ERROR("Failed to send previous message\n"); -+ return -EINVAL; -+ } -+ -+ WREG32(mmSMC_MSG_ARG_0, parameter); -+ -+ return fiji_send_msg_to_smc(adev, msg); -+} -+ -+static int fiji_send_msg_to_smc_with_parameter_without_waiting( -+ struct amdgpu_device *adev, -+ PPSMC_Msg msg, uint32_t parameter) -+{ -+ if (wait_smu_response(adev)) { -+ DRM_ERROR("Failed to send previous message\n"); -+ return -EINVAL; -+ } -+ -+ WREG32(mmSMC_MSG_ARG_0, parameter); -+ -+ return fiji_send_msg_to_smc_without_waiting(adev, msg); -+} -+ -+#if 0 /* not used yet */ -+static int fiji_wait_for_smc_inactive(struct amdgpu_device *adev) -+{ -+ int i; -+ uint32_t val; -+ -+ if (!fiji_is_smc_ram_running(adev)) -+ return -EINVAL; -+ -+ for (i = 0; i < adev->usec_timeout; i++) { -+ val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0); -+ if (REG_GET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, cken) == 0) -+ break; -+ udelay(1); -+ } -+ -+ if (i == adev->usec_timeout) -+ return -EINVAL; -+ -+ return 0; -+} -+#endif -+ -+static int fiji_smu_upload_firmware_image(struct amdgpu_device *adev) -+{ -+ const struct smc_firmware_header_v1_0 *hdr; -+ uint32_t ucode_size; -+ uint32_t ucode_start_address; -+ const uint8_t *src; -+ uint32_t val; -+ uint32_t byte_count; -+ uint32_t *data; -+ unsigned long flags; -+ -+ if (!adev->pm.fw) -+ return -EINVAL; -+ -+ hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data; -+ amdgpu_ucode_print_smc_hdr(&hdr->header); -+ -+ adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version); -+ ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes); -+ ucode_start_address = le32_to_cpu(hdr->ucode_start_addr); -+ src = (const uint8_t *) -+ (adev->pm.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); -+ -+ if (ucode_size & 3) { -+ DRM_ERROR("SMC ucode is not 4 bytes aligned\n"); -+ return -EINVAL; -+ } -+ -+ if (ucode_size > FIJI_SMC_SIZE) { -+ DRM_ERROR("SMC address is beyond the SMC RAM area\n"); -+ return -EINVAL; -+ } -+ -+ spin_lock_irqsave(&adev->smc_idx_lock, flags); -+ WREG32(mmSMC_IND_INDEX_0, ucode_start_address); -+ -+ val = RREG32(mmSMC_IND_ACCESS_CNTL); -+ val = REG_SET_FIELD(val, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); -+ WREG32(mmSMC_IND_ACCESS_CNTL, val); -+ -+ byte_count = ucode_size; -+ data = (uint32_t *)src; -+ for (; byte_count >= 4; data++, byte_count -= 4) -+ WREG32(mmSMC_IND_DATA_0, data[0]); -+ -+ val = RREG32(mmSMC_IND_ACCESS_CNTL); -+ val = REG_SET_FIELD(val, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); -+ WREG32(mmSMC_IND_ACCESS_CNTL, val); -+ spin_unlock_irqrestore(&adev->smc_idx_lock, flags); -+ -+ return 0; -+} -+ -+#if 0 /* not used yet */ -+static int fiji_read_smc_sram_dword(struct amdgpu_device *adev, -+ uint32_t smc_address, -+ uint32_t *value, -+ uint32_t limit) -+{ -+ int result; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&adev->smc_idx_lock, flags); -+ result = fiji_set_smc_sram_address(adev, smc_address, limit); -+ if (result == 0) -+ *value = RREG32(mmSMC_IND_DATA_0); -+ spin_unlock_irqrestore(&adev->smc_idx_lock, flags); -+ return result; -+} -+ -+static int fiji_write_smc_sram_dword(struct amdgpu_device *adev, -+ uint32_t smc_address, -+ uint32_t value, -+ uint32_t limit) -+{ -+ int result; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&adev->smc_idx_lock, flags); -+ result = fiji_set_smc_sram_address(adev, smc_address, limit); -+ if (result == 0) -+ WREG32(mmSMC_IND_DATA_0, value); -+ spin_unlock_irqrestore(&adev->smc_idx_lock, flags); -+ return result; -+} -+ -+static int fiji_smu_stop_smc(struct amdgpu_device *adev) -+{ -+ uint32_t val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL); -+ val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 1); -+ WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val); -+ -+ val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0); -+ val = REG_SET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 1); -+ WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, val); -+ -+ return 0; -+} -+#endif -+ -+static enum AMDGPU_UCODE_ID fiji_convert_fw_type(uint32_t fw_type) -+{ -+ switch (fw_type) { -+ case UCODE_ID_SDMA0: -+ return AMDGPU_UCODE_ID_SDMA0; -+ case UCODE_ID_SDMA1: -+ return AMDGPU_UCODE_ID_SDMA1; -+ case UCODE_ID_CP_CE: -+ return AMDGPU_UCODE_ID_CP_CE; -+ case UCODE_ID_CP_PFP: -+ return AMDGPU_UCODE_ID_CP_PFP; -+ case UCODE_ID_CP_ME: -+ return AMDGPU_UCODE_ID_CP_ME; -+ case UCODE_ID_CP_MEC: -+ case UCODE_ID_CP_MEC_JT1: -+ case UCODE_ID_CP_MEC_JT2: -+ return AMDGPU_UCODE_ID_CP_MEC1; -+ case UCODE_ID_RLC_G: -+ return AMDGPU_UCODE_ID_RLC_G; -+ default: -+ DRM_ERROR("ucode type is out of range!\n"); -+ return AMDGPU_UCODE_ID_MAXIMUM; -+ } -+} -+ -+static int fiji_smu_populate_single_firmware_entry(struct amdgpu_device *adev, -+ uint32_t fw_type, -+ struct SMU_Entry *entry) -+{ -+ enum AMDGPU_UCODE_ID id = fiji_convert_fw_type(fw_type); -+ struct amdgpu_firmware_info *ucode = &adev->firmware.ucode[id]; -+ const struct gfx_firmware_header_v1_0 *header = NULL; -+ uint64_t gpu_addr; -+ uint32_t data_size; -+ -+ if (ucode->fw == NULL) -+ return -EINVAL; -+ gpu_addr = ucode->mc_addr; -+ header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data; -+ data_size = le32_to_cpu(header->header.ucode_size_bytes); -+ -+ if ((fw_type == UCODE_ID_CP_MEC_JT1) || -+ (fw_type == UCODE_ID_CP_MEC_JT2)) { -+ gpu_addr += le32_to_cpu(header->jt_offset) << 2; -+ data_size = le32_to_cpu(header->jt_size) << 2; -+ } -+ -+ entry->version = (uint16_t)le32_to_cpu(header->header.ucode_version); -+ entry->id = (uint16_t)fw_type; -+ entry->image_addr_high = upper_32_bits(gpu_addr); -+ entry->image_addr_low = lower_32_bits(gpu_addr); -+ entry->meta_data_addr_high = 0; -+ entry->meta_data_addr_low = 0; -+ entry->data_size_byte = data_size; -+ entry->num_register_entries = 0; -+ -+ if (fw_type == UCODE_ID_RLC_G) -+ entry->flags = 1; -+ else -+ entry->flags = 0; -+ -+ return 0; -+} -+ -+static int fiji_smu_request_load_fw(struct amdgpu_device *adev) -+{ -+ struct fiji_smu_private_data *private = (struct fiji_smu_private_data *)adev->smu.priv; -+ struct SMU_DRAMData_TOC *toc; -+ uint32_t fw_to_load; -+ -+ WREG32_SMC(ixSOFT_REGISTERS_TABLE_28, 0); -+ -+ fiji_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SMU_DRAM_ADDR_HI, private->smu_buffer_addr_high); -+ fiji_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SMU_DRAM_ADDR_LO, private->smu_buffer_addr_low); -+ -+ toc = (struct SMU_DRAMData_TOC *)private->header; -+ toc->num_entries = 0; -+ toc->structure_version = 1; -+ -+ if (!adev->firmware.smu_load) -+ return 0; -+ -+ if (fiji_smu_populate_single_firmware_entry(adev, UCODE_ID_RLC_G, -+ &toc->entry[toc->num_entries++])) { -+ DRM_ERROR("Failed to get firmware entry for RLC\n"); -+ return -EINVAL; -+ } -+ -+ if (fiji_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_CE, -+ &toc->entry[toc->num_entries++])) { -+ DRM_ERROR("Failed to get firmware entry for CE\n"); -+ return -EINVAL; -+ } -+ -+ if (fiji_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_PFP, -+ &toc->entry[toc->num_entries++])) { -+ DRM_ERROR("Failed to get firmware entry for PFP\n"); -+ return -EINVAL; -+ } -+ -+ if (fiji_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_ME, -+ &toc->entry[toc->num_entries++])) { -+ DRM_ERROR("Failed to get firmware entry for ME\n"); -+ return -EINVAL; -+ } -+ -+ if (fiji_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC, -+ &toc->entry[toc->num_entries++])) { -+ DRM_ERROR("Failed to get firmware entry for MEC\n"); -+ return -EINVAL; -+ } -+ -+ if (fiji_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC_JT1, -+ &toc->entry[toc->num_entries++])) { -+ DRM_ERROR("Failed to get firmware entry for MEC_JT1\n"); -+ return -EINVAL; -+ } -+ -+ if (fiji_smu_populate_single_firmware_entry(adev, UCODE_ID_CP_MEC_JT2, -+ &toc->entry[toc->num_entries++])) { -+ DRM_ERROR("Failed to get firmware entry for MEC_JT2\n"); -+ return -EINVAL; -+ } -+ -+ if (fiji_smu_populate_single_firmware_entry(adev, UCODE_ID_SDMA0, -+ &toc->entry[toc->num_entries++])) { -+ DRM_ERROR("Failed to get firmware entry for SDMA0\n"); -+ return -EINVAL; -+ } -+ -+ if (fiji_smu_populate_single_firmware_entry(adev, UCODE_ID_SDMA1, -+ &toc->entry[toc->num_entries++])) { -+ DRM_ERROR("Failed to get firmware entry for SDMA1\n"); -+ return -EINVAL; -+ } -+ -+ fiji_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_DRV_DRAM_ADDR_HI, private->header_addr_high); -+ fiji_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_DRV_DRAM_ADDR_LO, private->header_addr_low); -+ -+ fw_to_load = 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_MASK; -+ -+ if (fiji_send_msg_to_smc_with_parameter_without_waiting(adev, PPSMC_MSG_LoadUcodes, fw_to_load)) { -+ DRM_ERROR("Fail to request SMU load ucode\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static uint32_t fiji_smu_get_mask_for_fw_type(uint32_t fw_type) -+{ -+ switch (fw_type) { -+ case AMDGPU_UCODE_ID_SDMA0: -+ return UCODE_ID_SDMA0_MASK; -+ case AMDGPU_UCODE_ID_SDMA1: -+ return UCODE_ID_SDMA1_MASK; -+ case AMDGPU_UCODE_ID_CP_CE: -+ return UCODE_ID_CP_CE_MASK; -+ case AMDGPU_UCODE_ID_CP_PFP: -+ return UCODE_ID_CP_PFP_MASK; -+ case AMDGPU_UCODE_ID_CP_ME: -+ return UCODE_ID_CP_ME_MASK; -+ case AMDGPU_UCODE_ID_CP_MEC1: -+ return UCODE_ID_CP_MEC_MASK; -+ case AMDGPU_UCODE_ID_CP_MEC2: -+ return UCODE_ID_CP_MEC_MASK; -+ case AMDGPU_UCODE_ID_RLC_G: -+ return UCODE_ID_RLC_G_MASK; -+ default: -+ DRM_ERROR("ucode type is out of range!\n"); -+ return 0; -+ } -+} -+ -+static int fiji_smu_check_fw_load_finish(struct amdgpu_device *adev, -+ uint32_t fw_type) -+{ -+ uint32_t fw_mask = fiji_smu_get_mask_for_fw_type(fw_type); -+ int i; -+ -+ for (i = 0; i < adev->usec_timeout; i++) { -+ if (fw_mask == (RREG32_SMC(ixSOFT_REGISTERS_TABLE_28) & fw_mask)) -+ break; -+ udelay(1); -+ } -+ -+ if (i == adev->usec_timeout) { -+ DRM_ERROR("check firmware loading failed\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int fiji_smu_start_in_protection_mode(struct amdgpu_device *adev) -+{ -+ int result; -+ uint32_t val; -+ int i; -+ -+ /* Assert reset */ -+ val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL); -+ val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 1); -+ WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val); -+ -+ result = fiji_smu_upload_firmware_image(adev); -+ if (result) -+ return result; -+ -+ /* Clear status */ -+ WREG32_SMC(ixSMU_STATUS, 0); -+ -+ /* Enable clock */ -+ val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0); -+ val = REG_SET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); -+ WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, val); -+ -+ /* De-assert reset */ -+ val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL); -+ val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 0); -+ WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val); -+ -+ /* Set SMU Auto Start */ -+ val = RREG32_SMC(ixSMU_INPUT_DATA); -+ val = REG_SET_FIELD(val, SMU_INPUT_DATA, AUTO_START, 1); -+ WREG32_SMC(ixSMU_INPUT_DATA, val); -+ -+ /* Clear firmware interrupt enable flag */ -+ WREG32_SMC(ixFIRMWARE_FLAGS, 0); -+ -+ for (i = 0; i < adev->usec_timeout; i++) { -+ val = RREG32_SMC(ixRCU_UC_EVENTS); -+ if (REG_GET_FIELD(val, RCU_UC_EVENTS, INTERRUPTS_ENABLED)) -+ break; -+ udelay(1); -+ } -+ -+ if (i == adev->usec_timeout) { -+ DRM_ERROR("Interrupt is not enabled by firmware\n"); -+ return -EINVAL; -+ } -+ -+ /* Call Test SMU message with 0x20000 offset -+ * to trigger SMU start -+ */ -+ fiji_send_msg_to_smc_offset(adev); -+ DRM_INFO("[FM]try triger smu start\n"); -+ /* Wait for done bit to be set */ -+ for (i = 0; i < adev->usec_timeout; i++) { -+ val = RREG32_SMC(ixSMU_STATUS); -+ if (REG_GET_FIELD(val, SMU_STATUS, SMU_DONE)) -+ break; -+ udelay(1); -+ } -+ -+ if (i == adev->usec_timeout) { -+ DRM_ERROR("Timeout for SMU start\n"); -+ return -EINVAL; -+ } -+ -+ /* Check pass/failed indicator */ -+ val = RREG32_SMC(ixSMU_STATUS); -+ if (!REG_GET_FIELD(val, SMU_STATUS, SMU_PASS)) { -+ DRM_ERROR("SMU Firmware start failed\n"); -+ return -EINVAL; -+ } -+ DRM_INFO("[FM]smu started\n"); -+ /* Wait for firmware to initialize */ -+ for (i = 0; i < adev->usec_timeout; i++) { -+ val = RREG32_SMC(ixFIRMWARE_FLAGS); -+ if(REG_GET_FIELD(val, FIRMWARE_FLAGS, INTERRUPTS_ENABLED)) -+ break; -+ udelay(1); -+ } -+ -+ if (i == adev->usec_timeout) { -+ DRM_ERROR("SMU firmware initialization failed\n"); -+ return -EINVAL; -+ } -+ DRM_INFO("[FM]smu initialized\n"); -+ -+ return 0; -+} -+ -+static int fiji_smu_start_in_non_protection_mode(struct amdgpu_device *adev) -+{ -+ int i, result; -+ uint32_t val; -+ -+ /* wait for smc boot up */ -+ for (i = 0; i < adev->usec_timeout; i++) { -+ val = RREG32_SMC(ixRCU_UC_EVENTS); -+ val = REG_GET_FIELD(val, RCU_UC_EVENTS, boot_seq_done); -+ if (val) -+ break; -+ udelay(1); -+ } -+ -+ if (i == adev->usec_timeout) { -+ DRM_ERROR("SMC boot sequence is not completed\n"); -+ return -EINVAL; -+ } -+ -+ /* Clear firmware interrupt enable flag */ -+ WREG32_SMC(ixFIRMWARE_FLAGS, 0); -+ -+ /* Assert reset */ -+ val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL); -+ val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 1); -+ WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val); -+ -+ result = fiji_smu_upload_firmware_image(adev); -+ if (result) -+ return result; -+ -+ /* Set smc instruct start point at 0x0 */ -+ fiji_program_jump_on_start(adev); -+ -+ /* Enable clock */ -+ val = RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0); -+ val = REG_SET_FIELD(val, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); -+ WREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0, val); -+ -+ /* De-assert reset */ -+ val = RREG32_SMC(ixSMC_SYSCON_RESET_CNTL); -+ val = REG_SET_FIELD(val, SMC_SYSCON_RESET_CNTL, rst_reg, 0); -+ WREG32_SMC(ixSMC_SYSCON_RESET_CNTL, val); -+ -+ /* Wait for firmware to initialize */ -+ for (i = 0; i < adev->usec_timeout; i++) { -+ val = RREG32_SMC(ixFIRMWARE_FLAGS); -+ if (REG_GET_FIELD(val, FIRMWARE_FLAGS, INTERRUPTS_ENABLED)) -+ break; -+ udelay(1); -+ } -+ -+ if (i == adev->usec_timeout) { -+ DRM_ERROR("Timeout for SMC firmware initialization\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+int fiji_smu_start(struct amdgpu_device *adev) -+{ -+ int result; -+ uint32_t val; -+ -+ if (!fiji_is_smc_ram_running(adev)) { -+ val = RREG32_SMC(ixSMU_FIRMWARE); -+ if (!REG_GET_FIELD(val, SMU_FIRMWARE, SMU_MODE)) { -+ DRM_INFO("[FM]start smu in nonprotection mode\n"); -+ result = fiji_smu_start_in_non_protection_mode(adev); -+ if (result) -+ return result; -+ } else { -+ DRM_INFO("[FM]start smu in protection mode\n"); -+ result = fiji_smu_start_in_protection_mode(adev); -+ if (result) -+ return result; -+ } -+ } -+ -+ return fiji_smu_request_load_fw(adev); -+} -+ -+static const struct amdgpu_smumgr_funcs fiji_smumgr_funcs = { -+ .check_fw_load_finish = fiji_smu_check_fw_load_finish, -+ .request_smu_load_fw = NULL, -+ .request_smu_specific_fw = NULL, -+}; -+ -+int fiji_smu_init(struct amdgpu_device *adev) -+{ -+ struct fiji_smu_private_data *private; -+ uint32_t image_size = ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096; -+ uint32_t smu_internal_buffer_size = 200*4096; -+ struct amdgpu_bo **toc_buf = &adev->smu.toc_buf; -+ struct amdgpu_bo **smu_buf = &adev->smu.smu_buf; -+ uint64_t mc_addr; -+ void *toc_buf_ptr; -+ void *smu_buf_ptr; -+ int ret; -+ -+ private = kzalloc(sizeof(struct fiji_smu_private_data), GFP_KERNEL); -+ if (NULL == private) -+ return -ENOMEM; -+ -+ /* allocate firmware buffers */ -+ if (adev->firmware.smu_load) -+ amdgpu_ucode_init_bo(adev); -+ -+ adev->smu.priv = private; -+ adev->smu.fw_flags = 0; -+ -+ /* Allocate FW image data structure and header buffer */ -+ ret = amdgpu_bo_create(adev, image_size, PAGE_SIZE, -+ true, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, toc_buf); -+ if (ret) { -+ DRM_ERROR("Failed to allocate memory for TOC buffer\n"); -+ return -ENOMEM; -+ } -+ -+ /* Allocate buffer for SMU internal buffer */ -+ ret = amdgpu_bo_create(adev, smu_internal_buffer_size, PAGE_SIZE, -+ true, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL, smu_buf); -+ if (ret) { -+ DRM_ERROR("Failed to allocate memory for SMU internal buffer\n"); -+ return -ENOMEM; -+ } -+ -+ /* Retrieve GPU address for header buffer and internal buffer */ -+ ret = amdgpu_bo_reserve(adev->smu.toc_buf, false); -+ if (ret) { -+ amdgpu_bo_unref(&adev->smu.toc_buf); -+ DRM_ERROR("Failed to reserve the TOC buffer\n"); -+ return -EINVAL; -+ } -+ -+ ret = amdgpu_bo_pin(adev->smu.toc_buf, AMDGPU_GEM_DOMAIN_VRAM, &mc_addr); -+ if (ret) { -+ amdgpu_bo_unreserve(adev->smu.toc_buf); -+ amdgpu_bo_unref(&adev->smu.toc_buf); -+ DRM_ERROR("Failed to pin the TOC buffer\n"); -+ return -EINVAL; -+ } -+ -+ ret = amdgpu_bo_kmap(*toc_buf, &toc_buf_ptr); -+ if (ret) { -+ amdgpu_bo_unreserve(adev->smu.toc_buf); -+ amdgpu_bo_unref(&adev->smu.toc_buf); -+ DRM_ERROR("Failed to map the TOC buffer\n"); -+ return -EINVAL; -+ } -+ -+ amdgpu_bo_unreserve(adev->smu.toc_buf); -+ private->header_addr_low = lower_32_bits(mc_addr); -+ private->header_addr_high = upper_32_bits(mc_addr); -+ private->header = toc_buf_ptr; -+ -+ ret = amdgpu_bo_reserve(adev->smu.smu_buf, false); -+ if (ret) { -+ amdgpu_bo_unref(&adev->smu.smu_buf); -+ amdgpu_bo_unref(&adev->smu.toc_buf); -+ DRM_ERROR("Failed to reserve the SMU internal buffer\n"); -+ return -EINVAL; -+ } -+ -+ ret = amdgpu_bo_pin(adev->smu.smu_buf, AMDGPU_GEM_DOMAIN_VRAM, &mc_addr); -+ if (ret) { -+ amdgpu_bo_unreserve(adev->smu.smu_buf); -+ amdgpu_bo_unref(&adev->smu.smu_buf); -+ amdgpu_bo_unref(&adev->smu.toc_buf); -+ DRM_ERROR("Failed to pin the SMU internal buffer\n"); -+ return -EINVAL; -+ } -+ -+ ret = amdgpu_bo_kmap(*smu_buf, &smu_buf_ptr); -+ if (ret) { -+ amdgpu_bo_unreserve(adev->smu.smu_buf); -+ amdgpu_bo_unref(&adev->smu.smu_buf); -+ amdgpu_bo_unref(&adev->smu.toc_buf); -+ DRM_ERROR("Failed to map the SMU internal buffer\n"); -+ return -EINVAL; -+ } -+ -+ amdgpu_bo_unreserve(adev->smu.smu_buf); -+ private->smu_buffer_addr_low = lower_32_bits(mc_addr); -+ private->smu_buffer_addr_high = upper_32_bits(mc_addr); -+ -+ adev->smu.smumgr_funcs = &fiji_smumgr_funcs; -+ -+ return 0; -+} -+ -+int fiji_smu_fini(struct amdgpu_device *adev) -+{ -+ amdgpu_bo_unref(&adev->smu.toc_buf); -+ amdgpu_bo_unref(&adev->smu.smu_buf); -+ kfree(adev->smu.priv); -+ adev->smu.priv = NULL; -+ if (adev->firmware.fw_buf) -+ amdgpu_ucode_fini_bo(adev); -+ -+ return 0; -+} -diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_smumgr.h b/drivers/gpu/drm/amd/amdgpu/fiji_smumgr.h -new file mode 100644 -index 0000000..1cef03d ---- /dev/null -+++ b/drivers/gpu/drm/amd/amdgpu/fiji_smumgr.h -@@ -0,0 +1,42 @@ -+/* -+ * 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 FIJI_SMUMGR_H -+#define FIJI_SMUMGR_H -+ -+#include "fiji_ppsmc.h" -+ -+int fiji_smu_init(struct amdgpu_device *adev); -+int fiji_smu_fini(struct amdgpu_device *adev); -+int fiji_smu_start(struct amdgpu_device *adev); -+ -+struct fiji_smu_private_data -+{ -+ uint8_t *header; -+ uint32_t smu_buffer_addr_high; -+ uint32_t smu_buffer_addr_low; -+ uint32_t header_addr_high; -+ uint32_t header_addr_low; -+}; -+ -+#endif -diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c -index 0549b81..505d9c2 100644 ---- a/drivers/gpu/drm/amd/amdgpu/vi.c -+++ b/drivers/gpu/drm/amd/amdgpu/vi.c -@@ -1188,6 +1188,13 @@ static const struct amdgpu_ip_block_version fiji_ip_blocks[] = - .rev = 0, - .funcs = &tonga_ih_ip_funcs, - }, -+ { -+ .type = AMD_IP_BLOCK_TYPE_SMC, -+ .major = 7, -+ .minor = 1, -+ .rev = 0, -+ .funcs = &fiji_dpm_ip_funcs, -+ }, - }; - - static const struct amdgpu_ip_block_version cz_ip_blocks[] = -diff --git a/drivers/gpu/drm/amd/amdgpu/vi_dpm.h b/drivers/gpu/drm/amd/amdgpu/vi_dpm.h -index 3b45332..fc120ba 100644 ---- a/drivers/gpu/drm/amd/amdgpu/vi_dpm.h -+++ b/drivers/gpu/drm/amd/amdgpu/vi_dpm.h -@@ -30,7 +30,7 @@ int cz_smu_start(struct amdgpu_device *adev); - int cz_smu_fini(struct amdgpu_device *adev); - - extern const struct amd_ip_funcs tonga_dpm_ip_funcs; -- -+extern const struct amd_ip_funcs fiji_dpm_ip_funcs; - extern const struct amd_ip_funcs iceland_dpm_ip_funcs; - - #endif --- -1.9.1 - |