Message ID | 20241022104119.3149051-2-alexander.usyskin@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | mtd: add driver for Intel discrete graphics | expand |
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 >
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__ */