Commit 4d718e33 authored by Federico Vaga's avatar Federico Vaga

Merge branch 'develop' into feature/platform

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