提交 adfeb6e9 编写于 作者: L Linus Torvalds

Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  hwmon: (sysfs-interface) Update tempX_type attribute to be more generic
  hwmon: (adm1031) Fix coding style issues
  hwmon: (it87) Add IT8728F support
  hwmon: (coretemp) Add missing section annotations
  hwmon: (lm90) Add range check to set_update_interval
  hwmon: (lm63) Support extended lookup table of LM96163
  hwmon: (lm63) Expose automatic fan speed control lookup table
  hwmon: (lm63) Fix incorrect comment about I2C address
  hwmon: (lm63) LM64 has a dedicated pin for tachometer
  hwmon: (lm63) Add sensor type attribute for external sensor on LM96163
  hwmon: (lm63) Add support for update_interval sysfs attribute
  hwmon: (lm63) Add support for writing the external critical temperature
  hwmon: (lm63) Add support for unsigned upper temperature limits
  hwmon: (lm63) Add support for LM96163
  hwmon: (lm63) Add support for external temperature offset register
  hwmon: (lm63) Fix checkpatch errors
  hwmon: (max1111) Change sysfs interface to in[0-3]_input in millivolts
......@@ -26,6 +26,10 @@ Supported chips:
Prefix: 'it8721'
Addresses scanned: from Super I/O config space (8 I/O ports)
Datasheet: Not publicly available
* IT8728F
Prefix: 'it8728'
Addresses scanned: from Super I/O config space (8 I/O ports)
Datasheet: Not publicly available
* SiS950 [clone of IT8705F]
Prefix: 'it87'
Addresses scanned: from Super I/O config space (8 I/O ports)
......@@ -71,7 +75,7 @@ Description
-----------
This driver implements support for the IT8705F, IT8712F, IT8716F,
IT8718F, IT8720F, IT8721F, IT8726F, IT8758E and SiS950 chips.
IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E and SiS950 chips.
These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
joysticks and other miscellaneous stuff. For hardware monitoring, they
......@@ -105,6 +109,9 @@ The IT8726F is just bit enhanced IT8716F with additional hardware
for AMD power sequencing. Therefore the chip will appear as IT8716F
to userspace applications.
The IT8728F is considered compatible with the IT8721F, until a datasheet
becomes available (hopefully.)
Temperatures are measured in degrees Celsius. An alarm is triggered once
when the Overtemperature Shutdown limit is crossed.
......@@ -121,8 +128,8 @@ alarm is triggered if the voltage has crossed a programmable minimum or
maximum limit. Note that minimum in this case always means 'closest to
zero'; this is important for negative voltage measurements. All voltage
inputs can measure voltages between 0 and 4.08 volts, with a resolution of
0.016 volt (except IT8721F/IT8758E: 0.012 volt.) The battery voltage in8 does
not have limit registers.
0.016 volt (except IT8721F/IT8758E and IT8728F: 0.012 volt.) The battery
voltage in8 does not have limit registers.
On the IT8721F/IT8758E, some voltage inputs are internal and scaled inside
the chip (in7, in8 and optionally in3). The driver handles this transparently
......
......@@ -12,6 +12,11 @@ Supported chips:
Addresses scanned: I2C 0x18 and 0x4e
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/pf/LM/LM64.html
* National Semiconductor LM96163
Prefix: 'lm96163'
Addresses scanned: I2C 0x4c
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/pf/LM/LM96163.html
Author: Jean Delvare <khali@linux-fr.org>
......@@ -49,16 +54,24 @@ value for measuring the speed of the fan. It can measure fan speeds down to
Note that the pin used for fan monitoring is shared with an alert out
function. Depending on how the board designer wanted to use the chip, fan
speed monitoring will or will not be possible. The proper chip configuration
is left to the BIOS, and the driver will blindly trust it.
is left to the BIOS, and the driver will blindly trust it. Only the original
LM63 suffers from this limitation, the LM64 and LM96163 have separate pins
for fan monitoring and alert out. On the LM64, monitoring is always enabled;
on the LM96163 it can be disabled.
A PWM output can be used to control the speed of the fan. The LM63 has two
PWM modes: manual and automatic. Automatic mode is not fully implemented yet
(you cannot define your custom PWM/temperature curve), and mode change isn't
supported either.
The lm63 driver will not update its values more frequently than every
second; reading them more often will do no harm, but will return 'old'
values.
The lm63 driver will not update its values more frequently than configured with
the update_interval sysfs attribute; reading them more often will do no harm,
but will return 'old' values. Values in the automatic fan control lookup table
(attributes pwm1_auto_*) have their own independent lifetime of 5 seconds.
The LM64 is effectively an LM63 with GPIO lines. The driver does not
support these GPIO lines at present.
The LM96163 is an enhanced version of LM63 with improved temperature accuracy
and better PWM resolution. For LM96163, the external temperature sensor type is
configurable as CPU embedded diode(1) or 3904 transistor(2).
......@@ -304,7 +304,7 @@ value (fastest fan speed) wins.
temp[1-*]_type Sensor type selection.
Integers 1 to 6
RW
1: PII/Celeron Diode
1: CPU embedded diode
2: 3904 transistor
3: thermal diode
4: thermistor
......
......@@ -474,8 +474,8 @@ config SENSORS_IT87
select HWMON_VID
help
If you say yes here you get support for ITE IT8705F, IT8712F,
IT8716F, IT8718F, IT8720F, IT8721F, IT8726F and IT8758E sensor
chips, and the SiS960 clone.
IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E
sensor chips, and the SiS960 clone.
This driver can also be built as a module. If so, the module
will be called it87.
......@@ -515,11 +515,11 @@ config SENSORS_LINEAGE
will be called lineage-pem.
config SENSORS_LM63
tristate "National Semiconductor LM63 and LM64"
tristate "National Semiconductor LM63 and compatibles"
depends on I2C
help
If you say yes here you get support for the National
Semiconductor LM63 and LM64 remote diode digital temperature
Semiconductor LM63, LM64, and LM96163 remote diode digital temperature
sensors with integrated fan control. Such chips are found
on the Tyan S4882 (Thunder K8QS Pro) motherboard, among
others.
......
......@@ -155,7 +155,8 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
#define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \
(val) | 0x70 : (val))
#define FAN_FROM_REG(reg, div) ((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
#define FAN_FROM_REG(reg, div) ((reg) ? \
(11250 * 60) / ((reg) * (div)) : 0)
static int FAN_TO_REG(int reg, int div)
{
......@@ -174,8 +175,8 @@ static int FAN_TO_REG(int reg, int div)
(((reg) & 0x1F) | (((val) << 5) & 0xe0))
#define AUTO_TEMP_MIN_TO_REG(val, reg) \
((((val)/500) & 0xf8)|((reg) & 0x7))
#define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1<< ((reg)&0x7)))
((((val) / 500) & 0xf8) | ((reg) & 0x7))
#define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1 << ((reg) & 0x7)))
#define AUTO_TEMP_MIN_FROM_REG(reg) (1000 * ((((reg) >> 3) & 0x1f) << 2))
#define AUTO_TEMP_MIN_FROM_REG_DEG(reg) ((((reg) >> 3) & 0x1f) << 2)
......@@ -202,7 +203,7 @@ static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
/* FAN auto control */
#define GET_FAN_AUTO_BITFIELD(data, idx) \
(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2]
(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2]
/* The tables below contains the possible values for the auto fan
* control bitfields. the index in the table is the register value.
......@@ -230,7 +231,7 @@ static const auto_chan_table_t auto_channel_select_table_adm1030 = {
*/
static int
get_fan_auto_nearest(struct adm1031_data *data,
int chan, u8 val, u8 reg, u8 * new_reg)
int chan, u8 val, u8 reg, u8 *new_reg)
{
int i;
int first_match = -1, exact_match = -1;
......@@ -258,13 +259,13 @@ get_fan_auto_nearest(struct adm1031_data *data,
}
}
if (exact_match >= 0) {
if (exact_match >= 0)
*new_reg = exact_match;
} else if (first_match >= 0) {
else if (first_match >= 0)
*new_reg = first_match;
} else {
else
return -EINVAL;
}
return 0;
}
......@@ -283,23 +284,28 @@ set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val = simple_strtol(buf, NULL, 10);
long val;
u8 reg;
int ret;
u8 old_fan_mode;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
old_fan_mode = data->conf1;
mutex_lock(&data->update_lock);
if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg);
if (ret) {
mutex_unlock(&data->update_lock);
return ret;
}
data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
(old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
if (data->conf1 & ADM1031_CONF1_AUTO_MODE){
if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
/* Switch to Auto Fan Mode
* Save PWM registers
* Set PWM registers to 33% Both */
......@@ -350,7 +356,12 @@ set_auto_temp_min(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val = simple_strtol(buf, NULL, 10);
long val;
int ret;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
mutex_lock(&data->update_lock);
data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
......@@ -374,10 +385,16 @@ set_auto_temp_max(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val = simple_strtol(buf, NULL, 10);
long val;
int ret;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
mutex_lock(&data->update_lock);
data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr],
data->pwm[nr]);
adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
data->temp_max[nr]);
mutex_unlock(&data->update_lock);
......@@ -410,8 +427,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val = simple_strtol(buf, NULL, 10);
int reg;
long val;
int ret, reg;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
mutex_lock(&data->update_lock);
if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
......@@ -449,9 +470,13 @@ static int trust_fan_readings(struct adm1031_data *data, int chan)
if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
switch (data->conf1 & 0x60) {
case 0x00: /* remote temp1 controls fan1 remote temp2 controls fan2 */
case 0x00:
/*
* remote temp1 controls fan1,
* remote temp2 controls fan2
*/
res = data->temp[chan+1] >=
AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
break;
case 0x20: /* remote temp1 controls both fans */
res =
......@@ -515,7 +540,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val = simple_strtol(buf, NULL, 10);
long val;
int ret;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
mutex_lock(&data->update_lock);
if (val) {
......@@ -534,10 +564,15 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val = simple_strtol(buf, NULL, 10);
long val;
u8 tmp;
int old_div;
int new_min;
int ret;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
tmp = val == 8 ? 0xc0 :
val == 4 ? 0x80 :
......@@ -631,9 +666,13 @@ static ssize_t set_temp_offset(struct device *dev,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val;
long val;
int ret;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -15000, 15000);
mutex_lock(&data->update_lock);
data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
......@@ -648,9 +687,13 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val;
long val;
int ret;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
mutex_lock(&data->update_lock);
data->temp_min[nr] = TEMP_TO_REG(val);
......@@ -665,9 +708,13 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val;
long val;
int ret;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
mutex_lock(&data->update_lock);
data->temp_max[nr] = TEMP_TO_REG(val);
......@@ -682,9 +729,13 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct adm1031_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int val;
long val;
int ret;
ret = kstrtol(buf, 10, &val);
if (ret)
return ret;
val = simple_strtol(buf, NULL, 10);
val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
mutex_lock(&data->update_lock);
data->temp_crit[nr] = TEMP_TO_REG(val);
......@@ -711,7 +762,8 @@ temp_reg(2);
temp_reg(3);
/* Alarms */
static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct adm1031_data *data = adm1031_update_device(dev);
return sprintf(buf, "%d\n", data->alarm);
......@@ -919,12 +971,13 @@ static int adm1031_probe(struct i2c_client *client,
adm1031_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
err = sysfs_create_group(&client->dev.kobj, &adm1031_group);
if (err)
goto exit_free;
if (data->chip_type == adm1031) {
if ((err = sysfs_create_group(&client->dev.kobj,
&adm1031_group_opt)))
err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt);
if (err)
goto exit_remove;
}
......@@ -970,14 +1023,13 @@ static void adm1031_init_client(struct i2c_client *client)
}
/* Initialize the ADM1031 chip (enables fan speed reading ) */
read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
if ((read_val | mask) != read_val) {
adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
}
if ((read_val | mask) != read_val)
adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
ADM1031_CONF1_MONITOR_ENABLE);
adm1031_write_value(client, ADM1031_REG_CONF1,
read_val | ADM1031_CONF1_MONITOR_ENABLE);
}
/* Read the chip's update rate */
......@@ -1024,8 +1076,7 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
/* oldh is actually newer */
if (newh != oldh)
dev_warn(&client->dev,
"Remote temperature may be "
"wrong.\n");
"Remote temperature may be wrong.\n");
#endif
}
data->temp[chan] = newh;
......@@ -1052,22 +1103,24 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
| (adm1031_read_value(client, ADM1031_REG_STATUS(1))
<< 8);
if (data->chip_type == adm1030) {
| (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
if (data->chip_type == adm1030)
data->alarm &= 0xc0ff;
}
for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
chan++) {
data->fan_div[chan] =
adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
adm1031_read_value(client,
ADM1031_REG_FAN_DIV(chan));
data->fan_min[chan] =
adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan));
adm1031_read_value(client,
ADM1031_REG_FAN_MIN(chan));
data->fan[chan] =
adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
adm1031_read_value(client,
ADM1031_REG_FAN_SPEED(chan));
data->pwm[chan] =
0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
(4*chan));
(adm1031_read_value(client,
ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
}
data->last_updated = jiffies;
data->valid = 1;
......
......@@ -190,7 +190,8 @@ static ssize_t show_temp(struct device *dev,
return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN;
}
static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
struct device *dev)
{
/* The 100C is default for both mobile and non mobile CPUs */
......@@ -284,7 +285,8 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
return tjmax;
}
static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
struct device *dev)
{
int err;
u32 eax, edx;
......@@ -323,7 +325,8 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
return adjust_tjmax(c, id, dev);
}
static int create_name_attr(struct platform_data *pdata, struct device *dev)
static int __devinit create_name_attr(struct platform_data *pdata,
struct device *dev)
{
sysfs_attr_init(&pdata->name_attr.attr);
pdata->name_attr.attr.name = "name";
......@@ -332,8 +335,8 @@ static int create_name_attr(struct platform_data *pdata, struct device *dev)
return device_create_file(dev, &pdata->name_attr);
}
static int create_core_attrs(struct temp_data *tdata, struct device *dev,
int attr_no)
static int __cpuinit create_core_attrs(struct temp_data *tdata,
struct device *dev, int attr_no)
{
int err, i;
static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
......@@ -383,7 +386,7 @@ static int __cpuinit chk_ucode_version(unsigned int cpu)
return 0;
}
static struct platform_device *coretemp_get_pdev(unsigned int cpu)
static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu)
{
u16 phys_proc_id = TO_PHYS_ID(cpu);
struct pdev_entry *p;
......@@ -400,7 +403,8 @@ static struct platform_device *coretemp_get_pdev(unsigned int cpu)
return NULL;
}
static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
static struct temp_data __cpuinit *init_temp_data(unsigned int cpu,
int pkg_flag)
{
struct temp_data *tdata;
......@@ -418,7 +422,7 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)
return tdata;
}
static int create_core_data(struct platform_device *pdev,
static int __cpuinit create_core_data(struct platform_device *pdev,
unsigned int cpu, int pkg_flag)
{
struct temp_data *tdata;
......@@ -489,7 +493,7 @@ static int create_core_data(struct platform_device *pdev,
return err;
}
static void coretemp_add_core(unsigned int cpu, int pkg_flag)
static void __cpuinit coretemp_add_core(unsigned int cpu, int pkg_flag)
{
struct platform_device *pdev = coretemp_get_pdev(cpu);
int err;
......@@ -618,7 +622,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
return err;
}
static void coretemp_device_remove(unsigned int cpu)
static void __cpuinit coretemp_device_remove(unsigned int cpu)
{
struct pdev_entry *p, *n;
u16 phys_proc_id = TO_PHYS_ID(cpu);
......@@ -634,7 +638,7 @@ static void coretemp_device_remove(unsigned int cpu)
mutex_unlock(&pdev_list_mutex);
}
static bool is_any_core_online(struct platform_data *pdata)
static bool __cpuinit is_any_core_online(struct platform_data *pdata)
{
int i;
......
......@@ -17,6 +17,7 @@
* IT8720F Super I/O chip w/LPC interface
* IT8721F Super I/O chip w/LPC interface
* IT8726F Super I/O chip w/LPC interface
* IT8728F Super I/O chip w/LPC interface
* IT8758E Super I/O chip w/LPC interface
* Sis950 A clone of the IT8705F
*
......@@ -58,7 +59,7 @@
#define DRVNAME "it87"
enum chips { it87, it8712, it8716, it8718, it8720, it8721 };
enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728 };
static unsigned short force_id;
module_param(force_id, ushort, 0);
......@@ -135,6 +136,7 @@ static inline void superio_exit(void)
#define IT8720F_DEVID 0x8720
#define IT8721F_DEVID 0x8721
#define IT8726F_DEVID 0x8726
#define IT8728F_DEVID 0x8728
#define IT87_ACT_REG 0x30
#define IT87_BASE_REG 0x60
......@@ -274,11 +276,31 @@ struct it87_data {
s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */
};
static inline int has_12mv_adc(const struct it87_data *data)
{
/*
* IT8721F and later have a 12 mV ADC, also with internal scaling
* on selected inputs.
*/
return data->type == it8721
|| data->type == it8728;
}
static inline int has_newer_autopwm(const struct it87_data *data)
{
/*
* IT8721F and later have separate registers for the temperature
* mapping and the manual duty cycle.
*/
return data->type == it8721
|| data->type == it8728;
}
static u8 in_to_reg(const struct it87_data *data, int nr, long val)
{
long lsb;
if (data->type == it8721) {
if (has_12mv_adc(data)) {
if (data->in_scaled & (1 << nr))
lsb = 24;
else
......@@ -292,7 +314,7 @@ static u8 in_to_reg(const struct it87_data *data, int nr, long val)
static int in_from_reg(const struct it87_data *data, int nr, int val)
{
if (data->type == it8721) {
if (has_12mv_adc(data)) {
if (data->in_scaled & (1 << nr))
return val * 24;
else
......@@ -329,7 +351,7 @@ static inline u16 FAN16_TO_REG(long rpm)
static u8 pwm_to_reg(const struct it87_data *data, long val)
{
if (data->type == it8721)
if (has_newer_autopwm(data))
return val;
else
return val >> 1;
......@@ -337,7 +359,7 @@ static u8 pwm_to_reg(const struct it87_data *data, long val)
static int pwm_from_reg(const struct it87_data *data, u8 reg)
{
if (data->type == it8721)
if (has_newer_autopwm(data))
return reg;
else
return (reg & 0x7f) << 1;
......@@ -374,7 +396,8 @@ static inline int has_16bit_fans(const struct it87_data *data)
|| data->type == it8716
|| data->type == it8718
|| data->type == it8720
|| data->type == it8721;
|| data->type == it8721
|| data->type == it8728;
}
static inline int has_old_autopwm(const struct it87_data *data)
......@@ -842,7 +865,7 @@ static ssize_t set_pwm_enable(struct device *dev,
data->fan_main_ctrl);
} else {
if (val == 1) /* Manual mode */
data->pwm_ctrl[nr] = data->type == it8721 ?
data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
data->pwm_temp_map[nr] :
data->pwm_duty[nr];
else /* Automatic mode */
......@@ -870,7 +893,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
return -EINVAL;
mutex_lock(&data->update_lock);
if (data->type == it8721) {
if (has_newer_autopwm(data)) {
/* If we are in automatic mode, the PWM duty cycle register
* is read-only so we can't write the value */
if (data->pwm_ctrl[nr] & 0x80) {
......@@ -1311,8 +1334,8 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
struct it87_data *data = dev_get_drvdata(dev);
int nr = to_sensor_dev_attr(attr)->index;
return sprintf(buf, "%s\n", data->type == it8721 ? labels_it8721[nr]
: labels[nr]);
return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr]
: labels[nr]);
}
static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
......@@ -1605,6 +1628,9 @@ static int __init it87_find(unsigned short *address,
case IT8721F_DEVID:
sio_data->type = it8721;
break;
case IT8728F_DEVID:
sio_data->type = it8728;
break;
case 0xffff: /* No device at all */
goto exit;
default:
......@@ -1646,8 +1672,11 @@ static int __init it87_find(unsigned short *address,
superio_select(GPIO);
reg = superio_inb(IT87_SIO_GPIO3_REG);
if (sio_data->type == it8721) {
/* The IT8721F/IT8758E doesn't have VID pins at all */
if (sio_data->type == it8721 || sio_data->type == it8728) {
/*
* The IT8721F/IT8758E doesn't have VID pins at all,
* not sure about the IT8728F.
*/
sio_data->skip_vid = 1;
} else {
/* We need at least 4 VID pins */
......@@ -1692,7 +1721,8 @@ static int __init it87_find(unsigned short *address,
}
if (reg & (1 << 0))
sio_data->internal |= (1 << 0);
if ((reg & (1 << 1)) || sio_data->type == it8721)
if ((reg & (1 << 1)) || sio_data->type == it8721 ||
sio_data->type == it8728)
sio_data->internal |= (1 << 1);
sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
......@@ -1770,6 +1800,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
"it8718",
"it8720",
"it8721",
"it8728",
};
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
......@@ -1807,7 +1838,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
enable_pwm_interface = it87_check_pwm(dev);
/* Starting with IT8721F, we handle scaling of internal voltages */
if (data->type == it8721) {
if (has_12mv_adc(data)) {
if (sio_data->internal & (1 << 0))
data->in_scaled |= (1 << 3); /* in3 is AVCC */
if (sio_data->internal & (1 << 1))
......@@ -2093,7 +2124,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
{
data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
if (data->type == it8721) {
if (has_newer_autopwm(data)) {
data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
data->pwm_duty[nr] = it87_read_value(data,
IT87_REG_PWM_DUTY(nr));
......
此差异已折叠。
......@@ -917,7 +917,7 @@ static ssize_t set_update_interval(struct device *dev,
return err;
mutex_lock(&data->update_lock);
lm90_set_convrate(client, data, val);
lm90_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000));
mutex_unlock(&data->update_lock);
return count;
......
......@@ -106,11 +106,14 @@ static ssize_t show_adc(struct device *dev,
if (ret < 0)
return ret;
return sprintf(buf, "%d\n", ret);
/* assume the reference voltage to be 2.048V, with an 8-bit sample,
* the LSB weight is 8mV
*/
return sprintf(buf, "%d\n", ret * 8);
}
#define MAX1111_ADC_ATTR(_id) \
SENSOR_DEVICE_ATTR(adc##_id##_in, S_IRUGO, show_adc, NULL, _id)
SENSOR_DEVICE_ATTR(in##_id##_input, S_IRUGO, show_adc, NULL, _id)
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static MAX1111_ADC_ATTR(0);
......@@ -120,10 +123,10 @@ static MAX1111_ADC_ATTR(3);
static struct attribute *max1111_attributes[] = {
&dev_attr_name.attr,
&sensor_dev_attr_adc0_in.dev_attr.attr,
&sensor_dev_attr_adc1_in.dev_attr.attr,
&sensor_dev_attr_adc2_in.dev_attr.attr,
&sensor_dev_attr_adc3_in.dev_attr.attr,
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_in3_input.dev_attr.attr,
NULL,
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册