Skip to content

Commit d6fb200

Browse files
lotus-nexthopmichaelc-nexthoplouis-nexthop
authored andcommitted
[PDDF] Add multi PCIE FPGA controlled XCVR (#22765)
* IGNORE THIS COMMIT: Multiple FPGAs w/ I2C IP block (PR #22748) * [PDDF] Add multi PCIE FPGA controlled XCVR * parse multifpgapciesystem appropriately * IGNORE THIS COMMIT: Remove PDDF_DATA_ATTR_VAL and use client device table (PR #22748) * [PDDF] Remove attr_bdf for MultiFPGA XCVR * IGNORE THIS COMMIT: Remove multifpgapcisystem_parse() in pddfapi.py (PR #22748) * Trigger Build * no-op commit to retrigger workflow --------- Co-authored-by: Michael Chan <[email protected]> Co-authored-by: Louis Maliyam <[email protected]>
1 parent 2ead8a5 commit d6fb200

File tree

5 files changed

+160
-8
lines changed

5 files changed

+160
-8
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424
#define MAX_NUM_XCVR 5
2525
#define MAX_XCVR_ATTRS 20
2626

27-
2827
typedef struct XCVR_ATTR
2928
{
3029
char aname[32]; // attr name, taken from enum xcvr_sysfs_attributes
3130
char devtype[32]; // either a 'eeprom' or 'cpld', or 'pmbus' attribute
3231
char devname[32]; // name of the device from where this sysfs is to be read
32+
struct pci_dev *fpga_pci_dev;
3333
uint32_t devaddr;
3434
uint32_t offset;
3535
uint32_t mask;
@@ -48,7 +48,7 @@ typedef struct XCVR_DATA
4848
int idx; // xcvr index
4949
XCVR_ATTR xcvr_attr;
5050
int len; // no of valid attributes for this xcvr client
51-
XCVR_ATTR xcvr_attrs[MAX_XCVR_ATTRS];
51+
XCVR_ATTR xcvr_attrs[MAX_XCVR_ATTRS];
5252
}XCVR_DATA;
5353

5454
typedef struct XCVR_PDATA

platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_api.c

Lines changed: 142 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/delay.h>
3030
#include <linux/dmi.h>
3131
#include <linux/kobject.h>
32+
#include "pddf_multifpgapci_defs.h"
3233
#include "pddf_xcvr_defs.h"
3334

3435
/*#define SFP_DEBUG*/
@@ -293,6 +294,81 @@ int xcvr_fpgapci_write(XCVR_ATTR *info, uint32_t val)
293294
return status;
294295
}
295296

297+
int xcvr_multifpgapci_read(XCVR_ATTR *info, int *output)
298+
{
299+
int status = 0;
300+
uint32_t offset = 0;
301+
struct pci_dev *pci_dev = NULL;
302+
303+
if (ptr_multifpgapci_readpci == NULL) {
304+
printk(KERN_ERR "PDDF_XCVR: Doesn't support MULTIFPGAPCI read yet");
305+
status = -1;
306+
goto ret;
307+
}
308+
309+
pci_dev = (struct pci_dev *)get_device_table(info->devname);
310+
if (pci_dev == NULL) {
311+
printk(KERN_ERR "PDDF_XCVR: Unable to get pci_dev of %s for %s\n", info->devname, info->aname);
312+
status = -1;
313+
goto ret;
314+
}
315+
316+
offset = info->devaddr + info->offset;
317+
status = ptr_multifpgapci_readpci(pci_dev, offset, output);
318+
319+
ret:
320+
if (status)
321+
printk(KERN_ERR "%s: Error status = %d", __FUNCTION__, status);
322+
323+
return status;
324+
}
325+
326+
int xcvr_multifpgapci_write(XCVR_ATTR *info, uint32_t val)
327+
{
328+
int status = 0;
329+
uint32_t reg, val_mask = 0, dnd_value = 0, reg_val;
330+
uint32_t offset = 0;
331+
struct pci_dev *pci_dev = NULL;
332+
333+
if (ptr_multifpgapci_readpci == NULL || ptr_multifpgapci_writepci == NULL) {
334+
printk(KERN_ERR
335+
"PDDF_XCVR: Doesn't support MULTIFPGAPCI read or write yet");
336+
return (-1);
337+
}
338+
339+
pci_dev = (struct pci_dev *)get_device_table(info->devname);
340+
if (pci_dev == NULL) {
341+
printk(KERN_ERR "PDDF_XCVR: Unable to get pci_dev of %s for %s\n", info->devname, info->aname);
342+
status = -1;
343+
goto ret;
344+
}
345+
346+
offset = info->devaddr + info->offset;
347+
val_mask = BIT_INDEX(info->mask);
348+
status = ptr_multifpgapci_readpci(pci_dev, offset, &reg_val);
349+
if (status)
350+
goto ret;
351+
dnd_value = reg_val & ~val_mask;
352+
353+
// We expect val to be either 0 or 1. This function doesn't write val thru to the FPGA.
354+
// Instead it uses val and a mask to toggle bits.
355+
if (((val == 1) && (info->cmpval != 0)) || ((val == 0) && (info->cmpval == 0))) {
356+
reg = dnd_value | val_mask;
357+
} else {
358+
reg = dnd_value;
359+
}
360+
361+
status = ptr_multifpgapci_writepci(pci_dev, reg, offset);
362+
if (status)
363+
goto ret;
364+
365+
ret:
366+
if (status)
367+
printk(KERN_ERR "%s: Error status = %d", __FUNCTION__, status);
368+
369+
return status;
370+
}
371+
296372
int sonic_i2c_get_mod_pres(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
297373
{
298374
int status = 0;
@@ -322,19 +398,31 @@ int sonic_i2c_get_mod_pres(struct i2c_client *client, XCVR_ATTR *info, struct xc
322398
sfp_dbg(KERN_INFO "\nMod presence :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modpres, status, info->devaddr, info->mask, info->offset);
323399
}
324400
}
325-
else if ( strcmp(info->devtype, "fpgapci") == 0)
401+
else if (strcmp(info->devtype, "fpgapci") == 0)
326402
{
327403
status = xcvr_fpgapci_read(info);
328404

329405
if (status < 0)
406+
{
330407
return status;
408+
}
331409
else
332410
{
333411
modpres = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
334412
sfp_dbg(KERN_INFO "\nMod presence :0x%x, status= 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modpres, status, info->devaddr, info->mask, info->offset);
335413
}
336414
}
415+
else if (strcmp(info->devtype, "multifpgapci") == 0)
416+
{
417+
int output;
337418

419+
status = xcvr_multifpgapci_read(info, &output);
420+
if (status)
421+
return status;
422+
423+
modpres = ((output & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
424+
sfp_dbg(KERN_INFO "\nMod presence :0x%x, reg_value=0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modpres, output, info->devaddr, info->mask, info->offset);
425+
}
338426
else if(strcmp(info->devtype, "eeprom") == 0)
339427
{
340428
/* get client client for eeprom - Not Applicable */
@@ -372,18 +460,31 @@ int sonic_i2c_get_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct x
372460
sfp_dbg(KERN_INFO "\nMod reset :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modpres, status, info->devaddr, info->mask, info->offset);
373461
}
374462
}
375-
else if ( strcmp(info->devtype, "fpgapci") == 0)
463+
else if (strcmp(info->devtype, "fpgapci") == 0)
376464
{
377465
status = xcvr_fpgapci_read(info);
378466
sfp_dbg(KERN_INFO "\n[%s] status=%x\n", __FUNCTION__, status);
379467
if (status < 0)
468+
{
380469
return status;
470+
}
381471
else
382472
{
383473
modreset = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
384474
sfp_dbg(KERN_INFO "\nMod reset :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modreset, status, info->devaddr, info->mask, info->offset);
385475
}
386476
}
477+
else if (strcmp(info->devtype, "multifpgapci") == 0)
478+
{
479+
int output;
480+
481+
status = xcvr_multifpgapci_read(info, &output);
482+
if (status)
483+
return status;
484+
485+
modreset = ((output & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
486+
sfp_dbg(KERN_INFO "\nMod reset :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modreset, output, info->devaddr, info->mask, info->offset);
487+
}
387488
else if(strcmp(info->devtype, "eeprom") == 0)
388489
{
389490
/* get client client for eeprom - Not Applicable */
@@ -421,19 +522,32 @@ int sonic_i2c_get_mod_intr_status(struct i2c_client *client, XCVR_ATTR *info, st
421522
sfp_dbg(KERN_INFO "\nModule Interrupt :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modpres, status, info->devaddr, info->mask, info->offset);
422523
}
423524
}
424-
else if ( strcmp(info->devtype, "fpgapci") == 0)
525+
else if (strcmp(info->devtype, "fpgapci") == 0)
425526
{
426527
status = xcvr_fpgapci_read(info);
427528
sfp_dbg(KERN_INFO "\n[%s] status=%x\n", __FUNCTION__, status);
428529
if (status < 0)
530+
{
429531
return status;
532+
}
430533
else
431534
{
432535
mod_intr = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
433536
sfp_dbg(KERN_INFO "\nModule Interrupt :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", mod_intr, status, info->devaddr, info->mask, info->offset);
434537
}
435538
}
539+
else if (strcmp(info->devtype, "multifpgapci") == 0)
540+
{
541+
int output;
436542

543+
status = xcvr_multifpgapci_read(info, &output);
544+
if (status) {
545+
return status;
546+
}
547+
548+
mod_intr = ((output & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
549+
sfp_dbg(KERN_INFO "\nModule Interrupt :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", mod_intr, output, info->devaddr, info->mask, info->offset);
550+
}
437551
else if(strcmp(info->devtype, "eeprom") == 0)
438552
{
439553
/* get client client for eeprom - Not Applicable */
@@ -472,18 +586,31 @@ int sonic_i2c_get_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct
472586
sfp_dbg(KERN_INFO "\nModule LPmode :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modpres, status, info->devaddr, info->mask, info->offset);
473587
}
474588
}
475-
else if ( strcmp(info->devtype, "fpgapci") == 0)
589+
else if (strcmp(info->devtype, "fpgapci") == 0)
476590
{
477591
status = xcvr_fpgapci_read(info);
478592
sfp_dbg(KERN_INFO "\n[%s] status=%x\n", __FUNCTION__, status);
479593
if (status < 0)
594+
{
480595
return status;
596+
}
481597
else
482598
{
483599
lpmode = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
484600
sfp_dbg(KERN_INFO "\nlpmode :0x%x, reg_val = 0x%x, op=0x%x, mask=0x%x, offset=0x%x\n", lpmode, status, status & BIT_INDEX(info->mask), info->mask, info->offset);
485601
}
486602
}
603+
else if (strcmp(info->devtype, "multifpgapci") == 0)
604+
{
605+
int output;
606+
607+
status = xcvr_multifpgapci_read(info, &output);
608+
if (status)
609+
return status;
610+
611+
lpmode = ((output & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
612+
sfp_dbg(KERN_INFO "\nlpmode :0x%x, reg_val = 0x%x, op=0x%x, mask=0x%x, offset=0x%x\n", lpmode, output, status & BIT_INDEX(info->mask), info->mask, info->offset);
613+
}
487614
else if (strcmp(info->devtype, "eeprom") == 0)
488615
{
489616
/* get client client for eeprom - Not Applicable */
@@ -610,12 +737,19 @@ int sonic_i2c_set_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct x
610737
{
611738
status = xcvr_fpgapci_write(info, data->reset);
612739
}
740+
else if (strcmp(info->devtype, "multifpgapci") == 0)
741+
{
742+
status = xcvr_multifpgapci_write(info, data->reset);
743+
}
613744
else
614745
{
615746
printk(KERN_ERR "Error: Invalid device type (%s) to set xcvr reset\n", info->devtype);
616747
status = -1;
617748
}
618749

750+
if (status < 0)
751+
printk(KERN_ERR "%s: Error status = %d", __FUNCTION__, status);
752+
619753
return status;
620754
}
621755

@@ -635,6 +769,10 @@ int sonic_i2c_set_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct
635769
{
636770
status = xcvr_fpgapci_write(info, data->lpmode);
637771
}
772+
else if (strcmp(info->devtype, "multifpgapci") == 0)
773+
{
774+
status = xcvr_multifpgapci_write(info, data->lpmode);
775+
}
638776
else
639777
{
640778
printk(KERN_ERR "Error: Invalid device type (%s) to set xcvr lpmode\n", info->devtype);

platform/pddf/i2c/modules/xcvr/pddf_xcvr_module.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ static ssize_t do_device_operation(struct device *dev, struct device_attribute *
109109
XCVR_PDATA *xcvr_platform_data;
110110

111111
adapter = i2c_get_adapter(cdata->parent_bus);
112+
if (!adapter) {
113+
printk(KERN_ERR "PDDF_ERROR: %s: Failed to get i2c adapter for bus %d\n", __FUNCTION__, cdata->parent_bus);
114+
goto clear_data;
115+
}
112116
/* Allocate the xcvr_platform_data */
113117
xcvr_platform_data = (XCVR_PDATA *)kzalloc(sizeof(XCVR_PDATA), GFP_KERNEL);
114118
xcvr_platform_data->xcvr_attrs = (XCVR_ATTR *)kzalloc(num*sizeof(XCVR_ATTR), GFP_KERNEL);
@@ -147,6 +151,10 @@ static ssize_t do_device_operation(struct device *dev, struct device_attribute *
147151
{
148152

149153
adapter = i2c_get_adapter(cdata->parent_bus);
154+
if (!adapter) {
155+
printk(KERN_ERR "PDDF_ERROR: %s: Failed to get i2c adapter for bus %d\n", __FUNCTION__, cdata->parent_bus);
156+
goto clear_data;
157+
}
150158
board_info = (struct i2c_board_info) {
151159
.platform_data = (void *)NULL,
152160
};

platform/pddf/i2c/utils/pddfparse.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,10 @@ def show_device_sysfs(self, dev, ops):
690690
return "/sys/bus/i2c/devices/"+"i2c-%d"%int(pdev['i2c']['topo_info']['dev_addr'], 0)
691691
else:
692692
return "/sys/bus/i2c/devices"
693-
return self.show_device_sysfs(pdev, ops) + "/" + "i2c-%d" % int(dev['i2c']['topo_info']['parent_bus'], 0)
693+
if 'topo_info' in dev['i2c'] and 'parent_bus' in dev['i2c']['topo_info']:
694+
return self.show_device_sysfs(pdev, ops) + "/" + "i2c-%d" % int(dev['i2c']['topo_info']['parent_bus'], 0)
695+
else:
696+
return self.show_device_sysfs(pdev, ops)
694697

695698
def get_gpio_attr_path(self, dev, offset):
696699
base = int(dev['i2c']['dev_attr']['gpio_base'], 16)

platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddfapi.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,10 @@ def show_device_sysfs(self, dev, ops):
303303
return "/sys/bus/i2c/devices/"+"i2c-%d"%int(pdev['i2c']['topo_info']['dev_addr'], 0)
304304
else:
305305
return "/sys/bus/i2c/devices"
306-
return self.show_device_sysfs(pdev, ops) + "/" + "i2c-%d" % int(dev['i2c']['topo_info']['parent_bus'], 0)
306+
if 'topo_info' in dev['i2c'] and 'parent_bus' in dev['i2c']['topo_info']:
307+
return self.show_device_sysfs(pdev, ops) + "/" + "i2c-%d" % int(dev['i2c']['topo_info']['parent_bus'], 0)
308+
else:
309+
return self.show_device_sysfs(pdev, ops)
307310

308311
def get_gpio_attr_path(self, dev, offset):
309312
base = int(dev['i2c']['dev_attr']['gpio_base'], 16)

0 commit comments

Comments
 (0)