mirror of
https://github.com/Fred78290/nct6687d
synced 2025-01-22 07:27:29 +01:00
FEAT: Add voltage support and min max values for temp & fan
This commit is contained in:
parent
b554b1df96
commit
17236eaa13
1 changed files with 186 additions and 152 deletions
338
nct6687.c
338
nct6687.c
|
@ -13,12 +13,13 @@
|
||||||
*
|
*
|
||||||
* Supports the following chips:
|
* Supports the following chips:
|
||||||
*
|
*
|
||||||
* Chip #vin #fan #pwm #temp chip IDs man ID
|
* Chip #voltage #fan #pwm #temp chip ID
|
||||||
* nct6687 14 8 8 7 0xd592 0xc1 0x5ca3
|
* nct6687 14(1) 8 8 7 0xd592
|
||||||
*
|
*
|
||||||
* Notes:
|
* Notes:
|
||||||
* (1) Total number of vin and temp inputs is 32.
|
* (1) Total number of voltage and 9 displayed.
|
||||||
*/
|
*/
|
||||||
|
#define DEBUG
|
||||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
@ -34,6 +35,9 @@
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||||
|
|
||||||
enum kinds
|
enum kinds
|
||||||
{
|
{
|
||||||
nct6687
|
nct6687
|
||||||
|
@ -120,7 +124,7 @@ static inline void superio_exit(int ioreg)
|
||||||
|
|
||||||
/* Common and NCT6687 specific data */
|
/* Common and NCT6687 specific data */
|
||||||
|
|
||||||
#define NCT6687_NUM_REG_VOLTAGE 14
|
#define NCT6687_NUM_REG_VOLTAGE (sizeof(nct6687_voltage_definition) / sizeof(struct voltage_reg))
|
||||||
#define NCT6687_NUM_REG_TEMP 7
|
#define NCT6687_NUM_REG_TEMP 7
|
||||||
#define NCT6687_NUM_REG_FAN 8
|
#define NCT6687_NUM_REG_FAN 8
|
||||||
#define NCT6687_NUM_REG_PWM 8
|
#define NCT6687_NUM_REG_PWM 8
|
||||||
|
@ -167,22 +171,68 @@ static inline void superio_exit(int ioreg)
|
||||||
#define EC_SPACE_DATA_REGISTER_OFFSET 0x06
|
#define EC_SPACE_DATA_REGISTER_OFFSET 0x06
|
||||||
#define EC_SPACE_PAGE_SELECT 0xFF
|
#define EC_SPACE_PAGE_SELECT 0xFF
|
||||||
|
|
||||||
static const char *const nct6687_voltage_label[] = {
|
struct voltage_reg
|
||||||
"+12V",
|
{
|
||||||
"+5V",
|
u16 reg;
|
||||||
"Vcore",
|
u16 multiplier;
|
||||||
"Voltage #1",
|
const char *label;
|
||||||
"DIMM",
|
};
|
||||||
"CPU I/O",
|
|
||||||
"CPU SA",
|
static struct voltage_reg nct6687_voltage_definition[] = {
|
||||||
"Voltage #2",
|
// +12V
|
||||||
"AVCC3",
|
{
|
||||||
"VTT",
|
.reg = 0,
|
||||||
"VRef",
|
.multiplier = 12,
|
||||||
"VSB",
|
.label = "+12V",
|
||||||
"AVSB",
|
},
|
||||||
"VBat",
|
// + 5V
|
||||||
NULL,
|
{
|
||||||
|
.reg = 1,
|
||||||
|
.multiplier = 5,
|
||||||
|
.label = "+5V",
|
||||||
|
},
|
||||||
|
// +3.3V
|
||||||
|
{
|
||||||
|
.reg = 11,
|
||||||
|
.multiplier = 1,
|
||||||
|
.label = "+3.3V",
|
||||||
|
},
|
||||||
|
// CPU SOC
|
||||||
|
{
|
||||||
|
.reg = 2,
|
||||||
|
.multiplier = 1,
|
||||||
|
.label = "CPU Soc",
|
||||||
|
},
|
||||||
|
// CPU Vcore
|
||||||
|
{
|
||||||
|
.reg = 4,
|
||||||
|
.multiplier = 1,
|
||||||
|
.label = "CPU Vcore",
|
||||||
|
},
|
||||||
|
// CPU 1P8
|
||||||
|
{
|
||||||
|
.reg = 9,
|
||||||
|
.multiplier = 1,
|
||||||
|
.label = "CPU 1P8",
|
||||||
|
},
|
||||||
|
// CPU VDDP
|
||||||
|
{
|
||||||
|
.reg = 10,
|
||||||
|
.multiplier = 1,
|
||||||
|
.label = "CPU VDDP",
|
||||||
|
},
|
||||||
|
// DRAM
|
||||||
|
{
|
||||||
|
.reg = 3,
|
||||||
|
.multiplier = 2,
|
||||||
|
.label = "DRAM",
|
||||||
|
},
|
||||||
|
// DRAM
|
||||||
|
{
|
||||||
|
.reg = 5,
|
||||||
|
.multiplier = 1,
|
||||||
|
.label = "Chipset",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *const nct6687_temp_label[] = {
|
static const char *const nct6687_temp_label[] = {
|
||||||
|
@ -209,7 +259,6 @@ static const char *const nct6687_fan_label[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------- */
|
/* ------------------------------------------------------- */
|
||||||
|
|
||||||
struct nct6687_data
|
struct nct6687_data
|
||||||
{
|
{
|
||||||
int addr; /* IO base of EC space */
|
int addr; /* IO base of EC space */
|
||||||
|
@ -224,19 +273,17 @@ struct nct6687_data
|
||||||
unsigned long last_updated; /* In jiffies */
|
unsigned long last_updated; /* In jiffies */
|
||||||
|
|
||||||
/* Voltage values */
|
/* Voltage values */
|
||||||
s16 voltage[NCT6687_NUM_REG_VOLTAGE];
|
s16 voltage[3][NCT6687_NUM_REG_VOLTAGE]; // 0 = current 1 = min 2 = max
|
||||||
|
|
||||||
/* Temperature values */
|
/* Temperature values */
|
||||||
s32 temperature[NCT6687_NUM_REG_TEMP];
|
s32 temperature[3][NCT6687_NUM_REG_TEMP]; // 0 = current 1 = min 2 = max
|
||||||
|
|
||||||
/* Fan attribute values */
|
/* Fan attribute values */
|
||||||
u16 rpm[NCT6687_NUM_REG_FAN];
|
u16 rpm[3][NCT6687_NUM_REG_FAN]; // 0 = current 1 = min 2 = max
|
||||||
u8 _initialFanControlMode[NCT6687_NUM_REG_FAN];
|
u8 _initialFanControlMode[NCT6687_NUM_REG_FAN];
|
||||||
u8 _initialFanPwmCommand[NCT6687_NUM_REG_FAN];
|
u8 _initialFanPwmCommand[NCT6687_NUM_REG_FAN];
|
||||||
bool _restoreDefaultFanControlRequired[NCT6687_NUM_REG_FAN];
|
bool _restoreDefaultFanControlRequired[NCT6687_NUM_REG_FAN];
|
||||||
u16 fan_min[NCT6687_NUM_REG_FAN];
|
|
||||||
|
|
||||||
u8 have_pwm;
|
|
||||||
u8 pwm[NCT6687_NUM_REG_PWM];
|
u8 pwm[NCT6687_NUM_REG_PWM];
|
||||||
|
|
||||||
/* Remember extra register values over suspend/resume */
|
/* Remember extra register values over suspend/resume */
|
||||||
|
@ -421,15 +468,63 @@ static void nct6687_write(struct nct6687_data *data, u16 address, u16 value)
|
||||||
outb_p(value, data->addr + EC_SPACE_DATA_REGISTER_OFFSET);
|
outb_p(value, data->addr + EC_SPACE_DATA_REGISTER_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nct6687_update_pwm(struct device *dev)
|
static void nct6687_update_temperatures(struct nct6687_data *data)
|
||||||
{
|
{
|
||||||
struct nct6687_data *data = dev_get_drvdata(dev);
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NCT6687_NUM_REG_TEMP; i++)
|
||||||
|
{
|
||||||
|
s32 value = (char)nct6687_read(data, NCT6687_REG_TEMP(i));
|
||||||
|
s32 half = (nct6687_read(data, NCT6687_REG_TEMP(i) + 1) >> 7) & 0x1;
|
||||||
|
s32 temperature = (value * 1000) + (5 * half);
|
||||||
|
|
||||||
|
data->temperature[0][i] = temperature;
|
||||||
|
data->temperature[1][i] = MIN(temperature, data->temperature[1][i]);
|
||||||
|
data->temperature[2][i] = MAX(temperature, data->temperature[2][i]);
|
||||||
|
|
||||||
|
pr_debug("nct6687_update_temperatures[%d]], addr=%04X, value=%d, half=%d, temperature=%d\n", i, NCT6687_REG_TEMP(i), value, half, temperature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nct6687_update_voltage(struct nct6687_data *data)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
/* Measured voltages and limits */
|
||||||
|
for (index = 0; index < NCT6687_NUM_REG_VOLTAGE; index++)
|
||||||
|
{
|
||||||
|
s16 reg = nct6687_voltage_definition[index].reg;
|
||||||
|
s16 high = nct6687_read(data, NCT6687_REG_VOLTAGE(reg)) * 16;
|
||||||
|
s16 low = ((u16)nct6687_read(data, NCT6687_REG_VOLTAGE(reg) + 1)) >> 4;
|
||||||
|
s16 value = low + high;
|
||||||
|
s16 voltage = value * nct6687_voltage_definition[index].multiplier;
|
||||||
|
|
||||||
|
data->voltage[0][index] = voltage;
|
||||||
|
data->voltage[1][index] = MIN(voltage, data->voltage[1][index]);
|
||||||
|
data->voltage[2][index] = MAX(voltage, data->voltage[2][index]);
|
||||||
|
|
||||||
|
pr_debug("nct6687_update_voltage[%d], %s, addr=0x%04x, value=%d, voltage=%d\n", index, nct6687_voltage_definition[index].label, NCT6687_REG_VOLTAGE(index), value, voltage);
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("nct6687_update_voltage\n");
|
||||||
|
pr_debug("nct6687_update_voltage\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nct6687_update_fans(struct nct6687_data *data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(data->rpm); i++)
|
||||||
|
{
|
||||||
|
s16 rmp = nct6687_read16(data, NCT6687_REG_FAN_RPM(i));
|
||||||
|
|
||||||
|
data->rpm[0][i] = rmp;
|
||||||
|
data->rpm[1][i] = MIN(rmp, data->rpm[1][i]);
|
||||||
|
data->rpm[2][i] = MAX(rmp, data->rpm[2][i]);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < NCT6687_NUM_REG_PWM; i++)
|
for (i = 0; i < NCT6687_NUM_REG_PWM; i++)
|
||||||
{
|
{
|
||||||
if (!(data->have_pwm & (1 << i)))
|
|
||||||
continue;
|
|
||||||
data->pwm[i] = nct6687_read(data, NCT6687_REG_PWM(i));
|
data->pwm[i] = nct6687_read(data, NCT6687_REG_PWM(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,54 +532,19 @@ static void nct6687_update_pwm(struct device *dev)
|
||||||
static struct nct6687_data *nct6687_update_device(struct device *dev)
|
static struct nct6687_data *nct6687_update_device(struct device *dev)
|
||||||
{
|
{
|
||||||
struct nct6687_data *data = dev_get_drvdata(dev);
|
struct nct6687_data *data = dev_get_drvdata(dev);
|
||||||
int i;
|
|
||||||
|
|
||||||
mutex_lock(&data->update_lock);
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
if (time_after(jiffies, data->last_updated + HZ) || !data->valid)
|
if (time_after(jiffies, data->last_updated + HZ) || !data->valid)
|
||||||
{
|
{
|
||||||
/* Measured voltages and limits */
|
/* Measured voltages and limits */
|
||||||
for (i = 0; i < NCT6687_NUM_REG_VOLTAGE; i++)
|
nct6687_update_voltage(data);
|
||||||
{
|
|
||||||
s16 high = nct6687_read(data, NCT6687_REG_TEMP(i)) * 16;
|
|
||||||
s16 low = ((u16)nct6687_read(data, NCT6687_REG_TEMP(i) + 1)) >> 4;
|
|
||||||
s16 value = low + high;
|
|
||||||
|
|
||||||
switch (i)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
value *= 12;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
value *= 5;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
value *= 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
data->voltage[i] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Measured temperatures and limits */
|
/* Measured temperatures and limits */
|
||||||
for (i = 0; i < NCT6687_NUM_REG_TEMP; i++)
|
nct6687_update_temperatures(data);
|
||||||
{
|
|
||||||
s32 value = (char)nct6687_read(data, NCT6687_REG_TEMP(i));
|
|
||||||
s32 half = (nct6687_read(data, NCT6687_REG_TEMP(i) + 1) >> 7) & 0x1;
|
|
||||||
|
|
||||||
data->temperature[i] = (value * 1000) + (5 * half);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Measured fan speeds and limits */
|
/* Measured fan speeds and limits */
|
||||||
for (i = 0; i < ARRAY_SIZE(data->rpm); i++)
|
nct6687_update_fans(data);
|
||||||
{
|
|
||||||
data->rpm[i] = nct6687_read16(data, NCT6687_REG_FAN_RPM(i));
|
|
||||||
data->fan_min[i] = nct6687_read16(data, NCT6687_REG_FAN_MIN(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
nct6687_update_pwm(dev);
|
|
||||||
|
|
||||||
data->last_updated = jiffies;
|
data->last_updated = jiffies;
|
||||||
data->valid = true;
|
data->valid = true;
|
||||||
|
@ -502,27 +562,27 @@ static ssize_t show_voltage_label(struct device *dev, struct device_attribute *a
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", nct6687_voltage_label[sattr->index]);
|
return sprintf(buf, "%s\n", nct6687_voltage_definition[sattr->index].label);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t show_voltage(struct device *dev, struct device_attribute *attr, char *buf)
|
static ssize_t show_voltage_value(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
|
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
|
||||||
struct nct6687_data *data = nct6687_update_device(dev);
|
struct nct6687_data *data = nct6687_update_device(dev);
|
||||||
int index = sattr->index;
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", data->voltage[index]);
|
return sprintf(buf, "%d\n", data->voltage[sattr->index][sattr->nr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static umode_t nct6687_voltage_is_visible(struct kobject *kobj, struct attribute *attr, int index)
|
static umode_t nct6687_voltage_is_visible(struct kobject *kobj, struct attribute *attr, int index)
|
||||||
{
|
{
|
||||||
|
pr_debug("nct6687_voltage_is_visible[%d], attr=0x%04X\n", index, attr->mode);
|
||||||
return attr->mode;
|
return attr->mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
SENSOR_TEMPLATE(voltage_label, "voltage%d_label", S_IRUGO, show_voltage_label, NULL, 0);
|
SENSOR_TEMPLATE(voltage_label, "in%d_label", S_IRUGO, show_voltage_label, NULL, 0);
|
||||||
SENSOR_TEMPLATE_2(voltage_input, "voltage%d_input", S_IRUGO, show_voltage, NULL, 0, 0);
|
SENSOR_TEMPLATE_2(voltage_input, "in%d_input", S_IRUGO, show_voltage_value, NULL, 0, 0);
|
||||||
SENSOR_TEMPLATE_2(voltage_min, "voltage%d_min", S_IRUGO, show_voltage, NULL, 0, 1);
|
SENSOR_TEMPLATE_2(voltage_min, "in%d_min", S_IRUGO, show_voltage_value, NULL, 0, 1);
|
||||||
SENSOR_TEMPLATE_2(voltage_max, "voltage%d_max", S_IRUGO, show_voltage, NULL, 0, 2);
|
SENSOR_TEMPLATE_2(voltage_max, "in%d_max", S_IRUGO, show_voltage_value, NULL, 0, 2);
|
||||||
|
|
||||||
static struct sensor_device_template *nct6687_attributes_voltage_template[] = {
|
static struct sensor_device_template *nct6687_attributes_voltage_template[] = {
|
||||||
&sensor_dev_template_voltage_label,
|
&sensor_dev_template_voltage_label,
|
||||||
|
@ -544,21 +604,12 @@ static ssize_t show_fan_label(struct device *dev, struct device_attribute *attr,
|
||||||
return sprintf(buf, "%s\n", nct6687_fan_label[sattr->index]);
|
return sprintf(buf, "%s\n", nct6687_fan_label[sattr->index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t show_fan(struct device *dev, struct device_attribute *attr, char *buf)
|
static ssize_t show_fan_value(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
|
||||||
struct nct6687_data *data = nct6687_update_device(dev);
|
struct nct6687_data *data = nct6687_update_device(dev);
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", data->rpm[sattr->index]);
|
return sprintf(buf, "%d\n", data->rpm[sattr->index][sattr->nr]);
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct nct6687_data *data = nct6687_update_device(dev);
|
|
||||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
|
||||||
int nr = sattr->index;
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", data->fan_min[nr]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static umode_t nct6687_fan_is_visible(struct kobject *kobj, struct attribute *attr, int index)
|
static umode_t nct6687_fan_is_visible(struct kobject *kobj, struct attribute *attr, int index)
|
||||||
|
@ -566,9 +617,10 @@ static umode_t nct6687_fan_is_visible(struct kobject *kobj, struct attribute *at
|
||||||
return attr->mode;
|
return attr->mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
|
|
||||||
SENSOR_TEMPLATE(fan_label, "fan%d_label", S_IRUGO, show_fan_label, NULL, 0);
|
SENSOR_TEMPLATE(fan_label, "fan%d_label", S_IRUGO, show_fan_label, NULL, 0);
|
||||||
//SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IRUGO, show_fan_min, NULL, 0);
|
SENSOR_TEMPLATE_2(fan_input, "fan%d_input", S_IRUGO, show_fan_value, NULL, 0, 0);
|
||||||
|
SENSOR_TEMPLATE_2(fan_min, "fan%d_min", S_IRUGO, show_fan_value, NULL, 0, 1);
|
||||||
|
SENSOR_TEMPLATE_2(fan_max, "fan%d_max", S_IRUGO, show_fan_value, NULL, 0, 2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nct6687_fan_is_visible uses the index into the following array
|
* nct6687_fan_is_visible uses the index into the following array
|
||||||
|
@ -576,9 +628,10 @@ SENSOR_TEMPLATE(fan_label, "fan%d_label", S_IRUGO, show_fan_label, NULL, 0);
|
||||||
* Any change in order or content must be matched.
|
* Any change in order or content must be matched.
|
||||||
*/
|
*/
|
||||||
static struct sensor_device_template *nct6687_attributes_fan_template[] = {
|
static struct sensor_device_template *nct6687_attributes_fan_template[] = {
|
||||||
&sensor_dev_template_fan_input,
|
|
||||||
&sensor_dev_template_fan_label,
|
&sensor_dev_template_fan_label,
|
||||||
// &sensor_dev_template_fan_min,
|
&sensor_dev_template_fan_input,
|
||||||
|
&sensor_dev_template_fan_min,
|
||||||
|
&sensor_dev_template_fan_max,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -597,11 +650,10 @@ static ssize_t show_temperature_label(struct device *dev, struct device_attribut
|
||||||
|
|
||||||
static ssize_t show_temperature_value(struct device *dev, struct device_attribute *attr, char *buf)
|
static ssize_t show_temperature_value(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
|
||||||
struct nct6687_data *data = nct6687_update_device(dev);
|
struct nct6687_data *data = nct6687_update_device(dev);
|
||||||
int index = sattr->index;
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", data->temperature[index]);
|
return sprintf(buf, "%d\n", data->temperature[sattr->index][sattr->nr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static umode_t nct6687_temp_is_visible(struct kobject *kobj, struct attribute *attr, int index)
|
static umode_t nct6687_temp_is_visible(struct kobject *kobj, struct attribute *attr, int index)
|
||||||
|
@ -609,8 +661,10 @@ static umode_t nct6687_temp_is_visible(struct kobject *kobj, struct attribute *a
|
||||||
return attr->mode;
|
return attr->mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
SENSOR_TEMPLATE(temp_input, "temp%d_input", S_IRUGO, show_temperature_value, NULL, 0);
|
|
||||||
SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temperature_label, NULL, 0);
|
SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temperature_label, NULL, 0);
|
||||||
|
SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temperature_value, NULL, 0, 0);
|
||||||
|
SENSOR_TEMPLATE_2(temp_min, "temp%d_min", S_IRUGO, show_temperature_value, NULL, 0, 1);
|
||||||
|
SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO, show_temperature_value, NULL, 0, 2);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nct6687_temp_is_visible uses the index into the following array
|
* nct6687_temp_is_visible uses the index into the following array
|
||||||
|
@ -620,6 +674,8 @@ SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temperature_label, NUL
|
||||||
static struct sensor_device_template *nct6687_attributes_temp_template[] = {
|
static struct sensor_device_template *nct6687_attributes_temp_template[] = {
|
||||||
&sensor_dev_template_temp_input,
|
&sensor_dev_template_temp_input,
|
||||||
&sensor_dev_template_temp_label,
|
&sensor_dev_template_temp_label,
|
||||||
|
&sensor_dev_template_temp_min,
|
||||||
|
&sensor_dev_template_temp_max,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -711,18 +767,7 @@ static void nct6687_restore_fan_control(struct nct6687_data *data, int index)
|
||||||
|
|
||||||
static umode_t nct6687_pwm_is_visible(struct kobject *kobj, struct attribute *attr, int index)
|
static umode_t nct6687_pwm_is_visible(struct kobject *kobj, struct attribute *attr, int index)
|
||||||
{
|
{
|
||||||
struct device *dev = container_of(kobj, struct device, kobj);
|
|
||||||
struct nct6687_data *data = dev_get_drvdata(dev);
|
|
||||||
int pwm = index; /* pwm index */
|
|
||||||
|
|
||||||
if (!(data->have_pwm & (1 << pwm)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Only update pwm values for Mitac boards */
|
|
||||||
//if (data->customer_id == NCT6687_CUSTOMER_ID_MITAC)
|
|
||||||
return attr->mode | S_IWUSR;
|
return attr->mode | S_IWUSR;
|
||||||
|
|
||||||
//return attr->mode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sensor_device_template *nct6687_attributes_pwm_template[] = {
|
static struct sensor_device_template *nct6687_attributes_pwm_template[] = {
|
||||||
|
@ -770,27 +815,36 @@ static void nct6687_setup_fans(struct nct6687_data *data)
|
||||||
{
|
{
|
||||||
u16 reg = nct6687_read(data, NCT6687_REG_FAN_CTRL_MODE(i));
|
u16 reg = nct6687_read(data, NCT6687_REG_FAN_CTRL_MODE(i));
|
||||||
u16 bitMask = 0x01 << i;
|
u16 bitMask = 0x01 << i;
|
||||||
|
u16 rpm = nct6687_read16(data, NCT6687_REG_FAN_RPM(i));
|
||||||
|
|
||||||
|
data->rpm[0][i] = rpm;
|
||||||
|
data->rpm[1][i] = rpm;
|
||||||
|
data->rpm[2][i] = rpm;
|
||||||
data->_initialFanControlMode[i] = (u8)(reg & bitMask);
|
data->_initialFanControlMode[i] = (u8)(reg & bitMask);
|
||||||
data->rpm[i] = nct6687_read16(data, NCT6687_REG_FAN_RPM(i));
|
|
||||||
data->fan_min[i] = nct6687_read16(data, NCT6687_REG_FAN_MIN(i));
|
|
||||||
data->_restoreDefaultFanControlRequired[i] = false;
|
data->_restoreDefaultFanControlRequired[i] = false;
|
||||||
|
|
||||||
pr_debug("nct6687_setup_fans[%d], %s - addr=%04X, ctrl=%04X, rpm=%d, fan min=%d, _initialFanControlMode=%d\n", i, nct6687_fan_label[i], NCT6687_REG_FAN_CTRL_MODE(i), reg, data->rpm[i], data->fan_min[i], data->_initialFanControlMode[i]);
|
pr_debug("nct6687_setup_fans[%d], %s - addr=%04X, ctrl=%04X, rpm=%d, _initialFanControlMode=%d\n", i, nct6687_fan_label[i], NCT6687_REG_FAN_CTRL_MODE(i), reg, rpm, data->_initialFanControlMode[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nct6687_setup_pwm(struct nct6687_data *data)
|
static void nct6687_setup_voltages(struct nct6687_data *data)
|
||||||
{
|
{
|
||||||
int i;
|
int index;
|
||||||
|
|
||||||
for (i = 0; i < NCT6687_NUM_REG_PWM; i++)
|
/* Measured voltages and limits */
|
||||||
|
for (index = 0; index < NCT6687_NUM_REG_VOLTAGE; index++)
|
||||||
{
|
{
|
||||||
data->have_pwm |= 1 << i;
|
s16 reg = nct6687_voltage_definition[index].reg;
|
||||||
data->_initialFanPwmCommand[i] = nct6687_read(data, NCT6687_REG_FAN_PWM_COMMAND(i));
|
s16 high = nct6687_read(data, NCT6687_REG_VOLTAGE(reg)) * 16;
|
||||||
data->pwm[i] = nct6687_read(data, NCT6687_REG_PWM(i));
|
s16 low = ((u16)nct6687_read(data, NCT6687_REG_VOLTAGE(reg) + 1)) >> 4;
|
||||||
|
s16 value = low + high;
|
||||||
|
s16 voltage = value * nct6687_voltage_definition[index].multiplier;
|
||||||
|
|
||||||
pr_debug("nct6687_setup_pwm[%d], addr=%04X, pwm=%d, _initialFanPwmCommand=%d\n", i, NCT6687_REG_FAN_PWM_COMMAND(i), data->pwm[i], data->_initialFanPwmCommand[i]);
|
data->voltage[0][index] = voltage;
|
||||||
|
data->voltage[1][index] = voltage;
|
||||||
|
data->voltage[2][index] = voltage;
|
||||||
|
|
||||||
|
pr_debug("nct6687_setup_voltages[%d], %s, addr=0x%04x, value=%d, voltage=%d\n", index, nct6687_voltage_definition[index].label, NCT6687_REG_VOLTAGE(index), value, voltage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,43 +856,26 @@ static void nct6687_setup_temperatures(struct nct6687_data *data)
|
||||||
{
|
{
|
||||||
s32 value = (char)nct6687_read(data, NCT6687_REG_TEMP(i));
|
s32 value = (char)nct6687_read(data, NCT6687_REG_TEMP(i));
|
||||||
s32 half = (nct6687_read(data, NCT6687_REG_TEMP(i) + 1) >> 7) & 0x1;
|
s32 half = (nct6687_read(data, NCT6687_REG_TEMP(i) + 1) >> 7) & 0x1;
|
||||||
|
s32 temperature = (value * 1000) + (5 * half);
|
||||||
|
|
||||||
data->temperature[i] = (value * 1000) + (5 * half);
|
data->temperature[0][i] = temperature;
|
||||||
|
data->temperature[1][i] = temperature;
|
||||||
|
data->temperature[2][i] = temperature;
|
||||||
|
|
||||||
pr_debug("nct6687_setup_temperatures[%d]], addr=%04X, value=%d, half=%d, temperature=%d\n", i, NCT6687_REG_TEMP(i), value, half, data->temperature[i]);
|
pr_debug("nct6687_setup_temperatures[%d]], addr=%04X, value=%d, half=%d, temperature=%d\n", i, NCT6687_REG_TEMP(i), value, half, temperature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nct6687_setup_voltage(struct nct6687_data *data)
|
static void nct6687_setup_pwm(struct nct6687_data *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Measured voltages and limits */
|
for (i = 0; i < NCT6687_NUM_REG_PWM; i++)
|
||||||
for (i = 0; i < NCT6687_NUM_REG_VOLTAGE; i++)
|
|
||||||
{
|
{
|
||||||
s16 high = nct6687_read(data, NCT6687_REG_TEMP(i)) * 16;
|
data->_initialFanPwmCommand[i] = nct6687_read(data, NCT6687_REG_FAN_PWM_COMMAND(i));
|
||||||
s16 low = ((u16)nct6687_read(data, NCT6687_REG_TEMP(i) + 1)) >> 4;
|
data->pwm[i] = nct6687_read(data, NCT6687_REG_PWM(i));
|
||||||
s16 value = low + high;
|
|
||||||
|
|
||||||
switch (i)
|
pr_debug("nct6687_setup_pwm[%d], addr=%04X, pwm=%d, _initialFanPwmCommand=%d\n", i, NCT6687_REG_FAN_PWM_COMMAND(i), data->pwm[i], data->_initialFanPwmCommand[i]);
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
value *= 12;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
value *= 5;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
value *= 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->voltage[i] = value;
|
|
||||||
|
|
||||||
pr_debug("nct6687_setup_voltage[%d], addr=0x%04x, voltage=%d\n", i, NCT6687_REG_TEMP(i), value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,19 +930,16 @@ static int nct6687_probe(struct platform_device *pdev)
|
||||||
nct6687_setup_fans(data);
|
nct6687_setup_fans(data);
|
||||||
nct6687_setup_pwm(data);
|
nct6687_setup_pwm(data);
|
||||||
nct6687_setup_temperatures(data);
|
nct6687_setup_temperatures(data);
|
||||||
nct6687_setup_voltage(data);
|
nct6687_setup_voltages(data);
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
/* Register sysfs hooks */
|
||||||
|
|
||||||
if (data->have_pwm)
|
group = nct6687_create_attr_group(dev, &nct6687_pwm_template_group, NCT6687_NUM_REG_FAN);
|
||||||
{
|
|
||||||
group = nct6687_create_attr_group(dev, &nct6687_pwm_template_group, fls(data->have_pwm));
|
|
||||||
|
|
||||||
if (IS_ERR(group))
|
if (IS_ERR(group))
|
||||||
return PTR_ERR(group);
|
return PTR_ERR(group);
|
||||||
|
|
||||||
data->groups[groups++] = group;
|
data->groups[groups++] = group;
|
||||||
}
|
|
||||||
|
|
||||||
group = nct6687_create_attr_group(dev, &nct6687_voltage_template_group, NCT6687_NUM_REG_VOLTAGE);
|
group = nct6687_create_attr_group(dev, &nct6687_voltage_template_group, NCT6687_NUM_REG_VOLTAGE);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue