Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FMC DIO 5ch TTL a
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
6
Issues
6
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 DIO 5ch TTL a
Commits
85bc40be
Commit
85bc40be
authored
May 14, 2020
by
Jorge Machado
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adapt kernel sources to the new structure
parent
a3efe86e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
229 additions
and
104 deletions
+229
-104
Kbuild
sw/kernel/Kbuild
+4
-1
fmc-dio-internal.c
sw/kernel/fmc-dio-internal.c
+203
-101
fmc-dio.c
sw/kernel/fmc-dio.c
+18
-2
fmc-dio.h
sw/kernel/fmc-dio.h
+4
-0
No files found.
sw/kernel/Kbuild
View file @
85bc40be
...
@@ -20,7 +20,10 @@ ccflags-y += -DGIT_VERSION=\"$(GIT_VERSION)\"
...
@@ -20,7 +20,10 @@ ccflags-y += -DGIT_VERSION=\"$(GIT_VERSION)\"
obj-m += wr-dio.o
obj-m += wr-dio.o
wr-dio-y = fmc-dio.o
wr-dio-y = ./hw/wr-dio-regs.o
wr-dio-y += ./hw/wr-dio-regs_v1.o
wr-dio-y += ./hw/wr-dio-regs_v2.o
wr-dio-y += fmc-dio.o
wr-dio-y += fmc-dio-internal.o
wr-dio-y += fmc-dio-internal.o
wr-dio-y += fmc-dio-mdev.o
wr-dio-y += fmc-dio-mdev.o
wr-dio-y += fmc-dio-gpio.o
wr-dio-y += fmc-dio-gpio.o
\ No newline at end of file
sw/kernel/fmc-dio-internal.c
View file @
85bc40be
...
@@ -32,75 +32,23 @@
...
@@ -32,75 +32,23 @@
#define fmc_dio_stat 0
#define fmc_dio_stat 0
#endif
#endif
/* We need a clear mapping for the registers of the various bits */
#define CHANNEL_5_IRQ_EN_MASK 0x100000
struct
regmap
{
int
trig_l
;
int
trig_h
;
int
cycle
;
int
pulse
;
int
fifo_tai_l
;
int
fifo_tai_h
;
int
fifo_cycle
;
int
fifo_status
;
};
#define R(x) (offsetof(struct DIO_WB, x))
static
struct
regmap
regmap
[]
=
{
{
.
trig_l
=
R
(
TRIG0
),
.
trig_h
=
R
(
TRIGH0
),
.
cycle
=
R
(
CYC0
),
.
pulse
=
R
(
PROG0_PULSE
),
.
fifo_tai_l
=
R
(
TSF0_R0
),
.
fifo_tai_h
=
R
(
TSF0_R1
),
.
fifo_cycle
=
R
(
TSF0_R2
),
.
fifo_status
=
R
(
TSF0_CSR
),
},
{
.
trig_l
=
R
(
TRIG1
),
.
trig_h
=
R
(
TRIGH1
),
.
cycle
=
R
(
CYC1
),
.
pulse
=
R
(
PROG1_PULSE
),
.
fifo_tai_l
=
R
(
TSF1_R0
),
.
fifo_tai_h
=
R
(
TSF1_R1
),
.
fifo_cycle
=
R
(
TSF1_R2
),
.
fifo_status
=
R
(
TSF1_CSR
),
},
{
.
trig_l
=
R
(
TRIG2
),
.
trig_h
=
R
(
TRIGH2
),
.
cycle
=
R
(
CYC2
),
.
pulse
=
R
(
PROG2_PULSE
),
.
fifo_tai_l
=
R
(
TSF2_R0
),
.
fifo_tai_h
=
R
(
TSF2_R1
),
.
fifo_cycle
=
R
(
TSF2_R2
),
.
fifo_status
=
R
(
TSF2_CSR
),
},
{
.
trig_l
=
R
(
TRIG3
),
.
trig_h
=
R
(
TRIGH3
),
.
cycle
=
R
(
CYC3
),
.
pulse
=
R
(
PROG3_PULSE
),
.
fifo_tai_l
=
R
(
TSF3_R0
),
.
fifo_tai_h
=
R
(
TSF3_R1
),
.
fifo_cycle
=
R
(
TSF3_R2
),
.
fifo_status
=
R
(
TSF3_CSR
),
},
{
.
trig_l
=
R
(
TRIG4
),
.
trig_h
=
R
(
TRIGH4
),
.
cycle
=
R
(
CYC4
),
.
pulse
=
R
(
PROG4_PULSE
),
.
fifo_tai_l
=
R
(
TSF4_R0
),
.
fifo_tai_h
=
R
(
TSF4_R1
),
.
fifo_cycle
=
R
(
TSF4_R2
),
.
fifo_status
=
R
(
TSF4_CSR
),
}
};
#define FMC_DIO_IRQ_MASK \
#define FMC_DIO_IRQ_MASK
\
(DIO_EIC_ISR_NEMPTY_0 \
(DIO_EIC_ISR_NEMPTY_0 \
| DIO_EIC_ISR_NEMPTY_1
\
| DIO_EIC_ISR_NEMPTY_1\
| DIO_EIC_ISR_NEMPTY_2
\
| DIO_EIC_ISR_NEMPTY_2\
| DIO_EIC_ISR_NEMPTY_3\
| DIO_EIC_ISR_NEMPTY_3\
| DIO_EIC_ISR_NEMPTY_4)
| DIO_EIC_ISR_NEMPTY_4)
#define FMC_DIO_IRQ_MASK_V2 \
(DIO_EIC_ISR_NEMPTY_0 \
| DIO_EIC_ISR_NEMPTY_1\
| DIO_EIC_ISR_NEMPTY_2\
| DIO_EIC_ISR_NEMPTY_3\
| DIO_EIC_ISR_NEMPTY_4\
| DIO_EIC_ISR_NEMPTY_5)
/* This is the structure we need to manage interrupts and loop internally */
/* This is the structure we need to manage interrupts and loop internally */
#define FMC_DIO_BUFFER_LEN 512
#define FMC_DIO_BUFFER_LEN 512
struct
dio_channel
{
struct
dio_channel
{
...
@@ -115,7 +63,7 @@ struct dio_channel {
...
@@ -115,7 +63,7 @@ struct dio_channel {
};
};
struct
dio_device
{
struct
dio_device
{
struct
dio_channel
ch
[
5
];
struct
dio_channel
ch
[
6
];
};
};
/* Instead of timespec_sub, just subtract the nanos */
/* Instead of timespec_sub, just subtract the nanos */
...
@@ -128,25 +76,27 @@ static inline void fmc_dio_int_ts_sub(struct timespec *ts, int nano)
...
@@ -128,25 +76,27 @@ static inline void fmc_dio_int_ts_sub(struct timespec *ts, int nano)
static
void
__fmc_dio_int_new_pulse
(
struct
fmc_dio
*
dev
,
int
ch
,
static
void
__fmc_dio_int_new_pulse
(
struct
fmc_dio
*
dev
,
int
ch
,
struct
timespec
*
ts
)
struct
timespec
*
ts
)
{
{
struct
DIO_WB
__iomem
*
dio
=
dev
->
dio
;
void
__iomem
*
base
=
dev
->
dio
;
void
__iomem
*
base
=
dio
;
struct
regmap
*
map
;
struct
regmap
*
map
;
map
=
regmap
+
ch
;
struct
regmap_common
dio
;
dio
=
get_regmap_common
(
dev
->
version
);
map
=
get_regmap
(
dev
->
version
);
map
+=
ch
;
fmc_dio_int_ts_sub
(
ts
,
8
);
/* 1 cycle, to account for output latencies */
fmc_dio_int_ts_sub
(
ts
,
8
);
/* 1 cycle, to account for output latencies */
writel
(
ts
->
tv_nsec
/
8
,
base
+
map
->
cycle
);
writel
(
ts
->
tv_nsec
/
8
,
base
+
map
->
cycle
);
writel
(
GET_HI32
(
ts
->
tv_sec
),
base
+
map
->
trig_h
);
writel
(
GET_HI32
(
ts
->
tv_sec
),
base
+
map
->
trig_h
);
writel
(
ts
->
tv_sec
,
base
+
map
->
trig_l
);
writel
(
ts
->
tv_sec
,
base
+
map
->
trig_l
);
writel
(
1
<<
ch
,
&
dio
->
R_LATCH
);
writel
(
1
<<
ch
,
base
+
dio
.
latch_reg
);
}
}
static
int
fmc_dio_int_cmd_pulse
(
struct
fmc_dio
*
dev
,
static
int
fmc_dio_int_cmd_pulse
(
struct
fmc_dio
*
dev
,
struct
wr_dio_cmd
*
cmd
)
struct
wr_dio_cmd
*
cmd
)
{
{
struct
DIO_WB
__iomem
*
dio
=
dev
->
dio
;
void
__iomem
*
base
=
dev
->
dio
;
void
__iomem
*
base
=
dio
;
struct
PPSG_WB
__iomem
*
ppsg
=
dev
->
ppsg
;
struct
PPSG_WB
__iomem
*
ppsg
=
dev
->
ppsg
;
struct
dio_device
*
d
=
dev
->
priv
;
struct
dio_device
*
d
=
dev
->
priv
;
struct
dio_channel
*
c
;
struct
dio_channel
*
c
;
...
@@ -154,31 +104,45 @@ static int fmc_dio_int_cmd_pulse(struct fmc_dio *dev,
...
@@ -154,31 +104,45 @@ static int fmc_dio_int_cmd_pulse(struct fmc_dio *dev,
struct
timespec
*
ts
;
struct
timespec
*
ts
;
uint32_t
reg
;
uint32_t
reg
;
int
ch
;
int
ch
;
struct
regmap_common
dio
;
dio
=
get_regmap_common
(
dev
->
version
);
ch
=
cmd
->
channel
;
ch
=
cmd
->
channel
;
if
(
ch
>
4
)
if
(
ch
>
4
)
return
-
EINVAL
;
/* mask not supported */
return
-
EINVAL
;
/* mask not supported */
c
=
d
->
ch
+
ch
;
c
=
d
->
ch
+
ch
;
map
=
regmap
+
ch
;
map
=
get_regmap
(
dev
->
version
);
map
+=
ch
;
ts
=
cmd
->
t
;
ts
=
cmd
->
t
;
/* First, configure this bit as DIO output */
/* First, configure this bit as DIO output */
reg
=
readl
(
&
dio
->
IOMODE
);
reg
=
readl
(
base
+
dio
.
iomode_reg
);
writel
(
reg
|
(
1
<<
4
*
ch
),
&
dio
->
IOMODE
);
writel
(
reg
|
(
1
<<
4
*
ch
),
base
+
dio
.
iomode_reg
);
writel
(
ts
[
1
].
tv_nsec
/
8
,
base
+
map
->
pulse
);
/* width */
writel
(
ts
[
1
].
tv_nsec
/
8
,
base
+
map
->
pulse
);
/* width */
if
(
cmd
->
flags
&
WR_DIO_F_NOW
)
{
if
(
cmd
->
flags
&
WR_DIO_F_NOW
)
{
/* Generate a pulse train from current time in V2 DIO version*/
if
(
dev
->
version
==
1
)
{
if
(
cmd
->
flags
&
WR_DIO_F_LOOP
&&
cmd
->
value
!=
1
)
{
writel
(
ts
[
2
].
tv_nsec
/
8
,
base
+
map
->
pulse_per
);
c
->
target_channel
=
ch
;
if
(
cmd
->
value
>
1
)
{
cmd
->
value
-=
2
;
}
atomic_set
(
&
c
->
count
,
cmd
->
value
);
}
}
/* if "now" we are done */
/* if "now" we are done */
writel
(
1
<<
ch
,
&
dio
->
PULSE
);
writel
(
1
<<
ch
,
base
+
dio
.
pulse_reg
);
return
0
;
return
0
;
}
}
/* if relative, add current 40-bit second to timespec */
/* if relative, add current 40-bit second to timespec */
if
(
cmd
->
flags
&
WR_DIO_F_REL
)
{
if
(
cmd
->
flags
&
WR_DIO_F_REL
)
{
uint32_t
h1
,
l
,
h2
;
uint32_t
h1
,
l
,
h2
;
unsigned
long
now
;
unsigned
long
now
;
h1
=
readl
(
&
ppsg
->
CNTR_UTCHI
);
h1
=
readl
(
&
ppsg
->
CNTR_UTCHI
);
l
=
readl
(
&
ppsg
->
CNTR_UTCLO
);
l
=
readl
(
&
ppsg
->
CNTR_UTCLO
);
h2
=
readl
(
&
ppsg
->
CNTR_UTCHI
);
h2
=
readl
(
&
ppsg
->
CNTR_UTCHI
);
...
@@ -189,15 +153,24 @@ static int fmc_dio_int_cmd_pulse(struct fmc_dio *dev,
...
@@ -189,15 +153,24 @@ static int fmc_dio_int_cmd_pulse(struct fmc_dio *dev,
ts
->
tv_sec
+=
now
;
ts
->
tv_sec
+=
now
;
}
}
if
(
cmd
->
flags
&
WR_DIO_F_LOOP
)
{
if
(
cmd
->
flags
&
WR_DIO_F_LOOP
&&
cmd
->
value
!=
1
)
{
c
->
target_channel
=
ch
;
c
->
target_channel
=
ch
;
if
(
dev
->
version
==
0
)
{
c
->
delay
=
ts
[
2
];
/* c->count is used after the pulse, so remove the first */
if
(
cmd
->
value
>
0
)
cmd
->
value
--
;
}
else
{
writel
(
ts
[
2
].
tv_nsec
/
8
,
base
+
map
->
pulse_per
);
if
(
cmd
->
value
>
1
)
{
cmd
->
value
-=
2
;
}
}
/* c->count is used after the pulse, so remove the first */
if
(
cmd
->
value
>
0
)
cmd
->
value
--
;
atomic_set
(
&
c
->
count
,
cmd
->
value
);
atomic_set
(
&
c
->
count
,
cmd
->
value
);
c
->
prevts
=
ts
[
0
];
/* our current setpoint */
c
->
prevts
=
ts
[
0
];
/* our current setpoint */
c
->
delay
=
ts
[
2
];
}
}
__fmc_dio_int_new_pulse
(
dev
,
ch
,
ts
);
__fmc_dio_int_new_pulse
(
dev
,
ch
,
ts
);
...
@@ -221,7 +194,10 @@ static int fmc_dio_int_cmd_stamp(struct fmc_dio *dev,
...
@@ -221,7 +194,10 @@ static int fmc_dio_int_cmd_stamp(struct fmc_dio *dev,
again:
again:
if
(
cmd
->
flags
&
WR_DIO_F_MASK
)
{
if
(
cmd
->
flags
&
WR_DIO_F_MASK
)
{
ch
=
0
;
ch
=
0
;
last
=
4
;
if
(
dev
->
version
==
0
)
last
=
4
;
else
last
=
5
;
mask
=
cmd
->
channel
;
mask
=
cmd
->
channel
;
}
else
{
}
else
{
ch
=
cmd
->
channel
;
ch
=
cmd
->
channel
;
...
@@ -233,7 +209,10 @@ again:
...
@@ -233,7 +209,10 @@ again:
for
(;
ch
<=
last
;
ch
++
,
c
++
)
{
for
(;
ch
<=
last
;
ch
++
,
c
++
)
{
if
(((
1
<<
ch
)
&
mask
)
==
0
)
if
(((
1
<<
ch
)
&
mask
)
==
0
)
continue
;
continue
;
map
=
regmap
+
ch
;
map
=
get_regmap
(
dev
->
version
);
map
+=
ch
;
while
(
1
)
{
while
(
1
)
{
if
(
nstamp
==
WR_DIO_N_STAMP
)
if
(
nstamp
==
WR_DIO_N_STAMP
)
break
;
break
;
...
@@ -270,10 +249,13 @@ again:
...
@@ -270,10 +249,13 @@ again:
static
int
fmc_dio_int_cmd_inout
(
struct
fmc_dio
*
dev
,
static
int
fmc_dio_int_cmd_inout
(
struct
fmc_dio
*
dev
,
struct
wr_dio_cmd
*
cmd
)
struct
wr_dio_cmd
*
cmd
)
{
{
struct
DIO_WB
__iomem
*
dio
=
dev
->
dio
;
struct
fmc_dio_gpio_block
__iomem
*
gpio
=
dev
->
gpio
;
struct
fmc_dio_gpio_block
__iomem
*
gpio
=
dev
->
gpio
;
int
mask
,
ch
,
last
,
bits
;
int
mask
,
ch
,
last
,
bits
;
uint32_t
reg
,
iomode
;
uint32_t
reg
,
iomode
;
void
__iomem
*
base
=
dev
->
dio
;
struct
regmap_common
dio
;
dio
=
get_regmap_common
(
dev
->
version
);
if
(
cmd
->
flags
&
WR_DIO_F_MASK
)
{
if
(
cmd
->
flags
&
WR_DIO_F_MASK
)
{
ch
=
0
;
ch
=
0
;
...
@@ -294,7 +276,7 @@ static int fmc_dio_int_cmd_inout(struct fmc_dio *dev,
...
@@ -294,7 +276,7 @@ static int fmc_dio_int_cmd_inout(struct fmc_dio *dev,
bits
=
cmd
->
value
>>
ch
;
bits
=
cmd
->
value
>>
ch
;
/* Obtain the current value in iomode */
/* Obtain the current value in iomode */
reg
=
readl
(
&
dio
->
IOMODE
)
&
~
(
0xF
<<
4
*
ch
);
reg
=
readl
(
base
+
dio
.
iomode_reg
)
&
~
(
0xF
<<
4
*
ch
);
/* Select IO mode */
/* Select IO mode */
if
(
bits
&
WR_DIO_INOUT_DIO
)
{
if
(
bits
&
WR_DIO_INOUT_DIO
)
{
...
@@ -315,9 +297,89 @@ static int fmc_dio_int_cmd_inout(struct fmc_dio *dev,
...
@@ -315,9 +297,89 @@ static int fmc_dio_int_cmd_inout(struct fmc_dio *dev,
/* Appends to iomode TERM and OUTPUT_ENABLE_N bits */
/* Appends to iomode TERM and OUTPUT_ENABLE_N bits */
iomode
|=
(((
bits
&
WR_DIO_INOUT_TERM
)
!=
0
)
<<
3
)
iomode
|=
(((
bits
&
WR_DIO_INOUT_TERM
)
!=
0
)
<<
3
)
|
(((
bits
&
WR_DIO_INOUT_OUTPUT
)
==
0
)
<<
2
);
|
(((
bits
&
WR_DIO_INOUT_OUTPUT
)
==
0
)
<<
2
);
writel
(
reg
|
(
iomode
<<
4
*
ch
),
&
dio
->
IOMODE
);
writel
(
reg
|
(
iomode
<<
4
*
ch
),
base
+
dio
.
iomode_reg
);
}
return
0
;
}
static
int
fmc_dio_int_cmd_irq
(
struct
fmc_dio
*
dev
,
struct
wr_dio_cmd
*
cmd
)
{
void
__iomem
*
base
=
dev
->
dio
;
struct
PPSG_WB
__iomem
*
ppsg
=
dev
->
ppsg
;
struct
dio_device
*
d
=
dev
->
priv
;
struct
dio_channel
*
c
;
struct
regmap
*
map
;
struct
timespec
*
ts
;
uint32_t
reg
;
int
ch
;
struct
regmap_common
dio
;
if
(
dev
->
version
!=
1
)
return
-
ENOTSUPP
;
dio
=
get_regmap_common
(
dev
->
version
);
ch
=
5
;
c
=
d
->
ch
+
ch
;
map
=
get_regmap
(
dev
->
version
);
map
+=
ch
;
ts
=
cmd
->
t
;
/* First, configure the IRQ channel */
reg
=
readl
(
base
+
dio
.
iomode_reg
);
writel
((
reg
|
CHANNEL_5_IRQ_EN_MASK
),
base
+
dio
.
iomode_reg
);
writel
(
100
,
base
+
map
->
pulse
);
/* width */
if
(
cmd
->
flags
&
WR_DIO_F_NOW
)
{
/* Generate a pulse train from current time*/
if
(
cmd
->
flags
&
WR_DIO_F_LOOP
&&
cmd
->
value
!=
1
)
{
writel
(
ts
[
1
].
tv_nsec
/
8
,
base
+
map
->
pulse_per
);
c
->
target_channel
=
ch
;
if
(
cmd
->
value
>
1
)
{
cmd
->
value
-=
2
;
}
atomic_set
(
&
c
->
count
,
cmd
->
value
);
}
writel
(
1
<<
ch
,
base
+
dio
.
pulse_reg
);
return
0
;
}
/* if relative, add current 40-bit 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
;
SET_HI32
(
now
,
h2
);
ts
->
tv_sec
+=
now
;
}
}
if
(
cmd
->
flags
&
WR_DIO_F_LOOP
&&
cmd
->
value
!=
1
)
{
c
->
target_channel
=
ch
;
writel
(
ts
[
1
].
tv_nsec
/
8
,
base
+
map
->
pulse_per
);
if
(
cmd
->
value
>
1
)
{
cmd
->
value
-=
2
;
}
atomic_set
(
&
c
->
count
,
cmd
->
value
);
c
->
prevts
=
ts
[
0
];
/* our current setpoint */
}
__fmc_dio_int_new_pulse
(
dev
,
ch
,
ts
);
return
0
;
return
0
;
}
}
...
@@ -359,6 +421,9 @@ int fmc_dio_int_ioctl(struct fmc_dio *dev, unsigned int ioctlcmd,
...
@@ -359,6 +421,9 @@ int fmc_dio_int_ioctl(struct fmc_dio *dev, unsigned int ioctlcmd,
case
WR_DIO_CMD_DAC
:
case
WR_DIO_CMD_DAC
:
ret
=
-
ENOTSUPP
;
ret
=
-
ENOTSUPP
;
goto
out
;
goto
out
;
case
WR_DIO_CMD_IRQ
:
ret
=
fmc_dio_int_cmd_irq
(
dev
,
cmd
);
break
;
default:
default:
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
goto
out
;
goto
out
;
...
@@ -397,7 +462,6 @@ static void fmc_dio_int_trig_next_pulse(struct fmc_dio *dev, int ch,
...
@@ -397,7 +462,6 @@ static void fmc_dio_int_trig_next_pulse(struct fmc_dio *dev, int ch,
irqreturn_t
fmc_dio_int_interrupt
(
struct
fmc_dio
*
dev
)
irqreturn_t
fmc_dio_int_interrupt
(
struct
fmc_dio
*
dev
)
{
{
struct
DIO_WB
__iomem
*
dio
=
dev
->
dio
;
struct
fmc_device
*
fmc
=
dev
->
fmc
;
struct
fmc_device
*
fmc
=
dev
->
fmc
;
void
__iomem
*
base
=
dev
->
dio
;
void
__iomem
*
base
=
dev
->
dio
;
struct
dio_device
*
d
=
dev
->
priv
;
struct
dio_device
*
d
=
dev
->
priv
;
...
@@ -409,10 +473,13 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
...
@@ -409,10 +473,13 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
uint32_t
mask
,
reg
;
uint32_t
mask
,
reg
;
int
ch
,
chm
;
int
ch
,
chm
;
struct
regmap_common
dio
;
dio
=
get_regmap_common
(
dev
->
version
);
if
(
unlikely
(
!
fmc
->
eeprom
))
{
if
(
unlikely
(
!
fmc
->
eeprom
))
{
dev_err
(
fmc
->
hwdev
,
"WR-DIO: No mezzanine, disabling irqs
\n
"
);
dev_err
(
fmc
->
hwdev
,
"WR-DIO: No mezzanine, disabling irqs
\n
"
);
writel
(
~
0
,
&
dio
->
EIC_IDR
);
writel
(
~
0
,
base
+
dio
.
eic_idr_reg
);
writel
(
~
0
,
&
dio
->
EIC_ISR
);
writel
(
~
0
,
base
+
dio
.
eic_isr_reg
);
return
IRQ_NONE
;
return
IRQ_NONE
;
}
}
...
@@ -439,7 +506,10 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
...
@@ -439,7 +506,10 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
}
}
}
}
mask
=
readl
(
&
dio
->
EIC_ISR
)
&
FMC_DIO_IRQ_MASK
;
if
(
dev
->
version
==
0
)
mask
=
readl
(
base
+
dio
.
eic_isr_reg
)
&
FMC_DIO_IRQ_MASK
;
else
mask
=
readl
(
base
+
dio
.
eic_isr_reg
)
&
FMC_DIO_IRQ_MASK_V2
;
/* Three indexes: channel, channel-mask, channel pointer */
/* Three indexes: channel, channel-mask, channel pointer */
for
(
ch
=
0
,
chm
=
1
,
c
=
d
->
ch
;
mask
;
ch
++
,
chm
<<=
1
,
c
++
)
{
for
(
ch
=
0
,
chm
=
1
,
c
=
d
->
ch
;
mask
;
ch
++
,
chm
<<=
1
,
c
++
)
{
...
@@ -450,7 +520,9 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
...
@@ -450,7 +520,9 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
mask
&=
~
chm
;
mask
&=
~
chm
;
/* Pull the FIFOs to the device structure */
/* Pull the FIFOs to the device structure */
map
=
regmap
+
ch
;
map
=
get_regmap
(
dev
->
version
);
map
+=
ch
;
ts
=
NULL
;
ts
=
NULL
;
while
(
1
)
{
while
(
1
)
{
reg
=
readl
(
base
+
map
->
fifo_status
);
reg
=
readl
(
base
+
map
->
fifo_status
);
...
@@ -472,10 +544,31 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
...
@@ -472,10 +544,31 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
/* subtract 5 cycles lost in input sync circuits */
/* subtract 5 cycles lost in input sync circuits */
fmc_dio_int_ts_sub
(
ts
,
40
);
fmc_dio_int_ts_sub
(
ts
,
40
);
}
}
writel
(
chm
,
&
dio
->
EIC_ISR
);
/* ack */
writel
(
chm
,
base
+
dio
.
eic_isr_reg
);
/* ack */
if
(
ts
&&
atomic_read
(
&
c
->
count
)
!=
0
)
{
fmc_dio_int_trig_next_pulse
(
dev
,
ch
,
c
,
ts
);
if
(
dev
->
version
==
0
)
{
if
(
ts
&&
atomic_read
(
&
c
->
count
)
!=
0
)
{
/* Only program new pulse if we are on the DIO V1 */
fmc_dio_int_trig_next_pulse
(
dev
,
ch
,
c
,
ts
);
}
}
else
{
if
(
atomic_read
(
&
c
->
count
)
==
0
)
{
/* If we are on the DIO V2, clear pulse period register
* when all the pulses have been generated
*/
writel
(
0
,
base
+
map
->
pulse_per
);
writel
(
1
<<
ch
,
base
+
dio
.
latch_reg
);
}
else
{
/* If the count is not-infinite, decrement it */
if
(
atomic_read
(
&
c
->
count
)
>
0
)
atomic_dec
(
&
c
->
count
);
}
}
}
wake_up_interruptible
(
&
c
->
q
);
wake_up_interruptible
(
&
c
->
q
);
}
}
t_end
=
ktime_get
();
t_end
=
ktime_get
();
...
@@ -485,10 +578,13 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
...
@@ -485,10 +578,13 @@ irqreturn_t fmc_dio_int_interrupt(struct fmc_dio *dev)
/* Init and exit below are called when a netdevice is created/destroyed */
/* Init and exit below are called when a netdevice is created/destroyed */
int
fmc_dio_internal_create
(
struct
fmc_dio
*
dev
)
int
fmc_dio_internal_create
(
struct
fmc_dio
*
dev
)
{
{
struct
DIO_WB
__iomem
*
dio
=
dev
->
dio
;
struct
dio_device
*
d
;
struct
dio_device
*
d
;
void
__iomem
*
base
=
dev
->
dio
;
int
i
;
int
i
;
struct
regmap_common
dio
;
dio
=
get_regmap_common
(
dev
->
version
);
/* Allocate the data structure and enable interrupts for stamping */
/* Allocate the data structure and enable interrupts for stamping */
d
=
kzalloc
(
sizeof
(
*
d
),
GFP_KERNEL
);
d
=
kzalloc
(
sizeof
(
*
d
),
GFP_KERNEL
);
if
(
!
d
)
if
(
!
d
)
...
@@ -501,15 +597,21 @@ int fmc_dio_internal_create(struct fmc_dio *dev)
...
@@ -501,15 +597,21 @@ int fmc_dio_internal_create(struct fmc_dio *dev)
* Enable interrupts for FIFO, if there's no mezzanine the
* Enable interrupts for FIFO, if there's no mezzanine the
* handler will notice and disable the interrupts
* handler will notice and disable the interrupts
*/
*/
writel
(
FMC_DIO_IRQ_MASK
,
&
dio
->
EIC_IER
);
if
(
dev
->
version
==
0
)
writel
(
FMC_DIO_IRQ_MASK
,
base
+
dio
.
eic_ier_reg
);
else
writel
(
FMC_DIO_IRQ_MASK_V2
,
base
+
dio
.
eic_ier_reg
);
return
0
;
return
0
;
}
}
void
fmc_dio_internal_destroy
(
struct
fmc_dio
*
dev
)
void
fmc_dio_internal_destroy
(
struct
fmc_dio
*
dev
)
{
{
struct
DIO_WB
__iomem
*
dio
=
dev
->
dio
;
struct
regmap_common
dio
;
void
__iomem
*
base
=
dev
->
dio
;
dio
=
get_regmap_common
(
dev
->
version
);
writel
(
~
0
,
&
dio
->
EIC_IDR
);
writel
(
~
0
,
base
+
dio
.
eic_idr_reg
);
if
(
dev
->
priv
)
if
(
dev
->
priv
)
kfree
(
dev
->
priv
);
kfree
(
dev
->
priv
);
}
}
...
...
sw/kernel/fmc-dio.c
View file @
85bc40be
...
@@ -55,7 +55,7 @@ static int fmc_dio_resource_map(struct fmc_dio *dio)
...
@@ -55,7 +55,7 @@ static int fmc_dio_resource_map(struct fmc_dio *dio)
{
{
int
i
,
err
;
int
i
,
err
;
struct
platform_device
*
dev
=
dio
->
pdev
;
struct
platform_device
*
dev
=
dio
->
pdev
;
struct
fmc_device
*
fmc
=
dio
->
fmc
;
//
struct fmc_device *fmc = dio->fmc;
struct
resource
*
r
;
struct
resource
*
r
;
void
__iomem
*
mem
;
void
__iomem
*
mem
;
...
@@ -170,7 +170,19 @@ static int fmc_dio_pl_probe(struct platform_device *dev)
...
@@ -170,7 +170,19 @@ static int fmc_dio_pl_probe(struct platform_device *dev)
// Specific board info
// Specific board info
dio
->
board
=
dev
->
id_entry
->
driver_data
;
dio
->
board
=
dev
->
id_entry
->
driver_data
;
dio
->
pdev
=
dev
;
dio
->
pdev
=
dev
;
dio
->
version
=
dio
->
board
;
if
(
dio
->
version
==
FMC_DIO_BOARD_SPEC
)
{
printk
(
"DIO driver. Detected DIO V1"
);
}
else
if
(
dio
->
version
==
FMC_DIOv2_BOARD_SPEC
)
{
printk
(
"DIO driver. Detected DIO V2"
);
}
else
{
printk
(
"DIO driver. DIO not detected"
);
}
/* Map the resources for the FMC DIO */
/* Map the resources for the FMC DIO */
ret
=
fmc_dio_resource_map
(
dio
);
ret
=
fmc_dio_resource_map
(
dio
);
if
(
ret
)
if
(
ret
)
...
@@ -239,6 +251,10 @@ static const struct platform_device_id fmc_dio_id_table[] = {
...
@@ -239,6 +251,10 @@ static const struct platform_device_id fmc_dio_id_table[] = {
.
name
=
"fmc-dio-spec"
,
.
name
=
"fmc-dio-spec"
,
.
driver_data
=
FMC_DIO_BOARD_SPEC
,
.
driver_data
=
FMC_DIO_BOARD_SPEC
,
},
},
{
/* SPEC compatible */
.
name
=
"fmc-diov2-spec"
,
.
driver_data
=
FMC_DIOv2_BOARD_SPEC
,
},
{},
{},
};
};
...
...
sw/kernel/fmc-dio.h
View file @
85bc40be
...
@@ -52,6 +52,7 @@ struct fmc_dio_gpio_block {
...
@@ -52,6 +52,7 @@ struct fmc_dio_gpio_block {
/* Board constants */
/* Board constants */
#define FMC_DIO_BOARD_SPEC 0
#define FMC_DIO_BOARD_SPEC 0
#define FMC_DIOv2_BOARD_SPEC 1
/**
/**
* @brief FMC DIO structure
* @brief FMC DIO structure
...
@@ -74,6 +75,8 @@ struct fmc_dio {
...
@@ -74,6 +75,8 @@ struct fmc_dio {
int
board
;
/**< Board info */
int
board
;
/**< Board info */
int
version
;
//*< HDL version */
void
*
priv
;
/**< Private data for FMC DIO */
void
*
priv
;
/**< Private data for FMC DIO */
};
};
...
@@ -104,6 +107,7 @@ enum wr_dio_cmd_name {
...
@@ -104,6 +107,7 @@ enum wr_dio_cmd_name {
WR_DIO_CMD_STAMP
,
WR_DIO_CMD_STAMP
,
WR_DIO_CMD_DAC
,
WR_DIO_CMD_DAC
,
WR_DIO_CMD_INOUT
,
WR_DIO_CMD_INOUT
,
WR_DIO_CMD_IRQ
,
};
};
/*
/*
...
...
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