Commit 32827bf3 authored by Alessandro Rubini's avatar Alessandro Rubini

attributes: the device has a 'command' channel, not host-time

parent 0fd9e2bf
...@@ -360,7 +360,8 @@ directory is @i{/sys/bus/zio/devices/zio-fd-0200}: ...@@ -360,7 +360,8 @@ directory is @i{/sys/bus/zio/devices/zio-fd-0200}:
@section Device Attributes @section Device Attributes
Device-wide attributes are the three time tags (@i{utc-h}, @i{utc-l}, Device-wide attributes are the three time tags (@i{utc-h}, @i{utc-l},
@i{coarse}) and a write-only @i{host-time}. To read device time you @i{coarse}), a read-only @i{version} and a write-only @i{command}.
To read device time you
should read @i{utc-h} first. Reading @u{utc-h} will atomically read should read @i{utc-h} first. Reading @u{utc-h} will atomically read
all values from the card and store them in the software driver: by all values from the card and store them in the software driver: by
reading @i{utc-l} and @i{coarse} you'll get such cached values. reading @i{utc-l} and @i{coarse} you'll get such cached values.
...@@ -385,14 +386,14 @@ last: writing @i{utc-h} atomically programs the hardware: ...@@ -385,14 +386,14 @@ last: writing @i{utc-h} atomically programs the hardware:
10003 10003
@end smallexample @end smallexample
If you write any value to @i{host-time}, board time will be If you write 0 to @i{command}, board time will be
synchronized to the current Linux clock within one microsecond synchronized to the current Linux clock within one microsecond
(reading Linux time and writing to the @i{fine-delay} registers is (reading Linux time and writing to the @i{fine-delay} registers is
done with interrupts disabled, so the actual synchronization precision done with interrupts disabled, so the actual synchronization precision
depends on the speed of your CPU and PCI bus): depends on the speed of your CPU and PCI bus):
@smallexample @smallexample
spusa# cat utc-h utc-l; echo 0 > host-time; cat utc-h utc-l; date +%s spusa# cat utc-h utc-l; echo 0 > command; cat utc-h utc-l; date +%s
0 0
50005 50005
0 0
...@@ -400,6 +401,11 @@ depends on the speed of your CPU and PCI bus): ...@@ -400,6 +401,11 @@ depends on the speed of your CPU and PCI bus):
1335948116 1335948116
@end smallexample @end smallexample
I chose to offer a @i{command} channel, which is opaque to the user,
because there are several commands that you may need to send to the
device, and we need to limit the number of attributes. The command numbers
are enumerated in @code{fine-delay.h}
@menu @menu
* Reading Board Time:: * Reading Board Time::
* Writing Board Time:: * Writing Board Time::
...@@ -440,7 +446,7 @@ the current board time using @i{sysfs} directly: ...@@ -440,7 +446,7 @@ the current board time using @i{sysfs} directly:
@b{Note:} the tool is bugged as of 2038 because it assumes utc-h is 0. @b{Note:} the tool is bugged as of 2038 because it assumes utc-h is 0.
No tool is there to sync the board to Linux time, because writing No tool is there to sync the board to Linux time, because writing
to the @i{host-time} attribute is atomic by itself. 0 to the @i{command} attribute is atomic by itself.
@c ========================================================================== @c ==========================================================================
@node The Input cset @node The Input cset
...@@ -791,8 +797,6 @@ allows: ...@@ -791,8 +797,6 @@ allows:
@item Output support is missing. It simply is not there at this point. @item Output support is missing. It simply is not there at this point.
@item The API for C programs is missing. This is being worked on.
@item We need interrupt support. The input is performed with a kernel timer. @item We need interrupt support. The input is performed with a kernel timer.
Also, we need an in-driver buffer for input samples. Also, we need an in-driver buffer for input samples.
...@@ -802,6 +806,8 @@ the output delay calibrated. ...@@ -802,6 +806,8 @@ the output delay calibrated.
@item There is no EEPROM support. The driver uses default calibration @item There is no EEPROM support. The driver uses default calibration
settings and no i2c support is there yet. settings and no i2c support is there yet.
@item Offsets for input and output timestamps are not used at this point.
@item We need a module parameter to avoid probing non-fine-delay SPEC @item We need a module parameter to avoid probing non-fine-delay SPEC
cards. Reading the magic number from an SPEC that is not programmed cards. Reading the magic number from an SPEC that is not programmed
(or likely that is programmed with a different gateware) may lock up (or likely that is programmed with a different gateware) may lock up
...@@ -824,6 +830,7 @@ them. ...@@ -824,6 +830,7 @@ them.
@menu @menu
* Wrong FPGA Image:: * Wrong FPGA Image::
* Version Mismatch::
@end menu @end menu
@c ========================================================================== @c ==========================================================================
...@@ -845,6 +852,23 @@ If this happens, please put the binary image in @i{/lib/firmware} ...@@ -845,6 +852,23 @@ If this happens, please put the binary image in @i{/lib/firmware}
where the spec driver can find it. In my case the file name is where the spec driver can find it. In my case the file name is
@code{spec-B0002.bin} (refer to @i{spec-sw} documentation for details. @code{spec-B0002.bin} (refer to @i{spec-sw} documentation for details.
@c ==========================================================================
@node Version Mismatch
@section Version Mismatch
The @i{fdelay} library may report a version mismatch like this:
@example
spusa# ./fdelay-board-time get
fdelay_init: version mismatch, lib(1) != drv(2)
./fdelay-board-time: fdelay_init(): Input/output error
@end example
This reports a difference in the way ZIO attributes are laid out, so user
space may exchange wrong data in the ZIO control block, or may try to
access inexistent files in @i{/sys}. I suggest recompiling both the kernel
driver and user space from a single release of the source package.
@c ########################################################################## @c ##########################################################################
@bye @bye
......
...@@ -27,31 +27,6 @@ ...@@ -27,31 +27,6 @@
#include "fine-delay.h" #include "fine-delay.h"
#include "hw/fd_main_regs.h" #include "hw/fd_main_regs.h"
/*
* We have a number of attributes here. For input channels they are:
*
* UTC-h (expected to be 0 untile 2038 a.d.),
* UTC-l
* coarse time
* fractional time
* sequential ID
* channel
* flags
*
* See the enum in "fine-delay.h"
*/
static struct zio_attribute fd_zattr_input[] = {
ZATTR_EXT_REG("utc-h", S_IRUGO, FD_ATTR_TDC_UTC_H, 0),
ZATTR_EXT_REG("utc-l", S_IRUGO, FD_ATTR_TDC_UTC_L, 0),
ZATTR_EXT_REG("coarse", S_IRUGO, FD_ATTR_TDC_COARSE, 0),
ZATTR_EXT_REG("frac", S_IRUGO, FD_ATTR_TDC_FRAC, 0),
ZATTR_EXT_REG("seq", S_IRUGO, FD_ATTR_TDC_SEQ, 0),
ZATTR_EXT_REG("chan", S_IRUGO, FD_ATTR_TDC_CHAN, 0),
ZATTR_EXT_REG("flags", S_IRUGO|S_IWUGO, FD_ATTR_TDC_FLAGS, 0),
ZATTR_EXT_REG("offset", S_IRUGO, FD_ATTR_TDC_OFFSET, 0),
};
/* The sample size. Mandatory, device-wide */ /* The sample size. Mandatory, device-wide */
DEFINE_ZATTR_STD(ZDEV, fd_zattr_dev_std) = { DEFINE_ZATTR_STD(ZDEV, fd_zattr_dev_std) = {
ZATTR_REG(zdev, ZATTR_NBITS, S_IRUGO, 0, 32), /* 32 bits. Really? */ ZATTR_REG(zdev, ZATTR_NBITS, S_IRUGO, 0, 32), /* 32 bits. Really? */
...@@ -64,9 +39,22 @@ static struct zio_attribute fd_zattr_dev[] = { ...@@ -64,9 +39,22 @@ static struct zio_attribute fd_zattr_dev[] = {
ZATTR_EXT_REG("utc-h", S_IRUGO | S_IWUGO, FD_ATTR_DEV_UTC_H, 0), ZATTR_EXT_REG("utc-h", S_IRUGO | S_IWUGO, FD_ATTR_DEV_UTC_H, 0),
ZATTR_EXT_REG("utc-l", S_IRUGO | S_IWUGO, FD_ATTR_DEV_UTC_L, 0), ZATTR_EXT_REG("utc-l", S_IRUGO | S_IWUGO, FD_ATTR_DEV_UTC_L, 0),
ZATTR_EXT_REG("coarse", S_IRUGO | S_IWUGO, FD_ATTR_DEV_COARSE, 0), ZATTR_EXT_REG("coarse", S_IRUGO | S_IWUGO, FD_ATTR_DEV_COARSE, 0),
ZATTR_EXT_REG("host-time", S_IWUGO, FD_ATTR_DEV_HOST_T, 0), ZATTR_EXT_REG("command", S_IWUGO, FD_ATTR_DEV_COMMAND, 0),
}; };
/* Extended attributes for the TDC (== input) cset */
static struct zio_attribute fd_zattr_input[] = {
ZATTR_EXT_REG("utc-h", S_IRUGO, FD_ATTR_TDC_UTC_H, 0),
ZATTR_EXT_REG("utc-l", S_IRUGO, FD_ATTR_TDC_UTC_L, 0),
ZATTR_EXT_REG("coarse", S_IRUGO, FD_ATTR_TDC_COARSE, 0),
ZATTR_EXT_REG("frac", S_IRUGO, FD_ATTR_TDC_FRAC, 0),
ZATTR_EXT_REG("seq", S_IRUGO, FD_ATTR_TDC_SEQ, 0),
ZATTR_EXT_REG("chan", S_IRUGO, FD_ATTR_TDC_CHAN, 0),
ZATTR_EXT_REG("flags", S_IRUGO|S_IWUGO, FD_ATTR_TDC_FLAGS, 0),
ZATTR_EXT_REG("offset", S_IRUGO, FD_ATTR_TDC_OFFSET, 0),
};
/* This identifies if our "struct device" is device, input, output */ /* This identifies if our "struct device" is device, input, output */
enum fd_devtype { enum fd_devtype {
FD_TYPE_WHOLEDEV, FD_TYPE_WHOLEDEV,
...@@ -148,18 +136,26 @@ static int fd_zio_conf_set(struct device *dev, struct zio_attribute *zattr, ...@@ -148,18 +136,26 @@ static int fd_zio_conf_set(struct device *dev, struct zio_attribute *zattr,
attr = zdev->zattr_set.ext_zattr; attr = zdev->zattr_set.ext_zattr;
fd = zdev->private_data; fd = zdev->private_data;
/* Special case: set host time to the board */ if (zattr->priv.addr == FD_ATTR_DEV_UTC_H) {
if (zattr->priv.addr == FD_ATTR_DEV_HOST_T) /* writing utc-h calls an atomic set-time */
return fd_time_set(fd, NULL, NULL); t.utc = (uint64_t)attr[FD_ATTR_DEV_UTC_H].value << 32;
t.utc |= attr[FD_ATTR_DEV_UTC_L].value;
t.coarse = attr[FD_ATTR_DEV_COARSE].value;
fd_time_set(fd, &t, NULL);
return 0;
}
if (zattr->priv.addr != FD_ATTR_DEV_UTC_H) /* Not command, nothing to do */
if (zattr->priv.addr != FD_ATTR_DEV_COMMAND)
return 0; return 0;
/* writing utc-h calls an atomic set-time */
t.utc = (uint64_t)attr[FD_ATTR_DEV_UTC_H].value << 32; printk("command %i\n", usr_val);
t.utc |= attr[FD_ATTR_DEV_UTC_L].value; switch(usr_val) {
t.coarse = attr[FD_ATTR_DEV_COARSE].value; case FD_CMD_HOST_TIME:
fd_time_set(fd, &t, NULL); return fd_time_set(fd, NULL, NULL);
return 0; default:
return -EINVAL;
}
} }
/* /*
......
...@@ -17,13 +17,17 @@ enum fd_zattr_dev_idx { ...@@ -17,13 +17,17 @@ enum fd_zattr_dev_idx {
FD_ATTR_DEV_UTC_H, FD_ATTR_DEV_UTC_H,
FD_ATTR_DEV_UTC_L, FD_ATTR_DEV_UTC_L,
FD_ATTR_DEV_COARSE, FD_ATTR_DEV_COARSE,
FD_ATTR_DEV_HOST_T, FD_ATTR_DEV_COMMAND, /* see below for commands */
FD_ATTR_DEV_RESERVE_5, FD_ATTR_DEV_RESERVE_5,
FD_ATTR_DEV_RESERVE_6, FD_ATTR_DEV_RESERVE_6,
FD_ATTR_DEV_RESERVE_7, FD_ATTR_DEV_RESERVE_7,
FD_ATTR_DEV__LAST, FD_ATTR_DEV__LAST,
}; };
enum fd_command {
FD_CMD_HOST_TIME = 0,
};
/* Input ZIO attributes (i.e. TDC attributes) */ /* Input ZIO attributes (i.e. TDC attributes) */
enum fd_zattr_in_idx { enum fd_zattr_in_idx {
......
...@@ -62,7 +62,7 @@ int fdelay_get_time(struct fdelay_board *userb, struct fdelay_time *t) ...@@ -62,7 +62,7 @@ int fdelay_get_time(struct fdelay_board *userb, struct fdelay_time *t)
for (i = 0; i < ARRAY_SIZE(names); i++) for (i = 0; i < ARRAY_SIZE(names); i++)
if (fdelay_sysfs_get(b, names[i], attrs + i) < 0) if (fdelay_sysfs_get(b, names[i], attrs + i) < 0)
return -1; return -1;
t->utc = attrs[0] << 32; t->utc = (long long)attrs[0] << 32;
t->utc += attrs[1]; t->utc += attrs[1];
t->coarse = attrs[2]; t->coarse = attrs[2];
return 0; return 0;
...@@ -71,8 +71,8 @@ int fdelay_get_time(struct fdelay_board *userb, struct fdelay_time *t) ...@@ -71,8 +71,8 @@ int fdelay_get_time(struct fdelay_board *userb, struct fdelay_time *t)
int fdelay_set_host_time(struct fdelay_board *userb) int fdelay_set_host_time(struct fdelay_board *userb)
{ {
__define_board(b, userb); __define_board(b, userb);
uint32_t i = 0; uint32_t i = FD_CMD_HOST_TIME;
return fdelay_sysfs_set(b, "host-time", &i); return fdelay_sysfs_set(b, "command", &i);
} }
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