Skip to content
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 @@ -34,8 +34,10 @@
#include <linux/delay.h>
#include <linux/dmi.h>

#define MAX_MODEL_NAME 16
#define MAX_SERIAL_NUMBER 18
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 as7326_56x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
extern int as7326_56x_cpld_read(unsigned short cpld_addr, u8 reg);

Expand All @@ -52,26 +54,30 @@ struct as7326_56x_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 serial_number[MAX_SERIAL_NUMBER+1];
};

static struct as7326_56x_psu_data *as7326_56x_psu_update_device(struct device *dev);

enum as7326_56x_psu_sysfs_attributes {
PSU_PRESENT,
PSU_MODEL_NAME,
PSU_SERIAL_NUMBER,
PSU_POWER_GOOD
};

/* 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_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME);
static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER);
static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD);

static struct attribute *as7326_56x_psu_attributes[] = {
&sensor_dev_attr_psu_present.dev_attr.attr,
&sensor_dev_attr_psu_model_name.dev_attr.attr,
&sensor_dev_attr_psu_serial_number.dev_attr.attr,
&sensor_dev_attr_psu_power_good.dev_attr.attr,
NULL
};
Expand All @@ -83,6 +89,10 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da,
struct as7326_56x_psu_data *data = as7326_56x_psu_update_device(dev);
u8 status = 0;

if (!data->valid) {
return -EIO;
}

if (attr->index == PSU_PRESENT) {
status = !(data->status >> (1-data->index) & 0x1);
}
Expand All @@ -93,12 +103,27 @@ 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,
char *buf)
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 as7326_56x_psu_data *data = as7326_56x_psu_update_device(dev);
char *ptr = NULL;

return sprintf(buf, "%s\n", data->model_name);
if (!data->valid) {
return -EIO;
}

if (attr->index == PSU_MODEL_NAME) {
ptr = data->model_name;
}
else if (attr->index == PSU_SERIAL_NUMBER) {
ptr = data->serial_number;
}
else {
return -EIO;
}
return sprintf(buf, "%s\n", ptr);
}

static const struct attribute_group as7326_56x_psu_group = {
Expand Down Expand Up @@ -219,6 +244,112 @@ static int as7326_56x_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,
PSU_TYPE_AC_ACBEL_FSF019,
PSU_TYPE_AC_ACBEL_FSF045
};

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

struct serial_number_info {
enum psu_type type;
u8 offset;
u8 length;
char* serial_number;
};

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"},
{PSU_TYPE_AC_ACBEL_FSF019, 0x15, 10, "FSF019-"},
{PSU_TYPE_AC_ACBEL_FSF045, 0x15, 10, "FSF045-"}
};

struct serial_number_info serials[] = {
{PSU_TYPE_AC_110V, 0x2e, 18, "YM-2651Y"},
{PSU_TYPE_DC_48V, 0x2e, 18, "YM-2651V"},
{PSU_TYPE_DC_12V, 0x2e, 18, "PSU-12V-750"},
{PSU_TYPE_AC_ACBEL_FSF019, 0x2e, 16, "FSF019-"},
{PSU_TYPE_AC_ACBEL_FSF045, 0x2e, 16, "FSF045-"}
};

static int as7326_56x_psu_model_name_get(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct as7326_56x_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 = as7326_56x_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, strlen(models[i].model_name)) == 0) {
return 0;
}
else {
data->model_name[0] = '\0';
}
}

return -ENODATA;
}

static int as7326_56x_psu_serial_number_get(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct as7326_56x_psu_data *data = i2c_get_clientdata(client);
int i, status;

for (i = 0; i < ARRAY_SIZE(models); i++) {
memset(data->serial_number, 0, sizeof(data->serial_number));

status = as7326_56x_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_number from (0x%x) offset(0x%x)\n",
client->addr, serials[i].offset);
return status;
}
else {
data->serial_number[serials[i].length] = '\0';
}

/* Determine if the model name is known, if not, read next index
*/
if (strncmp(data->model_name, models[i].model_name, strlen(models[i].model_name)) == 0) {
return 0;
}
else {
data->serial_number[0] = '\0';
}
}

return -ENODATA;
}

static struct as7326_56x_psu_data *as7326_56x_psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
Expand All @@ -231,39 +362,39 @@ static struct as7326_56x_psu_data *as7326_56x_psu_update_device(struct device *d
int status;
int power_good = 0;

data->valid = 0;
dev_dbg(&client->dev, "Starting as7326_56x update\n");

/* Read psu status */
status = as7326_56x_cpld_read(0x60, 0x2);

if (status < 0) {
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status);
goto exit;
}
else {
data->status = status;
}

/* Read model name */
memset(data->model_name, 0, sizeof(data->model_name));
memset(data->serial_number, 0, sizeof(data->serial_number));
power_good = (data->status >> (3-data->index) & 0x1);

if (power_good) {
status = as7326_56x_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 (as7326_56x_psu_model_name_get(dev) < 0) {
goto exit;
}
else {
data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0';
if (as7326_56x_psu_serial_number_get(dev) < 0) {
goto exit;
}
}

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

exit:
mutex_unlock(&data->update_lock);

return data;
Expand Down
Loading