Add auxiliary driver for intel discrete graphics
non-volatile memory device.
CC: Rodrigo Vivi <rodrigo.vivi@intel.com>
CC: Lucas De Marchi <lucas.demarchi@intel.com>
Co-developed-by: Tomas Winkler <tomasw@gmail.com>
Signed-off-by: Tomas Winkler <tomasw@gmail.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
---
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@vger.kernel.org
S: Supported
F: arch/x86/include/asm/intel-family.h
+INTEL DISCRETE GRAPHIC NVM MTD DRIVER
+M: Alexander Usyskin <alexander.usyskin@intel.com>
+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 <jani.nikula@linux.intel.com>
M: Rodrigo Vivi <rodrigo.vivi@intel.com>
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
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@intel.com> > CC: Lucas De Marchi <lucas.demarchi@intel.com> > Co-developed-by: Tomas Winkler <tomasw@gmail.com> > Signed-off-by: Tomas Winkler <tomasw@gmail.com> > Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> > --- > 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@vger.kernel.org > S: Supported > F: arch/x86/include/asm/intel-family.h > > +INTEL DISCRETE GRAPHIC NVM MTD DRIVER > +M: Alexander Usyskin <alexander.usyskin@intel.com> > +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 <jani.nikula@linux.intel.com> > M: Rodrigo Vivi <rodrigo.vivi@intel.com> > 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 >
© 2016 - 2024 Red Hat, Inc.