Skip to content

Commit 2408a65

Browse files
IGNORE THIS COMMENT: [PDDF] multifpgapci gpio module (PR #23669)
1 parent 7e1aef8 commit 2408a65

File tree

10 files changed

+532
-25
lines changed

10 files changed

+532
-25
lines changed

platform/pddf/i2c/debian/rules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-pddf
1919
KVERSION ?= $(shell uname -r)
2020
KERNEL_SRC := /lib/modules/$(KVERSION)
2121
MOD_SRC_DIR:= $(shell pwd)
22-
MODULE_DIRS:= client cpld cpld/driver cpldmux cpldmux/driver fpgai2c fpgai2c/driver fpgapci fpgapci/driver fpgapci/algos multifpgapci multifpgapci/driver multifpgapci/i2c fan fan/driver mux gpio led psu psu/driver sysstatus xcvr xcvr/driver
22+
MODULE_DIRS:= client cpld cpld/driver cpldmux cpldmux/driver fpgai2c fpgai2c/driver fpgapci fpgapci/driver fpgapci/algos multifpgapci multifpgapci/driver multifpgapci/gpio multifpgapci/gpio/driver multifpgapci/i2c fan fan/driver mux gpio led psu psu/driver sysstatus xcvr xcvr/driver
2323
MODULE_DIR:= modules
2424
UTILS_DIR := utils
2525
SERVICE_DIR := service

platform/pddf/i2c/modules/include/pddf_multifpgapci_defs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "linux/types.h"
2222
#include <linux/pci.h>
2323

24+
#include "pddf_multifpgapci_gpio_defs.h"
2425
#include "pddf_multifpgapci_i2c_defs.h"
2526

2627
#define NAME_SIZE 32
@@ -37,6 +38,10 @@ struct pddf_multifpgapci_drvdata {
3738
struct kobject *i2c_kobj;
3839
struct i2c_adapter_drvdata i2c_adapter_drvdata;
3940
bool i2c_adapter_drvdata_initialized;
41+
// gpio
42+
struct kobject *gpio_kobj;
43+
struct gpio_chip_drvdata gpio_chip_drvdata;
44+
bool gpio_chip_drvdata_initialized;
4045
};
4146

4247
// FPGA
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2025 Nexthop Systems Inc.
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*/
14+
15+
#ifndef __PDDF_MULTIFPGAPCI_GPIO_DEFS_H__
16+
#define __PDDF_MULTIFPGAPCI_GPIO_DEFS_H__
17+
18+
#include <linux/i2c-mux.h>
19+
#include <linux/kobject.h>
20+
#include <linux/mutex.h>
21+
#include <linux/pci.h>
22+
#include <linux/sysfs.h>
23+
24+
#include "pddf_client_defs.h"
25+
26+
#define MAX_MULTIFPGAPCI_GPIO_LINES 64
27+
28+
struct pddf_multifpgapci_gpio_line_pdata {
29+
// Offset within FPGA
30+
uint32_t offset;
31+
uint32_t bit;
32+
// GPIO_LINE_DIRECTION_IN = 0 or GPIO_LINE_DIRECTION_OUT = 1
33+
int direction;
34+
};
35+
36+
struct pddf_multifpgapci_gpio_chip_pdata {
37+
// The number of GPIOs handled by this controller.
38+
int ngpio;
39+
struct pci_dev *fpga;
40+
struct pddf_multifpgapci_gpio_line_pdata
41+
chan_data[MAX_MULTIFPGAPCI_GPIO_LINES];
42+
};
43+
44+
struct gpio_line_attrs {
45+
PDDF_ATTR attr_bit;
46+
PDDF_ATTR attr_offset;
47+
PDDF_ATTR attr_direction;
48+
PDDF_ATTR attr_create;
49+
};
50+
51+
#define NUM_GPIO_LINE_ATTRS (sizeof(struct gpio_line_attrs) / sizeof(PDDF_ATTR))
52+
53+
struct gpio_chip_attrs {
54+
struct gpio_line_attrs line_attrs;
55+
PDDF_ATTR attr_ngpio;
56+
PDDF_ATTR attr_create;
57+
};
58+
59+
#define NUM_GPIO_CHIP_ATTRS \
60+
((sizeof(struct gpio_chip_attrs) - sizeof(struct gpio_line_attrs)) / \
61+
sizeof(PDDF_ATTR))
62+
63+
struct gpio_chip_drvdata {
64+
// pdata is passed to gpio platform driver.
65+
struct pddf_multifpgapci_gpio_chip_pdata pdata;
66+
// temp_line_data is mutated by sysfs attrs and copied to pdata.
67+
struct pddf_multifpgapci_gpio_line_pdata temp_line_data;
68+
// sysfs attrs
69+
struct gpio_chip_attrs attrs;
70+
struct kobject *line_kobj;
71+
struct attribute *gpio_line_attrs[NUM_GPIO_LINE_ATTRS + 1];
72+
struct attribute_group gpio_line_attr_group;
73+
struct attribute *gpio_chip_attrs[NUM_GPIO_CHIP_ATTRS + 1];
74+
struct attribute_group gpio_chip_attr_group;
75+
};
76+
77+
extern int pddf_multifpgapci_gpio_module_init(struct pci_dev *pci_dev,
78+
struct kobject *kobj);
79+
80+
// Only called if multifpgapci_gpio_module_init succeeded
81+
extern void pddf_multifpgapci_gpio_module_exit(struct pci_dev *pci_dev,
82+
struct kobject *kobj);
83+
84+
#endif
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
obj-m := driver/ i2c/
1+
obj-m := driver/ gpio/ i2c/
22
obj-m += pddf_multifpgapci_module.o
33

44
ccflags-y:= -I$(M)/modules/include

platform/pddf/i2c/modules/multifpgapci/driver/pddf_multifpgapci_driver.c

Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151

5252
#include "pddf_client_defs.h"
5353
#include "pddf_multifpgapci_defs.h"
54+
#include "pddf_multifpgapci_gpio_defs.h"
5455
#include "pddf_multifpgapci_i2c_defs.h"
5556

5657
#define BDF_NAME_SIZE 32
@@ -86,6 +87,9 @@ struct pddf_attrs {
8687
PDDF_ATTR attr_dev_ops;
8788
};
8889

90+
#define NUM_FPGA_ATTRS \
91+
(sizeof(struct pddf_attrs) / sizeof(PDDF_ATTR))
92+
8993
struct pddf_multi_fpgapci_ops_t pddf_multi_fpgapci_ops;
9094

9195
EXPORT_SYMBOL(pddf_multi_fpgapci_ops);
@@ -95,10 +99,16 @@ struct fpga_data_node {
9599
char dev_name[DEVICE_NAME_SIZE]; // device_name as defined in pddf-device.json.
96100
struct kobject *kobj;
97101
struct pci_dev *dev;
98-
struct pddf_attrs attrs;
99102
void __iomem *fpga_ctl_addr;
100103
unsigned long bar_start;
101104
struct list_head list;
105+
106+
// sysfs attrs
107+
struct pddf_attrs attrs;
108+
struct attribute *fpga_attrs[NUM_FPGA_ATTRS + 1];
109+
struct attribute_group fpga_attr_group;
110+
bool fpga_attr_group_initialized;
111+
bool pddf_clients_data_group_initialized;
102112
};
103113

104114
LIST_HEAD(fpga_list);
@@ -165,12 +175,22 @@ void free_pci_drvdata(struct pci_dev *pci_dev)
165175
}
166176
KOBJ_FREE(pci_drvdata->i2c_kobj);
167177

178+
if (pci_drvdata->gpio_chip_drvdata_initialized) {
179+
pddf_multifpgapci_gpio_module_exit(pci_dev,
180+
pci_drvdata->gpio_kobj);
181+
}
182+
KOBJ_FREE(pci_drvdata->gpio_kobj);
183+
168184
pci_set_drvdata(pci_dev, NULL);
169185
}
170186

171187
void free_sysfs_attr_groups(struct fpga_data_node *node)
172188
{
173-
sysfs_remove_group(node->kobj, &pddf_clients_data_group);
189+
if (node->fpga_attr_group_initialized)
190+
sysfs_remove_group(node->kobj, &node->fpga_attr_group);
191+
192+
if (node->pddf_clients_data_group_initialized)
193+
sysfs_remove_group(node->kobj, &pddf_clients_data_group);
174194
}
175195

176196
void delete_fpga_data_node(const char *bdf)
@@ -181,11 +201,9 @@ void delete_fpga_data_node(const char *bdf)
181201

182202
list_for_each_entry_safe(node, tmp, &fpga_list, list) {
183203
if (strcmp(node->bdf, bdf) == 0) {
184-
KOBJ_FREE(node->kobj);
185-
186204
free_pci_drvdata(node->dev);
187205
free_sysfs_attr_groups(node);
188-
206+
KOBJ_FREE(node->kobj);
189207
list_del(&node->list);
190208
kfree(node);
191209
break;
@@ -290,6 +308,23 @@ static int pddf_pci_add_fpga(char *bdf, struct pci_dev *dev)
290308
}
291309
pci_drvdata->i2c_adapter_drvdata_initialized = true;
292310

311+
pci_drvdata->gpio_kobj = kobject_create_and_add("gpio", fpga_data->kobj);
312+
if (!pci_drvdata->gpio_kobj) {
313+
pddf_dbg(MULTIFPGA, KERN_ERR "%s create gpio kobj failed\n",
314+
__FUNCTION__);
315+
ret = -ENOMEM;
316+
goto free_i2c_dirs;
317+
}
318+
319+
ret = pddf_multifpgapci_gpio_module_init(dev, pci_drvdata->gpio_kobj);
320+
if (ret) {
321+
pddf_dbg(MULTIFPGA,
322+
KERN_ERR "%s create add gpio module failed %d\n",
323+
__FUNCTION__, ret);
324+
goto free_gpio_kobj;
325+
}
326+
pci_drvdata->gpio_chip_drvdata_initialized = true;
327+
293328
fpga_data->dev = dev;
294329

295330
PDDF_DATA_ATTR(
@@ -298,40 +333,50 @@ static int pddf_pci_add_fpga(char *bdf, struct pci_dev *dev)
298333

299334
fpga_data->attrs.attr_dev_ops = attr_dev_ops;
300335

301-
struct attribute *attrs_fpgapci[] = {
302-
&fpga_data->attrs.attr_dev_ops.dev_attr.attr,
303-
NULL,
304-
};
336+
fpga_data->fpga_attrs[0] = &fpga_data->attrs.attr_dev_ops.dev_attr.attr;
337+
fpga_data->fpga_attrs[1] = NULL;
305338

306-
struct attribute_group attr_group_fpgapci = {
307-
.attrs = attrs_fpgapci,
308-
};
309-
310-
mutex_lock(&fpga_list_lock);
311-
list_add(&fpga_data->list, &fpga_list);
312-
mutex_unlock(&fpga_list_lock);
339+
fpga_data->fpga_attr_group.attrs = fpga_data->fpga_attrs;
313340

314-
ret = sysfs_create_group(fpga_data->kobj, &attr_group_fpgapci);
341+
ret = sysfs_create_group(fpga_data->kobj, &fpga_data->fpga_attr_group);
315342

316343
if (ret) {
317344
pddf_dbg(MULTIFPGA,
318345
KERN_ERR "%s create fpga sysfs attributes failed\n",
319346
__FUNCTION__);
320-
return ret;
347+
goto free_gpio_dirs;
321348
}
349+
fpga_data->fpga_attr_group_initialized = true;
322350

323351
ret = sysfs_create_group(fpga_data->kobj, &pddf_clients_data_group);
324352
if (ret) {
325353
pddf_dbg(MULTIFPGA,
326-
KERN_ERR "[%s] sysfs_create_group failed: %d\n",
354+
KERN_ERR "[%s] create pddf_clients_data_group failed: %d\n",
327355
__FUNCTION__, ret);
328356
goto free_fpga_attr_group;
329357
}
358+
fpga_data->pddf_clients_data_group_initialized = true;
359+
360+
mutex_lock(&fpga_list_lock);
361+
list_add(&fpga_data->list, &fpga_list);
362+
mutex_unlock(&fpga_list_lock);
330363

331364
return 0;
332365

333366
free_fpga_attr_group:
334-
sysfs_remove_group(fpga_data->kobj, &attr_group_fpgapci);
367+
fpga_data->fpga_attr_group_initialized = false;
368+
sysfs_remove_group(fpga_data->kobj, &fpga_data->fpga_attr_group);
369+
370+
free_gpio_dirs:
371+
pci_drvdata->gpio_chip_drvdata_initialized = false;
372+
pddf_multifpgapci_gpio_module_exit(dev, pci_drvdata->gpio_kobj);
373+
374+
free_gpio_kobj:
375+
kobject_put(pci_drvdata->gpio_kobj);
376+
377+
free_i2c_dirs:
378+
pci_drvdata->i2c_adapter_drvdata_initialized = false;
379+
pddf_multifpgapci_i2c_module_exit(dev, pci_drvdata->i2c_kobj);
335380

336381
free_i2c_kobj:
337382
kobject_put(pci_drvdata->i2c_kobj);
@@ -571,7 +616,7 @@ static int pddf_multifpgapci_probe(struct pci_dev *dev,
571616
KERN_ERR
572617
"[%s] pci_enable_device failed. dev:%s err:%#x\n",
573618
__FUNCTION__, pci_name(dev), err);
574-
return err;
619+
goto error_enable_dev;
575620
}
576621

577622
// Enable DMA
@@ -595,6 +640,7 @@ static int pddf_multifpgapci_probe(struct pci_dev *dev,
595640
KERN_ERR
596641
"[%s] couldn't allocate pci_privdata memory\n",
597642
__FUNCTION__);
643+
err = -ENOMEM;
598644
goto error_pci_req;
599645
}
600646

@@ -605,10 +651,10 @@ static int pddf_multifpgapci_probe(struct pci_dev *dev,
605651

606652
return 0;
607653

608-
// ERROR HANDLING
609654
error_pci_req:
610655
pci_disable_device(dev);
611-
return -ENODEV;
656+
error_enable_dev:
657+
return err;
612658
}
613659

614660
// Initialize the driver module (but not any device) and register
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
obj-m := driver/
2+
3+
TARGET = pddf_multifpgapci_gpio_module
4+
obj-m += $(TARGET).o
5+
6+
ccflags-y := -I$(M)/modules/include
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
TARGET = pddf_multifpgapci_gpio_driver_module
2+
obj-m := pddf_multifpgapci_gpio_driver.o
3+
4+
ccflags-y := -I$(M)/modules/include

0 commit comments

Comments
 (0)