diff options
Diffstat (limited to 'drivers/fpga')
25 files changed, 828 insertions, 111 deletions
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 0a00763b9f28..2f689ac4ba3a 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -276,4 +276,6 @@ config FPGA_MGR_LATTICE_SYSCONFIG_SPI FPGA manager driver support for Lattice FPGAs programming over slave SPI sysCONFIG interface. +source "drivers/fpga/tests/Kconfig" + endif # FPGA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 72e554b4d2f7..352a2612623e 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -55,3 +55,6 @@ obj-$(CONFIG_FPGA_DFL_NIOS_INTEL_PAC_N3000) += dfl-n3000-nios.o # Drivers for FPGAs which implement DFL obj-$(CONFIG_FPGA_DFL_PCI) += dfl-pci.o + +# KUnit tests +obj-$(CONFIG_FPGA_KUNIT_TESTS) += tests/ diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c index ff3a646fd9e3..1fa2ccc321ab 100644 --- a/drivers/fpga/altera-fpga2sdram.c +++ b/drivers/fpga/altera-fpga2sdram.c @@ -27,7 +27,7 @@ #include <linux/kernel.h> #include <linux/mfd/syscon.h> #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/regmap.h> #define ALT_SDR_CTL_FPGAPORTRST_OFST 0x80 diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c index 445f4b011167..0c3fb8226908 100644 --- a/drivers/fpga/altera-freeze-bridge.c +++ b/drivers/fpga/altera-freeze-bridge.c @@ -7,8 +7,9 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/kernel.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> +#include <linux/platform_device.h> #include <linux/fpga/fpga-bridge.h> #define FREEZE_CSR_STATUS_OFFSET 0 @@ -198,13 +199,11 @@ static const struct fpga_bridge_ops altera_freeze_br_br_ops = { .enable_show = altera_freeze_br_enable_show, }; -#ifdef CONFIG_OF static const struct of_device_id altera_freeze_br_of_match[] = { { .compatible = "altr,freeze-bridge-controller", }, {}, }; MODULE_DEVICE_TABLE(of, altera_freeze_br_of_match); -#endif static int altera_freeze_br_probe(struct platform_device *pdev) { @@ -213,14 +212,12 @@ static int altera_freeze_br_probe(struct platform_device *pdev) void __iomem *base_addr; struct altera_freeze_br_data *priv; struct fpga_bridge *br; - struct resource *res; u32 status, revision; if (!np) return -ENODEV; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base_addr = devm_ioremap_resource(dev, res); + base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base_addr)) return PTR_ERR(base_addr); @@ -270,7 +267,7 @@ static struct platform_driver altera_freeze_br_driver = { .remove = altera_freeze_br_remove, .driver = { .name = "altera_freeze_br", - .of_match_table = of_match_ptr(altera_freeze_br_of_match), + .of_match_table = altera_freeze_br_of_match, }, }; diff --git a/drivers/fpga/altera-pr-ip-core-plat.c b/drivers/fpga/altera-pr-ip-core-plat.c index b008a6b8d2d3..9dc263930007 100644 --- a/drivers/fpga/altera-pr-ip-core-plat.c +++ b/drivers/fpga/altera-pr-ip-core-plat.c @@ -9,19 +9,16 @@ */ #include <linux/fpga/altera-pr-ip-core.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> static int alt_pr_platform_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; void __iomem *reg_base; - struct resource *res; /* First mmio base is for register access */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - reg_base = devm_ioremap_resource(dev, res); - + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c index bcb5d34b3b82..3dcf990bd261 100644 --- a/drivers/fpga/dfl-fme-main.c +++ b/drivers/fpga/dfl-fme-main.c @@ -19,6 +19,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/uaccess.h> +#include <linux/units.h> #include <linux/fpga-dfl.h> #include "dfl.h" @@ -231,19 +232,19 @@ static int thermal_hwmon_read(struct device *dev, enum hwmon_sensor_types type, switch (attr) { case hwmon_temp_input: v = readq(feature->ioaddr + FME_THERM_RDSENSOR_FMT1); - *val = (long)(FIELD_GET(FPGA_TEMPERATURE, v) * 1000); + *val = (long)(FIELD_GET(FPGA_TEMPERATURE, v) * MILLI); break; case hwmon_temp_max: v = readq(feature->ioaddr + FME_THERM_THRESHOLD); - *val = (long)(FIELD_GET(TEMP_THRESHOLD1, v) * 1000); + *val = (long)(FIELD_GET(TEMP_THRESHOLD1, v) * MILLI); break; case hwmon_temp_crit: v = readq(feature->ioaddr + FME_THERM_THRESHOLD); - *val = (long)(FIELD_GET(TEMP_THRESHOLD2, v) * 1000); + *val = (long)(FIELD_GET(TEMP_THRESHOLD2, v) * MILLI); break; case hwmon_temp_emergency: v = readq(feature->ioaddr + FME_THERM_THRESHOLD); - *val = (long)(FIELD_GET(TRIP_THRESHOLD, v) * 1000); + *val = (long)(FIELD_GET(TRIP_THRESHOLD, v) * MILLI); break; case hwmon_temp_max_alarm: v = readq(feature->ioaddr + FME_THERM_THRESHOLD); @@ -382,15 +383,15 @@ static int power_hwmon_read(struct device *dev, enum hwmon_sensor_types type, switch (attr) { case hwmon_power_input: v = readq(feature->ioaddr + FME_PWR_STATUS); - *val = (long)(FIELD_GET(PWR_CONSUMED, v) * 1000000); + *val = (long)(FIELD_GET(PWR_CONSUMED, v) * MICRO); break; case hwmon_power_max: v = readq(feature->ioaddr + FME_PWR_THRESHOLD); - *val = (long)(FIELD_GET(PWR_THRESHOLD1, v) * 1000000); + *val = (long)(FIELD_GET(PWR_THRESHOLD1, v) * MICRO); break; case hwmon_power_crit: v = readq(feature->ioaddr + FME_PWR_THRESHOLD); - *val = (long)(FIELD_GET(PWR_THRESHOLD2, v) * 1000000); + *val = (long)(FIELD_GET(PWR_THRESHOLD2, v) * MICRO); break; case hwmon_power_max_alarm: v = readq(feature->ioaddr + FME_PWR_THRESHOLD); @@ -415,7 +416,7 @@ static int power_hwmon_write(struct device *dev, enum hwmon_sensor_types type, int ret = 0; u64 v; - val = clamp_val(val / 1000000, 0, PWR_THRESHOLD_MAX); + val = clamp_val(val / MICRO, 0, PWR_THRESHOLD_MAX); mutex_lock(&pdata->lock); diff --git a/drivers/fpga/dfl-fme-mgr.c b/drivers/fpga/dfl-fme-mgr.c index af0785783b52..ab228d8837a0 100644 --- a/drivers/fpga/dfl-fme-mgr.c +++ b/drivers/fpga/dfl-fme-mgr.c @@ -280,7 +280,6 @@ static int fme_mgr_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct fme_mgr_priv *priv; struct fpga_manager *mgr; - struct resource *res; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -290,8 +289,7 @@ static int fme_mgr_probe(struct platform_device *pdev) priv->ioaddr = pdata->ioaddr; if (!priv->ioaddr) { - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->ioaddr = devm_ioremap_resource(dev, res); + priv->ioaddr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->ioaddr)) return PTR_ERR(priv->ioaddr); } diff --git a/drivers/fpga/dfl-pci.c b/drivers/fpga/dfl-pci.c index 1bc04378118c..98b8fd16183e 100644 --- a/drivers/fpga/dfl-pci.c +++ b/drivers/fpga/dfl-pci.c @@ -156,19 +156,12 @@ static int *cci_pci_create_irq_table(struct pci_dev *pcidev, unsigned int nvec) static int find_dfls_by_vsec(struct pci_dev *pcidev, struct dfl_fpga_enum_info *info) { - u32 bir, offset, vndr_hdr, dfl_cnt, dfl_res; - int dfl_res_off, i, bars, voff = 0; + u32 bir, offset, dfl_cnt, dfl_res; + int dfl_res_off, i, bars, voff; resource_size_t start, len; - while ((voff = pci_find_next_ext_capability(pcidev, voff, PCI_EXT_CAP_ID_VNDR))) { - vndr_hdr = 0; - pci_read_config_dword(pcidev, voff + PCI_VNDR_HEADER, &vndr_hdr); - - if (PCI_VNDR_HEADER_ID(vndr_hdr) == PCI_VSEC_ID_INTEL_DFLS && - pcidev->vendor == PCI_VENDOR_ID_INTEL) - break; - } - + voff = pci_find_vsec_capability(pcidev, PCI_VENDOR_ID_INTEL, + PCI_VSEC_ID_INTEL_DFLS); if (!voff) { dev_dbg(&pcidev->dev, "%s no DFL VSEC found\n", __func__); return -ENODEV; diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c index a6c25dee9cc1..a024be2b84e2 100644 --- a/drivers/fpga/fpga-bridge.c +++ b/drivers/fpga/fpga-bridge.c @@ -14,7 +14,7 @@ #include <linux/spinlock.h> static DEFINE_IDA(fpga_bridge_ida); -static struct class *fpga_bridge_class; +static const struct class fpga_bridge_class; /* Lock for adding/removing bridges to linked lists*/ static DEFINE_SPINLOCK(bridge_list_lock); @@ -87,19 +87,20 @@ err_dev: /** * of_fpga_bridge_get - get an exclusive reference to an fpga bridge * - * @np: node pointer of an FPGA bridge - * @info: fpga image specific information + * @np: node pointer of an FPGA bridge. + * @info: fpga image specific information. * - * Return fpga_bridge struct if successful. - * Return -EBUSY if someone already has a reference to the bridge. - * Return -ENODEV if @np is not an FPGA Bridge. + * Return: + * * fpga_bridge struct pointer if successful. + * * -EBUSY if someone already has a reference to the bridge. + * * -ENODEV if @np is not an FPGA Bridge or can't take parent driver refcount. */ struct fpga_bridge *of_fpga_bridge_get(struct device_node *np, struct fpga_image_info *info) { struct device *dev; - dev = class_find_device_by_of_node(fpga_bridge_class, np); + dev = class_find_device_by_of_node(&fpga_bridge_class, np); if (!dev) return ERR_PTR(-ENODEV); @@ -126,7 +127,7 @@ struct fpga_bridge *fpga_bridge_get(struct device *dev, { struct device *bridge_dev; - bridge_dev = class_find_device(fpga_bridge_class, NULL, dev, + bridge_dev = class_find_device(&fpga_bridge_class, NULL, dev, fpga_bridge_dev_match); if (!bridge_dev) return ERR_PTR(-ENODEV); @@ -155,9 +156,9 @@ EXPORT_SYMBOL_GPL(fpga_bridge_put); * fpga_bridges_enable - enable bridges in a list * @bridge_list: list of FPGA bridges * - * Enable each bridge in the list. If list is empty, do nothing. + * Enable each bridge in the list. If list is empty, do nothing. * - * Return 0 for success or empty bridge list; return error code otherwise. + * Return: 0 for success or empty bridge list or an error code otherwise. */ int fpga_bridges_enable(struct list_head *bridge_list) { @@ -179,9 +180,9 @@ EXPORT_SYMBOL_GPL(fpga_bridges_enable); * * @bridge_list: list of FPGA bridges * - * Disable each bridge in the list. If list is empty, do nothing. + * Disable each bridge in the list. If list is empty, do nothing. * - * Return 0 for success or empty bridge list; return error code otherwise. + * Return: 0 for success or empty bridge list or an error code otherwise. */ int fpga_bridges_disable(struct list_head *bridge_list) { @@ -230,7 +231,7 @@ EXPORT_SYMBOL_GPL(fpga_bridges_put); * * Get an exclusive reference to the bridge and it to the list. * - * Return 0 for success, error code from of_fpga_bridge_get() otherwise. + * Return: 0 for success, error code from of_fpga_bridge_get() otherwise. */ int of_fpga_bridge_get_to_list(struct device_node *np, struct fpga_image_info *info, @@ -260,7 +261,7 @@ EXPORT_SYMBOL_GPL(of_fpga_bridge_get_to_list); * * Get an exclusive reference to the bridge and it to the list. * - * Return 0 for success, error code from fpga_bridge_get() otherwise. + * Return: 0 for success, error code from fpga_bridge_get() otherwise. */ int fpga_bridge_get_to_list(struct device *dev, struct fpga_image_info *info, @@ -359,7 +360,7 @@ fpga_bridge_register(struct device *parent, const char *name, bridge->priv = priv; bridge->dev.groups = br_ops->groups; - bridge->dev.class = fpga_bridge_class; + bridge->dev.class = &fpga_bridge_class; bridge->dev.parent = parent; bridge->dev.of_node = parent->of_node; bridge->dev.id = id; @@ -415,21 +416,20 @@ static void fpga_bridge_dev_release(struct device *dev) kfree(bridge); } +static const struct class fpga_bridge_class = { + .name = "fpga_bridge", + .dev_groups = fpga_bridge_groups, + .dev_release = fpga_bridge_dev_release, +}; + static int __init fpga_bridge_dev_init(void) { - fpga_bridge_class = class_create("fpga_bridge"); - if (IS_ERR(fpga_bridge_class)) - return PTR_ERR(fpga_bridge_class); - - fpga_bridge_class->dev_groups = fpga_bridge_groups; - fpga_bridge_class->dev_release = fpga_bridge_dev_release; - - return 0; + return class_register(&fpga_bridge_class); } static void __exit fpga_bridge_dev_exit(void) { - class_destroy(fpga_bridge_class); + class_unregister(&fpga_bridge_class); ida_destroy(&fpga_bridge_ida); } diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index eb583f86a0b9..06651389c592 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -19,7 +19,7 @@ #include <linux/highmem.h> static DEFINE_IDA(fpga_mgr_ida); -static struct class *fpga_mgr_class; +static const struct class fpga_mgr_class; struct fpga_mgr_devres { struct fpga_manager *mgr; @@ -693,7 +693,7 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data) */ struct fpga_manager *fpga_mgr_get(struct device *dev) { - struct device *mgr_dev = class_find_device(fpga_mgr_class, NULL, dev, + struct device *mgr_dev = class_find_device(&fpga_mgr_class, NULL, dev, fpga_mgr_dev_match); if (!mgr_dev) return ERR_PTR(-ENODEV); @@ -713,7 +713,7 @@ struct fpga_manager *of_fpga_mgr_get(struct device_node *node) { struct device *dev; - dev = class_find_device_by_of_node(fpga_mgr_class, node); + dev = class_find_device_by_of_node(&fpga_mgr_class, node); if (!dev) return ERR_PTR(-ENODEV); @@ -809,7 +809,7 @@ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *in mgr->priv = info->priv; mgr->compat_id = info->compat_id; - mgr->dev.class = fpga_mgr_class; + mgr->dev.class = &fpga_mgr_class; mgr->dev.groups = mops->groups; mgr->dev.parent = parent; mgr->dev.of_node = parent->of_node; @@ -967,23 +967,22 @@ static void fpga_mgr_dev_release(struct device *dev) kfree(mgr); } +static const struct class fpga_mgr_class = { + .name = "fpga_manager", + .dev_groups = fpga_mgr_groups, + .dev_release = fpga_mgr_dev_release, +}; + static int __init fpga_mgr_class_init(void) { pr_info("FPGA manager framework\n"); - fpga_mgr_class = class_create("fpga_manager"); - if (IS_ERR(fpga_mgr_class)) - return PTR_ERR(fpga_mgr_class); - - fpga_mgr_class->dev_groups = fpga_mgr_groups; - fpga_mgr_class->dev_release = fpga_mgr_dev_release; - - return 0; + return class_register(&fpga_mgr_class); } static void __exit fpga_mgr_class_exit(void) { - class_destroy(fpga_mgr_class); + class_unregister(&fpga_mgr_class); ida_destroy(&fpga_mgr_ida); } diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index ccf6fdab1360..b364a929425c 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -16,7 +16,7 @@ #include <linux/spinlock.h> static DEFINE_IDA(fpga_region_ida); -static struct class *fpga_region_class; +static const struct class fpga_region_class; struct fpga_region * fpga_region_class_find(struct device *start, const void *data, @@ -24,7 +24,7 @@ fpga_region_class_find(struct device *start, const void *data, { struct device *dev; - dev = class_find_device(fpga_region_class, start, data, match); + dev = class_find_device(&fpga_region_class, start, data, match); if (!dev) return NULL; @@ -38,9 +38,10 @@ EXPORT_SYMBOL_GPL(fpga_region_class_find); * * Caller should call fpga_region_put() when done with region. * - * Return fpga_region struct if successful. - * Return -EBUSY if someone already has a reference to the region. - * Return -ENODEV if @np is not an FPGA Region. + * Return: + * * fpga_region struct if successful. + * * -EBUSY if someone already has a reference to the region. + * * -ENODEV if can't take parent driver module refcount. */ static struct fpga_region *fpga_region_get(struct fpga_region *region) { @@ -91,7 +92,7 @@ static void fpga_region_put(struct fpga_region *region) * The caller will need to call fpga_bridges_put() before attempting to * reprogram the region. * - * Return 0 for success or negative error code. + * Return: 0 for success or negative error code. */ int fpga_region_program_fpga(struct fpga_region *region) { @@ -216,7 +217,7 @@ fpga_region_register_full(struct device *parent, const struct fpga_region_info * mutex_init(®ion->mutex); INIT_LIST_HEAD(®ion->bridge_list); - region->dev.class = fpga_region_class; + region->dev.class = &fpga_region_class; region->dev.parent = parent; region->dev.of_node = parent->of_node; region->dev.id = id; @@ -287,25 +288,25 @@ static void fpga_region_dev_release(struct device *dev) kfree(region); } +static const struct class fpga_region_class = { + .name = "fpga_region", + .dev_groups = fpga_region_groups, + .dev_release = fpga_region_dev_release, +}; + /** - * fpga_region_init - init function for fpga_region class - * Creates the fpga_region class and registers a reconfig notifier. + * fpga_region_init - creates the fpga_region class. + * + * Return: 0 on success or ERR_PTR() on error. */ static int __init fpga_region_init(void) { - fpga_region_class = class_create("fpga_region"); - if (IS_ERR(fpga_region_class)) - return PTR_ERR(fpga_region_class); - - fpga_region_class->dev_groups = fpga_region_groups; - fpga_region_class->dev_release = fpga_region_dev_release; - - return 0; + return class_register(&fpga_region_class); } static void __exit fpga_region_exit(void) { - class_destroy(fpga_region_class); + class_unregister(&fpga_region_class); ida_destroy(&fpga_region_ida); } diff --git a/drivers/fpga/microchip-spi.c b/drivers/fpga/microchip-spi.c index d6070e7f5205..2a82c726d6e5 100644 --- a/drivers/fpga/microchip-spi.c +++ b/drivers/fpga/microchip-spi.c @@ -8,7 +8,7 @@ #include <linux/fpga/fpga-mgr.h> #include <linux/iopoll.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/spi/spi.h> #define MPF_SPI_ISC_ENABLE 0x0B diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c index ae82532fc127..a6affd83f275 100644 --- a/drivers/fpga/of-fpga-region.c +++ b/drivers/fpga/of-fpga-region.c @@ -12,7 +12,9 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/slab.h> #include <linux/spinlock.h> diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c index ac8e89b8a5cc..cc4861e345c9 100644 --- a/drivers/fpga/socfpga-a10.c +++ b/drivers/fpga/socfpga-a10.c @@ -471,7 +471,6 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev) struct a10_fpga_priv *priv; void __iomem *reg_base; struct fpga_manager *mgr; - struct resource *res; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -479,14 +478,12 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev) return -ENOMEM; /* First mmio base is for register access */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(dev, res); + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); /* Second mmio base is for writing FPGA image data */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->fpga_data_addr = devm_ioremap_resource(dev, res); + priv->fpga_data_addr = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(priv->fpga_data_addr)) return PTR_ERR(priv->fpga_data_addr); diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c index 7e0741f99696..723ea0ad3f09 100644 --- a/drivers/fpga/socfpga.c +++ b/drivers/fpga/socfpga.c @@ -545,20 +545,17 @@ static int socfpga_fpga_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct socfpga_fpga_priv *priv; struct fpga_manager *mgr; - struct resource *res; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->fpga_base_addr = devm_ioremap_resource(dev, res); + priv->fpga_base_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->fpga_base_addr)) return PTR_ERR(priv->fpga_base_addr); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->fpga_data_addr = devm_ioremap_resource(dev, res); + priv->fpga_data_addr = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(priv->fpga_data_addr)) return PTR_ERR(priv->fpga_data_addr); diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c index f7f01982a512..cacb9cc5757e 100644 --- a/drivers/fpga/stratix10-soc.c +++ b/drivers/fpga/stratix10-soc.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> /* * FPGA programming requires a higher level of privilege (EL3), per the SoC diff --git a/drivers/fpga/tests/.kunitconfig b/drivers/fpga/tests/.kunitconfig new file mode 100644 index 000000000000..a1c2a2974c39 --- /dev/null +++ b/drivers/fpga/tests/.kunitconfig @@ -0,0 +1,5 @@ +CONFIG_KUNIT=y +CONFIG_FPGA=y +CONFIG_FPGA_REGION=y +CONFIG_FPGA_BRIDGE=y +CONFIG_FPGA_KUNIT_TESTS=y diff --git a/drivers/fpga/tests/Kconfig b/drivers/fpga/tests/Kconfig new file mode 100644 index 000000000000..e4a64815f16d --- /dev/null +++ b/drivers/fpga/tests/Kconfig @@ -0,0 +1,11 @@ +config FPGA_KUNIT_TESTS + tristate "KUnit test for the FPGA subsystem" if !KUNIT_ALL_TESTS + depends on FPGA && FPGA_REGION && FPGA_BRIDGE && KUNIT=y + default KUNIT_ALL_TESTS + help + This builds unit tests for the FPGA subsystem + + For more information on KUnit and unit tests in general, + please refer to the KUnit documentation in Documentation/dev-tools/kunit/. + + If unsure, say N. diff --git a/drivers/fpga/tests/Makefile b/drivers/fpga/tests/Makefile new file mode 100644 index 000000000000..bb78215c645c --- /dev/null +++ b/drivers/fpga/tests/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for KUnit test suites for the FPGA subsystem +# + +obj-$(CONFIG_FPGA_KUNIT_TESTS) += fpga-mgr-test.o fpga-bridge-test.o fpga-region-test.o diff --git a/drivers/fpga/tests/fpga-bridge-test.c b/drivers/fpga/tests/fpga-bridge-test.c new file mode 100644 index 000000000000..1d258002cdd7 --- /dev/null +++ b/drivers/fpga/tests/fpga-bridge-test.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * KUnit test for the FPGA Bridge + * + * Copyright (C) 2023 Red Hat, Inc. + * + * Author: Marco Pagani <marpagan@redhat.com> + */ + +#include <kunit/test.h> +#include <linux/device.h> +#include <linux/fpga/fpga-bridge.h> +#include <linux/module.h> +#include <linux/types.h> + +struct bridge_stats { + bool enable; +}; + +struct bridge_ctx { + struct fpga_bridge *bridge; + struct platform_device *pdev; + struct bridge_stats stats; +}; + +static int op_enable_set(struct fpga_bridge *bridge, bool enable) +{ + struct bridge_stats *stats = bridge->priv; + + stats->enable = enable; + + return 0; +} + +/* + * Fake FPGA bridge that implements only the enable_set op to track + * the state. + */ +static const struct fpga_bridge_ops fake_bridge_ops = { + .enable_set = op_enable_set, +}; + +/** + * register_test_bridge() - Register a fake FPGA bridge for testing. + * @test: KUnit test context object. + * + * Return: Context of the newly registered FPGA bridge. + */ +static struct bridge_ctx *register_test_bridge(struct kunit *test) +{ + struct bridge_ctx *ctx; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + ctx->pdev = platform_device_register_simple("bridge_pdev", PLATFORM_DEVID_AUTO, NULL, 0); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->pdev); + + ctx->bridge = fpga_bridge_register(&ctx->pdev->dev, "Fake FPGA bridge", &fake_bridge_ops, + &ctx->stats); + KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->bridge)); + + return ctx; +} + +static void unregister_test_bridge(struct bridge_ctx *ctx) +{ + fpga_bridge_unregister(ctx->bridge); + platform_device_unregister(ctx->pdev); +} + +static void fpga_bridge_test_get(struct kunit *test) +{ + struct bridge_ctx *ctx = test->priv; + struct fpga_bridge *bridge; + + bridge = fpga_bridge_get(&ctx->pdev->dev, NULL); + KUNIT_EXPECT_PTR_EQ(test, bridge, ctx->bridge); + + bridge = fpga_bridge_get(&ctx->pdev->dev, NULL); + KUNIT_EXPECT_EQ(test, PTR_ERR(bridge), -EBUSY); + + fpga_bridge_put(ctx->bridge); +} + +static void fpga_bridge_test_toggle(struct kunit *test) +{ + struct bridge_ctx *ctx = test->priv; + int ret; + + ret = fpga_bridge_disable(ctx->bridge); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_FALSE(test, ctx->stats.enable); + + ret = fpga_bridge_enable(ctx->bridge); + KUNIT_EXPECT_EQ(test, ret, 0); + KUNIT_EXPECT_TRUE(test, ctx->stats.enable); +} + +/* Test the functions for getting and controlling a list of bridges */ +static void fpga_bridge_test_get_put_list(struct kunit *test) +{ + struct list_head bridge_list; + struct bridge_ctx *ctx_0, *ctx_1; + int ret; + + ctx_0 = test->priv; + ctx_1 = register_test_bridge(test); + + INIT_LIST_HEAD(&bridge_list); + + /* Get bridge 0 and add it to the list */ + ret = fpga_bridge_get_to_list(&ctx_0->pdev->dev, NULL, &bridge_list); + KUNIT_EXPECT_EQ(test, ret, 0); + + KUNIT_EXPECT_PTR_EQ(test, ctx_0->bridge, + list_first_entry_or_null(&bridge_list, struct fpga_bridge, node)); + + /* Get bridge 1 and add it to the list */ + ret = fpga_bridge_get_to_list(&ctx_1->pdev->dev, NULL, &bridge_list); + KUNIT_EXPECT_EQ(test, ret, 0); + + KUNIT_EXPECT_PTR_EQ(test, ctx_1->bridge, + list_first_entry_or_null(&bridge_list, struct fpga_bridge, node)); + + /* Disable an then enable both bridges from the list */ + ret = fpga_bridges_disable(&bridge_list); + KUNIT_EXPECT_EQ(test, ret, 0); + + KUNIT_EXPECT_FALSE(test, ctx_0->stats.enable); + KUNIT_EXPECT_FALSE(test, ctx_1->stats.enable); + + ret = fpga_bridges_enable(&bridge_list); + KUNIT_EXPECT_EQ(test, ret, 0); + + KUNIT_EXPECT_TRUE(test, ctx_0->stats.enable); + KUNIT_EXPECT_TRUE(test, ctx_1->stats.enable); + + /* Put and remove both bridges from the list */ + fpga_bridges_put(&bridge_list); + + KUNIT_EXPECT_TRUE(test, list_empty(&bridge_list)); + + unregister_test_bridge(ctx_1); +} + +static int fpga_bridge_test_init(struct kunit *test) +{ + test->priv = register_test_bridge(test); + + return 0; +} + +static void fpga_bridge_test_exit(struct kunit *test) +{ + unregister_test_bridge(test->priv); +} + +static struct kunit_case fpga_bridge_test_cases[] = { + KUNIT_CASE(fpga_bridge_test_get), + KUNIT_CASE(fpga_bridge_test_toggle), + KUNIT_CASE(fpga_bridge_test_get_put_list), + {} +}; + +static struct kunit_suite fpga_bridge_suite = { + .name = "fpga_bridge", + .init = fpga_bridge_test_init, + .exit = fpga_bridge_test_exit, + .test_cases = fpga_bridge_test_cases, +}; + +kunit_test_suite(fpga_bridge_suite); + +MODULE_LICENSE("GPL"); diff --git a/drivers/fpga/tests/fpga-mgr-test.c b/drivers/fpga/tests/fpga-mgr-test.c new file mode 100644 index 000000000000..6acec55b60ce --- /dev/null +++ b/drivers/fpga/tests/fpga-mgr-test.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * KUnit test for the FPGA Manager + * + * Copyright (C) 2023 Red Hat, Inc. + * + * Author: Marco Pagani <marpagan@redhat.com> + */ + +#include <kunit/test.h> +#include <linux/device.h> +#include <linux/fpga/fpga-mgr.h> +#include <linux/module.h> +#include <linux/scatterlist.h> +#include <linux/types.h> + +#define HEADER_FILL 'H' +#define IMAGE_FILL 'P' +#define IMAGE_BLOCK 1024 + +#define HEADER_SIZE IMAGE_BLOCK +#define IMAGE_SIZE (IMAGE_BLOCK * 4) + +struct mgr_stats { + bool header_match; + bool image_match; + u32 seq_num; + u32 op_parse_header_seq; + u32 op_write_init_seq; + u32 op_write_seq; + u32 op_write_sg_seq; + u32 op_write_complete_seq; + enum fpga_mgr_states op_parse_header_state; + enum fpga_mgr_states op_write_init_state; + enum fpga_mgr_states op_write_state; + enum fpga_mgr_states op_write_sg_state; + enum fpga_mgr_states op_write_complete_state; +}; + +struct mgr_ctx { + struct fpga_image_info *img_info; + struct fpga_manager *mgr; + struct platform_device *pdev; + struct mgr_stats stats; +}; + +/** + * init_test_buffer() - Allocate and initialize a test image in a buffer. + * @test: KUnit test context object. + * @count: image size in bytes. + * + * Return: pointer to the newly allocated image. + */ +static char *init_test_buffer(struct kunit *test, size_t count) +{ + char *buf; + + KUNIT_ASSERT_GE(test, count, HEADER_SIZE); + + buf = kunit_kzalloc(test, count, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); + + memset(buf, HEADER_FILL, HEADER_SIZE); + memset(buf + HEADER_SIZE, IMAGE_FILL, count - HEADER_SIZE); + + return buf; +} + +/* + * Check the image header. Do not return an error code if the image check fails + * since, in this case, it is a failure of the FPGA manager itself, not this + * op that tests it. + */ +static int op_parse_header(struct fpga_manager *mgr, struct fpga_image_info *info, + const char *buf, size_t count) +{ + struct mgr_stats *stats = mgr->priv; + size_t i; + + stats->op_parse_header_state = mgr->state; + stats->op_parse_header_seq = stats->seq_num++; + + /* Set header_size and data_size for later */ + info->header_size = HEADER_SIZE; + info->data_size = info->count - HEADER_SIZE; + + stats->header_match = true; + for (i = 0; i < info->header_size; i++) { + if (buf[i] != HEADER_FILL) { + stats->header_match = false; + break; + } + } + + return 0; +} + +static int op_write_init(struct fpga_manager *mgr, struct fpga_image_info *info, + const char *buf, size_t count) +{ + struct mgr_stats *stats = mgr->priv; + + stats->op_write_init_state = mgr->state; + stats->op_write_init_seq = stats->seq_num++; + + return 0; +} + +/* + * Check the image data. As with op_parse_header, do not return an error code + * if the image check fails. + */ +static int op_write(struct fpga_manager *mgr, const char *buf, size_t count) +{ + struct mgr_stats *stats = mgr->priv; + size_t i; + + stats->op_write_state = mgr->state; + stats->op_write_seq = stats->seq_num++; + + stats->image_match = true; + for (i = 0; i < count; i++) { + if (buf[i] != IMAGE_FILL) { + stats->image_match = false; + break; + } + } + + return 0; +} + +/* + * Check the image data, but first skip the header since write_sg will get + * the whole image in sg_table. As with op_parse_header, do not return an + * error code if the image check fails. + */ +static int op_write_sg(struct fpga_manager *mgr, struct sg_table *sgt) +{ + struct mgr_stats *stats = mgr->priv; + struct sg_mapping_iter miter; + char *img; + size_t i; + + stats->op_write_sg_state = mgr->state; + stats->op_write_sg_seq = stats->seq_num++; + + stats->image_match = true; + sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG); + + if (!sg_miter_skip(&miter, HEADER_SIZE)) { + stats->image_match = false; + goto out; + } + + while (sg_miter_next(&miter)) { + img = miter.addr; + for (i = 0; i < miter.length; i++) { + if (img[i] != IMAGE_FILL) { + stats->image_match = false; + goto out; + } + } + } +out: + sg_miter_stop(&miter); + return 0; +} + +static int op_write_complete(struct fpga_manager *mgr, struct fpga_image_info *info) +{ + struct mgr_stats *stats = mgr->priv; + + stats->op_write_complete_state = mgr->state; + stats->op_write_complete_seq = stats->seq_num++; + + return 0; +} + +/* + * Fake FPGA manager that implements all ops required to check the programming + * sequence using a single contiguous buffer and a scatter gather table. + */ +static const struct fpga_manager_ops fake_mgr_ops = { + .skip_header = true, + .parse_header = op_parse_header, + .write_init = op_write_init, + .write = op_write, + .write_sg = op_write_sg, + .write_complete = op_write_complete, +}; + +static void fpga_mgr_test_get(struct kunit *test) +{ + struct mgr_ctx *ctx = test->priv; + struct fpga_manager *mgr; + + mgr = fpga_mgr_get(&ctx->pdev->dev); + KUNIT_EXPECT_PTR_EQ(test, mgr, ctx->mgr); + + fpga_mgr_put(ctx->mgr); +} + +static void fpga_mgr_test_lock(struct kunit *test) +{ + struct mgr_ctx *ctx = test->priv; + int ret; + + ret = fpga_mgr_lock(ctx->mgr); + KUNIT_EXPECT_EQ(test, ret, 0); + + ret = fpga_mgr_lock(ctx->mgr); + KUNIT_EXPECT_EQ(test, ret, -EBUSY); + + fpga_mgr_unlock(ctx->mgr); +} + +/* Check the programming sequence using an image in a buffer */ +static void fpga_mgr_test_img_load_buf(struct kunit *test) +{ + struct mgr_ctx *ctx = test->priv; + char *img_buf; + int ret; + + img_buf = init_test_buffer(test, IMAGE_SIZE); + + ctx->img_info->count = IMAGE_SIZE; + ctx->img_info->buf = img_buf; + + ret = fpga_mgr_load(ctx->mgr, ctx->img_info); + KUNIT_EXPECT_EQ(test, ret, 0); + + KUNIT_EXPECT_TRUE(test, ctx->stats.header_match); + KUNIT_EXPECT_TRUE(test, ctx->stats.image_match); + + KUNIT_EXPECT_EQ(test, ctx->stats.op_parse_header_state, FPGA_MGR_STATE_PARSE_HEADER); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_state, FPGA_MGR_STATE_WRITE_INIT); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_state, FPGA_MGR_STATE_WRITE); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_state, FPGA_MGR_STATE_WRITE_COMPLETE); + + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_seq, ctx->stats.op_parse_header_seq + 1); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_seq, ctx->stats.op_parse_header_seq + 2); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_seq, ctx->stats.op_parse_header_seq + 3); +} + +/* Check the programming sequence using an image in a scatter gather table */ +static void fpga_mgr_test_img_load_sgt(struct kunit *test) +{ + struct mgr_ctx *ctx = test->priv; + struct sg_table *sgt; + char *img_buf; + int ret; + + img_buf = init_test_buffer(test, IMAGE_SIZE); + + sgt = kunit_kzalloc(test, sizeof(*sgt), GFP_KERNEL); + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); + KUNIT_ASSERT_EQ(test, ret, 0); + sg_init_one(sgt->sgl, img_buf, IMAGE_SIZE); + + ctx->img_info->sgt = sgt; + + ret = fpga_mgr_load(ctx->mgr, ctx->img_info); + KUNIT_EXPECT_EQ(test, ret, 0); + + KUNIT_EXPECT_TRUE(test, ctx->stats.header_match); + KUNIT_EXPECT_TRUE(test, ctx->stats.image_match); + + KUNIT_EXPECT_EQ(test, ctx->stats.op_parse_header_state, FPGA_MGR_STATE_PARSE_HEADER); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_state, FPGA_MGR_STATE_WRITE_INIT); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_sg_state, FPGA_MGR_STATE_WRITE); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_state, FPGA_MGR_STATE_WRITE_COMPLETE); + + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_seq, ctx->stats.op_parse_header_seq + 1); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_sg_seq, ctx->stats.op_parse_header_seq + 2); + KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_seq, ctx->stats.op_parse_header_seq + 3); + + sg_free_table(ctx->img_info->sgt); +} + +static int fpga_mgr_test_init(struct kunit *test) +{ + struct mgr_ctx *ctx; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + ctx->pdev = platform_device_register_simple("mgr_pdev", PLATFORM_DEVID_AUTO, NULL, 0); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->pdev); + + ctx->mgr = devm_fpga_mgr_register(&ctx->pdev->dev, "Fake FPGA Manager", &fake_mgr_ops, + &ctx->stats); + KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->mgr)); + + ctx->img_info = fpga_image_info_alloc(&ctx->pdev->dev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->img_info); + + test->priv = ctx; + + return 0; +} + +static void fpga_mgr_test_exit(struct kunit *test) +{ + struct mgr_ctx *ctx = test->priv; + + fpga_image_info_free(ctx->img_info); + platform_device_unregister(ctx->pdev); +} + +static struct kunit_case fpga_mgr_test_cases[] = { + KUNIT_CASE(fpga_mgr_test_get), + KUNIT_CASE(fpga_mgr_test_lock), + KUNIT_CASE(fpga_mgr_test_img_load_buf), + KUNIT_CASE(fpga_mgr_test_img_load_sgt), + {} +}; + +static struct kunit_suite fpga_mgr_suite = { + .name = "fpga_mgr", + .init = fpga_mgr_test_init, + .exit = fpga_mgr_test_exit, + .test_cases = fpga_mgr_test_cases, +}; + +kunit_test_suite(fpga_mgr_suite); + +MODULE_LICENSE("GPL"); diff --git a/drivers/fpga/tests/fpga-region-test.c b/drivers/fpga/tests/fpga-region-test.c new file mode 100644 index 000000000000..9f9d50ee7871 --- /dev/null +++ b/drivers/fpga/tests/fpga-region-test.c @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * KUnit test for the FPGA Region + * + * Copyright (C) 2023 Red Hat, Inc. + * + * Author: Marco Pagani <marpagan@redhat.com> + */ + +#include <kunit/test.h> +#include <linux/fpga/fpga-bridge.h> +#include <linux/fpga/fpga-mgr.h> +#include <linux/fpga/fpga-region.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/types.h> + +struct mgr_stats { + u32 write_count; +}; + +struct bridge_stats { + bool enable; + u32 cycles_count; +}; + +struct test_ctx { + struct fpga_manager *mgr; + struct platform_device *mgr_pdev; + struct fpga_bridge *bridge; + struct platform_device *bridge_pdev; + struct fpga_region *region; + struct platform_device *region_pdev; + struct bridge_stats bridge_stats; + struct mgr_stats mgr_stats; +}; + +static int op_write(struct fpga_manager *mgr, const char *buf, size_t count) +{ + struct mgr_stats *stats = mgr->priv; + + stats->write_count++; + + return 0; +} + +/* + * Fake FPGA manager that implements only the write op to count the number + * of programming cycles. The internals of the programming sequence are + * tested in the Manager suite since they are outside the responsibility + * of the Region. + */ +static const struct fpga_manager_ops fake_mgr_ops = { + .write = op_write, +}; + +static int op_enable_set(struct fpga_bridge *bridge, bool enable) +{ + struct bridge_stats *stats = bridge->priv; + + if (!stats->enable && enable) + stats->cycles_count++; + + stats->enable = enable; + + return 0; +} + +/* + * Fake FPGA bridge that implements only enable_set op to count the number + * of activation cycles. + */ +static const struct fpga_bridge_ops fake_bridge_ops = { + .enable_set = op_enable_set, +}; + +static int fake_region_get_bridges(struct fpga_region *region) +{ + struct fpga_bridge *bridge = region->priv; + + return fpga_bridge_get_to_list(bridge->dev.parent, region->info, ®ion->bridge_list); +} + +static int fake_region_match(struct device *dev, const void *data) +{ + return dev->parent == data; +} + +static void fpga_region_test_class_find(struct kunit *test) +{ + struct test_ctx *ctx = test->priv; + struct fpga_region *region; + + region = fpga_region_class_find(NULL, &ctx->region_pdev->dev, fake_region_match); + KUNIT_EXPECT_PTR_EQ(test, region, ctx->region); +} + +/* + * FPGA Region programming test. The Region must call get_bridges() to get + * and control the bridges, and then the Manager for the actual programming. + */ +static void fpga_region_test_program_fpga(struct kunit *test) +{ + struct test_ctx *ctx = test->priv; + struct fpga_image_info *img_info; + char img_buf[4]; + int ret; + + img_info = fpga_image_info_alloc(&ctx->mgr_pdev->dev); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, img_info); + + img_info->buf = img_buf; + img_info->count = sizeof(img_buf); + + ctx->region->info = img_info; + ret = fpga_region_program_fpga(ctx->region); + KUNIT_ASSERT_EQ(test, ret, 0); + + KUNIT_EXPECT_EQ(test, 1, ctx->mgr_stats.write_count); + KUNIT_EXPECT_EQ(test, 1, ctx->bridge_stats.cycles_count); + + fpga_bridges_put(&ctx->region->bridge_list); + + ret = fpga_region_program_fpga(ctx->region); + KUNIT_ASSERT_EQ(test, ret, 0); + + KUNIT_EXPECT_EQ(test, 2, ctx->mgr_stats.write_count); + KUNIT_EXPECT_EQ(test, 2, ctx->bridge_stats.cycles_count); + + fpga_bridges_put(&ctx->region->bridge_list); + + fpga_image_info_free(img_info); +} + +/* + * The configuration used in this test suite uses a single bridge to + * limit the code under test to a single unit. The functions used by the + * Region for getting and controlling bridges are tested (with a list of + * multiple bridges) in the Bridge suite. + */ +static int fpga_region_test_init(struct kunit *test) +{ + struct test_ctx *ctx; + struct fpga_region_info region_info = { 0 }; + + ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + + ctx->mgr_pdev = platform_device_register_simple("mgr_pdev", PLATFORM_DEVID_AUTO, NULL, 0); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->mgr_pdev); + + ctx->mgr = devm_fpga_mgr_register(&ctx->mgr_pdev->dev, "Fake FPGA Manager", &fake_mgr_ops, + &ctx->mgr_stats); + KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->mgr)); + + ctx->bridge_pdev = platform_device_register_simple("bridge_pdev", PLATFORM_DEVID_AUTO, + NULL, 0); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->bridge_pdev); + + ctx->bridge = fpga_bridge_register(&ctx->bridge_pdev->dev, "Fake FPGA Bridge", + &fake_bridge_ops, &ctx->bridge_stats); + KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->bridge)); + + ctx->bridge_stats.enable = true; + + ctx->region_pdev = platform_device_register_simple("region_pdev", PLATFORM_DEVID_AUTO, + NULL, 0); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->region_pdev); + + region_info.mgr = ctx->mgr; + region_info.priv = ctx->bridge; + region_info.get_bridges = fake_region_get_bridges; + + ctx->region = fpga_region_register_full(&ctx->region_pdev->dev, ®ion_info); + KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->region)); + + test->priv = ctx; + + return 0; +} + +static void fpga_region_test_exit(struct kunit *test) +{ + struct test_ctx *ctx = test->priv; + + fpga_region_unregister(ctx->region); + platform_device_unregister(ctx->region_pdev); + + fpga_bridge_unregister(ctx->bridge); + platform_device_unregister(ctx->bridge_pdev); + + platform_device_unregister(ctx->mgr_pdev); +} + +static struct kunit_case fpga_region_test_cases[] = { + KUNIT_CASE(fpga_region_test_class_find), + KUNIT_CASE(fpga_region_test_program_fpga), + + {} +}; + +static struct kunit_suite fpga_region_suite = { + .name = "fpga_mgr", + .init = fpga_region_test_init, + .exit = fpga_region_test_exit, + .test_cases = fpga_region_test_cases, +}; + +kunit_test_suite(fpga_region_suite); + +MODULE_LICENSE("GPL"); diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c index 8e6e9c840d9d..4e1d2a4d3df4 100644 --- a/drivers/fpga/ts73xx-fpga.c +++ b/drivers/fpga/ts73xx-fpga.c @@ -103,7 +103,6 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) struct device *kdev = &pdev->dev; struct ts73xx_fpga_priv *priv; struct fpga_manager *mgr; - struct resource *res; priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -111,8 +110,7 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) priv->dev = kdev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->io_base = devm_ioremap_resource(kdev, res); + priv->io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->io_base)) return PTR_ERR(priv->io_base); diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c index b76d85449b8f..208d9560f56d 100644 --- a/drivers/fpga/xilinx-pr-decoupler.c +++ b/drivers/fpga/xilinx-pr-decoupler.c @@ -108,7 +108,6 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) struct xlnx_pr_decoupler_data *priv; struct fpga_bridge *br; int err; - struct resource *res; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -122,8 +121,7 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) priv->ipconfig = match->data; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->io_base = devm_ioremap_resource(&pdev->dev, res); + priv->io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->io_base)) return PTR_ERR(priv->io_base); diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c index f8214cae9b6e..96611d424a10 100644 --- a/drivers/fpga/zynq-fpga.c +++ b/drivers/fpga/zynq-fpga.c @@ -555,7 +555,6 @@ static int zynq_fpga_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct zynq_fpga_priv *priv; struct fpga_manager *mgr; - struct resource *res; int err; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -563,8 +562,7 @@ static int zynq_fpga_probe(struct platform_device *pdev) return -ENOMEM; spin_lock_init(&priv->dma_lock); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->io_base = devm_ioremap_resource(dev, res); + priv->io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->io_base)) return PTR_ERR(priv->io_base); |