Commit 9e3eba72 authored by Federico Vaga's avatar Federico Vaga

kernel: replace FMC with PLATFORM

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 64ff2335
[submodule "zio"] [submodule "zio"]
path = zio path = zio
url = git://ohwr.org/misc/zio.git url = git://ohwr.org/misc/zio.git
[submodule "fmc-bus"]
path = fmc-bus
url = git://ohwr.org/fmc-projects/fmc-bus.git
[submodule "spec-sw"] [submodule "spec-sw"]
path = spec-sw path = spec-sw
url = git://ohwr.org/fmc-projects/spec/spec-sw.git url = git://ohwr.org/fmc-projects/spec/spec-sw.git
...@@ -10,17 +10,14 @@ CONFIG_WR_NIC=n ...@@ -10,17 +10,14 @@ CONFIG_WR_NIC=n
export CONFIG_WR_NIC export CONFIG_WR_NIC
# The user can override, using environment variables, all these three: # The user can override, using environment variables, all these three:
FMC_BUS ?= $(shell pwd)/fmc-bus
ZIO ?= $(shell pwd)/zio ZIO ?= $(shell pwd)/zio
SPEC_SW ?= $(shell pwd)/spec-sw SPEC_SW ?= $(shell pwd)/spec-sw
# FMC_BUS_ABS, ZIO_ABS and SPEC_SW_ABS has to be absolut path, due to beeing # ZIO_ABS and SPEC_SW_ABS has to be absolut path, due to beeing
# passed to the Kbuild # passed to the Kbuild
FMC_BUS_ABS ?= $(abspath $(FMC_BUS) )
ZIO_ABS ?= $(abspath $(ZIO) ) ZIO_ABS ?= $(abspath $(ZIO) )
SPEC_SW_ABS ?= $(abspath $(SPEC_SW) ) SPEC_SW_ABS ?= $(abspath $(SPEC_SW) )
export FMC_BUS_ABS
export ZIO_ABS export ZIO_ABS
export SPEC_SW_ABS export SPEC_SW_ABS
...@@ -28,10 +25,10 @@ ZIO_VERSION = $(shell cd $(ZIO_ABS); git describe --always --dirty --long --tags ...@@ -28,10 +25,10 @@ ZIO_VERSION = $(shell cd $(ZIO_ABS); git describe --always --dirty --long --tags
export ZIO_VERSION export ZIO_VERSION
DIRS = $(FMC_BUS_ABS) $(ZIO_ABS) $(SPEC_SW_ABS) kernel lib tools DIRS = $(ZIO_ABS) $(SPEC_SW_ABS) kernel lib tools
$(SPEC_SW_ABS): $(FMC_BUS_ABS) $(SPEC_SW_ABS):
kernel: $(FMC_BUS_ABS) $(ZIO_ABS) $(SPEC_SW_ABS) kernel: $(ZIO_ABS) $(SPEC_SW_ABS)
lib: $(ZIO_ABS) lib: $(ZIO_ABS)
tools: lib tools: lib
...@@ -52,7 +49,7 @@ $(DIRS): ...@@ -52,7 +49,7 @@ $(DIRS):
$(MAKE) -C $@ $(TARGET) $(MAKE) -C $@ $(TARGET)
SUBMOD = $(FMC_BUS_ABS) $(ZIO_ABS) $(SPEC_SW_ABS) SUBMOD = $(ZIO_ABS) $(SPEC_SW_ABS)
prereq_install_warn: prereq_install_warn:
@test -f .prereq_installed || \ @test -f .prereq_installed || \
...@@ -62,14 +59,9 @@ prereq_install: ...@@ -62,14 +59,9 @@ prereq_install:
for d in $(SUBMOD); do $(MAKE) -C $$d modules_install || exit 1; done for d in $(SUBMOD); do $(MAKE) -C $$d modules_install || exit 1; done
touch .prereq_installed touch .prereq_installed
$(FMC_BUS_ABS): fmc-bus-init_repo
$(ZIO_ABS): zio-init_repo $(ZIO_ABS): zio-init_repo
$(SPEC_SW_ABS): spec-sw-init_repo $(SPEC_SW_ABS): spec-sw-init_repo
# init submodule if missing
fmc-bus-init_repo:
@test -d $(FMC_BUS_ABS)/doc || ( echo "Checking out submodule $(FMC_BUS_ABS)"; git submodule update --init $(FMC_BUS_ABS) )
# init submodule if missing # init submodule if missing
zio-init_repo: zio-init_repo:
@test -d $(ZIO_ABS)/doc || ( echo "Checking out submodule $(ZIO_ABS)" && git submodule update --init $(ZIO_ABS) ) @test -d $(ZIO_ABS)/doc || ( echo "Checking out submodule $(ZIO_ABS)" && git submodule update --init $(ZIO_ABS) )
......
fmc-bus @ acb6fd69
Subproject commit acb6fd69c5b88ac3ad4face89a9feed415ba9c19
# FMC_BUS, ZIO, SPEC_SW comes from the Makefile # ZIO, SPEC_SW comes from the Makefile
KBUILD_EXTRA_SYMBOLS := \ KBUILD_EXTRA_SYMBOLS := \
$(ZIO_ABS)/Module.symvers \ $(ZIO_ABS)/Module.symvers \
$(SPEC_SW_ABS)/kernel/Module.symvers \ $(SPEC_SW_ABS)/kernel/Module.symvers
$(FMC_BUS_ABS)/kernel/Module.symvers
# The library includes <sdb.h>, so point -I directtly there
# include our header before to avoid conflicts with the kernel
LINUXINCLUDE := -I$(FMC_BUS_ABS)/kernel/include -I$(FMC_BUS_ABS)/kernel/include/linux $(LINUXINCLUDE)
ccflags-y = -DGIT_VERSION=\"$(GIT_VERSION)\" \ ccflags-y = -DGIT_VERSION=\"$(GIT_VERSION)\" \
-I$(src) \ -I$(src) \
-I$(ZIO_ABS)/include \ -I$(ZIO_ABS)/include \
-I$(FMC_BUS_ABS)/sdb-lib/ \
-I$(SPEC_SW_ABS)/kernel -I$(SPEC_SW_ABS)/kernel
ccflags-$(CONFIG_FMC_TDC_DEBUG) += -DDEBUG ccflags-$(CONFIG_FMC_TDC_DEBUG) += -DDEBUG
...@@ -30,7 +24,6 @@ SUBMODULE_VERSIONS += MODULE_INFO(version_$(CONFIG_SUPER_REPO),\"$(CONFIG_SUPER_ ...@@ -30,7 +24,6 @@ SUBMODULE_VERSIONS += MODULE_INFO(version_$(CONFIG_SUPER_REPO),\"$(CONFIG_SUPER_
endif endif
endif endif
# add versions of used submodules # add versions of used submodules
SUBMODULE_VERSIONS += MODULE_INFO(version_fmc_bus,\"$(FMC_BUS_VERSION)\");
SUBMODULE_VERSIONS += MODULE_INFO(version_zio,\"$(ZIO_VERSION)\"); SUBMODULE_VERSIONS += MODULE_INFO(version_zio,\"$(ZIO_VERSION)\");
SUBMODULE_VERSIONS += MODULE_INFO(version_spec_sw,\"$(SPEC_SW_VERSION)\"); SUBMODULE_VERSIONS += MODULE_INFO(version_spec_sw,\"$(SPEC_SW_VERSION)\");
...@@ -39,6 +32,5 @@ ccflags-y += -DADDITIONAL_VERSIONS="$(SUBMODULE_VERSIONS)" ...@@ -39,6 +32,5 @@ ccflags-y += -DADDITIONAL_VERSIONS="$(SUBMODULE_VERSIONS)"
subdirs-ccflags-y = $(ccflags-y) subdirs-ccflags-y = $(ccflags-y)
obj-m := fmc-tdc.o obj-m := fmc-tdc.o
fmc-tdc-objs = acam.o calibration.o fmc-util.o \ fmc-tdc-objs = acam.o calibration.o \
ft-core.o onewire.o ft-time.o ft-irq.o ft-zio.o\ ft-core.o onewire.o ft-time.o ft-irq.o ft-zio.o
fmc-bus-link/sdb-lib/access.o fmc-bus-link/sdb-lib/glue.o
...@@ -5,34 +5,27 @@ REPO_PARENT ?= $(shell /bin/pwd)/../.. ...@@ -5,34 +5,27 @@ REPO_PARENT ?= $(shell /bin/pwd)/../..
LINUX ?= /lib/modules/$(shell uname -r)/build LINUX ?= /lib/modules/$(shell uname -r)/build
FMC_BUS ?= ../fmc-bus
ZIO ?= ../zio ZIO ?= ../zio
SPEC_SW ?= ../spec-sw SPEC_SW ?= ../spec-sw
# FMC_BUS_ABS, ZIO_ABS and SPEC_SW_ABS has to be absolut path, due to beeing # ZIO_ABS and SPEC_SW_ABS has to be absolut path, due to beeing
# passed to the Kbuild # passed to the Kbuild
FMC_BUS_ABS ?= $(abspath $(FMC_BUS) )
ZIO_ABS ?= $(abspath $(ZIO) ) ZIO_ABS ?= $(abspath $(ZIO) )
SPEC_SW_ABS ?= $(abspath $(SPEC_SW) ) SPEC_SW_ABS ?= $(abspath $(SPEC_SW) )
GIT_VERSION = $(shell git describe --always --dirty --long --tags) GIT_VERSION = $(shell git describe --always --dirty --long --tags)
export GIT_VERSION export GIT_VERSION
FMC_BUS_VERSION ?= $(shell cd $(FMC_BUS_ABS); git describe --always --dirty --long --tags)
ZIO_VERSION ?= $(shell cd $(ZIO_ABS); git describe --always --dirty --long --tags) ZIO_VERSION ?= $(shell cd $(ZIO_ABS); git describe --always --dirty --long --tags)
SPEC_SW_VERSION ?= $(shell cd $(SPEC_SW_ABS); git describe --always --dirty --long --tags) SPEC_SW_VERSION ?= $(shell cd $(SPEC_SW_ABS); git describe --always --dirty --long --tags)
export FMC_BUS_VERSION
export ZIO_VERSION export ZIO_VERSION
export SPEC_SW_VERSION export SPEC_SW_VERSION
all: modules all: modules
modules_install modules: modules_install modules:
rm -f fmc-bus-link $(MAKE) -C $(LINUX) M=$(shell /bin/pwd) ZIO_ABS=$(ZIO_ABS) SPEC_SW_ABS=$(SPEC_SW_ABS) $@
ln -s $(FMC_BUS_ABS) fmc-bus-link
$(MAKE) -C $(LINUX) M=$(shell /bin/pwd) FMC_BUS_ABS=$(FMC_BUS_ABS) ZIO_ABS=$(ZIO_ABS) SPEC_SW_ABS=$(SPEC_SW_ABS) $@
rm -f fmc-bus-link
clean: clean:
$(MAKE) -C $(LINUX) M=$(shell /bin/pwd) $@ $(MAKE) -C $(LINUX) M=$(shell /bin/pwd) $@
...@@ -64,7 +64,7 @@ int ft_acam_init(struct fmctdc_dev *ft) ...@@ -64,7 +64,7 @@ int ft_acam_init(struct fmctdc_dev *ft)
int i; int i;
unsigned long tmo; unsigned long tmo;
dev_dbg(&ft->fmc->dev, "%s: initializing ACAM TDC...\n", __func__); dev_dbg(&ft->pdev->dev, "%s: initializing ACAM TDC...\n", __func__);
ft_writel(ft, TDC_CTRL_RESET_ACAM, TDC_REG_CTRL); ft_writel(ft, TDC_CTRL_RESET_ACAM, TDC_REG_CTRL);
...@@ -87,13 +87,13 @@ int ft_acam_init(struct fmctdc_dev *ft) ...@@ -87,13 +87,13 @@ int ft_acam_init(struct fmctdc_dev *ft)
tmo = jiffies + 2 * HZ; tmo = jiffies + 2 * HZ;
while (time_before(jiffies, tmo)) { while (time_before(jiffies, tmo)) {
if (acam_is_pll_locked(ft)) { if (acam_is_pll_locked(ft)) {
dev_dbg(&ft->fmc->dev, "%s: ACAM initialization OK.\n", dev_dbg(&ft->pdev->dev, "%s: ACAM initialization OK.\n",
__func__); __func__);
return 0; return 0;
} }
} }
dev_err(&ft->fmc->dev, "%s: ACAM PLL doesn't lock\n", __func__); dev_err(&ft->pdev->dev, "%s: ACAM PLL doesn't lock\n", __func__);
return -EIO; return -EIO;
} }
......
...@@ -26,6 +26,12 @@ ...@@ -26,6 +26,12 @@
#define FT_CH_1 1 #define FT_CH_1 1
#define FT_NUM_CHANNELS 5 #define FT_NUM_CHANNELS 5
enum mock_turtle_versions {
TDC_VER_SPEC = 0,
TDC_VER_SVEC,
};
enum ft_zattr_dev_idx { enum ft_zattr_dev_idx {
FT_ATTR_DEV_VERSION = 0, FT_ATTR_DEV_VERSION = 0,
FT_ATTR_DEV_SECONDS, FT_ATTR_DEV_SECONDS,
...@@ -69,8 +75,28 @@ enum ft_command { ...@@ -69,8 +75,28 @@ enum ft_command {
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/fmc.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/platform_device.h>
struct ft_memory_ops {
u32 (*read)(void *addr);
void (*write)(u32 value, void *addr);
};
extern struct ft_memory_ops memops;
enum mockturtle_irq_resource {
TDC_IRQ = 0,
};
enum mockturtle_mem_resource {
TDC_MEM_BASE = 0,
TDC_CARR_MEM_BASE,
};
enum mockturtle_bus_resource {
TDC_BUS_FMC_SLOT = 0,
};
#define FT_USER_OFFSET_RANGE 1000000000 /* picoseconds */ #define FT_USER_OFFSET_RANGE 1000000000 /* picoseconds */
...@@ -136,13 +162,15 @@ struct fmctdc_dev { ...@@ -136,13 +162,15 @@ struct fmctdc_dev {
/* HW buffer/FIFO access lock */ /* HW buffer/FIFO access lock */
spinlock_t lock; spinlock_t lock;
/* base addresses, taken from SDB */ /* base addresses, taken from SDB */
int ft_core_base; void *ft_carrier_base;
int ft_i2c_base; void *ft_base;
int ft_owregs_base; void *ft_core_base;
int ft_irq_base; void *ft_i2c_base;
int ft_buffer_base; void *ft_owregs_base;
void *ft_irq_base;
void *ft_buffer_base;
/* IRQ base index (for SVEC) */ /* IRQ base index (for SVEC) */
struct fmc_device *fmc; struct platform_device *pdev;
struct zio_device *zdev, *hwzdev; struct zio_device *zdev, *hwzdev;
/* carrier private data */ /* carrier private data */
void *carrier_data; void *carrier_data;
...@@ -164,15 +192,15 @@ struct fmctdc_dev { ...@@ -164,15 +192,15 @@ struct fmctdc_dev {
uint64_t sequence; /**< Board time-stamp sequence number */ uint64_t sequence; /**< Board time-stamp sequence number */
}; };
static inline u32 ft_ioread(struct fmctdc_dev *ft, unsigned long addr) static inline u32 ft_ioread(struct fmctdc_dev *ft, void *addr)
{ {
return fmc_readl(ft->fmc, addr); return memops.read(addr);
} }
static inline void ft_iowrite(struct fmctdc_dev *ft, static inline void ft_iowrite(struct fmctdc_dev *ft,
u32 value, unsigned long addr) u32 value, void *addr)
{ {
fmc_writel(ft->fmc, value, addr); memops.write(value, addr);
} }
static inline uint32_t ft_readl(struct fmctdc_dev *ft, unsigned long reg) static inline uint32_t ft_readl(struct fmctdc_dev *ft, unsigned long reg)
...@@ -232,10 +260,6 @@ struct zio_channel; ...@@ -232,10 +260,6 @@ struct zio_channel;
int ft_enable_termination(struct fmctdc_dev *ft, int channel, int enable); int ft_enable_termination(struct fmctdc_dev *ft, int channel, int enable);
signed long fmc_sdb_find_nth_device (struct sdb_array *tree, uint64_t vid,
uint32_t did, int *ordinal,
uint32_t *size );
#endif // __KERNEL__ #endif // __KERNEL__
#endif // __FMC_TDC_H__ #endif // __FMC_TDC_H__
/*
* Some utility functions not supported in the current version of fmc-bus.
*
* Copyright (C) 2012-2014 CERN (www.cern.ch)
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/
#include <linux/fmc.h>
#include <linux/fmc-sdb.h>
#include <linux/err.h>
#include <asm/byteorder.h>
#include "fmc-tdc.h"
typedef int (*sdb_traverse_cb) (uint32_t address, uint32_t size, uint64_t vid, uint32_t did, void *data);
static int traverse_sdb_devices(struct sdb_array *tree,
sdb_traverse_cb cb,
void *data)
{
union sdb_record *r;
struct sdb_product *p;
struct sdb_component *c;
int i, n = tree->len, rv;
uint64_t last, first, vid;
uint32_t did, size;
/* FIXME: what if the first interconnect is not at zero? */
for (i = 0; i < n; i++) {
r = &tree->record[i];
c = &r->dev.sdb_component;
p = &c->product;
if (!IS_ERR(tree->subtree[i]))
{
rv = traverse_sdb_devices ( tree->subtree[i], cb, data );
if(rv > 0)
return 1;
}
if (r->empty.record_type != sdb_type_device)
continue;
/* record is a device?*/
last = __be64_to_cpu(c->addr_last);
first = __be64_to_cpu(c->addr_first);
vid = __be64_to_cpu(p->vendor_id);
did = __be32_to_cpu(p->device_id);
size = (uint32_t) (last + 1 - first);
if (cb (first + tree->baseaddr, size, vid, did, data))
return 1;
}
return 0;
}
struct callback_state {
int n;
int *ordinal;
uint32_t current_address;
uint32_t current_size;
uint64_t did;
uint32_t vid;
};
static int callback (uint32_t address, uint32_t size, uint64_t vid_, uint32_t did_, void *data)
{
struct callback_state *st = (struct callback_state *) data;
if(vid_ == st->vid && did_ == st->did)
{
st->n++;
st->current_address = address;
st->current_size = size;
if(!st->ordinal || st->n == *st->ordinal)
{
return 1;
}
}
return 0; /* continue scanning */
}
/* Finds the Nth SDB device that matches (vid/did) pair, where N <= *ordinal.
If N < *ordinal, the value of N is stored at *ordinal.
This magic is used to handle hybrid bistreams (with two or more different
mezzanines). */
signed long fmc_sdb_find_nth_device (struct sdb_array *tree, uint64_t vid, uint32_t did, int *ordinal, uint32_t *size )
{
struct callback_state st;
st.n = -1;
st.ordinal = ordinal;
st.vid = vid;
st.did = did;
traverse_sdb_devices (tree, callback, &st);
if (st.n >= 0)
{
if(size)
*size = st.current_size;
if(ordinal)
*ordinal = st.n;
return st.current_address;
}
return -ENODEV;
}
...@@ -22,9 +22,7 @@ ...@@ -22,9 +22,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/fmc.h>
#include <linux/fmc-sdb.h>
#include <linux/zio.h> #include <linux/zio.h>
#include <linux/zio-trigger.h> #include <linux/zio-trigger.h>
...@@ -37,33 +35,41 @@ static int ft_verbose; ...@@ -37,33 +35,41 @@ static int ft_verbose;
module_param_named(verbose, ft_verbose, int, 0444); module_param_named(verbose, ft_verbose, int, 0444);
MODULE_PARM_DESC(verbose, "Print a lot of debugging messages."); MODULE_PARM_DESC(verbose, "Print a lot of debugging messages.");
static struct fmc_driver ft_drv; /* forward declaration */ struct ft_memory_ops memops = {
FMC_PARAM_BUSID(ft_drv); .read = NULL,
FMC_PARAM_GATEWARE(ft_drv); .write = NULL,
};
static char bitstream_name[32];
static int ft_reset_core(struct fmctdc_dev *ft) static int ft_reset_core(struct fmctdc_dev *ft)
{ {
uint32_t val, shift = 0, addr; struct resource *r;
uint32_t val, shift = 0;
if (!strcmp(ft->fmc->carrier_name, "SVEC")) { void *addr;
shift = 1;
addr = TDC_SVEC_CARRIER_BASE; addr = ft->ft_carrier_base + TDC_REG_CARRIER_RST;
} else { switch (ft->pdev->id_entry->driver_data) {
addr = TDC_SPEC_CARRIER_BASE; case TDC_VER_SPEC:
shift = -1;
break;
default:
break;
} }
addr += TDC_REG_CARRIER_RST;
dev_dbg(&ft->fmc->dev, "Un-resetting FMCs...\n"); dev_dbg(&ft->pdev->dev, "Un-resetting FMCs...\n");
/* FMC slot counting starts from 1 */
r = platform_get_resource(ft->pdev, IORESOURCE_BUS, TDC_BUS_FMC_SLOT);
/* Reset - reset bits are shifted by 1 */ /* Reset - reset bits are shifted by 1 */
ft_iowrite(ft, ~(1 << (ft->fmc->slot_id + shift)), addr); /* FIXME pdev->id is not correct because we mayhave different TDCs
in slot 0 on different carriers */
ft_iowrite(ft, ~(1 << (r->start + shift)), addr);
udelay(5000); udelay(5000);
val = ft_ioread(ft, addr); val = ft_ioread(ft, addr);
val |= (1 << (ft->fmc->slot_id + shift)); val |= (1 << (r->start + shift));
/* Un-Reset */ /* Un-Reset */
ft_iowrite(ft, val, addr); ft_iowrite(ft, val, addr);
...@@ -162,101 +168,104 @@ static struct ft_modlist init_subsystems[] = { ...@@ -162,101 +168,104 @@ static struct ft_modlist init_subsystems[] = {
{"zio", ft_zio_init, ft_zio_exit} {"zio", ft_zio_init, ft_zio_exit}
}; };
/* probe and remove are called by the FMC bus core */ static int ft_resource_validation(struct platform_device *pdev)
int ft_probe(struct fmc_device *fmc)
{ {
struct ft_modlist *m; struct resource *r;
struct fmctdc_dev *ft;
struct device *dev = &fmc->dev;
char *fwname;
int i, index, ret, ord;
ft = kzalloc(sizeof(struct fmctdc_dev), GFP_KERNEL); r = platform_get_resource(pdev, IORESOURCE_IRQ, TDC_IRQ);
if (!ft) { if (!r) {
dev_err(dev, "can't allocate device\n"); dev_err(&pdev->dev,
return -ENOMEM; "The TDC needs an interrupt number\n");
return -ENXIO;
} }
index = fmc_validate(fmc, &ft_drv); r = platform_get_resource(pdev, IORESOURCE_MEM, TDC_MEM_BASE);
if (index < 0) { if (!r) {
dev_info(dev, "not using \"%s\" according to modparam\n", dev_err(&pdev->dev,
KBUILD_MODNAME); "The TDC needs base address\n");
return -ENODEV; return -ENXIO;
} }
fmc->mezzanine_data = ft; r = platform_get_resource(pdev, IORESOURCE_MEM, TDC_CARR_MEM_BASE);
ft->fmc = fmc; if (!r) {
ft->verbose = ft_verbose; dev_err(&pdev->dev,
"The TDC needs the carrier base address\n");
/* apply carrier-specific hacks and workarounds */ return -ENXIO;
if (!strcmp(ft->fmc->carrier_name, "SVEC")) {
sprintf(bitstream_name, FT_GATEWARE_SVEC);
} else if (!strcmp(fmc->carrier_name, "SPEC")) {
sprintf(bitstream_name, FT_GATEWARE_SPEC);
} else {
dev_err(dev, "unsupported carrier '%s'\n", fmc->carrier_name);
return -ENODEV;
} }
/* r = platform_get_resource(pdev, IORESOURCE_BUS, TDC_BUS_FMC_SLOT);
* If the carrier is still using the golden bitstream or the user is if (!r) {
* asking for a particular one, then program our bistream, otherwise dev_err(&pdev->dev,
* we already have our bitstream "The TDC needs to be assigned to an FMC slot\n");
*/ return -ENXIO;
if (fmc->flags & FMC_DEVICE_HAS_GOLDEN || ft_drv.gw_n) {
if (ft_drv.gw_n)
fwname = ""; /* reprogram will pick from module parameter */
else
fwname = bitstream_name;
dev_info(fmc->hwdev, "Gateware (%s)\n", fwname);
ret = fmc_reprogram(fmc, &ft_drv, fwname, -1);
if (ret < 0) {
dev_err(fmc->hwdev, "write firmware \"%s\": error %i\n",
fwname, ret);
if (ret == -ESRCH) {
dev_err(dev, "no gateware at index %i\n",
index);
return -ENODEV;
}
return ret; /* other error: pass over */
}
dev_dbg(dev, "Gateware successfully loaded\n");
} else {
dev_info(fmc->hwdev,
"Gateware already there. Set the \"gateware\" parameter to overwrite the current gateware\n");
} }
ret = ft_reset_core(ft); return 0;
if (ret < 0) }
return ret;
/* Now that the PLL is locked, we can read the SDB info */ /**
ret = fmc_scan_sdb_tree(fmc, 0); * probe and remove are called by the FMC bus core
if (ret < 0 && ret != -EBUSY) { */
dev_err(dev, int ft_probe(struct platform_device *pdev)
"%s: no SDB in the bitstream. Are you sure you've provided the correct one?\n", {
KBUILD_MODNAME); struct ft_modlist *m;
return ret; struct fmctdc_dev *ft;
struct device *dev = &pdev->dev;
struct resource *r;
int i, ret, err;
err = ft_resource_validation(pdev);
if (err)
return err;
/* Assign IO operation */
switch (pdev->id_entry->driver_data) {
case TDC_VER_SPEC:
memops.read = ioread32;
memops.write = iowrite32;
break;
case TDC_VER_SVEC:
memops.read = ioread32be;
memops.write = iowrite32be;
break;
default:
dev_err(&pdev->dev, "Unknow version %lu\n",
pdev->id_entry->driver_data);
return -EINVAL;
} }
/* Now use SDB to find the base addresses */ ft = kzalloc(sizeof(struct fmctdc_dev), GFP_KERNEL);
ord = fmc->slot_id; if (!ft) {
ft->ft_core_base = fmc_sdb_find_nth_device(fmc->sdb, 0xce42, 0x604, dev_err(dev, "can't allocate device\n");
&ord, NULL); return -ENOMEM;
}
platform_set_drvdata(pdev, ft);
ft->pdev = pdev;
ft->ft_irq_base = ft->ft_core_base + TDC_MEZZ_EIC_OFFSET; ft->verbose = ft_verbose;
ft->ft_owregs_base = ft->ft_core_base + TDC_MEZZ_ONEWIRE_OFFSET;
ft->ft_buffer_base = ft->ft_core_base + TDC_MEZZ_MEM_OFFSET; /* Now use SDB to find the base addresses */
r = platform_get_resource(pdev, IORESOURCE_MEM, TDC_CARR_MEM_BASE);
ft->ft_carrier_base = ioremap(r->start, resource_size(r));
r = platform_get_resource(pdev, IORESOURCE_MEM, TDC_MEM_BASE);
ft->ft_base = ioremap(r->start, resource_size(r));
ft->ft_core_base = ft->ft_base + TDC_MEZZ_CORE_OFFSET;
ft->ft_irq_base = ft->ft_base + TDC_MEZZ_EIC_OFFSET;
ft->ft_owregs_base = ft->ft_base + TDC_MEZZ_ONEWIRE_OFFSET;
ft->ft_buffer_base = ft->ft_base + TDC_MEZZ_MEM_OFFSET;
if (ft_verbose) { if (ft_verbose) {
dev_info(dev, dev_info(dev,
"Base addrs: core 0x%x, irq 0x%x, 1wire 0x%x, buffer/DMA 0x%X\n", "Base addrs: carr %p, core %p, irq %p, 1wire %p, buffer/DMA %p\n",
ft->ft_carrier_base,
ft->ft_core_base, ft->ft_irq_base, ft->ft_core_base, ft->ft_irq_base,
ft->ft_owregs_base, ft->ft_buffer_base); ft->ft_owregs_base, ft->ft_buffer_base);
} }
ret = ft_reset_core(ft);
if (ret < 0)
return ret;
spin_lock_init(&ft->lock); spin_lock_init(&ft->lock);
/* Retrieve calibration from the eeprom, and validate */ /* Retrieve calibration from the eeprom, and validate */
...@@ -284,15 +293,8 @@ int ft_probe(struct fmc_device *fmc) ...@@ -284,15 +293,8 @@ int ft_probe(struct fmc_device *fmc)
ft->initialized = 1; ft->initialized = 1;
ft->sequence = 0; ft->sequence = 0;
/* Pin the carrier */
if (!try_module_get(fmc->owner))
goto out_mod;
return 0; return 0;
out_mod:
device_remove_bin_file(&ft->pdev->dev, &dev_attr_eeprom);
ft_enable_acquisition(ft, 0);
err_bin: err_bin:
ft_irq_exit(ft); ft_irq_exit(ft);
err: err:
...@@ -302,10 +304,10 @@ err: ...@@ -302,10 +304,10 @@ err:
return ret; return ret;
} }
int ft_remove(struct fmc_device *fmc) int ft_remove(struct platform_device *pdev)
{ {
struct ft_modlist *m; struct ft_modlist *m;
struct fmctdc_dev *ft = fmc->mezzanine_data; struct fmctdc_dev *ft = platform_get_drvdata(pdev);
int i = ARRAY_SIZE(init_subsystems); int i = ARRAY_SIZE(init_subsystems);
...@@ -322,27 +324,29 @@ int ft_remove(struct fmc_device *fmc) ...@@ -322,27 +324,29 @@ int ft_remove(struct fmc_device *fmc)
m->exit(ft); m->exit(ft);
} }
/* Release the carrier */
module_put(fmc->owner);
return 0; return 0;
} }
static struct fmc_fru_id ft_fru_id[] = {
static const struct platform_device_id ft_id[] = {
{ {
.product_name = "FmcTdc1ns5cha", .name = "fmc-tdc-spec",
}, .driver_data = TDC_VER_SPEC,
}, {
.name = "fmc-tdc-svec",
.driver_data = TDC_VER_SVEC,
},
/* TODO we should support different version */
}; };
static struct fmc_driver ft_drv = { static struct platform_driver ft_platform_driver = {
.version = FMC_VERSION, .driver = {
.driver.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
},
.probe = ft_probe, .probe = ft_probe,
.remove = ft_remove, .remove = ft_remove,
.id_table = { .id_table = ft_id,
.fru_id = ft_fru_id,
.fru_id_nr = ARRAY_SIZE(ft_fru_id),
},
}; };
static int ft_init(void) static int ft_init(void)
...@@ -353,7 +357,7 @@ static int ft_init(void) ...@@ -353,7 +357,7 @@ static int ft_init(void)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = fmc_driver_register(&ft_drv); ret = platform_driver_register(&ft_platform_driver);
if (ret < 0) { if (ret < 0) {
ft_zio_unregister(); ft_zio_unregister();
return ret; return ret;
...@@ -363,7 +367,7 @@ static int ft_init(void) ...@@ -363,7 +367,7 @@ static int ft_init(void)
static void ft_exit(void) static void ft_exit(void)
{ {
fmc_driver_unregister(&ft_drv); platform_driver_unregister(&ft_platform_driver);
ft_zio_unregister(); ft_zio_unregister();
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kfifo.h> #include <linux/kfifo.h>
#include <linux/interrupt.h>
#include <linux/zio.h> #include <linux/zio.h>
#include <linux/zio-trigger.h> #include <linux/zio-trigger.h>
...@@ -41,7 +42,7 @@ static void ft_read_sw_fifo(struct zio_cset *cset, struct ft_wr_timestamp *wrts) ...@@ -41,7 +42,7 @@ static void ft_read_sw_fifo(struct zio_cset *cset, struct ft_wr_timestamp *wrts)
struct ft_wr_timestamp ts = *wrts, *reflast; struct ft_wr_timestamp ts = *wrts, *reflast;
struct ft_channel_state *st; struct ft_channel_state *st;
dev_dbg(&ft->fmc->dev, dev_dbg(&ft->pdev->dev,
"Set in ZIO block ch %d: hseq %u: dseq %u: gseq %llu %llu %u %u\n", "Set in ZIO block ch %d: hseq %u: dseq %u: gseq %llu %llu %u %u\n",
ts.channel, ts.hseq_id, ts.dseq_id, ts.gseq_id, ts.channel, ts.hseq_id, ts.dseq_id, ts.gseq_id,
ts.seconds, ts.coarse, ts.frac); ts.seconds, ts.coarse, ts.frac);
...@@ -118,12 +119,12 @@ static inline int process_timestamp(struct zio_cset *cset, ...@@ -118,12 +119,12 @@ static inline int process_timestamp(struct zio_cset *cset,
st = &ft->channels[cset->index]; st = &ft->channels[cset->index];
dev_vdbg(&ft->fmc->dev, "process TS(%p): 0x%x 0x%x 0x%x 0x%x\n", dev_vdbg(&ft->pdev->dev, "process TS(%p): 0x%x 0x%x 0x%x 0x%x\n",
hwts, hwts->metadata, hwts->utc, hwts->coarse, hwts->bins); hwts, hwts->metadata, hwts->utc, hwts->coarse, hwts->bins);
channel = (hwts->metadata & 0x7); channel = (hwts->metadata & 0x7);
/* channel from 1 to 5, cset is from 0 to 4 */ /* channel from 1 to 5, cset is from 0 to 4 */
if (channel != cset->index) { if (channel != cset->index) {
dev_err(&ft->fmc->dev, dev_err(&ft->pdev->dev,
"reading from the wrong channel (expected %d, given %d)\n", "reading from the wrong channel (expected %d, given %d)\n",
channel, cset->index); channel, cset->index);
return 0; return 0;
...@@ -223,15 +224,13 @@ static int ft_timestap_get(struct zio_cset *cset, struct ft_hw_timestamp *hwts, ...@@ -223,15 +224,13 @@ static int ft_timestap_get(struct zio_cset *cset, struct ft_hw_timestamp *hwts,
unsigned int last) unsigned int last)
{ {
struct fmctdc_dev *ft = cset->zdev->priv_d; struct fmctdc_dev *ft = cset->zdev->priv_d;
uint32_t fifo_addr = ft->ft_buffer_base + TDC_FIFO_OFFSET * cset->index; void *fifo_addr = ft->ft_buffer_base + TDC_FIFO_OFFSET * cset->index;
uint32_t data[TDC_FIFO_OUT_N]; uint32_t data[TDC_FIFO_OUT_N];
int i, valid = 1; int i, valid = 1;
fifo_addr += last ? TDC_FIFO_LAST : TDC_FIFO_OUT; fifo_addr += last ? TDC_FIFO_LAST : TDC_FIFO_OUT;
for (i = 0; i < TDC_FIFO_OUT_N; ++i) { for (i = 0; i < TDC_FIFO_OUT_N; ++i) {
data[i] = ft_ioread(ft, fifo_addr + i * 4); data[i] = ft_ioread(ft, fifo_addr + i * 4);
dev_vdbg(&cset->head.dev, "FIFO read 0x%x from 0x%x\n",
data[i], fifo_addr + i * 4);
} }
if (last) { if (last) {
...@@ -272,11 +271,11 @@ static void ft_readout_fifo_one(struct zio_cset *cset) ...@@ -272,11 +271,11 @@ static void ft_readout_fifo_one(struct zio_cset *cset)
/** /**
* An interrupt is ready, get time stamps from the FIFOs * An interrupt is ready, get time stamps from the FIFOs
*/ */
static irqreturn_t ft_irq_handler(int irq, void *dev_id) static irqreturn_t ft_irq_handler(int irq, void *arg)
{ {
struct fmc_device *fmc = dev_id; struct fmctdc_dev *ft = arg;
struct fmctdc_dev *ft = fmc->mezzanine_data; uint32_t irq_stat, tmp_irq_stat, fifo_stat;
uint32_t irq_stat, tmp_irq_stat, fifo_stat, fifo_csr_addr; void *fifo_csr_addr;
struct zio_cset *cset; struct zio_cset *cset;
int i; int i;
...@@ -285,7 +284,7 @@ static irqreturn_t ft_irq_handler(int irq, void *dev_id) ...@@ -285,7 +284,7 @@ static irqreturn_t ft_irq_handler(int irq, void *dev_id)
return IRQ_NONE; return IRQ_NONE;
irq: irq:
dev_vdbg(&ft->fmc->dev, "pending IRQ 0x%x\n", irq_stat); dev_vdbg(&ft->pdev->dev, "pending IRQ 0x%x\n", irq_stat);
/* /*
* Go through all FIFOs and read data. Democracy is a complicated thing, * Go through all FIFOs and read data. Democracy is a complicated thing,
* the following loops is a democratic loop, so it goes trough all * the following loops is a democratic loop, so it goes trough all
...@@ -320,9 +319,6 @@ irq: ...@@ -320,9 +319,6 @@ irq:
if (irq_stat) if (irq_stat)
goto irq; goto irq;
/* Ack the FMC signal, we have finished */
fmc_irq_ack(fmc);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -338,25 +334,18 @@ int ft_irq_init(struct fmctdc_dev *ft) ...@@ -338,25 +334,18 @@ int ft_irq_init(struct fmctdc_dev *ft)
/* disable timestamp readout IRQ, user will enable it manually */ /* disable timestamp readout IRQ, user will enable it manually */
ft_iowrite(ft, 0x1F, ft->ft_irq_base + TDC_REG_EIC_IDR); ft_iowrite(ft, 0x1F, ft->ft_irq_base + TDC_REG_EIC_IDR);
/* pass the core's base addr as the VIC IRQ vector. */ ret = request_irq(platform_get_irq(ft->pdev, 0), ft_irq_handler, 0,
/* fixme: vector table points to the bridge instead of dev_name(&ft->pdev->dev), ft);
the core's base address */
ft->fmc->irq = ft->ft_irq_base;
ret = fmc_irq_request(ft->fmc, ft_irq_handler, "fmc-tdc", 0);
if (ret < 0) { if (ret < 0) {
dev_err(&ft->fmc->dev, "Request interrupt failed: %d\n", ret); dev_err(&ft->pdev->dev, "Request interrupt failed: %d\n", ret);
return ret; return ret;
} }
/* kick off the interrupts (fixme: possible issue with the HDL) */
fmc_irq_ack(ft->fmc);
return 0; return 0;
} }
void ft_irq_exit(struct fmctdc_dev *ft) void ft_irq_exit(struct fmctdc_dev *ft)
{ {
ft_iowrite(ft, ~0, ft->ft_irq_base + TDC_REG_EIC_IDR); ft_iowrite(ft, ~0, ft->ft_irq_base + TDC_REG_EIC_IDR);
fmc_irq_free(ft->fmc); free_irq(platform_get_irq(ft->pdev, 0), ft);
} }
...@@ -89,11 +89,11 @@ void ft_set_tai_time(struct fmctdc_dev *ft, uint64_t seconds, uint32_t coarse) ...@@ -89,11 +89,11 @@ void ft_set_tai_time(struct fmctdc_dev *ft, uint64_t seconds, uint32_t coarse)
ft_enable_acquisition(ft, 0); ft_enable_acquisition(ft, 0);
if (ft->verbose) if (ft->verbose)
dev_info(&ft->fmc->dev, "Setting TAI time to %lld:%d\n", dev_info(&ft->pdev->dev, "Setting TAI time to %lld:%d\n",
seconds, coarse); seconds, coarse);
if (coarse != 0) if (coarse != 0)
dev_warn(&ft->fmc->dev, dev_warn(&ft->pdev->dev,
"Warning: ignoring sub-second part (%d) when setting time.\n", "Warning: ignoring sub-second part (%d) when setting time.\n",
coarse); coarse);
......
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#include <linux/zio-buffer.h> #include <linux/zio-buffer.h>
#include <linux/zio-trigger.h> #include <linux/zio-trigger.h>
#include <linux/fmc.h>
#include "fmc-tdc.h" #include "fmc-tdc.h"
#include "hw/tdc_regs.h" #include "hw/tdc_regs.h"
...@@ -405,7 +403,7 @@ int ft_zio_init(struct fmctdc_dev *ft) ...@@ -405,7 +403,7 @@ int ft_zio_init(struct fmctdc_dev *ft)
ft->hwzdev->owner = THIS_MODULE; ft->hwzdev->owner = THIS_MODULE;
ft->hwzdev->priv_d = ft; ft->hwzdev->priv_d = ft;
dev_id = ft->fmc->device_id; dev_id = ft->pdev->id;
err = zio_register_device(ft->hwzdev, "tdc-1n5c", dev_id); err = zio_register_device(ft->hwzdev, "tdc-1n5c", dev_id);
if (err) { if (err) {
......
...@@ -126,10 +126,11 @@ ...@@ -126,10 +126,11 @@
/* TDC core submodule offsets (wrs to the TDC control registers block) */ /* TDC core submodule offsets (wrs to the TDC control registers block) */
#define TDC_MEZZ_ONEWIRE_OFFSET (-0x1000) #define TDC_MEZZ_ONEWIRE_OFFSET (0x1000)
#define TDC_MEZZ_EIC_OFFSET (0x1000) #define TDC_MEZZ_CORE_OFFSET (0x2000)
#define TDC_MEZZ_I2C_OFFSET (0x2000) #define TDC_MEZZ_EIC_OFFSET (0x3000)
#define TDC_MEZZ_MEM_OFFSET (0x3000) #define TDC_MEZZ_I2C_OFFSET (0x4000)
#define TDC_MEZZ_MEM_OFFSET (0x5000)
#endif /* __TDC_REGISTERS_H */ #endif /* __TDC_REGISTERS_H */
...@@ -143,7 +143,7 @@ static int ow_read_block(struct fmctdc_dev *ft, int port, uint8_t * block, ...@@ -143,7 +143,7 @@ static int ow_read_block(struct fmctdc_dev *ft, int port, uint8_t * block,
static int ds18x_read_serial(struct fmctdc_dev *ft) static int ds18x_read_serial(struct fmctdc_dev *ft)
{ {
if (!ow_reset(ft, 0)) { if (!ow_reset(ft, 0)) {
dev_err(&ft->fmc->dev, dev_err(&ft->pdev->dev,
"Failure in resetting one-wire channel\n"); "Failure in resetting one-wire channel\n");
return -EIO; return -EIO;
} }
...@@ -167,7 +167,7 @@ static int ds18x_access(struct fmctdc_dev *ft) ...@@ -167,7 +167,7 @@ static int ds18x_access(struct fmctdc_dev *ft)
return ow_write_byte(ft, FT_OW_PORT, CMD_ROM_SKIP); return ow_write_byte(ft, FT_OW_PORT, CMD_ROM_SKIP);
} }
out: out:
dev_err(&ft->fmc->dev, "Failure in one-wire communication\n"); dev_err(&ft->pdev->dev, "Failure in one-wire communication\n");
return -EIO; return -EIO;
} }
...@@ -187,7 +187,7 @@ int ft_read_temp(struct fmctdc_dev *ft, int verbose) ...@@ -187,7 +187,7 @@ int ft_read_temp(struct fmctdc_dev *ft, int verbose)
int i, temp; int i, temp;
unsigned long j; unsigned long j;
uint8_t data[9]; uint8_t data[9];
struct device *dev = &ft->fmc->dev; struct device *dev = &ft->pdev->dev;
/* If first conversion, ask for it first */ /* If first conversion, ask for it first */
if (ft->next_t == 0) if (ft->next_t == 0)
...@@ -239,7 +239,7 @@ int ft_onewire_init(struct fmctdc_dev *ft) ...@@ -239,7 +239,7 @@ int ft_onewire_init(struct fmctdc_dev *ft)
return -EIO; return -EIO;
if (ft->verbose) { if (ft->verbose) {
dev_info(&ft->fmc->dev, "%s: Found DS18xx sensor: ", __func__); dev_info(&ft->pdev->dev, "%s: Found DS18xx sensor: ", __func__);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
printk("%02x%c", ft->ds18_id[i], i == 7 ? '\n' : ':'); printk("%02x%c", ft->ds18_id[i], i == 7 ? '\n' : ':');
} }
......
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