[as5916-54xks] Add support for YM-2851J DC PSU

This commit is contained in:
brandon_chuang
2019-08-21 14:33:31 +08:00
parent 53dc8fd8d5
commit c3573cd514

View File

@@ -39,6 +39,7 @@
static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
static ssize_t show_linear(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_psu(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t show_string(struct device *dev, struct device_attribute *attr, char *buf);
static int as5916_54xks_psu_probe(struct platform_device *pdev);
@@ -70,6 +71,7 @@ enum psu_data_index {
PSU_FAN1,
PSU_POUT0,
PSU_POUT1,
PSU_VOUT_MODE,
PSU_STATUS_COUNT,
PSU_MODEL = 0,
PSU_SERIAL = 0
@@ -93,7 +95,7 @@ struct ipmi_data {
};
struct ipmi_psu_resp_data {
unsigned char status[19];
unsigned char status[20];
char serial[19];
char model[9];
};
@@ -152,7 +154,7 @@ enum as5916_54x_psu_sysfs_attrs {
#define DECLARE_PSU_SENSOR_DEVICE_ATTR(index) \
static SENSOR_DEVICE_ATTR(psu##index##_present, S_IRUGO, show_psu, NULL, PSU##index##_PRESENT); \
static SENSOR_DEVICE_ATTR(psu##index##_power_good, S_IRUGO, show_psu, NULL, PSU##index##_POWER_GOOD); \
static SENSOR_DEVICE_ATTR(psu##index##_vout, S_IRUGO, show_linear, NULL, PSU##index##_VOUT); \
static SENSOR_DEVICE_ATTR(psu##index##_vout, S_IRUGO, show_vout, NULL, PSU##index##_VOUT); \
static SENSOR_DEVICE_ATTR(psu##index##_iout, S_IRUGO, show_linear, NULL, PSU##index##_IOUT); \
static SENSOR_DEVICE_ATTR(psu##index##_pout, S_IRUGO, show_linear, NULL, PSU##index##_POUT); \
static SENSOR_DEVICE_ATTR(psu##index##_model, S_IRUGO, show_string, NULL, PSU##index##_MODEL); \
@@ -304,6 +306,7 @@ static struct as5916_54xks_psu_data *as5916_54xks_psu_update_device(struct devic
}
data->valid[pid] = 0;
data->ipmi_resp[pid].status[PSU_VOUT_MODE] = 0xff; /* To be compatible for older BMC firmware */
/* Get status from ipmi */
data->ipmi_tx_data[0] = pid + 1; /* PSU ID base id for ipmi start from 1 */
@@ -319,7 +322,7 @@ static struct as5916_54xks_psu_data *as5916_54xks_psu_update_device(struct devic
}
/* Get model name from ipmi */
data->ipmi_tx_data[1] = 0x10;
data->ipmi_tx_data[1] = IPMI_PSU_MODEL_NAME_CMD;
status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2,
data->ipmi_resp[pid].model, sizeof(data->ipmi_resp[pid].model) - 1);
if (unlikely(status != 0)) {
@@ -332,7 +335,7 @@ static struct as5916_54xks_psu_data *as5916_54xks_psu_update_device(struct devic
}
/* Get serial number from ipmi */
data->ipmi_tx_data[1] = 0x11;
data->ipmi_tx_data[1] = IPMI_PSU_SERIAL_NUM_CMD;
status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2,
data->ipmi_resp[pid].serial, sizeof(data->ipmi_resp[pid].serial) - 1);
if (unlikely(status != 0)) {
@@ -421,6 +424,50 @@ exit:
return error;
}
static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR;
u16 value = 0;
int error = 0;
int exponent = 0, mantissa = 0;
int multiplier = 1000;
u8 vout_mode = 0xff;
mutex_lock(&data->update_lock);
data = as5916_54xks_psu_update_device(da);
if (!data->valid[pid]) {
error = -EIO;
goto exit;
}
vout_mode = (u8)data->ipmi_resp[pid].status[PSU_VOUT_MODE];
value = ((u16)data->ipmi_resp[pid].status[PSU_VOUT0] |
(u16)data->ipmi_resp[pid].status[PSU_VOUT1] << 8);
mutex_unlock(&data->update_lock);
if (vout_mode == 0xff) {
exponent = two_complement_to_int(value >> 11, 5, 0x1f);
mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
}
else if (!(vout_mode & 0xe0)){
exponent = two_complement_to_int(vout_mode & 0x1f, 5, 0x1f);
mantissa = two_complement_to_int(value & 0xffff, 16, 0xffff);
}
else {
return -EINVAL;
}
return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) :
sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
exit:
mutex_unlock(&data->update_lock);
return error;
}
static ssize_t show_psu(struct device *dev, struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);