mbox series

[v8,00/12] mtd: add driver for Intel discrete graphics

Message ID 20250414093803.2133463-1-alexander.usyskin@intel.com
Headers show
Series mtd: add driver for Intel discrete graphics | expand

Message

Alexander Usyskin April 14, 2025, 9:37 a.m. UTC
Add driver for access to Intel discrete graphics card
internal NVM device.
Expose device on auxiliary bus by i915 and Xe drivers and
provide mtd driver to register this device with MTD framework.

This is a rewrite of "drm/i915/spi: spi access for discrete graphics"
and "spi: add driver for Intel discrete graphics"
series with connection to the Xe driver and splitting
the spi driver part to separate module in mtd subsystem.

This series intended to be pushed through drm-xe-next.

V2: Replace dev_* prints with drm_* prints in drm (xe and i915) patches.
    Enable NVM device on Battlemage HW (xe driver patch)
    Fix overwrite register address (xe driver patch)
    Add Rodrigo's r-b

V3: Use devm_pm_runtime_enable to simplify flow.
    Drop print in i915 unload that was accidentally set as error.
    Drop HAS_GSC_NVM macro in line with latest Xe changes.
    Add more Rodrigo's r-b and Miquel's ack.

V4: Add patch that always creates mtd master device
    and adjust mtd-intel-dg power management to use this device.

V5: Fix master device creation to accomodate for devices without
    partitions (create partitoned master in this case)
    Rebase over latest drm-xe-next
    Add ack's
V6: Fix master device release (use rigth idr in release)
    Rebase over latest drm-xe-next
    Grammar and style fixes

V7: Add patch with non-posted erase support (fix hang on BMG)
    Rebase over latest drm-xe-next

V8: Create separate partition device under master device, if requested
    and configure parent of usual partitions to this partition.
    Rebase over drm-tip.

Abliyev, Reuven (1):
  drm/xe/nvm: add support for non-posted erase

Alexander Usyskin (11):
  mtd: core: always create master device
  mtd: add driver for intel graphics non-volatile memory device
  mtd: intel-dg: implement region enumeration
  mtd: intel-dg: implement access functions
  mtd: intel-dg: register with mtd
  mtd: intel-dg: align 64bit read and write
  mtd: intel-dg: wake card on operations
  drm/i915/nvm: add nvm device for discrete graphics
  drm/i915/nvm: add support for access mode
  drm/xe/nvm: add on-die non-volatile memory device
  drm/xe/nvm: add support for access mode

 MAINTAINERS                           |   7 +
 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      | 115 ++++
 drivers/gpu/drm/i915/intel_nvm.h      |  15 +
 drivers/gpu/drm/xe/Makefile           |   1 +
 drivers/gpu/drm/xe/regs/xe_gsc_regs.h |   4 +
 drivers/gpu/drm/xe/xe_device.c        |   5 +
 drivers/gpu/drm/xe/xe_device_types.h  |   6 +
 drivers/gpu/drm/xe/xe_heci_gsc.c      |   5 +-
 drivers/gpu/drm/xe/xe_nvm.c           | 161 +++++
 drivers/gpu/drm/xe/xe_nvm.h           |  15 +
 drivers/gpu/drm/xe/xe_pci.c           |   6 +
 drivers/mtd/devices/Kconfig           |  11 +
 drivers/mtd/devices/Makefile          |   1 +
 drivers/mtd/devices/mtd_intel_dg.c    | 884 ++++++++++++++++++++++++++
 drivers/mtd/mtdchar.c                 |   2 +-
 drivers/mtd/mtdcore.c                 | 152 +++--
 drivers/mtd/mtdcore.h                 |   2 +-
 drivers/mtd/mtdpart.c                 |  16 +-
 include/linux/intel_dg_nvm_aux.h      |  29 +
 include/linux/mtd/partitions.h        |   2 +-
 24 files changed, 1398 insertions(+), 55 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/intel_nvm.c
 create mode 100644 drivers/gpu/drm/i915/intel_nvm.h
 create mode 100644 drivers/gpu/drm/xe/xe_nvm.c
 create mode 100644 drivers/gpu/drm/xe/xe_nvm.h
 create mode 100644 drivers/mtd/devices/mtd_intel_dg.c
 create mode 100644 include/linux/intel_dg_nvm_aux.h

Comments

Rodrigo Vivi April 21, 2025, 4:04 p.m. UTC | #1
On Mon, Apr 14, 2025 at 12:38:03PM +0300, Alexander Usyskin wrote:
> From: "Abliyev, Reuven" <reuven.abliyev@intel.com>
> 
> 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.
> 
> Signed-off-by: Abliyev, Reuven <reuven.abliyev@intel.com>
> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

and

Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

on all xe and i915 patches to get merged through another trees if needed.

> ---
>  drivers/gpu/drm/xe/xe_nvm.c        | 25 +++++++++++++++++
>  drivers/mtd/devices/mtd_intel_dg.c | 43 ++++++++++++++++++++++++++++--
>  include/linux/intel_dg_nvm_aux.h   |  2 ++
>  3 files changed, 68 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_nvm.c b/drivers/gpu/drm/xe/xe_nvm.c
> index 8aec20bc629a..dd91f2e37661 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"
>  
>  #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)
>  
>  static const struct intel_dg_nvm_region regions[INTEL_DG_NVM_REGIONS] = {
> @@ -28,6 +36,16 @@ static void xe_nvm_release_dev(struct device *dev)
>  {
>  }
>  
> +static bool xe_nvm_non_posted_erase(struct xe_device *xe)
> +{
> +	struct xe_gt *gt = xe_root_mmio_gt(xe);
> +
> +	if (xe->info.platform != XE_BATTLEMAGE)
> +		return false;
> +	return !(xe_mmio_read32(&gt->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 = xe_root_mmio_gt(xe);
> @@ -85,6 +103,7 @@ void xe_nvm_init(struct xe_device *xe)
>  	nvm = xe->nvm;
>  
>  	nvm->writable_override = xe_nvm_writable_override(xe);
> +	nvm->non_posted_erase = xe_nvm_non_posted_erase(xe);
>  	nvm->bar.parent = &pdev->resource[0];
>  	nvm->bar.start = GEN12_GUNIT_NVM_BASE + pdev->resource[0].start;
>  	nvm->bar.end = nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1;
> @@ -92,6 +111,12 @@ void xe_nvm_init(struct xe_device *xe)
>  	nvm->bar.desc = IORES_DESC_NONE;
>  	nvm->regions = regions;
>  
> +	nvm->bar2.parent = &pdev->resource[0];
> +	nvm->bar2.start = GEN12_DEBUG_NVM_BASE + pdev->resource[0].start;
> +	nvm->bar2.end = nvm->bar2.start + GEN12_DEBUG_NVM_SIZE - 1;
> +	nvm->bar2.flags = IORESOURCE_MEM;
> +	nvm->bar2.desc = IORES_DESC_NONE;
> +
>  	aux_dev = &nvm->aux_dev;
>  
>  	aux_dev->name = "nvm";
> diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_intel_dg.c
> index 9f4bb15a03b8..c898107a588f 100644
> --- a/drivers/mtd/devices/mtd_intel_dg.c
> +++ b/drivers/mtd/devices/mtd_intel_dg.c
> @@ -28,6 +28,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 {
> @@ -44,6 +47,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 = 0x0010 4K 0x0080 32K 0x0100 64K
>   * [23:16]-Reserved
> @@ -75,6 +79,9 @@ struct intel_dg_nvm {
>  #define NVM_FREG_ADDR_SHIFT 12
>  #define NVM_FREG_MIN_REGION_SIZE 0xFFF
>  
> +#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 region)
>  {
>  	iowrite32((u32)region, nvm->base + NVM_REGION_ID_REG);
> @@ -370,11 +377,30 @@ idg_erase(struct intel_dg_nvm *nvm, u8 region, loff_t from, u64 len, u64 *fail_a
>  {
>  	u64 i;
>  	const u32 block = 0x10;
> +	u32 reg;
> +	u32 iter = 0;
>  	void __iomem *base = nvm->base;
> +	void __iomem *base2 = nvm->base2;
>  
>  	for (i = 0; i < len; i += 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 = ioread32(base2 + NVM_DEBUG_REG);
> +			while (!(reg & NVM_NON_POSTED_ERASE_DONE) &&
> +				++iter < NVM_NON_POSTED_ERASE_DONE_ITER) {
> +				msleep(10);
> +				reg = ioread32(base2 + NVM_DEBUG_REG);
> +			}
> +			if (reg & NVM_NON_POSTED_ERASE_DONE) {
> +				/* Clear Erase Done */
> +				iowrite32(reg, base2 + NVM_DEBUG_REG);
> +			} else {
> +				*fail_addr = from + i;
> +				return -ETIME;
> +			}
> +		}
>  		/* Since the writes are via sguint
>  		 * we cannot do back to back erases.
>  		 */
> @@ -383,7 +409,8 @@ idg_erase(struct intel_dg_nvm *nvm, u8 region, loff_t from, u64 len, u64 *fail_a
>  	return len;
>  }
>  
> -static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device)
> +static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device,
> +			     bool non_posted_erase)
>  {
>  	int ret;
>  	unsigned int i, n;
> @@ -443,7 +470,10 @@ static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device)
>  			n++;
>  	}
>  
> +	nvm->non_posted_erase = non_posted_erase;
> +
>  	dev_dbg(device, "Registered %d regions\n", n);
> +	dev_dbg(device, "Non posted erase %d\n", nvm->non_posted_erase);
>  
>  	/* Need to add 1 to the amount of memory
>  	 * so it is reported as an even block
> @@ -778,7 +808,16 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev,
>  		goto err;
>  	}
>  
> -	ret = intel_dg_nvm_init(nvm, device);
> +	if (invm->non_posted_erase) {
> +		nvm->base2 = devm_ioremap_resource(device, &invm->bar2);
> +		if (IS_ERR(nvm->base2)) {
> +			dev_err(device, "base2 mmio not mapped\n");
> +			ret = PTR_ERR(nvm->base2);
> +			goto err;
> +		}
> +	}
> +
> +	ret = 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 68df634c994c..bee25dfc6982 100644
> --- a/include/linux/intel_dg_nvm_aux.h
> +++ b/include/linux/intel_dg_nvm_aux.h
> @@ -17,7 +17,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;
>  };
>  
> -- 
> 2.43.0
>