#include <linux/fs.h>
#include <linux/firmware.h>
#include <linux/fpga/fpga-mgr.h>
/* ... ваши существующие функции I2C-транспорта (sysconfig_i2c_...) ... */
/*
* Sysfs callback handler for writing the firmware.
* This function is triggered when you execute: echo file.bit > /sys/bus/i2c/devices/.../load_fpga
*/
static ssize_t load_fpga_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct fpga_csi_bridge_priv *priv = dev_get_drvdata(dev);
struct fpga_image_info *info;
char fw_name[64];
int ret;
if (count == 0 || count >= sizeof(fw_name))
return -EINVAL;
/* Copy the filename and strip the trailing newline character */
strscpy(fw_name, buf, count);
strim(fw_name);
dev_info(dev, "Loading FPGA bitstream file: %s ...\n", fw_name);
/* Allocate image info structure required by modern FPGA Manager API */
info = fpga_image_info_alloc(dev);
if (!info)
return -ENOMEM;
info->firmware_name = fw_name;
/*
* In modern kernels (6.x+), fpga_mgr_load uses fpga_priv.mgr pointer.
* If sysconfig_probe registers it, we find the registered manager.
*/
struct fpga_manager *mgr = __fpga_mgr_get(dev);
if (IS_ERR_OR_NULL(mgr)) {
dev_err(dev, "Could not find registered FPGA Manager instance\n");
fpga_image_info_free(info);
return -ENODEV;
}
/* Trigger the generic architecture-agnostic load sequence */
ret = fpga_mgr_load(mgr, info);
fpga_image_info_free(info);
if (ret) {
dev_err(dev, "FPGA programming failed with error code: %d\n", ret);
return ret;
}
dev_info(dev, "FPGA successfully programmed!\n");
return count;
}
/* Define the custom sysfs attribute named "load_fpga" with write-only permissions */
static DEVICE_ATTR_WO(load_fpga);