Commit 29c35f2a authored by Federico Vaga's avatar Federico Vaga

Merge branch 'release/v0.3'

parents 3dc5715e 1bf3ef45
......@@ -5,7 +5,7 @@
REPO_PARENT ?= $(shell /bin/pwd)/..
-include $(REPO_PARENT)/parent_common.mk
DIRS = kernel doc
DIRS = kernel
.PHONY: all clean modules install modules_install $(DIRS)
......
......@@ -9,20 +9,21 @@ endif
ccflags-y += -DADDITIONAL_VERSIONS="$(SUBMODULE_VERSIONS)"
ccflags-y += -DGIT_VERSION=\"$(GIT_VERSION)\"
ccflags-y += -I$(FPGA_MGR_ABS)/include
ccflags-y += -I$(FMC_ABS)/include
ccflags-y += -I$(I2C_ABS)/include
ccflags-y += -Wall -Werror
# priority to I2C headers from our sources
LINUXINCLUDE := -I$(FMC_MGR_ABS)/include -I$(FMC_MGR_ABS)/include/linux -I$(FMC_ABS)/include -I$(FMC_ABS)/include/linux -I$(I2C_ABS)/include -I$(I2C_ABS)/include/linux $(LINUXINCLUDE)
ccflags-$(CONFIG_FPGA_MGR_BACKPORT) += -DCONFIG_FPGA_MGR_BACKPORT
ccflags-$(CONFIG_FPGA_MGR_BACKPORT) += -I$(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS)/include
KBUILD_EXTRA_SYMBOLS += $(FPGA_MGR_ABS)/drivers/fpga/Module.symvers
KBUILD_EXTRA_SYMBOLS += $(FMC_ABS)/drivers/fmc/Module.symvers
ifeq ($(CONFIG_FPGA_MGR_BACKPORT), y)
CONFIG_FPGA_MGR_BACKPORT_INCLUDE := -I$(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS)/include
CONFIG_FPGA_MGR_BACKPORT_INCLUDE += -I$(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS)/include/linux
LINUXINCLUDE := $(CONFIG_FPGA_MGR_BACKPORT_INCLUDE) $(LINUXINCLUDE)
KBUILD_EXTRA_SYMBOLS += $(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS)/drivers/fpga/Module.symvers
endif
obj-m := spec.o
spec-objs := spec-core.o
spec-objs += spec-fpga.o
spec-objs += spec-fmc.o
spec-objs += spec-irq.o
spec-objs += spec-compat.o
......@@ -5,12 +5,12 @@ REPO_PARENT ?= $(shell /bin/pwd)/../..
LINUX ?= /lib/modules/$(shell uname -r)/build
FPGA_MGR_ABS ?= $(abspath $(FPGA_MGR))
FMC_ABS ?= $(abspath $(FMC))
I2C_ABS ?= $(abspath $(I2C))
CONFIG_FPGA_MGR_BACKPORT_PATH_ABS ?= $(abspath $(CONFIG_FPGA_MGR_BACKPORT_PATH))
GIT_VERSION = $(shell git describe --dirty --long --tags)
export GIT_VERSION
......@@ -19,7 +19,7 @@ all: modules
.PHONY: all modules clean help install modules_install
modules help install modules_install:
$(MAKE) -C $(LINUX) M=$(shell pwd) GIT_VERSION=$(GIT_VERSION) FPGA_MGR_ABS=$(FPGA_MGR_ABS) FMC_ABS=$(FMC_ABS) I2C_ABS=$(I2C_ABS) $@
$(MAKE) -C $(LINUX) M=$(shell pwd) GIT_VERSION=$(GIT_VERSION) CONFIG_FPGA_MGR_BACKPORT_PATH_ABS=$(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS) CONFIG_FPGA_MGR_BACKPORT=$(CONFIG_FPGA_MGR_BACKPORT) $@
# be able to run the "clean" rule even if $(LINUX) is not valid
clean:
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2017 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/fpga/fpga-mgr.h>
#include <linux/version.h>
#include "spec-compat.h"
int compat_get_fpga_last_word_size(struct fpga_image_info *info, size_t count)
{
#if KERNEL_VERSION(4,16,0) > LINUX_VERSION_CODE && !defined(CONFIG_FPGA_MGR_BACKPORT)
return count;
#else
return info ? info->count : count;
#endif
}
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE && !defined(CONFIG_FPGA_MGR_BACKPORT)
int compat_spec_fpga_write_init(struct fpga_manager *mgr,
u32 flags,
const char *buf, size_t count)
{
return spec_fpga_write_init(mgr, NULL, buf, count);
}
int compat_spec_fpga_write_complete(struct fpga_manager *mgr,
u32 flags)
{
return spec_fpga_write_complete(mgr, NULL);
}
#else
int compat_spec_fpga_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count)
{
return spec_fpga_write_init(mgr, info, buf, count);
}
int compat_spec_fpga_write_complete(struct fpga_manager *mgr,
struct fpga_image_info *info)
{
return spec_fpga_write_complete(mgr, info);
}
#endif
#if KERNEL_VERSION(4,18,0) > LINUX_VERSION_CODE && !defined(CONFIG_FPGA_MGR_BACKPORT)
struct fpga_manager *compat_fpga_mgr_create(struct device *dev, const char *name,
const struct fpga_manager_ops *mops,
void *priv)
{
int err;
err = fpga_mgr_register(dev, name, mops, priv);
if (err)
return NULL;
return (struct fpga_manager *)dev;
}
void compat_fpga_mgr_free(struct fpga_manager *mgr)
{
fpga_mgr_unregister((struct device *)mgr);
}
int compat_fpga_mgr_register(struct fpga_manager *mgr)
{
return mgr ? 0 : 1;
}
void compat_fpga_mgr_unregister(struct fpga_manager *mgr)
{
fpga_mgr_unregister((struct device *)mgr);
}
#else
struct fpga_manager *compat_fpga_mgr_create(struct device *dev,
const char *name,
const struct fpga_manager_ops *mops,
void *priv)
{
return fpga_mgr_create(dev, name, mops, priv);
}
void compat_fpga_mgr_free(struct fpga_manager *mgr)
{
fpga_mgr_free(mgr);
}
int compat_fpga_mgr_register(struct fpga_manager *mgr)
{
return fpga_mgr_register(mgr);
}
void compat_fpga_mgr_unregister(struct fpga_manager *mgr)
{
fpga_mgr_unregister(mgr);
}
#endif
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2017 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/fpga/fpga-mgr.h>
#include <linux/types.h>
#include <linux/version.h>
#if KERNEL_VERSION(4,10,0) <= LINUX_VERSION_CODE
#if KERNEL_VERSION(4,16,0) > LINUX_VERSION_CODE
/* So that we select the buffer size because smaller */
#define compat_fpga_ops_initial_header_size .initial_header_size = 0xFFFFFFFF,
#else
#define compat_fpga_ops_initial_header_size .initial_header_size = 0,
#endif
#else
#define compat_fpga_ops_initial_header_size
#endif
#if KERNEL_VERSION(4,16,0) > LINUX_VERSION_CODE && ! defined(CONFIG_FPGA_MGR_BACKPORT)
#define compat_fpga_ops_groups
#else
#define compat_fpga_ops_groups .groups = NULL,
#endif
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE && ! defined(CONFIG_FPGA_MGR_BACKPORT)
struct fpga_image_info;
#endif
int spec_fpga_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count);
int spec_fpga_write_complete(struct fpga_manager *mgr,
struct fpga_image_info *info);
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE && ! defined(CONFIG_FPGA_MGR_BACKPORT)
int compat_spec_fpga_write_init(struct fpga_manager *mgr, u32 flags,
const char *buf, size_t count);
int compat_spec_fpga_write_complete(struct fpga_manager *mgr, u32 flags);
#else
int compat_spec_fpga_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count);
int compat_spec_fpga_write_complete(struct fpga_manager *mgr,
struct fpga_image_info *info);
#endif
int compat_get_fpga_last_word_size(struct fpga_image_info *info,
size_t count);
struct fpga_manager *compat_fpga_mgr_create(struct device *dev,
const char *name,
const struct fpga_manager_ops *mops,
void *priv);
void compat_fpga_mgr_free(struct fpga_manager *mgr);
int compat_fpga_mgr_register(struct fpga_manager *mgr);
void compat_fpga_mgr_unregister(struct fpga_manager *mgr);
......@@ -14,6 +14,10 @@
#include "spec.h"
static void spec_release(struct device *dev)
{
}
static int spec_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
......@@ -21,11 +25,9 @@ static int spec_probe(struct pci_dev *pdev,
struct spec_dev *spec;
int err, i;
spec = kzalloc(sizeof(struct spec_dev), GFP_KERNEL);
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
spec->pdev = pdev;
pci_set_drvdata(pdev, spec);
err = pci_enable_device(pdev);
if (err)
......@@ -49,30 +51,37 @@ static int spec_probe(struct pci_dev *pdev,
if (err)
goto err_remap;
err = spec_fpga_init(spec);
spec->dev.parent = &pdev->dev;
spec->dev.release = spec_release;
err = dev_set_name(&spec->dev, "spec-%s", dev_name(&pdev->dev));
if (err)
goto err_fpga;
goto err_name;
err = device_register(&spec->dev);
if (err)
goto err_dev;
err = spec_fmc_init(spec);
err = spec_fpga_init(spec);
if (err)
goto err_fmc;
goto err_fpga;
err = spec_irq_init(spec);
if (err)
goto err_irq;
pci_set_drvdata(pdev, spec);
return 0;
err_irq:
spec_fmc_exit(spec);
err_fmc:
spec_fpga_exit(spec);
err_fpga:
pci_set_drvdata(pdev, NULL);
device_unregister(&spec->dev);
err_dev:
err_name:
for (i = 0; i < 3; i++) {
if (spec->remap[i])
iounmap(spec->remap[i]);
spec->remap[i] = NULL;
}
err_remap:
pci_disable_device(pdev);
......@@ -87,17 +96,14 @@ static void spec_remove(struct pci_dev *pdev)
struct spec_dev *spec = pci_get_drvdata(pdev);
int i;
pci_set_drvdata(pdev, NULL);
spec_irq_exit(spec);
spec_fmc_exit(spec);
spec_fpga_exit(spec);
for (i = 0; i < 3; i++) {
for (i = 0; i < 3; i++)
if (spec->remap[i])
iounmap(spec->remap[i]);
spec->remap[i] = NULL;
}
device_unregister(&spec->dev);
pci_disable_device(pdev);
kfree(spec);
}
......
/*
* Copyright (C) 2017 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <linux/kernel.h>
#include <linux/platform_data/i2c-ocores.h>
#include "spec.h"
static int spec_fmc_is_present(struct fmc_carrier *carrier,
struct fmc_slot *slot)
{
/* TODO implement me */
return 0;
}
static const struct fmc_carrier_operations spec_fmc_ops = {
.is_present = spec_fmc_is_present,
};
static const struct ocores_i2c_platform_data pdata = {
.reg_shift = 0,
.reg_io_width = 4,
.clock_khz = 62500,
.big_endian = 0,
.num_devices = 0,
.devices = NULL,
};
static int spec_i2c_find_adapter(struct device *dev, void *data)
{
struct spec_dev *spec = data;
struct i2c_adapter *adap, *adap_parent;
if (dev->type != &i2c_adapter_type)
return 0;
adap = to_i2c_adapter(dev);
adap_parent = i2c_parent_is_i2c_adapter(adap);
if (!adap_parent)
return 0;
if (&spec->i2c_pdev->dev != adap_parent->dev.parent)
return 0;
/* Found! */
return i2c_adapter_id(adap);
}
/**
* Get the I2C adapter associated with an FMC slot
* @spec: SPEC instance
*
* Return: the I2C bus to be used
*/
static int spec_i2c_get_bus(struct spec_dev *spec)
{
return i2c_for_each_dev(spec, spec_i2c_find_adapter);
}
static int id;
/**
* It builds the platform_device_info necessary to register the
* I2C master device.
* @spec the SPEC instance
*
* Return: an array of I2C master devices
*/
static int spec_i2c_add(struct spec_dev *spec)
{
struct resource res = {
.name = "i2c-ocores-mem",
.flags = IORESOURCE_MEM,
};
int err;
/* VME function 1 */
res.start = pci_resource_start(to_pci_dev(spec->pdev->dev.parent), 0);
res.start += SPEC_I2C_MASTER_ADDR;
res.end = res.start + SPEC_I2C_MASTER_SIZE;
/* FIXME find better ID */
spec->i2c_pdev = platform_device_register_resndata(&spec->pdev->dev,
"ocores-i2c", id++,
&res, 1,
&pdata,
sizeof(pdata));
if (!spec->i2c_pdev)
return -ENODEV;
err = i2c_for_each_dev(spec, spec_i2c_find_adapter);
if (err <= 0)
goto err;
return 0;
err:
platform_device_unregister(spec->i2c_pdev);
return -ENODEV;
}
static void spec_i2c_del(struct spec_dev *spec)
{
platform_device_unregister(spec->i2c_pdev);
if (spec->i2c_adapter)
i2c_put_adapter(spec->i2c_adapter);
}
int spec_fmc_init(struct spec_dev *spec)
{
int err;
return 0; /* UNTIL WE TEST IT */
if (!spec)
return -EINVAL;
err = spec_i2c_add(spec);
if (err)
goto err_i2c;
spec->slot_info.i2c_bus_nr = spec_i2c_get_bus(spec);
if (spec->slot_info.i2c_bus_nr <= 0)
goto err_i2c_bus;
spec->slot_info.ga = 0;
spec->slot_info.lun = 0;
err = fmc_carrier_register(&spec->pdev->dev, &spec_fmc_ops,
SPEC_FMC_SLOTS, &spec->slot_info, spec);
if (err)
goto err_fmc;
return 0;
err_fmc:
err_i2c_bus:
spec_i2c_del(spec);
err_i2c:
return err;
}
void spec_fmc_exit(struct spec_dev *spec)
{
return; /* UNTIL WE TEST IT */
if (!spec)
return;
fmc_carrier_unregister(&spec->pdev->dev);
spec_i2c_del(spec);
}
......@@ -4,10 +4,11 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <linux/fpga/fpga-mgr.h>
#include <linux/delay.h>
#include "spec.h"
#include "spec-compat.h"
static inline uint8_t reverse_bits8(uint8_t x)
{
......@@ -240,15 +241,16 @@ static enum fpga_mgr_states spec_fpga_state(struct fpga_manager *mgr)
}
static int spec_fpga_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count)
int spec_fpga_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count)
{
struct spec_dev *spec = mgr->priv;
int err = 0;
int err = 0, last_word_size;
gn4124_fpga_gpio_config(spec);
err = gn4124_fpga_fcl_init(spec, info->count & 0x3);
last_word_size = compat_get_fpga_last_word_size(info, count) & 0x3;
err = gn4124_fpga_fcl_init(spec, last_word_size);
if (err < 0)
goto err;
......@@ -259,7 +261,6 @@ err:
return err;
}
static int spec_fpga_write(struct fpga_manager *mgr, const char *buf, size_t count)
{
struct spec_dev *spec = mgr->priv;
......@@ -268,8 +269,8 @@ static int spec_fpga_write(struct fpga_manager *mgr, const char *buf, size_t cou
}
static int spec_fpga_write_complete(struct fpga_manager *mgr,
struct fpga_image_info *info)
int spec_fpga_write_complete(struct fpga_manager *mgr,
struct fpga_image_info *info)
{
struct spec_dev *spec = mgr->priv;
int err;
......@@ -292,15 +293,15 @@ static void spec_fpga_remove(struct fpga_manager *mgr)
/* do nothing */
}
static const struct fpga_manager_ops spec_fpga_ops = {
.initial_header_size = 0,
compat_fpga_ops_initial_header_size
compat_fpga_ops_groups
.state = spec_fpga_state,
.write_init = spec_fpga_write_init,
.write_init = compat_spec_fpga_write_init,
.write = spec_fpga_write,
.write_complete = spec_fpga_write_complete,
.write_complete = compat_spec_fpga_write_complete,
.fpga_remove = spec_fpga_remove,
.groups = NULL,
};
......@@ -308,18 +309,15 @@ int spec_fpga_init(struct spec_dev *spec)
{
int err;
if (!spec)
return -EINVAL;
spec->mgr = fpga_mgr_create(&spec->pdev->dev,
dev_name(&spec->pdev->dev),
&spec_fpga_ops, spec);
if (!spec->mgr)
spec->mgr = compat_fpga_mgr_create(&spec->dev,
dev_name(&spec->dev),
&spec_fpga_ops, spec);
if (!spec || !spec->mgr)
return -EPERM;
err = fpga_mgr_register(spec->mgr);
err = compat_fpga_mgr_register(spec->mgr);
if (err) {
fpga_mgr_free(spec->mgr);
compat_fpga_mgr_free(spec->mgr);
return err;
}
......@@ -328,7 +326,7 @@ int spec_fpga_init(struct spec_dev *spec)
void spec_fpga_exit(struct spec_dev *spec)
{
if (!spec || !spec->mgr)
if (!spec)
return;
fpga_mgr_unregister(spec->mgr);
compat_fpga_mgr_unregister(spec->mgr);
}
......@@ -36,9 +36,9 @@ static int spec_irq_dbg_info(struct seq_file *s, void *offset)
struct spec_dev *spec = s->private;
int i;
seq_printf(s, "'%s':\n",dev_name(&spec->pdev->dev));
seq_printf(s, "'%s':\n",dev_name(spec->dev.parent));
seq_printf(s, " redirect: %d\n", spec->pdev->irq);
seq_printf(s, " redirect: %d\n", to_pci_dev(spec->dev.parent)->irq);
seq_printf(s, " irq-mapping:\n");
for (i = 0; i < GN4124_GPIO_IRQ_MAX; ++i) {
seq_printf(s, " - hardware: %d\n", i);
......@@ -73,9 +73,9 @@ static const struct file_operations spec_irq_dbg_info_ops = {
*/
static int spec_irq_debug_init(struct spec_dev *spec)
{
spec->dbg_dir = debugfs_create_dir(dev_name(&spec->pdev->dev), NULL);
spec->dbg_dir = debugfs_create_dir(dev_name(&spec->dev), NULL);
if (IS_ERR_OR_NULL(spec->dbg_dir)) {
dev_err(&spec->pdev->dev,
dev_err(&spec->dev,
"Cannot create debugfs directory (%ld)\n",
PTR_ERR(spec->dbg_dir));
return PTR_ERR(spec->dbg_dir);
......@@ -85,7 +85,7 @@ static int spec_irq_debug_init(struct spec_dev *spec)
spec->dbg_dir, spec,
&spec_irq_dbg_info_ops);
if (IS_ERR_OR_NULL(spec->dbg_info)) {
dev_err(&spec->pdev->dev,
dev_err(&spec->dev,
"Cannot create debugfs file \"%s\" (%ld)\n",
SPEC_DBG_INFO_NAME, PTR_ERR(spec->dbg_info));
return PTR_ERR(spec->dbg_info);
......@@ -101,8 +101,7 @@ static int spec_irq_debug_init(struct spec_dev *spec)
*/
static void spec_irq_debug_exit(struct spec_dev *spec)
{
if (spec->dbg_dir)
debugfs_remove_recursive(spec->dbg_dir);
debugfs_remove_recursive(spec->dbg_dir);
}
......@@ -139,7 +138,8 @@ static int spec_irq_gpio_set_type(struct irq_data *d, unsigned int flow_type)
*/
if ((flow_type & IRQ_TYPE_LEVEL_MASK) &&
(flow_type & IRQ_TYPE_EDGE_BOTH)) {
dev_err(&spec->pdev->dev, "Impossible to set GPIO IRQ %ld to both LEVEL and EDGE (0x%x)\n",
dev_err(&spec->dev,
"Impossible to set GPIO IRQ %ld to both LEVEL and EDGE (0x%x)\n",
d->hwirq, flow_type);
return -EINVAL;
}
......@@ -215,27 +215,6 @@ static struct irq_chip spec_irq_gpio_chip = {
.irq_set_type = spec_irq_gpio_set_type,
};
/**
* It match a given device with the irq_domain. `struct device_node *` is just
* a convention. actually it can be anything (I do not understand why kernel
* people did not use `void *`)
*
* In our case here we expect a string because we identify this domain by
* name
*/
static int spec_irq_gpio_domain_match(struct irq_domain *d, struct device_node *node)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
char *name = (char *)node;
if (strcmp(d->name, name) == 0)
return 1;
#endif
return 0;
}
/**
* Given the hardware IRQ and the Linux IRQ number (virtirq), configure the
* Linux IRQ number in order to handle properly the incoming interrupts
......@@ -258,7 +237,6 @@ static int spec_irq_gpio_domain_map(struct irq_domain *h,
static struct irq_domain_ops spec_irq_gpio_domain_ops = {
.match = spec_irq_gpio_domain_match,
.map = spec_irq_gpio_domain_map,
};
......@@ -370,7 +348,7 @@ static int spec_irq_gpio_init(struct spec_dev *spec)
return -ENOMEM;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
spec->gpio_domain->name = kasprintf(GFP_KERNEL, "%s-gn4124-gpio-irq",
dev_name(&spec->pdev->dev));
dev_name(&spec->dev));
#endif
......@@ -449,7 +427,7 @@ static int spec_irq_sw_test(struct spec_dev *spec)
msecs_to_jiffies(10000));
if (ret == 0) {
gennum_writel(spec, 0x0000, GNINT_STAT); /* disable */
dev_err(&spec->pdev->dev, "Cannot receive interrupts\n");
dev_err(&spec->dev, "Cannot receive interrupts\n");
return -EINVAL;
}
return 0;
......@@ -463,6 +441,7 @@ static int spec_irq_sw_test(struct spec_dev *spec)
*/
int spec_irq_init(struct spec_dev *spec)
{
int irq = to_pci_dev(spec->dev.parent)->irq;
int err;
int i;
......@@ -481,22 +460,21 @@ int spec_irq_init(struct spec_dev *spec)
goto err_sw;
#if CHAIN
irq_set_chained_handler(spec->pdev->irq, spec_irq_chain_handler);
irq_set_handler_data(spec->pdev->irq, spec);
irq_set_chained_handler(irq, spec_irq_chain_handler);
irq_set_handler_data(irq, spec);
#else
/*
* It depends on the platform and on the IRQ on which we are connecting to
* but most likely our interrupt handler will be a thread.
*/
err = request_threaded_irq(spec->pdev->irq,
err = request_threaded_irq(irq,
spec_irq_handler,
spec_irq_gpio_handler,
IRQF_SHARED,
dev_name(&spec->pdev->dev),
dev_name(&spec->dev),
spec);
if (err) {
dev_err(&spec->pdev->dev, "Can't request IRQ %d (%d)\n",
spec->pdev->irq, err);
dev_err(&spec->dev, "Can't request IRQ %d (%d)\n", irq, err);
goto err_req;
}
#endif
......@@ -510,7 +488,7 @@ int spec_irq_init(struct spec_dev *spec)
err_test:
spec_irq_debug_exit(spec);
free_irq(spec->pdev->irq, spec);
free_irq(irq, spec);
err_req:
spec_irq_sw_exit(spec);
err_sw:
......@@ -522,6 +500,7 @@ err_gpio:
void spec_irq_exit(struct spec_dev *spec)
{
int i;
int irq = to_pci_dev(spec->dev.parent)->irq;
if (!spec)
return;
......@@ -529,8 +508,9 @@ void spec_irq_exit(struct spec_dev *spec)
/* disable all source of interrupts */
for (i = 0; i < 7; i++)
gennum_writel(spec, 0, GNINT_CFG(i));
spec_irq_debug_exit(spec);
free_irq(spec->pdev->irq, spec);
free_irq(irq, spec);
spec_irq_sw_exit(spec);
spec_irq_gpio_exit(spec);
}
......@@ -10,7 +10,6 @@
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/fmc.h>
#include <linux/fpga/fpga-mgr.h>
#include <linux/i2c.h>
#include <linux/irqdomain.h>
......@@ -119,7 +118,7 @@ enum {
* @compl: for IRQ testing
*/
struct spec_dev {
struct pci_dev *pdev;
struct device dev;
struct irq_domain *gpio_domain;
......@@ -128,10 +127,6 @@ struct spec_dev {
DECLARE_BITMAP(flags, SPEC_FLAG_BITS);
void __iomem *remap[3]; /* ioremap of bar 0, 2, 4 */
struct fmc_slot_info slot_info;
struct platform_device *i2c_pdev;
struct i2c_adapter *i2c_adapter;
struct dentry *dbg_dir;
#define SPEC_DBG_INFO_NAME "info"
struct dentry *dbg_info;
......@@ -140,6 +135,11 @@ struct spec_dev {
};
static inline struct spec_dev *to_spec_dev(struct device *_dev)
{
return container_of(_dev, struct spec_dev, dev);
}
/**
* It reads a 32bit register from the gennum chip
* @spec spec device instance
......@@ -184,9 +184,6 @@ static inline void gennum_mask_val(struct spec_dev *spec,
extern int spec_fpga_init(struct spec_dev *spec);
extern void spec_fpga_exit(struct spec_dev *spec);
extern int spec_fmc_init(struct spec_dev *spec);
extern void spec_fmc_exit(struct spec_dev *spec);
extern int spec_irq_init(struct spec_dev *spec);
extern void spec_irq_exit(struct spec_dev *spec);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment