From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1603922F767 for ; Tue, 3 Jun 2025 11:53:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951614; cv=none; b=Zo6jLF08Ct1N8bUCDv/eM4BenmrIFJTPjT2U7YbQkIkBUj1VxhJue/EcB32/G+PFgrQq3g2SFx6xoP2cn94Aklr2RxSDA7Hb+w/R3sfiOCuwAXUzajdk7FJjjdW3cuWN/0/xDZAtfxQ8FnSsfthKed1eE05td11JxoBxWENOpKM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951614; c=relaxed/simple; bh=aSgvIdP+ojEHSDG1CUmc1DtuQ/TYaem9leeq4TuxoWw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PeEfPN6szNraBKucj3mIHifKyzTFhWY2KUrnbKCyqrRQqFJsOdGQZ+L+rAHDCywBCsJxkTq0/FDZ/1F72ccwnWlf95Vx2Gp1DwtVcIpgF4ISzYvL7toXCPqqigvFcblAd7ZkzYNQHUBooXKH5KXOtjwqckeCBebLnb6zCpqQm+U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=nEsKA43h; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="nEsKA43h" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951613; x=1780487613; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=aSgvIdP+ojEHSDG1CUmc1DtuQ/TYaem9leeq4TuxoWw=; b=nEsKA43h9mv4LM/HHN0LMnCunbRrkg8JiW54T9W8mvHeNoSW9dvSL0jW M2hz3mt/5YwOyt5fRi7I3Ep3Tz/sEwEYPgFuDxYGxCpouTSM9IPdxNAFJ TsHk5ZZmQkNA77dTMOmhfUTv01cL1wYiOlpTmf+YAQ2Z96A2Gnv34K0s+ Mgo6YX/E04gHiBH+Qm0IFO3XobkBq/KGh+lERbu8Qo/WQTYtmeSL3eK7d mMaFV7LGFBuLqONWtKhG1ir3fjn/vWMwbZa4fv/Fw49e53PEcgDTX3MaY 5WPDQChb0QNdsfRrZClI2MMJqdzhlMJBV5rZyF34da2gydEICrBhk+GdR w==; X-CSE-ConnectionGUID: Oq6WplT6QLuPPo0Omtjlvg== X-CSE-MsgGUID: +aBcakb2RWSydRFT7TsT1g== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616410" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616410" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:33 -0700 X-CSE-ConnectionGUID: BBpA8KhjRySFtJDUbHtZCA== X-CSE-MsgGUID: g+wbcYNtTqGoOnv0jQV6Fw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993309" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:27 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin , Tomas Winkler Subject: [PATCH v12 01/10] mtd: add driver for intel graphics non-volatile memory device Date: Tue, 3 Jun 2025 14:39:44 +0300 Message-ID: <20250603113953.3599816-2-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add auxiliary driver for intel discrete graphics non-volatile memory device. CC: Lucas De Marchi Reviewed-by: Raag Jadav Reviewed-by: Rodrigo Vivi Acked-by: Miquel Raynal Co-developed-by: Tomas Winkler Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin --- MAINTAINERS | 7 ++ drivers/mtd/devices/Kconfig | 11 +++ drivers/mtd/devices/Makefile | 1 + drivers/mtd/devices/mtd_intel_dg.c | 134 +++++++++++++++++++++++++++++ include/linux/intel_dg_nvm_aux.h | 30 +++++++ 5 files changed, 183 insertions(+) create mode 100644 drivers/mtd/devices/mtd_intel_dg.c create mode 100644 include/linux/intel_dg_nvm_aux.h diff --git a/MAINTAINERS b/MAINTAINERS index 578ac300033a..7f0db98ed365 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11931,6 +11931,13 @@ L: linux-kernel@vger.kernel.org S: Supported F: arch/x86/include/asm/intel-family.h =20 +INTEL DISCRETE GRAPHICS NVM MTD DRIVER +M: Alexander Usyskin +L: linux-mtd@lists.infradead.org +S: Supported +F: drivers/mtd/devices/mtd_intel_dg.c +F: include/linux/intel_dg_nvm_aux.h + INTEL DRM DISPLAY FOR XE AND I915 DRIVERS M: Jani Nikula M: Rodrigo Vivi diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index ff2f9e55ef28..59be6d3f0d32 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -183,6 +183,17 @@ config MTD_POWERNV_FLASH platforms from Linux. This device abstracts away the firmware interface for flash access. =20 +config MTD_INTEL_DG + tristate "Intel Discrete Graphics non-volatile memory driver" + depends on AUXILIARY_BUS + depends on MTD + help + This provides an MTD device to access Intel Discrete Graphics + non-volatile memory. + + To compile this driver as a module, choose M here: the module + will be called mtd-intel-dg. + comment "Disk-On-Chip Device Drivers" =20 config MTD_DOCG3 diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index d11eb2b8b6f8..9fe4ce9cffde 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_MTD_SST25L) +=3D sst25l.o obj-$(CONFIG_MTD_BCM47XXSFLASH) +=3D bcm47xxsflash.o obj-$(CONFIG_MTD_ST_SPI_FSM) +=3D st_spi_fsm.o obj-$(CONFIG_MTD_POWERNV_FLASH) +=3D powernv_flash.o +obj-$(CONFIG_MTD_INTEL_DG) +=3D mtd_intel_dg.o =20 =20 CFLAGS_docg3.o +=3D -I$(src) diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_i= ntel_dg.c new file mode 100644 index 000000000000..c2d0dbfb0378 --- /dev/null +++ b/drivers/mtd/devices/mtd_intel_dg.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright(c) 2019-2025, Intel Corporation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct intel_dg_nvm { + struct kref refcnt; + void __iomem *base; + size_t size; + unsigned int nregions; + struct { + const char *name; + u8 id; + u64 offset; + u64 size; + } regions[] __counted_by(nregions); +}; + +static void intel_dg_nvm_release(struct kref *kref) +{ + struct intel_dg_nvm *nvm =3D container_of(kref, struct intel_dg_nvm, refc= nt); + int i; + + pr_debug("freeing intel_dg nvm\n"); + for (i =3D 0; i < nvm->nregions; i++) + kfree(nvm->regions[i].name); + kfree(nvm); +} + +static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev, + const struct auxiliary_device_id *aux_dev_id) +{ + struct intel_dg_nvm_dev *invm =3D auxiliary_dev_to_intel_dg_nvm_dev(aux_d= ev); + struct intel_dg_nvm *nvm; + struct device *device; + unsigned int nregions; + unsigned int i, n; + int ret; + + device =3D &aux_dev->dev; + + /* count available regions */ + for (nregions =3D 0, i =3D 0; i < INTEL_DG_NVM_REGIONS; i++) { + if (invm->regions[i].name) + nregions++; + } + + if (!nregions) { + dev_err(device, "no regions defined\n"); + return -ENODEV; + } + + nvm =3D kzalloc(struct_size(nvm, regions, nregions), GFP_KERNEL); + if (!nvm) + return -ENOMEM; + + kref_init(&nvm->refcnt); + + for (n =3D 0, i =3D 0; i < INTEL_DG_NVM_REGIONS; i++) { + if (!invm->regions[i].name) + continue; + + char *name =3D kasprintf(GFP_KERNEL, "%s.%s", + dev_name(&aux_dev->dev), invm->regions[i].name); + if (!name) + continue; + nvm->regions[n].name =3D name; + nvm->regions[n].id =3D i; + n++; + } + nvm->nregions =3D n; /* in case where kasprintf fail */ + + nvm->base =3D devm_ioremap_resource(device, &invm->bar); + if (IS_ERR(nvm->base)) { + ret =3D PTR_ERR(nvm->base); + goto err; + } + + dev_set_drvdata(&aux_dev->dev, nvm); + + return 0; + +err: + kref_put(&nvm->refcnt, intel_dg_nvm_release); + return ret; +} + +static void intel_dg_mtd_remove(struct auxiliary_device *aux_dev) +{ + struct intel_dg_nvm *nvm =3D dev_get_drvdata(&aux_dev->dev); + + if (!nvm) + return; + + dev_set_drvdata(&aux_dev->dev, NULL); + + kref_put(&nvm->refcnt, intel_dg_nvm_release); +} + +static const struct auxiliary_device_id intel_dg_mtd_id_table[] =3D { + { + .name =3D "i915.nvm", + }, + { + .name =3D "xe.nvm", + }, + { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(auxiliary, intel_dg_mtd_id_table); + +static struct auxiliary_driver intel_dg_mtd_driver =3D { + .probe =3D intel_dg_mtd_probe, + .remove =3D intel_dg_mtd_remove, + .driver =3D { + /* auxiliary_driver_register() sets .name to be the modname */ + }, + .id_table =3D intel_dg_mtd_id_table +}; +module_auxiliary_driver(intel_dg_mtd_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Intel DGFX MTD driver"); diff --git a/include/linux/intel_dg_nvm_aux.h b/include/linux/intel_dg_nvm_= aux.h new file mode 100644 index 000000000000..00b6c1301bd8 --- /dev/null +++ b/include/linux/intel_dg_nvm_aux.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright(c) 2019-2025, Intel Corporation. All rights reserved. + */ + +#ifndef __INTEL_DG_NVM_AUX_H__ +#define __INTEL_DG_NVM_AUX_H__ + +#include +#include +#include +#include + +#define INTEL_DG_NVM_REGIONS 13 + +struct intel_dg_nvm_region { + const char *name; +}; + +struct intel_dg_nvm_dev { + struct auxiliary_device aux_dev; + bool writable_override; + struct resource bar; + const struct intel_dg_nvm_region *regions; +}; + +#define auxiliary_dev_to_intel_dg_nvm_dev(auxiliary_dev) \ + container_of(auxiliary_dev, struct intel_dg_nvm_dev, aux_dev) + +#endif /* __INTEL_DG_NVM_AUX_H__ */ --=20 2.43.0 From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9C4322DF96 for ; Tue, 3 Jun 2025 11:53:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951620; cv=none; b=OrumidXOQhRSV3j04Eugud1+Eltc5ILXL52XS9Yaz5VDkekrJzhfj0gCOdwtEb2nJdLgZUbgbWDWlIKuGQVPtbzgx53z3J3HgmXVOfujswnvFYuLRL49OXyMwMXngTIq3AQIvPRWvEWMD/7GYq7GIMgNijOV/hSsXExzNp67q5o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951620; c=relaxed/simple; bh=GFube+gC6502VTBuZaY4++giPU/6FLO2ZUzV5+IsC6Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=orIMB9tjLoLZf+/R9duQYgBE8U+KfgVqBR8sGoE6PRXRct6Vz6pYTnHEujV9ABC3mHa0vVNXZbdiSWkskHN/X5EUtyu2KzvdA2sAJR+2dWHKVQ4lqBPPeuvvvV1q7bN7i6u7xYMMkv/1G+7XMnquQC9augXkj1gBTkNRiSUkXjA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Kck2CUmh; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Kck2CUmh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951619; x=1780487619; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GFube+gC6502VTBuZaY4++giPU/6FLO2ZUzV5+IsC6Q=; b=Kck2CUmhjrgqEXScbCPcJ1zgARVDmlIDgekCSiPtmSwtGU+O3FrY4e1+ V7ntXCkRgkb08M4OIHeCD2FxCZUaad0dAkDj3qc8W4peINf5j8Se+BU9L qaKn25WGyeB5db6hNzcAzxnbxNlQQZyKoOUNJ8dxIFBld90vr2oOo8u6f N1E04iY1xG8llwPBDMNLDPDBDTGiH4R6kwtDmDWDV7Xbuq9CNF4MEmd24 KNC82DIqtT1orVJUkPvTn7/81mamWaYyhSgDuzINjqFoVsfkmf/UriWBk iS8dHJWYgBuo8ZosKOHdsMXMV3+VuuF/IxJioV4CpN7Jo3bHofMed4dID A==; X-CSE-ConnectionGUID: FPDUePM3T3uORR5W1bMc1A== X-CSE-MsgGUID: ngxbdLn5SgqDCNyG62retg== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616429" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616429" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:38 -0700 X-CSE-ConnectionGUID: ZRHBYvqUTdqXQmWc/47hlg== X-CSE-MsgGUID: 8hcx0x7PRR+IuQ+8qpjsWg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993325" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:33 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin , Tomas Winkler Subject: [PATCH v12 02/10] mtd: intel-dg: implement region enumeration Date: Tue, 3 Jun 2025 14:39:45 +0300 Message-ID: <20250603113953.3599816-3-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In intel-dg, there is no access to the spi controller, the information is extracted from the descriptor region. CC: Lucas De Marchi Reviewed-by: Raag Jadav Reviewed-by: Rodrigo Vivi Acked-by: Miquel Raynal Co-developed-by: Tomas Winkler Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin --- drivers/mtd/devices/mtd_intel_dg.c | 206 +++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_i= ntel_dg.c index c2d0dbfb0378..478dd2b158e3 100644 --- a/drivers/mtd/devices/mtd_intel_dg.c +++ b/drivers/mtd/devices/mtd_intel_dg.c @@ -3,6 +3,8 @@ * Copyright(c) 2019-2025, Intel Corporation. All rights reserved. */ =20 +#include +#include #include #include #include @@ -22,9 +24,207 @@ struct intel_dg_nvm { u8 id; u64 offset; u64 size; + unsigned int is_readable:1; + unsigned int is_writable:1; } regions[] __counted_by(nregions); }; =20 +#define NVM_TRIGGER_REG 0x00000000 +#define NVM_VALSIG_REG 0x00000010 +#define NVM_ADDRESS_REG 0x00000040 +#define NVM_REGION_ID_REG 0x00000044 +/* + * [15:0]-Erase size =3D 0x0010 4K 0x0080 32K 0x0100 64K + * [23:16]-Reserved + * [31:24]-Erase MEM RegionID + */ +#define NVM_ERASE_REG 0x00000048 +#define NVM_ACCESS_ERROR_REG 0x00000070 +#define NVM_ADDRESS_ERROR_REG 0x00000074 + +/* Flash Valid Signature */ +#define NVM_FLVALSIG 0x0FF0A55A + +#define NVM_MAP_ADDR_MASK GENMASK(7, 0) +#define NVM_MAP_ADDR_SHIFT 0x00000004 + +#define NVM_REGION_ID_DESCRIPTOR 0 +/* Flash Region Base Address */ +#define NVM_FRBA 0x40 +/* Flash Region __n - Flash Descriptor Record */ +#define NVM_FLREG(__n) (NVM_FRBA + ((__n) * 4)) +/* Flash Map 1 Register */ +#define NVM_FLMAP1_REG 0x18 +#define NVM_FLMSTR4_OFFSET 0x00C + +#define NVM_ACCESS_ERROR_PCIE_MASK 0x7 + +#define NVM_FREG_BASE_MASK GENMASK(15, 0) +#define NVM_FREG_ADDR_MASK GENMASK(31, 16) +#define NVM_FREG_ADDR_SHIFT 12 +#define NVM_FREG_MIN_REGION_SIZE 0xFFF + +static inline void idg_nvm_set_region_id(struct intel_dg_nvm *nvm, u8 regi= on) +{ + iowrite32((u32)region, nvm->base + NVM_REGION_ID_REG); +} + +static inline u32 idg_nvm_error(struct intel_dg_nvm *nvm) +{ + void __iomem *base =3D nvm->base; + + u32 reg =3D ioread32(base + NVM_ACCESS_ERROR_REG) & NVM_ACCESS_ERROR_PCIE= _MASK; + + /* reset error bits */ + if (reg) + iowrite32(reg, base + NVM_ACCESS_ERROR_REG); + + return reg; +} + +static inline u32 idg_nvm_read32(struct intel_dg_nvm *nvm, u32 address) +{ + void __iomem *base =3D nvm->base; + + iowrite32(address, base + NVM_ADDRESS_REG); + + return ioread32(base + NVM_TRIGGER_REG); +} + +static int idg_nvm_get_access_map(struct intel_dg_nvm *nvm, u32 *access_ma= p) +{ + u32 fmstr4_addr; + u32 fmstr4; + u32 flmap1; + u32 fmba; + + idg_nvm_set_region_id(nvm, NVM_REGION_ID_DESCRIPTOR); + + flmap1 =3D idg_nvm_read32(nvm, NVM_FLMAP1_REG); + if (idg_nvm_error(nvm)) + return -EIO; + /* Get Flash Master Baser Address (FMBA) */ + fmba =3D (FIELD_GET(NVM_MAP_ADDR_MASK, flmap1) << NVM_MAP_ADDR_SHIFT); + fmstr4_addr =3D fmba + NVM_FLMSTR4_OFFSET; + + fmstr4 =3D idg_nvm_read32(nvm, fmstr4_addr); + if (idg_nvm_error(nvm)) + return -EIO; + + *access_map =3D fmstr4; + return 0; +} + +/* + * Region read/write access encoded in the access map + * in the following order from the lower bit: + * [3:0] regions 12-15 read state + * [7:4] regions 12-15 write state + * [19:8] regions 0-11 read state + * [31:20] regions 0-11 write state + */ +static bool idg_nvm_region_readable(u32 access_map, u8 region) +{ + if (region < 12) + return access_map & BIT(region + 8); /* [19:8] */ + else + return access_map & BIT(region - 12); /* [3:0] */ +} + +static bool idg_nvm_region_writable(u32 access_map, u8 region) +{ + if (region < 12) + return access_map & BIT(region + 20); /* [31:20] */ + else + return access_map & BIT(region - 8); /* [7:4] */ +} + +static int idg_nvm_is_valid(struct intel_dg_nvm *nvm) +{ + u32 is_valid; + + idg_nvm_set_region_id(nvm, NVM_REGION_ID_DESCRIPTOR); + + is_valid =3D idg_nvm_read32(nvm, NVM_VALSIG_REG); + if (idg_nvm_error(nvm)) + return -EIO; + + if (is_valid !=3D NVM_FLVALSIG) + return -ENODEV; + + return 0; +} + +static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *devi= ce) +{ + u32 access_map =3D 0; + unsigned int i, n; + int ret; + + /* clean error register, previous errors are ignored */ + idg_nvm_error(nvm); + + ret =3D idg_nvm_is_valid(nvm); + if (ret) { + dev_err(device, "The MEM is not valid %d\n", ret); + return ret; + } + + if (idg_nvm_get_access_map(nvm, &access_map)) + return -EIO; + + for (i =3D 0, n =3D 0; i < nvm->nregions; i++) { + u32 address, base, limit, region; + u8 id =3D nvm->regions[i].id; + + address =3D NVM_FLREG(id); + region =3D idg_nvm_read32(nvm, address); + + base =3D FIELD_GET(NVM_FREG_BASE_MASK, region) << NVM_FREG_ADDR_SHIFT; + limit =3D (FIELD_GET(NVM_FREG_ADDR_MASK, region) << NVM_FREG_ADDR_SHIFT)= | + NVM_FREG_MIN_REGION_SIZE; + + dev_dbg(device, "[%d] %s: region: 0x%08X base: 0x%08x limit: 0x%08x\n", + id, nvm->regions[i].name, region, base, limit); + + if (base >=3D limit || (i > 0 && limit =3D=3D 0)) { + dev_dbg(device, "[%d] %s: disabled\n", + id, nvm->regions[i].name); + nvm->regions[i].is_readable =3D 0; + continue; + } + + if (nvm->size < limit) + nvm->size =3D limit; + + nvm->regions[i].offset =3D base; + nvm->regions[i].size =3D limit - base + 1; + /* No write access to descriptor; mask it out*/ + nvm->regions[i].is_writable =3D idg_nvm_region_writable(access_map, id); + + nvm->regions[i].is_readable =3D idg_nvm_region_readable(access_map, id); + dev_dbg(device, "Registered, %s id=3D%d offset=3D%lld size=3D%lld rd=3D%= d wr=3D%d\n", + nvm->regions[i].name, + nvm->regions[i].id, + nvm->regions[i].offset, + nvm->regions[i].size, + nvm->regions[i].is_readable, + nvm->regions[i].is_writable); + + if (nvm->regions[i].is_readable) + n++; + } + + dev_dbg(device, "Registered %d regions\n", n); + + /* Need to add 1 to the amount of memory + * so it is reported as an even block + */ + nvm->size +=3D 1; + + return n; +} + static void intel_dg_nvm_release(struct kref *kref) { struct intel_dg_nvm *nvm =3D container_of(kref, struct intel_dg_nvm, refc= nt); @@ -85,6 +285,12 @@ static int intel_dg_mtd_probe(struct auxiliary_device *= aux_dev, goto err; } =20 + ret =3D intel_dg_nvm_init(nvm, device); + if (ret < 0) { + dev_err(device, "cannot initialize nvm %d\n", ret); + goto err; + } + dev_set_drvdata(&aux_dev->dev, nvm); =20 return 0; --=20 2.43.0 From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BDECF230BC8 for ; Tue, 3 Jun 2025 11:53:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951626; cv=none; b=qaBoKk2wRMGys9P8pswkSXfEEUz6/pq9M7IO5UUZKgQTLUtxuwMYdRPFqJfiqtXuslgjRc61TEWD6EPlWqakR/uh+mDaUgEhPwOXYvCnbTF4A/WT04/a2M+8dnYiz8ZRjGgldNKsQKbjHx1HwQXPUqW3pGXRyA8tdpL0UqCMdU0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951626; c=relaxed/simple; bh=WvLWJRAv8idelb+wbiysTqm+mBTnrzkj5Bl282lOSrk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XIDTQT6ppkPFk6Hu1UXa6T76j4J7sy1pTQiPTEg/0jmw34UBk4B2QCAWhlhmONBuXndS5yxmGGs1jAXMzAH8j9jRM/lSbH7UMznoYc8tAm7PoVBkF+49XUHeQ62fl67SCZXnz4xrng3QzwtMO2msqPgN9AP2I3KKDUu41jVgMAE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=DJ9uj+RJ; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="DJ9uj+RJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951625; x=1780487625; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WvLWJRAv8idelb+wbiysTqm+mBTnrzkj5Bl282lOSrk=; b=DJ9uj+RJhuWr2PM9QjnUiWEh/MccrgkUFq4Zb+42BmEGkfXN/x91j3jt E9BSiyyLpJ/Cl70ge6fbjVVdk1q87O72oztqGiEb+SczBGQsf3yiQYipS decRH0e6HrmReR5JqSBACxhW/waA8CJQRvjyLHD8xBiO51S2XUqwbP0e/ 8g7swEbQlm2kLXp8u9zB71iXwk8Q82Cr9h3F4QwewJN0qqnVVZv+qc9Xk dvfYLEO9g/X8vHkVeoaFAJZFmfvN7MG9FnlbpbVOOCpCWhKOkNqeXbL+J VPr8wRNXclFBWsvCetCmiahCVtYQFzrbdeDlwxTjOHARM/UmOw4ss8ued Q==; X-CSE-ConnectionGUID: JH5Q8qaESfibzgHwOEYTfg== X-CSE-MsgGUID: xflXGp/pRAaa4ExPG/G63w== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616445" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616445" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:44 -0700 X-CSE-ConnectionGUID: QzKZFU9kSqqUP/lL/zSQwQ== X-CSE-MsgGUID: tvbWHSwJTRupVEC3dU8O5Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993333" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:38 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin , Tomas Winkler , Vitaly Lubart Subject: [PATCH v12 03/10] mtd: intel-dg: implement access functions Date: Tue, 3 Jun 2025 14:39:46 +0300 Message-ID: <20250603113953.3599816-4-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement read(), erase() and write() functions. CC: Lucas De Marchi CC: Rodrigo Vivi Reviewed-by: Raag Jadav Acked-by: Miquel Raynal Co-developed-by: Tomas Winkler Signed-off-by: Tomas Winkler Co-developed-by: Vitaly Lubart Signed-off-by: Vitaly Lubart Signed-off-by: Alexander Usyskin --- drivers/mtd/devices/mtd_intel_dg.c | 197 +++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_i= ntel_dg.c index 478dd2b158e3..4d6e2c009b45 100644 --- a/drivers/mtd/devices/mtd_intel_dg.c +++ b/drivers/mtd/devices/mtd_intel_dg.c @@ -5,13 +5,16 @@ =20 #include #include +#include #include #include #include +#include #include #include #include #include +#include #include =20 struct intel_dg_nvm { @@ -91,6 +94,33 @@ static inline u32 idg_nvm_read32(struct intel_dg_nvm *nv= m, u32 address) return ioread32(base + NVM_TRIGGER_REG); } =20 +static inline u64 idg_nvm_read64(struct intel_dg_nvm *nvm, u32 address) +{ + void __iomem *base =3D nvm->base; + + iowrite32(address, base + NVM_ADDRESS_REG); + + return readq(base + NVM_TRIGGER_REG); +} + +static void idg_nvm_write32(struct intel_dg_nvm *nvm, u32 address, u32 dat= a) +{ + void __iomem *base =3D nvm->base; + + iowrite32(address, base + NVM_ADDRESS_REG); + + iowrite32(data, base + NVM_TRIGGER_REG); +} + +static void idg_nvm_write64(struct intel_dg_nvm *nvm, u32 address, u64 dat= a) +{ + void __iomem *base =3D nvm->base; + + iowrite32(address, base + NVM_ADDRESS_REG); + + writeq(data, base + NVM_TRIGGER_REG); +} + static int idg_nvm_get_access_map(struct intel_dg_nvm *nvm, u32 *access_ma= p) { u32 fmstr4_addr; @@ -155,6 +185,173 @@ static int idg_nvm_is_valid(struct intel_dg_nvm *nvm) return 0; } =20 +__maybe_unused +static unsigned int idg_nvm_get_region(const struct intel_dg_nvm *nvm, lof= f_t from) +{ + unsigned int i; + + for (i =3D 0; i < nvm->nregions; i++) { + if ((nvm->regions[i].offset + nvm->regions[i].size - 1) >=3D from && + nvm->regions[i].offset <=3D from && + nvm->regions[i].size !=3D 0) + break; + } + + return i; +} + +static ssize_t idg_nvm_rewrite_partial(struct intel_dg_nvm *nvm, loff_t to, + loff_t offset, size_t len, const u32 *newdata) +{ + u32 data =3D idg_nvm_read32(nvm, to); + + if (idg_nvm_error(nvm)) + return -EIO; + + memcpy((u8 *)&data + offset, newdata, len); + + idg_nvm_write32(nvm, to, data); + if (idg_nvm_error(nvm)) + return -EIO; + + return len; +} + +__maybe_unused +static ssize_t idg_write(struct intel_dg_nvm *nvm, u8 region, + loff_t to, size_t len, const unsigned char *buf) +{ + size_t len_s =3D len; + size_t to_shift; + size_t len8; + size_t len4; + ssize_t ret; + size_t to4; + size_t i; + + idg_nvm_set_region_id(nvm, region); + + to4 =3D ALIGN_DOWN(to, sizeof(u32)); + to_shift =3D min(sizeof(u32) - ((size_t)to - to4), len); + if (to - to4) { + ret =3D idg_nvm_rewrite_partial(nvm, to4, to - to4, to_shift, (u32 *)&bu= f[0]); + if (ret < 0) + return ret; + + buf +=3D to_shift; + to +=3D to_shift; + len_s -=3D to_shift; + } + + len8 =3D ALIGN_DOWN(len_s, sizeof(u64)); + for (i =3D 0; i < len8; i +=3D sizeof(u64)) { + u64 data; + + memcpy(&data, &buf[i], sizeof(u64)); + idg_nvm_write64(nvm, to + i, data); + if (idg_nvm_error(nvm)) + return -EIO; + } + + len4 =3D len_s - len8; + if (len4 >=3D sizeof(u32)) { + u32 data; + + memcpy(&data, &buf[i], sizeof(u32)); + idg_nvm_write32(nvm, to + i, data); + if (idg_nvm_error(nvm)) + return -EIO; + i +=3D sizeof(u32); + len4 -=3D sizeof(u32); + } + + if (len4 > 0) { + ret =3D idg_nvm_rewrite_partial(nvm, to + i, 0, len4, (u32 *)&buf[i]); + if (ret < 0) + return ret; + } + + return len; +} + +__maybe_unused +static ssize_t idg_read(struct intel_dg_nvm *nvm, u8 region, + loff_t from, size_t len, unsigned char *buf) +{ + size_t len_s =3D len; + size_t from_shift; + size_t from4; + size_t len8; + size_t len4; + size_t i; + + idg_nvm_set_region_id(nvm, region); + + from4 =3D ALIGN_DOWN(from, sizeof(u32)); + from_shift =3D min(sizeof(u32) - ((size_t)from - from4), len); + + if (from - from4) { + u32 data =3D idg_nvm_read32(nvm, from4); + + if (idg_nvm_error(nvm)) + return -EIO; + memcpy(&buf[0], (u8 *)&data + (from - from4), from_shift); + len_s -=3D from_shift; + buf +=3D from_shift; + from +=3D from_shift; + } + + len8 =3D ALIGN_DOWN(len_s, sizeof(u64)); + for (i =3D 0; i < len8; i +=3D sizeof(u64)) { + u64 data =3D idg_nvm_read64(nvm, from + i); + + if (idg_nvm_error(nvm)) + return -EIO; + + memcpy(&buf[i], &data, sizeof(data)); + } + + len4 =3D len_s - len8; + if (len4 >=3D sizeof(u32)) { + u32 data =3D idg_nvm_read32(nvm, from + i); + + if (idg_nvm_error(nvm)) + return -EIO; + memcpy(&buf[i], &data, sizeof(data)); + i +=3D sizeof(u32); + len4 -=3D sizeof(u32); + } + + if (len4 > 0) { + u32 data =3D idg_nvm_read32(nvm, from + i); + + if (idg_nvm_error(nvm)) + return -EIO; + memcpy(&buf[i], &data, len4); + } + + return len; +} + +__maybe_unused +static ssize_t +idg_erase(struct intel_dg_nvm *nvm, u8 region, loff_t from, u64 len, u64 *= fail_addr) +{ + void __iomem *base =3D nvm->base; + const u32 block =3D 0x10; + u64 i; + + for (i =3D 0; i < len; i +=3D SZ_4K) { + iowrite32(from + i, base + NVM_ADDRESS_REG); + iowrite32(region << 24 | block, base + NVM_ERASE_REG); + /* Since the writes are via sgunit + * we cannot do back to back erases. + */ + msleep(50); + } + return len; +} + static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *devi= ce) { u32 access_map =3D 0; --=20 2.43.0 From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECA09230BC8 for ; Tue, 3 Jun 2025 11:53:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951632; cv=none; b=YmHZWFpdEUDyFX4HvVoAytZ1Q6lkivPuRcTMFNOhkVEv9SOj2le7+zImE/g6pt5GMcqf+pehSxVlaXTnbxcJ3UB2m+EU0JNlSgneLrju5qSmc19zCTdA7XaQYzpJSTvxAUq+LJTItiMoqcgI6m2RVDqWdAgq8eHpZQ1goA2nOZ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951632; c=relaxed/simple; bh=1rWZu6zk+/8Dn/O0RQ+wvJF7YY6eB0G1xr7Z4PhkCPE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qml13meWwL0T6/qlC7hpDRweJkbOHyX9YJNZRx8Zm7S0qibkJQYupc/9UvQsT16VypHRjs3nH+GTvMgr2H1y2ZclVVSW5SXaYqbL2ZITmX36pUPVSPQbXFHdYyWc9SuDnv2cviBxr6BqBNNRu+p2gKZJevdzha8HSICLZAT50Ec= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Ck6eac5i; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Ck6eac5i" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951631; x=1780487631; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1rWZu6zk+/8Dn/O0RQ+wvJF7YY6eB0G1xr7Z4PhkCPE=; b=Ck6eac5iwMmKjLEWFzOYb38yBNBvdYnDMp2KzcwtwLu3wFlj/q7mhg9f qugS1avbzxme6CvYJNA5OCb+40HaU7x6VVOUtxEWuQslzHGUhveyZb9gj FmWWNOGlIIq9tQPl6B9YDQHaEML3RL1fBN9Vgx+JUtL+Pq6BXb1rnIuIm baLyPCbTxxJQ2JLQ5ZE43KB8r/Gb7XbNVum/YowoMWrlhP3TXLt/Vhozm J+mZVvXd5ULchpMt2jaJyHIiSWPzMTeSHgqMswZ4WMxNek/SY606GFaZb Jsumm0vI3BTODZEyqUUE26y9GyNLzDjtFKVXtAawGIhqkow9k85rM+Ltq w==; X-CSE-ConnectionGUID: RKSvoqoSSz+9ZftxubwSFg== X-CSE-MsgGUID: LUuTFES8Qp6oPmP8iJxQKQ== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616462" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616462" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:50 -0700 X-CSE-ConnectionGUID: zc8PVXCqQFSz6+98yJLfQQ== X-CSE-MsgGUID: cczEwOWMTZ2mBHmdAgQHRw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993337" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:44 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin , Tomas Winkler , Vitaly Lubart Subject: [PATCH v12 04/10] mtd: intel-dg: register with mtd Date: Tue, 3 Jun 2025 14:39:47 +0300 Message-ID: <20250603113953.3599816-5-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Register the on-die nvm device with the mtd subsystem. Refcount nvm object on _get and _put mtd callbacks. For erase operation address and size should be 4K aligned. For write operation address and size has to be 4bytes aligned. CC: Rodrigo Vivi CC: Lucas De Marchi Reviewed-by: Raag Jadav Acked-by: Miquel Raynal Co-developed-by: Tomas Winkler Signed-off-by: Tomas Winkler Co-developed-by: Vitaly Lubart Signed-off-by: Vitaly Lubart Signed-off-by: Alexander Usyskin --- drivers/mtd/devices/mtd_intel_dg.c | 228 ++++++++++++++++++++++++++++- 1 file changed, 224 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_i= ntel_dg.c index 4d6e2c009b45..6d971fb77938 100644 --- a/drivers/mtd/devices/mtd_intel_dg.c +++ b/drivers/mtd/devices/mtd_intel_dg.c @@ -5,6 +5,7 @@ =20 #include #include +#include #include #include #include @@ -12,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -19,6 +22,8 @@ =20 struct intel_dg_nvm { struct kref refcnt; + struct mtd_info mtd; + struct mutex lock; /* region access lock */ void __iomem *base; size_t size; unsigned int nregions; @@ -185,7 +190,6 @@ static int idg_nvm_is_valid(struct intel_dg_nvm *nvm) return 0; } =20 -__maybe_unused static unsigned int idg_nvm_get_region(const struct intel_dg_nvm *nvm, lof= f_t from) { unsigned int i; @@ -217,7 +221,6 @@ static ssize_t idg_nvm_rewrite_partial(struct intel_dg_= nvm *nvm, loff_t to, return len; } =20 -__maybe_unused static ssize_t idg_write(struct intel_dg_nvm *nvm, u8 region, loff_t to, size_t len, const unsigned char *buf) { @@ -274,7 +277,6 @@ static ssize_t idg_write(struct intel_dg_nvm *nvm, u8 r= egion, return len; } =20 -__maybe_unused static ssize_t idg_read(struct intel_dg_nvm *nvm, u8 region, loff_t from, size_t len, unsigned char *buf) { @@ -333,7 +335,6 @@ static ssize_t idg_read(struct intel_dg_nvm *nvm, u8 re= gion, return len; } =20 -__maybe_unused static ssize_t idg_erase(struct intel_dg_nvm *nvm, u8 region, loff_t from, u64 len, u64 *= fail_addr) { @@ -422,6 +423,147 @@ static int intel_dg_nvm_init(struct intel_dg_nvm *nvm= , struct device *device) return n; } =20 +static int intel_dg_mtd_erase(struct mtd_info *mtd, struct erase_info *inf= o) +{ + struct intel_dg_nvm *nvm =3D mtd->priv; + size_t total_len; + unsigned int idx; + ssize_t bytes; + loff_t from; + size_t len; + u8 region; + u64 addr; + + if (WARN_ON(!nvm)) + return -EINVAL; + + if (!IS_ALIGNED(info->addr, SZ_4K) || !IS_ALIGNED(info->len, SZ_4K)) { + dev_err(&mtd->dev, "unaligned erase %llx %llx\n", + info->addr, info->len); + info->fail_addr =3D MTD_FAIL_ADDR_UNKNOWN; + return -EINVAL; + } + + total_len =3D info->len; + addr =3D info->addr; + + guard(mutex)(&nvm->lock); + + while (total_len > 0) { + if (!IS_ALIGNED(addr, SZ_4K) || !IS_ALIGNED(total_len, SZ_4K)) { + dev_err(&mtd->dev, "unaligned erase %llx %zx\n", addr, total_len); + info->fail_addr =3D addr; + return -ERANGE; + } + + idx =3D idg_nvm_get_region(nvm, addr); + if (idx >=3D nvm->nregions) { + dev_err(&mtd->dev, "out of range"); + info->fail_addr =3D MTD_FAIL_ADDR_UNKNOWN; + return -ERANGE; + } + + from =3D addr - nvm->regions[idx].offset; + region =3D nvm->regions[idx].id; + len =3D total_len; + if (len > nvm->regions[idx].size - from) + len =3D nvm->regions[idx].size - from; + + dev_dbg(&mtd->dev, "erasing region[%d] %s from %llx len %zx\n", + region, nvm->regions[idx].name, from, len); + + bytes =3D idg_erase(nvm, region, from, len, &info->fail_addr); + if (bytes < 0) { + dev_dbg(&mtd->dev, "erase failed with %zd\n", bytes); + info->fail_addr +=3D nvm->regions[idx].offset; + return bytes; + } + + addr +=3D len; + total_len -=3D len; + } + + return 0; +} + +static int intel_dg_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct intel_dg_nvm *nvm =3D mtd->priv; + unsigned int idx; + ssize_t ret; + u8 region; + + if (WARN_ON(!nvm)) + return -EINVAL; + + idx =3D idg_nvm_get_region(nvm, from); + + dev_dbg(&mtd->dev, "reading region[%d] %s from %lld len %zd\n", + nvm->regions[idx].id, nvm->regions[idx].name, from, len); + + if (idx >=3D nvm->nregions) { + dev_err(&mtd->dev, "out of range"); + return -ERANGE; + } + + from -=3D nvm->regions[idx].offset; + region =3D nvm->regions[idx].id; + if (len > nvm->regions[idx].size - from) + len =3D nvm->regions[idx].size - from; + + guard(mutex)(&nvm->lock); + + ret =3D idg_read(nvm, region, from, len, buf); + if (ret < 0) { + dev_dbg(&mtd->dev, "read failed with %zd\n", ret); + return ret; + } + + *retlen =3D ret; + + return 0; +} + +static int intel_dg_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct intel_dg_nvm *nvm =3D mtd->priv; + unsigned int idx; + ssize_t ret; + u8 region; + + if (WARN_ON(!nvm)) + return -EINVAL; + + idx =3D idg_nvm_get_region(nvm, to); + + dev_dbg(&mtd->dev, "writing region[%d] %s to %lld len %zd\n", + nvm->regions[idx].id, nvm->regions[idx].name, to, len); + + if (idx >=3D nvm->nregions) { + dev_err(&mtd->dev, "out of range"); + return -ERANGE; + } + + to -=3D nvm->regions[idx].offset; + region =3D nvm->regions[idx].id; + if (len > nvm->regions[idx].size - to) + len =3D nvm->regions[idx].size - to; + + guard(mutex)(&nvm->lock); + + ret =3D idg_write(nvm, region, to, len, buf); + if (ret < 0) { + dev_dbg(&mtd->dev, "write failed with %zd\n", ret); + return ret; + } + + *retlen =3D ret; + + return 0; +} + static void intel_dg_nvm_release(struct kref *kref) { struct intel_dg_nvm *nvm =3D container_of(kref, struct intel_dg_nvm, refc= nt); @@ -430,9 +572,78 @@ static void intel_dg_nvm_release(struct kref *kref) pr_debug("freeing intel_dg nvm\n"); for (i =3D 0; i < nvm->nregions; i++) kfree(nvm->regions[i].name); + mutex_destroy(&nvm->lock); kfree(nvm); } =20 +static int intel_dg_mtd_get_device(struct mtd_info *mtd) +{ + struct mtd_info *master =3D mtd_get_master(mtd); + struct intel_dg_nvm *nvm =3D master->priv; + + if (WARN_ON(!nvm)) + return -EINVAL; + pr_debug("get mtd %s %d\n", mtd->name, kref_read(&nvm->refcnt)); + kref_get(&nvm->refcnt); + + return 0; +} + +static void intel_dg_mtd_put_device(struct mtd_info *mtd) +{ + struct mtd_info *master =3D mtd_get_master(mtd); + struct intel_dg_nvm *nvm =3D master->priv; + + if (WARN_ON(!nvm)) + return; + pr_debug("put mtd %s %d\n", mtd->name, kref_read(&nvm->refcnt)); + kref_put(&nvm->refcnt, intel_dg_nvm_release); +} + +static int intel_dg_nvm_init_mtd(struct intel_dg_nvm *nvm, struct device *= device, + unsigned int nparts, bool writable_override) +{ + struct mtd_partition *parts =3D NULL; + unsigned int i, n; + int ret; + + dev_dbg(device, "registering with mtd\n"); + + nvm->mtd.owner =3D THIS_MODULE; + nvm->mtd.dev.parent =3D device; + nvm->mtd.flags =3D MTD_CAP_NORFLASH; + nvm->mtd.type =3D MTD_DATAFLASH; + nvm->mtd.priv =3D nvm; + nvm->mtd._write =3D intel_dg_mtd_write; + nvm->mtd._read =3D intel_dg_mtd_read; + nvm->mtd._erase =3D intel_dg_mtd_erase; + nvm->mtd._get_device =3D intel_dg_mtd_get_device; + nvm->mtd._put_device =3D intel_dg_mtd_put_device; + nvm->mtd.writesize =3D SZ_1; /* 1 byte granularity */ + nvm->mtd.erasesize =3D SZ_4K; /* 4K bytes granularity */ + nvm->mtd.size =3D nvm->size; + + parts =3D kcalloc(nvm->nregions, sizeof(*parts), GFP_KERNEL); + if (!parts) + return -ENOMEM; + + for (i =3D 0, n =3D 0; i < nvm->nregions && n < nparts; i++) { + if (!nvm->regions[i].is_readable) + continue; + parts[n].name =3D nvm->regions[i].name; + parts[n].offset =3D nvm->regions[i].offset; + parts[n].size =3D nvm->regions[i].size; + if (!nvm->regions[i].is_writable && !writable_override) + parts[n].mask_flags =3D MTD_WRITEABLE; + n++; + } + + ret =3D mtd_device_register(&nvm->mtd, parts, n); + + kfree(parts); + return ret; +} + static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev, const struct auxiliary_device_id *aux_dev_id) { @@ -461,6 +672,7 @@ static int intel_dg_mtd_probe(struct auxiliary_device *= aux_dev, return -ENOMEM; =20 kref_init(&nvm->refcnt); + mutex_init(&nvm->lock); =20 for (n =3D 0, i =3D 0; i < INTEL_DG_NVM_REGIONS; i++) { if (!invm->regions[i].name) @@ -488,6 +700,12 @@ static int intel_dg_mtd_probe(struct auxiliary_device = *aux_dev, goto err; } =20 + ret =3D intel_dg_nvm_init_mtd(nvm, device, ret, invm->writable_override); + if (ret) { + dev_err(device, "failed init mtd %d\n", ret); + goto err; + } + dev_set_drvdata(&aux_dev->dev, nvm); =20 return 0; @@ -504,6 +722,8 @@ static void intel_dg_mtd_remove(struct auxiliary_device= *aux_dev) if (!nvm) return; =20 + mtd_device_unregister(&nvm->mtd); + dev_set_drvdata(&aux_dev->dev, NULL); =20 kref_put(&nvm->refcnt, intel_dg_nvm_release); --=20 2.43.0 From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D28923182D for ; Tue, 3 Jun 2025 11:53:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951638; cv=none; b=SKHDDDxvyrKAAweOmuGn4VGb7sFOk6BxMysFpGNug0fK9Wg8CaZsK/N1KYL98UjCIQCjmuP6lS49f3/lVyj0+7gmvvm5ogi5S1zuMRAt3KRy2uA8rag+/Rumczn7MASeKRPrDlGcw9gmwNts996U2uYnbgJN59Axb0wJxPbk9YQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951638; c=relaxed/simple; bh=MkAaleCQCNNCm9AdIhhOV9O8nKl/pJB/jBgEA4uGWKQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nAxOatqxsxcL2uI6Y3DnrABhOwpOHPMbQLAEkyDVWud714f5uoWojtXdl6z33vpPtwkPZZOoGZPJAAmqn4L4V7xeO/xYw/I9S+0qO/X5JC4bqmXPjZq8Fgi8G8F00ASoPzQjc5gls7ZnvbKw0eiTH90w+mCdNQmF1y/6Hyy3uzw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=P3nWwxvP; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="P3nWwxvP" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951636; x=1780487636; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MkAaleCQCNNCm9AdIhhOV9O8nKl/pJB/jBgEA4uGWKQ=; b=P3nWwxvPoCQW1Pe589WoAFZ+5OereTT8mnECKGJpQIsqSxRffYJZr9Y+ LLCGKZiOOUM3f5p+M3rAPz+lEMkDWlR/aaOoGiLSY449Lj6p8dvp1DJeU QS8l1lVLBTvH43bjAy7c/QmtA4Zrvzz4uA16SfMayRoytLxTYkN8Nu/Rr 9Tj5NDzdRbtzOpZ9YscbeCFuguIimOPCepfvQPJ0pbUoD/NKO8TiBfg+F WJ5quXx/lIIiKlz4pzI8m3hSQUav8ixeTVxH/bmqxxOh/o7l4dVmpuzFe msCipUlsBCgwx6fkSGCfFPelOGajNdKo6yV35n3zylGN23/d8FKy7tLbG Q==; X-CSE-ConnectionGUID: r+Zp9Sv4QkqDs+OQhgSeeg== X-CSE-MsgGUID: GtXqXCIDRSOk8EZ8xwbz7g== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616486" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616486" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:56 -0700 X-CSE-ConnectionGUID: 3Kg06+3UReSGpUqmjqRIyw== X-CSE-MsgGUID: 3MIc2jGdTYSp+iV0IJil8w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993346" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:50 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin Subject: [PATCH v12 05/10] mtd: intel-dg: align 64bit read and write Date: Tue, 3 Jun 2025 14:39:48 +0300 Message-ID: <20250603113953.3599816-6-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" GSC NVM controller HW errors on quad access overlapping 1K border. Align 64bit read and write to avoid readq/writeq over 1K border. Reviewed-by: Raag Jadav Acked-by: Miquel Raynal Signed-off-by: Alexander Usyskin --- drivers/mtd/devices/mtd_intel_dg.c | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_i= ntel_dg.c index 6d971fb77938..97e1dc1ada5d 100644 --- a/drivers/mtd/devices/mtd_intel_dg.c +++ b/drivers/mtd/devices/mtd_intel_dg.c @@ -246,6 +246,24 @@ static ssize_t idg_write(struct intel_dg_nvm *nvm, u8 = region, len_s -=3D to_shift; } =20 + if (!IS_ALIGNED(to, sizeof(u64)) && + ((to ^ (to + len_s)) & GENMASK(31, 10))) { + /* + * Workaround reads/writes across 1k-aligned addresses + * (start u32 before 1k, end u32 after) + * as this fails on hardware. + */ + u32 data; + + memcpy(&data, &buf[0], sizeof(u32)); + idg_nvm_write32(nvm, to, data); + if (idg_nvm_error(nvm)) + return -EIO; + buf +=3D sizeof(u32); + to +=3D sizeof(u32); + len_s -=3D sizeof(u32); + } + len8 =3D ALIGN_DOWN(len_s, sizeof(u64)); for (i =3D 0; i < len8; i +=3D sizeof(u64)) { u64 data; @@ -303,6 +321,23 @@ static ssize_t idg_read(struct intel_dg_nvm *nvm, u8 r= egion, from +=3D from_shift; } =20 + if (!IS_ALIGNED(from, sizeof(u64)) && + ((from ^ (from + len_s)) & GENMASK(31, 10))) { + /* + * Workaround reads/writes across 1k-aligned addresses + * (start u32 before 1k, end u32 after) + * as this fails on hardware. + */ + u32 data =3D idg_nvm_read32(nvm, from); + + if (idg_nvm_error(nvm)) + return -EIO; + memcpy(&buf[0], &data, sizeof(data)); + len_s -=3D sizeof(u32); + buf +=3D sizeof(u32); + from +=3D sizeof(u32); + } + len8 =3D ALIGN_DOWN(len_s, sizeof(u64)); for (i =3D 0; i < len8; i +=3D sizeof(u64)) { u64 data =3D idg_nvm_read64(nvm, from + i); --=20 2.43.0 From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 64A5722FE02 for ; Tue, 3 Jun 2025 11:54:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951644; cv=none; b=Twd1QrU5dfraoC+eXJxwMGNseDMUjQUkt0eLKbuUm9BtsCVqvGkrCAdFKQsqZMTPmXfvL45BITIPyF+FgwGfTjxVEuG9MVwTpHKgUN6/U2N45a5le51WnHQfMqfenDFEvM50vVhwZqIb4AP6dCVlR3e7+QbYy2Y2iNMzBZRdGE0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951644; c=relaxed/simple; bh=12QsiCuGoHCubRfpXftCU3zZKpyp9XRRkhXynQ2ULTA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z5L3y9VbdFw10lw5ORGX6Iy32I5HMEDCwhGnJ0wJujh3iIrGgRBomOxx4i1eeHEUmVtxS9qJIlLOYPX/r/bVLqQ2uAJhcMk7uvFhQ6lPUO4qrbMSQeAlZzvIV97CGohmQHw75+pXL58F/lR7oCrOpljr0CYzZ6cMpgl0e7x+X4Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=gyf+fxB7; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="gyf+fxB7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951642; x=1780487642; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=12QsiCuGoHCubRfpXftCU3zZKpyp9XRRkhXynQ2ULTA=; b=gyf+fxB7sQ8+juh+ViGgtmrn3pm7CyUQ3Cu2obu0zLsniLcLSFBA6YKO bnzMT3XzZBsPUcy1UDfBpFNYa8MtPcrel19XlDNdlXrEMt9brxhhVGiOX ok0TBrt2GOpM6ZIq6ZIRFSVUua5JTUK2VYUMRS9q4bGQ7YZCfE+cWGC8s 1qfUM4mUHYvUUTXz3PWcyLRKi/18/p6lRhr9aorREKT82vQDDUsT2dSv4 ebxaR7zJkq8j4UGeHfNXHJLlxPOtmpCiXerFli08i3GEWUEwCROG85GsJ htcqF2tsZcLARIXaDhTGPXZCcI3Oyn12jjmAzHpY3CISa57IY8hsi/3/4 g==; X-CSE-ConnectionGUID: MRUxDXfPS6ew8DhZbzWugA== X-CSE-MsgGUID: sn2apYL7S4O9GepBlZuykg== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616519" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616519" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:54:02 -0700 X-CSE-ConnectionGUID: JxOBkSObT26M4apRzCaspQ== X-CSE-MsgGUID: tdkAGN2kTpipatiW6rKeOA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993355" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:53:56 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin , Tomas Winkler Subject: [PATCH v12 06/10] drm/i915/nvm: add nvm device for discrete graphics Date: Tue, 3 Jun 2025 14:39:49 +0300 Message-ID: <20250603113953.3599816-7-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Enable access to internal non-volatile memory on DGFX devices via a child device. The nvm child device is exposed via auxiliary bus. CC: Lucas De Marchi Reviewed-by: Rodrigo Vivi Acked-by: Rodrigo Vivi Co-developed-by: Tomas Winkler Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin --- drivers/gpu/drm/i915/Makefile | 4 ++ drivers/gpu/drm/i915/i915_driver.c | 6 ++ drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_nvm.c | 98 ++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_nvm.h | 15 +++++ 6 files changed, 127 insertions(+) create mode 100644 drivers/gpu/drm/i915/intel_nvm.c create mode 100644 drivers/gpu/drm/i915/intel_nvm.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 1a90eb1f180a..2e0fa85491a8 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -212,6 +212,10 @@ i915-y +=3D \ i915-y +=3D \ gt/intel_gsc.o =20 +# graphics nvm device (DGFX) support +i915-y +=3D \ + intel_nvm.o + # graphics hardware monitoring (HWMON) support i915-$(CONFIG_HWMON) +=3D \ i915_hwmon.o diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915= _driver.c index 3b0bda74697d..4d91d5075fde 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -84,6 +84,8 @@ #include "soc/intel_dram.h" #include "soc/intel_gmch.h" =20 +#include "intel_nvm.h" + #include "i915_debugfs.h" #include "i915_driver.h" #include "i915_drm_client.h" @@ -643,6 +645,8 @@ static int i915_driver_register(struct drm_i915_private= *dev_priv) /* Depends on sysfs having been initialized */ i915_perf_register(dev_priv); =20 + intel_nvm_init(dev_priv); + for_each_gt(gt, dev_priv, i) intel_gt_driver_register(gt); =20 @@ -685,6 +689,8 @@ static void i915_driver_unregister(struct drm_i915_priv= ate *dev_priv) =20 i915_hwmon_unregister(dev_priv); =20 + intel_nvm_fini(dev_priv); + i915_perf_unregister(dev_priv); i915_pmu_unregister(dev_priv); =20 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_dr= v.h index b6c632bd522c..d6203a49335c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -64,6 +64,7 @@ struct drm_i915_clock_gating_funcs; struct intel_display; struct intel_pxp; struct vlv_s0ix_state; +struct intel_dg_nvm_dev; =20 #define GEM_QUIRK_PIN_SWIZZLED_PAGES BIT(0) =20 @@ -309,6 +310,8 @@ struct drm_i915_private { =20 struct i915_perf perf; =20 + struct intel_dg_nvm_dev *nvm; + struct i915_hwmon *hwmon; =20 struct intel_gt *gt[I915_MAX_GT]; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_re= g.h index 8822c639a4f4..9d35af6fa76e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -321,6 +321,7 @@ #define DG2_GSC_HECI2_BASE 0x00374000 #define MTL_GSC_HECI1_BASE 0x00116000 #define MTL_GSC_HECI2_BASE 0x00117000 +#define GEN12_GUNIT_NVM_BASE 0x00102040 =20 #define HECI_H_CSR(base) _MMIO((base) + 0x4) #define HECI_H_CSR_IE REG_BIT(0) diff --git a/drivers/gpu/drm/i915/intel_nvm.c b/drivers/gpu/drm/i915/intel_= nvm.c new file mode 100644 index 000000000000..ae7f9f2c01bf --- /dev/null +++ b/drivers/gpu/drm/i915/intel_nvm.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright(c) 2019-2024, Intel Corporation. All rights reserved. + */ + +#include +#include +#include +#include "i915_reg.h" +#include "i915_drv.h" +#include "intel_nvm.h" + +#define GEN12_GUNIT_NVM_SIZE 0x80 + +static const struct intel_dg_nvm_region regions[INTEL_DG_NVM_REGIONS] =3D { + [0] =3D { .name =3D "DESCRIPTOR", }, + [2] =3D { .name =3D "GSC", }, + [11] =3D { .name =3D "OptionROM", }, + [12] =3D { .name =3D "DAM", }, +}; + +static void i915_nvm_release_dev(struct device *dev) +{ +} + +int intel_nvm_init(struct drm_i915_private *i915) +{ + struct pci_dev *pdev =3D to_pci_dev(i915->drm.dev); + struct auxiliary_device *aux_dev; + struct intel_dg_nvm_dev *nvm; + int ret; + + /* Only the DGFX devices have internal NVM */ + if (!IS_DGFX(i915)) + return 0; + + /* Nvm pointer should be NULL here */ + if (WARN_ON(i915->nvm)) + return -EFAULT; + + i915->nvm =3D kzalloc(sizeof(*nvm), GFP_KERNEL); + if (!i915->nvm) + return -ENOMEM; + + nvm =3D i915->nvm; + + nvm->writable_override =3D true; + nvm->bar.parent =3D &pdev->resource[0]; + nvm->bar.start =3D GEN12_GUNIT_NVM_BASE + pdev->resource[0].start; + nvm->bar.end =3D nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1; + nvm->bar.flags =3D IORESOURCE_MEM; + nvm->bar.desc =3D IORES_DESC_NONE; + nvm->regions =3D regions; + + aux_dev =3D &nvm->aux_dev; + + aux_dev->name =3D "nvm"; + aux_dev->id =3D (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev); + aux_dev->dev.parent =3D &pdev->dev; + aux_dev->dev.release =3D i915_nvm_release_dev; + + ret =3D auxiliary_device_init(aux_dev); + if (ret) { + drm_err(&i915->drm, "i915-nvm aux init failed %d\n", ret); + goto err; + } + + ret =3D auxiliary_device_add(aux_dev); + if (ret) { + drm_err(&i915->drm, "i915-nvm aux add failed %d\n", ret); + auxiliary_device_uninit(aux_dev); + goto err; + } + return 0; + +err: + kfree(nvm); + i915->nvm =3D NULL; + return ret; +} + +void intel_nvm_fini(struct drm_i915_private *i915) +{ + struct intel_dg_nvm_dev *nvm =3D i915->nvm; + + /* Only the DGFX devices have internal NVM */ + if (!IS_DGFX(i915)) + 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); + i915->nvm =3D NULL; +} diff --git a/drivers/gpu/drm/i915/intel_nvm.h b/drivers/gpu/drm/i915/intel_= nvm.h new file mode 100644 index 000000000000..a9e4046b830f --- /dev/null +++ b/drivers/gpu/drm/i915/intel_nvm.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright(c) 2019-2024 Intel Corporation. All rights reserved. + */ + +#ifndef __INTEL_NVM_H__ +#define __INTEL_NVM_H__ + +struct drm_i915_private; + +int intel_nvm_init(struct drm_i915_private *i915); + +void intel_nvm_fini(struct drm_i915_private *i915); + +#endif /* __INTEL_NVM_H__ */ --=20 2.43.0 From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0E8FB22F767 for ; Tue, 3 Jun 2025 11:54:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951649; cv=none; b=hGzmfwq/h7EXZ76+oz+Dw57UC7HtVvIKqCrqtA0MDI4+rgF4aLGhiqx2V1Gz85vVCkRl7cyHZeZV7cX+QenWZwIzaKBjN9y5WAvr5iCgf7fozK5BacuUJ/13esAOkQgq/HIU/w48pBJfgdwEs5ShBDFY+tSRs6VXQHFKAkAXe8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951649; c=relaxed/simple; bh=brHnIOdScb0KxCyYh6StjKNndkZEaHPzreNgxMkxZxU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=V+cEl2G7GwrApeXym39looKjpobINbFZNk5cP2vuDa8iCpQxK/W94d7gTFWd/qihI5rum3yBigZ9kSeAQBmubxMtakZnC30BXCoIiUm866jCn/uZHQZHeWgOZ9d4r0OzDDItSEzOi4mXtCmJRQXvMzkWMIccwHtRCVrbOTKIVME= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=calNgK9x; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="calNgK9x" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951648; x=1780487648; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=brHnIOdScb0KxCyYh6StjKNndkZEaHPzreNgxMkxZxU=; b=calNgK9xKbNOMPZ/tqs7Gb3NA3GUo4djZSR/pAErUa7Lls0qHD2hmB+3 IGimkxZwS/TxgXsxf8oHYV8bX5j7kqOVOsEUcF5ee6JDdiXQC+62+pfIS 53JcNhn1UYR03fqzNGWniUdsE9Lig9Fl7W7uNcyAu59g5wFCuirHLg8qL uIe2EYZanr9GZVFCfrzMPpJxgdTUXrryFeipZtmqlIPLOoUasx8d5oPkx 9J/blUkKZzdxInFAWlT5rzHMXjDOMJ3JCf2AzNYzDSOLDSWdfCFDAO1M6 QKJyIGxn+e9RS+jUZ9SJMUKBZfqMOAc2Au1jN5lItWvGF0zHaNviqlRZR w==; X-CSE-ConnectionGUID: VmofzIZXRAuY7EyVLlI7kw== X-CSE-MsgGUID: iEoeWmugQqiimkNAM4mQ+A== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616564" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616564" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:54:08 -0700 X-CSE-ConnectionGUID: 7S6iikLySZy+8OMx6WwHZA== X-CSE-MsgGUID: 77pSL+LyRPqxicxawx8dkw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993363" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:54:02 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin Subject: [PATCH v12 07/10] drm/i915/nvm: add support for access mode Date: Tue, 3 Jun 2025 14:39:50 +0300 Message-ID: <20250603113953.3599816-8-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Check NVM access mode from GSC FW status registers and overwrite access status read from SPI descriptor, if needed. Reviewed-by: Rodrigo Vivi Acked-by: Rodrigo Vivi Signed-off-by: Alexander Usyskin --- drivers/gpu/drm/i915/intel_nvm.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_nvm.c b/drivers/gpu/drm/i915/intel_= nvm.c index ae7f9f2c01bf..4624cba26fa7 100644 --- a/drivers/gpu/drm/i915/intel_nvm.c +++ b/drivers/gpu/drm/i915/intel_nvm.c @@ -11,6 +11,7 @@ #include "intel_nvm.h" =20 #define GEN12_GUNIT_NVM_SIZE 0x80 +#define HECI_FW_STATUS_2_NVM_ACCESS_MODE BIT(3) =20 static const struct intel_dg_nvm_region regions[INTEL_DG_NVM_REGIONS] =3D { [0] =3D { .name =3D "DESCRIPTOR", }, @@ -23,6 +24,28 @@ static void i915_nvm_release_dev(struct device *dev) { } =20 +static bool i915_nvm_writable_override(struct drm_i915_private *i915) +{ + bool writable_override; + resource_size_t base; + + if (IS_DG1(i915)) { + base =3D DG1_GSC_HECI2_BASE; + } else if (IS_DG2(i915)) { + base =3D DG2_GSC_HECI2_BASE; + } else { + drm_err(&i915->drm, "Unknown platform\n"); + return true; + } + + writable_override =3D + !(intel_uncore_read(&i915->uncore, HECI_FWSTS(base, 2)) & + HECI_FW_STATUS_2_NVM_ACCESS_MODE); + if (writable_override) + drm_info(&i915->drm, "NVM access overridden by jumper\n"); + return writable_override; +} + int intel_nvm_init(struct drm_i915_private *i915) { struct pci_dev *pdev =3D to_pci_dev(i915->drm.dev); @@ -44,7 +67,7 @@ int intel_nvm_init(struct drm_i915_private *i915) =20 nvm =3D i915->nvm; =20 - nvm->writable_override =3D true; + nvm->writable_override =3D i915_nvm_writable_override(i915); nvm->bar.parent =3D &pdev->resource[0]; nvm->bar.start =3D GEN12_GUNIT_NVM_BASE + pdev->resource[0].start; nvm->bar.end =3D nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1; --=20 2.43.0 From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A1BB22F767 for ; Tue, 3 Jun 2025 11:54:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951655; cv=none; b=W2zfGgZU/+m/YdSJYn+Xqur2oyPqTnLqTVJNTVYtZxdiGoHrH2OL8BnltJxxnt92F1ahmqeq7JSbYPgIxYnwyOD2GuwOFvADyZNpW/96gLplpT/evOQ9cpJOf/6FQ0w4ympYLkQeTiPewrMTAqwviz9YpFgXTSgueeMlgkWjO3k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951655; c=relaxed/simple; bh=HvtSue/RLt1bCacQGtABgCZRQKieVtGOwWRB9zKATEM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WQuYwgTmlNOFjph8s2fZqoPqPcbI+7l/GY1qdc6TzqNQ41/O4DROZ+sFUbOtxnAv6+QDekydzFSy5IN6M3/Oljeg1Ms170ojTJEOfu4LX2VFjmkbSyXwQ3PwZRVIUmrVhEvWRvDnHNwycdqqHQnByYk+JU3vR6V5MvgGsoOwjTk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=UbwdFwsC; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="UbwdFwsC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951653; x=1780487653; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HvtSue/RLt1bCacQGtABgCZRQKieVtGOwWRB9zKATEM=; b=UbwdFwsCiS3XjS+l37ksnr+1PkTPmknyWrheiBqJ/XI2UP0ObfB4lNbl Onre+/NKi3e069onHONPUcXzczPQC14HJUup8/8ntclUx8btuYPOq0UGS HjsPofiQUUMOnPe7ISKfQknL8mrszpFNqvo+2WNMD/f4snoLCmrsWKxf7 ro07QMiJqWdittDmFMOdsvLHvNwT/h4fIE/Tjj9cRpliQbWZ0IZbyCxXc h0dzstJosdEIC2FfsyLL1uU3WvUWDkhManVAkv+x2sDCjwoAxLBiCK3wc rEotA8DDl21SLhgijIfhH0UIUxHFUuV2XnXjm9Xlsms6Ey5RbALf9UXqZ Q==; X-CSE-ConnectionGUID: gX84yXIwR9GESFtfdWV7fw== X-CSE-MsgGUID: BHYC6WmtSeKSHTDVjPZNOA== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616601" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616601" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:54:13 -0700 X-CSE-ConnectionGUID: 0yG/XisMTgyyxdjKpJjMMg== X-CSE-MsgGUID: purpTvM1QGOKOirOY9Cw8g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993374" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:54:08 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin Subject: [PATCH v12 08/10] drm/xe/nvm: add on-die non-volatile memory device Date: Tue, 3 Jun 2025 14:39:51 +0300 Message-ID: <20250603113953.3599816-9-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Acked-by: Rodrigo Vivi Signed-off-by: Alexander Usyskin --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/xe_device.c | 5 ++ drivers/gpu/drm/xe/xe_device_types.h | 6 ++ drivers/gpu/drm/xe/xe_nvm.c | 107 +++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_nvm.h | 15 ++++ drivers/gpu/drm/xe/xe_pci.c | 6 ++ 6 files changed, 140 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_nvm.c create mode 100644 drivers/gpu/drm/xe/xe_nvm.h diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index e4bf484d4121..4c51fe3520dc 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -80,6 +80,7 @@ xe-y +=3D xe_bb.o \ xe_mmio.o \ xe_mocs.o \ xe_module.o \ + xe_nvm.o \ xe_oa.o \ xe_observation.o \ xe_pat.o \ diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 660b0c5126dc..aebdd8e74c7e 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -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" @@ -880,6 +881,8 @@ int xe_device_probe(struct xe_device *xe) return err; } =20 + xe_nvm_init(xe); + err =3D xe_heci_gsc_init(xe); if (err) return err; @@ -937,6 +940,8 @@ void xe_device_remove(struct xe_device *xe) { xe_display_unregister(xe); =20 + xe_nvm_fini(xe); + drm_dev_unplug(&xe->drm); =20 xe_bo_pci_dev_remove_all(xe); diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_d= evice_types.h index b93c04466637..bb3e5e360f1a 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -31,6 +31,7 @@ #endif =20 struct intel_display; +struct intel_dg_nvm_dev; struct xe_ggtt; struct xe_pat_ops; struct xe_pxp; @@ -315,6 +316,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 */ @@ -544,6 +547,9 @@ struct xe_device { /** @heci_gsc: graphics security controller */ struct xe_heci_gsc heci_gsc; =20 + /** @nvm: discrete graphics non-volatile memory */ + struct intel_dg_nvm_dev *nvm; + /** @oa: oa observation subsystem */ struct xe_oa oa; =20 diff --git a/drivers/gpu/drm/xe/xe_nvm.c b/drivers/gpu/drm/xe/xe_nvm.c new file mode 100644 index 000000000000..33ba635ce116 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_nvm.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright(c) 2019-2025, Intel Corporation. All rights reserved. + */ + +#include +#include + +#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] =3D { + [0] =3D { .name =3D "DESCRIPTOR", }, + [2] =3D { .name =3D "GSC", }, + [9] =3D { .name =3D "PADDING", }, + [11] =3D { .name =3D "OptionROM", }, + [12] =3D { .name =3D "DAM", }, +}; + +static void xe_nvm_release_dev(struct device *dev) +{ +} + +int xe_nvm_init(struct xe_device *xe) +{ + struct pci_dev *pdev =3D 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 =3D kzalloc(sizeof(*nvm), GFP_KERNEL); + if (!xe->nvm) + return -ENOMEM; + + nvm =3D xe->nvm; + + nvm->writable_override =3D false; + nvm->bar.parent =3D &pdev->resource[0]; + nvm->bar.start =3D GEN12_GUNIT_NVM_BASE + pdev->resource[0].start; + nvm->bar.end =3D nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1; + nvm->bar.flags =3D IORESOURCE_MEM; + nvm->bar.desc =3D IORES_DESC_NONE; + nvm->regions =3D regions; + + aux_dev =3D &nvm->aux_dev; + + aux_dev->name =3D "nvm"; + aux_dev->id =3D (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev); + aux_dev->dev.parent =3D &pdev->dev; + aux_dev->dev.release =3D xe_nvm_release_dev; + + ret =3D auxiliary_device_init(aux_dev); + if (ret) { + drm_err(&xe->drm, "xe-nvm aux init failed %d\n", ret); + goto err; + } + + ret =3D 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 =3D NULL; + return ret; +} + +void xe_nvm_fini(struct xe_device *xe) +{ + struct intel_dg_nvm_dev *nvm =3D 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 =3D NULL; +} diff --git a/drivers/gpu/drm/xe/xe_nvm.h b/drivers/gpu/drm/xe/xe_nvm.h new file mode 100644 index 000000000000..7f3d5f57bed0 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_nvm.h @@ -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 diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index b5559800db7a..635fddc3ab24 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -63,6 +63,7 @@ struct xe_device_desc { =20 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 =3D { PLATFORM(DG1), .dma_mask_size =3D 39, .has_display =3D true, + .has_gsc_nvm =3D 1, .has_heci_gscfi =3D 1, .require_force_probe =3D true, }; @@ -283,6 +285,7 @@ static const u16 dg2_g12_ids[] =3D { INTEL_DG2_G12_IDS(= NOP), 0 }; #define DG2_FEATURES \ DGFX_FEATURES, \ PLATFORM(DG2), \ + .has_gsc_nvm =3D 1, \ .has_heci_gscfi =3D 1, \ .subplatforms =3D (const struct xe_subplatform_desc[]) { \ { XE_SUBPLATFORM_DG2_G10, "G10", dg2_g10_ids }, \ @@ -320,6 +323,7 @@ static const __maybe_unused struct xe_device_desc pvc_d= esc =3D { PLATFORM(PVC), .dma_mask_size =3D 52, .has_display =3D false, + .has_gsc_nvm =3D 1, .has_heci_gscfi =3D 1, .max_remote_tiles =3D 1, .require_force_probe =3D true, @@ -350,6 +354,7 @@ static const struct xe_device_desc bmg_desc =3D { .has_display =3D true, .has_fan_control =3D true, .has_mbx_power_limits =3D true, + .has_gsc_nvm =3D 1, .has_heci_cscfi =3D 1, .needs_scratch =3D true, }; @@ -594,6 +599,7 @@ static int xe_info_init_early(struct xe_device *xe, xe->info.is_dgfx =3D desc->is_dgfx; xe->info.has_fan_control =3D desc->has_fan_control; xe->info.has_mbx_power_limits =3D desc->has_mbx_power_limits; + xe->info.has_gsc_nvm =3D desc->has_gsc_nvm; xe->info.has_heci_gscfi =3D desc->has_heci_gscfi; xe->info.has_heci_cscfi =3D desc->has_heci_cscfi; xe->info.has_llc =3D desc->has_llc; --=20 2.43.0 From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 31855232395 for ; Tue, 3 Jun 2025 11:54:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951660; cv=none; b=OZ5DkZkEIZrBS6KJTGOo5qJv5Mvnv2nEHkFhvHaoVfV9leexAojxV2XU8GRRnCxmbFzHQ1TzCQYGyWB8wD4CEHOr1tv/9v8UWtkk4A8RMl4mgYP9pKQlU+KTJVsJPgbF5cvuNEYNscT/zN5znY8tmaH4RhjgmqUnpPPBrL4deDc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951660; c=relaxed/simple; bh=luOze6g0PP5F5pCLOK5jBaa2umhqnsfnayAFqvQ9H4M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QLQp/7+Zeqkel2HxnMqmailvapL2IBuxYT8H6Rz09FhQcoscnU1kNqR8+/UUNB0msF5318qlSc8azM2UEdY9xxFfLith/QOoza20f8pmh04Uu/ZK6UoVmXwUW7t6Bhi93dnvgAyd+eAUwK+T3o5qdiklv2/XsDjvl7/1w1Au6D0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=jbVrE+xU; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="jbVrE+xU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951659; x=1780487659; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=luOze6g0PP5F5pCLOK5jBaa2umhqnsfnayAFqvQ9H4M=; b=jbVrE+xUWsxdBjg+R0Bls5XKFSG9aoI0qg2KctUHKp0EuyeP2S+xB6gY XM1fgbHamibUESqM8k4WHJ82165d8bwXZKit7S80Qf3t2fTaTO7mMbzWF IMzFAOfrJFV+kpfVXxWvQM+vwXurv06gGPmAAHCpNHYfH+X2HlXY3weUE C+p28d1slClp4BbhRjoAurox0xYX6Qekp6wLy1H6VnMOR8f7ZL01Pnb4T gqgLxex5PvsR+E1M8t2qp1YffH5naEhyTwhyn+Rm2p5HGqXEVbphE36tF oyKeDKMXifAM3rKwPlHJyFtjy8TeA+1zb/+DjiAweAfP4Ax3hJO61A+b+ g==; X-CSE-ConnectionGUID: 2HyTcfWwQS6KcEGNL7ENyQ== X-CSE-MsgGUID: gcz7GMEiTRS8m4Ssbptnzg== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616621" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616621" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:54:19 -0700 X-CSE-ConnectionGUID: kbX4Z/TfQz+MpDyxdnKABQ== X-CSE-MsgGUID: zvM0KdqDTMG0eHWd8DPTkw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993387" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:54:13 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin Subject: [PATCH v12 09/10] drm/xe/nvm: add support for access mode Date: Tue, 3 Jun 2025 14:39:52 +0300 Message-ID: <20250603113953.3599816-10-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Check NVM access mode from GSC FW status registers and overwrite access status read from SPI descriptor, if needed. Reviewed-by: Rodrigo Vivi Acked-by: Rodrigo Vivi Signed-off-by: Alexander Usyskin --- drivers/gpu/drm/xe/regs/xe_gsc_regs.h | 4 +++ drivers/gpu/drm/xe/xe_heci_gsc.c | 5 +--- drivers/gpu/drm/xe/xe_nvm.c | 37 ++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h b/drivers/gpu/drm/xe/reg= s/xe_gsc_regs.h index 7702364b65f1..9b66cc972a63 100644 --- a/drivers/gpu/drm/xe/regs/xe_gsc_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gsc_regs.h @@ -16,6 +16,10 @@ #define MTL_GSC_HECI1_BASE 0x00116000 #define MTL_GSC_HECI2_BASE 0x00117000 =20 +#define DG1_GSC_HECI2_BASE 0x00259000 +#define PVC_GSC_HECI2_BASE 0x00285000 +#define DG2_GSC_HECI2_BASE 0x00374000 + #define HECI_H_CSR(base) XE_REG((base) + 0x4) #define HECI_H_CSR_IE REG_BIT(0) #define HECI_H_CSR_IS REG_BIT(1) diff --git a/drivers/gpu/drm/xe/xe_heci_gsc.c b/drivers/gpu/drm/xe/xe_heci_= gsc.c index 27d11e06a82b..6d7b62724126 100644 --- a/drivers/gpu/drm/xe/xe_heci_gsc.c +++ b/drivers/gpu/drm/xe/xe_heci_gsc.c @@ -11,15 +11,12 @@ #include "xe_device_types.h" #include "xe_drv.h" #include "xe_heci_gsc.h" +#include "regs/xe_gsc_regs.h" #include "xe_platform_types.h" #include "xe_survivability_mode.h" =20 #define GSC_BAR_LENGTH 0x00000FFC =20 -#define DG1_GSC_HECI2_BASE 0x259000 -#define PVC_GSC_HECI2_BASE 0x285000 -#define DG2_GSC_HECI2_BASE 0x374000 - static void heci_gsc_irq_mask(struct irq_data *d) { /* generic irq handling */ diff --git a/drivers/gpu/drm/xe/xe_nvm.c b/drivers/gpu/drm/xe/xe_nvm.c index 33ba635ce116..20aa3b5d3637 100644 --- a/drivers/gpu/drm/xe/xe_nvm.c +++ b/drivers/gpu/drm/xe/xe_nvm.c @@ -6,8 +6,11 @@ #include #include =20 +#include "xe_device.h" #include "xe_device_types.h" +#include "xe_mmio.h" #include "xe_nvm.h" +#include "regs/xe_gsc_regs.h" #include "xe_sriov.h" =20 #define GEN12_GUNIT_NVM_BASE 0x00102040 @@ -26,6 +29,38 @@ static void xe_nvm_release_dev(struct device *dev) { } =20 +static bool xe_nvm_writable_override(struct xe_device *xe) +{ + struct xe_gt *gt =3D xe_root_mmio_gt(xe); + bool writable_override; + resource_size_t base; + + switch (xe->info.platform) { + case XE_BATTLEMAGE: + base =3D DG2_GSC_HECI2_BASE; + break; + case XE_PVC: + base =3D PVC_GSC_HECI2_BASE; + break; + case XE_DG2: + base =3D DG2_GSC_HECI2_BASE; + break; + case XE_DG1: + base =3D DG1_GSC_HECI2_BASE; + break; + default: + drm_err(&xe->drm, "Unknown platform\n"); + return true; + } + + writable_override =3D + !(xe_mmio_read32(>->mmio, HECI_FWSTS2(base)) & + HECI_FW_STATUS_2_NVM_ACCESS_MODE); + if (writable_override) + drm_info(&xe->drm, "NVM access overridden by jumper\n"); + return writable_override; +} + int xe_nvm_init(struct xe_device *xe) { struct pci_dev *pdev =3D to_pci_dev(xe->drm.dev); @@ -50,7 +85,7 @@ int xe_nvm_init(struct xe_device *xe) =20 nvm =3D xe->nvm; =20 - nvm->writable_override =3D false; + nvm->writable_override =3D xe_nvm_writable_override(xe); nvm->bar.parent =3D &pdev->resource[0]; nvm->bar.start =3D GEN12_GUNIT_NVM_BASE + pdev->resource[0].start; nvm->bar.end =3D nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1; --=20 2.43.0 From nobody Sun Feb 8 13:46:47 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D533E230BC6 for ; Tue, 3 Jun 2025 11:54:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951666; cv=none; b=mCZjTbM2VqabXZofsk25HzrkeOdlgVs7bTfegNupEo769hot5n+cKCUAuaCRUx51eh51+ILIjdRBz3af211/KfIelDh7PrSAnkf/UjQ9coTPY52l+yXqWAbCqaYq5a2fD/hJbh9pTMx6HMH1z1uXWqhMtj/egg4k+SIz9ENbS9I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748951666; c=relaxed/simple; bh=fH2hdGzwTf4pZxd5L5oHs+dVIY/4d4It2eb8BdPFp3E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y6ahCH0vKyu8aly4Wkv1wbigI6xXjg2pCH18OvRihr/uREz0yq2D0ibvPuIC8sT0N6eokhxqteTOTct7HKpiI3z7o1uVa2kchjN0X7kl3YqcVz9T2iKrDnwZ0TvHxEcNv5i0xxFEpPTF7SunZ2iPlnwWPYh8cVif3Yid1H+lNGc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=hu37j3af; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hu37j3af" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1748951665; x=1780487665; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=fH2hdGzwTf4pZxd5L5oHs+dVIY/4d4It2eb8BdPFp3E=; b=hu37j3af8bPkGDzL/Esam1CMhlC0RStqTPBZ1VvM/DbdQDKC9FVR06+C zhVQyUEkfyKt8BBbH3hiNWL807xt7H5l05hKuf7rzPOr3x2E/F8bLC4Lu fOR6Cx3Y4ZoYdtqmDSPTm23NfWva0O63yClknWgqWeR49njXRRExsHslR 7rNXfqk+/ccNoVbK5YMPaCzWkssqMIn345t3SkULAdYHu8amoKgeAr8Sr 1bXjZHbBdWkJ26Rtrwg4ccX5WBWfL+yK9pA6jA408iHc8J257HD9wesPW JS6z6erujIfzKJgtxtvgMuQ6+TVccu/QfdiuQFvh4Mz72CMQablaN562J g==; X-CSE-ConnectionGUID: Dod197JGSr+W7tyFKA4zAw== X-CSE-MsgGUID: ECZrsaJuRAipPU+E96GjGw== X-IronPort-AV: E=McAfee;i="6700,10204,11451"; a="53616660" X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="53616660" Received: from fmviesa004.fm.intel.com ([10.60.135.144]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:54:24 -0700 X-CSE-ConnectionGUID: KozutAM8ScyStY8QfYLPow== X-CSE-MsgGUID: NKY/bKSKQ/C0dSC7kN9vJw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,206,1744095600"; d="scan'208";a="149993420" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jun 2025 04:54:19 -0700 From: Alexander Usyskin To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Rodrigo Vivi , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jani Nikula , Joonas Lahtinen , Tvrtko Ursulin , Karthik Poosa , Raag Jadav Cc: Reuven Abliyev , Oren Weil , linux-mtd@lists.infradead.org, intel-xe@lists.freedesktop.org, dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, Alexander Usyskin Subject: [PATCH v12 10/10] drm/xe/nvm: add support for non-posted erase Date: Tue, 3 Jun 2025 14:39:53 +0300 Message-ID: <20250603113953.3599816-11-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250603113953.3599816-1-alexander.usyskin@intel.com> References: <20250603113953.3599816-1-alexander.usyskin@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Reuven Abliyev Erase command is slow on discrete graphics storage and may overshot PCI completion timeout. BMG introduces the ability to have non-posted erase. Add driver support for non-posted erase with polling for erase completion. Reviewed-by: Rodrigo Vivi Acked-by: Rodrigo Vivi Signed-off-by: Reuven Abliyev Signed-off-by: Alexander Usyskin --- drivers/gpu/drm/xe/xe_nvm.c | 25 ++++++++++++++++++ drivers/mtd/devices/mtd_intel_dg.c | 42 ++++++++++++++++++++++++++++-- include/linux/intel_dg_nvm_aux.h | 2 ++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_nvm.c b/drivers/gpu/drm/xe/xe_nvm.c index 20aa3b5d3637..61b0a1531a53 100644 --- a/drivers/gpu/drm/xe/xe_nvm.c +++ b/drivers/gpu/drm/xe/xe_nvm.c @@ -14,7 +14,15 @@ #include "xe_sriov.h" =20 #define GEN12_GUNIT_NVM_BASE 0x00102040 +#define GEN12_DEBUG_NVM_BASE 0x00101018 + +#define GEN12_CNTL_PROTECTED_NVM_REG 0x0010100C + #define GEN12_GUNIT_NVM_SIZE 0x80 +#define GEN12_DEBUG_NVM_SIZE 0x4 + +#define NVM_NON_POSTED_ERASE_CHICKEN_BIT BIT(13) + #define HECI_FW_STATUS_2_NVM_ACCESS_MODE BIT(3) =20 static const struct intel_dg_nvm_region regions[INTEL_DG_NVM_REGIONS] =3D { @@ -29,6 +37,16 @@ static void xe_nvm_release_dev(struct device *dev) { } =20 +static bool xe_nvm_non_posted_erase(struct xe_device *xe) +{ + struct xe_gt *gt =3D xe_root_mmio_gt(xe); + + if (xe->info.platform !=3D XE_BATTLEMAGE) + return false; + return !(xe_mmio_read32(>->mmio, XE_REG(GEN12_CNTL_PROTECTED_NVM_REG)) & + NVM_NON_POSTED_ERASE_CHICKEN_BIT); +} + static bool xe_nvm_writable_override(struct xe_device *xe) { struct xe_gt *gt =3D xe_root_mmio_gt(xe); @@ -86,6 +104,7 @@ int xe_nvm_init(struct xe_device *xe) nvm =3D xe->nvm; =20 nvm->writable_override =3D xe_nvm_writable_override(xe); + nvm->non_posted_erase =3D xe_nvm_non_posted_erase(xe); nvm->bar.parent =3D &pdev->resource[0]; nvm->bar.start =3D GEN12_GUNIT_NVM_BASE + pdev->resource[0].start; nvm->bar.end =3D nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1; @@ -93,6 +112,12 @@ int xe_nvm_init(struct xe_device *xe) nvm->bar.desc =3D IORES_DESC_NONE; nvm->regions =3D regions; =20 + nvm->bar2.parent =3D &pdev->resource[0]; + nvm->bar2.start =3D GEN12_DEBUG_NVM_BASE + pdev->resource[0].start; + nvm->bar2.end =3D nvm->bar2.start + GEN12_DEBUG_NVM_SIZE - 1; + nvm->bar2.flags =3D IORESOURCE_MEM; + nvm->bar2.desc =3D IORES_DESC_NONE; + aux_dev =3D &nvm->aux_dev; =20 aux_dev->name =3D "nvm"; diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_i= ntel_dg.c index 97e1dc1ada5d..b438ee5aacc3 100644 --- a/drivers/mtd/devices/mtd_intel_dg.c +++ b/drivers/mtd/devices/mtd_intel_dg.c @@ -25,6 +25,9 @@ struct intel_dg_nvm { struct mtd_info mtd; struct mutex lock; /* region access lock */ void __iomem *base; + void __iomem *base2; + bool non_posted_erase; + size_t size; unsigned int nregions; struct { @@ -41,6 +44,7 @@ struct intel_dg_nvm { #define NVM_VALSIG_REG 0x00000010 #define NVM_ADDRESS_REG 0x00000040 #define NVM_REGION_ID_REG 0x00000044 +#define NVM_DEBUG_REG 0x00000000 /* * [15:0]-Erase size =3D 0x0010 4K 0x0080 32K 0x0100 64K * [23:16]-Reserved @@ -72,6 +76,9 @@ struct intel_dg_nvm { #define NVM_FREG_ADDR_SHIFT 12 #define NVM_FREG_MIN_REGION_SIZE 0xFFF =20 +#define NVM_NON_POSTED_ERASE_DONE BIT(23) +#define NVM_NON_POSTED_ERASE_DONE_ITER 3000 + static inline void idg_nvm_set_region_id(struct intel_dg_nvm *nvm, u8 regi= on) { iowrite32((u32)region, nvm->base + NVM_REGION_ID_REG); @@ -373,13 +380,32 @@ static ssize_t idg_read(struct intel_dg_nvm *nvm, u8 = region, static ssize_t idg_erase(struct intel_dg_nvm *nvm, u8 region, loff_t from, u64 len, u64 *= fail_addr) { + void __iomem *base2 =3D nvm->base2; void __iomem *base =3D nvm->base; const u32 block =3D 0x10; + u32 iter =3D 0; + u32 reg; u64 i; =20 for (i =3D 0; i < len; i +=3D SZ_4K) { iowrite32(from + i, base + NVM_ADDRESS_REG); iowrite32(region << 24 | block, base + NVM_ERASE_REG); + if (nvm->non_posted_erase) { + /* Wait for Erase Done */ + reg =3D ioread32(base2 + NVM_DEBUG_REG); + while (!(reg & NVM_NON_POSTED_ERASE_DONE) && + ++iter < NVM_NON_POSTED_ERASE_DONE_ITER) { + msleep(10); + reg =3D ioread32(base2 + NVM_DEBUG_REG); + } + if (reg & NVM_NON_POSTED_ERASE_DONE) { + /* Clear Erase Done */ + iowrite32(reg, base2 + NVM_DEBUG_REG); + } else { + *fail_addr =3D from + i; + return -ETIME; + } + } /* Since the writes are via sgunit * we cannot do back to back erases. */ @@ -388,7 +414,8 @@ idg_erase(struct intel_dg_nvm *nvm, u8 region, loff_t f= rom, u64 len, u64 *fail_a return len; } =20 -static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *devi= ce) +static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *devi= ce, + bool non_posted_erase) { u32 access_map =3D 0; unsigned int i, n; @@ -448,7 +475,10 @@ static int intel_dg_nvm_init(struct intel_dg_nvm *nvm,= struct device *device) n++; } =20 + nvm->non_posted_erase =3D non_posted_erase; + dev_dbg(device, "Registered %d regions\n", n); + dev_dbg(device, "Non posted erase %d\n", nvm->non_posted_erase); =20 /* Need to add 1 to the amount of memory * so it is reported as an even block @@ -729,7 +759,15 @@ static int intel_dg_mtd_probe(struct auxiliary_device = *aux_dev, goto err; } =20 - ret =3D intel_dg_nvm_init(nvm, device); + if (invm->non_posted_erase) { + nvm->base2 =3D devm_ioremap_resource(device, &invm->bar2); + if (IS_ERR(nvm->base2)) { + ret =3D PTR_ERR(nvm->base2); + goto err; + } + } + + ret =3D intel_dg_nvm_init(nvm, device, invm->non_posted_erase); if (ret < 0) { dev_err(device, "cannot initialize nvm %d\n", ret); goto err; diff --git a/include/linux/intel_dg_nvm_aux.h b/include/linux/intel_dg_nvm_= aux.h index 00b6c1301bd8..625d46a6b96e 100644 --- a/include/linux/intel_dg_nvm_aux.h +++ b/include/linux/intel_dg_nvm_aux.h @@ -20,7 +20,9 @@ struct intel_dg_nvm_region { struct intel_dg_nvm_dev { struct auxiliary_device aux_dev; bool writable_override; + bool non_posted_erase; struct resource bar; + struct resource bar2; const struct intel_dg_nvm_region *regions; }; =20 --=20 2.43.0