Synchronize with upstream version

Also ensure the driver still builds with the latest upstream kernel.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Guenter Roeck
2015-01-17 10:00:02 -08:00
parent 91230349d3
commit 034e27046c
3 changed files with 160 additions and 55 deletions

View File

@@ -3,8 +3,8 @@ TARGET := $(shell uname -r)
# Or specific version
#TARGET := 2.6.33.5
KERNEL_MODULES := /lib/modules/$(TARGET)
KERNEL_BUILD := $(KERNEL_MODULES)/build
# KERNEL_BUILD := /usr/src/linux-headers-$(TARGET)
# KERNEL_BUILD := $(KERNEL_MODULES)/build
KERNEL_BUILD := /usr/src/linux-headers-$(TARGET)
#SYSTEM_MAP := $(KERNEL_BUILD)/System.map
SYSTEM_MAP := /boot/System.map-$(TARGET)
@@ -15,7 +15,8 @@ DRIVER := it87
# the module:
MOD_SUBDIR = drivers/hwmon
obj-m := $(DRIVER).o
obj-m := $(patsubst %,%.o,$(DRIVER))
obj-ko := $(patsubst %,%.ko,$(DRIVER))
MAKEFLAGS += --no-print-directory

View File

@@ -11,6 +11,10 @@
#include <linux/version.h>
#ifndef clamp_val
#define clamp_val SENSORS_LIMIT
#endif
#ifndef request_muxed_region
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 28)
#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name))

204
it87.c
View File

@@ -10,7 +10,9 @@
* This driver supports only the Environment Controller in the IT8705F and
* similar parts. The other devices are supported by different drivers.
*
* Supports: IT8705F Super I/O chip w/LPC interface
* Supports: IT8603E Super I/O chip w/LPC interface
* IT8623E Super I/O chip w/LPC interface
* IT8705F Super I/O chip w/LPC interface
* IT8712F Super I/O chip w/LPC interface
* IT8716F Super I/O chip w/LPC interface
* IT8718F Super I/O chip w/LPC interface
@@ -19,12 +21,14 @@
* IT8726F Super I/O chip w/LPC interface
* IT8728F Super I/O chip w/LPC interface
* IT8758E Super I/O chip w/LPC interface
* IT8771E Super I/O chip w/LPC interface
* IT8772E Super I/O chip w/LPC interface
* IT8782F Super I/O chip w/LPC interface
* IT8783E/F Super I/O chip w/LPC interface
* Sis950 A clone of the IT8705F
*
* Copyright (C) 2001 Chris Gauthron
* Copyright (C) 2005-2010 Jean Delvare <khali@linux-fr.org>
* Copyright (C) 2005-2010 Jean Delvare <jdelvare@suse.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -62,8 +66,8 @@
#define DRVNAME "it87"
enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8782,
it8783 };
enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8771,
it8772, it8782, it8783, it8603 };
static unsigned short force_id;
module_param(force_id, ushort, 0);
@@ -141,8 +145,12 @@ static inline void superio_exit(void)
#define IT8721F_DEVID 0x8721
#define IT8726F_DEVID 0x8726
#define IT8728F_DEVID 0x8728
#define IT8771E_DEVID 0x8771
#define IT8772E_DEVID 0x8772
#define IT8782F_DEVID 0x8782
#define IT8783E_DEVID 0x8783
#define IT8603E_DEVID 0x8603
#define IT8623E_DEVID 0x8623
#define IT87_ACT_REG 0x30
#define IT87_BASE_REG 0x60
@@ -282,6 +290,24 @@ static const struct it87_devices it87_devices[] = {
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
.peci_mask = 0x07,
},
[it8771] = {
.name = "it8771",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
/* PECI: guesswork */
/* 12mV ADC (OHM) */
/* 16 bit fans (OHM) */
.peci_mask = 0x07,
},
[it8772] = {
.name = "it8772",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
/* PECI (coreboot) */
/* 12mV ADC (HWSensors4, OHM) */
/* 16 bit fans (HWSensors4, OHM) */
.peci_mask = 0x07,
},
[it8782] = {
.name = "it8782",
.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
@@ -294,6 +320,12 @@ static const struct it87_devices it87_devices[] = {
| FEAT_TEMP_OLD_PECI,
.old_peci_mask = 0x4,
},
[it8603] = {
.name = "it8603",
.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
| FEAT_TEMP_OFFSET | FEAT_TEMP_PECI,
.peci_mask = 0x07,
},
};
#define has_16bit_fans(data) ((data)->features & FEAT_16BIT_FANS)
@@ -340,7 +372,7 @@ struct it87_data {
unsigned long last_updated; /* In jiffies */
u16 in_scaled; /* Internal voltage sensors are scaled */
u8 in[9][3]; /* [nr][0]=in, [1]=min, [2]=max */
u8 in[10][3]; /* [nr][0]=in, [1]=min, [2]=max */
u8 has_fan; /* Bitfield, fans enabled */
u16 fan[5][2]; /* Register values, [nr][0]=fan, [1]=min */
u8 has_temp; /* Bitfield, temp sensors enabled */
@@ -385,7 +417,7 @@ static int adc_lsb(const struct it87_data *data, int nr)
static u8 in_to_reg(const struct it87_data *data, int nr, long val)
{
val = DIV_ROUND_CLOSEST(val, adc_lsb(data, nr));
return SENSORS_LIMIT(val, 0, 255);
return clamp_val(val, 0, 255);
}
static int in_from_reg(const struct it87_data *data, int nr, int val)
@@ -397,16 +429,15 @@ static inline u8 FAN_TO_REG(long rpm, int div)
{
if (rpm == 0)
return 255;
rpm = SENSORS_LIMIT(rpm, 1, 1000000);
return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1,
254);
rpm = clamp_val(rpm, 1, 1000000);
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
}
static inline u16 FAN16_TO_REG(long rpm)
{
if (rpm == 0)
return 0xffff;
return SENSORS_LIMIT((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
return clamp_val((1350000 + rpm) / (rpm * 2), 1, 0xfffe);
}
#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 255 ? 0 : \
@@ -415,8 +446,8 @@ static inline u16 FAN16_TO_REG(long rpm)
#define FAN16_FROM_REG(val) ((val) == 0 ? -1 : (val) == 0xffff ? 0 : \
1350000 / ((val) * 2))
#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (((val) - 500) / 1000) : \
((val) + 500) / 1000), -128, 127))
#define TEMP_TO_REG(val) (clamp_val(((val) < 0 ? (((val) - 500) / 1000) : \
((val) + 500) / 1000), -128, 127))
#define TEMP_FROM_REG(val) ((val) * 1000)
static u8 pwm_to_reg(const struct it87_data *data, long val)
@@ -457,7 +488,7 @@ static const unsigned int pwm_freq[8] = {
};
static int it87_probe(struct platform_device *pdev);
static int __devexit it87_remove(struct platform_device *pdev);
static int it87_remove(struct platform_device *pdev);
static int it87_read_value(struct it87_data *data, u8 reg);
static void it87_write_value(struct it87_data *data, u8 reg, u8 value);
@@ -468,11 +499,10 @@ static void it87_init_device(struct platform_device *pdev);
static struct platform_driver it87_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRVNAME,
},
.probe = it87_probe,
.remove = __devexit_p(it87_remove),
.remove = it87_remove,
};
static ssize_t show_in(struct device *dev, struct device_attribute *attr,
@@ -558,6 +588,7 @@ static SENSOR_DEVICE_ATTR_2(in7_max, S_IRUGO | S_IWUSR, show_in, set_in,
7, 2);
static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0);
static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 9, 0);
/* 3 temperatures */
static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
@@ -714,7 +745,7 @@ static int pwm_mode(const struct it87_data *data, int nr)
{
int ctrl = data->fan_main_ctrl & (1 << nr);
if (ctrl == 0) /* Full speed */
if (ctrl == 0 && data->type != it8603) /* Full speed */
return 0;
if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */
return 2;
@@ -909,6 +940,10 @@ static ssize_t set_pwm_enable(struct device *dev,
return -EINVAL;
}
/* IT8603E does not have on/off mode */
if (val == 0 && data->type == it8603)
return -EINVAL;
mutex_lock(&data->update_lock);
if (val == 0) {
@@ -928,10 +963,13 @@ static ssize_t set_pwm_enable(struct device *dev,
else /* Automatic mode */
data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
/* set SmartGuardian mode */
data->fan_main_ctrl |= (1 << nr);
it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
data->fan_main_ctrl);
if (data->type != it8603) {
/* set SmartGuardian mode */
data->fan_main_ctrl |= (1 << nr);
it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
data->fan_main_ctrl);
}
}
mutex_unlock(&data->update_lock);
@@ -1395,6 +1433,8 @@ static ssize_t show_label(struct device *dev, struct device_attribute *attr,
static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2);
/* special AVCC3 IT8603E in9 */
static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 0);
static ssize_t show_name(struct device *dev, struct device_attribute
*devattr, char *buf)
@@ -1404,7 +1444,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static struct attribute *it87_attributes_in[9][5] = {
static struct attribute *it87_attributes_in[10][5] = {
{
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_min.dev_attr.attr,
@@ -1456,9 +1496,12 @@ static struct attribute *it87_attributes_in[9][5] = {
}, {
&sensor_dev_attr_in8_input.dev_attr.attr,
NULL
}, {
&sensor_dev_attr_in9_input.dev_attr.attr,
NULL
} };
static const struct attribute_group it87_group_in[9] = {
static const struct attribute_group it87_group_in[10] = {
{ .attrs = it87_attributes_in[0] },
{ .attrs = it87_attributes_in[1] },
{ .attrs = it87_attributes_in[2] },
@@ -1468,6 +1511,7 @@ static const struct attribute_group it87_group_in[9] = {
{ .attrs = it87_attributes_in[6] },
{ .attrs = it87_attributes_in[7] },
{ .attrs = it87_attributes_in[8] },
{ .attrs = it87_attributes_in[9] },
};
static struct attribute *it87_attributes_temp[3][6] = {
@@ -1526,7 +1570,8 @@ static struct attribute *it87_attributes_in_beep[] = {
&sensor_dev_attr_in5_beep.dev_attr.attr,
&sensor_dev_attr_in6_beep.dev_attr.attr,
&sensor_dev_attr_in7_beep.dev_attr.attr,
NULL
NULL,
NULL,
};
static struct attribute *it87_attributes_temp_beep[] = {
@@ -1665,6 +1710,7 @@ static struct attribute *it87_attributes_label[] = {
&sensor_dev_attr_in3_label.dev_attr.attr,
&sensor_dev_attr_in7_label.dev_attr.attr,
&sensor_dev_attr_in8_label.dev_attr.attr,
&sensor_dev_attr_in9_label.dev_attr.attr,
NULL
};
@@ -1710,12 +1756,22 @@ static int __init it87_find(unsigned short *address,
case IT8728F_DEVID:
sio_data->type = it8728;
break;
case IT8771E_DEVID:
sio_data->type = it8771;
break;
case IT8772E_DEVID:
sio_data->type = it8772;
break;
case IT8782F_DEVID:
sio_data->type = it8782;
break;
case IT8783E_DEVID:
sio_data->type = it8783;
break;
case IT8603E_DEVID:
case IT8623E_DEVID:
sio_data->type = it8603;
break;
case 0xffff: /* No device at all */
goto exit;
default:
@@ -1737,11 +1793,16 @@ static int __init it87_find(unsigned short *address,
err = 0;
sio_data->revision = superio_inb(DEVREV) & 0x0f;
pr_info("Found IT%04xF chip at 0x%x, revision %d\n",
chip_type, *address, sio_data->revision);
pr_info("Found IT%04x%c chip at 0x%x, revision %d\n", chip_type,
chip_type == 0x8771 || chip_type == 0x8772 ||
chip_type == 0x8603 ? 'E' : 'F', *address,
sio_data->revision);
/* in8 (Vbat) is always internal */
sio_data->internal = (1 << 2);
/* Only the IT8603E has in9 */
if (sio_data->type != it8603)
sio_data->skip_in |= (1 << 9);
/* Read GPIO config and VID value from LDN 7 (GPIO) */
if (sio_data->type == it87) {
@@ -1752,7 +1813,7 @@ static int __init it87_find(unsigned short *address,
superio_select(5);
sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
} else if (sio_data->type == it8783) {
int reg25, reg27, reg2A, reg2C, regEF;
int reg25, reg27, reg2a, reg2c, regef;
sio_data->skip_vid = 1; /* No VID */
@@ -1760,15 +1821,15 @@ static int __init it87_find(unsigned short *address,
reg25 = superio_inb(IT87_SIO_GPIO1_REG);
reg27 = superio_inb(IT87_SIO_GPIO3_REG);
reg2A = superio_inb(IT87_SIO_PINX1_REG);
reg2C = superio_inb(IT87_SIO_PINX2_REG);
regEF = superio_inb(IT87_SIO_SPI_REG);
reg2a = superio_inb(IT87_SIO_PINX1_REG);
reg2c = superio_inb(IT87_SIO_PINX2_REG);
regef = superio_inb(IT87_SIO_SPI_REG);
/* Check if fan3 is there or not */
if ((reg27 & (1 << 0)) || !(reg2C & (1 << 2)))
if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2)))
sio_data->skip_fan |= (1 << 2);
if ((reg25 & (1 << 4))
|| (!(reg2A & (1 << 1)) && (regEF & (1 << 0))))
|| (!(reg2a & (1 << 1)) && (regef & (1 << 0))))
sio_data->skip_pwm |= (1 << 2);
/* Check if fan2 is there or not */
@@ -1778,7 +1839,7 @@ static int __init it87_find(unsigned short *address,
sio_data->skip_pwm |= (1 << 1);
/* VIN5 */
if ((reg27 & (1 << 0)) || (reg2C & (1 << 2)))
if ((reg27 & (1 << 0)) || (reg2c & (1 << 2)))
sio_data->skip_in |= (1 << 5); /* No VIN5 */
/* VIN6 */
@@ -1803,22 +1864,53 @@ static int __init it87_find(unsigned short *address,
* not the case, and ask the user to report if the
* resulting voltage is sane.
*/
if (!(reg2C & (1 << 1))) {
reg2C |= (1 << 1);
superio_outb(IT87_SIO_PINX2_REG, reg2C);
if (!(reg2c & (1 << 1))) {
reg2c |= (1 << 1);
superio_outb(IT87_SIO_PINX2_REG, reg2c);
pr_notice("Routing internal VCCH5V to in7.\n");
}
pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n");
pr_notice("Please report if it displays a reasonable voltage.\n");
}
if (reg2C & (1 << 0))
if (reg2c & (1 << 0))
sio_data->internal |= (1 << 0);
if (reg2C & (1 << 1))
if (reg2c & (1 << 1))
sio_data->internal |= (1 << 1);
sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
} else if (sio_data->type == it8603) {
int reg27, reg29;
sio_data->skip_vid = 1; /* No VID */
superio_select(GPIO);
reg27 = superio_inb(IT87_SIO_GPIO3_REG);
/* Check if fan3 is there or not */
if (reg27 & (1 << 6))
sio_data->skip_pwm |= (1 << 2);
if (reg27 & (1 << 7))
sio_data->skip_fan |= (1 << 2);
/* Check if fan2 is there or not */
reg29 = superio_inb(IT87_SIO_GPIO5_REG);
if (reg29 & (1 << 1))
sio_data->skip_pwm |= (1 << 1);
if (reg29 & (1 << 2))
sio_data->skip_fan |= (1 << 1);
sio_data->skip_in |= (1 << 5); /* No VIN5 */
sio_data->skip_in |= (1 << 6); /* No VIN6 */
/* no fan4 */
sio_data->skip_pwm |= (1 << 3);
sio_data->skip_fan |= (1 << 3);
sio_data->internal |= (1 << 1); /* in7 is VSB */
sio_data->internal |= (1 << 3); /* in9 is AVCC */
sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
} else {
int reg;
bool uart6;
@@ -1827,10 +1919,11 @@ static int __init it87_find(unsigned short *address,
reg = superio_inb(IT87_SIO_GPIO3_REG);
if (sio_data->type == it8721 || sio_data->type == it8728 ||
sio_data->type == it8771 || sio_data->type == it8772 ||
sio_data->type == it8782) {
/*
* IT8721F/IT8758E, and IT8782F don't have VID pins
* at all, not sure about the IT8728F.
* at all, not sure about the IT8728F and compatibles.
*/
sio_data->skip_vid = 1;
} else {
@@ -1884,7 +1977,9 @@ 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 ||
sio_data->type == it8728)
sio_data->type == it8728 ||
sio_data->type == it8771 ||
sio_data->type == it8772)
sio_data->internal |= (1 << 1);
/*
@@ -1933,11 +2028,11 @@ exit:
static void it87_remove_files(struct device *dev)
{
struct it87_data *data = platform_get_drvdata(pdev);
struct it87_sio_data *sio_data = dev->platform_data;
struct it87_sio_data *sio_data = dev_get_platdata(dev);
int i;
sysfs_remove_group(&dev->kobj, &it87_group);
for (i = 0; i < 9; i++) {
for (i = 0; i < 10; i++) {
if (sio_data->skip_in & (1 << i))
continue;
sysfs_remove_group(&dev->kobj, &it87_group_in[i]);
@@ -1980,12 +2075,12 @@ static void it87_remove_files(struct device *dev)
sysfs_remove_group(&dev->kobj, &it87_group_label);
}
static int __devinit it87_probe(struct platform_device *pdev)
static int it87_probe(struct platform_device *pdev)
{
struct it87_data *data;
struct resource *res;
struct device *dev = &pdev->dev;
struct it87_sio_data *sio_data = dev->platform_data;
struct it87_sio_data *sio_data = dev_get_platdata(dev);
int err = 0, i;
int enable_pwm_interface;
int fan_beep_need_rw;
@@ -2051,6 +2146,8 @@ static int __devinit it87_probe(struct platform_device *pdev)
data->in_scaled |= (1 << 7); /* in7 is VSB */
if (sio_data->internal & (1 << 2))
data->in_scaled |= (1 << 8); /* in8 is Vbat */
if (sio_data->internal & (1 << 3))
data->in_scaled |= (1 << 9); /* in9 is AVCC */
} else if (sio_data->type == it8782 || sio_data->type == it8783) {
if (sio_data->internal & (1 << 0))
data->in_scaled |= (1 << 3); /* in3 is VCC5V */
@@ -2073,7 +2170,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
if (err)
return err;
for (i = 0; i < 9; i++) {
for (i = 0; i < 10; i++) {
if (sio_data->skip_in & (1 << i))
continue;
err = sysfs_create_group(&dev->kobj, &it87_group_in[i]);
@@ -2173,7 +2270,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
}
/* Export labels for internal sensors */
for (i = 0; i < 3; i++) {
for (i = 0; i < 4; i++) {
if (!(sio_data->internal & (1 << i)))
continue;
err = sysfs_create_file(&dev->kobj,
@@ -2195,7 +2292,7 @@ error:
return err;
}
static int __devexit it87_remove(struct platform_device *pdev)
static int it87_remove(struct platform_device *pdev)
{
struct it87_data *data = platform_get_drvdata(pdev);
@@ -2228,7 +2325,7 @@ static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
}
/* Return 1 if and only if the PWM interface is safe to use */
static int __devinit it87_check_pwm(struct device *dev)
static int it87_check_pwm(struct device *dev)
{
struct it87_data *data = dev_get_drvdata(dev);
/*
@@ -2285,9 +2382,9 @@ static int __devinit it87_check_pwm(struct device *dev)
}
/* Called when we have found a new IT87. */
static void __devinit it87_init_device(struct platform_device *pdev)
static void it87_init_device(struct platform_device *pdev)
{
struct it87_sio_data *sio_data = pdev->dev.platform_data;
struct it87_sio_data *sio_data = dev_get_platdata(&pdev->dev);
struct it87_data *data = platform_get_drvdata(pdev);
int tmp, i;
u8 mask;
@@ -2354,8 +2451,9 @@ static void __devinit it87_init_device(struct platform_device *pdev)
}
data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
/* Set tachometers to 16-bit mode if needed */
if (has_16bit_fans(data)) {
/* Set tachometers to 16-bit mode if needed, IT8603E (and IT8728F?)
* has it by default */
if (has_16bit_fans(data) && data->type != it8603) {
tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
if (~tmp & 0x07 & data->has_fan) {
dev_dbg(&pdev->dev,
@@ -2435,6 +2533,8 @@ static struct it87_data *it87_update_device(struct device *dev)
}
/* in8 (battery) has no limit registers */
data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8));
if (data->type == it8603)
data->in[9][0] = it87_read_value(data, 0x2f);
for (i = 0; i < 5; i++) {
/* Skip disabled fans */
@@ -2591,7 +2691,7 @@ static void __exit sm_it87_exit(void)
}
MODULE_AUTHOR("Chris Gauthron, Jean Delvare <khali@linux-fr.org>");
MODULE_AUTHOR("Chris Gauthron, Jean Delvare <jdelvare@suse.de>");
MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver");
module_param(update_vbat, bool, 0);
MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");