mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-26 17:57:01 +00:00
[as7712] Support DC12V(PSU-12V-650)/DC48V(YM-2651V) power supply
This commit is contained in:
@@ -44,10 +44,10 @@ index f8ee399..ea97f4a 100644
|
||||
obj-$(CONFIG_SENSORS_AD7414) += ad7414.o
|
||||
diff --git a/drivers/hwmon/accton_as7712_32x_fan.c b/drivers/hwmon/accton_as7712_32x_fan.c
|
||||
new file mode 100644
|
||||
index 0000000..f2246e3
|
||||
index 0000000..74c577d
|
||||
--- /dev/null
|
||||
+++ b/drivers/hwmon/accton_as7712_32x_fan.c
|
||||
@@ -0,0 +1,452 @@
|
||||
@@ -0,0 +1,491 @@
|
||||
+/*
|
||||
+ * A hwmon driver for the Accton as7712 32x fan
|
||||
+ *
|
||||
@@ -93,6 +93,7 @@ index 0000000..f2246e3
|
||||
+ */
|
||||
+static const u8 fan_reg[] = {
|
||||
+ 0x0F, /* fan 1-6 present status */
|
||||
+ 0x10, /* fan 1-6 direction(0:B2F 1:F2B) */
|
||||
+ 0x11, /* fan PWM(for all fan) */
|
||||
+ 0x12, /* front fan 1 speed(rpm) */
|
||||
+ 0x13, /* front fan 2 speed(rpm) */
|
||||
@@ -128,6 +129,7 @@ index 0000000..f2246e3
|
||||
+
|
||||
+enum sysfs_fan_attributes {
|
||||
+ FAN_PRESENT_REG,
|
||||
+ FAN_DIRECTION_REG,
|
||||
+ FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */
|
||||
+ FAN1_FRONT_SPEED_RPM,
|
||||
+ FAN2_FRONT_SPEED_RPM,
|
||||
@@ -141,6 +143,12 @@ index 0000000..f2246e3
|
||||
+ FAN4_REAR_SPEED_RPM,
|
||||
+ FAN5_REAR_SPEED_RPM,
|
||||
+ FAN6_REAR_SPEED_RPM,
|
||||
+ FAN1_DIRECTION,
|
||||
+ FAN2_DIRECTION,
|
||||
+ FAN3_DIRECTION,
|
||||
+ FAN4_DIRECTION,
|
||||
+ FAN5_DIRECTION,
|
||||
+ FAN6_DIRECTION,
|
||||
+ FAN1_PRESENT,
|
||||
+ FAN2_PRESENT,
|
||||
+ FAN3_PRESENT,
|
||||
@@ -200,6 +208,13 @@ index 0000000..f2246e3
|
||||
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4);
|
||||
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5);
|
||||
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6);
|
||||
+/* 6 fan direction attribute in this platform */
|
||||
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1);
|
||||
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2);
|
||||
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3);
|
||||
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4);
|
||||
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5);
|
||||
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(6);
|
||||
+/* 1 fan duty cycle attribute in this platform */
|
||||
+DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
|
||||
+
|
||||
@@ -223,6 +238,12 @@ index 0000000..f2246e3
|
||||
+ DECLARE_FAN_PRESENT_ATTR(4),
|
||||
+ DECLARE_FAN_PRESENT_ATTR(5),
|
||||
+ DECLARE_FAN_PRESENT_ATTR(6),
|
||||
+ DECLARE_FAN_DIRECTION_ATTR(1),
|
||||
+ DECLARE_FAN_DIRECTION_ATTR(2),
|
||||
+ DECLARE_FAN_DIRECTION_ATTR(3),
|
||||
+ DECLARE_FAN_DIRECTION_ATTR(4),
|
||||
+ DECLARE_FAN_DIRECTION_ATTR(5),
|
||||
+ DECLARE_FAN_DIRECTION_ATTR(6),
|
||||
+ DECLARE_FAN_DUTY_CYCLE_ATTR(),
|
||||
+ NULL
|
||||
+};
|
||||
@@ -259,6 +280,14 @@ index 0000000..f2246e3
|
||||
+ return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP;
|
||||
+}
|
||||
+
|
||||
+static u8 reg_val_to_direction(u8 reg_val, enum fan_id id)
|
||||
+{
|
||||
+ u8 mask = (1 << id);
|
||||
+
|
||||
+ reg_val &= mask;
|
||||
+
|
||||
+ return reg_val ? 1 : 0;
|
||||
+}
|
||||
+static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id)
|
||||
+{
|
||||
+ u8 mask = (1 << id);
|
||||
@@ -349,6 +378,16 @@ index 0000000..f2246e3
|
||||
+ case FAN6_FAULT:
|
||||
+ ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
|
||||
+ break;
|
||||
+ case FAN1_DIRECTION:
|
||||
+ case FAN2_DIRECTION:
|
||||
+ case FAN3_DIRECTION:
|
||||
+ case FAN4_DIRECTION:
|
||||
+ case FAN5_DIRECTION:
|
||||
+ case FAN6_DIRECTION:
|
||||
+ ret = sprintf(buf, "%d\n",
|
||||
+ reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG],
|
||||
+ attr->index - FAN1_DIRECTION));
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
@@ -480,10 +519,10 @@ index 0000000..f2246e3
|
||||
+
|
||||
+static int __init as7712_32x_fan_init(void)
|
||||
+{
|
||||
+ extern int platform_accton_as7712_32x(void);
|
||||
+ if (!platform_accton_as7712_32x()) {
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ extern int platform_accton_as7712_32x(void);
|
||||
+ if (!platform_accton_as7712_32x()) {
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return i2c_add_driver(&as7712_32x_fan_driver);
|
||||
+}
|
||||
@@ -502,10 +541,10 @@ index 0000000..f2246e3
|
||||
+
|
||||
diff --git a/drivers/hwmon/accton_as7712_32x_psu.c b/drivers/hwmon/accton_as7712_32x_psu.c
|
||||
new file mode 100644
|
||||
index 0000000..4574150
|
||||
index 0000000..f1f11f5
|
||||
--- /dev/null
|
||||
+++ b/drivers/hwmon/accton_as7712_32x_psu.c
|
||||
@@ -0,0 +1,293 @@
|
||||
@@ -0,0 +1,384 @@
|
||||
+/*
|
||||
+ * An hwmon driver for accton as7712_32x Power Module
|
||||
+ *
|
||||
@@ -542,14 +581,18 @@ index 0000000..4574150
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/dmi.h>
|
||||
+
|
||||
+#define MAX_MODEL_NAME 16
|
||||
+
|
||||
+#define DC12V_FAN_DIR_OFFSET 0x34
|
||||
+#define DC12V_FAN_DIR_LEN 3
|
||||
+
|
||||
+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 as7712_32x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
|
||||
+extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
+
|
||||
+/* 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
|
||||
+ */
|
||||
@@ -560,27 +603,32 @@ index 0000000..4574150
|
||||
+ 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]; /* Model name, read from eeprom */
|
||||
+ char fan_dir[DC12V_FAN_DIR_LEN+1]; /* DC12V fan direction */
|
||||
+};
|
||||
+
|
||||
+static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf);
|
||||
+static struct as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *dev);
|
||||
+
|
||||
+enum as7712_32x_psu_sysfs_attributes {
|
||||
+ PSU_PRESENT,
|
||||
+ PSU_MODEL_NAME,
|
||||
+ PSU_POWER_GOOD
|
||||
+ PSU_POWER_GOOD,
|
||||
+ PSU_FAN_DIR /* For DC12V only */
|
||||
+};
|
||||
+
|
||||
+/* 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_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD);
|
||||
+static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT);
|
||||
+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_fan_dir, S_IRUGO, show_string, NULL, PSU_FAN_DIR);
|
||||
+
|
||||
+static struct attribute *as7712_32x_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_fan_dir.dev_attr.attr,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
@@ -591,6 +639,10 @@ index 0000000..4574150
|
||||
+ struct as7712_32x_psu_data *data = as7712_32x_psu_update_device(dev);
|
||||
+ u8 status = 0;
|
||||
+
|
||||
+ if (!data->valid) {
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ if (attr->index == PSU_PRESENT) {
|
||||
+ status = !(data->status >> (1-data->index) & 0x1);
|
||||
+ }
|
||||
@@ -601,12 +653,25 @@ index 0000000..4574150
|
||||
+ return sprintf(buf, "%d\n", status);
|
||||
+}
|
||||
+
|
||||
+static ssize_t show_model_name(struct device *dev, struct device_attribute *da,
|
||||
+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 as7712_32x_psu_data *data = as7712_32x_psu_update_device(dev);
|
||||
+
|
||||
+ return sprintf(buf, "%s\n", data->model_name);
|
||||
+ char *ptr = NULL;
|
||||
+
|
||||
+ if (!data->valid) {
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ if (attr->index == PSU_MODEL_NAME) {
|
||||
+ ptr = data->model_name;
|
||||
+ }
|
||||
+ else { /* PSU_FAN_DIR */
|
||||
+ ptr = data->fan_dir;
|
||||
+ }
|
||||
+
|
||||
+ return sprintf(buf, "%s\n", ptr);
|
||||
+}
|
||||
+
|
||||
+static const struct attribute_group as7712_32x_psu_group = {
|
||||
@@ -703,30 +768,83 @@ index 0000000..4574150
|
||||
+{
|
||||
+ int result = 0;
|
||||
+ int retry_count = 5;
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ while (retry_count) {
|
||||
+ retry_count--;
|
||||
+
|
||||
+ result = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
|
||||
+
|
||||
+ if (unlikely(result < 0)) {
|
||||
+ msleep(10);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ result = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ if (unlikely(result != data_len)) {
|
||||
+ result = -EIO;
|
||||
+ msleep(10);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ result = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+enum psu_type {
|
||||
+ PSU_TYPE_AC_110V,
|
||||
+ PSU_TYPE_DC_48V,
|
||||
+ PSU_TYPE_DC_12V
|
||||
+};
|
||||
+
|
||||
+struct model_name_info {
|
||||
+ enum psu_type type;
|
||||
+ u8 offset;
|
||||
+ u8 length;
|
||||
+ char* model_name;
|
||||
+};
|
||||
+
|
||||
+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"},
|
||||
+};
|
||||
+
|
||||
+static int as7712_32x_psu_model_name_get(struct device *dev)
|
||||
+{
|
||||
+ struct i2c_client *client = to_i2c_client(dev);
|
||||
+ struct as7712_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 = as7712_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';
|
||||
+ }
|
||||
+
|
||||
+ /* 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 as7712_32x_psu_data *as7712_32x_psu_update_device(struct device *dev)
|
||||
+{
|
||||
+ struct i2c_client *client = to_i2c_client(dev);
|
||||
@@ -737,8 +855,9 @@ index 0000000..4574150
|
||||
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|
||||
+ || !data->valid) {
|
||||
+ int status;
|
||||
+ int power_good = 0;
|
||||
+ int power_good = 0;
|
||||
+
|
||||
+ data->valid = 0;
|
||||
+ dev_dbg(&client->dev, "Starting as7712_32x update\n");
|
||||
+
|
||||
+ /* Read psu status */
|
||||
@@ -746,25 +865,35 @@ index 0000000..4574150
|
||||
+
|
||||
+ 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->fan_dir, 0, sizeof(data->fan_dir));
|
||||
+ power_good = (data->status >> (3-data->index) & 0x1);
|
||||
+
|
||||
+ if (power_good) {
|
||||
+ status = as7712_32x_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 (power_good) {
|
||||
+ if (as7712_32x_psu_model_name_get(dev) < 0) {
|
||||
+ goto exit;
|
||||
+ }
|
||||
+ else {
|
||||
+ data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0';
|
||||
+
|
||||
+ if (strncmp(data->model_name,
|
||||
+ models[PSU_TYPE_DC_12V].model_name,
|
||||
+ models[PSU_TYPE_DC_12V].length) == 0) {
|
||||
+ /* Read fan direction */
|
||||
+ status = as7712_32x_psu_read_block(client, DC12V_FAN_DIR_OFFSET,
|
||||
+ data->fan_dir, DC12V_FAN_DIR_LEN);
|
||||
+
|
||||
+ if (status < 0) {
|
||||
+ data->fan_dir[0] = '\0';
|
||||
+ dev_dbg(&client->dev, "unable to read fan direction from (0x%x) offset(0x%x)\n",
|
||||
+ client->addr, DC12V_FAN_DIR_OFFSET);
|
||||
+ goto exit;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@@ -772,6 +901,7 @@ index 0000000..4574150
|
||||
+ data->valid = 1;
|
||||
+ }
|
||||
+
|
||||
+exit:
|
||||
+ mutex_unlock(&data->update_lock);
|
||||
+
|
||||
+ return data;
|
||||
@@ -779,10 +909,10 @@ index 0000000..4574150
|
||||
+
|
||||
+static int __init as7712_32x_psu_init(void)
|
||||
+{
|
||||
+ extern int platform_accton_as7712_32x(void);
|
||||
+ if (!platform_accton_as7712_32x()) {
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ extern int platform_accton_as7712_32x(void);
|
||||
+ if (!platform_accton_as7712_32x()) {
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return i2c_add_driver(&as7712_32x_psu_driver);
|
||||
+}
|
||||
@@ -803,7 +933,7 @@ diff --git a/drivers/hwmon/accton_i2c_cpld.c b/drivers/hwmon/accton_i2c_cpld.c
|
||||
index 96e3490..3aeb08d 100644
|
||||
--- a/drivers/hwmon/accton_i2c_cpld.c
|
||||
+++ b/drivers/hwmon/accton_i2c_cpld.c
|
||||
@@ -201,6 +201,29 @@ int platform_accton_as7512_32x(void)
|
||||
@@ -201,6 +201,22 @@ int platform_accton_as7512_32x(void)
|
||||
}
|
||||
EXPORT_SYMBOL(platform_accton_as7512_32x);
|
||||
|
||||
@@ -814,14 +944,7 @@ index 96e3490..3aeb08d 100644
|
||||
+ DMI_MATCH(DMI_BOARD_VENDOR, "Accton"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .ident = "Accton AS7712",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "Accton"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"),
|
||||
+ },
|
||||
+ },
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+int platform_accton_as7712_32x(void)
|
||||
|
||||
@@ -49,21 +49,23 @@
|
||||
|
||||
typedef struct fan_path_S
|
||||
{
|
||||
char present[LEN_FILE_NAME];
|
||||
char status[LEN_FILE_NAME];
|
||||
char speed[LEN_FILE_NAME];
|
||||
char direction[LEN_FILE_NAME];
|
||||
char ctrl_speed[LEN_FILE_NAME];
|
||||
char r_speed[LEN_FILE_NAME];
|
||||
}fan_path_T;
|
||||
|
||||
#define _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) \
|
||||
{ #prj"fan"#id"_fault", #prj"fan"#id"_front_speed_rpm", \
|
||||
#prj"fan_duty_cycle_percentage", #prj"fan"#id"_rear_speed_rpm" }
|
||||
{ #prj"fan"#id"_present", #prj"fan"#id"_fault", #prj"fan"#id"_front_speed_rpm", \
|
||||
#prj"fan"#id"_direction", #prj"fan"#id"_duty_cycle_percentage", #prj"fan"#id"_rear_speed_rpm" }
|
||||
|
||||
#define MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id) _MAKE_FAN_PATH_ON_MAIN_BOARD(prj,id)
|
||||
|
||||
#define MAKE_FAN_PATH_ON_PSU(folder) \
|
||||
{#folder"/psu_fan1_fault", #folder"/psu_fan1_speed_rpm", \
|
||||
#folder"/psu_fan1_duty_cycle_percentage", "" }
|
||||
{"", #folder"/psu_fan1_fault", #folder"/psu_fan1_speed_rpm", \
|
||||
"", #folder"/psu_fan1_duty_cycle_percentage", "" }
|
||||
|
||||
static fan_path_T fan_path[] = /* must map with onlp_fan_id */
|
||||
{
|
||||
@@ -129,6 +131,39 @@ onlp_fan_info_t linfo[] = {
|
||||
if (close(fd) == -1) \
|
||||
return ONLP_STATUS_E_INTERNAL
|
||||
|
||||
static uint32_t
|
||||
_onlp_fani_info_get_psu_fan_direction(void)
|
||||
{
|
||||
/* Try to read direction from PSU1.
|
||||
* If PSU1 is not valid, read from PSU2
|
||||
*/
|
||||
int i = 0;
|
||||
|
||||
for (i = PSU1_ID; i <= PSU2_ID; i++) {
|
||||
psu_type_t psu_type;
|
||||
psu_type = get_psu_type(i, NULL, 0);
|
||||
|
||||
if (psu_type == PSU_TYPE_UNKNOWN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (psu_type) {
|
||||
case PSU_TYPE_AC_F2B:
|
||||
case PSU_TYPE_DC_48V_F2B:
|
||||
case PSU_TYPE_DC_12V_F2B:
|
||||
return ONLP_FAN_STATUS_F2B;
|
||||
case PSU_TYPE_AC_B2F:
|
||||
case PSU_TYPE_DC_48V_B2F:
|
||||
case PSU_TYPE_DC_12V_B2F:
|
||||
return ONLP_FAN_STATUS_B2F;
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info)
|
||||
{
|
||||
@@ -136,14 +171,34 @@ _onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info)
|
||||
char r_data[10] = {0};
|
||||
char fullpath[65] = {0};
|
||||
|
||||
/* check if fan is present
|
||||
*/
|
||||
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].present);
|
||||
OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len);
|
||||
if (atoi(r_data) == 0) {
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
info->status |= ONLP_FAN_STATUS_PRESENT;
|
||||
|
||||
/* get fan fault status (turn on when any one fails)
|
||||
*/
|
||||
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, 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;
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
/* get fan/fanr direction (both : the same)
|
||||
*/
|
||||
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].direction);
|
||||
OPEN_READ_FILE(fd,fullpath,r_data,nbytes,len);
|
||||
|
||||
if (atoi(r_data) == 0) /*B2F*/
|
||||
info->status |= ONLP_FAN_STATUS_B2F;
|
||||
else
|
||||
info->status |= ONLP_FAN_STATUS_F2B;
|
||||
|
||||
/* get fan speed (take the min from two speeds)
|
||||
*/
|
||||
sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].speed);
|
||||
@@ -159,16 +214,11 @@ _onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info)
|
||||
/* get speed percentage from rpm */
|
||||
info->percentage = (info->rpm * 100)/MAX_FAN_SPEED;
|
||||
|
||||
/* check present */
|
||||
if (info->rpm > 0) {
|
||||
info->status |= ONLP_FAN_STATUS_PRESENT;
|
||||
}
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
_onlp_fani_info_get_fan_on_psu(int local_id, int psu_id, onlp_fan_info_t* info)
|
||||
_onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info)
|
||||
{
|
||||
int fd, len, nbytes = 10;
|
||||
char r_data[10] = {0};
|
||||
@@ -176,17 +226,7 @@ _onlp_fani_info_get_fan_on_psu(int local_id, int psu_id, onlp_fan_info_t* info)
|
||||
|
||||
/* get fan direction
|
||||
*/
|
||||
switch(get_psu_type(psu_id, NULL, 0))
|
||||
{
|
||||
case PSU_TYPE_AC_F2B:
|
||||
info->status |= ONLP_FAN_STATUS_F2B;
|
||||
break;
|
||||
case PSU_TYPE_AC_B2F:
|
||||
info->status |= ONLP_FAN_STATUS_B2F;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
info->status |= _onlp_fani_info_get_psu_fan_direction();
|
||||
|
||||
/* get fan fault status
|
||||
*/
|
||||
@@ -227,12 +267,10 @@ onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info)
|
||||
*info = linfo[local_id];
|
||||
|
||||
switch (local_id)
|
||||
{
|
||||
case FAN_1_ON_PSU1:
|
||||
rc = _onlp_fani_info_get_fan_on_psu(local_id, PSU1_ID, info);
|
||||
break;
|
||||
{
|
||||
case FAN_1_ON_PSU1:
|
||||
case FAN_1_ON_PSU2:
|
||||
rc = _onlp_fani_info_get_fan_on_psu(local_id, PSU2_ID, info);
|
||||
rc = _onlp_fani_info_get_fan_on_psu(local_id, info);
|
||||
break;
|
||||
case FAN_1_ON_MAIN_BOARD:
|
||||
case FAN_2_ON_MAIN_BOARD:
|
||||
@@ -245,7 +283,7 @@ onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info)
|
||||
default:
|
||||
rc = ONLP_STATUS_E_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ int deviceNodeReadString(char *filename, char *buffer, int buf_size, int data_le
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define I2C_PSU_MODEL_NAME_LEN 9
|
||||
#define I2C_PSU_MODEL_NAME_LEN 11
|
||||
#define I2C_PSU_FAN_DIR_LEN 3
|
||||
#include <ctype.h>
|
||||
psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
|
||||
@@ -124,7 +124,6 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
|
||||
char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0};
|
||||
char fan_dir[I2C_PSU_FAN_DIR_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);
|
||||
|
||||
@@ -132,32 +131,70 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
if (strncmp(model_name, "YM-2651Y", strlen("YM-2651Y")) != 0) {
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if(isspace(model_name[strlen(model_name)-1])) {
|
||||
model_name[strlen(model_name)-1] = 0;
|
||||
}
|
||||
|
||||
if (modelname) {
|
||||
strncpy(modelname, model_name, modelname_len-1);
|
||||
if (strncmp(model_name, "YM-2651Y", 8) == 0) {
|
||||
if (modelname) {
|
||||
strncpy(modelname, model_name, 8);
|
||||
}
|
||||
|
||||
node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir);
|
||||
if (deviceNodeReadString(node, fan_dir, sizeof(fan_dir), 0) != 0) {
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) {
|
||||
return PSU_TYPE_AC_F2B;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) {
|
||||
return PSU_TYPE_AC_B2F;
|
||||
}
|
||||
}
|
||||
|
||||
node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir);
|
||||
if (strncmp(model_name, "YM-2651V", 8) == 0) {
|
||||
if (modelname) {
|
||||
strncpy(modelname, model_name, 8);
|
||||
}
|
||||
|
||||
if (deviceNodeReadString(node, fan_dir, sizeof(fan_dir), 0) != 0) {
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir);
|
||||
if (deviceNodeReadString(node, fan_dir, sizeof(fan_dir), 0) != 0) {
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) {
|
||||
return PSU_TYPE_DC_48V_F2B;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) {
|
||||
return PSU_TYPE_DC_48V_B2F;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) {
|
||||
return PSU_TYPE_AC_F2B;
|
||||
}
|
||||
if (strncmp(model_name, "PSU-12V-750", 11) == 0) {
|
||||
if (modelname) {
|
||||
strncpy(modelname, model_name, 11);
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) {
|
||||
return PSU_TYPE_AC_B2F;
|
||||
}
|
||||
node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_fan_dir) : PSU2_AC_HWMON_NODE(psu_fan_dir);
|
||||
if (deviceNodeReadString(node, fan_dir, sizeof(fan_dir), 0) != 0) {
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "F2B", 3) == 0) {
|
||||
return PSU_TYPE_DC_12V_F2B;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "B2F", 3) == 0) {
|
||||
return PSU_TYPE_DC_12V_B2F;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "NON", 3) == 0) {
|
||||
return PSU_TYPE_DC_12V_FANLESS;
|
||||
}
|
||||
}
|
||||
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,12 @@ 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_B2F,
|
||||
PSU_TYPE_DC_48V_F2B,
|
||||
PSU_TYPE_DC_48V_B2F,
|
||||
PSU_TYPE_DC_12V_FANLESS,
|
||||
PSU_TYPE_DC_12V_F2B,
|
||||
PSU_TYPE_DC_12V_B2F
|
||||
} psu_type_t;
|
||||
|
||||
psu_type_t get_psu_type(int id, char* modelname, int modelname_len);
|
||||
|
||||
@@ -68,7 +68,7 @@ psu_status_info_get(int id, char *node, int *value)
|
||||
}
|
||||
|
||||
static int
|
||||
psu_ym2651y_pmbus_info_get(int id, char *node, int *value)
|
||||
psu_ym2651_pmbus_info_get(int id, char *node, int *value)
|
||||
{
|
||||
int ret = 0;
|
||||
char buf[PSU_NODE_MAX_INT_LEN + 1] = {0};
|
||||
@@ -99,35 +99,31 @@ onlp_psui_init(void)
|
||||
}
|
||||
|
||||
static int
|
||||
psu_ym2651y_info_get(onlp_psu_info_t* info)
|
||||
psu_ym2651_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;
|
||||
}
|
||||
|
||||
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_ym2651y_pmbus_info_get(index, "psu_v_out", &val) == 0) {
|
||||
if (psu_ym2651_pmbus_info_get(index, "psu_v_out", &val) == 0) {
|
||||
info->mvout = val;
|
||||
info->caps |= ONLP_PSU_CAPS_VOUT;
|
||||
}
|
||||
|
||||
if (psu_ym2651y_pmbus_info_get(index, "psu_i_out", &val) == 0) {
|
||||
if (psu_ym2651_pmbus_info_get(index, "psu_i_out", &val) == 0) {
|
||||
info->miout = val;
|
||||
info->caps |= ONLP_PSU_CAPS_IOUT;
|
||||
}
|
||||
|
||||
if (psu_ym2651y_pmbus_info_get(index, "psu_p_out", &val) == 0) {
|
||||
if (psu_ym2651_pmbus_info_get(index, "psu_p_out", &val) == 0) {
|
||||
info->mpout = val;
|
||||
info->caps |= ONLP_PSU_CAPS_POUT;
|
||||
}
|
||||
@@ -135,6 +131,56 @@ psu_ym2651y_info_get(onlp_psu_info_t* info)
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
#include <onlplib/i2c.h>
|
||||
#define DC12V_750_REG_TO_CURRENT(low, high) (((low << 4 | high >> 4) * 20 * 1000) / 754)
|
||||
#define DC12V_750_REG_TO_VOLTAGE(low, high) ((low << 4 | high >> 4) * 25)
|
||||
|
||||
static int
|
||||
psu_dc12v_750_info_get(onlp_psu_info_t* info)
|
||||
{
|
||||
int pid = ONLP_OID_ID_GET(info->hdr.id);
|
||||
int bus = (PSU1_ID == pid) ? 11 : 10;
|
||||
int iout_low, iout_high;
|
||||
int vout_low, vout_high;
|
||||
|
||||
/* Set capability
|
||||
*/
|
||||
info->caps = ONLP_PSU_CAPS_DC12;
|
||||
|
||||
if (info->status & ONLP_PSU_STATUS_FAILED) {
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Get current
|
||||
*/
|
||||
iout_low = onlp_i2c_readb(bus, 0x6f, 0x0, ONLP_I2C_F_FORCE);
|
||||
iout_high = onlp_i2c_readb(bus, 0x6f, 0x1, ONLP_I2C_F_FORCE);
|
||||
|
||||
if ((iout_low >= 0) && (iout_high >= 0)) {
|
||||
info->miout = DC12V_750_REG_TO_CURRENT(iout_low, iout_high);
|
||||
info->caps |= ONLP_PSU_CAPS_IOUT;
|
||||
}
|
||||
|
||||
/* Get voltage
|
||||
*/
|
||||
vout_low = onlp_i2c_readb(bus, 0x6f, 0x2, ONLP_I2C_F_FORCE);
|
||||
vout_high = onlp_i2c_readb(bus, 0x6f, 0x3, ONLP_I2C_F_FORCE);
|
||||
|
||||
if ((vout_low >= 0) && (vout_high >= 0)) {
|
||||
info->mvout = DC12V_750_REG_TO_VOLTAGE(vout_low, vout_high);
|
||||
info->caps |= ONLP_PSU_CAPS_VOUT;
|
||||
}
|
||||
|
||||
/* Get power based on current and voltage
|
||||
*/
|
||||
if ((info->caps & ONLP_PSU_CAPS_IOUT) && (info->caps & ONLP_PSU_CAPS_VOUT)) {
|
||||
info->mpout = (info->miout * info->mvout) / 1000;
|
||||
info->caps |= ONLP_PSU_CAPS_POUT;
|
||||
}
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all information about the given PSU oid.
|
||||
*/
|
||||
@@ -191,7 +237,18 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
|
||||
switch (psu_type) {
|
||||
case PSU_TYPE_AC_F2B:
|
||||
case PSU_TYPE_AC_B2F:
|
||||
ret = psu_ym2651y_info_get(info);
|
||||
info->caps = ONLP_PSU_CAPS_AC;
|
||||
ret = psu_ym2651_info_get(info);
|
||||
break;
|
||||
case PSU_TYPE_DC_48V_F2B:
|
||||
case PSU_TYPE_DC_48V_B2F:
|
||||
info->caps = ONLP_PSU_CAPS_DC48;
|
||||
ret = psu_ym2651_info_get(info);
|
||||
break;
|
||||
case PSU_TYPE_DC_12V_F2B:
|
||||
case PSU_TYPE_DC_12V_B2F:
|
||||
case PSU_TYPE_DC_12V_FANLESS:
|
||||
ret = psu_dc12v_750_info_get(info);
|
||||
break;
|
||||
case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/
|
||||
info->status |= ONLP_PSU_STATUS_UNPLUGGED;
|
||||
|
||||
Reference in New Issue
Block a user