Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FMC TDC 1ns 5cha
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
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
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