1*19c468b4SFrançois Tigeot /* 2*19c468b4SFrançois Tigeot * Copyright © 2014 Intel Corporation 3*19c468b4SFrançois Tigeot * 4*19c468b4SFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 5*19c468b4SFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 6*19c468b4SFrançois Tigeot * to deal in the Software without restriction, including without limitation 7*19c468b4SFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*19c468b4SFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 9*19c468b4SFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 10*19c468b4SFrançois Tigeot * 11*19c468b4SFrançois Tigeot * The above copyright notice and this permission notice (including the next 12*19c468b4SFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 13*19c468b4SFrançois Tigeot * Software. 14*19c468b4SFrançois Tigeot * 15*19c468b4SFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*19c468b4SFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*19c468b4SFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*19c468b4SFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19*19c468b4SFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20*19c468b4SFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21*19c468b4SFrançois Tigeot * IN THE SOFTWARE. 22*19c468b4SFrançois Tigeot * 23*19c468b4SFrançois Tigeot */ 24*19c468b4SFrançois Tigeot #include <linux/firmware.h> 25*19c468b4SFrançois Tigeot #include "i915_drv.h" 26*19c468b4SFrançois Tigeot #include "i915_reg.h" 27*19c468b4SFrançois Tigeot #include "intel_drv.h" 28*19c468b4SFrançois Tigeot 29*19c468b4SFrançois Tigeot /** 30*19c468b4SFrançois Tigeot * DOC: csr support for dmc 31*19c468b4SFrançois Tigeot * 32*19c468b4SFrançois Tigeot * Display Context Save and Restore (CSR) firmware support added from gen9 33*19c468b4SFrançois Tigeot * onwards to drive newly added DMC (Display microcontroller) in display 34*19c468b4SFrançois Tigeot * engine to save and restore the state of display engine when it enter into 35*19c468b4SFrançois Tigeot * low-power state and comes back to normal. 36*19c468b4SFrançois Tigeot * 37*19c468b4SFrançois Tigeot * Firmware loading status will be one of the below states: FW_UNINITIALIZED, 38*19c468b4SFrançois Tigeot * FW_LOADED, FW_FAILED. 39*19c468b4SFrançois Tigeot * 40*19c468b4SFrançois Tigeot * Once the firmware is written into the registers status will be moved from 41*19c468b4SFrançois Tigeot * FW_UNINITIALIZED to FW_LOADED and for any erroneous condition status will 42*19c468b4SFrançois Tigeot * be moved to FW_FAILED. 43*19c468b4SFrançois Tigeot */ 44*19c468b4SFrançois Tigeot 45*19c468b4SFrançois Tigeot #define I915_CSR_SKL "i915/skl_dmc_ver1.bin" 46*19c468b4SFrançois Tigeot 47*19c468b4SFrançois Tigeot MODULE_FIRMWARE(I915_CSR_SKL); 48*19c468b4SFrançois Tigeot 49*19c468b4SFrançois Tigeot /* 50*19c468b4SFrançois Tigeot * SKL CSR registers for DC5 and DC6 51*19c468b4SFrançois Tigeot */ 52*19c468b4SFrançois Tigeot #define CSR_PROGRAM_BASE 0x80000 53*19c468b4SFrançois Tigeot #define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0 54*19c468b4SFrançois Tigeot #define CSR_HTP_ADDR_SKL 0x00500034 55*19c468b4SFrançois Tigeot #define CSR_SSP_BASE 0x8F074 56*19c468b4SFrançois Tigeot #define CSR_HTP_SKL 0x8F004 57*19c468b4SFrançois Tigeot #define CSR_LAST_WRITE 0x8F034 58*19c468b4SFrançois Tigeot #define CSR_LAST_WRITE_VALUE 0xc003b400 59*19c468b4SFrançois Tigeot /* MMIO address range for CSR program (0x80000 - 0x82FFF) */ 60*19c468b4SFrançois Tigeot #define CSR_MAX_FW_SIZE 0x2FFF 61*19c468b4SFrançois Tigeot #define CSR_DEFAULT_FW_OFFSET 0xFFFFFFFF 62*19c468b4SFrançois Tigeot #define CSR_MMIO_START_RANGE 0x80000 63*19c468b4SFrançois Tigeot #define CSR_MMIO_END_RANGE 0x8FFFF 64*19c468b4SFrançois Tigeot 65*19c468b4SFrançois Tigeot struct intel_css_header { 66*19c468b4SFrançois Tigeot /* 0x09 for DMC */ 67*19c468b4SFrançois Tigeot uint32_t module_type; 68*19c468b4SFrançois Tigeot 69*19c468b4SFrançois Tigeot /* Includes the DMC specific header in dwords */ 70*19c468b4SFrançois Tigeot uint32_t header_len; 71*19c468b4SFrançois Tigeot 72*19c468b4SFrançois Tigeot /* always value would be 0x10000 */ 73*19c468b4SFrançois Tigeot uint32_t header_ver; 74*19c468b4SFrançois Tigeot 75*19c468b4SFrançois Tigeot /* Not used */ 76*19c468b4SFrançois Tigeot uint32_t module_id; 77*19c468b4SFrançois Tigeot 78*19c468b4SFrançois Tigeot /* Not used */ 79*19c468b4SFrançois Tigeot uint32_t module_vendor; 80*19c468b4SFrançois Tigeot 81*19c468b4SFrançois Tigeot /* in YYYYMMDD format */ 82*19c468b4SFrançois Tigeot uint32_t date; 83*19c468b4SFrançois Tigeot 84*19c468b4SFrançois Tigeot /* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */ 85*19c468b4SFrançois Tigeot uint32_t size; 86*19c468b4SFrançois Tigeot 87*19c468b4SFrançois Tigeot /* Not used */ 88*19c468b4SFrançois Tigeot uint32_t key_size; 89*19c468b4SFrançois Tigeot 90*19c468b4SFrançois Tigeot /* Not used */ 91*19c468b4SFrançois Tigeot uint32_t modulus_size; 92*19c468b4SFrançois Tigeot 93*19c468b4SFrançois Tigeot /* Not used */ 94*19c468b4SFrançois Tigeot uint32_t exponent_size; 95*19c468b4SFrançois Tigeot 96*19c468b4SFrançois Tigeot /* Not used */ 97*19c468b4SFrançois Tigeot uint32_t reserved1[12]; 98*19c468b4SFrançois Tigeot 99*19c468b4SFrançois Tigeot /* Major Minor */ 100*19c468b4SFrançois Tigeot uint32_t version; 101*19c468b4SFrançois Tigeot 102*19c468b4SFrançois Tigeot /* Not used */ 103*19c468b4SFrançois Tigeot uint32_t reserved2[8]; 104*19c468b4SFrançois Tigeot 105*19c468b4SFrançois Tigeot /* Not used */ 106*19c468b4SFrançois Tigeot uint32_t kernel_header_info; 107*19c468b4SFrançois Tigeot } __packed; 108*19c468b4SFrançois Tigeot 109*19c468b4SFrançois Tigeot struct intel_fw_info { 110*19c468b4SFrançois Tigeot uint16_t reserved1; 111*19c468b4SFrançois Tigeot 112*19c468b4SFrançois Tigeot /* Stepping (A, B, C, ..., *). * is a wildcard */ 113*19c468b4SFrançois Tigeot char stepping; 114*19c468b4SFrançois Tigeot 115*19c468b4SFrançois Tigeot /* Sub-stepping (0, 1, ..., *). * is a wildcard */ 116*19c468b4SFrançois Tigeot char substepping; 117*19c468b4SFrançois Tigeot 118*19c468b4SFrançois Tigeot uint32_t offset; 119*19c468b4SFrançois Tigeot uint32_t reserved2; 120*19c468b4SFrançois Tigeot } __packed; 121*19c468b4SFrançois Tigeot 122*19c468b4SFrançois Tigeot struct intel_package_header { 123*19c468b4SFrançois Tigeot /* DMC container header length in dwords */ 124*19c468b4SFrançois Tigeot unsigned char header_len; 125*19c468b4SFrançois Tigeot 126*19c468b4SFrançois Tigeot /* always value would be 0x01 */ 127*19c468b4SFrançois Tigeot unsigned char header_ver; 128*19c468b4SFrançois Tigeot 129*19c468b4SFrançois Tigeot unsigned char reserved[10]; 130*19c468b4SFrançois Tigeot 131*19c468b4SFrançois Tigeot /* Number of valid entries in the FWInfo array below */ 132*19c468b4SFrançois Tigeot uint32_t num_entries; 133*19c468b4SFrançois Tigeot 134*19c468b4SFrançois Tigeot struct intel_fw_info fw_info[20]; 135*19c468b4SFrançois Tigeot } __packed; 136*19c468b4SFrançois Tigeot 137*19c468b4SFrançois Tigeot struct intel_dmc_header { 138*19c468b4SFrançois Tigeot /* always value would be 0x40403E3E */ 139*19c468b4SFrançois Tigeot uint32_t signature; 140*19c468b4SFrançois Tigeot 141*19c468b4SFrançois Tigeot /* DMC binary header length */ 142*19c468b4SFrançois Tigeot unsigned char header_len; 143*19c468b4SFrançois Tigeot 144*19c468b4SFrançois Tigeot /* 0x01 */ 145*19c468b4SFrançois Tigeot unsigned char header_ver; 146*19c468b4SFrançois Tigeot 147*19c468b4SFrançois Tigeot /* Reserved */ 148*19c468b4SFrançois Tigeot uint16_t dmcc_ver; 149*19c468b4SFrançois Tigeot 150*19c468b4SFrançois Tigeot /* Major, Minor */ 151*19c468b4SFrançois Tigeot uint32_t project; 152*19c468b4SFrançois Tigeot 153*19c468b4SFrançois Tigeot /* Firmware program size (excluding header) in dwords */ 154*19c468b4SFrançois Tigeot uint32_t fw_size; 155*19c468b4SFrançois Tigeot 156*19c468b4SFrançois Tigeot /* Major Minor version */ 157*19c468b4SFrançois Tigeot uint32_t fw_version; 158*19c468b4SFrançois Tigeot 159*19c468b4SFrançois Tigeot /* Number of valid MMIO cycles present. */ 160*19c468b4SFrançois Tigeot uint32_t mmio_count; 161*19c468b4SFrançois Tigeot 162*19c468b4SFrançois Tigeot /* MMIO address */ 163*19c468b4SFrançois Tigeot uint32_t mmioaddr[8]; 164*19c468b4SFrançois Tigeot 165*19c468b4SFrançois Tigeot /* MMIO data */ 166*19c468b4SFrançois Tigeot uint32_t mmiodata[8]; 167*19c468b4SFrançois Tigeot 168*19c468b4SFrançois Tigeot /* FW filename */ 169*19c468b4SFrançois Tigeot unsigned char dfile[32]; 170*19c468b4SFrançois Tigeot 171*19c468b4SFrançois Tigeot uint32_t reserved1[2]; 172*19c468b4SFrançois Tigeot } __packed; 173*19c468b4SFrançois Tigeot 174*19c468b4SFrançois Tigeot struct stepping_info { 175*19c468b4SFrançois Tigeot char stepping; 176*19c468b4SFrançois Tigeot char substepping; 177*19c468b4SFrançois Tigeot }; 178*19c468b4SFrançois Tigeot 179*19c468b4SFrançois Tigeot static const struct stepping_info skl_stepping_info[] = { 180*19c468b4SFrançois Tigeot {'A', '0'}, {'B', '0'}, {'C', '0'}, 181*19c468b4SFrançois Tigeot {'D', '0'}, {'E', '0'}, {'F', '0'}, 182*19c468b4SFrançois Tigeot {'G', '0'}, {'H', '0'}, {'I', '0'} 183*19c468b4SFrançois Tigeot }; 184*19c468b4SFrançois Tigeot 185*19c468b4SFrançois Tigeot #if 0 186*19c468b4SFrançois Tigeot static char intel_get_stepping(struct drm_device *dev) 187*19c468b4SFrançois Tigeot { 188*19c468b4SFrançois Tigeot if (IS_SKYLAKE(dev) && (dev->pdev->revision < 189*19c468b4SFrançois Tigeot ARRAY_SIZE(skl_stepping_info))) 190*19c468b4SFrançois Tigeot return skl_stepping_info[dev->pdev->revision].stepping; 191*19c468b4SFrançois Tigeot else 192*19c468b4SFrançois Tigeot return -ENODATA; 193*19c468b4SFrançois Tigeot } 194*19c468b4SFrançois Tigeot 195*19c468b4SFrançois Tigeot static char intel_get_substepping(struct drm_device *dev) 196*19c468b4SFrançois Tigeot { 197*19c468b4SFrançois Tigeot if (IS_SKYLAKE(dev) && (dev->pdev->revision < 198*19c468b4SFrançois Tigeot ARRAY_SIZE(skl_stepping_info))) 199*19c468b4SFrançois Tigeot return skl_stepping_info[dev->pdev->revision].substepping; 200*19c468b4SFrançois Tigeot else 201*19c468b4SFrançois Tigeot return -ENODATA; 202*19c468b4SFrançois Tigeot } 203*19c468b4SFrançois Tigeot #endif 204*19c468b4SFrançois Tigeot 205*19c468b4SFrançois Tigeot /** 206*19c468b4SFrançois Tigeot * intel_csr_load_status_get() - to get firmware loading status. 207*19c468b4SFrançois Tigeot * @dev_priv: i915 device. 208*19c468b4SFrançois Tigeot * 209*19c468b4SFrançois Tigeot * This function helps to get the firmware loading status. 210*19c468b4SFrançois Tigeot * 211*19c468b4SFrançois Tigeot * Return: Firmware loading status. 212*19c468b4SFrançois Tigeot */ 213*19c468b4SFrançois Tigeot enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv) 214*19c468b4SFrançois Tigeot { 215*19c468b4SFrançois Tigeot enum csr_state state; 216*19c468b4SFrançois Tigeot 217*19c468b4SFrançois Tigeot mutex_lock(&dev_priv->csr_lock); 218*19c468b4SFrançois Tigeot state = dev_priv->csr.state; 219*19c468b4SFrançois Tigeot mutex_unlock(&dev_priv->csr_lock); 220*19c468b4SFrançois Tigeot 221*19c468b4SFrançois Tigeot return state; 222*19c468b4SFrançois Tigeot } 223*19c468b4SFrançois Tigeot 224*19c468b4SFrançois Tigeot /** 225*19c468b4SFrançois Tigeot * intel_csr_load_status_set() - help to set firmware loading status. 226*19c468b4SFrançois Tigeot * @dev_priv: i915 device. 227*19c468b4SFrançois Tigeot * @state: enumeration of firmware loading status. 228*19c468b4SFrançois Tigeot * 229*19c468b4SFrançois Tigeot * Set the firmware loading status. 230*19c468b4SFrançois Tigeot */ 231*19c468b4SFrançois Tigeot void intel_csr_load_status_set(struct drm_i915_private *dev_priv, 232*19c468b4SFrançois Tigeot enum csr_state state) 233*19c468b4SFrançois Tigeot { 234*19c468b4SFrançois Tigeot mutex_lock(&dev_priv->csr_lock); 235*19c468b4SFrançois Tigeot dev_priv->csr.state = state; 236*19c468b4SFrançois Tigeot mutex_unlock(&dev_priv->csr_lock); 237*19c468b4SFrançois Tigeot } 238*19c468b4SFrançois Tigeot 239*19c468b4SFrançois Tigeot /** 240*19c468b4SFrançois Tigeot * intel_csr_load_program() - write the firmware from memory to register. 241*19c468b4SFrançois Tigeot * @dev: drm device. 242*19c468b4SFrançois Tigeot * 243*19c468b4SFrançois Tigeot * CSR firmware is read from a .bin file and kept in internal memory one time. 244*19c468b4SFrançois Tigeot * Everytime display comes back from low power state this function is called to 245*19c468b4SFrançois Tigeot * copy the firmware from internal memory to registers. 246*19c468b4SFrançois Tigeot */ 247*19c468b4SFrançois Tigeot void intel_csr_load_program(struct drm_device *dev) 248*19c468b4SFrançois Tigeot { 249*19c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 250*19c468b4SFrançois Tigeot __be32 *payload = dev_priv->csr.dmc_payload; 251*19c468b4SFrançois Tigeot uint32_t i, fw_size; 252*19c468b4SFrançois Tigeot 253*19c468b4SFrançois Tigeot if (!IS_GEN9(dev)) { 254*19c468b4SFrançois Tigeot DRM_ERROR("No CSR support available for this platform\n"); 255*19c468b4SFrançois Tigeot return; 256*19c468b4SFrançois Tigeot } 257*19c468b4SFrançois Tigeot 258*19c468b4SFrançois Tigeot mutex_lock(&dev_priv->csr_lock); 259*19c468b4SFrançois Tigeot fw_size = dev_priv->csr.dmc_fw_size; 260*19c468b4SFrançois Tigeot for (i = 0; i < fw_size; i++) 261*19c468b4SFrançois Tigeot I915_WRITE(CSR_PROGRAM_BASE + i * 4, 262*19c468b4SFrançois Tigeot (u32 __force)payload[i]); 263*19c468b4SFrançois Tigeot 264*19c468b4SFrançois Tigeot for (i = 0; i < dev_priv->csr.mmio_count; i++) { 265*19c468b4SFrançois Tigeot I915_WRITE(dev_priv->csr.mmioaddr[i], 266*19c468b4SFrançois Tigeot dev_priv->csr.mmiodata[i]); 267*19c468b4SFrançois Tigeot } 268*19c468b4SFrançois Tigeot 269*19c468b4SFrançois Tigeot dev_priv->csr.state = FW_LOADED; 270*19c468b4SFrançois Tigeot mutex_unlock(&dev_priv->csr_lock); 271*19c468b4SFrançois Tigeot } 272*19c468b4SFrançois Tigeot 273*19c468b4SFrançois Tigeot #if 0 274*19c468b4SFrançois Tigeot static void finish_csr_load(const struct firmware *fw, void *context) 275*19c468b4SFrançois Tigeot { 276*19c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = context; 277*19c468b4SFrançois Tigeot struct drm_device *dev = dev_priv->dev; 278*19c468b4SFrançois Tigeot struct intel_css_header *css_header; 279*19c468b4SFrançois Tigeot struct intel_package_header *package_header; 280*19c468b4SFrançois Tigeot struct intel_dmc_header *dmc_header; 281*19c468b4SFrançois Tigeot struct intel_csr *csr = &dev_priv->csr; 282*19c468b4SFrançois Tigeot char stepping = intel_get_stepping(dev); 283*19c468b4SFrançois Tigeot char substepping = intel_get_substepping(dev); 284*19c468b4SFrançois Tigeot uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes; 285*19c468b4SFrançois Tigeot uint32_t i; 286*19c468b4SFrançois Tigeot __be32 *dmc_payload; 287*19c468b4SFrançois Tigeot bool fw_loaded = false; 288*19c468b4SFrançois Tigeot 289*19c468b4SFrançois Tigeot if (!fw) { 290*19c468b4SFrançois Tigeot i915_firmware_load_error_print(csr->fw_path, 0); 291*19c468b4SFrançois Tigeot goto out; 292*19c468b4SFrançois Tigeot } 293*19c468b4SFrançois Tigeot 294*19c468b4SFrançois Tigeot if ((stepping == -ENODATA) || (substepping == -ENODATA)) { 295*19c468b4SFrançois Tigeot DRM_ERROR("Unknown stepping info, firmware loading failed\n"); 296*19c468b4SFrançois Tigeot goto out; 297*19c468b4SFrançois Tigeot } 298*19c468b4SFrançois Tigeot 299*19c468b4SFrançois Tigeot /* Extract CSS Header information*/ 300*19c468b4SFrançois Tigeot css_header = (struct intel_css_header *)fw->data; 301*19c468b4SFrançois Tigeot if (sizeof(struct intel_css_header) != 302*19c468b4SFrançois Tigeot (css_header->header_len * 4)) { 303*19c468b4SFrançois Tigeot DRM_ERROR("Firmware has wrong CSS header length %u bytes\n", 304*19c468b4SFrançois Tigeot (css_header->header_len * 4)); 305*19c468b4SFrançois Tigeot goto out; 306*19c468b4SFrançois Tigeot } 307*19c468b4SFrançois Tigeot readcount += sizeof(struct intel_css_header); 308*19c468b4SFrançois Tigeot 309*19c468b4SFrançois Tigeot /* Extract Package Header information*/ 310*19c468b4SFrançois Tigeot package_header = (struct intel_package_header *) 311*19c468b4SFrançois Tigeot &fw->data[readcount]; 312*19c468b4SFrançois Tigeot if (sizeof(struct intel_package_header) != 313*19c468b4SFrançois Tigeot (package_header->header_len * 4)) { 314*19c468b4SFrançois Tigeot DRM_ERROR("Firmware has wrong package header length %u bytes\n", 315*19c468b4SFrançois Tigeot (package_header->header_len * 4)); 316*19c468b4SFrançois Tigeot goto out; 317*19c468b4SFrançois Tigeot } 318*19c468b4SFrançois Tigeot readcount += sizeof(struct intel_package_header); 319*19c468b4SFrançois Tigeot 320*19c468b4SFrançois Tigeot /* Search for dmc_offset to find firware binary. */ 321*19c468b4SFrançois Tigeot for (i = 0; i < package_header->num_entries; i++) { 322*19c468b4SFrançois Tigeot if (package_header->fw_info[i].substepping == '*' && 323*19c468b4SFrançois Tigeot stepping == package_header->fw_info[i].stepping) { 324*19c468b4SFrançois Tigeot dmc_offset = package_header->fw_info[i].offset; 325*19c468b4SFrançois Tigeot break; 326*19c468b4SFrançois Tigeot } else if (stepping == package_header->fw_info[i].stepping && 327*19c468b4SFrançois Tigeot substepping == package_header->fw_info[i].substepping) { 328*19c468b4SFrançois Tigeot dmc_offset = package_header->fw_info[i].offset; 329*19c468b4SFrançois Tigeot break; 330*19c468b4SFrançois Tigeot } else if (package_header->fw_info[i].stepping == '*' && 331*19c468b4SFrançois Tigeot package_header->fw_info[i].substepping == '*') 332*19c468b4SFrançois Tigeot dmc_offset = package_header->fw_info[i].offset; 333*19c468b4SFrançois Tigeot } 334*19c468b4SFrançois Tigeot if (dmc_offset == CSR_DEFAULT_FW_OFFSET) { 335*19c468b4SFrançois Tigeot DRM_ERROR("Firmware not supported for %c stepping\n", stepping); 336*19c468b4SFrançois Tigeot goto out; 337*19c468b4SFrançois Tigeot } 338*19c468b4SFrançois Tigeot readcount += dmc_offset; 339*19c468b4SFrançois Tigeot 340*19c468b4SFrançois Tigeot /* Extract dmc_header information. */ 341*19c468b4SFrançois Tigeot dmc_header = (struct intel_dmc_header *)&fw->data[readcount]; 342*19c468b4SFrançois Tigeot if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) { 343*19c468b4SFrançois Tigeot DRM_ERROR("Firmware has wrong dmc header length %u bytes\n", 344*19c468b4SFrançois Tigeot (dmc_header->header_len)); 345*19c468b4SFrançois Tigeot goto out; 346*19c468b4SFrançois Tigeot } 347*19c468b4SFrançois Tigeot readcount += sizeof(struct intel_dmc_header); 348*19c468b4SFrançois Tigeot 349*19c468b4SFrançois Tigeot /* Cache the dmc header info. */ 350*19c468b4SFrançois Tigeot if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) { 351*19c468b4SFrançois Tigeot DRM_ERROR("Firmware has wrong mmio count %u\n", 352*19c468b4SFrançois Tigeot dmc_header->mmio_count); 353*19c468b4SFrançois Tigeot goto out; 354*19c468b4SFrançois Tigeot } 355*19c468b4SFrançois Tigeot csr->mmio_count = dmc_header->mmio_count; 356*19c468b4SFrançois Tigeot for (i = 0; i < dmc_header->mmio_count; i++) { 357*19c468b4SFrançois Tigeot if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE && 358*19c468b4SFrançois Tigeot dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) { 359*19c468b4SFrançois Tigeot DRM_ERROR(" Firmware has wrong mmio address 0x%x\n", 360*19c468b4SFrançois Tigeot dmc_header->mmioaddr[i]); 361*19c468b4SFrançois Tigeot goto out; 362*19c468b4SFrançois Tigeot } 363*19c468b4SFrançois Tigeot csr->mmioaddr[i] = dmc_header->mmioaddr[i]; 364*19c468b4SFrançois Tigeot csr->mmiodata[i] = dmc_header->mmiodata[i]; 365*19c468b4SFrançois Tigeot } 366*19c468b4SFrançois Tigeot 367*19c468b4SFrançois Tigeot /* fw_size is in dwords, so multiplied by 4 to convert into bytes. */ 368*19c468b4SFrançois Tigeot nbytes = dmc_header->fw_size * 4; 369*19c468b4SFrançois Tigeot if (nbytes > CSR_MAX_FW_SIZE) { 370*19c468b4SFrançois Tigeot DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes); 371*19c468b4SFrançois Tigeot goto out; 372*19c468b4SFrançois Tigeot } 373*19c468b4SFrançois Tigeot csr->dmc_fw_size = dmc_header->fw_size; 374*19c468b4SFrançois Tigeot 375*19c468b4SFrançois Tigeot csr->dmc_payload = kmalloc(nbytes, M_DRM, M_WAITOK); 376*19c468b4SFrançois Tigeot if (!csr->dmc_payload) { 377*19c468b4SFrançois Tigeot DRM_ERROR("Memory allocation failed for dmc payload\n"); 378*19c468b4SFrançois Tigeot goto out; 379*19c468b4SFrançois Tigeot } 380*19c468b4SFrançois Tigeot 381*19c468b4SFrançois Tigeot dmc_payload = csr->dmc_payload; 382*19c468b4SFrançois Tigeot for (i = 0; i < dmc_header->fw_size; i++) { 383*19c468b4SFrançois Tigeot uint32_t *tmp = (u32 *)&fw->data[readcount + i * 4]; 384*19c468b4SFrançois Tigeot /* 385*19c468b4SFrançois Tigeot * The firmware payload is an array of 32 bit words stored in 386*19c468b4SFrançois Tigeot * little-endian format in the firmware image and programmed 387*19c468b4SFrançois Tigeot * as 32 bit big-endian format to memory. 388*19c468b4SFrançois Tigeot */ 389*19c468b4SFrançois Tigeot dmc_payload[i] = cpu_to_be32(*tmp); 390*19c468b4SFrançois Tigeot } 391*19c468b4SFrançois Tigeot 392*19c468b4SFrançois Tigeot /* load csr program during system boot, as needed for DC states */ 393*19c468b4SFrançois Tigeot intel_csr_load_program(dev); 394*19c468b4SFrançois Tigeot fw_loaded = true; 395*19c468b4SFrançois Tigeot 396*19c468b4SFrançois Tigeot out: 397*19c468b4SFrançois Tigeot if (fw_loaded) 398*19c468b4SFrançois Tigeot intel_runtime_pm_put(dev_priv); 399*19c468b4SFrançois Tigeot else 400*19c468b4SFrançois Tigeot intel_csr_load_status_set(dev_priv, FW_FAILED); 401*19c468b4SFrançois Tigeot 402*19c468b4SFrançois Tigeot release_firmware(fw); 403*19c468b4SFrançois Tigeot } 404*19c468b4SFrançois Tigeot #endif 405*19c468b4SFrançois Tigeot 406*19c468b4SFrançois Tigeot /** 407*19c468b4SFrançois Tigeot * intel_csr_ucode_init() - initialize the firmware loading. 408*19c468b4SFrançois Tigeot * @dev: drm device. 409*19c468b4SFrançois Tigeot * 410*19c468b4SFrançois Tigeot * This function is called at the time of loading the display driver to read 411*19c468b4SFrançois Tigeot * firmware from a .bin file and copied into a internal memory. 412*19c468b4SFrançois Tigeot */ 413*19c468b4SFrançois Tigeot void intel_csr_ucode_init(struct drm_device *dev) 414*19c468b4SFrançois Tigeot { 415*19c468b4SFrançois Tigeot #if 0 416*19c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 417*19c468b4SFrançois Tigeot struct intel_csr *csr = &dev_priv->csr; 418*19c468b4SFrançois Tigeot int ret; 419*19c468b4SFrançois Tigeot 420*19c468b4SFrançois Tigeot if (!HAS_CSR(dev)) 421*19c468b4SFrançois Tigeot return; 422*19c468b4SFrançois Tigeot 423*19c468b4SFrançois Tigeot if (IS_SKYLAKE(dev)) 424*19c468b4SFrançois Tigeot csr->fw_path = I915_CSR_SKL; 425*19c468b4SFrançois Tigeot else { 426*19c468b4SFrançois Tigeot DRM_ERROR("Unexpected: no known CSR firmware for platform\n"); 427*19c468b4SFrançois Tigeot intel_csr_load_status_set(dev_priv, FW_FAILED); 428*19c468b4SFrançois Tigeot return; 429*19c468b4SFrançois Tigeot } 430*19c468b4SFrançois Tigeot 431*19c468b4SFrançois Tigeot /* 432*19c468b4SFrançois Tigeot * Obtain a runtime pm reference, until CSR is loaded, 433*19c468b4SFrançois Tigeot * to avoid entering runtime-suspend. 434*19c468b4SFrançois Tigeot */ 435*19c468b4SFrançois Tigeot intel_runtime_pm_get(dev_priv); 436*19c468b4SFrançois Tigeot 437*19c468b4SFrançois Tigeot /* CSR supported for platform, load firmware */ 438*19c468b4SFrançois Tigeot ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path, 439*19c468b4SFrançois Tigeot &dev_priv->dev->pdev->dev, 440*19c468b4SFrançois Tigeot GFP_KERNEL, dev_priv, 441*19c468b4SFrançois Tigeot finish_csr_load); 442*19c468b4SFrançois Tigeot if (ret) { 443*19c468b4SFrançois Tigeot i915_firmware_load_error_print(csr->fw_path, ret); 444*19c468b4SFrançois Tigeot intel_csr_load_status_set(dev_priv, FW_FAILED); 445*19c468b4SFrançois Tigeot } 446*19c468b4SFrançois Tigeot #endif 447*19c468b4SFrançois Tigeot } 448*19c468b4SFrançois Tigeot 449*19c468b4SFrançois Tigeot /** 450*19c468b4SFrançois Tigeot * intel_csr_ucode_fini() - unload the CSR firmware. 451*19c468b4SFrançois Tigeot * @dev: drm device. 452*19c468b4SFrançois Tigeot * 453*19c468b4SFrançois Tigeot * Firmmware unloading includes freeing the internal momory and reset the 454*19c468b4SFrançois Tigeot * firmware loading status. 455*19c468b4SFrançois Tigeot */ 456*19c468b4SFrançois Tigeot void intel_csr_ucode_fini(struct drm_device *dev) 457*19c468b4SFrançois Tigeot { 458*19c468b4SFrançois Tigeot #if 0 459*19c468b4SFrançois Tigeot struct drm_i915_private *dev_priv = dev->dev_private; 460*19c468b4SFrançois Tigeot 461*19c468b4SFrançois Tigeot if (!HAS_CSR(dev)) 462*19c468b4SFrançois Tigeot return; 463*19c468b4SFrançois Tigeot 464*19c468b4SFrançois Tigeot intel_csr_load_status_set(dev_priv, FW_FAILED); 465*19c468b4SFrançois Tigeot kfree(dev_priv->csr.dmc_payload); 466*19c468b4SFrançois Tigeot #endif 467*19c468b4SFrançois Tigeot } 468*19c468b4SFrançois Tigeot 469*19c468b4SFrançois Tigeot void assert_csr_loaded(struct drm_i915_private *dev_priv) 470*19c468b4SFrançois Tigeot { 471*19c468b4SFrançois Tigeot WARN((intel_csr_load_status_get(dev_priv) != FW_LOADED), "CSR is not loaded.\n"); 472*19c468b4SFrançois Tigeot WARN(!I915_READ(CSR_PROGRAM_BASE), 473*19c468b4SFrançois Tigeot "CSR program storage start is NULL\n"); 474*19c468b4SFrançois Tigeot WARN(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n"); 475*19c468b4SFrançois Tigeot WARN(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n"); 476*19c468b4SFrançois Tigeot } 477