Subversion Repositories Kolibri OS

Rev

Rev 6084 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6084 Rev 6937
Line 25... Line 25...
25
 *    Ben Widawsky 
25
 *    Ben Widawsky 
26
 *    Dave Gordon 
26
 *    Dave Gordon 
27
 *    Alex Dai 
27
 *    Alex Dai 
28
 */
28
 */
29
#include 
29
#include 
30
#include "intel_drv.h"
-
 
31
#include "i915_drv.h"
30
#include "i915_drv.h"
32
#include "intel_guc.h"
31
#include "intel_guc.h"
Line 33... Line 32...
33
 
32
 
34
/**
33
/**
35
 * DOC: GuC
34
 * DOC: GuC-specific firmware loader
36
 *
35
 *
37
 * intel_guc:
36
 * intel_guc:
38
 * Top level structure of guc. It handles firmware loading and manages client
37
 * Top level structure of guc. It handles firmware loading and manages client
39
 * pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy
38
 * pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy
Line 207... Line 206...
207
}
206
}
Line 208... Line 207...
208
 
207
 
209
/*
208
/*
210
 * Transfer the firmware image to RAM for execution by the microcontroller.
209
 * Transfer the firmware image to RAM for execution by the microcontroller.
211
 *
-
 
212
 * GuC Firmware layout:
-
 
213
 * +-------------------------------+  ----
-
 
214
 * |          CSS header           |  128B
-
 
215
 * | contains major/minor version  |
-
 
216
 * +-------------------------------+  ----
-
 
217
 * |             uCode             |
-
 
218
 * +-------------------------------+  ----
-
 
219
 * |         RSA signature         |  256B
-
 
220
 * +-------------------------------+  ----
-
 
221
 *
210
 *
222
 * Architecturally, the DMA engine is bidirectional, and can potentially even
211
 * Architecturally, the DMA engine is bidirectional, and can potentially even
223
 * transfer between GTT locations. This functionality is left out of the API
212
 * transfer between GTT locations. This functionality is left out of the API
224
 * for now as there is no need for it.
213
 * for now as there is no need for it.
225
 *
214
 *
226
 * Note that GuC needs the CSS header plus uKernel code to be copied by the
215
 * Note that GuC needs the CSS header plus uKernel code to be copied by the
227
 * DMA engine in one operation, whereas the RSA signature is loaded via MMIO.
216
 * DMA engine in one operation, whereas the RSA signature is loaded via MMIO.
228
 */
-
 
229
 
-
 
230
#define UOS_CSS_HEADER_OFFSET		0
-
 
231
#define UOS_VER_MINOR_OFFSET		0x44
-
 
232
#define UOS_VER_MAJOR_OFFSET		0x46
-
 
233
#define UOS_CSS_HEADER_SIZE		0x80
-
 
234
#define UOS_RSA_SIG_SIZE		0x100
-
 
235
 
217
 */
236
static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
218
static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv)
237
{
219
{
238
	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
220
	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
239
	struct drm_i915_gem_object *fw_obj = guc_fw->guc_fw_obj;
221
	struct drm_i915_gem_object *fw_obj = guc_fw->guc_fw_obj;
240
	unsigned long offset;
222
	unsigned long offset;
241
	struct sg_table *sg = fw_obj->pages;
223
	struct sg_table *sg = fw_obj->pages;
242
	u32 status, ucode_size, rsa[UOS_RSA_SIG_SIZE / sizeof(u32)];
224
	u32 status, rsa[UOS_RSA_SCRATCH_MAX_COUNT];
Line 243... Line 225...
243
	int i, ret = 0;
225
	int i, ret = 0;
244
 
226
 
245
	/* uCode size, also is where RSA signature starts */
-
 
Line 246... Line 227...
246
	offset = ucode_size = guc_fw->guc_fw_size - UOS_RSA_SIG_SIZE;
227
	/* where RSA signature starts */
247
	I915_WRITE(DMA_COPY_SIZE, ucode_size);
228
	offset = guc_fw->rsa_offset;
248
 
229
 
249
	/* Copy RSA signature from the fw image to HW for verification */
230
	/* Copy RSA signature from the fw image to HW for verification */
Line -... Line 231...
-
 
231
	sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, sizeof(rsa), offset);
-
 
232
	for (i = 0; i < UOS_RSA_SCRATCH_MAX_COUNT; i++)
-
 
233
		I915_WRITE(UOS_RSA_SCRATCH(i), rsa[i]);
-
 
234
 
250
	sg_pcopy_to_buffer(sg->sgl, sg->nents, rsa, UOS_RSA_SIG_SIZE, offset);
235
	/* The header plus uCode will be copied to WOPCM via DMA, excluding any
251
	for (i = 0; i < UOS_RSA_SIG_SIZE / sizeof(u32); i++)
236
	 * other components */
252
		I915_WRITE(UOS_RSA_SCRATCH(i), rsa[i]);
237
	I915_WRITE(DMA_COPY_SIZE, guc_fw->header_size + guc_fw->ucode_size);
253
 
238
 
Line 254... Line 239...
254
	/* Set the source address for the new blob */
239
	/* Set the source address for the new blob */
255
	offset = i915_gem_obj_ggtt_offset(fw_obj);
240
	offset = i915_gem_obj_ggtt_offset(fw_obj) + guc_fw->header_offset;
Line 321... Line 306...
321
 
306
 
322
	/* Enable MIA caching. GuC clock gating is disabled. */
307
	/* Enable MIA caching. GuC clock gating is disabled. */
Line 323... Line 308...
323
	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
308
	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
324
 
309
 
325
	/* WaDisableMinuteIaClockGating:skl,bxt */
310
	/* WaDisableMinuteIaClockGating:skl,bxt */
326
	if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) ||
311
	if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
327
	    (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) {
312
	    IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
328
		I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) &
313
		I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) &
Line 329... Line 314...
329
					      ~GUC_ENABLE_MIA_CLOCK_GATING));
314
					      ~GUC_ENABLE_MIA_CLOCK_GATING));
Line 377... Line 362...
377
{
362
{
378
	struct drm_i915_private *dev_priv = dev->dev_private;
363
	struct drm_i915_private *dev_priv = dev->dev_private;
379
	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
364
	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
380
	int err = 0;
365
	int err = 0;
Line -... Line 366...
-
 
366
 
-
 
367
	if (!i915.enable_guc_submission)
-
 
368
		return 0;
381
 
369
 
382
	DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
370
	DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
383
		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
371
		intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
Line 384... Line 372...
384
		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
372
		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
Line 456... Line 444...
456
 
444
 
457
static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
445
static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
458
{
446
{
459
	struct drm_i915_gem_object *obj;
447
	struct drm_i915_gem_object *obj;
460
	const struct firmware *fw;
448
	const struct firmware *fw;
461
	const u8 *css_header;
449
	struct guc_css_header *css;
462
	const size_t minsize = UOS_CSS_HEADER_SIZE + UOS_RSA_SIG_SIZE;
-
 
463
	const size_t maxsize = GUC_WOPCM_SIZE_VALUE + UOS_RSA_SIG_SIZE
-
 
464
			- 0x8000; /* 32k reserved (8K stack + 24k context) */
450
	size_t size;
Line 465... Line 451...
465
	int err;
451
	int err;
466
 
452
 
Line 473... Line 459...
473
	if (!fw)
459
	if (!fw)
474
		goto fail;
460
		goto fail;
Line 475... Line 461...
475
 
461
 
476
	DRM_DEBUG_DRIVER("fetch GuC fw from %s succeeded, fw %p\n",
462
	DRM_DEBUG_DRIVER("fetch GuC fw from %s succeeded, fw %p\n",
477
		guc_fw->guc_fw_path, fw);
-
 
478
	DRM_DEBUG_DRIVER("firmware file size %zu (minimum %zu, maximum %zu)\n",
-
 
Line 479... Line 463...
479
		fw->size, minsize, maxsize);
463
		guc_fw->guc_fw_path, fw);
480
 
464
 
-
 
465
	/* Check the size of the blob before examining buffer contents */
-
 
466
	if (fw->size < sizeof(struct guc_css_header)) {
-
 
467
		DRM_ERROR("Firmware header is missing\n");
-
 
468
		goto fail;
-
 
469
	}
-
 
470
 
-
 
471
	css = (struct guc_css_header *)fw->data;
-
 
472
 
-
 
473
	/* Firmware bits always start from header */
-
 
474
	guc_fw->header_offset = 0;
-
 
475
	guc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
-
 
476
		css->key_size_dw - css->exponent_size_dw) * sizeof(u32);
-
 
477
 
-
 
478
	if (guc_fw->header_size != sizeof(struct guc_css_header)) {
-
 
479
		DRM_ERROR("CSS header definition mismatch\n");
-
 
480
		goto fail;
-
 
481
	}
-
 
482
 
-
 
483
	/* then, uCode */
-
 
484
	guc_fw->ucode_offset = guc_fw->header_offset + guc_fw->header_size;
-
 
485
	guc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
-
 
486
 
-
 
487
	/* now RSA */
-
 
488
	if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) {
-
 
489
		DRM_ERROR("RSA key size is bad\n");
-
 
490
		goto fail;
-
 
491
	}
-
 
492
	guc_fw->rsa_offset = guc_fw->ucode_offset + guc_fw->ucode_size;
-
 
493
	guc_fw->rsa_size = css->key_size_dw * sizeof(u32);
-
 
494
 
-
 
495
	/* At least, it should have header, uCode and RSA. Size of all three. */
-
 
496
	size = guc_fw->header_size + guc_fw->ucode_size + guc_fw->rsa_size;
-
 
497
	if (fw->size < size) {
-
 
498
		DRM_ERROR("Missing firmware components\n");
-
 
499
		goto fail;
-
 
500
	}
-
 
501
 
-
 
502
	/* Header and uCode will be loaded to WOPCM. Size of the two. */
-
 
503
	size = guc_fw->header_size + guc_fw->ucode_size;
-
 
504
 
-
 
505
	/* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */
481
	/* Check the size of the blob befoe examining buffer contents */
506
	if (size > GUC_WOPCM_SIZE_VALUE - 0x8000) {
-
 
507
		DRM_ERROR("Firmware is too large to fit in WOPCM\n");
Line 482... Line 508...
482
	if (fw->size < minsize || fw->size > maxsize)
508
		goto fail;
483
		goto fail;
509
	}
484
 
510
 
485
	/*
511
	/*
486
	 * The GuC firmware image has the version number embedded at a well-known
512
	 * The GuC firmware image has the version number embedded at a well-known
487
	 * offset within the firmware blob; note that major / minor version are
513
	 * offset within the firmware blob; note that major / minor version are
488
	 * TWO bytes each (i.e. u16), although all pointers and offsets are defined
-
 
489
	 * in terms of bytes (u8).
514
	 * TWO bytes each (i.e. u16), although all pointers and offsets are defined
490
	 */
515
	 * in terms of bytes (u8).
Line 491... Line 516...
491
	css_header = fw->data + UOS_CSS_HEADER_OFFSET;
516
	 */
492
	guc_fw->guc_fw_major_found = *(u16 *)(css_header + UOS_VER_MAJOR_OFFSET);
517
	guc_fw->guc_fw_major_found = css->guc_sw_version >> 16;
493
	guc_fw->guc_fw_minor_found = *(u16 *)(css_header + UOS_VER_MINOR_OFFSET);
518
	guc_fw->guc_fw_minor_found = css->guc_sw_version & 0xFFFF;
494
 
519
 
Line 565... Line 590...
565
	} else {
590
	} else {
566
		i915.enable_guc_submission = false;
591
		i915.enable_guc_submission = false;
567
		fw_path = "";	/* unknown device */
592
		fw_path = "";	/* unknown device */
568
	}
593
	}
Line -... Line 594...
-
 
594
 
-
 
595
	if (!i915.enable_guc_submission)
-
 
596
		return;
569
 
597
 
570
	guc_fw->guc_dev = dev;
598
	guc_fw->guc_dev = dev;
571
	guc_fw->guc_fw_path = fw_path;
599
	guc_fw->guc_fw_path = fw_path;
572
	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
600
	guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;