File Index
Files and directories
Sign in
FILE

xe_nvm.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/xe/xe_nvm.c 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.h"
 10#include "xe_device_types.h"
 11#include "xe_mmio.h"
 12#include "xe_nvm.h"
 13#include "regs/xe_gsc_regs.h"
 14#include "xe_sriov.h"
 15
 16#define GEN12_GUNIT_NVM_BASE 0x00102040
 17#define GEN12_DEBUG_NVM_BASE 0x00101018
 18
 19#define GEN12_CNTL_PROTECTED_NVM_REG 0x0010100C
 20
 21#define GEN12_GUNIT_NVM_SIZE 0x80
 22#define GEN12_DEBUG_NVM_SIZE 0x4
 23
 24#define NVM_NON_POSTED_ERASE_CHICKEN_BIT BIT(13)
 25
 26#define HECI_FW_STATUS_2_NVM_ACCESS_MODE BIT(3)
 27
 28static const struct intel_dg_nvm_region regions[INTEL_DG_NVM_REGIONS] = {
 29	[0] = { .name = "DESCRIPTOR", },
 30	[2] = { .name = "GSC", },
 31	[9] = { .name = "PADDING", },
 32	[11] = { .name = "OptionROM", },
 33	[12] = { .name = "DAM", },
 34};
 35
 36static void xe_nvm_release_dev(struct device *dev)
 37{
 38	struct auxiliary_device *aux = container_of(dev, struct auxiliary_device, dev);
 39	struct intel_dg_nvm_dev *nvm = container_of(aux, struct intel_dg_nvm_dev, aux_dev);
 40
 41	kfree(nvm);
 42}
 43
 44static bool xe_nvm_non_posted_erase(struct xe_device *xe)
 45{
 46	struct xe_mmio *mmio = xe_root_tile_mmio(xe);
 47
 48	if (xe->info.platform != XE_BATTLEMAGE)
 49		return false;
 50	return !(xe_mmio_read32(mmio, XE_REG(GEN12_CNTL_PROTECTED_NVM_REG)) &
 51		 NVM_NON_POSTED_ERASE_CHICKEN_BIT);
 52}
 53
 54static bool xe_nvm_writable_override(struct xe_device *xe)
 55{
 56	struct xe_mmio *mmio = xe_root_tile_mmio(xe);
 57	bool writable_override;
 58	resource_size_t base;
 59
 60	switch (xe->info.platform) {
 61	case XE_BATTLEMAGE:
 62		base = DG2_GSC_HECI2_BASE;
 63		break;
 64	case XE_PVC:
 65		base = PVC_GSC_HECI2_BASE;
 66		break;
 67	case XE_DG2:
 68		base = DG2_GSC_HECI2_BASE;
 69		break;
 70	case XE_DG1:
 71		base = DG1_GSC_HECI2_BASE;
 72		break;
 73	default:
 74		drm_err(&xe->drm, "Unknown platform\n");
 75		return true;
 76	}
 77
 78	writable_override =
 79		!(xe_mmio_read32(mmio, HECI_FWSTS2(base)) &
 80		  HECI_FW_STATUS_2_NVM_ACCESS_MODE);
 81	if (writable_override)
 82		drm_info(&xe->drm, "NVM access overridden by jumper\n");
 83	return writable_override;
 84}
 85
 86static void xe_nvm_fini(void *arg)
 87{
 88	struct xe_device *xe = arg;
 89	struct intel_dg_nvm_dev *nvm = xe->nvm;
 90
 91	if (!xe->info.has_gsc_nvm)
 92		return;
 93
 94	/* No access to internal NVM from VFs */
 95	if (IS_SRIOV_VF(xe))
 96		return;
 97
 98	/* Nvm pointer should not be NULL here */
 99	if (WARN_ON(!nvm))
100		return;
101
102	auxiliary_device_delete(&nvm->aux_dev);
103	auxiliary_device_uninit(&nvm->aux_dev);
104	xe->nvm = NULL;
105}
106
107int xe_nvm_init(struct xe_device *xe)
108{
109	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
110	struct auxiliary_device *aux_dev;
111	struct intel_dg_nvm_dev *nvm;
112	int ret;
113
114	if (!xe->info.has_gsc_nvm)
115		return 0;
116
117	/* No access to internal NVM from VFs */
118	if (IS_SRIOV_VF(xe))
119		return 0;
120
121	/* Nvm pointer should be NULL here */
122	if (WARN_ON(xe->nvm))
123		return -EFAULT;
124
125	xe->nvm = kzalloc(sizeof(*nvm), GFP_KERNEL);
126	if (!xe->nvm)
127		return -ENOMEM;
128
129	nvm = xe->nvm;
130
131	nvm->writable_override = xe_nvm_writable_override(xe);
132	nvm->non_posted_erase = xe_nvm_non_posted_erase(xe);
133	nvm->bar.parent = &pdev->resource[0];
134	nvm->bar.start = GEN12_GUNIT_NVM_BASE + pdev->resource[0].start;
135	nvm->bar.end = nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1;
136	nvm->bar.flags = IORESOURCE_MEM;
137	nvm->bar.desc = IORES_DESC_NONE;
138	nvm->regions = regions;
139
140	nvm->bar2.parent = &pdev->resource[0];
141	nvm->bar2.start = GEN12_DEBUG_NVM_BASE + pdev->resource[0].start;
142	nvm->bar2.end = nvm->bar2.start + GEN12_DEBUG_NVM_SIZE - 1;
143	nvm->bar2.flags = IORESOURCE_MEM;
144	nvm->bar2.desc = IORES_DESC_NONE;
145
146	aux_dev = &nvm->aux_dev;
147
148	aux_dev->name = "nvm";
149	aux_dev->id = (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev);
150	aux_dev->dev.parent = &pdev->dev;
151	aux_dev->dev.release = xe_nvm_release_dev;
152
153	ret = auxiliary_device_init(aux_dev);
154	if (ret) {
155		drm_err(&xe->drm, "xe-nvm aux init failed %d\n", ret);
156		kfree(nvm);
157		xe->nvm = NULL;
158		return ret;
159	}
160
161	ret = auxiliary_device_add(aux_dev);
162	if (ret) {
163		drm_err(&xe->drm, "xe-nvm aux add failed %d\n", ret);
164		auxiliary_device_uninit(aux_dev);
165		xe->nvm = NULL;
166		return ret;
167	}
168	return devm_add_action_or_reset(xe->drm.dev, xe_nvm_fini, xe);
169}
~/ Read-only file preview.