Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FMC DEL 1ns 4cha - 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 DEL 1ns 4cha - Software
Commits
7bd454c9
Commit
7bd454c9
authored
Apr 29, 2012
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fd-zio: initial input support (incomplete, bugged)
parent
5a3a351b
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
155 additions
and
16 deletions
+155
-16
fd-zio.c
fd-zio.c
+140
-15
fine-delay.h
fine-delay.h
+15
-1
No files found.
fd-zio.c
View file @
7bd454c9
...
...
@@ -13,33 +13,133 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/io.h>
#include <linux/zio.h>
#include <linux/zio-buffer.h>
#include <linux/zio-trigger.h>
#include "spec.h"
#include "fine-delay.h"
#include "hw/fd_main_regs.h"
/*
* We have a number of attributes here. For input channels they are:
*
* UTC-h (expected to be 0 untile 2038 a.d.),
* UTC-l
* coarse time
* fractional time
* sequential ID
* channel
*
* See the enum in "fine-delay.h"
*/
static
struct
zio_attribute
fd_zattr_input
[]
=
{
ZATTR_EXT_REG
(
"utc-h"
,
S_IRUGO
,
FD_ATTR_IN_UTC_H
,
0
),
ZATTR_EXT_REG
(
"utc-l"
,
S_IRUGO
,
FD_ATTR_IN_UTC_L
,
0
),
ZATTR_EXT_REG
(
"coarse"
,
S_IRUGO
,
FD_ATTR_IN_COARSE
,
0
),
ZATTR_EXT_REG
(
"frac"
,
S_IRUGO
,
FD_ATTR_IN_FRAC
,
0
),
ZATTR_EXT_REG
(
"seq"
,
S_IRUGO
,
FD_ATTR_IN_SEQ
,
0
),
ZATTR_EXT_REG
(
"chan"
,
S_IRUGO
,
FD_ATTR_IN_CHAN
,
0
),
};
/*
FIXME: all the attributes
*/
/*
The sample size. Mandatory, device-wide
*/
DEFINE_ZATTR_STD
(
ZDEV
,
fd_zattr_dev
)
=
{
ZATTR_REG
(
zdev
,
ZATTR_NBITS
,
S_IRUGO
,
0
,
1
),
/* 1 bit. bah...
*/
ZATTR_REG
(
zdev
,
ZATTR_NBITS
,
S_IRUGO
,
0
,
32
),
/* 32 bits. Really?
*/
};
static
int
fd_read_fifo
(
struct
spec_fd
*
fd
,
struct
zio_channel
*
chan
)
{
struct
zio_control
*
ctrl
;
uint32_t
*
v
,
reg
;
if
((
fd_readl
(
fd
,
FD_REG_TSBCR
)
&
FD_TSBCR_EMPTY
))
return
-
EAGAIN
;
if
(
!
chan
->
active_block
)
return
0
;
ctrl
=
zio_get_ctrl
(
chan
->
active_block
);
/* The input data is written to attributes */
v
=
ctrl
->
attr_channel
.
ext_val
;
v
[
FD_ATTR_IN_UTC_H
]
=
fd_readl
(
fd
,
FD_REG_TSBR_SECH
)
&
0xff
;
v
[
FD_ATTR_IN_UTC_L
]
=
fd_readl
(
fd
,
FD_REG_TSBR_SECL
);
v
[
FD_ATTR_IN_COARSE
]
=
fd_readl
(
fd
,
FD_REG_TSBR_CYCLES
)
&
0xfffffff
;
reg
=
fd_readl
(
fd
,
FD_REG_TSBR_FID
);
v
[
FD_ATTR_IN_FRAC
]
=
FD_TSBR_FID_FINE_R
(
reg
);
v
[
FD_ATTR_IN_SEQ
]
=
FD_TSBR_FID_SEQID_R
(
reg
);
v
[
FD_ATTR_IN_CHAN
]
=
FD_TSBR_FID_CHANNEL_R
(
reg
);
return
0
;
}
/*
* We have a timer, used to poll for input samples, until the interrupt
* is there. A timer duration of 0 selects the interrupt.
*/
static
int
fd_timer_period_ms
=
100
;
module_param_named
(
timer_ms
,
fd_timer_period_ms
,
int
,
0444
);
static
int
fd_timer_period_jiffies
;
/* converted from ms at init time */
static
struct
zio_device
*
__HACK__ZDEV__
;
/* don't do it! */
static
struct
spec_fd
*
__HACK__FD__
;
/* don't do it! */
static
void
fd_timer_fn
(
unsigned
long
arg
)
{
struct
spec_fd
*
fd
=
(
void
*
)
arg
;
struct
zio_channel
*
chan
=
NULL
;
struct
zio_device
*
zdev
=
__HACK__ZDEV__
;
if
(
zdev
)
{
chan
=
zdev
->
cset
[
0
].
chan
;
}
else
{
/* nobody read the device so far: we lack the information */
goto
out
;
}
/* FIXME: manage an array of input samples */
if
(
fd_read_fifo
(
fd
,
chan
)
==
0
)
{
if
(
chan
->
active_block
)
chan
->
cset
->
trig
->
t_op
->
data_done
(
chan
->
cset
);
else
pr_err
(
"data and no block
\n
"
);
}
out:
mod_timer
(
&
fd
->
timer
,
jiffies
+
fd_timer_period_jiffies
);
}
static
int
fd_output
(
struct
zio_cset
*
cset
)
{
/* FIXME:
use chan->active_block
*/
/* FIXME:
the output channels
*/
return
0
;
/* Already done, as the trigger is hardware */
}
/*
* The input method will return immediately, because input is
* asynchronous. The data_done callback is invoked when the block is
* full.
*/
static
int
fd_input
(
struct
zio_cset
*
cset
)
{
/* FIXME: fill chan->active_block */
struct
spec_fd
*
fd
;
return
0
;
/* Already done, as the trigger is hardware */
__HACK__ZDEV__
=
cset
->
zdev
;
fd
=
__HACK__FD__
;
/* Configure the device for input */
if
(
!
fd
->
flags
&
FD_FLAG_INPUT
)
{
fd_writel
(
fd
,
FD_TSBCR_PURGE
|
FD_TSBCR_RST_SEQ
,
FD_REG_TSBCR
);
fd_writel
(
fd
,
FD_TSBCR_CHAN_MASK_W
(
1
)
|
FD_TSBCR_ENABLE
,
FD_REG_TSBCR
);
fd
->
flags
|=
FD_FLAG_INPUT
;
}
return
-
EAGAIN
;
/* Will be completed over time */
}
/* We have 5 csets, since each output triggers separately */
...
...
@@ -48,41 +148,46 @@ static struct zio_cset fd_cset[] = {
SET_OBJECT_NAME
(
"fd-input"
),
.
raw_io
=
fd_input
,
.
n_chan
=
1
,
.
ssize
=
1
,
/* FIXME: 0? */
.
ssize
=
4
,
/* FIXME: 0? */
.
flags
=
ZIO_DIR_INPUT
|
ZCSET_TYPE_TIME
,
.
zattr_set
=
{
.
ext_zattr
=
fd_zattr_input
,
.
n_ext_attr
=
ARRAY_SIZE
(
fd_zattr_input
),
},
},
{
SET_OBJECT_NAME
(
"fd-ch1"
),
.
raw_io
=
fd_output
,
.
n_chan
=
1
,
.
ssize
=
1
,
/* FIXME: 0? */
.
ssize
=
4
,
/* FIXME: 0? */
.
flags
=
ZIO_DIR_OUTPUT
|
ZCSET_TYPE_TIME
,
},
{
SET_OBJECT_NAME
(
"fd-ch2"
),
.
raw_io
=
fd_output
,
.
n_chan
=
1
,
.
ssize
=
1
,
/* FIXME: 0? */
.
ssize
=
4
,
/* FIXME: 0? */
.
flags
=
ZIO_DIR_OUTPUT
|
ZCSET_TYPE_TIME
,
},
{
SET_OBJECT_NAME
(
"fd-ch3"
),
.
raw_io
=
fd_output
,
.
n_chan
=
1
,
.
ssize
=
1
,
/* FIXME: 0? */
.
ssize
=
4
,
/* FIXME: 0? */
.
flags
=
ZIO_DIR_OUTPUT
|
ZCSET_TYPE_TIME
,
},
{
SET_OBJECT_NAME
(
"fd-ch4"
),
.
raw_io
=
fd_output
,
.
n_chan
=
1
,
.
ssize
=
1
,
/* FIXME: 0? */
.
ssize
=
4
,
/* FIXME: 0? */
.
flags
=
ZIO_DIR_OUTPUT
|
ZCSET_TYPE_TIME
,
},
};
static
struct
zio_device
fd_tmpl
=
{
.
owner
=
THIS_MODULE
,
.
preferred_trigger
=
"user"
,
.
cset
=
fd_cset
,
.
n_cset
=
ARRAY_SIZE
(
fd_cset
),
.
zattr_set
=
{
...
...
@@ -90,7 +195,6 @@ static struct zio_device fd_tmpl = {
},
};
static
const
struct
zio_device_id
fd_table
[]
=
{
{
"fd"
,
&
fd_tmpl
},
{},
...
...
@@ -114,7 +218,15 @@ int fd_zio_register(void)
if
(
err
)
return
err
;
/* FIXME: register a trigger too */
fd_timer_period_jiffies
=
msecs_to_jiffies
(
fd_timer_period_ms
);
if
(
fd_timer_period_ms
)
{
pr_info
(
"%s: using a timer for input stamps (%i ms)
\n
"
,
KBUILD_MODNAME
,
fd_timer_period_ms
);
}
else
{
pr_info
(
"%s: NOT using interrupt (not implemented)
\n
"
,
KBUILD_MODNAME
);
return
-
EINVAL
;
}
return
0
;
}
...
...
@@ -129,21 +241,34 @@ void fd_zio_unregister(void)
int
fd_zio_init
(
struct
spec_fd
*
fd
)
{
int
err
=
0
;
struct
pci_dev
*
pdev
;
int
dev_id
;
fd
->
zdev
=
zio_allocate_device
();
if
(
IS_ERR
(
fd
->
zdev
))
return
PTR_ERR
(
fd
->
zdev
);
/* Our dev_id is bus+devfn */
pdev
=
fd
->
spec
->
pdev
;
dev_id
=
(
pdev
->
bus
->
number
<<
8
)
|
pdev
->
devfn
;
fd
->
zdev
->
owner
=
THIS_MODULE
;
err
=
zio_register_device
(
fd
->
zdev
,
"fd"
,
0
);
err
=
zio_register_device
(
fd
->
zdev
,
"fd"
,
dev_id
);
if
(
err
)
{
zio_free_device
(
fd
->
zdev
);
return
err
;
}
__HACK__FD__
=
fd
;
setup_timer
(
&
fd
->
timer
,
fd_timer_fn
,
(
unsigned
long
)
fd
);
if
(
fd_timer_period_ms
)
mod_timer
(
&
fd
->
timer
,
jiffies
+
fd_timer_period_jiffies
);
return
0
;
}
void
fd_zio_exit
(
struct
spec_fd
*
fd
)
{
del_timer_sync
(
&
fd
->
timer
);
zio_unregister_device
(
fd
->
zdev
);
zio_free_device
(
fd
->
zdev
);
}
fine-delay.h
View file @
7bd454c9
...
...
@@ -2,6 +2,7 @@
#define __FINE_DELAY_H__
#include <linux/spinlock.h>
#include <linux/timer.h>
struct
fd_calib
{
int64_t
frr_poly
[
3
];
/* SY89295 delay/temp poly coeffs */
...
...
@@ -33,8 +34,10 @@ struct fd_ch {
/* This is the device we use all around */
struct
spec_fd
{
spinlock_t
lock
;
unsigned
long
flags
;
struct
spec_dev
*
spec
;
struct
zio_device
*
zdev
;
struct
timer_list
timer
;
struct
fd_calib
calib
;
struct
fd_ch
ch
[
FD_CH_NUMBER
];
unsigned
char
__iomem
*
base
;
/* regs files are byte-oriented */
...
...
@@ -47,8 +50,9 @@ struct spec_fd {
int
temp
;
/* temperature: scaled by 4 bits */
int
verbose
;
};
#define FD_FLAG_INPUT 1
/* temporary: check flags */
/* Internal time: the first three fields
are just
converted to zio time */
/* Internal time: the first three fields
should be
converted to zio time */
struct
fd_time
{
int64_t
utc
;
int32_t
coarse
;
...
...
@@ -57,6 +61,16 @@ struct fd_time {
uint16_t
seq_id
;
};
/* input ZIO attributes (actually, the internal time is represented as attrs */
enum
fd_zattr_in_idx
{
FD_ATTR_IN_UTC_H
=
0
,
FD_ATTR_IN_UTC_L
,
FD_ATTR_IN_COARSE
,
FD_ATTR_IN_FRAC
,
FD_ATTR_IN_SEQ
,
FD_ATTR_IN_CHAN
,
};
static
inline
uint32_t
fd_readl
(
struct
spec_fd
*
fd
,
unsigned
long
reg
)
{
...
...
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