...
 
Commits (8)
......@@ -181,10 +181,18 @@ The ADC registers can be accessed in the proper sysfs directory. For a
card in slot 0 of bus 2 (like shown above), the directory is
*/sys/bus/zio/devices/adc-100m14b-0200*.
The overall device (*adc-100m14b*) does not offer configuration items
besides its own temperature (read-only) because configuration is
specific of the cset and the trigger, or the individual channel.
The overall device (*adc-100m14b*) provides the following attributes:
calibration_data
It is a binary attribute which allows the user to change the runt-time
calibration data (the EEPROM will not be touched). The ``fau-calibration``
tool can be used to read write calibration data.
To be consistent, this binary interface expects **only** little endian
values because this is the endianess used to store calibration data for
this device.
temperature
It shows the current temperature
The Channel Set
'''''''''''''''
......@@ -511,6 +519,13 @@ integer.
- Values
- Comments
* - device
- calibration_data
- rw
- --
-
- Run-time calibration data
* - device
- temperature
- ro
......
......@@ -73,24 +73,40 @@ static void fa_verify_calib(struct device *msgdev,
}
}
static void fa_endian_calib(struct fa_calib *calib)
/**
* @calib: calibration data
*
* We know for sure that our structure is only made of 16bit fields
*/
static void fa_calib_le16_to_cpus(struct fa_calib *calib)
{
int i;
uint16_t *p = (void *)calib;
/* We know for sure that our structure is only made of 16bit fields */
for (i = 0; i < sizeof(*calib) / sizeof(uint16_t); i++)
le16_to_cpus(p + i); /* s == in situ */
}
/**
* @calib: calibration data
*
* We know for sure that our structure is only made of 16bit fields
*/
static void fa_calib_cpu_to_le16s(struct fa_calib *calib)
{
int i;
uint16_t *p = (void *)calib;
for (i = 0; i < sizeof(*calib) / sizeof(uint16_t); i++)
cpu_to_le16s(p + i); /* s == in situ */
}
void fa_identity_calib_set(struct fa_dev *fa)
{
/* Retrieve calibration data from the eeprom, then verify it */
memcpy(&fa->calib, &fa_identity_calib, sizeof(fa->calib));
fa_endian_calib(&fa->calib);
fa_calib_le16_to_cpus(&fa->calib);
fa_verify_calib(&fa->pdev->dev, &fa->calib, &fa_identity_calib);
dev_info(fa->msgdev, "%s succeeds.\n", __func__);
}
/**
......@@ -119,7 +135,7 @@ static ssize_t fa_write_eeprom(struct file *file, struct kobject *kobj,
if (off != 0 || count != sizeof(*calib))
return -EINVAL;
fa_endian_calib(calib);
fa_calib_le16_to_cpus(calib);
fa_verify_calib(dev, calib, &fa_identity_calib);
/*
......@@ -139,11 +155,14 @@ static ssize_t fa_read_eeprom(struct file *file, struct kobject *kobj,
{
struct device *dev = container_of(kobj, struct device, kobj);
struct fa_dev *fa = get_zfadc(dev);
struct fa_calib *calib = (struct fa_calib *) buf;
if (off != 0 || count < sizeof(fa->calib))
return -EINVAL;
memcpy(buf, &fa->calib, sizeof(fa->calib));
memcpy(calib, &fa->calib, sizeof(fa->calib));
fa_calib_cpu_to_le16s(calib);
return count;
}
......@@ -151,7 +170,7 @@ static ssize_t fa_read_eeprom(struct file *file, struct kobject *kobj,
struct bin_attribute dev_attr_calibration = {
.attr = {
.name = "calibration_data",
.mode = 0744,
.mode = 0644,
},
.size = sizeof(struct fa_calib),
.write = fa_write_eeprom,
......
......@@ -544,7 +544,7 @@ static int zfad_zio_probe(struct zio_device *zdev)
if (err)
return err;
err = device_create_bin_file(&zdev->cset->head.dev, &dev_attr_calibration);
err = device_create_bin_file(&zdev->head.dev, &dev_attr_calibration);
if (err)
return err;
......@@ -560,7 +560,7 @@ static int zfad_zio_probe(struct zio_device *zdev)
*/
static int zfad_zio_remove(struct zio_device *zdev)
{
device_remove_bin_file(&zdev->cset->head.dev, &dev_attr_calibration);
device_remove_bin_file(&zdev->head.dev, &dev_attr_calibration);
return 0;
}
......
// SPDX-License-Identifier: GPL-3.0-or-later
/*
* It lists all VME devices
* Copyright (C) 2018 CERN (www.cern.ch)
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
......@@ -15,6 +14,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <endian.h>
#include <fmc-adc-100m14b4cha.h>
......@@ -29,6 +29,7 @@ static const char help_msg[] =
"This could be used to change the ADC calibration data at runtime\n"
"by redirectiong the binary output of this program to the proper \n"
"sysfs binary attribute\n"
"Rembember that we expect all values to be little endian\n"
"\n"
"General options:\n"
"-h Print this message\n"
......@@ -44,33 +45,38 @@ static const char help_msg[] =
/**
* Read calibration data from file
* @path: file path
* @data: data location
* @size: data size
* @calib: calibration data
* @offset: offset in file
*
* Return: number of bytes read
*/
static int fau_calibration_read(char *path, void *data,
size_t size, off_t offset)
static int fau_calibration_read(char *path, struct fa_calib *calib,
off_t offset)
{
int fd;
int ret = 0;
uint16_t *data16 = (uint16_t *)calib;
int i;
fd = open(path, O_RDONLY);
if (fd < 0)
return -1;
ret = lseek(fd, offset, SEEK_SET);
if (ret >= 0)
ret = read(fd, data, size);
ret = read(fd, calib, sizeof(*calib));
close(fd);
/* Fix endianess */
for (i = 0; i < sizeof(*calib) / sizeof(uint16_t); ++i)
data16[i] = le16toh(data16[i]);
return ret;
}
static void fau_calibration_dump_stanza(struct fa_calib_stanza *stanza)
{
fprintf(stdout, " temperature: 0x%x\n",
stanza->temperature);
fprintf(stdout, " temperature: %f C\n",
stanza->temperature * 0.01);
fprintf(stdout, " gain: [0x%04"PRIx16", 0x%04"PRIx16", 0x%04"PRIx16", 0x%04"PRIx16"]\n",
stanza->gain[0],
stanza->gain[1],
......@@ -118,25 +124,33 @@ static void fau_calibration_dump_machine(struct fa_calib *calib)
/**
* Write calibration data to device
* @devid: Device ID
* @data: data location
* @size: data size
* @calib: calibration data
*
* Return: number of bytes wrote
*/
static int fau_calibration_write(unsigned int devid,
void *data, size_t size)
static int fau_calibration_write(unsigned int devid, struct fa_calib *calib)
{
struct fa_calib calib_cp;
char path[128];
uint16_t *data16;
int i;
int fd;
int ret;
sprintf(path,
"/sys/bus/zio/devices/adc-100m14b-%04x/cset0/calibration_data",
"/sys/bus/zio/devices/adc-100m14b-%04x/calibration_data",
devid);
/* Fix endianess */
memcpy(&calib_cp, calib, sizeof(calib_cp));
data16 = (uint16_t *) &calib_cp;
for (i = 0; i < sizeof(calib_cp) / sizeof(uint16_t); ++i)
data16[i] = htole16(data16[i]);
fd = open(path, O_WRONLY);
if (fd < 0)
return -1;
ret = write(fd, data, size);
ret = write(fd, &calib_cp, sizeof(calib_cp));
close(fd);
return ret;
......@@ -195,7 +209,7 @@ int main(int argc, char *argv[])
}
/* Read EEPROM file */
ret = fau_calibration_read(path, &calib, sizeof(calib), offset);
ret = fau_calibration_read(path, &calib, offset);
if (ret < 0) {
fprintf(stderr, "Can't read calibration data from '%s'. %s\n",
path, strerror(errno));
......@@ -216,7 +230,7 @@ int main(int argc, char *argv[])
/* Write calibration data */
if (write) {
ret = fau_calibration_write(devid, &calib, sizeof(calib));
ret = fau_calibration_write(devid, &calib);
if (ret < 0) {
fprintf(stderr,
"Can't write calibration data to '0x%x'. %s\n",
......