Add to support read psu serial number for as6812-32x

This commit is contained in:
Jostar Yang
2018-03-08 17:54:50 +08:00
parent 60b4db8f82
commit 3b304d59c4
4 changed files with 113 additions and 11 deletions

View File

@@ -42,9 +42,10 @@
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 ssize_t show_serial_number(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);
static int as6812_32x_psu_model_name_get(struct device *dev, int get_serial);
/* Addresses scanned
*/
@@ -60,6 +61,7 @@ struct as6812_32x_psu_data {
u8 index; /* PSU index */
u8 status; /* Status(present/power_good) register read from CPLD */
char model_name[14]; /* Model name, read from eeprom */
char serial[16]; /* Model name, read from eeprom */
};
static struct as6812_32x_psu_data *as6812_32x_psu_update_device(struct device *dev);
@@ -68,7 +70,8 @@ enum as6812_32x_psu_sysfs_attributes {
PSU_INDEX,
PSU_PRESENT,
PSU_MODEL_NAME,
PSU_POWER_GOOD
PSU_POWER_GOOD,
PSU_SERIAL_NUMBER
};
/* sysfs attributes for hwmon
@@ -76,12 +79,14 @@ enum as6812_32x_psu_sysfs_attributes {
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_serial, S_IRUGO, show_serial_number, NULL, PSU_SERIAL_NUMBER);
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_serial.dev_attr.attr,
&sensor_dev_attr_psu_power_good.dev_attr.attr,
NULL
};
@@ -116,6 +121,25 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da,
return sprintf(buf, "%d\n", status);
}
static ssize_t show_serial_number(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, 1) < 0) {
return -ENXIO;
}
return sprintf(buf, "%s\n", data->serial);
}
static ssize_t show_model_name(struct device *dev, struct device_attribute *da,
char *buf)
{
@@ -129,7 +153,7 @@ static ssize_t show_model_name(struct device *dev, struct device_attribute *da,
return 0;
}
if (as6812_32x_psu_model_name_get(dev) < 0) {
if (as6812_32x_psu_model_name_get(dev, 0) < 0) {
return -ENXIO;
}
return sprintf(buf, "%s\n", data->model_name);
@@ -264,6 +288,57 @@ enum psu_type {
PSU_UM400D01_01G /* DC48V - B2F */
};
struct serial_number_info {
enum psu_type type;
u8 offset;
u8 length;
};
struct serial_number_info serials[] = {
{PSU_YM_2401_JCR, 0x20, 11},
{PSU_YM_2401_JDR, 0x20, 11},
{PSU_CPR_4011_4M11, 0x46, 15},
{PSU_CPR_4011_4M21, 0x46, 15},
{PSU_CPR_6011_2M11, 0x46, 15},
{PSU_CPR_6011_2M21, 0x46, 15},
{PSU_UM400D_01G, 0x50, 9},
{PSU_UM400D01_01G, 0x50, 12},
};
static int as6812_32x_psu_serial_number_get(struct device *dev, enum psu_type type)
{
struct i2c_client *client = to_i2c_client(dev);
struct as6812_32x_psu_data *data = i2c_get_clientdata(client);
int i, status;
switch (type) {
case PSU_CPR_4011_4M11:
case PSU_CPR_4011_4M21:
case PSU_CPR_6011_2M11:
case PSU_CPR_6011_2M21:
{
status = as6812_32x_psu_read_block(client, serials[i].offset,
data->serial, serials[i].length);
if (status < 0) {
data->serial[0] = '\0';
dev_dbg(&client->dev, "unable to read serial number from (0x%x) offset(0x%x)\n",
client->addr, serials[i].offset);
return status;
}
else {
data->serial[serials[i].length] = '\0';
return 0;
}
}
break;
default:
break;
}
return -ENODATA;
}
struct model_name_info {
enum psu_type type;
u8 offset;
@@ -282,7 +357,7 @@ struct model_name_info models[] = {
{PSU_UM400D01_01G, 0x50, 12, "um400d01-01G"},
};
static int as6812_32x_psu_model_name_get(struct device *dev)
static int as6812_32x_psu_model_name_get(struct device *dev, int get_serial)
{
struct i2c_client *client = to_i2c_client(dev);
struct as6812_32x_psu_data *data = i2c_get_clientdata(client);
@@ -313,7 +388,7 @@ static int as6812_32x_psu_model_name_get(struct device *dev)
/* 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;
return get_serial ? as6812_32x_psu_serial_number_get(dev, i) : 0;
}
else {
data->model_name[0] = '\0';
@@ -359,12 +434,7 @@ exit:
}
static int __init as6812_32x_psu_init(void)
{
extern int platform_accton_as6812_32x(void);
if(!platform_accton_as6812_32x()) {
return -ENODEV;
}
{
return i2c_add_driver(&as6812_32x_psu_driver);
}

View File

@@ -23,6 +23,8 @@
*
*
***********************************************************/
#include <onlp/onlp.h>
#include <onlplib/file.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
@@ -248,3 +250,29 @@ int psu_ym2401_pmbus_info_set(int id, char *node, int value)
return ONLP_STATUS_OK;
}
#define PSU_SERIAL_NUMBER_LEN 18
int psu_serial_number_get(int id, int is_ac, char *serial, int serial_len)
{
int size = 0;
int ret = ONLP_STATUS_OK;
char *prefix = NULL;
if (serial == NULL || serial_len < PSU_SERIAL_NUMBER_LEN) {
return ONLP_STATUS_E_PARAM;
}
memset((void *)serial, 0x0, serial_len);
if(is_ac)
prefix = (id == PSU1_ID) ? PSU1_AC_EEPROM_PREFIX : PSU2_AC_EEPROM_PREFIX;
else
prefix = (id == PSU1_ID) ? PSU1_DC_EEPROM_PREFIX : PSU2_DC_EEPROM_PREFIX;
ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, "%s%s", prefix, "psu_serial");
if (ret != ONLP_STATUS_OK || size != PSU_SERIAL_NUMBER_LEN) {
return ONLP_STATUS_E_INTERNAL;
}
serial[PSU_SERIAL_NUMBER_LEN] = '\0';
return ONLP_STATUS_OK;
}

View File

@@ -72,6 +72,7 @@ typedef enum psu_type {
} psu_type_t;
psu_type_t get_psu_type(int id, char* modelname, int modelname_len);
int psu_serial_number_get(int id, int is_ac, char *serial, int serial_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);

View File

@@ -225,6 +225,7 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
int val = 0;
int ret = ONLP_STATUS_OK;
int index = ONLP_OID_ID_GET(id);
int is_ac=1;
psu_type_t psu_type;
VALIDATE(id);
@@ -270,12 +271,14 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
break;
case PSU_TYPE_DC_48V_F2B:
case PSU_TYPE_DC_48V_B2F:
is_ac=0;
ret = psu_um400d_info_get(info);
break;
default:
ret = ONLP_STATUS_E_UNSUPPORTED;
break;
}
psu_serial_number_get(index, is_ac, info->serial, sizeof(info->serial));
return ret;
}