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_mmio.h" 11 #include "xe_nvm.h" 12 #include "xe_pcode_api.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 28 static 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 36 static 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 44 static bool xe_nvm_non_posted_erase(struct xe_device *xe) 45 { 46 struct xe_mmio *mmio = xe_root_tile_mmio(xe); 47 48 switch (xe->info.platform) { 49 case XE_CRESCENTISLAND: 50 case XE_BATTLEMAGE: 51 return !(xe_mmio_read32(mmio, XE_REG(GEN12_CNTL_PROTECTED_NVM_REG)) & 52 NVM_NON_POSTED_ERASE_CHICKEN_BIT); 53 default: 54 return false; 55 } 56 } 57 58 static bool xe_nvm_writable_override(struct xe_device *xe) 59 { 60 struct xe_mmio *mmio = xe_root_tile_mmio(xe); 61 bool writable_override; 62 struct xe_reg reg; 63 u32 test_bit, test_val; 64 65 switch (xe->info.platform) { 66 case XE_CRESCENTISLAND: 67 reg = PCODE_SCRATCH(0); 68 test_bit = FDO_MODE; 69 test_val = FDO_MODE; 70 break; 71 case XE_BATTLEMAGE: 72 reg = HECI_FWSTS2(DG2_GSC_HECI2_BASE); 73 test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE; 74 test_val = 0; 75 break; 76 case XE_PVC: 77 reg = HECI_FWSTS2(PVC_GSC_HECI2_BASE); 78 test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE; 79 test_val = 0; 80 break; 81 case XE_DG2: 82 reg = HECI_FWSTS2(DG2_GSC_HECI2_BASE); 83 test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE; 84 test_val = 0; 85 break; 86 case XE_DG1: 87 reg = HECI_FWSTS2(DG1_GSC_HECI2_BASE); 88 test_bit = HECI_FW_STATUS_2_NVM_ACCESS_MODE; 89 test_val = 0; 90 break; 91 default: 92 drm_err(&xe->drm, "Unknown platform\n"); 93 return true; 94 } 95 96 writable_override = (xe_mmio_read32(mmio, reg) & test_bit) == test_val; 97 if (writable_override) 98 drm_info(&xe->drm, "NVM access overridden by jumper\n"); 99 return writable_override; 100 } 101 102 static void xe_nvm_fini(void *arg) 103 { 104 struct xe_device *xe = arg; 105 struct intel_dg_nvm_dev *nvm = xe->nvm; 106 107 if (!xe->info.has_gsc_nvm) 108 return; 109 110 /* No access to internal NVM from VFs */ 111 if (IS_SRIOV_VF(xe)) 112 return; 113 114 /* Nvm pointer should not be NULL here */ 115 if (WARN_ON(!nvm)) 116 return; 117 118 auxiliary_device_delete(&nvm->aux_dev); 119 auxiliary_device_uninit(&nvm->aux_dev); 120 xe->nvm = NULL; 121 } 122 123 int xe_nvm_init(struct xe_device *xe) 124 { 125 struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 126 struct auxiliary_device *aux_dev; 127 struct intel_dg_nvm_dev *nvm; 128 int ret; 129 130 if (!xe->info.has_gsc_nvm) 131 return 0; 132 133 /* No access to internal NVM from VFs */ 134 if (IS_SRIOV_VF(xe)) 135 return 0; 136 137 /* Nvm pointer should be NULL here */ 138 if (WARN_ON(xe->nvm)) 139 return -EFAULT; 140 141 nvm = kzalloc_obj(*nvm); 142 if (!nvm) 143 return -ENOMEM; 144 145 nvm->writable_override = xe_nvm_writable_override(xe); 146 nvm->non_posted_erase = xe_nvm_non_posted_erase(xe); 147 nvm->bar.parent = &pdev->resource[0]; 148 nvm->bar.start = GEN12_GUNIT_NVM_BASE + pdev->resource[0].start; 149 nvm->bar.end = nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1; 150 nvm->bar.flags = IORESOURCE_MEM; 151 nvm->bar.desc = IORES_DESC_NONE; 152 nvm->regions = regions; 153 154 nvm->bar2.parent = &pdev->resource[0]; 155 nvm->bar2.start = GEN12_DEBUG_NVM_BASE + pdev->resource[0].start; 156 nvm->bar2.end = nvm->bar2.start + GEN12_DEBUG_NVM_SIZE - 1; 157 nvm->bar2.flags = IORESOURCE_MEM; 158 nvm->bar2.desc = IORES_DESC_NONE; 159 160 aux_dev = &nvm->aux_dev; 161 162 aux_dev->name = "nvm"; 163 aux_dev->id = (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev); 164 aux_dev->dev.parent = &pdev->dev; 165 aux_dev->dev.release = xe_nvm_release_dev; 166 167 ret = auxiliary_device_init(aux_dev); 168 if (ret) { 169 drm_err(&xe->drm, "xe-nvm aux init failed %d\n", ret); 170 kfree(nvm); 171 return ret; 172 } 173 174 ret = auxiliary_device_add(aux_dev); 175 if (ret) { 176 drm_err(&xe->drm, "xe-nvm aux add failed %d\n", ret); 177 auxiliary_device_uninit(aux_dev); 178 return ret; 179 } 180 181 xe->nvm = nvm; 182 return devm_add_action_or_reset(xe->drm.dev, xe_nvm_fini, xe); 183 } 184