[AS9716-32D]Support multi PSU SN in PDDF (#8214)

Add needed code to pddf_custom_psu.c to deal with multi PSU and get SN.

How to verify it
Plugin new PSU (3Y) and test,

```
root@sonic:/sys/bus/i2c/drivers/psu/9-0050# cat psu_serial_num
S0A000X601919000013
root@sonic:/sys/bus/i2c/drivers/psu/9-0050# cat psu_model_name
YESM1300AM
root@sonic:/home/admin# pddf_psuutil mfrinfo
PSU Status Manufacturer ID Model Serial Fan Airflow Direction

PSU1 NOT OK 3Y POWER YESM1300AM S0A000X601919000007 exhaust
PSU2 OK 3Y POWER YESM1300AM S0A000X601919000013 exhaust
```

Co-authored-by: Jostar Yang <jostar_yang@accton.com.tw>
This commit is contained in:
jostar-yang 2021-07-25 07:30:11 +08:00 committed by GitHub
parent fed8957b47
commit 3e7228d45c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -13,6 +13,95 @@
ssize_t pddf_show_custom_psu_v_out(struct device *dev, struct device_attribute *da, char *buf);
extern PSU_SYSFS_ATTR_DATA access_psu_v_out;
ssize_t pddf_get_custom_psu_model_name(struct device *dev, struct device_attribute *da, char *buf);
ssize_t pddf_get_custom_psu_serial_num(struct device *dev, struct device_attribute *da, char *buf);
extern PSU_SYSFS_ATTR_DATA access_psu_model_name;
extern PSU_SYSFS_ATTR_DATA access_psu_serial_num;
#define MAX_MODEL_NAME 16
#define MAX_SERIAL_NUMBER 19
enum psu_type {
PSU_TYPE_AC_110V,
PSU_TYPE_DC_48V,
PSU_TYPE_DC_12V,
PSU_TYPE_AC_ACBEL_FSF019,
PSU_TYPE_AC_ACBEL_FSH082,
PSU_TYPE_YESM1300
};
struct model_name_info {
enum psu_type type;
u8 offset;
u8 length;
u8 chk_length;
char* model_name;
};
struct serial_number_info {
enum psu_type type;
u8 offset;
u8 length;
u8 chk_length;
char* serial_number;
};
struct model_name_info models[] = {
{PSU_TYPE_AC_110V, 0x20, 8, 8, "YM-2651Y"},
{PSU_TYPE_DC_48V, 0x20, 8, 8, "YM-2651V"},
{PSU_TYPE_DC_12V, 0x00, 11, 11, "PSU-12V-750"},
{PSU_TYPE_AC_ACBEL_FSF019, 0x15, 10, 7, "FSF019-"},
{PSU_TYPE_AC_ACBEL_FSH082, 0x20, 10, 7, "FSH082-"},
{PSU_TYPE_YESM1300, 0x20, 11, 8, "YESM1300"},
};
struct serial_number_info serials[] = {
{PSU_TYPE_AC_110V, 0x2e, 18, 18, "YM-2651Y"},
{PSU_TYPE_DC_48V, 0x2e, 18, 18, "YM-2651V"},
{PSU_TYPE_DC_12V, 0x2e, 18, 18, "PSU-12V-750"},
{PSU_TYPE_AC_ACBEL_FSF019, 0x2e, 16, 16, "FSF019-"},
{PSU_TYPE_AC_ACBEL_FSH082, 0x35, 18, 18, "FSH082-"},
{PSU_TYPE_YESM1300, 0x35, 20, 19, "YESM1300"},
};
struct pddf_psu_data {
char model_name[MAX_MODEL_NAME+1];
char serial_number[MAX_SERIAL_NUMBER+1];
};
static int pddf_psu_read_block(struct i2c_client *client, u8 command, u8 *data,
int data_len)
{
int result = 0;
int retry_count = 10;
while (retry_count) {
retry_count--;
result = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
if (unlikely(result < 0)) {
msleep(10);
continue;
}
if (unlikely(result != data_len)) {
result = -EIO;
msleep(10);
continue;
}
result = 0;
break;
}
return result;
}
static int two_complement_to_int(u16 data, u8 valid_bit, int mask)
{
@ -90,7 +179,7 @@ ssize_t pddf_show_custom_psu_v_out(struct device *dev, struct device_attribute *
exponent = two_complement_to_int(vout_mode & 0x1f, 5, 0x1f);
else
{
printk(KERN_ERR "%s: Only support linear mode for vout mode\n", __func__);
/*printk(KERN_ERR "%s: Only support linear mode for vout mode\n", __func__);*/
exponent = 0;
}
mantissa = value;
@ -100,13 +189,117 @@ ssize_t pddf_show_custom_psu_v_out(struct device *dev, struct device_attribute *
return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
}
ssize_t pddf_get_custom_psu_serial_num(struct device *dev, struct device_attribute *da, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct pddf_psu_data data;
int i, status;
for (i = 0; i < ARRAY_SIZE(models); i++) {
memset(data.serial_number, 0, sizeof(data.serial_number));
status = pddf_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].chk_length) == 0) {
status = pddf_psu_read_block(client, serials[i].offset,
data.serial_number, serials[i].length);
if (status < 0) {
data.serial_number[0] = '\0';
dev_dbg(&client->dev, "unable to read serial num from (0x%x) offset(0x%x)\n",
client->addr, serials[i].offset);
return status;
}
else {
data.serial_number[serials[i].length] = '\0';
return sprintf(buf, "%s\n", data.serial_number);
}
return 0;
}
else {
data.serial_number[0] = '\0';
}
}
return -ENODATA;
}
ssize_t pddf_get_custom_psu_model_name(struct device *dev, struct device_attribute *da, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct pddf_psu_data data;
int i, status;
for (i = 0; i < ARRAY_SIZE(models); i++) {
memset(data.model_name, 0, sizeof(data.model_name));
status = pddf_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].chk_length) == 0) {
if (models[i].type==PSU_TYPE_YESM1300)
{
if (data.model_name[9]=='A' && data.model_name[10]=='M')
{
data.model_name[8]='A';
data.model_name[9]='M';
data.model_name[strlen("YESM1300AM")]='\0';
}
else
data.model_name[strlen("YESM1300")]='\0';
}
return sprintf(buf, "%s\n", data.model_name);
}
else {
data.model_name[0] = '\0';
}
}
return -ENODATA;
}
static int __init pddf_custom_psu_init(void)
{
access_psu_v_out.show = pddf_show_custom_psu_v_out;
access_psu_v_out.do_get = NULL;
printk(KERN_ERR "pddf_custom_psu_init\n");
access_psu_serial_num.show = pddf_get_custom_psu_serial_num;
access_psu_serial_num.do_get = NULL;
access_psu_model_name.show = pddf_get_custom_psu_model_name;
access_psu_model_name.do_get = NULL;
return 0;
}