mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-01-10 12:46:32 +01:00
mtd: add driver for intel graphics non-volatile memory device
Add auxiliary driver for intel discrete graphics non-volatile memory device. CC: Lucas De Marchi <lucas.demarchi@intel.com> Reviewed-by: Raag Jadav <raag.jadav@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Acked-by: Miquel Raynal <miquel.raynal@bootlin.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> Link: https://lore.kernel.org/r/20250617145159.3803852-2-alexander.usyskin@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
committed by
Rodrigo Vivi
parent
0089d6ee3b
commit
ceb5ab3cb6
@@ -12086,6 +12086,13 @@ L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
F: arch/x86/include/asm/intel-family.h
|
||||
|
||||
INTEL DISCRETE GRAPHICS 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>
|
||||
|
||||
@@ -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 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"
|
||||
|
||||
config MTD_DOCG3
|
||||
|
||||
@@ -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)
|
||||
|
||||
134
drivers/mtd/devices/mtd_intel_dg.c
Normal file
134
drivers/mtd/devices/mtd_intel_dg.c
Normal file
@@ -0,0 +1,134 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright(c) 2019-2025, 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[] __counted_by(nregions);
|
||||
};
|
||||
|
||||
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 intel_dg_nvm *nvm;
|
||||
struct device *device;
|
||||
unsigned int nregions;
|
||||
unsigned int i, n;
|
||||
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;
|
||||
}
|
||||
|
||||
nvm = kzalloc(struct_size(nvm, regions, nregions), GFP_KERNEL);
|
||||
if (!nvm)
|
||||
return -ENOMEM;
|
||||
|
||||
kref_init(&nvm->refcnt);
|
||||
|
||||
for (n = 0, i = 0; i < INTEL_DG_NVM_REGIONS; i++) {
|
||||
if (!invm->regions[i].name)
|
||||
continue;
|
||||
|
||||
char *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->nregions = n; /* in case where kasprintf fail */
|
||||
|
||||
nvm->base = devm_ioremap_resource(device, &invm->bar);
|
||||
if (IS_ERR(nvm->base)) {
|
||||
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");
|
||||
30
include/linux/intel_dg_nvm_aux.h
Normal file
30
include/linux/intel_dg_nvm_aux.h
Normal file
@@ -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 <linux/auxiliary_bus.h>
|
||||
#include <linux/container_of.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/types.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 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__ */
|
||||
Reference in New Issue
Block a user