From nobody Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 82CD21A5B94 for ; Tue, 17 Jun 2025 13:59:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168752; cv=none; b=OmtcrBctWFaejnuC3gyiV55pE8bE+cdPi55+iPgLrp6GX0XrHpK7kWd4npNU1sQiT4kF9zXpae3p7VJhuvuHHzFTk/ztSlGKNyw4K/kMNSHWaSvKatzKFZmZNg6ex2VcoYBjpsFiHCSV65CVfgwtFIddVpq/mgy+yBH8qhifjq8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168752; c=relaxed/simple; bh=whBs2iAagZKltqwmIXWaToW4Srekvx9gqm0G/7aOwhc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DI0VvvW972xjXIoxD84DdQMbPqbm/n1UHdvMBFJpFEbnD/N4Et3dtmpMTth7k23No4oEwuBp8osrQkOKx3L/7CwTeD29/RZMsXDZP9xK+XIQtz1tDWHf1Ju0eFWSuTZQZuGtHZMZ4owsDR4qc5CVMz2nGO65j8KvSFk3/MT6h3c= 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=ANcV3ie/; arc=none smtp.client-ip=198.175.65.15 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="ANcV3ie/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168751; x=1781704751; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=whBs2iAagZKltqwmIXWaToW4Srekvx9gqm0G/7aOwhc=; b=ANcV3ie/zVtrKr/FbKqG2fPazbJR8AAvuOTB7gNpseDl6G/Gpl9gYEKt jenjRYO6rXkW78OhAGOARkSsz3P2Mz1+bI5ojuyHjaI6zaB6mPKYkPpy5 CGBIfAxsRY5Lb+kHxcKoK0ndf3gzHWcsyjl0owEiYBBA8zgCpjs1uqmPS rrh9ae/JtltB49UHDbSNVUyWhrJHvtNjTPS4AEktc/WiiaUstpdEL/SU1 4SVt0cTPCsJ5afV+rkF3GFVhnvvuK4vpP3i03AOHRPbIStogmj28qLDLe A/oWadHLvLrZa+Q2vINjXWt/i5UCDZecYnSWFmSkB3epuVNxOra+Px933 w==; X-CSE-ConnectionGUID: cbz0xhfGTd+RB35NgfeORw== X-CSE-MsgGUID: WGBkU4aOT1q+BiD/z9lyOg== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026475" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026475" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:10 -0700 X-CSE-ConnectionGUID: TH29ff8KSZuWku9JMegUFQ== X-CSE-MsgGUID: pPln/wRzRry5Vh0zylvHBg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739449" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:04 -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 , 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 v13 01/10] mtd: add driver for intel graphics non-volatile memory device Date: Tue, 17 Jun 2025 16:45:23 +0300 Message-ID: <20250617134532.3768283-2-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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 7e7515a412e9..521730530243 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12086,6 +12086,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 aed653ce8fa2..46cebde79f34 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 Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 EB5D92DE212 for ; Tue, 17 Jun 2025 13:59:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168758; cv=none; b=T1R6OtNqJp5B7o19LoPEmn0vBstUH2+Ql8ElThEj+z+U3lYp/LHns62bDU5laFAihA9wJjuB7SFUX6jKuHEdkbeXVB/7j1L/s+tvpfg6zpDf1S7mn0OS8eihUB9360Ez3AU6YUGRtVNhECf27ZnvgCw0TIt/G4z85Eu1a2G8Bd4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168758; c=relaxed/simple; bh=GFube+gC6502VTBuZaY4++giPU/6FLO2ZUzV5+IsC6Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QPB/JOKxmNCze6KPDk+sivIa11zB3XIxuLOy+MVWH3B/t06xYPN1DsdgZ6YZDeK8/bCPBzBKbdmcfzC192g2oPyoApL+8gXvevmJ1qr2nWguBCpqS/Q18dGqz90sNb/0zFoLyOjlI2G43eHf/YpWx+5rycgZEmR0R5WWgn+Bz7U= 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=IJozCQbV; arc=none smtp.client-ip=198.175.65.15 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="IJozCQbV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168757; x=1781704757; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GFube+gC6502VTBuZaY4++giPU/6FLO2ZUzV5+IsC6Q=; b=IJozCQbV3qNnkcb5Qb068ldJSe/AYOUpzMSCyaY5Zzhcc3XiGegxVS1C hSWk/qgllcjAz8koByymrUBfMKl0TLphTiXuGRwOZlSTDZNPE3Tbdzcc0 ymnhGW6EbzESeK5tfzYXD4+iRnnB9fVZOJosTLWIsKMzDrGRJsKQGiBe7 64C0GBLdMl31RgoCv4evXMWPGDlm24qjOAm1Fg85gfT9PVCxD/YspduFJ PxYc89fUGCNjBRCRRWMeWZwR2ogqa53vtaMG24d74LOSLMEL+8cfpXUUO 8ipwProdo1TJffhGaB8L02O75WLfztRXnT4kwWMioXC+eMDnW7gjpR6aB A==; X-CSE-ConnectionGUID: dgqTIzs5Q3Wi02fgfnpCvA== X-CSE-MsgGUID: r2ctofnWTTyEGvAUU8HT5w== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026490" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026490" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:17 -0700 X-CSE-ConnectionGUID: qN/VHkQ4RgeYMjlPcwMFEg== X-CSE-MsgGUID: h9U9nX62RE+eBay1bLLo0g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739465" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:10 -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 , 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 v13 02/10] mtd: intel-dg: implement region enumeration Date: Tue, 17 Jun 2025 16:45:24 +0300 Message-ID: <20250617134532.3768283-3-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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 Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 A575F2E264E for ; Tue, 17 Jun 2025 13:59:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168765; cv=none; b=ii4smD/ojiBRzdFHN/KMpnCbSfP+21t8tLyQaBxwb833+M891ZXtIDvxEKV3snObM/zSj7qoTjDDv0aUwux/KQllXtUopQWAjfEZDKeYDgTN0t5GcH09afvGzB1c8w3GTwfDwsu7nFZBNWBJIFQLihvF2OXBGXwJ7awsKwwJvoY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168765; c=relaxed/simple; bh=WvLWJRAv8idelb+wbiysTqm+mBTnrzkj5Bl282lOSrk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LnKX9fT5kosRxw124BkZG5C60dA61xijntR/8PH8xbziR9BVejJaHbHnZgU9TLrwWi4TlwSNaTMsNDd4SnZzZ0cdO0HqxuL6+cLhDmvbFzbeSLMLHsEgrsRFP2e9G2ZnlMKFLZ9qg3nhFjC53DFgInh163q3TtgXGTDibMubXa4= 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=ZSNZkArC; arc=none smtp.client-ip=198.175.65.15 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="ZSNZkArC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168764; x=1781704764; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WvLWJRAv8idelb+wbiysTqm+mBTnrzkj5Bl282lOSrk=; b=ZSNZkArCJfph6hbnFLvRk8WcC5G+bvpMZUr9pRC3truUfyyBB0qv+6Jt ptWqiFNzZ4VX5tyLzi3NUpCgjLjjkrTmZOPSbveWZaq0ih4DKU9fviHLz rq5ypT8HV8IhvANz2Wa45FdBdLb3ZSZ3KvgRMcEjPB1CZDP/lxBfF5Kxu fBCjjl0Y8+d4FHWaY6bHBnHgZ5zALSVVxZM1NtVFoNxRPjhYpZlMuUyiC DEIiK0Ul61RNoGfGygiDcTdV79qQGpm+tvdD2k21JC7IY/ouj12f0a1ZE nwRYWcx9rv9c9yFDWH49QtFLGwWL2zrvObaSkMGM4Ec5bEaAMbQhqPPhb Q==; X-CSE-ConnectionGUID: o9zd8OjpSTOuYaF6LjC+NA== X-CSE-MsgGUID: 07AFIN19QZyyqelV1aCFCw== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026510" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026510" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:23 -0700 X-CSE-ConnectionGUID: +TZD++AcRbmdfhPS3xwoHg== X-CSE-MsgGUID: O1/1xVXgTTuOECAmH2hHRg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739481" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:17 -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 , 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 v13 03/10] mtd: intel-dg: implement access functions Date: Tue, 17 Jun 2025 16:45:25 +0300 Message-ID: <20250617134532.3768283-4-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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 Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 1BDB42DE20F for ; Tue, 17 Jun 2025 13:59:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168772; cv=none; b=Qt1tk1m4X2ApdmbOFu6bE58CFn2sojpj0A+39J3krp7Gqj/UC/0JdktNYW33ltei3LvqgHQFrVp0oryoI9jeJGziRidAatUtYDNhBKugWIJa9l+9IZMUL+Xvyou7otj0Qyv9rCzJcYz710/kAzt+6/2P3oJ6L/S5YMWv3hVEXZY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168772; c=relaxed/simple; bh=1rWZu6zk+/8Dn/O0RQ+wvJF7YY6eB0G1xr7Z4PhkCPE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nc89c6zTnKDq0YVWLnvW8iJ3+pc2CD9R9IlTP702r74Ntatakqhs9Bi0A/GcctWt2rHXbo2lBc9cQvxYp1Bm0ClYtw4aggWFb7x3d98R1EAuaEaEDrfcVOLI13zFOpCi+Nn/ZIGPqUlGBOGWjVzeHIOnVFsgFn4gIs+LNOquZwk= 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=Lg8gm7Ua; arc=none smtp.client-ip=198.175.65.15 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="Lg8gm7Ua" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168771; x=1781704771; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1rWZu6zk+/8Dn/O0RQ+wvJF7YY6eB0G1xr7Z4PhkCPE=; b=Lg8gm7Ua5byFzn9pgag5preUggt276W8BkReuEOAAIONRXQlxsh+6yy9 Gcss0LeRYiuLAA7cF3rUlAqwlEGXQUGFF1IF/35LMP4aTPjNdUARY4PFv UKYwObnoKPsH4C02xX6aHhJK28E03hVItTnrozNNWn+Z4Py3F8mX4wDO/ BTD5pfN4/7NKLZ0Uc5oOc0tRSJpam57cSmZbihNzkYY/uurlvN77nMwGZ 6XyNinIIGj5+UzGLZoR7pXSVFXw1p66yhp2r6R2qsQJZXT+mSoVfquUSN tiEd3O2ulVV+r88+IFP7ic+w0NWoMX+fu//JeYm79zkLJxjpiK7dYPSPr w==; X-CSE-ConnectionGUID: JaHqgXtwTXe2ake6WLrAJA== X-CSE-MsgGUID: tT46UbOHRO2/XajSUkzoSQ== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026535" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026535" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:30 -0700 X-CSE-ConnectionGUID: srpDNi0vTCa0Ur94taDj6w== X-CSE-MsgGUID: jojVs+5KRGeqQ3501Z4Ivg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739507" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:23 -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 , 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 v13 04/10] mtd: intel-dg: register with mtd Date: Tue, 17 Jun 2025 16:45:26 +0300 Message-ID: <20250617134532.3768283-5-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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 Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 1C5682E3B14 for ; Tue, 17 Jun 2025 13:59:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168778; cv=none; b=bqH0tfgMSPHdRAqAtEVnQ8oLLeXffqivAGtrtK7eDsRtzi1i+nkIR9aPTuc893BOCTy0L1AiC80k1YLPSBg/MRXM6U4UrWBRchXn950YhIimIwAPa5z0l7TYALSFKskvUyB41nNoFjkFdrPXvuaEIdJI6EMtGKejMdrQa+w2Jv4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168778; c=relaxed/simple; bh=MkAaleCQCNNCm9AdIhhOV9O8nKl/pJB/jBgEA4uGWKQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Enaum1Stxid+1eFo4zTXl4ZoxXOrzrABB8wmxYMZaI+zdaDn2M+S0sc6DQFv5itqshGFPRUDja3Jo4MW5ewom1Nld/dB5WmRsSxnilvNDhFZ4h0GEoihdaR5WJf7g8j3L3nHBrSTXpPIJAs0dvl4XJmkfa8cEzEepqQae5vv3VA= 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=hOKbt8pN; arc=none smtp.client-ip=198.175.65.15 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="hOKbt8pN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168777; x=1781704777; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MkAaleCQCNNCm9AdIhhOV9O8nKl/pJB/jBgEA4uGWKQ=; b=hOKbt8pN8zyGQf2D3Lu6pUGg6Hflr54GU4lcj2ee5MyDxvfKj2sFmzNs CzCGMlO3M6lVwFdb9F1CknxEbqZKPmllIobT40X5CO3/B3Ijkf5yJD8Bl DQ4Ev9FtD8HTZMiKHJW0RTZSc3ebWhDIDC31xVVwPWjz59qRXKkeMHcQu ZMk455HDahZ63RmWQuLIE9/tA93z0Y2L73j3uCdxnBGrg7XqMzC7ZETPz fAFvm+kv3qLk6dEtH6g2mxRY9b4LLtdNjcoPhv0JjbolYbr75HaJ5QGr7 vy9DiKz7KeVeKLW3Y3nKShyYbh7GepYCeXaqdMzEA9NxwOKQ7SCXa0FLM w==; X-CSE-ConnectionGUID: 7L73qfNLSYmlHC75f2yQdQ== X-CSE-MsgGUID: 1fwpcGOCTny/Fwl8LqFu8w== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026546" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026546" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:37 -0700 X-CSE-ConnectionGUID: PbhM4P2yTgCbvnOoS790gA== X-CSE-MsgGUID: JXDj5XcwRMOH719PZLtkww== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739519" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:30 -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 , 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 v13 05/10] mtd: intel-dg: align 64bit read and write Date: Tue, 17 Jun 2025 16:45:27 +0300 Message-ID: <20250617134532.3768283-6-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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 Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 877A32E4253 for ; Tue, 17 Jun 2025 13:59:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168785; cv=none; b=GACkudp5fT9iIsaOdA85LLRWjgZ7MRaPtihfxO8Ak/4D8zaXJ8DXjYBjj7rqje0hXxMku1SgnlQaAuLY3I+ACXWq0K7HGvfgMlUI3V4iSnfspGte/6D5fFMwojENAym8vlbr60vXqbjDdXIhf9d5ME34OBKkncGLniAG7Y5G6HY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168785; c=relaxed/simple; bh=q0hWiCYmWKAaZmB913NuWi2bGtvj235TysVC+ofT7zg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Zznb9RCYjbcmTpqCd9xg6GAUbtvIG2cm2UNhRH1NTQDWFTIlTiJPeFNN/74AzrAXqpwvPTmHW8TuKZzruze5nneS/0IKeiXlrbnsk18O6k9dHS68SeAiv2MKhjRDZCbeT6ChR4PalhvdiIvvsJmnDOTKpx98X4UgU1aLX+hr6Ek= 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=aPIO2alt; arc=none smtp.client-ip=198.175.65.15 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="aPIO2alt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168784; x=1781704784; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=q0hWiCYmWKAaZmB913NuWi2bGtvj235TysVC+ofT7zg=; b=aPIO2altna8Ip+LpVxJyVAJlyuxpfMcrKDYwlfsAKuGQMzWZvOyM/lk4 aXLFczeDTYJ+5EZBDCq2GHNcFY5EyhVUBl29zSdMvftv4dmqjxA+ebMNU 08hP0U6+kIa14SJwrbxRIID0P7oOv9XwtvcaRHJGQl7Hri7zsK8sWTSEN SkN/dK/3f0C+mxDnYw3CYKc1cjcHVcp83sJyxOnzsC9K/NiQfP+F4gSRu kDPwk44RI5OG4dI5nPO9C5rPqF0+wuoFAq2kmlATDYfY9LkmPtCc/ZoZW hIVhJ/Myt3bDPe0kI7u1t5YHTClDqjEwKOQb+KH4KywVHH/2PRlR3CdPG Q==; X-CSE-ConnectionGUID: 7EB6c8uQS3qR9rF/TP5TOg== X-CSE-MsgGUID: vuLuyX4uSIW+gI1ERBkjMw== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026567" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026567" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:43 -0700 X-CSE-ConnectionGUID: Mw7D4kP0RlaIFsOMDRwH1Q== X-CSE-MsgGUID: gnq+P81GQHqzX+BSEZXwRg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739542" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:37 -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 , 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 v13 06/10] drm/i915/nvm: add nvm device for discrete graphics Date: Tue, 17 Jun 2025 16:45:28 +0300 Message-ID: <20250617134532.3768283-7-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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 7c6075bc483c..ed4d15ad4cdf 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -211,6 +211,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 c6263c6d3384..6d83f8d1a957 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -85,6 +85,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" @@ -645,6 +647,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 @@ -687,6 +691,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 5e4c49f0d5d4..ba75e7651c5e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -65,6 +65,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 @@ -289,6 +290,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 52a902532e6f..ea9b90d59cd3 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -277,6 +277,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 Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 945A22E267E for ; Tue, 17 Jun 2025 13:59:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168791; cv=none; b=YnPabiAfUKzPizwYyWP38A9PK5dchpbDIGl6khvJayfGf3XXyGeZMGapSRrk2It8Ed+ilDOP02UiZMKuPOK7EtYjXSZL7HEE7H6SQSxwXzdWia0L5Z+dBhesivPzjZB2YEUF3IoCOWEAZkBisnIRRqYZjCKHfYv6NuXE8dfrpME= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168791; c=relaxed/simple; bh=brHnIOdScb0KxCyYh6StjKNndkZEaHPzreNgxMkxZxU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Hwh9IhaVzS9bMSTxR3ciSoOEadLU8js3a4quovEqE0XaOt88STdZupbOTbBp2DitZnPX7Qa8fjJarn3BZ3kQ1roS97Q92YvjX+RhfSWz6oDUGerwWvLdXVw03p7534svbUB4nJrnq0XWzFconPzmT0FhlujgO+RueT0WOmWIJTo= 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=PGDzQiCI; arc=none smtp.client-ip=198.175.65.15 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="PGDzQiCI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168790; x=1781704790; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=brHnIOdScb0KxCyYh6StjKNndkZEaHPzreNgxMkxZxU=; b=PGDzQiCILF+ErBHaI7GdSz3FZW9nRcSRy/PaTmJSASMySLAAH3bzT9Wg la0IJXW8VFkvf7d0ABo91g7g4P/Lu3fhI6UspQl/Bry13INegfpx1T9Mw NcfXZNjUx7/DA4+I03TGNnODVVIiEd8dGqLYjEJrpnut11Snaq30UUtWs cEhKX6RYz1lcOs+jlAG7Gci5IYtEfPE7Ej1OHBI2DpjzKo+T0m3H4O+xg oc0xm+DP6r5vfpLVY4rmJ4aKfBcqR0fqst8BfXEb9GpGVlCb9vCkf/bzF Vd4tn7Ky8k3E32/nt/ZcJN8PGP4qdItBEoKQAjxRO8E/7oCAntMR4HkZ+ g==; X-CSE-ConnectionGUID: 70xAjLH2RuaTOnBnxVhmVw== X-CSE-MsgGUID: 6Cpe5BQxQD27fq8r3qHlnw== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026582" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026582" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:49 -0700 X-CSE-ConnectionGUID: kVM6VBcbTL24Dzz690BmJQ== X-CSE-MsgGUID: SteaBKKCRLeHZUO7Whk3Ig== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739554" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:43 -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 , 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 v13 07/10] drm/i915/nvm: add support for access mode Date: Tue, 17 Jun 2025 16:45:29 +0300 Message-ID: <20250617134532.3768283-8-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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 Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 3D4B32DBF4C for ; Tue, 17 Jun 2025 13:59:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168802; cv=none; b=iCYIq6Sy67DR2//Ax62QsRbT90c/tZAo0Z+W8lLfphV4eSW2N9f7v+27GnRV+Gpva34QCa9MgPnfsjjyjDccyXban7ldw/1HrWT3I6yRRCCt7rW3xz5c4zoNEzqzb/BpvNWdonMeiNBiFs3xgtDKAS+VnjWl0XG+P48B7EMIeYQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168802; c=relaxed/simple; bh=AcC0NG4hsKbguskxsYFmplOm6kj9faB0tBx/chwtYD0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jOY7RoLQcpNhaljMv7qTNQ739jJy8zU1qIS3LooBVvZ6npa5Y6t3XrfKVNzOXSjulnkGdcv4STek84je2Mxcnht4RuL36sn36pGueiJc2yNQGhdh43ko9lDnWda8lRZo83+gAXrDsnaIIBpNCm0dK2vc82G56PocK/kDXTYwtqE= 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=k1s7HqCk; arc=none smtp.client-ip=198.175.65.15 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="k1s7HqCk" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168800; x=1781704800; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AcC0NG4hsKbguskxsYFmplOm6kj9faB0tBx/chwtYD0=; b=k1s7HqCkmhjCfsPRE/7QWi9MaPhf8zFYFRXZ7LJDG4TFj3fXBhXnG1qq ACY0unIYAPS1xKMq9yD3S+LWCTh2B5Qb4qVpZjObxAEJ2TBMJB2KKDIue r475uQV8ryTsx/qYULN041hk7IMZIAcVGLdcvBwZVRLw0p0XiHniewOlI /R4xreFgrZfz/JJQ/8NsNoVLjYMFjYvzd4Jv2HMRS//H0V0iQuf4Jkj0n RThuID7ioIX9Vr1WhpKDRx1C48A3nYKNKjxa+FjppVAeKM2tBpk51u/B/ bWp4bB/e2Fso2lDcuTvAQLl5N2Z0NxR6VMWCLc/ij1OP1wmJiyiw56l/0 Q==; X-CSE-ConnectionGUID: yXwqABi+Tkm7eOD5zqCbrg== X-CSE-MsgGUID: cb5BlatUQuOiAP/7/tYwrg== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026611" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026611" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:56 -0700 X-CSE-ConnectionGUID: PlO27p/oRZ6QGAZWGHdizg== X-CSE-MsgGUID: Hg1wsBAwTziLWjcbUu5edg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739575" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59:49 -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 , 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 v13 08/10] drm/xe/nvm: add on-die non-volatile memory device Date: Tue, 17 Jun 2025 16:45:30 +0300 Message-ID: <20250617134532.3768283-9-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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 f5f5775acdc0..7c039caefd00 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 7e87344943cd..c7d50b098b5c 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" @@ -881,6 +882,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; @@ -938,6 +941,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 003afb279a5e..6aca4b1a2824 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -32,6 +32,7 @@ =20 struct dram_info; struct intel_display; +struct intel_dg_nvm_dev; struct xe_ggtt; struct xe_pat_ops; struct xe_pxp; @@ -316,6 +317,8 @@ struct xe_device { u8 has_fan_control:1; /** @info.has_flat_ccs: Whether flat CCS metadata is used */ u8 has_flat_ccs:1; + /** @info.has_gsc_nvm: Device has gsc non-volatile memory */ + u8 has_gsc_nvm:1; /** @info.has_heci_cscfi: device has heci cscfi */ u8 has_heci_cscfi:1; /** @info.has_heci_gscfi: device has heci gscfi */ @@ -549,6 +552,9 @@ struct xe_device { /** @heci_gsc: graphics security controller */ struct xe_heci_gsc heci_gsc; =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 5d24cc320d72..367d2b2c2ded 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; @@ -273,6 +274,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, }; @@ -284,6 +286,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 }, \ @@ -321,6 +324,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, @@ -351,6 +355,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, }; @@ -595,6 +600,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 Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 54BF32E337C for ; Tue, 17 Jun 2025 14:00:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168803; cv=none; b=E91NCvZc0xPU2Zj9PvREE5C2zYQHcCxcx2WOkOq0YY3oBfO36LZTBv47+EKTHVpvchcCOAIRLJDqcjAtczfcVQcvaAXT6HW4kfrzTYDVm4c1EkFthgAqWjdIQxvsVFq1DuUqjPGARXORXuuQ2QijuUhIXsZxkotLKaV2JHnN4PI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168803; c=relaxed/simple; bh=luOze6g0PP5F5pCLOK5jBaa2umhqnsfnayAFqvQ9H4M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AAy10qcEHK6U9sCdPQxy/RRk/mN6rgYBlRPr6JfEz4mfaIzfmLCuqxslVnnkuZ6Xd97k5pnbhShEA0sl8Q//sbPCe6/0XoiXw8ZfpTqw0IQyk4ztcA5enA2hu8zwTNAzTNVmw70mYIjQOaciqwLjP1cyIPsyYI4CMT7c53eSXVM= 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=kEFdY1Pa; arc=none smtp.client-ip=198.175.65.15 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="kEFdY1Pa" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168802; x=1781704802; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=luOze6g0PP5F5pCLOK5jBaa2umhqnsfnayAFqvQ9H4M=; b=kEFdY1PaIU7yD332r/EJ59NDEqLjBbF5BAO7XaHCg3g3vxLaxVenL5nH EX2NpX9ls2PccIXWyheOzIXK1O852IOEjHkbKBuuURo05iV+xwUmTBhpy vFwrgQ2sLS8UuhxugY5XaDel5ntx2s7/LM7Y6O6mvTjdnp52EloH02vsO rm9pMQJqXQcxAhHQ8xs7nxoYdWF11n/XrQNeFrXHXmPpWPS52sVFrG4Ml LEqluWDESEpDqf1hHgVCsbXc2M1/y/208YypoLN4fehreNNwYzoOa4loY kh/WS8LTB/fvt/2eH5BFbzW0BYIyr/mFpIubRe4U0EvtqMfPhysS7GmOl A==; X-CSE-ConnectionGUID: JvDeQZY+T5yob3WDa32ZXA== X-CSE-MsgGUID: aLLdW2cETlmyfJBYfMl6IA== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026621" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026621" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 07:00:02 -0700 X-CSE-ConnectionGUID: i15ZEAL8RnmLowW2w0pDRQ== X-CSE-MsgGUID: 0G+t6T5yTzyE6tQFi27Gjg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739583" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 06:59: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 , 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 v13 09/10] drm/xe/nvm: add support for access mode Date: Tue, 17 Jun 2025 16:45:31 +0300 Message-ID: <20250617134532.3768283-10-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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 Thu Oct 9 13:34:56 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.15]) (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 B17EB2DE1F0 for ; Tue, 17 Jun 2025 14:00:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.15 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168810; cv=none; b=rKjFdOOwMdFrfxi6kaxdnfJpVpVSOW/z3Q2RDc8HpLwSWGm2RLReBoiUk1uRkNUhy0zo+Itqy7vTmD9Iy0SEMzDEKWbmHughyOaWvcN2gyhSd6bB0i9B3Wi9mEfr2+OMxdjyOq4EzlL1JI/vOzxaPHWTlhc6jhN4n0HnxShJRrE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750168810; c=relaxed/simple; bh=fH2hdGzwTf4pZxd5L5oHs+dVIY/4d4It2eb8BdPFp3E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lBk0Yuwva9DwmrYKb6aff9qg/kw/Oob4l20xlo9MOeZ3er9KtUcbED7dMm/Tvirl819Nbih9yOzYqwS4j2iS5RjkBUUmZM/w47SQmFfDphR+Z2Cg8HvajKldLngP/bzhTU4R2LQNTXPTirx+MfXjAIO/jGgrZ2C00kxoEMFT1us= 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=BQLBR045; arc=none smtp.client-ip=198.175.65.15 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="BQLBR045" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750168809; x=1781704809; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=fH2hdGzwTf4pZxd5L5oHs+dVIY/4d4It2eb8BdPFp3E=; b=BQLBR045vlaI7BiQiBa4zlfagZgGm82qx3umRS4hMy5KNkKesJ6IMrSU iwvdUlVgliLaauH9w3pvMJcZ44UkEjPtPrEObskqfKCC8Q2oiDCUAa4Sh CLD/dIF8YiTEL0XPua8VpJTmadf0oXur24+S1YdYaa2WNkudyQDyjrVGq wyUb7bNnLxcuyCQYUAgl+TpFlDXMAL50mIcl1vYLBoZ6Tz5sZ10OGmF65 zuFaAakpVcUfC7NJeIbnVB5N3q+wN1HEFAd2YmCGZm1SDFl6YF/QAkWlp 4RxVKswIFcv/tCT1tRiVShpqal5kcxFzKdq5kzpIXo2kZaEJiA9dAImDp g==; X-CSE-ConnectionGUID: meoOLQCoS6efhRyGv86eQg== X-CSE-MsgGUID: Ok40gKz2R5K0/ILdZ6Qq7g== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="56026639" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="56026639" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by orvoesa107.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 07:00:08 -0700 X-CSE-ConnectionGUID: 2IFawBLdTQOaUXsDmhraDA== X-CSE-MsgGUID: stGB8uL4S2CqXect/Zb6bQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="153739594" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by orviesa004-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 07:00: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 , 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 v13 10/10] drm/xe/nvm: add support for non-posted erase Date: Tue, 17 Jun 2025 16:45:32 +0300 Message-ID: <20250617134532.3768283-11-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617134532.3768283-1-alexander.usyskin@intel.com> References: <20250617134532.3768283-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