Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Simple PCIe FMC carrier SPEC
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
50
Issues
50
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
Commits
6edffd1c
Commit
6edffd1c
authored
Apr 05, 2019
by
Federico Vaga
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop'
parents
5e972983
3f8b3d4a
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
232 additions
and
7 deletions
+232
-7
GPL-2.0.txt
LICENSES/GPL-2.0.txt
+0
-0
Makefile
kernel/Makefile
+0
-5
spec-compat.c
kernel/spec-compat.c
+95
-0
spec-compat.h
kernel/spec-compat.h
+17
-0
spec-core.c
kernel/spec-core.c
+119
-1
spec-irq.c
kernel/spec-irq.c
+1
-1
No files found.
LICENSE
→
LICENSE
S/GPL-2.0.txt
View file @
6edffd1c
File moved
kernel/Makefile
View file @
6edffd1c
...
...
@@ -5,14 +5,9 @@ REPO_PARENT ?= $(shell /bin/pwd)/../..
LINUX
?=
/lib/modules/
$(
shell
uname
-r
)
/build
FMC_ABS
?=
$
(
abspath
$(FMC)
)
I2C_ABS
?=
$
(
abspath
$(I2C)
)
CONFIG_FPGA_MGR_BACKPORT_PATH_ABS
?=
$
(
abspath
$(CONFIG_FPGA_MGR_BACKPORT_PATH)
)
GIT_VERSION
=
$(
shell
git describe
--dirty
--long
--tags
)
export
GIT_VERSION
all
:
modules
...
...
kernel/spec-compat.c
View file @
6edffd1c
...
...
@@ -3,6 +3,8 @@
* Copyright (C) 2017 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/kallsyms.h>
#include <linux/module.h>
#include <linux/fpga/fpga-mgr.h>
#include <linux/version.h>
#include "spec-compat.h"
...
...
@@ -93,3 +95,96 @@ void compat_fpga_mgr_unregister(struct fpga_manager *mgr)
fpga_mgr_unregister
(
mgr
);
}
#endif
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE
struct
fpga_manager
*
__fpga_mgr_get
(
struct
device
*
dev
)
{
struct
fpga_manager
*
mgr
;
int
ret
=
-
ENODEV
;
mgr
=
to_fpga_manager
(
dev
);
if
(
!
mgr
)
goto
err_dev
;
/* Get exclusive use of fpga manager */
if
(
!
mutex_trylock
(
&
mgr
->
ref_mutex
))
{
ret
=
-
EBUSY
;
goto
err_dev
;
}
if
(
!
try_module_get
(
dev
->
parent
->
driver
->
owner
))
goto
err_ll_mod
;
return
mgr
;
err_ll_mod:
mutex_unlock
(
&
mgr
->
ref_mutex
);
err_dev:
put_device
(
dev
);
return
ERR_PTR
(
ret
);
}
static
int
fpga_mgr_dev_match
(
struct
device
*
dev
,
const
void
*
data
)
{
return
dev
->
parent
==
data
;
}
/**
* fpga_mgr_get - get an exclusive reference to a fpga mgr
* @dev:parent device that fpga mgr was registered with
*
* Given a device, get an exclusive reference to a fpga mgr.
*
* Return: fpga manager struct or IS_ERR() condition containing error code.
*/
struct
fpga_manager
*
fpga_mgr_get
(
struct
device
*
dev
)
{
void
*
fpga_mgr_class
=
(
void
*
)
kallsyms_lookup_name
(
"fpga_mgr_class"
);
struct
device
*
mgr_dev
=
class_find_device
(
fpga_mgr_class
,
NULL
,
dev
,
fpga_mgr_dev_match
);
if
(
!
mgr_dev
)
return
ERR_PTR
(
-
ENODEV
);
return
__fpga_mgr_get
(
mgr_dev
);
}
#endif
static
int
__compat_spec_fw_load
(
struct
fpga_manager
*
mgr
,
const
char
*
name
)
{
#if KERNEL_VERSION(4,16,0) > LINUX_VERSION_CODE && !defined(CONFIG_FPGA_MGR_BACKPORT)
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE
return
fpga_mgr_firmware_load
(
mgr
,
0
,
name
);
#else
struct
fpga_image_info
image
;
memset
(
&
image
,
0
,
sizeof
(
image
));
return
fpga_mgr_firmware_load
(
mgr
,
&
image
,
name
);
#endif
#else
struct
fpga_image_info
image
;
memset
(
&
image
,
0
,
sizeof
(
image
));
image
.
firmware_name
=
(
char
*
)
name
;
image
.
dev
=
mgr
->
dev
.
parent
;
return
fpga_mgr_load
(
mgr
,
&
image
);
#endif
}
int
compat_spec_fw_load
(
struct
spec_dev
*
spec
,
const
char
*
name
)
{
struct
fpga_manager
*
mgr
;
int
err
;
mgr
=
fpga_mgr_get
(
&
spec
->
dev
);
if
(
IS_ERR
(
mgr
))
return
-
ENODEV
;
err
=
__compat_spec_fw_load
(
mgr
,
name
);
fpga_mgr_put
(
mgr
);
return
err
;
}
kernel/spec-compat.h
View file @
6edffd1c
...
...
@@ -6,6 +6,7 @@
#include <linux/fpga/fpga-mgr.h>
#include <linux/types.h>
#include <linux/version.h>
#include "spec.h"
#if KERNEL_VERSION(4,10,0) <= LINUX_VERSION_CODE
#if KERNEL_VERSION(4,16,0) > LINUX_VERSION_CODE
...
...
@@ -54,3 +55,19 @@ struct fpga_manager *compat_fpga_mgr_create(struct device *dev,
void
compat_fpga_mgr_free
(
struct
fpga_manager
*
mgr
);
int
compat_fpga_mgr_register
(
struct
fpga_manager
*
mgr
);
void
compat_fpga_mgr_unregister
(
struct
fpga_manager
*
mgr
);
int
compat_spec_fw_load
(
struct
spec_dev
*
spec
,
const
char
*
name
);
#if KERNEL_VERSION(3, 11, 0) > LINUX_VERSION_CODE
#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \
_name##_show, _name##_store)
#define __ATTR_WO(_name) { \
.attr = { .name = __stringify(_name), .mode = S_IWUSR }, \
.store = _name##_store, \
}
#define DEVICE_ATTR_RW(_name) \
struct device_attribute dev_attr_##_name = __ATTR_RW(_name)
#define DEVICE_ATTR_RO(_name) \
struct device_attribute dev_attr_##_name = __ATTR_RO(_name)
#define DEVICE_ATTR_WO(_name) \
struct device_attribute dev_attr_##_name = __ATTR_WO(_name)
#endif
kernel/spec-core.c
View file @
6edffd1c
...
...
@@ -11,14 +11,123 @@
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/firmware.h>
#include <linux/moduleparam.h>
#include "spec.h"
#include "spec-compat.h"
static
char
*
spec_fw_name_45t
=
"spec-init-45T.bin"
;
static
char
*
spec_fw_name_100t
=
"spec-init-100T.bin"
;
static
char
*
spec_fw_name_150t
=
"spec-init-150T.bin"
;
char
*
spec_fw_name
=
""
;
module_param_named
(
fw_name
,
spec_fw_name
,
charp
,
0444
);
/**
* Return the SPEC defult FPGA firmware name based on PCI ID
* @spec: SPEC device
*
* Return: FPGA firmware name
*/
static
const
char
*
spec_fw_name_init_get
(
struct
spec_dev
*
spec
)
{
struct
pci_dev
*
pdev
=
to_pci_dev
(
spec
->
dev
.
parent
);
if
(
strlen
(
spec_fw_name
)
>
0
)
return
spec_fw_name
;
switch
(
pdev
->
device
)
{
case
PCI_DEVICE_ID_SPEC_45T
:
return
spec_fw_name_45t
;
case
PCI_DEVICE_ID_SPEC_100T
:
return
spec_fw_name_100t
;
case
PCI_DEVICE_ID_SPEC_150T
:
return
spec_fw_name_150t
;
default:
return
NULL
;
}
}
/**
* Load FPGA code
* @spec: SPEC device
* @name: FPGA bitstream file name
*
* Return: 0 on success, otherwise a negative error number
*/
static
int
spec_fw_load
(
struct
spec_dev
*
spec
,
const
char
*
name
)
{
pr_info
(
"%s:%d %s
\n
"
,
__func__
,
__LINE__
,
name
);
return
compat_spec_fw_load
(
spec
,
name
);
}
/**
* Return: True if the FPGA is programmed, otherwise false
*/
static
bool
spec_fw_is_pre_programmed
(
struct
spec_dev
*
spec
)
{
return
false
;
}
/**
* Load default FPGA code
* @spec: SPEC device
*
* Return: 0 on success, otherwise a negative error number
*/
static
int
spec_fw_load_init
(
struct
spec_dev
*
spec
)
{
if
(
spec_fw_is_pre_programmed
(
spec
))
return
0
;
return
spec_fw_load
(
spec
,
spec_fw_name_init_get
(
spec
));
}
static
ssize_t
fpga_load_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
int
err
;
err
=
spec_fw_load
(
to_spec_dev
(
dev
),
buf
);
return
err
?
err
:
count
;
}
static
DEVICE_ATTR_WO
(
fpga_load
);
static
struct
attribute
*
spec_attrs
[]
=
{
&
dev_attr_fpga_load
.
attr
,
NULL
,
};
static
struct
attribute_group
spec_attr_group
=
{
.
attrs
=
spec_attrs
,
};
static
const
struct
attribute_group
*
spec_attr_groups
[]
=
{
&
spec_attr_group
,
NULL
,
};
static
void
spec_release
(
struct
device
*
dev
)
{
}
static
int
spec_uevent
(
struct
device
*
dev
,
struct
kobj_uevent_env
*
env
)
{
return
0
;
}
static
const
struct
device_type
spec_dev_type
=
{
.
name
=
"spec"
,
.
release
=
spec_release
,
.
groups
=
spec_attr_groups
,
.
uevent
=
spec_uevent
,
};
static
int
spec_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
)
{
...
...
@@ -52,7 +161,7 @@ static int spec_probe(struct pci_dev *pdev,
goto
err_remap
;
spec
->
dev
.
parent
=
&
pdev
->
dev
;
spec
->
dev
.
release
=
spec_releas
e
;
spec
->
dev
.
type
=
&
spec_dev_typ
e
;
err
=
dev_set_name
(
&
spec
->
dev
,
"spec-%s"
,
dev_name
(
&
pdev
->
dev
));
if
(
err
)
goto
err_name
;
...
...
@@ -60,6 +169,8 @@ static int spec_probe(struct pci_dev *pdev,
err
=
device_register
(
&
spec
->
dev
);
if
(
err
)
goto
err_dev
;
/* This virtual device is assciated with this driver */
spec
->
dev
.
driver
=
pdev
->
dev
.
driver
;
err
=
spec_fpga_init
(
spec
);
if
(
err
)
...
...
@@ -69,10 +180,17 @@ static int spec_probe(struct pci_dev *pdev,
if
(
err
)
goto
err_irq
;
err
=
spec_fw_load_init
(
spec
);
if
(
err
)
goto
err_fw
;
pci_set_drvdata
(
pdev
,
spec
);
dev_info
(
spec
->
dev
.
parent
,
"Spec registered devptr=0x%p
\n
"
,
spec
->
dev
.
parent
);
return
0
;
err_fw:
spec_irq_exit
(
spec
);
err_irq:
spec_fpga_exit
(
spec
);
err_fpga:
...
...
kernel/spec-irq.c
View file @
6edffd1c
...
...
@@ -6,8 +6,8 @@
*
* Driver for SPEC (Simple PCI FMC carrier) board.
*/
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
...
...
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