Commit f6e73254 authored by Alessandro Rubini's avatar Alessandro Rubini

kernel/calibration and doc: new calibration is there

The new calibration is now there, but some details are still missing,
like using the DAC value for the VCXO and validating against the
installed gateware.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 6aa4d0fd
......@@ -35,7 +35,7 @@
@setchapternewpage off
@set update-month February 2013
@set update-month April 2013
@c @set release 1.1
@set tagname fine-delay-sw-v1.1
@c WARNING: in @example I Can't use @value{tagname}, so please look for this
......@@ -948,7 +948,8 @@ read by the actual reading process).
The @i{offset} attribute
is the stamping offset, in picoseconds, for the TDC channel.
The @i{user-offset} attribute, which currently defaults to 0, is a
The @i{user-offset} attribute, which defaults to 0 every time the
driver is loaded, is a
signed value that users can write to represent a number of picoseconds
to be added (or subtracted) to the hardware-reported stamps. This is
used to account for delays induced by cabling (range: -2ms to 2ms).
......@@ -1215,9 +1216,9 @@ from @i{sysfs}.
@b{Note:} the @i{delay-offset} is used for delay mode but not
for pulse-generation mode.
The @i{user-offset} attribute, which currently defaults to 0, is a
The @i{user-offset} attribute, which defaults to 0 at module load time, is a
signed value that users can write to represent a number of picoseconds
to be added (or subtracted) to the every user-command (for both delay
to be added (or subtracted) to every user-command (for both delay
and pulse generation). This is used to account for delays induced by
cabling (range: -2ms to 2ms). The value can be modified
from @i{sysfs}.
......@@ -1679,12 +1680,7 @@ The following functions are offered:
@chapter Calibration
Calibration data for a fine-delay card is stored in the I2C FMC EEPROM
device. The FMC standard reserves the initial part of the memory for
its own data structures, so our calibration is stored at offset 0x1800
(6kB over a size of 8kB).
Future releases of this driver are expected to use SDB for describe
flash layout, but the offset of 6kB will be retained for compatibility.
device, using the SDB filesystem.
The driver automatically loads calibration data from the flash at
initialization time, but only uses it if its hash is valid. The
......@@ -1702,26 +1698,31 @@ time.
@item calibration_check
This integer parameter, if not zero, makes the driver dump the binary
structure of calibration data in a few places during initialization.
structure of calibration data during initialization.
It is mainly a debug tool.
@item calibration_default
The user can set this integer parameter to tell the driver to ignore
calibration data found on the EEPROM, thus enacting the compile-time
defaults.
This option should only be used by developers. If not zero, it tells
the driver to ignore
calibration data found on the EEPROM, thus enacting a build-time
default (which is most likely wrong for any board).
@item calibration_load
This parameter is a string. The name is used to ask the @i{firmware loader}
to retrieve a file from @file{/lib/firmware}. The driver tries both
the name it receives, and if that fails a name with bus and @i{devfn}
number appended -- so you can reconfigure a card even if more than one
of them is plugged on the same host. The data, once read, is used only
if the size is correct (0x54 == 84).
This parameter is a file name, and it should only be used by developers.
The name is used to ask the @i{firmware loader}
to retrieve a file from @file{/lib/firmware}.
The data, once read, is used only
if the size is correct. The hash is regenerated by the driver. Please
remember that all values in the calibration structure are stored as big-endian.
@item calibration_save
This option should only be used by developers, and is not supported
in this release. If you are a developer and need to change the calibration,
please check the current master branch on the repository, or a later
release.
The integer parameter is used to request saving calibration data to EEPROM,
whatever values are active after the other parameters have been used.
You can thus save the compiled-in default, the content of the firmware
......@@ -1730,8 +1731,8 @@ but not denied either.
@end table
This package offers no tool to generate the binary file (the 84 bytes
of calibration).
This package currently offers no tool to generate the binary file for
the calibration.
@c ##########################################################################
......
......@@ -15,6 +15,7 @@
#include <linux/firmware.h>
#include <linux/jhash.h>
#include "fine-delay.h"
#include "../sdb-lib/libsdbfs.h"
/* At factory config time, it's possible to load a file and/or write eeprom */
static char *calibration_load;
......@@ -71,48 +72,113 @@ static struct fd_calibration fd_calib_default = {
.magic = 0xf19ede1a,
.version = 3,
.date = 0x20130427,
/* .. FIXME .. */
.frr_poly = { -165202LL, -29825595LL, 3801939743082LL },
.zero_offset = { -38186, -38155, -38147, -38362 },
.tdc_zero_offset = 127500,
.vcxo_default_tune = 41711,
};
/* sdbfs-related function */
static int fd_read_calibration_eeprom(struct fmc_device *fmc,
struct fd_calibration *calib)
{
int i, ret;
static struct sdbfs fs;
fs.data = fmc->eeprom;
fs.datalen = fmc->eeprom_len;
/* Look for sdb entry point at powers of 2 and onwards */
for (i = 0x40; i < 0x1000; i *= 2) {
fs.entrypoint = i;
ret = sdbfs_dev_create(&fs, 0);
if (ret == 0)
break;
}
if (ret)
return ret;
/* Open "cali" as a device id, vendor is "FileData" -- big endian */
ret = sdbfs_open_id(&fs, 0x61746144656c6946LL, 0x696c6163);
if (ret)
return ret;
ret = sdbfs_fread(&fs, 0, (void *)calib, sizeof(*calib));
sdbfs_dev_destroy(&fs);
return ret;
}
/* This is the only thing called by outside */
int fd_handle_eeprom_calibration(struct fd_dev *fd)
{
struct fd_calibration *calib;
struct device *d = fd->fmc->hwdev;
//u32 hash;
int i;
u32 hash, horig;
/* Retrieve and validate the calibration */
calib = &fd->calib;
/* FIXME: run SDB on the eeprom */
dev_warn(d, "Calibration NOT yet read from eeprom\n");
i = fd_read_calibration_eeprom(fd->fmc, calib);
if (i != sizeof(*calib))
dev_warn(d, "Calibration NOT read from eeprom (got %i)\n", i);
if (calibration_check)
dumpstruct("Calibration data from eeprom:", calib,
sizeof(*calib));
/* FIXME: verify hash */
/* Verify hash (used later) */
horig = be32_to_cpu(calib->hash);
calib->hash = 0;
hash = jhash(calib, sizeof(*calib), 0);
/* FIXME: validate with gateware version */
if (calibration_load)
if (calibration_load) {
fd_i2c_load_calib(fd, calib, calibration_load);
hash = horig; /* whatever it is */
}
/* FIXME: convert endianneess */
/* convert endianneess */
calib->magic = be32_to_cpu(calib->magic);
calib->size = be16_to_cpu(calib->size);
calib->version = be16_to_cpu(calib->version);
calib->date = be32_to_cpu(calib->date);
for (i = 0; i < ARRAY_SIZE(calib->frr_poly); i++)
calib->frr_poly[i] = be64_to_cpu(calib->frr_poly[i]);
for (i = 0; i < ARRAY_SIZE(calib->zero_offset); i++)
calib->zero_offset[i] = be32_to_cpu(calib->zero_offset[i]);
calib->tdc_zero_offset = be32_to_cpu(calib->tdc_zero_offset);
calib->vcxo_default_tune = be32_to_cpu(calib->vcxo_default_tune);
if (calibration_default) {
dev_info(d, "Overriding with default calibration\n");
*calib = fd_calib_default;
hash = horig; /* whatever it is */
}
if (calibration_check) {
/* FIXME: dump human-readable values */
/* dump human-readable values */
dev_info(d, "calib: magic 0x%08x, date %08x\n", calib->magic,
calib->date);
dev_info(d, "calib: version %i\n", calib->version);
for (i = 0; i < ARRAY_SIZE(calib->frr_poly); i++)
dev_info(d, "calib: poly[%i] = %lli\n", i,
(long long)calib->frr_poly[i]);
for (i = 0; i < ARRAY_SIZE(calib->zero_offset); i++)
dev_info(d, "calib: offset[%i] = %li\n", i,
(long)calib->zero_offset[i]);
dev_info(d, "calib: tdc_offset %i\n", calib->tdc_zero_offset);
dev_info(d, "calib: vcxo %i\n", calib->vcxo_default_tune);
}
/* FIXME: recreate hash */
if (hash != horig) {
dev_err(d, "Calibration hash %08x is wrong (expected %08x)\n",
hash, horig);
return -EINVAL;
}
if (calibration_save) {
/* FIXME: save to eeprom */
/* FIXME: save to eeprom: re-convert endianness and hash */
dev_warn(d, "Saving is not supported\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