1 /* 2 * Copyright © 2016-2017 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 */ 24 #include <linux/firmware.h> 25 #include "i915_drv.h" 26 #include "intel_uc.h" 27 28 /** 29 * DOC: HuC Firmware 30 * 31 * Motivation: 32 * GEN9 introduces a new dedicated firmware for usage in media HEVC (High 33 * Efficiency Video Coding) operations. Userspace can use the firmware 34 * capabilities by adding HuC specific commands to batch buffers. 35 * 36 * Implementation: 37 * The same firmware loader is used as the GuC. However, the actual 38 * loading to HW is deferred until GEM initialization is done. 39 * 40 * Note that HuC firmware loading must be done before GuC loading. 41 */ 42 43 #define BXT_HUC_FW_MAJOR 01 44 #define BXT_HUC_FW_MINOR 07 45 #define BXT_BLD_NUM 1398 46 47 #define SKL_HUC_FW_MAJOR 01 48 #define SKL_HUC_FW_MINOR 07 49 #define SKL_BLD_NUM 1398 50 51 #define KBL_HUC_FW_MAJOR 02 52 #define KBL_HUC_FW_MINOR 00 53 #define KBL_BLD_NUM 1810 54 55 #define HUC_FW_PATH(platform, major, minor, bld_num) \ 56 "i915/" __stringify(platform) "_huc_ver" __stringify(major) "_" \ 57 __stringify(minor) "_" __stringify(bld_num) ".bin" 58 59 #define I915_SKL_HUC_UCODE HUC_FW_PATH(skl, SKL_HUC_FW_MAJOR, \ 60 SKL_HUC_FW_MINOR, SKL_BLD_NUM) 61 MODULE_FIRMWARE(I915_SKL_HUC_UCODE); 62 63 #define I915_BXT_HUC_UCODE HUC_FW_PATH(bxt, BXT_HUC_FW_MAJOR, \ 64 BXT_HUC_FW_MINOR, BXT_BLD_NUM) 65 MODULE_FIRMWARE(I915_BXT_HUC_UCODE); 66 67 #define I915_KBL_HUC_UCODE HUC_FW_PATH(kbl, KBL_HUC_FW_MAJOR, \ 68 KBL_HUC_FW_MINOR, KBL_BLD_NUM) 69 MODULE_FIRMWARE(I915_KBL_HUC_UCODE); 70 71 /** 72 * huc_ucode_xfer() - DMA's the firmware 73 * @dev_priv: the drm_i915_private device 74 * 75 * Transfer the firmware image to RAM for execution by the microcontroller. 76 * 77 * Return: 0 on success, non-zero on failure 78 */ 79 static int huc_ucode_xfer(struct drm_i915_private *dev_priv) 80 { 81 struct intel_uc_fw *huc_fw = &dev_priv->huc.fw; 82 struct i915_vma *vma; 83 unsigned long offset = 0; 84 u32 size; 85 int ret; 86 87 ret = i915_gem_object_set_to_gtt_domain(huc_fw->obj, false); 88 if (ret) { 89 DRM_DEBUG_DRIVER("set-domain failed %d\n", ret); 90 return ret; 91 } 92 93 vma = i915_gem_object_ggtt_pin(huc_fw->obj, NULL, 0, 0, 94 PIN_OFFSET_BIAS | GUC_WOPCM_TOP); 95 if (IS_ERR(vma)) { 96 DRM_DEBUG_DRIVER("pin failed %d\n", (int)PTR_ERR(vma)); 97 return PTR_ERR(vma); 98 } 99 100 intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); 101 102 /* init WOPCM */ 103 I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv)); 104 I915_WRITE(DMA_GUC_WOPCM_OFFSET, GUC_WOPCM_OFFSET_VALUE | 105 HUC_LOADING_AGENT_GUC); 106 107 /* Set the source address for the uCode */ 108 offset = guc_ggtt_offset(vma) + huc_fw->header_offset; 109 I915_WRITE(DMA_ADDR_0_LOW, lower_32_bits(offset)); 110 I915_WRITE(DMA_ADDR_0_HIGH, upper_32_bits(offset) & 0xFFFF); 111 112 /* Hardware doesn't look at destination address for HuC. Set it to 0, 113 * but still program the correct address space. 114 */ 115 I915_WRITE(DMA_ADDR_1_LOW, 0); 116 I915_WRITE(DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM); 117 118 size = huc_fw->header_size + huc_fw->ucode_size; 119 I915_WRITE(DMA_COPY_SIZE, size); 120 121 /* Start the DMA */ 122 I915_WRITE(DMA_CTRL, _MASKED_BIT_ENABLE(HUC_UKERNEL | START_DMA)); 123 124 /* Wait for DMA to finish */ 125 ret = wait_for((I915_READ(DMA_CTRL) & START_DMA) == 0, 100); 126 127 DRM_DEBUG_DRIVER("HuC DMA transfer wait over with ret %d\n", ret); 128 129 /* Disable the bits once DMA is over */ 130 I915_WRITE(DMA_CTRL, _MASKED_BIT_DISABLE(HUC_UKERNEL)); 131 132 intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); 133 134 /* 135 * We keep the object pages for reuse during resume. But we can unpin it 136 * now that DMA has completed, so it doesn't continue to take up space. 137 */ 138 i915_vma_unpin(vma); 139 140 return ret; 141 } 142 143 /** 144 * intel_huc_select_fw() - selects HuC firmware for loading 145 * @huc: intel_huc struct 146 */ 147 void intel_huc_select_fw(struct intel_huc *huc) 148 { 149 struct drm_i915_private *dev_priv = huc_to_i915(huc); 150 151 huc->fw.path = NULL; 152 huc->fw.fetch_status = INTEL_UC_FIRMWARE_NONE; 153 huc->fw.load_status = INTEL_UC_FIRMWARE_NONE; 154 huc->fw.type = INTEL_UC_FW_TYPE_HUC; 155 156 if (i915.huc_firmware_path) { 157 huc->fw.path = i915.huc_firmware_path; 158 huc->fw.major_ver_wanted = 0; 159 huc->fw.minor_ver_wanted = 0; 160 } else if (IS_SKYLAKE(dev_priv)) { 161 huc->fw.path = I915_SKL_HUC_UCODE; 162 huc->fw.major_ver_wanted = SKL_HUC_FW_MAJOR; 163 huc->fw.minor_ver_wanted = SKL_HUC_FW_MINOR; 164 } else if (IS_BROXTON(dev_priv)) { 165 huc->fw.path = I915_BXT_HUC_UCODE; 166 huc->fw.major_ver_wanted = BXT_HUC_FW_MAJOR; 167 huc->fw.minor_ver_wanted = BXT_HUC_FW_MINOR; 168 } else if (IS_KABYLAKE(dev_priv)) { 169 huc->fw.path = I915_KBL_HUC_UCODE; 170 huc->fw.major_ver_wanted = KBL_HUC_FW_MAJOR; 171 huc->fw.minor_ver_wanted = KBL_HUC_FW_MINOR; 172 } else { 173 DRM_ERROR("No HuC firmware known for platform with HuC!\n"); 174 return; 175 } 176 } 177 178 /** 179 * intel_huc_init_hw() - load HuC uCode to device 180 * @huc: intel_huc structure 181 * 182 * Called from guc_setup() during driver loading and also after a GPU reset. 183 * Be note that HuC loading must be done before GuC loading. 184 * 185 * The firmware image should have already been fetched into memory by the 186 * earlier call to intel_huc_init(), so here we need only check that 187 * is succeeded, and then transfer the image to the h/w. 188 * 189 * Return: non-zero code on error 190 */ 191 int intel_huc_init_hw(struct intel_huc *huc) 192 { 193 struct drm_i915_private *dev_priv = huc_to_i915(huc); 194 int err; 195 196 if (huc->fw.fetch_status == INTEL_UC_FIRMWARE_NONE) 197 return 0; 198 199 DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n", 200 huc->fw.path, 201 intel_uc_fw_status_repr(huc->fw.fetch_status), 202 intel_uc_fw_status_repr(huc->fw.load_status)); 203 204 if (huc->fw.fetch_status == INTEL_UC_FIRMWARE_SUCCESS && 205 huc->fw.load_status == INTEL_UC_FIRMWARE_FAIL) 206 return -ENOEXEC; 207 208 huc->fw.load_status = INTEL_UC_FIRMWARE_PENDING; 209 210 switch (huc->fw.fetch_status) { 211 case INTEL_UC_FIRMWARE_FAIL: 212 /* something went wrong :( */ 213 err = -EIO; 214 goto fail; 215 216 case INTEL_UC_FIRMWARE_NONE: 217 case INTEL_UC_FIRMWARE_PENDING: 218 default: 219 /* "can't happen" */ 220 WARN_ONCE(1, "HuC fw %s invalid fetch_status %s [%d]\n", 221 huc->fw.path, 222 intel_uc_fw_status_repr(huc->fw.fetch_status), 223 huc->fw.fetch_status); 224 err = -ENXIO; 225 goto fail; 226 227 case INTEL_UC_FIRMWARE_SUCCESS: 228 break; 229 } 230 231 err = huc_ucode_xfer(dev_priv); 232 if (err) 233 goto fail; 234 235 huc->fw.load_status = INTEL_UC_FIRMWARE_SUCCESS; 236 237 DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n", 238 huc->fw.path, 239 intel_uc_fw_status_repr(huc->fw.fetch_status), 240 intel_uc_fw_status_repr(huc->fw.load_status)); 241 242 return 0; 243 244 fail: 245 if (huc->fw.load_status == INTEL_UC_FIRMWARE_PENDING) 246 huc->fw.load_status = INTEL_UC_FIRMWARE_FAIL; 247 248 DRM_ERROR("Failed to complete HuC uCode load with ret %d\n", err); 249 250 return err; 251 } 252 253 /** 254 * intel_guc_auth_huc() - authenticate ucode 255 * @dev_priv: the drm_i915_device 256 * 257 * Triggers a HuC fw authentication request to the GuC via intel_guc_action_ 258 * authenticate_huc interface. 259 */ 260 void intel_guc_auth_huc(struct drm_i915_private *dev_priv) 261 { 262 struct intel_guc *guc = &dev_priv->guc; 263 struct intel_huc *huc = &dev_priv->huc; 264 struct i915_vma *vma; 265 int ret; 266 u32 data[2]; 267 268 if (huc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) 269 return; 270 271 vma = i915_gem_object_ggtt_pin(huc->fw.obj, NULL, 0, 0, 272 PIN_OFFSET_BIAS | GUC_WOPCM_TOP); 273 if (IS_ERR(vma)) { 274 DRM_ERROR("failed to pin huc fw object %d\n", 275 (int)PTR_ERR(vma)); 276 return; 277 } 278 279 /* Specify auth action and where public signature is. */ 280 data[0] = INTEL_GUC_ACTION_AUTHENTICATE_HUC; 281 data[1] = guc_ggtt_offset(vma) + huc->fw.rsa_offset; 282 283 ret = intel_guc_send(guc, data, ARRAY_SIZE(data)); 284 if (ret) { 285 DRM_ERROR("HuC: GuC did not ack Auth request %d\n", ret); 286 goto out; 287 } 288 289 /* Check authentication status, it should be done by now */ 290 ret = intel_wait_for_register(dev_priv, 291 HUC_STATUS2, 292 HUC_FW_VERIFIED, 293 HUC_FW_VERIFIED, 294 50); 295 296 if (ret) { 297 DRM_ERROR("HuC: Authentication failed %d\n", ret); 298 goto out; 299 } 300 301 out: 302 i915_vma_unpin(vma); 303 } 304 305