Commit bf34340d authored by Federico Vaga's avatar Federico Vaga

core: update to new spec-sw driver

Signed-off-by: 's avatarFederico Vaga <federico.vaga@gmail.com>
parent 2427a5fe
......@@ -5,7 +5,7 @@ SPEC_SW ?= $(HOME)/spec-sw
KBUILD_EXTRA_SYMBOLS := $(ZIO)/Module.symvers $(SPEC_SW)/kernel/Module.symvers
ccflags-y = -I$(ZIO)/include -I$(SPEC_SW)/kernel -I$M
ccflags-y = -I$(ZIO)/include -I$(SPEC_SW)/kernel -I$(SPEC_SW)/kernel/include -I$M
ccflags-y += -DDEBUG # temporary
......@@ -16,7 +16,6 @@ obj-m := spec-fmc-adc.o
spec-fmc-adc-objs = fa-zio-drv.o
spec-fmc-adc-objs += fa-core.o
spec-fmc-adc-objs += fa-spec.o
spec-fmc-adc-objs += fa-zio-trg.o
spec-fmc-adc-objs += fa-dma.o
......
......@@ -13,45 +13,57 @@
#include "spec.h"
#include "fmc-adc.h"
int fa_probe(struct spec_dev *spec)
int fa_probe(struct fmc_device *fmc)
{
struct spec_fa *fa;
struct spec_dev *spec = fmc->carrier_data;
int err;
pr_info("%s:%d\n", __func__, __LINE__);
fa = kzalloc(sizeof(struct spec_fa), GFP_KERNEL);
/* Driver data */
fa = devm_kzalloc(&fmc->dev, sizeof(struct spec_fa), GFP_KERNEL);
if (!fa)
return -ENOMEM;
fmc_set_drvdata(fmc, fa);
spec->sub_priv = fa;
fa->spec = spec;
fa->fmc = fmc;
fa->base = spec->remap[0];
/* Initliaze sub-system (FIXME only ZIO at the moment) */
err = fa_zio_init(fa);
if (err) {
kfree(fa);
devm_kfree(&fmc->dev, fa);
return err;
}
return 0;
}
void fa_remove(struct spec_dev *dev)
int fa_remove(struct fmc_device *fmc)
{
fa_zio_exit(dev->sub_priv);
kfree(dev->sub_priv);
struct spec_fa *fa = fmc_get_drvdata(fmc);
fa_zio_exit(fa);
devm_kfree(&fmc->dev, fa);
return 0;
}
static struct fmc_driver fmc_adc__drv = {
.driver.name = KBUILD_MODNAME,
.probe = fa_probe,
.remove = fa_remove,
/* no table, as the current match just matches everything */
};
static int fa_init(void)
{
int ret;
pr_debug("%s\n",__func__);
ret = fa_zio_register();
if (ret < 0)
ret = fmc_driver_register(&fmc_adc__drv);
if (ret)
return ret;
ret = fa_spec_init();
if (ret < 0) {
fa_zio_unregister();
ret = fa_zio_register();
if (ret) {
fmc_driver_unregister(&fmc_adc__drv);
return ret;
}
return 0;
......@@ -59,8 +71,8 @@ static int fa_init(void)
static void fa_exit(void)
{
fa_spec_exit();
fa_zio_unregister();
fmc_driver_unregister(&fmc_adc__drv);
}
module_init(fa_init);
......
/*
* SPEC interface for the fmc-adc driver
*
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@gmail.com>
* Copied from fine-delay fd-spec.c
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/io.h>
#include "spec.h"
#include "fmc-adc.h"
static int fa_is_valid(int bus, int devfn)
{
/* FIXME: restrict to some of the spec devices with moduleparam */
pr_debug("%s: %x %x\n", __func__, bus, devfn);
return 1;
}
int fa_spec_init(void)
{
struct spec_dev *dev;
int ret, success = 0, retsave = 0, err = 0;
/* Scan the list and see what is there. Take hold of everything */
list_for_each_entry(dev, &spec_list, list) {
if (!fa_is_valid(dev->pdev->bus->number, dev->pdev->devfn))
continue;
pr_debug("%s: init %04x:%04x (%pR - %p)\n", __func__,
dev->pdev->bus->number, dev->pdev->devfn,
dev->area[0], dev->remap[0]);
ret = fa_probe(dev);
if (ret < 0) {
retsave = ret;
err++;
} else {
success++;
}
}
if (err) {
pr_err("%s: Setup of %i boards failed (%i succeeded)\n",
KBUILD_MODNAME, err, success);
pr_err("%s: last error: %i\n", KBUILD_MODNAME, retsave);
}
if (success) {
/* At least one board has been successfully initialized */
return 0;
}
return retsave; /* last error code */
}
void fa_spec_exit(void)
{
struct spec_dev *dev;
list_for_each_entry(dev, &spec_list, list) {
if (!fa_is_valid(dev->pdev->bus->number, dev->pdev->devfn))
continue;
pr_debug("%s: release %04x:%04x (%pR - %p)\n", __func__,
dev->pdev->bus->number, dev->pdev->devfn,
dev->area[0], dev->remap[0]);
fa_remove(dev);
}
}
......@@ -252,7 +252,6 @@ static int zfad_input_cset(struct zio_cset *cset)
static int zfad_zio_probe(struct zio_device *zdev)
{
struct spec_fa *fa = zdev->priv_d;
const struct zio_reg_desc *reg;
int i;
......@@ -342,16 +341,18 @@ void fa_zio_unregister(void)
/* Init and exit are called for each FMC-ADC card we have */
int fa_zio_init(struct spec_fa *fa)
{
struct pci_dev *pdev = fa->spec->pdev;
struct device *hwdev = fa->fmc->hwdev;
struct spec_dev *spec = fa->fmc->carrier_data;
struct pci_dev *pdev = spec->pdev;
uint32_t dev_id;
int err;
/* Check if hardware support 64-bit DMA */
if(dma_set_mask(&fa->spec->pdev->dev, DMA_BIT_MASK(64))) {
dev_err(&pdev->dev, "64-bit DMA addressing not available\n");
if(dma_set_mask(hwdev, DMA_BIT_MASK(64))) {
dev_err(hwdev, "64-bit DMA addressing not available\n");
return -EINVAL;
}
pr_info("%s:%d\n", __func__, __LINE__);
/* Allocate the hardware zio_device for registration */
fa->hwzdev = zio_allocate_device();
if (IS_ERR(fa->hwzdev))
......@@ -362,7 +363,6 @@ int fa_zio_init(struct spec_fa *fa)
fa->hwzdev->priv_d = fa;
/* Our dev_id is bus+devfn*/
pdev = fa->spec->pdev;
dev_id = (pdev->bus->number << 8) | pdev->devfn;
/* Register our trigger hardware */
......
......@@ -157,12 +157,14 @@ static const struct zio_sysfs_operations zfat_s_op = {
irqreturn_t zfadc_irq(int irq, void *ptr)
{
struct zfat_instance *zfat = ptr;
struct spec_fa *fa = zfat->fa;
uint32_t irq_status = 0, val;
zfa_common_info_get(&zfat->ti.cset->head.dev,
&zfad_regs[ZFA_IRQ_SRC],&irq_status);
dev_dbg(&zfat->ti.head.dev, "irq status = 0x%x\n", irq_status);
fa->fmc->op->irq_ack(fa->fmc);
if (irq_status & (ZFAT_DMA_DONE | ZFAT_DMA_ERR)) {
if (irq_status & ZFAT_DMA_DONE) { /* DMA done*/
zio_trigger_data_done(zfat->ti.cset);
......@@ -243,8 +245,7 @@ static struct zio_ti *zfat_create(struct zio_trigger_type *trig,
zfat->fa = fa;
err = request_irq(fa->spec->pdev->irq, zfadc_irq, IRQF_SHARED,
"wr-nic", zfat);
err = fa->fmc->op->irq_request(fa->fmc, zfadc_irq, "fmc-adc", 0);
if (err) {
dev_err(&fa->spec->pdev->dev, "can't request irq %i (err %i)\n",
fa->spec->pdev->irq, err);
......@@ -260,13 +261,17 @@ static struct zio_ti *zfat_create(struct zio_trigger_type *trig,
static void zfat_destroy(struct zio_ti *ti)
{
struct spec_fa *fa = ti->cset->zdev->priv_d;
struct zfat_instance *zfat = to_zfat_instance(ti);
/* Disable all interrupt */
zfa_common_conf_set(&ti->cset->head.dev, &zfad_regs[ZFA_IRQ_MASK],
ZFAT_NONE);
kfree(to_zfat_instance(ti));
fa->fmc->op->irq_free(fa->fmc);
kfree(zfat);
}
/* status is active low on ZIO but active high on the FMC-ADC */
/* status is active low on ZIO but active high on the FMC-ADC, then use ! */
static void zfat_change_status(struct zio_ti *ti, unsigned int status)
{
/* Enable/Disable HW trigger */
......
......@@ -15,16 +15,23 @@
#define FA_UTC_MEM_OFF 0x40000
#define FA_IRQ_MEM_OFF 0x50000
#define FA_ADC_MEM_OFF 0x90000
#define FA_OWI_MEM_OFF 0XA0000 /* one-wire */
/* ADC DDR memory */
#define FA_MAX_ACQ_BYTE 0x10000000 /* 256MB */
struct spec_fa {
struct fmc_device *fmc;
struct spec_dev *spec;
struct zio_device *hwzdev;
struct sg_table sgt; /* scatter/gather table */
unsigned char __iomem *base; /* regs files are byte-oriented */
/* one-wire */
uint8_t ds18_id[8];
unsigned long next_t;
int temp; /* temperature: scaled by 4 bits */
};
/* The information about a DMA transfer */
......@@ -255,18 +262,16 @@ static inline void zfa_common_info_get(struct device *dev,
/* Read current register*/
cur = fa_read_reg(get_zfadc(dev), reg);
/* Mask the value */
cur &= (reg->mask << reg->off);
cur &= (reg->mask << reg->shift);
/* Return the value */
*usr_val = cur >> reg->off;
*usr_val = cur >> reg->shift;
}
extern struct zio_trigger_type zfat_type;
/* Registers lists used in fd-zio-drv.c and fd-zio-trg.c */
extern const struct zio_reg_desc zfad_regs[];
/* Functions exported by fd-core.c */
extern int fa_probe(struct spec_dev *dev);
extern void fa_remove(struct spec_dev *dev);
/* Functions exported by fa-zio.c */
extern int fa_zio_register(void);
extern void fa_zio_unregister(void);
......@@ -276,6 +281,9 @@ extern void fa_zio_exit(struct spec_fa *fa);
/* Functions exported by fa-spec.c */
extern int fa_spec_init(void);
extern void fa_spec_exit(void);
/* Functions exported by onewire.c */
extern int fa_onewire_init(struct spec_fa *fa);
extern void fa_onewire_exit(struct spec_fa *fa);
#endif /* __KERNEL__ */
#endif /* _FMC_ADC_H_ */
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