From ae1fd98724bc375376642891e7eee5f54dcaf1c6 Mon Sep 17 00:00:00 2001 From: brandonchuang Date: Tue, 24 Jan 2017 15:51:28 +0800 Subject: [PATCH] [as7716-32x] Support DC12V(PSU-12V-650)/DC48V(YM-2651V) power supply --- .../builds/x86-64-accton-as7716-32x-fan.c | 39 ++++++ .../builds/x86-64-accton-as7716-32x-psu.c | 127 +++++++++++++++--- .../onlp/builds/src/module/src/fani.c | 43 +++--- .../onlp/builds/src/module/src/platform_lib.c | 75 ++++++++--- .../onlp/builds/src/module/src/platform_lib.h | 7 +- .../onlp/builds/src/module/src/psui.c | 84 ++++++++++-- 6 files changed, 312 insertions(+), 63 deletions(-) diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/modules/builds/x86-64-accton-as7716-32x-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/modules/builds/x86-64-accton-as7716-32x-fan.c index 924374c6..08b02c35 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/modules/builds/x86-64-accton-as7716-32x-fan.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/modules/builds/x86-64-accton-as7716-32x-fan.c @@ -43,6 +43,7 @@ extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); */ static const u8 fan_reg[] = { 0x0F, /* fan 1-6 present status */ + 0x10, /* fan 1-6 direction(0:B2F 1:F2B) */ 0x11, /* fan PWM(for all fan) */ 0x12, /* front fan 1 speed(rpm) */ 0x13, /* front fan 2 speed(rpm) */ @@ -78,6 +79,7 @@ enum fan_id { enum sysfs_fan_attributes { FAN_PRESENT_REG, + FAN_DIRECTION_REG, FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ FAN1_FRONT_SPEED_RPM, FAN2_FRONT_SPEED_RPM, @@ -91,6 +93,12 @@ enum sysfs_fan_attributes { FAN4_REAR_SPEED_RPM, FAN5_REAR_SPEED_RPM, FAN6_REAR_SPEED_RPM, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, FAN1_PRESENT, FAN2_PRESENT, FAN3_PRESENT, @@ -150,6 +158,13 @@ DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3); DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4); DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5); DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6); +/* 6 fan direction attribute in this platform */ +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5); +DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6); /* 1 fan duty cycle attribute in this platform */ DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); @@ -173,6 +188,12 @@ static struct attribute *as7716_32x_fan_attributes[] = { DECLARE_FAN_PRESENT_ATTR(4), DECLARE_FAN_PRESENT_ATTR(5), DECLARE_FAN_PRESENT_ATTR(6), + DECLARE_FAN_DIRECTION_ATTR(1), + DECLARE_FAN_DIRECTION_ATTR(2), + DECLARE_FAN_DIRECTION_ATTR(3), + DECLARE_FAN_DIRECTION_ATTR(4), + DECLARE_FAN_DIRECTION_ATTR(5), + DECLARE_FAN_DIRECTION_ATTR(6), DECLARE_FAN_DUTY_CYCLE_ATTR(), NULL }; @@ -209,6 +230,14 @@ static u32 reg_val_to_speed_rpm(u8 reg_val) return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; } +static u8 reg_val_to_direction(u8 reg_val, enum fan_id id) +{ + u8 mask = (1 << id); + + reg_val &= mask; + + return reg_val ? 1 : 0; +} static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id) { u8 mask = (1 << id); @@ -299,6 +328,16 @@ static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, case FAN6_FAULT: ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); break; + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + ret = sprintf(buf, "%d\n", + reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG], + attr->index - FAN1_DIRECTION)); + break; default: break; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/modules/builds/x86-64-accton-as7716-32x-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/modules/builds/x86-64-accton-as7716-32x-psu.c index 4fd15ae1..79e36a9a 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/modules/builds/x86-64-accton-as7716-32x-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/modules/builds/x86-64-accton-as7716-32x-psu.c @@ -34,14 +34,19 @@ #include #include +#define MAX_MODEL_NAME 16 + +#define DC12V_FAN_DIR_OFFSET 0x34 +#define DC12V_FAN_DIR_LEN 3 + static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf); static int as7716_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); /* Addresses scanned */ -static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; /* Each client has this additional data */ @@ -52,7 +57,8 @@ struct as7716_32x_psu_data { unsigned long last_updated; /* In jiffies */ u8 index; /* PSU index */ u8 status; /* Status(present/power_good) register read from CPLD */ - char model_name[9]; /* Model name, read from eeprom */ + char model_name[MAX_MODEL_NAME+1]; /* Model name, read from eeprom */ + char fan_dir[DC12V_FAN_DIR_LEN+1]; /* DC12V fan direction */ }; static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *dev); @@ -60,19 +66,22 @@ static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *d enum as7716_32x_psu_sysfs_attributes { PSU_PRESENT, PSU_MODEL_NAME, - PSU_POWER_GOOD + PSU_POWER_GOOD, + PSU_FAN_DIR /* For DC12V only */ }; /* sysfs attributes for hwmon */ -static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); -static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); -static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); +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_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 *as7716_32x_psu_attributes[] = { &sensor_dev_attr_psu_present.dev_attr.attr, &sensor_dev_attr_psu_model_name.dev_attr.attr, &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, NULL }; @@ -83,6 +92,10 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, struct as7716_32x_psu_data *data = as7716_32x_psu_update_device(dev); u8 status = 0; + if (!data->valid) { + return -EIO; + } + if (attr->index == PSU_PRESENT) { status = !(data->status >> (1-data->index) & 0x1); } @@ -93,12 +106,25 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, return sprintf(buf, "%d\n", status); } -static ssize_t show_model_name(struct device *dev, struct device_attribute *da, +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf) { + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct as7716_32x_psu_data *data = as7716_32x_psu_update_device(dev); - - return sprintf(buf, "%s\n", data->model_name); + char *ptr = NULL; + + if (!data->valid) { + return -EIO; + } + + if (attr->index == PSU_MODEL_NAME) { + ptr = data->model_name; + } + else { /* PSU_FAN_DIR */ + ptr = data->fan_dir; + } + + return sprintf(buf, "%s\n", ptr); } static const struct attribute_group as7716_32x_psu_group = { @@ -219,6 +245,59 @@ static int as7716_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; + u8 length; + char* model_name; +}; + +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"}, +}; + +static int as7716_32x_psu_model_name_get(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7716_32x_psu_data *data = i2c_get_clientdata(client); + int i, status; + + for (i = 0; i < ARRAY_SIZE(models); i++) { + memset(data->model_name, 0, sizeof(data->model_name)); + + status = as7716_32x_psu_read_block(client, models[i].offset, + data->model_name, models[i].length); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x%x)\n", + client->addr, models[i].offset); + return status; + } + else { + data->model_name[models[i].length] = '\0'; + } + + /* 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) { + return 0; + } + else { + data->model_name[0] = '\0'; + } + } + + return -ENODATA; +} + static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -231,6 +310,7 @@ static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *d int status; int power_good = 0; + data->valid = 0; dev_dbg(&client->dev, "Starting as7716_32x update\n"); /* Read psu status */ @@ -238,6 +318,7 @@ static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *d if (status < 0) { dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); + goto exit; } else { data->status = status; @@ -245,18 +326,27 @@ static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *d /* Read model name */ memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->fan_dir, 0, sizeof(data->fan_dir)); power_good = (data->status >> (3-data->index) & 0x1); if (power_good) { - status = as7716_32x_psu_read_block(client, 0x20, data->model_name, - ARRAY_SIZE(data->model_name)-1); - - if (status < 0) { - data->model_name[0] = '\0'; - dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + if (as7716_32x_psu_model_name_get(dev) < 0) { + goto exit; } - else { - data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; + + if (strncmp(data->model_name, + models[PSU_TYPE_DC_12V].model_name, + models[PSU_TYPE_DC_12V].length) == 0) { + /* Read fan direction */ + status = as7716_32x_psu_read_block(client, DC12V_FAN_DIR_OFFSET, + data->fan_dir, DC12V_FAN_DIR_LEN); + + if (status < 0) { + data->fan_dir[0] = '\0'; + dev_dbg(&client->dev, "unable to read fan direction from (0x%x) offset(0x%x)\n", + client->addr, DC12V_FAN_DIR_OFFSET); + goto exit; + } } } @@ -264,6 +354,7 @@ static struct as7716_32x_psu_data *as7716_32x_psu_update_device(struct device *d data->valid = 1; } +exit: mutex_unlock(&data->update_lock); return data; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/fani.c index e435ec94..58e436b5 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/fani.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/fani.c @@ -52,19 +52,20 @@ typedef struct fan_path_S char present[LEN_FILE_NAME]; char status[LEN_FILE_NAME]; char speed[LEN_FILE_NAME]; + char direction[LEN_FILE_NAME]; char ctrl_speed[LEN_FILE_NAME]; char r_speed[LEN_FILE_NAME]; }fan_path_T; #define _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) \ { #prj"fan"#id"_present", #prj"fan"#id"_fault", #prj"fan"#id"_front_speed_rpm", \ - #prj"fan"#id"_duty_cycle_percentage", #prj"fan"#id"_rear_speed_rpm" } + #prj"fan"#id"_direction", #prj"fan"#id"_duty_cycle_percentage", #prj"fan"#id"_rear_speed_rpm" } #define MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) #define MAKE_FAN_PATH_ON_PSU(folder) \ - {#folder"/psu_fan1_fault", #folder"/psu_fan1_speed_rpm", \ - #folder"/psu_fan1_duty_cycle_percentage", "" } + {"", #folder"/psu_fan1_fault", #folder"/psu_fan1_speed_rpm", \ + "", #folder"/psu_fan1_duty_cycle_percentage", "" } static fan_path_T fan_path[] = /* must map with onlp_fan_id */ { @@ -130,12 +131,8 @@ onlp_fan_info_t linfo[] = { if (close(fd) == -1) \ return ONLP_STATUS_E_INTERNAL -/* There is no CPLD register for reading fan direction on this platform, - * to read fan direction, we need to read from PSU-fan, - * the direction of PSU-fan and chassis-fan are the same. - */ static uint32_t -_onlp_fani_info_get_fan_direction(void) +_onlp_fani_info_get_psu_fan_direction(void) { /* Try to read direction from PSU1. * If PSU1 is not valid, read from PSU2 @@ -150,12 +147,18 @@ _onlp_fani_info_get_fan_direction(void) continue; } - if (PSU_TYPE_AC_F2B == psu_type) { - return ONLP_FAN_STATUS_F2B; - } - else { - return ONLP_FAN_STATUS_B2F; - } + switch (psu_type) { + case PSU_TYPE_AC_F2B: + 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_DC_48V_B2F: + case PSU_TYPE_DC_12V_B2F: + return ONLP_FAN_STATUS_B2F; + default: + return 0; + }; } return 0; @@ -186,9 +189,15 @@ _onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info) return ONLP_STATUS_OK; } - /* get fan direction (both : the same) + /* get fan/fanr direction (both : the same) */ - info->status |= _onlp_fani_info_get_fan_direction(); + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].direction); + OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len); + + if (atoi(r_data) == 0) /*B2F*/ + info->status |= ONLP_FAN_STATUS_B2F; + else + info->status |= ONLP_FAN_STATUS_F2B; /* get fan speed (take the min from two speeds) */ @@ -217,7 +226,7 @@ _onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) /* get fan direction */ - info->status |= _onlp_fani_info_get_fan_direction(); + info->status |= _onlp_fani_info_get_psu_fan_direction(); /* get fan fault status */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/platform_lib.c index 9772c70f..b4ef2d04 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/platform_lib.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/platform_lib.c @@ -66,7 +66,7 @@ int deviceNodeWriteInt(char *filename, int value, int data_len) char buf[8] = {0}; sprintf(buf, "%d", value); - return deviceNodeWrite(filename, buf, sizeof(buf)-1, data_len); + return deviceNodeWrite(filename, buf, (int)strlen(buf), data_len); } int deviceNodeReadBinary(char *filename, char *buffer, int buf_size, int data_len) @@ -115,9 +115,9 @@ int deviceNodeReadString(char *filename, char *buffer, int buf_size, int data_le return ret; } -#define I2C_PSU_MODEL_NAME_LEN 9 +#define I2C_PSU_MODEL_NAME_LEN 11 #define I2C_PSU_FAN_DIR_LEN 3 - +#include psu_type_t get_psu_type(int id, char* modelname, int modelname_len) { char *node = NULL; @@ -131,27 +131,70 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len) return PSU_TYPE_UNKNOWN; } - if (strncmp(model_name, "YM-2651Y", strlen("YM-2651Y")) != 0) { - return PSU_TYPE_UNKNOWN; + if(isspace(model_name[strlen(model_name)-1])) { + model_name[strlen(model_name)-1] = 0; } - if (modelname) { - strncpy(modelname, model_name, modelname_len-1); + if (strncmp(model_name, "YM-2651Y", 8) == 0) { + if (modelname) { + strncpy(modelname, model_name, 8); + } + + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + if (deviceNodeReadString(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_AC_F2B; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_AC_B2F; + } } - node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + if (strncmp(model_name, "YM-2651V", 8) == 0) { + if (modelname) { + strncpy(modelname, model_name, 8); + } - if (deviceNodeReadString(node, fan_dir, sizeof(fan_dir), 0) != 0) { - return PSU_TYPE_UNKNOWN; + node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir); + if (deviceNodeReadString(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { + return PSU_TYPE_DC_48V_F2B; + } + + if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { + return PSU_TYPE_DC_48V_B2F; + } } - if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) { - return PSU_TYPE_AC_F2B; - } + if (strncmp(model_name, "PSU-12V-750", 11) == 0) { + if (modelname) { + strncpy(modelname, model_name, 11); + } - if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) { - return PSU_TYPE_AC_B2F; - } + node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_fan_dir) : PSU2_AC_HWMON_NODE(psu_fan_dir); + if (deviceNodeReadString(node, fan_dir, sizeof(fan_dir), 0) != 0) { + return PSU_TYPE_UNKNOWN; + } + + if (strncmp(fan_dir, "F2B", 3) == 0) { + return PSU_TYPE_DC_12V_F2B; + } + + if (strncmp(fan_dir, "B2F", 3) == 0) { + return PSU_TYPE_DC_12V_B2F; + } + + if (strncmp(fan_dir, "NON", 3) == 0) { + return PSU_TYPE_DC_12V_FANLESS; + } + } return PSU_TYPE_UNKNOWN; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/platform_lib.h index 116b2751..6c88df33 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/platform_lib.h +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/platform_lib.h @@ -55,7 +55,12 @@ 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_B2F, + PSU_TYPE_DC_48V_F2B, + PSU_TYPE_DC_48V_B2F, + PSU_TYPE_DC_12V_FANLESS, + PSU_TYPE_DC_12V_F2B, + PSU_TYPE_DC_12V_B2F } psu_type_t; psu_type_t get_psu_type(int id, char* modelname, int modelname_len); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/psui.c index b7b5d707..562901d2 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7716-32x/onlp/builds/src/module/src/psui.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7716-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_ym2651y_pmbus_info_get(int id, char *node, int *value) +psu_ym2651_pmbus_info_get(int id, char *node, int *value) { int ret = 0; char buf[PSU_NODE_MAX_INT_LEN + 1] = {0}; @@ -99,15 +99,11 @@ onlp_psui_init(void) } static int -psu_ym2651y_info_get(onlp_psu_info_t* info) +psu_ym2651_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; } @@ -117,20 +113,70 @@ psu_ym2651y_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_ym2651y_pmbus_info_get(index, "psu_v_out", &val) == 0) { + if (psu_ym2651_pmbus_info_get(index, "psu_v_out", &val) == 0) { info->mvout = val; info->caps |= ONLP_PSU_CAPS_VOUT; } - if (psu_ym2651y_pmbus_info_get(index, "psu_i_out", &val) == 0) { + if (psu_ym2651_pmbus_info_get(index, "psu_i_out", &val) == 0) { info->miout = val; info->caps |= ONLP_PSU_CAPS_IOUT; } - if (psu_ym2651y_pmbus_info_get(index, "psu_p_out", &val) == 0) { + if (psu_ym2651_pmbus_info_get(index, "psu_p_out", &val) == 0) { info->mpout = val; info->caps |= ONLP_PSU_CAPS_POUT; - } + } + + return ONLP_STATUS_OK; +} + +#include +#define DC12V_750_REG_TO_CURRENT(low, high) (((low << 4 | high >> 4) * 20 * 1000) / 754) +#define DC12V_750_REG_TO_VOLTAGE(low, high) ((low << 4 | high >> 4) * 25) + +static int +psu_dc12v_750_info_get(onlp_psu_info_t* info) +{ + int pid = ONLP_OID_ID_GET(info->hdr.id); + int bus = (PSU1_ID == pid) ? 18 : 17; + int iout_low, iout_high; + int vout_low, vout_high; + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_DC12; + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + + /* Get current + */ + iout_low = onlp_i2c_readb(bus, 0x6f, 0x0, ONLP_I2C_F_FORCE); + iout_high = onlp_i2c_readb(bus, 0x6f, 0x1, ONLP_I2C_F_FORCE); + + if ((iout_low >= 0) && (iout_high >= 0)) { + info->miout = DC12V_750_REG_TO_CURRENT(iout_low, iout_high); + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + /* Get voltage + */ + vout_low = onlp_i2c_readb(bus, 0x6f, 0x2, ONLP_I2C_F_FORCE); + vout_high = onlp_i2c_readb(bus, 0x6f, 0x3, ONLP_I2C_F_FORCE); + + if ((vout_low >= 0) && (vout_high >= 0)) { + info->mvout = DC12V_750_REG_TO_VOLTAGE(vout_low, vout_high); + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + /* Get power based on current and voltage + */ + if ((info->caps & ONLP_PSU_CAPS_IOUT) && (info->caps & ONLP_PSU_CAPS_VOUT)) { + info->mpout = (info->miout * info->mvout) / 1000; + info->caps |= ONLP_PSU_CAPS_POUT; + } return ONLP_STATUS_OK; } @@ -191,7 +237,23 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) switch (psu_type) { case PSU_TYPE_AC_F2B: case PSU_TYPE_AC_B2F: - ret = psu_ym2651y_info_get(info); + info->caps = ONLP_PSU_CAPS_AC; + ret = psu_ym2651_info_get(info); + break; + case PSU_TYPE_DC_48V_F2B: + case PSU_TYPE_DC_48V_B2F: + info->caps = ONLP_PSU_CAPS_DC48; + ret = psu_ym2651_info_get(info); + break; + case PSU_TYPE_DC_12V_F2B: + case PSU_TYPE_DC_12V_B2F: + case PSU_TYPE_DC_12V_FANLESS: + ret = psu_dc12v_750_info_get(info); + break; + case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + info->status &= ~ONLP_PSU_STATUS_FAILED; + ret = ONLP_STATUS_OK; break; default: ret = ONLP_STATUS_E_UNSUPPORTED;