On Tue, Oct 22, 2024 at 01:41:10PM +0300, Alexander Usyskin wrote: > Add auxiliary driver for intel discrete graphics > non-volatile memory device. > > CC: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> > CC: Lucas De Marchi <lucas.demarchi@xxxxxxxxx> > Co-developed-by: Tomas Winkler <tomasw@xxxxxxxxx> > Signed-off-by: Tomas Winkler <tomasw@xxxxxxxxx> > Signed-off-by: Alexander Usyskin <alexander.usyskin@xxxxxxxxx> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> > --- > MAINTAINERS | 7 ++ > drivers/mtd/devices/Kconfig | 11 +++ > drivers/mtd/devices/Makefile | 1 + > drivers/mtd/devices/mtd-intel-dg.c | 139 +++++++++++++++++++++++++++++ > include/linux/intel_dg_nvm_aux.h | 27 ++++++ > 5 files changed, 185 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 c27f3190737f..a09c035849ef 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -11360,6 +11360,13 @@ L: linux-kernel@xxxxxxxxxxxxxxx > S: Supported > F: arch/x86/include/asm/intel-family.h > > +INTEL DISCRETE GRAPHIC NVM MTD DRIVER > +M: Alexander Usyskin <alexander.usyskin@xxxxxxxxx> > +L: linux-mtd@xxxxxxxxxxxxxxxxxxx > +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 <jani.nikula@xxxxxxxxxxxxxxx> > M: Rodrigo Vivi <rodrigo.vivi@xxxxxxxxx> > diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig > index ff2f9e55ef28..d93edf45c0bb 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. > > +config MTD_INTEL_DG > + tristate "Intel Discrete Graphic non-volatile memory driver" > + depends on AUXILIARY_BUS > + depends on MTD > + help > + This provides MTD device to access Intel Discrete Graphic > + 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" > > config MTD_DOCG3 > diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile > index d11eb2b8b6f8..77c05d269034 100644 > --- a/drivers/mtd/devices/Makefile > +++ b/drivers/mtd/devices/Makefile > @@ -18,6 +18,7 @@ obj-$(CONFIG_MTD_SST25L) += sst25l.o > obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o > obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o > obj-$(CONFIG_MTD_POWERNV_FLASH) += powernv_flash.o > +obj-$(CONFIG_MTD_INTEL_DG) += mtd-intel-dg.o > > > CFLAGS_docg3.o += -I$(src) > diff --git a/drivers/mtd/devices/mtd-intel-dg.c b/drivers/mtd/devices/mtd-intel-dg.c > new file mode 100644 > index 000000000000..746c963ea540 > --- /dev/null > +++ b/drivers/mtd/devices/mtd-intel-dg.c > @@ -0,0 +1,139 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright(c) 2019-2024, Intel Corporation. All rights reserved. > + */ > + > +#include <linux/device.h> > +#include <linux/intel_dg_nvm_aux.h> > +#include <linux/io.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/string.h> > +#include <linux/slab.h> > +#include <linux/types.h> > + > +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[]; > +}; > + > +static void intel_dg_nvm_release(struct kref *kref) > +{ > + struct intel_dg_nvm *nvm = container_of(kref, struct intel_dg_nvm, refcnt); > + int i; > + > + pr_debug("freeing intel_dg nvm\n"); > + for (i = 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 = auxiliary_dev_to_intel_dg_nvm_dev(aux_dev); > + struct device *device; > + struct intel_dg_nvm *nvm; > + unsigned int nregions; > + unsigned int i, n; > + size_t size; > + char *name; > + int ret; > + > + device = &aux_dev->dev; > + > + /* count available regions */ > + for (nregions = 0, i = 0; i < INTEL_DG_NVM_REGIONS; i++) { > + if (invm->regions[i].name) > + nregions++; > + } > + > + if (!nregions) { > + dev_err(device, "no regions defined\n"); > + return -ENODEV; > + } > + > + size = sizeof(*nvm) + sizeof(nvm->regions[0]) * nregions; > + nvm = kzalloc(size, GFP_KERNEL); > + if (!nvm) > + return -ENOMEM; > + > + kref_init(&nvm->refcnt); > + > + nvm->nregions = nregions; > + for (n = 0, i = 0; i < INTEL_DG_NVM_REGIONS; i++) { > + if (!invm->regions[i].name) > + continue; > + > + name = kasprintf(GFP_KERNEL, "%s.%s", > + dev_name(&aux_dev->dev), invm->regions[i].name); > + if (!name) > + continue; > + nvm->regions[n].name = name; > + nvm->regions[n].id = i; > + n++; > + } > + > + nvm->base = devm_ioremap_resource(device, &invm->bar); > + if (IS_ERR(nvm->base)) { > + dev_err(device, "mmio not mapped\n"); > + ret = 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 = 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[] = { > + { > + .name = "i915.nvm", > + }, > + { > + .name = "xe.nvm", > + }, > + { > + /* sentinel */ > + } > +}; > +MODULE_DEVICE_TABLE(auxiliary, intel_dg_mtd_id_table); > + > +static struct auxiliary_driver intel_dg_mtd_driver = { > + .probe = intel_dg_mtd_probe, > + .remove = intel_dg_mtd_remove, > + .driver = { > + /* auxiliary_driver_register() sets .name to be the modname */ > + }, > + .id_table = 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..2cc4179fbde2 > --- /dev/null > +++ b/include/linux/intel_dg_nvm_aux.h > @@ -0,0 +1,27 @@ > +/* SPDX-License-Identifier: MIT */ > +/* > + * Copyright(c) 2019-2024, Intel Corporation. All rights reserved. > + */ > + > +#ifndef __INTEL_DG_NVM_AUX_H__ > +#define __INTEL_DG_NVM_AUX_H__ > + > +#include <linux/auxiliary_bus.h> > + > +#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 writeable_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__ */ > -- > 2.43.0 >