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
b9faf1f8
Commit
b9faf1f8
authored
Apr 15, 2014
by
Tomasz Wlostowski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel: unified readout buffer for all carriers. Dummy API for WR
parent
b7de3eb5
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
80 additions
and
153 deletions
+80
-153
fmc-tdc.h
kernel/fmc-tdc.h
+1
-5
ft-core.c
kernel/ft-core.c
+0
-10
ft-irq.c
kernel/ft-irq.c
+22
-12
ft-spec.c
kernel/ft-spec.c
+1
-104
ft-svec.c
kernel/ft-svec.c
+3
-19
ft-zio.c
kernel/ft-zio.c
+53
-3
No files found.
kernel/fmc-tdc.h
View file @
b9faf1f8
...
...
@@ -85,8 +85,6 @@ struct ft_carrier_specific {
int
(
*
init
)
(
struct
fmctdc_dev
*
);
int
(
*
reset_core
)
(
struct
fmctdc_dev
*
);
int
(
*
copy_timestamps
)
(
struct
fmctdc_dev
*
,
int
base_addr
,
int
size
,
void
*
dst
);
void
(
*
exit
)
(
struct
fmctdc_dev
*
);
};
...
...
@@ -139,7 +137,6 @@ struct fmctdc_dev {
int
ft_core_base
;
int
ft_i2c_base
;
int
ft_owregs_base
;
int
ft_dma_base
;
int
ft_carrier_base
;
int
ft_irq_base
;
int
ft_buffer_base
;
...
...
@@ -168,10 +165,9 @@ struct fmctdc_dev {
/* output lots of debug stuff? */
int
verbose
;
struct
ft_channel_state
channels
[
FT_NUM_CHANNELS
];
int
flags
;
/* hardware buffer pointers / dacapo regs */
uint32_t
cur_wr_ptr
,
prev_wr_ptr
;
/* DMA buffer */
struct
ft_hw_timestamp
*
raw_events
;
};
extern
struct
ft_carrier_specific
ft_carrier_spec
;
...
...
kernel/ft-core.c
View file @
b9faf1f8
...
...
@@ -203,14 +203,6 @@ int ft_probe(struct fmc_device *fmc)
return
-
ENOMEM
;
}
ft
->
raw_events
=
kzalloc
(
sizeof
(
struct
ft_hw_timestamp
)
*
FT_BUFFER_EVENTS
,
GFP_KERNEL
);
if
(
!
ft
->
raw_events
)
{
dev_err
(
dev
,
"can't allocate buffer
\n
"
);
return
-
ENOMEM
;
}
index
=
fmc
->
op
->
validate
(
fmc
,
&
ft_drv
);
if
(
index
<
0
)
{
dev_info
(
dev
,
"not using
\"
%s
\"
according to "
...
...
@@ -291,8 +283,6 @@ int ft_probe(struct fmc_device *fmc)
fmc_find_sdb_device_ext
(
fmc
->
sdb
,
0xce42
,
0x602
,
fmc
->
slot_id
+
1
,
NULL
);
ft
->
ft_dma_base
=
fmc_find_sdb_device
(
fmc
->
sdb
,
0xce42
,
0x601
,
NULL
);
ft
->
ft_buffer_base
=
fmc_find_sdb_device_ext
(
fmc
->
sdb
,
0xce42
,
0x601
,
fmc
->
slot_id
,
NULL
);
...
...
kernel/ft-irq.c
View file @
b9faf1f8
...
...
@@ -30,6 +30,22 @@
static
void
ft_readout_tasklet
(
unsigned
long
arg
);
static
void
copy_timestamps
(
struct
fmctdc_dev
*
ft
,
int
base_addr
,
int
size
,
void
*
dst
)
{
int
i
;
uint32_t
addr
;
uint32_t
*
dptr
;
BUG_ON
(
size
&
3
||
base_addr
&
3
);
/* no unaligned reads, please. */
/* FIXME: use SDB to determine buffer base address (after fixing the HDL) */
addr
=
ft
->
ft_buffer_base
+
base_addr
;
for
(
i
=
0
,
dptr
=
(
uint32_t
*
)
dst
;
i
<
size
/
4
;
i
++
,
dptr
++
)
*
dptr
=
fmc_readl
(
ft
->
fmc
,
addr
+
i
*
4
);
}
int
ft_read_sw_fifo
(
struct
fmctdc_dev
*
ft
,
int
channel
,
struct
zio_channel
*
chan
)
{
...
...
@@ -122,7 +138,7 @@ static inline void process_timestamp(struct fmctdc_dev *ft,
/* first, convert the timestamp from the HDL units (81 ps bins)
to the WR format (where fractional part is 8 ns rescaled to 4096 units) */
ts
.
channel
=
channel
;
ts
.
seconds
=
hwts
->
utc
;
frac
=
hwts
->
bins
*
81
*
64
/
125
;
/* 64/125 = 4096/8000: reduce fraction to avoid 64-bit division */
...
...
@@ -153,6 +169,7 @@ static inline void process_timestamp(struct fmctdc_dev *ft,
if
(
likely
(
diff
.
seconds
||
diff
.
coarse
>
12
||
(
diff
.
coarse
==
12
&&
diff
.
frac
>=
2048
)))
{
ts
=
st
->
prev_ts
;
ft_ts_apply_offset
(
&
ts
,
ft
->
calib
.
zero_offset
[
channel
-
1
]);
...
...
@@ -245,16 +262,6 @@ static void ft_readout_tasklet(unsigned long arg)
ft
->
prev_wr_ptr
=
ft
->
cur_wr_ptr
;
ft
->
cur_wr_ptr
=
ft_readl
(
ft
,
TDC_REG_BUFFER_PTR
);
/* read the timestamps via DMA - we read the whole buffer, it doesn't really matter
for the HW if it's 16 bytes or a 4k page */
if
(
ft
->
carrier_specific
->
copy_timestamps
(
ft
,
0
,
FT_BUFFER_EVENTS
*
sizeof
(
struct
ft_hw_timestamp
),
ft
->
raw_events
)
<
0
)
return
;
/* we can do nothing about this */
dacapo
=
check_lost_events
(
ft
->
cur_wr_ptr
,
ft
->
prev_wr_ptr
,
&
count
);
/* Start reading from the oldest event */
...
...
@@ -264,7 +271,10 @@ static void ft_readout_tasklet(unsigned long arg)
rd_ptr
=
(
ft
->
prev_wr_ptr
>>
4
)
&
0x000ff
;
/* The oldest is prev_wr_ptr */
for
(;
count
>
0
;
count
--
)
{
process_timestamp
(
ft
,
&
ft
->
raw_events
[
rd_ptr
],
dacapo
);
struct
ft_hw_timestamp
hwts
;
copy_timestamps
(
ft
,
rd_ptr
*
sizeof
(
struct
ft_hw_timestamp
),
sizeof
(
struct
ft_hw_timestamp
),
&
hwts
);
process_timestamp
(
ft
,
&
hwts
,
dacapo
);
rd_ptr
=
(
rd_ptr
+
1
)
%
FT_BUFFER_EVENTS
;
}
...
...
kernel/ft-spec.c
View file @
b9faf1f8
...
...
@@ -18,32 +18,6 @@
#include "hw/tdc_regs.h"
struct
ft_spec_data
{
void
*
buffer
;
dma_addr_t
dma_addr
;
size_t
buffer_size
;
};
static
inline
uint32_t
dma_readl
(
struct
fmctdc_dev
*
ft
,
unsigned
long
reg
)
{
return
fmc_readl
(
ft
->
fmc
,
ft
->
ft_dma_base
+
reg
);
}
static
inline
void
dma_writel
(
struct
fmctdc_dev
*
ft
,
uint32_t
v
,
unsigned
long
reg
)
{
fmc_writel
(
ft
->
fmc
,
v
,
ft
->
ft_dma_base
+
reg
);
}
static
int
ft_spec_init
(
struct
fmctdc_dev
*
ft
)
{
ft
->
carrier_data
=
kzalloc
(
sizeof
(
struct
ft_spec_data
),
GFP_KERNEL
);
if
(
!
ft
->
carrier_data
)
return
-
ENOMEM
;
return
0
;
}
static
int
ft_spec_reset
(
struct
fmctdc_dev
*
ft
)
{
struct
spec_dev
*
spec
=
(
struct
spec_dev
*
)
ft
->
fmc
->
carrier_data
;
...
...
@@ -69,84 +43,7 @@ static int ft_spec_reset(struct fmctdc_dev *ft)
return
0
;
}
static
int
ft_spec_copy_timestamps
(
struct
fmctdc_dev
*
ft
,
int
base_addr
,
int
size
,
void
*
dst
)
{
struct
ft_spec_data
*
cspec
=
ft
->
carrier_data
;
uint32_t
status
;
int
i
,
ret
=
0
;
cspec
->
dma_addr
=
dma_map_single
(
ft
->
fmc
->
hwdev
,
(
char
*
)
dst
,
size
,
DMA_FROM_DEVICE
);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
if
(
dma_mapping_error
(
cspec
->
dma_addr
))
{
#else
if
(
dma_mapping_error
(
ft
->
fmc
->
hwdev
,
cspec
->
dma_addr
))
{
#endif
dev_err
(
&
ft
->
fmc
->
dev
,
"dma_map_single failed
\n
"
);
return
-
ENOMEM
;
}
dma_writel
(
ft
,
0
,
TDC_REG_DMA_CTRL
);
dma_writel
(
ft
,
base_addr
,
TDC_REG_DMA_C_START
);
dma_writel
(
ft
,
cspec
->
dma_addr
&
0xffffffff
,
TDC_REG_DMA_H_START_L
);
dma_writel
(
ft
,
((
uint64_t
)
cspec
->
dma_addr
>>
32
)
&
0x00ffffffff
,
TDC_REG_DMA_H_START_H
);
dma_writel
(
ft
,
0
,
TDC_REG_DMA_NEXT_L
);
dma_writel
(
ft
,
0
,
TDC_REG_DMA_NEXT_H
);
/* Write the DMA length */
dma_writel
(
ft
,
size
,
TDC_REG_DMA_LEN
);
/* No chained xfers, PCIe to host */
dma_writel
(
ft
,
0
,
TDC_REG_DMA_ATTRIB
);
/* Start the transfer */
dma_writel
(
ft
,
1
,
TDC_REG_DMA_CTRL
);
udelay
(
1
);
dma_writel
(
ft
,
0
,
TDC_REG_DMA_CTRL
);
/* Don't bother about end-of-DMA IRQ, it only makes the driver unnecessarily complicated. */
for
(
i
=
0
;
i
<
1000
;
i
++
)
{
status
=
dma_readl
(
ft
,
TDC_REG_DMA_STAT
)
&
TDC_DMA_STAT_MASK
;
if
(
status
==
TDC_DMA_STAT_DONE
)
{
ret
=
0
;
break
;
}
else
if
(
status
==
TDC_DMA_STAT_ERROR
)
{
ret
=
-
EIO
;
break
;
}
udelay
(
1
);
}
if
(
i
==
1000
)
{
dev_err
(
&
ft
->
fmc
->
dev
,
"%s: DMA transfer taking way too long. Something's really weird.
\n
"
,
__func__
);
ret
=
-
EIO
;
}
dma_sync_single_for_cpu
(
ft
->
fmc
->
hwdev
,
cspec
->
dma_addr
,
size
,
DMA_FROM_DEVICE
);
dma_unmap_single
(
ft
->
fmc
->
hwdev
,
cspec
->
dma_addr
,
size
,
DMA_FROM_DEVICE
);
return
ret
;
}
static
void
ft_spec_exit
(
struct
fmctdc_dev
*
ft
)
{
kfree
(
ft
->
carrier_data
);
}
struct
ft_carrier_specific
ft_carrier_spec
=
{
FT_GATEWARE_SPEC
,
ft_spec_init
,
ft_spec_reset
,
ft_spec_copy_timestamps
,
ft_spec_exit
,
ft_spec_reset
};
kernel/ft-svec.c
View file @
b9faf1f8
...
...
@@ -20,18 +20,6 @@
#include "hw/tdc_regs.h"
/*
static int ft_poll_interval = 200;
module_param_named(poll_interval, ft_poll_interval, int, 0444);
MODULE_PARM_DESC(poll_interval,
"Buffer polling interval in milliseconds. Applies to SVEC version only.");
*/
static
int
ft_svec_init
(
struct
fmctdc_dev
*
ft
)
{
return
0
;
}
static
int
ft_svec_reset
(
struct
fmctdc_dev
*
ft
)
{
unsigned
long
tmo
;
...
...
@@ -66,6 +54,7 @@ static int ft_svec_reset(struct fmctdc_dev *ft)
return
-
EIO
;
}
#if 0
static int ft_svec_copy_timestamps(struct fmctdc_dev *ft, int base_addr,
int size, void *dst)
{
...
...
@@ -84,15 +73,10 @@ static int ft_svec_copy_timestamps(struct fmctdc_dev *ft, int base_addr,
return 0;
}
#endif
static
void
ft_svec_exit
(
struct
fmctdc_dev
*
ft
)
{
}
struct
ft_carrier_specific
ft_carrier_svec
=
{
FT_GATEWARE_SVEC
,
ft_svec_init
,
ft_svec_reset
,
ft_svec_copy_timestamps
,
ft_svec_exit
ft_svec_reset
};
kernel/ft-zio.c
View file @
b9faf1f8
...
...
@@ -62,6 +62,9 @@ enum ft_devtype {
FT_TYPE_INPUT
};
static
int
ft_wr_mode
(
struct
fmctdc_dev
*
fd
,
int
on
);
static
int
ft_wr_query
(
struct
fmctdc_dev
*
ft
);
static
enum
ft_devtype
__ft_get_type
(
struct
device
*
dev
)
{
struct
zio_obj_head
*
head
=
to_zio_head
(
dev
);
...
...
@@ -256,16 +259,63 @@ static int ft_zio_conf_set(struct device *dev, struct zio_attribute *zattr,
case
FT_CMD_SET_HOST_TIME
:
return
ft_set_host_time
(
ft
);
case
FT_CMD_WR_ENABLE
:
return
ft_wr_mode
(
ft
,
1
);
case
FT_CMD_WR_DISABLE
:
return
ft_wr_mode
(
ft
,
0
);
case
FT_CMD_WR_QUERY
:
dev_warn
(
&
ft
->
fmc
->
dev
,
"%s: sorry, no White Rabbit support yet."
,
__func__
);
return
-
ENOTSUPP
;
return
ft_wr_query
(
ft
);
default:
return
-
EINVAL
;
}
}
static
int
ft_wr_mode
(
struct
fmctdc_dev
*
fd
,
int
on
)
{
#if 0
unsigned long flags;
uint32_t tcr;
spin_lock_irqsave(&ft->lock, flags);
// tcr = fd_readl(fd, FD_REG_TCR);
if (on) {
fd_writel(fd, FD_TCR_WR_ENABLE, FD_REG_TCR);
set_bit(FD_FLAG_WR_MODE, &fd->flags);
} else {
fd_writel(fd, 0, FD_REG_TCR);
clear_bit(FD_FLAG_WR_MODE, &fd->flags);
/* not white-rabbit: write default to DAC for VCXO */
fd_spi_xfer(fd, FD_CS_DAC, 24,
ft->calib.vcxo_default_tune & 0xffff, NULL);
}
spin_unlock_irqrestore(&fd->lock, flags);
if(! (tcr & FD_TCR_WR_PRESENT))
return -EOPNOTSUPP;
else if( ! (tcr & FD_TCR_WR_LINK))
return -ENOLINK;
else
return 0;
#endif
return
0
;
}
static
int
ft_wr_query
(
struct
fmctdc_dev
*
ft
)
{
#if 0
int ena = test_bit(FD_FLAG_WR_MODE, &fd->flags);
if (!ena)
return -ENODEV;
if (! (fd_readl(fd, FD_REG_TCR) & FD_TCR_WR_LINK))
return -ENOLINK;
if (fd_readl(fd, FD_REG_TCR) & FD_TCR_WR_LOCKED)
return 0;
return -EAGAIN;
#endif
return
0
;
}
/*
* The probe function receives a new zio_device, which is different from
* what we allocated (that one is the "hardwre" device) but has the
...
...
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