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
99232716
Commit
99232716
authored
Sep 04, 2019
by
Miguel Jimenez Lopez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update FMC DIO driver for new IRQ scheme.
parent
3b614a4b
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
164 additions
and
117 deletions
+164
-117
fmc-dio-mdev.c
sw/kernel/fmc-dio-mdev.c
+1
-5
fmc-dio.c
sw/kernel/fmc-dio.c
+160
-111
fmc-dio.h
sw/kernel/fmc-dio.h
+3
-1
No files found.
sw/kernel/fmc-dio-mdev.c
View file @
99232716
...
...
@@ -26,30 +26,26 @@ static int fmc_dio_mdev_open(struct inode *inode, struct file *file)
static
int
fmc_dio_mdev_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
// FIXME: Nothing to do here
return
0
;
}
static
ssize_t
fmc_dio_mdev_write
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
offp
)
{
// FIXME: Nothing to do here
return
0
;
}
static
ssize_t
fmc_dio_mdev_read
(
struct
file
*
file
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
offp
)
{
// FIXME: Nothing to do here
return
0
;
}
//long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
//long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
static
long
fmc_dio_mdev_unlocked_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
fmc_dio
*
dio
=
file
->
private_data
;
return
fmc_dio_int_ioctl
(
dio
,
cmd
,
arg
);
}
...
...
sw/kernel/fmc-dio.c
View file @
99232716
/*
* Copyright (C) 2019
CERN
(www.sevensols.com)
* Copyright (C) 2019
Seven Solutions
(www.sevensols.com)
* Author: Miguel Jimenez Lopez <miguel.jimenez@sevensols.com>
*
* Released according to the GNU GPL, version 2 or any later version.
...
...
@@ -18,8 +18,8 @@
#include "fmc-dio.h"
/
/ IRQ domain for SPEC board
static
const
char
*
spec_irqdomain_name
=
"htvic-spec.0"
;
/
* Temporary pointer to the last FMC DIO */
static
struct
fmc_dio
*
last_dio
;
/**
* FMC DIO Interrupt Service Routing (ISR)
...
...
@@ -31,7 +31,11 @@ static const char *spec_irqdomain_name = "htvic-spec.0";
*/
irqreturn_t
fmc_dio_interrupt
(
int
irq
,
void
*
dev_id
)
{
return
fmc_dio_int_interrupt
(
dev_id
);
irqreturn_t
ret
;
ret
=
fmc_dio_int_interrupt
(
dev_id
);
return
ret
;
}
// Macros for the memory-mapped hardware resources
...
...
@@ -51,17 +55,20 @@ static int fmc_dio_resource_map(struct fmc_dio *dio)
struct
platform_device
*
dev
=
dio
->
pdev
;
struct
fmc_device
*
fmc
=
dio
->
fmc
;
struct
resource
*
r
;
int
irq
;
void
__iomem
*
mem
;
struct
irq_domain
*
irqdomain
;
// Map the resources
for
(
i
=
0
;
i
<
dev
->
num_resources
;
i
++
)
{
r
=
platform_get_resource
(
dev
,
IORESOURCE_MEM
,
i
);
if
(
!
r
)
if
(
!
r
||
!
r
->
start
)
continue
;
mem
=
fmc
->
fpga_base
+
r
->
start
;
mem
=
ioremap
(
r
->
start
,
r
->
end
+
1
-
r
->
start
);
if
(
!
mem
)
{
dev_err
(
&
dev
->
dev
,
"Remap for res %i %pr failed
\n
"
,
i
,
r
);
return
-
ENOMEM
;
}
switch
(
i
)
{
...
...
@@ -81,25 +88,24 @@ static int fmc_dio_resource_map(struct fmc_dio *dio)
}
// If some hardware resource is not detected, fail
if
(
!
dio
->
dio
||
!
dio
->
gpio
||
!
dio
->
ppsg
)
return
-
EINVAL
;
// Search the IRQ domain
irqdomain
=
irq_find_host
((
struct
device_node
*
)
dio
->
irqdomain_name
);
if
(
!
irqdomain
)
if
(
!
dio
->
dio
||
!
dio
->
gpio
||
!
dio
->
ppsg
)
{
printk
(
"%s: ERROR in FPGA base pointers initialization.
\n
"
,
__func__
);
return
-
EINVAL
;
}
// Map the IRQ
irq
=
platform_get_irq
(
dev
,
0
);
if
(
irq
<
0
)
dio
->
irq
=
platform_get_irq
(
dev
,
0
);
if
(
dio
->
irq
<
0
)
{
printk
(
"%s: ERROR in FMC DIO IRQ extraction.
\n
"
,
__func__
);
return
-
EINVAL
;
// Register the IRQ handler
dio
->
irq
=
irq_find_mapping
(
irqdomain
,
irq
);
err
=
request_irq
(
irq
,
fmc_dio_interrupt
,
IRQF_TRIGGER_LOW
,
dio
->
name
,
dio
);
if
(
err
)
}
err
=
request_any_context_irq
(
dio
->
irq
,
fmc_dio_interrupt
,
IRQF_TRIGGER_HIGH
,
dio
->
name
,
dio
);
if
(
err
<
0
)
{
printk
(
"%s: ERROR in request IRQ (%d).
\n
"
,
__func__
,
err
);
return
err
;
}
return
0
;
}
...
...
@@ -119,70 +125,6 @@ static int fmc_dio_resource_release(struct fmc_dio *dio)
return
0
;
}
/**
* FMC DIO probe function
*
* This function initializes the FMC DIO data structures.
*
* @param fmc FMC DIO device
*
* @return 0 if success and a negative error code otherwise
*/
int
fmc_dio_probe
(
struct
fmc_device
*
fmc
)
{
struct
fmc_dio
*
dio
;
/* Driver data */
dio
=
devm_kzalloc
(
&
fmc
->
dev
,
sizeof
(
*
dio
),
GFP_KERNEL
);
if
(
!
dio
)
return
-
ENOMEM
;
fmc_set_drvdata
(
fmc
,
dio
);
/* Set up the FMC DIO name for the Linux Miscdevice */
snprintf
(
dio
->
name
,
FMC_DIO_NAME_MAX
,
FMC_DIO_NAME_PATTERN
,
fmc
->
device_id
);
dio
->
fmc
=
fmc
;
return
0
;
}
/**
* FMC DIO remove function
*
* This function releases the FMC DIO data structures.
*
* @param fmc FMC DIO device
*
* @return 0 if success and a negative error code otherwise
*/
int
fmc_dio_remove
(
struct
fmc_device
*
fmc
)
{
struct
fmc_dio
*
dio
=
fmc_get_drvdata
(
fmc
);
/* Free FMC DIO internal structure */
kfree
(
dio
);
return
0
;
}
// FMC DIO FRU identifier
static
struct
fmc_fru_id
fd_fru_id
[]
=
{
{
.
product_name
=
"FmcDio5cha"
,
},
};
// FMC DIO driver structure (FMC)
static
struct
fmc_driver
fmc_dio_drv
=
{
.
version
=
FMC_VERSION
,
.
driver
.
name
=
KBUILD_MODNAME
,
.
probe
=
fmc_dio_probe
,
.
remove
=
fmc_dio_remove
,
.
id_table
=
{
.
fru_id
=
fd_fru_id
,
.
fru_id_nr
=
ARRAY_SIZE
(
fd_fru_id
),
},
};
/**
* FMC DIO probe function for the platform_device
*
...
...
@@ -196,31 +138,57 @@ static int fmc_dio_pl_probe(struct platform_device *dev)
* and it had filled the private data structure pointer of the
* platform_device before registering it.
*/
struct
fmc_device
*
fmc
=
platform_get_drvdata
(
dev
)
;
struct
fmc_dio
*
dio
=
fmc_get_drvdata
(
fmc
)
;
struct
fmc_device
*
fmc
;
struct
fmc_dio
*
dio
;
int
ret
=
0
;
unsigned
int
devfn
;
unsigned
char
busn
;
dio
=
last_dio
;
if
(
!
dio
)
{
printk
(
"%s: DIO internal structure is NULL
\n
"
,
__func__
);
ret
=
-
EINVAL
;
goto
exit
;
}
fmc
=
dio
->
fmc
;
if
(
!
fmc
)
{
printk
(
"%s: FMC device is NULL
\n
"
,
__func__
);
ret
=
-
EINVAL
;
goto
exit
;
}
/* Set up the FMC DIO name for the Linux Miscdevice */
busn
=
(
unsigned
char
)
(
fmc
->
device_id
>>
8
);
devfn
=
(
unsigned
int
)
(
fmc
->
device_id
&
0xFF
);
snprintf
(
dio
->
name
,
FMC_DIO_NAME_MAX
,
FMC_DIO_NAME_PATTERN
,
busn
,
devfn
);
// Specific board info
dio
->
board
=
dev
->
id_entry
->
driver_data
;
// Assign IRQ domain depending on the specific board
if
(
dio
->
board
==
FMC_DIO_BOARD_SPEC
)
dio
->
irqdomain_name
=
spec_irqdomain_name
;
// FIXME: Implement for other boards
dio
->
pdev
=
dev
;
/* Map the resources for the FMC DIO */
ret
=
fmc_dio_resource_map
(
dio
);
if
(
ret
)
return
ret
;
goto
exit
;
ret
=
fmc_dio_internal_create
(
dio
);
if
(
ret
)
goto
exit
;
/* Create a Linux Miscdevice for the FMC DIO */
ret
=
fmc_dio_mdev_create
(
dio
);
if
(
ret
)
return
re
t
;
goto
exi
t
;
/* Create Linux GPIO for the FMC DIO */
ret
=
fmc_dio_gpio_init
(
dio
);
if
(
ret
)
goto
exit
;
exit:
return
ret
;
}
...
...
@@ -233,30 +201,40 @@ static int fmc_dio_pl_probe(struct platform_device *dev)
*/
static
int
fmc_dio_pl_remove
(
struct
platform_device
*
dev
)
{
struct
fmc_device
*
fmc
=
platform_get_drvdata
(
dev
)
;
struct
fmc_dio
*
dio
=
fmc_get_drvdata
(
fmc
)
;
struct
fmc_device
*
fmc
;
struct
fmc_dio
*
dio
;
int
ret
=
0
;
dio
=
last_dio
;
fmc
=
dio
->
fmc
;
/* Release Linux GPIO for the FMC DIO */
fmc_dio_gpio_exit
(
dio
);
/* Destroy the Linux Miscdevice for the FMC DIO */
fmc_dio_mdev_destroy
(
dio
);
/* Destroy internal DIO structure */
fmc_dio_internal_destroy
(
dio
);
/* Release the resources for the FMC DIO */
ret
=
fmc_dio_resource_release
(
dio
);
if
(
ret
)
return
ret
;
/* Destroy the Linux Miscdevice for the FMC DIO */
fmc_dio_mdev_destroy
(
dio
);
return
ret
;
}
/* Forward declarations */
int
fmc_dio_probe
(
struct
fmc_device
*
fmc
);
int
fmc_dio_remove
(
struct
fmc_device
*
fmc
);
/**
* List of supported platform
*/
static
const
struct
platform_device_id
fmc_dio_id_table
[]
=
{
{
/* SPEC compatible */
.
name
=
"
spec-fmc-dio
"
,
.
name
=
"
fmc-dio-spec
"
,
.
driver_data
=
FMC_DIO_BOARD_SPEC
,
},
{},
...
...
@@ -274,6 +252,82 @@ static struct platform_driver fmc_dio_pl_drv = {
},
};
// FMC DIO FRU identifier
static
struct
fmc_fru_id
fd_fru_id
[]
=
{
{
.
product_name
=
"FmcDio5cha"
,
},
};
// FMC DIO driver structure (FMC)
static
struct
fmc_driver
fmc_dio_drv
=
{
.
version
=
FMC_VERSION
,
.
driver
.
name
=
KBUILD_MODNAME
,
.
probe
=
fmc_dio_probe
,
.
remove
=
fmc_dio_remove
,
.
id_table
=
{
.
fru_id
=
fd_fru_id
,
.
fru_id_nr
=
ARRAY_SIZE
(
fd_fru_id
),
},
};
/**
* FMC DIO probe function
*
* This function initializes the FMC DIO data structures.
*
* @param fmc FMC DIO device
*
* @return 0 if success and a negative error code otherwise
*/
int
fmc_dio_probe
(
struct
fmc_device
*
fmc
)
{
struct
fmc_dio
*
dio
;
int
ret
=
0
;
/* Driver data */
dio
=
devm_kzalloc
(
&
fmc
->
dev
,
sizeof
(
*
dio
),
GFP_KERNEL
);
if
(
!
dio
)
return
-
ENOMEM
;
fmc_set_drvdata
(
fmc
,
dio
);
dio
->
fmc
=
fmc
;
/* FIXME: Recover the DIO internal structure pointer for a global temporary var */
last_dio
=
dio
;
/* Now register the platform_driver */
ret
=
platform_driver_register
(
&
fmc_dio_pl_drv
);
if
(
ret
<
0
)
{
fmc_driver_unregister
(
&
fmc_dio_drv
);
}
return
ret
;
}
/**
* FMC DIO remove function
*
* This function releases the FMC DIO data structures.
*
* @param fmc FMC DIO device
*
* @return 0 if success and a negative error code otherwise
*/
int
fmc_dio_remove
(
struct
fmc_device
*
fmc
)
{
//struct fmc_dio *dio = fmc_get_drvdata(fmc);
/* Free FMC DIO internal structure */
/* NOTE: Here is not necessary to free the memory because
* we use devm_kmalloc in the probe function
*/
platform_driver_unregister
(
&
fmc_dio_pl_drv
);
return
0
;
}
/**
* FMC DIO init function
*
...
...
@@ -286,11 +340,7 @@ static int fmc_dio_init(void)
int
ret
;
ret
=
fmc_driver_register
(
&
fmc_dio_drv
);
if
(
ret
<
0
)
return
ret
;
platform_driver_register
(
&
fmc_dio_pl_drv
);
if
(
ret
<
0
)
fmc_driver_unregister
(
&
fmc_dio_drv
);
return
ret
;
}
...
...
@@ -302,7 +352,6 @@ static int fmc_dio_init(void)
*/
static
void
fmc_dio_exit
(
void
)
{
platform_driver_unregister
(
&
fmc_dio_pl_drv
);
fmc_driver_unregister
(
&
fmc_dio_drv
);
}
...
...
sw/kernel/fmc-dio.h
View file @
99232716
...
...
@@ -46,7 +46,7 @@ struct fmc_dio_gpio_block {
#define FMC_DIO_GPIO_VALUE(bit) (1 << ((4 * (bit)) + 0))
/* FMC DIO name string pattern */
#define FMC_DIO_NAME_PATTERN "fmc-dio-%
x
"
#define FMC_DIO_NAME_PATTERN "fmc-dio-%
d:%d
"
/* Size of the name field of the fmc_dio structure */
#define FMC_DIO_NAME_MAX 20
...
...
@@ -81,6 +81,8 @@ struct fmc_dio {
extern
irqreturn_t
fmc_dio_int_interrupt
(
struct
fmc_dio
*
dev
);
extern
int
fmc_dio_int_ioctl
(
struct
fmc_dio
*
dev
,
unsigned
int
ioctlcmd
,
unsigned
long
arg
);
extern
int
fmc_dio_internal_create
(
struct
fmc_dio
*
dev
);
extern
void
fmc_dio_internal_destroy
(
struct
fmc_dio
*
dev
);
// From fmc-dio-mdev.c
extern
int
fmc_dio_mdev_create
(
struct
fmc_dio
*
dio
);
...
...
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