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
061bbd7e
Commit
061bbd7e
authored
Nov 09, 2020
by
Federico Vaga
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'release/v2.1.0' into master
parents
f63c5572
0c8a72ce
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
562 additions
and
175 deletions
+562
-175
CHANGELOG.rst
CHANGELOG.rst
+26
-2
general-cores
hdl/ip_cores/general-cores
+1
-1
gn4124-core
hdl/ip_cores/gn4124-core
+1
-1
spec_base_wr.vhd
hdl/rtl/spec_base_wr.vhd
+1
-1
conftest.py
pytest/conftest.py
+7
-1
test_dma.py
pytest/test_dma.py
+63
-80
Makefile
software/Makefile
+1
-1
spec.h
software/include/uapi/linux/spec.h
+59
-0
Kbuild
software/kernel/Kbuild
+1
-0
gn412x-gpio.c
software/kernel/gn412x-gpio.c
+50
-7
gn412x.h
software/kernel/gn412x.h
+14
-0
spec-core-fpga.c
software/kernel/spec-core-fpga.c
+16
-2
spec-core.c
software/kernel/spec-core.c
+1
-1
spec-gn412x-dma.c
software/kernel/spec-gn412x-dma.c
+58
-35
spec.h
software/kernel/spec.h
+1
-43
.gitignore
software/tools/.gitignore
+1
-0
Makefile
software/tools/Makefile
+36
-0
spec-firmware-version.c
software/tools/spec-firmware-version.c
+225
-0
No files found.
CHANGELOG.rst
View file @
061bbd7e
...
...
@@ -6,11 +6,35 @@
Changelog
=========
2.
0.0 - 2020-08-20
2.
1.0 - 2020-11-09
==================
Fixed
-----
- program 2 or more SPEC FPGAs in parallel. There is a bug in the
- hdl: cross-page DMA failure
- sw: DMA pool memory leak
- sw: fix concurrent DMA tasklet
Changed
-------
- tst: keep the DMA interface open while testing to avoid continuos
memory re-allocation
Added
-----
- sw: tool to firmware version inspection
- sw: FLASH partitions
2.0.2 - 2020-09-29
==================
Fixed
-----
- hdl: L2P DMA issues reported with slower hosts
2.0.1 - 2020-08-20
==================
Fixed
-----
- sw: program 2 or more SPEC FPGAs in parallel. There is a bug in the
GN412x chip that we fixed in software by serializing any attempt of
parallel programming
...
...
general-cores
@
347e0de1
Subproject commit
258eb8e00f99f795fe9b98840b01ac4a8b92ec94
Subproject commit
347e0de1e0d91834d298a146569530b71adeb33a
gn4124-core
@
c6293643
Subproject commit
e763762405dd5274d342285dbc64683221f1fb15
Subproject commit
c629364388453726da401909b5154306ab4e6930
hdl/rtl/spec_base_wr.vhd
View file @
061bbd7e
...
...
@@ -604,7 +604,7 @@ begin -- architecture top
metadata_data
<=
x"53504543"
;
when
x"2"
=>
-- Version
metadata_data
<=
x"0200000
0
"
;
metadata_data
<=
x"0200000
2
"
;
when
x"3"
=>
-- BOM
metadata_data
<=
x"fffe0000"
;
...
...
pytest/conftest.py
View file @
061bbd7e
...
...
@@ -7,11 +7,17 @@ import pytest
from
PySPEC
import
PySPEC
@
pytest
.
fixture
(
scope
=
"
function
"
)
@
pytest
.
fixture
(
scope
=
"
module
"
)
def
spec
():
spec_dev
=
PySPEC
(
pytest
.
pci_id
)
yield
spec_dev
@
pytest
.
fixture
(
scope
=
"class"
)
def
dma
():
spec
=
PySPEC
(
pytest
.
pci_id
)
with
spec
.
dma
()
as
spec_dma
:
yield
spec_dma
def
pytest_addoption
(
parser
):
parser
.
addoption
(
"--pci-id"
,
required
=
True
,
help
=
"SPEC PCI Identifier"
)
...
...
pytest/test_dma.py
View file @
061bbd7e
This diff is collapsed.
Click to expand it.
software/Makefile
View file @
061bbd7e
-include
Makefile.specific
-include
$(REPO_PARENT)/parent_common.mk
DIRS
=
kernel
DIRS
=
kernel
tools
.PHONY
:
all clean modules install modules_install coccicheck $(DIRS)
...
...
software/include/uapi/linux/spec.h
0 → 100644
View file @
061bbd7e
/*
* Copyright (C) 2020 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#ifndef __LINUX_UAPI_SPEC_H
#define __LINUX_UAPI_SPEC_H
#ifndef __KERNEL__
#include <stdint.h>
#endif
#define SPEC_FMC_SLOTS 1
/* On FPGA components */
#define PCI_VENDOR_ID_CERN (0x10DC)
#define PCI_DEVICE_ID_SPEC_45T (0x018D)
#define PCI_DEVICE_ID_SPEC_100T (0x01A2)
#define PCI_DEVICE_ID_SPEC_150T (0x01A3)
#define PCI_VENDOR_ID_GENNUM (0x1A39)
#define PCI_DEVICE_ID_GN4124 (0x0004)
#define GN4124_GPIO_MAX 16
#define GN4124_GPIO_BOOTSEL0 15
#define GN4124_GPIO_BOOTSEL1 14
#define GN4124_GPIO_SPRI_DIN 13
#define GN4124_GPIO_SPRI_FLASH_CS 12
#define GN4124_GPIO_IRQ0 9
#define GN4124_GPIO_IRQ1 8
#define GN4124_GPIO_SCL 5
#define GN4124_GPIO_SDA 4
#define SPEC_DDR_SIZE (256 * 1024 * 1024)
#define SPEC_META_VENDOR_ID PCI_VENDOR_ID_CERN
#define SPEC_META_DEVICE_ID 0x53504543
#define SPEC_META_BOM_LE 0xFFFE0000
#define SPEC_META_BOM_END_MASK 0xFFFF0000
#define SPEC_META_BOM_VER_MASK 0x0000FFFF
#define SPEC_META_VERSION_MASK 0xFFFF0000
#define SPEC_META_VERSION_2_0 0x02000000
/**
* struct spec_meta_id Metadata
*/
struct
spec_meta_id
{
uint32_t
vendor
;
uint32_t
device
;
uint32_t
version
;
uint32_t
bom
;
uint32_t
src
[
4
];
uint32_t
cap
;
uint32_t
uuid
[
4
];
};
#define SPEC_META_VERSION_MAJ(_v) ((_v >> 24) & 0xFF)
#define SPEC_META_VERSION_MIN(_v) ((_v >> 16) & 0xFF)
#define SPEC_META_VERSION_PATCH(_v) (_v & 0xFFFF)
#endif
/* __LINUX_UAPI_SPEC_H */
software/kernel/Kbuild
View file @
061bbd7e
...
...
@@ -15,6 +15,7 @@ ccflags-y += -I$(FPGA_MGR_ABS)/include
ccflags-$(CONFIG_FPGA_MGR_BACKPORT) += -DCONFIG_FPGA_MGR_BACKPORT
ccflags-y += -I$(FMC_ABS)/include
ccflags-y += -I$(SPI_ABS)/include
ccflags-y += -I$(src)/../include
# priority to I2C, FMC headers from our sources
LINUXINCLUDE := -I$(FMC_ABS)/include -I$(FMC_ABS)/include/linux -I$(I2C_ABS)/include -I$(I2C_ABS)/include/linux $(LINUXINCLUDE)
...
...
software/kernel/gn412x-gpio.c
View file @
061bbd7e
...
...
@@ -156,13 +156,43 @@ static void gn412x_gpio_reg_write(struct gpio_chip *chip,
gn412x_iowrite32
(
gn412x
,
regval
,
reg
);
}
/**
* Enable Internal Gennum error's interrupts
* @gn412x gn412x device
*
* Return: 0 on success, otherwise a negative error number
*/
static
void
gn412x_gpio_int_cfg_enable_err
(
struct
gn412x_gpio_dev
*
gn412x
)
{
uint32_t
int_cfg
;
int_cfg
=
gn412x_ioread32
(
gn412x
,
GNINT_CFG
(
gn412x
->
pdata
->
int_cfg
));
int_cfg
|=
GNINT_STAT_ERR_ALL
;
gn412x_iowrite32
(
gn412x
,
int_cfg
,
GNINT_CFG
(
gn412x
->
pdata
->
int_cfg
));
}
/**
* disable Internal Gennum error's interrupts
* @gn412x gn412x device
*
* Return: 0 on success, otherwise a negative error number
*/
static
void
gn412x_gpio_int_cfg_disable_err
(
struct
gn412x_gpio_dev
*
gn412x
)
{
uint32_t
int_cfg
;
int_cfg
=
gn412x_ioread32
(
gn412x
,
GNINT_CFG
(
gn412x
->
pdata
->
int_cfg
));
int_cfg
&=
~
GNINT_STAT_ERR_ALL
;
gn412x_iowrite32
(
gn412x
,
int_cfg
,
GNINT_CFG
(
gn412x
->
pdata
->
int_cfg
));
}
/**
* Enable GPIO interrupts
* @gn412x gn412x device
*
* Return: 0 on success, otherwise a negative error number
*/
static
void
gn412x_gpio_int_cfg_enable
(
struct
gn412x_gpio_dev
*
gn412x
)
static
void
gn412x_gpio_int_cfg_enable
_gpio
(
struct
gn412x_gpio_dev
*
gn412x
)
{
uint32_t
int_cfg
;
...
...
@@ -175,7 +205,7 @@ static void gn412x_gpio_int_cfg_enable(struct gn412x_gpio_dev *gn412x)
* Disable GPIO interrupts from a single configuration space
* @gn412x gn412x device
*/
static
void
gn412x_gpio_int_cfg_disable
(
struct
gn412x_gpio_dev
*
gn412x
)
static
void
gn412x_gpio_int_cfg_disable
_gpio
(
struct
gn412x_gpio_dev
*
gn412x
)
{
uint32_t
int_cfg
;
...
...
@@ -435,7 +465,7 @@ static irqreturn_t gn412x_gpio_irq_handler_t(int irq, void *arg)
out_enable_irq:
/* Re-enable the GPIO interrupts, we are done here */
gn412x_gpio_int_cfg_enable
(
gn412x
);
gn412x_gpio_int_cfg_enable
_gpio
(
gn412x
);
return
ret
;
}
...
...
@@ -454,6 +484,13 @@ static irqreturn_t gn412x_gpio_irq_handler_h(int irq, void *arg)
if
(
unlikely
(
int_stat
&
GNINT_STAT_SW_ALL
))
/* only for testing */
return
spec_irq_sw_handler
(
irq
,
gn412x
);
if
(
WARN
(
int_stat
&
GNINT_STAT_ERR_ALL
,
"GN412x ERROR 0x%08x"
,
int_stat
))
{
gn412x_iowrite32
(
gn412x
,
int_stat
&
GNINT_STAT_ERR_ALL
,
GNINT_STAT
);
return
IRQ_HANDLED
;
}
/*
* Do not listen to new interrupts while handling the current GPIOs.
* This may take a while since the chain behind each GPIO can be long.
...
...
@@ -462,8 +499,10 @@ static irqreturn_t gn412x_gpio_irq_handler_h(int irq, void *arg)
* devices sharing the same IRQ to wait for us; just to play safe,
* let's disable interrupts. Within the thread we will re-enable them
* when we are ready (like IRQF_ONESHOT).
*
* We keep the error interrupts enabled
*/
gn412x_gpio_int_cfg_disable
(
gn412x
);
gn412x_gpio_int_cfg_disable
_gpio
(
gn412x
);
return
IRQ_WAKE_THREAD
;
}
...
...
@@ -521,7 +560,8 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
}
gn412x_iowrite32
(
gn412x
,
0
,
GNGPIO_BYPASS_MODE
);
gn412x_gpio_int_cfg_disable
(
gn412x
);
gn412x_gpio_int_cfg_disable_err
(
gn412x
);
gn412x_gpio_int_cfg_disable_gpio
(
gn412x
);
gn412x_iowrite32
(
gn412x
,
0xFFFF
,
GNGPIO_INT_MASK_SET
);
gn412x
->
irqchip
.
name
=
"GN412X-GPIO"
,
...
...
@@ -594,7 +634,8 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
goto
err_req
;
}
gn412x_gpio_int_cfg_enable
(
gn412x
);
gn412x_gpio_int_cfg_enable_err
(
gn412x
);
gn412x_gpio_int_cfg_enable_gpio
(
gn412x
);
gn412x_dbg_init
(
gn412x
);
...
...
@@ -621,7 +662,9 @@ static int gn412x_gpio_remove(struct platform_device *pdev)
gn412x_dbg_exit
(
gn412x
);
gn412x_gpio_int_cfg_disable
(
gn412x
);
gn412x_gpio_int_cfg_disable_gpio
(
gn412x
);
gn412x_gpio_int_cfg_disable_err
(
gn412x
);
free_irq
(
platform_get_irq
(
pdev
,
0
),
gn412x
);
gn412x_gpio_irq_set_nested_thread_all
(
gn412x
,
false
);
...
...
software/kernel/gn412x.h
View file @
061bbd7e
...
...
@@ -7,8 +7,22 @@
#define __GN412X_H__
#define GNINT_STAT_GPIO BIT(15)
#define GNINT_STAT_ALI6 BIT(14)
#define GNINT_STAT_ALI5 BIT(13)
#define GNINT_STAT_ALI4 BIT(12)
#define GNINT_STAT_ALI3 BIT(11)
#define GNINT_STAT_ALI2 BIT(10)
#define GNINT_STAT_ALI1 BIT(9)
#define GNINT_STAT_ALI0 BIT(8)
#define GNINT_STAT_SW0 BIT(2)
#define GNINT_STAT_SW1 BIT(3)
#define GNINT_STAT_ERR_ALL (GNINT_STAT_ALI0 | \
GNINT_STAT_ALI1 | \
GNINT_STAT_ALI2 | \
GNINT_STAT_ALI3 | \
GNINT_STAT_ALI4 | \
GNINT_STAT_ALI5 | \
GNINT_STAT_ALI6)
#define GNINT_STAT_SW_ALL (GNINT_STAT_SW0 | GNINT_STAT_SW1)
/* Registers for GN4124 access */
...
...
software/kernel/spec-core-fpga.c
View file @
061bbd7e
...
...
@@ -20,6 +20,7 @@
#include <linux/jiffies.h>
#include <linux/uaccess.h>
#include <linux/moduleparam.h>
#include <linux/mtd/partitions.h>
#include "linux/printk.h"
#include "spec.h"
...
...
@@ -646,10 +647,23 @@ static struct resource spec_fpga_spi_res[] = {
},
};
static
struct
mtd_partition
spec_flash_parts
[]
=
{
{
.
name
=
"AFPGA"
,
.
offset
=
0x00000000
,
.
size
=
5
*
SZ_1M
,
},
{
.
name
=
"AFPGA_DATA"
,
.
offset
=
MTDPART_OFS_APPEND
,
.
size
=
MTDPART_SIZ_FULL
,
},
};
struct
flash_platform_data
spec_flash_pdata
=
{
.
name
=
"spec-flash"
,
.
parts
=
NULL
,
.
nr_parts
=
0
,
.
parts
=
spec_flash_parts
,
.
nr_parts
=
ARRAY_SIZE
(
spec_flash_parts
)
,
.
type
=
"m25p32"
,
};
...
...
software/kernel/spec-core.c
View file @
061bbd7e
...
...
@@ -783,6 +783,6 @@ MODULE_VERSION(VERSION);
MODULE_DESCRIPTION
(
"Driver for the 'Simple PCIe FMC Carrier' a.k.a. SPEC"
);
MODULE_DEVICE_TABLE
(
pci
,
spec_pci_tbl
);
MODULE_SOFTDEP
(
"pre: gn412x_gpio gn412x_fcl htvic spec_gn412x_dma i2c_mux i2c-ocores spi-ocores"
);
MODULE_SOFTDEP
(
"pre: gn412x_gpio gn412x_fcl htvic spec_gn412x_dma i2c_mux i2c-ocores spi-ocores
m25p80
"
);
ADDITIONAL_VERSIONS
;
software/kernel/spec-gn412x-dma.c
View file @
061bbd7e
...
...
@@ -310,25 +310,17 @@ static void gn412x_dma_ctrl_swapping(struct gn412x_dma_device *gn412x_dma,
static
enum
gn412x_dma_state
gn412x_dma_state
(
struct
gn412x_dma_device
*
gn412x_dma
)
{
return
ioread32
(
gn412x_dma
->
addr
+
GN412X_DMA_STAT
);
return
ioread32
(
gn412x_dma
->
addr
+
GN412X_DMA_STAT
)
&
0x3
;
}
static
bool
gn412x_dma_is_busy
(
struct
gn412x_dma_device
*
gn412x_dma
)
{
uint32_t
status
;
status
=
ioread32
(
gn412x_dma
->
addr
+
GN412X_DMA_STAT
);
return
status
&
GN412X_DMA_STAT_BUSY
;
return
gn412x_dma_state
(
gn412x_dma
)
==
GN412X_DMA_STAT_BUSY
;
}
static
bool
gn412x_dma_is_abort
(
struct
gn412x_dma_device
*
gn412x_dma
)
{
uint32_t
status
;
status
=
ioread32
(
gn412x_dma
->
addr
+
GN412X_DMA_STAT
);
return
status
&
GN412X_DMA_STAT_ABORTED
;
return
gn412x_dma_state
(
gn412x_dma
)
==
GN412X_DMA_STAT_ABORTED
;
}
static
void
gn412x_dma_irq_ack
(
struct
gn412x_dma_device
*
gn412x_dma
)
...
...
@@ -535,6 +527,32 @@ err:
return
NULL
;
}
static
void
gn412x_dma_tx_free
(
struct
gn412x_dma_tx
*
tx
)
{
struct
gn412x_dma_device
*
gn412x_dma
;
int
i
;
if
(
unlikely
(
!
tx
))
return
;
gn412x_dma
=
to_gn412x_dma_device
(
tx
->
tx
.
chan
->
device
);
for
(
i
=
0
;
i
<
tx
->
sg_len
;
++
i
)
{
dma_addr_t
phys
;
dev_dbg
(
&
gn412x_dma
->
pdev
->
dev
,
"Release TX (%p) DMA desc %d
\n
"
,
tx
,
i
);
if
(
i
==
0
)
{
phys
=
tx
->
tx
.
phys
;
}
else
{
phys
=
tx
->
sgl_hw
[
i
-
1
]
->
next_addr_h
;
phys
<<=
32
;
phys
|=
tx
->
sgl_hw
[
i
-
1
]
->
next_addr_l
;
}
dma_pool_free
(
gn412x_dma
->
pool
,
tx
->
sgl_hw
[
i
],
phys
);
}
kfree
(
tx
->
sgl_hw
);
kfree
(
tx
);
}
static
void
gn412x_dma_schedule_next
(
struct
gn412x_dma_chan
*
gn412x_dma_chan
)
{
unsigned
long
flags
;
...
...
@@ -609,27 +627,33 @@ static int gn412x_dma_slave_config(struct dma_chan *chan,
static
int
gn412x_dma_terminate_all
(
struct
dma_chan
*
chan
)
{
struct
gn412x_dma_chan
*
gn412x_dma_chan
=
to_gn412x_dma_chan
(
chan
);
struct
gn412x_dma_device
*
gn412x_dma
;
struct
gn412x_dma_tx
*
tx
;
struct
gn412x_dma_tx
*
tx
,
*
tx_tmp
;
unsigned
long
flags
;
gn412x_dma
=
to_gn412x_dma_device
(
chan
->
device
);
gn412x_dma_ctrl_abort
(
gn412x_dma
);
/* FIXME remove all pending */
if
(
!
gn412x_dma_is_abort
(
gn412x_dma
))
{
dev_err
(
&
gn412x_dma
->
pdev
->
dev
,
"Failed to abort DMA transfer
\n
"
);
return
-
EINVAL
;
}
tx
=
to_gn412x_dma_chan
(
chan
)
->
tx_curr
;
if
(
tx
&&
tx
->
tx
.
callback_result
)
{
const
struct
dmaengine_result
result
=
{
.
result
=
DMA_TRANS_ABORTED
,
.
residue
=
0
,
};
tx
->
tx
.
callback_result
(
tx
->
tx
.
callback_param
,
&
result
);
spin_lock_irqsave
(
&
gn412x_dma_chan
->
lock
,
flags
);
list_for_each_entry_safe
(
tx
,
tx_tmp
,
&
gn412x_dma_chan
->
pending_list
,
list
)
{
list_del
(
&
tx
->
list
);
gn412x_dma_tx_free
(
tx
);
}
tx
=
gn412x_dma_chan
->
tx_curr
;
if
(
tx
)
{
gn412x_dma_ctrl_abort
(
gn412x_dma
);
gn412x_dma_chan
->
tx_curr
=
NULL
;
if
(
tx
->
tx
.
callback_result
&&
gn412x_dma_is_abort
(
gn412x_dma
))
{
const
struct
dmaengine_result
result
=
{
.
result
=
DMA_TRANS_ABORTED
,
.
residue
=
0
,
};
tx
->
tx
.
callback_result
(
tx
->
tx
.
callback_param
,
&
result
);
}
gn412x_dma_tx_free
(
tx
);
}
spin_unlock_irqrestore
(
&
gn412x_dma_chan
->
lock
,
flags
);
return
0
;
}
...
...
@@ -656,13 +680,13 @@ static int gn412x_dma_device_control(struct dma_chan *chan,
}
#endif
static
irqreturn_t
gn412x_dma_irq_handler
(
int
irq
,
void
*
arg
)
{
struct
gn412x_dma_device
*
gn412x_dma
=
arg
;
struct
gn412x_dma_chan
*
chan
=
&
gn412x_dma
->
chan
;
struct
gn412x_dma_tx
*
tx
;
unsigned
long
flags
;
unsigned
int
i
;
enum
gn412x_dma_state
state
;
/* FIXME check for spurious - need HDL fix */
...
...
@@ -683,6 +707,7 @@ static irqreturn_t gn412x_dma_irq_handler(int irq, void *arg)
spin_unlock_irqrestore
(
&
chan
->
lock
,
flags
);
state
=
gn412x_dma_state
(
gn412x_dma
);
gn412x_dma_schedule_next
(
chan
);
switch
(
state
)
{
case
GN412X_DMA_STAT_IDLE
:
dma_cookie_complete
(
&
tx
->
tx
);
...
...
@@ -706,7 +731,8 @@ static irqreturn_t gn412x_dma_irq_handler(int irq, void *arg)
tx
->
tx
.
callback_result
(
tx
->
tx
.
callback_param
,
&
result
);
}
dev_err
(
&
gn412x_dma
->
pdev
->
dev
,
"DMA transfer failed: error
\n
"
);
dev_err
(
&
gn412x_dma
->
pdev
->
dev
,
"DMA transfer failed: error
\n
"
);
break
;
default:
dev_err
(
&
gn412x_dma
->
pdev
->
dev
,
...
...
@@ -716,12 +742,7 @@ static irqreturn_t gn412x_dma_irq_handler(int irq, void *arg)
}
/* Clean up memory */
for
(
i
=
0
;
i
<
tx
->
sg_len
;
++
i
)
dma_pool_free
(
gn412x_dma
->
pool
,
tx
->
sgl_hw
[
i
],
tx
->
tx
.
phys
);
kfree
(
tx
->
sgl_hw
);
kfree
(
tx
);
gn412x_dma_schedule_next
(
chan
);
gn412x_dma_tx_free
(
tx
);
return
IRQ_HANDLED
;
}
...
...
@@ -779,6 +800,8 @@ static int gn412x_dma_engine_init(struct gn412x_dma_device *gn412x_dma,
dma
->
dev
=
parent
;
if
(
dma_set_mask
(
dma
->
dev
,
DMA_BIT_MASK
(
64
)))
{
dev_warn
(
dma
->
dev
,
"64-bit DMA addressing not available
\n
"
);
/* Check if hardware supports 32-bit DMA */
if
(
dma_set_mask
(
dma
->
dev
,
DMA_BIT_MASK
(
32
)))
{
dev_err
(
dma
->
dev
,
...
...
software/kernel/spec.h
View file @
061bbd7e
...
...
@@ -15,32 +15,11 @@
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/fmc.h>
#include <uapi/linux/spec.h>
#include "gn412x.h"
#include "spec-core-fpga.h"
#define SPEC_FMC_SLOTS 1
/* On FPGA components */
#define PCI_VENDOR_ID_CERN (0x10DC)
#define PCI_DEVICE_ID_SPEC_45T (0x018D)
#define PCI_DEVICE_ID_SPEC_100T (0x01A2)
#define PCI_DEVICE_ID_SPEC_150T (0x01A3)
#define PCI_VENDOR_ID_GENNUM (0x1A39)
#define PCI_DEVICE_ID_GN4124 (0x0004)
#define GN4124_GPIO_MAX 16
#define GN4124_GPIO_BOOTSEL0 15
#define GN4124_GPIO_BOOTSEL1 14
#define GN4124_GPIO_SPRI_DIN 13
#define GN4124_GPIO_SPRI_FLASH_CS 12
#define GN4124_GPIO_IRQ0 9
#define GN4124_GPIO_IRQ1 8
#define GN4124_GPIO_SCL 5
#define GN4124_GPIO_SDA 4
#define SPEC_DDR_SIZE (256 * 1024 * 1024)
/**
* @SPEC_FPGA_SELECT_FPGA_FLASH: (default) the FPGA is an SPI master that can
* access the flash (at boot it takes its
...
...
@@ -79,27 +58,6 @@ enum {
SPEC_META_UUID
=
SPEC_META_BASE
+
FPGA_META_UUID
,
};
#define SPEC_META_VENDOR_ID PCI_VENDOR_ID_CERN
#define SPEC_META_DEVICE_ID 0x53504543
#define SPEC_META_BOM_LE 0xFFFE0000
#define SPEC_META_BOM_END_MASK 0xFFFF0000
#define SPEC_META_BOM_VER_MASK 0x0000FFFF
#define SPEC_META_VERSION_MASK 0xFFFF0000
#define SPEC_META_VERSION_2_0 0x02000000
/**
* struct spec_meta_id Metadata
*/
struct
spec_meta_id
{
uint32_t
vendor
;
uint32_t
device
;
uint32_t
version
;
uint32_t
bom
;
uint32_t
src
[
4
];
uint32_t
cap
;
uint32_t
uuid
[
4
];
};
/**
* struct spec_fpga - it contains data to handle the FPGA
*
...
...
software/tools/.gitignore
0 → 100644
View file @
061bbd7e
spec-firmware-version
software/tools/Makefile
0 → 100644
View file @
061bbd7e
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# Copyright (C) 2020 CERN
# If it exists includes Makefile.specific. In this Makefile, you should put
# specific Makefile code that you want to run before this. For example,
# build a particular environment.
-include
Makefile.specific
DESTDIR
?=
/usr/local/
TOOLS
=
spec-firmware-version
INCLUDE
:=
-I
.
-I
../kernel
-I
../include/uapi
CFLAGS
=
-ggdb
$(INCLUDE)
-Wall
-Werror
$(EXTRACFLAGS)
GIT_VERSION
:=
$(
shell
git describe
--dirty
--long
--tags
)
CFLAGS
+=
-DGIT_VERSION
=
"
\"
$(GIT_VERSION)
\"
"
CPPCHECK
?=
cppcheck
all
:
$(TOOLS)
$(TOOLS)
:
clean
:
rm
-f
$(TOOLS)
install
:
install
-d
$(DESTDIR)
/bin
install
-D
$(TOOLS)
$(DESTDIR)
/bin
cppcheck
:
$(CPPCHECK)
-q
$(INCLUDE)
--suppress
=
missingIncludeSystem
--enable
=
all
*
.c
*
.h
--error-exitcode
=
1
.PHONY
=
cppcheck
software/tools/spec-firmware-version.c
0 → 100644
View file @
061bbd7e
/*
* SPDX-License-Identifier: LGPL-3.0-or-later
* Copyright (C) 2020 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <getopt.h>
#include <libgen.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/spec.h>
#include <spec-core-fpga.h>
static
const
char
git_version
[]
=
"git version: "
GIT_VERSION
;
static
char
*
name
;
static
bool
singleline
=
false
;
static
unsigned
int
verbose
;
static
void
help
(
void
)
{
fprintf
(
stderr
,
"%s [options]
\n
"
"
\t
Print the firmware version
\n
"
"
\t
-p <PCIID>
\n
"
"
\t
-b print spec-base
\n
"
"
\t
-a print spec-application
\n
"
"
\t
-1 print on a single line
\n
"
"
\t
-V print version
\n
"
"
\t
-h print help
\n
"
,
name
);
}
static
void
print_version
(
void
)
{
printf
(
"%s version %s
\n
"
,
name
,
git_version
);
}
static
void
cleanup
(
void
)
{
if
(
name
)
free
(
name
);
}
static
const
char
*
bom_to_str
(
uint32_t
bom
)
{
if
((
bom
&
SPEC_META_BOM_END_MASK
)
==
SPEC_META_BOM_LE
)
return
"little-endian"
;
else
return
"wrong"
;
}
static
void
print_meta_id_one
(
struct
spec_meta_id
*
rom
)
{
fprintf
(
stdout
,
"0x%08x,0x%08x,%u.%u.%u"
,
rom
->
vendor
,
rom
->
device
,
SPEC_META_VERSION_MAJ
(
rom
->
version
),
SPEC_META_VERSION_MIN
(
rom
->
version
),
SPEC_META_VERSION_PATCH
(
rom
->
version
));
if
(
verbose
>
1
)
{
fprintf
(
stdout
,
",%08x%08x%08x%08x,%s,%08x%08x%08x%08x"
,
rom
->
src
[
0
],
rom
->
src
[
1
],
rom
->
src
[
2
],
rom
->
src
[
3
],
bom_to_str
(
rom
->
bom
),
rom
->
uuid
[
0
],
rom
->
uuid
[
1
],
rom
->
uuid
[
2
],
rom
->
uuid
[
3
]);
}
fputc
(
'\n'
,
stdout
);
}
static
void
print_meta_id
(
struct
spec_meta_id
*
rom
)
{
fputc
(
'\n'
,
stdout
);
fprintf
(
stdout
,
" vendor : 0x%08x
\n
"
,
rom
->
vendor
);
fprintf
(
stdout
,
" device : 0x%08x
\n
"
,
rom
->
device
);
fprintf
(
stdout
,
" version : %u.%u.%u
\n
"
,
SPEC_META_VERSION_MAJ
(
rom
->
version
),
SPEC_META_VERSION_MIN
(
rom
->
version
),
SPEC_META_VERSION_PATCH
(
rom
->
version
));
if
(
verbose
>
1
)
{
fprintf
(
stdout
,
" byte-order : %s
\n
"
,
bom_to_str
(
rom
->
bom
));
fprintf
(
stdout
,
" sources : %08x%08x%08x%08x
\n
"
,
rom
->
src
[
0
],
rom
->
src
[
1
],
rom
->
src
[
2
],
rom
->
src
[
3
]);
fprintf
(
stdout
,
" capabilities : 0x%08x
\n
"
,
rom
->
cap
);
fprintf
(
stdout
,
" UUID : %08x%08x%08x%08x
\n
"
,
rom
->
uuid
[
0
],
rom
->
uuid
[
1
],
rom
->
uuid
[
2
],
rom
->
uuid
[
3
]);
}
}
static
int
print_base_meta_id
(
int
fd
)
{
struct
spec_meta_id
*
rom
;
rom
=
mmap
(
NULL
,
sizeof
(
*
rom
),
PROT_READ
,
MAP_SHARED
,
fd
,
SPEC_BASE_REGS_METADATA
);
if
((
long
)
rom
==
-
1
)
{
fputs
(
"Failed while reading SPEC-BASE FPGA ROM
\n
"
,
stderr
);
return
-
1
;
}
fputs
(
"spec-base: "
,
stdout
);
if
(
singleline
)
print_meta_id_one
(
rom
);
else
print_meta_id
(
rom
);
munmap
(
rom
,
sizeof
(
*
rom
));
return
0
;
}
static
off_t
app_meta_id_offset
(
int
fd
)
{
off_t
offset
;
void
*
regs
;
regs
=
mmap
(
NULL
,
0x100
,
PROT_READ
,
MAP_SHARED
,
fd
,
0
);
if
((
long
)
regs
==
-
1
)
return
-
1
;
offset
=
*
((
uint32_t
*
)(
regs
+
SPEC_BASE_REGS_CSR_APP_OFFSET
));
munmap
(
regs
,
0x100
);
return
offset
;
}
static
int
print_app_meta_id
(
int
fd
)
{
struct
spec_meta_id
*
rom
;
off_t
offset
;
offset
=
app_meta_id_offset
(
fd
);
if
(
offset
<
0
)
{
fputs
(
"Can't get spec-app offset
\n
"
,
stderr
);
return
-
1
;
}
if
(
offset
==
0
)
{
fputs
(
"spec-application:
\n
None
\n
"
,
stderr
);
return
0
;
}
rom
=
mmap
(
NULL
,
sizeof
(
*
rom
),
PROT_READ
,
MAP_SHARED
,
fd
,
offset
);
if
((
long
)
rom
==
-
1
)
{
fputs
(
"Failed while reading SPEC-APP FPGA ROM
\n
"
,
stderr
);
return
-
1
;
}
fputs
(
"spec-application: "
,
stdout
);
if
(
singleline
)
print_meta_id_one
(
rom
);
else
print_meta_id
(
rom
);
munmap
(
rom
,
sizeof
(
*
rom
));
return
0
;
}
#define PCIID_STR_LEN 16
int
main
(
int
argc
,
char
*
argv
[])
{
bool
base
=
false
,
app
=
false
;
int
err
;
int
fd
;
char
path
[
128
];
char
opt
;
char
pciid_str
[
PCIID_STR_LEN
]
=
"
\0
"
;
name
=
strndup
(
basename
(
argv
[
0
]),
64
);
if
(
!
name
)
exit
(
EXIT_FAILURE
);
err
=
atexit
(
cleanup
);
if
(
err
)
exit
(
EXIT_FAILURE
);
while
((
opt
=
getopt
(
argc
,
argv
,
"h?Vvp:ba1"
))
!=
-
1
)
{
switch
(
opt
)
{
case
'h'
:
case
'?'
:
help
();
exit
(
EXIT_SUCCESS
);
case
'V'
:
print_version
();
exit
(
EXIT_SUCCESS
);
case
'p'
:
strncpy
(
pciid_str
,
optarg
,
PCIID_STR_LEN
);
break
;
case
'a'
:
app
=
true
;
break
;
case
'b'
:
base
=
true
;
break
;
case
'v'
:
verbose
++
;
break
;
case
'1'
:
singleline
=
true
;
break
;
}
}
if
(
strlen
(
pciid_str
)
==
0
)
{
fputs
(
"PCI ID is mandatory
\n
"
,
stderr
);
help
();
exit
(
EXIT_FAILURE
);
}
snprintf
(
path
,
128
,
"/sys/bus/pci/devices/%s/resource0"
,
pciid_str
);
fd
=
open
(
path
,
O_RDONLY
);
if
(
fd
<
0
)
{
fprintf
(
stderr
,
"Can't open
\"
%s
\"
: %s
\n
"
,
path
,
strerror
(
errno
));
exit
(
EXIT_FAILURE
);
}
if
(
base
)
err
=
print_base_meta_id
(
fd
);
if
(
app
)
err
=
print_app_meta_id
(
fd
);
close
(
fd
);
exit
(
err
?
EXIT_FAILURE
:
EXIT_SUCCESS
);
}
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