Commit 27ed4476 authored by Federico Vaga's avatar Federico Vaga

sw:drv: make GN412X GPIO independent

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent e3b26a42
......@@ -23,9 +23,10 @@ dkms-src: dkms-tree
$(eval $@_src := $(shell git ls-tree -r --name-only HEAD $(TOP_DIR) | grep "kernel" | tr '\n' ' '))
$(eval $@_dir := $(BUILD_DKMSSOURCE)/$(DRIVER_NAME)-$(VERSION))
@mkdir -p $($@_dir)
@cp $($@_src) $(TOP_DIR)/distribution/dkms.conf $($@_dir)
@cp $(TOP_DIR)/LICENSES/GPL-2.0.txt $($@_dir)/LICENSE
@mkdir -p $($@_dir)/platform_data
@cp -a $($@_src) $(TOP_DIR)/distribution/dkms.conf $($@_dir)
@mv $($@_dir)/gn412x-gpio.h $($@_dir)/platform_data
@cp -a $(TOP_DIR)/LICENSES/GPL-2.0.txt $($@_dir)/LICENSE
@sed -r -i -e "s/^VERSION\s=\s.*/VERSION = $(VERSION)/" $($@_dir)/Makefile
@sed -r -i -e "s/@PKGNAME@/$(DRIVER_NAME)/" $($@_dir)/dkms.conf
@sed -r -i -e "s/@PKGVER@/$(VERSION)/" $($@_dir)/dkms.conf
......
......@@ -2,6 +2,9 @@ PACKAGE_NAME="@PKGNAME@"
PACKAGE_VERSION="@PKGVER@"
CLEAN="make clean"
MAKE[0]="make KVERSION=$kernelver all"
MAKE[1]="make KVERSION=$kernelver all"
BUILT_MODULE_NAME[0]="@PKGNAME@"
BUILT_MODULE_NAME[1]="gn412x-gpio"
DEST_MODULE_LOCATION[0]="/updates"
DEST_MODULE_LOCATION[1]="/updates"
AUTOINSTALL="yes"
......@@ -28,6 +28,7 @@ endif
KBUILD_EXTRA_SYMBOLS += $(FMC_ABS)/drivers/fmc/Module.symvers
obj-m := spec-fmc-carrier.o
obj-m += gn412x-gpio.o
spec-fmc-carrier-objs := spec-core.o
spec-fmc-carrier-objs += spec-core-fpga.o
......@@ -35,5 +36,4 @@ spec-fmc-carrier-objs += spec-fpga.o
spec-fmc-carrier-objs += spec-dbg.o
spec-fmc-carrier-objs += spec-fmc.o
spec-fmc-carrier-objs += spec-compat.o
spec-fmc-carrier-objs += gn412x-gpio.o
spec-fmc-carrier-objs += spec-gpio.o
This diff is collapsed.
//SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2010-2019 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#ifndef __GN412X_H__
#define __GN412X_H__
#define GNINT_STAT_GPIO BIT(15)
#define GNINT_STAT_SW0 BIT(2)
#define GNINT_STAT_SW1 BIT(3)
#define GNINT_STAT_SW_ALL (GNINT_STAT_SW0 | GNINT_STAT_SW1)
/* Registers for GN4124 access */
enum {
/* page 106 */
GNPPCI_MSI_CONTROL = 0x48, /* actually, 3 smaller regs */
GNPPCI_MSI_ADDRESS_LOW = 0x4c,
GNPPCI_MSI_ADDRESS_HIGH = 0x50,
GNPPCI_MSI_DATA = 0x54,
GNPCI_SYS_CFG_SYSTEM = 0x800,
/* page 130 ff */
GNINT_CTRL = 0x810,
GNINT_STAT = 0x814,
GNINT_CFG_0 = 0x820,
GNINT_CFG_1 = 0x824,
GNINT_CFG_2 = 0x828,
GNINT_CFG_3 = 0x82c,
GNINT_CFG_4 = 0x830,
GNINT_CFG_5 = 0x834,
GNINT_CFG_6 = 0x838,
GNINT_CFG_7 = 0x83c,
#define GNINT_CFG(x) (GNINT_CFG_0 + 4 * (x))
/* page 146 ff */
GNGPIO_BASE = 0xA00,
GNGPIO_BYPASS_MODE = GNGPIO_BASE,
GNGPIO_DIRECTION_MODE = GNGPIO_BASE + 0x04, /* 0 == output */
GNGPIO_OUTPUT_ENABLE = GNGPIO_BASE + 0x08,
GNGPIO_OUTPUT_VALUE = GNGPIO_BASE + 0x0C,
GNGPIO_INPUT_VALUE = GNGPIO_BASE + 0x10,
GNGPIO_INT_MASK = GNGPIO_BASE + 0x14, /* 1 == disabled */
GNGPIO_INT_MASK_CLR = GNGPIO_BASE + 0x18, /* irq enable */
GNGPIO_INT_MASK_SET = GNGPIO_BASE + 0x1C, /* irq disable */
GNGPIO_INT_STATUS = GNGPIO_BASE + 0x20,
GNGPIO_INT_TYPE = GNGPIO_BASE + 0x24, /* 1 == level */
GNGPIO_INT_VALUE = GNGPIO_BASE + 0x28, /* 1 == high/rise */
GNGPIO_INT_ON_ANY = GNGPIO_BASE + 0x2C, /* both edges */
/* page 158 ff */
FCL_BASE = 0xB00,
FCL_CTRL = FCL_BASE,
FCL_STATUS = FCL_BASE + 0x04,
FCL_IODATA_IN = FCL_BASE + 0x08,
FCL_IODATA_OUT = FCL_BASE + 0x0C,
FCL_EN = FCL_BASE + 0x10,
FCL_TIMER_0 = FCL_BASE + 0x14,
FCL_TIMER_1 = FCL_BASE + 0x18,
FCL_CLK_DIV = FCL_BASE + 0x1C,
FCL_IRQ = FCL_BASE + 0x20,
FCL_TIMER_CTRL = FCL_BASE + 0x24,
FCL_IM = FCL_BASE + 0x28,
FCL_TIMER2_0 = FCL_BASE + 0x2C,
FCL_TIMER2_1 = FCL_BASE + 0x30,
FCL_DBG_STS = FCL_BASE + 0x34,
FCL_FIFO = 0xE00,
PCI_SYS_CFG_SYSTEM = 0x800
};
#endif
#ifndef __GN412X_GPIO_H__
#define __GN412X_GPIO_H__
struct gn412x_platform_data {
unsigned int int_cfg;
};
#endif
......@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/fpga/fpga-mgr.h>
#include <linux/version.h>
#include <linux/gpio/driver.h>
#include "spec-compat.h"
int compat_get_fpga_last_word_size(struct fpga_image_info *info, size_t count)
......@@ -216,17 +217,4 @@ void gpiod_remove_lookup_table(struct gpiod_lookup_table *table)
mutex_unlock(gpio_lookup_lock_p);
}
void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
{
void (*gpiochip_irqchip_remove_p)(struct gpio_chip *gpiochip);
gpiochip_irqchip_remove_p = (void *) kallsyms_lookup_name("gpiochip_irqchip_remove");
if (gpiochip_irqchip_remove_p)
gpiochip_irqchip_remove_p(gpiochip);
else
WARN(1, "Cannot find 'gpiochip_irqchip_remove'");
}
#endif
......@@ -6,6 +6,7 @@
#include <linux/fpga/fpga-mgr.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/gpio/driver.h>
#include "spec.h"
#if KERNEL_VERSION(4,10,0) <= LINUX_VERSION_CODE
......@@ -81,5 +82,4 @@ extern int compat_gpiod_add_lookup_table(struct gpiod_lookup_table *table);
#if KERNEL_VERSION(4, 3, 0) > LINUX_VERSION_CODE
extern void gpiod_remove_lookup_table(struct gpiod_lookup_table *table);
extern void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
#endif
......@@ -13,10 +13,14 @@
#include <linux/pci.h>
#include <linux/firmware.h>
#include <linux/moduleparam.h>
#include <linux/mfd/core.h>
#include "platform_data/gn412x-gpio.h"
#include "spec.h"
#include "spec-compat.h"
static int mfd_id; /* FIXME look for something better */
static char *spec_fw_name_45t = "spec-init-45T.bin";
static char *spec_fw_name_100t = "spec-init-100T.bin";
static char *spec_fw_name_150t = "spec-init-150T.bin";
......@@ -24,6 +28,37 @@ static char *spec_fw_name_150t = "spec-init-150T.bin";
char *spec_fw_name = "";
module_param_named(fw_name, spec_fw_name, charp, 0444);
static struct gn412x_platform_data gn412x_gpio_pdata = {
.int_cfg = 0,
};
static struct resource gn412x_gpio_res[] = {
{
.name = "gn412x-gpio-mem",
.flags = IORESOURCE_MEM,
.start = 0,
.end = 0x1000 - 1,
}, {
.name = "gn412x-gpio-irq",
.flags = IORESOURCE_IRQ,
.start = 0,
.end = 0,
}
};
enum spec_mfd_enum {
SPEC_MFD_GN412X_GPIO = 0,
};
static const struct mfd_cell spec_mfd_devs[] = {
[SPEC_MFD_GN412X_GPIO] = {
.name = "gn412x-gpio",
.platform_data = &gn412x_gpio_pdata,
.pdata_size = sizeof(gn412x_gpio_pdata),
.num_resources = ARRAY_SIZE(gn412x_gpio_res),
.resources = gn412x_gpio_res,
},
};
/**
* Return the SPEC defult FPGA firmware name based on PCI ID
* @spec: SPEC device
......@@ -100,6 +135,7 @@ static const struct device_type spec_dev_type = {
.uevent = spec_uevent,
};
static int spec_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
......@@ -146,10 +182,12 @@ static int spec_probe(struct pci_dev *pdev,
/* This virtual device is assciated with this driver */
spec->dev.driver = pdev->dev.driver;
spec->gn412x.mem = spec->remap[2];
err = gn412x_gpio_init(&spec->dev, &spec->gn412x);
err = mfd_add_devices(&spec->dev, mfd_id++,
spec_mfd_devs,
ARRAY_SIZE(spec_mfd_devs),
&pdev->resource[4], pdev->irq, NULL);
if (err)
goto err_ggpio;
goto err_mfd;
err = spec_gpio_init(spec);
if (err)
......@@ -185,8 +223,8 @@ err_fw:
err_fpga:
spec_gpio_exit(spec);
err_sgpio:
gn412x_gpio_exit(&spec->gn412x);
err_ggpio:
mfd_remove_devices(&spec->dev);
err_mfd:
device_unregister(&spec->dev);
err_dev:
err_name:
......@@ -212,7 +250,8 @@ static void spec_remove(struct pci_dev *pdev)
spec_core_fpga_exit(spec);
spec_fpga_exit(spec);
spec_gpio_exit(spec);
gn412x_gpio_exit(&spec->gn412x);
mfd_remove_devices(&spec->dev);
for (i = 0; i < 3; i++)
if (spec->remap[i])
......
......@@ -66,13 +66,15 @@ static inline size_t spec_gpiod_table_size(void)
int spec_gpio_init(struct spec_dev *spec)
{
struct gpiod_lookup_table *lookup;
int err;
int err = 0;
lookup = devm_kzalloc(&spec->dev,
spec_gpiod_table_size(),
GFP_KERNEL);
if (!lookup)
return -ENOMEM;
if (!lookup) {
err = -ENOMEM;
goto err_alloc;
}
memcpy(lookup, &spec_gpiod_table, spec_gpiod_table_size());
......@@ -148,8 +150,9 @@ err_lookup:
err_dup:
devm_kfree(&spec->dev, lookup);
spec->gpiod_table = NULL;
err_alloc:
return -ENODEV;
return err;
}
void spec_gpio_exit(struct spec_dev *spec)
......
......@@ -7,7 +7,6 @@
*/
#ifndef __SPEC_H__
#define __SPEC_H__
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/fpga/fpga-mgr.h>
......@@ -15,10 +14,11 @@
#include <linux/irqdomain.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/gpio/driver.h>
#include <linux/spinlock.h>
#include <linux/fmc.h>
#include "gn412x.h"
#define SPEC_FMC_SLOTS 1
/* On FPGA components */
......@@ -58,65 +58,6 @@ enum spec_fpga_select {
SPEC_FPGA_SELECT_SPI,
};
/* Registers for GN4124 access */
enum {
/* page 106 */
GNPPCI_MSI_CONTROL = 0x48, /* actually, 3 smaller regs */
GNPPCI_MSI_ADDRESS_LOW = 0x4c,
GNPPCI_MSI_ADDRESS_HIGH = 0x50,
GNPPCI_MSI_DATA = 0x54,
GNPCI_SYS_CFG_SYSTEM = 0x800,
/* page 130 ff */
GNINT_CTRL = 0x810,
GNINT_STAT = 0x814,
GNINT_CFG_0 = 0x820,
GNINT_CFG_1 = 0x824,
GNINT_CFG_2 = 0x828,
GNINT_CFG_3 = 0x82c,
GNINT_CFG_4 = 0x830,
GNINT_CFG_5 = 0x834,
GNINT_CFG_6 = 0x838,
GNINT_CFG_7 = 0x83c,
#define GNINT_CFG(x) (GNINT_CFG_0 + 4 * (x))
/* page 146 ff */
GNGPIO_BASE = 0xA00,
GNGPIO_BYPASS_MODE = GNGPIO_BASE,
GNGPIO_DIRECTION_MODE = GNGPIO_BASE + 0x04, /* 0 == output */
GNGPIO_OUTPUT_ENABLE = GNGPIO_BASE + 0x08,
GNGPIO_OUTPUT_VALUE = GNGPIO_BASE + 0x0C,
GNGPIO_INPUT_VALUE = GNGPIO_BASE + 0x10,
GNGPIO_INT_MASK = GNGPIO_BASE + 0x14, /* 1 == disabled */
GNGPIO_INT_MASK_CLR = GNGPIO_BASE + 0x18, /* irq enable */
GNGPIO_INT_MASK_SET = GNGPIO_BASE + 0x1C, /* irq disable */
GNGPIO_INT_STATUS = GNGPIO_BASE + 0x20,
GNGPIO_INT_TYPE = GNGPIO_BASE + 0x24, /* 1 == level */
GNGPIO_INT_VALUE = GNGPIO_BASE + 0x28, /* 1 == high/rise */
GNGPIO_INT_ON_ANY = GNGPIO_BASE + 0x2C, /* both edges */
/* page 158 ff */
FCL_BASE = 0xB00,
FCL_CTRL = FCL_BASE,
FCL_STATUS = FCL_BASE + 0x04,
FCL_IODATA_IN = FCL_BASE + 0x08,
FCL_IODATA_OUT = FCL_BASE + 0x0C,
FCL_EN = FCL_BASE + 0x10,
FCL_TIMER_0 = FCL_BASE + 0x14,
FCL_TIMER_1 = FCL_BASE + 0x18,
FCL_CLK_DIV = FCL_BASE + 0x1C,
FCL_IRQ = FCL_BASE + 0x20,
FCL_TIMER_CTRL = FCL_BASE + 0x24,
FCL_IM = FCL_BASE + 0x28,
FCL_TIMER2_0 = FCL_BASE + 0x2C,
FCL_TIMER2_1 = FCL_BASE + 0x30,
FCL_DBG_STS = FCL_BASE + 0x34,
FCL_FIFO = 0xE00,
PCI_SYS_CFG_SYSTEM = 0x800
};
enum {
/* Metadata */
......@@ -143,7 +84,6 @@ enum {
#define SPEC_META_CAP_DMA BIT(0)
#define SPEC_META_CAP_WR BIT(0)
/**
* struct spec_meta_id Metadata
*/
......@@ -157,30 +97,6 @@ struct spec_meta_id {
uint32_t uuid[4];
};
#define GNINT_STAT_GPIO BIT(15)
#define GNINT_STAT_SW0 BIT(2)
#define GNINT_STAT_SW1 BIT(3)
#define GNINT_STAT_SW_ALL (GNINT_STAT_SW0 | GNINT_STAT_SW1)
/**
* struct gn412x_dev GN412X device descriptor
* @compl: for IRQ testing
* @int_cfg_gpio: INT_CFG used for GPIO interrupts
*/
struct gn412x_dev {
void __iomem *mem;
struct gpio_chip gpiochip;
struct completion compl;
int int_cfg_gpio;
};
static inline struct gn412x_dev *to_gn412x_dev_gpio(struct gpio_chip *chip)
{
return container_of(chip, struct gn412x_dev, gpiochip);
}
/**
* struct spec_dev - SPEC instance
* It describes a SPEC device instance.
......@@ -215,8 +131,6 @@ struct spec_dev {
#define SPEC_DBG_META_NAME "fpga_device_metadata"
struct dentry *dbg_meta;
struct gn412x_dev gn412x;
struct gpiod_lookup_table *gpiod_table;
struct gpio_desc *gpiod[GN4124_GPIO_MAX];
};
......@@ -267,12 +181,6 @@ static inline void gennum_mask_val(struct spec_dev *spec,
gennum_writel(spec, v, reg);
}
extern int gn412x_gpio_init(struct device *parent, struct gn412x_dev *spec);
extern void gn412x_gpio_exit(struct gn412x_dev *spec);
extern int gn412x_int_gpio_enable(struct gn412x_dev *gn412x,
unsigned int cfg_n);
extern void gn412x_int_gpio_disable(struct gn412x_dev *gn412x);
extern int spec_fpga_init(struct spec_dev *spec);
extern void spec_fpga_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