Merge branch 'master' of github.com:opencomputeproject/OpenNetworkLinux

This commit is contained in:
Jeffrey Townsend
2017-06-15 16:43:58 +00:00
16 changed files with 857 additions and 253 deletions

View File

@@ -32,14 +32,22 @@
#include <linux/slab.h>
#include <linux/delay.h>
#define PSU_STATUS_I2C_ADDR 0x60
#define PSU_STATUS_I2C_REG_OFFSET 0x2
#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1)))
#define IS_PRESENT(id, value) (!(value & BIT(id*4)))
static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf);
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 int as6712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
extern int as6712_32x_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
static int as6712_32x_psu_model_name_get(struct device *dev);
/* 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
*/
@@ -56,6 +64,7 @@ struct as6712_32x_psu_data {
static struct as6712_32x_psu_data *as6712_32x_psu_update_device(struct device *dev);
enum as6712_32x_psu_sysfs_attributes {
PSU_INDEX,
PSU_PRESENT,
PSU_MODEL_NAME,
PSU_POWER_GOOD
@@ -63,17 +72,28 @@ enum as6712_32x_psu_sysfs_attributes {
/* sysfs attributes for hwmon
*/
static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX);
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 struct attribute *as6712_32x_psu_attributes[] = {
&sensor_dev_attr_psu_index.dev_attr.attr,
&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,
NULL
};
static ssize_t show_index(struct device *dev, struct device_attribute *da,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct as6712_32x_psu_data *data = i2c_get_clientdata(client);
return sprintf(buf, "%d\n", data->index);
}
static ssize_t show_status(struct device *dev, struct device_attribute *da,
char *buf)
{
@@ -81,11 +101,15 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da,
struct as6712_32x_psu_data *data = as6712_32x_psu_update_device(dev);
u8 status = 0;
if (!data->valid) {
return sprintf(buf, "0\n");
}
if (attr->index == PSU_PRESENT) {
status = !(data->status >> ((data->index-1)*4) & 0x1);
status = IS_PRESENT(data->index, data->status);
}
else { /* PSU_POWER_GOOD */
status = data->status >> ((data->index-1)*4 + 1) & 0x1;
status = IS_POWER_GOOD(data->index, data->status);
}
return sprintf(buf, "%d\n", status);
@@ -96,6 +120,17 @@ static ssize_t show_model_name(struct device *dev, struct device_attribute *da,
{
struct as6712_32x_psu_data *data = as6712_32x_psu_update_device(dev);
if (!data->valid) {
return 0;
}
if (!IS_PRESENT(data->index, data->status)) {
return 0;
}
if (as6712_32x_psu_model_name_get(dev) < 0) {
return -ENXIO;
}
return sprintf(buf, "%s\n", data->model_name);
}
@@ -122,6 +157,7 @@ static int as6712_32x_psu_probe(struct i2c_client *client,
i2c_set_clientdata(client, data);
data->valid = 0;
data->index = dev_id->driver_data;
mutex_init(&data->update_lock);
dev_info(&client->dev, "chip found\n");
@@ -138,14 +174,6 @@ static int as6712_32x_psu_probe(struct i2c_client *client,
goto exit_remove;
}
/* Update PSU index */
if (client->addr == 0x50 || client->addr == 0x38) {
data->index = 1;
}
else if (client->addr == 0x53 || client->addr == 0x3b) {
data->index = 2;
}
dev_info(&client->dev, "%s: psu '%s'\n",
dev_name(data->hwmon_dev), client->name);
@@ -171,8 +199,15 @@ static int as6712_32x_psu_remove(struct i2c_client *client)
return 0;
}
enum psu_index
{
as6712_32x_psu1,
as6712_32x_psu2
};
static const struct i2c_device_id as6712_32x_psu_id[] = {
{ "as6712_32x_psu", 0 },
{ "as6712_32x_psu1", as6712_32x_psu1 },
{ "as6712_32x_psu2", as6712_32x_psu2 },
{}
};
MODULE_DEVICE_TABLE(i2c, as6712_32x_psu_id);
@@ -217,6 +252,75 @@ static int as6712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *
return result;
}
enum psu_type {
PSU_YM_2401_JCR, /* AC110V - F2B */
PSU_YM_2401_JDR, /* AC110V - B2F */
PSU_CPR_4011_4M11, /* AC110V - F2B */
PSU_CPR_4011_4M21, /* AC110V - B2F */
PSU_CPR_6011_2M11, /* AC110V - F2B */
PSU_CPR_6011_2M21, /* AC110V - B2F */
PSU_UM400D_01G, /* DC48V - F2B */
PSU_UM400D01_01G /* DC48V - B2F */
};
struct model_name_info {
enum psu_type type;
u8 offset;
u8 length;
char* model_name;
};
struct model_name_info models[] = {
{PSU_YM_2401_JCR, 0x20, 11, "YM-2401JCR"},
{PSU_YM_2401_JDR, 0x20, 11, "YM-2401JDR"},
{PSU_CPR_4011_4M11, 0x26, 13, "CPR-4011-4M11"},
{PSU_CPR_4011_4M21, 0x26, 13, "CPR-4011-4M21"},
{PSU_CPR_6011_2M11, 0x26, 13, "CPR-6011-2M11"},
{PSU_CPR_6011_2M21, 0x26, 13, "CPR-6011-2M21"},
{PSU_UM400D_01G, 0x50, 9, "um400d01G"},
{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"},
};
static int as6712_32x_psu_model_name_get(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct as6712_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 = as6712_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';
}
if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR) {
/* Skip the meaningless data byte 8*/
data->model_name[8] = data->model_name[9];
data->model_name[9] = data->model_name[10];
data->model_name[10] = '\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 as6712_32x_psu_data *as6712_32x_psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -226,56 +330,27 @@ static struct as6712_32x_psu_data *as6712_32x_psu_update_device(struct device *d
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int status;
int present = 0;
int status = -1;
dev_dbg(&client->dev, "Starting as6712_32x update\n");
dev_dbg(&client->dev, "Starting as6812_32x update\n");
data->valid = 0;
/* Read psu status */
status = as6712_32x_i2c_cpld_read(0x60, 0x2);
status = as6712_32x_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
if (status < 0) {
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status);
dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status);
goto exit;
}
else {
data->status = status;
}
/* Read model name */
memset(data->model_name, 0, sizeof(data->model_name));
present = !(data->status >> ((data->index-1)*4) & 0x1);
if (present) {
u8 command;
int model_name_len = 0;
if (client->addr == 0x38 || client->addr == 0x3b) {
/* cpr_4011_4mxx AC power */
command = 0x26;
model_name_len = 13;
}
else { /* 0x50 & 0x53 */
/* um400d01x DC power */
command = 0x50;
model_name_len = 13;
}
status = as6712_32x_psu_read_block(client,command,data->model_name,
model_name_len);
if (status < 0) {
data->model_name[0] = '\0';
dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr);
}
else {
data->model_name[model_name_len] = '\0';
}
}
data->last_updated = jiffies;
data->valid = 1;
}
exit:
mutex_unlock(&data->update_lock);
return data;

View File

@@ -24,7 +24,8 @@
*
***********************************************************/
#include <onlp/platformi/fani.h>
#include <onlplib/mmap.h>
#include <unistd.h>
#include <onlplib/file.h>
#include <fcntl.h>
#include "platform_lib.h"
@@ -128,6 +129,22 @@ onlp_fan_info_t linfo[] = {
if (close(fd) == -1) \
return ONLP_STATUS_E_INTERNAL
/* PSU relative marco */
#define SET_PSU_TYPE_AC_F2B_FAN(info) \
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_F2B); \
info->caps |= ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE
#define SET_PSU_TYPE_AC_B2F_FAN(info) \
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F); \
info->caps |= ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE
#define SET_PSU_TYPE_UM400D_F2B_FAN(info) \
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_F2B)
#define SET_PSU_TYPE_UM400D_B2F_FAN(info) \
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F)
static int
_onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info)
{
@@ -178,10 +195,26 @@ _onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info)
return ONLP_STATUS_OK;
}
static int
_onlp_fani_info_get_fan_on_psu_ym2401(int pid, onlp_fan_info_t* info)
{
int val = 0;
/* get fan status
*/
if (psu_ym2401_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) {
info->status |= (val > 0) ? 0 : ONLP_FAN_STATUS_FAILED;
info->rpm = val;
info->percentage = (info->rpm * 100) / 21600;
}
return ONLP_STATUS_OK;
}
static int
_onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info)
{
int psu_id, is_ac = 0;
int psu_id;
int fd, len, nbytes = 10;
char r_data[10] = {0};
char fullpath[80] = {0};
@@ -197,28 +230,26 @@ _onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info)
switch (psu_type) {
case PSU_TYPE_AC_F2B:
is_ac = 1;
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_F2B);
info->caps |= ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE;
case PSU_TYPE_AC_COMPUWARE_F2B:
case PSU_TYPE_AC_3YPOWER_F2B:
SET_PSU_TYPE_AC_F2B_FAN(info);
break;
case PSU_TYPE_AC_B2F:
is_ac = 1;
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F);
info->caps |= ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE;
case PSU_TYPE_AC_COMPUWARE_B2F:
case PSU_TYPE_AC_3YPOWER_B2F:
SET_PSU_TYPE_AC_B2F_FAN(info);
break;
case PSU_TYPE_DC_48V_F2B:
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_F2B);
SET_PSU_TYPE_UM400D_F2B_FAN(info);
break;
case PSU_TYPE_DC_48V_B2F:
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F);
break;
SET_PSU_TYPE_UM400D_B2F_FAN(info);
break;
default:
DEBUG_PRINT("[Debug][%s][%d][psu_type=%d]\n", __FUNCTION__, __LINE__, psu_type);
break;
}
if (is_ac)
if (psu_type == PSU_TYPE_AC_COMPUWARE_F2B ||
psu_type == PSU_TYPE_AC_COMPUWARE_B2F )
{
/* get fan fault status
*/
@@ -234,8 +265,12 @@ _onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info)
info->rpm = atoi(r_data);
/* get speed percentage from rpm */
info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED;
info->status |= ONLP_FAN_STATUS_PRESENT;
info->percentage = (info->rpm * 100)/MAX_PSU_FAN_SPEED;
}
else if (psu_type == PSU_TYPE_AC_3YPOWER_F2B ||
psu_type == PSU_TYPE_AC_3YPOWER_B2F )
{
return _onlp_fani_info_get_fan_on_psu_ym2401(psu_id, info);
}
return ONLP_STATUS_OK;
@@ -324,8 +359,21 @@ onlp_fani_percentage_set(onlp_oid_t id, int p)
{
case FAN_1_ON_PSU1:
case FAN_1_ON_PSU2:
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].ctrl_speed);
{
int psu_id;
psu_type_t psu_type;
psu_id = local_id - FAN_1_ON_PSU1 + 1;
psu_type = get_psu_type(psu_id, NULL, 0);
if (psu_type == PSU_TYPE_AC_3YPOWER_F2B ||
psu_type == PSU_TYPE_AC_3YPOWER_B2F ) {
return psu_ym2401_pmbus_info_set(psu_id, "psu_fan1_duty_cycle_percentage", p);
}
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].ctrl_speed);
break;
}
case FAN_1_ON_MAIN_BOARD:
case FAN_2_ON_MAIN_BOARD:
case FAN_3_ON_MAIN_BOARD:

View File

@@ -23,12 +23,13 @@
*
*
***********************************************************/
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <onlp/onlp.h>
#include <onlplib/file.h>
#include <AIM/aim.h>
#include "platform_lib.h"
@@ -64,9 +65,9 @@ int deviceNodeWrite(char *filename, char *buffer, int buf_size, int data_len)
int deviceNodeWriteInt(char *filename, int value, int data_len)
{
char buf[8] = {0};
sprintf(buf, "%d", value);
return deviceNodeWrite(filename, buf, (int)strlen(buf), data_len);
return deviceNodeWrite(filename, buf, sizeof(buf)-1, data_len);
}
int deviceNodeReadBinary(char *filename, char *buffer, int buf_size, int data_len)
@@ -102,20 +103,25 @@ int deviceNodeReadString(char *filename, char *buffer, int buf_size, int data_le
{
int ret;
if (data_len >= buf_size) {
if (data_len >= buf_size || data_len < 0) {
return -1;
}
ret = deviceNodeReadBinary(filename, buffer, buf_size-1, data_len);
if (ret == 0) {
buffer[buf_size-1] = '\0';
if (data_len) {
buffer[data_len] = '\0';
}
else {
buffer[buf_size-1] = '\0';
}
}
return ret;
}
#define I2C_PSU_MODEL_NAME_LEN 13
#define STRLEN(x) (sizeof(x) - 1)
psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
{
@@ -123,41 +129,122 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0};
/* Check AC model name */
node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_model_name) : PSU2_AC_HWMON_NODE(psu_model_name);
node = (id == PSU1_ID) ? PSU1_AC_EEPROM_NODE(psu_model_name) : PSU2_AC_EEPROM_NODE(psu_model_name);
if (deviceNodeReadString(node, model_name, sizeof(model_name), 0) == 0) {
if (strncmp(model_name, "CPR-4011-4M11", strlen("CPR-4011-4M11")) == 0) {
if (strncmp(model_name, "CPR-4011-4M11", STRLEN("CPR-4011-4M11")) == 0) {
if (modelname) {
strncpy(modelname, model_name, modelname_len-1);
strncpy(modelname, model_name, sizeof(model_name));
}
return PSU_TYPE_AC_F2B;
return PSU_TYPE_AC_COMPUWARE_F2B;
}
else if (strncmp(model_name, "CPR-4011-4M21", strlen("CPR-4011-4M21")) == 0) {
else if (strncmp(model_name, "CPR-4011-4M21", STRLEN("CPR-4011-4M21")) == 0) {
if (modelname) {
strncpy(modelname, model_name, modelname_len-1);
strncpy(modelname, model_name, sizeof(model_name));
}
return PSU_TYPE_AC_B2F;
return PSU_TYPE_AC_COMPUWARE_B2F;
}
else if (strncmp(model_name, "CPR-6011-2M11", STRLEN("CPR-6011-2M11")) == 0) {
if (modelname) {
strncpy(modelname, model_name, sizeof(model_name));
}
return PSU_TYPE_AC_COMPUWARE_F2B;
}
else if (strncmp(model_name, "CPR-6011-2M21", STRLEN("CPR-6011-2M21")) == 0) {
if (modelname) {
strncpy(modelname, model_name, sizeof(model_name));
}
return PSU_TYPE_AC_COMPUWARE_B2F;
}
}
/* Check 3Y-Power AC model name */
memset(model_name, 0, sizeof(model_name));
node = (id == PSU1_ID) ? PSU1_AC_3YPOWER_EEPROM_NODE(psu_model_name) : PSU2_AC_3YPOWER_EEPROM_NODE(psu_model_name);
if (deviceNodeReadString(node, model_name, sizeof(model_name), 0) == 0) {
if (strncmp(model_name, "YM-2401JCR", STRLEN("YM-2401JCR")) == 0) {
if (modelname) {
model_name[STRLEN("YM-2401JCR")] = 0;
strncpy(modelname, model_name, 11);
}
return PSU_TYPE_AC_3YPOWER_F2B;
}
else if (strncmp(model_name, "YM-2401JDR", STRLEN("YM-2401JDR")) == 0) {
if (modelname) {
model_name[STRLEN("YM-2401JDR")] = 0;
strncpy(modelname, model_name, 11);
}
return PSU_TYPE_AC_3YPOWER_B2F;
}
}
/* Check DC model name */
memset(model_name, 0, sizeof(model_name));
node = (id == PSU1_ID) ? PSU1_DC_HWMON_NODE(psu_model_name) : PSU2_DC_HWMON_NODE(psu_model_name);
node = (id == PSU1_ID) ? PSU1_DC_EEPROM_NODE(psu_model_name) : PSU2_DC_EEPROM_NODE(psu_model_name);
if (deviceNodeReadString(node, model_name, sizeof(model_name), 0) == 0) {
if (strncmp(model_name, "um400d01G", strlen("um400d01G")) == 0) {
if (strncmp(model_name, "um400d01G", STRLEN("um400d01G")) == 0) {
if (modelname) {
strncpy(modelname, model_name, modelname_len-1);
model_name[STRLEN("um400d01G")] = 0;
strncpy(modelname, model_name, 10);
}
return PSU_TYPE_DC_48V_B2F;
}
else if (strncmp(model_name, "um400d01-01G", strlen("um400d01-01G")) == 0) {
else if (strncmp(model_name, "um400d01-01G", STRLEN("um400d01-01G")) == 0) {
if (modelname) {
strncpy(modelname, model_name, modelname_len-1);
model_name[STRLEN("um400d01-01G")] = 0;
strncpy(modelname, model_name, 13);
}
return PSU_TYPE_DC_48V_F2B;
}
}
}
return PSU_TYPE_UNKNOWN;
}
int psu_ym2401_pmbus_info_get(int id, char *node, int *value)
{
int ret = 0;
char path[64] = {0};
*value = 0;
if (PSU1_ID == id) {
sprintf(path, "%s%s", PSU1_AC_3YPOWER_PMBUS_PREFIX, node);
}
else {
sprintf(path, "%s%s", PSU2_AC_3YPOWER_PMBUS_PREFIX, node);
}
if (onlp_file_read_int(value, path) < 0) {
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", path);
return ONLP_STATUS_E_INTERNAL;
}
return ret;
}
int psu_ym2401_pmbus_info_set(int id, char *node, int value)
{
char path[64] = {0};
switch (id) {
case PSU1_ID:
sprintf(path, "%s%s", PSU1_AC_3YPOWER_PMBUS_PREFIX, node);
break;
case PSU2_ID:
sprintf(path, "%s%s", PSU2_AC_3YPOWER_PMBUS_PREFIX, node);
break;
default:
return ONLP_STATUS_E_UNSUPPORTED;
};
if (deviceNodeWriteInt(path, value, 0) < 0) {
AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}

View File

@@ -36,22 +36,24 @@
#define PSU1_ID 1
#define PSU2_ID 2
#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/35-003c/"
#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/36-003f/"
#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/35-003c/" /* Compuware psu */
#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/36-003f/" /* Compuware psu */
#define PSU1_AC_3YPOWER_PMBUS_PREFIX "/sys/bus/i2c/devices/35-0058/" /* 3YPower psu */
#define PSU2_AC_3YPOWER_PMBUS_PREFIX "/sys/bus/i2c/devices/36-005b/" /* 3YPower psu */
#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node
#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node
#define PSU1_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/35-0038/"
#define PSU1_DC_EEPROM_PREFIX "/sys/bus/i2c/devices/35-0050/"
#define PSU2_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/36-003b/"
#define PSU2_DC_EEPROM_PREFIX "/sys/bus/i2c/devices/36-0053/"
#define PSU1_AC_3YPOWER_EEPROM_PREFIX "/sys/bus/i2c/devices/35-0050/"
#define PSU2_AC_3YPOWER_EEPROM_PREFIX "/sys/bus/i2c/devices/36-0053/"
#define PSU1_AC_HWMON_PREFIX "/sys/bus/i2c/devices/35-0038/"
#define PSU2_AC_HWMON_PREFIX "/sys/bus/i2c/devices/36-003b/"
#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node
#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node
#define PSU1_DC_HWMON_PREFIX "/sys/bus/i2c/devices/35-0050/"
#define PSU2_DC_HWMON_PREFIX "/sys/bus/i2c/devices/36-0053/"
#define PSU1_DC_HWMON_NODE(node) PSU1_DC_HWMON_PREFIX#node
#define PSU2_DC_HWMON_NODE(node) PSU2_DC_HWMON_PREFIX#node
#define PSU1_AC_EEPROM_NODE(node) PSU1_AC_EEPROM_PREFIX#node
#define PSU1_DC_EEPROM_NODE(node) PSU1_DC_EEPROM_PREFIX#node
#define PSU2_AC_EEPROM_NODE(node) PSU2_AC_EEPROM_PREFIX#node
#define PSU2_DC_EEPROM_NODE(node) PSU2_DC_EEPROM_PREFIX#node
#define PSU1_AC_3YPOWER_EEPROM_NODE(node) PSU1_AC_3YPOWER_EEPROM_PREFIX#node
#define PSU2_AC_3YPOWER_EEPROM_NODE(node) PSU2_AC_3YPOWER_EEPROM_PREFIX#node
#define IDPROM_PATH "/sys/class/i2c-adapter/i2c-1/1-0057/eeprom"
@@ -61,20 +63,25 @@ 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_COMPUWARE_F2B,
PSU_TYPE_AC_COMPUWARE_B2F,
PSU_TYPE_AC_3YPOWER_F2B,
PSU_TYPE_AC_3YPOWER_B2F,
PSU_TYPE_DC_48V_F2B,
PSU_TYPE_DC_48V_B2F
} psu_type_t;
psu_type_t get_psu_type(int id, char* modelname, int modelname_len);
int psu_ym2401_pmbus_info_get(int id, char *node, int *value);
int psu_ym2401_pmbus_info_set(int id, char *node, int value);
#define DEBUG_MODE 0
#if (DEBUG_MODE == 1)
#define DEBUG_PRINT(format, ...) printf(format, __VA_ARGS__)
#define DEBUG_PRINT(fmt, args...) \
printf("%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args)
#else
#define DEBUG_PRINT(format, ...)
#define DEBUG_PRINT(fmt, args...)
#endif
#endif /* __PLATFORM_LIB_H__ */

View File

@@ -24,7 +24,6 @@
*
***********************************************************/
#include <onlp/platformi/psui.h>
#include <onlplib/mmap.h>
#include <stdio.h>
#include <string.h>
#include "platform_lib.h"
@@ -43,7 +42,7 @@
} while(0)
static int
psu_status_info_get(int id, char *node, int *value)
psu_status_info_get(int id, int is_ac, char *node, int *value)
{
int ret = 0;
char buf[PSU_NODE_MAX_INT_LEN + 1] = {0};
@@ -52,12 +51,12 @@ psu_status_info_get(int id, char *node, int *value)
*value = 0;
if (PSU1_ID == id) {
sprintf(node_path, "%s%s", PSU1_AC_HWMON_PREFIX, node);
sprintf(node_path, "%s%s", is_ac ? PSU1_AC_EEPROM_PREFIX : PSU1_DC_EEPROM_PREFIX, node);
}
else if (PSU2_ID == id) {
sprintf(node_path, "%s%s", PSU2_AC_HWMON_PREFIX, node);
sprintf(node_path, "%s%s", is_ac ? PSU2_AC_EEPROM_PREFIX : PSU2_DC_EEPROM_PREFIX, node);
}
ret = deviceNodeReadString(node_path, buf, sizeof(buf), 0);
if (ret == 0) {
@@ -92,25 +91,6 @@ psu_cpr_4011_pmbus_info_get(int id, char *node, int *value)
return ret;
}
int
psu_um400d_info_get(onlp_psu_info_t* info)
{
int index = ONLP_OID_ID_GET(info->hdr.id);
/* Set capability
*/
info->caps = ONLP_PSU_CAPS_DC48;
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);
return ONLP_STATUS_OK;
}
int
onlp_psui_init(void)
{
@@ -169,6 +149,62 @@ psu_cpr_4011_info_get(onlp_psu_info_t* info)
return ONLP_STATUS_OK;
}
int
psu_um400d_info_get(onlp_psu_info_t* info)
{
int index = ONLP_OID_ID_GET(info->hdr.id);
/* Set capability
*/
info->caps = ONLP_PSU_CAPS_DC48;
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);
return ONLP_STATUS_OK;
}
static int
psu_ym2401_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_ym2401_pmbus_info_get(index, "psu_v_out", &val) == 0) {
info->mvout = val;
info->caps |= ONLP_PSU_CAPS_VOUT;
}
if (psu_ym2401_pmbus_info_get(index, "psu_i_out", &val) == 0) {
info->miout = val;
info->caps |= ONLP_PSU_CAPS_IOUT;
}
if (psu_ym2401_pmbus_info_get(index, "psu_p_out", &val) == 0) {
info->mpout = val;
info->caps |= ONLP_PSU_CAPS_POUT;
}
return ONLP_STATUS_OK;
}
/*
* Get all information about the given PSU oid.
*/
@@ -197,7 +233,7 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
*info = pinfo[index]; /* Set the onlp_oid_hdr_t */
/* Get the present state */
if (psu_status_info_get(index, "psu_present", &val) != 0) {
if (psu_status_info_get(index, 1, "psu_present", &val) != 0) {
printf("Unable to read PSU(%d) node(psu_present)\r\n", index);
}
@@ -209,12 +245,13 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
/* Get power good status */
if (psu_status_info_get(index, "psu_power_good", &val) != 0) {
if (psu_status_info_get(index, 1, "psu_power_good", &val) != 0) {
printf("Unable to read PSU(%d) node(psu_power_good)\r\n", index);
}
if (val != PSU_STATUS_POWER_GOOD) {
info->status |= ONLP_PSU_STATUS_FAILED;
return 0;
}
@@ -223,10 +260,14 @@ 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_COMPUWARE_F2B:
case PSU_TYPE_AC_COMPUWARE_B2F:
ret = psu_cpr_4011_info_get(info);
break;
case PSU_TYPE_AC_3YPOWER_F2B:
case PSU_TYPE_AC_3YPOWER_B2F:
ret = psu_ym2401_info_get(info);
break;
case PSU_TYPE_DC_48V_F2B:
case PSU_TYPE_DC_48V_B2F:
ret = psu_um400d_info_get(info);

View File

@@ -24,10 +24,8 @@
*
***********************************************************/
#include <unistd.h>
#include <onlplib/mmap.h>
#include <onlplib/file.h>
#include <onlp/platformi/thermali.h>
#include <fcntl.h>
#include "platform_lib.h"
#define VALIDATE(_id) \
@@ -112,6 +110,9 @@ int
onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info)
{
int local_id;
int psu_id;
psu_type_t psu_type;
VALIDATE(id);
local_id = ONLP_OID_ID_GET(id);
@@ -124,5 +125,13 @@ onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info)
return rv;
}
psu_id = local_id - THERMAL_1_ON_PSU1 + 1;
psu_type = get_psu_type(psu_id, NULL, 0);
if (psu_type == PSU_TYPE_AC_3YPOWER_F2B || psu_type == PSU_TYPE_AC_3YPOWER_B2F ) {
int rv = psu_ym2401_pmbus_info_get(psu_id, "psu_temp1_input", &info->mcelsius);
return rv;
}
return onlp_file_read_int(&info->mcelsius, devfiles[local_id]);
}

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -9,6 +9,7 @@ class OnlPlatform_x86_64_accton_as6712_32x_r0(OnlPlatformAccton,
def baseconfig(self):
self.insmod('cpr_4011_4mxx')
self.insmod("ym2651y")
for m in [ 'cpld', 'fan', 'psu', 'leds', 'sfp' ]:
self.insmod("x86-64-accton-as6712-32x-%s.ko" % m)
@@ -34,19 +35,17 @@ class OnlPlatform_x86_64_accton_as6712_32x_r0(OnlPlatformAccton,
# initiate multiplexer (PCA9548)
('pca9548', 0x70, 1),
# initiate PSU-1 AC Power
('as6712_32x_psu', 0x38, 35),
# initiate PSU-1
('as6712_32x_psu1', 0x38, 35),
('cpr_4011_4mxx', 0x3C, 35),
('as6712_32x_psu1', 0x50, 35),
('ym2401', 0x58, 35),
# initiate PSU-2 AC Power
('as6712_32x_psu', 0x3b, 36),
# initiate PSU-2
('as6712_32x_psu2', 0x3b, 36),
('cpr_4011_4mxx', 0x3F, 36),
# initiate PSU-1 DC Power
('as6712_32x_psu', 0x50, 35),
# initiate PSU-2 DC Power
('as6712_32x_psu', 0x53, 36),
('as6712_32x_psu2', 0x53, 36),
('ym2401', 0x5b, 36),
# initiate lm75
('lm75', 0x48, 38),

View File

@@ -33,14 +33,22 @@
#include <linux/slab.h>
#include <linux/delay.h>
#define PSU_STATUS_I2C_ADDR 0x60
#define PSU_STATUS_I2C_REG_OFFSET 0x2
#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1)))
#define IS_PRESENT(id, value) (!(value & BIT(id*4)))
static ssize_t show_index(struct device *dev, struct device_attribute *da, char *buf);
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 int as6812_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
extern int as6812_32x_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
static int as6812_32x_psu_model_name_get(struct device *dev);
/* 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
*/
@@ -57,6 +65,7 @@ struct as6812_32x_psu_data {
static struct as6812_32x_psu_data *as6812_32x_psu_update_device(struct device *dev);
enum as6812_32x_psu_sysfs_attributes {
PSU_INDEX,
PSU_PRESENT,
PSU_MODEL_NAME,
PSU_POWER_GOOD
@@ -64,17 +73,28 @@ enum as6812_32x_psu_sysfs_attributes {
/* sysfs attributes for hwmon
*/
static SENSOR_DEVICE_ATTR(psu_index, S_IRUGO, show_index, NULL, PSU_INDEX);
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 struct attribute *as6812_32x_psu_attributes[] = {
&sensor_dev_attr_psu_index.dev_attr.attr,
&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,
NULL
};
static ssize_t show_index(struct device *dev, struct device_attribute *da,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct as6812_32x_psu_data *data = i2c_get_clientdata(client);
return sprintf(buf, "%d\n", data->index);
}
static ssize_t show_status(struct device *dev, struct device_attribute *da,
char *buf)
{
@@ -82,11 +102,15 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da,
struct as6812_32x_psu_data *data = as6812_32x_psu_update_device(dev);
u8 status = 0;
if (!data->valid) {
return sprintf(buf, "0\n");
}
if (attr->index == PSU_PRESENT) {
status = !(data->status >> ((data->index-1)*4) & 0x1);
status = IS_PRESENT(data->index, data->status);
}
else { /* PSU_POWER_GOOD */
status = data->status >> ((data->index-1)*4 + 1) & 0x1;
status = IS_POWER_GOOD(data->index, data->status);
}
return sprintf(buf, "%d\n", status);
@@ -96,7 +120,18 @@ static ssize_t show_model_name(struct device *dev, struct device_attribute *da,
char *buf)
{
struct as6812_32x_psu_data *data = as6812_32x_psu_update_device(dev);
if (!data->valid) {
return 0;
}
if (!IS_PRESENT(data->index, data->status)) {
return 0;
}
if (as6812_32x_psu_model_name_get(dev) < 0) {
return -ENXIO;
}
return sprintf(buf, "%s\n", data->model_name);
}
@@ -123,6 +158,7 @@ static int as6812_32x_psu_probe(struct i2c_client *client,
i2c_set_clientdata(client, data);
data->valid = 0;
data->index = dev_id->driver_data;
mutex_init(&data->update_lock);
dev_info(&client->dev, "chip found\n");
@@ -139,14 +175,6 @@ static int as6812_32x_psu_probe(struct i2c_client *client,
goto exit_remove;
}
/* Update PSU index */
if (client->addr == 0x50 || client->addr == 0x38) {
data->index = 1;
}
else if (client->addr == 0x53 || client->addr == 0x3b) {
data->index = 2;
}
dev_info(&client->dev, "%s: psu '%s'\n",
dev_name(data->hwmon_dev), client->name);
@@ -172,8 +200,15 @@ static int as6812_32x_psu_remove(struct i2c_client *client)
return 0;
}
enum psu_index
{
as6812_32x_psu1,
as6812_32x_psu2
};
static const struct i2c_device_id as6812_32x_psu_id[] = {
{ "as6812_32x_psu", 0 },
{ "as6812_32x_psu1", as6812_32x_psu1 },
{ "as6812_32x_psu2", as6812_32x_psu2 },
{}
};
MODULE_DEVICE_TABLE(i2c, as6812_32x_psu_id);
@@ -218,6 +253,76 @@ static int as6812_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *
return result;
}
enum psu_type {
PSU_YM_2401_JCR, /* AC110V - F2B */
PSU_YM_2401_JDR, /* AC110V - B2F */
PSU_CPR_4011_4M11, /* AC110V - F2B */
PSU_CPR_4011_4M21, /* AC110V - B2F */
PSU_CPR_6011_2M11, /* AC110V - F2B */
PSU_CPR_6011_2M21, /* AC110V - B2F */
PSU_UM400D_01G, /* DC48V - F2B */
PSU_UM400D01_01G /* DC48V - B2F */
};
struct model_name_info {
enum psu_type type;
u8 offset;
u8 length;
char* model_name;
};
struct model_name_info models[] = {
{PSU_YM_2401_JCR, 0x20, 11, "YM-2401JCR"},
{PSU_YM_2401_JDR, 0x20, 11, "YM-2401JDR"},
{PSU_CPR_4011_4M11, 0x26, 13, "CPR-4011-4M11"},
{PSU_CPR_4011_4M21, 0x26, 13, "CPR-4011-4M21"},
{PSU_CPR_6011_2M11, 0x26, 13, "CPR-6011-2M11"},
{PSU_CPR_6011_2M21, 0x26, 13, "CPR-6011-2M21"},
{PSU_UM400D_01G, 0x50, 9, "um400d01G"},
{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"},
};
static int as6812_32x_psu_model_name_get(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct as6812_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 = as6812_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';
}
if (i == PSU_YM_2401_JCR || i == PSU_YM_2401_JDR) {
/* Skip the meaningless data byte 8*/
data->model_name[8] = data->model_name[9];
data->model_name[9] = data->model_name[10];
data->model_name[10] = '\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 as6812_32x_psu_data *as6812_32x_psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -227,56 +332,27 @@ static struct as6812_32x_psu_data *as6812_32x_psu_update_device(struct device *d
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int status;
int present = 0;
int status = -1;
dev_dbg(&client->dev, "Starting as6812_32x update\n");
data->valid = 0;
/* Read psu status */
status = as6812_32x_i2c_cpld_read(0x60, 0x2);
status = as6812_32x_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
if (status < 0) {
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status);
dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status);
goto exit;
}
else {
data->status = status;
}
/* Read model name */
memset(data->model_name, 0, sizeof(data->model_name));
present = !(data->status >> ((data->index-1)*4) & 0x1);
if (present) {
u8 command;
int model_name_len = 0;
if (client->addr == 0x38 || client->addr == 0x3b) {
/* cpr_4011_4mxx AC power */
command = 0x26;
model_name_len = 13;
}
else { /* 0x50 & 0x53 */
/* ym2651 AC power */
command = 0x20;
model_name_len = 8;
}
status = as6812_32x_psu_read_block(client,command,data->model_name,
model_name_len);
if (status < 0) {
data->model_name[0] = '\0';
dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr);
}
else {
data->model_name[model_name_len] = '\0';
}
}
data->last_updated = jiffies;
data->valid = 1;
}
exit:
mutex_unlock(&data->update_lock);
return data;

View File

@@ -24,14 +24,15 @@
*
***********************************************************/
#include <onlp/platformi/fani.h>
#include <onlplib/mmap.h>
#include <unistd.h>
#include <onlplib/file.h>
#include <fcntl.h>
#include "platform_lib.h"
#define PREFIX_PATH_ON_MAIN_BOARD "/sys/devices/platform/as6812_32x_fan/"
#define PREFIX_PATH_ON_PSU "/sys/bus/i2c/devices/"
#define MAX_FAN_SPEED 25500
#define MAX_FAN_SPEED 18000 /* use the smaller max_speed of the 2 fans in a fantray */
#define MAX_PSU_FAN_SPEED 19328
#define PROJECT_NAME
@@ -92,7 +93,7 @@ static fan_path_T fan_path[] = /* must map with onlp_fan_id */
{ \
{ ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \
0x0, \
(ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \
0, \
0, \
0, \
ONLP_FAN_MODE_INVALID, \
@@ -128,6 +129,22 @@ onlp_fan_info_t linfo[] = {
if (close(fd) == -1) \
return ONLP_STATUS_E_INTERNAL
/* PSU relative marco */
#define SET_PSU_TYPE_AC_F2B_FAN(info) \
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_F2B); \
info->caps |= ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE
#define SET_PSU_TYPE_AC_B2F_FAN(info) \
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F); \
info->caps |= ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE
#define SET_PSU_TYPE_UM400D_F2B_FAN(info) \
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_F2B)
#define SET_PSU_TYPE_UM400D_B2F_FAN(info) \
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F)
static int
_onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info)
{
@@ -178,6 +195,22 @@ _onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info)
return ONLP_STATUS_OK;
}
static int
_onlp_fani_info_get_fan_on_psu_ym2401(int pid, onlp_fan_info_t* info)
{
int val = 0;
/* get fan status
*/
if (psu_ym2401_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) {
info->status |= (val > 0) ? 0 : ONLP_FAN_STATUS_FAILED;
info->rpm = val;
info->percentage = (info->rpm * 100) / 21600;
}
return ONLP_STATUS_OK;
}
static int
_onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info)
{
@@ -197,32 +230,48 @@ _onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info)
switch (psu_type) {
case PSU_TYPE_AC_F2B:
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_F2B);
case PSU_TYPE_AC_COMPUWARE_F2B:
case PSU_TYPE_AC_3YPOWER_F2B:
SET_PSU_TYPE_AC_F2B_FAN(info);
break;
case PSU_TYPE_AC_B2F:
info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F);
case PSU_TYPE_AC_COMPUWARE_B2F:
case PSU_TYPE_AC_3YPOWER_B2F:
SET_PSU_TYPE_AC_B2F_FAN(info);
break;
case PSU_TYPE_DC_48V_F2B:
SET_PSU_TYPE_UM400D_F2B_FAN(info);
break;
case PSU_TYPE_DC_48V_B2F:
SET_PSU_TYPE_UM400D_B2F_FAN(info);
break;
default:
DEBUG_PRINT("[Debug][%s][%d][psu_type=%d]\n", __FUNCTION__, __LINE__, psu_type);
break;
}
/* get fan fault status
*/
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].status);
OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len);
if (atoi(r_data) > 0)
info->status |= ONLP_FAN_STATUS_FAILED;
if (psu_type == PSU_TYPE_AC_COMPUWARE_F2B ||
psu_type == PSU_TYPE_AC_COMPUWARE_B2F )
{
/* get fan fault status
*/
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].status);
OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len);
if (atoi(r_data) > 0)
info->status |= ONLP_FAN_STATUS_FAILED;
/* get fan speed
*/
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].speed);
OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len);
info->rpm = atoi(r_data);
/* get fan speed
*/
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].speed);
OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len);
info->rpm = atoi(r_data);
/* get speed percentage from rpm */
info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED;
info->status |= ONLP_FAN_STATUS_PRESENT;
/* get speed percentage from rpm */
info->percentage = (info->rpm * 100)/MAX_PSU_FAN_SPEED;
}
else if (psu_type == PSU_TYPE_AC_3YPOWER_F2B ||
psu_type == PSU_TYPE_AC_3YPOWER_B2F )
{
return _onlp_fani_info_get_fan_on_psu_ym2401(psu_id, info);
}
return ONLP_STATUS_OK;
}
@@ -310,8 +359,21 @@ onlp_fani_percentage_set(onlp_oid_t id, int p)
{
case FAN_1_ON_PSU1:
case FAN_1_ON_PSU2:
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].ctrl_speed);
{
int psu_id;
psu_type_t psu_type;
psu_id = local_id - FAN_1_ON_PSU1 + 1;
psu_type = get_psu_type(psu_id, NULL, 0);
if (psu_type == PSU_TYPE_AC_3YPOWER_F2B ||
psu_type == PSU_TYPE_AC_3YPOWER_B2F ) {
return psu_ym2401_pmbus_info_set(psu_id, "psu_fan1_duty_cycle_percentage", p);
}
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].ctrl_speed);
break;
}
case FAN_1_ON_MAIN_BOARD:
case FAN_2_ON_MAIN_BOARD:
case FAN_3_ON_MAIN_BOARD:

View File

@@ -23,12 +23,13 @@
*
*
***********************************************************/
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <onlp/onlp.h>
#include <onlplib/file.h>
#include <AIM/aim.h>
#include "platform_lib.h"
@@ -66,7 +67,7 @@ int deviceNodeWriteInt(char *filename, int value, int data_len)
char buf[8] = {0};
sprintf(buf, "%d", value);
return deviceNodeWrite(filename, buf, strlen(buf), data_len);
return deviceNodeWrite(filename, buf, sizeof(buf)-1, data_len);
}
int deviceNodeReadBinary(char *filename, char *buffer, int buf_size, int data_len)
@@ -102,20 +103,25 @@ int deviceNodeReadString(char *filename, char *buffer, int buf_size, int data_le
{
int ret;
if (data_len >= buf_size) {
if (data_len >= buf_size || data_len < 0) {
return -1;
}
ret = deviceNodeReadBinary(filename, buffer, buf_size-1, data_len);
if (ret == 0) {
buffer[buf_size-1] = '\0';
if (data_len) {
buffer[data_len] = '\0';
}
else {
buffer[buf_size-1] = '\0';
}
}
return ret;
}
#define I2C_PSU_MODEL_NAME_LEN 13
#define STRLEN(x) (sizeof(x) - 1)
psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
{
@@ -123,22 +129,122 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0};
/* Check AC model name */
node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_model_name) : PSU2_AC_HWMON_NODE(psu_model_name);
node = (id == PSU1_ID) ? PSU1_AC_EEPROM_NODE(psu_model_name) : PSU2_AC_EEPROM_NODE(psu_model_name);
if (deviceNodeReadString(node, model_name, sizeof(model_name), 0) == 0) {
if (strncmp(model_name, "CPR-4011-4M11", strlen("CPR-4011-4M11")) == 0) {
if (strncmp(model_name, "CPR-4011-4M11", STRLEN("CPR-4011-4M11")) == 0) {
if (modelname) {
strncpy(modelname, model_name, modelname_len-1);
strncpy(modelname, model_name, sizeof(model_name));
}
return PSU_TYPE_AC_F2B;
return PSU_TYPE_AC_COMPUWARE_F2B;
}
else if (strncmp(model_name, "CPR-4011-4M21", strlen("CPR-4011-4M21")) == 0) {
else if (strncmp(model_name, "CPR-4011-4M21", STRLEN("CPR-4011-4M21")) == 0) {
if (modelname) {
strncpy(modelname, model_name, modelname_len-1);
strncpy(modelname, model_name, sizeof(model_name));
}
return PSU_TYPE_AC_B2F;
return PSU_TYPE_AC_COMPUWARE_B2F;
}
else if (strncmp(model_name, "CPR-6011-2M11", STRLEN("CPR-6011-2M11")) == 0) {
if (modelname) {
strncpy(modelname, model_name, sizeof(model_name));
}
return PSU_TYPE_AC_COMPUWARE_F2B;
}
else if (strncmp(model_name, "CPR-6011-2M21", STRLEN("CPR-6011-2M21")) == 0) {
if (modelname) {
strncpy(modelname, model_name, sizeof(model_name));
}
return PSU_TYPE_AC_COMPUWARE_B2F;
}
}
/* Check 3Y-Power AC model name */
memset(model_name, 0, sizeof(model_name));
node = (id == PSU1_ID) ? PSU1_AC_3YPOWER_EEPROM_NODE(psu_model_name) : PSU2_AC_3YPOWER_EEPROM_NODE(psu_model_name);
if (deviceNodeReadString(node, model_name, sizeof(model_name), 0) == 0) {
if (strncmp(model_name, "YM-2401JCR", STRLEN("YM-2401JCR")) == 0) {
if (modelname) {
model_name[STRLEN("YM-2401JCR")] = 0;
strncpy(modelname, model_name, 11);
}
return PSU_TYPE_AC_3YPOWER_F2B;
}
else if (strncmp(model_name, "YM-2401JDR", STRLEN("YM-2401JDR")) == 0) {
if (modelname) {
model_name[STRLEN("YM-2401JDR")] = 0;
strncpy(modelname, model_name, 11);
}
return PSU_TYPE_AC_3YPOWER_B2F;
}
}
/* Check DC model name */
memset(model_name, 0, sizeof(model_name));
node = (id == PSU1_ID) ? PSU1_DC_EEPROM_NODE(psu_model_name) : PSU2_DC_EEPROM_NODE(psu_model_name);
if (deviceNodeReadString(node, model_name, sizeof(model_name), 0) == 0) {
if (strncmp(model_name, "um400d01G", STRLEN("um400d01G")) == 0) {
if (modelname) {
model_name[STRLEN("um400d01G")] = 0;
strncpy(modelname, model_name, 10);
}
return PSU_TYPE_DC_48V_B2F;
}
else if (strncmp(model_name, "um400d01-01G", STRLEN("um400d01-01G")) == 0) {
if (modelname) {
model_name[STRLEN("um400d01-01G")] = 0;
strncpy(modelname, model_name, 13);
}
return PSU_TYPE_DC_48V_F2B;
}
}
return PSU_TYPE_UNKNOWN;
}
int psu_ym2401_pmbus_info_get(int id, char *node, int *value)
{
int ret = 0;
char path[64] = {0};
*value = 0;
if (PSU1_ID == id) {
sprintf(path, "%s%s", PSU1_AC_3YPOWER_PMBUS_PREFIX, node);
}
else {
sprintf(path, "%s%s", PSU2_AC_3YPOWER_PMBUS_PREFIX, node);
}
if (onlp_file_read_int(value, path) < 0) {
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", path);
return ONLP_STATUS_E_INTERNAL;
}
return ret;
}
int psu_ym2401_pmbus_info_set(int id, char *node, int value)
{
char path[64] = {0};
switch (id) {
case PSU1_ID:
sprintf(path, "%s%s", PSU1_AC_3YPOWER_PMBUS_PREFIX, node);
break;
case PSU2_ID:
sprintf(path, "%s%s", PSU2_AC_3YPOWER_PMBUS_PREFIX, node);
break;
default:
return ONLP_STATUS_E_UNSUPPORTED;
};
if (deviceNodeWriteInt(path, value, 0) < 0) {
AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}

View File

@@ -36,17 +36,24 @@
#define PSU1_ID 1
#define PSU2_ID 2
#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/35-003c/"
#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/36-003f/"
#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/35-003c/" /* Compuware psu */
#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/36-003f/" /* Compuware psu */
#define PSU1_AC_3YPOWER_PMBUS_PREFIX "/sys/bus/i2c/devices/35-0058/" /* 3YPower psu */
#define PSU2_AC_3YPOWER_PMBUS_PREFIX "/sys/bus/i2c/devices/36-005b/" /* 3YPower psu */
#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node
#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node
#define PSU1_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/35-0038/"
#define PSU1_DC_EEPROM_PREFIX "/sys/bus/i2c/devices/35-0050/"
#define PSU2_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/36-003b/"
#define PSU2_DC_EEPROM_PREFIX "/sys/bus/i2c/devices/36-0053/"
#define PSU1_AC_3YPOWER_EEPROM_PREFIX "/sys/bus/i2c/devices/35-0050/"
#define PSU2_AC_3YPOWER_EEPROM_PREFIX "/sys/bus/i2c/devices/36-0053/"
#define PSU1_AC_HWMON_PREFIX "/sys/bus/i2c/devices/35-0038/"
#define PSU2_AC_HWMON_PREFIX "/sys/bus/i2c/devices/36-003b/"
#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node
#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node
#define PSU1_AC_EEPROM_NODE(node) PSU1_AC_EEPROM_PREFIX#node
#define PSU1_DC_EEPROM_NODE(node) PSU1_DC_EEPROM_PREFIX#node
#define PSU2_AC_EEPROM_NODE(node) PSU2_AC_EEPROM_PREFIX#node
#define PSU2_DC_EEPROM_NODE(node) PSU2_DC_EEPROM_PREFIX#node
#define PSU1_AC_3YPOWER_EEPROM_NODE(node) PSU1_AC_3YPOWER_EEPROM_PREFIX#node
#define PSU2_AC_3YPOWER_EEPROM_NODE(node) PSU2_AC_3YPOWER_EEPROM_PREFIX#node
#define IDPROM_PATH "/sys/class/i2c-adapter/i2c-1/1-0057/eeprom"
@@ -56,18 +63,25 @@ 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_COMPUWARE_F2B,
PSU_TYPE_AC_COMPUWARE_B2F,
PSU_TYPE_AC_3YPOWER_F2B,
PSU_TYPE_AC_3YPOWER_B2F,
PSU_TYPE_DC_48V_F2B,
PSU_TYPE_DC_48V_B2F
} psu_type_t;
psu_type_t get_psu_type(int id, char* modelname, int modelname_len);
int psu_ym2401_pmbus_info_get(int id, char *node, int *value);
int psu_ym2401_pmbus_info_set(int id, char *node, int value);
#define DEBUG_MODE 0
#if (DEBUG_MODE == 1)
#define DEBUG_PRINT(format, ...) printf(format, __VA_ARGS__)
#define DEBUG_PRINT(fmt, args...) \
printf("%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args)
#else
#define DEBUG_PRINT(format, ...)
#define DEBUG_PRINT(fmt, args...)
#endif
#endif /* __PLATFORM_LIB_H__ */

View File

@@ -24,7 +24,6 @@
*
***********************************************************/
#include <onlp/platformi/psui.h>
#include <onlplib/mmap.h>
#include <stdio.h>
#include <string.h>
#include "platform_lib.h"
@@ -43,7 +42,7 @@
} while(0)
static int
psu_status_info_get(int id, char *node, int *value)
psu_status_info_get(int id, int is_ac, char *node, int *value)
{
int ret = 0;
char buf[PSU_NODE_MAX_INT_LEN + 1] = {0};
@@ -52,12 +51,12 @@ psu_status_info_get(int id, char *node, int *value)
*value = 0;
if (PSU1_ID == id) {
sprintf(node_path, "%s%s", PSU1_AC_HWMON_PREFIX, node);
sprintf(node_path, "%s%s", is_ac ? PSU1_AC_EEPROM_PREFIX : PSU1_DC_EEPROM_PREFIX, node);
}
else if (PSU2_ID == id) {
sprintf(node_path, "%s%s", PSU2_AC_HWMON_PREFIX, node);
sprintf(node_path, "%s%s", is_ac ? PSU2_AC_EEPROM_PREFIX : PSU2_DC_EEPROM_PREFIX, node);
}
ret = deviceNodeReadString(node_path, buf, sizeof(buf), 0);
if (ret == 0) {
@@ -150,6 +149,62 @@ psu_cpr_4011_info_get(onlp_psu_info_t* info)
return ONLP_STATUS_OK;
}
int
psu_um400d_info_get(onlp_psu_info_t* info)
{
int index = ONLP_OID_ID_GET(info->hdr.id);
/* Set capability
*/
info->caps = ONLP_PSU_CAPS_DC48;
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);
return ONLP_STATUS_OK;
}
static int
psu_ym2401_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_ym2401_pmbus_info_get(index, "psu_v_out", &val) == 0) {
info->mvout = val;
info->caps |= ONLP_PSU_CAPS_VOUT;
}
if (psu_ym2401_pmbus_info_get(index, "psu_i_out", &val) == 0) {
info->miout = val;
info->caps |= ONLP_PSU_CAPS_IOUT;
}
if (psu_ym2401_pmbus_info_get(index, "psu_p_out", &val) == 0) {
info->mpout = val;
info->caps |= ONLP_PSU_CAPS_POUT;
}
return ONLP_STATUS_OK;
}
/*
* Get all information about the given PSU oid.
*/
@@ -178,7 +233,7 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
*info = pinfo[index]; /* Set the onlp_oid_hdr_t */
/* Get the present state */
if (psu_status_info_get(index, "psu_present", &val) != 0) {
if (psu_status_info_get(index, 1, "psu_present", &val) != 0) {
printf("Unable to read PSU(%d) node(psu_present)\r\n", index);
}
@@ -190,12 +245,13 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
/* Get power good status */
if (psu_status_info_get(index, "psu_power_good", &val) != 0) {
if (psu_status_info_get(index, 1, "psu_power_good", &val) != 0) {
printf("Unable to read PSU(%d) node(psu_power_good)\r\n", index);
}
if (val != PSU_STATUS_POWER_GOOD) {
info->status |= ONLP_PSU_STATUS_FAILED;
return 0;
}
@@ -204,10 +260,18 @@ 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_COMPUWARE_F2B:
case PSU_TYPE_AC_COMPUWARE_B2F:
ret = psu_cpr_4011_info_get(info);
break;
case PSU_TYPE_AC_3YPOWER_F2B:
case PSU_TYPE_AC_3YPOWER_B2F:
ret = psu_ym2401_info_get(info);
break;
case PSU_TYPE_DC_48V_F2B:
case PSU_TYPE_DC_48V_B2F:
ret = psu_um400d_info_get(info);
break;
default:
ret = ONLP_STATUS_E_UNSUPPORTED;
break;

View File

@@ -24,10 +24,8 @@
*
***********************************************************/
#include <unistd.h>
#include <onlplib/mmap.h>
#include <onlplib/file.h>
#include <onlp/platformi/thermali.h>
#include <fcntl.h>
#include "platform_lib.h"
#define VALIDATE(_id) \
@@ -112,6 +110,9 @@ int
onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info)
{
int local_id;
int psu_id;
psu_type_t psu_type;
VALIDATE(id);
local_id = ONLP_OID_ID_GET(id);
@@ -124,5 +125,13 @@ onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info)
return rv;
}
psu_id = local_id - THERMAL_1_ON_PSU1 + 1;
psu_type = get_psu_type(psu_id, NULL, 0);
if (psu_type == PSU_TYPE_AC_3YPOWER_F2B || psu_type == PSU_TYPE_AC_3YPOWER_B2F ) {
int rv = psu_ym2401_pmbus_info_get(psu_id, "psu_temp1_input", &info->mcelsius);
return rv;
}
return onlp_file_read_int(&info->mcelsius, devfiles[local_id]);
}

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -9,6 +9,7 @@ class OnlPlatform_x86_64_accton_as6812_32x_r0(OnlPlatformAccton,
def baseconfig(self):
self.insmod('cpr_4011_4mxx')
self.insmod("ym2651y")
for m in [ 'cpld', 'fan', 'psu', 'leds', 'sfp' ]:
self.insmod("x86-64-accton-as6812-32x-%s.ko" % m)
@@ -35,12 +36,16 @@ class OnlPlatform_x86_64_accton_as6812_32x_r0(OnlPlatformAccton,
('pca9548', 0x70, 1),
# initiate PSU-1
('as6812_32x_psu', 0x38, 35),
('as6812_32x_psu1', 0x38, 35),
('cpr_4011_4mxx', 0x3C, 35),
('as6812_32x_psu1', 0x50, 35),
('ym2401', 0x58, 35),
# initiate PSU-2
('as6812_32x_psu', 0x3b, 36),
('as6812_32x_psu2', 0x3b, 36),
('cpr_4011_4mxx', 0x3F, 36),
('as6812_32x_psu2', 0x53, 36),
('ym2401', 0x5b, 36),
# initiate lm75
('lm75', 0x48, 38),