Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Simple PCIe FMC carrier SPEC - Software
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
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
Simple PCIe FMC carrier SPEC - Software
Commits
4bfbcf06
Commit
4bfbcf06
authored
Sep 14, 2012
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kerne/wr-nic-dio: more stuff in ioctl
Signed-off-by:
Alessandro Rubini
<
rubini@gnudd.com
>
parent
bea96ff7
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
135 additions
and
3 deletions
+135
-3
wr-dio.h
kernel/wr-dio.h
+1
-1
wr-nic-dio.c
kernel/wr-nic-dio.c
+134
-2
No files found.
kernel/wr-dio.h
View file @
4bfbcf06
...
...
@@ -28,7 +28,7 @@ struct wr_dio_cmd {
uint32_t
channel
;
/* 0..4 from user */
uint32_t
flags
;
uint32_t
nstamp
;
/* from kernel, if IN_STAMP */
struct
timespec
t
[
WR_DIO_N_STAMP
];
/*
t[0]
may be from user */
struct
timespec
t
[
WR_DIO_N_STAMP
];
/* may be from user */
};
#define WR_DIO_F_NOW 0x01
/* Output is now, t[0] ignored */
...
...
kernel/wr-nic-dio.c
View file @
4bfbcf06
...
...
@@ -10,12 +10,144 @@
#include <linux/module.h>
#include <linux/fmc.h>
#include <linux/fmc-sdb.h>
#include <linux/ktime.h>
#include <asm/uaccess.h>
#include "spec-nic.h"
#include "wr_nic/wr-nic.h"
#include "wr-dio.h"
#define DIO_STAT
#ifdef DIO_STAT
#define wrn_stat 1
#else
#define wrn_stat 0
#endif
/* FIXME: should this access use fmc_readl/writel? */
static
int
wrn_dio_cmd_out
(
struct
wrn_drvdata
*
drvdata
,
struct
wr_dio_cmd
*
cmd
)
{
struct
DIO_WB
__iomem
*
dio
=
drvdata
->
wrdio_base
;
struct
PPSG_WB
__iomem
*
ppsg
=
drvdata
->
ppsg_base
;
void
__iomem
*
p
;
struct
timespec
*
ts
;
uint32_t
val
;
if
(
cmd
->
channel
>
4
)
return
-
EINVAL
;
/* FIXME: mask */
/* First, put this bit as output (FIXME: plain GPIO support?) */
val
=
readl
(
&
dio
->
OUT
)
|
(
1
<<
cmd
->
channel
);
writel
(
val
,
&
dio
->
OUT
);
ts
=
cmd
->
t
;
/* if relative, add current second to timespec */
if
(
cmd
->
flags
&
WR_DIO_F_REL
)
{
uint32_t
h1
,
l
,
h2
;
unsigned
long
now
;
h1
=
readl
(
&
ppsg
->
CNTR_UTCHI
);
l
=
readl
(
&
ppsg
->
CNTR_UTCLO
);
h2
=
readl
(
&
ppsg
->
CNTR_UTCHI
);
if
(
h2
!=
h1
)
l
=
readl
(
&
ppsg
->
CNTR_UTCLO
);
now
=
l
;
if
(
sizeof
(
now
)
>
4
)
now
|=
h2
<<
32
;
ts
->
tv_sec
+=
now
;
printk
(
"relative: %li -> %li
\n
"
,
now
,
ts
->
tv_sec
);
}
/* if not "now", set trig, trigh, cycles */
if
(
!
(
cmd
->
flags
&
WR_DIO_F_NOW
))
{
/* not now: set relevant registers */
p
=
&
dio
->
TRIG0
;
p
+=
(
cmd
->
channel
*
12
);
printk
(
"%li -> %p
\n
"
,
ts
->
tv_sec
,
p
);
writel
(
ts
->
tv_sec
,
p
);
if
(
sizeof
(
ts
->
tv_sec
)
>
4
)
writel
(
ts
->
tv_sec
>>
32
,
p
+
4
);
printk
(
"%li -> %p
\n
"
,
ts
->
tv_nsec
,
p
+
8
);
writel
(
ts
->
tv_nsec
/
8
,
p
+
8
);
}
/* set the width */
ts
++
;
p
=
&
dio
->
PROG0_PULSE
;
p
+=
cmd
->
channel
*
4
;
printk
(
"%li -> %p
\n
"
,
ts
->
tv_nsec
/
8
,
p
);
writel
(
ts
->
tv_nsec
/
8
,
p
);
/* no loop yet (FIXME: interrupts) */
if
(
cmd
->
flags
&
WR_DIO_F_NOW
)
writel
(
1
<<
cmd
->
channel
,
&
dio
->
PULSE
);
else
writel
(
1
<<
cmd
->
channel
,
&
dio
->
R_LATCH
);
return
0
;
}
static
int
wrn_dio_cmd_stamp
(
struct
wrn_drvdata
*
drvdata
,
struct
wr_dio_cmd
*
cmd
)
{
return
-
ENOTSUPP
;
}
int
wrn_mezzanine_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
int
ioctl
cmd
)
{
return
-
EAGAIN
;
struct
wr_dio_cmd
*
cmd
;
struct
wrn_drvdata
*
drvdata
=
dev
->
dev
.
parent
->
platform_data
;
ktime_t
t
,
t0
;
int
ret
;
if
(
ioctlcmd
==
PRIV_MEZZANINE_ID
)
return
-
EAGAIN
;
/* Special marker */
if
(
ioctlcmd
!=
PRIV_MEZZANINE_CMD
)
return
-
ENOIOCTLCMD
;
if
(
wrn_stat
)
{
t0
=
ktime_get
();
}
/* The cmd struct can't fit in the stack, so allocate it */
cmd
=
kmalloc
(
sizeof
(
*
cmd
),
GFP_KERNEL
);
if
(
!
cmd
)
return
-
ENOMEM
;
ret
=
-
EFAULT
;
if
(
copy_from_user
(
cmd
,
rq
->
ifr_data
,
sizeof
(
*
cmd
)))
goto
out
;
switch
(
cmd
->
command
)
{
case
WR_DIO_CMD_OUT
:
ret
=
wrn_dio_cmd_out
(
drvdata
,
cmd
);
break
;
case
WR_DIO_CMD_STAMP
:
ret
=
wrn_dio_cmd_stamp
(
drvdata
,
cmd
);
break
;
case
WR_DIO_CMD_DAC
:
ret
=
-
ENOTSUPP
;
goto
out
;
default:
ret
=
-
EINVAL
;
goto
out
;
}
if
(
copy_to_user
(
rq
->
ifr_data
,
cmd
,
sizeof
(
*
cmd
)))
return
-
EFAULT
;
out:
kfree
(
cmd
);
if
(
wrn_stat
)
{
t
=
ktime_sub
(
ktime_get
(),
t0
);
dev_info
(
&
dev
->
dev
,
"ioctl: %li ns
\n
"
,
(
long
)
ktime_to_ns
(
t
));
}
return
ret
;
}
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