FPGA 管理器¶
概述¶
FPGA 管理器核心导出了一组用于使用映像编程 FPGA 的函数。该 API 与制造商无关。 所有制造商的特殊性都隐藏在底层驱动程序中,该驱动程序向核心注册一组操作。 FPGA 映像数据本身非常特定于制造商,但就我们的目的而言,它只是二进制数据。 FPGA 管理器核心不会解析它。
要编程的 FPGA 映像可以在散布/聚集列表中、单个连续缓冲区中或固件文件中。 因为应避免为缓冲区分配连续的内核内存,因此建议用户尽可能改用散布/聚集列表。
编程映像的详细信息显示在一个结构体 (struct fpga_image_info
) 中。 此结构体包含诸如指向 FPGA 映像的指针以及映像特定的详细信息(例如映像是为完全还是部分重新配置而构建的)之类的参数。
如何支持新的 FPGA 设备¶
要添加另一个 FPGA 管理器,请编写一个实现一组操作的驱动程序。 probe 函数调用 fpga_mgr_register()
或 fpga_mgr_register_full()
,例如
static const struct fpga_manager_ops socfpga_fpga_ops = {
.write_init = socfpga_fpga_ops_configure_init,
.write = socfpga_fpga_ops_configure_write,
.write_complete = socfpga_fpga_ops_configure_complete,
.state = socfpga_fpga_ops_state,
};
static int socfpga_fpga_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct socfpga_fpga_priv *priv;
struct fpga_manager *mgr;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
/*
* do ioremaps, get interrupts, etc. and save
* them in priv
*/
mgr = fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
&socfpga_fpga_ops, priv);
if (IS_ERR(mgr))
return PTR_ERR(mgr);
platform_set_drvdata(pdev, mgr);
return 0;
}
static int socfpga_fpga_remove(struct platform_device *pdev)
{
struct fpga_manager *mgr = platform_get_drvdata(pdev);
fpga_mgr_unregister(mgr);
return 0;
}
或者,probe 函数可以调用资源管理的注册函数之一 devm_fpga_mgr_register()
或 devm_fpga_mgr_register_full()
。 使用这些函数时,参数语法相同,但应删除对 fpga_mgr_unregister()
的调用。 在上面的示例中,不需要 socfpga_fpga_remove()
函数。
这些操作将实现所需的任何设备特定寄存器写入,以执行此特定 FPGA 的编程序列。 这些操作成功时返回 0,否则返回负错误代码。
- 编程序列为:
.parse_header(可选,可以调用一次或多次)
.write_init
.write 或 .write_sg(可以调用一次或多次)
.write_complete
.parse_header 函数会将 header_size 和 data_size 设置为 struct fpga_image_info
。 在 parse_header 调用之前,header_size 会使用 initial_header_size 初始化。 如果 fpga_manager_ops 的标志 skip_header 为 true,则 .write 函数将获取从头 header_size 偏移量开始的映像缓冲区。 如果设置了 data_size,则 .write 函数将获取映像缓冲区的 data_size 个字节,否则 .write 将获取数据直到映像缓冲区的末尾。 这不会影响 .write_sg,.write_sg 仍将以 sg_table 形式获取整个映像。 如果 FPGA 映像已映射为单个连续缓冲区,则整个缓冲区将传递到 .parse_header。 如果映像采用散布-聚集形式,则核心代码将在第一次调用 .parse_header 之前缓冲至少 .initial_header_size,如果这不够,则 .parse_header 应将所需大小设置为 info->header_size 并返回 -EAGAIN,然后将再次使用输入端上的较大映像缓冲区调用它。
.write_init 函数将准备 FPGA 以接收映像数据。 传递到 .write_init 的缓冲区将至少为 info->header_size 字节长;如果整个比特流不可立即使用,则核心代码将在启动之前缓冲至少这么多。
.write 函数将缓冲区写入 FPGA。 该缓冲区可能包含整个 FPGA 映像,也可能包含 FPGA 映像的较小块。 在后一种情况下,会为连续块多次调用此函数。 此接口适用于使用 PIO 的驱动程序。
.write_sg 版本的行为与 .write 相同,只是输入是 sg_table 散布列表。 此接口适用于使用 DMA 的驱动程序。
.write_complete 函数在所有映像都已写入后调用,以使 FPGA 进入运行模式。
这些操作包括一个 .state 函数,该函数将确定 FPGA 所处的状态,并返回 enum fpga_mgr_states
类型的代码。 它不会导致状态更改。
用于实现新的 FPGA 管理器驱动程序的 API¶
fpga_mgr_states
- fpga_manager->state 的值。struct fpga_manager
- FPGA 管理器结构体struct fpga_manager_ops
- 底层 FPGA 管理器驱动程序操作struct fpga_manager_info
- fpga_mgr_register_full() 的参数结构体__fpga_mgr_register_full()
- 创建并注册 FPGA 管理器,使用 fpga_mgr_info 结构体来提供选项的全部灵活性__fpga_mgr_register()
- 创建并注册 FPGA 管理器,使用标准参数__devm_fpga_mgr_register_full()
-__fpga_mgr_register_full()
的资源管理版本fpga_mgr_unregister()
- 注销 FPGA 管理器
辅助宏 fpga_mgr_register_full()
、fpga_mgr_register()
、devm_fpga_mgr_register_full()
和 devm_fpga_mgr_register()
可用于简化注册。
-
enum fpga_mgr_states¶
fpga 框架状态
常量
FPGA_MGR_STATE_UNKNOWN
无法确定状态
FPGA_MGR_STATE_POWER_OFF
FPGA 电源已关闭
FPGA_MGR_STATE_POWER_UP
FPGA 报告电源已开启
FPGA_MGR_STATE_RESET
FPGA 处于复位状态
FPGA_MGR_STATE_FIRMWARE_REQ
固件请求正在进行中
FPGA_MGR_STATE_FIRMWARE_REQ_ERR
固件请求失败
FPGA_MGR_STATE_PARSE_HEADER
解析 FPGA 映像标头
FPGA_MGR_STATE_PARSE_HEADER_ERR
PARSE_HEADER 阶段期间出错
FPGA_MGR_STATE_WRITE_INIT
准备 FPGA 进行编程
FPGA_MGR_STATE_WRITE_INIT_ERR
WRITE_INIT 阶段期间出错
FPGA_MGR_STATE_WRITE
将映像写入 FPGA
FPGA_MGR_STATE_WRITE_ERR
写入 FPGA 时出错
FPGA_MGR_STATE_WRITE_COMPLETE
执行编程后步骤
FPGA_MGR_STATE_WRITE_COMPLETE_ERR
WRITE_COMPLETE 期间出错
FPGA_MGR_STATE_OPERATING
FPGA 已编程并正在运行
-
struct fpga_manager¶
fpga 管理器结构体
定义:
struct fpga_manager {
const char *name;
struct device dev;
struct mutex ref_mutex;
enum fpga_mgr_states state;
struct fpga_compat_id *compat_id;
const struct fpga_manager_ops *mops;
struct module *mops_owner;
void *priv;
};
成员
name
底层 fpga 管理器的名称
dev
fpga 管理器设备
ref_mutex
仅允许对 fpga 管理器的一个引用
state
fpga 管理器的状态
compat_id
用于兼容性检查的 FPGA 管理器 ID。
mops
指向 fpga 管理器操作结构体的指针
mops_owner
包含 mops 的模块
priv
底层驱动程序私有日期
-
struct fpga_manager_ops¶
底层 fpga 管理器驱动程序的操作
定义:
struct fpga_manager_ops {
size_t initial_header_size;
bool skip_header;
enum fpga_mgr_states (*state)(struct fpga_manager *mgr);
u64 (*status)(struct fpga_manager *mgr);
int (*parse_header)(struct fpga_manager *mgr,struct fpga_image_info *info, const char *buf, size_t count);
int (*write_init)(struct fpga_manager *mgr,struct fpga_image_info *info, const char *buf, size_t count);
int (*write)(struct fpga_manager *mgr, const char *buf, size_t count);
int (*write_sg)(struct fpga_manager *mgr, struct sg_table *sgt);
int (*write_complete)(struct fpga_manager *mgr, struct fpga_image_info *info);
void (*fpga_remove)(struct fpga_manager *mgr);
const struct attribute_group **groups;
};
成员
initial_header_size
应传递到 parse_header 和 write_init 的最小字节数。
skip_header
bool 标志,用于告诉 fpga-mgr 核心在调用写入回调时是否应跳过映像开头的 info->header_size 部分。
state
返回 FPGA 状态的枚举值
status
返回 FPGA 的状态,包括重新配置错误代码
parse_header
解析 FPGA 映像标头以设置 info->header_size 和 info->data_size。 如果输入缓冲区不够大,请将所需大小设置为 info->header_size 并返回 -EAGAIN。
write_init
准备 FPGA 以接收配置数据
write
将 count 个字节的配置数据写入 FPGA
write_sg
将配置数据的散布列表写入 FPGA
write_complete
写入完成后,将 FPGA 设置为运行状态
fpga_remove
可选:在驱动程序移除期间将 FPGA 设置为特定状态
groups
可选的属性组。
描述
fpga_manager_ops 是由特定的 fpga 管理器驱动程序实现的底层函数。 可选的函数在调用之前会测试是否为 NULL,因此省略它们是可以的。
-
struct fpga_manager_info¶
FPGA 管理器的参数集合
定义:
struct fpga_manager_info {
const char *name;
struct fpga_compat_id *compat_id;
const struct fpga_manager_ops *mops;
void *priv;
};
成员
name
fpga 管理器名称
compat_id
用于兼容性检查的 FPGA 管理器 ID。
mops
指向 fpga 管理器操作结构体的指针
priv
fpga 管理器私有数据
描述
fpga_manager_info 包含 register_full 函数的参数。 这些参数被分成一个 info 结构体,因为它们中的一些是可选的,而其他的可能会在将来被添加。 info 结构体有助于维护稳定的 API。
-
struct fpga_manager *__fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info, struct module *owner)¶
创建并注册 FPGA 管理器设备
参数
struct device *parent
来自 pdev 的 fpga 管理器设备
const struct fpga_manager_info *info
fpga 管理器的参数
struct module *owner
包含操作的 owner 模块
描述
此函数的调用者负责调用 fpga_mgr_unregister()
。 建议改用 devm_fpga_mgr_register_full()。
返回
指向 struct fpga_manager
指针的指针,或者 ERR_PTR()
-
struct fpga_manager *__fpga_mgr_register(struct device *parent, const char *name, const struct fpga_manager_ops *mops, void *priv, struct module *owner)¶
创建并注册 FPGA 管理器设备
参数
struct device *parent
来自 pdev 的 fpga 管理器设备
const char *name
fpga 管理器名称
const struct fpga_manager_ops *mops
指向 fpga 管理器操作结构体的指针
void *priv
fpga 管理器私有数据
struct module *owner
包含操作的 owner 模块
描述
此函数的调用者负责调用 fpga_mgr_unregister()
。 建议改用 devm_fpga_mgr_register()。 此简单版本的注册函数应足以满足大多数用户的需求。 fpga_mgr_register_full() 函数可用于需要传递其他可选参数的用户。
返回
指向 struct fpga_manager
指针的指针,或者 ERR_PTR()
-
struct fpga_manager *__devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info, struct module *owner)¶
fpga_mgr_register() 的资源管理变体
参数
struct device *parent
来自 pdev 的 fpga 管理器设备
const struct fpga_manager_info *info
fpga 管理器的参数
struct module *owner
包含操作的 owner 模块
返回
成功时返回 FPGA 管理器指针,否则返回负的错误代码。
描述
这是 fpga_mgr_register_full() 的 devres 变体,当管理设备分离时,将自动调用注销函数。
-
struct fpga_manager *__devm_fpga_mgr_register(struct device *parent, const char *name, const struct fpga_manager_ops *mops, void *priv, struct module *owner)¶
fpga_mgr_register() 的资源管理变体
参数
struct device *parent
来自 pdev 的 fpga 管理器设备
const char *name
fpga 管理器名称
const struct fpga_manager_ops *mops
指向 fpga 管理器操作结构体的指针
void *priv
fpga 管理器私有数据
struct module *owner
包含操作的 owner 模块
返回
成功时返回 FPGA 管理器指针,否则返回负的错误代码。
描述
这是 fpga_mgr_register() 的 devres 变体,当管理设备分离时,将自动调用注销函数。
-
void fpga_mgr_unregister(struct fpga_manager *mgr)¶
注销一个 FPGA 管理器
参数
struct fpga_manager *mgr
FPGA 管理器结构体
描述
此函数旨在用于 FPGA 管理器驱动程序的 remove 函数中。