diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/modules/builds/x86-64-accton-as7712-32x-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/modules/builds/x86-64-accton-as7712-32x-psu.c index e3802603..83833c35 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/modules/builds/x86-64-accton-as7712-32x-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/modules/builds/x86-64-accton-as7712-32x-psu.c @@ -35,6 +35,7 @@ #include #define MAX_MODEL_NAME 16 +#define MAX_SERIAL_NUMBER 19 #define DC12V_FAN_DIR_OFFSET 0x34 #define DC12V_FAN_DIR_LEN 3 @@ -47,6 +48,13 @@ extern int as7712_32x_cpld_read (unsigned short cpld_addr, u8 reg); */ static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; +enum psu_type { + PSU_TYPE_AC_110V, + PSU_TYPE_DC_48V, + PSU_TYPE_DC_12V, + PSU_TYPE_AC_ACBEL_FSF019, +}; + /* Each client has this additional data */ struct as7712_32x_psu_data { @@ -58,6 +66,8 @@ struct as7712_32x_psu_data { u8 status; /* Status(present/power_good) register read from CPLD */ char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */ char fan_dir[DC12V_FAN_DIR_LEN+1]; /* DC12V fan direction */ + char serial_number[MAX_SERIAL_NUMBER]; + enum psu_type type; }; static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); @@ -66,6 +76,7 @@ static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *d enum as7712_32x_psu_sysfs_attributes { PSU_PRESENT, PSU_MODEL_NAME, + PSU_SERIAL_NUMBER, /* For ACBEL PSU only */ PSU_POWER_GOOD, PSU_FAN_DIR /* For DC12V only */ }; @@ -74,12 +85,14 @@ enum as7712_32x_psu_sysfs_attributes { */ static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_string, NULL, PSU_FAN_DIR); static struct attribute *as7712_32x_psu_attributes[] = { &sensor_dev_attr_psu_present.dev_attr.attr, &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_serial_number.dev_attr.attr, &sensor_dev_attr_psu_power_good.dev_attr.attr, &sensor_dev_attr_psu_fan_dir.dev_attr.attr, NULL @@ -117,12 +130,19 @@ static ssize_t show_string(struct device *dev, struct device_attribute *da, return -EIO; } - if (attr->index == PSU_MODEL_NAME) { - ptr = data->model_name; - } - else { /* PSU_FAN_DIR */ - ptr = data->fan_dir; - } + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial_number; + break; + case PSU_FAN_DIR: + ptr = data->fan_dir; + break; + default: + return -EINVAL; + } return sprintf(buf, "%s\n", ptr); } @@ -245,12 +265,6 @@ static int as7712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 * return result; } -enum psu_type { - PSU_TYPE_AC_110V, - PSU_TYPE_DC_48V, - PSU_TYPE_DC_12V -}; - struct model_name_info { enum psu_type type; u8 offset; @@ -258,10 +272,38 @@ struct model_name_info { char* model_name; }; +static int acbel_psu_serial_number_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7712_32x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + memset(data->serial_number, 0, sizeof(data->serial_number)); + + /* Read from offset 0x2e ~ 0x3d (16 bytes) */ + status = as7712_32x_psu_read_block(client, 0x2e,data->serial_number, 16); + if (status < 0) { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x2e)\n", client->addr); + return status; + } + + /* Read from offset 0x4f ~ 0x50 (2 bytes) */ + status = as7712_32x_psu_read_block(client, 0x4f, data->serial_number + 16, 2); + if (status < 0) { + data->serial_number[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x4f)\n", client->addr); + return status; + } + + return 0; +} + struct model_name_info models[] = { {PSU_TYPE_AC_110V, 0x20, 8, "YM-2651Y"}, {PSU_TYPE_DC_48V, 0x20, 8, "YM-2651V"}, {PSU_TYPE_DC_12V, 0x00, 11, "PSU-12V-750"}, +{PSU_TYPE_AC_ACBEL_FSF019, 0x15, 7, "FSF019-"}, }; static int as7712_32x_psu_model_name_get(struct device *dev) @@ -285,6 +327,20 @@ static int as7712_32x_psu_model_name_get(struct device *dev) data->model_name[models[i].length] = '\0'; } + /* Get the remaining model name for FSF019 */ + if (strncmp(data->model_name, "FSF019-", 7) == 0) { + char buf[5] = {0}; + + status = as7712_32x_psu_read_block(client, 0x48, data->model_name + models[i].length, 4); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x48)\n", client->addr); + return status; + } + + data->type = PSU_TYPE_AC_ACBEL_FSF019; + } + /* Determine if the model name is known, if not, read next index */ if (strncmp(data->model_name, models[i].model_name, models[i].length) == 0) { @@ -348,6 +404,11 @@ static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *d goto exit; } } + + if (data->type == PSU_TYPE_AC_ACBEL_FSF019 && + acbel_psu_serial_number_get(dev) < 0) { + goto exit; + } } data->last_updated = jiffies; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/fani.c index 5fd76b00..da2ac83f 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/fani.c @@ -148,11 +148,13 @@ _onlp_fani_info_get_psu_fan_direction(void) } switch (psu_type) { - case PSU_TYPE_AC_F2B: + case PSU_TYPE_AC_F2B_3YPOWER: + case PSU_TYPE_AC_F2B_ACBEL: case PSU_TYPE_DC_48V_F2B: case PSU_TYPE_DC_12V_F2B: return ONLP_FAN_STATUS_F2B; - case PSU_TYPE_AC_B2F: + case PSU_TYPE_AC_B2F_3YPOWER: + case PSU_TYPE_AC_B2F_ACBEL: case PSU_TYPE_DC_48V_B2F: case PSU_TYPE_DC_12V_B2F: return ONLP_FAN_STATUS_B2F; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.c index ea139ae7..0a2f5e68 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.c @@ -148,11 +148,11 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len) } if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { - return PSU_TYPE_AC_F2B; + return PSU_TYPE_AC_F2B_3YPOWER; } if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { - return PSU_TYPE_AC_B2F; + return PSU_TYPE_AC_B2F_3YPOWER; } } @@ -198,12 +198,37 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len) } } + if (strncmp(model_name, "FSF019", 6) == 0) { + if (modelname) { + strncpy(modelname, model_name, 11); /* Copy full model name */ + } + + /* Read model */ + char *string = NULL; + char *prefix = (id == PSU1_ID) ? PSU1_AC_PMBUS_PREFIX : PSU2_AC_PMBUS_PREFIX; + int len = onlp_file_read_str(&string, "%s""psu_fan_dir", prefix); + if (!string || len <= 0) { + return PSU_TYPE_UNKNOWN; + } + + strncpy(fan_dir, string, len); + aim_free(string); + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_AC_F2B_ACBEL; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_AC_B2F_ACBEL; + } + } + return PSU_TYPE_UNKNOWN; } #define PSU_SERIAL_NUMBER_LEN 18 -int psu_serial_number_get(int id, char *serial, int serial_len) +int psu_pmbus_serial_number_get(int id, char *serial, int serial_len) { int size = 0; int ret = ONLP_STATUS_OK; @@ -225,3 +250,20 @@ int psu_serial_number_get(int id, char *serial, int serial_len) return ONLP_STATUS_OK; } +int psu_acbel_serial_number_get(int id, char *serial, int serial_len) +{ + char *serial_number = NULL; + char *prefix = (id == PSU1_ID) ? PSU1_AC_HWMON_PREFIX : PSU2_AC_HWMON_PREFIX; + + int len = onlp_file_read_str(&serial_number, "%s""psu_serial_number", prefix); + if (!serial || len <= 0) { + return ONLP_STATUS_E_INTERNAL; + } + + strncpy(serial, serial_number, len); + aim_free(serial_number); + + serial[len] = '\0'; + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.h index a1e32542..675ce207 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/platform_lib.h @@ -54,8 +54,10 @@ int deviceNodeReadString(char *filename, char *buffer, int buf_size, int data_le typedef enum psu_type { PSU_TYPE_UNKNOWN, - PSU_TYPE_AC_F2B, - PSU_TYPE_AC_B2F, + PSU_TYPE_AC_F2B_3YPOWER, + PSU_TYPE_AC_B2F_3YPOWER, + PSU_TYPE_AC_F2B_ACBEL, + PSU_TYPE_AC_B2F_ACBEL, PSU_TYPE_DC_48V_F2B, PSU_TYPE_DC_48V_B2F, PSU_TYPE_DC_12V_FANLESS, @@ -64,7 +66,8 @@ typedef enum psu_type { } psu_type_t; psu_type_t get_psu_type(int id, char* modelname, int modelname_len); -int psu_serial_number_get(int id, char *serial, int serial_len); +int psu_pmbus_serial_number_get(int id, char *serial, int serial_len); +int psu_acbel_serial_number_get(int id, char *serial, int serial_len); #define DEBUG_MODE 0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/psui.c index 9a1a1436..4c25eae7 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7712-32x/onlp/builds/src/module/src/psui.c @@ -68,7 +68,7 @@ psu_status_info_get(int id, char *node, int *value) } static int -psu_ym2651_pmbus_info_get(int id, char *node, int *value) +psu_pmbus_info_get(int id, char *node, int *value) { int ret = 0; char buf[PSU_NODE_MAX_INT_LEN + 1] = {0}; @@ -113,22 +113,57 @@ psu_ym2651_info_get(onlp_psu_info_t* info) info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); /* Read voltage, current and power */ - if (psu_ym2651_pmbus_info_get(index, "psu_v_out", &val) == 0) { + if (psu_pmbus_info_get(index, "psu_v_out", &val) == 0) { info->mvout = val; info->caps |= ONLP_PSU_CAPS_VOUT; } - if (psu_ym2651_pmbus_info_get(index, "psu_i_out", &val) == 0) { + if (psu_pmbus_info_get(index, "psu_i_out", &val) == 0) { info->miout = val; info->caps |= ONLP_PSU_CAPS_IOUT; } - if (psu_ym2651_pmbus_info_get(index, "psu_p_out", &val) == 0) { + if (psu_pmbus_info_get(index, "psu_p_out", &val) == 0) { info->mpout = val; info->caps |= ONLP_PSU_CAPS_POUT; } - psu_serial_number_get(index, info->serial, sizeof(info->serial)); + psu_pmbus_serial_number_get(index, info->serial, sizeof(info->serial)); + + return ONLP_STATUS_OK; +} + +static int +psu_acbel_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT); + + /* Read voltage, current and power */ + if (psu_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + psu_acbel_serial_number_get(index, info->serial, sizeof(info->serial)); return ONLP_STATUS_OK; } @@ -237,11 +272,16 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) psu_type = get_psu_type(index, info->model, sizeof(info->model)); switch (psu_type) { - case PSU_TYPE_AC_F2B: - case PSU_TYPE_AC_B2F: + case PSU_TYPE_AC_F2B_3YPOWER: + case PSU_TYPE_AC_B2F_3YPOWER: info->caps = ONLP_PSU_CAPS_AC; ret = psu_ym2651_info_get(info); break; + case PSU_TYPE_AC_F2B_ACBEL: + case PSU_TYPE_AC_B2F_ACBEL: + info->caps = ONLP_PSU_CAPS_AC; + ret = psu_acbel_info_get(info); + break; case PSU_TYPE_DC_48V_F2B: case PSU_TYPE_DC_48V_B2F: info->caps = ONLP_PSU_CAPS_DC48;