Commit 0c4ef6cd authored by Federico Vaga's avatar Federico Vaga Committed by Federico Vaga

drv: make the fpga-mgr code compatible from v4.4 to v5.0

At least it compiles on all of them, but I have tested it only
on v4.14.

For older versions the FPGA manager does not exist but we provide
a backport of it.
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 3fb3a956
......@@ -16,3 +16,4 @@ obj-m := spec.o
spec-objs := spec-core.o
spec-objs += spec-fpga.o
spec-objs += spec-irq.o
spec-objs += spec-compat.o
// 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)
{
int last_word_size = count;
#if KERNEL_VERSION(4,16,0) <= LINUX_VERSION_CODE
if (info)
last_word_size = info->count;
#endif
return last_word_size;
}
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE
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
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;
}
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
// 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
#define compat_fpga_ops_groups .groups = NULL,
#else
#define compat_fpga_ops_groups
#endif
#if KERNEL_VERSION(4,10,0) > LINUX_VERSION_CODE
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
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);
......@@ -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,19 +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);
#if KERNEL_VERSION(4,16,0) > LINUX_VERSION_CODE
err = gn4124_fpga_fcl_init(spec, count & 0x3);
#else
err = gn4124_fpga_fcl_init(spec, info->count & 0x3);
#endif
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;
......@@ -263,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;
......@@ -272,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;
......@@ -296,35 +293,40 @@ static void spec_fpga_remove(struct fpga_manager *mgr)
/* do nothing */
}
static const struct fpga_manager_ops spec_fpga_ops = {
#if KERNEL_VERSION(4,15,0) > LINUX_VERSION_CODE
/* So that we select the buffer size because smaller */
.initial_header_size = 0xFFFFFFFF,
#else
.initial_header_size = 0,
#endif
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,
};
int spec_fpga_init(struct spec_dev *spec)
{
if (!spec)
return -EINVAL;
int err;
return fpga_mgr_register(&spec->dev,
dev_name(&spec->dev),
&spec_fpga_ops, spec);
spec->mgr = compat_fpga_mgr_create(&spec->dev,
dev_name(&spec->dev),
&spec_fpga_ops, spec);
if (!spec || !spec->mgr)
return -EPERM;
err = compat_fpga_mgr_register(spec->mgr);
if (err) {
compat_fpga_mgr_free(spec->mgr);
return err;
}
return 0;
}
void spec_fpga_exit(struct spec_dev *spec)
{
if (!spec)
return;
fpga_mgr_unregister(&spec->dev);
compat_fpga_mgr_unregister(spec->mgr);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment