Commit e334446a authored by Alessandro Rubini's avatar Alessandro Rubini

Merge branch 'fmc-bus'

parents cdcdbe2c 63280175
[submodule "spec-sw"]
path = spec-sw
url = git://ohwr.org/fmc-projects/spec/spec-sw.git
[submodule "zio"]
path = zio
url = git://ohwr.org/misc/zio.git
[submodule "fmc-bus"]
path = fmc-bus
url = git://ohwr.org/fmc-projects/fmc-bus.git
LINUX ?= /lib/modules/$(shell uname -r)/build
ZIO ?= $(HOME)/zio
SPEC_SW ?= $(HOME)/spec-sw
.PHONY: all clean modules install modules_install
.PHONY: gitmodules prereq prereq_install_warn prereq_install_warn
KBUILD_EXTRA_SYMBOLS := $(ZIO)/Module.symvers $(SPEC_SW)/kernel/Module.symvers
DIRS = kernel tools lib
ccflags-y = -I$(ZIO)/include -I$(SPEC_SW)/kernel -I$M
all clean modules install modules_install: gitmodules
for d in $(DIRS); do $(MAKE) -C $$d $@ || exit 1; done
@if echo $@ | grep -q install; then $(MAKE) prereq_install_warn; fi
#ccflags-y += -DDEBUG
all modules: prereq
subdirs-ccflags-y = $(ccflags-y)
# The following targets are used to manage prerequisite repositories
gitmodules:
@test -d fmc-bus/doc || echo "Checking out submodules"
@test -d fmc-bus/doc || git submodule init && git submodule update
obj-m := spec-fine-delay.o
SUBMOD = fmc-bus spec-sw zio
spec-fine-delay-objs = fd-zio.o fd-spec.o fd-core.o
spec-fine-delay-objs += onewire.o spi.o i2c.o gpio.o
spec-fine-delay-objs += acam.o calibrate.o pll.o time.o
prereq:
for d in $(SUBMOD); do $(MAKE) -C $$d || exit 1; done
all: modules
prereq_install_warn:
@test -f .prereq_installed || \
echo -e "\n\n\tWARNING: Consider \"make prereq_install\"\n"
modules_install clean modules:
$(MAKE) -C $(LINUX) M=$(shell /bin/pwd) $@
$(MAKE) -C tools M=$(shell /bin/pwd) $@
$(MAKE) -C lib $@
prereq_install:
for d in $(SUBMOD); do $(MAKE) -C $$d modules_install || exit 1; done
touch .prereq_installed
Please check doc/
There, fine-delay.in is the source file, and you can "make" to get
In ./doc/, fine-delay.in is the source file, and you can "make" to get
pdf and other formats provided you have the proper tools installed
(mainly texinfo and tex).
\ No newline at end of file
(mainly texinfo and tex).
......@@ -58,3 +58,5 @@ clean: terse
install:
# add the other unused targets, so the rule in ../Makefile works
modules modules_install:
This diff is collapsed.
/*
* SPEC interface for the fine-delay driver
*
* Copyright (C) 2012 CERN (www.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/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 "fine-delay.h"
static int fd_is_valid(int bus, int devfn)
{
/* FIXME: restrict to some of the spec devices with moduleparam */
return 1;
}
int fd_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 (!fd_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 = fd_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 fd_spec_exit(void)
{
struct spec_dev *dev;
list_for_each_entry(dev, &spec_list, list) {
if (!fd_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]);
fd_remove(dev);
}
}
fmc-bus @ dc30ce99
Subproject commit dc30ce998628084c4402291e6052c7feb77be424
LINUX ?= /lib/modules/$(shell uname -r)/build
ZIO ?= $(M)/../zio
SPEC_SW ?= $(M)/../spec-sw
FMC_BUS ?= $(M)/../fmc-bus
KBUILD_EXTRA_SYMBOLS := \
$(ZIO)/Module.symvers \
$(SPEC_SW)/kernel/Module.symvers \
$(FMC_BUS)/kernel/Module.sysmvers
ccflags-y = \
-I$(ZIO)/include \
-I$(SPEC_SW)/kernel \
-I$(SPEC_SW)/kernel/include \
-I$(FMC_BUS)/kernel/include \
-I$M
#ccflags-y += -DDEBUG
subdirs-ccflags-y = $(ccflags-y)
obj-m := fmc-fine-delay.o
fmc-fine-delay-objs = fd-zio.o fd-core.o
fmc-fine-delay-objs += onewire.o spi.o i2c.o gpio.o
fmc-fine-delay-objs += acam.o calibrate.o pll.o time.o
all modules:
$(MAKE) -C $(LINUX) M=$(shell /bin/pwd) modules
install modules_install:
$(MAKE) -C $(LINUX) M=$(shell /bin/pwd) modules_install
# be able to run the "clean" rule even if $(LINUX) is not valid
clean:
rm -rf *.o *~ .*.cmd *.ko *.mod.c .tmp_versions Module.symvers \
Module.markers modules.order
......@@ -21,17 +21,26 @@
#include <linux/list.h>
#include <linux/io.h>
#include <linux/fmc.h>
#include <linux/fmc-sdb.h>
#include "spec.h"
#include "fine-delay.h"
#include "hw/fd_main_regs.h"
/* Module parameters */
static int fd_regs_offset = FD_REGS_OFFSET;
module_param_named(regs, fd_regs_offset, int, 0444);
static int fd_verbose = 0;
module_param_named(verbose, fd_verbose, int, 0444);
static struct fmc_driver fd_drv; /* forward declaration */
FMC_PARAM_BUSID(fd_drv);
FMC_PARAM_GATEWARE(fd_drv);
static int fd_show_sdb;
module_param_named(show_sdb, fd_show_sdb, int, 0444);
/* FIXME: add parameters "file=" and "wrc=" like wr-nic-core does */
/* This is pre-set at load time (data by Tomasz) */
static struct fd_calib fd_default_calib = {
.frr_poly = {
......@@ -128,37 +137,83 @@ static struct fd_modlist mods[] = {
SUBSYS(zio),
};
/* probe and remove are called by fd-spec.c */
int fd_probe(struct spec_dev *dev)
/* probe and remove are called by the FMC bus core */
int fd_probe(struct fmc_device *fmc)
{
struct fd_modlist *m;
struct spec_fd *fd;
int i, ret;
struct spec_dev *spec;
struct device *dev = fmc->hwdev;
char *fwname;
int i, index, ret;
fd = kzalloc(sizeof(*fd), GFP_KERNEL);
if (!fd) {
pr_err("%s: can't allocate device\n", __func__);
dev_err(fmc->hwdev, "can't allocate device\n");
return -ENOMEM;
}
if (strcmp (fmc->carrier_name, "SPEC")) {
dev_err(fmc->hwdev, "driver \"%s\" only works on SPEC card\n",
KBUILD_MODNAME);
dev_err(fmc->hwdev, "support for carrier \"%s\" is missing\n",
fmc->carrier_name);
return -ENODEV;
}
index = fmc->op->validate(fmc, &fd_drv);
if (index < 0) {
dev_info(fmc->hwdev, "not using \"%s\" according to "
"modparam\n", KBUILD_MODNAME);
return -ENODEV;
}
fwname = FDELAY_GATEWARE_NAME;
if (fd_drv.gw_n)
fwname = ""; /* ->reprogram will pick from module parameter */
ret = fmc->op->reprogram(fmc, &fd_drv, fwname);
if (ret < 0) {
if (ret == -ESRCH) {
dev_info(fmc->hwdev, "%s: no gateware at index %i\n",
KBUILD_MODNAME, index);
return -ENODEV;
}
return ret; /* other error: pass over */
}
/* FIXME: factorize the following stuff */
/* Verify that we have SDB at offset 0 */
if (fmc_readl(fmc, 0) != 0x5344422d) {
dev_err(dev, "Can't find SDB magic\n");
ret = -ENODEV;
goto out;
}
dev_info(dev, "Gateware successfully loaded\n");
if ( (ret = fmc_scan_sdb_tree(fmc, 0)) < 0) {
dev_err(dev, "scan fmc failed %i\n", ret);
goto out;
}
if (fd_show_sdb)
fmc_show_sdb_tree(fmc);
spec = fmc->carrier_data;
spin_lock_init(&fd->lock);
dev->sub_priv = fd;
fd->spec = dev;
fd->base = dev->remap[0];
fd->regs = fd->base + fd_regs_offset;
fmc->mezzanine_data = fd;
fd->fmc = fmc;
/* FIXME: don't use base below, but fmc_readl/fmc_writel */
fd->regs = fmc->base + 0x80000; /* sdb_find_device(cern, f19ede1a) */
fd->ow_regs = fd->regs + 0x500;
fd->verbose = fd_verbose;
fd->calib = fd_default_calib;
/* Check the binary is there */
if (fd_readl(fd, FD_REG_IDR) != FD_MAGIC_FPGA) {
pr_err("%s: card at %04x:%04x (regs @ 0x%x): wrong gateware\n",
__func__, dev->pdev->bus->number, dev->pdev->devfn,
fd_regs_offset);
dev_err(fmc->hwdev, "wrong gateware\n");
return -ENODEV;
} else {
pr_info("%s: card at %04x:%04x (regs @ 0x%x): initializing\n",
__func__, dev->pdev->bus->number, dev->pdev->devfn,
fd_regs_offset);
dev_info(fmc->hwdev, "%s: initializing\n", KBUILD_MODNAME);
}
/* First, hardware reset */
......@@ -199,25 +254,35 @@ err:
while (--m, --i >= 0)
if (m->exit)
m->exit(fd);
out:
return ret;
}
void fd_remove(struct spec_dev *dev)
int fd_remove(struct fmc_device *fmc)
{
struct fd_modlist *m;
struct spec_fd *fd = dev->sub_priv;
struct spec_fd *fd = fmc->mezzanine_data;
int i = ARRAY_SIZE(mods);
if (!test_bit(FD_FLAG_INITED, &fd->flags))
return; /* No init, no exit */
if (!test_bit(FD_FLAG_INITED, &fd->flags)) /* FIXME: ditch this */
return 0; /* No init, no exit */
while (--i >= 0) {
m = mods + i;
if (m->exit)
m->exit(fd);
}
return 0;
}
static struct fmc_driver fd_drv = {
.version = FMC_VERSION,
.driver.name = KBUILD_MODNAME,
.probe = fd_probe,
.remove = fd_remove,
/* no table, as the current match just matches everything */
};
static int fd_init(void)
{
int ret;
......@@ -225,7 +290,7 @@ static int fd_init(void)
ret = fd_zio_register();
if (ret < 0)
return ret;
ret = fd_spec_init();
ret = fmc_driver_register(&fd_drv);
if (ret < 0) {
fd_zio_unregister();
return ret;
......@@ -235,7 +300,7 @@ static int fd_init(void)
static void fd_exit(void)
{
fd_spec_exit();
fmc_driver_unregister(&fd_drv);
fd_zio_unregister();
}
......
......@@ -802,6 +802,7 @@ void fd_zio_unregister(void)
int fd_zio_init(struct spec_fd *fd)
{
int err = 0;
struct spec_dev *spec;
struct pci_dev *pdev;
int dev_id;
......@@ -814,7 +815,8 @@ int fd_zio_init(struct spec_fd *fd)
fd->hwzdev->private_data = fd;
/* Our dev_id is bus+devfn */
pdev = fd->spec->pdev;
spec = fd->fmc->carrier_data;
pdev = spec->pdev;
dev_id = (pdev->bus->number << 8) | pdev->devfn;
err = zio_register_device(fd->hwzdev, "fd", dev_id);
......
#ifndef __FINE_DELAY_H__
#define __FINE_DELAY_H__
#define FDELAY_VERSION 2
#define FDELAY_GATEWARE_NAME "fmc/fine-delay.bin"
#define FDELAY_VERSION 2 /* version of the layout of registers */
/*
* ZIO concatenates device, cset and channel extended attributes in the 32
* values that are reported in the control block. So we are limited to
......@@ -153,7 +155,7 @@ struct fd_ch {
struct spec_fd {
spinlock_t lock;
unsigned long flags;
struct spec_dev *spec;
struct fmc_device *fmc;
struct zio_device *zdev, *hwzdev;
struct timer_list fifo_timer;
struct timer_list temp_timer;
......@@ -285,10 +287,6 @@ static inline void __check_output(int x)
#define FD_GPIO_TRIG_INTERNAL 0x0040 /* TDC trig (1=in, 1=fpga) */
#define FD_GPIO_CAL_DISABLE 0x0080 /* 0 enables calibration */
/* Functions exported by fd-core.c */
extern int fd_probe(struct spec_dev *dev);
extern void fd_remove(struct spec_dev *dev);
/* Functions exported by spi.c */
extern int fd_spi_xfer(struct spec_fd *fd, int ss, int num_bits,
uint32_t in, uint32_t *out);
......
......@@ -218,39 +218,25 @@ static void fd_i2c_load_calib(struct spec_fd *fd,
struct fd_calib_on_eeprom *cal_ee)
{
const struct firmware *fw;
struct pci_dev *pdev = fd->spec->pdev;
char *fwname, *newname = NULL;
int err;
/* the calibration_load string is known to be valid */
fwname = calibration_load;
err = request_firmware(&fw, calibration_load, &pdev->dev);
err = request_firmware(&fw, calibration_load, fd->fmc->hwdev);
if (err < 0) {
dev_warn(&pdev->dev, "can't load \"%s\"\n",
dev_warn(fd->fmc->hwdev, "can't load \"%s\"\n",
calibration_load);
newname = kasprintf(GFP_KERNEL, "%s-%02x%02x\n",
calibration_load,
pdev->bus->number, pdev->devfn);
err = request_firmware(&fw, newname, &pdev->dev);
if (err < 0) {
dev_warn(&pdev->dev, "can't load \"%s\"\n",
newname);
}
fwname = newname;
}
if (err < 0) {
kfree(newname);
return;
}
if (fw->size != sizeof(cal_ee->calib)) {
dev_warn(&pdev->dev, "File \"%s\" has wrong size\n",
dev_warn(fd->fmc->hwdev, "File \"%s\" has wrong size\n",
fwname);
} else {
memcpy(&cal_ee->calib, fw->data, fw->size);
dev_info(&pdev->dev, "calibration data loaded from \"%s\"\n",
fwname);
dev_info(fd->fmc->hwdev,
"calibration data loaded from \"%s\"\n", fwname);
}
release_firmware(fw);
kfree(newname);
......
......@@ -6,3 +6,4 @@ fdelay-term
fdelay-read
fdelay-fread
fdelay-pulse
fdelay-open-by-lun
......@@ -6,7 +6,7 @@ LOBJ += fdelay-time.o
LOBJ += fdelay-tdc.o
LOBJ += fdelay-output.o
CFLAGS = -Wall -ggdb -O2 -I.. -I$(ZIO)/include
CFLAGS = -Wall -ggdb -O2 -I../kernel -I../zio/include
LDFLAGS = -L. -lfdelay
DEMOSRC := fdelay-list.c
......@@ -37,5 +37,7 @@ clean:
.depend: Makefile $(wildcard *.c *.h ../*.h)
$(CC) $(CFLAGS) -M $(LOBJ:.o=.c) -o $@
install modules_install:
-include .depend
......@@ -43,9 +43,11 @@ int fdelay_init(void)
/* Look for boards in /dev: old and new pathnames: only one matches */
glob("/dev/fd-*-0-0-ctrl", 0, NULL, &glob_dev);
glob("/dev/zio/fd-*-0-0-ctrl", GLOB_APPEND, NULL, &glob_dev);
glob("/dev/zio/zio-fd-*-0-0-ctrl", GLOB_APPEND, NULL, &glob_dev);
/* And look in /sys as well */
glob("/sys/bus/zio/devices/fd-*",0 , NULL, &glob_sys);
glob("/sys/bus/zio/devices/fd-*", 0, NULL, &glob_sys);
glob("/sys/bus/zio/devices/zio-fd-*", GLOB_APPEND , NULL, &glob_sys);
assert(glob_dev.gl_pathc == glob_sys.gl_pathc);
/* Allocate as needed */
......
......@@ -13,7 +13,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
......
spec-sw @ 35480a19
Subproject commit 35480a19bc562ebfa76f4663d41d026ff1b9df29
# user-space tools for spec-fine-delay
HOST_EXTRACFLAGS += -I$(M) -I$(ZIO)/include -Wno-trigraphs -Wall -ggdb
M = $(shell /bin/pwd)/../kernel
HOST_EXTRACFLAGS += -I$(M) -I../zio/include -Wno-trigraphs -Wall -ggdb
HOSTCC ?= gcc
......@@ -12,13 +14,13 @@ hostprogs-y += fd-raw-output
hostprogs-y += fd-raw-perf
# we are not in the kernel, so we need to piggy-back on "make modules"
modules: $(hostprogs-y)
all modules: $(hostprogs-y)
clean:
rm -f $(hostprogs-y) *.o *~
# make nothing for module_install, but avoid errors
module_install:
# make nothing for modules_install, but avoid errors
modules_install install:
# we need this as we are out of the kernel
%: %.c
......
......@@ -13,7 +13,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
......
......@@ -164,6 +164,8 @@ int main(int argc, char **argv)
glob("/dev/fd-*-0-0-ctrl", GLOB_DOOFFS, NULL, &glob_buf);
glob("/dev/zio/fd-*-0-0-ctrl",
GLOB_DOOFFS | GLOB_APPEND, NULL, &glob_buf);
glob("/dev/zio/zio-fd-*-0-0-ctrl",
GLOB_DOOFFS | GLOB_APPEND, NULL, &glob_buf);
glob_buf.gl_pathv[0] = argv[0];
argv = glob_buf.gl_pathv;
argc = glob_buf.gl_pathc + glob_buf.gl_offs;
......
......@@ -38,6 +38,7 @@ int main(int argc, char **argv)
/* glob to find the device; use the first */
glob("/dev/fd-*-1-0-ctrl", 0, NULL, &glob_buf);
glob("/dev/zio/fd-*-1-0-ctrl", GLOB_APPEND, NULL, &glob_buf);
glob("/dev/zio/zio-fd-*-1-0-ctrl", GLOB_APPEND, NULL, &glob_buf);
if (glob_buf.gl_pathc != 1) {
fprintf(stderr, "%s: found %i devices, need 1 only\n",
......
......@@ -148,6 +148,8 @@ int main(int argc, char **argv)
glob("/dev/fd-*-0-0-ctrl", GLOB_DOOFFS, NULL, &glob_buf);
glob("/dev/zio/fd-*-0-0-ctrl",
GLOB_DOOFFS | GLOB_APPEND, NULL, &glob_buf);
glob("/dev/zio/zio-fd-*-0-0-ctrl",
GLOB_DOOFFS | GLOB_APPEND, NULL, &glob_buf);
glob_buf.gl_pathv[0] = argv[0];
argv = glob_buf.gl_pathv;
argc = glob_buf.gl_pathc + glob_buf.gl_offs;
......
......@@ -13,7 +13,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
......
#!/bin/bash
rmmod rawrabbit
rmmod fine_delay
rmmod spec
cp wrc.bin /lib/firmware/spec-B0005-cpu.bin
cp spec_top_wr.bin /lib/firmware/spec-B0005.bin
insmod ../zio/zio.ko
insmod ../spec-sw/kernel/spec.ko lm32=0xc0000
insmod spec-fine-delay.ko regs=0x80000
modprobe fmc
modprobe spec
insmod spec-fine-delay.ko wrc=1
......@@ -13,7 +13,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
......
zio @ 97387e89
Subproject commit 97387e89601f80946ddd9ec2f8d17749ae2afe56
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