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 @@ ...@@ -35,7 +35,7 @@
@setchapternewpage off @setchapternewpage off
@set update-month February 2013 @set update-month April 2013
@c @set release 1.1 @c @set release 1.1
@set tagname fine-delay-sw-v1.1 @set tagname fine-delay-sw-v1.1
@c WARNING: in @example I Can't use @value{tagname}, so please look for this @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). ...@@ -948,7 +948,8 @@ read by the actual reading process).
The @i{offset} attribute The @i{offset} attribute
is the stamping offset, in picoseconds, for the TDC channel. 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 signed value that users can write to represent a number of picoseconds
to be added (or subtracted) to the hardware-reported stamps. This is to be added (or subtracted) to the hardware-reported stamps. This is
used to account for delays induced by cabling (range: -2ms to 2ms). used to account for delays induced by cabling (range: -2ms to 2ms).
...@@ -1215,9 +1216,9 @@ from @i{sysfs}. ...@@ -1215,9 +1216,9 @@ from @i{sysfs}.
@b{Note:} the @i{delay-offset} is used for delay mode but not @b{Note:} the @i{delay-offset} is used for delay mode but not
for pulse-generation mode. 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 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 and pulse generation). This is used to account for delays induced by
cabling (range: -2ms to 2ms). The value can be modified cabling (range: -2ms to 2ms). The value can be modified
from @i{sysfs}. from @i{sysfs}.
...@@ -1679,12 +1680,7 @@ The following functions are offered: ...@@ -1679,12 +1680,7 @@ The following functions are offered:
@chapter Calibration @chapter Calibration
Calibration data for a fine-delay card is stored in the I2C FMC EEPROM 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 device, using the SDB filesystem.
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.
The driver automatically loads calibration data from the flash at The driver automatically loads calibration data from the flash at
initialization time, but only uses it if its hash is valid. The initialization time, but only uses it if its hash is valid. The
...@@ -1702,26 +1698,31 @@ time. ...@@ -1702,26 +1698,31 @@ time.
@item calibration_check @item calibration_check
This integer parameter, if not zero, makes the driver dump the binary 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. It is mainly a debug tool.
@item calibration_default @item calibration_default
The user can set this integer parameter to tell the driver to ignore This option should only be used by developers. If not zero, it tells
calibration data found on the EEPROM, thus enacting the compile-time the driver to ignore
defaults. calibration data found on the EEPROM, thus enacting a build-time
default (which is most likely wrong for any board).
@item calibration_load @item calibration_load
This parameter is a string. The name is used to ask the @i{firmware loader} This parameter is a file name, and it should only be used by developers.
to retrieve a file from @file{/lib/firmware}. The driver tries both The name is used to ask the @i{firmware loader}
the name it receives, and if that fails a name with bus and @i{devfn} to retrieve a file from @file{/lib/firmware}.
number appended -- so you can reconfigure a card even if more than one The data, once read, is used only
of them is plugged on the same host. The data, once read, is used only if the size is correct. The hash is regenerated by the driver. Please
if the size is correct (0x54 == 84). remember that all values in the calibration structure are stored as big-endian.
@item calibration_save @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, The integer parameter is used to request saving calibration data to EEPROM,
whatever values are active after the other parameters have been used. whatever values are active after the other parameters have been used.
You can thus save the compiled-in default, the content of the firmware You can thus save the compiled-in default, the content of the firmware
...@@ -1730,8 +1731,8 @@ but not denied either. ...@@ -1730,8 +1731,8 @@ but not denied either.
@end table @end table
This package offers no tool to generate the binary file (the 84 bytes This package currently offers no tool to generate the binary file for
of calibration). the calibration.
@c ########################################################################## @c ##########################################################################
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/jhash.h> #include <linux/jhash.h>
#include "fine-delay.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 */ /* At factory config time, it's possible to load a file and/or write eeprom */
static char *calibration_load; static char *calibration_load;
...@@ -71,48 +72,113 @@ static struct fd_calibration fd_calib_default = { ...@@ -71,48 +72,113 @@ static struct fd_calibration fd_calib_default = {
.magic = 0xf19ede1a, .magic = 0xf19ede1a,
.version = 3, .version = 3,
.date = 0x20130427, .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) int fd_handle_eeprom_calibration(struct fd_dev *fd)
{ {
struct fd_calibration *calib; struct fd_calibration *calib;
struct device *d = fd->fmc->hwdev; struct device *d = fd->fmc->hwdev;
//u32 hash; int i;
u32 hash, horig;
/* Retrieve and validate the calibration */ /* Retrieve and validate the calibration */
calib = &fd->calib; calib = &fd->calib;
/* FIXME: run SDB on the eeprom */ i = fd_read_calibration_eeprom(fd->fmc, calib);
dev_warn(d, "Calibration NOT yet read from eeprom\n"); if (i != sizeof(*calib))
dev_warn(d, "Calibration NOT read from eeprom (got %i)\n", i);
if (calibration_check) if (calibration_check)
dumpstruct("Calibration data from eeprom:", calib, dumpstruct("Calibration data from eeprom:", calib,
sizeof(*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 */ /* FIXME: validate with gateware version */
if (calibration_load) if (calibration_load) {
fd_i2c_load_calib(fd, calib, 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) { if (calibration_default) {
dev_info(d, "Overriding with default calibration\n"); dev_info(d, "Overriding with default calibration\n");
*calib = fd_calib_default; *calib = fd_calib_default;
hash = horig; /* whatever it is */
} }
if (calibration_check) { 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) { if (calibration_save) {
/* FIXME: save to eeprom */ /* FIXME: save to eeprom: re-convert endianness and hash */
dev_warn(d, "Saving is not supported\n"); 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