From nobody Thu Oct 9 13:34:55 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (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 A4B5D2E9732 for ; Tue, 17 Jun 2025 15:05:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172738; cv=none; b=M3RWBPj1R0dEks/0lHyycp4na/6rT43AabDzyM9712u9VaQSDMVGRD2eZhqxrDA8XxfS6zpjW0ht2wKMJVAXuDbyDe854vimRPg4ALS5ihqk1jiXoRY3IrSMWUt6/sEpyA31gJ9ZYjujtjGcdpAkW+iDEEvL1wDViko1GYKo6h4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172738; c=relaxed/simple; bh=whBs2iAagZKltqwmIXWaToW4Srekvx9gqm0G/7aOwhc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k7zB0JGrFDz5gmplP6D8gnrcVMrUCF+YUziwMB20Vb029WYtp+iBQjYcHRuXtCLlaVaE8wMO+itx0KyP1XYSsUBjEd+of9sXNsXjQeGZEKKzZmghvf8EDOf5mKGo2tJ+idiUvy44XaSQg19PUPgbFVjTLxDdWRUECPO+BjThoNA= 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=YjZ75WEW; arc=none smtp.client-ip=192.198.163.9 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="YjZ75WEW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750172737; x=1781708737; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=whBs2iAagZKltqwmIXWaToW4Srekvx9gqm0G/7aOwhc=; b=YjZ75WEWMSyusE5PPF/QhyiexgsFrrY2h09x7hDFGyRz0VbN2+WdDgTE hQBclWf4lm2ASpFU4XxHxaEewWer8aNt9Pr2h5RRyb9jG7UneaWhZpQu6 5u1nSUPIEwptHivovvNSj8b2Pe3zr+Rxfk5gDXLeBIqAdCjKr5qt8Mpga mPxSb0nPHYD3wuzxERc1l+U9nKhhdf8gXdNMUayxJwonIG9O2Y+36h0fJ JrXM+V3Xa5RPY2h+/YcBy82KH657E3sLJmHVGxJbgqSgnxhf01BExBuWJ ExXc/VzQn5HvEukTLNwlQuO9RbbX7N3tDCjkCtwgwjB1dd4XYNYlTisIC Q==; X-CSE-ConnectionGUID: o1dTaVOXRiet3RDTkAIZAg== X-CSE-MsgGUID: hXaFlvIeRHOy6/NjqoQBvw== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="63008738" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="63008738" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:05:37 -0700 X-CSE-ConnectionGUID: kdMoRDLJTxGzpmGblCnDKw== X-CSE-MsgGUID: Eeux6R3QT4+Zehgvx1wkWA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="152672151" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:05: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 , Tomas Winkler Subject: [PATCH v14 1/8] mtd: add driver for intel graphics non-volatile memory device Date: Tue, 17 Jun 2025 17:51:51 +0300 Message-ID: <20250617145159.3803852-2-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617145159.3803852-1-alexander.usyskin@intel.com> References: <20250617145159.3803852-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:55 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (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 D0DA52E974D for ; Tue, 17 Jun 2025 15:05:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172744; cv=none; b=bDLnwBLyS7ThwbjcQUBder+/eB2YDyNtTMMCLDaW0hqufhjgi6zUA1yynWDd1+Q1/ukfslKIalKOmKeMSorjOCgNVGvKF3cp0QA10SpN3u+AKjY7/dcH5qwinGnDAOCQDCZplhBLZ9PGm57b1DgcImOZYRZupBNBfwgEFafAJZw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172744; c=relaxed/simple; bh=GFube+gC6502VTBuZaY4++giPU/6FLO2ZUzV5+IsC6Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=o5tB2hJfVQ4WPocWLzNmknOSWJreeFAeJaF2mrGtKH7i7VcIyFcejcjNYy7GXZZezl1wh5Fmj5H12p7GCM04gh4DAp0HwqULRmKmMpz0GBm9wo3mrjtAZvw20pcD8K+kJ4dOiIU8ssooIPc5ko2m11XRsJfx2PksRw2wIYjf2Ak= 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=bhificOU; arc=none smtp.client-ip=192.198.163.9 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="bhificOU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750172743; x=1781708743; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GFube+gC6502VTBuZaY4++giPU/6FLO2ZUzV5+IsC6Q=; b=bhificOU6t8AAMLO9b/IPby9mhVCYqTLT+Z/a6+FxP6HPOBBb0eEqc0C oiR9fMbDGaAOHvDADbfsg8qHt6G0HVy/OJNuzfQkFMBdA4bARIjyFrVb1 +sK6RCO/kubTquqzsErNheRvh1YXazRyS71clZjKpn5lH87aOgQko9W5Z OEewZnDlsiPglM1CrsVYeEKiwx1KO/uM3PROzixRVEgkokA9sorHTGd9M wgxWFtdsOsYIxJc9fjs3bf3ze5R6FSUpHg77SIMzsRN0AE/dvqVAftZWp L1TegBeWySKcUrX85DhsBD9yA5Ves3eOCFO5wVFzfJHsqZp0CO/DM9y/K Q==; X-CSE-ConnectionGUID: IGgq8s+ZS7OrJVuJtS2KJg== X-CSE-MsgGUID: iSb0rgURR9Onbria59ud9Q== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="63008766" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="63008766" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:05:43 -0700 X-CSE-ConnectionGUID: EJ7WXqzzR1ecdIUmyyWTpg== X-CSE-MsgGUID: aBHDY+fJR4uaJ6JRwNCzPA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="152672208" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:05:36 -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 v14 2/8] mtd: intel-dg: implement region enumeration Date: Tue, 17 Jun 2025 17:51:52 +0300 Message-ID: <20250617145159.3803852-3-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617145159.3803852-1-alexander.usyskin@intel.com> References: <20250617145159.3803852-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:55 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (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 3B5A82E92A5 for ; Tue, 17 Jun 2025 15:05:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172751; cv=none; b=uYxPVRYfwbeJzQMB1hxTOrN4kgK5gYHmRjmRdZmuV7ABtRWQg5shTRr7e9sr35lHvnxmqW6WvI+8HsLST/KKAGeUO6HLJjsK2iZB1Ojq8xB9G91U93pQU/t/DQa/3itmGPF2jwMS3cppT1X85AYhbikFfawy9fArkryUnKBhL58= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172751; c=relaxed/simple; bh=WvLWJRAv8idelb+wbiysTqm+mBTnrzkj5Bl282lOSrk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O74Ut63E2RGiN+Q/gLJ0zLfnausQsWXH3iKidTunknjt/rxMDDxJ9K9t9DtCexRw8+d/VzjMBl2ISyJmopOW1Z0We0rkGHOkeRAUisyL/BsH4b63+qupc3Ba984UoJRk8T6KZZoH4sFSxSYIxL6c38OhTDfSpfNtm7TzqUoxYJg= 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=iFdtQw+N; arc=none smtp.client-ip=192.198.163.9 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="iFdtQw+N" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750172750; x=1781708750; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WvLWJRAv8idelb+wbiysTqm+mBTnrzkj5Bl282lOSrk=; b=iFdtQw+NjU1HlFN5oVgKenUJUMjr6jBjbA5F9xOtGZQvnoMr/LpRUIm7 X6TFrz5tPSMx9lQ/BWCaUMdHfCcjmgab/sHhVhsDRNUyYjn28OBpQiLYy BjzplmY3sWP2G1C6lQke9dra/QMNahrHexNhVAG6by+2HO2FwIgB5W66A cD8l64SIlCEqbYNamibYoW69w9Lh+DAlOYDiLLToIzXevFocT6t/kJTtl FKxEikq4C0JeEOfXdAtfvYMoywm+PRrHweAWEFK5zLeMx5BE+klSmO3hx OhmpuvUe1FRjO+5f1egG9/nrIbSVwWWiaipkAPu30yVVoaxqejf02LCs0 g==; X-CSE-ConnectionGUID: xQMVLNx2Qu6w+ailrMhBgQ== X-CSE-MsgGUID: 5zBsM0aYQKuHEM6BFjkFdg== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="63008799" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="63008799" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:05:50 -0700 X-CSE-ConnectionGUID: 5K82F0eBQdmzCaF3yqASiQ== X-CSE-MsgGUID: 4kn8rnixQh2vyIHcgeETgg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="152672274" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:05:42 -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 v14 3/8] mtd: intel-dg: implement access functions Date: Tue, 17 Jun 2025 17:51:53 +0300 Message-ID: <20250617145159.3803852-4-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617145159.3803852-1-alexander.usyskin@intel.com> References: <20250617145159.3803852-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:55 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (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 CD4A22E92CB for ; Tue, 17 Jun 2025 15:05:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172760; cv=none; b=N2lk4stUD/Dk3vv46ZtdpYT3hVspOoHoXwH3y1l442fdeE7guW6DvQVJYcU27zoQrVeidoEszgh4cL5PqnSWl2pcpLfbrMqO3ya3Af2T6+7S4J0XOFAsn2/P5LLP1MwDqfvHAxiY1HbDn353cH4gqoQSLbP6ocxhfU/DegTXm9g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172760; c=relaxed/simple; bh=1rWZu6zk+/8Dn/O0RQ+wvJF7YY6eB0G1xr7Z4PhkCPE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GlBJbUOtOyifmsobJqfJmAyXGfx8sVkzsnhMJVayV4gqzDyaFgfDuYW7IVvjhF57LWXv9P0L855icpDEoT4O7z5E40JtMhjrWBQUl+Oe09QqxJfw9VwDUH5UyP712Mg6ORp8su8rm9tgTEInnDb9tr46zSLJXtUXyd0TidFU6Qs= 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=K2dL9G9h; arc=none smtp.client-ip=192.198.163.9 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="K2dL9G9h" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750172759; x=1781708759; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1rWZu6zk+/8Dn/O0RQ+wvJF7YY6eB0G1xr7Z4PhkCPE=; b=K2dL9G9hQqGULHQUNv1Uuk91SJHjQkpyqwyjMTTOWu/yFZXQbxWlGWLY VxeyWfhNAiWc5LFs9DOVXw8atVy9ZXCvB8dWQYcPvLFstKMXoneDnL4BQ xv47zSkCM8ZILxASWolQXcAAggAdgxQGp6JnOz3+FTM2oCJkqQtulLIvs XmPXeJc7wuw1tzIVHQNU5Pv8bIW+kVYYhlQMK5tU+xEjvIDcyUybw9Xss 3xMUrBm0UiekW0ecqPlt5K1ojQR4ZggB2ED3XGp4zNCjx2YthkvHxjmEb xzUpbk9RitdSwhyKPBpo9QIeqS8E+MLhZaZrqFUqy61S2cd6pjg8PddGB w==; X-CSE-ConnectionGUID: droClPp4SNaCL5gCvQD20Q== X-CSE-MsgGUID: MBOpuSqiQH6QDHR46aDUZg== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="63008842" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="63008842" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:05:58 -0700 X-CSE-ConnectionGUID: PLN/m13ET12KKwAq0tV9yg== X-CSE-MsgGUID: 7nHd4GGnRy2RaaouO0/3vw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="152672357" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:05: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 , Tomas Winkler , Vitaly Lubart Subject: [PATCH v14 4/8] mtd: intel-dg: register with mtd Date: Tue, 17 Jun 2025 17:51:54 +0300 Message-ID: <20250617145159.3803852-5-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617145159.3803852-1-alexander.usyskin@intel.com> References: <20250617145159.3803852-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:55 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (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 405CB2E92DE for ; Tue, 17 Jun 2025 15:06:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172765; cv=none; b=LYGKa/y8SeACvjQWEzdAhiTP3aQLHfHNG3bKI/9KPjkGHxKl7ud4Zf6pjxkRWxaUoUdrfm0Q01khL37QCB7RQ4z1OISL0wOPYfhfK9ezEoD0985/S+E7+5E402wBHKOMfh/h1ZCHEshkS9V3HmbmXLXyxbdMUl2WJgKlnO1GlGs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172765; c=relaxed/simple; bh=MkAaleCQCNNCm9AdIhhOV9O8nKl/pJB/jBgEA4uGWKQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sLUCije07f6NvLPxuSviDc1ZzwpqLw6CP/ZLdBzhFJYKaPFgIa1g6R3YDvZXIjwbXWq8kzae5a/fhiSRe0zAfJfYFfjB9+EhHIU0OuVlKB9bIR2UGnZs0/gNAhO5q/0J3EcL296pu9iJEeCr31Q1+V6KSbU8Ynt2k1oBFged4Rg= 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=IWrgbtnq; arc=none smtp.client-ip=192.198.163.9 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="IWrgbtnq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750172764; x=1781708764; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MkAaleCQCNNCm9AdIhhOV9O8nKl/pJB/jBgEA4uGWKQ=; b=IWrgbtnqS4yLmrPEA2PmPxJ4SIUNYT/vAS5CHdzNN3a7FIc4yCrjgq5u fC+xaTopfgtAWQQ5+DxuOupl2UHVNsjIkdSz1IOr0oNuJw2QOAdsYI490 gqxMW2n7YYdPSX0jEyfhDFKr3HL4jv5vlYoJMjfgG07kX9TzheOtO9r+s 7b8NI+fR2BBb+nGlUP4ZjJkMupHA26r348llajef2PyfRUZWVCn4gbq6x KawNwtelfMeUDC8vsecdO+vES1puvdjT1nR008yK8m4ET4AxC7jpETIJY OM2KDTEToMoQFPOfhAalANi0WchoQ9PQLaQ5hKQZ3sqC9j+Cmqg7VDrON A==; X-CSE-ConnectionGUID: IKV9kcV8Qc2RfLwSfa8jlg== X-CSE-MsgGUID: hVFnFQXLSXWj2v7+ZIQqRg== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="63008880" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="63008880" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:06:04 -0700 X-CSE-ConnectionGUID: TSTXB9ytRMivJi5Xsl9lhQ== X-CSE-MsgGUID: px+5zqaBQluQwlaJqwyHLQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="152672420" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:05:58 -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 v14 5/8] mtd: intel-dg: align 64bit read and write Date: Tue, 17 Jun 2025 17:51:55 +0300 Message-ID: <20250617145159.3803852-6-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617145159.3803852-1-alexander.usyskin@intel.com> References: <20250617145159.3803852-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:55 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (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 339FF2E2662 for ; Tue, 17 Jun 2025 15:06:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172774; cv=none; b=FJzjUDp/0h1bjobogGWEhWvpH4CDFSVFwkS9UBeyZDo8YeeVxA6F6eoVeU2n5TJR0Kg18uQR02UR5Xx+k8sDgeaV7b8imAgAXdBx44dVSYZjpb1zrvGO56xA92rjJ/ChlMeXSJI2XrAD0KcK+gMFtMlpVYHi9M3e68lQtZ3On9I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172774; c=relaxed/simple; bh=AcC0NG4hsKbguskxsYFmplOm6kj9faB0tBx/chwtYD0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jJmgVC6/BM65lmKr8w2hQpi5hJOF4RbFif+iKh+g5MWHwSNHRe2n24Cr/QQYgdrxY+2accv8ux345AbofLLL2U8Ps2fy+S5eOyZX2uXzkTuMDkKamJEVzp526qucsyXh7joX79WiMXxycQyaxqLm29SG9IxZJcbFgQe03q0L6Xo= 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=D5utNkzI; arc=none smtp.client-ip=192.198.163.9 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="D5utNkzI" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750172772; x=1781708772; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AcC0NG4hsKbguskxsYFmplOm6kj9faB0tBx/chwtYD0=; b=D5utNkzIkX/7LugQzFsc3JZdoK7eVn5mVl32neMlRXkIloQO4x5UHPsG YT8whBhYNPA/dMsVolVjUmVIBFOOozEphQd0pRz+gY6S3SSJIkZhM1eTM gSP/ge9b5K88VOlLPVjA6ngY2SwR7Zo9PrcQyWT5ZuXdR+DTzVuvCtjID 2HCLTne0TM2H9hsf1DSqC5E4vBdz9FoHQeUfd3/VOHNIJhABUBVVNfNnb hkP2jf6MkqKV6zMtcXKAtrHXHCCZc0IUfNshB8IhUT0FP9IS5Xc9nzyxH mkW0B1CeRtLfRmFXQwEWkGFl+zSIWOkU8A1wzHktnFXLrPgADXtIjRVsj g==; X-CSE-ConnectionGUID: 0aseW1RRQw6w1ByxOKgHfA== X-CSE-MsgGUID: B4DtQG1lT7ylor7WyM+kWg== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="63008934" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="63008934" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:06:11 -0700 X-CSE-ConnectionGUID: gZYqdmarTtKJQrqqBstHtw== X-CSE-MsgGUID: s3VCNXwzSbyxxIRNAOPkuA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="152672476" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:06: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 Subject: [PATCH v14 6/8] drm/xe/nvm: add on-die non-volatile memory device Date: Tue, 17 Jun 2025 17:51:56 +0300 Message-ID: <20250617145159.3803852-7-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617145159.3803852-1-alexander.usyskin@intel.com> References: <20250617145159.3803852-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:55 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (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 6E02C2E2662 for ; Tue, 17 Jun 2025 15:06:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172780; cv=none; b=RhJXHN5Bxhs369iTsDrp5RBaWmlBaZSLLPJJuUN7fMfgEsaCS7Sg1OW7msnW/m4ia1tRHbeEvfEgxo5CqDqmOrGfaRy/5pMcz1mnOjzjuxNufgU5BtKbhkKDqEF1rFJsbvZLY+py8sE6cLTBVcff+VegBDiqfzvYwIM+fUXABBI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172780; c=relaxed/simple; bh=luOze6g0PP5F5pCLOK5jBaa2umhqnsfnayAFqvQ9H4M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kzFALUAjTciQnI36lUio7tT4HWeCv7Q3HiaE6JD3EzN+EjUElM5WLPA63RP5mzWFM1I6pmXjw/SgRaliHswi4txRZzg3sHQYpyqSs5xcXhZjgckNuRBPeYpOhao5cLQR7o7d/+GrQTKXVQv/f4PyFjPbdvg89XvZw62quCVKfGk= 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=I+riMXFb; arc=none smtp.client-ip=192.198.163.9 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="I+riMXFb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750172779; x=1781708779; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=luOze6g0PP5F5pCLOK5jBaa2umhqnsfnayAFqvQ9H4M=; b=I+riMXFbMcHAQmrwie3gJ1IP6HQe5ksbvNe25OMVxU/3njZWiuS1CyIq 6Si14aPtyp5Kl7d/No5xvVlNDINOVVsz2zGJLR2bItS6FpFLeCF1Wvb6c 0jzxGfI4bvcRUcyBNLX5JB2rSkLv6Mb+0e6+gQo7uGILfRfSmH5kzMQuI h0TPoxgpIdXX9GKHKNCUTIOJlxv5WPtWTKhDwxEc0U37z7li92+0V6c9h l9f93Yy07ndSbfVeIM5PBrePu8GoKxUk/qHE9pTIyREKsRPpgmuoMA/Iy tXAV+814J5j05bjyQOMinTPusPCUELdF5xC+RH6NXoraVqq6gKzSPrNSF g==; X-CSE-ConnectionGUID: +DBqxyqRRtuNBmoan4zf0A== X-CSE-MsgGUID: noQVJ4B0Sh+sYuefgWp2zQ== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="63009000" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="63009000" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:06:17 -0700 X-CSE-ConnectionGUID: KzuYzApqQ/i7b3GGQhy4rA== X-CSE-MsgGUID: Cz/996wDTKuXrf6bGtKMUw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="152672526" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:06:11 -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 v14 7/8] drm/xe/nvm: add support for access mode Date: Tue, 17 Jun 2025 17:51:57 +0300 Message-ID: <20250617145159.3803852-8-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617145159.3803852-1-alexander.usyskin@intel.com> References: <20250617145159.3803852-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:55 2025 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.9]) (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 AA0382E2662 for ; Tue, 17 Jun 2025 15:06:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.9 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172785; cv=none; b=TZV+z+u7d8ZPdsx40w9zfgzXicDDe4Xyuy6t/e5FcdlmOxaRKPifsb67pD9jJFsj7j6Ex/hUgF1yKEkPYfSdT7CeRDdtcZI6B9OCUA4EvYPITIeKBxfopJPnzbUXP2HMYlz2qmwPXUQtjSds7XQ4wf7px8uF81FevppdW8HbrKA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750172785; c=relaxed/simple; bh=fH2hdGzwTf4pZxd5L5oHs+dVIY/4d4It2eb8BdPFp3E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dCxo1qo8NdveDy2ZCkC2O4CPbSy3aQgnQR7ROcTNnUyva4LIYAqq0kG3ccLqAPQvA3IRLRJyQiyl7aV5xUeSxivNfyZ+riy9eSG0fmTO41eIaH/YN482c3i2ae6RRgW77SN/zRYuW3k8vbFR49EYwnQ8xIvY8B0Zh+bP7AYinx4= 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=Y8mpSpPX; arc=none smtp.client-ip=192.198.163.9 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="Y8mpSpPX" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750172784; x=1781708784; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=fH2hdGzwTf4pZxd5L5oHs+dVIY/4d4It2eb8BdPFp3E=; b=Y8mpSpPXpu3iwk1oAaQCqwr/LLcLkiXFC4oidNVs5XxHYhSZeTetD+Me sEBIIT8H6CRuq9VeVMrLBQq0dFrJUktwcZc3RLp/BgQLgODD68JSUSMtp ZHJYTxezi5yX0/EQ2j1EuMwWmUix3hsYrvj8a95rzBSdDKZSioqBJ3QW5 x7QzjyxIvzE0CPKvGgdi3ZEJT3zO7lTAthA3zSQGa+nG14DvzuhsxTkoF 7KjCZZXEIoVzsl836O1iduwrICtWhzct9cnlAG5x0SBxpYskM9jdOeuOm qjjbLA4kkjCJDGfydLdhX2VNSzFX+bhNBVMWpsoYIA0+zGvw1bhhX8F8p w==; X-CSE-ConnectionGUID: lho62PyeS6SCnvWhPpRkNw== X-CSE-MsgGUID: YYlW5peMTwG7ODaG9t4oMg== X-IronPort-AV: E=McAfee;i="6800,10657,11467"; a="63009088" X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="63009088" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by fmvoesa103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:06:24 -0700 X-CSE-ConnectionGUID: 7kDG+z/ZRkWrEXaNarPRlA== X-CSE-MsgGUID: 73MgP5m+R4OaWWFt4moqSQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,243,1744095600"; d="scan'208";a="152672573" Received: from sannilnx-dsk.jer.intel.com ([10.12.231.107]) by fmviesa003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Jun 2025 08:06: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 Subject: [PATCH v14 8/8] drm/xe/nvm: add support for non-posted erase Date: Tue, 17 Jun 2025 17:51:58 +0300 Message-ID: <20250617145159.3803852-9-alexander.usyskin@intel.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250617145159.3803852-1-alexander.usyskin@intel.com> References: <20250617145159.3803852-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