Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FMC ADC 100M 14b 4cha
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 ADC 100M 14b 4cha
Commits
05bbebf8
Commit
05bbebf8
authored
Sep 07, 2021
by
Federico Vaga
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'release/v6.0.0.rc1'
parents
2f6f18d7
8ce74dac
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
789 additions
and
361 deletions
+789
-361
.gitlab-ci.yml
.gitlab-ci.yml
+7
-0
CHANGELOG.rst
CHANGELOG.rst
+20
-0
index.rst
doc/gateware/index.rst
+6
-3
driver.rst
doc/software/driver.rst
+4
-4
fmc_adc_100Ms_csr.cheby
hdl/cheby/fmc_adc_100Ms_csr.cheby
+2
-4
fmc_adc_100Ms_csr.vhd
hdl/cheby/fmc_adc_100Ms_csr.vhd
+7
-5
ltc2174_2l16b_receiver.vhd
hdl/platform/xilinx/spartan6/ltc2174_2l16b_receiver.vhd
+205
-57
fmc_adc_100Ms_core.vhd
hdl/rtl/fmc_adc_100Ms_core.vhd
+23
-10
fmc_adc_mezzanine.vhd
hdl/rtl/fmc_adc_mezzanine.vhd
+5
-2
fmc_adc_100Ms_csr.v
hdl/testbench/include/fmc_adc_100Ms_csr.v
+2
-2
svec_ref_fmc_adc_100Ms.vhd
hdl/top/svec_ref_design/svec_ref_fmc_adc_100Ms.vhd
+2
-1
Kbuild
software/kernel/Kbuild
+4
-0
fa-calibration.c
software/kernel/fa-calibration.c
+71
-47
fa-core.c
software/kernel/fa-core.c
+144
-23
fa-debug.c
software/kernel/fa-debug.c
+24
-33
fa-dma.c
software/kernel/fa-dma.c
+36
-52
fa-zio-drv.c
software/kernel/fa-zio-drv.c
+36
-34
fa-zio-trg.c
software/kernel/fa-zio-trg.c
+4
-6
fmc-adc-100m14b4ch-spec-core.c
software/kernel/fmc-adc-100m14b4ch-spec-core.c
+18
-6
fmc-adc-100m14b4ch-svec-core.c
software/kernel/fmc-adc-100m14b4ch-svec-core.c
+34
-16
fmc-adc-100m14b4cha-private.h
software/kernel/fmc-adc-100m14b4cha-private.h
+27
-7
fmc-adc-100m14b4cha.h
software/kernel/fmc-adc-100m14b4cha.h
+11
-0
fmc-adc-100m14b4cha.h
software/kernel/platform_data/fmc-adc-100m14b4cha.h
+1
-2
spi.c
software/kernel/spi.c
+5
-2
Makefile
software/tools/Makefile
+4
-0
fau-acq-time.c
software/tools/fau-acq-time.c
+6
-5
fau-calibration.c
software/tools/fau-calibration.c
+49
-27
fau-trg-config.c
software/tools/fau-trg-config.c
+32
-13
No files found.
.gitlab-ci.yml
View file @
05bbebf8
...
...
@@ -26,6 +26,13 @@ cppcheck:
script
:
-
make -C software cppcheck
flawfinder
:
stage
:
static-analysis
image
:
name
:
gitlab-registry.cern.ch/coht/common-containers/static-analysis:latest
script
:
-
make -C software/tools flawfinder
documentation
:
stage
:
build
image
:
...
...
CHANGELOG.rst
View file @
05bbebf8
...
...
@@ -6,6 +6,26 @@
Changelog
=========
6.0.0 - 2021-09-07
==================
Added
-----
- hdl: configurable auto byte swap in hardware, useful for SVEC to reduce software complexity
- hdl,sw: DMA data is always little-endian
- sw: software version validation against FPGA version
- bld: flawfinder check on software tools
Changed
-------
- sw: offsets are not anymore in uV but they are just raw values
Fixed
-----
- sw: security fixes detected by flawfinder
- sw: fixes detected by checkpatch.pl
- sw: style fixes detected by checkpatch.pl
- sw: improve compatibility with newer ( > 3.10) Linux kernel versions
5.0.4 - 2021-07-09
==================
Fixed
...
...
doc/gateware/index.rst
View file @
05bbebf8
...
...
@@ -377,7 +377,7 @@ Mezzanine 1-wire Master
~~~~~~~~~~~~~~~~~~~~~~~
.. note::
FIXME talk about the themometer core in general-cores
FIXME talk about the the
r
mometer core in general-cores
Mezzanine I2C Master
~~~~~~~~~~~~~~~~~~~~
...
...
@@ -470,8 +470,8 @@ register enables the sampling clock (Si570 chip), and the other
internal components. Also, in order to use the input offset DACs, the
``OFFSET_DAC_CLR_N`` field must be set to one.
The field ``
MAN_BITSLIP`` allows to ’manually’ control the ADC data
alignment in the de-serialiser. The fields ``TRIG_LED`` and
The field ``
SERDES_CALIB`` allows to ’manually’ restart the timing
calibration and
alignment in the de-serialiser. The fields ``TRIG_LED`` and
``ACQ_LED`` allows to control the FMC front panel LEDs. Those four
fields are for test purpose only and must stay zero in normal
operation.
...
...
@@ -1047,6 +1047,9 @@ state.
The start of an acquisition is prohibited if either the number of
shots or the number of post-trigger samples is equal to zero.
.. note::
Acquired data are always stored to be read in little endian.
Single-shot Mode
----------------
...
...
doc/software/driver.rst
View file @
05bbebf8
...
...
@@ -195,16 +195,16 @@ chN-50ohm-term
turn on the termination resistor. Default is 0.
chN-offset
The user offset is an integer value in the range [-5
000000,5000000], and
it represents microvolts. The offset represents the center-scale
of conversion for the input channel.
Internally, a DAC is used to
The user offset is an integer value in the range [-5
.000V, +4.999V]. It
follows the DAC data format, so the range is describe by 16bits from 0x0000
(-5.000V) to 0xFFFF (+4.999V).
Internally, a DAC is used to
generate the requested voltage, which is then subtracted from the
input signal. DAC values are corrected according to the
calibration values retrieved from the FMC EEPROM. For this reason,
the offset may saturate at values less than +/- 5V.
chN-offset-zero
The necessary offset to to bring the signal to 0 in
microv
olts (it must be
The necessary offset to to bring the signal to 0 in
V
olts (it must be
withing the range of chN-offset).
chN-vref
...
...
hdl/cheby/fmc_adc_100Ms_csr.cheby
View file @
05bbebf8
...
...
@@ -41,11 +41,9 @@ memory-map:
range: 3
description: Offset DACs clear (active low)
- field:
name:
man_bitslip
name:
serdes_calib
range: 4
description: Manual serdes bitslip (ignore on read)
x-hdl:
type: wire
description: Initial serdes calibration
- field:
name: trig_led
range: 6
...
...
hdl/cheby/fmc_adc_100Ms_csr.vhd
View file @
05bbebf8
...
...
@@ -15,7 +15,7 @@ package fmc_adc_100ms_csr_pkg is
ctl_fsm_cmd
:
std_logic_vector
(
1
downto
0
);
ctl_fmc_clk_oe
:
std_logic
;
ctl_offset_dac_clr_n
:
std_logic
;
ctl_
man_bitslip
:
std_logic
;
ctl_
serdes_calib
:
std_logic
;
ctl_trig_led
:
std_logic
;
ctl_acq_led
:
std_logic
;
ctl_clear_trig_stat
:
std_logic
;
...
...
@@ -47,7 +47,6 @@ package fmc_adc_100ms_csr_pkg is
type
t_fmc_adc_100ms_csr_slave_out
is
record
ctl_fsm_cmd
:
std_logic_vector
(
1
downto
0
);
ctl_man_bitslip
:
std_logic
;
ctl_clear_trig_stat
:
std_logic
;
ctl_calib_apply
:
std_logic
;
sta_fsm
:
std_logic_vector
(
2
downto
0
);
...
...
@@ -120,6 +119,7 @@ architecture syn of fmc_adc_100ms_csr is
signal
wb_wip
:
std_logic
;
signal
ctl_fmc_clk_oe_reg
:
std_logic
;
signal
ctl_offset_dac_clr_n_reg
:
std_logic
;
signal
ctl_serdes_calib_reg
:
std_logic
;
signal
ctl_trig_led_reg
:
std_logic
;
signal
ctl_acq_led_reg
:
std_logic
;
signal
ctl_wreq
:
std_logic
;
...
...
@@ -250,7 +250,7 @@ begin
fmc_adc_100ms_csr_o
.
ctl_fsm_cmd
<=
wr_dat_d0
(
1
downto
0
);
fmc_adc_100ms_csr_o
.
ctl_fmc_clk_oe
<=
ctl_fmc_clk_oe_reg
;
fmc_adc_100ms_csr_o
.
ctl_offset_dac_clr_n
<=
ctl_offset_dac_clr_n_reg
;
fmc_adc_100ms_csr_o
.
ctl_
man_bitslip
<=
wr_dat_d0
(
4
)
;
fmc_adc_100ms_csr_o
.
ctl_
serdes_calib
<=
ctl_serdes_calib_reg
;
fmc_adc_100ms_csr_o
.
ctl_trig_led
<=
ctl_trig_led_reg
;
fmc_adc_100ms_csr_o
.
ctl_acq_led
<=
ctl_acq_led_reg
;
fmc_adc_100ms_csr_o
.
ctl_clear_trig_stat
<=
wr_dat_d0
(
8
);
...
...
@@ -260,6 +260,7 @@ begin
if
rst_n_i
=
'0'
then
ctl_fmc_clk_oe_reg
<=
'0'
;
ctl_offset_dac_clr_n_reg
<=
'0'
;
ctl_serdes_calib_reg
<=
'0'
;
ctl_trig_led_reg
<=
'0'
;
ctl_acq_led_reg
<=
'0'
;
ctl_wack
<=
'0'
;
...
...
@@ -267,6 +268,7 @@ begin
if
ctl_wreq
=
'1'
then
ctl_fmc_clk_oe_reg
<=
wr_dat_d0
(
2
);
ctl_offset_dac_clr_n_reg
<=
wr_dat_d0
(
3
);
ctl_serdes_calib_reg
<=
wr_dat_d0
(
4
);
ctl_trig_led_reg
<=
wr_dat_d0
(
6
);
ctl_acq_led_reg
<=
wr_dat_d0
(
7
);
end
if
;
...
...
@@ -624,7 +626,7 @@ begin
end
process
;
-- Process for read requests.
process
(
rd_adr_d0
,
rd_req_d0
,
fmc_adc_100ms_csr_i
.
ctl_fsm_cmd
,
ctl_fmc_clk_oe_reg
,
ctl_offset_dac_clr_n_reg
,
fmc_adc_100ms_csr_i
.
ctl_man_bitslip
,
ctl_trig_led_reg
,
ctl_acq_led_reg
,
fmc_adc_100ms_csr_i
.
ctl_clear_trig_stat
,
fmc_adc_100ms_csr_i
.
ctl_calib_apply
,
fmc_adc_100ms_csr_i
.
sta_fsm
,
fmc_adc_100ms_csr_i
.
sta_serdes_pll
,
fmc_adc_100ms_csr_i
.
sta_serdes_synced
,
fmc_adc_100ms_csr_i
.
sta_acq_cfg
,
fmc_adc_100ms_csr_i
.
sta_fmc_nr
,
fmc_adc_100ms_csr_i
.
sta_calib_busy
,
fmc_adc_100ms_csr_i
.
trig_stat_ext
,
fmc_adc_100ms_csr_i
.
trig_stat_sw
,
fmc_adc_100ms_csr_i
.
trig_stat_time
,
fmc_adc_100ms_csr_i
.
trig_stat_ch1
,
fmc_adc_100ms_csr_i
.
trig_stat_ch2
,
fmc_adc_100ms_csr_i
.
trig_stat_ch3
,
fmc_adc_100ms_csr_i
.
trig_stat_ch4
,
trig_en_ext_reg
,
fmc_adc_100ms_csr_i
.
trig_en_sw
,
trig_en_time_reg
,
fmc_adc_100ms_csr_i
.
trig_en_aux_time
,
trig_en_ch1_reg
,
trig_en_ch2_reg
,
trig_en_ch3_reg
,
trig_en_ch4_reg
,
trig_pol_ext_reg
,
trig_pol_ch1_reg
,
trig_pol_ch2_reg
,
trig_pol_ch3_reg
,
trig_pol_ch4_reg
,
ext_trig_dly_reg
,
shots_nbr_reg
,
fmc_adc_100ms_csr_i
.
shots_remain
,
fmc_adc_100ms_csr_i
.
multi_depth
,
fmc_adc_100ms_csr_i
.
trig_pos
,
fmc_adc_100ms_csr_i
.
fs_freq
,
downsample_reg
,
pre_samples_reg
,
post_samples_reg
,
fmc_adc_100ms_csr_i
.
samples_cnt
,
fmc_adc_ch1_i
.
dat
,
fmc_adc_ch1_rack
,
fmc_adc_ch2_i
.
dat
,
fmc_adc_ch2_rack
,
fmc_adc_ch3_i
.
dat
,
fmc_adc_ch3_rack
,
fmc_adc_ch4_i
.
dat
,
fmc_adc_ch4_rack
)
begin
process
(
rd_adr_d0
,
rd_req_d0
,
fmc_adc_100ms_csr_i
.
ctl_fsm_cmd
,
ctl_fmc_clk_oe_reg
,
ctl_offset_dac_clr_n_reg
,
ctl_serdes_calib_reg
,
ctl_trig_led_reg
,
ctl_acq_led_reg
,
fmc_adc_100ms_csr_i
.
ctl_clear_trig_stat
,
fmc_adc_100ms_csr_i
.
ctl_calib_apply
,
fmc_adc_100ms_csr_i
.
sta_fsm
,
fmc_adc_100ms_csr_i
.
sta_serdes_pll
,
fmc_adc_100ms_csr_i
.
sta_serdes_synced
,
fmc_adc_100ms_csr_i
.
sta_acq_cfg
,
fmc_adc_100ms_csr_i
.
sta_fmc_nr
,
fmc_adc_100ms_csr_i
.
sta_calib_busy
,
fmc_adc_100ms_csr_i
.
trig_stat_ext
,
fmc_adc_100ms_csr_i
.
trig_stat_sw
,
fmc_adc_100ms_csr_i
.
trig_stat_time
,
fmc_adc_100ms_csr_i
.
trig_stat_ch1
,
fmc_adc_100ms_csr_i
.
trig_stat_ch2
,
fmc_adc_100ms_csr_i
.
trig_stat_ch3
,
fmc_adc_100ms_csr_i
.
trig_stat_ch4
,
trig_en_ext_reg
,
fmc_adc_100ms_csr_i
.
trig_en_sw
,
trig_en_time_reg
,
fmc_adc_100ms_csr_i
.
trig_en_aux_time
,
trig_en_ch1_reg
,
trig_en_ch2_reg
,
trig_en_ch3_reg
,
trig_en_ch4_reg
,
trig_pol_ext_reg
,
trig_pol_ch1_reg
,
trig_pol_ch2_reg
,
trig_pol_ch3_reg
,
trig_pol_ch4_reg
,
ext_trig_dly_reg
,
shots_nbr_reg
,
fmc_adc_100ms_csr_i
.
shots_remain
,
fmc_adc_100ms_csr_i
.
multi_depth
,
fmc_adc_100ms_csr_i
.
trig_pos
,
fmc_adc_100ms_csr_i
.
fs_freq
,
downsample_reg
,
pre_samples_reg
,
post_samples_reg
,
fmc_adc_100ms_csr_i
.
samples_cnt
,
fmc_adc_ch1_i
.
dat
,
fmc_adc_ch1_rack
,
fmc_adc_ch2_i
.
dat
,
fmc_adc_ch2_rack
,
fmc_adc_ch3_i
.
dat
,
fmc_adc_ch3_rack
,
fmc_adc_ch4_i
.
dat
,
fmc_adc_ch4_rack
)
begin
-- By default ack read requests
rd_dat_d0
<=
(
others
=>
'X'
);
fmc_adc_ch1_re
<=
'0'
;
...
...
@@ -640,7 +642,7 @@ begin
rd_dat_d0
(
1
downto
0
)
<=
fmc_adc_100ms_csr_i
.
ctl_fsm_cmd
;
rd_dat_d0
(
2
)
<=
ctl_fmc_clk_oe_reg
;
rd_dat_d0
(
3
)
<=
ctl_offset_dac_clr_n_reg
;
rd_dat_d0
(
4
)
<=
fmc_adc_100ms_csr_i
.
ctl_man_bitslip
;
rd_dat_d0
(
4
)
<=
ctl_serdes_calib_reg
;
rd_dat_d0
(
5
)
<=
'0'
;
rd_dat_d0
(
6
)
<=
ctl_trig_led_reg
;
rd_dat_d0
(
7
)
<=
ctl_acq_led_reg
;
...
...
hdl/platform/xilinx/spartan6/ltc2174_2l16b_receiver.vhd
View file @
05bbebf8
This diff is collapsed.
Click to expand it.
hdl/rtl/fmc_adc_100Ms_core.vhd
View file @
05bbebf8
...
...
@@ -40,6 +40,8 @@ entity fmc_adc_100Ms_core is
g_TRIG_DELAY_SW
:
natural
:
=
9
;
-- FMC-ADC identification number
g_FMC_ADC_NR
:
natural
:
=
0
;
-- Data endianness. If set, swap memory data byte
g_BYTE_SWAP
:
boolean
:
=
false
;
-- WB interface configuration
g_WB_CSR_MODE
:
t_wishbone_interface_mode
:
=
PIPELINED
;
g_WB_CSR_GRANULARITY
:
t_wishbone_address_granularity
:
=
BYTE
);
...
...
@@ -71,7 +73,7 @@ entity fmc_adc_100Ms_core is
acq_stop_p_o
:
out
std_logic
;
acq_end_p_o
:
out
std_logic
;
-- Trigger time-tag inputs
-- Trigger time-tag inputs
(sys_clk_i)
trigger_tag_i
:
in
t_timetag
;
time_trig_i
:
in
std_logic
;
aux_time_trig_i
:
in
std_logic
;
...
...
@@ -151,8 +153,7 @@ architecture rtl of fmc_adc_100Ms_core is
-- SerDes
signal
serdes_out_data
:
std_logic_vector
(
63
downto
0
);
signal
serdes_out_data_synced
:
std_logic_vector
(
63
downto
0
);
signal
serdes_man_bitslip
:
std_logic
;
signal
serdes_man_bitslip_sync
:
std_logic
;
signal
serdes_calib_sync
:
std_logic
;
signal
serdes_locked
:
std_logic
;
signal
serdes_locked_sync
:
std_logic
;
signal
serdes_synced
:
std_logic
;
...
...
@@ -293,6 +294,7 @@ architecture rtl of fmc_adc_100Ms_core is
-- Wishbone to DDR flowcontrol FIFO
signal
wb_ddr_fifo_din
:
std_logic_vector
(
64
downto
0
);
signal
wb_ddr_fifo_dout
:
std_logic_vector
(
64
downto
0
);
signal
wb_ddr_fifo_dout2
:
std_logic_vector
(
63
downto
0
);
signal
wb_ddr_fifo_empty
:
std_logic
;
signal
wb_ddr_fifo_full
:
std_logic
;
signal
wb_ddr_fifo_wr
:
std_logic
;
...
...
@@ -427,8 +429,8 @@ begin
port
map
(
clk_i
=>
fs_clk
,
rst_n_a_i
=>
'1'
,
d_i
=>
serdes_man_bitslip
,
q_o
=>
serdes_
man_bitslip
_sync
);
d_i
=>
csr_regout
.
ctl_serdes_calib
,
q_o
=>
serdes_
calib
_sync
);
cmp_adc_serdes
:
entity
work
.
ltc2174_2l16b_receiver
generic
map
(
...
...
@@ -443,7 +445,7 @@ begin
adc_outb_p_i
=>
adc_outb_p_i
,
adc_outb_n_i
=>
adc_outb_n_i
,
serdes_arst_i
=>
serdes_arst
,
serdes_
bslip_i
=>
serdes_man_bitslip
_sync
,
serdes_
calib_i
=>
serdes_calib
_sync
,
serdes_locked_o
=>
serdes_locked
,
serdes_synced_o
=>
serdes_synced
,
adc_data_o
=>
serdes_out_data
,
...
...
@@ -484,7 +486,6 @@ begin
fmc_adc_ch4_o
=>
wb_channel_in
(
4
));
csr_regin
.
ctl_fsm_cmd
<=
fsm_cmd
;
csr_regin
.
ctl_man_bitslip
<=
serdes_man_bitslip
;
csr_regin
.
ctl_clear_trig_stat
<=
trig_storage_clear
;
csr_regin
.
ctl_calib_apply
<=
sync_calib_apply
;
...
...
@@ -530,12 +531,10 @@ begin
if
rising_edge
(
sys_clk_i
)
then
if
ctl_reg_wr
=
'1'
then
fsm_cmd
<=
csr_regout
.
ctl_fsm_cmd
;
serdes_man_bitslip
<=
csr_regout
.
ctl_man_bitslip
;
trig_storage_clear
<=
csr_regout
.
ctl_clear_trig_stat
;
sync_calib_apply
<=
csr_regout
.
ctl_calib_apply
;
else
fsm_cmd
<=
(
others
=>
'0'
);
serdes_man_bitslip
<=
'0'
;
trig_storage_clear
<=
'0'
;
sync_calib_apply
<=
'0'
;
end
if
;
...
...
@@ -1633,6 +1632,20 @@ begin
-- Convert to 32-bit word addressing for Wishbone
wb_ddr_skidpad_adr_in
<=
std_logic_vector
(
ram_addr_cnt
);
gen_no_byte_swap
:
if
not
g_BYTE_SWAP
generate
wb_ddr_fifo_dout2
<=
wb_ddr_fifo_dout
(
63
downto
0
);
end
generate
;
gen_byte_swap
:
if
g_BYTE_SWAP
generate
wb_ddr_fifo_dout2
(
63
downto
32
)
<=
(
wb_ddr_fifo_dout
(
39
downto
32
)
&
wb_ddr_fifo_dout
(
47
downto
40
)
&
wb_ddr_fifo_dout
(
55
downto
48
)
&
wb_ddr_fifo_dout
(
63
downto
56
));
wb_ddr_fifo_dout2
(
31
downto
0
)
<=
(
wb_ddr_fifo_dout
(
7
downto
0
)
&
wb_ddr_fifo_dout
(
15
downto
8
)
&
wb_ddr_fifo_dout
(
23
downto
16
)
&
wb_ddr_fifo_dout
(
31
downto
24
));
end
generate
;
inst_skidpad
:
entity
work
.
wb_skidpad2
generic
map
(
g_adrbits
=>
ram_addr_cnt
'length
,
...
...
@@ -1644,7 +1657,7 @@ begin
stb_i
=>
wb_ddr_skidpad_stb_in
,
adr_i
=>
wb_ddr_skidpad_adr_in
,
dat_i
=>
wb_ddr_fifo_dout
(
63
downto
0
)
,
dat_i
=>
wb_ddr_fifo_dout
2
,
sel_i
=>
(
others
=>
'1'
),
we_i
=>
'1'
,
stall_o
=>
wb_ddr_skidpad_stall
,
...
...
hdl/rtl/fmc_adc_mezzanine.vhd
View file @
05bbebf8
...
...
@@ -41,6 +41,8 @@ entity fmc_adc_mezzanine is
g_TAG_ADJUST
:
natural
:
=
27
;
-- FMC-ADC identification number
g_FMC_ADC_NR
:
natural
:
=
0
;
-- Data endianness. If set, swap memory data byte
g_BYTE_SWAP
:
boolean
:
=
false
;
-- WB interface configuration
g_WB_MODE
:
t_wishbone_interface_mode
:
=
PIPELINED
;
g_WB_GRANULARITY
:
t_wishbone_address_granularity
:
=
BYTE
);
...
...
@@ -67,11 +69,11 @@ entity fmc_adc_mezzanine is
acq_cfg_ok_o
:
out
std_logic
;
-- Auxiliary trigger input wishbone interface
wb_trigin_slave_i
:
in
t_wishbone_slave_in
;
wb_trigin_slave_i
:
in
t_wishbone_slave_in
:
=
c_DUMMY_WB_SLAVE_IN
;
wb_trigin_slave_o
:
out
t_wishbone_slave_out
;
-- Trigout wishbone interface
wb_trigout_slave_i
:
in
t_wishbone_slave_in
;
wb_trigout_slave_i
:
in
t_wishbone_slave_in
:
=
c_DUMMY_WB_SLAVE_IN
;
wb_trigout_slave_o
:
out
t_wishbone_slave_out
;
-- FMC interface
...
...
@@ -309,6 +311,7 @@ begin
g_TRIG_DELAY_EXT
=>
g_TRIG_DELAY_EXT
,
g_TRIG_DELAY_SW
=>
g_TRIG_DELAY_SW
,
g_FMC_ADC_NR
=>
g_FMC_ADC_NR
,
g_BYTE_SWAP
=>
g_BYTE_SWAP
,
g_WB_CSR_MODE
=>
PIPELINED
,
g_WB_CSR_GRANULARITY
=>
BYTE
)
port
map
(
...
...
hdl/testbench/include/fmc_adc_100Ms_csr.v
View file @
05bbebf8
...
...
@@ -10,8 +10,8 @@
`define
FMC_ADC_100MS_CSR_CTL_FMC_CLK_OE
'
h4
`define
FMC_ADC_100MS_CSR_CTL_OFFSET_DAC_CLR_N_OFFSET 3
`define
FMC_ADC_100MS_CSR_CTL_OFFSET_DAC_CLR_N
'
h8
`define
FMC_ADC_100MS_CSR_CTL_
MAN_BITSLIP
_OFFSET 4
`define
FMC_ADC_100MS_CSR_CTL_
MAN_BITSLIP
'
h10
`define
FMC_ADC_100MS_CSR_CTL_
SERDES_CALIB
_OFFSET 4
`define
FMC_ADC_100MS_CSR_CTL_
SERDES_CALIB
'
h10
`define
FMC_ADC_100MS_CSR_CTL_TRIG_LED_OFFSET 6
`define
FMC_ADC_100MS_CSR_CTL_TRIG_LED
'
h40
`define
FMC_ADC_100MS_CSR_CTL_ACQ_LED_OFFSET 7
...
...
hdl/top/svec_ref_design/svec_ref_fmc_adc_100Ms.vhd
View file @
05bbebf8
...
...
@@ -531,10 +531,11 @@ begin -- architecture arch
d_i
=>
fmc_irq
(
I
),
q_o
=>
irq_vector
(
I
));
cmp_fmc_adc_mezzanine
:
fmc_adc_mezzanine
cmp_fmc_adc_mezzanine
:
entity
work
.
fmc_adc_mezzanine
generic
map
(
g_MULTISHOT_RAM_SIZE
=>
g_MULTISHOT_RAM_SIZE
,
g_SPARTAN6_USE_PLL
=>
TRUE
,
g_BYTE_SWAP
=>
TRUE
,
g_FMC_ADC_NR
=>
I
,
g_WB_MODE
=>
PIPELINED
,
g_WB_GRANULARITY
=>
BYTE
)
...
...
software/kernel/Kbuild
View file @
05bbebf8
...
...
@@ -8,12 +8,16 @@ VMEBUS_EXTRA_SYMBOLS-$(CONFIG_FMC_ADC_SVEC) := $(VMEBUS_ABS)/driver/Module.symve
ZIO_VERSION = $(shell cd $(ZIO_ABS); git describe --always --dirty --long --tags)
VERSION = $(shell cd $(src); git describe --always --dirty --long --tags)
VER_MAJ := $(shell echo $(subst v,,$(VERSION)) | cut -d '.' -f 1)
VER_MIN := $(shell echo $(subst v,,$(VERSION)) | cut -d '.' -f 2)
FA_VERSION_BLD := $(shell printf "0x%02x%02x0000" $(VER_MAJ) $(VER_MIN))
KBUILD_EXTRA_SYMBOLS += $(ZIO_EXTRA_SYMBOLS-y)
KBUILD_EXTRA_SYMBOLS += $(FMC_EXTRA_SYMBOLS-y)
KBUILD_EXTRA_SYMBOLS += $(VMEBUS_EXTRA_SYMBOLS-y)
ccflags-y = -DVERSION=\"$(VERSION)\"
ccflags-y += -DFA_VERSION_BLD=$(FA_VERSION_BLD)
ccflags-y += -DCONFIG_FMC_ADC_SVEC
ccflags-y += -I$(src)
ccflags-y += -I$(ZIO_ABS)/include
...
...
software/kernel/fa-calibration.c
View file @
05bbebf8
// SPDX-FileCopyrightText: 2020 CERN (home.cern)
//
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2020 CERN (home.cern)
/*
* EEPROM calibration block retreival code for fa-dev
...
...
@@ -16,10 +15,10 @@
#include <linux/jiffies.h>
#include "fmc-adc-100m14b4cha-private.h"
static
int
fa_calib_temp_period
=
0
;
static
int
fa_calib_temp_period
;
module_param_named
(
temp_calib_period
,
fa_calib_temp_period
,
int
,
0444
);
static
int
fa_calib_temp
=
0
;
static
int
fa_calib_temp
;
module_param_named
(
temp_calib
,
fa_calib_temp
,
int
,
0444
);
/* This identity calibration is used as default */
...
...
@@ -48,7 +47,7 @@ static int fa_calib_apply(struct fa_dev *fa)
return
-
EBUSY
;
}
fa_writel
(
fa
,
fa
->
fa_adc_csr_base
,
&
zfad_regs
[
ZFA_CTL_CALIB_APPLY
],
1
);
ndelay
(
100
);
ndelay
(
100
);
if
(
fa_calib_is_busy
(
fa
))
{
dev_err
(
&
fa
->
pdev
->
dev
,
"%s Calibration value applied but still 'busy'
\n
"
,
...
...
@@ -134,7 +133,7 @@ static const int64_t gain_dac_error_slope_fix[] = {
static
int
fa_calib_dac_gain_fix
(
int
range
,
uint32_t
gain_c
,
int32_t
delta_temp
)
{
int64_t
error
;
int64_t
error
;
error
=
gain_dac_error_slope_fix
[
range
]
*
delta_temp
;
error
/=
0x2000
;
/* see comment above for gain_dac_error_slope_fix */
...
...
@@ -148,7 +147,7 @@ static bool fa_calib_is_compensation_on(struct fa_dev *fa)
if
(
unlikely
((
fa
->
flags
&
FA_DEV_F_PATTERN_DATA
)))
return
false
;
if
(
unlikely
(
fa_calib_temp
))
if
(
unlikely
(
fa_calib_temp
))
return
true
;
return
false
;
...
...
@@ -208,47 +207,52 @@ static int fa_dac_offset_set(struct fa_dev *fa, unsigned int chan,
return
fa_spi_xfer
(
fa
,
FA_SPI_SS_DAC
(
chan
),
16
,
val
,
NULL
);
}
static
int64_t
fa_dac_offset_raw_get
(
int32_t
offset
)
static
uint16_t
fa_dac_offset_raw_calibrate
(
struct
fa_dev
*
fa
,
uint16_t
raw_offset
,
int
gain
,
int
offset
)
{
int32_t
signed_offset
=
raw_offset
-
0x8000
;
int64_t
hwval
;
hwval
=
offset
*
0x8000LL
/
5000000
;
if
(
hwval
==
0x8000
)
hwval
=
0x7fff
;
/* -32768 .. 32767 */
return
hwval
;
}
static
int64_t
fa_dac_offset_raw_calibrate
(
int32_t
raw_offset
,
int
gain
,
int
offset
)
{
int64_t
hwval
;
hwval
=
((
signed_offset
+
offset
)
*
gain
)
>>
15
;
/* signed */
hwval
+=
0x8000
;
/* offset binary */
dev_dbg
(
&
fa
->
pdev
->
dev
,
"Final DAC calibrated value: (0x%08x + 0x%08x) * 0x%08x = 0x%08llx
\n
"
,
signed_offset
,
offset
,
gain
,
hwval
);
hwval
=
((
raw_offset
+
offset
)
*
gain
)
>>
15
;
/* signed */
hwval
+=
0x8000
;
/* offset binary */
if
(
hwval
<
0
)
/* Saturate */
if
(
hwval
<
0
)
{
hwval
=
0
;
if
(
hwval
>
0xffff
)
dev_warn
(
&
fa
->
pdev
->
dev
,
"Final DAC calibrated value: lower saturation, set 0x%04llx"
,
hwval
);
}
if
(
hwval
>
0xffff
)
{
hwval
=
0xffff
;
dev_warn
(
&
fa
->
pdev
->
dev
,
"Final DAC calibrated value: lower saturation, set 0x%04llx"
,
hwval
);
}
return
hwval
;
}
static
int
fa_dac_offset_get
(
struct
fa_dev
*
fa
,
unsigned
int
chan
)
static
int
fa_dac_offset_get
(
struct
fa_dev
*
fa
,
unsigned
int
chan
,
uint16_t
*
offset
)
{
int32_t
off_uv
=
fa
->
user_offset
[
chan
]
+
fa
->
zero_offset
[
chan
];
int32_t
user
=
fa
->
user_offset
[
chan
];
int32_t
zero
=
fa
->
zero_offset
[
chan
];
int32_t
__offset
=
(
user
+
zero
)
-
0x8000
;
/* Bring back to DAC format */
if
(
WARN
(
off_uv
<
DAC_SAT_LOW
,
"DAC lower saturation %d < %d
\n
"
,
off_uv
,
DAC_SAT_LOW
))
{
off_uv
=
DAC_SAT_LOW
;
}
if
(
WARN
(
off_uv
>
DAC_SAT_UP
,
"DAC upper saturation %d > %d
\n
"
,
off_uv
,
DAC_SAT_UP
))
{
off_uv
=
DAC_SAT_UP
;
if
(
__offset
&
~
DAC_VAL_MASK
)
{
dev_err
(
&
fa
->
pdev
->
dev
,
"DAC offset value overflows 16bits. {user: 0x%04x, zero: 0x%04x, sum: 0x%08x}
\n
"
,
user
,
zero
,
__offset
);
return
-
EINVAL
;
}
return
off_uv
;
*
offset
=
__offset
;
return
0
;
}
/**
...
...
@@ -262,12 +266,16 @@ static int fa_dac_offset_get(struct fa_dev *fa, unsigned int chan)
int
fa_calib_dac_config_chan
(
struct
fa_dev
*
fa
,
unsigned
int
chan
,
int32_t
temperature
,
unsigned
int
flags
)
{
int32_t
off_uv
=
fa_dac_offset_get
(
fa
,
chan
);
int32_t
off_uv_raw
=
fa_dac_offset_raw_get
(
off_uv
);
int
range
=
fa
->
range
[
chan
];
struct
fa_calib_stanza
*
cal
=
&
fa
->
calib
.
dac
[
range
];
uint16_t
value
;
int
range
=
fa
->
range
[
chan
];
struct
fa_calib_stanza
*
cal
=
&
fa
->
calib
.
dac
[
range
];
int
gain
;
int
hwval
;
int
err
;
err
=
fa_dac_offset_get
(
fa
,
chan
,
&
value
);
if
(
err
)
return
err
;
if
(
fa_calib_is_compensation_on
(
fa
))
{
int32_t
delta_temp
;
...
...
@@ -287,10 +295,10 @@ int fa_calib_dac_config_chan(struct fa_dev *fa, unsigned int chan,
__func__
,
chan
,
range
,
gain
,
cal
->
offset
[
chan
]);
}
hwval
=
fa_dac_offset_raw_calibrate
(
off_uv_raw
,
gain
,
hwval
=
fa_dac_offset_raw_calibrate
(
fa
,
value
,
gain
,
cal
->
offset
[
chan
]);
return
fa_dac_offset_set
(
fa
,
chan
,
hwval
);
return
fa_dac_offset_set
(
fa
,
chan
,
hwval
);
}
void
fa_calib_config_chan
(
struct
fa_dev
*
fa
,
unsigned
int
chan
,
...
...
@@ -311,6 +319,14 @@ void fa_calib_config(struct fa_dev *fa)
fa_calib_config_chan
(
fa
,
i
,
temperature
,
0
);
spin_unlock
(
&
fa
->
zdev
->
cset
->
lock
);
}
static
void
__fa_calib_gain_update
(
struct
fa_dev
*
fa
)
{
fa_calib_config
(
fa
);
mod_timer
(
&
fa
->
calib_timer
,
jiffies
+
HZ
*
fa_calib_temp_period
);
}
/**
* Periodically update gain calibration values
* @fa: FMC ADC device
...
...
@@ -320,14 +336,17 @@ void fa_calib_config(struct fa_dev *fa)
* linear behavior with respect to the temperature.
*
*/
#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
static
void
fa_calib_gain_update
(
struct
timer_list
*
timer
)
{
__fa_calib_gain_update
(
from_timer
(
fa
,
timer
,
calib_timer
));
}
#else
static
void
fa_calib_gain_update
(
unsigned
long
arg
)
{
struct
fa_dev
*
fa
=
(
void
*
)
arg
;
fa_calib_config
(
fa
);
mod_timer
(
&
fa
->
calib_timer
,
jiffies
+
HZ
*
fa_calib_temp_period
);
__fa_calib_gain_update
((
void
*
)
arg
);
}
#endif
/* Actual verification code */
static
int
fa_verify_calib_stanza
(
struct
device
*
msgdev
,
char
*
name
,
int
r
,
struct
fa_calib_stanza
*
cal
)
...
...
@@ -493,14 +512,19 @@ int fa_calib_init(struct fa_dev *fa)
fa_calib_write
(
fa
,
&
calib
);
/* First calibration.
The board has just been reset by the carrier before calling this
driver and reading the temperature read needs at least 350ms */
* The board has just been reset by the carrier before calling this
* driver and reading the temperature read needs at least 350ms
*/
msleep
(
400
);
fa_calib_config
(
fa
);
/* Prepare the timely recalibration */
if
(
fa_calib_is_compensation_on
(
fa
)
&&
fa_calib_temp_period
)
{
#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
timer_setup
(
&
fa
->
calib_timer
,
fa_calib_gain_update
,
0
);
#else
setup_timer
(
&
fa
->
calib_timer
,
fa_calib_gain_update
,
(
unsigned
long
)
fa
);
#endif
mod_timer
(
&
fa
->
calib_timer
,
jiffies
+
HZ
*
fa_calib_temp_period
);
}
...
...
software/kernel/fa-core.c
View file @
05bbebf8
...
...
@@ -12,6 +12,7 @@
#include <linux/mod_devicetable.h>
#include <uapi/linux/ipmi/fru.h>
#include <linux/fmc.h>
#include <linux/io.h>
#include "fmc-adc-100m14b4cha-private.h"
#include <platform_data/fmc-adc-100m14b4cha.h>
...
...
@@ -19,6 +20,12 @@
static
int
fa_enable_test_data_fpga
;
module_param_named
(
enable_test_data_fpga
,
fa_enable_test_data_fpga
,
int
,
0444
);
static
int
version_ignore
;
module_param
(
version_ignore
,
int
,
0644
);
MODULE_PARM_DESC
(
version_ignore
,
"Ignore the version declared in the FPGA and force the driver to load all components (default 0)"
);
#define FA_EEPROM_TYPE "at24c64"
...
...
@@ -36,6 +43,29 @@ static const int zfad_hw_range[] = {
struct
workqueue_struct
*
fa_workqueue
;
static
int
fa_sg_alloc_table_from_pages
(
struct
sg_table
*
sgt
,
struct
page
**
pages
,
unsigned
int
n_pages
,
unsigned
int
offset
,
unsigned
long
size
,
unsigned
int
max_segment
,
gfp_t
gfp_mask
)
{
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
struct
scatterlist
*
sg
;
sg
=
__sg_alloc_table_from_pages
(
sgt
,
pages
,
n_pages
,
offset
,
size
,
max_segment
,
NULL
,
0
,
gfp_mask
);
if
(
IS_ERR
(
sg
))
return
PTR_ERR
(
sg
);
else
return
0
;
#else
return
__sg_alloc_table_from_pages
(
sgt
,
pages
,
n_pages
,
offset
,
size
,
max_segment
,
gfp_mask
);
#endif
}
/**
* Enable/Disable Data Output Randomizer
* @fa: the adc descriptor
...
...
@@ -46,17 +76,20 @@ int fa_adc_output_randomizer_set(struct fa_dev *fa, bool enable)
uint32_t
tx
,
rx
;
int
err
;
tx
=
0x8000
;
/* Read register A1 */
tx
=
0x8000
;
tx
|=
(
1
<<
8
);
err
=
fa_spi_xfer
(
fa
,
FA_SPI_SS_ADC
,
16
,
tx
,
&
rx
);
if
(
err
)
return
err
;
/* Set or clear RAND bit */
if
(
enable
)
rx
|=
BIT
(
6
);
else
rx
&=
~
BIT
(
6
);
/* Write back A1 */
tx
=
0x0000
;
tx
|=
(
1
<<
8
);
tx
|=
(
rx
&
0xFF
);
...
...
@@ -76,7 +109,8 @@ bool fa_adc_is_output_randomizer(struct fa_dev *fa)
uint32_t
tx
,
rx
;
int
err
;
tx
=
0x8000
;
/* Read register A1 */
tx
=
0x8000
;
tx
|=
(
1
<<
8
);
err
=
fa_spi_xfer
(
fa
,
FA_SPI_SS_ADC
,
16
,
tx
,
&
rx
);
if
(
err
)
...
...
@@ -127,13 +161,13 @@ int fa_trigger_software(struct fa_dev *fa)
return
-
EPERM
;
}
/* Fire if nsamples!=0 */
/* Fire if nsamples!=0 */
if
(
!
ti
->
nsamples
)
{
dev_info
(
&
fa
->
pdev
->
dev
,
"pre + post = 0: cannot acquire
\n
"
);
return
-
EINVAL
;
}
/*
/*
* We can do a software trigger if the FSM is not in
* the WAIT trigger status. Wait for it.
* Remember that: timeout is in us, a sample takes 10ns
...
...
@@ -347,7 +381,7 @@ err:
* @enable 0 to disable, 1 to enable
*/
int
fa_adc_data_pattern_get
(
struct
fa_dev
*
fa
,
uint16_t
*
pattern
,
unsigned
int
*
enable
)
unsigned
int
*
enable
)
{
uint32_t
tx
,
rx
;
int
err
;
...
...
@@ -443,8 +477,7 @@ int zfad_fsm_command(struct fa_dev *fa, uint32_t command)
if
(
command
==
FA100M14B4C_CMD_START
)
{
if
(
!
fa_adc_is_serdes_ready
(
fa
))
{
dev_err
(
fa
->
msgdev
,
"Cannot start acquisition: "
"SerDes PLL not locked or synchronized (0x%08x)
\n
"
,
"Cannot start acquisition: SerDes PLL not locked or synchronized (0x%08x)
\n
"
,
fa_ioread
(
fa
,
fa
->
fa_adc_csr_base
+
ADC_CSR_STA_REG_OFFSET
));
return
-
EBUSY
;
}
...
...
@@ -459,8 +492,8 @@ int zfad_fsm_command(struct fa_dev *fa, uint32_t command)
* from zfat_arm_trigger() or zfad_input_cset()
*/
if
(
!
(
cset
->
ti
->
flags
&
ZIO_TI_ARMED
))
{
dev_info
(
fa
->
msgdev
,
"Cannot start acquisition: "
"
Trigger refuses to arm
\n
"
);
dev_info
(
fa
->
msgdev
,
"Cannot start acquisition:
Trigger refuses to arm
\n
"
);
return
-
EIO
;
}
...
...
@@ -484,7 +517,11 @@ static void fa_init_timetag(struct fa_dev *fa)
{
unsigned
long
seconds
;
#if KERNEL_VERSION(5, 11, 0) <= LINUX_VERSION_CODE
seconds
=
ktime_get_real_seconds
();
#else
seconds
=
get_seconds
();
#endif
fa_writel
(
fa
,
fa
->
fa_utc_base
,
&
zfad_regs
[
ZFA_UTC_SECONDS_U
],
(
seconds
>>
32
)
&
0xFFFFFFFF
);
fa_writel
(
fa
,
fa
->
fa_utc_base
,
&
zfad_regs
[
ZFA_UTC_SECONDS_L
],
...
...
@@ -517,12 +554,8 @@ static int __fa_init(struct fa_dev *fa)
fa_writel
(
fa
,
fa
->
fa_adc_csr_base
,
&
zfad_regs
[
ZFA_CTL_FMS_CMD
],
FA100M14B4C_CMD_STOP
);
/* Initialize channels to use 1V range */
for
(
i
=
0
;
i
<
4
;
++
i
)
{
for
(
i
=
0
;
i
<
FA100M14B4C_NCHAN
;
++
i
)
fa_adc_range_set
(
fa
,
&
zdev
->
cset
->
chan
[
i
],
FA100M14B4C_RANGE_1V
);
/* reset channel offset */
fa
->
user_offset
[
i
]
=
0
;
fa
->
zero_offset
[
i
]
=
0
;
}
/* Set decimation to minimum */
fa_writel
(
fa
,
fa
->
fa_adc_csr_base
,
&
zfad_regs
[
ZFAT_SR_UNDER
],
1
);
...
...
@@ -554,12 +587,11 @@ static int __fa_init(struct fa_dev *fa)
/* This structure lists the various subsystems */
struct
fa_modlist
{
char
*
name
;
int
(
*
init
)(
struct
fa_dev
*
);
void
(
*
exit
)(
struct
fa_dev
*
);
int
(
*
init
)(
struct
fa_dev
*
fa
);
void
(
*
exit
)(
struct
fa_dev
*
fa
);
};
static
struct
fa_modlist
mods
[]
=
{
{
"spi"
,
fa_spi_init
,
fa_spi_exit
},
{
"zio"
,
fa_zio_init
,
fa_zio_exit
},
{
"debug"
,
fa_debug_init
,
fa_debug_exit
},
{
"calibration"
,
fa_calib_init
,
fa_calib_exit
},
...
...
@@ -645,19 +677,85 @@ static void fa_sg_alloc_table_init(struct fa_dev *fa)
if
(
fa_is_flag_set
(
fa
,
FMC_ADC_NOSQUASH_SCATTERLIST
))
fa
->
sg_alloc_table_from_pages
=
sg_alloc_table_from_pages_no_squash
;
else
fa
->
sg_alloc_table_from_pages
=
_
_sg_alloc_table_from_pages
;
fa
->
sg_alloc_table_from_pages
=
fa
_sg_alloc_table_from_pages
;
}
static
struct
fmc_adc_platform_data
fmc_adc_pdata_default
=
{
.
flags
=
0
,
.
vme_reg_offset
=
0
,
.
vme_dma_offset
=
0
,
.
vme_dma_offset
=
0
,
.
calib_trig_time
=
0
,
.
calib_trig_threshold
=
0
,
.
calib_trig_internal
=
0
,
};
static
int
fa_metadata_get
(
struct
fa_dev
*
fa
)
{
struct
resource
*
r
;
void
*
mem
;
int
i
;
r
=
platform_get_resource
(
fa
->
pdev
,
IORESOURCE_MEM
,
ADC_MEM_META
);
if
(
r
==
NULL
)
{
dev_err
(
&
fa
->
pdev
->
dev
,
"Can't inspect ADC device metadata: missing resource
\n
"
);
return
-
ENODEV
;
}
mem
=
ioremap
(
r
->
start
,
resource_size
(
r
));
if
(
!
mem
)
{
dev_err
(
&
fa
->
pdev
->
dev
,
"Can't inspect ADC device metadata: failed to map
\n
"
);
return
-
ENODEV
;
}
/* Dump meta*/
for
(
i
=
0
;
i
<
sizeof
(
fa
->
meta
)
/
4
;
++
i
)
((
uint32_t
*
)
&
fa
->
meta
)[
i
]
=
fa_ioread
(
fa
,
mem
+
(
i
*
4
));
iounmap
(
mem
);
return
0
;
}
static
bool
fa_is_fpga_version_valid
(
uint32_t
expected
,
uint32_t
found
)
{
if
(
version_ignore
)
return
true
;
if
(
FA_VERSION_MAJ
(
found
)
!=
FA_VERSION_MAJ
(
expected
))
return
false
;
if
(
FA_VERSION_MIN
(
found
)
<
FA_VERSION_MIN
(
expected
))
return
false
;
return
true
;
}
static
bool
fa_is_fpga_valid
(
struct
fa_dev
*
fa
)
{
if
(
fa
->
meta
.
vendor
!=
FA_META_VENDOR_ID
)
{
dev_err
(
&
fa
->
pdev
->
dev
,
"Unknow vendor ID: %08x
\n
"
,
fa
->
meta
.
vendor
);
return
false
;
}
switch
(
fa
->
meta
.
device
)
{
case
FA_META_DEVICE_ID_SVEC_DBL_ADC
:
break
;
case
FA_META_DEVICE_ID_SPEC
:
break
;
default:
dev_err
(
&
fa
->
pdev
->
dev
,
"Unknow device ID: %08x
\n
"
,
fa
->
meta
.
device
);
return
false
;
}
if
(
!
fa_is_fpga_version_valid
(
FA_VERSION_DRV
,
fa
->
meta
.
version
))
{
dev_err
(
&
fa
->
pdev
->
dev
,
"Invalid version: %08x, expected: %08x
\n
"
,
fa
->
meta
.
version
,
FA_VERSION_DRV
);
return
false
;
}
return
true
;
}
/* probe and remove are called by fa-spec.c */
int
fa_probe
(
struct
platform_device
*
pdev
)
{
...
...
@@ -720,7 +818,7 @@ int fa_probe(struct platform_device *pdev)
}
}
if
(
!
fa_fmc_slot_is_valid
(
fa
))
if
(
!
fa_fmc_slot_is_valid
(
fa
))
goto
out_fmc_err
;
err
=
sysfs_create_link
(
&
fa
->
pdev
->
dev
.
kobj
,
&
fa
->
slot
->
dev
.
kobj
,
...
...
@@ -731,18 +829,34 @@ int fa_probe(struct platform_device *pdev)
goto
err_fmc_link
;
}
err
=
fa_metadata_get
(
fa
);
if
(
err
)
goto
out_meta
;
if
(
!
fa_is_fpga_valid
(
fa
))
goto
out_valid
;
err
=
fa_dma_request_channel
(
fa
);
if
(
err
)
goto
out_dma
;
fa_clock_enable
(
fa
);
err
=
fa_spi_init
(
fa
);
if
(
err
)
goto
out_spi
;
err
=
fa_adc_wait_serdes_ready
(
fa
,
msecs_to_jiffies
(
10
));
if
(
err
)
{
dev_err
(
&
fa
->
pdev
->
dev
,
"The SERDES did not syncronize
\n
"
);
goto
out_serdes
;
}
/* reset channel offset before calibration */
for
(
i
=
0
;
i
<
FA100M14B4C_NCHAN
;
++
i
)
{
fa
->
user_offset
[
i
]
=
0x8000
;
fa
->
zero_offset
[
i
]
=
0x8000
;
}
/* init all subsystems */
for
(
i
=
0
,
m
=
mods
;
i
<
ARRAY_SIZE
(
mods
);
i
++
,
m
++
)
{
dev_dbg
(
fa
->
msgdev
,
"Calling init for
\"
%s
\"\n
"
,
m
->
name
);
...
...
@@ -771,9 +885,13 @@ out:
m
->
exit
(
fa
);
iounmap
(
fa
->
fa_top_level
);
out_serdes:
fa_spi_exit
(
fa
);
out_spi:
fa_clock_disable
(
fa
);
fa_dma_release_channel
(
fa
);
out_dma:
out_valid:
out_meta:
sysfs_remove_link
(
&
fa
->
pdev
->
dev
.
kobj
,
dev_name
(
&
fa
->
slot
->
dev
));
err_fmc_link:
out_fmc_err:
...
...
@@ -799,9 +917,12 @@ int fa_remove(struct platform_device *pdev)
while
(
--
i
>=
0
)
{
struct
fa_modlist
*
m
=
mods
+
i
;
if
(
m
->
exit
)
m
->
exit
(
fa
);
}
fa_spi_exit
(
fa
);
fa_clock_disable
(
fa
);
fa_dma_release_channel
(
fa
);
...
...
@@ -836,14 +957,14 @@ static int fa_init(void)
{
int
ret
;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)
#if KERNEL_VERSION(3, 15, 0) > LINUX_VERSION_CODE
fa_workqueue
=
alloc_workqueue
(
fa_dev_drv
.
driver
.
name
,
WQ_NON_REENTRANT
|
WQ_UNBOUND
|
WQ_MEM_RECLAIM
,
1
);
#else
#else
fa_workqueue
=
alloc_workqueue
(
fa_dev_drv
.
driver
.
name
,
WQ_UNBOUND
|
WQ_MEM_RECLAIM
,
1
);
#endif
#endif
if
(
fa_workqueue
==
NULL
)
return
-
ENOMEM
;
...
...
software/kernel/fa-debug.c
View file @
05bbebf8
...
...
@@ -9,22 +9,22 @@
#include "fmc-adc-100m14b4cha-private.h"
#define FA_DBG_REG32_CH(_n) \
{.name = "ADC-CSR:ch"#_n"_ctl", .offset = ADC_CSR_OFF + 0x080 + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_sta", .offset = ADC_CSR_OFF + 0x084 + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_cal_nb", .offset = ADC_CSR_OFF + 0x088 + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_sat", .offset = ADC_CSR_OFF + 0x08C + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_trig_thres", .offset = ADC_CSR_OFF + 0x090 + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_ctl", .offset = ADC_CSR_OFF + 0x080 + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_sta", .offset = ADC_CSR_OFF + 0x084 + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_cal_nb", .offset = ADC_CSR_OFF + 0x088 + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_sat", .offset = ADC_CSR_OFF + 0x08C + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_trig_thres", .offset = ADC_CSR_OFF + 0x090 + ((_n - 1) * 0x40)},
\
{.name = "ADC-CSR:ch"#_n"_trig_dly", .offset = ADC_CSR_OFF + 0x094 + ((_n - 1) * 0x40)}
#define FA_DBG_REG32_TIM(_name, _off)
\
{ \
.name = "TIME-TAG:"#_name"_seconds_upper",
\
#define FA_DBG_REG32_TIM(_name, _off) \
{
\
.name = "TIME-TAG:"#_name"_seconds_upper", \
.offset = ADC_UTC_OFF + _off \
}, { \
.name = "TIME-TAG:"#_name"_seconds_lower",
\
}, {
\
.name = "TIME-TAG:"#_name"_seconds_lower", \
.offset = ADC_UTC_OFF + _off + 0x4, \
}, { \
.name = "TIME-TAG:"#_name"_coarse",
\
}, {
\
.name = "TIME-TAG:"#_name"_coarse", \
.offset = ADC_UTC_OFF + _off + 0x8, \
}
...
...
@@ -139,8 +139,8 @@ static void fa_regdump_seq_read_spi(struct fa_dev *fa, struct seq_file *s)
{
int
i
;
seq_p
rintf
(
s
,
"ADC SPI registers
\n
"
);
seq_p
rintf
(
s
,
"Address Data
\n
"
);
seq_p
uts
(
s
,
"ADC SPI registers
\n
"
);
seq_p
uts
(
s
,
"Address Data
\n
"
);
for
(
i
=
0
;
i
<
5
;
++
i
)
{
uint32_t
tx
,
rx
;
int
err
;
...
...
@@ -149,11 +149,9 @@ static void fa_regdump_seq_read_spi(struct fa_dev *fa, struct seq_file *s)
err
=
fa_spi_xfer
(
fa
,
FA_SPI_SS_ADC
,
16
,
tx
,
&
rx
);
rx
&=
0xFF
;
/* the value is 8bit */
if
(
err
)
seq_printf
(
s
,
"A%d %02xh read failure!
\n
"
,
i
,
i
);
seq_printf
(
s
,
"A%d %02xh read failure!
\n
"
,
i
,
i
);
else
seq_printf
(
s
,
"A%d %02xh 0x%02x
\n
"
,
i
,
i
,
rx
);
seq_printf
(
s
,
"A%d %02xh 0x%02x
\n
"
,
i
,
i
,
rx
);
}
}
...
...
@@ -183,7 +181,7 @@ static const struct file_operations fa_regdump_ops = {
static
ssize_t
fa_trg_sw_write
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
size_t
count
,
loff_t
*
ppos
)
{
struct
fa_dev
*
fa
=
file
->
private_data
;
int
err
;
...
...
@@ -212,7 +210,7 @@ static int fa_data_pattern_adc_write(struct fa_dev *fa, const char __user *buf,
if
(
err
)
return
-
EFAULT
;
if
((
count
==
1
||
count
==
2
)
&&
buf_l
[
0
]
==
'0'
)
{
if
((
count
==
1
||
count
==
2
)
&&
buf_l
[
0
]
==
'0'
)
{
err
=
fa_adc_data_pattern_set
(
fa
,
0
,
0
);
fa_calib_init
(
fa
);
return
err
;
...
...
@@ -249,10 +247,10 @@ static ssize_t fa_data_pattern_write(struct file *file, const char __user *buf,
err
=
fa_data_pattern_adc_write
(
fa
,
buf
+
4
,
count
-
4
);
return
err
?
err
:
count
;
}
else
{
dev_err
(
&
fa
->
pdev
->
dev
,
"Unknown command
\"
%s
\"\n
"
,
buf_l
);
return
-
EINVAL
;
}
dev_err
(
&
fa
->
pdev
->
dev
,
"Unknown command
\"
%s
\"\n
"
,
buf_l
);
return
-
EINVAL
;
}
static
ssize_t
fa_data_pattern_read
(
struct
file
*
file
,
char
__user
*
buf
,
...
...
@@ -264,10 +262,10 @@ static ssize_t fa_data_pattern_read(struct file *file, char __user *buf,
unsigned
int
enable
;
int
err
;
if
(
*
ppos
>
0
)
if
(
*
ppos
>
0
)
return
0
;
err
=
fa_adc_data_pattern_get
(
fa
,
&
pattern
,
&
enable
);
err
=
fa_adc_data_pattern_get
(
fa
,
&
pattern
,
&
enable
);
if
(
err
)
return
err
;
snprintf
(
buf_l
,
FA_ADC_DATA_PATTERN_CMD_SIZE
,
"adc %u 0x%02x
\n
"
,
...
...
@@ -301,14 +299,7 @@ int fa_debug_init(struct fa_dev *fa)
fa
->
dbg_reg32
.
regs
=
fa_debugfs_reg32
;
fa
->
dbg_reg32
.
nregs
=
ARRAY_SIZE
(
fa_debugfs_reg32
);
fa
->
dbg_reg32
.
base
=
fa
->
fa_top_level
;
fa
->
dbg_reg
=
debugfs_create_regset32
(
"regs"
,
0444
,
fa
->
dbg_dir
,
&
fa
->
dbg_reg32
);
if
(
IS_ERR_OR_NULL
(
fa
->
dbg_reg
))
{
err
=
PTR_ERR
(
fa
->
dbg_reg
);
dev_warn
(
&
fa
->
pdev
->
dev
,
"Cannot create debugfs file
\"
regs
\"
(%d)
\n
"
,
err
);
}
debugfs_create_regset32
(
"regs"
,
0444
,
fa
->
dbg_dir
,
&
fa
->
dbg_reg32
);
fa
->
dbg_reg_spi
=
debugfs_create_file
(
"spi-regs"
,
0444
,
fa
->
dbg_dir
,
fa
,
...
...
software/kernel/fa-dma.c
View file @
05bbebf8
...
...
@@ -4,53 +4,43 @@
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#ifdef CONFIG_FMC_ADC_SVEC
#include "vmebus.h"
#endif
#include "fmc-adc-100m14b4cha-private.h"
/* Endianess */
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 0
#endif
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 1
#endif
static
void
zfad_dma_done
(
struct
zio_cset
*
cset
);
static
int
__get_endian
(
void
)
{
int
i
=
1
;
char
*
p
=
(
char
*
)
&
i
;
if
(
p
[
0
]
==
1
)
return
LITTLE_ENDIAN
;
else
return
BIG_ENDIAN
;
}
/**
* Fix endianess from big to host endianess (32bit)
* Fix endianness from little to host endianess (32bit)
* @byte_lenght: number of bytes to fix (32bit aligned)
* @buffer: buffer to fix
*
* Data coming from the ADC IP-CORE are little-endian, so on big endian CPUs
* we have to swap the byte order.
*/
static
void
__endianness
(
unsigned
int
byte_length
,
void
*
buffer
)
#ifdef __BIG_ENDIAN
static
void
fix_endianness
(
unsigned
int
byte_length
,
void
*
buffer
)
{
/* CPU may be little endian, VME is big endian */
if
(
__get_endian
()
==
LITTLE_ENDIAN
)
{
/* swap samples and trig timetag all seen as 32bits words */
int
i
;
int
size
=
byte_length
/
4
;
uint32_t
*
ptr
=
buffer
;
/* swap samples and trig timetag all seen as 32bits words */
int
i
;
int
size
=
byte_length
/
4
;
uint32_t
*
ptr
=
buffer
;
for
(
i
=
0
;
i
<
size
;
++
i
,
++
ptr
)
*
ptr
=
__be32_to_cpu
(
*
ptr
);
}
for
(
i
=
0
;
i
<
size
;
++
i
,
++
ptr
)
le32_to_cpus
(
ptr
);
}
#else
static
void
fix_endianness
(
unsigned
int
byte_length
,
void
*
buffer
)
{
}
#endif
struct
zfad_timetag
{
uint32_t
sec_low
;
...
...
@@ -76,7 +66,7 @@ static bool fa_dmaengine_filter_svec(struct dma_chan *dchan, void *arg)
struct
fa_dev
*
fa
=
arg
;
struct
device
*
device_ref
;
device_ref
=
fa
->
pdev
->
dev
.
parent
->
parent
->
parent
->
parent
->
parent
->
parent
;
device_ref
=
fa
->
pdev
->
dev
.
parent
->
parent
->
parent
->
parent
->
parent
->
parent
;
return
(
dchan
->
device
->
dev
==
device_ref
);
}
...
...
@@ -87,7 +77,7 @@ int fa_dma_request_channel(struct fa_dev *fa)
struct
resource
*
r
;
int
dma_dev_id
;
if
(
fa_is_flag_set
(
fa
,
FMC_ADC_SVEC
))
if
(
fa_is_flag_set
(
fa
,
FMC_ADC_SVEC
))
return
0
;
r
=
platform_get_resource
(
fa
->
pdev
,
IORESOURCE_DMA
,
ADC_DMA
);
...
...
@@ -189,7 +179,7 @@ static uint32_t fa_ddr_offset_multi(struct fa_dev *fa, uint32_t shot_n)
struct
zio_cset
*
cset
=
fa
->
zdev
->
cset
;
uint32_t
off
;
off
=
cset
->
interleave
->
current_ctrl
->
ssize
*
cset
->
ti
->
nsamples
;
off
=
cset
->
interleave
->
current_ctrl
->
ssize
*
cset
->
ti
->
nsamples
;
off
+=
FA_TRIG_TIMETAG_BYTES
;
off
*=
shot_n
;
...
...
@@ -200,11 +190,10 @@ static uint32_t fa_ddr_offset(struct fa_dev *fa, uint32_t shot_n)
{
WARN
(
fa
->
n_shots
==
1
&&
shot_n
!=
0
,
"Inconsistent shot number %d
\n
"
,
shot_n
);
if
(
fa
->
n_shots
==
1
)
{
if
(
fa
->
n_shots
==
1
)
return
fa_ddr_offset_single
(
fa
);
}
else
{
else
return
fa_ddr_offset_multi
(
fa
,
shot_n
);
}
}
static
unsigned
int
zfad_block_n_pages
(
struct
zio_block
*
block
)
...
...
@@ -320,12 +309,7 @@ static int zfad_dma_block_to_pages(struct page **pages, unsigned int nr_pages,
static
void
zfad_dma_context_exit_svec
(
struct
zio_cset
*
cset
,
struct
zfad_block
*
zfad_block
)
{
struct
fa_dev
*
fa
=
cset
->
zdev
->
priv_d
;
kfree
(
zfad_block
->
dma_ctx
);
if
(
fa_is_flag_set
(
fa
,
FMC_ADC_DATA_NO_SWAP
))
return
;
__endianness
(
zfad_block
->
block
->
datalen
,
zfad_block
->
block
->
data
);
}
static
void
zfad_dma_context_exit
(
struct
zio_cset
*
cset
,
...
...
@@ -333,6 +317,7 @@ static void zfad_dma_context_exit(struct zio_cset *cset,
{
struct
fa_dev
*
fa
=
cset
->
zdev
->
priv_d
;
fix_endianness
(
zfad_block
->
block
->
datalen
,
zfad_block
->
block
->
data
);
if
(
fa_is_flag_set
(
fa
,
FMC_ADC_SVEC
))
zfad_dma_context_exit_svec
(
cset
,
zfad_block
);
}
...
...
@@ -546,7 +531,7 @@ static int fa_svec_ddr_window_set(struct fa_dev *fa, unsigned int offset)
return
-
ENODEV
;
fa_iowrite
(
fa
,
offset
,
addr
);
return
0
;
return
0
;
}
static
int
fa_dmaengine_slave_config
(
struct
fa_dev
*
fa
,
...
...
@@ -582,7 +567,7 @@ static int fa_dma_shot_wait_svec(struct fa_dev *fa,
{
int
err
;
if
(
fa
->
n_shots
==
1
)
if
(
fa
->
n_shots
==
1
)
return
0
;
err
=
wait_for_completion_interruptible_timeout
(
&
zfad_block
->
shot_done
,
...
...
@@ -596,7 +581,7 @@ static int fa_dma_shot_wait_svec(struct fa_dev *fa,
return
-
EINVAL
;
}
return
0
;
return
0
;
}
static
int
fa_dma_start_svec
(
struct
zio_cset
*
cset
)
...
...
@@ -698,12 +683,11 @@ static int zfad_dma_start(struct zio_cset *cset)
err
=
fa_fsm_wait_state
(
fa
,
FA100M14B4C_STATE_IDLE
,
10
);
if
(
err
)
{
dev_warn
(
&
fa
->
pdev
->
dev
,
"Can't start DMA on the last acquisition, "
"State Machine is not IDLE
\n
"
);
"Can't start DMA on the last acquisition, State Machine is not IDLE
\n
"
);
return
err
;
}
dev_dbg
(
&
fa
->
pdev
->
dev
,
dev_dbg
(
&
fa
->
pdev
->
dev
,
"Start DMA transfer for %i shots of %i samples
\n
"
,
fa
->
n_shots
,
cset
->
ti
->
nsamples
);
...
...
@@ -712,14 +696,14 @@ static int zfad_dma_start(struct zio_cset *cset)
* different DMA transfers required for multi-shots
*/
fa_writel
(
fa
,
fa
->
fa_adc_csr_base
,
&
zfad_regs
[
ZFAT_CFG_SRC
],
0
);
if
(
fa_is_flag_set
(
fa
,
FMC_ADC_SVEC
))
if
(
fa_is_flag_set
(
fa
,
FMC_ADC_SVEC
))
err
=
fa_dma_start_svec
(
cset
);
else
err
=
fa_dma_start_spec
(
cset
);
if
(
err
)
goto
err_start
;
return
0
;
return
0
;
err_start:
fa_writel
(
fa
,
fa
->
fa_adc_csr_base
,
&
zfad_regs
[
ZFAT_CFG_SRC
],
...
...
@@ -774,7 +758,7 @@ static void zfad_block_ctrl_attr_update(struct zio_block *block,
struct
zio_control
*
ctrl
=
zio_get_ctrl
(
block
);
uint32_t
*
ext_val
=
ctrl
->
attr_channel
.
ext_val
;
ext_val
[
FA100M14B4C_TATTR_STA
]
=
timetag
->
status
;
ext_val
[
FA100M14B4C_TATTR_STA
]
=
timetag
->
status
;
ctrl
->
seq_num
=
seq_num
;
}
...
...
software/kernel/fa-zio-drv.c
View file @
05bbebf8
...
...
@@ -44,15 +44,15 @@ static struct zio_attribute zfad_cset_ext_zattr[] = {
*/
ZIO_ATTR_EXT
(
"undersample"
,
ZIO_RW_PERM
,
ZFAT_SR_UNDER
,
1
),
ZIO_ATTR_EXT
(
"ch0-offset"
,
ZIO_RW_PERM
,
ZFA_CH1_OFFSET
,
0
),
ZIO_ATTR_EXT
(
"ch1-offset"
,
ZIO_RW_PERM
,
ZFA_CH2_OFFSET
,
0
),
ZIO_ATTR_EXT
(
"ch2-offset"
,
ZIO_RW_PERM
,
ZFA_CH3_OFFSET
,
0
),
ZIO_ATTR_EXT
(
"ch3-offset"
,
ZIO_RW_PERM
,
ZFA_CH4_OFFSET
,
0
),
ZIO_ATTR_EXT
(
"ch0-offset"
,
ZIO_RW_PERM
,
ZFA_CH1_OFFSET
,
0
x8000
),
ZIO_ATTR_EXT
(
"ch1-offset"
,
ZIO_RW_PERM
,
ZFA_CH2_OFFSET
,
0
x8000
),
ZIO_ATTR_EXT
(
"ch2-offset"
,
ZIO_RW_PERM
,
ZFA_CH3_OFFSET
,
0
x8000
),
ZIO_ATTR_EXT
(
"ch3-offset"
,
ZIO_RW_PERM
,
ZFA_CH4_OFFSET
,
0
x8000
),
ZIO_ATTR_EXT
(
"ch0-offset-zero"
,
ZIO_RW_PERM
,
ZFA_SW_CH1_OFFSET_ZERO
,
0
),
ZIO_ATTR_EXT
(
"ch1-offset-zero"
,
ZIO_RW_PERM
,
ZFA_SW_CH2_OFFSET_ZERO
,
0
),
ZIO_ATTR_EXT
(
"ch2-offset-zero"
,
ZIO_RW_PERM
,
ZFA_SW_CH3_OFFSET_ZERO
,
0
),
ZIO_ATTR_EXT
(
"ch3-offset-zero"
,
ZIO_RW_PERM
,
ZFA_SW_CH4_OFFSET_ZERO
,
0
),
ZIO_ATTR_EXT
(
"ch0-offset-zero"
,
ZIO_RW_PERM
,
ZFA_SW_CH1_OFFSET_ZERO
,
0
x8000
),
ZIO_ATTR_EXT
(
"ch1-offset-zero"
,
ZIO_RW_PERM
,
ZFA_SW_CH2_OFFSET_ZERO
,
0
x8000
),
ZIO_ATTR_EXT
(
"ch2-offset-zero"
,
ZIO_RW_PERM
,
ZFA_SW_CH3_OFFSET_ZERO
,
0
x8000
),
ZIO_ATTR_EXT
(
"ch3-offset-zero"
,
ZIO_RW_PERM
,
ZFA_SW_CH4_OFFSET_ZERO
,
0
x8000
),
ZIO_ATTR_EXT
(
"ch0-vref"
,
ZIO_RW_PERM
,
ZFA_CH1_CTL_RANGE
,
0
),
ZIO_ATTR_EXT
(
"ch1-vref"
,
ZIO_RW_PERM
,
ZFA_CH2_CTL_RANGE
,
0
),
...
...
@@ -104,7 +104,7 @@ static struct zio_attribute zfad_cset_ext_zattr[] = {
* 4: POST_TRIG
* 5: DECR_SHOT
* 7: Illegal
*
*
/
*/
ZIO_PARAM_EXT
(
"fsm-state"
,
ZIO_RO_PERM
,
ZFA_STA_FSM
,
0
),
/* last acquisition end time stamp */
ZIO_PARAM_EXT
(
"tstamp-acq-end-su"
,
ZIO_RO_PERM
,
...
...
@@ -160,12 +160,6 @@ int zfad_convert_user_range(uint32_t user_val)
return
zfad_convert_hw_range
(
user_val
);
}
static
bool
fa_is_dac_offset_valid
(
int32_t
user
,
int32_t
zero
)
{
int32_t
offset
=
user
+
zero
;
return
(
offset
>=
DAC_SAT_LOW
&&
offset
<=
DAC_SAT_UP
);
}
/*
* zfad_conf_set
*
...
...
@@ -209,15 +203,17 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr,
/*fallthrough*/
case
ZFA_SW_CH4_OFFSET_ZERO
:
i
--
;
chan
=
to_zio_cset
(
dev
)
->
chan
+
i
;
if
(
!
fa_is_dac_offset_valid
(
fa
->
user_offset
[
chan
->
index
],
usr_val
))
if
(
usr_val
&
0xFFFF0000
)
{
dev_err
(
dev
,
"Offset must be a 16bit unsigned value (0x%08x)
\n
"
,
usr_val
);
return
-
EINVAL
;
}
spin_lock
(
&
fa
->
zdev
->
cset
->
lock
);
fa
->
zero_offset
[
i
]
=
usr_val
;
fa_calib_dac_config_chan
(
fa
,
i
,
0
,
FA_CALIB_FLAG_READ_TEMP
);
err
=
fa_calib_dac_config_chan
(
fa
,
i
,
0
,
FA_CALIB_FLAG_READ_TEMP
);
spin_unlock
(
&
fa
->
zdev
->
cset
->
lock
);
return
0
;
return
err
;
case
ZFA_CHx_SAT
:
/* TODO when TLV */
break
;
...
...
@@ -244,18 +240,27 @@ static int zfad_conf_set(struct device *dev, struct zio_attribute *zattr,
/*fallthrough*/
case
ZFA_CH4_OFFSET
:
i
--
;
chan
=
to_zio_cset
(
dev
)
->
chan
+
i
;
if
(
!
fa_is_dac_offset_valid
(
usr_val
,
fa
->
zero_offset
[
chan
->
index
]))
if
(
usr_val
&
0xFFFF0000
)
{
dev_err
(
dev
,
"Offset must be a 16bit unsigned value (0x%08x)
\n
"
,
usr_val
);
return
-
EINVAL
;
}
spin_lock
(
&
fa
->
zdev
->
cset
->
lock
);
fa
->
user_offset
[
chan
->
index
]
=
usr_val
;
fa
->
user_offset
[
i
]
=
usr_val
;
err
=
fa_calib_dac_config_chan
(
fa
,
i
,
0
,
FA_CALIB_FLAG_READ_TEMP
);
spin_unlock
(
&
fa
->
zdev
->
cset
->
lock
);
return
err
;
case
ZFA_CHx_OFFSET
:
chan
=
to_zio_chan
(
dev
);
if
(
usr_val
&
0xFFFF0000
)
{
dev_err
(
dev
,
"Offset must be a 16bit unsigned value (0x%08x)
\n
"
,
usr_val
);
return
-
EINVAL
;
}
spin_lock
(
&
fa
->
zdev
->
cset
->
lock
);
fa
->
user_offset
[
chan
->
index
]
=
usr_val
;
err
=
fa_calib_dac_config_chan
(
fa
,
chan
->
index
,
0
,
...
...
@@ -425,18 +430,16 @@ static inline int zfat_overflow_detection(struct zio_ti *ti)
nsamples
=
ti_zattr
[
ZIO_ATTR_TRIG_PRE_SAMP
].
value
+
ti_zattr
[
ZIO_ATTR_TRIG_POST_SAMP
].
value
;
shot_size
=
((
nsamples
+
2
)
*
ti
->
cset
->
ssize
)
*
FA100M14B4C_NCHAN
;
if
(
(
shot_size
*
nshot_t
)
>
FA100M14B4C_MAX_ACQ_BYTE
)
{
if
(
(
shot_size
*
nshot_t
)
>
FA100M14B4C_MAX_ACQ_BYTE
)
{
dev_err
(
fa
->
msgdev
,
"Cannot acquire, dev memory overflow
\n
"
);
return
-
ENOMEM
;
}
/* in case of multi shot, each shot cannot exceed the dpram size */
if
(
(
nshot_t
>
1
)
&&
(
nsamples
>
fa
->
mshot_max_samples
)
)
{
dev_err
(
fa
->
msgdev
,
"Cannot acquire such amount of samples "
"(req: %d , max: %d) in multi shot mode."
"dev memory overflow
\n
"
,
nsamples
,
fa
->
mshot_max_samples
);
if
((
nshot_t
>
1
)
&&
(
nsamples
>
fa
->
mshot_max_samples
))
{
dev_err
(
fa
->
msgdev
,
"Cannot acquire such amount of samples (req: %d , max: %d) in multi shot mode. dev memory overflow
\n
"
,
nsamples
,
fa
->
mshot_max_samples
);
return
-
ENOMEM
;
}
return
0
;
...
...
@@ -634,9 +637,8 @@ static struct zio_driver fa_zdrv = {
.
remove
=
zfad_zio_remove
,
/* Take the version from ZIO git sub-module */
.
min_version
=
ZIO_VERSION
(
__ZIO_MIN_MAJOR_VERSION
,
__ZIO_MIN_MINOR_VERSION
,
0
),
/* Change it if you use new features from
a specific patch */
__ZIO_MIN_MINOR_VERSION
,
0
),
};
...
...
software/kernel/fa-zio-trg.c
View file @
05bbebf8
...
...
@@ -297,8 +297,7 @@ static int zfat_data_done(struct zio_cset *cset)
i
+
1
,
fa
->
n_shots
);
zio_buffer_store_block
(
bi
,
zfad_block
[
i
].
block
);
}
else
{
/* Free un-filled blocks */
dev_dbg
(
fa
->
msgdev
,
"Free un-acquired block %d/%d "
"(received %d shots)
\n
"
,
dev_dbg
(
fa
->
msgdev
,
"Free un-acquired block %d/%d (received %d shots)
\n
"
,
i
+
1
,
fa
->
n_shots
,
fa
->
n_fires
);
zio_buffer_free_block
(
bi
,
zfad_block
[
i
].
block
);
}
...
...
@@ -383,8 +382,7 @@ static int zfat_arm_trigger(struct zio_ti *ti)
if
(
size
%
4
)
{
/* should never happen: increase the size accordling */
dev_warn
(
fa
->
msgdev
,
"zio data block size should 32bit word aligned."
"original size:%d was increased by %d bytes
\n
"
,
"zio data block size should 32bit word aligned. original size:%d was increased by %d bytes
\n
"
,
size
,
size
%
4
);
size
+=
size
%
4
;
}
...
...
@@ -496,8 +494,8 @@ int fa_trig_init(void)
err
=
zio_register_trig
(
&
zfat_type
,
"adc-100m14b"
);
if
(
err
)
pr_err
(
"%s: Cannot register ZIO trigger type
"
"
\"
adc-100m14b
\"
(error %i)
\n
"
,
KBUILD_MODNAME
,
err
);
pr_err
(
"%s: Cannot register ZIO trigger type
\"
adc-100m14b
\"
(error %i)
\n
"
,
KBUILD_MODNAME
,
err
);
return
err
;
}
...
...
software/kernel/fmc-adc-100m14b4ch-spec-core.c
View file @
05bbebf8
...
...
@@ -12,6 +12,8 @@
#include "platform_data/fmc-adc-100m14b4cha.h"
enum
fa_spec_dev_offsets
{
FA_SPEC_DBL_ADC_META_START
=
0x00000000
,
FA_SPEC_DBL_ADC_META_END
=
0x00000040
,
FA_SPEC_ADC_MEM_START
=
0x000002000
,
FA_SPEC_ADC_MEM_END
=
0x000003FFF
,
};
...
...
@@ -23,7 +25,8 @@ static const struct fmc_adc_platform_data fmc_adc_pdata = {
.
calib_trig_internal
=
0
,
};
static
int
fa_spec_probe
(
struct
platform_device
*
pdev
)
{
static
int
fa_spec_probe
(
struct
platform_device
*
pdev
)
{
static
struct
resource
fa_spec_fdt_res
[]
=
{
{
.
name
=
"fmc-adc-mem"
,
...
...
@@ -36,7 +39,14 @@ static int fa_spec_probe(struct platform_device *pdev) {
{
.
name
=
"fmc-adc-irq"
,
.
flags
=
IORESOURCE_IRQ
|
IORESOURCE_IRQ_HIGHLEVEL
,
}};
},
{
.
name
=
"fmc-adc-meta"
,
.
flags
=
IORESOURCE_MEM
,
.
start
=
FA_SPEC_DBL_ADC_META_START
,
.
end
=
FA_SPEC_DBL_ADC_META_END
,
},
};
struct
platform_device_info
pdevinfo
=
{
.
parent
=
&
pdev
->
dev
,
.
name
=
"fmc-adc-100m"
,
...
...
@@ -93,6 +103,8 @@ static int fa_spec_probe(struct platform_device *pdev) {
fa_spec_fdt_res
[
0
].
end
=
rmem
->
start
+
FA_SPEC_ADC_MEM_END
;
fa_spec_fdt_res
[
1
].
start
=
dma_dev_chan
;
fa_spec_fdt_res
[
2
].
start
=
irq
;
fa_spec_fdt_res
[
3
].
start
=
rmem
->
start
+
FA_SPEC_DBL_ADC_META_START
;
fa_spec_fdt_res
[
3
].
end
=
rmem
->
start
+
FA_SPEC_DBL_ADC_META_END
;
pdev_child
=
platform_device_register_full
(
&
pdevinfo
);
if
(
IS_ERR
(
pdev_child
))
...
...
@@ -101,7 +113,8 @@ static int fa_spec_probe(struct platform_device *pdev) {
return
0
;
}
static
int
fa_spec_remove
(
struct
platform_device
*
pdev
)
{
static
int
fa_spec_remove
(
struct
platform_device
*
pdev
)
{
struct
platform_device
*
pdev_child
=
platform_get_drvdata
(
pdev
);
platform_device_unregister
(
pdev_child
);
...
...
@@ -133,11 +146,10 @@ static const struct platform_device_id fa_spec_id_table[] = {
};
static
struct
platform_driver
fa_spec_driver
=
{
.
driver
=
{
.
driver
=
{
.
name
=
"fmc-adc-100m-spec"
,
.
owner
=
THIS_MODULE
,
},
},
.
id_table
=
fa_spec_id_table
,
.
probe
=
fa_spec_probe
,
.
remove
=
fa_spec_remove
,
...
...
software/kernel/fmc-adc-100m14b4ch-svec-core.c
View file @
05bbebf8
...
...
@@ -12,6 +12,7 @@
#include <linux/mfd/core.h>
#include <linux/fmc.h>
#include "fmc-adc-100m14b4cha-private.h"
#include "platform_data/fmc-adc-100m14b4cha.h"
#define SVEC_FMC_SLOTS 2
...
...
@@ -28,10 +29,12 @@
#define SVEC_FPGA_DDR5_DMA (0x3000)
enum
fa_svec_dev_offsets
{
FA_SVEC_ADC1_MEM_START
=
0x00002000
,
FA_SVEC_ADC1_MEM_END
=
0x00003FFF
,
FA_SVEC_ADC2_MEM_START
=
0x00004000
,
FA_SVEC_ADC2_MEM_END
=
0x00005FFF
,
FA_SVEC_DBL_ADC_META_START
=
0x00000000
,
FA_SVEC_DBL_ADC_META_END
=
0x00000040
,
FA_SVEC_ADC1_MEM_START
=
0x00002000
,
FA_SVEC_ADC1_MEM_END
=
0x00003FFF
,
FA_SVEC_ADC2_MEM_START
=
0x00004000
,
FA_SVEC_ADC2_MEM_END
=
0x00005FFF
,
};
static
inline
struct
platform_device
*
platform_device_register_resndata_mask
(
...
...
@@ -57,19 +60,19 @@ static inline struct platform_device *platform_device_register_resndata_mask(
static
struct
fmc_adc_platform_data
fa_svec_adc_pdata
[]
=
{
{
.
flags
=
FMC_ADC_BIG_ENDIAN
|
FMC_ADC_SVEC
|
FMC_ADC_NOSQUASH_SCATTERLIST
,
FMC_ADC_SVEC
|
FMC_ADC_NOSQUASH_SCATTERLIST
,
.
vme_reg_offset
=
SVEC_FPGA_CSR_DDR4_ADDR
,
.
vme_dma_offset
=
SVEC_FPGA_DDR4_DMA
,
.
vme_dma_offset
=
SVEC_FPGA_DDR4_DMA
,
.
calib_trig_time
=
0
,
.
calib_trig_threshold
=
0
,
.
calib_trig_internal
=
0
,
},
{
.
flags
=
FMC_ADC_BIG_ENDIAN
|
FMC_ADC_SVEC
|
FMC_ADC_NOSQUASH_SCATTERLIST
,
FMC_ADC_SVEC
|
FMC_ADC_NOSQUASH_SCATTERLIST
,
.
vme_reg_offset
=
SVEC_FPGA_CSR_DDR5_ADDR
,
.
vme_dma_offset
=
SVEC_FPGA_DDR5_DMA
,
.
vme_dma_offset
=
SVEC_FPGA_DDR5_DMA
,
.
calib_trig_time
=
0
,
.
calib_trig_threshold
=
0
,
.
calib_trig_internal
=
0
,
...
...
@@ -93,6 +96,12 @@ static struct resource fa_svec_res1[] = {
.
start
=
0
,
.
end
=
0
,
},
{
.
name
=
"fmc-adc-100m-meta.1"
,
.
flags
=
IORESOURCE_MEM
,
.
start
=
FA_SVEC_DBL_ADC_META_START
,
.
end
=
FA_SVEC_DBL_ADC_META_END
,
},
};
static
struct
resource
fa_svec_res2
[]
=
{
...
...
@@ -112,6 +121,12 @@ static struct resource fa_svec_res2[] = {
.
start
=
1
,
.
end
=
1
,
},
{
.
name
=
"fmc-adc-100m-meta.2"
,
.
flags
=
IORESOURCE_MEM
,
.
start
=
FA_SVEC_DBL_ADC_META_START
,
.
end
=
FA_SVEC_DBL_ADC_META_END
,
},
};
static
struct
resource
*
fa_svec_res
[]
=
{
...
...
@@ -131,7 +146,7 @@ static int fa_svec_probe(struct platform_device *pdev)
int
irq
;
int
i
;
rmem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
rmem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
rmem
)
{
dev_err
(
&
pdev
->
dev
,
"Missing memory resource
\n
"
);
return
-
EINVAL
;
...
...
@@ -153,7 +168,7 @@ static int fa_svec_probe(struct platform_device *pdev)
struct
fmc_slot
*
slot
=
fmc_slot_get
(
pdev
->
dev
.
parent
,
i
+
1
);
int
present
;
if
(
IS_ERR
(
slot
))
{
if
(
IS_ERR
(
slot
))
{
dev_err
(
&
pdev
->
dev
,
"Can't find FMC slot %d err: %ld
\n
"
,
i
+
1
,
PTR_ERR
(
slot
));
...
...
@@ -169,10 +184,13 @@ static int fa_svec_probe(struct platform_device *pdev)
memcpy
(
res
,
fa_svec_res
[
i
],
sizeof
(
res
));
res
[
0
].
parent
=
rmem
;
res
[
0
].
parent
=
rmem
;
res
[
0
].
start
+=
rmem
->
start
;
res
[
0
].
end
+=
rmem
->
start
;
res
[
2
].
start
+=
irq
;
res
[
3
].
start
=
rmem
->
start
+
FA_SVEC_DBL_ADC_META_START
;
res
[
3
].
end
=
rmem
->
start
+
FA_SVEC_DBL_ADC_META_END
;
pdev_data
->
adc
[
i
]
=
platform_device_register_resndata_mask
(
&
pdev
->
dev
,
"fmc-adc-100m"
,
PLATFORM_DEVID_AUTO
,
...
...
@@ -190,7 +208,7 @@ static int fa_svec_probe(struct platform_device *pdev)
}
platform_set_drvdata
(
pdev
,
pdev_data
);
return
0
;
return
0
;
}
static
int
fa_svec_remove
(
struct
platform_device
*
pdev
)
...
...
@@ -201,12 +219,12 @@ static int fa_svec_remove(struct platform_device *pdev)
if
(
!
pdev_data
)
return
0
;
for
(
i
=
0
;
i
<
SVEC_FMC_SLOTS
;
++
i
)
for
(
i
=
0
;
i
<
SVEC_FMC_SLOTS
;
++
i
)
if
(
pdev_data
->
adc
[
i
])
platform_device_unregister
(
pdev_data
->
adc
[
i
]);
kfree
(
pdev_data
);
return
0
;
return
0
;
}
/**
...
...
software/kernel/fmc-adc-100m14b4cha-private.h
View file @
05bbebf8
...
...
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/fmc.h>
#include <linux/completion.h>
#include <linux/version.h>
#include <linux/zio.h>
#include <linux/zio-dma.h>
...
...
@@ -31,6 +32,20 @@ enum fa_versions {
ADC_VER
=
0
,
};
/**
* struct device_meta_id Metadata
*/
struct
device_meta_id
{
uint32_t
vendor
;
uint32_t
device
;
uint32_t
version
;
uint32_t
bom
;
uint32_t
src
[
4
];
uint32_t
cap
;
uint32_t
uuid
[
4
];
};
enum
fa100m14b4c_trg_ext_attr_krn
{
FA100M14B4C_TATTR_TRG_SU
=
__FA100M14B4C_TATTR_TRG_MAX
,
FA100M14B4C_TATTR_TRG_SL
,
...
...
@@ -42,8 +57,7 @@ enum fa100m14b4c_trg_ext_attr_krn {
#define ADC_SPI_OFF 0x1800
#define ADC_UTC_OFF 0x1900
#define DAC_SAT_LOW -5000000
#define DAC_SAT_UP 5000000
#define DAC_VAL_MASK 0xFFFF
#define ADC_DMA 0
...
...
@@ -57,6 +71,7 @@ enum fa_irq_resource {
enum
fa_mem_resource
{
ADC_MEM_BASE
=
0
,
ADC_MEM_META
,
};
enum
fa_bus_resource
{
...
...
@@ -64,7 +79,11 @@ enum fa_bus_resource {
};
struct
fa_memory_ops
{
#if KERNEL_VERSION(5, 8, 0) <= LINUX_VERSION_CODE
u32
(
*
read
)(
const
void
*
addr
);
#else
u32
(
*
read
)(
void
*
addr
);
#endif
void
(
*
write
)(
u32
value
,
void
*
addr
);
};
...
...
@@ -272,8 +291,8 @@ struct fa_dev; /* forward declaration */
* @n_fires: number of trigger fire occurred within an acquisition
*
* @n_dma_err: number of errors
* @user_offset: user offset
(micro-Volts)
* @zero_offset: necessary offset to push the channel to zero
(micro-Volts)
* @user_offset: user offset
* @zero_offset: necessary offset to push the channel to zero
*/
struct
fa_dev
{
unsigned
long
flags
;
...
...
@@ -289,6 +308,8 @@ struct fa_dev {
struct
fmc_slot
*
slot
;
struct
fa_memory_ops
memops
;
struct
device_meta_id
meta
;
/* carrier common base offset addresses */
void
*
fa_adc_csr_base
;
void
*
fa_spi_base
;
...
...
@@ -319,8 +340,8 @@ struct fa_dev {
unsigned
int
n_dma_err
;
/* Configuration */
int32_t
user_offset
[
4
];
/* one per channel */
int32
_t
zero_offset
[
FA100M14B4C_NCHAN
];
uint16_t
user_offset
[
FA100M14B4C_NCHAN
];
/* one per channel */
uint16
_t
zero_offset
[
FA100M14B4C_NCHAN
];
/* one-wire */
uint8_t
ds18_id
[
8
];
unsigned
long
next_t
;
...
...
@@ -336,7 +357,6 @@ struct fa_dev {
struct
dentry
*
dbg_dir
;
struct
debugfs_regset32
dbg_reg32
;
struct
dentry
*
dbg_reg
;
struct
dentry
*
dbg_reg_spi
;
struct
dentry
*
dbg_trg_sw
;
struct
dentry
*
dbg_data_pattern
;
...
...
software/kernel/fmc-adc-100m14b4cha.h
View file @
05bbebf8
...
...
@@ -139,4 +139,15 @@ struct fa_calib {
struct
fa_calib_stanza
dac
[
FA_CALIB_STANZA_N
];
/* For user offset, one per range */
};
#define FA_VERSION_DRV FA_VERSION_BLD
#define FA_VERSION_MAJ(_VER) ((_VER >> 24) & 0xFF)
#define FA_VERSION_MIN(_VER) ((_VER >> 16) & 0xFF)
#define FA_VERSION_PATCH(_VER) (_VER & 0xFFFF)
#define PCI_VENDOR_ID_CERN (0x10DC)
#define FA_META_VENDOR_ID PCI_VENDOR_ID_CERN
#define FA_META_DEVICE_ID_SPEC 0x41444301
#define FA_META_DEVICE_ID_SVEC_DBL_ADC 0x41444302
#endif
/* FMC_ADC_H_ */
software/kernel/platform_data/fmc-adc-100m14b4cha.h
View file @
05bbebf8
...
...
@@ -7,9 +7,8 @@
#ifndef __FMC_ADC_PDATA_H__
#define __FMC_ADC_PDATA_H__
#define FMC_ADC_BIG_ENDIAN BIT(0)
#define FMC_ADC_BIG_ENDIAN BIT(0)
/* Registers are in BIG ENDIAN */
#define FMC_ADC_NOSQUASH_SCATTERLIST BIT(1)
#define FMC_ADC_DATA_NO_SWAP BIT(2)
/*
* In principle this should not be necessary. The two variants should
...
...
software/kernel/spi.c
View file @
05bbebf8
...
...
@@ -49,7 +49,7 @@ int fa_spi_xfer(struct fa_dev *fa, int cs, int num_bits,
/* Wait transfer complete */
while
(
fa_ioread
(
fa
,
fa
->
fa_spi_base
+
FA_SPI_CTRL
)
&
FA_SPI_CTRL_BUSY
)
{
if
(
jiffies
>
j
)
{
if
(
time_after
(
jiffies
,
j
)
)
{
dev_err
(
fa
->
msgdev
,
"SPI transfer error cs:%d, ctrl: 0x%x
\n
"
,
cs
,
fa_ioread
(
fa
,
fa
->
fa_spi_base
+
FA_SPI_CTRL
));
err
=
-
EIO
;
...
...
@@ -77,11 +77,14 @@ int fa_spi_init(struct fa_dev *fa)
/* software reset the ADC chip (register 0) */
fa_spi_xfer
(
fa
,
FA_SPI_SS_ADC
,
16
,
BIT
(
7
),
&
rx
);
msleep
(
5
);
msleep
(
20
);
/* Force 2's complement data output (register 1, bit 5) */
fa_spi_xfer
(
fa
,
FA_SPI_SS_ADC
,
16
,
BIT
(
8
)
|
BIT
(
5
),
&
rx
);
/* 2 lanes, 14-bit serializaion (register 2) */
fa_spi_xfer
(
fa
,
FA_SPI_SS_ADC
,
16
,
(
2
<<
8
)
|
0x1
,
&
rx
);
return
0
;
}
...
...
software/tools/Makefile
View file @
05bbebf8
...
...
@@ -19,6 +19,7 @@ CFLAGS += -I../kernel -Wno-trigraphs -Wall -Werror -ggdb -O2 $(EXTRACFLAGS)
CFLAGS
+=
-DGIT_VERSION
=
"
\"
$(GIT_VERSION)
\"
"
CPPCHECK
?=
cppcheck
FLAWFINDER
?=
flawfinder
CC
?=
$(CROSS_COMPILE)
gcc
progs
:=
fau-trg-config
...
...
@@ -45,3 +46,6 @@ install:
cppcheck
:
$(CPPCHECK)
-q
-I
.
--suppress
=
missingIncludeSystem
--enable
=
all
*
.c
*
.h
--error-exitcode
=
1
flawfinder
:
$(FLAWFINDER)
-SQDC
--error-level
=
4 .
software/tools/fau-acq-time.c
View file @
05bbebf8
...
...
@@ -17,9 +17,10 @@
static
char
git_version
[]
=
"version: "
GIT_VERSION
;
#define buf_len 50
#define path_len 200
#define base_len 40
/* user will edit by adding the device name */
char
basepath
[
40
]
=
"/sys/bus/zio/devices/"
;
char
basepath
[
base_len
]
=
"/sys/bus/zio/devices/"
;
enum
fau_attribute
{
FAU_UTR_STR_S
,
...
...
@@ -55,10 +56,10 @@ const char *attribute[] = {
/* Write a sysfs attribute */
int
fau_read_attribute
(
enum
fau_attribute
attr
,
long
*
val
)
{
char
fullpath
[
200
];
char
fullpath
[
path_len
];
FILE
*
f
;
s
printf
(
fullpath
,
"%s%s"
,
basepath
,
attribute
[
attr
]);
s
nprintf
(
fullpath
,
path_len
,
"%s%s"
,
basepath
,
attribute
[
attr
]);
f
=
fopen
(
fullpath
,
"r"
);
if
(
!
f
)
return
-
1
;
...
...
@@ -153,7 +154,7 @@ int main(int argc, char *argv[])
exit
(
1
);
}
str
cat
(
basepath
,
argv
[
argc
-
1
]
);
str
ncat
(
basepath
,
argv
[
argc
-
1
],
base_len
);
printf
(
"Sysfs path to device is: %s
\n
"
,
basepath
);
if
(
last
)
{
...
...
software/tools/fau-calibration.c
View file @
05bbebf8
...
...
@@ -18,28 +18,32 @@
#include <fmc-adc-100m14b4cha.h>
#define MAX_OPT_NR 5
static
char
options
[]
=
"hf:o:D:b"
;
static
const
char
help_msg
[]
=
"Usage: fau-calibration [options]
\n
"
"
\n
"
"It reads calibration data from a file that contains it in binary
\n
"
"form and it shows it on STDOUT in binary form or in human readable
\n
"
"one (default).
\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
"
"sysfs binary attribute
\n
"
"Rembember that we expect all values to be little endian
\n
"
"
\n
"
"General options:
\n
"
"-h Print this message
\n
"
"-b Show Calibration in binary form
\n
"
"
\n
"
"Read options:
\n
"
"-f Source file where to read calibration data from
\n
"
"-o Offset in bytes within the file (default 0)
\n
"
"Write options:
\n
"
"-D FMC ADC Target Device ID
\n
"
"
\n
"
;
static
void
fau_calibration_help
(
void
)
{
fputs
(
"Usage: fau-calibration [options]
\n
"
"
\n
"
"It reads calibration data from a file that contains it in binary
\n
"
"form and it shows it on STDOUT in binary form or in human readable
\n
"
"one (default).
\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
"
"sysfs binary attribute
\n
"
"Rembember that we expect all values to be little endian
\n
"
"
\n
"
"General options:
\n
"
"-h Print this message
\n
"
"-b Show Calibration in binary form
\n
"
"
\n
"
"Read options:
\n
"
"-f Source file where to read calibration data from
\n
"
"-o Offset in bytes within the file (default 0)
\n
"
"Write options:
\n
"
"-D FMC ADC Target Device ID
\n
"
"
\n
"
,
stdout
);
}
/**
* Read calibration data from file
...
...
@@ -49,7 +53,7 @@ static const char help_msg[] =
*
* Return: number of bytes read
*/
static
int
fau_calibration_read
(
char
*
path
,
struct
fa_calib
*
calib
,
static
int
fau_calibration_read
(
c
onst
c
har
*
path
,
struct
fa_calib
*
calib
,
off_t
offset
)
{
int
fd
;
...
...
@@ -59,8 +63,13 @@ static int fau_calibration_read(char *path, struct fa_calib *calib,
if
(
fd
<
0
)
return
-
1
;
ret
=
lseek
(
fd
,
offset
,
SEEK_SET
);
if
(
ret
>=
0
)
if
(
ret
>=
0
)
{
ret
=
read
(
fd
,
calib
,
sizeof
(
*
calib
));
if
(
ret
!=
sizeof
(
*
calib
))
{
ret
=
-
1
;
errno
=
EINVAL
;
}
}
close
(
fd
);
return
ret
;
...
...
@@ -121,11 +130,11 @@ static int fau_calibration_dump_machine(struct fa_calib *calib)
*/
static
int
fau_calibration_write
(
unsigned
int
devid
,
struct
fa_calib
*
calib
)
{
char
path
[
128
];
char
path
[
55
];
// store exactly the path we need
int
fd
;
int
ret
;
s
printf
(
path
,
s
nprintf
(
path
,
sizeof
(
path
)
,
"/sys/bus/zio/devices/adc-100m14b-%04x/calibration_data"
,
devid
);
...
...
@@ -148,11 +157,24 @@ int main(int argc, char *argv[])
int
show_bin
=
0
,
write
=
0
;
struct
fa_calib
calib
;
if
(
argc
<=
0
)
{
fprintf
(
stderr
,
"What is going on here?
\n
"
);
exit
(
EXIT_FAILURE
);
}
if
(
argc
>
MAX_OPT_NR
)
{
fprintf
(
stderr
,
"This program accepts no more that %d arguments, you provides %d
\n
"
,
MAX_OPT_NR
,
argc
);
fau_calibration_help
();
exit
(
EXIT_FAILURE
);
}
while
((
c
=
getopt
(
argc
,
argv
,
options
))
!=
-
1
)
{
switch
(
c
)
{
default:
case
'h'
:
f
printf
(
stderr
,
help_msg
);
case
'h'
:
f
au_calibration_help
(
);
exit
(
EXIT_SUCCESS
);
case
'D'
:
ret
=
sscanf
(
optarg
,
"0x%x"
,
&
devid
);
...
...
software/tools/fau-trg-config.c
View file @
05bbebf8
...
...
@@ -12,16 +12,20 @@
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <fcntl.h>
#include <errno.h>
static
char
git_version
[]
=
"version: "
GIT_VERSION
;
#define path_len 200
#define buf_len 50
#define base_len 40
/* user will edit by adding the device name */
char
basepath
[
40
]
=
"/sys/bus/zio/devices/"
;
char
basepath
[
base_len
]
=
"/sys/bus/zio/devices/"
;
enum
fau_attribute
{
FAU_TRG_EN
,
...
...
@@ -54,19 +58,21 @@ const char *attribute[] = {
int
fau_write_attribute
(
enum
fau_attribute
attr
,
uint32_t
val
)
{
int
ret
,
fd
;
char
buf
[
buf_len
],
fullpath
[
200
];
char
buf
[
buf_len
],
fullpath
[
path_len
];
/* convert val to string */
s
printf
(
buf
,
"%u"
,
val
);
s
nprintf
(
buf
,
buf_len
,
"%u"
,
val
);
/* build the attribute path */
strcpy
(
fullpath
,
basepath
);
strcat
(
fullpath
,
attribute
[
attr
]);
strncpy
(
fullpath
,
basepath
,
path_len
);
if
(
path_len
>
0
)
fullpath
[
path_len
-
1
]
=
'\0'
;
strncat
(
fullpath
,
attribute
[
attr
],
path_len
);
/* Write the attribute */
printf
(
"Writing %s in %s
\n
"
,
buf
,
fullpath
);
fd
=
open
(
fullpath
,
O_WRONLY
);
if
(
fd
<
0
)
return
-
ENOENT
;
ret
=
write
(
fd
,
buf
,
str
len
(
buf
));
ret
=
write
(
fd
,
buf
,
str
nlen
(
buf
,
buf_len
));
close
(
fd
);
return
ret
;
}
...
...
@@ -102,6 +108,19 @@ static void print_version(char *pname)
printf
(
"%s %s
\n
"
,
pname
,
git_version
);
}
static
long
strtol_or_die
(
const
char
*
arg
)
{
long
val
=
strtol
(
arg
,
NULL
,
0
);
if
((
errno
==
ERANGE
&&
(
val
==
LONG_MAX
||
val
==
LONG_MIN
))
||
(
errno
!=
0
&&
val
==
0
))
{
fprintf
(
stderr
,
"Can't convert
\"
%s
\"
to integer
\n
"
,
optarg
);
exit
(
EXIT_FAILURE
);
}
return
val
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
/* default attribute */
...
...
@@ -137,22 +156,22 @@ int main(int argc, char *argv[])
options
,
&
opt_index
))
>=
0
){
switch
(
c
){
case
'p'
:
attrval
[
FAU_TRG_PRE
]
=
atoi
(
optarg
);
attrval
[
FAU_TRG_PRE
]
=
strtol_or_die
(
optarg
);
break
;
case
'P'
:
attrval
[
FAU_TRG_PST
]
=
atoi
(
optarg
);
attrval
[
FAU_TRG_PST
]
=
strtol_or_die
(
optarg
);
break
;
case
'n'
:
attrval
[
FAU_TRG_RE_EN
]
=
atoi
(
optarg
);
attrval
[
FAU_TRG_RE_EN
]
=
strtol_or_die
(
optarg
);
break
;
case
'd'
:
attrval
[
FAU_TRG_DLY
]
=
atoi
(
optarg
);
attrval
[
FAU_TRG_DLY
]
=
strtol_or_die
(
optarg
);
break
;
case
't'
:
attrval
[
FAU_TRG_THR
]
=
atoi
(
optarg
);
attrval
[
FAU_TRG_THR
]
=
strtol_or_die
(
optarg
);
break
;
case
'c'
:
attrval
[
FAU_TRG_CHN
]
=
atoi
(
optarg
);
attrval
[
FAU_TRG_CHN
]
=
strtol_or_die
(
optarg
);
break
;
case
'V'
:
print_version
(
argv
[
0
]);
...
...
@@ -171,7 +190,7 @@ int main(int argc, char *argv[])
exit
(
1
);
}
str
cat
(
basepath
,
argv
[
optind
]
);
str
ncat
(
basepath
,
argv
[
optind
],
base_len
);
printf
(
"Sysfs path to device is: %s
\n
"
,
basepath
);
for
(
i
=
0
;
i
<
FAU_TRIG_NUM_ATTR
;
++
i
)
{
...
...
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