Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alexander Usyskin and committed by
Rodrigo Vivi
c28bfb10 4b93f5fc

+140
+1
drivers/gpu/drm/xe/Makefile
··· 80 80 xe_mmio.o \ 81 81 xe_mocs.o \ 82 82 xe_module.o \ 83 + xe_nvm.o \ 83 84 xe_oa.o \ 84 85 xe_observation.o \ 85 86 xe_pat.o \
+5
drivers/gpu/drm/xe/xe_device.c
··· 46 46 #include "xe_memirq.h" 47 47 #include "xe_mmio.h" 48 48 #include "xe_module.h" 49 + #include "xe_nvm.h" 49 50 #include "xe_oa.h" 50 51 #include "xe_observation.h" 51 52 #include "xe_pat.h" ··· 882 881 return err; 883 882 } 884 883 884 + xe_nvm_init(xe); 885 + 885 886 err = xe_heci_gsc_init(xe); 886 887 if (err) 887 888 return err; ··· 940 937 void xe_device_remove(struct xe_device *xe) 941 938 { 942 939 xe_display_unregister(xe); 940 + 941 + xe_nvm_fini(xe); 943 942 944 943 drm_dev_unplug(&xe->drm); 945 944
+6
drivers/gpu/drm/xe/xe_device_types.h
··· 32 32 33 33 struct dram_info; 34 34 struct intel_display; 35 + struct intel_dg_nvm_dev; 35 36 struct xe_ggtt; 36 37 struct xe_pat_ops; 37 38 struct xe_pxp; ··· 317 316 u8 has_fan_control:1; 318 317 /** @info.has_flat_ccs: Whether flat CCS metadata is used */ 319 318 u8 has_flat_ccs:1; 319 + /** @info.has_gsc_nvm: Device has gsc non-volatile memory */ 320 + u8 has_gsc_nvm:1; 320 321 /** @info.has_heci_cscfi: device has heci cscfi */ 321 322 u8 has_heci_cscfi:1; 322 323 /** @info.has_heci_gscfi: device has heci gscfi */ ··· 551 548 552 549 /** @heci_gsc: graphics security controller */ 553 550 struct xe_heci_gsc heci_gsc; 551 + 552 + /** @nvm: discrete graphics non-volatile memory */ 553 + struct intel_dg_nvm_dev *nvm; 554 554 555 555 /** @oa: oa observation subsystem */ 556 556 struct xe_oa oa;
+107
drivers/gpu/drm/xe/xe_nvm.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright(c) 2019-2025, Intel Corporation. All rights reserved. 4 + */ 5 + 6 + #include <linux/intel_dg_nvm_aux.h> 7 + #include <linux/pci.h> 8 + 9 + #include "xe_device_types.h" 10 + #include "xe_nvm.h" 11 + #include "xe_sriov.h" 12 + 13 + #define GEN12_GUNIT_NVM_BASE 0x00102040 14 + #define GEN12_GUNIT_NVM_SIZE 0x80 15 + #define HECI_FW_STATUS_2_NVM_ACCESS_MODE BIT(3) 16 + 17 + static const struct intel_dg_nvm_region regions[INTEL_DG_NVM_REGIONS] = { 18 + [0] = { .name = "DESCRIPTOR", }, 19 + [2] = { .name = "GSC", }, 20 + [9] = { .name = "PADDING", }, 21 + [11] = { .name = "OptionROM", }, 22 + [12] = { .name = "DAM", }, 23 + }; 24 + 25 + static void xe_nvm_release_dev(struct device *dev) 26 + { 27 + } 28 + 29 + int xe_nvm_init(struct xe_device *xe) 30 + { 31 + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 32 + struct auxiliary_device *aux_dev; 33 + struct intel_dg_nvm_dev *nvm; 34 + int ret; 35 + 36 + if (!xe->info.has_gsc_nvm) 37 + return 0; 38 + 39 + /* No access to internal NVM from VFs */ 40 + if (IS_SRIOV_VF(xe)) 41 + return 0; 42 + 43 + /* Nvm pointer should be NULL here */ 44 + if (WARN_ON(xe->nvm)) 45 + return -EFAULT; 46 + 47 + xe->nvm = kzalloc(sizeof(*nvm), GFP_KERNEL); 48 + if (!xe->nvm) 49 + return -ENOMEM; 50 + 51 + nvm = xe->nvm; 52 + 53 + nvm->writable_override = false; 54 + nvm->bar.parent = &pdev->resource[0]; 55 + nvm->bar.start = GEN12_GUNIT_NVM_BASE + pdev->resource[0].start; 56 + nvm->bar.end = nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1; 57 + nvm->bar.flags = IORESOURCE_MEM; 58 + nvm->bar.desc = IORES_DESC_NONE; 59 + nvm->regions = regions; 60 + 61 + aux_dev = &nvm->aux_dev; 62 + 63 + aux_dev->name = "nvm"; 64 + aux_dev->id = (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev); 65 + aux_dev->dev.parent = &pdev->dev; 66 + aux_dev->dev.release = xe_nvm_release_dev; 67 + 68 + ret = auxiliary_device_init(aux_dev); 69 + if (ret) { 70 + drm_err(&xe->drm, "xe-nvm aux init failed %d\n", ret); 71 + goto err; 72 + } 73 + 74 + ret = auxiliary_device_add(aux_dev); 75 + if (ret) { 76 + drm_err(&xe->drm, "xe-nvm aux add failed %d\n", ret); 77 + auxiliary_device_uninit(aux_dev); 78 + goto err; 79 + } 80 + return 0; 81 + 82 + err: 83 + kfree(nvm); 84 + xe->nvm = NULL; 85 + return ret; 86 + } 87 + 88 + void xe_nvm_fini(struct xe_device *xe) 89 + { 90 + struct intel_dg_nvm_dev *nvm = xe->nvm; 91 + 92 + if (!xe->info.has_gsc_nvm) 93 + return; 94 + 95 + /* No access to internal NVM from VFs */ 96 + if (IS_SRIOV_VF(xe)) 97 + return; 98 + 99 + /* Nvm pointer should not be NULL here */ 100 + if (WARN_ON(!nvm)) 101 + return; 102 + 103 + auxiliary_device_delete(&nvm->aux_dev); 104 + auxiliary_device_uninit(&nvm->aux_dev); 105 + kfree(nvm); 106 + xe->nvm = NULL; 107 + }
+15
drivers/gpu/drm/xe/xe_nvm.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright(c) 2019-2025 Intel Corporation. All rights reserved. 4 + */ 5 + 6 + #ifndef __XE_NVM_H__ 7 + #define __XE_NVM_H__ 8 + 9 + struct xe_device; 10 + 11 + int xe_nvm_init(struct xe_device *xe); 12 + 13 + void xe_nvm_fini(struct xe_device *xe); 14 + 15 + #endif
+6
drivers/gpu/drm/xe/xe_pci.c
··· 63 63 64 64 u8 has_display:1; 65 65 u8 has_fan_control:1; 66 + u8 has_gsc_nvm:1; 66 67 u8 has_heci_gscfi:1; 67 68 u8 has_heci_cscfi:1; 68 69 u8 has_llc:1; ··· 273 272 PLATFORM(DG1), 274 273 .dma_mask_size = 39, 275 274 .has_display = true, 275 + .has_gsc_nvm = 1, 276 276 .has_heci_gscfi = 1, 277 277 .require_force_probe = true, 278 278 }; ··· 285 283 #define DG2_FEATURES \ 286 284 DGFX_FEATURES, \ 287 285 PLATFORM(DG2), \ 286 + .has_gsc_nvm = 1, \ 288 287 .has_heci_gscfi = 1, \ 289 288 .subplatforms = (const struct xe_subplatform_desc[]) { \ 290 289 { XE_SUBPLATFORM_DG2_G10, "G10", dg2_g10_ids }, \ ··· 322 319 PLATFORM(PVC), 323 320 .dma_mask_size = 52, 324 321 .has_display = false, 322 + .has_gsc_nvm = 1, 325 323 .has_heci_gscfi = 1, 326 324 .max_remote_tiles = 1, 327 325 .require_force_probe = true, ··· 353 349 .has_display = true, 354 350 .has_fan_control = true, 355 351 .has_mbx_power_limits = true, 352 + .has_gsc_nvm = 1, 356 353 .has_heci_cscfi = 1, 357 354 .needs_scratch = true, 358 355 }; ··· 597 592 xe->info.is_dgfx = desc->is_dgfx; 598 593 xe->info.has_fan_control = desc->has_fan_control; 599 594 xe->info.has_mbx_power_limits = desc->has_mbx_power_limits; 595 + xe->info.has_gsc_nvm = desc->has_gsc_nvm; 600 596 xe->info.has_heci_gscfi = desc->has_heci_gscfi; 601 597 xe->info.has_heci_cscfi = desc->has_heci_cscfi; 602 598 xe->info.has_llc = desc->has_llc;