From 00cb4739053fa0ce4594a7798a4095007a1c7c79 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 May 2007 17:21:59 +0200 Subject: hwmon/smsc47m192: Document the LPC47M292 as supported The new SMSC LPC47M292 Super-I/O chip includes a hardware monitoring block which is compatible with those of the LPC47M192. Signed-off-by: Jean Delvare Cc: Hartmut Rick --- drivers/hwmon/Kconfig | 3 ++- drivers/hwmon/smsc47m192.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 6d105a1d41b1..68ee9702e339 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -437,7 +437,8 @@ config SENSORS_SMSC47M192 select HWMON_VID help If you say yes here you get support for the temperature and - voltage sensors of the SMSC LPC47M192 and LPC47M997 chips. + voltage sensors of the SMSC LPC47M192, LPC47M15x, LPC47M292 + and LPC47M997 chips. The fan monitoring and control capabilities of these chips are supported by another driver, select diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index a6833f437395..a012f396f354 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -1,6 +1,6 @@ /* smsc47m192.c - Support for hardware monitoring block of - SMSC LPC47M192 and LPC47M997 Super I/O chips + SMSC LPC47M192 and compatible Super I/O chips Copyright (C) 2006 Hartmut Rick @@ -518,7 +518,7 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, && (i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID4) & 0xfe) == 0x80) { dev_info(&adapter->dev, - "found SMSC47M192 or SMSC47M997, " + "found SMSC47M192 or compatible, " "version 2, stepping A%d\n", version & 0x0f); } else { dev_dbg(&adapter->dev, -- cgit v1.2.3 From ce7ee4e80a72d3b1009ca232be8981de93c015f6 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 May 2007 17:21:59 +0200 Subject: hwmon: Request the I/O regions in platform drivers My understanding of the resource management in the Linux 2.6 device driver model is that the devices should declare their resources, and then when a driver attaches to a device, it should request the resources it will be using, so as to mark them busy. This is how the PCI and PNP subsystems work, you can clearly see the two levels of resources (declaration and request) in /proc/ioports for these devices. So I believe that our platform hardware monitoring drivers should follow the same logic. At the moment, we only declare the resources but we do not request them. This patch adds the I/O region request and release calls. Signed-off-by: Jean Delvare Acked-by: Juerg Haefliger --- drivers/hwmon/f71805f.c | 16 +++++++++++++++- drivers/hwmon/pc87427.c | 15 ++++++++++++++- drivers/hwmon/vt1211.c | 13 +++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 7c2973487122..cdbe309b8fc4 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -35,6 +35,7 @@ #include #include #include +#include #include static struct platform_device *pdev; @@ -1140,6 +1141,13 @@ static int __devinit f71805f_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start + ADDR_REG_OFFSET, 2, DRVNAME)) { + err = -EBUSY; + dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)(res->start + ADDR_REG_OFFSET), + (unsigned long)(res->start + ADDR_REG_OFFSET + 1)); + goto exit_free; + } data->addr = res->start; data->name = names[sio_data->kind]; mutex_init(&data->update_lock); @@ -1165,7 +1173,7 @@ static int __devinit f71805f_probe(struct platform_device *pdev) /* Register sysfs interface files */ if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group))) - goto exit_free; + goto exit_release_region; if (data->has_in & (1 << 4)) { /* in4 */ if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group_optin[0]))) @@ -1219,6 +1227,8 @@ exit_remove_files: for (i = 0; i < 4; i++) sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); +exit_release_region: + release_region(res->start + ADDR_REG_OFFSET, 2); exit_free: platform_set_drvdata(pdev, NULL); kfree(data); @@ -1229,6 +1239,7 @@ exit: static int __devexit f71805f_remove(struct platform_device *pdev) { struct f71805f_data *data = platform_get_drvdata(pdev); + struct resource *res; int i; platform_set_drvdata(pdev, NULL); @@ -1239,6 +1250,9 @@ static int __devexit f71805f_remove(struct platform_device *pdev) sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); kfree(data); + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + release_region(res->start + ADDR_REG_OFFSET, 2); + return 0; } diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index affa21a5ccfd..29354fa26f81 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c @@ -31,6 +31,7 @@ #include #include #include +#include #include static struct platform_device *pdev; @@ -429,6 +430,12 @@ static int __devinit pc87427_probe(struct platform_device *pdev) /* This will need to be revisited when we add support for temperature and voltage monitoring. */ res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) { + err = -EBUSY; + dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)res->start, (unsigned long)res->end); + goto exit_kfree; + } data->address[0] = res->start; mutex_init(&data->lock); @@ -438,7 +445,7 @@ static int __devinit pc87427_probe(struct platform_device *pdev) /* Register sysfs hooks */ if ((err = device_create_file(&pdev->dev, &dev_attr_name))) - goto exit_kfree; + goto exit_release_region; for (i = 0; i < 8; i++) { if (!(data->fan_enabled & (1 << i))) continue; @@ -462,6 +469,8 @@ exit_remove_files: continue; sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); } +exit_release_region: + release_region(res->start, res->end - res->start + 1); exit_kfree: platform_set_drvdata(pdev, NULL); kfree(data); @@ -472,6 +481,7 @@ exit: static int __devexit pc87427_remove(struct platform_device *pdev) { struct pc87427_data *data = platform_get_drvdata(pdev); + struct resource *res; int i; platform_set_drvdata(pdev, NULL); @@ -484,6 +494,9 @@ static int __devexit pc87427_remove(struct platform_device *pdev) } kfree(data); + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + release_region(res->start, res->end - res->start + 1); + return 0; } diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 89c23d6add7b..9f3e332c5b7f 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -31,6 +31,7 @@ #include #include #include +#include #include static int uch_config = -1; @@ -1130,6 +1131,12 @@ static int __devinit vt1211_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) { + err = -EBUSY; + dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)res->start, (unsigned long)res->end); + goto EXIT_KFREE; + } data->addr = res->start; data->name = DRVNAME; mutex_init(&data->update_lock); @@ -1197,6 +1204,8 @@ EXIT_DEV_REMOVE: dev_err(dev, "Sysfs interface creation failed (%d)\n", err); EXIT_DEV_REMOVE_SILENT: vt1211_remove_sysfs(pdev); + release_region(res->start, res->end - res->start + 1); +EXIT_KFREE: platform_set_drvdata(pdev, NULL); kfree(data); EXIT: @@ -1206,12 +1215,16 @@ EXIT: static int __devexit vt1211_remove(struct platform_device *pdev) { struct vt1211_data *data = platform_get_drvdata(pdev); + struct resource *res; hwmon_device_unregister(data->class_dev); vt1211_remove_sysfs(pdev); platform_set_drvdata(pdev, NULL); kfree(data); + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + release_region(res->start, res->end - res->start + 1); + return 0; } -- cgit v1.2.3 From 8eccbb6fb97a5b54a9db166399f0d24f33114522 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 May 2007 17:21:59 +0200 Subject: 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: Jean Delvare --- drivers/hwmon/Kconfig | 9 +-- drivers/hwmon/smsc47m1.c | 160 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 131 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 68ee9702e339..399b6a92e9b0 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -422,11 +422,12 @@ config SENSORS_SMSC47M1 If you say yes here you get support for the integrated fan monitoring and control capabilities of the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x, - LPC47M192 and LPC47M997 chips. + LPC47M192, LPC47M292 and LPC47M997 chips. - The temperature and voltage sensor features of the LPC47M192 - and LPC47M997 are supported by another driver, select also - "SMSC LPC47M192 and compatibles" below for those. + The temperature and voltage sensor features of the LPC47M15x, + LPC47M192, LPC47M292 and LPC47M997 are supported by another + driver, select also "SMSC LPC47M192 and compatibles" below for + those. This driver can also be built as a module. If so, the module will be called smsc47m1. diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index beb881c4b2e8..16762cca87e5 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -3,10 +3,11 @@ for hardware monitoring 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 - Copyright (C) 2004 Jean Delvare + Copyright (C) 2004-2007 Jean Delvare Ported to Linux 2.6 by Gabriele Gorla and Jean Delvare @@ -40,6 +41,8 @@ /* Address is autodetected, there is no default value */ static unsigned short address; +static u8 devid; +enum chips { smsc47m1, smsc47m2 }; /* Super-I/0 registers and commands */ @@ -87,10 +90,18 @@ superio_exit(void) #define SMSC47M1_REG_ALARM 0x04 #define SMSC47M1_REG_TPIN(nr) (0x34 - (nr)) #define SMSC47M1_REG_PPIN(nr) (0x36 - (nr)) -#define SMSC47M1_REG_PWM(nr) (0x56 + (nr)) #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 : \ 983040/((192-(reg))*(div))) @@ -103,17 +114,18 @@ superio_exit(void) struct smsc47m1_data { struct i2c_client client; + enum chips type; struct class_device *class_dev; struct mutex lock; struct mutex update_lock; unsigned long last_updated; /* In jiffies */ - u8 fan[2]; /* Register value */ - u8 fan_preload[2]; /* Register value */ - u8 fan_div[2]; /* Register encoding, shifted right */ + u8 fan[3]; /* Register value */ + u8 fan_preload[3]; /* Register value */ + u8 fan_div[3]; /* Register encoding, shifted right */ 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, } 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]); mutex_unlock(&data->update_lock); @@ -234,15 +246,26 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, return -EINVAL; } - tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV) & 0x0F; - tmp |= (data->fan_div[0] << 4) | (data->fan_div[1] << 6); - smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, tmp); + switch (nr) { + case 0: + 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 */ tmp = 192 - (old_div * (192 - data->fan_preload[nr]) + new_div / 2) / new_div; 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]); mutex_unlock(&data->update_lock); @@ -263,7 +286,7 @@ static ssize_t set_pwm(struct device *dev, const char *buf, mutex_lock(&data->update_lock); data->pwm[nr] &= 0x81; /* Preserve additional bits */ 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]); mutex_unlock(&data->update_lock); @@ -284,7 +307,7 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf, mutex_lock(&data->update_lock); data->pwm[nr] &= 0xFE; /* preserve the other bits */ data->pwm[nr] |= !val; - smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr), + smsc47m1_write_value(client, SMSC47M1_REG_PWM[nr], data->pwm[nr]); mutex_unlock(&data->update_lock); @@ -345,6 +368,7 @@ static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ fan_present(1); fan_present(2); +fan_present(3); static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); @@ -358,11 +382,16 @@ static struct attribute *smsc47m1_attributes[] = { &dev_attr_fan2_input.attr, &dev_attr_fan2_min.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_enable.attr, &dev_attr_pwm2.attr, &dev_attr_pwm2_enable.attr, + &dev_attr_pwm3.attr, + &dev_attr_pwm3_enable.attr, &dev_attr_alarms.attr, NULL @@ -377,7 +406,7 @@ static int __init smsc47m1_find(unsigned short *addr) u8 val; superio_enter(); - val = superio_inb(SUPERIO_REG_DEVID); + devid = superio_inb(SUPERIO_REG_DEVID); /* * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x @@ -386,18 +415,29 @@ static int __init smsc47m1_find(unsigned short *addr) * can do much more besides (device id 0x60). * The LPC47M997 is undocumented, but seems to be compatible with * 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"); - else if (val == 0x59) + break; + case 0x59: printk(KERN_INFO "smsc47m1: Found SMSC " "LPC47M10x/LPC47M112/LPC47M13x\n"); - else if (val == 0x5F) + break; + case 0x5F: printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n"); - else if (val == 0x60) + break; + case 0x60: printk(KERN_INFO "smsc47m1: Found SMSC " "LPC47M15x/LPC47M192/LPC47M997\n"); - else { + break; + case 0x6B: + printk(KERN_INFO "smsc47m1: Found SMSC LPC47M292\n"); + break; + default: superio_exit(); return -ENODEV; } @@ -421,7 +461,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) struct i2c_client *new_client; struct smsc47m1_data *data; 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)) { dev_err(&adapter->dev, "Region 0x%x already in use!\n", address); @@ -433,6 +473,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) goto error_release; } + data->type = devid == 0x6B ? smsc47m2 : smsc47m1; new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; @@ -441,20 +482,35 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) new_client->driver = &smsc47m1_driver; 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); /* If no function is properly configured, there's no point in 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) == 0x04; pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05) == 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, " "will not use\n", new_client->addr); err = -ENODEV; @@ -497,6 +553,18 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, " "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 ((err = device_create_file(&new_client->dev, &dev_attr_pwm1)) @@ -506,6 +574,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) } else dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, " "skipping\n"); + if (pwm2) { if ((err = device_create_file(&new_client->dev, &dev_attr_pwm2)) @@ -516,6 +585,16 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, " "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))) goto error_remove_files; @@ -580,15 +659,16 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, mutex_lock(&data->update_lock); 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, - SMSC47M1_REG_FAN(i)); + SMSC47M1_REG_FAN[i]); 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, - SMSC47M1_REG_PWM(i)); + SMSC47M1_REG_PWM[i]); } i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV); @@ -601,6 +681,18 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, if (data->alarms) 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; } -- cgit v1.2.3 From 94e183fd0425a917d9c1453041ef88f3610c0f01 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 May 2007 17:21:59 +0200 Subject: hwmon/smsc47m1: Get rid of a useless mutex The smsc47m1 driver uses a mutex to protect the accesses to the hardware registers. It really doesn't need any protection, as the register space is flat. Get rid of that mutex for a smaller and faster driver. Signed-off-by: Jean Delvare --- drivers/hwmon/smsc47m1.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 16762cca87e5..f219d7c6a982 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -116,7 +116,6 @@ struct smsc47m1_data { struct i2c_client client; enum chips type; struct class_device *class_dev; - struct mutex lock; struct mutex update_lock; unsigned long last_updated; /* In jiffies */ @@ -131,13 +130,19 @@ struct smsc47m1_data { static int smsc47m1_detect(struct i2c_adapter *adapter); static int smsc47m1_detach_client(struct i2c_client *client); - -static int smsc47m1_read_value(struct i2c_client *client, u8 reg); -static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value); - static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, int init); +static inline int smsc47m1_read_value(struct i2c_client *client, u8 reg) +{ + return inb_p(client->addr + reg); +} + +static inline void smsc47m1_write_value(struct i2c_client *client, u8 reg, + u8 value) +{ + outb_p(value, client->addr + reg); +} static struct i2c_driver smsc47m1_driver = { .driver = { @@ -477,7 +482,6 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; - mutex_init(&data->lock); new_client->adapter = adapter; new_client->driver = &smsc47m1_driver; new_client->flags = 0; @@ -633,23 +637,6 @@ static int smsc47m1_detach_client(struct i2c_client *client) return 0; } -static int smsc47m1_read_value(struct i2c_client *client, u8 reg) -{ - int res; - - mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); - res = inb_p(client->addr + reg); - mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); - return res; -} - -static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value) -{ - mutex_lock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); - outb_p(value, client->addr + reg); - mutex_unlock(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock); -} - static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, int init) { -- cgit v1.2.3 From 8a665a0552c414af88788cc0e2cf0e4626182c20 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 May 2007 17:21:59 +0200 Subject: hwmon: Only call vid_which_vrm() when needed Some hardware monitoring drivers create the VID/VRM interface files conditionally depending on the chip model or configuration. We should only call vid_which_vrm() when we are actually going to create the files. Not only it is more logical and efficient that way, but it also prevents printing unnecessary warnings such as the one reported here: http://lists.lm-sensors.org/pipermail/lm-sensors/2007-February/018954.html Signed-off-by: Jean Delvare --- drivers/hwmon/lm87.c | 2 +- drivers/hwmon/w83627hf.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 3ce825489e34..988ae1c4aada 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -747,6 +747,7 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) } if (!(data->channel & CHAN_NO_VID)) { + data->vrm = vid_which_vrm(); if ((err = device_create_file(&new_client->dev, &dev_attr_cpu0_vid)) || (err = device_create_file(&new_client->dev, @@ -779,7 +780,6 @@ static void lm87_init_client(struct i2c_client *client) u8 config; data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE); - data->vrm = vid_which_vrm(); config = lm87_read_value(client, LM87_REG_CONFIG); if (!(config & 0x01)) { diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index d7e240635b3b..3ed67a5cd53c 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -1181,12 +1181,16 @@ static int w83627hf_detect(struct i2c_adapter *adapter) &dev_attr_temp3_type))) goto ERROR4; - if (kind != w83697hf && data->vid != 0xff) + if (kind != w83697hf && data->vid != 0xff) { + /* Convert VID to voltage based on VRM */ + data->vrm = vid_which_vrm(); + if ((err = device_create_file(&new_client->dev, &dev_attr_cpu0_vid)) || (err = device_create_file(&new_client->dev, &dev_attr_vrm))) goto ERROR4; + } if (kind == w83627thf || kind == w83637hf || kind == w83687thf) if ((err = device_create_file(&new_client->dev, @@ -1420,9 +1424,6 @@ static void w83627hf_init_client(struct i2c_client *client) w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); } - /* Convert VID to voltage based on VRM */ - data->vrm = vid_which_vrm(); - tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); for (i = 1; i <= 3; i++) { if (!(tmp & BIT_SCFG1[i - 1])) { -- cgit v1.2.3 From e46751bfd69839edd15ee54cabbeed8e801a4274 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Tue, 8 May 2007 17:21:59 +0200 Subject: hwmon-vid: Add support for VIA Esther Update the VID type for certain VIA processors and remove the Itanium entries. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare --- drivers/hwmon/hwmon-vid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index b80f6ed5acfc..5aab23b93e24 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -166,16 +166,16 @@ static struct vrm_model vrm_models[] = { {X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14}, /* Intel Core (65 nm) */ {X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110}, /* Intel Conroe */ {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */ - {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */ {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */ {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */ {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */ {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */ - {X86_VENDOR_INTEL, 0x10, ANY, ANY, 0}, /* Itanium 2 */ {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */ {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */ {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */ - {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M */ + {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M, Eden-N */ + {X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0}, /* No information */ + {X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13}, /* C7, Esther */ {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */ }; -- cgit v1.2.3 From d27c37c0be3fd97a696dafb28507277d49875dcb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 May 2007 17:21:59 +0200 Subject: hwmon/w83627hf: Preliminary cleanups Some preliminary cleanups to the w83627hf hardware monitoring driver, to make its conversion to a platform driver easier: * Add missing include ioport.h * Drop unused enum value any_chip * Group module parameters * Define and use DRVNAME * Drop unused struct member lm75 * Move the handling of force_addr and device activation to w83627hf_find * Consistently use local type in w83627hf_init_client Signed-off-by: Jean Delvare --- drivers/hwmon/w83627hf.c | 76 +++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 3ed67a5cd53c..7738d30a11b8 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -48,9 +48,16 @@ #include #include #include +#include #include #include "lm75.h" +/* The actual ISA address is read from Super-I/O configuration space */ +static unsigned short address; + +#define DRVNAME "w83627hf" +enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; + static u16 force_addr; module_param(force_addr, ushort, 0); MODULE_PARM_DESC(force_addr, @@ -60,12 +67,6 @@ module_param(force_i2c, byte, 0); MODULE_PARM_DESC(force_i2c, "Initialize the i2c address of the sensors"); -/* The actual ISA address is read from Super-I/O configuration space */ -static unsigned short address; - -/* Insmod parameters */ -enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; - static int reset; module_param(reset, bool, 0); MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); @@ -298,9 +299,6 @@ struct w83627hf_data { char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ - struct i2c_client *lm75; /* for secondary I2C addresses */ - /* pointer to array of 2 subclients */ - u8 in[9]; /* Register value */ u8 in_max[9]; /* Register value */ u8 in_min[9]; /* Register value */ @@ -339,7 +337,7 @@ static void w83627hf_init_client(struct i2c_client *client); static struct i2c_driver w83627hf_driver = { .driver = { .owner = THIS_MODULE, - .name = "w83627hf", + .name = DRVNAME, }, .attach_adapter = w83627hf_detect, .detach_client = w83627hf_detach_client, @@ -931,6 +929,7 @@ sysfs_sensor(3); static int __init w83627hf_find(int sioaddr, unsigned short *addr) { + int err = -ENODEV; u16 val; REG = sioaddr; @@ -943,21 +942,37 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr) val != W697_DEVID && val != W637_DEVID && val != W687THF_DEVID) { - superio_exit(); - return -ENODEV; + goto exit; } superio_select(W83627HF_LD_HWM); + force_addr &= WINB_ALIGNMENT; + if (force_addr) { + printk(KERN_WARNING DRVNAME ": Forcing address 0x%x\n", + force_addr); + superio_outb(WINB_BASE_REG, force_addr >> 8); + superio_outb(WINB_BASE_REG + 1, force_addr & 0xff); + } val = (superio_inb(WINB_BASE_REG) << 8) | superio_inb(WINB_BASE_REG + 1); *addr = val & WINB_ALIGNMENT; - if (*addr == 0 && force_addr == 0) { - superio_exit(); - return -ENODEV; + if (*addr == 0) { + printk(KERN_WARNING DRVNAME ": Base address not set, " + "skipping\n"); + goto exit; + } + + val = superio_inb(WINB_ACT_REG); + if (!(val & 0x01)) { + printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n"); + superio_outb(WINB_ACT_REG, val | 0x01); } + err = 0; + + exit: superio_exit(); - return 0; + return err; } static struct attribute *w83627hf_attributes[] = { @@ -1047,24 +1062,12 @@ static int w83627hf_detect(struct i2c_adapter *adapter) int err = 0; const char *client_name = ""; - if(force_addr) - address = force_addr & WINB_ALIGNMENT; - if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE, w83627hf_driver.driver.name)) { err = -EBUSY; goto ERROR0; } - if(force_addr) { - printk("w83627hf.o: forcing ISA address 0x%04X\n", address); - superio_enter(); - superio_select(W83627HF_LD_HWM); - superio_outb(WINB_BASE_REG, address >> 8); - superio_outb(WINB_BASE_REG+1, address & 0xff); - superio_exit(); - } - superio_enter(); val= superio_inb(DEVID); if(val == W627_DEVID) @@ -1082,10 +1085,6 @@ static int w83627hf_detect(struct i2c_adapter *adapter) "Unsupported chip (dev_id=0x%02X).\n", val); goto ERROR1; } - - superio_select(W83627HF_LD_HWM); - if((val = 0x01 & superio_inb(WINB_ACT_REG)) == 0) - superio_outb(WINB_ACT_REG, 1); superio_exit(); /* OK. For now, we presume we have a valid client. We now create the @@ -1128,8 +1127,6 @@ static int w83627hf_detect(struct i2c_adapter *adapter) if ((err = i2c_attach_client(new_client))) goto ERROR2; - data->lm75 = NULL; - /* Initialize the chip */ w83627hf_init_client(new_client); @@ -1374,7 +1371,7 @@ static void w83627hf_init_client(struct i2c_client *client) { struct w83627hf_data *data = i2c_get_clientdata(client); int i; - int type = data->type; + enum chips type = data->type; u8 tmp; if (reset) { @@ -1407,19 +1404,18 @@ static void w83627hf_init_client(struct i2c_client *client) w83627hf_write_value(client, W83781D_REG_I2C_ADDR, force_i2c); /* Read VID only once */ - if (w83627hf == data->type || w83637hf == data->type) { + if (type == w83627hf || type == w83637hf) { int lo = w83627hf_read_value(client, W83781D_REG_VID_FANDIV); int hi = w83627hf_read_value(client, W83781D_REG_CHIPID); data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); - } else if (w83627thf == data->type) { + } else if (type == w83627thf) { data->vid = w83627thf_read_gpio5(client); - } else if (w83687thf == data->type) { + } else if (type == w83687thf) { data->vid = w83687thf_read_vid(client); } /* Read VRM & OVT Config only once */ - if (w83627thf == data->type || w83637hf == data->type - || w83687thf == data->type) { + if (type == w83627thf || type == w83637hf || type == w83687thf) { data->vrm_ovt = w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG); } -- cgit v1.2.3 From 787c72b107888805981faf148c8fea96a752d22e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 May 2007 17:22:00 +0200 Subject: hwmon/w83627hf: Convert to a platform driver Convert the w83627hf driver from the nonsensical i2c-isa hack to a regular platform driver. Signed-off-by: Jean Delvare --- drivers/hwmon/Kconfig | 3 +- drivers/hwmon/w83627hf.c | 591 +++++++++++++++++++++++++---------------------- 2 files changed, 311 insertions(+), 283 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 399b6a92e9b0..ae3ab9169d52 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -550,8 +550,7 @@ config SENSORS_W83L785TS config SENSORS_W83627HF tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" - depends on HWMON && I2C - select I2C_ISA + depends on HWMON select HWMON_VID help If you say yes here you get support for the Winbond W836X7 series diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 7738d30a11b8..a5b774b07cbd 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -5,6 +5,7 @@ Philip Edelbrock , and Mark Studebaker Ported to 2.6 by Bernhard C. Schrenk + Copyright (c) 2007 Jean Delvare 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 @@ -42,8 +43,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -52,8 +52,7 @@ #include #include "lm75.h" -/* The actual ISA address is read from Super-I/O configuration space */ -static unsigned short address; +static struct platform_device *pdev; #define DRVNAME "w83627hf" enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; @@ -157,9 +156,9 @@ superio_exit(void) #define WINB_REGION_OFFSET 5 #define WINB_REGION_SIZE 2 -/* Where are the sensors address/data registers relative to the base address */ -#define W83781D_ADDR_REG_OFFSET 5 -#define W83781D_DATA_REG_OFFSET 6 +/* Where are the sensors address/data registers relative to the region offset */ +#define W83781D_ADDR_REG_OFFSET 0 +#define W83781D_DATA_REG_OFFSET 1 /* The W83781D registers */ /* The W83782D registers for nr=7,8 are in bank 5 */ @@ -290,7 +289,8 @@ static inline u8 DIV_TO_REG(long val) /* For each registered chip, we need to keep some data in memory. The structure is dynamically allocated. */ struct w83627hf_data { - struct i2c_client client; + unsigned short addr; + const char *name; struct class_device *class_dev; struct mutex lock; enum chips type; @@ -325,22 +325,26 @@ struct w83627hf_data { u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ }; +struct w83627hf_sio_data { + enum chips type; +}; -static int w83627hf_detect(struct i2c_adapter *adapter); -static int w83627hf_detach_client(struct i2c_client *client); -static int w83627hf_read_value(struct i2c_client *client, u16 reg); -static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value); +static int w83627hf_probe(struct platform_device *pdev); +static int w83627hf_remove(struct platform_device *pdev); + +static int w83627hf_read_value(struct w83627hf_data *data, u16 reg); +static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value); static struct w83627hf_data *w83627hf_update_device(struct device *dev); -static void w83627hf_init_client(struct i2c_client *client); +static void w83627hf_init_device(struct platform_device *pdev); -static struct i2c_driver w83627hf_driver = { +static struct platform_driver w83627hf_driver = { .driver = { .owner = THIS_MODULE, .name = DRVNAME, }, - .attach_adapter = w83627hf_detect, - .detach_client = w83627hf_detach_client, + .probe = w83627hf_probe, + .remove = __devexit_p(w83627hf_remove), }; /* following are the sysfs callback functions */ @@ -358,15 +362,14 @@ show_in_reg(in_max) static ssize_t \ store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ { \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83627hf_data *data = i2c_get_clientdata(client); \ + struct w83627hf_data *data = dev_get_drvdata(dev); \ u32 val; \ \ val = simple_strtoul(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ data->in_##reg[nr] = IN_TO_REG(val); \ - w83627hf_write_value(client, W83781D_REG_IN_##REG(nr), \ + w83627hf_write_value(data, W83781D_REG_IN_##REG(nr), \ data->in_##reg[nr]); \ \ mutex_unlock(&data->update_lock); \ @@ -450,8 +453,7 @@ static ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *at static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627hf_data *data = i2c_get_clientdata(client); + struct w83627hf_data *data = dev_get_drvdata(dev); u32 val; val = simple_strtoul(buf, NULL, 10); @@ -470,7 +472,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a /* use VRM8 (standard) calculation */ data->in_min[0] = IN_TO_REG(val); - w83627hf_write_value(client, W83781D_REG_IN_MIN(0), data->in_min[0]); + w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]); mutex_unlock(&data->update_lock); return count; } @@ -478,8 +480,7 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627hf_data *data = i2c_get_clientdata(client); + struct w83627hf_data *data = dev_get_drvdata(dev); u32 val; val = simple_strtoul(buf, NULL, 10); @@ -498,7 +499,7 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a /* use VRM8 (standard) calculation */ data->in_max[0] = IN_TO_REG(val); - w83627hf_write_value(client, W83781D_REG_IN_MAX(0), data->in_max[0]); + w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]); mutex_unlock(&data->update_lock); return count; } @@ -523,8 +524,7 @@ show_fan_reg(fan_min); static ssize_t store_fan_min(struct device *dev, const char *buf, size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627hf_data *data = i2c_get_clientdata(client); + struct w83627hf_data *data = dev_get_drvdata(dev); u32 val; val = simple_strtoul(buf, NULL, 10); @@ -532,7 +532,7 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr) mutex_lock(&data->update_lock); data->fan_min[nr - 1] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); - w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr), + w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr), data->fan_min[nr - 1]); mutex_unlock(&data->update_lock); @@ -585,8 +585,7 @@ show_temp_reg(temp_max_hyst); static ssize_t \ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ { \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83627hf_data *data = i2c_get_clientdata(client); \ + struct w83627hf_data *data = dev_get_drvdata(dev); \ u32 val; \ \ val = simple_strtoul(buf, NULL, 10); \ @@ -595,11 +594,11 @@ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ \ if (nr >= 2) { /* TEMP2 and TEMP3 */ \ data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ - w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \ + w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \ data->temp_##reg##_add[nr-2]); \ } else { /* TEMP1 */ \ data->temp_##reg = TEMP_TO_REG(val); \ - w83627hf_write_value(client, W83781D_REG_TEMP_##REG(nr), \ + w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \ data->temp_##reg); \ } \ \ @@ -657,8 +656,7 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627hf_data *data = i2c_get_clientdata(client); + struct w83627hf_data *data = dev_get_drvdata(dev); u32 val; val = simple_strtoul(buf, NULL, 10); @@ -693,8 +691,7 @@ static ssize_t store_beep_reg(struct device *dev, const char *buf, size_t count, int update_mask) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627hf_data *data = i2c_get_clientdata(client); + struct w83627hf_data *data = dev_get_drvdata(dev); u32 val, val2; val = simple_strtoul(buf, NULL, 10); @@ -703,18 +700,18 @@ store_beep_reg(struct device *dev, const char *buf, size_t count, if (update_mask == BEEP_MASK) { /* We are storing beep_mask */ data->beep_mask = BEEP_MASK_TO_REG(val); - w83627hf_write_value(client, W83781D_REG_BEEP_INTS1, + w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, data->beep_mask & 0xff); - w83627hf_write_value(client, W83781D_REG_BEEP_INTS3, + w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, ((data->beep_mask) >> 16) & 0xff); val2 = (data->beep_mask >> 8) & 0x7f; } else { /* We are storing beep_enable */ val2 = - w83627hf_read_value(client, W83781D_REG_BEEP_INTS2) & 0x7f; + w83627hf_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f; data->beep_enable = BEEP_ENABLE_TO_REG(val); } - w83627hf_write_value(client, W83781D_REG_BEEP_INTS2, + w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, val2 | data->beep_enable << 7); mutex_unlock(&data->update_lock); @@ -752,8 +749,7 @@ show_fan_div_reg(struct device *dev, char *buf, int nr) static ssize_t store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627hf_data *data = i2c_get_clientdata(client); + struct w83627hf_data *data = dev_get_drvdata(dev); unsigned long min; u8 reg; unsigned long val = simple_strtoul(buf, NULL, 10); @@ -766,19 +762,19 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) data->fan_div[nr] = DIV_TO_REG(val); - reg = (w83627hf_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) + reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) & (nr==0 ? 0xcf : 0x3f)) | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); - w83627hf_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); + w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); - reg = (w83627hf_read_value(client, W83781D_REG_VBAT) + reg = (w83627hf_read_value(data, W83781D_REG_VBAT) & ~(1 << (5 + nr))) | ((data->fan_div[nr] & 0x04) << (3 + nr)); - w83627hf_write_value(client, W83781D_REG_VBAT, reg); + w83627hf_write_value(data, W83781D_REG_VBAT, reg); /* Restore fan_min */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); + w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; @@ -812,8 +808,7 @@ show_pwm_reg(struct device *dev, char *buf, int nr) static ssize_t store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627hf_data *data = i2c_get_clientdata(client); + struct w83627hf_data *data = dev_get_drvdata(dev); u32 val; val = simple_strtoul(buf, NULL, 10); @@ -823,14 +818,14 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) if (data->type == w83627thf) { /* bits 0-3 are reserved in 627THF */ data->pwm[nr - 1] = PWM_TO_REG(val) & 0xf0; - w83627hf_write_value(client, + w83627hf_write_value(data, W836X7HF_REG_PWM(data->type, nr), data->pwm[nr - 1] | - (w83627hf_read_value(client, + (w83627hf_read_value(data, W836X7HF_REG_PWM(data->type, nr)) & 0x0f)); } else { data->pwm[nr - 1] = PWM_TO_REG(val); - w83627hf_write_value(client, + w83627hf_write_value(data, W836X7HF_REG_PWM(data->type, nr), data->pwm[nr - 1]); } @@ -866,8 +861,7 @@ show_sensor_reg(struct device *dev, char *buf, int nr) static ssize_t store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627hf_data *data = i2c_get_clientdata(client); + struct w83627hf_data *data = dev_get_drvdata(dev); u32 val, tmp; val = simple_strtoul(buf, NULL, 10); @@ -876,31 +870,31 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) switch (val) { case 1: /* PII/Celeron diode */ - tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); - w83627hf_write_value(client, W83781D_REG_SCFG1, + tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); + w83627hf_write_value(data, W83781D_REG_SCFG1, tmp | BIT_SCFG1[nr - 1]); - tmp = w83627hf_read_value(client, W83781D_REG_SCFG2); - w83627hf_write_value(client, W83781D_REG_SCFG2, + tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); + w83627hf_write_value(data, W83781D_REG_SCFG2, tmp | BIT_SCFG2[nr - 1]); data->sens[nr - 1] = val; break; case 2: /* 3904 */ - tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); - w83627hf_write_value(client, W83781D_REG_SCFG1, + tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); + w83627hf_write_value(data, W83781D_REG_SCFG1, tmp | BIT_SCFG1[nr - 1]); - tmp = w83627hf_read_value(client, W83781D_REG_SCFG2); - w83627hf_write_value(client, W83781D_REG_SCFG2, + tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); + w83627hf_write_value(data, W83781D_REG_SCFG2, tmp & ~BIT_SCFG2[nr - 1]); data->sens[nr - 1] = val; break; case W83781D_DEFAULT_BETA: /* thermistor */ - tmp = w83627hf_read_value(client, W83781D_REG_SCFG1); - w83627hf_write_value(client, W83781D_REG_SCFG1, + tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); + w83627hf_write_value(data, W83781D_REG_SCFG1, tmp & ~BIT_SCFG1[nr - 1]); data->sens[nr - 1] = val; break; default: - dev_err(&client->dev, + dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n", (long) val, W83781D_DEFAULT_BETA); break; @@ -927,21 +921,52 @@ sysfs_sensor(1); sysfs_sensor(2); sysfs_sensor(3); -static int __init w83627hf_find(int sioaddr, unsigned short *addr) +static ssize_t show_name(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct w83627hf_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", data->name); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +static int __init w83627hf_find(int sioaddr, unsigned short *addr, + struct w83627hf_sio_data *sio_data) { int err = -ENODEV; u16 val; + static const __initdata char *names[] = { + "W83627HF", + "W83627THF", + "W83697HF", + "W83637HF", + "W83687THF", + }; + REG = sioaddr; VAL = sioaddr + 1; superio_enter(); val= superio_inb(DEVID); - if(val != W627_DEVID && - val != W627THF_DEVID && - val != W697_DEVID && - val != W637_DEVID && - val != W687THF_DEVID) { + switch (val) { + case W627_DEVID: + sio_data->type = w83627hf; + break; + case W627THF_DEVID: + sio_data->type = w83627thf; + break; + case W697_DEVID: + sio_data->type = w83697hf; + break; + case W637_DEVID: + sio_data->type = w83637hf; + break; + case W687THF_DEVID: + sio_data->type = w83687thf; + break; + default: + pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n", val); goto exit; } @@ -969,6 +994,8 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr) } err = 0; + pr_info(DRVNAME ": Found %s chip at %#x\n", + names[sio_data->type], *addr); exit: superio_exit(); @@ -1018,6 +1045,7 @@ static struct attribute *w83627hf_attributes[] = { &dev_attr_pwm1.attr, &dev_attr_pwm2.attr, + &dev_attr_name.attr, NULL }; @@ -1054,147 +1082,92 @@ static const struct attribute_group w83627hf_group_opt = { .attrs = w83627hf_attributes_opt, }; -static int w83627hf_detect(struct i2c_adapter *adapter) +static int __devinit w83627hf_probe(struct platform_device *pdev) { - int val, kind; - struct i2c_client *new_client; + struct device *dev = &pdev->dev; + struct w83627hf_sio_data *sio_data = dev->platform_data; struct w83627hf_data *data; - int err = 0; - const char *client_name = ""; + struct resource *res; + int err; - if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE, - w83627hf_driver.driver.name)) { + static const char *names[] = { + "w83627hf", + "w83627thf", + "w83697hf", + "w83637hf", + "w83687thf", + }; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) { + dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)res->start, + (unsigned long)(res->start + WINB_REGION_SIZE - 1)); err = -EBUSY; goto ERROR0; } - superio_enter(); - val= superio_inb(DEVID); - if(val == W627_DEVID) - kind = w83627hf; - else if(val == W697_DEVID) - kind = w83697hf; - else if(val == W627THF_DEVID) - kind = w83627thf; - else if(val == W637_DEVID) - kind = w83637hf; - else if (val == W687THF_DEVID) - kind = w83687thf; - else { - dev_info(&adapter->dev, - "Unsupported chip (dev_id=0x%02X).\n", val); - goto ERROR1; - } - superio_exit(); - - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. - But it allows us to access w83627hf_{read,write}_value. */ - if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) { err = -ENOMEM; goto ERROR1; } - - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; + data->addr = res->start; + data->type = sio_data->type; + data->name = names[sio_data->type]; mutex_init(&data->lock); - new_client->adapter = adapter; - new_client->driver = &w83627hf_driver; - new_client->flags = 0; - - - if (kind == w83627hf) { - client_name = "w83627hf"; - } else if (kind == w83627thf) { - client_name = "w83627thf"; - } else if (kind == w83697hf) { - client_name = "w83697hf"; - } else if (kind == w83637hf) { - client_name = "w83637hf"; - } else if (kind == w83687thf) { - client_name = "w83687thf"; - } - - /* Fill in the remaining client fields and put into the global list */ - strlcpy(new_client->name, client_name, I2C_NAME_SIZE); - data->type = kind; - data->valid = 0; mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto ERROR2; + platform_set_drvdata(pdev, data); /* Initialize the chip */ - w83627hf_init_client(new_client); + w83627hf_init_device(pdev); /* A few vars need to be filled upon startup */ - data->fan_min[0] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(1)); - data->fan_min[1] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(2)); - data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3)); + data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1)); + data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2)); + data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3)); /* Register common device attributes */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &w83627hf_group))) + if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group))) goto ERROR3; /* Register chip-specific device attributes */ - if (kind == w83627hf || kind == w83697hf) - if ((err = device_create_file(&new_client->dev, - &dev_attr_in5_input)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in5_min)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in5_max)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in6_input)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in6_min)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in6_max))) + if (data->type == w83627hf || data->type == w83697hf) + if ((err = device_create_file(dev, &dev_attr_in5_input)) + || (err = device_create_file(dev, &dev_attr_in5_min)) + || (err = device_create_file(dev, &dev_attr_in5_max)) + || (err = device_create_file(dev, &dev_attr_in6_input)) + || (err = device_create_file(dev, &dev_attr_in6_min)) + || (err = device_create_file(dev, &dev_attr_in6_max))) goto ERROR4; - if (kind != w83697hf) - if ((err = device_create_file(&new_client->dev, - &dev_attr_in1_input)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in1_min)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in1_max)) - || (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)) - || (err = device_create_file(&new_client->dev, - &dev_attr_temp3_input)) - || (err = device_create_file(&new_client->dev, - &dev_attr_temp3_max)) - || (err = device_create_file(&new_client->dev, - &dev_attr_temp3_max_hyst)) - || (err = device_create_file(&new_client->dev, - &dev_attr_temp3_type))) + if (data->type != w83697hf) + if ((err = device_create_file(dev, &dev_attr_in1_input)) + || (err = device_create_file(dev, &dev_attr_in1_min)) + || (err = device_create_file(dev, &dev_attr_in1_max)) + || (err = device_create_file(dev, &dev_attr_fan3_input)) + || (err = device_create_file(dev, &dev_attr_fan3_min)) + || (err = device_create_file(dev, &dev_attr_fan3_div)) + || (err = device_create_file(dev, &dev_attr_temp3_input)) + || (err = device_create_file(dev, &dev_attr_temp3_max)) + || (err = device_create_file(dev, &dev_attr_temp3_max_hyst)) + || (err = device_create_file(dev, &dev_attr_temp3_type))) goto ERROR4; - if (kind != w83697hf && data->vid != 0xff) { + if (data->type != w83697hf && data->vid != 0xff) { /* Convert VID to voltage based on VRM */ data->vrm = vid_which_vrm(); - if ((err = device_create_file(&new_client->dev, - &dev_attr_cpu0_vid)) - || (err = device_create_file(&new_client->dev, - &dev_attr_vrm))) + if ((err = device_create_file(dev, &dev_attr_cpu0_vid)) + || (err = device_create_file(dev, &dev_attr_vrm))) goto ERROR4; } - if (kind == w83627thf || kind == w83637hf || kind == w83687thf) - if ((err = device_create_file(&new_client->dev, - &dev_attr_pwm3))) + if (data->type == w83627thf || data->type == w83637hf + || data->type == w83687thf) + if ((err = device_create_file(dev, &dev_attr_pwm3))) goto ERROR4; - data->class_dev = hwmon_device_register(&new_client->dev); + data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto ERROR4; @@ -1203,47 +1176,37 @@ static int w83627hf_detect(struct i2c_adapter *adapter) return 0; ERROR4: - sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group); - sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group_opt); + sysfs_remove_group(&dev->kobj, &w83627hf_group); + sysfs_remove_group(&dev->kobj, &w83627hf_group_opt); ERROR3: - i2c_detach_client(new_client); - ERROR2: kfree(data); ERROR1: - release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE); + release_region(res->start, WINB_REGION_SIZE); ERROR0: return err; } -static int w83627hf_detach_client(struct i2c_client *client) +static int __devexit w83627hf_remove(struct platform_device *pdev) { - struct w83627hf_data *data = i2c_get_clientdata(client); - int err; + struct w83627hf_data *data = platform_get_drvdata(pdev); + struct resource *res; + platform_set_drvdata(pdev, NULL); hwmon_device_unregister(data->class_dev); - sysfs_remove_group(&client->dev.kobj, &w83627hf_group); - sysfs_remove_group(&client->dev.kobj, &w83627hf_group_opt); - - if ((err = i2c_detach_client(client))) - return err; - - release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE); + sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group); + sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt); kfree(data); + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + release_region(res->start, WINB_REGION_SIZE); + return 0; } -/* - ISA access must always be locked explicitly! - We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, - would slow down the W83781D access and should not be necessary. - There are some ugly typecasts here, but the good news is - they should - nowhere else be necessary! */ -static int w83627hf_read_value(struct i2c_client *client, u16 reg) +static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) { - struct w83627hf_data *data = i2c_get_clientdata(client); int res, word_sized; mutex_lock(&data->lock); @@ -1254,29 +1217,29 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg) || ((reg & 0x00ff) == 0x55)); if (reg & 0xff00) { outb_p(W83781D_REG_BANK, - client->addr + W83781D_ADDR_REG_OFFSET); + data->addr + W83781D_ADDR_REG_OFFSET); outb_p(reg >> 8, - client->addr + W83781D_DATA_REG_OFFSET); + data->addr + W83781D_DATA_REG_OFFSET); } - outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); - res = inb_p(client->addr + W83781D_DATA_REG_OFFSET); + outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); + res = inb_p(data->addr + W83781D_DATA_REG_OFFSET); if (word_sized) { outb_p((reg & 0xff) + 1, - client->addr + W83781D_ADDR_REG_OFFSET); + data->addr + W83781D_ADDR_REG_OFFSET); res = - (res << 8) + inb_p(client->addr + + (res << 8) + inb_p(data->addr + W83781D_DATA_REG_OFFSET); } if (reg & 0xff00) { outb_p(W83781D_REG_BANK, - client->addr + W83781D_ADDR_REG_OFFSET); - outb_p(0, client->addr + W83781D_DATA_REG_OFFSET); + data->addr + W83781D_ADDR_REG_OFFSET); + outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); } mutex_unlock(&data->lock); return res; } -static int w83627thf_read_gpio5(struct i2c_client *client) +static int __devinit w83627thf_read_gpio5(struct platform_device *pdev) { int res = 0xff, sel; @@ -1285,7 +1248,7 @@ static int w83627thf_read_gpio5(struct i2c_client *client) /* Make sure these GPIO pins are enabled */ if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) { - dev_dbg(&client->dev, "GPIO5 disabled, no VID function\n"); + dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n"); goto exit; } @@ -1293,12 +1256,12 @@ static int w83627thf_read_gpio5(struct i2c_client *client) There must be at least five (VRM 9), and possibly 6 (VRM 10) */ sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f; if ((sel & 0x1f) != 0x1f) { - dev_dbg(&client->dev, "GPIO5 not configured for VID " + dev_dbg(&pdev->dev, "GPIO5 not configured for VID " "function\n"); goto exit; } - dev_info(&client->dev, "Reading VID from GPIO5\n"); + dev_info(&pdev->dev, "Reading VID from GPIO5\n"); res = superio_inb(W83627THF_GPIO5_DR) & sel; exit: @@ -1306,7 +1269,7 @@ exit: return res; } -static int w83687thf_read_vid(struct i2c_client *client) +static int __devinit w83687thf_read_vid(struct platform_device *pdev) { int res = 0xff; @@ -1315,13 +1278,13 @@ static int w83687thf_read_vid(struct i2c_client *client) /* Make sure these GPIO pins are enabled */ if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { - dev_dbg(&client->dev, "VID disabled, no VID function\n"); + dev_dbg(&pdev->dev, "VID disabled, no VID function\n"); goto exit; } /* Make sure the pins are configured for input */ if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { - dev_dbg(&client->dev, "VID configured as output, " + dev_dbg(&pdev->dev, "VID configured as output, " "no VID function\n"); goto exit; } @@ -1333,9 +1296,8 @@ exit: return res; } -static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) +static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value) { - struct w83627hf_data *data = i2c_get_clientdata(client); int word_sized; mutex_lock(&data->lock); @@ -1345,31 +1307,31 @@ static int w83627hf_write_value(struct i2c_client *client, u16 reg, u16 value) || ((reg & 0x00ff) == 0x55)); if (reg & 0xff00) { outb_p(W83781D_REG_BANK, - client->addr + W83781D_ADDR_REG_OFFSET); + data->addr + W83781D_ADDR_REG_OFFSET); outb_p(reg >> 8, - client->addr + W83781D_DATA_REG_OFFSET); + data->addr + W83781D_DATA_REG_OFFSET); } - outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET); + outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); if (word_sized) { outb_p(value >> 8, - client->addr + W83781D_DATA_REG_OFFSET); + data->addr + W83781D_DATA_REG_OFFSET); outb_p((reg & 0xff) + 1, - client->addr + W83781D_ADDR_REG_OFFSET); + data->addr + W83781D_ADDR_REG_OFFSET); } outb_p(value & 0xff, - client->addr + W83781D_DATA_REG_OFFSET); + data->addr + W83781D_DATA_REG_OFFSET); if (reg