The CPLD and FPGA driver framework module complies with s3ip sysfs specification (#12891)
Why I did it Provide CPLD and FPGA driver framework that complies with s3ip sysfs specification How I did it 1、 The framework module provides register and unregister interface and implementation. 2、 The framework will help you create the sysfs node How to verify it A demo driver base on this framework will display the sysfs node wich conform to the s3ip sysfs specification
This commit is contained in:
parent
67ced0724c
commit
a2885b31ed
365
platform/s3ip-sysfs/s3ip_sysfs_frame/cpld_sysfs.c
Normal file
365
platform/s3ip-sysfs/s3ip_sysfs_frame/cpld_sysfs.c
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
/*
|
||||||
|
* cpld_sysfs.c
|
||||||
|
*
|
||||||
|
* This module create cpld kobjects and attributes in /sys/s3ip/cpld
|
||||||
|
*
|
||||||
|
* History
|
||||||
|
* [Version] [Date] [Description]
|
||||||
|
* * v1.0 2021-08-31 S3IP sysfs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include "switch.h"
|
||||||
|
#include "cpld_sysfs.h"
|
||||||
|
|
||||||
|
static int g_cpld_loglevel = 0;
|
||||||
|
|
||||||
|
#define CPLD_INFO(fmt, args...) do { \
|
||||||
|
if (g_cpld_loglevel & INFO) { \
|
||||||
|
printk(KERN_INFO "[CPLD_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CPLD_ERR(fmt, args...) do { \
|
||||||
|
if (g_cpld_loglevel & ERR) { \
|
||||||
|
printk(KERN_ERR "[CPLD_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CPLD_DBG(fmt, args...) do { \
|
||||||
|
if (g_cpld_loglevel & DBG) { \
|
||||||
|
printk(KERN_DEBUG "[CPLD_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
struct cpld_obj_s {
|
||||||
|
struct switch_obj *obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpld_s {
|
||||||
|
unsigned int cpld_number;
|
||||||
|
struct cpld_obj_s *cpld;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cpld_s g_cpld;
|
||||||
|
static struct switch_obj *g_cpld_obj = NULL;
|
||||||
|
static struct s3ip_sysfs_cpld_drivers_s *g_cpld_drv = NULL;
|
||||||
|
|
||||||
|
static ssize_t cpld_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_cpld.cpld_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cpld_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int cpld_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_cpld_drv);
|
||||||
|
check_p(g_cpld_drv->get_main_board_cpld_alias);
|
||||||
|
|
||||||
|
cpld_index = obj->index;
|
||||||
|
CPLD_DBG("cpld index: %u\n", cpld_index);
|
||||||
|
ret = g_cpld_drv->get_main_board_cpld_alias(cpld_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
CPLD_ERR("get cpld%u alias failed, ret: %d\n", cpld_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cpld_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int cpld_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_cpld_drv);
|
||||||
|
check_p(g_cpld_drv->get_main_board_cpld_type);
|
||||||
|
|
||||||
|
cpld_index = obj->index;
|
||||||
|
CPLD_DBG("cpld index: %u\n", cpld_index);
|
||||||
|
ret = g_cpld_drv->get_main_board_cpld_type(cpld_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
CPLD_ERR("get cpld%u type failed, ret: %d\n", cpld_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cpld_fw_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int cpld_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_cpld_drv);
|
||||||
|
check_p(g_cpld_drv->get_main_board_cpld_firmware_version);
|
||||||
|
|
||||||
|
cpld_index = obj->index;
|
||||||
|
CPLD_DBG("cpld index: %u\n", cpld_index);
|
||||||
|
ret = g_cpld_drv->get_main_board_cpld_firmware_version(cpld_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
CPLD_ERR("get cpld%u firmware version failed, ret: %d\n", cpld_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cpld_board_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int cpld_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_cpld_drv);
|
||||||
|
check_p(g_cpld_drv->get_main_board_cpld_board_version);
|
||||||
|
|
||||||
|
cpld_index = obj->index;
|
||||||
|
CPLD_DBG("cpld index: %u\n", cpld_index);
|
||||||
|
ret = g_cpld_drv->get_main_board_cpld_board_version(cpld_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
CPLD_ERR("get cpld%u board version failed, ret: %d\n", cpld_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cpld_test_reg_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int cpld_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_cpld_drv);
|
||||||
|
check_p(g_cpld_drv->get_main_board_cpld_test_reg);
|
||||||
|
|
||||||
|
cpld_index = obj->index;
|
||||||
|
CPLD_DBG("cpld index: %u\n", cpld_index);
|
||||||
|
ret = g_cpld_drv->get_main_board_cpld_test_reg(cpld_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
CPLD_ERR("get cpld%u test register failed, ret: %d\n", cpld_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cpld_test_reg_store(struct switch_obj *obj, struct switch_attribute *attr,
|
||||||
|
const char* buf, size_t count)
|
||||||
|
{
|
||||||
|
unsigned int cpld_index, value;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_cpld_drv);
|
||||||
|
check_p(g_cpld_drv->set_main_board_cpld_test_reg);
|
||||||
|
|
||||||
|
cpld_index = obj->index;
|
||||||
|
sscanf(buf, "0x%x", &value);
|
||||||
|
ret = g_cpld_drv->set_main_board_cpld_test_reg(cpld_index, value);
|
||||||
|
if (ret < 0) {
|
||||||
|
CPLD_ERR("set cpld%u test reg failed, value:0x%x, ret: %d.\n", cpld_index, value, ret);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
CPLD_DBG("set cpld%u test reg success, value: 0x%x.\n", cpld_index, value);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************cpld dir and attrs*******************************************/
|
||||||
|
static struct switch_attribute cpld_number_att = __ATTR(number, S_IRUGO, cpld_number_show, NULL);
|
||||||
|
|
||||||
|
static struct attribute *cpld_dir_attrs[] = {
|
||||||
|
&cpld_number_att.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group cpld_root_attr_group = {
|
||||||
|
.attrs = cpld_dir_attrs,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************cpld[1-n] dir and attrs*******************************************/
|
||||||
|
static struct switch_attribute cpld_alias_attr = __ATTR(alias, S_IRUGO, cpld_alias_show, NULL);
|
||||||
|
static struct switch_attribute cpld_type_attr = __ATTR(type, S_IRUGO, cpld_type_show, NULL);
|
||||||
|
static struct switch_attribute cpld_fw_version_attr = __ATTR(firmware_version, S_IRUGO, cpld_fw_version_show, NULL);
|
||||||
|
static struct switch_attribute cpld_board_version_attr = __ATTR(board_version, S_IRUGO, cpld_board_version_show, NULL);
|
||||||
|
static struct switch_attribute cpld_test_reg_attr = __ATTR(reg_test, S_IRUGO | S_IWUSR, cpld_test_reg_show, cpld_test_reg_store);
|
||||||
|
|
||||||
|
static struct attribute *cpld_attrs[] = {
|
||||||
|
&cpld_alias_attr.attr,
|
||||||
|
&cpld_type_attr.attr,
|
||||||
|
&cpld_fw_version_attr.attr,
|
||||||
|
&cpld_board_version_attr.attr,
|
||||||
|
&cpld_test_reg_attr.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group cpld_attr_group = {
|
||||||
|
.attrs = cpld_attrs,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int cpld_sub_single_remove_kobj_and_attrs(unsigned int index)
|
||||||
|
{
|
||||||
|
struct cpld_obj_s *curr_cpld;
|
||||||
|
|
||||||
|
curr_cpld = &g_cpld.cpld[index - 1];
|
||||||
|
if (curr_cpld->obj) {
|
||||||
|
sysfs_remove_group(&curr_cpld->obj->kobj, &cpld_attr_group);
|
||||||
|
switch_kobject_delete(&curr_cpld->obj);
|
||||||
|
CPLD_DBG("delete cpld%u dir and attrs success.\n", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpld_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
|
||||||
|
{
|
||||||
|
char name[8];
|
||||||
|
struct cpld_obj_s *curr_cpld;
|
||||||
|
|
||||||
|
curr_cpld = &g_cpld.cpld[index - 1];
|
||||||
|
memset(name, 0, sizeof(name));
|
||||||
|
snprintf(name, sizeof(name), "cpld%u", index);
|
||||||
|
curr_cpld->obj = switch_kobject_create(name, parent);
|
||||||
|
if (!curr_cpld->obj) {
|
||||||
|
CPLD_ERR("create %s object error!\n", name);
|
||||||
|
return -EBADRQC;
|
||||||
|
}
|
||||||
|
curr_cpld->obj->index = index;
|
||||||
|
if (sysfs_create_group(&curr_cpld->obj->kobj, &cpld_attr_group) != 0) {
|
||||||
|
CPLD_ERR("create %s attrs error.\n", name);
|
||||||
|
switch_kobject_delete(&curr_cpld->obj);
|
||||||
|
return -EBADRQC;
|
||||||
|
}
|
||||||
|
CPLD_DBG("create %s dir and attrs success.\n", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpld_sub_create_kobj_and_attrs(struct kobject *parent, int cpld_num)
|
||||||
|
{
|
||||||
|
unsigned int cpld_index, i;
|
||||||
|
|
||||||
|
g_cpld.cpld = kzalloc(sizeof(struct cpld_obj_s) * cpld_num, GFP_KERNEL);
|
||||||
|
if (!g_cpld.cpld) {
|
||||||
|
CPLD_ERR("kzalloc g_cpld.cpld error, cpld number = %d.\n", cpld_num);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(cpld_index = 1; cpld_index <= cpld_num; cpld_index++) {
|
||||||
|
if(cpld_sub_single_create_kobj_and_attrs(parent, cpld_index) != 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
for(i = cpld_index; i > 0; i--) {
|
||||||
|
cpld_sub_single_remove_kobj_and_attrs(i);
|
||||||
|
}
|
||||||
|
kfree(g_cpld.cpld);
|
||||||
|
g_cpld.cpld = NULL;
|
||||||
|
return -EBADRQC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create cpld[1-n] directory and attributes*/
|
||||||
|
static int cpld_sub_create(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = cpld_sub_create_kobj_and_attrs(&g_cpld_obj->kobj, g_cpld.cpld_number);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete cpld[1-n] directory and attributes*/
|
||||||
|
static void cpld_sub_remove(void)
|
||||||
|
{
|
||||||
|
unsigned int cpld_index;
|
||||||
|
|
||||||
|
if (g_cpld.cpld) {
|
||||||
|
for (cpld_index = g_cpld.cpld_number; cpld_index > 0; cpld_index--) {
|
||||||
|
cpld_sub_single_remove_kobj_and_attrs(cpld_index);
|
||||||
|
}
|
||||||
|
kfree(g_cpld.cpld);
|
||||||
|
g_cpld.cpld = NULL;
|
||||||
|
}
|
||||||
|
g_cpld.cpld_number = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create cpld directory and number attributes */
|
||||||
|
static int cpld_root_create(void)
|
||||||
|
{
|
||||||
|
g_cpld_obj = switch_kobject_create("cpld", NULL);
|
||||||
|
if (!g_cpld_obj) {
|
||||||
|
CPLD_ERR("switch_kobject_create cpld error!\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysfs_create_group(&g_cpld_obj->kobj, &cpld_root_attr_group) != 0) {
|
||||||
|
switch_kobject_delete(&g_cpld_obj);
|
||||||
|
CPLD_ERR("create cpld dir attrs error!\n");
|
||||||
|
return -EBADRQC;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete cpld directory and number attributes */
|
||||||
|
static void cpld_root_remove(void)
|
||||||
|
{
|
||||||
|
if (g_cpld_obj) {
|
||||||
|
sysfs_remove_group(&g_cpld_obj->kobj, &cpld_root_attr_group);
|
||||||
|
switch_kobject_delete(&g_cpld_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int s3ip_sysfs_cpld_drivers_register(struct s3ip_sysfs_cpld_drivers_s *drv)
|
||||||
|
{
|
||||||
|
int ret, cpld_num;
|
||||||
|
|
||||||
|
CPLD_INFO("s3ip_sysfs_cpld_drivers_register...\n");
|
||||||
|
if (g_cpld_drv) {
|
||||||
|
CPLD_ERR("g_cpld_drv is not NULL, can't register\n");
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_p(drv);
|
||||||
|
check_p(drv->get_main_board_cpld_number);
|
||||||
|
g_cpld_drv = drv;
|
||||||
|
|
||||||
|
cpld_num = g_cpld_drv->get_main_board_cpld_number();
|
||||||
|
if (cpld_num <= 0) {
|
||||||
|
CPLD_ERR("cpld number: %d, don't need to create cpld dirs and attrs.\n", cpld_num);
|
||||||
|
g_cpld_drv = NULL;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&g_cpld, 0, sizeof(struct cpld_s));
|
||||||
|
g_cpld.cpld_number = cpld_num;
|
||||||
|
ret = cpld_root_create();
|
||||||
|
if (ret < 0) {
|
||||||
|
CPLD_ERR("create cpld root dir and attrs failed, ret: %d\n", ret);
|
||||||
|
g_cpld_drv = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = cpld_sub_create();
|
||||||
|
if (ret < 0) {
|
||||||
|
CPLD_ERR("create cpld sub dir and attrs failed, ret: %d\n", ret);
|
||||||
|
cpld_root_remove();
|
||||||
|
g_cpld_drv = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
CPLD_INFO("s3ip_sysfs_cpld_drivers_register success\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s3ip_sysfs_cpld_drivers_unregister(void)
|
||||||
|
{
|
||||||
|
if (g_cpld_drv) {
|
||||||
|
cpld_sub_remove();
|
||||||
|
cpld_root_remove();
|
||||||
|
g_cpld_drv = NULL;
|
||||||
|
CPLD_DBG("s3ip_sysfs_cpld_drivers_unregister success.\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(s3ip_sysfs_cpld_drivers_register);
|
||||||
|
EXPORT_SYMBOL(s3ip_sysfs_cpld_drivers_unregister);
|
||||||
|
module_param(g_cpld_loglevel, int, 0644);
|
||||||
|
MODULE_PARM_DESC(g_cpld_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
|
366
platform/s3ip-sysfs/s3ip_sysfs_frame/fpga_sysfs.c
Normal file
366
platform/s3ip-sysfs/s3ip_sysfs_frame/fpga_sysfs.c
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
/*
|
||||||
|
* fpga_sysfs.c
|
||||||
|
*
|
||||||
|
* This module create fpga kobjects and attributes in /sys/s3ip/fpga
|
||||||
|
*
|
||||||
|
* History
|
||||||
|
* [Version] [Date] [Description]
|
||||||
|
* * v1.0 2021-08-31 S3IP sysfs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include "switch.h"
|
||||||
|
#include "fpga_sysfs.h"
|
||||||
|
|
||||||
|
static int g_fpga_loglevel = 0;
|
||||||
|
|
||||||
|
#define FPGA_INFO(fmt, args...) do { \
|
||||||
|
if (g_fpga_loglevel & INFO) { \
|
||||||
|
printk(KERN_INFO "[FPGA_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define FPGA_ERR(fmt, args...) do { \
|
||||||
|
if (g_fpga_loglevel & ERR) { \
|
||||||
|
printk(KERN_ERR "[FPGA_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define FPGA_DBG(fmt, args...) do { \
|
||||||
|
if (g_fpga_loglevel & DBG) { \
|
||||||
|
printk(KERN_DEBUG "[FPGA_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
struct fpga_obj_s {
|
||||||
|
struct switch_obj *obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fpga_s {
|
||||||
|
unsigned int fpga_number;
|
||||||
|
struct fpga_obj_s *fpga;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct fpga_s g_fpga;
|
||||||
|
static struct switch_obj *g_fpga_obj = NULL;
|
||||||
|
static struct s3ip_sysfs_fpga_drivers_s *g_fpga_drv = NULL;
|
||||||
|
|
||||||
|
static ssize_t fpga_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_fpga.fpga_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fpga_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int fpga_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_fpga_drv);
|
||||||
|
check_p(g_fpga_drv->get_main_board_fpga_alias);
|
||||||
|
|
||||||
|
fpga_index = obj->index;
|
||||||
|
FPGA_DBG("fpga index: %u\n", fpga_index);
|
||||||
|
ret = g_fpga_drv->get_main_board_fpga_alias(fpga_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
FPGA_ERR("get fpga%u alias failed, ret: %d\n", fpga_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fpga_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int fpga_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_fpga_drv);
|
||||||
|
check_p(g_fpga_drv->get_main_board_fpga_type);
|
||||||
|
|
||||||
|
fpga_index = obj->index;
|
||||||
|
FPGA_DBG("fpga index: %u\n", fpga_index);
|
||||||
|
ret = g_fpga_drv->get_main_board_fpga_type(fpga_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
FPGA_ERR("get fpga%u type failed, ret: %d\n", fpga_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fpga_fw_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int fpga_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_fpga_drv);
|
||||||
|
check_p(g_fpga_drv->get_main_board_fpga_firmware_version);
|
||||||
|
|
||||||
|
fpga_index = obj->index;
|
||||||
|
FPGA_DBG("fpga index: %u\n", fpga_index);
|
||||||
|
ret = g_fpga_drv->get_main_board_fpga_firmware_version(fpga_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
FPGA_ERR("get fpga%u firmware version failed, ret: %d\n", fpga_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fpga_board_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int fpga_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_fpga_drv);
|
||||||
|
check_p(g_fpga_drv->get_main_board_fpga_board_version);
|
||||||
|
|
||||||
|
fpga_index = obj->index;
|
||||||
|
FPGA_DBG("fpga index: %u\n", fpga_index);
|
||||||
|
ret = g_fpga_drv->get_main_board_fpga_board_version(fpga_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
FPGA_ERR("get fpga%u board version failed, ret: %d\n", fpga_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fpga_test_reg_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int fpga_index;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_fpga_drv);
|
||||||
|
check_p(g_fpga_drv->get_main_board_fpga_test_reg);
|
||||||
|
|
||||||
|
fpga_index = obj->index;
|
||||||
|
FPGA_DBG("fpga index: %u\n", fpga_index);
|
||||||
|
ret = g_fpga_drv->get_main_board_fpga_test_reg(fpga_index, buf, PAGE_SIZE);
|
||||||
|
if (ret < 0) {
|
||||||
|
FPGA_ERR("get fpga%u test register failed, ret: %d\n", fpga_index, ret);
|
||||||
|
return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SYSFS_DEV_ERROR);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fpga_test_reg_store(struct switch_obj *obj, struct switch_attribute *attr,
|
||||||
|
const char* buf, size_t count)
|
||||||
|
{
|
||||||
|
unsigned int fpga_index, value;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
check_p(g_fpga_drv);
|
||||||
|
check_p(g_fpga_drv->set_main_board_fpga_test_reg);
|
||||||
|
|
||||||
|
fpga_index = obj->index;
|
||||||
|
sscanf(buf, "0x%x", &value);
|
||||||
|
ret = g_fpga_drv->set_main_board_fpga_test_reg(fpga_index, value);
|
||||||
|
if (ret < 0) {
|
||||||
|
FPGA_ERR("set fpga%u test reg failed, value:0x%x, ret: %d.\n", fpga_index, value, ret);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
FPGA_DBG("set fpga%u test reg success, value: 0x%x.\n", fpga_index, value);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************fpga dir and attrs*******************************************/
|
||||||
|
static struct switch_attribute fpga_number_att = __ATTR(number, S_IRUGO, fpga_number_show, NULL);
|
||||||
|
|
||||||
|
static struct attribute *fpga_dir_attrs[] = {
|
||||||
|
&fpga_number_att.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group fpga_root_attr_group = {
|
||||||
|
.attrs = fpga_dir_attrs,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*******************************fpga[1-n] dir and attrs*******************************************/
|
||||||
|
static struct switch_attribute fpga_alias_attr = __ATTR(alias, S_IRUGO, fpga_alias_show, NULL);
|
||||||
|
static struct switch_attribute fpga_type_attr = __ATTR(type, S_IRUGO, fpga_type_show, NULL);
|
||||||
|
static struct switch_attribute fpga_fw_version_attr = __ATTR(firmware_version, S_IRUGO, fpga_fw_version_show, NULL);
|
||||||
|
static struct switch_attribute fpga_board_version_attr = __ATTR(board_version, S_IRUGO, fpga_board_version_show, NULL);
|
||||||
|
static struct switch_attribute fpga_test_reg_attr = __ATTR(reg_test, S_IRUGO | S_IWUSR, fpga_test_reg_show, fpga_test_reg_store);
|
||||||
|
|
||||||
|
static struct attribute *fpga_attrs[] = {
|
||||||
|
&fpga_alias_attr.attr,
|
||||||
|
&fpga_type_attr.attr,
|
||||||
|
&fpga_fw_version_attr.attr,
|
||||||
|
&fpga_board_version_attr.attr,
|
||||||
|
&fpga_test_reg_attr.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group fpga_attr_group = {
|
||||||
|
.attrs = fpga_attrs,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int fpga_sub_single_remove_kobj_and_attrs(unsigned int index)
|
||||||
|
{
|
||||||
|
struct fpga_obj_s *curr_fpga;
|
||||||
|
|
||||||
|
curr_fpga = &g_fpga.fpga[index - 1];
|
||||||
|
if (curr_fpga->obj) {
|
||||||
|
sysfs_remove_group(&curr_fpga->obj->kobj, &fpga_attr_group);
|
||||||
|
switch_kobject_delete(&curr_fpga->obj);
|
||||||
|
FPGA_DBG("delete fpga%u dir and attrs success.\n", index);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fpga_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
|
||||||
|
{
|
||||||
|
char name[8];
|
||||||
|
struct fpga_obj_s *curr_fpga;
|
||||||
|
|
||||||
|
curr_fpga = &g_fpga.fpga[index - 1];
|
||||||
|
memset(name, 0, sizeof(name));
|
||||||
|
snprintf(name, sizeof(name), "fpga%u", index);
|
||||||
|
curr_fpga->obj = switch_kobject_create(name, parent);
|
||||||
|
if (!curr_fpga->obj) {
|
||||||
|
FPGA_ERR("create %s object error!\n", name);
|
||||||
|
return -EBADRQC;
|
||||||
|
}
|
||||||
|
curr_fpga->obj->index = index;
|
||||||
|
if (sysfs_create_group(&curr_fpga->obj->kobj, &fpga_attr_group) != 0) {
|
||||||
|
FPGA_ERR("create %s attrs error.\n", name);
|
||||||
|
switch_kobject_delete(&curr_fpga->obj);
|
||||||
|
return -EBADRQC;
|
||||||
|
}
|
||||||
|
FPGA_DBG("create %s dir and attrs success.\n", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fpga_sub_create_kobj_and_attrs(struct kobject *parent, int fpga_num)
|
||||||
|
{
|
||||||
|
unsigned int fpga_index, i;
|
||||||
|
|
||||||
|
g_fpga.fpga = kzalloc(sizeof(struct fpga_obj_s) * fpga_num, GFP_KERNEL);
|
||||||
|
if (!g_fpga.fpga) {
|
||||||
|
FPGA_ERR("kzalloc g_fpga.fpga error, fpga number = %d.\n", fpga_num);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(fpga_index = 1; fpga_index <= fpga_num; fpga_index++) {
|
||||||
|
if(fpga_sub_single_create_kobj_and_attrs(parent, fpga_index) != 0 ) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
for(i = fpga_index; i > 0; i--) {
|
||||||
|
fpga_sub_single_remove_kobj_and_attrs(i);
|
||||||
|
}
|
||||||
|
kfree(g_fpga.fpga);
|
||||||
|
g_fpga.fpga = NULL;
|
||||||
|
return -EBADRQC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create fpga[1-n] directory and attributes*/
|
||||||
|
static int fpga_sub_create(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = fpga_sub_create_kobj_and_attrs(&g_fpga_obj->kobj, g_fpga.fpga_number);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete fpga[1-n] directory and attributes*/
|
||||||
|
static void fpga_sub_remove(void)
|
||||||
|
{
|
||||||
|
unsigned int fpga_index;
|
||||||
|
|
||||||
|
if (g_fpga.fpga) {
|
||||||
|
for (fpga_index = g_fpga.fpga_number; fpga_index > 0; fpga_index--) {
|
||||||
|
fpga_sub_single_remove_kobj_and_attrs(fpga_index);
|
||||||
|
}
|
||||||
|
kfree(g_fpga.fpga);
|
||||||
|
g_fpga.fpga = NULL;
|
||||||
|
}
|
||||||
|
g_fpga.fpga_number = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create fpga directory and number attributes */
|
||||||
|
static int fpga_root_create(void)
|
||||||
|
{
|
||||||
|
g_fpga_obj = switch_kobject_create("fpga", NULL);
|
||||||
|
if (!g_fpga_obj) {
|
||||||
|
FPGA_ERR("switch_kobject_create fpga error!\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysfs_create_group(&g_fpga_obj->kobj, &fpga_root_attr_group) != 0) {
|
||||||
|
switch_kobject_delete(&g_fpga_obj);
|
||||||
|
FPGA_ERR("create fpga dir attrs error!\n");
|
||||||
|
return -EBADRQC;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete fpga directory and number attributes */
|
||||||
|
static void fpga_root_remove(void)
|
||||||
|
{
|
||||||
|
if (g_fpga_obj) {
|
||||||
|
sysfs_remove_group(&g_fpga_obj->kobj, &fpga_root_attr_group);
|
||||||
|
switch_kobject_delete(&g_fpga_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int s3ip_sysfs_fpga_drivers_register(struct s3ip_sysfs_fpga_drivers_s *drv)
|
||||||
|
{
|
||||||
|
int ret, fpga_num;
|
||||||
|
|
||||||
|
FPGA_INFO("s3ip_sysfs_fpga_drivers_register...\n");
|
||||||
|
if (g_fpga_drv) {
|
||||||
|
FPGA_ERR("g_fpga_drv is not NULL, can't register\n");
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_p(drv);
|
||||||
|
check_p(drv->get_main_board_fpga_number);
|
||||||
|
g_fpga_drv = drv;
|
||||||
|
|
||||||
|
fpga_num = g_fpga_drv->get_main_board_fpga_number();
|
||||||
|
if (fpga_num <= 0) {
|
||||||
|
FPGA_ERR("fpga number: %d, don't need to create fpga dirs and attrs.\n", fpga_num);
|
||||||
|
g_fpga_drv = NULL;
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&g_fpga, 0, sizeof(struct fpga_s));
|
||||||
|
g_fpga.fpga_number = fpga_num;
|
||||||
|
ret = fpga_root_create();
|
||||||
|
if (ret < 0) {
|
||||||
|
FPGA_ERR("create fpga root dir and attrs failed, ret: %d\n", ret);
|
||||||
|
g_fpga_drv = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = fpga_sub_create();
|
||||||
|
if (ret < 0) {
|
||||||
|
FPGA_ERR("create fpga sub dir and attrs failed, ret: %d\n", ret);
|
||||||
|
fpga_root_remove();
|
||||||
|
g_fpga_drv = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
FPGA_INFO("s3ip_sysfs_fpga_drivers_register success\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s3ip_sysfs_fpga_drivers_unregister(void)
|
||||||
|
{
|
||||||
|
if (g_fpga_drv) {
|
||||||
|
fpga_sub_remove();
|
||||||
|
fpga_root_remove();
|
||||||
|
g_fpga_drv = NULL;
|
||||||
|
FPGA_DBG("s3ip_sysfs_fpga_drivers_unregister success.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(s3ip_sysfs_fpga_drivers_register);
|
||||||
|
EXPORT_SYMBOL(s3ip_sysfs_fpga_drivers_unregister);
|
||||||
|
module_param(g_fpga_loglevel, int, 0644);
|
||||||
|
MODULE_PARM_DESC(g_fpga_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
|
||||||
|
|
16
platform/s3ip-sysfs/s3ip_sysfs_frame/include/cpld_sysfs.h
Normal file
16
platform/s3ip-sysfs/s3ip_sysfs_frame/include/cpld_sysfs.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _CPLD_SYSFS_H_
|
||||||
|
#define _CPLD_SYSFS_H_
|
||||||
|
|
||||||
|
struct s3ip_sysfs_cpld_drivers_s {
|
||||||
|
int (*get_main_board_cpld_number)(void);
|
||||||
|
ssize_t (*get_main_board_cpld_alias)(unsigned int cpld_index, char *buf, size_t count);
|
||||||
|
ssize_t (*get_main_board_cpld_type)(unsigned int cpld_index, char *buf, size_t count);
|
||||||
|
ssize_t (*get_main_board_cpld_firmware_version)(unsigned int cpld_index, char *buf, size_t count);
|
||||||
|
ssize_t (*get_main_board_cpld_board_version)(unsigned int cpld_index, char *buf, size_t count);
|
||||||
|
ssize_t (*get_main_board_cpld_test_reg)(unsigned int cpld_index, char *buf, size_t count);
|
||||||
|
int (*set_main_board_cpld_test_reg)(unsigned int cpld_index, unsigned int value);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int s3ip_sysfs_cpld_drivers_register(struct s3ip_sysfs_cpld_drivers_s *drv);
|
||||||
|
extern void s3ip_sysfs_cpld_drivers_unregister(void);
|
||||||
|
#endif /*_CPLD_SYSFS_H_ */
|
16
platform/s3ip-sysfs/s3ip_sysfs_frame/include/fpga_sysfs.h
Normal file
16
platform/s3ip-sysfs/s3ip_sysfs_frame/include/fpga_sysfs.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _FPGA_SYSFS_H_
|
||||||
|
#define _FPGA_SYSFS_H_
|
||||||
|
|
||||||
|
struct s3ip_sysfs_fpga_drivers_s {
|
||||||
|
int (*get_main_board_fpga_number)(void);
|
||||||
|
ssize_t (*get_main_board_fpga_alias)(unsigned int fpga_index, char *buf, size_t count);
|
||||||
|
ssize_t (*get_main_board_fpga_type)(unsigned int fpga_index, char *buf, size_t count);
|
||||||
|
ssize_t (*get_main_board_fpga_firmware_version)(unsigned int fpga_index, char *buf, size_t count);
|
||||||
|
ssize_t (*get_main_board_fpga_board_version)(unsigned int fpga_index, char *buf, size_t count);
|
||||||
|
ssize_t (*get_main_board_fpga_test_reg)(unsigned int fpga_index, char *buf, size_t count);
|
||||||
|
int (*set_main_board_fpga_test_reg)(unsigned int fpga_index, unsigned int value);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int s3ip_sysfs_fpga_drivers_register(struct s3ip_sysfs_fpga_drivers_s *drv);
|
||||||
|
extern void s3ip_sysfs_fpga_drivers_unregister(void);
|
||||||
|
#endif /*_FPGA_SYSFS_H_ */
|
Loading…
Reference in New Issue
Block a user