extern int amdgpu_msi;
 extern int amdgpu_lockup_timeout;
 extern int amdgpu_dpm;
-extern int amdgpu_smc_load_fw;
+extern int amdgpu_fw_load_type;
 extern int amdgpu_aspm;
 extern int amdgpu_runtime_pm;
 extern unsigned amdgpu_ip_block_mask;
 /*
  * Firmware
  */
+enum amdgpu_firmware_load_type {
+       AMDGPU_FW_LOAD_DIRECT = 0,
+       AMDGPU_FW_LOAD_SMU,
+       AMDGPU_FW_LOAD_PSP,
+};
+
 struct amdgpu_firmware {
        struct amdgpu_firmware_info ucode[AMDGPU_UCODE_ID_MAXIMUM];
-       bool smu_load;
+       enum amdgpu_firmware_load_type load_type;
        struct amdgpu_bo *fw_buf;
        unsigned int fw_size;
 };
 
 int amdgpu_msi = -1;
 int amdgpu_lockup_timeout = 0;
 int amdgpu_dpm = -1;
-int amdgpu_smc_load_fw = 1;
+int amdgpu_fw_load_type = -1;
 int amdgpu_aspm = -1;
 int amdgpu_runtime_pm = -1;
 unsigned amdgpu_ip_block_mask = 0xffffffff;
 MODULE_PARM_DESC(dpm, "DPM support (1 = enable, 0 = disable, -1 = auto)");
 module_param_named(dpm, amdgpu_dpm, int, 0444);
 
-MODULE_PARM_DESC(smc_load_fw, "SMC firmware loading(1 = enable, 0 = disable)");
-module_param_named(smc_load_fw, amdgpu_smc_load_fw, int, 0444);
+MODULE_PARM_DESC(fw_load_type, "firmware loading type (0 = direct, 1 = SMU, 2 = PSP, -1 = auto)");
+module_param_named(fw_load_type, amdgpu_fw_load_type, int, 0444);
 
 MODULE_PARM_DESC(aspm, "ASPM support (1 = enable, 0 = disable, -1 = auto)");
 module_param_named(aspm, amdgpu_aspm, int, 0444);
 
        int ret = 0;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (adev->pp_enabled && adev->firmware.smu_load)
+       if (adev->pp_enabled && adev->firmware.load_type == AMDGPU_FW_LOAD_SMU)
                amdgpu_ucode_init_bo(adev);
 
        if (adev->powerplay.ip_funcs->hw_init)
                ret = adev->powerplay.ip_funcs->hw_fini(
                                        adev->powerplay.pp_handle);
 
-       if (adev->pp_enabled && adev->firmware.smu_load)
+       if (adev->pp_enabled && adev->firmware.load_type == AMDGPU_FW_LOAD_SMU)
                amdgpu_ucode_fini_bo(adev);
 
        return ret;
 
        return true;
 }
 
+enum amdgpu_firmware_load_type
+amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
+{
+       switch (adev->asic_type) {
+#ifdef CONFIG_DRM_AMDGPU_SI
+       case CHIP_TAHITI:
+       case CHIP_PITCAIRN:
+       case CHIP_VERDE:
+       case CHIP_OLAND:
+               return AMDGPU_FW_LOAD_DIRECT;
+#endif
+#ifdef CONFIG_DRM_AMDGPU_CIK
+       case CHIP_BONAIRE:
+       case CHIP_KAVERI:
+       case CHIP_KABINI:
+       case CHIP_HAWAII:
+       case CHIP_MULLINS:
+               return AMDGPU_FW_LOAD_DIRECT;
+#endif
+       case CHIP_TOPAZ:
+       case CHIP_TONGA:
+       case CHIP_FIJI:
+       case CHIP_CARRIZO:
+       case CHIP_STONEY:
+       case CHIP_POLARIS10:
+       case CHIP_POLARIS11:
+       case CHIP_POLARIS12:
+               if (!load_type)
+                       return AMDGPU_FW_LOAD_DIRECT;
+               else
+                       return AMDGPU_FW_LOAD_SMU;
+       case CHIP_VEGA10:
+               if (!load_type)
+                       return AMDGPU_FW_LOAD_DIRECT;
+               else
+                       return AMDGPU_FW_LOAD_PSP;
+       default:
+               DRM_ERROR("Unknow firmware load type\n");
+       }
+
+       return AMDGPU_FW_LOAD_DIRECT;
+}
+
 static int amdgpu_ucode_init_single_fw(struct amdgpu_firmware_info *ucode,
                                uint64_t mc_addr, void *kptr)
 {
        uint64_t fw_mc_addr;
        void *fw_buf_ptr = NULL;
        uint64_t fw_offset = 0;
-       int i, err;
+       int i, err, max;
        struct amdgpu_firmware_info *ucode = NULL;
        const struct common_firmware_header *header = NULL;
 
 
        amdgpu_bo_unreserve(*bo);
 
-       for (i = 0; i < AMDGPU_UCODE_ID_MAXIMUM; i++) {
+       /*
+        * if SMU loaded firmware, it needn't add SMC, UVD, and VCE
+        * ucode info here
+        */
+       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
+               max = AMDGPU_UCODE_ID_MAXIMUM - 3;
+       else
+               max = AMDGPU_UCODE_ID_MAXIMUM;
+
+       for (i = 0; i < max; i++) {
                ucode = &adev->firmware.ucode[i];
                if (ucode->fw) {
                        header = (const struct common_firmware_header *)ucode->fw->data;
 failed_reserve:
        amdgpu_bo_unref(bo);
 failed:
-       adev->firmware.smu_load = false;
+       if (err)
+               adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT;
 
        return err;
 }
 {
        int i;
        struct amdgpu_firmware_info *ucode = NULL;
+       int max;
+
+       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
+               max = AMDGPU_UCODE_ID_MAXIMUM - 3;
+       else
+               max = AMDGPU_UCODE_ID_MAXIMUM;
 
-       for (i = 0; i < AMDGPU_UCODE_ID_MAXIMUM; i++) {
+       for (i = 0; i < max; i++) {
                ucode = &adev->firmware.ucode[i];
                if (ucode->fw) {
                        ucode->mc_addr = 0;
 
 int amdgpu_ucode_init_bo(struct amdgpu_device *adev);
 int amdgpu_ucode_fini_bo(struct amdgpu_device *adev);
 
+enum amdgpu_firmware_load_type
+amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type);
+
 #endif
 
                return -EINVAL;
        }
 
+       adev->firmware.load_type = amdgpu_ucode_get_load_type(adev, amdgpu_fw_load_type);
+
        amdgpu_get_pcie_info(adev);
 
        return 0;
 
                }
        }
 
-       if (adev->firmware.smu_load) {
+       if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) {
                info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_PFP];
                info->ucode_id = AMDGPU_UCODE_ID_CP_PFP;
                info->fw = adev->gfx.pfp_fw;
        gfx_v8_0_init_pg(adev);
 
        if (!adev->pp_enabled) {
-               if (!adev->firmware.smu_load) {
+               if (adev->firmware.load_type != AMDGPU_FW_LOAD_SMU) {
                        /* legacy rlc firmware loading */
                        r = gfx_v8_0_rlc_load_microcode(adev);
                        if (r)
                gfx_v8_0_enable_gui_idle_interrupt(adev, false);
 
        if (!adev->pp_enabled) {
-               if (!adev->firmware.smu_load) {
+               if (adev->firmware.load_type != AMDGPU_FW_LOAD_SMU) {
                        /* legacy firmware loading */
                        r = gfx_v8_0_cp_gfx_load_microcode(adev);
                        if (r)
 
                if (adev->sdma.instance[i].feature_version >= 20)
                        adev->sdma.instance[i].burst_nop = true;
 
-               if (adev->firmware.smu_load) {
+               if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) {
                        info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
                        info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
                        info->fw = adev->sdma.instance[i].fw;
        int r;
 
        if (!adev->pp_enabled) {
-               if (!adev->firmware.smu_load) {
+               if (adev->firmware.load_type != AMDGPU_FW_LOAD_SMU) {
                        r = sdma_v2_4_load_microcode(adev);
                        if (r)
                                return r;
 
                if (adev->sdma.instance[i].feature_version >= 20)
                        adev->sdma.instance[i].burst_nop = true;
 
-               if (adev->firmware.smu_load) {
+               if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) {
                        info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
                        info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
                        info->fw = adev->sdma.instance[i].fw;
        int r, i;
 
        if (!adev->pp_enabled) {
-               if (!adev->firmware.smu_load) {
+               if (adev->firmware.load_type != AMDGPU_FW_LOAD_SMU) {
                        r = sdma_v3_0_load_microcode(adev);
                        if (r)
                                return r;
 
                return -EINVAL;
        }
 
-       if (amdgpu_smc_load_fw && smc_enabled)
-               adev->firmware.smu_load = true;
+       /* vi use smc load by default */
+       adev->firmware.load_type = amdgpu_ucode_get_load_type(adev, amdgpu_fw_load_type);
 
        amdgpu_get_pcie_info(adev);