From e93637540996cde4bbbc57547b74cea90e7873ad Mon Sep 17 00:00:00 2001 From: willy_liu Date: Thu, 21 Mar 2024 10:39:07 +0800 Subject: [PATCH] [Edgecore][as5912-54x] Add lpmode and reset function 1. Add lpmode sysfs node and lpmode function 2. Add reset sysfs node and reset function Signed-off-by: willy_liu --- .../builds/x86-64-accton-as5912-54x-cpld.c | 112 ++++++++++++++++++ .../module/src/sfpi.c | 83 ++++++++++++- 2 files changed, 193 insertions(+), 2 deletions(-) diff --git a/packages/platforms/accton/x86-64/as5912-54x/modules/builds/x86-64-accton-as5912-54x-cpld.c b/packages/platforms/accton/x86-64/as5912-54x/modules/builds/x86-64-accton-as5912-54x-cpld.c index 3c8d557cc6..f0c3c09942 100644 --- a/packages/platforms/accton/x86-64/as5912-54x/modules/builds/x86-64-accton-as5912-54x-cpld.c +++ b/packages/platforms/accton/x86-64/as5912-54x/modules/builds/x86-64-accton-as5912-54x-cpld.c @@ -67,6 +67,8 @@ MODULE_DEVICE_TABLE(i2c, as5912_54x_cpld_id); #define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index #define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index #define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index +#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index +#define TRANSCEIVER_LPMODE_ATTR_ID(index) MODULE_LPMODE_##index enum as5912_54x_cpld1_sysfs_attributes { CPLD_VERSION, @@ -272,6 +274,18 @@ enum as5912_54x_cpld1_sysfs_attributes { TRANSCEIVER_TXFAULT_ATTR_ID(46), TRANSCEIVER_TXFAULT_ATTR_ID(47), TRANSCEIVER_TXFAULT_ATTR_ID(48), + TRANSCEIVER_RESET_ATTR_ID(49), + TRANSCEIVER_RESET_ATTR_ID(50), + TRANSCEIVER_RESET_ATTR_ID(51), + TRANSCEIVER_RESET_ATTR_ID(52), + TRANSCEIVER_RESET_ATTR_ID(53), + TRANSCEIVER_RESET_ATTR_ID(54), + TRANSCEIVER_LPMODE_ATTR_ID(49), + TRANSCEIVER_LPMODE_ATTR_ID(50), + TRANSCEIVER_LPMODE_ATTR_ID(51), + TRANSCEIVER_LPMODE_ATTR_ID(52), + TRANSCEIVER_LPMODE_ATTR_ID(53), + TRANSCEIVER_LPMODE_ATTR_ID(54), }; /* sysfs attributes for hwmon @@ -284,6 +298,8 @@ static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, char *buf); static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +static ssize_t set_qsfp_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); static ssize_t access(struct device *dev, struct device_attribute *da, const char *buf, size_t count); static ssize_t show_version(struct device *dev, struct device_attribute *da, @@ -305,6 +321,13 @@ static int as5912_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr +#define DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_qsfp_control, MODULE_RESET_##index); \ + static SENSOR_DEVICE_ATTR(module_lpmode_##index, S_IRUGO | S_IWUSR, show_status, set_qsfp_control, MODULE_LPMODE_##index); +#define DECLARE_QSFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr, \ + &sensor_dev_attr_module_lpmode_##index.dev_attr.attr + static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); /* transceiver attributes */ @@ -414,6 +437,13 @@ DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); + static struct attribute *as5912_54x_cpld1_attributes[] = { &sensor_dev_attr_version.dev_attr.attr, &sensor_dev_attr_access.dev_attr.attr, @@ -535,6 +565,12 @@ static struct attribute *as5912_54x_cpld2_attributes[] = { DECLARE_SFP_TRANSCEIVER_ATTR(46), DECLARE_SFP_TRANSCEIVER_ATTR(47), DECLARE_SFP_TRANSCEIVER_ATTR(48), + DECLARE_QSFP_TRANSCEIVER_ATTR(49), + DECLARE_QSFP_TRANSCEIVER_ATTR(50), + DECLARE_QSFP_TRANSCEIVER_ATTR(51), + DECLARE_QSFP_TRANSCEIVER_ATTR(52), + DECLARE_QSFP_TRANSCEIVER_ATTR(53), + DECLARE_QSFP_TRANSCEIVER_ATTR(54), NULL }; @@ -725,6 +761,15 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, reg = 0x34; mask = 0x1 << (attr->index - MODULE_RXLOS_41); break; + case MODULE_RESET_49 ... MODULE_RESET_54: + revert = 1; + reg = 0x53; + mask = 0x1 << (attr->index - MODULE_RESET_49); + break; + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x54; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; default: return 0; } @@ -819,6 +864,73 @@ static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, return status; } +static ssize_t set_qsfp_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5912_54x_cpld_data *data = i2c_get_clientdata(client); + long value; + int status; + u8 reg = 0, mask = 0, invert = 0; + + status = kstrtol(buf, 10, &value); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_RESET_49 ... MODULE_RESET_54: + invert = 1; + reg = 0x53; + mask = 0x1 << (attr->index - MODULE_RESET_49); + break; + case MODULE_LPMODE_49 ... MODULE_LPMODE_54: + reg = 0x54; + mask = 0x1 << (attr->index - MODULE_LPMODE_49); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5912_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update qsfp status */ + if (invert) + { + if (value) + status &= ~mask; + else + status |= mask; + } + else + { + if (value) { + status |= mask; + } + else { + status &= ~mask; + } + } + + status = as5912_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + static ssize_t access(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { diff --git a/packages/platforms/accton/x86-64/as5912-54x/onlp/builds/x86_64_accton_as5912_54x/module/src/sfpi.c b/packages/platforms/accton/x86-64/as5912-54x/onlp/builds/x86_64_accton_as5912_54x/module/src/sfpi.c index 4cad7c70a8..3f5231e841 100644 --- a/packages/platforms/accton/x86-64/as5912-54x/onlp/builds/x86_64_accton_as5912_54x/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/as5912-54x/onlp/builds/x86_64_accton_as5912_54x/module/src/sfpi.c @@ -36,10 +36,25 @@ #define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d" #define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d" #define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d" +#define MODULE_RESET_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_reset_%d" +#define MODULE_LPMODE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_lpmode_%d" #define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/%d-00%d/module_present_all" #define MODULE_RXLOS_ALL_ATTR_CPLD1 "/sys/bus/i2c/devices/4-0060/module_rx_los_all" #define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/5-0062/module_rx_los_all" +#define PORT_MAX_NUM 54 +#define VALIDATE_SFP(_port) \ + do { \ + if (_port < 0 || _port >= 48) \ + return ONLP_STATUS_E_UNSUPPORTED; \ + } while(0) + +#define VALIDATE_QSFP(_port) \ + do { \ + if (_port < 48 || _port >= PORT_MAX_NUM) \ + return ONLP_STATUS_E_UNSUPPORTED; \ + } while(0) + /************************************************************ * * SFPI Entry Points @@ -291,7 +306,7 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { int rv; - if (port < 0 || port >= 48) { + if (port < 0 || port >= PORT_MAX_NUM) { return ONLP_STATUS_E_UNSUPPORTED; } @@ -302,6 +317,8 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { case ONLP_SFP_CONTROL_TX_DISABLE: { + VALIDATE_SFP(port); + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -312,6 +329,34 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) break; } + case ONLP_SFP_CONTROL_RESET: + { + VALIDATE_QSFP(port); + + if (onlp_file_write_int(value, MODULE_RESET_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to set reset status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_LP_MODE: + { + VALIDATE_QSFP(port); + + if (onlp_file_write_int(value, MODULE_LPMODE_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to set lpmode status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + default: rv = ONLP_STATUS_E_UNSUPPORTED; break; @@ -325,7 +370,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; - if (port < 0 || port >= 48) { + if (port < 0 || port >= PORT_MAX_NUM) { return ONLP_STATUS_E_UNSUPPORTED; } @@ -336,6 +381,8 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { case ONLP_SFP_CONTROL_RX_LOS: { + VALIDATE_SFP(port); + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -348,6 +395,8 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { + VALIDATE_SFP(port); + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -360,6 +409,8 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_DISABLE: { + VALIDATE_SFP(port); + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; @@ -370,6 +421,34 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) break; } + case ONLP_SFP_CONTROL_RESET: + { + VALIDATE_QSFP(port); + + if (onlp_file_read_int(value, MODULE_RESET_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read reset status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_LP_MODE: + { + VALIDATE_QSFP(port); + + if (onlp_file_read_int(value, MODULE_LPMODE_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read lpmode status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + default: rv = ONLP_STATUS_E_UNSUPPORTED; }