mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 10:10:33 +02:00 
			
		
		
		
	drm/xe/nvm: add on-die non-volatile memory device
Enable access to internal non-volatile memory on DGFX with GSC/CSC devices via a child device. The nvm child device is exposed via auxiliary bus. Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Link: https://lore.kernel.org/r/20250617145159.3803852-7-alexander.usyskin@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
		
							parent
							
								
									4b93f5fc3b
								
							
						
					
					
						commit
						c28bfb107d
					
				
					 6 changed files with 140 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -80,6 +80,7 @@ xe-y += xe_bb.o \
 | 
			
		|||
	xe_mmio.o \
 | 
			
		||||
	xe_mocs.o \
 | 
			
		||||
	xe_module.o \
 | 
			
		||||
	xe_nvm.o \
 | 
			
		||||
	xe_oa.o \
 | 
			
		||||
	xe_observation.o \
 | 
			
		||||
	xe_pat.o \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,7 @@
 | 
			
		|||
#include "xe_memirq.h"
 | 
			
		||||
#include "xe_mmio.h"
 | 
			
		||||
#include "xe_module.h"
 | 
			
		||||
#include "xe_nvm.h"
 | 
			
		||||
#include "xe_oa.h"
 | 
			
		||||
#include "xe_observation.h"
 | 
			
		||||
#include "xe_pat.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -881,6 +882,8 @@ int xe_device_probe(struct xe_device *xe)
 | 
			
		|||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xe_nvm_init(xe);
 | 
			
		||||
 | 
			
		||||
	err = xe_heci_gsc_init(xe);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
| 
						 | 
				
			
			@ -938,6 +941,8 @@ void xe_device_remove(struct xe_device *xe)
 | 
			
		|||
{
 | 
			
		||||
	xe_display_unregister(xe);
 | 
			
		||||
 | 
			
		||||
	xe_nvm_fini(xe);
 | 
			
		||||
 | 
			
		||||
	drm_dev_unplug(&xe->drm);
 | 
			
		||||
 | 
			
		||||
	xe_bo_pci_dev_remove_all(xe);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,7 @@
 | 
			
		|||
 | 
			
		||||
struct dram_info;
 | 
			
		||||
struct intel_display;
 | 
			
		||||
struct intel_dg_nvm_dev;
 | 
			
		||||
struct xe_ggtt;
 | 
			
		||||
struct xe_pat_ops;
 | 
			
		||||
struct xe_pxp;
 | 
			
		||||
| 
						 | 
				
			
			@ -316,6 +317,8 @@ struct xe_device {
 | 
			
		|||
		u8 has_fan_control:1;
 | 
			
		||||
		/** @info.has_flat_ccs: Whether flat CCS metadata is used */
 | 
			
		||||
		u8 has_flat_ccs:1;
 | 
			
		||||
		/** @info.has_gsc_nvm: Device has gsc non-volatile memory */
 | 
			
		||||
		u8 has_gsc_nvm:1;
 | 
			
		||||
		/** @info.has_heci_cscfi: device has heci cscfi */
 | 
			
		||||
		u8 has_heci_cscfi:1;
 | 
			
		||||
		/** @info.has_heci_gscfi: device has heci gscfi */
 | 
			
		||||
| 
						 | 
				
			
			@ -549,6 +552,9 @@ struct xe_device {
 | 
			
		|||
	/** @heci_gsc: graphics security controller */
 | 
			
		||||
	struct xe_heci_gsc heci_gsc;
 | 
			
		||||
 | 
			
		||||
	/** @nvm: discrete graphics non-volatile memory */
 | 
			
		||||
	struct intel_dg_nvm_dev *nvm;
 | 
			
		||||
 | 
			
		||||
	/** @oa: oa observation subsystem */
 | 
			
		||||
	struct xe_oa oa;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										107
									
								
								drivers/gpu/drm/xe/xe_nvm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								drivers/gpu/drm/xe/xe_nvm.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,107 @@
 | 
			
		|||
// SPDX-License-Identifier: MIT
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright(c) 2019-2025, Intel Corporation. All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/intel_dg_nvm_aux.h>
 | 
			
		||||
#include <linux/pci.h>
 | 
			
		||||
 | 
			
		||||
#include "xe_device_types.h"
 | 
			
		||||
#include "xe_nvm.h"
 | 
			
		||||
#include "xe_sriov.h"
 | 
			
		||||
 | 
			
		||||
#define GEN12_GUNIT_NVM_BASE 0x00102040
 | 
			
		||||
#define GEN12_GUNIT_NVM_SIZE 0x80
 | 
			
		||||
#define HECI_FW_STATUS_2_NVM_ACCESS_MODE BIT(3)
 | 
			
		||||
 | 
			
		||||
static const struct intel_dg_nvm_region regions[INTEL_DG_NVM_REGIONS] = {
 | 
			
		||||
	[0] = { .name = "DESCRIPTOR", },
 | 
			
		||||
	[2] = { .name = "GSC", },
 | 
			
		||||
	[9] = { .name = "PADDING", },
 | 
			
		||||
	[11] = { .name = "OptionROM", },
 | 
			
		||||
	[12] = { .name = "DAM", },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void xe_nvm_release_dev(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int xe_nvm_init(struct xe_device *xe)
 | 
			
		||||
{
 | 
			
		||||
	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
 | 
			
		||||
	struct auxiliary_device *aux_dev;
 | 
			
		||||
	struct intel_dg_nvm_dev *nvm;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (!xe->info.has_gsc_nvm)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* No access to internal NVM from VFs */
 | 
			
		||||
	if (IS_SRIOV_VF(xe))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* Nvm pointer should be NULL here */
 | 
			
		||||
	if (WARN_ON(xe->nvm))
 | 
			
		||||
		return -EFAULT;
 | 
			
		||||
 | 
			
		||||
	xe->nvm = kzalloc(sizeof(*nvm), GFP_KERNEL);
 | 
			
		||||
	if (!xe->nvm)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	nvm = xe->nvm;
 | 
			
		||||
 | 
			
		||||
	nvm->writable_override = false;
 | 
			
		||||
	nvm->bar.parent = &pdev->resource[0];
 | 
			
		||||
	nvm->bar.start = GEN12_GUNIT_NVM_BASE + pdev->resource[0].start;
 | 
			
		||||
	nvm->bar.end = nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1;
 | 
			
		||||
	nvm->bar.flags = IORESOURCE_MEM;
 | 
			
		||||
	nvm->bar.desc = IORES_DESC_NONE;
 | 
			
		||||
	nvm->regions = regions;
 | 
			
		||||
 | 
			
		||||
	aux_dev = &nvm->aux_dev;
 | 
			
		||||
 | 
			
		||||
	aux_dev->name = "nvm";
 | 
			
		||||
	aux_dev->id = (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev);
 | 
			
		||||
	aux_dev->dev.parent = &pdev->dev;
 | 
			
		||||
	aux_dev->dev.release = xe_nvm_release_dev;
 | 
			
		||||
 | 
			
		||||
	ret = auxiliary_device_init(aux_dev);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		drm_err(&xe->drm, "xe-nvm aux init failed %d\n", ret);
 | 
			
		||||
		goto err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = auxiliary_device_add(aux_dev);
 | 
			
		||||
	if (ret) {
 | 
			
		||||
		drm_err(&xe->drm, "xe-nvm aux add failed %d\n", ret);
 | 
			
		||||
		auxiliary_device_uninit(aux_dev);
 | 
			
		||||
		goto err;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
err:
 | 
			
		||||
	kfree(nvm);
 | 
			
		||||
	xe->nvm = NULL;
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void xe_nvm_fini(struct xe_device *xe)
 | 
			
		||||
{
 | 
			
		||||
	struct intel_dg_nvm_dev *nvm = xe->nvm;
 | 
			
		||||
 | 
			
		||||
	if (!xe->info.has_gsc_nvm)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* No access to internal NVM from VFs */
 | 
			
		||||
	if (IS_SRIOV_VF(xe))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* Nvm pointer should not be NULL here */
 | 
			
		||||
	if (WARN_ON(!nvm))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	auxiliary_device_delete(&nvm->aux_dev);
 | 
			
		||||
	auxiliary_device_uninit(&nvm->aux_dev);
 | 
			
		||||
	kfree(nvm);
 | 
			
		||||
	xe->nvm = NULL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								drivers/gpu/drm/xe/xe_nvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								drivers/gpu/drm/xe/xe_nvm.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
/* SPDX-License-Identifier: MIT */
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright(c) 2019-2025 Intel Corporation. All rights reserved.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __XE_NVM_H__
 | 
			
		||||
#define __XE_NVM_H__
 | 
			
		||||
 | 
			
		||||
struct xe_device;
 | 
			
		||||
 | 
			
		||||
int xe_nvm_init(struct xe_device *xe);
 | 
			
		||||
 | 
			
		||||
void xe_nvm_fini(struct xe_device *xe);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +63,7 @@ struct xe_device_desc {
 | 
			
		|||
 | 
			
		||||
	u8 has_display:1;
 | 
			
		||||
	u8 has_fan_control:1;
 | 
			
		||||
	u8 has_gsc_nvm:1;
 | 
			
		||||
	u8 has_heci_gscfi:1;
 | 
			
		||||
	u8 has_heci_cscfi:1;
 | 
			
		||||
	u8 has_llc:1;
 | 
			
		||||
| 
						 | 
				
			
			@ -272,6 +273,7 @@ static const struct xe_device_desc dg1_desc = {
 | 
			
		|||
	PLATFORM(DG1),
 | 
			
		||||
	.dma_mask_size = 39,
 | 
			
		||||
	.has_display = true,
 | 
			
		||||
	.has_gsc_nvm = 1,
 | 
			
		||||
	.has_heci_gscfi = 1,
 | 
			
		||||
	.require_force_probe = true,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -283,6 +285,7 @@ static const u16 dg2_g12_ids[] = { INTEL_DG2_G12_IDS(NOP), 0 };
 | 
			
		|||
#define DG2_FEATURES \
 | 
			
		||||
	DGFX_FEATURES, \
 | 
			
		||||
	PLATFORM(DG2), \
 | 
			
		||||
	.has_gsc_nvm = 1, \
 | 
			
		||||
	.has_heci_gscfi = 1, \
 | 
			
		||||
	.subplatforms = (const struct xe_subplatform_desc[]) { \
 | 
			
		||||
		{ XE_SUBPLATFORM_DG2_G10, "G10", dg2_g10_ids }, \
 | 
			
		||||
| 
						 | 
				
			
			@ -319,6 +322,7 @@ static const __maybe_unused struct xe_device_desc pvc_desc = {
 | 
			
		|||
	PLATFORM(PVC),
 | 
			
		||||
	.dma_mask_size = 52,
 | 
			
		||||
	.has_display = false,
 | 
			
		||||
	.has_gsc_nvm = 1,
 | 
			
		||||
	.has_heci_gscfi = 1,
 | 
			
		||||
	.max_remote_tiles = 1,
 | 
			
		||||
	.require_force_probe = true,
 | 
			
		||||
| 
						 | 
				
			
			@ -349,6 +353,7 @@ static const struct xe_device_desc bmg_desc = {
 | 
			
		|||
	.has_display = true,
 | 
			
		||||
	.has_fan_control = true,
 | 
			
		||||
	.has_mbx_power_limits = true,
 | 
			
		||||
	.has_gsc_nvm = 1,
 | 
			
		||||
	.has_heci_cscfi = 1,
 | 
			
		||||
	.needs_scratch = true,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -592,6 +597,7 @@ static int xe_info_init_early(struct xe_device *xe,
 | 
			
		|||
	xe->info.is_dgfx = desc->is_dgfx;
 | 
			
		||||
	xe->info.has_fan_control = desc->has_fan_control;
 | 
			
		||||
	xe->info.has_mbx_power_limits = desc->has_mbx_power_limits;
 | 
			
		||||
	xe->info.has_gsc_nvm = desc->has_gsc_nvm;
 | 
			
		||||
	xe->info.has_heci_gscfi = desc->has_heci_gscfi;
 | 
			
		||||
	xe->info.has_heci_cscfi = desc->has_heci_cscfi;
 | 
			
		||||
	xe->info.has_llc = desc->has_llc;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue