Unverified Commit c28bfb10 authored by Alexander Usyskin's avatar Alexander Usyskin Committed by Rodrigo Vivi
Browse files

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: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Acked-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Link: https://lore.kernel.org/r/20250617145159.3803852-7-alexander.usyskin@intel.com


Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent 4b93f5fc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 \
+5 −0
Original line number Diff line number Diff line
@@ -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);
+6 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
// 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 −0
Original line number Diff line number Diff line
/* 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
Loading