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
29c35f2a
Commit
29c35f2a
authored
Mar 29, 2019
by
Federico Vaga
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'release/v0.3'
parents
3dc5715e
1bf3ef45
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
235 additions
and
259 deletions
+235
-259
Makefile
Makefile
+1
-1
Kbuild
kernel/Kbuild
+9
-8
Makefile
kernel/Makefile
+3
-3
spec-compat.c
kernel/spec-compat.c
+95
-0
spec-compat.h
kernel/spec-compat.h
+56
-0
spec-core.c
kernel/spec-core.c
+22
-16
spec-fmc.c
kernel/spec-fmc.c
+0
-157
spec-fpga.c
kernel/spec-fpga.c
+23
-25
spec-irq.c
kernel/spec-irq.c
+20
-40
spec.h
kernel/spec.h
+6
-9
No files found.
Makefile
View file @
29c35f2a
...
...
@@ -5,7 +5,7 @@
REPO_PARENT
?=
$(
shell
/bin/pwd
)
/..
-include
$(REPO_PARENT)/parent_common.mk
DIRS
=
kernel
doc
DIRS
=
kernel
.PHONY
:
all clean modules install modules_install $(DIRS)
...
...
kernel/Kbuild
View file @
29c35f2a
...
...
@@ -9,20 +9,21 @@ endif
ccflags-y += -DADDITIONAL_VERSIONS="$(SUBMODULE_VERSIONS)"
ccflags-y += -DGIT_VERSION=\"$(GIT_VERSION)\"
ccflags-y += -I$(FPGA_MGR_ABS)/include
ccflags-y += -I$(FMC_ABS)/include
ccflags-y += -I$(I2C_ABS)/include
ccflags-y += -Wall -Werror
# priority to I2C headers from our sources
LINUXINCLUDE := -I$(FMC_MGR_ABS)/include -I$(FMC_MGR_ABS)/include/linux -I$(FMC_ABS)/include -I$(FMC_ABS)/include/linux -I$(I2C_ABS)/include -I$(I2C_ABS)/include/linux $(LINUXINCLUDE)
ccflags-$(CONFIG_FPGA_MGR_BACKPORT) += -DCONFIG_FPGA_MGR_BACKPORT
ccflags-$(CONFIG_FPGA_MGR_BACKPORT) += -I$(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS)/include
KBUILD_EXTRA_SYMBOLS += $(FPGA_MGR_ABS)/drivers/fpga/Module.symvers
KBUILD_EXTRA_SYMBOLS += $(FMC_ABS)/drivers/fmc/Module.symvers
ifeq ($(CONFIG_FPGA_MGR_BACKPORT), y)
CONFIG_FPGA_MGR_BACKPORT_INCLUDE := -I$(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS)/include
CONFIG_FPGA_MGR_BACKPORT_INCLUDE += -I$(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS)/include/linux
LINUXINCLUDE := $(CONFIG_FPGA_MGR_BACKPORT_INCLUDE) $(LINUXINCLUDE)
KBUILD_EXTRA_SYMBOLS += $(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS)/drivers/fpga/Module.symvers
endif
obj-m := spec.o
spec-objs := spec-core.o
spec-objs += spec-fpga.o
spec-objs += spec-fmc.o
spec-objs += spec-irq.o
spec-objs += spec-compat.o
kernel/Makefile
View file @
29c35f2a
...
...
@@ -5,12 +5,12 @@ REPO_PARENT ?= $(shell /bin/pwd)/../..
LINUX
?=
/lib/modules/
$(
shell
uname
-r
)
/build
FPGA_MGR_ABS
?=
$
(
abspath
$(FPGA_MGR)
)
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
...
...
@@ -19,7 +19,7 @@ all: modules
.PHONY
:
all modules clean help install modules_install
modules help install modules_install
:
$(MAKE)
-C
$(LINUX)
M
=
$(
shell
pwd
)
GIT_VERSION
=
$(GIT_VERSION)
FPGA_MGR_ABS
=
$(FPGA_MGR_ABS)
FMC_ABS
=
$(FMC_ABS)
I2C_ABS
=
$(I2C_ABS
)
$@
$(MAKE)
-C
$(LINUX)
M
=
$(
shell
pwd
)
GIT_VERSION
=
$(GIT_VERSION)
CONFIG_FPGA_MGR_BACKPORT_PATH_ABS
=
$(CONFIG_FPGA_MGR_BACKPORT_PATH_ABS)
CONFIG_FPGA_MGR_BACKPORT
=
$(CONFIG_FPGA_MGR_BACKPORT
)
$@
# be able to run the "clean" rule even if $(LINUX) is not valid
clean
:
...
...
kernel/spec-compat.c
0 → 100644
View file @
29c35f2a
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2017 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/fpga/fpga-mgr.h>
#include <linux/version.h>
#include "spec-compat.h"
int
compat_get_fpga_last_word_size
(
struct
fpga_image_info
*
info
,
size_t
count
)
{
#if KERNEL_VERSION(4,16,0) > LINUX_VERSION_CODE && !defined(CONFIG_FPGA_MGR_BACKPORT)
return
count
;
#else
return
info
?
info
->
count
:
count
;
#endif
}
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE && !defined(CONFIG_FPGA_MGR_BACKPORT)
int
compat_spec_fpga_write_init
(
struct
fpga_manager
*
mgr
,
u32
flags
,
const
char
*
buf
,
size_t
count
)
{
return
spec_fpga_write_init
(
mgr
,
NULL
,
buf
,
count
);
}
int
compat_spec_fpga_write_complete
(
struct
fpga_manager
*
mgr
,
u32
flags
)
{
return
spec_fpga_write_complete
(
mgr
,
NULL
);
}
#else
int
compat_spec_fpga_write_init
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
,
const
char
*
buf
,
size_t
count
)
{
return
spec_fpga_write_init
(
mgr
,
info
,
buf
,
count
);
}
int
compat_spec_fpga_write_complete
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
)
{
return
spec_fpga_write_complete
(
mgr
,
info
);
}
#endif
#if KERNEL_VERSION(4,18,0) > LINUX_VERSION_CODE && !defined(CONFIG_FPGA_MGR_BACKPORT)
struct
fpga_manager
*
compat_fpga_mgr_create
(
struct
device
*
dev
,
const
char
*
name
,
const
struct
fpga_manager_ops
*
mops
,
void
*
priv
)
{
int
err
;
err
=
fpga_mgr_register
(
dev
,
name
,
mops
,
priv
);
if
(
err
)
return
NULL
;
return
(
struct
fpga_manager
*
)
dev
;
}
void
compat_fpga_mgr_free
(
struct
fpga_manager
*
mgr
)
{
fpga_mgr_unregister
((
struct
device
*
)
mgr
);
}
int
compat_fpga_mgr_register
(
struct
fpga_manager
*
mgr
)
{
return
mgr
?
0
:
1
;
}
void
compat_fpga_mgr_unregister
(
struct
fpga_manager
*
mgr
)
{
fpga_mgr_unregister
((
struct
device
*
)
mgr
);
}
#else
struct
fpga_manager
*
compat_fpga_mgr_create
(
struct
device
*
dev
,
const
char
*
name
,
const
struct
fpga_manager_ops
*
mops
,
void
*
priv
)
{
return
fpga_mgr_create
(
dev
,
name
,
mops
,
priv
);
}
void
compat_fpga_mgr_free
(
struct
fpga_manager
*
mgr
)
{
fpga_mgr_free
(
mgr
);
}
int
compat_fpga_mgr_register
(
struct
fpga_manager
*
mgr
)
{
return
fpga_mgr_register
(
mgr
);
}
void
compat_fpga_mgr_unregister
(
struct
fpga_manager
*
mgr
)
{
fpga_mgr_unregister
(
mgr
);
}
#endif
kernel/spec-compat.h
0 → 100644
View file @
29c35f2a
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2017 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/fpga/fpga-mgr.h>
#include <linux/types.h>
#include <linux/version.h>
#if KERNEL_VERSION(4,10,0) <= LINUX_VERSION_CODE
#if KERNEL_VERSION(4,16,0) > LINUX_VERSION_CODE
/* So that we select the buffer size because smaller */
#define compat_fpga_ops_initial_header_size .initial_header_size = 0xFFFFFFFF,
#else
#define compat_fpga_ops_initial_header_size .initial_header_size = 0,
#endif
#else
#define compat_fpga_ops_initial_header_size
#endif
#if KERNEL_VERSION(4,16,0) > LINUX_VERSION_CODE && ! defined(CONFIG_FPGA_MGR_BACKPORT)
#define compat_fpga_ops_groups
#else
#define compat_fpga_ops_groups .groups = NULL,
#endif
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE && ! defined(CONFIG_FPGA_MGR_BACKPORT)
struct
fpga_image_info
;
#endif
int
spec_fpga_write_init
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
,
const
char
*
buf
,
size_t
count
);
int
spec_fpga_write_complete
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
);
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE && ! defined(CONFIG_FPGA_MGR_BACKPORT)
int
compat_spec_fpga_write_init
(
struct
fpga_manager
*
mgr
,
u32
flags
,
const
char
*
buf
,
size_t
count
);
int
compat_spec_fpga_write_complete
(
struct
fpga_manager
*
mgr
,
u32
flags
);
#else
int
compat_spec_fpga_write_init
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
,
const
char
*
buf
,
size_t
count
);
int
compat_spec_fpga_write_complete
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
);
#endif
int
compat_get_fpga_last_word_size
(
struct
fpga_image_info
*
info
,
size_t
count
);
struct
fpga_manager
*
compat_fpga_mgr_create
(
struct
device
*
dev
,
const
char
*
name
,
const
struct
fpga_manager_ops
*
mops
,
void
*
priv
);
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
);
kernel/spec-core.c
View file @
29c35f2a
...
...
@@ -14,6 +14,10 @@
#include "spec.h"
static
void
spec_release
(
struct
device
*
dev
)
{
}
static
int
spec_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
)
...
...
@@ -21,11 +25,9 @@ static int spec_probe(struct pci_dev *pdev,
struct
spec_dev
*
spec
;
int
err
,
i
;
spec
=
kzalloc
(
sizeof
(
struct
spec_dev
),
GFP_KERNEL
);
spec
=
kzalloc
(
sizeof
(
*
spec
),
GFP_KERNEL
);
if
(
!
spec
)
return
-
ENOMEM
;
spec
->
pdev
=
pdev
;
pci_set_drvdata
(
pdev
,
spec
);
err
=
pci_enable_device
(
pdev
);
if
(
err
)
...
...
@@ -49,30 +51,37 @@ static int spec_probe(struct pci_dev *pdev,
if
(
err
)
goto
err_remap
;
err
=
spec_fpga_init
(
spec
);
spec
->
dev
.
parent
=
&
pdev
->
dev
;
spec
->
dev
.
release
=
spec_release
;
err
=
dev_set_name
(
&
spec
->
dev
,
"spec-%s"
,
dev_name
(
&
pdev
->
dev
));
if
(
err
)
goto
err_fpga
;
goto
err_name
;
err
=
device_register
(
&
spec
->
dev
);
if
(
err
)
goto
err_dev
;
err
=
spec_f
mc
_init
(
spec
);
err
=
spec_f
pga
_init
(
spec
);
if
(
err
)
goto
err_f
mc
;
goto
err_f
pga
;
err
=
spec_irq_init
(
spec
);
if
(
err
)
goto
err_irq
;
pci_set_drvdata
(
pdev
,
spec
);
return
0
;
err_irq:
spec_fmc_exit
(
spec
);
err_fmc:
spec_fpga_exit
(
spec
);
err_fpga:
pci_set_drvdata
(
pdev
,
NULL
);
device_unregister
(
&
spec
->
dev
);
err_dev:
err_name:
for
(
i
=
0
;
i
<
3
;
i
++
)
{
if
(
spec
->
remap
[
i
])
iounmap
(
spec
->
remap
[
i
]);
spec
->
remap
[
i
]
=
NULL
;
}
err_remap:
pci_disable_device
(
pdev
);
...
...
@@ -87,17 +96,14 @@ static void spec_remove(struct pci_dev *pdev)
struct
spec_dev
*
spec
=
pci_get_drvdata
(
pdev
);
int
i
;
pci_set_drvdata
(
pdev
,
NULL
);
spec_irq_exit
(
spec
);
spec_fmc_exit
(
spec
);
spec_fpga_exit
(
spec
);
for
(
i
=
0
;
i
<
3
;
i
++
)
{
for
(
i
=
0
;
i
<
3
;
i
++
)
if
(
spec
->
remap
[
i
])
iounmap
(
spec
->
remap
[
i
]);
spec
->
remap
[
i
]
=
NULL
;
}
device_unregister
(
&
spec
->
dev
);
pci_disable_device
(
pdev
);
kfree
(
spec
);
}
...
...
kernel/spec-fmc.c
deleted
100644 → 0
View file @
3dc5715e
/*
* Copyright (C) 2017 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <linux/kernel.h>
#include <linux/platform_data/i2c-ocores.h>
#include "spec.h"
static
int
spec_fmc_is_present
(
struct
fmc_carrier
*
carrier
,
struct
fmc_slot
*
slot
)
{
/* TODO implement me */
return
0
;
}
static
const
struct
fmc_carrier_operations
spec_fmc_ops
=
{
.
is_present
=
spec_fmc_is_present
,
};
static
const
struct
ocores_i2c_platform_data
pdata
=
{
.
reg_shift
=
0
,
.
reg_io_width
=
4
,
.
clock_khz
=
62500
,
.
big_endian
=
0
,
.
num_devices
=
0
,
.
devices
=
NULL
,
};
static
int
spec_i2c_find_adapter
(
struct
device
*
dev
,
void
*
data
)
{
struct
spec_dev
*
spec
=
data
;
struct
i2c_adapter
*
adap
,
*
adap_parent
;
if
(
dev
->
type
!=
&
i2c_adapter_type
)
return
0
;
adap
=
to_i2c_adapter
(
dev
);
adap_parent
=
i2c_parent_is_i2c_adapter
(
adap
);
if
(
!
adap_parent
)
return
0
;
if
(
&
spec
->
i2c_pdev
->
dev
!=
adap_parent
->
dev
.
parent
)
return
0
;
/* Found! */
return
i2c_adapter_id
(
adap
);
}
/**
* Get the I2C adapter associated with an FMC slot
* @spec: SPEC instance
*
* Return: the I2C bus to be used
*/
static
int
spec_i2c_get_bus
(
struct
spec_dev
*
spec
)
{
return
i2c_for_each_dev
(
spec
,
spec_i2c_find_adapter
);
}
static
int
id
;
/**
* It builds the platform_device_info necessary to register the
* I2C master device.
* @spec the SPEC instance
*
* Return: an array of I2C master devices
*/
static
int
spec_i2c_add
(
struct
spec_dev
*
spec
)
{
struct
resource
res
=
{
.
name
=
"i2c-ocores-mem"
,
.
flags
=
IORESOURCE_MEM
,
};
int
err
;
/* VME function 1 */
res
.
start
=
pci_resource_start
(
to_pci_dev
(
spec
->
pdev
->
dev
.
parent
),
0
);
res
.
start
+=
SPEC_I2C_MASTER_ADDR
;
res
.
end
=
res
.
start
+
SPEC_I2C_MASTER_SIZE
;
/* FIXME find better ID */
spec
->
i2c_pdev
=
platform_device_register_resndata
(
&
spec
->
pdev
->
dev
,
"ocores-i2c"
,
id
++
,
&
res
,
1
,
&
pdata
,
sizeof
(
pdata
));
if
(
!
spec
->
i2c_pdev
)
return
-
ENODEV
;
err
=
i2c_for_each_dev
(
spec
,
spec_i2c_find_adapter
);
if
(
err
<=
0
)
goto
err
;
return
0
;
err:
platform_device_unregister
(
spec
->
i2c_pdev
);
return
-
ENODEV
;
}
static
void
spec_i2c_del
(
struct
spec_dev
*
spec
)
{
platform_device_unregister
(
spec
->
i2c_pdev
);
if
(
spec
->
i2c_adapter
)
i2c_put_adapter
(
spec
->
i2c_adapter
);
}
int
spec_fmc_init
(
struct
spec_dev
*
spec
)
{
int
err
;
return
0
;
/* UNTIL WE TEST IT */
if
(
!
spec
)
return
-
EINVAL
;
err
=
spec_i2c_add
(
spec
);
if
(
err
)
goto
err_i2c
;
spec
->
slot_info
.
i2c_bus_nr
=
spec_i2c_get_bus
(
spec
);
if
(
spec
->
slot_info
.
i2c_bus_nr
<=
0
)
goto
err_i2c_bus
;
spec
->
slot_info
.
ga
=
0
;
spec
->
slot_info
.
lun
=
0
;
err
=
fmc_carrier_register
(
&
spec
->
pdev
->
dev
,
&
spec_fmc_ops
,
SPEC_FMC_SLOTS
,
&
spec
->
slot_info
,
spec
);
if
(
err
)
goto
err_fmc
;
return
0
;
err_fmc:
err_i2c_bus:
spec_i2c_del
(
spec
);
err_i2c:
return
err
;
}
void
spec_fmc_exit
(
struct
spec_dev
*
spec
)
{
return
;
/* UNTIL WE TEST IT */
if
(
!
spec
)
return
;
fmc_carrier_unregister
(
&
spec
->
pdev
->
dev
);
spec_i2c_del
(
spec
);
}
kernel/spec-fpga.c
View file @
29c35f2a
...
...
@@ -4,10 +4,11 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <linux/fpga/fpga-mgr.h>
#include <linux/delay.h>
#include "spec.h"
#include "spec-compat.h"
static
inline
uint8_t
reverse_bits8
(
uint8_t
x
)
{
...
...
@@ -240,15 +241,16 @@ static enum fpga_mgr_states spec_fpga_state(struct fpga_manager *mgr)
}
static
int
spec_fpga_write_init
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
,
const
char
*
buf
,
size_t
count
)
int
spec_fpga_write_init
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
,
const
char
*
buf
,
size_t
count
)
{
struct
spec_dev
*
spec
=
mgr
->
priv
;
int
err
=
0
;
int
err
=
0
,
last_word_size
;
gn4124_fpga_gpio_config
(
spec
);
err
=
gn4124_fpga_fcl_init
(
spec
,
info
->
count
&
0x3
);
last_word_size
=
compat_get_fpga_last_word_size
(
info
,
count
)
&
0x3
;
err
=
gn4124_fpga_fcl_init
(
spec
,
last_word_size
);
if
(
err
<
0
)
goto
err
;
...
...
@@ -259,7 +261,6 @@ err:
return
err
;
}
static
int
spec_fpga_write
(
struct
fpga_manager
*
mgr
,
const
char
*
buf
,
size_t
count
)
{
struct
spec_dev
*
spec
=
mgr
->
priv
;
...
...
@@ -268,8 +269,8 @@ static int spec_fpga_write(struct fpga_manager *mgr, const char *buf, size_t cou
}
static
int
spec_fpga_write_complete
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
)
int
spec_fpga_write_complete
(
struct
fpga_manager
*
mgr
,
struct
fpga_image_info
*
info
)
{
struct
spec_dev
*
spec
=
mgr
->
priv
;
int
err
;
...
...
@@ -292,15 +293,15 @@ static void spec_fpga_remove(struct fpga_manager *mgr)
/* do nothing */
}
static
const
struct
fpga_manager_ops
spec_fpga_ops
=
{
.
initial_header_size
=
0
,
compat_fpga_ops_initial_header_size
compat_fpga_ops_groups
.
state
=
spec_fpga_state
,
.
write_init
=
spec_fpga_write_init
,
.
write_init
=
compat_
spec_fpga_write_init
,
.
write
=
spec_fpga_write
,
.
write_complete
=
spec_fpga_write_complete
,
.
write_complete
=
compat_
spec_fpga_write_complete
,
.
fpga_remove
=
spec_fpga_remove
,
.
groups
=
NULL
,
};
...
...
@@ -308,18 +309,15 @@ int spec_fpga_init(struct spec_dev *spec)
{
int
err
;
if
(
!
spec
)
return
-
EINVAL
;
spec
->
mgr
=
fpga_mgr_create
(
&
spec
->
pdev
->
dev
,
dev_name
(
&
spec
->
pdev
->
dev
),
&
spec_fpga_ops
,
spec
);
if
(
!
spec
->
mgr
)
spec
->
mgr
=
compat_fpga_mgr_create
(
&
spec
->
dev
,
dev_name
(
&
spec
->
dev
),
&
spec_fpga_ops
,
spec
);
if
(
!
spec
||
!
spec
->
mgr
)
return
-
EPERM
;
err
=
fpga_mgr_register
(
spec
->
mgr
);
err
=
compat_
fpga_mgr_register
(
spec
->
mgr
);
if
(
err
)
{
fpga_mgr_free
(
spec
->
mgr
);
compat_
fpga_mgr_free
(
spec
->
mgr
);
return
err
;
}
...
...
@@ -328,7 +326,7 @@ int spec_fpga_init(struct spec_dev *spec)
void
spec_fpga_exit
(
struct
spec_dev
*
spec
)
{
if
(
!
spec
||
!
spec
->
mgr
)
if
(
!
spec
)
return
;
fpga_mgr_unregister
(
spec
->
mgr
);
compat_
fpga_mgr_unregister
(
spec
->
mgr
);
}
kernel/spec-irq.c
View file @
29c35f2a
...
...
@@ -36,9 +36,9 @@ static int spec_irq_dbg_info(struct seq_file *s, void *offset)
struct
spec_dev
*
spec
=
s
->
private
;
int
i
;
seq_printf
(
s
,
"'%s':
\n
"
,
dev_name
(
&
spec
->
pdev
->
dev
));
seq_printf
(
s
,
"'%s':
\n
"
,
dev_name
(
spec
->
dev
.
parent
));
seq_printf
(
s
,
" redirect: %d
\n
"
,
spec
->
pdev
->
irq
);
seq_printf
(
s
,
" redirect: %d
\n
"
,
to_pci_dev
(
spec
->
dev
.
parent
)
->
irq
);
seq_printf
(
s
,
" irq-mapping:
\n
"
);
for
(
i
=
0
;
i
<
GN4124_GPIO_IRQ_MAX
;
++
i
)
{
seq_printf
(
s
,
" - hardware: %d
\n
"
,
i
);
...
...
@@ -73,9 +73,9 @@ static const struct file_operations spec_irq_dbg_info_ops = {
*/
static
int
spec_irq_debug_init
(
struct
spec_dev
*
spec
)
{
spec
->
dbg_dir
=
debugfs_create_dir
(
dev_name
(
&
spec
->
pdev
->
dev
),
NULL
);
spec
->
dbg_dir
=
debugfs_create_dir
(
dev_name
(
&
spec
->
dev
),
NULL
);
if
(
IS_ERR_OR_NULL
(
spec
->
dbg_dir
))
{
dev_err
(
&
spec
->
pdev
->
dev
,
dev_err
(
&
spec
->
dev
,
"Cannot create debugfs directory (%ld)
\n
"
,
PTR_ERR
(
spec
->
dbg_dir
));
return
PTR_ERR
(
spec
->
dbg_dir
);
...
...
@@ -85,7 +85,7 @@ static int spec_irq_debug_init(struct spec_dev *spec)
spec
->
dbg_dir
,
spec
,
&
spec_irq_dbg_info_ops
);
if
(
IS_ERR_OR_NULL
(
spec
->
dbg_info
))
{
dev_err
(
&
spec
->
pdev
->
dev
,
dev_err
(
&
spec
->
dev
,
"Cannot create debugfs file
\"
%s
\"
(%ld)
\n
"
,
SPEC_DBG_INFO_NAME
,
PTR_ERR
(
spec
->
dbg_info
));
return
PTR_ERR
(
spec
->
dbg_info
);
...
...
@@ -101,8 +101,7 @@ static int spec_irq_debug_init(struct spec_dev *spec)
*/
static
void
spec_irq_debug_exit
(
struct
spec_dev
*
spec
)
{
if
(
spec
->
dbg_dir
)
debugfs_remove_recursive
(
spec
->
dbg_dir
);
debugfs_remove_recursive
(
spec
->
dbg_dir
);
}
...
...
@@ -139,7 +138,8 @@ static int spec_irq_gpio_set_type(struct irq_data *d, unsigned int flow_type)
*/
if
((
flow_type
&
IRQ_TYPE_LEVEL_MASK
)
&&
(
flow_type
&
IRQ_TYPE_EDGE_BOTH
))
{
dev_err
(
&
spec
->
pdev
->
dev
,
"Impossible to set GPIO IRQ %ld to both LEVEL and EDGE (0x%x)
\n
"
,
dev_err
(
&
spec
->
dev
,
"Impossible to set GPIO IRQ %ld to both LEVEL and EDGE (0x%x)
\n
"
,
d
->
hwirq
,
flow_type
);
return
-
EINVAL
;
}
...
...
@@ -215,27 +215,6 @@ static struct irq_chip spec_irq_gpio_chip = {
.
irq_set_type
=
spec_irq_gpio_set_type
,
};
/**
* It match a given device with the irq_domain. `struct device_node *` is just
* a convention. actually it can be anything (I do not understand why kernel
* people did not use `void *`)
*
* In our case here we expect a string because we identify this domain by
* name
*/
static
int
spec_irq_gpio_domain_match
(
struct
irq_domain
*
d
,
struct
device_node
*
node
)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
char
*
name
=
(
char
*
)
node
;
if
(
strcmp
(
d
->
name
,
name
)
==
0
)
return
1
;
#endif
return
0
;
}
/**
* Given the hardware IRQ and the Linux IRQ number (virtirq), configure the
* Linux IRQ number in order to handle properly the incoming interrupts
...
...
@@ -258,7 +237,6 @@ static int spec_irq_gpio_domain_map(struct irq_domain *h,
static
struct
irq_domain_ops
spec_irq_gpio_domain_ops
=
{
.
match
=
spec_irq_gpio_domain_match
,
.
map
=
spec_irq_gpio_domain_map
,
};
...
...
@@ -370,7 +348,7 @@ static int spec_irq_gpio_init(struct spec_dev *spec)
return
-
ENOMEM
;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
spec
->
gpio_domain
->
name
=
kasprintf
(
GFP_KERNEL
,
"%s-gn4124-gpio-irq"
,
dev_name
(
&
spec
->
pdev
->
dev
));
dev_name
(
&
spec
->
dev
));
#endif
...
...
@@ -449,7 +427,7 @@ static int spec_irq_sw_test(struct spec_dev *spec)
msecs_to_jiffies
(
10000
));
if
(
ret
==
0
)
{
gennum_writel
(
spec
,
0x0000
,
GNINT_STAT
);
/* disable */
dev_err
(
&
spec
->
pdev
->
dev
,
"Cannot receive interrupts
\n
"
);
dev_err
(
&
spec
->
dev
,
"Cannot receive interrupts
\n
"
);
return
-
EINVAL
;
}
return
0
;
...
...
@@ -463,6 +441,7 @@ static int spec_irq_sw_test(struct spec_dev *spec)
*/
int
spec_irq_init
(
struct
spec_dev
*
spec
)
{
int
irq
=
to_pci_dev
(
spec
->
dev
.
parent
)
->
irq
;
int
err
;
int
i
;
...
...
@@ -481,22 +460,21 @@ int spec_irq_init(struct spec_dev *spec)
goto
err_sw
;
#if CHAIN
irq_set_chained_handler
(
spec
->
pdev
->
irq
,
spec_irq_chain_handler
);
irq_set_handler_data
(
spec
->
pdev
->
irq
,
spec
);
irq_set_chained_handler
(
irq
,
spec_irq_chain_handler
);
irq_set_handler_data
(
irq
,
spec
);
#else
/*
* It depends on the platform and on the IRQ on which we are connecting to
* but most likely our interrupt handler will be a thread.
*/
err
=
request_threaded_irq
(
spec
->
pdev
->
irq
,
err
=
request_threaded_irq
(
irq
,
spec_irq_handler
,
spec_irq_gpio_handler
,
IRQF_SHARED
,
dev_name
(
&
spec
->
pdev
->
dev
),
dev_name
(
&
spec
->
dev
),
spec
);
if
(
err
)
{
dev_err
(
&
spec
->
pdev
->
dev
,
"Can't request IRQ %d (%d)
\n
"
,
spec
->
pdev
->
irq
,
err
);
dev_err
(
&
spec
->
dev
,
"Can't request IRQ %d (%d)
\n
"
,
irq
,
err
);
goto
err_req
;
}
#endif
...
...
@@ -510,7 +488,7 @@ int spec_irq_init(struct spec_dev *spec)
err_test:
spec_irq_debug_exit
(
spec
);
free_irq
(
spec
->
pdev
->
irq
,
spec
);
free_irq
(
irq
,
spec
);
err_req:
spec_irq_sw_exit
(
spec
);
err_sw:
...
...
@@ -522,6 +500,7 @@ err_gpio:
void
spec_irq_exit
(
struct
spec_dev
*
spec
)
{
int
i
;
int
irq
=
to_pci_dev
(
spec
->
dev
.
parent
)
->
irq
;
if
(
!
spec
)
return
;
...
...
@@ -529,8 +508,9 @@ void spec_irq_exit(struct spec_dev *spec)
/* disable all source of interrupts */
for
(
i
=
0
;
i
<
7
;
i
++
)
gennum_writel
(
spec
,
0
,
GNINT_CFG
(
i
));
spec_irq_debug_exit
(
spec
);
free_irq
(
spec
->
pdev
->
irq
,
spec
);
free_irq
(
irq
,
spec
);
spec_irq_sw_exit
(
spec
);
spec_irq_gpio_exit
(
spec
);
}
kernel/spec.h
View file @
29c35f2a
...
...
@@ -10,7 +10,6 @@
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/fmc.h>
#include <linux/fpga/fpga-mgr.h>
#include <linux/i2c.h>
#include <linux/irqdomain.h>
...
...
@@ -119,7 +118,7 @@ enum {
* @compl: for IRQ testing
*/
struct
spec_dev
{
struct
pci_dev
*
p
dev
;
struct
device
dev
;
struct
irq_domain
*
gpio_domain
;
...
...
@@ -128,10 +127,6 @@ struct spec_dev {
DECLARE_BITMAP
(
flags
,
SPEC_FLAG_BITS
);
void
__iomem
*
remap
[
3
];
/* ioremap of bar 0, 2, 4 */
struct
fmc_slot_info
slot_info
;
struct
platform_device
*
i2c_pdev
;
struct
i2c_adapter
*
i2c_adapter
;
struct
dentry
*
dbg_dir
;
#define SPEC_DBG_INFO_NAME "info"
struct
dentry
*
dbg_info
;
...
...
@@ -140,6 +135,11 @@ struct spec_dev {
};
static
inline
struct
spec_dev
*
to_spec_dev
(
struct
device
*
_dev
)
{
return
container_of
(
_dev
,
struct
spec_dev
,
dev
);
}
/**
* It reads a 32bit register from the gennum chip
* @spec spec device instance
...
...
@@ -184,9 +184,6 @@ static inline void gennum_mask_val(struct spec_dev *spec,
extern
int
spec_fpga_init
(
struct
spec_dev
*
spec
);
extern
void
spec_fpga_exit
(
struct
spec_dev
*
spec
);
extern
int
spec_fmc_init
(
struct
spec_dev
*
spec
);
extern
void
spec_fmc_exit
(
struct
spec_dev
*
spec
);
extern
int
spec_irq_init
(
struct
spec_dev
*
spec
);
extern
void
spec_irq_exit
(
struct
spec_dev
*
spec
);
...
...
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