Commit 8eccbb6f authored by Jean Delvare's avatar Jean Delvare Committed by Jean Delvare

hwmon/smsc47m1: Add support for the LPC47M292

The new SMSC LPC47M292 Super-I/O chip is a bit different from the
previous ones, it supports a 3rd fan, but unfortunately the pin
configuration registers are different.
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent ce7ee4e8
...@@ -14,6 +14,10 @@ Supported chips: ...@@ -14,6 +14,10 @@ Supported chips:
http://www.smsc.com/main/datasheets/47m14x.pdf http://www.smsc.com/main/datasheets/47m14x.pdf
http://www.smsc.com/main/tools/discontinued/47m15x.pdf http://www.smsc.com/main/tools/discontinued/47m15x.pdf
http://www.smsc.com/main/datasheets/47m192.pdf http://www.smsc.com/main/datasheets/47m192.pdf
* SMSC LPC47M292
Addresses scanned: none, address read from Super I/O config space
Prefix: 'smsc47m2'
Datasheet: Not public
* SMSC LPC47M997 * SMSC LPC47M997
Addresses scanned: none, address read from Super I/O config space Addresses scanned: none, address read from Super I/O config space
Prefix: 'smsc47m1' Prefix: 'smsc47m1'
...@@ -32,9 +36,10 @@ Description ...@@ -32,9 +36,10 @@ Description
The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips
contain monitoring and PWM control circuitry for two fans. contain monitoring and PWM control circuitry for two fans.
The 47M15x and 47M192 chips contain a full 'hardware monitoring block' The LPC47M15x, LPC47M192 and LPC47M292 chips contain a full 'hardware
in addition to the fan monitoring and control. The hardware monitoring monitoring block' in addition to the fan monitoring and control. The
block is not supported by the driver. hardware monitoring block is not supported by this driver, use the
smsc47m192 driver for that.
No documentation is available for the 47M997, but it has the same device No documentation is available for the 47M997, but it has the same device
ID as the 47M15x and 47M192 chips and seems to be compatible. ID as the 47M15x and 47M192 chips and seems to be compatible.
......
...@@ -422,11 +422,12 @@ config SENSORS_SMSC47M1 ...@@ -422,11 +422,12 @@ config SENSORS_SMSC47M1
If you say yes here you get support for the integrated fan If you say yes here you get support for the integrated fan
monitoring and control capabilities of the SMSC LPC47B27x, monitoring and control capabilities of the SMSC LPC47B27x,
LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x, LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x,
LPC47M192 and LPC47M997 chips. LPC47M192, LPC47M292 and LPC47M997 chips.
The temperature and voltage sensor features of the LPC47M192 The temperature and voltage sensor features of the LPC47M15x,
and LPC47M997 are supported by another driver, select also LPC47M192, LPC47M292 and LPC47M997 are supported by another
"SMSC LPC47M192 and compatibles" below for those. driver, select also "SMSC LPC47M192 and compatibles" below for
those.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called smsc47m1. will be called smsc47m1.
......
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
for hardware monitoring for hardware monitoring
Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x,
LPC47M14x, LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips. LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997
Super-I/O chips.
Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> Copyright (C) 2004-2007 Jean Delvare <khali@linux-fr.org>
Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com> Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com>
and Jean Delvare and Jean Delvare
...@@ -40,6 +41,8 @@ ...@@ -40,6 +41,8 @@
/* Address is autodetected, there is no default value */ /* Address is autodetected, there is no default value */
static unsigned short address; static unsigned short address;
static u8 devid;
enum chips { smsc47m1, smsc47m2 };
/* Super-I/0 registers and commands */ /* Super-I/0 registers and commands */
...@@ -87,10 +90,18 @@ superio_exit(void) ...@@ -87,10 +90,18 @@ superio_exit(void)
#define SMSC47M1_REG_ALARM 0x04 #define SMSC47M1_REG_ALARM 0x04
#define SMSC47M1_REG_TPIN(nr) (0x34 - (nr)) #define SMSC47M1_REG_TPIN(nr) (0x34 - (nr))
#define SMSC47M1_REG_PPIN(nr) (0x36 - (nr)) #define SMSC47M1_REG_PPIN(nr) (0x36 - (nr))
#define SMSC47M1_REG_PWM(nr) (0x56 + (nr))
#define SMSC47M1_REG_FANDIV 0x58 #define SMSC47M1_REG_FANDIV 0x58
#define SMSC47M1_REG_FAN(nr) (0x59 + (nr))
#define SMSC47M1_REG_FAN_PRELOAD(nr) (0x5B + (nr)) static const u8 SMSC47M1_REG_FAN[3] = { 0x59, 0x5a, 0x6b };
static const u8 SMSC47M1_REG_FAN_PRELOAD[3] = { 0x5b, 0x5c, 0x6c };
static const u8 SMSC47M1_REG_PWM[3] = { 0x56, 0x57, 0x69 };
#define SMSC47M2_REG_ALARM6 0x09
#define SMSC47M2_REG_TPIN1 0x38
#define SMSC47M2_REG_TPIN2 0x37
#define SMSC47M2_REG_TPIN3 0x2d
#define SMSC47M2_REG_PPIN3 0x2c
#define SMSC47M2_REG_FANDIV3 0x6a
#define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \ #define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \
983040/((192-(reg))*(div))) 983040/((192-(reg))*(div)))
...@@ -103,17 +114,18 @@ superio_exit(void) ...@@ -103,17 +114,18 @@ superio_exit(void)
struct smsc47m1_data { struct smsc47m1_data {
struct i2c_client client; struct i2c_client client;
enum chips type;
struct class_device *class_dev; struct class_device *class_dev;
struct mutex lock; struct mutex lock;
struct mutex update_lock; struct mutex update_lock;
unsigned long last_updated; /* In jiffies */ unsigned long last_updated; /* In jiffies */
u8 fan[2]; /* Register value */ u8 fan[3]; /* Register value */
u8 fan_preload[2]; /* Register value */ u8 fan_preload[3]; /* Register value */
u8 fan_div[2]; /* Register encoding, shifted right */ u8 fan_div[3]; /* Register encoding, shifted right */
u8 alarms; /* Register encoding */ u8 alarms; /* Register encoding */
u8 pwm[2]; /* Register value (bit 7 is enable) */ u8 pwm[3]; /* Register value (bit 0 is disable) */
}; };
...@@ -200,7 +212,7 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, ...@@ -200,7 +212,7 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
} }
data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv);
smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD[nr],
data->fan_preload[nr]); data->fan_preload[nr]);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
...@@ -234,15 +246,26 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, ...@@ -234,15 +246,26 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
return -EINVAL; return -EINVAL;
} }
tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV) & 0x0F; switch (nr) {
tmp |= (data->fan_div[0] << 4) | (data->fan_div[1] << 6); case 0:
smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, tmp); case 1:
tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV)
& ~(0x03 << (4 + 2 * nr));
tmp |= data->fan_div[nr] << (4 + 2 * nr);
smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, tmp);
break;
case 2:
tmp = smsc47m1_read_value(client, SMSC47M2_REG_FANDIV3) & 0xCF;
tmp |= data->fan_div[2] << 4;
smsc47m1_write_value(client, SMSC47M2_REG_FANDIV3, tmp);
break;
}
/* Preserve fan min */ /* Preserve fan min */
tmp = 192 - (old_div * (192 - data->fan_preload[nr]) tmp = 192 - (old_div * (192 - data->fan_preload[nr])
+ new_div / 2) / new_div; + new_div / 2) / new_div;
data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr), smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD[nr],
data->fan_preload[nr]); data->fan_preload[nr]);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
...@@ -263,7 +286,7 @@ static ssize_t set_pwm(struct device *dev, const char *buf, ...@@ -263,7 +286,7 @@ static ssize_t set_pwm(struct device *dev, const char *buf,
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm[nr] &= 0x81; /* Preserve additional bits */ data->pwm[nr] &= 0x81; /* Preserve additional bits */
data->pwm[nr] |= PWM_TO_REG(val); data->pwm[nr] |= PWM_TO_REG(val);
smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), smsc47m1_write_value(client, SMSC47M1_REG_PWM[nr],
data->pwm[nr]); data->pwm[nr]);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
...@@ -284,7 +307,7 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf, ...@@ -284,7 +307,7 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf,
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->pwm[nr] &= 0xFE; /* preserve the other bits */ data->pwm[nr] &= 0xFE; /* preserve the other bits */
data->pwm[nr] |= !val; data->pwm[nr] |= !val;
smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), smsc47m1_write_value(client, SMSC47M1_REG_PWM[nr],
data->pwm[nr]); data->pwm[nr]);
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
...@@ -345,6 +368,7 @@ static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ ...@@ -345,6 +368,7 @@ static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
fan_present(1); fan_present(1);
fan_present(2); fan_present(2);
fan_present(3);
static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
...@@ -358,11 +382,16 @@ static struct attribute *smsc47m1_attributes[] = { ...@@ -358,11 +382,16 @@ static struct attribute *smsc47m1_attributes[] = {
&dev_attr_fan2_input.attr, &dev_attr_fan2_input.attr,
&dev_attr_fan2_min.attr, &dev_attr_fan2_min.attr,
&dev_attr_fan2_div.attr, &dev_attr_fan2_div.attr,
&dev_attr_fan3_input.attr,
&dev_attr_fan3_min.attr,
&dev_attr_fan3_div.attr,
&dev_attr_pwm1.attr, &dev_attr_pwm1.attr,
&dev_attr_pwm1_enable.attr, &dev_attr_pwm1_enable.attr,
&dev_attr_pwm2.attr, &dev_attr_pwm2.attr,
&dev_attr_pwm2_enable.attr, &dev_attr_pwm2_enable.attr,
&dev_attr_pwm3.attr,
&dev_attr_pwm3_enable.attr,
&dev_attr_alarms.attr, &dev_attr_alarms.attr,
NULL NULL
...@@ -377,7 +406,7 @@ static int __init smsc47m1_find(unsigned short *addr) ...@@ -377,7 +406,7 @@ static int __init smsc47m1_find(unsigned short *addr)
u8 val; u8 val;
superio_enter(); superio_enter();
val = superio_inb(SUPERIO_REG_DEVID); devid = superio_inb(SUPERIO_REG_DEVID);
/* /*
* SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
...@@ -386,18 +415,29 @@ static int __init smsc47m1_find(unsigned short *addr) ...@@ -386,18 +415,29 @@ static int __init smsc47m1_find(unsigned short *addr)
* can do much more besides (device id 0x60). * can do much more besides (device id 0x60).
* The LPC47M997 is undocumented, but seems to be compatible with * The LPC47M997 is undocumented, but seems to be compatible with
* the LPC47M192, and has the same device id. * the LPC47M192, and has the same device id.
* The LPC47M292 (device id 0x6B) is somewhat compatible, but it
* supports a 3rd fan, and the pin configuration registers are
* unfortunately different.
*/ */
if (val == 0x51) switch (devid) {
case 0x51:
printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n"); printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
else if (val == 0x59) break;
case 0x59:
printk(KERN_INFO "smsc47m1: Found SMSC " printk(KERN_INFO "smsc47m1: Found SMSC "
"LPC47M10x/LPC47M112/LPC47M13x\n"); "LPC47M10x/LPC47M112/LPC47M13x\n");
else if (val == 0x5F) break;
case 0x5F:
printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n"); printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
else if (val == 0x60) break;
case 0x60:
printk(KERN_INFO "smsc47m1: Found SMSC " printk(KERN_INFO "smsc47m1: Found SMSC "
"LPC47M15x/LPC47M192/LPC47M997\n"); "LPC47M15x/LPC47M192/LPC47M997\n");
else { break;
case 0x6B:
printk(KERN_INFO "smsc47m1: Found SMSC LPC47M292\n");
break;
default:
superio_exit(); superio_exit();
return -ENODEV; return -ENODEV;
} }
...@@ -421,7 +461,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) ...@@ -421,7 +461,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
struct i2c_client *new_client; struct i2c_client *new_client;
struct smsc47m1_data *data; struct smsc47m1_data *data;
int err = 0; int err = 0;
int fan1, fan2, pwm1, pwm2; int fan1, fan2, fan3, pwm1, pwm2, pwm3;
if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.driver.name)) { if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.driver.name)) {
dev_err(&adapter->dev, "Region 0x%x already in use!\n", address); dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
...@@ -433,6 +473,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) ...@@ -433,6 +473,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
goto error_release; goto error_release;
} }
data->type = devid == 0x6B ? smsc47m2 : smsc47m1;
new_client = &data->client; new_client = &data->client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(new_client, data);
new_client->addr = address; new_client->addr = address;
...@@ -441,20 +482,35 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) ...@@ -441,20 +482,35 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
new_client->driver = &smsc47m1_driver; new_client->driver = &smsc47m1_driver;
new_client->flags = 0; new_client->flags = 0;
strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE); strlcpy(new_client->name,
data->type == smsc47m2 ? "smsc47m2" : "smsc47m1",
I2C_NAME_SIZE);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* If no function is properly configured, there's no point in /* If no function is properly configured, there's no point in
actually registering the chip. */ actually registering the chip. */
fan1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05)
== 0x05;
fan2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05)
== 0x05;
pwm1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05) pwm1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05)
== 0x04; == 0x04;
pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05) pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05)
== 0x04; == 0x04;
if (!(fan1 || fan2 || pwm1 || pwm2)) { if (data->type == smsc47m2) {
fan1 = (smsc47m1_read_value(new_client, SMSC47M2_REG_TPIN1)
& 0x0d) == 0x09;
fan2 = (smsc47m1_read_value(new_client, SMSC47M2_REG_TPIN2)
& 0x0d) == 0x09;
fan3 = (smsc47m1_read_value(new_client, SMSC47M2_REG_TPIN3)
& 0x0d) == 0x0d;
pwm3 = (smsc47m1_read_value(new_client, SMSC47M2_REG_PPIN3)
& 0x0d) == 0x08;
} else {
fan1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0))
& 0x05) == 0x05;
fan2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1))
& 0x05) == 0x05;
fan3 = 0;
pwm3 = 0;
}
if (!(fan1 || fan2 || fan3 || pwm1 || pwm2 || pwm3)) {
dev_warn(&adapter->dev, "Device at 0x%x is not configured, " dev_warn(&adapter->dev, "Device at 0x%x is not configured, "
"will not use\n", new_client->addr); "will not use\n", new_client->addr);
err = -ENODEV; err = -ENODEV;
...@@ -497,6 +553,18 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) ...@@ -497,6 +553,18 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, " dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, "
"skipping\n"); "skipping\n");
if (fan3) {
if ((err = device_create_file(&new_client->dev,
&dev_attr_fan3_input))
|| (err = device_create_file(&new_client->dev,
&dev_attr_fan3_min))
|| (err = device_create_file(&new_client->dev,
&dev_attr_fan3_div)))
goto error_remove_files;
} else
dev_dbg(&new_client->dev, "Fan 3 not enabled by hardware, "
"skipping\n");
if (pwm1) { if (pwm1) {
if ((err = device_create_file(&new_client->dev, if ((err = device_create_file(&new_client->dev,
&dev_attr_pwm1)) &dev_attr_pwm1))
...@@ -506,6 +574,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) ...@@ -506,6 +574,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
} else } else
dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, " dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, "
"skipping\n"); "skipping\n");
if (pwm2) { if (pwm2) {
if ((err = device_create_file(&new_client->dev, if ((err = device_create_file(&new_client->dev,
&dev_attr_pwm2)) &dev_attr_pwm2))
...@@ -516,6 +585,16 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) ...@@ -516,6 +585,16 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, " dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, "
"skipping\n"); "skipping\n");
if (pwm3) {
if ((err = device_create_file(&new_client->dev,
&dev_attr_pwm3))
|| (err = device_create_file(&new_client->dev,
&dev_attr_pwm3_enable)))
goto error_remove_files;
} else
dev_dbg(&new_client->dev, "PWM 3 not enabled by hardware, "
"skipping\n");
if ((err = device_create_file(&new_client->dev, &dev_attr_alarms))) if ((err = device_create_file(&new_client->dev, &dev_attr_alarms)))
goto error_remove_files; goto error_remove_files;
...@@ -580,15 +659,16 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, ...@@ -580,15 +659,16 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
int i; int i, fan_nr;
fan_nr = data->type == smsc47m2 ? 3 : 2;
for (i = 0; i < 2; i++) { for (i = 0; i < fan_nr; i++) {
data->fan[i] = smsc47m1_read_value(client, data->fan[i] = smsc47m1_read_value(client,
SMSC47M1_REG_FAN(i)); SMSC47M1_REG_FAN[i]);
data->fan_preload[i] = smsc47m1_read_value(client, data->fan_preload[i] = smsc47m1_read_value(client,
SMSC47M1_REG_FAN_PRELOAD(i)); SMSC47M1_REG_FAN_PRELOAD[i]);
data->pwm[i] = smsc47m1_read_value(client, data->pwm[i] = smsc47m1_read_value(client,
SMSC47M1_REG_PWM(i)); SMSC47M1_REG_PWM[i]);
} }
i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV); i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV);
...@@ -601,6 +681,18 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, ...@@ -601,6 +681,18 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
if (data->alarms) if (data->alarms)
smsc47m1_write_value(client, SMSC47M1_REG_ALARM, 0xC0); smsc47m1_write_value(client, SMSC47M1_REG_ALARM, 0xC0);
if (fan_nr >= 3) {
data->fan_div[2] = (smsc47m1_read_value(client,
SMSC47M2_REG_FANDIV3) >> 4) & 0x03;
data->alarms |= (smsc47m1_read_value(client,
SMSC47M2_REG_ALARM6) & 0x40) >> 4;
/* Clear alarm if needed */
if (data->alarms & 0x04)
smsc47m1_write_value(client,
SMSC47M2_REG_ALARM6,
0x40);
}
data->last_updated = jiffies; data->last_updated = jiffies;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment