Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FMC ADC 100M 14b 4cha - Software
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
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 - Software
Commits
467c3470
Commit
467c3470
authored
Jul 22, 2019
by
Federico Vaga
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drv: split dma code in smaller functions
Signed-off-by:
Federico Vaga
<
federico.vaga@cern.ch
>
parent
4102bbde
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
146 additions
and
78 deletions
+146
-78
fa-dma.c
kernel/fa-dma.c
+146
-78
No files found.
kernel/fa-dma.c
View file @
467c3470
...
...
@@ -7,20 +7,17 @@
#include <linux/errno.h>
#include "fmc-adc-100m14b4cha.h"
/**
* It maps the ZIO blocks with an sg table, then it starts the DMA transfer
* from the ADC to the host memory.
*
* @param cset
*/
int
zfad_dma_start
(
struct
zio_cset
*
cset
)
struct
zfad_timetag
{
uint32_t
sec_low
;
uint32_t
sec_high
;
uint32_t
ticks
;
uint32_t
status
;
};
static
int
zfad_wait_idle
(
struct
fa_dev
*
fa
)
{
struct
fa_dev
*
fa
=
cset
->
zdev
->
priv_d
;
struct
zfad_block
*
zfad_block
=
cset
->
interleave
->
priv_d
;
uint32_t
dev_mem_off
,
trg_pos
,
pre_samp
;
uint32_t
val
=
0
;
int
try
=
5
,
err
;
int
try
=
5
;
/*
* All programmed triggers fire, so the acquisition is ended.
...
...
@@ -33,12 +30,51 @@ int zfad_dma_start(struct zio_cset *cset)
&
zfad_regs
[
ZFA_STA_FSM
]);
}
if
(
val
!=
FA100M14B4C_STATE_IDLE
)
{
/* we can't DMA if the state machine is not idle */
return
val
!=
FA100M14B4C_STATE_IDLE
?
-
EBUSY
:
0
;
}
static
uint32_t
zfad_dev_mem_offset
(
struct
zio_cset
*
cset
)
{
struct
fa_dev
*
fa
=
cset
->
zdev
->
priv_d
;
uint32_t
dev_mem_off
,
trg_pos
,
pre_samp
;
int
nchan
=
FA100M14B4C_NCHAN
;
struct
zio_control
*
ctrl
=
cset
->
chan
[
nchan
].
current_ctrl
;
/* get pre-samples from the current control (interleave chan) */
pre_samp
=
ctrl
->
attr_trigger
.
std_val
[
ZIO_ATTR_TRIG_PRE_SAMP
];
/* Get trigger position in DDR */
trg_pos
=
fa_readl
(
fa
,
fa
->
fa_adc_csr_base
,
&
zfad_regs
[
ZFAT_POS
]);
/*
* compute mem offset (in bytes): pre-samp is converted to
* bytes
*/
dev_mem_off
=
trg_pos
-
(
pre_samp
*
cset
->
ssize
*
nchan
);
dev_dbg
(
fa
->
msgdev
,
"Trigger @ 0x%08x, pre_samp %i, offset 0x%08x
\n
"
,
trg_pos
,
pre_samp
,
dev_mem_off
);
return
dev_mem_off
;
}
/**
* It maps the ZIO blocks with an sg table, then it starts the DMA transfer
* from the ADC to the host memory.
*
* @param cset
*/
int
zfad_dma_start
(
struct
zio_cset
*
cset
)
{
struct
fa_dev
*
fa
=
cset
->
zdev
->
priv_d
;
struct
zfad_block
*
zfad_block
=
cset
->
interleave
->
priv_d
;
int
err
;
err
=
zfad_wait_idle
(
fa
);
if
(
err
)
{
dev_warn
(
fa
->
msgdev
,
"Can't start DMA on the last acquisition, "
"State Machine is not IDLE
(status:%d)
\n
"
,
val
);
return
-
EBUSY
;
"State Machine is not IDLE
\n
"
);
return
err
;
}
/*
...
...
@@ -48,26 +84,8 @@ int zfad_dma_start(struct zio_cset *cset)
fa_writel
(
fa
,
fa
->
fa_adc_csr_base
,
&
zfad_regs
[
ZFAT_CFG_SRC
],
0
);
/* Fix dev_mem_addr in single-shot mode */
if
(
fa
->
n_shots
==
1
)
{
int
nchan
=
FA100M14B4C_NCHAN
;
struct
zio_control
*
ctrl
=
cset
->
chan
[
nchan
].
current_ctrl
;
/* get pre-samples from the current control (interleave chan) */
pre_samp
=
ctrl
->
attr_trigger
.
std_val
[
ZIO_ATTR_TRIG_PRE_SAMP
];
/* Get trigger position in DDR */
trg_pos
=
fa_readl
(
fa
,
fa
->
fa_adc_csr_base
,
&
zfad_regs
[
ZFAT_POS
]);
/*
* compute mem offset (in bytes): pre-samp is converted to
* bytes
*/
dev_mem_off
=
trg_pos
-
(
pre_samp
*
cset
->
ssize
*
nchan
);
dev_dbg
(
fa
->
msgdev
,
"Trigger @ 0x%08x, pre_samp %i, offset 0x%08x
\n
"
,
trg_pos
,
pre_samp
,
dev_mem_off
);
zfad_block
[
0
].
dev_mem_off
=
dev_mem_off
;
}
if
(
fa
->
n_shots
==
1
)
zfad_block
[
0
].
dev_mem_off
=
zfad_dev_mem_offset
(
cset
);
dev_dbg
(
fa
->
msgdev
,
"Start DMA transfer
\n
"
);
err
=
fa
->
carrier_op
->
dma_start
(
cset
);
...
...
@@ -77,6 +95,85 @@ int zfad_dma_start(struct zio_cset *cset)
return
0
;
}
static
void
zfad_tstamp_start_get
(
struct
fa_dev
*
fa
,
struct
zio_timestamp
*
ztstamp
)
{
ztstamp
->
secs
=
fa_readl
(
fa
,
fa
->
fa_utc_base
,
&
zfad_regs
[
ZFA_UTC_ACQ_START_SECONDS
]);
ztstamp
->
ticks
=
fa_readl
(
fa
,
fa
->
fa_utc_base
,
&
zfad_regs
[
ZFA_UTC_ACQ_START_COARSE
]);
ztstamp
->
bins
=
fa_readl
(
fa
,
fa
->
fa_utc_base
,
&
zfad_regs
[
ZFA_UTC_ACQ_START_FINE
]);
}
static
int
zfad_block_timetag_extract
(
struct
zio_block
*
block
,
struct
zfad_timetag
*
timetag
)
{
struct
zfad_timetag
*
tg
;
tg
=
block
->
data
+
block
->
datalen
-
FA_TRIG_TIMETAG_BYTES
;
if
(
unlikely
((
tg
->
sec_high
>>
8
)
!=
0xACCE55
))
return
-
EINVAL
;
/* resize the datalen, by removing the trigger tstamp */
block
->
datalen
=
block
->
datalen
-
FA_TRIG_TIMETAG_BYTES
;
memcpy
(
timetag
,
tg
,
sizeof
(
*
timetag
));
return
0
;
}
static
void
zfad_block_ctrl_tstamp_update
(
struct
zio_block
*
block
,
struct
zfad_timetag
*
timetag
)
{
struct
zio_control
*
ctrl
=
zio_get_ctrl
(
block
);
struct
zio_timestamp
*
ztstamp
=
&
ctrl
->
tstamp
;
ztstamp
->
secs
=
((
uint64_t
)
timetag
->
sec_high
&
0xFF
)
<<
32
;
ztstamp
->
secs
|=
timetag
->
sec_low
;
ztstamp
->
ticks
=
timetag
->
ticks
;
ztstamp
->
bins
=
0
;
}
static
void
zfad_block_ctrl_attr_update
(
struct
zio_block
*
block
,
struct
zfad_timetag
*
timetag
,
unsigned
int
seq_num
)
{
struct
zio_control
*
ctrl
=
zio_get_ctrl
(
block
);
uint32_t
*
ext_val
=
ctrl
->
attr_channel
.
ext_val
;
ext_val
[
FA100M14B4C_TATTR_STA
]
=
timetag
->
status
;
ctrl
->
seq_num
=
seq_num
;
}
static
void
zfad_block_ctrl_tstamp_start_update
(
struct
zio_block
*
block
,
struct
zio_timestamp
*
ztstamp
)
{
struct
zio_control
*
ctrl
=
zio_get_ctrl
(
block
);
uint32_t
*
ext_val
;
ext_val
=
ctrl
->
attr_channel
.
ext_val
;
ext_val
[
FA100M14B4C_DATTR_ACQ_START_S
]
=
ztstamp
->
secs
;
ext_val
[
FA100M14B4C_DATTR_ACQ_START_C
]
=
ztstamp
->
ticks
;
ext_val
[
FA100M14B4C_DATTR_ACQ_START_F
]
=
ztstamp
->
bins
;
}
static
void
zfad_curr_ctrl_sync
(
struct
zio_cset
*
cset
,
struct
zio_block
*
block
)
{
struct
zio_channel
*
interleave
=
cset
->
interleave
;
struct
zio_control
*
ctrl
;
if
(
WARN
(
!
block
,
"Missing block
\n
"
))
return
;
ctrl
=
zio_get_ctrl
(
block
);
/* Sync the channel current control with the last ctrl block*/
memcpy
(
&
interleave
->
current_ctrl
->
tstamp
,
&
ctrl
->
tstamp
,
sizeof
(
struct
zio_timestamp
));
interleave
->
current_ctrl
->
seq_num
=
ctrl
->
seq_num
;
}
/**
* It completes a DMA transfer.
* It tells to the ZIO framework that all blocks are done. Then, it re-enable
...
...
@@ -89,14 +186,12 @@ int zfad_dma_start(struct zio_cset *cset)
void
zfad_dma_done
(
struct
zio_cset
*
cset
)
{
struct
fa_dev
*
fa
=
cset
->
zdev
->
priv_d
;
struct
zio_channel
*
interleave
=
cset
->
interleave
;
struct
zfad_block
*
zfad_block
=
interleave
->
priv_d
;
struct
zfad_block
*
zfad_block
=
cset
->
interleave
->
priv_d
;
struct
zio_control
*
ctrl
=
NULL
;
struct
zio_ti
*
ti
=
cset
->
ti
;
struct
zio_block
*
block
;
struct
zio_block
*
block
=
NULL
;
struct
zio_timestamp
ztstamp
;
int
i
;
uint32_t
*
trig_timetag
;
fa
->
carrier_op
->
dma_done
(
cset
);
...
...
@@ -104,47 +199,20 @@ void zfad_dma_done(struct zio_cset *cset)
* trig-timetag appended after the samples. Set also the acquisition
* start timetag on every blocks
*/
ztstamp
.
secs
=
fa_readl
(
fa
,
fa
->
fa_utc_base
,
&
zfad_regs
[
ZFA_UTC_ACQ_START_SECONDS
]);
ztstamp
.
ticks
=
fa_readl
(
fa
,
fa
->
fa_utc_base
,
&
zfad_regs
[
ZFA_UTC_ACQ_START_COARSE
]);
ztstamp
.
bins
=
fa_readl
(
fa
,
fa
->
fa_utc_base
,
&
zfad_regs
[
ZFA_UTC_ACQ_START_FINE
]);
zfad_tstamp_start_get
(
fa
,
&
ztstamp
);
for
(
i
=
0
;
i
<
fa
->
n_shots
;
++
i
)
{
struct
zfad_timetag
timetag
;
int
err
;
block
=
zfad_block
[
i
].
block
;
ctrl
=
zio_get_ctrl
(
block
);
trig_timetag
=
(
uint32_t
*
)(
block
->
data
+
block
->
datalen
-
FA_TRIG_TIMETAG_BYTES
);
if
(
unlikely
((
*
(
trig_timetag
+
1
)
>>
8
)
!=
0xACCE55
))
dev_err
(
fa
->
msgdev
,
"Wrong acquisition TAG, expected 0xACCE55 but got 0x%X (0x%X)
\n
"
,
(
*
(
trig_timetag
+
1
)
>>
8
),
*
trig_timetag
);
ctrl
->
tstamp
.
secs
=
((
uint64_t
)
*
(
trig_timetag
+
1
)
&
0xFF
)
<<
32
;
ctrl
->
tstamp
.
secs
|=
*
(
trig_timetag
);
ctrl
->
tstamp
.
ticks
=
*
(
trig_timetag
+
2
);
ctrl
->
tstamp
.
bins
=
0
;
ctrl
->
attr_trigger
.
ext_val
[
FA100M14B4C_TATTR_STA
]
=
*
(
trig_timetag
+
3
);
/* Acquisition start Timetag */
ctrl
->
attr_channel
.
ext_val
[
FA100M14B4C_DATTR_ACQ_START_S
]
=
ztstamp
.
secs
;
ctrl
->
attr_channel
.
ext_val
[
FA100M14B4C_DATTR_ACQ_START_C
]
=
ztstamp
.
ticks
;
ctrl
->
attr_channel
.
ext_val
[
FA100M14B4C_DATTR_ACQ_START_F
]
=
ztstamp
.
bins
;
/* resize the datalen, by removing the trigger tstamp */
block
->
datalen
=
block
->
datalen
-
FA_TRIG_TIMETAG_BYTES
;
/* update seq num */
ctrl
->
seq_num
=
i
;
err
=
zfad_block_timetag_extract
(
block
,
&
timetag
);
if
(
err
)
memset
(
&
timetag
,
0
,
sizeof
(
timetag
));
zfad_block_ctrl_tstamp_start_update
(
block
,
&
ztstamp
);
zfad_block_ctrl_tstamp_update
(
block
,
&
timetag
);
zfad_block_ctrl_attr_update
(
block
,
&
timetag
,
i
);
}
/* Sync the channel current control with the last ctrl block*/
memcpy
(
&
interleave
->
current_ctrl
->
tstamp
,
&
ctrl
->
tstamp
,
sizeof
(
struct
zio_timestamp
));
/* Update sequence number */
interleave
->
current_ctrl
->
seq_num
=
ctrl
->
seq_num
;
zfad_curr_ctrl_sync
(
cset
,
block
);
/*
* All DMA transfers done! Inform the trigger about this, so
...
...
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