Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Simple VME FMC Carrier SVEC - Software
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
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 VME FMC Carrier SVEC - Software
Commits
d3d45d25
Commit
d3d45d25
authored
Apr 27, 2015
by
Federico Vaga
Browse files
Options
Browse Files
Download
Plain Diff
program fpga from userspace
parents
92b2ad31
4abad220
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
136 additions
and
31 deletions
+136
-31
svec-drv.c
kernel/svec-drv.c
+82
-3
svec-fmc.c
kernel/svec-fmc.c
+41
-18
svec-sysfs.c
kernel/svec-sysfs.c
+9
-8
svec.h
kernel/svec.h
+4
-2
No files found.
kernel/svec-drv.c
View file @
d3d45d25
...
...
@@ -16,6 +16,7 @@
#include <linux/firmware.h>
#include <linux/delay.h>
#include <linux/jhash.h>
#include <linux/fmc-sdb.h>
#include "svec.h"
#include "hw/xloader_regs.h"
...
...
@@ -40,6 +41,8 @@ static int vme_size[SVEC_MAX_DEVICES] = SVEC_DEFAULT_VME_SIZE;
static
unsigned
int
vme_size_num
;
static
int
verbose
;
static
void
svec_destroy_misc_device
(
struct
svec_dev
*
svec
);
module_param_array
(
slot
,
int
,
&
slot_num
,
S_IRUGO
);
MODULE_PARM_DESC
(
slot
,
"Slot where SVEC card is installed"
);
module_param_array
(
lun
,
int
,
&
lun_num
,
S_IRUGO
);
...
...
@@ -382,6 +385,7 @@ static int svec_remove(struct device *pdev, unsigned int ndev)
svec_unmap_window
(
svec
,
MAP_CR_CSR
);
svec_unmap_window
(
svec
,
MAP_REG
);
svec_destroy_misc_device
(
svec
);
svec_remove_sysfs_files
(
svec
);
if
(
svec
->
verbose
)
...
...
@@ -656,7 +660,7 @@ static void svec_prepare_description(struct svec_dev *svec)
* via module parameters) or when the configuration is assigned through
* sysfs. Reconfiguration implies re-loading the FMCs.
*/
int
svec_reconfigure
(
struct
svec_dev
*
svec
)
int
svec_reconfigure
(
struct
svec_dev
*
svec
,
struct
fmc_gateware
*
gw
)
{
int
error
;
...
...
@@ -691,7 +695,7 @@ int svec_reconfigure(struct svec_dev *svec)
/* FMC initialization enabled? Start up the FMC drivers. */
if
(
svec
->
cfg_cur
.
use_fmc
)
{
error
=
svec_fmc_create
(
svec
);
error
=
svec_fmc_create
(
svec
,
gw
);
if
(
error
)
{
dev_err
(
svec
->
dev
,
"error creating fmc devices
\n
"
);
goto
failed_unmap
;
...
...
@@ -723,6 +727,73 @@ int svec_load_golden(struct svec_dev *svec)
return
0
;
}
/* * * * * * MISC DEVICE * * * * * */
static
int
svec_mdev_simple_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
miscdevice
*
mdev_ptr
=
file
->
private_data
;
file
->
private_data
=
container_of
(
mdev_ptr
,
struct
svec_dev
,
mdev
);
return
0
;
}
static
ssize_t
svec_mdev_write_raw
(
struct
file
*
f
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
offp
)
{
struct
svec_dev
*
svec
=
f
->
private_data
;
struct
fmc_gateware
gw
;
int
err
=
0
;
if
(
!
count
)
return
-
EINVAL
;
/* Copy FPGA bitstream to kernel space */
gw
.
len
=
count
;
gw
.
bitstream
=
vmalloc
(
count
);
if
(
!
gw
.
bitstream
)
return
-
ENOMEM
;
if
(
copy_from_user
(
gw
.
bitstream
,
buf
,
gw
.
len
))
{
err
=
-
EFAULT
;
goto
out
;
}
/* Program FPGA */
err
=
svec_reconfigure
(
svec
,
&
gw
);
if
(
err
)
dev_err
(
svec
->
dev
,
"Manually program FPGA bitstream from buffer: fail
\n
"
);
else
dev_info
(
svec
->
dev
,
"Manually program FPGA bitstream from buffer: success
\n
"
);
out:
vfree
(
gw
.
bitstream
);
return
err
?
err
:
count
;
}
static
const
struct
file_operations
svec_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
svec_mdev_simple_open
,
.
write
=
svec_mdev_write_raw
,
};
static
int
svec_create_misc_device
(
struct
svec_dev
*
svec
)
{
svec
->
mdev
.
minor
=
MISC_DYNAMIC_MINOR
;
svec
->
mdev
.
fops
=
&
svec_fops
;
svec
->
mdev
.
name
=
svec
->
name
;
return
misc_register
(
&
svec
->
mdev
);
}
static
void
svec_destroy_misc_device
(
struct
svec_dev
*
svec
)
{
misc_deregister
(
&
svec
->
mdev
);
}
/* * * * * * END MISC DEVICE * * * * */
static
int
svec_probe
(
struct
device
*
pdev
,
unsigned
int
ndev
)
{
struct
svec_dev
*
svec
;
...
...
@@ -800,11 +871,19 @@ static int svec_probe(struct device *pdev, unsigned int ndev)
goto
failed
;
}
error
=
svec_create_misc_device
(
svec
);
if
(
error
)
{
dev_err
(
pdev
,
"Error creating misc device
\n
"
);
goto
failed_misc
;
}
/* Map user address space & give control to the FMCs */
svec_reconfigure
(
svec
);
svec_reconfigure
(
svec
,
NULL
);
return
0
;
failed_misc:
svec_remove_sysfs_files
(
svec
);
failed:
kfree
(
svec
);
...
...
kernel/svec-fmc.c
View file @
d3d45d25
...
...
@@ -33,6 +33,41 @@ static void svec_writel(struct fmc_device *fmc, uint32_t val, int offset)
iowrite32be
(
val
,
fmc
->
fpga_base
+
offset
);
}
static
int
svec_reprogram_raw
(
struct
fmc_device
*
fmc
,
struct
fmc_driver
*
drv
,
void
*
gw
,
unsigned
long
len
)
{
struct
svec_dev
*
svec
=
fmc
->
carrier_data
;
struct
device
*
dev
=
fmc
->
hwdev
;
int
ret
;
if
(
!
gw
||
!
len
)
{
dev_err
(
dev
,
"Invalid firmware buffer - buf: %p len: %ld
\n
"
,
gw
,
len
);
return
-
EINVAL
;
}
if
(
!
drv
)
dev_info
(
dev
,
"Carrier FPGA re-program
\n
"
);
fmc_free_sdb_tree
(
fmc
);
fmc
->
flags
&=
~
FMC_DEVICE_HAS_GOLDEN
;
/* load the firmware */
ret
=
svec_load_fpga
(
svec
,
gw
,
len
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"error %i programming firmware
\n
"
,
ret
);
return
ret
;
}
/* Configure & activate CSR functions depending on chosen AM */
svec_setup_csr
(
svec
);
fmc
->
flags
|=
FMC_DEVICE_HAS_CUSTOM
;
return
0
;
}
static
int
svec_reprogram
(
struct
fmc_device
*
fmc
,
struct
fmc_driver
*
drv
,
char
*
gw
)
{
...
...
@@ -67,23 +102,10 @@ static int svec_reprogram(struct fmc_device *fmc, struct fmc_driver *drv,
dev_warn
(
dev
,
"request firmware
\"
%s
\"
: error %i
\n
"
,
gw
,
ret
);
return
ret
;
}
fmc_free_sdb_tree
(
fmc
);
fmc
->
flags
&=
~
FMC_DEVICE_HAS_GOLDEN
;
/* load the firmware */
ret
=
svec_load_fpga
(
svec
,
fw
->
data
,
fw
->
size
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"error %i programming firmware
\"
%s
\"\n
"
,
ret
,
gw
);
goto
out
;
}
/* Configure & activate CSR functions depending on chosen AM */
svec_setup_csr
(
svec
);
fmc
->
flags
|=
FMC_DEVICE_HAS_CUSTOM
;
/* Re-Program FPGA */
ret
=
svec_reprogram_raw
(
fmc
,
drv
,
(
void
*
)
fw
->
data
,
fw
->
size
);
out:
release_firmware
(
fw
);
if
(
ret
<
0
)
dev_err
(
dev
,
"svec reprogram failed while loading %s
\n
"
,
gw
);
...
...
@@ -120,6 +142,7 @@ static int svec_write_ee(struct fmc_device *fmc, int pos,
static
struct
fmc_operations
svec_fmc_operations
=
{
.
read32
=
svec_readl
,
.
write32
=
svec_writel
,
.
reprogram_raw
=
svec_reprogram_raw
,
.
reprogram
=
svec_reprogram
,
.
irq_request
=
svec_irq_request
,
.
irq_ack
=
svec_irq_ack
,
...
...
@@ -231,7 +254,7 @@ int svec_fmc_prepare(struct svec_dev *svec, unsigned int fmc_slot)
return
ret
;
}
int
svec_fmc_create
(
struct
svec_dev
*
svec
)
int
svec_fmc_create
(
struct
svec_dev
*
svec
,
struct
fmc_gateware
*
gw
)
{
int
i
;
int
error
=
0
;
...
...
@@ -244,7 +267,7 @@ int svec_fmc_create(struct svec_dev *svec)
}
/* fmc device creation */
error
=
fmc_device_register_n
(
svec
->
fmcs
,
svec
->
fmcs_n
);
error
=
fmc_device_register_n
_gw
(
svec
->
fmcs
,
svec
->
fmcs_n
,
gw
);
if
(
error
)
{
dev_err
(
svec
->
dev
,
"Error registering fmc devices
\n
"
);
goto
failed
;
...
...
@@ -274,7 +297,7 @@ void svec_fmc_destroy(struct svec_dev *svec)
fmc_device_unregister_n
(
svec
->
fmcs
,
svec
->
fmcs_n
);
WARN
(
test_bit
(
SVEC_FLAG_IRQS_REQUESTED
,
&
svec
->
flags
)
||
svec
->
vic
,
"A Mezzanine driver didn't release all its IRQ handlers (VIC %p, FLAG 0x%x)
\n
"
,
"A Mezzanine driver didn't release all its IRQ handlers (VIC %p, FLAG 0x%
l
x)
\n
"
,
svec
->
vic
,
svec
->
flags
);
memset
(
svec
->
fmcs
,
0
,
sizeof
(
struct
fmc_devices
*
)
*
SVEC_N_SLOTS
);
...
...
kernel/svec-sysfs.c
View file @
d3d45d25
...
...
@@ -57,22 +57,23 @@ static int svec_fw_cmd_reset(struct svec_dev *card)
static
int
svec_fw_cmd_program
(
struct
svec_dev
*
card
)
{
int
err
;
struct
fmc_gateware
gw
=
{
card
->
fw_buffer
,
card
->
fw_length
};
int
err
=
0
;
if
(
!
card
->
fw_buffer
||
!
card
->
fw_length
)
return
-
EINVAL
;
err
=
svec_load_fpga
(
card
,
card
->
fw_buffer
,
card
->
fw_length
);
vfree
(
card
->
fw_buffer
)
;
if
(
err
)
goto
out
;
card
->
fw_buffer
=
NULL
;
card
->
fw_length
=
0
;
if
(
err
<
0
)
return
err
;
svec_reconfigure
(
card
);
return
0
;
svec_reconfigure
(
card
,
&
gw
);
out:
vfree
(
card
->
fw_buffer
);
return
err
;
}
...
...
@@ -401,7 +402,7 @@ ATTR_STORE_CALLBACK(configured)
card
->
cfg_new
.
configured
=
1
;
card
->
cfg_cur
=
card
->
cfg_new
;
error
=
svec_reconfigure
(
card
);
error
=
svec_reconfigure
(
card
,
NULL
);
if
(
error
)
return
error
;
...
...
kernel/svec.h
View file @
d3d45d25
...
...
@@ -10,6 +10,7 @@
#ifndef __SVEC_H__
#define __SVEC_H__
#include <linux/miscdevice.h>
#include <linux/firmware.h>
#include <linux/fmc.h>
#include "vmebus.h"
...
...
@@ -74,6 +75,7 @@ struct svec_dev {
uint32_t
fw_hash
;
struct
vme_mapping
*
map
[
__MAX_MAP
];
struct
svec_config
cfg_cur
,
cfg_new
;
struct
miscdevice
mdev
;
struct
fmc_device
*
fmcs
[
SVEC_N_SLOTS
];
irq_handler_t
fmc_handlers
[
SVEC_N_SLOTS
];
...
...
@@ -104,7 +106,7 @@ extern int svec_map_window(struct svec_dev *svec, enum svec_map_win map_type);
extern
char
*
svec_fw_name
;
/* Functions in svec-fmc.c, used by svec-vme.c */
extern
int
svec_fmc_create
(
struct
svec_dev
*
svec
);
extern
int
svec_fmc_create
(
struct
svec_dev
*
svec
,
struct
fmc_gateware
*
gw
);
extern
void
svec_fmc_destroy
(
struct
svec_dev
*
svec
);
/* Functions in svec-i2c.c, used by svec-fmc.c */
...
...
@@ -138,7 +140,7 @@ int svec_dma_read(struct svec_dev *svec, uint32_t addr, int am, size_t size,
void
*
buf
,
int
is_fifo
);
int
svec_reconfigure
(
struct
svec_dev
*
svec
);
int
svec_reconfigure
(
struct
svec_dev
*
svec
,
struct
fmc_gateware
*
gw
);
int
svec_setup_csr
(
struct
svec_dev
*
svec
);
int
svec_validate_configuration
(
struct
device
*
pdev
,
struct
svec_config
*
cfg
);
...
...
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