Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AS4630-54NPE/PE/TE] Support 2nd source PSU #284

Open
wants to merge 1 commit into
base: 202311.X
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
"pddf_fan_driver_module",
"pddf_fan_module",
"pddf_led_module"
],
"custom_kos":
[
"pddf_custom_psu"
]
},

Expand Down Expand Up @@ -369,7 +373,7 @@
"attr_list":
[
{ "attr_name":"psu_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_offset":"0x22", "attr_mask":"0x20", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"psu_model_name", "attr_devaddr":"0x50", "attr_devtype":"eeprom", "attr_offset":"0x20", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"12" },
{ "attr_name":"psu_model_name", "attr_devaddr":"0x50", "attr_devtype":"eeprom", "attr_offset":"0x20", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"13" },
{ "attr_name":"psu_power_good", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_offset":"0x22", "attr_mask":"0x40", "attr_cmpval":"0x40", "attr_len":"1"},
{ "attr_name":"psu_serial_num", "attr_devaddr":"0x50", "attr_devtype":"eeprom", "attr_offset":"0x35", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"19" }
]
Expand Down Expand Up @@ -424,7 +428,7 @@
"attr_list":
[
{ "attr_name":"psu_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_offset":"0x22", "attr_mask":"0x2", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"psu_model_name", "attr_devaddr":"0x51", "attr_devtype":"eeprom", "attr_offset":"0x20", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"12" },
{ "attr_name":"psu_model_name", "attr_devaddr":"0x51", "attr_devtype":"eeprom", "attr_offset":"0x20", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"13" },
{ "attr_name":"psu_power_good", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_offset":"0x22", "attr_mask":"0x4", "attr_cmpval":"0x4", "attr_len":"1"},
{ "attr_name":"psu_serial_num", "attr_devaddr":"0x51", "attr_devtype":"eeprom", "attr_offset":"0x35", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"19" }
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@

#define MAX_MODEL_NAME 20
#define MAX_SERIAL_NUMBER 19
#define FAN_DIR_LEN 4

const char FAN_DIR_F2B[] = "F2B";
const char FAN_DIR_B2F[] = "B2F";

static int models_min_offset = 0;
static ssize_t show_status(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 as4630_54npe_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
Expand All @@ -59,6 +64,7 @@ struct as4630_54npe_psu_data {
u8 status; /* Status(present/power_good) register read from CPLD */
char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */
char serial_number[MAX_SERIAL_NUMBER];
char fan_dir[FAN_DIR_LEN];
};

static struct as4630_54npe_psu_data *as4630_54npe_psu_update_device(struct device *dev);
Expand All @@ -67,7 +73,39 @@ enum as4630_54npe_psu_sysfs_attributes {
PSU_PRESENT,
PSU_MODEL_NAME,
PSU_POWER_GOOD,
PSU_SERIAL_NUMBER
PSU_SERIAL_NUMBER,
PSU_FAN_DIR
};

enum psu_type {
PSU_YPEB1200, /* F2B */
PSU_YPEB1200AM, /* F2B */
PSU_UP1K21R_1085G, /* F2B */
UNKNOWN_PSU
};

struct model_name_info {
enum psu_type type;
u8 offset;
u8 length;
char* model_name;
};

struct model_name_info models[] = {
{PSU_YPEB1200, 0x20, 11, "YPEB1200"},
{PSU_YPEB1200AM, 0x20, 11, "YPEB1200AM"}, /* Replace YPEB1200-AM to YPEB1200AM */
{PSU_UP1K21R_1085G, 0x20, 13, "UP1K21R-1085G"},
};

struct serial_number_info {
u8 offset;
u8 length;
};

struct serial_number_info serials[] = {
[PSU_YPEB1200] = {0x35, 17},
[PSU_YPEB1200AM] = {0x35, 18},
[PSU_UP1K21R_1085G] = {0x3B, 9},
};

/* sysfs attributes for hwmon
Expand All @@ -76,13 +114,14 @@ static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRE
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_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER);

static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_string, NULL, PSU_FAN_DIR);

static struct attribute *as4630_54npe_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_serial_number.dev_attr.attr,
&sensor_dev_attr_psu_fan_dir.dev_attr.attr,
NULL
};

Expand Down Expand Up @@ -127,6 +166,9 @@ static ssize_t show_string(struct device *dev, struct device_attribute *da,
case PSU_SERIAL_NUMBER:
ptr = data->serial_number;
break;
case PSU_FAN_DIR:
ptr = data->fan_dir;
break;
default:
return -EINVAL;
}
Expand All @@ -138,6 +180,18 @@ static const struct attribute_group as4630_54npe_psu_group = {
.attrs = as4630_54npe_psu_attributes,
};

static int find_models_min_offset(void) {
int i, min_offset = models[0].offset;

for(i = 1; i < (sizeof(models) / sizeof(models[0])); i++) {
if(models[i].offset < min_offset) {
min_offset = models[i].offset;
}
}

return min_offset;
}

static int as4630_54npe_psu_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
Expand All @@ -159,6 +213,7 @@ static int as4630_54npe_psu_probe(struct i2c_client *client,
data->valid = 0;
data->index = dev_id->driver_data;
mutex_init(&data->update_lock);
models_min_offset = find_models_min_offset();

dev_info(&client->dev, "chip found\n");

Expand Down Expand Up @@ -256,13 +311,14 @@ static struct as4630_54npe_psu_data *as4630_54npe_psu_update_device(struct devic
{
struct i2c_client *client = to_i2c_client(dev);
struct as4630_54npe_psu_data *data = i2c_get_clientdata(client);
char temp_model_name[MAX_MODEL_NAME] = {0};

mutex_lock(&data->update_lock);

if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int status;
int power_good = 0;
int i, power_good = 0;

dev_dbg(&client->dev, "Starting as4630_54npe update\n");

Expand All @@ -282,54 +338,104 @@ static struct as4630_54npe_psu_data *as4630_54npe_psu_update_device(struct devic
memset(data->model_name, 0, sizeof(data->model_name));
#endif
#ifdef __STDC_LIB_EXT1__
memset_s(data->serial_number, sizeof(data->serial_number), 0, sizeof(data->serial_number));
memset_s(data->serial_number, sizeof(data->serial_number), 0, sizeof(data->serial_number));
#else
memset(data->serial_number, 0, sizeof(data->serial_number));
#endif
#ifdef __STDC_LIB_EXT1__
memset_s(data->fan_dir, sizeof(data->fan_dir), 0, sizeof(data->fan_dir));
#else
memset(data->fan_dir, 0, sizeof(data->fan_dir));
#endif
power_good = (data->status >> (data->index==0? 6:2)) & 0x1;

if (power_good) {
status = as4630_54npe_psu_read_block(client, 0x20, data->model_name,
ARRAY_SIZE(data->model_name)-1);
enum psu_type type = UNKNOWN_PSU;

status = as4630_54npe_psu_read_block(client, models_min_offset,
temp_model_name,
ARRAY_SIZE(temp_model_name));
if (status < 0) {
data->model_name[0] = '\0';
dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr);
goto exit;
}
else if(!strncmp(data->model_name, "YPEB1200", strlen("YPEB1200")))
{

for (i = 0; i < ARRAY_SIZE(models); i++) {
if ((models[i].length+1) > ARRAY_SIZE(data->model_name)) {
dev_dbg(&client->dev,
"invalid models[%d].length(%d), should not exceed the size of data->model_name(%ld)\n",
i, models[i].length, ARRAY_SIZE(data->model_name));
continue;
}

snprintf(data->model_name, models[i].length + 1, "%s",
temp_model_name + (models[i].offset - models_min_offset));

if(!strncmp(data->model_name, "YPEB1200", strlen("YPEB1200")))
{
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("YPEB1200AM")]='\0';
data->model_name[8]='A';
data->model_name[9]='M';
data->model_name[strlen("YPEB1200AM")]='\0';
}
else
data->model_name[strlen("YPEB1200")]='\0';
}

/* Determine if the model name is known, if not, read next index */
if (strcmp(data->model_name, models[i].model_name) == 0) {
type = models[i].type;
break;
}

data->model_name[0] = '\0';
}
else
{
data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0';

switch (type) {
case PSU_YPEB1200:
case PSU_YPEB1200AM:
case PSU_UP1K21R_1085G:
memcpy(data->fan_dir, FAN_DIR_F2B, sizeof(FAN_DIR_F2B));
break;
default:
dev_dbg(&client->dev, "Unknown PSU type for fan direction\n");
break;
}
/* Read from offset 0x35 ~ 0x46 (18 bytes) */
status = as4630_54npe_psu_read_block(client, 0x35,data->serial_number, MAX_SERIAL_NUMBER);
if (status < 0)
{
data->serial_number[0] = '\0';
dev_dbg(&client->dev, "unable to read model name from (0x%x) offset(0x35)\n", client->addr);

if (type < ARRAY_SIZE(serials)) {
if ((serials[type].length+1) > ARRAY_SIZE(data->serial_number)) {
dev_dbg(&client->dev,
"invalid serials[%d].length(%d), should not exceed the size of data->serial_number(%ld)\n",
type, serials[type].length, ARRAY_SIZE(data->serial_number));
goto exit;
}

memset(data->serial_number, 0, sizeof(data->serial_number));
status = as4630_54npe_psu_read_block(client, serials[type].offset,
data->serial_number,
serials[type].length);
if (status < 0) {
dev_dbg(&client->dev,
"unable to read serial from (0x%x) offset(0x%02x)\n",
client->addr, serials[type].length);
goto exit;
}
else {
data->serial_number[serials[type].length]= '\0';
}
}
if (!strncmp(data->model_name, "YPEB1200AM", strlen("YPEB1200AM"))) /*for YPEB1200AM, SN length=18*/
{
data->serial_number[MAX_SERIAL_NUMBER-1]='\0';
else {
dev_dbg(&client->dev, "invalid PSU type(%d)\n", type);
goto exit;
}
else
data->serial_number[MAX_SERIAL_NUMBER-2]='\0';

}

data->last_updated = jiffies;
data->valid = 1;
}

exit:
mutex_unlock(&data->update_lock);

return data;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
ifneq ($(KERNELRELEASE),)
obj-m:= x86-64-accton-as4630-54pe-cpld.o x86-64-accton-as4630-54pe-psu.o \
x86-64-accton-as4630-54pe-leds.o ym2651y.o
x86-64-accton-as4630-54pe-leds.o ym2651y.o pddf_custom_psu.o

CFLAGS_pddf_custom_psu.o := -I$(M)/../../../../pddf/i2c/modules/include
KBUILD_EXTRA_SYMBOLS := $(M)/../../../../pddf/i2c/Module.symvers.PDDF

else
ifeq (,$(KERNEL_SRC))
$(error KERNEL_SRC is not defined)
Expand Down
Loading