Home | History | Annotate | Line # | Download | only in uc
      1 /*	$NetBSD: intel_uc_fw.h,v 1.2 2021/12/18 23:45:31 riastradh Exp $	*/
      2 
      3 /* SPDX-License-Identifier: MIT */
      4 /*
      5  * Copyright  2014-2019 Intel Corporation
      6  */
      7 
      8 #ifndef _INTEL_UC_FW_H_
      9 #define _INTEL_UC_FW_H_
     10 
     11 #include <linux/types.h>
     12 #include "intel_uc_fw_abi.h"
     13 #include "intel_device_info.h"
     14 #include "i915_gem.h"
     15 
     16 struct drm_printer;
     17 struct drm_i915_private;
     18 struct intel_gt;
     19 
     20 /* Home of GuC, HuC and DMC firmwares */
     21 #define INTEL_UC_FIRMWARE_URL "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/i915"
     22 
     23 /*
     24  * +------------+---------------------------------------------------+
     25  * |   PHASE    |           FIRMWARE STATUS TRANSITIONS             |
     26  * +============+===================================================+
     27  * |            |               UNINITIALIZED                       |
     28  * +------------+-               /   |   \                         -+
     29  * |            |   DISABLED <--/    |    \--> NOT_SUPPORTED        |
     30  * | init_early |                    V                              |
     31  * |            |                 SELECTED                          |
     32  * +------------+-               /   |   \                         -+
     33  * |            |    MISSING <--/    |    \--> ERROR                |
     34  * |   fetch    |                    |                              |
     35  * |            |        /------> AVAILABLE <---<-----------\       |
     36  * +------------+-       \         /    \        \           \     -+
     37  * |            |         FAIL <--<      \--> TRANSFERRED     \     |
     38  * |   upload   |                  \           /   \          /     |
     39  * |            |                   \---------/     \--> RUNNING    |
     40  * +------------+---------------------------------------------------+
     41  */
     42 
     43 enum intel_uc_fw_status {
     44 	INTEL_UC_FIRMWARE_NOT_SUPPORTED = -1, /* no uc HW */
     45 	INTEL_UC_FIRMWARE_UNINITIALIZED = 0, /* used to catch checks done too early */
     46 	INTEL_UC_FIRMWARE_DISABLED, /* disabled */
     47 	INTEL_UC_FIRMWARE_SELECTED, /* selected the blob we want to load */
     48 	INTEL_UC_FIRMWARE_MISSING, /* blob not found on the system */
     49 	INTEL_UC_FIRMWARE_ERROR, /* invalid format or version */
     50 	INTEL_UC_FIRMWARE_AVAILABLE, /* blob found and copied in mem */
     51 	INTEL_UC_FIRMWARE_FAIL, /* failed to xfer or init/auth the fw */
     52 	INTEL_UC_FIRMWARE_TRANSFERRED, /* dma xfer done */
     53 	INTEL_UC_FIRMWARE_RUNNING /* init/auth done */
     54 };
     55 
     56 enum intel_uc_fw_type {
     57 	INTEL_UC_FW_TYPE_GUC = 0,
     58 	INTEL_UC_FW_TYPE_HUC
     59 };
     60 #define INTEL_UC_FW_NUM_TYPES 2
     61 
     62 /*
     63  * This structure encapsulates all the data needed during the process
     64  * of fetching, caching, and loading the firmware image into the uC.
     65  */
     66 struct intel_uc_fw {
     67 	enum intel_uc_fw_type type;
     68 	union {
     69 		const enum intel_uc_fw_status status;
     70 		enum intel_uc_fw_status __status; /* no accidental overwrites */
     71 	};
     72 	const char *path;
     73 	bool user_overridden;
     74 	size_t size;
     75 	struct drm_i915_gem_object *obj;
     76 
     77 	/*
     78 	 * The firmware build process will generate a version header file with major and
     79 	 * minor version defined. The versions are built into CSS header of firmware.
     80 	 * i915 kernel driver set the minimal firmware version required per platform.
     81 	 */
     82 	u16 major_ver_wanted;
     83 	u16 minor_ver_wanted;
     84 	u16 major_ver_found;
     85 	u16 minor_ver_found;
     86 
     87 	u32 rsa_size;
     88 	u32 ucode_size;
     89 };
     90 
     91 #ifdef CONFIG_DRM_I915_DEBUG_GUC
     92 void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
     93 			       enum intel_uc_fw_status status);
     94 #else
     95 static inline void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
     96 					     enum intel_uc_fw_status status)
     97 {
     98 	uc_fw->__status = status;
     99 }
    100 #endif
    101 
    102 static inline
    103 const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status)
    104 {
    105 	switch (status) {
    106 	case INTEL_UC_FIRMWARE_NOT_SUPPORTED:
    107 		return "N/A";
    108 	case INTEL_UC_FIRMWARE_UNINITIALIZED:
    109 		return "UNINITIALIZED";
    110 	case INTEL_UC_FIRMWARE_DISABLED:
    111 		return "DISABLED";
    112 	case INTEL_UC_FIRMWARE_SELECTED:
    113 		return "SELECTED";
    114 	case INTEL_UC_FIRMWARE_MISSING:
    115 		return "MISSING";
    116 	case INTEL_UC_FIRMWARE_ERROR:
    117 		return "ERROR";
    118 	case INTEL_UC_FIRMWARE_AVAILABLE:
    119 		return "AVAILABLE";
    120 	case INTEL_UC_FIRMWARE_FAIL:
    121 		return "FAIL";
    122 	case INTEL_UC_FIRMWARE_TRANSFERRED:
    123 		return "TRANSFERRED";
    124 	case INTEL_UC_FIRMWARE_RUNNING:
    125 		return "RUNNING";
    126 	}
    127 	return "<invalid>";
    128 }
    129 
    130 static inline int intel_uc_fw_status_to_error(enum intel_uc_fw_status status)
    131 {
    132 	switch (status) {
    133 	case INTEL_UC_FIRMWARE_NOT_SUPPORTED:
    134 		return -ENODEV;
    135 	case INTEL_UC_FIRMWARE_UNINITIALIZED:
    136 		return -EACCES;
    137 	case INTEL_UC_FIRMWARE_DISABLED:
    138 		return -EPERM;
    139 	case INTEL_UC_FIRMWARE_MISSING:
    140 		return -ENOENT;
    141 	case INTEL_UC_FIRMWARE_ERROR:
    142 		return -ENOEXEC;
    143 	case INTEL_UC_FIRMWARE_FAIL:
    144 		return -EIO;
    145 	case INTEL_UC_FIRMWARE_SELECTED:
    146 		return -ESTALE;
    147 	case INTEL_UC_FIRMWARE_AVAILABLE:
    148 	case INTEL_UC_FIRMWARE_TRANSFERRED:
    149 	case INTEL_UC_FIRMWARE_RUNNING:
    150 		return 0;
    151 	}
    152 	return -EINVAL;
    153 }
    154 
    155 static inline const char *intel_uc_fw_type_repr(enum intel_uc_fw_type type)
    156 {
    157 	switch (type) {
    158 	case INTEL_UC_FW_TYPE_GUC:
    159 		return "GuC";
    160 	case INTEL_UC_FW_TYPE_HUC:
    161 		return "HuC";
    162 	}
    163 	return "uC";
    164 }
    165 
    166 static inline enum intel_uc_fw_status
    167 __intel_uc_fw_status(struct intel_uc_fw *uc_fw)
    168 {
    169 	/* shouldn't call this before checking hw/blob availability */
    170 	GEM_BUG_ON(uc_fw->status == INTEL_UC_FIRMWARE_UNINITIALIZED);
    171 	return uc_fw->status;
    172 }
    173 
    174 static inline bool intel_uc_fw_is_supported(struct intel_uc_fw *uc_fw)
    175 {
    176 	return __intel_uc_fw_status(uc_fw) != INTEL_UC_FIRMWARE_NOT_SUPPORTED;
    177 }
    178 
    179 static inline bool intel_uc_fw_is_enabled(struct intel_uc_fw *uc_fw)
    180 {
    181 	return __intel_uc_fw_status(uc_fw) > INTEL_UC_FIRMWARE_DISABLED;
    182 }
    183 
    184 static inline bool intel_uc_fw_is_available(struct intel_uc_fw *uc_fw)
    185 {
    186 	return __intel_uc_fw_status(uc_fw) >= INTEL_UC_FIRMWARE_AVAILABLE;
    187 }
    188 
    189 static inline bool intel_uc_fw_is_loaded(struct intel_uc_fw *uc_fw)
    190 {
    191 	return __intel_uc_fw_status(uc_fw) >= INTEL_UC_FIRMWARE_TRANSFERRED;
    192 }
    193 
    194 static inline bool intel_uc_fw_is_running(struct intel_uc_fw *uc_fw)
    195 {
    196 	return __intel_uc_fw_status(uc_fw) == INTEL_UC_FIRMWARE_RUNNING;
    197 }
    198 
    199 static inline bool intel_uc_fw_is_overridden(const struct intel_uc_fw *uc_fw)
    200 {
    201 	return uc_fw->user_overridden;
    202 }
    203 
    204 static inline void intel_uc_fw_sanitize(struct intel_uc_fw *uc_fw)
    205 {
    206 	if (intel_uc_fw_is_loaded(uc_fw))
    207 		intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
    208 }
    209 
    210 static inline u32 __intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw)
    211 {
    212 	return sizeof(struct uc_css_header) + uc_fw->ucode_size;
    213 }
    214 
    215 /**
    216  * intel_uc_fw_get_upload_size() - Get size of firmware needed to be uploaded.
    217  * @uc_fw: uC firmware.
    218  *
    219  * Get the size of the firmware and header that will be uploaded to WOPCM.
    220  *
    221  * Return: Upload firmware size, or zero on firmware fetch failure.
    222  */
    223 static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw)
    224 {
    225 	if (!intel_uc_fw_is_available(uc_fw))
    226 		return 0;
    227 
    228 	return __intel_uc_fw_get_upload_size(uc_fw);
    229 }
    230 
    231 void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
    232 			    enum intel_uc_fw_type type, bool supported,
    233 			    enum intel_platform platform, u8 rev);
    234 int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw);
    235 void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw);
    236 int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 offset, u32 dma_flags);
    237 int intel_uc_fw_init(struct intel_uc_fw *uc_fw);
    238 void intel_uc_fw_fini(struct intel_uc_fw *uc_fw);
    239 size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len);
    240 void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p);
    241 
    242 #endif
    243