Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FMC TDC 1ns 5cha - Software
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
FMC TDC 1ns 5cha - Software
Commits
66a090be
Commit
66a090be
authored
Feb 19, 2019
by
Federico Vaga
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drv: add support to set/get run-time calibration data
Signed-off-by:
Federico Vaga
<
federico.vaga@cern.ch
>
parent
9c2c4765
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
169 additions
and
46 deletions
+169
-46
calibration.c
kernel/calibration.c
+115
-37
fmc-tdc.h
kernel/fmc-tdc.h
+36
-9
ft-zio.c
kernel/ft-zio.c
+18
-0
No files found.
kernel/calibration.c
View file @
66a090be
...
...
@@ -17,6 +17,7 @@
#include <linux/jhash.h>
#include <linux/slab.h>
#include <linux/ipmi-fru.h>
#include <linux/zio.h>
#include "libsdbfs.h"
#include "fmc-tdc.h"
...
...
@@ -109,59 +110,136 @@ out:
return
year
;
}
/**
* @calib: calibration data
*
* We know for sure that our structure is only made of 32bit fields
*/
static
void
ft_calib_le32_to_cpus
(
struct
ft_calibration_raw
*
calib
)
{
int
i
;
uint32_t
*
p
=
(
uint32_t
*
)
calib
;
for
(
i
=
0
;
i
<
sizeof
(
*
calib
)
/
sizeof
(
uint32_t
);
i
++
)
le32_to_cpus
(
p
+
i
);
/* s == in situ */
}
/**
* @calib: calibration data
*
* We know for sure that our structure is only made of 32bit fields
*/
static
void
ft_calib_cpu_to_le32s
(
struct
ft_calibration_raw
*
calib
)
{
int
i
;
uint32_t
*
p
=
(
uint32_t
*
)
calib
;
for
(
i
=
0
;
i
<
sizeof
(
*
calib
)
/
sizeof
(
uint32_t
);
i
++
)
cpu_to_le32s
(
p
+
i
);
/* s == in situ */
}
static
void
ft_calib_cpy_from_raw
(
struct
ft_calibration
*
calib
,
struct
ft_calibration_raw
*
calib_raw
)
{
int
i
;
ft_calib_le32_to_cpus
(
calib_raw
);
calib
->
zero_offset
[
0
]
=
0
;
for
(
i
=
1
;
i
<
FT_NUM_CHANNELS
;
i
++
)
calib
->
zero_offset
[
i
]
=
calib_raw
->
zero_offset
[
i
-
1
]
/
100
;
calib
->
vcxo_default_tune
=
calib_raw
->
vcxo_default_tune
/
100
;
calib
->
calibration_temp
=
calib_raw
->
calibration_temp
;
calib
->
wr_offset
=
calib_raw
->
wr_offset
/
100
;
calib
->
wr_offset
+=
wr_calibration_offset_carrier
;
}
static
void
ft_calib_cpy_to_raw
(
struct
ft_calibration_raw
*
calib_raw
,
struct
ft_calibration
*
calib
)
{
int
i
;
for
(
i
=
1
;
i
<
FT_NUM_CHANNELS
;
i
++
)
calib_raw
->
zero_offset
[
i
-
1
]
=
calib
->
zero_offset
[
i
]
*
100
;
calib_raw
->
vcxo_default_tune
=
calib
->
vcxo_default_tune
*
100
;
calib_raw
->
calibration_temp
=
calib
->
calibration_temp
;
calib_raw
->
wr_offset
=
(
calib
->
wr_offset
-
wr_calibration_offset_carrier
)
*
100
;
ft_calib_cpu_to_le32s
(
calib_raw
);
}
/* This is the only thing called by outside */
int
ft_handle_eeprom_calibration
(
struct
fmctdc_dev
*
ft
)
{
struct
ft_calibration
*
calib
;
struct
ft_calibration_raw
calib_raw
;
struct
device
*
d
=
&
ft
->
fmc
->
dev
;
int
i
;
u32
raw_calib
[
7
],
year
;
/* Retrieve and validate the calibration */
calib
=
&
ft
->
calib
;
memcpy
(
calib
,
&
default_calibration
,
sizeof
(
struct
ft_calibration
));
i
=
ft_read_calibration_eeprom
(
ft
->
fmc
,
raw_calib
,
sizeof
(
raw_calib
));
if
(
i
<
0
)
{
i
=
ft_read_calibration_eeprom
(
ft
->
fmc
,
&
calib_raw
,
sizeof
(
calib_raw
));
if
(
i
>=
0
)
{
u32
year
;
ft_calib_cpy_from_raw
(
calib
,
&
calib_raw
);
year
=
__get_ipmi_fru_id_year
(
ft
);
if
(
year
<
WR_OFFSET_FIX_YEAR
)
{
calib
->
wr_offset
=
wr_calibration_offset
;
calib
->
wr_offset
+=
wr_calibration_offset_carrier
;
dev_warn
(
d
,
"Apply default calibration correction to White-Rabbit offset if done before 2018 (%d)
\n
"
,
year
);
}
}
else
{
dev_err
(
d
,
"Failed to read calibration EEPROM. Using default.
\n
"
);
for
(
i
=
0
;
i
<
FT_NUM_CHANNELS
;
i
++
)
calib
->
zero_offset
[
i
]
=
0
;
calib
->
vcxo_default_tune
=
32000
;
}
else
{
calib
->
zero_offset
[
0
]
=
0
;
for
(
i
=
FT_CH_1
+
1
;
i
<
FT_NUM_CHANNELS
;
i
++
)
calib
->
zero_offset
[
i
]
=
le32_to_cpu
(
raw_calib
[
i
-
1
])
/
100
;
calib
->
vcxo_default_tune
=
le32_to_cpu
(
raw_calib
[
4
]);
memcpy
(
calib
,
&
default_calibration
,
sizeof
(
*
calib
));
calib
->
wr_offset
+=
wr_calibration_offset_carrier
;
}
calib
->
calibration_temp
=
le32_to_cpu
(
raw_calib
[
5
])
;
calib
->
wr_offset
=
le32_to_cpu
(
raw_calib
[
6
])
/
100
;
return
0
;
}
year
=
__get_ipmi_fru_id_year
(
ft
);
if
(
year
<
WR_OFFSET_FIX_YEAR
)
{
calib
->
wr_offset
=
wr_calibration_offset
;
dev_warn
(
d
,
"Apply default calibration correction to White-Rabbit offset if done before 2018 (%d)
\n
"
,
year
);
}
calib
->
wr_offset
+=
wr_calibration_offset_carrier
;
static
ssize_t
ft_write_eeprom
(
struct
file
*
file
,
struct
kobject
*
kobj
,
struct
bin_attribute
*
attr
,
char
*
buf
,
loff_t
off
,
size_t
count
)
{
struct
device
*
dev
=
container_of
(
kobj
,
struct
device
,
kobj
);
struct
fmctdc_dev
*
ft
=
to_zio_dev
(
dev
)
->
priv_d
;
struct
ft_calibration_raw
*
calib_raw
=
(
struct
ft_calibration_raw
*
)
buf
;
if
(
ft
->
verbose
)
{
/* Print verbose messages */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
calib
->
zero_offset
);
i
++
)
dev_info
(
d
,
"calib: zero_offset[%i] = %i ps
\n
"
,
i
,
calib
->
zero_offset
[
i
]);
if
(
off
!=
0
||
count
!=
sizeof
(
*
calib_raw
))
return
-
EINVAL
;
dev_info
(
d
,
"calib: vcxo_default_tune %i
\n
"
,
calib
->
vcxo_default_tune
);
dev_info
(
d
,
"calib: wr offset = %i ps
\n
"
,
calib
->
wr_offset
);
}
return
0
;
ft_calib_cpy_from_raw
(
&
ft
->
calib
,
calib_raw
);
return
count
;
}
static
ssize_t
ft_read_eeprom
(
struct
file
*
file
,
struct
kobject
*
kobj
,
struct
bin_attribute
*
attr
,
char
*
buf
,
loff_t
off
,
size_t
count
)
{
struct
device
*
dev
=
container_of
(
kobj
,
struct
device
,
kobj
);
struct
fmctdc_dev
*
ft
=
to_zio_dev
(
dev
)
->
priv_d
;
struct
ft_calibration_raw
*
calib_raw
=
(
struct
ft_calibration_raw
*
)
buf
;
if
(
off
!=
0
||
count
<
sizeof
(
*
calib_raw
))
return
-
EINVAL
;
ft_calib_cpy_to_raw
(
calib_raw
,
&
ft
->
calib
);
return
count
;
}
struct
bin_attribute
dev_attr_calibration
=
{
.
attr
=
{
.
name
=
"calibration_data"
,
.
mode
=
0644
,
},
.
size
=
sizeof
(
struct
ft_calibration_raw
),
.
write
=
ft_write_eeprom
,
.
read
=
ft_read_eeprom
,
};
kernel/fmc-tdc.h
View file @
66a090be
...
...
@@ -14,6 +14,12 @@
#ifndef __FMC_TDC_H__
#define __FMC_TDC_H__
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <stdint.h>
#endif
#define FT_VERSION_MAJ 2
/* version of the driver */
#define FT_VERSION_MIN 1
...
...
@@ -64,6 +70,23 @@ enum ft_command {
FT_CMD_IDENTIFY_OFF
};
/**
* struct ft_calibration - TDC calibration data
* @zero_offset: time difference to channel 1
* @vcxo_default_tune: Default DAC value for VCXO. Set during init and for
* local timing
* @calibration_temp: Temperature at which the device has been calibrated
* @wr_offset: White Rabbit timescale offset in ps
*
* All of these are little endian in the EEPROM
*/
struct
ft_calibration_raw
{
int32_t
zero_offset
[
FT_NUM_CHANNELS
-
1
];
uint32_t
vcxo_default_tune
;
uint32_t
calibration_temp
;
int32_t
wr_offset
;
};
/* rest of the file is kernel-only */
#ifdef __KERNEL__
...
...
@@ -84,17 +107,20 @@ enum ft_channel_flags {
struct
fmctdc_dev
;
struct
ft_calibration
{
/* All of these are big endian in the EEPROM */
/* Input-to-WR timebase offset in ps. */
int32_t
zero_offset
[
5
];
/* Default DAC value for VCXO. Set during init and for local timing */
/**
* struct ft_calibration - TDC calibration data
* @zero_offset: Input-to-WR timebase offset in ps
* @vcxo_default_tune: Default DAC value for VCXO. Set during init and for
* local timing
* @calibration_temp: Temperature at which the device has been calibrated
* @wr_offset: White Rabbit timescale offset in ps
*
* All of these are little endian in the EEPROM
*/
struct
ft_calibration
{
int32_t
zero_offset
[
FT_NUM_CHANNELS
];
uint32_t
vcxo_default_tune
;
/* Temperature at which the device has been calibrated */
uint32_t
calibration_temp
;
/* White Rabbit timescale offset in ps */
int32_t
wr_offset
;
};
...
...
@@ -212,6 +238,7 @@ int ft_wr_mode(struct fmctdc_dev *ft, int on);
int
ft_wr_query
(
struct
fmctdc_dev
*
ft
);
int
ft_handle_eeprom_calibration
(
struct
fmctdc_dev
*
ft
);
extern
struct
bin_attribute
dev_attr_calibration
;
int
ft_irq_init
(
struct
fmctdc_dev
*
ft
);
void
ft_irq_exit
(
struct
fmctdc_dev
*
ft
);
...
...
kernel/ft-zio.c
View file @
66a090be
...
...
@@ -250,15 +250,32 @@ static int ft_zio_conf_set(struct device *dev, struct zio_attribute *zattr,
static
int
ft_zio_probe
(
struct
zio_device
*
zdev
)
{
struct
fmctdc_dev
*
ft
;
int
err
;
/* link the new device from the fd structure */
ft
=
zdev
->
priv_d
;
ft
->
zdev
=
zdev
;
err
=
device_create_bin_file
(
&
zdev
->
head
.
dev
,
&
dev_attr_calibration
);
if
(
err
)
return
err
;
/* We don't have csets at this point, so don't do anything more */
return
0
;
}
/*
* zfad_zio_remove
* @zdev: the real zio device
*/
static
int
ft_zio_remove
(
struct
zio_device
*
zdev
)
{
device_remove_bin_file
(
&
zdev
->
head
.
dev
,
&
dev_attr_calibration
);
return
0
;
}
/* Our sysfs operations to access internal settings */
static
const
struct
zio_sysfs_operations
ft_zio_sysfs_ops
=
{
.
conf_set
=
ft_zio_conf_set
,
...
...
@@ -366,6 +383,7 @@ static struct zio_driver ft_zdrv = {
},
.
id_table
=
ft_table
,
.
probe
=
ft_zio_probe
,
.
remove
=
ft_zio_remove
,
/* Take the version from ZIO git sub-module */
.
min_version
=
ZIO_VERSION
(
__ZIO_MIN_MAJOR_VERSION
,
__ZIO_MIN_MINOR_VERSION
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment