From edaff9f1590b150e1971ce3b36c5891f21ec004f Mon Sep 17 00:00:00 2001 From: Jostar Yang Date: Wed, 3 Oct 2018 11:05:15 +0800 Subject: [PATCH] Modify psu driver to support both 3y and delte power --- packages/base/any/kernels/modules/dps850.c | 509 ++++++++++++++++++ .../onlp/builds/src/module/src/fani.c | 27 +- .../onlp/builds/src/module/src/platform_lib.c | 27 +- .../onlp/builds/src/module/src/platform_lib.h | 6 +- .../onlp/builds/src/module/src/psui.c | 57 ++ .../x86_64_accton_as7816_64x_r0/__init__.py | 47 +- 6 files changed, 665 insertions(+), 8 deletions(-) create mode 100755 packages/base/any/kernels/modules/dps850.c mode change 100644 => 100755 packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/fani.c mode change 100644 => 100755 packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.c mode change 100644 => 100755 packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.h mode change 100644 => 100755 packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/psui.c diff --git a/packages/base/any/kernels/modules/dps850.c b/packages/base/any/kernels/modules/dps850.c new file mode 100755 index 00000000..41d742d7 --- /dev/null +++ b/packages/base/any/kernels/modules/dps850.c @@ -0,0 +1,509 @@ +/* + * An hwmon driver for the Delta DPS-850AB-4 Power Module + * + * Copyright (C) 2017 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +enum chips { + DPS850 +}; + +/* Each client has this additional data + */ +struct dps850_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 chip; /* chip id */ + u8 vout_mode; /* Register value */ + u16 v_in; /* Register value */ + u16 v_out; /* Register value */ + u16 i_in; /* Register value */ + u16 i_out; /* Register value */ + u16 p_in; /* Register value */ + u16 p_out; /* Register value */ + u16 temp_input[3]; /* Register value */ + u16 fan_speed; /* Register value */ + u8 mfr_model[16]; /* Register value */ + u8 mfr_serial[16]; /* Register value */ +}; + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_vout_by_mode(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf); +static struct dps850_data *dps850_update_device(struct device *dev); +static int dps850_write_word(struct i2c_client *client, u8 reg, u16 value); + +enum dps850_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_TEMP2_INPUT, + PSU_TEMP3_INPUT, + PSU_FAN1_SPEED, + PSU_MFR_MODEL, + PSU_MFR_SERIAL +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_linear, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out,S_IRUGO, show_vout_by_mode,NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_linear, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out,S_IRUGO, show_linear, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, show_linear, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out,S_IRUGO, show_linear, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp2_input, S_IRUGO, show_linear, NULL, PSU_TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(psu_temp3_input, S_IRUGO, show_linear, NULL, PSU_TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, S_IRUGO, show_ascii, NULL, PSU_MFR_SERIAL); + +static struct attribute *dps850_attributes[] = { + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_temp2_input.dev_attr.attr, + &sensor_dev_attr_psu_temp3_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + NULL +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t show_linear(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct dps850_data *data = dps850_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + case PSU_TEMP2_INPUT: + case PSU_TEMP3_INPUT: + value = data->temp_input[attr->index-PSU_TEMP1_INPUT]; + break; + case PSU_FAN1_SPEED: + value = data->fan_speed; + multiplier = 1; + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t show_ascii(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct dps850_data *data = dps850_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) { + return 0; + } + + switch (attr->index) { + case PSU_MFR_MODEL: /* psu_mfr_model */ + ptr = data->mfr_model + 1; /* The first byte is the length of string. */ + break; + case PSU_MFR_SERIAL: /* psu_mfr_serial */ + ptr = data->mfr_serial + 1; /* The first byte is the length of string. */ + break; + default: + return 0; + } + + return sprintf(buf, "%s\n", ptr); +} + +static ssize_t show_vout_by_mode(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct dps850_data *data = dps850_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + if (!data->valid) { + return 0; + } + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static const struct attribute_group dps850_group = { + .attrs = dps850_attributes, +}; + +static int dps850_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct dps850_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct dps850_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->chip = dev_id->driver_data; + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &dps850_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &dps850_group); +exit_free: + kfree(data); +exit: + + return status; +} + +static int dps850_remove(struct i2c_client *client) +{ + struct dps850_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &dps850_group); + kfree(data); + + return 0; +} + +static const struct i2c_device_id dps850_id[] = { + { "dps850", DPS850 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dps850_id); + +static struct i2c_driver dps850_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "dps850", + }, + .probe = dps850_probe, + .remove = dps850_remove, + .id_table = dps850_id, + .address_list = normal_i2c, +}; + +static int dps850_read_byte(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int dps850_read_word(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_word_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int dps850_write_word(struct i2c_client *client, u8 reg, u16 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_word_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int dps850_read_block(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct dps850_data *dps850_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct dps850_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status, length; + u8 command, buf; + struct reg_data_byte regs_byte[] = { {0x20, &data->vout_mode}}; + struct reg_data_word regs_word[] = { {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x8f, &(data->temp_input[2])}, + {0x90, &data->fan_speed}}; + + dev_dbg(&client->dev, "Starting dps850 update\n"); + data->valid = 0; + + /* Read byte data */ + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = dps850_read_byte(client, regs_byte[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + goto exit; + } + else { + *(regs_byte[i].value) = status; + } + } + + /* Read word data */ + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = dps850_read_word(client, regs_word[i].reg); + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + goto exit; + } + else { + *(regs_word[i].value) = status; + } + } + + /* Read mfr_model */ + command = 0x9a; + length = 1; + memset(data->mfr_model, 0, sizeof(data->mfr_model)); + + /* Read first byte to determine the length of data */ + status = dps850_read_block(client, command, &buf, length); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + status = dps850_read_block(client, command, data->mfr_model, buf+1); + data->mfr_model[buf+1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + + /* Read mfr_serial */ + command = 0x9e; + length = 1; + memset(data->mfr_serial, 0, sizeof(data->mfr_serial)); + + /* Read first byte to determine the length of data */ + status = dps850_read_block(client, command, &buf, length); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + status = dps850_read_block(client, command, data->mfr_serial, buf+1); + data->mfr_serial[buf+1] = '\0'; + + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, status); + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init dps850_init(void) +{ + return i2c_add_driver(&dps850_driver); +} + +static void __exit dps850_exit(void) +{ + i2c_del_driver(&dps850_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("DELTA DPS-850AB driver"); +MODULE_LICENSE("GPL"); + +module_init(dps850_init); +module_exit(dps850_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/fani.c old mode 100644 new mode 100755 index 76fc16b9..03d7c58b --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/fani.c @@ -162,6 +162,10 @@ _onlp_get_fan_direction_on_psu(void) } switch (psu_type) { + case PSU_TYPE_AC_DPS850_F2B: + return ONLP_FAN_STATUS_F2B; + case PSU_TYPE_AC_DPS850_B2F: + return ONLP_FAN_STATUS_B2F; case PSU_TYPE_AC_YM2851_F2B: return ONLP_FAN_STATUS_F2B; case PSU_TYPE_AC_YM2851_B2F: @@ -178,6 +182,7 @@ static int _onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) { int val = 0; + psu_type_t psu_type; info->status |= ONLP_FAN_STATUS_PRESENT; @@ -185,13 +190,33 @@ _onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) */ info->status |= _onlp_get_fan_direction_on_psu(); + + + psu_type = psu_type_get(pid, NULL, 0); + if (psu_type == PSU_TYPE_UNKNOWN) + return ONLP_FAN_STATUS_FAILED; + /* get fan speed */ - if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) { + if (psu_type == PSU_TYPE_AC_DPS850_F2B || psu_type == PSU_TYPE_AC_DPS850_B2F) + { + if (psu_dps850_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) + { info->rpm = val; info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; info->status |= (val == 0) ? ONLP_FAN_STATUS_FAILED : 0; } + } + + if (psu_type == PSU_TYPE_AC_YM2851_F2B || psu_type == PSU_TYPE_AC_YM2851_B2F) + { + if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) + { + info->rpm = val; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + info->status |= (val == 0) ? ONLP_FAN_STATUS_FAILED : 0; + } + } return ONLP_STATUS_OK; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.c old mode 100644 new mode 100755 index dffc3c46..52c64d94 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.c @@ -37,15 +37,14 @@ int psu_serial_number_get(int id, char *serial, int serial_len) { int size = 0; int ret = ONLP_STATUS_OK; - char *prefix = NULL; + char *path = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_mfr_serial) : + PSU2_AC_PMBUS_NODE(psu_mfr_serial) ; if (serial == NULL || serial_len < PSU_SERIAL_NUMBER_LEN) { return ONLP_STATUS_E_PARAM; } - prefix = (id == PSU1_ID) ? PSU1_AC_PMBUS_PREFIX : PSU2_AC_PMBUS_PREFIX; - - ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, "%s%s", prefix, "psu_mfr_serial"); + ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, path); if (ret != ONLP_STATUS_OK || size != PSU_SERIAL_NUMBER_LEN) { return ONLP_STATUS_E_INTERNAL; @@ -89,6 +88,10 @@ psu_type_t psu_type_get(int id, char* modelname, int modelname_len) memcpy(modelname, model, sizeof(model)); } + if (strncmp(model, "DPS-850A", strlen("DPS-850A")) == 0) { + return PSU_TYPE_AC_DPS850_F2B; + } + if (strncmp(model, "YM-2851F", strlen("YM-2851F")) == 0) { return PSU_TYPE_AC_YM2851_F2B; } @@ -123,3 +126,19 @@ int psu_ym2651y_pmbus_info_set(int id, char *node, int value) return ONLP_STATUS_OK; } +int psu_dps850_pmbus_info_get(int id, char *node, int *value) +{ + char *prefix = NULL; + + *value = 0; + + prefix = (id == PSU1_ID) ? PSU1_AC_PMBUS_PREFIX : PSU2_AC_PMBUS_PREFIX; + if (onlp_file_read_int(value, "%s%s", prefix, node) < 0) { + AIM_LOG_ERROR("Unable to read status from file(%s%s)\r\n", prefix, node); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.h old mode 100644 new mode 100755 index 3a37a536..1aacc5ad --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/platform_lib.h @@ -77,13 +77,17 @@ enum onlp_thermal_id typedef enum psu_type { PSU_TYPE_UNKNOWN, PSU_TYPE_AC_YM2851_F2B, - PSU_TYPE_AC_YM2851_B2F + PSU_TYPE_AC_YM2851_B2F, + PSU_TYPE_AC_DPS850_F2B, + PSU_TYPE_AC_DPS850_B2F } psu_type_t; psu_type_t psu_type_get(int id, char* modelname, int modelname_len); int psu_serial_number_get(int id, char *serial, int serial_len); int psu_ym2651y_pmbus_info_get(int id, char *node, int *value); int psu_ym2651y_pmbus_info_set(int id, char *node, int value); +int psu_dps850_pmbus_info_get(int id, char *node, int *value); + #define DEBUG_MODE 0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/psui.c old mode 100644 new mode 100755 index 6e347b6e..a58bdee6 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/onlp/builds/src/module/src/psui.c @@ -82,6 +82,59 @@ psu_ym2651y_info_get(onlp_psu_info_t* info) return ONLP_STATUS_OK; } +static int +psu_dps850_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_AC; + 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_dps850_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_dps850_pmbus_info_get(index, "psu_v_in", &val) == 0) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + if (psu_dps850_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_dps850_pmbus_info_get(index, "psu_i_in", &val) == 0) { + info->caps |= ONLP_PSU_CAPS_IIN; + } + + if (psu_dps850_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + if (psu_dps850_pmbus_info_get(index, "psu_p_in", &val) == 0) { + info->mpin = val; + info->caps |= ONLP_PSU_CAPS_PIN; + } + + psu_serial_number_get(index, info->serial, sizeof(info->serial)); + + return ONLP_STATUS_OK; +} + + /* * Get all information about the given PSU oid. */ @@ -137,6 +190,10 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) psu_type = psu_type_get(index, info->model, sizeof(info->model)); switch (psu_type) { + case PSU_TYPE_AC_DPS850_F2B: + case PSU_TYPE_AC_DPS850_B2F: + ret = psu_dps850_info_get(info); + break; case PSU_TYPE_AC_YM2851_F2B: case PSU_TYPE_AC_YM2851_B2F: ret = psu_ym2651y_info_get(info); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/platform-config/r0/src/python/x86_64_accton_as7816_64x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/platform-config/r0/src/python/x86_64_accton_as7816_64x_r0/__init__.py index 9abc46f4..accf55b5 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/platform-config/r0/src/python/x86_64_accton_as7816_64x_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7816-64x/platform-config/r0/src/python/x86_64_accton_as7816_64x_r0/__init__.py @@ -6,10 +6,16 @@ class OnlPlatform_x86_64_accton_as7816_64x_r0(OnlPlatformAccton, PLATFORM='x86-64-accton-as7816-64x-r0' MODEL="AS7816-64x" SYS_OBJECT_ID=".7816.64" + PSU1_MODEL="/sys/bus/i2c/devices/i2c-10/10-005b/psu_mfr_model" + PSU2_MODEL="/sys/bus/i2c/devices/i2c-9/9-0058/psu_mfr_model" + PSU1_POWER="/sys/bus/i2c/devices/i2c-19/19-0060/psu1_power_good" + PSU2_POWER="/sys/bus/i2c/devices/i2c-19/19-0060/psu2_power_good" + def baseconfig(self): self.insmod('optoe') self.insmod('ym2651y') + self.insmod('dps850') self.insmod('accton_i2c_cpld') for m in [ 'fan', 'cpld1', 'leds' ]: self.insmod("x86-64-accton-as7816-64x-%s.ko" % m) @@ -26,11 +32,13 @@ class OnlPlatform_x86_64_accton_as7816_64x_r0(OnlPlatformAccton, # initiate PSU-1 ('24c02', 0x53, 10), - ('ym2851', 0x5b, 10), + ('dps850', 0x5b, 10), + #('ym2851', 0x5b, 10), # initiate PSU-2 ('24c02', 0x50, 9), - ('ym2851', 0x58, 9), + ('dps850', 0x58, 9), + #('ym2851', 0x58, 9), # initiate chassis fan ('as7816_64x_fan', 0x68, 17), @@ -193,4 +201,39 @@ class OnlPlatform_x86_64_accton_as7816_64x_r0(OnlPlatformAccton, subprocess.call('echo port51 > /sys/bus/i2c/devices/87-0050/port_name', shell=True) subprocess.call('echo port52 > /sys/bus/i2c/devices/88-0050/port_name', shell=True) + PSU_DELTA="DPS-850" + PSU_3Y= "YM-2851F" + if os.path.exists(self.PSU2_POWER): + with open(self.PSU2_POWER, 'r') as fd: + val=int(fd.read()) + if val==1: + if os.path.exists(self.PSU2_MODEL): + with open(self.PSU2_MODEL, 'r') as fd: + f=open(self.PSU2_MODEL) + val_str=f.read() + if int(val_str.find(PSU_3Y))== 0: + subprocess.call('echo 0x58 > /sys/bus/i2c/devices/i2c-9/delete_device', shell=True) + subprocess.call('echo 0x5b > /sys/bus/i2c/devices/i2c-10/delete_device', shell=True) + self.new_i2c_devices([ + ('ym2851', 0x58, 9), + ('ym2851', 0x5b, 10), + ]) + return True + if os.path.exists(self.PSU1_POWER): + with open(self.PSU1_POWER, 'r') as fd: + val=int(fd.read()) + if val==1: + if os.path.exists(self.PSU1_MODEL): + with open(self.PSU1_MODEL, 'r') as fd: + f=open(self.PSU1_MODEL) + val_str=f.read() + if int(val_str.find(PSU_3Y))== 0: + subprocess.call('echo 0x58 > /sys/bus/i2c/devices/i2c-9/delete_device', shell=True) + subprocess.call('echo 0x5b > /sys/bus/i2c/devices/i2c-10/delete_device', shell=True) + self.new_i2c_devices([ + ('ym2851', 0x58, 9), + ('ym2851', 0x5b, 10), + ]) + return True + return True