diff options
author | Justin Waters <justin.waters@timesys.com> | 2008-02-26 13:07:02 -0500 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2008-02-26 13:07:02 -0500 |
commit | b80a32b9cc634adfa8eaef33ec981e7febf2ade2 (patch) | |
tree | f256bce13ba11f514a388160df84e1410bedbe2b /drivers/hwmon | |
parent | 594133ef22fae0d737bd1b57352cf3f48a192c63 (diff) |
Update the i.MX31 Kernel to 2.6.232.6.23-mx31ads-2008022618072.6.23-mx31-200802261807
This is the result of a brute-force attempt to update the kernel to 2.6.23.
Now that we have a git tree, our effort will be a little nicer in the future.
Signed-off-by: Justin Waters <justin.waters@timesys.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/Kconfig | 92 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 4 | ||||
-rw-r--r-- | drivers/hwmon/abituguru.c | 45 | ||||
-rw-r--r-- | drivers/hwmon/ams/ams-core.c | 1 | ||||
-rw-r--r-- | drivers/hwmon/applesmc.c | 14 | ||||
-rw-r--r-- | drivers/hwmon/coretemp.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/ds1621.c | 161 | ||||
-rw-r--r-- | drivers/hwmon/f71805f.c | 178 | ||||
-rw-r--r-- | drivers/hwmon/fscher.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/it87.c | 497 | ||||
-rw-r--r-- | drivers/hwmon/lm63.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/lm70.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/lm78.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/lm83.c | 12 | ||||
-rw-r--r-- | drivers/hwmon/lm90.c | 78 | ||||
-rw-r--r-- | drivers/hwmon/pc87360.c | 232 | ||||
-rw-r--r-- | drivers/hwmon/pc87427.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/sis5595.c | 510 | ||||
-rw-r--r-- | drivers/hwmon/smsc47b397.c | 7 | ||||
-rw-r--r-- | drivers/hwmon/smsc47m1.c | 14 | ||||
-rw-r--r-- | drivers/hwmon/smsc47m192.c | 37 | ||||
-rw-r--r-- | drivers/hwmon/via686a.c | 538 | ||||
-rw-r--r-- | drivers/hwmon/vt8231.c | 318 | ||||
-rw-r--r-- | drivers/hwmon/w83627ehf.c | 661 | ||||
-rw-r--r-- | drivers/hwmon/w83627hf.c | 155 | ||||
-rw-r--r-- | drivers/hwmon/w83781d.c | 2 |
26 files changed, 2137 insertions, 1439 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 13eea47dceb3..192953b29b28 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -29,17 +29,34 @@ config HWMON_VID default n config SENSORS_ABITUGURU - tristate "Abit uGuru" + tristate "Abit uGuru (rev 1 & 2)" depends on EXPERIMENTAL help - If you say yes here you get support for the Abit uGuru chips - sensor part. The voltage and frequency control parts of the Abit - uGuru are not supported. The Abit uGuru chip can be found on Abit - uGuru featuring motherboards (most modern Abit motherboards). + If you say yes here you get support for the sensor part of the first + and second revision of the Abit uGuru chip. The voltage and frequency + control parts of the Abit uGuru are not supported. The Abit uGuru + chip can be found on Abit uGuru featuring motherboards (most modern + Abit motherboards from before end 2005). For more info and a list + of which motherboards have which revision see + Documentation/hwmon/abituguru This driver can also be built as a module. If so, the module will be called abituguru. +config SENSORS_ABITUGURU3 + tristate "Abit uGuru (rev 3)" + depends on HWMON && EXPERIMENTAL + help + If you say yes here you get support for the sensor part of the + third revision of the Abit uGuru chip. Only reading the sensors + and their settings is supported. The third revision of the Abit + uGuru chip can be found on recent Abit motherboards (since end + 2005). For more info and a list of which motherboards have which + revision see Documentation/hwmon/abituguru3 + + This driver can also be built as a module. If so, the module + will be called abituguru3. + config SENSORS_AD7418 tristate "Analog Devices AD7416, AD7417 and AD7418" depends on I2C && EXPERIMENTAL @@ -250,12 +267,10 @@ config SENSORS_CORETEMP config SENSORS_IT87 tristate "ITE IT87xx and compatibles" - depends on I2C - select I2C_ISA select HWMON_VID help If you say yes here you get support for ITE IT8705F, IT8712F, - IT8716F and IT8718F sensor chips, and the SiS960 clone. + IT8716F, IT8718F and IT8726F sensor chips, and the SiS960 clone. This driver can also be built as a module. If so, the module will be called it87. @@ -365,8 +380,8 @@ config SENSORS_LM90 depends on I2C help If you say yes here you get support for National Semiconductor LM90, - LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and - MAX6658 sensor chips. + LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657, + MAX6658, MAX6659, MAX6680 and MAX6681 sensor chips. The Analog Devices ADT7461 sensor chip is also supported, but only if found in ADM1032 compatibility mode. @@ -384,6 +399,17 @@ config SENSORS_LM92 This driver can also be built as a module. If so, the module will be called lm92. +config SENSORS_LM93 + tristate "National Semiconductor LM93 and compatibles" + depends on HWMON && I2C + select HWMON_VID + help + If you say yes here you get support for National Semiconductor LM93 + sensor chips. + + This driver can also be built as a module. If so, the module + will be called lm93. + config SENSORS_MAX1619 tristate "Maxim MAX1619 sensor chip" depends on I2C @@ -405,8 +431,6 @@ config SENSORS_MAX6650 config SENSORS_PC87360 tristate "National Semiconductor PC87360 family" - depends on I2C && EXPERIMENTAL - select I2C_ISA select HWMON_VID help If you say yes here you get access to the hardware monitoring @@ -433,8 +457,7 @@ config SENSORS_PC87427 config SENSORS_SIS5595 tristate "Silicon Integrated Systems Corp. SiS5595" - depends on I2C && PCI && EXPERIMENTAL - select I2C_ISA + depends on PCI help If you say yes here you get support for the integrated sensors in SiS5595 South Bridges. @@ -442,6 +465,18 @@ config SENSORS_SIS5595 This driver can also be built as a module. If so, the module will be called sis5595. +config SENSORS_DME1737 + tristate "SMSC DME1737 and compatibles" + depends on I2C && EXPERIMENTAL + select HWMON_VID + help + If you say yes here you get support for the hardware monitoring + and fan control features of the SMSC DME1737 (and compatibles + like the Asus A8000) Super-I/O chip. + + This driver can also be built as a module. If so, the module + will be called dme1737. + config SENSORS_SMSC47M1 tristate "SMSC LPC47M10x and compatibles" help @@ -485,10 +520,19 @@ config SENSORS_SMSC47B397 This driver can also be built as a module. If so, the module will be called smsc47b397. +config SENSORS_THMC50 + tristate "Texas Instruments THMC50 / Analog Devices ADM1022" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for Texas Instruments THMC50 + sensor chips and clones: the Analog Devices ADM1022. + + This driver can also be built as a module. If so, the module + will be called thmc50. + config SENSORS_VIA686A tristate "VIA686A" - depends on I2C && PCI - select I2C_ISA + depends on PCI help If you say yes here you get support for the integrated sensors in Via 686A/B South Bridges. @@ -509,9 +553,8 @@ config SENSORS_VT1211 config SENSORS_VT8231 tristate "VIA VT8231" - depends on I2C && PCI && EXPERIMENTAL + depends on PCI select HWMON_VID - select I2C_ISA help If you say yes here then you get support for the integrated sensors in the VIA VT8231 device. @@ -584,17 +627,16 @@ config SENSORS_W83627HF will be called w83627hf. config SENSORS_W83627EHF - tristate "Winbond W83627EHF" - depends on I2C && EXPERIMENTAL - select I2C_ISA + tristate "Winbond W83627EHF/DHG" + select HWMON_VID help - If you say yes here you get preliminary support for the hardware + If you say yes here you get support for the hardware monitoring functionality of the Winbond W83627EHF Super-I/O chip. - Only fan and temperature inputs are supported at the moment, while - the chip does much more than that. This driver also supports the W83627EHG, which is the lead-free - version of the W83627EHF. + version of the W83627EHF, and the W83627DHG, which is a similar + chip suited for specific Intel processors that use PECI such as + the Core 2 Duo. This driver can also be built as a module. If so, the module will be called w83627ehf. diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index cfaf338919dd..d04f90031ebf 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_SENSORS_W83781D) += w83781d.o obj-$(CONFIG_SENSORS_W83791D) += w83791d.o obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o +obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o obj-$(CONFIG_SENSORS_AD7418) += ad7418.o obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o @@ -25,6 +26,7 @@ obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o obj-$(CONFIG_SENSORS_AMS) += ams/ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o +obj-$(CONFIG_SENSORS_DME1737) += dme1737.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_FSCHER) += fscher.o @@ -45,6 +47,7 @@ obj-$(CONFIG_SENSORS_LM85) += lm85.o obj-$(CONFIG_SENSORS_LM87) += lm87.o obj-$(CONFIG_SENSORS_LM90) += lm90.o obj-$(CONFIG_SENSORS_LM92) += lm92.o +obj-$(CONFIG_SENSORS_LM93) += lm93.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o obj-$(CONFIG_SENSORS_MAX6650) += max6650.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o @@ -53,6 +56,7 @@ obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o +obj-$(CONFIG_SENSORS_THMC50) += thmc50.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_VT1211) += vt1211.o obj-$(CONFIG_SENSORS_VT8231) += vt8231.o diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index bede4d990ea6..d575ee958de5 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c @@ -16,9 +16,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - This driver supports the sensor part of the custom Abit uGuru chip found - on Abit uGuru motherboards. Note: because of lack of specs the CPU / RAM / - etc voltage & frequency control is not supported! + This driver supports the sensor part of the first and second revision of + the custom Abit uGuru chip found on Abit uGuru motherboards. Note: because + of lack of specs the CPU/RAM voltage & frequency control is not supported! */ #include <linux/module.h> #include <linux/sched.h> @@ -31,6 +31,7 @@ #include <linux/platform_device.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> +#include <linux/dmi.h> #include <asm/io.h> /* Banks */ @@ -418,7 +419,7 @@ static int __devinit abituguru_detect_bank1_sensor_type(struct abituguru_data *data, u8 sensor_addr) { - u8 val, buf[3]; + u8 val, test_flag, buf[3]; int i, ret = -ENODEV; /* error is the most common used retval :| */ /* If overriden by the user return the user selected type */ @@ -436,7 +437,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, return -ENODEV; /* Test val is sane / usable for sensor type detection. */ - if ((val < 10u) || (val > 240u)) { + if ((val < 10u) || (val > 250u)) { printk(KERN_WARNING ABIT_UGURU_NAME ": bank1-sensor: %d reading (%d) too close to limits, " "unable to determine sensor type, skipping sensor\n", @@ -449,10 +450,20 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr); /* Volt sensor test, enable volt low alarm, set min value ridicously - high. If its a volt sensor this should always give us an alarm. */ - buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE; - buf[1] = 245; - buf[2] = 250; + high, or vica versa if the reading is very high. If its a volt + sensor this should always give us an alarm. */ + if (val <= 240u) { + buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE; + buf[1] = 245; + buf[2] = 250; + test_flag = ABIT_UGURU_VOLT_LOW_ALARM_FLAG; + } else { + buf[0] = ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE; + buf[1] = 5; + buf[2] = 10; + test_flag = ABIT_UGURU_VOLT_HIGH_ALARM_FLAG; + } + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, buf, 3) != 3) goto abituguru_detect_bank1_sensor_type_exit; @@ -469,13 +480,13 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, sensor_addr, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) goto abituguru_detect_bank1_sensor_type_exit; - if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) { + if (buf[0] & test_flag) { ABIT_UGURU_DEBUG(2, " found volt sensor\n"); ret = ABIT_UGURU_IN_SENSOR; goto abituguru_detect_bank1_sensor_type_exit; } else ABIT_UGURU_DEBUG(2, " alarm raised during volt " - "sensor test, but volt low flag not set\n"); + "sensor test, but volt range flag not set\n"); } else ABIT_UGURU_DEBUG(2, " alarm not raised during volt sensor " "test\n"); @@ -1287,6 +1298,7 @@ abituguru_probe_error: for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) device_remove_file(&pdev->dev, &abituguru_sysfs_attr[i].dev_attr); + platform_set_drvdata(pdev, NULL); kfree(data); return res; } @@ -1296,13 +1308,13 @@ static int __devexit abituguru_remove(struct platform_device *pdev) int i; struct abituguru_data *data = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); hwmon_device_unregister(data->class_dev); for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) device_remove_file(&pdev->dev, &abituguru_sysfs_attr[i].dev_attr); + platform_set_drvdata(pdev, NULL); kfree(data); return 0; @@ -1436,6 +1448,15 @@ static int __init abituguru_init(void) int address, err; struct resource res = { .flags = IORESOURCE_IO }; +#ifdef CONFIG_DMI + char *board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); + + /* safety check, refuse to load on non Abit motherboards */ + if (!force && (!board_vendor || + strcmp(board_vendor, "http://www.abit.com.tw/"))) + return -ENODEV; +#endif + address = abituguru_detect(); if (address < 0) return address; diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c index 6db973739725..a112a03e8f29 100644 --- a/drivers/hwmon/ams/ams-core.c +++ b/drivers/hwmon/ams/ams-core.c @@ -23,7 +23,6 @@ #include <linux/types.h> #include <linux/errno.h> #include <linux/init.h> -#include <linux/module.h> #include <asm/pmac_pfunc.h> #include <asm/of_platform.h> diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index fd1281f42209..941729a131f5 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -79,11 +79,15 @@ /* * Temperature sensors keys (sp78 - 2 bytes). - * First set for Macbook(Pro), second for Macmini. */ static const char* temperature_sensors_sets[][13] = { +/* Set 0: Macbook Pro */ { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H", "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL }, +/* Set 1: Macbook set */ + { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S", + "Th1H", "Ts0P", NULL }, +/* Set 2: Macmini set */ { "TC0D", "TC0P", NULL } }; @@ -1150,10 +1154,10 @@ static void applesmc_release_accelerometer(void) static __initdata struct dmi_match_data applesmc_dmi_data[] = { /* MacBook Pro: accelerometer, backlight and temperature set 0 */ { .accelerometer = 1, .light = 1, .temperature_set = 0 }, -/* MacBook: accelerometer and temperature set 0 */ - { .accelerometer = 1, .light = 0, .temperature_set = 0 }, -/* MacBook: temperature set 1 */ - { .accelerometer = 0, .light = 0, .temperature_set = 1 } +/* MacBook: accelerometer and temperature set 1 */ + { .accelerometer = 1, .light = 0, .temperature_set = 1 }, +/* MacMini: temperature set 2 */ + { .accelerometer = 0, .light = 0, .temperature_set = 2 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 6d54c8caed79..7c1795225b06 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -318,7 +318,7 @@ exit: } #ifdef CONFIG_HOTPLUG_CPU -void coretemp_device_remove(unsigned int cpu) +static void coretemp_device_remove(unsigned int cpu) { struct pdev_entry *p, *n; mutex_lock(&pdev_list_mutex); diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index d5ac422d73b2..1212d6b7f316 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c @@ -27,6 +27,7 @@ #include <linux/jiffies.h> #include <linux/i2c.h> #include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> #include <linux/sysfs.h> @@ -52,9 +53,11 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low") #define DS1621_REG_CONFIG_DONE 0x80 /* The DS1621 registers */ -#define DS1621_REG_TEMP 0xAA /* word, RO */ -#define DS1621_REG_TEMP_MIN 0xA2 /* word, RW */ -#define DS1621_REG_TEMP_MAX 0xA1 /* word, RW */ +static const u8 DS1621_REG_TEMP[3] = { + 0xAA, /* input, word, RO */ + 0xA2, /* min, word, RW */ + 0xA1, /* max, word, RW */ +}; #define DS1621_REG_CONF 0xAC /* byte, RW */ #define DS1621_COM_START 0xEE /* no data */ #define DS1621_COM_STOP 0x22 /* no data */ @@ -63,10 +66,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low") #define DS1621_ALARM_TEMP_HIGH 0x40 #define DS1621_ALARM_TEMP_LOW 0x20 -/* Conversions. Rounding and limit checking is only done on the TO_REG - variants. Note that you should be a bit careful with which arguments - these macros are called: arguments may be evaluated more than once. - Fixing this is just not worth it. */ +/* Conversions */ #define ALARMS_FROM_REG(val) ((val) & \ (DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW)) @@ -78,7 +78,7 @@ struct ds1621_data { char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ - u16 temp, temp_min, temp_max; /* Register values, word */ + u16 temp[3]; /* Register values, word */ u8 conf; /* Register encoding, combined */ }; @@ -101,7 +101,7 @@ static struct i2c_driver ds1621_driver = { /* All registers are word-sized, except for the configuration register. DS1621 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ + the SMBus standard. */ static int ds1621_read_value(struct i2c_client *client, u8 reg) { if (reg == DS1621_REG_CONF) @@ -110,9 +110,6 @@ static int ds1621_read_value(struct i2c_client *client, u8 reg) return swab16(i2c_smbus_read_word_data(client, reg)); } -/* All registers are word-sized, except for the configuration register. - DS1621 uses a high-byte first convention, which is exactly opposite to - the usual practice. */ static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value) { if (reg == DS1621_REG_CONF) @@ -139,50 +136,61 @@ static void ds1621_init_client(struct i2c_client *client) i2c_smbus_write_byte(client, DS1621_COM_START); } -#define show(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct ds1621_data *data = ds1621_update_client(dev); \ - return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \ +static ssize_t show_temp(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ds1621_data *data = ds1621_update_client(dev); + return sprintf(buf, "%d\n", + LM75_TEMP_FROM_REG(data->temp[attr->index])); } -show(temp); -show(temp_min); -show(temp_max); - -#define set_temp(suffix, value, reg) \ -static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \ - size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct ds1621_data *data = ds1621_update_client(dev); \ - u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \ - \ - mutex_lock(&data->update_lock); \ - data->value = val; \ - ds1621_write_value(client, reg, data->value); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} +static ssize_t set_temp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct ds1621_data *data = ds1621_update_client(dev); + u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); -set_temp(min, temp_min, DS1621_REG_TEMP_MIN); -set_temp(max, temp_max, DS1621_REG_TEMP_MAX); + mutex_lock(&data->update_lock); + data->temp[attr->index] = val; + ds1621_write_value(client, DS1621_REG_TEMP[attr->index], + data->temp[attr->index]); + mutex_unlock(&data->update_lock); + return count; +} -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_alarms(struct device *dev, struct device_attribute *da, + char *buf) { struct ds1621_data *data = ds1621_update_client(dev); return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf)); } +static ssize_t show_alarm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct ds1621_data *data = ds1621_update_client(dev); + return sprintf(buf, "%d\n", !!(data->conf & attr->index)); +} + static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); -static DEVICE_ATTR(temp1_input, S_IRUGO , show_temp, NULL); -static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min); -static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, + DS1621_ALARM_TEMP_LOW); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, + DS1621_ALARM_TEMP_HIGH); static struct attribute *ds1621_attributes[] = { - &dev_attr_temp1_input.attr, - &dev_attr_temp1_min.attr, - &dev_attr_temp1_max.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, &dev_attr_alarms.attr, NULL }; @@ -204,9 +212,9 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address, int kind) { int conf, temp; - struct i2c_client *new_client; + struct i2c_client *client; struct ds1621_data *data; - int err = 0; + int i, err = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA @@ -221,55 +229,44 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address, goto exit; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &ds1621_driver; - new_client->flags = 0; - + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &ds1621_driver; /* Now, we do the remaining detection. It is lousy. */ if (kind < 0) { /* The NVB bit should be low if no EEPROM write has been requested during the latest 10ms, which is highly improbable in our case. */ - conf = ds1621_read_value(new_client, DS1621_REG_CONF); + conf = ds1621_read_value(client, DS1621_REG_CONF); if (conf & DS1621_REG_CONFIG_NVB) goto exit_free; /* The 7 lowest bits of a temperature should always be 0. */ - temp = ds1621_read_value(new_client, DS1621_REG_TEMP); - if (temp & 0x007f) - goto exit_free; - temp = ds1621_read_value(new_client, DS1621_REG_TEMP_MIN); - if (temp & 0x007f) - goto exit_free; - temp = ds1621_read_value(new_client, DS1621_REG_TEMP_MAX); - if (temp & 0x007f) - goto exit_free; + for (i = 0; i < ARRAY_SIZE(data->temp); i++) { + temp = ds1621_read_value(client, DS1621_REG_TEMP[i]); + if (temp & 0x007f) + goto exit_free; + } } - /* Determine the chip type - only one kind supported! */ - if (kind <= 0) - kind = ds1621; - /* Fill in remaining client fields and put it into the global list */ - strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE); - data->valid = 0; + strlcpy(client->name, "ds1621", I2C_NAME_SIZE); mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto exit_free; /* Initialize the DS1621 chip */ - ds1621_init_client(new_client); + ds1621_init_client(client); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &ds1621_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); + data->class_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto exit_remove_files; @@ -278,9 +275,9 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address, return 0; exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &ds1621_group); + sysfs_remove_group(&client->dev.kobj, &ds1621_group); exit_detach: - i2c_detach_client(new_client); + i2c_detach_client(client); exit_free: kfree(data); exit: @@ -314,23 +311,21 @@ static struct ds1621_data *ds1621_update_client(struct device *dev) if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { + int i; dev_dbg(&client->dev, "Starting ds1621 update\n"); data->conf = ds1621_read_value(client, DS1621_REG_CONF); - data->temp = ds1621_read_value(client, DS1621_REG_TEMP); - - data->temp_min = ds1621_read_value(client, - DS1621_REG_TEMP_MIN); - data->temp_max = ds1621_read_value(client, - DS1621_REG_TEMP_MAX); + for (i = 0; i < ARRAY_SIZE(data->temp); i++) + data->temp[i] = ds1621_read_value(client, + DS1621_REG_TEMP[i]); /* reset alarms if necessary */ new_conf = data->conf; - if (data->temp > data->temp_min) + if (data->temp[0] > data->temp[1]) /* input > min */ new_conf &= ~DS1621_ALARM_TEMP_LOW; - if (data->temp < data->temp_max) + if (data->temp[0] < data->temp[2]) /* input < max */ new_conf &= ~DS1621_ALARM_TEMP_HIGH; if (data->conf != new_conf) ds1621_write_value(client, DS1621_REG_CONF, diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index cdbe309b8fc4..6f60715f34f8 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -127,6 +127,13 @@ superio_exit(int base) #define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr)) #define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr)) #define F71805F_REG_TEMP_MODE 0x01 +/* pwm/fan pwmnr from 0 to 2, auto point apnr from 0 to 2 */ +/* map Fintek numbers to our numbers as follows: 9->0, 5->1, 1->2 */ +#define F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr) \ + (0xA0 + 0x10 * (pwmnr) + (2 - (apnr))) +#define F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr) \ + (0xA4 + 0x10 * (pwmnr) + \ + 2 * (2 - (apnr))) #define F71805F_REG_START 0x00 /* status nr from 0 to 2 */ @@ -144,6 +151,11 @@ superio_exit(int base) * Data structures and manipulation thereof */ +struct f71805f_auto_point { + u8 temp[3]; + u16 fan[3]; +}; + struct f71805f_data { unsigned short addr; const char *name; @@ -170,6 +182,7 @@ struct f71805f_data { u8 temp_hyst[3]; u8 temp_mode; unsigned long alarms; + struct f71805f_auto_point auto_points[3]; }; struct f71805f_sio_data { @@ -312,7 +325,7 @@ static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) static struct f71805f_data *f71805f_update_device(struct device *dev) { struct f71805f_data *data = dev_get_drvdata(dev); - int nr; + int nr, apnr; mutex_lock(&data->update_lock); @@ -342,6 +355,18 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) F71805F_REG_TEMP_HYST(nr)); } data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE); + for (nr = 0; nr < 3; nr++) { + for (apnr = 0; apnr < 3; apnr++) { + data->auto_points[nr].temp[apnr] = + f71805f_read8(data, + F71805F_REG_PWM_AUTO_POINT_TEMP(nr, + apnr)); + data->auto_points[nr].fan[apnr] = + f71805f_read16(data, + F71805F_REG_PWM_AUTO_POINT_FAN(nr, + apnr)); + } + } data->last_limits = jiffies; } @@ -705,6 +730,70 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute return count; } +static ssize_t show_pwm_auto_point_temp(struct device *dev, + struct device_attribute *devattr, + char* buf) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + int pwmnr = attr->nr; + int apnr = attr->index; + + return sprintf(buf, "%ld\n", + temp_from_reg(data->auto_points[pwmnr].temp[apnr])); +} + +static ssize_t set_pwm_auto_point_temp(struct device *dev, + struct device_attribute *devattr, + const char* buf, size_t count) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + int pwmnr = attr->nr; + int apnr = attr->index; + unsigned long val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->auto_points[pwmnr].temp[apnr] = temp_to_reg(val); + f71805f_write8(data, F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr), + data->auto_points[pwmnr].temp[apnr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_pwm_auto_point_fan(struct device *dev, + struct device_attribute *devattr, + char* buf) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + int pwmnr = attr->nr; + int apnr = attr->index; + + return sprintf(buf, "%ld\n", + fan_from_reg(data->auto_points[pwmnr].fan[apnr])); +} + +static ssize_t set_pwm_auto_point_fan(struct device *dev, + struct device_attribute *devattr, + const char* buf, size_t count) +{ + struct f71805f_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + int pwmnr = attr->nr; + int apnr = attr->index; + unsigned long val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->auto_points[pwmnr].fan[apnr] = fan_to_reg(val); + f71805f_write16(data, F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr), + data->auto_points[pwmnr].fan[apnr]); + mutex_unlock(&data->update_lock); + + return count; +} + static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -932,6 +1021,63 @@ static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq, 2); static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR, + show_pwm_auto_point_temp, set_pwm_auto_point_temp, + 0, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_fan, S_IRUGO | S_IWUSR, + show_pwm_auto_point_fan, set_pwm_auto_point_fan, + 0, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR, + show_pwm_auto_point_temp, set_pwm_auto_point_temp, + 0, 1); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_fan, S_IRUGO | S_IWUSR, + show_pwm_auto_point_fan, set_pwm_auto_point_fan, + 0, 1); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR, + show_pwm_auto_point_temp, set_pwm_auto_point_temp, + 0, 2); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_fan, S_IRUGO | S_IWUSR, + show_pwm_auto_point_fan, set_pwm_auto_point_fan, + 0, 2); + +static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR, + show_pwm_auto_point_temp, set_pwm_auto_point_temp, + 1, 0); +static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_fan, S_IRUGO | S_IWUSR, + show_pwm_auto_point_fan, set_pwm_auto_point_fan, + 1, 0); +static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR, + show_pwm_auto_point_temp, set_pwm_auto_point_temp, + 1, 1); +static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_fan, S_IRUGO | S_IWUSR, + show_pwm_auto_point_fan, set_pwm_auto_point_fan, + 1, 1); +static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR, + show_pwm_auto_point_temp, set_pwm_auto_point_temp, + 1, 2); +static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_fan, S_IRUGO | S_IWUSR, + show_pwm_auto_point_fan, set_pwm_auto_point_fan, + 1, 2); + +static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR, + show_pwm_auto_point_temp, set_pwm_auto_point_temp, + 2, 0); +static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_fan, S_IRUGO | S_IWUSR, + show_pwm_auto_point_fan, set_pwm_auto_point_fan, + 2, 0); +static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR, + show_pwm_auto_point_temp, set_pwm_auto_point_temp, + 2, 1); +static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_fan, S_IRUGO | S_IWUSR, + show_pwm_auto_point_fan, set_pwm_auto_point_fan, + 2, 1); +static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR, + show_pwm_auto_point_temp, set_pwm_auto_point_temp, + 2, 2); +static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_fan, S_IRUGO | S_IWUSR, + show_pwm_auto_point_fan, set_pwm_auto_point_fan, + 2, 2); + static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); @@ -1014,6 +1160,25 @@ static struct attribute *f71805f_attributes[] = { &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, &sensor_dev_attr_temp3_type.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point1_fan.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point2_fan.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point3_fan.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point1_fan.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point2_fan.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point3_fan.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point1_fan.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point2_fan.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point3_fan.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, &sensor_dev_attr_in1_alarm.dev_attr.attr, &sensor_dev_attr_in2_alarm.dev_attr.attr, @@ -1242,12 +1407,12 @@ static int __devexit f71805f_remove(struct platform_device *pdev) struct resource *res; int i; - platform_set_drvdata(pdev, NULL); hwmon_device_unregister(data->class_dev); sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); 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); + platform_set_drvdata(pdev, NULL); kfree(data); res = platform_get_resource(pdev, IORESOURCE_IO, 0); @@ -1290,15 +1455,12 @@ static int __init f71805f_device_add(unsigned short address, goto exit_device_put; } - pdev->dev.platform_data = kmalloc(sizeof(struct f71805f_sio_data), - GFP_KERNEL); - if (!pdev->dev.platform_data) { - err = -ENOMEM; + err = platform_device_add_data(pdev, sio_data, + sizeof(struct f71805f_sio_data)); + if (err) { printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); goto exit_device_put; } - memcpy(pdev->dev.platform_data, sio_data, - sizeof(struct f71805f_sio_data)); err = platform_device_add(pdev); if (err) { diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c index 19717752cfca..b34b546c68b8 100644 --- a/drivers/hwmon/fscher.c +++ b/drivers/hwmon/fscher.c @@ -441,6 +441,8 @@ static struct fscher_data *fscher_update_device(struct device *dev) data->watchdog[2] = fscher_read_value(client, FSCHER_REG_WDOG_CONTROL); data->global_event = fscher_read_value(client, FSCHER_REG_EVENT_STATE); + data->global_control = fscher_read_value(client, + FSCHER_REG_CONTROL); data->last_updated = jiffies; data->valid = 1; @@ -599,7 +601,7 @@ static ssize_t set_control(struct i2c_client *client, struct fscher_data *data, unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; mutex_lock(&data->update_lock); - data->global_control &= ~v; + data->global_control = v; fscher_write_value(client, reg, v); mutex_unlock(&data->update_lock); return count; diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 62afc63708a5..d75dba9b810b 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -6,6 +6,7 @@ IT8712F Super I/O chip w/LPC interface IT8716F Super I/O chip w/LPC interface IT8718F Super I/O chip w/LPC interface + IT8726F Super I/O chip w/LPC interface Sis950 A clone of the IT8705F Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> @@ -30,8 +31,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/jiffies.h> -#include <linux/i2c.h> -#include <linux/i2c-isa.h> +#include <linux/platform_device.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/hwmon-vid.h> @@ -40,10 +40,12 @@ #include <linux/sysfs.h> #include <asm/io.h> +#define DRVNAME "it87" -static unsigned short isa_address; enum chips { it87, it8712, it8716, it8718 }; +static struct platform_device *pdev; + #define REG 0x2e /* The register to read/write */ #define DEV 0x07 /* Register: Logical device select */ #define VAL 0x2f /* The value to read/write */ @@ -97,6 +99,7 @@ superio_exit(void) #define IT8705F_DEVID 0x8705 #define IT8716F_DEVID 0x8716 #define IT8718F_DEVID 0x8718 +#define IT8726F_DEVID 0x8726 #define IT87_ACT_REG 0x30 #define IT87_BASE_REG 0x60 @@ -110,10 +113,6 @@ static int update_vbat; /* Not all BIOSes properly configure the PWM registers */ static int fix_pwm_polarity; -/* Values read from Super-I/O config space */ -static u16 chip_type; -static u8 vid_value; - /* Many IT87 constants specified below */ /* Length of ISA address segment */ @@ -214,13 +213,20 @@ static const unsigned int pwm_freq[8] = { }; +struct it87_sio_data { + enum chips type; + /* Values read from Super-I/O config space */ + u8 vid_value; +}; + /* For each registered chip, we need to keep some data in memory. The structure is dynamically allocated. */ struct it87_data { - struct i2c_client client; struct class_device *class_dev; enum chips type; + unsigned short addr; + const char *name; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -245,26 +251,25 @@ struct it87_data { }; -static int it87_detect(struct i2c_adapter *adapter); -static int it87_detach_client(struct i2c_client *client); +static int it87_probe(struct platform_device *pdev); +static int __devexit it87_remove(struct platform_device *pdev); -static int it87_read_value(struct i2c_client *client, u8 reg); -static void it87_write_value(struct i2c_client *client, u8 reg, u8 value); +static int it87_read_value(struct it87_data *data, u8 reg); +static void it87_write_value(struct it87_data *data, u8 reg, u8 value); static struct it87_data *it87_update_device(struct device *dev); -static int it87_check_pwm(struct i2c_client *client); -static void it87_init_client(struct i2c_client *client, struct it87_data *data); +static int it87_check_pwm(struct device *dev); +static void it87_init_device(struct platform_device *pdev); -static struct i2c_driver it87_isa_driver = { +static struct platform_driver it87_driver = { .driver = { .owner = THIS_MODULE, - .name = "it87-isa", + .name = DRVNAME, }, - .attach_adapter = it87_detect, - .detach_client = it87_detach_client, + .probe = it87_probe, + .remove = __devexit_p(it87_remove), }; - static ssize_t show_in(struct device *dev, struct device_attribute *attr, char *buf) { @@ -301,13 +306,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val); - it87_write_value(client, IT87_REG_VIN_MIN(nr), + it87_write_value(data, IT87_REG_VIN_MIN(nr), data->in_min[nr]); mutex_unlock(&data->update_lock); return count; @@ -318,13 +322,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val); - it87_write_value(client, IT87_REG_VIN_MAX(nr), + it87_write_value(data, IT87_REG_VIN_MAX(nr), data->in_max[nr]); mutex_unlock(&data->update_lock); return count; @@ -392,13 +395,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_high[nr] = TEMP_TO_REG(val); - it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); + it87_write_value(data, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); mutex_unlock(&data->update_lock); return count; } @@ -408,13 +410,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_low[nr] = TEMP_TO_REG(val); - it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); + it87_write_value(data, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); mutex_unlock(&data->update_lock); return count; } @@ -451,8 +452,7 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -468,7 +468,7 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, mutex_unlock(&data->update_lock); return -EINVAL; } - it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); + it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); mutex_unlock(&data->update_lock); return count; } @@ -542,13 +542,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); u8 reg; mutex_lock(&data->update_lock); - reg = it87_read_value(client, IT87_REG_FAN_DIV); + reg = it87_read_value(data, IT87_REG_FAN_DIV); switch (nr) { case 0: data->fan_div[nr] = reg & 0x07; break; case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; @@ -556,7 +555,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, } data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); + it87_write_value(data, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; } @@ -566,14 +565,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); int min; u8 old; mutex_lock(&data->update_lock); - old = it87_read_value(client, IT87_REG_FAN_DIV); + old = it87_read_value(data, IT87_REG_FAN_DIV); /* Save fan min limit */ min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -594,11 +592,11 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, val |= (data->fan_div[1] & 0x07) << 3; if (data->fan_div[2] == 3) val |= 0x1 << 6; - it87_write_value(client, IT87_REG_FAN_DIV, val); + it87_write_value(data, IT87_REG_FAN_DIV, val); /* Restore fan min limit */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); + it87_write_value(data, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; @@ -609,8 +607,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -618,17 +615,17 @@ static ssize_t set_pwm_enable(struct device *dev, if (val == 0) { int tmp; /* make sure the fan is on when in on/off mode */ - tmp = it87_read_value(client, IT87_REG_FAN_CTL); - it87_write_value(client, IT87_REG_FAN_CTL, tmp | (1 << nr)); + tmp = it87_read_value(data, IT87_REG_FAN_CTL); + it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); /* set on/off mode */ data->fan_main_ctrl &= ~(1 << nr); - it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); + it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); } else if (val == 1) { /* set SmartGuardian mode */ data->fan_main_ctrl |= (1 << nr); - it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); + it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); /* set saved pwm value, clear FAN_CTLX PWM mode bit */ - it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); + it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); } else { mutex_unlock(&data->update_lock); return -EINVAL; @@ -643,8 +640,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); if (val < 0 || val > 255) @@ -653,15 +649,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->manual_pwm_ctl[nr] = val; if (data->fan_main_ctrl & (1 << nr)) - it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); + it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); mutex_unlock(&data->update_lock); return count; } static ssize_t set_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); int i; @@ -672,9 +667,9 @@ static ssize_t set_pwm_freq(struct device *dev, } mutex_lock(&data->update_lock); - data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL) & 0x8f; + data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f; data->fan_ctl |= i << 4; - it87_write_value(client, IT87_REG_FAN_CTL, data->fan_ctl); + it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl); mutex_unlock(&data->update_lock); return count; @@ -729,15 +724,14 @@ static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan_min[nr] = FAN16_TO_REG(val); - it87_write_value(client, IT87_REG_FAN_MIN(nr), + it87_write_value(data, IT87_REG_FAN_MIN(nr), data->fan_min[nr] & 0xff); - it87_write_value(client, IT87_REG_FANX_MIN(nr), + it87_write_value(data, IT87_REG_FANX_MIN(nr), data->fan_min[nr] >> 8); mutex_unlock(&data->update_lock); return count; @@ -775,8 +769,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 it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); u32 val; val = simple_strtoul(buf, NULL, 10); @@ -794,6 +787,14 @@ show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); +static ssize_t show_name(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct it87_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", data->name); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + static struct attribute *it87_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -835,6 +836,7 @@ static struct attribute *it87_attributes[] = { &sensor_dev_attr_temp3_type.dev_attr.attr, &dev_attr_alarms.attr, + &dev_attr_name.attr, NULL }; @@ -877,17 +879,36 @@ static const struct attribute_group it87_group_opt = { }; /* SuperIO detection - will change isa_address if a chip is found */ -static int __init it87_find(unsigned short *address) +static int __init it87_find(unsigned short *address, + struct it87_sio_data *sio_data) { int err = -ENODEV; + u16 chip_type; superio_enter(); chip_type = superio_inw(DEVID); - if (chip_type != IT8712F_DEVID - && chip_type != IT8716F_DEVID - && chip_type != IT8718F_DEVID - && chip_type != IT8705F_DEVID) - goto exit; + + switch (chip_type) { + case IT8705F_DEVID: + sio_data->type = it87; + break; + case IT8712F_DEVID: + sio_data->type = it8712; + break; + case IT8716F_DEVID: + case IT8726F_DEVID: + sio_data->type = it8716; + break; + case IT8718F_DEVID: + sio_data->type = it8718; + break; + case 0xffff: /* No device at all */ + goto exit; + default: + pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n", + chip_type); + goto exit; + } superio_select(PME); if (!(superio_inb(IT87_ACT_REG) & 0x01)) { @@ -911,7 +932,7 @@ static int __init it87_find(unsigned short *address) superio_select(GPIO); if (chip_type == it8718) - vid_value = superio_inb(IT87_SIO_VID_REG); + sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); reg = superio_inb(IT87_SIO_PINX2_REG); if (reg & (1 << 0)) @@ -925,18 +946,26 @@ exit: return err; } -/* This function is called by i2c_probe */ -static int it87_detect(struct i2c_adapter *adapter) +static int __devinit it87_probe(struct platform_device *pdev) { - struct i2c_client *new_client; struct it87_data *data; + struct resource *res; + struct device *dev = &pdev->dev; + struct it87_sio_data *sio_data = dev->platform_data; int err = 0; - const char *name; int enable_pwm_interface; - - /* Reserve the ISA region */ - if (!request_region(isa_address, IT87_EXTENT, - it87_isa_driver.driver.name)){ + static const char *names[] = { + "it87", + "it8712", + "it8716", + "it8718", + }; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, IT87_EXTENT, DRVNAME)) { + dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)res->start, + (unsigned long)(res->start + IT87_EXTENT - 1)); err = -EBUSY; goto ERROR0; } @@ -946,129 +975,104 @@ static int it87_detect(struct i2c_adapter *adapter) goto ERROR1; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = isa_address; - new_client->adapter = adapter; - new_client->driver = &it87_isa_driver; + data->addr = res->start; + data->type = sio_data->type; + data->name = names[sio_data->type]; /* Now, we do the remaining detection. */ - if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80) - || it87_read_value(new_client, IT87_REG_CHIPID) != 0x90) { + if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) + || it87_read_value(data, IT87_REG_CHIPID) != 0x90) { err = -ENODEV; goto ERROR2; } - /* Determine the chip type. */ - switch (chip_type) { - case IT8712F_DEVID: - data->type = it8712; - name = "it8712"; - break; - case IT8716F_DEVID: - data->type = it8716; - name = "it8716"; - break; - case IT8718F_DEVID: - data->type = it8718; - name = "it8718"; - break; - default: - data->type = it87; - name = "it87"; - } + platform_set_drvdata(pdev, data); - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, name, I2C_NAME_SIZE); mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto ERROR2; - /* Check PWM configuration */ - enable_pwm_interface = it87_check_pwm(new_client); + enable_pwm_interface = it87_check_pwm(dev); /* Initialize the IT87 chip */ - it87_init_client(new_client, data); + it87_init_device(pdev); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &it87_group))) - goto ERROR3; + if ((err = sysfs_create_group(&dev->kobj, &it87_group))) + goto ERROR2; /* Do not create fan files for disabled fans */ if (data->type == it8716 || data->type == it8718) { /* 16-bit tachometers */ if (data->has_fan & (1 << 0)) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(dev, &sensor_dev_attr_fan1_input16.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_fan1_min16.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 1)) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(dev, &sensor_dev_attr_fan2_input16.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_fan2_min16.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 2)) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(dev, &sensor_dev_attr_fan3_input16.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_fan3_min16.dev_attr))) goto ERROR4; } } else { /* 8-bit tachometers with clock divider */ if (data->has_fan & (1 << 0)) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(dev, &sensor_dev_attr_fan1_input.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_fan1_min.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_fan1_div.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 1)) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(dev, &sensor_dev_attr_fan2_input.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_fan2_min.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_fan2_div.dev_attr))) goto ERROR4; } if (data->has_fan & (1 << 2)) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(dev, &sensor_dev_attr_fan3_input.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_fan3_min.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_fan3_div.dev_attr))) goto ERROR4; } } if (enable_pwm_interface) { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(dev, &sensor_dev_attr_pwm1_enable.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_pwm2_enable.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_pwm3_enable.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_pwm1.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_pwm2.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &sensor_dev_attr_pwm3.dev_attr)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &dev_attr_pwm1_freq)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &dev_attr_pwm2_freq)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &dev_attr_pwm3_freq))) goto ERROR4; } @@ -1077,15 +1081,15 @@ static int it87_detect(struct i2c_adapter *adapter) || data->type == it8718) { data->vrm = vid_which_vrm(); /* VID reading from Super-I/O config space if available */ - data->vid = vid_value; - if ((err = device_create_file(&new_client->dev, + data->vid = sio_data->vid_value; + if ((err = device_create_file(dev, &dev_attr_vrm)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(dev, &dev_attr_cpu0_vid))) 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; @@ -1094,31 +1098,27 @@ static int it87_detect(struct i2c_adapter *adapter) return 0; ERROR4: - sysfs_remove_group(&new_client->dev.kobj, &it87_group); - sysfs_remove_group(&new_client->dev.kobj, &it87_group_opt); -ERROR3: - i2c_detach_client(new_client); + sysfs_remove_group(&dev->kobj, &it87_group); + sysfs_remove_group(&dev->kobj, &it87_group_opt); ERROR2: + platform_set_drvdata(pdev, NULL); kfree(data); ERROR1: - release_region(isa_address, IT87_EXTENT); + release_region(res->start, IT87_EXTENT); ERROR0: return err; } -static int it87_detach_client(struct i2c_client *client) +static int __devexit it87_remove(struct platform_device *pdev) { - struct it87_data *data = i2c_get_clientdata(client); - int err; + struct it87_data *data = platform_get_drvdata(pdev); hwmon_device_unregister(data->class_dev); - sysfs_remove_group(&client->dev.kobj, &it87_group); - sysfs_remove_group(&client->dev.kobj, &it87_group_opt); + sysfs_remove_group(&pdev->dev.kobj, &it87_group); + sysfs_remove_group(&pdev->dev.kobj, &it87_group_opt); - if ((err = i2c_detach_client(client))) - return err; - - release_region(client->addr, IT87_EXTENT); + release_region(data->addr, IT87_EXTENT); + platform_set_drvdata(pdev, NULL); kfree(data); return 0; @@ -1127,28 +1127,29 @@ static int it87_detach_client(struct i2c_client *client) /* Must be called with data->update_lock held, except during initialization. We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, would slow down the IT87 access and should not be necessary. */ -static int it87_read_value(struct i2c_client *client, u8 reg) +static int it87_read_value(struct it87_data *data, u8 reg) { - outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); - return inb_p(client->addr + IT87_DATA_REG_OFFSET); + outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); + return inb_p(data->addr + IT87_DATA_REG_OFFSET); } /* Must be called with data->update_lock held, except during initialization. We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, would slow down the IT87 access and should not be necessary. */ -static void it87_write_value(struct i2c_client *client, u8 reg, u8 value) +static void it87_write_value(struct it87_data *data, u8 reg, u8 value) { - outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); - outb_p(value, client->addr + IT87_DATA_REG_OFFSET); + outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); + outb_p(value, data->addr + IT87_DATA_REG_OFFSET); } /* Return 1 if and only if the PWM interface is safe to use */ -static int it87_check_pwm(struct i2c_client *client) +static int __devinit it87_check_pwm(struct device *dev) { + struct it87_data *data = dev_get_drvdata(dev); /* Some BIOSes fail to correctly configure the IT87 fans. All fans off * and polarity set to active low is sign that this is the case so we * disable pwm control to protect the user. */ - int tmp = it87_read_value(client, IT87_REG_FAN_CTL); + int tmp = it87_read_value(data, IT87_REG_FAN_CTL); if ((tmp & 0x87) == 0) { if (fix_pwm_polarity) { /* The user asks us to attempt a chip reconfiguration. @@ -1158,7 +1159,7 @@ static int it87_check_pwm(struct i2c_client *client) u8 pwm[3]; for (i = 0; i < 3; i++) - pwm[i] = it87_read_value(client, + pwm[i] = it87_read_value(data, IT87_REG_PWM(i)); /* If any fan is in automatic pwm mode, the polarity @@ -1166,26 +1167,26 @@ static int it87_check_pwm(struct i2c_client *client) * better don't change anything (but still disable the * PWM interface). */ if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) { - dev_info(&client->dev, "Reconfiguring PWM to " + dev_info(dev, "Reconfiguring PWM to " "active high polarity\n"); - it87_write_value(client, IT87_REG_FAN_CTL, + it87_write_value(data, IT87_REG_FAN_CTL, tmp | 0x87); for (i = 0; i < 3; i++) - it87_write_value(client, + it87_write_value(data, IT87_REG_PWM(i), 0x7f & ~pwm[i]); return 1; } - dev_info(&client->dev, "PWM configuration is " + dev_info(dev, "PWM configuration is " "too broken to be fixed\n"); } - dev_info(&client->dev, "Detected broken BIOS " + dev_info(dev, "Detected broken BIOS " "defaults, disabling PWM interface\n"); return 0; } else if (fix_pwm_polarity) { - dev_info(&client->dev, "PWM configuration looks " + dev_info(dev, "PWM configuration looks " "sane, won't touch\n"); } @@ -1193,8 +1194,9 @@ static int it87_check_pwm(struct i2c_client *client) } /* Called when we have found a new IT87. */ -static void it87_init_client(struct i2c_client *client, struct it87_data *data) +static void __devinit it87_init_device(struct platform_device *pdev) { + struct it87_data *data = platform_get_drvdata(pdev); int tmp, i; /* initialize to sane defaults: @@ -1214,48 +1216,48 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data) * means -1 degree C, which surprisingly doesn't trigger an alarm, * but is still confusing, so change to 127 degrees C. */ for (i = 0; i < 8; i++) { - tmp = it87_read_value(client, IT87_REG_VIN_MIN(i)); + tmp = it87_read_value(data, IT87_REG_VIN_MIN(i)); if (tmp == 0xff) - it87_write_value(client, IT87_REG_VIN_MIN(i), 0); + it87_write_value(data, IT87_REG_VIN_MIN(i), 0); } for (i = 0; i < 3; i++) { - tmp = it87_read_value(client, IT87_REG_TEMP_HIGH(i)); + tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i)); if (tmp == 0xff) - it87_write_value(client, IT87_REG_TEMP_HIGH(i), 127); + it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); } /* Check if temperature channnels are reset manually or by some reason */ - tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE); + tmp = it87_read_value(data, IT87_REG_TEMP_ENABLE); if ((tmp & 0x3f) == 0) { /* Temp1,Temp3=thermistor; Temp2=thermal diode */ tmp = (tmp & 0xc0) | 0x2a; - it87_write_value(client, IT87_REG_TEMP_ENABLE, tmp); + it87_write_value(data, IT87_REG_TEMP_ENABLE, tmp); } data->sensor = tmp; /* Check if voltage monitors are reset manually or by some reason */ - tmp = it87_read_value(client, IT87_REG_VIN_ENABLE); + tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); if ((tmp & 0xff) == 0) { /* Enable all voltage monitors */ - it87_write_value(client, IT87_REG_VIN_ENABLE, 0xff); + it87_write_value(data, IT87_REG_VIN_ENABLE, 0xff); } /* Check if tachometers are reset manually or by some reason */ - data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); + data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); if ((data->fan_main_ctrl & 0x70) == 0) { /* Enable all fan tachometers */ data->fan_main_ctrl |= 0x70; - it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); + it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); } data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; /* Set tachometers to 16-bit mode if needed */ if (data->type == it8716 || data->type == it8718) { - tmp = it87_read_value(client, IT87_REG_FAN_16BIT); + tmp = it87_read_value(data, IT87_REG_FAN_16BIT); if (~tmp & 0x07 & data->has_fan) { - dev_dbg(&client->dev, + dev_dbg(&pdev->dev, "Setting fan1-3 to 16-bit mode\n"); - it87_write_value(client, IT87_REG_FAN_16BIT, + it87_write_value(data, IT87_REG_FAN_16BIT, tmp | 0x07); } } @@ -1265,7 +1267,7 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data) for (i = 0; i < 3; i++) { if (data->fan_main_ctrl & (1 << i)) { /* pwm mode */ - tmp = it87_read_value(client, IT87_REG_PWM(i)); + tmp = it87_read_value(data, IT87_REG_PWM(i)); if (tmp & 0x80) { /* automatic pwm - not yet implemented, but * leave the settings made by the BIOS alone @@ -1279,15 +1281,14 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data) } /* Start monitoring */ - it87_write_value(client, IT87_REG_CONFIG, - (it87_read_value(client, IT87_REG_CONFIG) & 0x36) + it87_write_value(data, IT87_REG_CONFIG, + (it87_read_value(data, IT87_REG_CONFIG) & 0x36) | (update_vbat ? 0x41 : 0x01)); } static struct it87_data *it87_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct it87_data *data = i2c_get_clientdata(client); + struct it87_data *data = dev_get_drvdata(dev); int i; mutex_lock(&data->update_lock); @@ -1298,20 +1299,20 @@ static struct it87_data *it87_update_device(struct device *dev) if (update_vbat) { /* Cleared after each update, so reenable. Value returned by this read will be previous value */ - it87_write_value(client, IT87_REG_CONFIG, - it87_read_value(client, IT87_REG_CONFIG) | 0x40); + it87_write_value(data, IT87_REG_CONFIG, + it87_read_value(data, IT87_REG_CONFIG) | 0x40); } for (i = 0; i <= 7; i++) { data->in[i] = - it87_read_value(client, IT87_REG_VIN(i)); + it87_read_value(data, IT87_REG_VIN(i)); data->in_min[i] = - it87_read_value(client, IT87_REG_VIN_MIN(i)); + it87_read_value(data, IT87_REG_VIN_MIN(i)); data->in_max[i] = - it87_read_value(client, IT87_REG_VIN_MAX(i)); + it87_read_value(data, IT87_REG_VIN_MAX(i)); } /* in8 (battery) has no limit registers */ data->in[8] = - it87_read_value(client, IT87_REG_VIN(8)); + it87_read_value(data, IT87_REG_VIN(8)); for (i = 0; i < 3; i++) { /* Skip disabled fans */ @@ -1319,46 +1320,47 @@ static struct it87_data *it87_update_device(struct device *dev) continue; data->fan_min[i] = - it87_read_value(client, IT87_REG_FAN_MIN(i)); - data->fan[i] = it87_read_value(client, + it87_read_value(data, IT87_REG_FAN_MIN(i)); + data->fan[i] = it87_read_value(data, IT87_REG_FAN(i)); /* Add high byte if in 16-bit mode */ if (data->type == it8716 || data->type == it8718) { - data->fan[i] |= it87_read_value(client, + data->fan[i] |= it87_read_value(data, IT87_REG_FANX(i)) << 8; - data->fan_min[i] |= it87_read_value(client, + data->fan_min[i] |= it87_read_value(data, IT87_REG_FANX_MIN(i)) << 8; } } for (i = 0; i < 3; i++) { data->temp[i] = - it87_read_value(client, IT87_REG_TEMP(i)); + it87_read_value(data, IT87_REG_TEMP(i)); data->temp_high[i] = - it87_read_value(client, IT87_REG_TEMP_HIGH(i)); + it87_read_value(data, IT87_REG_TEMP_HIGH(i)); data->temp_low[i] = - it87_read_value(client, IT87_REG_TEMP_LOW(i)); + it87_read_value(data, IT87_REG_TEMP_LOW(i)); } /* Newer chips don't have clock dividers */ if ((data->has_fan & 0x07) && data->type != it8716 && data->type != it8718) { - i = it87_read_value(client, IT87_REG_FAN_DIV); + i = it87_read_value(data, IT87_REG_FAN_DIV); data->fan_div[0] = i & 0x07; data->fan_div[1] = (i >> 3) & 0x07; data->fan_div[2] = (i & 0x40) ? 3 : 1; } data->alarms = - it87_read_value(client, IT87_REG_ALARM1) | - (it87_read_value(client, IT87_REG_ALARM2) << 8) | - (it87_read_value(client, IT87_REG_ALARM3) << 16); - data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); - data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL); - - data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); + it87_read_value(data, IT87_REG_ALARM1) | + (it87_read_value(data, IT87_REG_ALARM2) << 8) | + (it87_read_value(data, IT87_REG_ALARM3) << 16); + data->fan_main_ctrl = it87_read_value(data, + IT87_REG_FAN_MAIN_CTRL); + data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); + + data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); /* The 8705 does not have VID capability */ if (data->type == it8712 || data->type == it8716) { - data->vid = it87_read_value(client, IT87_REG_VID); + data->vid = it87_read_value(data, IT87_REG_VID); /* The older IT8712F revisions had only 5 VID pins, but we assume it is always safe to read 6 bits. */ data->vid &= 0x3f; @@ -1372,24 +1374,85 @@ static struct it87_data *it87_update_device(struct device *dev) return data; } +static int __init it87_device_add(unsigned short address, + const struct it87_sio_data *sio_data) +{ + struct resource res = { + .start = address , + .end = address + IT87_EXTENT - 1, + .name = DRVNAME, + .flags = IORESOURCE_IO, + }; + int err; + + pdev = platform_device_alloc(DRVNAME, address); + if (!pdev) { + err = -ENOMEM; + printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + goto exit; + } + + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + printk(KERN_ERR DRVNAME ": Device resource addition failed " + "(%d)\n", err); + goto exit_device_put; + } + + err = platform_device_add_data(pdev, sio_data, + sizeof(struct it87_sio_data)); + if (err) { + printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + goto exit_device_put; + } + + err = platform_device_add(pdev); + if (err) { + printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", + err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit: + return err; +} + static int __init sm_it87_init(void) { - int res; + int err; + unsigned short isa_address=0; + struct it87_sio_data sio_data; + + err = it87_find(&isa_address, &sio_data); + if (err) + return err; + err = platform_driver_register(&it87_driver); + if (err) + return err; - if ((res = it87_find(&isa_address))) - return res; - return i2c_isa_add_driver(&it87_isa_driver); + err = it87_device_add(isa_address, &sio_data); + if (err){ + platform_driver_unregister(&it87_driver); + return err; + } + + return 0; } static void __exit sm_it87_exit(void) { - i2c_isa_del_driver(&it87_isa_driver); + platform_device_unregister(pdev); + platform_driver_unregister(&it87_driver); } MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>, " "Jean Delvare <khali@linux-fr.org>"); -MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F, SiS950 driver"); +MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8726F, SiS950 driver"); module_param(update_vbat, bool, 0); MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); module_param(fix_pwm_polarity, bool, 0); diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index d69f3cf07122..2162d69a8c06 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -364,7 +364,7 @@ static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, /* Individual alarm files */ static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0); static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); @@ -383,7 +383,7 @@ static struct attribute *lm63_attributes[] = { &dev_attr_temp2_crit_hyst.attr, &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input_fault.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index 7eaae3834e15..275d392eca61 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -96,6 +96,10 @@ static int __devinit lm70_probe(struct spi_device *spi) struct lm70 *p_lm70; int status; + /* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */ + if ((spi->mode & (SPI_CPOL|SPI_CPHA)) || !(spi->mode & SPI_3WIRE)) + return -EINVAL; + p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); if (!p_lm70) return -ENOMEM; diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 9fb572f03ba5..6eea3476b90c 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -864,7 +864,7 @@ static int __init lm78_isa_found(unsigned short address) /* Determine the chip type */ outb_p(LM78_REG_CHIPID, address + LM78_ADDR_REG_OFFSET); val = inb_p(address + LM78_DATA_REG_OFFSET); - if (val == 0x00 /* LM78 */ + if (val == 0x00 || val == 0x20 /* LM78 */ || val == 0x40 /* LM78-J */ || (val & 0xfe) == 0xc0) /* LM79 */ found = 1; @@ -882,7 +882,7 @@ static int __init lm78_isa_device_add(unsigned short address) { struct resource res = { .start = address, - .end = address + LM78_EXTENT, + .end = address + LM78_EXTENT - 1, .name = "lm78", .flags = IORESOURCE_IO, }; diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index feb87b41e986..654c0f73464d 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -223,14 +223,14 @@ static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8); /* Individual alarm files */ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4); static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(temp4_input_fault, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 10); static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 13); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 13); static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15); /* Raw alarm file for compatibility */ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); @@ -245,7 +245,7 @@ static struct attribute *lm83_attributes[] = { &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_input_fault.dev_attr.attr, + &sensor_dev_attr_temp3_fault.dev_attr.attr, &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, &dev_attr_alarms.attr, @@ -266,9 +266,9 @@ static struct attribute *lm83_attributes_opt[] = { &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_input_fault.dev_attr.attr, + &sensor_dev_attr_temp4_fault.dev_attr.attr, &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input_fault.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, NULL }; diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 6882ce75feee..af541d67245d 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -43,6 +43,13 @@ * variants. The extra address and features of the MAX6659 are not * supported by this driver. * + * This driver also supports the MAX6680 and MAX6681, two other sensor + * chips made by Maxim. These are quite similar to the other Maxim + * chips. Complete datasheet can be obtained at: + * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3370 + * The MAX6680 and MAX6681 only differ in the pinout so they can be + * treated identically. + * * This driver also supports the ADT7461 chip from Analog Devices but * only in its "compatability mode". If an ADT7461 chip is found but * is configured in non-compatible mode (where its temperature @@ -84,20 +91,25 @@ /* * Addresses to scan * Address is fully defined internally and cannot be changed except for - * MAX6659. + * MAX6659, MAX6680 and MAX6681. * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6657 and MAX6658 * have address 0x4c. * ADM1032-2, ADT7461-2, LM89-1, and LM99-1 have address 0x4d. * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported). + * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, + * 0x4c, 0x4d or 0x4e. */ -static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, + 0x29, 0x2a, 0x2b, + 0x4c, 0x4d, 0x4e, + I2C_CLIENT_END }; /* * Insmod parameters */ -I2C_CLIENT_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461); +I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680); /* * The LM90 registers @@ -359,7 +371,7 @@ static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4); /* Individual alarm files */ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5); @@ -381,7 +393,7 @@ static struct attribute *lm90_attributes[] = { &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input_fault.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, @@ -429,7 +441,7 @@ static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec); */ /* The ADM1032 supports PEC but not on write byte transactions, so we need - to explicitely ask for a transaction without PEC. */ + to explicitly ask for a transaction without PEC. */ static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value) { return i2c_smbus_xfer(client->adapter, client->addr, @@ -525,7 +537,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) ®_convrate) < 0) goto exit_free; - if (man_id == 0x01) { /* National Semiconductor */ + if ((address == 0x4C || address == 0x4D) + && man_id == 0x01) { /* National Semiconductor */ u8 reg_config2; if (lm90_read_reg(new_client, LM90_REG_R_CONFIG2, @@ -548,7 +561,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) } } } else - if (man_id == 0x41) { /* Analog Devices */ + if ((address == 0x4C || address == 0x4D) + && man_id == 0x41) { /* Analog Devices */ if ((chip_id & 0xF0) == 0x40 /* ADM1032 */ && (reg_config1 & 0x3F) == 0x00 && reg_convrate <= 0x0A) { @@ -562,18 +576,30 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) } else if (man_id == 0x4D) { /* Maxim */ /* - * The Maxim variants do NOT have a chip_id register. - * Reading from that address will return the last read - * value, which in our case is those of the man_id - * register. Likewise, the config1 register seems to - * lack a low nibble, so the value will be those of the - * previous read, so in our case those of the man_id - * register. + * The MAX6657, MAX6658 and MAX6659 do NOT have a + * chip_id register. Reading from that address will + * return the last read value, which in our case is + * those of the man_id register. Likewise, the config1 + * register seems to lack a low nibble, so the value + * will be those of the previous read, so in our case + * those of the man_id register. */ if (chip_id == man_id + && (address == 0x4C || address == 0x4D) && (reg_config1 & 0x1F) == (man_id & 0x0F) && reg_convrate <= 0x09) { kind = max6657; + } else + /* The chip_id register of the MAX6680 and MAX6681 + * holds the revision of the chip. + * the lowest bit of the config1 register is unused + * and should return zero when read, so should the + * second to last bit of config1 (software reset) + */ + if (chip_id == 0x01 + && (reg_config1 & 0x03) == 0x00 + && reg_convrate <= 0x07) { + kind = max6680; } } @@ -599,6 +625,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) name = "lm86"; } else if (kind == max6657) { name = "max6657"; + } else if (kind == max6680) { + name = "max6680"; } else if (kind == adt7461) { name = "adt7461"; } @@ -646,7 +674,8 @@ exit: static void lm90_init_client(struct i2c_client *client) { - u8 config; + u8 config, config_orig; + struct lm90_data *data = i2c_get_clientdata(client); /* * Start the conversions. @@ -657,9 +686,20 @@ static void lm90_init_client(struct i2c_client *client) dev_warn(&client->dev, "Initialization failed!\n"); return; } - if (config & 0x40) - i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, - config & 0xBF); /* run */ + config_orig = config; + + /* + * Put MAX6680/MAX8881 into extended resolution (bit 0x10, + * 0.125 degree resolution) and range (0x08, extend range + * to -64 degree) mode for the remote temperature sensor. + */ + if (data->kind == max6680) { + config |= 0x18; + } + + config &= 0xBF; /* run */ + if (config != config_orig) /* Only write if changed */ + i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); } static int lm90_detach_client(struct i2c_client *client) diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index c8a21be09d87..f57c75d59a5b 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -1,7 +1,7 @@ /* * pc87360.c - Part of lm_sensors, Linux kernel modules * for hardware monitoring - * Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2004, 2007 Jean Delvare <khali@linux-fr.org> * * Copied from smsc47m1.c: * Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> @@ -37,8 +37,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/jiffies.h> -#include <linux/i2c.h> -#include <linux/i2c-isa.h> +#include <linux/platform_device.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/hwmon-vid.h> @@ -47,12 +46,10 @@ #include <asm/io.h> static u8 devid; -static unsigned short address; +static struct platform_device *pdev; static unsigned short extra_isa[3]; static u8 confreg[4]; -enum chips { any_chip, pc87360, pc87363, pc87364, pc87365, pc87366 }; - static int init = 1; module_param(init, int, 0); MODULE_PARM_DESC(init, @@ -178,11 +175,11 @@ static inline u8 PWM_TO_REG(int val, int inv) ((val) + 500) / 1000) /* - * Client data (each client gets its own) + * Device data */ struct pc87360_data { - struct i2c_client client; + const char *name; struct class_device *class_dev; struct mutex lock; struct mutex update_lock; @@ -222,27 +219,28 @@ struct pc87360_data { * Functions declaration */ -static int pc87360_detect(struct i2c_adapter *adapter); -static int pc87360_detach_client(struct i2c_client *client); +static int pc87360_probe(struct platform_device *pdev); +static int __devexit pc87360_remove(struct platform_device *pdev); static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, u8 reg); static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, u8 reg, u8 value); -static void pc87360_init_client(struct i2c_client *client, int use_thermistors); +static void pc87360_init_device(struct platform_device *pdev, + int use_thermistors); static struct pc87360_data *pc87360_update_device(struct device *dev); /* - * Driver data (common to all clients) + * Driver data */ -static struct i2c_driver pc87360_driver = { +static struct platform_driver pc87360_driver = { .driver = { .owner = THIS_MODULE, .name = "pc87360", }, - .attach_adapter = pc87360_detect, - .detach_client = pc87360_detach_client, + .probe = pc87360_probe, + .remove = __devexit_p(pc87360_remove), }; /* @@ -281,8 +279,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long fan_min = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -347,8 +344,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, con size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -410,8 +406,7 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -425,8 +420,7 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -511,8 +505,7 @@ static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char } static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); data->vrm = simple_strtoul(buf, NULL, 10); return count; } @@ -584,8 +577,7 @@ static ssize_t set_therm_min(struct device *dev, struct device_attribute *devatt size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -599,8 +591,7 @@ static ssize_t set_therm_max(struct device *dev, struct device_attribute *devatt size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -614,8 +605,7 @@ static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devat size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -715,8 +705,7 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -730,8 +719,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -745,8 +733,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devatt size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); @@ -818,6 +805,14 @@ static const struct attribute_group pc8736x_temp_group = { .attrs = pc8736x_temp_attr_array, }; +static ssize_t show_name(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct pc87360_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", data->name); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + /* * Device detection, registration and update */ @@ -912,28 +907,18 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses return 0; } -static int pc87360_detect(struct i2c_adapter *adapter) +static int __devinit pc87360_probe(struct platform_device *pdev) { int i; - struct i2c_client *client; struct pc87360_data *data; int err = 0; const char *name = "pc87360"; int use_thermistors = 0; - struct device *dev; + struct device *dev = &pdev->dev; if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL))) return -ENOMEM; - client = &data->client; - dev = &client->dev; - i2c_set_clientdata(client, data); - client->addr = address; - mutex_init(&data->lock); - client->adapter = adapter; - client->driver = &pc87360_driver; - client->flags = 0; - data->fannr = 2; data->innr = 0; data->tempnr = 0; @@ -960,15 +945,17 @@ static int pc87360_detect(struct i2c_adapter *adapter) break; } - strlcpy(client->name, name, sizeof(client->name)); + data->name = name; data->valid = 0; + mutex_init(&data->lock); mutex_init(&data->update_lock); + platform_set_drvdata(pdev, data); for (i = 0; i < 3; i++) { if (((data->address[i] = extra_isa[i])) && !request_region(extra_isa[i], PC87360_EXTENT, pc87360_driver.driver.name)) { - dev_err(&client->dev, "Region 0x%x-0x%x already " + dev_err(dev, "Region 0x%x-0x%x already " "in use!\n", extra_isa[i], extra_isa[i]+PC87360_EXTENT-1); for (i--; i >= 0; i--) @@ -982,9 +969,6 @@ static int pc87360_detect(struct i2c_adapter *adapter) if (data->fannr) data->fan_conf = confreg[0] | (confreg[1] << 8); - if ((err = i2c_attach_client(client))) - goto ERROR2; - /* Use the correct reference voltage Unless both the VLM and the TMS logical devices agree to use an external Vref, the internal one is used. */ @@ -996,7 +980,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) PC87365_REG_TEMP_CONFIG); } data->in_vref = (i&0x02) ? 3025 : 2966; - dev_dbg(&client->dev, "Using %s reference voltage\n", + dev_dbg(dev, "Using %s reference voltage\n", (i&0x02) ? "external" : "internal"); data->vid_conf = confreg[3]; @@ -1015,18 +999,18 @@ static int pc87360_detect(struct i2c_adapter *adapter) if (devid == 0xe9 && data->address[1]) /* PC87366 */ use_thermistors = confreg[2] & 0x40; - pc87360_init_client(client, use_thermistors); + pc87360_init_device(pdev, use_thermistors); } /* Register all-or-nothing sysfs groups */ if (data->innr && - (err = sysfs_create_group(&client->dev.kobj, + (err = sysfs_create_group(&dev->kobj, &pc8736x_vin_group))) goto ERROR3; if (data->innr == 14 && - (err = sysfs_create_group(&client->dev.kobj, + (err = sysfs_create_group(&dev->kobj, &pc8736x_therm_group))) goto ERROR3; @@ -1067,7 +1051,10 @@ static int pc87360_detect(struct i2c_adapter *adapter) goto ERROR3; } - data->class_dev = hwmon_device_register(&client->dev); + if ((err = device_create_file(dev, &dev_attr_name))) + goto ERROR3; + + data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto ERROR3; @@ -1075,14 +1062,12 @@ static int pc87360_detect(struct i2c_adapter *adapter) return 0; ERROR3: + device_remove_file(dev, &dev_attr_name); /* can still remove groups whose members were added individually */ - sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group); - sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group); - sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group); - sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group); - - i2c_detach_client(client); -ERROR2: + sysfs_remove_group(&dev->kobj, &pc8736x_temp_group); + sysfs_remove_group(&dev->kobj, &pc8736x_fan_group); + sysfs_remove_group(&dev->kobj, &pc8736x_therm_group); + sysfs_remove_group(&dev->kobj, &pc8736x_vin_group); for (i = 0; i < 3; i++) { if (data->address[i]) { release_region(data->address[i], PC87360_EXTENT); @@ -1093,20 +1078,18 @@ ERROR1: return err; } -static int pc87360_detach_client(struct i2c_client *client) +static int __devexit pc87360_remove(struct platform_device *pdev) { - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = platform_get_drvdata(pdev); int i; hwmon_device_unregister(data->class_dev); - sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group); - sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group); - sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group); - sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group); - - if ((i = i2c_detach_client(client))) - return i; + device_remove_file(&pdev->dev, &dev_attr_name); + sysfs_remove_group(&pdev->dev.kobj, &pc8736x_temp_group); + sysfs_remove_group(&pdev->dev.kobj, &pc8736x_fan_group); + sysfs_remove_group(&pdev->dev.kobj, &pc8736x_therm_group); + sysfs_remove_group(&pdev->dev.kobj, &pc8736x_vin_group); for (i = 0; i < 3; i++) { if (data->address[i]) { @@ -1144,9 +1127,10 @@ static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, mutex_unlock(&(data->lock)); } -static void pc87360_init_client(struct i2c_client *client, int use_thermistors) +static void pc87360_init_device(struct platform_device *pdev, + int use_thermistors) { - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = platform_get_drvdata(pdev); int i, nr; const u8 init_in[14] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 1, 2, 2, 2 }; const u8 init_temp[3] = { 2, 2, 1 }; @@ -1155,7 +1139,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) if (init >= 2 && data->innr) { reg = pc87360_read_value(data, LD_IN, NO_BANK, PC87365_REG_IN_CONVRATE); - dev_info(&client->dev, "VLM conversion set to " + dev_info(&pdev->dev, "VLM conversion set to " "1s period, 160us delay\n"); pc87360_write_value(data, LD_IN, NO_BANK, PC87365_REG_IN_CONVRATE, @@ -1169,7 +1153,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) reg = pc87360_read_value(data, LD_IN, i, PC87365_REG_IN_STATUS); if (!(reg & 0x01)) { - dev_dbg(&client->dev, "Forcibly " + dev_dbg(&pdev->dev, "Forcibly " "enabling in%d\n", i); pc87360_write_value(data, LD_IN, i, PC87365_REG_IN_STATUS, @@ -1193,7 +1177,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) reg = pc87360_read_value(data, LD_TEMP, i, PC87365_REG_TEMP_STATUS); if (!(reg & 0x01)) { - dev_dbg(&client->dev, "Forcibly " + dev_dbg(&pdev->dev, "Forcibly " "enabling temp%d\n", i+1); pc87360_write_value(data, LD_TEMP, i, PC87365_REG_TEMP_STATUS, @@ -1210,7 +1194,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) reg = pc87360_read_value(data, LD_TEMP, (i-11)/2, PC87365_REG_TEMP_STATUS); if (reg & 0x01) { - dev_dbg(&client->dev, "Skipping " + dev_dbg(&pdev->dev, "Skipping " "temp%d, pin already in use " "by temp%d\n", i-7, (i-11)/2); continue; @@ -1220,7 +1204,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) reg = pc87360_read_value(data, LD_IN, i, PC87365_REG_IN_STATUS); if (!(reg & 0x01)) { - dev_dbg(&client->dev, "Forcibly " + dev_dbg(&pdev->dev, "Forcibly " "enabling temp%d\n", i-7); pc87360_write_value(data, LD_IN, i, PC87365_REG_TEMP_STATUS, @@ -1234,7 +1218,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) reg = pc87360_read_value(data, LD_IN, NO_BANK, PC87365_REG_IN_CONFIG); if (reg & 0x01) { - dev_dbg(&client->dev, "Forcibly " + dev_dbg(&pdev->dev, "Forcibly " "enabling monitoring (VLM)\n"); pc87360_write_value(data, LD_IN, NO_BANK, PC87365_REG_IN_CONFIG, @@ -1246,7 +1230,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) reg = pc87360_read_value(data, LD_TEMP, NO_BANK, PC87365_REG_TEMP_CONFIG); if (reg & 0x01) { - dev_dbg(&client->dev, "Forcibly enabling " + dev_dbg(&pdev->dev, "Forcibly enabling " "monitoring (TMS)\n"); pc87360_write_value(data, LD_TEMP, NO_BANK, PC87365_REG_TEMP_CONFIG, @@ -1268,9 +1252,9 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) } } -static void pc87360_autodiv(struct i2c_client *client, int nr) +static void pc87360_autodiv(struct device *dev, int nr) { - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); u8 old_min = data->fan_min[nr]; /* Increase clock divider if needed and possible */ @@ -1280,7 +1264,7 @@ static void pc87360_autodiv(struct i2c_client *client, int nr) data->fan_status[nr] += 0x20; data->fan_min[nr] >>= 1; data->fan[nr] >>= 1; - dev_dbg(&client->dev, "Increasing " + dev_dbg(dev, "Increasing " "clock divider to %d for fan %d\n", FAN_DIV_FROM_REG(data->fan_status[nr]), nr+1); } @@ -1292,7 +1276,7 @@ static void pc87360_autodiv(struct i2c_client *client, int nr) data->fan_status[nr] -= 0x20; data->fan_min[nr] <<= 1; data->fan[nr] <<= 1; - dev_dbg(&client->dev, "Decreasing " + dev_dbg(dev, "Decreasing " "clock divider to %d for fan %d\n", FAN_DIV_FROM_REG(data->fan_status[nr]), nr+1); @@ -1309,14 +1293,13 @@ static void pc87360_autodiv(struct i2c_client *client, int nr) static struct pc87360_data *pc87360_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct pc87360_data *data = i2c_get_clientdata(client); + struct pc87360_data *data = dev_get_drvdata(dev); u8 i; mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - dev_dbg(&client->dev, "Data update\n"); + dev_dbg(dev, "Data update\n"); /* Fans */ for (i = 0; i < data->fannr; i++) { @@ -1330,7 +1313,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(i)); /* Change clock divider if needed */ - pc87360_autodiv(client, i); + pc87360_autodiv(dev, i); /* Clear bits and write new divider */ pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(i), @@ -1418,9 +1401,53 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) return data; } +static int __init pc87360_device_add(unsigned short address) +{ + struct resource res = { + .name = "pc87360", + .flags = IORESOURCE_IO, + }; + int err, i; + + pdev = platform_device_alloc("pc87360", address); + if (!pdev) { + err = -ENOMEM; + printk(KERN_ERR "pc87360: Device allocation failed\n"); + goto exit; + } + + for (i = 0; i < 3; i++) { + if (!extra_isa[i]) + continue; + res.start = extra_isa[i]; + res.end = extra_isa[i] + PC87360_EXTENT - 1; + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + printk(KERN_ERR "pc87360: Device resource[%d] " + "addition failed (%d)\n", i, err); + goto exit_device_put; + } + } + + err = platform_device_add(pdev); + if (err) { + printk(KERN_ERR "pc87360: Device addition failed (%d)\n", + err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit: + return err; +} + static int __init pc87360_init(void) { - int i; + int err, i; + unsigned short address = 0; if (pc87360_find(0x2e, &devid, extra_isa) && pc87360_find(0x4e, &devid, extra_isa)) { @@ -1443,12 +1470,27 @@ static int __init pc87360_init(void) return -ENODEV; } - return i2c_isa_add_driver(&pc87360_driver); + err = platform_driver_register(&pc87360_driver); + if (err) + goto exit; + + /* Sets global pdev as a side effect */ + err = pc87360_device_add(address); + if (err) + goto exit_driver; + + return 0; + + exit_driver: + platform_driver_unregister(&pc87360_driver); + exit: + return err; } static void __exit pc87360_exit(void) { - i2c_isa_del_driver(&pc87360_driver); + platform_device_unregister(pdev); + platform_driver_unregister(&pc87360_driver); } diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index 29354fa26f81..2915bc4ad0d5 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c @@ -484,7 +484,6 @@ static int __devexit pc87427_remove(struct platform_device *pdev) struct resource *res; int i; - platform_set_drvdata(pdev, NULL); hwmon_device_unregister(data->class_dev); device_remove_file(&pdev->dev, &dev_attr_name); for (i = 0; i < 8; i++) { @@ -492,6 +491,7 @@ static int __devexit pc87427_remove(struct platform_device *pdev) continue; sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); } + platform_set_drvdata(pdev, NULL); kfree(data); res = platform_get_resource(pdev, IORESOURCE_IO, 0); diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 3f400263fc0f..92956eb3f3c1 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -54,9 +54,9 @@ #include <linux/slab.h> #include <linux/ioport.h> #include <linux/pci.h> -#include <linux/i2c.h> -#include <linux/i2c-isa.h> +#include <linux/platform_device.h> #include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/init.h> #include <linux/jiffies.h> @@ -72,17 +72,13 @@ module_param(force_addr, ushort, 0); MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors"); -/* Device address - Note that we can't determine the ISA address until we have initialized - our module */ -static unsigned short address; +static struct platform_device *pdev; /* Many SIS5595 constants specified below */ /* Length of ISA address segment */ #define SIS5595_EXTENT 8 /* PCI Config Registers */ -#define SIS5595_REVISION_REG 0x08 #define SIS5595_BASE_REG 0x68 #define SIS5595_PIN_REG 0x7A #define SIS5595_ENABLE_REG 0x7B @@ -165,7 +161,8 @@ static inline u8 DIV_TO_REG(int val) /* For each registered chip, we need to keep some data in memory. The structure is dynamically allocated. */ struct sis5595_data { - struct i2c_client client; + unsigned short addr; + const char *name; struct class_device *class_dev; struct mutex lock; @@ -189,102 +186,88 @@ struct sis5595_data { static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */ -static int sis5595_detect(struct i2c_adapter *adapter); -static int sis5595_detach_client(struct i2c_client *client); +static int sis5595_probe(struct platform_device *pdev); +static int __devexit sis5595_remove(struct platform_device *pdev); -static int sis5595_read_value(struct i2c_client *client, u8 reg); -static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value); +static int sis5595_read_value(struct sis5595_data *data, u8 reg); +static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value); static struct sis5595_data *sis5595_update_device(struct device *dev); -static void sis5595_init_client(struct i2c_client *client); +static void sis5595_init_device(struct sis5595_data *data); -static struct i2c_driver sis5595_driver = { +static struct platform_driver sis5595_driver = { .driver = { .owner = THIS_MODULE, .name = "sis5595", }, - .attach_adapter = sis5595_detect, - .detach_client = sis5595_detach_client, + .probe = sis5595_probe, + .remove = __devexit_p(sis5595_remove), }; /* 4 Voltages */ -static ssize_t show_in(struct device *dev, char *buf, int nr) +static ssize_t show_in(struct device *dev, struct device_attribute *da, + char *buf) { struct sis5595_data *data = sis5595_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])); } -static ssize_t show_in_min(struct device *dev, char *buf, int nr) +static ssize_t show_in_min(struct device *dev, struct device_attribute *da, + char *buf) { struct sis5595_data *data = sis5595_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])); } -static ssize_t show_in_max(struct device *dev, char *buf, int nr) +static ssize_t show_in_max(struct device *dev, struct device_attribute *da, + char *buf) { struct sis5595_data *data = sis5595_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])); } -static ssize_t set_in_min(struct device *dev, const char *buf, - size_t count, int nr) +static ssize_t set_in_min(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct sis5595_data *data = i2c_get_clientdata(client); + struct sis5595_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val); - sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]); + sis5595_write_value(data, SIS5595_REG_IN_MIN(nr), data->in_min[nr]); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_in_max(struct device *dev, const char *buf, - size_t count, int nr) +static ssize_t set_in_max(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct sis5595_data *data = i2c_get_clientdata(client); + struct sis5595_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val); - sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]); + sis5595_write_value(data, SIS5595_REG_IN_MAX(nr), data->in_max[nr]); mutex_unlock(&data->update_lock); return count; } #define show_in_offset(offset) \ -static ssize_t \ - show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in(dev, buf, offset); \ -} \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in##offset, NULL); \ -static ssize_t \ - show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in_min(dev, buf, offset); \ -} \ -static ssize_t \ - show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in_max(dev, buf, offset); \ -} \ -static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_in_min(dev, buf, count, offset); \ -} \ -static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_in_max(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in##offset##_min, set_in##offset##_min); \ -static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in##offset##_max, set_in##offset##_max); +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ + show_in_min, set_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ + show_in_max, set_in_max, offset); show_in_offset(0); show_in_offset(1); @@ -307,13 +290,12 @@ static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct sis5595_data *data = i2c_get_clientdata(client); + struct sis5595_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_over = TEMP_TO_REG(val); - sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over); + sis5595_write_value(data, SIS5595_REG_TEMP_OVER, data->temp_over); mutex_unlock(&data->update_lock); return count; } @@ -326,13 +308,12 @@ static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct sis5595_data *data = i2c_get_clientdata(client); + struct sis5595_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_hyst = TEMP_TO_REG(val); - sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst); + sis5595_write_value(data, SIS5595_REG_TEMP_HYST, data->temp_hyst); mutex_unlock(&data->update_lock); return count; } @@ -344,37 +325,47 @@ static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp_hyst, set_temp_hyst); /* 2 Fans */ -static ssize_t show_fan(struct device *dev, char *buf, int nr) +static ssize_t show_fan(struct device *dev, struct device_attribute *da, + char *buf) { struct sis5595_data *data = sis5595_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr])) ); } -static ssize_t show_fan_min(struct device *dev, char *buf, int nr) +static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, + char *buf) { struct sis5595_data *data = sis5595_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) ); } -static ssize_t set_fan_min(struct device *dev, const char *buf, - size_t count, int nr) +static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct sis5595_data *data = i2c_get_clientdata(client); + struct sis5595_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); + sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; } -static ssize_t show_fan_div(struct device *dev, char *buf, int nr) +static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, + char *buf) { struct sis5595_data *data = sis5595_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) ); } @@ -382,11 +373,12 @@ static ssize_t show_fan_div(struct device *dev, char *buf, int nr) determined in part by the fan divisor. This follows the principle of least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ -static ssize_t set_fan_div(struct device *dev, const char *buf, - size_t count, int nr) +static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct sis5595_data *data = i2c_get_clientdata(client); + struct sis5595_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; unsigned long min; unsigned long val = simple_strtoul(buf, NULL, 10); int reg; @@ -394,7 +386,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, mutex_lock(&data->update_lock); min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); - reg = sis5595_read_value(client, SIS5595_REG_FANDIV); + reg = sis5595_read_value(data, SIS5595_REG_FANDIV); switch (val) { case 1: data->fan_div[nr] = 0; break; @@ -402,7 +394,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, case 4: data->fan_div[nr] = 2; break; case 8: data->fan_div[nr] = 3; break; default: - dev_err(&client->dev, "fan_div value %ld not " + dev_err(dev, "fan_div value %ld not " "supported. Choose one of 1, 2, 4 or 8!\n", val); mutex_unlock(&data->update_lock); return -EINVAL; @@ -416,55 +408,25 @@ static ssize_t set_fan_div(struct device *dev, const char *buf, reg = (reg & 0x3f) | (data->fan_div[nr] << 6); break; } - sis5595_write_value(client, SIS5595_REG_FANDIV, reg); + sis5595_write_value(data, SIS5595_REG_FANDIV, reg); data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); + sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; } #define show_fan_offset(offset) \ -static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan(dev, buf, offset - 1); \ -} \ -static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_min(dev, buf, offset - 1); \ -} \ -static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_div(dev, buf, offset - 1); \ -} \ -static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_fan_min(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_min, set_fan_##offset##_min); +static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ + show_fan, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ + show_fan_min, set_fan_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ + show_fan_div, set_fan_div, offset - 1); show_fan_offset(1); show_fan_offset(2); -static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf, - size_t count) -{ - return set_fan_div(dev, buf, count, 0) ; -} - -static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf, - size_t count) -{ - return set_fan_div(dev, buf, count, 1) ; -} -static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, - show_fan_1_div, set_fan_1_div); -static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, - show_fan_2_div, set_fan_2_div); - /* Alarms */ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) { @@ -473,28 +435,37 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_name(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sis5595_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", data->name); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + static struct attribute *sis5595_attributes[] = { - &dev_attr_in0_input.attr, - &dev_attr_in0_min.attr, - &dev_attr_in0_max.attr, - &dev_attr_in1_input.attr, - &dev_attr_in1_min.attr, - &dev_attr_in1_max.attr, - &dev_attr_in2_input.attr, - &dev_attr_in2_min.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_input.attr, - &dev_attr_in3_min.attr, - &dev_attr_in3_max.attr, - - &dev_attr_fan1_input.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan1_div.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan2_min.attr, - &dev_attr_fan2_div.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, &dev_attr_alarms.attr, + &dev_attr_name.attr, NULL }; @@ -503,9 +474,9 @@ static const struct attribute_group sis5595_group = { }; static struct attribute *sis5595_attributes_opt[] = { - &dev_attr_in4_input.attr, - &dev_attr_in4_min.attr, - &dev_attr_in4_max.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, &dev_attr_temp1_input.attr, &dev_attr_temp1_max.attr, @@ -518,68 +489,35 @@ static const struct attribute_group sis5595_group_opt = { }; /* This is called when the module is loaded */ -static int sis5595_detect(struct i2c_adapter *adapter) +static int __devinit sis5595_probe(struct platform_device *pdev) { int err = 0; int i; - struct i2c_client *new_client; struct sis5595_data *data; + struct resource *res; char val; - u16 a; - if (force_addr) - address = force_addr & ~(SIS5595_EXTENT - 1); /* Reserve the ISA region */ - if (!request_region(address, SIS5595_EXTENT, + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, SIS5595_EXTENT, sis5595_driver.driver.name)) { err = -EBUSY; goto exit; } - if (force_addr) { - dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", address); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(s_bridge, SIS5595_BASE_REG, address)) - goto exit_release; - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(s_bridge, SIS5595_BASE_REG, &a)) - goto exit_release; - if ((a & ~(SIS5595_EXTENT - 1)) != address) - /* doesn't work for some chips? */ - goto exit_release; - } - - if (PCIBIOS_SUCCESSFUL != - pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val)) { - goto exit_release; - } - if ((val & 0x80) == 0) { - if (PCIBIOS_SUCCESSFUL != - pci_write_config_byte(s_bridge, SIS5595_ENABLE_REG, - val | 0x80)) - goto exit_release; - if (PCIBIOS_SUCCESSFUL != - pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val)) - goto exit_release; - if ((val & 0x80) == 0) - /* doesn't work for some chips! */ - goto exit_release; - } if (!(data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL))) { err = -ENOMEM; goto exit_release; } - new_client = &data->client; - new_client->addr = address; mutex_init(&data->lock); - i2c_set_clientdata(new_client, data); - new_client->adapter = adapter; - new_client->driver = &sis5595_driver; - new_client->flags = 0; + mutex_init(&data->update_lock); + data->addr = res->start; + data->name = "sis5595"; + platform_set_drvdata(pdev, data); /* Check revision and pin registers to determine whether 4 or 5 voltages */ - pci_read_config_byte(s_bridge, SIS5595_REVISION_REG, &(data->revision)); + pci_read_config_byte(s_bridge, PCI_REVISION_ID, &data->revision); /* 4 voltages, 1 temp */ data->maxins = 3; if (data->revision >= REV2MIN) { @@ -589,47 +527,37 @@ static int sis5595_detect(struct i2c_adapter *adapter) data->maxins = 4; } - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE); - - 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 exit_free; - /* Initialize the SIS5595 chip */ - sis5595_init_client(new_client); + sis5595_init_device(data); /* A few vars need to be filled upon startup */ for (i = 0; i < 2; i++) { - data->fan_min[i] = sis5595_read_value(new_client, + data->fan_min[i] = sis5595_read_value(data, SIS5595_REG_FAN_MIN(i)); } /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &sis5595_group))) - goto exit_detach; + if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group))) + goto exit_free; if (data->maxins == 4) { - if ((err = device_create_file(&new_client->dev, - &dev_attr_in4_input)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in4_min)) - || (err = device_create_file(&new_client->dev, - &dev_attr_in4_max))) + if ((err = device_create_file(&pdev->dev, + &sensor_dev_attr_in4_input.dev_attr)) + || (err = device_create_file(&pdev->dev, + &sensor_dev_attr_in4_min.dev_attr)) + || (err = device_create_file(&pdev->dev, + &sensor_dev_attr_in4_max.dev_attr))) goto exit_remove_files; } else { - if ((err = device_create_file(&new_client->dev, + if ((err = device_create_file(&pdev->dev, &dev_attr_temp1_input)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(&pdev->dev, &dev_attr_temp1_max)) - || (err = device_create_file(&new_client->dev, + || (err = device_create_file(&pdev->dev, &dev_attr_temp1_max_hyst))) goto exit_remove_files; } - data->class_dev = hwmon_device_register(&new_client->dev); + data->class_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto exit_remove_files; @@ -638,32 +566,26 @@ static int sis5595_detect(struct i2c_adapter *adapter) return 0; exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &sis5595_group); - sysfs_remove_group(&new_client->dev.kobj, &sis5595_group_opt); -exit_detach: - i2c_detach_client(new_client); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt); exit_free: kfree(data); exit_release: - release_region(address, SIS5595_EXTENT); + release_region(res->start, SIS5595_EXTENT); exit: return err; } -static int sis5595_detach_client(struct i2c_client *client) +static int __devexit sis5595_remove(struct platform_device *pdev) { - struct sis5595_data *data = i2c_get_clientdata(client); - int err; + struct sis5595_data *data = platform_get_drvdata(pdev); hwmon_device_unregister(data->class_dev); - sysfs_remove_group(&client->dev.kobj, &sis5595_group); - sysfs_remove_group(&client->dev.kobj, &sis5595_group_opt); - - if ((err = i2c_detach_client(client))) - return err; - - release_region(client->addr, SIS5595_EXTENT); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group); + sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt); + release_region(data->addr, SIS5595_EXTENT); + platform_set_drvdata(pdev, NULL); kfree(data); return 0; @@ -671,41 +593,37 @@ static int sis5595_detach_client(struct i2c_client *client) /* ISA access must be locked explicitly. */ -static int sis5595_read_value(struct i2c_client *client, u8 reg) +static int sis5595_read_value(struct sis5595_data *data, u8 reg) { int res; - struct sis5595_data *data = i2c_get_clientdata(client); mutex_lock(&data->lock); - outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); - res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET); + outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET); + res = inb_p(data->addr + SIS5595_DATA_REG_OFFSET); mutex_unlock(&data->lock); return res; } -static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value) +static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value) { - struct sis5595_data *data = i2c_get_clientdata(client); mutex_lock(&data->lock); - outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET); - outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET); + outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET); + outb_p(value, data->addr + SIS5595_DATA_REG_OFFSET); mutex_unlock(&data->lock); - return 0; } /* Called when we have found a new SIS5595. */ -static void sis5595_init_client(struct i2c_client *client) +static void __devinit sis5595_init_device(struct sis5595_data *data) { - u8 config = sis5595_read_value(client, SIS5595_REG_CONFIG); + u8 config = sis5595_read_value(data, SIS5595_REG_CONFIG); if (!(config & 0x01)) - sis5595_write_value(client, SIS5595_REG_CONFIG, + sis5595_write_value(data, SIS5595_REG_CONFIG, (config & 0xf7) | 0x01); } static struct sis5595_data *sis5595_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct sis5595_data *data = i2c_get_clientdata(client); + struct sis5595_data *data = dev_get_drvdata(dev); int i; mutex_lock(&data->update_lock); @@ -715,35 +633,35 @@ static struct sis5595_data *sis5595_update_device(struct device *dev) for (i = 0; i <= data->maxins; i++) { data->in[i] = - sis5595_read_value(client, SIS5595_REG_IN(i)); + sis5595_read_value(data, SIS5595_REG_IN(i)); data->in_min[i] = - sis5595_read_value(client, + sis5595_read_value(data, SIS5595_REG_IN_MIN(i)); data->in_max[i] = - sis5595_read_value(client, + sis5595_read_value(data, SIS5595_REG_IN_MAX(i)); } for (i = 0; i < 2; i++) { data->fan[i] = - sis5595_read_value(client, SIS5595_REG_FAN(i)); + sis5595_read_value(data, SIS5595_REG_FAN(i)); data->fan_min[i] = - sis5595_read_value(client, + sis5595_read_value(data, SIS5595_REG_FAN_MIN(i)); } if (data->maxins == 3) { data->temp = - sis5595_read_value(client, SIS5595_REG_TEMP); + sis5595_read_value(data, SIS5595_REG_TEMP); data->temp_over = - sis5595_read_value(client, SIS5595_REG_TEMP_OVER); + sis5595_read_value(data, SIS5595_REG_TEMP_OVER); data->temp_hyst = - sis5595_read_value(client, SIS5595_REG_TEMP_HYST); + sis5595_read_value(data, SIS5595_REG_TEMP_HYST); } - i = sis5595_read_value(client, SIS5595_REG_FANDIV); + i = sis5595_read_value(data, SIS5595_REG_FANDIV); data->fan_div[0] = (i >> 4) & 0x03; data->fan_div[1] = i >> 6; data->alarms = - sis5595_read_value(client, SIS5595_REG_ALARM1) | - (sis5595_read_value(client, SIS5595_REG_ALARM2) << 8); + sis5595_read_value(data, SIS5595_REG_ALARM1) | + (sis5595_read_value(data, SIS5595_REG_ALARM2) << 8); data->last_updated = jiffies; data->valid = 1; } @@ -774,10 +692,50 @@ static int blacklist[] __devinitdata = { PCI_DEVICE_ID_SI_5598, 0 }; +static int __devinit sis5595_device_add(unsigned short address) +{ + struct resource res = { + .start = address, + .end = address + SIS5595_EXTENT - 1, + .name = "sis5595", + .flags = IORESOURCE_IO, + }; + int err; + + pdev = platform_device_alloc("sis5595", address); + if (!pdev) { + err = -ENOMEM; + printk(KERN_ERR "sis5595: Device allocation failed\n"); + goto exit; + } + + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + printk(KERN_ERR "sis5595: Device resource addition failed " + "(%d)\n", err); + goto exit_device_put; + } + + err = platform_device_add(pdev); + if (err) { + printk(KERN_ERR "sis5595: Device addition failed (%d)\n", + err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit: + return err; +} + static int __devinit sis5595_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { - u16 val; + u16 address; + u8 enable; int *i; for (i = blacklist; *i != 0; i++) { @@ -790,27 +748,68 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev, } } + force_addr &= ~(SIS5595_EXTENT - 1); + if (force_addr) { + dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", force_addr); + pci_write_config_word(dev, SIS5595_BASE_REG, force_addr); + } + if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(dev, SIS5595_BASE_REG, &val)) + pci_read_config_word(dev, SIS5595_BASE_REG, &address)) { + dev_err(&dev->dev, "Failed to read ISA address\n"); return -ENODEV; + } - address = val & ~(SIS5595_EXTENT - 1); - if (address == 0 && force_addr == 0) { + address &= ~(SIS5595_EXTENT - 1); + if (!address) { dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n"); return -ENODEV; } + if (force_addr && address != force_addr) { + /* doesn't work for some chips? */ + dev_err(&dev->dev, "Failed to force ISA address\n"); + return -ENODEV; + } - s_bridge = pci_dev_get(dev); - if (i2c_isa_add_driver(&sis5595_driver)) { - pci_dev_put(s_bridge); - s_bridge = NULL; + if (PCIBIOS_SUCCESSFUL != + pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) { + dev_err(&dev->dev, "Failed to read enable register\n"); + return -ENODEV; + } + if (!(enable & 0x80)) { + if ((PCIBIOS_SUCCESSFUL != + pci_write_config_byte(dev, SIS5595_ENABLE_REG, + enable | 0x80)) + || (PCIBIOS_SUCCESSFUL != + pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) + || (!(enable & 0x80))) { + /* doesn't work for some chips! */ + dev_err(&dev->dev, "Failed to enable HWM device\n"); + return -ENODEV; + } } + if (platform_driver_register(&sis5595_driver)) { + dev_dbg(&dev->dev, "Failed to register sis5595 driver\n"); + goto exit; + } + + s_bridge = pci_dev_get(dev); + /* Sets global pdev as a side effect */ + if (sis5595_device_add(address)) + goto exit_unregister; + /* Always return failure here. This is to allow other drivers to bind * to this pci device. We don't really want to have control over the * pci device, we only wanted to read as few register values from it. */ return -ENODEV; + +exit_unregister: + pci_dev_put(dev); + platform_driver_unregister(&sis5595_driver); +exit: + return -ENODEV; } static struct pci_driver sis5595_pci_driver = { @@ -828,7 +827,8 @@ static void __exit sm_sis5595_exit(void) { pci_unregister_driver(&sis5595_pci_driver); if (s_bridge != NULL) { - i2c_isa_del_driver(&sis5595_driver); + platform_device_unregister(pdev); + platform_driver_unregister(&sis5595_driver); pci_dev_put(s_bridge); s_bridge = NULL; } diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 943abbd95ab5..45266b30ce1d 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -174,6 +174,8 @@ static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); REG: count of 90kHz pulses / revolution */ static int fan_from_reg(u16 reg) { + if (reg == 0 || reg == 0xffff) + return 0; return 90000 * 60 / reg; } @@ -333,7 +335,7 @@ static int __init smsc47b397_find(unsigned short *addr) superio_enter(); id = superio_inb(SUPERIO_REG_DEVID); - if ((id != 0x6f) && (id != 0x81)) { + if ((id != 0x6f) && (id != 0x81) && (id != 0x85)) { superio_exit(); return -ENODEV; } @@ -346,7 +348,8 @@ static int __init smsc47b397_find(unsigned short *addr) printk(KERN_INFO DRVNAME ": found SMSC %s " "(base address 0x%04x, revision %u)\n", - id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev); + id == 0x81 ? "SCH5307-NS" : id == 0x85 ? "SCH5317" : + "LPC47B397-NC", *addr, rev); superio_exit(); return 0; diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index c3e716e7e56f..d3181967f167 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -134,7 +134,7 @@ struct smsc47m1_sio_data { static int smsc47m1_probe(struct platform_device *pdev); -static int smsc47m1_remove(struct platform_device *pdev); +static int __devexit smsc47m1_remove(struct platform_device *pdev); static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, int init); @@ -599,6 +599,7 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev) error_remove_files: sysfs_remove_group(&dev->kobj, &smsc47m1_group); error_free: + platform_set_drvdata(pdev, NULL); kfree(data); error_release: release_region(res->start, SMSC_EXTENT); @@ -610,12 +611,12 @@ static int __devexit smsc47m1_remove(struct platform_device *pdev) struct smsc47m1_data *data = platform_get_drvdata(pdev); struct resource *res; - platform_set_drvdata(pdev, NULL); hwmon_device_unregister(data->class_dev); sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group); res = platform_get_resource(pdev, IORESOURCE_IO, 0); release_region(res->start, SMSC_EXTENT); + platform_set_drvdata(pdev, NULL); kfree(data); return 0; @@ -695,15 +696,12 @@ static int __init smsc47m1_device_add(unsigned short address, goto exit_device_put; } - pdev->dev.platform_data = kmalloc(sizeof(struct smsc47m1_sio_data), - GFP_KERNEL); - if (!pdev->dev.platform_data) { - err = -ENOMEM; + err = platform_device_add_data(pdev, sio_data, + sizeof(struct smsc47m1_sio_data)); + if (err) { printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); goto exit_device_put; } - memcpy(pdev->dev.platform_data, sio_data, - sizeof(struct smsc47m1_sio_data)); err = platform_device_add(pdev); if (err) { diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index a012f396f354..d3a3ba04cb0f 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -31,6 +31,7 @@ #include <linux/hwmon-vid.h> #include <linux/err.h> #include <linux/sysfs.h> +#include <linux/mutex.h> /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; @@ -97,7 +98,7 @@ static inline int TEMP_FROM_REG(s8 val) struct smsc47m192_data { struct i2c_client client; struct class_device *class_dev; - struct semaphore update_lock; + struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -164,11 +165,11 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, struct smsc47m192_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val, nr); i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr), data->in_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -181,11 +182,11 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, struct smsc47m192_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val, nr); i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr), data->in_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -243,11 +244,11 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, struct smsc47m192_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_min[nr] = TEMP_TO_REG(val); i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr], data->temp_min[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -260,11 +261,11 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, struct smsc47m192_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_max[nr] = TEMP_TO_REG(val); i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr], data->temp_max[nr]); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -287,7 +288,7 @@ static ssize_t set_temp_offset(struct device *dev, struct device_attribute u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); long val = simple_strtol(buf, NULL, 10); - down(&data->update_lock); + mutex_lock(&data->update_lock); data->temp_offset[nr] = TEMP_TO_REG(val); if (nr>1) i2c_smbus_write_byte_data(client, @@ -303,7 +304,7 @@ static ssize_t set_temp_offset(struct device *dev, struct device_attribute } else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0)) i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_OFFSET(nr), 0); - up(&data->update_lock); + mutex_unlock(&data->update_lock); return count; } @@ -360,8 +361,8 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010); static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020); static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040); -static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 0x4000); -static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 0x8000); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 0x4000); +static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 0x8000); static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001); static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002); static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004); @@ -411,13 +412,13 @@ static struct attribute *smsc47m192_attributes[] = { &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp2_offset.dev_attr.attr, &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input_fault.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, &sensor_dev_attr_temp3_offset.dev_attr.attr, &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_input_fault.dev_attr.attr, + &sensor_dev_attr_temp3_fault.dev_attr.attr, &dev_attr_cpu0_vid.attr, &dev_attr_vrm.attr, @@ -531,7 +532,7 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, /* Fill in the remaining client fields and put into the global list */ strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE); data->vrm = vid_which_vrm(); - init_MUTEX(&data->update_lock); + mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(client))) @@ -594,7 +595,7 @@ static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) struct smsc47m192_data *data = i2c_get_clientdata(client); int i, config; - down(&data->update_lock); + mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { @@ -645,7 +646,7 @@ static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) data->valid = 1; } - up(&data->update_lock); + mutex_unlock(&data->update_lock); return data; } diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index 9a440c8cc520..696c8a2e5374 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -34,9 +34,9 @@ #include <linux/slab.h> #include <linux/pci.h> #include <linux/jiffies.h> -#include <linux/i2c.h> -#include <linux/i2c-isa.h> +#include <linux/platform_device.h> #include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/init.h> #include <linux/mutex.h> @@ -51,10 +51,7 @@ module_param(force_addr, ushort, 0); MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors"); -/* Device address - Note that we can't determine the ISA address until we have initialized - our module */ -static unsigned short address; +static struct platform_device *pdev; /* The Via 686a southbridge has a LM78-like chip integrated on the same IC. @@ -295,7 +292,8 @@ static inline long TEMP_FROM_REG10(u16 val) /* For each registered chip, we need to keep some data in memory. The structure is dynamically allocated. */ struct via686a_data { - struct i2c_client client; + unsigned short addr; + const char *name; struct class_device *class_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -315,98 +313,85 @@ struct via686a_data { static struct pci_dev *s_bridge; /* pointer to the (only) via686a */ -static int via686a_detect(struct i2c_adapter *adapter); -static int via686a_detach_client(struct i2c_client *client); +static int via686a_probe(struct platform_device *pdev); +static int __devexit via686a_remove(struct platform_device *pdev); -static inline int via686a_read_value(struct i2c_client *client, u8 reg) +static inline int via686a_read_value(struct via686a_data *data, u8 reg) { - return (inb_p(client->addr + reg)); + return inb_p(data->addr + reg); } -static inline void via686a_write_value(struct i2c_client *client, u8 reg, +static inline void via686a_write_value(struct via686a_data *data, u8 reg, u8 value) { - outb_p(value, client->addr + reg); + outb_p(value, data->addr + reg); } static struct via686a_data *via686a_update_device(struct device *dev); -static void via686a_init_client(struct i2c_client *client); +static void via686a_init_device(struct via686a_data *data); /* following are the sysfs callback functions */ /* 7 voltage sensors */ -static ssize_t show_in(struct device *dev, char *buf, int nr) { +static ssize_t show_in(struct device *dev, struct device_attribute *da, + char *buf) { struct via686a_data *data = via686a_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)); } -static ssize_t show_in_min(struct device *dev, char *buf, int nr) { +static ssize_t show_in_min(struct device *dev, struct device_attribute *da, + char *buf) { struct via686a_data *data = via686a_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)); } -static ssize_t show_in_max(struct device *dev, char *buf, int nr) { +static ssize_t show_in_max(struct device *dev, struct device_attribute *da, + char *buf) { struct via686a_data *data = via686a_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)); } -static ssize_t set_in_min(struct device *dev, const char *buf, - size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct via686a_data *data = i2c_get_clientdata(client); +static ssize_t set_in_min(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + struct via686a_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_min[nr] = IN_TO_REG(val, nr); - via686a_write_value(client, VIA686A_REG_IN_MIN(nr), + via686a_write_value(data, VIA686A_REG_IN_MIN(nr), data->in_min[nr]); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_in_max(struct device *dev, const char *buf, - size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct via686a_data *data = i2c_get_clientdata(client); +static ssize_t set_in_max(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + struct via686a_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_max[nr] = IN_TO_REG(val, nr); - via686a_write_value(client, VIA686A_REG_IN_MAX(nr), + via686a_write_value(data, VIA686A_REG_IN_MAX(nr), data->in_max[nr]); mutex_unlock(&data->update_lock); return count; } #define show_in_offset(offset) \ -static ssize_t \ - show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in(dev, buf, offset); \ -} \ -static ssize_t \ - show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in_min(dev, buf, offset); \ -} \ -static ssize_t \ - show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in_max(dev, buf, offset); \ -} \ -static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_in_min(dev, buf, count, offset); \ -} \ -static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_in_max(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);\ -static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in##offset##_min, set_in##offset##_min); \ -static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in##offset##_max, set_in##offset##_max); +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ + show_in_min, set_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ + show_in_max, set_in_max, offset); show_in_offset(0); show_in_offset(1); @@ -415,150 +400,128 @@ show_in_offset(3); show_in_offset(4); /* 3 temperatures */ -static ssize_t show_temp(struct device *dev, char *buf, int nr) { +static ssize_t show_temp(struct device *dev, struct device_attribute *da, + char *buf) { struct via686a_data *data = via686a_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])); } -static ssize_t show_temp_over(struct device *dev, char *buf, int nr) { +static ssize_t show_temp_over(struct device *dev, struct device_attribute *da, + char *buf) { struct via686a_data *data = via686a_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])); } -static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) { +static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da, + char *buf) { struct via686a_data *data = via686a_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])); } -static ssize_t set_temp_over(struct device *dev, const char *buf, - size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct via686a_data *data = i2c_get_clientdata(client); +static ssize_t set_temp_over(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + struct via686a_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_over[nr] = TEMP_TO_REG(val); - via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr], + via686a_write_value(data, VIA686A_REG_TEMP_OVER[nr], data->temp_over[nr]); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_temp_hyst(struct device *dev, const char *buf, - size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct via686a_data *data = i2c_get_clientdata(client); +static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + struct via686a_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_hyst[nr] = TEMP_TO_REG(val); - via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr], + via686a_write_value(data, VIA686A_REG_TEMP_HYST[nr], data->temp_hyst[nr]); mutex_unlock(&data->update_lock); return count; } #define show_temp_offset(offset) \ -static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp(dev, buf, offset - 1); \ -} \ -static ssize_t \ -show_temp_##offset##_over (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_over(dev, buf, offset - 1); \ -} \ -static ssize_t \ -show_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_hyst(dev, buf, offset - 1); \ -} \ -static ssize_t set_temp_##offset##_over (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_over(dev, buf, count, offset - 1); \ -} \ -static ssize_t set_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_hyst(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);\ -static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_over, set_temp_##offset##_over); \ -static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_hyst, set_temp_##offset##_hyst); +static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ + show_temp, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ + show_temp_over, set_temp_over, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ + show_temp_hyst, set_temp_hyst, offset - 1); show_temp_offset(1); show_temp_offset(2); show_temp_offset(3); /* 2 Fans */ -static ssize_t show_fan(struct device *dev, char *buf, int nr) { +static ssize_t show_fan(struct device *dev, struct device_attribute *da, + char *buf) { struct via686a_data *data = via686a_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr])) ); } -static ssize_t show_fan_min(struct device *dev, char *buf, int nr) { +static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, + char *buf) { struct via686a_data *data = via686a_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) ); } -static ssize_t show_fan_div(struct device *dev, char *buf, int nr) { +static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, + char *buf) { struct via686a_data *data = via686a_update_device(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) ); } -static ssize_t set_fan_min(struct device *dev, const char *buf, - size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct via686a_data *data = i2c_get_clientdata(client); +static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + struct via686a_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); + via686a_write_value(data, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; } -static ssize_t set_fan_div(struct device *dev, const char *buf, - size_t count, int nr) { - struct i2c_client *client = to_i2c_client(dev); - struct via686a_data *data = i2c_get_clientdata(client); +static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) { + struct via686a_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int nr = attr->index; int val = simple_strtol(buf, NULL, 10); int old; mutex_lock(&data->update_lock); - old = via686a_read_value(client, VIA686A_REG_FANDIV); + old = via686a_read_value(data, VIA686A_REG_FANDIV); data->fan_div[nr] = DIV_TO_REG(val); old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); - via686a_write_value(client, VIA686A_REG_FANDIV, old); + via686a_write_value(data, VIA686A_REG_FANDIV, old); mutex_unlock(&data->update_lock); return count; } #define show_fan_offset(offset) \ -static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan(dev, buf, offset - 1); \ -} \ -static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_min(dev, buf, offset - 1); \ -} \ -static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_div(dev, buf, offset - 1); \ -} \ -static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_fan_min(dev, buf, count, offset - 1); \ -} \ -static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_fan_div(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_min, set_fan_##offset##_min); \ -static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_div, set_fan_##offset##_div); +static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ + show_fan, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ + show_fan_min, set_fan_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ + show_fan_div, set_fan_div, offset - 1); show_fan_offset(1); show_fan_offset(2); @@ -570,41 +533,50 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_name(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct via686a_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", data->name); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + static struct attribute *via686a_attributes[] = { - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - &dev_attr_in2_input.attr, - &dev_attr_in3_input.attr, - &dev_attr_in4_input.attr, - &dev_attr_in0_min.attr, - &dev_attr_in1_min.attr, - &dev_attr_in2_min.attr, - &dev_attr_in3_min.attr, - &dev_attr_in4_min.attr, - &dev_attr_in0_max.attr, - &dev_attr_in1_max.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_max.attr, - &dev_attr_in4_max.attr, - - &dev_attr_temp1_input.attr, - &dev_attr_temp2_input.attr, - &dev_attr_temp3_input.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp3_max.attr, - &dev_attr_temp1_max_hyst.attr, - &dev_attr_temp2_max_hyst.attr, - &dev_attr_temp3_max_hyst.attr, - - &dev_attr_fan1_input.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan2_min.attr, - &dev_attr_fan1_div.attr, - &dev_attr_fan2_div.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, + + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, + + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan2_div.dev_attr.attr, &dev_attr_alarms.attr, + &dev_attr_name.attr, NULL }; @@ -612,58 +584,29 @@ static const struct attribute_group via686a_group = { .attrs = via686a_attributes, }; -/* The driver. I choose to use type i2c_driver, as at is identical to both - smbus_driver and isa_driver, and clients could be of either kind */ -static struct i2c_driver via686a_driver = { +static struct platform_driver via686a_driver = { .driver = { .owner = THIS_MODULE, .name = "via686a", }, - .attach_adapter = via686a_detect, - .detach_client = via686a_detach_client, + .probe = via686a_probe, + .remove = __devexit_p(via686a_remove), }; /* This is called when the module is loaded */ -static int via686a_detect(struct i2c_adapter *adapter) +static int __devinit via686a_probe(struct platform_device *pdev) { - struct i2c_client *new_client; struct via686a_data *data; - int err = 0; - const char client_name[] = "via686a"; - u16 val; - - /* 8231 requires multiple of 256, we enforce that on 686 as well */ - if (force_addr) { - address = force_addr & 0xFF00; - dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", - address); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(s_bridge, VIA686A_BASE_REG, address)) - return -ENODEV; - } - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val)) - return -ENODEV; - if (!(val & 0x0001)) { - if (force_addr) { - dev_info(&adapter->dev, "enabling sensors\n"); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(s_bridge, VIA686A_ENABLE_REG, - val | 0x0001)) - return -ENODEV; - } else { - dev_warn(&adapter->dev, "sensors disabled - enable " - "with force_addr=0x%x\n", address); - return -ENODEV; - } - } + struct resource *res; + int err; /* Reserve the ISA region */ - if (!request_region(address, VIA686A_EXTENT, + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, VIA686A_EXTENT, via686a_driver.driver.name)) { - dev_err(&adapter->dev, "region 0x%x already in use!\n", - address); + dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n", + (unsigned long)res->start, (unsigned long)res->end); return -ENODEV; } @@ -672,30 +615,19 @@ static int via686a_detect(struct i2c_adapter *adapter) goto exit_release; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &via686a_driver; - new_client->flags = 0; - - /* Fill in the remaining client fields and put into the global list */ - strlcpy(new_client->name, client_name, I2C_NAME_SIZE); - - data->valid = 0; + platform_set_drvdata(pdev, data); + data->addr = res->start; + data->name = "via686a"; mutex_init(&data->update_lock); - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) - goto exit_free; /* Initialize the VIA686A chip */ - via686a_init_client(new_client); + via686a_init_device(data); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &via686a_group))) - goto exit_detach; + if ((err = sysfs_create_group(&pdev->dev.kobj, &via686a_group))) + goto exit_free; - data->class_dev = hwmon_device_register(&new_client->dev); + data->class_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto exit_remove_files; @@ -704,51 +636,46 @@ static int via686a_detect(struct i2c_adapter *adapter) return 0; exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &via686a_group); -exit_detach: - i2c_detach_client(new_client); + sysfs_remove_group(&pdev->dev.kobj, &via686a_group); exit_free: kfree(data); exit_release: - release_region(address, VIA686A_EXTENT); + release_region(res->start, VIA686A_EXTENT); return err; } -static int via686a_detach_client(struct i2c_client *client) +static int __devexit via686a_remove(struct platform_device *pdev) { - struct via686a_data *data = i2c_get_clientdata(client); - int err; + struct via686a_data *data = platform_get_drvdata(pdev); hwmon_device_unregister(data->class_dev); - sysfs_remove_group(&client->dev.kobj, &via686a_group); + sysfs_remove_group(&pdev->dev.kobj, &via686a_group); - if ((err = i2c_detach_client(client))) - return err; - - release_region(client->addr, VIA686A_EXTENT); + release_region(data->addr, VIA686A_EXTENT); + platform_set_drvdata(pdev, NULL); kfree(data); return 0; } -static void via686a_init_client(struct i2c_client *client) +static void __devinit via686a_init_device(struct via686a_data *data) { u8 reg; /* Start monitoring */ - reg = via686a_read_value(client, VIA686A_REG_CONFIG); - via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F); + reg = via686a_read_value(data, VIA686A_REG_CONFIG); + via686a_write_value(data, VIA686A_REG_CONFIG, (reg | 0x01) & 0x7F); /* Configure temp interrupt mode for continuous-interrupt operation */ - via686a_write_value(client, VIA686A_REG_TEMP_MODE, - via686a_read_value(client, VIA686A_REG_TEMP_MODE) & - !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS)); + reg = via686a_read_value(data, VIA686A_REG_TEMP_MODE); + via686a_write_value(data, VIA686A_REG_TEMP_MODE, + (reg & ~VIA686A_TEMP_MODE_MASK) + | VIA686A_TEMP_MODE_CONTINUOUS); } static struct via686a_data *via686a_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct via686a_data *data = i2c_get_clientdata(client); + struct via686a_data *data = dev_get_drvdata(dev); int i; mutex_lock(&data->update_lock); @@ -757,27 +684,27 @@ static struct via686a_data *via686a_update_device(struct device *dev) || !data->valid) { for (i = 0; i <= 4; i++) { data->in[i] = - via686a_read_value(client, VIA686A_REG_IN(i)); - data->in_min[i] = via686a_read_value(client, + via686a_read_value(data, VIA686A_REG_IN(i)); + data->in_min[i] = via686a_read_value(data, VIA686A_REG_IN_MIN (i)); data->in_max[i] = - via686a_read_value(client, VIA686A_REG_IN_MAX(i)); + via686a_read_value(data, VIA686A_REG_IN_MAX(i)); } for (i = 1; i <= 2; i++) { data->fan[i - 1] = - via686a_read_value(client, VIA686A_REG_FAN(i)); - data->fan_min[i - 1] = via686a_read_value(client, + via686a_read_value(data, VIA686A_REG_FAN(i)); + data->fan_min[i - 1] = via686a_read_value(data, VIA686A_REG_FAN_MIN(i)); } for (i = 0; i <= 2; i++) { - data->temp[i] = via686a_read_value(client, + data->temp[i] = via686a_read_value(data, VIA686A_REG_TEMP[i]) << 2; data->temp_over[i] = - via686a_read_value(client, + via686a_read_value(data, VIA686A_REG_TEMP_OVER[i]); data->temp_hyst[i] = - via686a_read_value(client, + via686a_read_value(data, VIA686A_REG_TEMP_HYST[i]); } /* add in lower 2 bits @@ -785,23 +712,23 @@ static struct via686a_data *via686a_update_device(struct device *dev) temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23 temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23 */ - data->temp[0] |= (via686a_read_value(client, + data->temp[0] |= (via686a_read_value(data, VIA686A_REG_TEMP_LOW1) & 0xc0) >> 6; data->temp[1] |= - (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) & + (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & 0x30) >> 4; data->temp[2] |= - (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) & + (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & 0xc0) >> 6; - i = via686a_read_value(client, VIA686A_REG_FANDIV); + i = via686a_read_value(data, VIA686A_REG_FANDIV); data->fan_div[0] = (i >> 4) & 0x03; data->fan_div[1] = i >> 6; data->alarms = - via686a_read_value(client, + via686a_read_value(data, VIA686A_REG_ALARM1) | - (via686a_read_value(client, VIA686A_REG_ALARM2) << 8); + (via686a_read_value(data, VIA686A_REG_ALARM2) << 8); data->last_updated = jiffies; data->valid = 1; } @@ -818,32 +745,102 @@ static struct pci_device_id via686a_pci_ids[] = { MODULE_DEVICE_TABLE(pci, via686a_pci_ids); +static int __devinit via686a_device_add(unsigned short address) +{ + struct resource res = { + .start = address, + .end = address + VIA686A_EXTENT - 1, + .name = "via686a", + .flags = IORESOURCE_IO, + }; + int err; + + pdev = platform_device_alloc("via686a", address); + if (!pdev) { + err = -ENOMEM; + printk(KERN_ERR "via686a: Device allocation failed\n"); + goto exit; + } + + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + printk(KERN_ERR "via686a: Device resource addition failed " + "(%d)\n", err); + goto exit_device_put; + } + + err = platform_device_add(pdev); + if (err) { + printk(KERN_ERR "via686a: Device addition failed (%d)\n", + err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit: + return err; +} + static int __devinit via686a_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { - u16 val; + u16 address, val; + if (force_addr) { + address = force_addr & ~(VIA686A_EXTENT - 1); + dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address); + if (PCIBIOS_SUCCESSFUL != + pci_write_config_word(dev, VIA686A_BASE_REG, address | 1)) + return -ENODEV; + } if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VIA686A_BASE_REG, &val)) return -ENODEV; address = val & ~(VIA686A_EXTENT - 1); - if (address == 0 && force_addr == 0) { + if (address == 0) { dev_err(&dev->dev, "base address not set - upgrade BIOS " "or use force_addr=0xaddr\n"); return -ENODEV; } - s_bridge = pci_dev_get(dev); - if (i2c_isa_add_driver(&via686a_driver)) { - pci_dev_put(s_bridge); - s_bridge = NULL; + if (PCIBIOS_SUCCESSFUL != + pci_read_config_word(dev, VIA686A_ENABLE_REG, &val)) + return -ENODEV; + if (!(val & 0x0001)) { + if (!force_addr) { + dev_warn(&dev->dev, "Sensors disabled, enable " + "with force_addr=0x%x\n", address); + return -ENODEV; + } + + dev_warn(&dev->dev, "Enabling sensors\n"); + if (PCIBIOS_SUCCESSFUL != + pci_write_config_word(dev, VIA686A_ENABLE_REG, + val | 0x0001)) + return -ENODEV; } + if (platform_driver_register(&via686a_driver)) + goto exit; + + /* Sets global pdev as a side effect */ + if (via686a_device_add(address)) + goto exit_unregister; + /* Always return failure here. This is to allow other drivers to bind * to this pci device. We don't really want to have control over the * pci device, we only wanted to read as few register values from it. */ + s_bridge = pci_dev_get(dev); + return -ENODEV; + +exit_unregister: + platform_driver_unregister(&via686a_driver); +exit: return -ENODEV; } @@ -862,7 +859,8 @@ static void __exit sm_via686a_exit(void) { pci_unregister_driver(&via686a_pci_driver); if (s_bridge != NULL) { - i2c_isa_del_driver(&via686a_driver); + platform_device_unregister(pdev); + platform_driver_unregister(&via686a_driver); pci_dev_put(s_bridge); s_bridge = NULL; } diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index a6a4aa0eee16..3e63eaf19041 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -29,8 +29,7 @@ #include <linux/slab.h> #include <linux/pci.h> #include <linux/jiffies.h> -#include <linux/i2c.h> -#include <linux/i2c-isa.h> +#include <linux/platform_device.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/hwmon-vid.h> @@ -42,10 +41,7 @@ static int force_addr; module_param(force_addr, int, 0); MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors"); -/* Device address - Note that we can't determine the ISA address until we have initialized - our module */ -static unsigned short isa_address; +static struct platform_device *pdev; #define VT8231_EXTENT 0x80 #define VT8231_BASE_REG 0x70 @@ -148,7 +144,9 @@ static inline u8 FAN_TO_REG(long rpm, int div) #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : 1310720 / ((val) * (div))) struct vt8231_data { - struct i2c_client client; + unsigned short addr; + const char *name; + struct mutex update_lock; struct class_device *class_dev; char valid; /* !=0 if following fields are valid */ @@ -168,20 +166,20 @@ struct vt8231_data { }; static struct pci_dev *s_bridge; -static int vt8231_detect(struct i2c_adapter *adapter); -static int vt8231_detach_client(struct i2c_client *client); +static int vt8231_probe(struct platform_device *pdev); +static int __devexit vt8231_remove(struct platform_device *pdev); static struct vt8231_data *vt8231_update_device(struct device *dev); -static void vt8231_init_client(struct i2c_client *client); +static void vt8231_init_device(struct vt8231_data *data); -static inline int vt8231_read_value(struct i2c_client *client, u8 reg) +static inline int vt8231_read_value(struct vt8231_data *data, u8 reg) { - return inb_p(client->addr + reg); + return inb_p(data->addr + reg); } -static inline void vt8231_write_value(struct i2c_client *client, u8 reg, +static inline void vt8231_write_value(struct vt8231_data *data, u8 reg, u8 value) { - outb_p(value, client->addr + reg); + outb_p(value, data->addr + reg); } /* following are the sysfs callback functions */ @@ -220,13 +218,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); - vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]); + vt8231_write_value(data, regvoltmin[nr], data->in_min[nr]); mutex_unlock(&data->update_lock); return count; } @@ -236,13 +233,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); - vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]); + vt8231_write_value(data, regvoltmax[nr], data->in_max[nr]); mutex_unlock(&data->update_lock); return count; } @@ -278,14 +274,13 @@ static ssize_t show_in5_max(struct device *dev, struct device_attribute *attr, static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, 0, 255); - vt8231_write_value(client, regvoltmin[5], data->in_min[5]); + vt8231_write_value(data, regvoltmin[5], data->in_min[5]); mutex_unlock(&data->update_lock); return count; } @@ -293,14 +288,13 @@ static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr, static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, 0, 255); - vt8231_write_value(client, regvoltmax[5], data->in_max[5]); + vt8231_write_value(data, regvoltmax[5], data->in_max[5]); mutex_unlock(&data->update_lock); return count; } @@ -348,26 +342,24 @@ static ssize_t show_temp0_min(struct device *dev, struct device_attribute *attr, static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); - vt8231_write_value(client, regtempmax[0], data->temp_max[0]); + vt8231_write_value(data, regtempmax[0], data->temp_max[0]); mutex_unlock(&data->update_lock); return count; } static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); - vt8231_write_value(client, regtempmin[0], data->temp_min[0]); + vt8231_write_value(data, regtempmin[0], data->temp_min[0]); mutex_unlock(&data->update_lock); return count; } @@ -404,13 +396,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); - vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]); + vt8231_write_value(data, regtempmax[nr], data->temp_max[nr]); mutex_unlock(&data->update_lock); return count; } @@ -419,13 +410,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); int val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); - vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]); + vt8231_write_value(data, regtempmin[nr], data->temp_min[nr]); mutex_unlock(&data->update_lock); return count; } @@ -486,13 +476,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); int val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); + vt8231_write_value(data, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; } @@ -500,12 +489,11 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); unsigned long val = simple_strtoul(buf, NULL, 10); int nr = sensor_attr->index; - int old = vt8231_read_value(client, VT8231_REG_FANDIV); + int old = vt8231_read_value(data, VT8231_REG_FANDIV); long min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); @@ -516,7 +504,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, case 4: data->fan_div[nr] = 2; break; case 8: data->fan_div[nr] = 3; break; default: - dev_err(&client->dev, "fan_div value %ld not supported." + dev_err(dev, "fan_div value %ld not supported." "Choose one of 1, 2, 4 or 8!\n", val); mutex_unlock(&data->update_lock); return -EINVAL; @@ -524,10 +512,10 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, /* Correct the fan minimum speed */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); + vt8231_write_value(data, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); - vt8231_write_value(client, VT8231_REG_FANDIV, old); + vt8231_write_value(data, VT8231_REG_FANDIV, old); mutex_unlock(&data->update_lock); return count; } @@ -551,9 +539,16 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, struct vt8231_data *data = vt8231_update_device(dev); return sprintf(buf, "%d\n", data->alarms); } - static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_name(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct vt8231_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%s\n", data->name); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + static struct attribute *vt8231_attributes_temps[6][4] = { { &dev_attr_temp1_input.attr, @@ -648,6 +643,7 @@ static struct attribute *vt8231_attributes[] = { &sensor_dev_attr_fan1_div.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, &dev_attr_alarms.attr, + &dev_attr_name.attr, NULL }; @@ -655,13 +651,13 @@ static const struct attribute_group vt8231_group = { .attrs = vt8231_attributes, }; -static struct i2c_driver vt8231_driver = { +static struct platform_driver vt8231_driver = { .driver = { .owner = THIS_MODULE, .name = "vt8231", }, - .attach_adapter = vt8231_detect, - .detach_client = vt8231_detach_client, + .probe = vt8231_probe, + .remove = __devexit_p(vt8231_remove), }; static struct pci_device_id vt8231_pci_ids[] = { @@ -680,40 +676,18 @@ static struct pci_driver vt8231_pci_driver = { .probe = vt8231_pci_probe, }; -int vt8231_detect(struct i2c_adapter *adapter) +int vt8231_probe(struct platform_device *pdev) { - struct i2c_client *client; + struct resource *res; struct vt8231_data *data; int err = 0, i; - u16 val; - - /* 8231 requires multiple of 256 */ - if (force_addr) { - isa_address = force_addr & 0xFF00; - dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", - isa_address); - if (PCIBIOS_SUCCESSFUL != pci_write_config_word(s_bridge, - VT8231_BASE_REG, isa_address)) - return -ENODEV; - } - - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(s_bridge, VT8231_ENABLE_REG, &val)) - return -ENODEV; - - if (!(val & 0x0001)) { - dev_warn(&adapter->dev, "enabling sensors\n"); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(s_bridge, VT8231_ENABLE_REG, - val | 0x0001)) - return -ENODEV; - } /* Reserve the ISA region */ - if (!request_region(isa_address, VT8231_EXTENT, - vt8231_pci_driver.name)) { - dev_err(&adapter->dev, "region 0x%x already in use!\n", - isa_address); + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, VT8231_EXTENT, + vt8231_driver.driver.name)) { + dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n", + (unsigned long)res->start, (unsigned long)res->end); return -ENODEV; } @@ -722,33 +696,23 @@ int vt8231_detect(struct i2c_adapter *adapter) goto exit_release; } - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = isa_address; - client->adapter = adapter; - client->driver = &vt8231_driver; - - /* Fill in the remaining client fields and put into the global list */ - strlcpy(client->name, "vt8231", I2C_NAME_SIZE); + platform_set_drvdata(pdev, data); + data->addr = res->start; + data->name = "vt8231"; mutex_init(&data->update_lock); - - /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto exit_free; - - vt8231_init_client(client); + vt8231_init_device(data); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&client->dev.kobj, &vt8231_group))) - goto exit_detach; + if ((err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group))) + goto exit_free; /* Must update device information to find out the config field */ - data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG); + data->uch_config = vt8231_read_value(data, VT8231_REG_UCH_CONFIG); for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) { if (ISTEMP(i, data->uch_config)) { - if ((err = sysfs_create_group(&client->dev.kobj, + if ((err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group_temps[i]))) goto exit_remove_files; } @@ -756,13 +720,13 @@ int vt8231_detect(struct i2c_adapter *adapter) for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) { if (ISVOLT(i, data->uch_config)) { - if ((err = sysfs_create_group(&client->dev.kobj, + if ((err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group_volts[i]))) goto exit_remove_files; } } - data->class_dev = hwmon_device_register(&client->dev); + data->class_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto exit_remove_files; @@ -771,56 +735,52 @@ int vt8231_detect(struct i2c_adapter *adapter) exit_remove_files: for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) - sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]); + sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_volts[i]); for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) - sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]); + sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]); + + sysfs_remove_group(&pdev->dev.kobj, &vt8231_group); - sysfs_remove_group(&client->dev.kobj, &vt8231_group); -exit_detach: - i2c_detach_client(client); exit_free: + platform_set_drvdata(pdev, NULL); kfree(data); + exit_release: - release_region(isa_address, VT8231_EXTENT); + release_region(res->start, VT8231_EXTENT); return err; } -static int vt8231_detach_client(struct i2c_client *client) +static int __devexit vt8231_remove(struct platform_device *pdev) { - struct vt8231_data *data = i2c_get_clientdata(client); - int err, i; + struct vt8231_data *data = platform_get_drvdata(pdev); + int i; hwmon_device_unregister(data->class_dev); for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) - sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]); + sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_volts[i]); for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) - sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]); + sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]); - sysfs_remove_group(&client->dev.kobj, &vt8231_group); + sysfs_remove_group(&pdev->dev.kobj, &vt8231_group); - if ((err = i2c_detach_client(client))) { - return err; - } - - release_region(client->addr, VT8231_EXTENT); + release_region(data->addr, VT8231_EXTENT); + platform_set_drvdata(pdev, NULL); kfree(data); - return 0; } -static void vt8231_init_client(struct i2c_client *client) +static void vt8231_init_device(struct vt8231_data *data) { - vt8231_write_value(client, VT8231_REG_TEMP1_CONFIG, 0); - vt8231_write_value(client, VT8231_REG_TEMP2_CONFIG, 0); + vt8231_write_value(data, VT8231_REG_TEMP1_CONFIG, 0); + vt8231_write_value(data, VT8231_REG_TEMP2_CONFIG, 0); } static struct vt8231_data *vt8231_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct vt8231_data *data = i2c_get_clientdata(client); + struct vt8231_data *data = dev_get_drvdata(dev); int i; u16 low; @@ -830,41 +790,41 @@ static struct vt8231_data *vt8231_update_device(struct device *dev) || !data->valid) { for (i = 0; i < 6; i++) { if (ISVOLT(i, data->uch_config)) { - data->in[i] = vt8231_read_value(client, + data->in[i] = vt8231_read_value(data, regvolt[i]); - data->in_min[i] = vt8231_read_value(client, + data->in_min[i] = vt8231_read_value(data, regvoltmin[i]); - data->in_max[i] = vt8231_read_value(client, + data->in_max[i] = vt8231_read_value(data, regvoltmax[i]); } } for (i = 0; i < 2; i++) { - data->fan[i] = vt8231_read_value(client, + data->fan[i] = vt8231_read_value(data, VT8231_REG_FAN(i)); - data->fan_min[i] = vt8231_read_value(client, + data->fan_min[i] = vt8231_read_value(data, VT8231_REG_FAN_MIN(i)); } - low = vt8231_read_value(client, VT8231_REG_TEMP_LOW01); + low = vt8231_read_value(data, VT8231_REG_TEMP_LOW01); low = (low >> 6) | ((low & 0x30) >> 2) - | (vt8231_read_value(client, VT8231_REG_TEMP_LOW25) << 4); + | (vt8231_read_value(data, VT8231_REG_TEMP_LOW25) << 4); for (i = 0; i < 6; i++) { if (ISTEMP(i, data->uch_config)) { - data->temp[i] = (vt8231_read_value(client, + data->temp[i] = (vt8231_read_value(data, regtemp[i]) << 2) | ((low >> (2 * i)) & 0x03); - data->temp_max[i] = vt8231_read_value(client, + data->temp_max[i] = vt8231_read_value(data, regtempmax[i]); - data->temp_min[i] = vt8231_read_value(client, + data->temp_min[i] = vt8231_read_value(data, regtempmin[i]); } } - i = vt8231_read_value(client, VT8231_REG_FANDIV); + i = vt8231_read_value(data, VT8231_REG_FANDIV); data->fan_div[0] = (i >> 4) & 0x03; data->fan_div[1] = i >> 6; - data->alarms = vt8231_read_value(client, VT8231_REG_ALARM1) | - (vt8231_read_value(client, VT8231_REG_ALARM2) << 8); + data->alarms = vt8231_read_value(data, VT8231_REG_ALARM1) | + (vt8231_read_value(data, VT8231_REG_ALARM2) << 8); /* Set alarm flags correctly */ if (!data->fan[0] && data->fan_min[0]) { @@ -888,33 +848,102 @@ static struct vt8231_data *vt8231_update_device(struct device *dev) return data; } +static int __devinit vt8231_device_add(unsigned short address) +{ + struct resource res = { + .start = address, + .end = address + VT8231_EXTENT - 1, + .name = "vt8231", + .flags = IORESOURCE_IO, + }; + int err; + + pdev = platform_device_alloc("vt8231", address); + if (!pdev) { + err = -ENOMEM; + printk(KERN_ERR "vt8231: Device allocation failed\n"); + goto exit; + } + + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + printk(KERN_ERR "vt8231: Device resource addition failed " + "(%d)\n", err); + goto exit_device_put; + } + + err = platform_device_add(pdev); + if (err) { + printk(KERN_ERR "vt8231: Device addition failed (%d)\n", + err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit: + return err; +} + static int __devinit vt8231_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { - u16 val; + u16 address, val; + if (force_addr) { + address = force_addr & 0xff00; + dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", + address); + + if (PCIBIOS_SUCCESSFUL != + pci_write_config_word(dev, VT8231_BASE_REG, address | 1)) + return -ENODEV; + } if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_BASE_REG, &val)) return -ENODEV; - isa_address = val & ~(VT8231_EXTENT - 1); - if (isa_address == 0 && force_addr == 0) { + address = val & ~(VT8231_EXTENT - 1); + if (address == 0) { dev_err(&dev->dev, "base address not set -\ upgrade BIOS or use force_addr=0xaddr\n"); return -ENODEV; } - s_bridge = pci_dev_get(dev); + if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_ENABLE_REG, + &val)) + return -ENODEV; - if (i2c_isa_add_driver(&vt8231_driver)) { - pci_dev_put(s_bridge); - s_bridge = NULL; + if (!(val & 0x0001)) { + dev_warn(&dev->dev, "enabling sensors\n"); + if (PCIBIOS_SUCCESSFUL != + pci_write_config_word(dev, VT8231_ENABLE_REG, + val | 0x0001)) + return -ENODEV; } + if (platform_driver_register(&vt8231_driver)) + goto exit; + + /* Sets global pdev as a side effect */ + if (vt8231_device_add(address)) + goto exit_unregister; + /* Always return failure here. This is to allow other drivers to bind * to this pci device. We don't really want to have control over the * pci device, we only wanted to read as few register values from it. */ + + /* We do, however, mark ourselves as using the PCI device to stop it + getting unloaded. */ + s_bridge = pci_dev_get(dev); + return -ENODEV; + +exit_unregister: + platform_driver_unregister(&vt8231_driver); +exit: return -ENODEV; } @@ -927,7 +956,8 @@ static void __exit sm_vt8231_exit(void) { pci_unregister_driver(&vt8231_pci_driver); if (s_bridge != NULL) { - i2c_isa_del_driver(&vt8231_driver); + platform_device_unregister(pdev); + platform_driver_unregister(&vt8231_driver); pci_dev_put(s_bridge); s_bridge = NULL; } diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 30a76404f0af..d9a9ec7dd84a 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -41,41 +41,39 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/i2c-isa.h> +#include <linux/jiffies.h> +#include <linux/platform_device.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> +#include <linux/hwmon-vid.h> #include <linux/err.h> #include <linux/mutex.h> #include <asm/io.h> #include "lm75.h" -/* The actual ISA address is read from Super-I/O configuration space */ -static unsigned short address; +enum kinds { w83627ehf, w83627dhg }; -/* - * Super-I/O constants and functions - */ +/* used to set data->name = w83627ehf_device_names[data->sio_kind] */ +static const char * w83627ehf_device_names[] = { + "w83627ehf", + "w83627dhg", +}; + +#define DRVNAME "w83627ehf" /* - * The three following globals are initialized in w83627ehf_find(), before - * the i2c-isa device is created. Otherwise, they could be stored in - * w83627ehf_data. This is ugly, but necessary, and when the driver is next - * updated to become a platform driver, the globals will disappear. + * Super-I/O constants and functions */ -static int REG; /* The register to read/write */ -static int VAL; /* The value to read/write */ -/* The w83627ehf/ehg have 10 voltage inputs, but the w83627dhg has 9. This - * value is also used in w83627ehf_detect() to export a device name in sysfs - * (e.g. w83627ehf or w83627dhg) */ -static int w83627ehf_num_in; #define W83627EHF_LD_HWM 0x0b #define SIO_REG_LDSEL 0x07 /* Logical device select */ #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_EN_VRM10 0x2C /* GPIO3, GPIO4 selection */ #define SIO_REG_ENABLE 0x30 /* Logical device enable */ #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ +#define SIO_REG_VID_CTRL 0xF0 /* VID control */ +#define SIO_REG_VID_DATA 0xF1 /* VID data */ #define SIO_W83627EHF_ID 0x8850 #define SIO_W83627EHG_ID 0x8860 @@ -83,38 +81,38 @@ static int w83627ehf_num_in; #define SIO_ID_MASK 0xFFF0 static inline void -superio_outb(int reg, int val) +superio_outb(int ioreg, int reg, int val) { - outb(reg, REG); - outb(val, VAL); + outb(reg, ioreg); + outb(val, ioreg + 1); } static inline int -superio_inb(int reg) +superio_inb(int ioreg, int reg) { - outb(reg, REG); - return inb(VAL); + outb(reg, ioreg); + return inb(ioreg + 1); } static inline void -superio_select(int ld) +superio_select(int ioreg, int ld) { - outb(SIO_REG_LDSEL, REG); - outb(ld, VAL); + outb(SIO_REG_LDSEL, ioreg); + outb(ld, ioreg + 1); } static inline void -superio_enter(void) +superio_enter(int ioreg) { - outb(0x87, REG); - outb(0x87, REG); + outb(0x87, ioreg); + outb(0x87, ioreg); } static inline void -superio_exit(void) +superio_exit(int ioreg) { - outb(0x02, REG); - outb(0x02, VAL); + outb(0x02, ioreg); + outb(0x02, ioreg + 1); } /* @@ -124,8 +122,8 @@ superio_exit(void) #define IOREGION_ALIGNMENT ~7 #define IOREGION_OFFSET 5 #define IOREGION_LENGTH 2 -#define ADDR_REG_OFFSET 5 -#define DATA_REG_OFFSET 6 +#define ADDR_REG_OFFSET 0 +#define DATA_REG_OFFSET 1 #define W83627EHF_REG_BANK 0x4E #define W83627EHF_REG_CONFIG 0x40 @@ -255,7 +253,9 @@ static inline u8 in_to_reg(u32 val, u8 nr) */ struct w83627ehf_data { - struct i2c_client client; + int addr; /* IO base of hw monitor block */ + const char *name; + struct class_device *class_dev; struct mutex lock; @@ -264,6 +264,7 @@ struct w83627ehf_data { unsigned long last_updated; /* In jiffies */ /* Register values */ + u8 in_num; /* number of in inputs we have */ u8 in[10]; /* Register value */ u8 in_max[10]; /* Register value */ u8 in_min[10]; /* Register value */ @@ -271,6 +272,7 @@ struct w83627ehf_data { u8 fan_min[5]; u8 fan_div[5]; u8 has_fan; /* some fan inputs can be disabled */ + u8 temp_type[3]; s8 temp1; s8 temp1_max; s8 temp1_max_hyst; @@ -288,6 +290,14 @@ struct w83627ehf_data { u8 fan_min_output[4]; /* minimum fan speed */ u8 fan_stop_time[4]; + + u8 vid; + u8 vrm; +}; + +struct w83627ehf_sio_data { + int sioreg; + enum kinds kind; }; static inline int is_word_sized(u16 reg) @@ -299,160 +309,161 @@ static inline int is_word_sized(u16 reg) || (reg & 0x00ff) == 0x55)); } -/* We assume that the default bank is 0, thus the following two functions do - nothing for registers which live in bank 0. For others, they respectively - set the bank register to the correct value (before the register is - accessed), and back to 0 (afterwards). */ -static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg) +/* Registers 0x50-0x5f are banked */ +static inline void w83627ehf_set_bank(struct w83627ehf_data *data, u16 reg) { - if (reg & 0xff00) { - outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET); - outb_p(reg >> 8, client->addr + DATA_REG_OFFSET); + if ((reg & 0x00f0) == 0x50) { + outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET); + outb_p(reg >> 8, data->addr + DATA_REG_OFFSET); } } -static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg) +/* Not strictly necessary, but play it safe for now */ +static inline void w83627ehf_reset_bank(struct w83627ehf_data *data, u16 reg) { if (reg & 0xff00) { - outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET); - outb_p(0, client->addr + DATA_REG_OFFSET); + outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET); + outb_p(0, data->addr + DATA_REG_OFFSET); } } -static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg) +static u16 w83627ehf_read_value(struct w83627ehf_data *data, u16 reg) { - struct w83627ehf_data *data = i2c_get_clientdata(client); int res, word_sized = is_word_sized(reg); mutex_lock(&data->lock); - w83627ehf_set_bank(client, reg); - outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); - res = inb_p(client->addr + DATA_REG_OFFSET); + w83627ehf_set_bank(data, reg); + outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); + res = inb_p(data->addr + DATA_REG_OFFSET); if (word_sized) { outb_p((reg & 0xff) + 1, - client->addr + ADDR_REG_OFFSET); - res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET); + data->addr + ADDR_REG_OFFSET); + res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET); } - w83627ehf_reset_bank(client, reg); + w83627ehf_reset_bank(data, reg); mutex_unlock(&data->lock); return res; } -static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value) +static int w83627ehf_write_value(struct w83627ehf_data *data, u16 reg, u16 value) { - struct w83627ehf_data *data = i2c_get_clientdata(client); int word_sized = is_word_sized(reg); mutex_lock(&data->lock); - w83627ehf_set_bank(client, reg); - outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET); + w83627ehf_set_bank(data, reg); + outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET); if (word_sized) { - outb_p(value >> 8, client->addr + DATA_REG_OFFSET); + outb_p(value >> 8, data->addr + DATA_REG_OFFSET); outb_p((reg & 0xff) + 1, - client->addr + ADDR_REG_OFFSET); + data->addr + ADDR_REG_OFFSET); } - outb_p(value & 0xff, client->addr + DATA_REG_OFFSET); - w83627ehf_reset_bank(client, reg); + outb_p(value & 0xff, data->addr + DATA_REG_OFFSET); + w83627ehf_reset_bank(data, reg); mutex_unlock(&data->lock); return 0; } /* This function assumes that the caller holds data->update_lock */ -static void w83627ehf_write_fan_div(struct i2c_client *client, int nr) +static void w83627ehf_write_fan_div(struct w83627ehf_data *data, int nr) { - struct w83627ehf_data *data = i2c_get_clientdata(client); u8 reg; switch (nr) { case 0: - reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf) + reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV1) & 0xcf) | ((data->fan_div[0] & 0x03) << 4); /* fan5 input control bit is write only, compute the value */ reg |= (data->has_fan & (1 << 4)) ? 1 : 0; - w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg); - reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf) + w83627ehf_write_value(data, W83627EHF_REG_FANDIV1, reg); + reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0xdf) | ((data->fan_div[0] & 0x04) << 3); - w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg); + w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg); break; case 1: - reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f) + reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV1) & 0x3f) | ((data->fan_div[1] & 0x03) << 6); /* fan5 input control bit is write only, compute the value */ reg |= (data->has_fan & (1 << 4)) ? 1 : 0; - w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg); - reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf) + w83627ehf_write_value(data, W83627EHF_REG_FANDIV1, reg); + reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0xbf) | ((data->fan_div[1] & 0x04) << 4); - w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg); + w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg); break; case 2: - reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f) + reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV2) & 0x3f) | ((data->fan_div[2] & 0x03) << 6); - w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg); - reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f) + w83627ehf_write_value(data, W83627EHF_REG_FANDIV2, reg); + reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0x7f) | ((data->fan_div[2] & 0x04) << 5); - w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg); + w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg); break; case 3: - reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc) + reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0xfc) | (data->fan_div[3] & 0x03); - w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg); - reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f) + w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg); + reg = (w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT) & 0x7f) | ((data->fan_div[3] & 0x04) << 5); - w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg); + w83627ehf_write_value(data, W83627EHF_REG_SMI_OVT, reg); break; case 4: - reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73) + reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0x73) | ((data->fan_div[4] & 0x03) << 2) | ((data->fan_div[4] & 0x04) << 5); - w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg); + w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg); break; } } +static void w83627ehf_update_fan_div(struct w83627ehf_data *data) +{ + int i; + + i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1); + data->fan_div[0] = (i >> 4) & 0x03; + data->fan_div[1] = (i >> 6) & 0x03; + i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV2); + data->fan_div[2] = (i >> 6) & 0x03; + i = w83627ehf_read_value(data, W83627EHF_REG_VBAT); + data->fan_div[0] |= (i >> 3) & 0x04; + data->fan_div[1] |= (i >> 4) & 0x04; + data->fan_div[2] |= (i >> 5) & 0x04; + if (data->has_fan & ((1 << 3) | (1 << 4))) { + i = w83627ehf_read_value(data, W83627EHF_REG_DIODE); + data->fan_div[3] = i & 0x03; + data->fan_div[4] = ((i >> 2) & 0x03) + | ((i >> 5) & 0x04); + } + if (data->has_fan & (1 << 3)) { + i = w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT); + data->fan_div[3] |= (i >> 5) & 0x04; + } +} + static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627ehf_data *data = i2c_get_clientdata(client); + struct w83627ehf_data *data = dev_get_drvdata(dev); int pwmcfg = 0, tolerance = 0; /* shut up the compiler */ int i; mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + HZ) + if (time_after(jiffies, data->last_updated + HZ + HZ/2) || !data->valid) { /* Fan clock dividers */ - i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = (i >> 6) & 0x03; - i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2); - data->fan_div[2] = (i >> 6) & 0x03; - i = w83627ehf_read_value(client, W83627EHF_REG_VBAT); - data->fan_div[0] |= (i >> 3) & 0x04; - data->fan_div[1] |= (i >> 4) & 0x04; - data->fan_div[2] |= (i >> 5) & 0x04; - if (data->has_fan & ((1 << 3) | (1 << 4))) { - i = w83627ehf_read_value(client, W83627EHF_REG_DIODE); - data->fan_div[3] = i & 0x03; - data->fan_div[4] = ((i >> 2) & 0x03) - | ((i >> 5) & 0x04); - } - if (data->has_fan & (1 << 3)) { - i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT); - data->fan_div[3] |= (i >> 5) & 0x04; - } + w83627ehf_update_fan_div(data); /* Measured voltages and limits */ - for (i = 0; i < w83627ehf_num_in; i++) { - data->in[i] = w83627ehf_read_value(client, + for (i = 0; i < data->in_num; i++) { + data->in[i] = w83627ehf_read_value(data, W83627EHF_REG_IN(i)); - data->in_min[i] = w83627ehf_read_value(client, + data->in_min[i] = w83627ehf_read_value(data, W83627EHF_REG_IN_MIN(i)); - data->in_max[i] = w83627ehf_read_value(client, + data->in_max[i] = w83627ehf_read_value(data, W83627EHF_REG_IN_MAX(i)); } @@ -461,9 +472,9 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) if (!(data->has_fan & (1 << i))) continue; - data->fan[i] = w83627ehf_read_value(client, + data->fan[i] = w83627ehf_read_value(data, W83627EHF_REG_FAN[i]); - data->fan_min[i] = w83627ehf_read_value(client, + data->fan_min[i] = w83627ehf_read_value(data, W83627EHF_REG_FAN_MIN[i]); /* If we failed to measure the fan speed and clock @@ -471,16 +482,16 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) time */ if (data->fan[i] == 0xff && data->fan_div[i] < 0x07) { - dev_dbg(&client->dev, "Increasing fan%d " + dev_dbg(dev, "Increasing fan%d " "clock divider from %u to %u\n", i + 1, div_from_reg(data->fan_div[i]), div_from_reg(data->fan_div[i] + 1)); data->fan_div[i]++; - w83627ehf_write_fan_div(client, i); + w83627ehf_write_fan_div(data, i); /* Preserve min limit if possible */ if (data->fan_min[i] >= 2 && data->fan_min[i] != 255) - w83627ehf_write_value(client, + w83627ehf_write_value(data, W83627EHF_REG_FAN_MIN[i], (data->fan_min[i] /= 2)); } @@ -489,9 +500,9 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) for (i = 0; i < 4; i++) { /* pwmcfg, tolarance mapped for i=0, i=1 to same reg */ if (i != 1) { - pwmcfg = w83627ehf_read_value(client, + pwmcfg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[i]); - tolerance = w83627ehf_read_value(client, + tolerance = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[i]); } data->pwm_mode[i] = @@ -500,14 +511,14 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) data->pwm_enable[i] = ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i]) & 3) + 1; - data->pwm[i] = w83627ehf_read_value(client, + data->pwm[i] = w83627ehf_read_value(data, W83627EHF_REG_PWM[i]); - data->fan_min_output[i] = w83627ehf_read_value(client, + data->fan_min_output[i] = w83627ehf_read_value(data, W83627EHF_REG_FAN_MIN_OUTPUT[i]); - data->fan_stop_time[i] = w83627ehf_read_value(client, + data->fan_stop_time[i] = w83627ehf_read_value(data, W83627EHF_REG_FAN_STOP_TIME[i]); data->target_temp[i] = - w83627ehf_read_value(client, + w83627ehf_read_value(data, W83627EHF_REG_TARGET[i]) & (data->pwm_mode[i] == 1 ? 0x7f : 0xff); data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0)) @@ -515,26 +526,26 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) } /* Measured temperatures and limits */ - data->temp1 = w83627ehf_read_value(client, + data->temp1 = w83627ehf_read_value(data, W83627EHF_REG_TEMP1); - data->temp1_max = w83627ehf_read_value(client, + data->temp1_max = w83627ehf_read_value(data, W83627EHF_REG_TEMP1_OVER); - data->temp1_max_hyst = w83627ehf_read_value(client, + data->temp1_max_hyst = w83627ehf_read_value(data, W83627EHF_REG_TEMP1_HYST); for (i = 0; i < 2; i++) { - data->temp[i] = w83627ehf_read_value(client, + data->temp[i] = w83627ehf_read_value(data, W83627EHF_REG_TEMP[i]); - data->temp_max[i] = w83627ehf_read_value(client, + data->temp_max[i] = w83627ehf_read_value(data, W83627EHF_REG_TEMP_OVER[i]); - data->temp_max_hyst[i] = w83627ehf_read_value(client, + data->temp_max_hyst[i] = w83627ehf_read_value(data, W83627EHF_REG_TEMP_HYST[i]); } - data->alarms = w83627ehf_read_value(client, + data->alarms = w83627ehf_read_value(data, W83627EHF_REG_ALARM1) | - (w83627ehf_read_value(client, + (w83627ehf_read_value(data, W83627EHF_REG_ALARM2) << 8) | - (w83627ehf_read_value(client, + (w83627ehf_read_value(data, W83627EHF_REG_ALARM3) << 16); data->last_updated = jiffies; @@ -567,15 +578,14 @@ static ssize_t \ store_in_##reg (struct device *dev, struct device_attribute *attr, \ const char *buf, size_t count) \ { \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83627ehf_data *data = i2c_get_clientdata(client); \ + struct w83627ehf_data *data = dev_get_drvdata(dev); \ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ u32 val = simple_strtoul(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ data->in_##reg[nr] = in_to_reg(val, nr); \ - w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \ + w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \ data->in_##reg[nr]); \ mutex_unlock(&data->update_lock); \ return count; \ @@ -673,8 +683,7 @@ static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627ehf_data *data = i2c_get_clientdata(client); + struct w83627ehf_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; unsigned int val = simple_strtoul(buf, NULL, 10); @@ -716,18 +725,25 @@ store_fan_min(struct device *dev, struct device_attribute *attr, /* Write both the fan clock divider (if it changed) and the new fan min (unconditionally) */ if (new_div != data->fan_div[nr]) { - if (new_div > data->fan_div[nr]) - data->fan[nr] >>= (data->fan_div[nr] - new_div); - else - data->fan[nr] <<= (new_div - data->fan_div[nr]); + /* Preserve the fan speed reading */ + if (data->fan[nr] != 0xff) { + if (new_div > data->fan_div[nr]) + data->fan[nr] >>= new_div - data->fan_div[nr]; + else if (data->fan[nr] & 0x80) + data->fan[nr] = 0xff; + else + data->fan[nr] <<= data->fan_div[nr] - new_div; + } dev_dbg(dev, "fan%u clock divider changed from %u to %u\n", nr + 1, div_from_reg(data->fan_div[nr]), div_from_reg(new_div)); data->fan_div[nr] = new_div; - w83627ehf_write_fan_div(client, nr); + w83627ehf_write_fan_div(data, nr); + /* Give the chip time to sample a new speed value */ + data->last_updated = jiffies; } - w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr], + w83627ehf_write_value(data, W83627EHF_REG_FAN_MIN[nr], data->fan_min[nr]); mutex_unlock(&data->update_lock); @@ -788,13 +804,12 @@ static ssize_t \ store_temp1_##reg(struct device *dev, struct device_attribute *attr, \ const char *buf, size_t count) \ { \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83627ehf_data *data = i2c_get_clientdata(client); \ + struct w83627ehf_data *data = dev_get_drvdata(dev); \ u32 val = simple_strtoul(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \ - w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \ + w83627ehf_write_value(data, W83627EHF_REG_TEMP1_##REG, \ data->temp1_##reg); \ mutex_unlock(&data->update_lock); \ return count; \ @@ -822,15 +837,14 @@ static ssize_t \ store_##reg(struct device *dev, struct device_attribute *attr, \ const char *buf, size_t count) \ { \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83627ehf_data *data = i2c_get_clientdata(client); \ + struct w83627ehf_data *data = dev_get_drvdata(dev); \ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ u32 val = simple_strtoul(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ data->reg[nr] = LM75_TEMP_TO_REG(val); \ - w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \ + w83627ehf_write_value(data, W83627EHF_REG_TEMP_##REG[nr], \ data->reg[nr]); \ mutex_unlock(&data->update_lock); \ return count; \ @@ -838,6 +852,15 @@ store_##reg(struct device *dev, struct device_attribute *attr, \ store_temp_reg(OVER, temp_max); store_temp_reg(HYST, temp_max_hyst); +static ssize_t +show_temp_type(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct w83627ehf_data *data = w83627ehf_update_device(dev); + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + return sprintf(buf, "%d\n", (int)data->temp_type[nr]); +} + static struct sensor_device_attribute sda_temp[] = { SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0), SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0), @@ -857,6 +880,9 @@ static struct sensor_device_attribute sda_temp[] = { SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), + SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), + SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), + SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), }; #define show_pwm_reg(reg) \ @@ -877,8 +903,7 @@ static ssize_t store_pwm_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627ehf_data *data = i2c_get_clientdata(client); + struct w83627ehf_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; u32 val = simple_strtoul(buf, NULL, 10); @@ -887,12 +912,12 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, if (val > 1) return -EINVAL; mutex_lock(&data->update_lock); - reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]); + reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]); data->pwm_mode[nr] = val; reg &= ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]); if (!val) reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr]; - w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg); + w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg); mutex_unlock(&data->update_lock); return count; } @@ -901,15 +926,14 @@ static ssize_t store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627ehf_data *data = i2c_get_clientdata(client); + struct w83627ehf_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255); mutex_lock(&data->update_lock); data->pwm[nr] = val; - w83627ehf_write_value(client, W83627EHF_REG_PWM[nr], val); + w83627ehf_write_value(data, W83627EHF_REG_PWM[nr], val); mutex_unlock(&data->update_lock); return count; } @@ -918,8 +942,7 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627ehf_data *data = i2c_get_clientdata(client); + struct w83627ehf_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; u32 val = simple_strtoul(buf, NULL, 10); @@ -928,11 +951,11 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, if (!val || (val > 2)) /* only modes 1 and 2 are supported */ return -EINVAL; mutex_lock(&data->update_lock); - reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]); + reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]); data->pwm_enable[nr] = val; reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]); reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr]; - w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg); + w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg); mutex_unlock(&data->update_lock); return count; } @@ -955,15 +978,14 @@ static ssize_t store_target_temp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627ehf_data *data = i2c_get_clientdata(client); + struct w83627ehf_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 127000); mutex_lock(&data->update_lock); data->target_temp[nr] = val; - w83627ehf_write_value(client, W83627EHF_REG_TARGET[nr], val); + w83627ehf_write_value(data, W83627EHF_REG_TARGET[nr], val); mutex_unlock(&data->update_lock); return count; } @@ -972,8 +994,7 @@ static ssize_t store_tolerance(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct w83627ehf_data *data = i2c_get_clientdata(client); + struct w83627ehf_data *data = dev_get_drvdata(dev); struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; u16 reg; @@ -981,13 +1002,13 @@ store_tolerance(struct device *dev, struct device_attribute *attr, u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 15000); mutex_lock(&data->update_lock); - reg = w83627ehf_read_value(client, W83627EHF_REG_TOLERANCE[nr]); + reg = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[nr]); data->tolerance[nr] = val; if (nr == 1) reg = (reg & 0x0f) | (val << 4); else reg = (reg & 0xf0) | val; - w83627ehf_write_value(client, W83627EHF_REG_TOLERANCE[nr], reg); + w83627ehf_write_value(data, W83627EHF_REG_TOLERANCE[nr], reg); mutex_unlock(&data->update_lock); return count; } @@ -1058,14 +1079,13 @@ static ssize_t \ store_##reg(struct device *dev, struct device_attribute *attr, \ const char *buf, size_t count) \ {\ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83627ehf_data *data = i2c_get_clientdata(client); \ + struct w83627ehf_data *data = dev_get_drvdata(dev); \ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \ mutex_lock(&data->update_lock); \ data->reg[nr] = val; \ - w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \ + w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \ mutex_unlock(&data->update_lock); \ return count; \ } @@ -1087,21 +1107,28 @@ static ssize_t \ store_##reg(struct device *dev, struct device_attribute *attr, \ const char *buf, size_t count) \ { \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83627ehf_data *data = i2c_get_clientdata(client); \ + struct w83627ehf_data *data = dev_get_drvdata(dev); \ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ u8 val = step_time_to_reg(simple_strtoul(buf, NULL, 10), \ data->pwm_mode[nr]); \ mutex_lock(&data->update_lock); \ data->reg[nr] = val; \ - w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \ + w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \ mutex_unlock(&data->update_lock); \ return count; \ } \ fan_time_functions(fan_stop_time, FAN_STOP_TIME) +static ssize_t show_name(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct w83627ehf_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", data->name); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static struct sensor_device_attribute sda_sf3_arrays_fan4[] = { SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, @@ -1125,8 +1152,16 @@ static struct sensor_device_attribute sda_sf3_arrays[] = { store_fan_min_output, 2), }; +static ssize_t +show_vid(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct w83627ehf_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +} +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); + /* - * Driver and client management + * Driver and device management */ static void w83627ehf_device_remove_files(struct device *dev) @@ -1134,12 +1169,13 @@ static void w83627ehf_device_remove_files(struct device *dev) /* some entries in the following arrays may not have been used in * device_create_file(), but device_remove_file() will ignore them */ int i; + struct w83627ehf_data *data = dev_get_drvdata(dev); for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); - for (i = 0; i < w83627ehf_num_in; i++) { + for (i = 0; i < data->in_num; i++) { device_remove_file(dev, &sda_in_input[i].dev_attr); device_remove_file(dev, &sda_in_alarm[i].dev_attr); device_remove_file(dev, &sda_in_min[i].dev_attr); @@ -1160,43 +1196,64 @@ static void w83627ehf_device_remove_files(struct device *dev) } for (i = 0; i < ARRAY_SIZE(sda_temp); i++) device_remove_file(dev, &sda_temp[i].dev_attr); -} -static struct i2c_driver w83627ehf_driver; + device_remove_file(dev, &dev_attr_name); + if (data->vid != 0x3f) + device_remove_file(dev, &dev_attr_cpu0_vid); +} -static void w83627ehf_init_client(struct i2c_client *client) +/* Get the monitoring functions started */ +static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data) { int i; - u8 tmp; + u8 tmp, diode; /* Start monitoring is needed */ - tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG); + tmp = w83627ehf_read_value(data, W83627EHF_REG_CONFIG); if (!(tmp & 0x01)) - w83627ehf_write_value(client, W83627EHF_REG_CONFIG, + w83627ehf_write_value(data, W83627EHF_REG_CONFIG, tmp | 0x01); /* Enable temp2 and temp3 if needed */ for (i = 0; i < 2; i++) { - tmp = w83627ehf_read_value(client, + tmp = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[i]); if (tmp & 0x01) - w83627ehf_write_value(client, + w83627ehf_write_value(data, W83627EHF_REG_TEMP_CONFIG[i], tmp & 0xfe); } + + /* Enable VBAT monitoring if needed */ + tmp = w83627ehf_read_value(data, W83627EHF_REG_VBAT); + if (!(tmp & 0x01)) + w83627ehf_write_value(data, W83627EHF_REG_VBAT, tmp | 0x01); + + /* Get thermal sensor types */ + diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE); + for (i = 0; i < 3; i++) { + if ((tmp & (0x02 << i))) + data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 2; + else + data->temp_type[i] = 4; /* thermistor */ + } } -static int w83627ehf_detect(struct i2c_adapter *adapter) +static int __devinit w83627ehf_probe(struct platform_device *pdev) { - struct i2c_client *client; + struct device *dev = &pdev->dev; + struct w83627ehf_sio_data *sio_data = dev->platform_data; struct w83627ehf_data *data; - struct device *dev; - u8 fan4pin, fan5pin; + struct resource *res; + u8 fan4pin, fan5pin, en_vrm10; int i, err = 0; - if (!request_region(address + IOREGION_OFFSET, IOREGION_LENGTH, - w83627ehf_driver.driver.name)) { + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, IOREGION_LENGTH, DRVNAME)) { err = -EBUSY; + dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", + (unsigned long)res->start, + (unsigned long)res->start + IOREGION_LENGTH - 1); goto exit; } @@ -1205,41 +1262,47 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) goto exit_release; } - client = &data->client; - i2c_set_clientdata(client, data); - client->addr = address; + data->addr = res->start; mutex_init(&data->lock); - client->adapter = adapter; - client->driver = &w83627ehf_driver; - client->flags = 0; - dev = &client->dev; - - if (w83627ehf_num_in == 9) - strlcpy(client->name, "w83627dhg", I2C_NAME_SIZE); - else /* just say ehf. 627EHG is 627EHF in lead-free packaging. */ - strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE); - - data->valid = 0; mutex_init(&data->update_lock); + data->name = w83627ehf_device_names[sio_data->kind]; + platform_set_drvdata(pdev, data); - /* Tell the i2c layer a new client has arrived */ - if ((err = i2c_attach_client(client))) - goto exit_free; + /* 627EHG and 627EHF have 10 voltage inputs; DHG has 9 */ + data->in_num = (sio_data->kind == w83627dhg) ? 9 : 10; /* Initialize the chip */ - w83627ehf_init_client(client); - - /* A few vars need to be filled upon startup */ - for (i = 0; i < 5; i++) - data->fan_min[i] = w83627ehf_read_value(client, - W83627EHF_REG_FAN_MIN[i]); + w83627ehf_init_device(data); + + data->vrm = vid_which_vrm(); + superio_enter(sio_data->sioreg); + /* Set VID input sensibility if needed. In theory the BIOS should + have set it, but in practice it's not always the case. */ + en_vrm10 = superio_inb(sio_data->sioreg, SIO_REG_EN_VRM10); + if ((en_vrm10 & 0x08) && data->vrm != 100) { + dev_warn(dev, "Setting VID input voltage to TTL\n"); + superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10, + en_vrm10 & ~0x08); + } else if (!(en_vrm10 & 0x08) && data->vrm == 100) { + dev_warn(dev, "Setting VID input voltage to VRM10\n"); + superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10, + en_vrm10 | 0x08); + } + /* Read VID value */ + superio_select(sio_data->sioreg, W83627EHF_LD_HWM); + if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) + data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA) & 0x3f; + else { + dev_info(dev, "VID pins in output mode, CPU VID not " + "available\n"); + data->vid = 0x3f; + } /* fan4 and fan5 share some pins with the GPIO and serial flash */ - superio_enter(); - fan5pin = superio_inb(0x24) & 0x2; - fan4pin = superio_inb(0x29) & 0x6; - superio_exit(); + fan5pin = superio_inb(sio_data->sioreg, 0x24) & 0x2; + fan4pin = superio_inb(sio_data->sioreg, 0x29) & 0x6; + superio_exit(sio_data->sioreg); /* It looks like fan4 and fan5 pins can be alternatively used as fan on/off switches, but fan5 control is write only :/ @@ -1248,12 +1311,15 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) is not the default. */ data->has_fan = 0x07; /* fan1, fan2 and fan3 */ - i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1); + i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1); if ((i & (1 << 2)) && (!fan4pin)) data->has_fan |= (1 << 3); if (!(i & (1 << 1)) && (!fan5pin)) data->has_fan |= (1 << 4); + /* Read fan clock dividers immediately */ + w83627ehf_update_fan_div(data); + /* Register sysfs hooks */ for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) if ((err = device_create_file(dev, @@ -1268,7 +1334,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) goto exit_remove; } - for (i = 0; i < w83627ehf_num_in; i++) + for (i = 0; i < data->in_num; i++) if ((err = device_create_file(dev, &sda_in_input[i].dev_attr)) || (err = device_create_file(dev, &sda_in_alarm[i].dev_attr)) @@ -1308,6 +1374,16 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) if ((err = device_create_file(dev, &sda_temp[i].dev_attr))) goto exit_remove; + err = device_create_file(dev, &dev_attr_name); + if (err) + goto exit_remove; + + if (data->vid != 0x3f) { + err = device_create_file(dev, &dev_attr_cpu0_vid); + if (err) + goto exit_remove; + } + data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); @@ -1318,95 +1394,172 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) exit_remove: w83627ehf_device_remove_files(dev); - i2c_detach_client(client); -exit_free: kfree(data); + platform_set_drvdata(pdev, NULL); exit_release: - release_region(address + IOREGION_OFFSET, IOREGION_LENGTH); + release_region(res->start, IOREGION_LENGTH); exit: return err; } -static int w83627ehf_detach_client(struct i2c_client *client) +static int __devexit w83627ehf_remove(struct platform_device *pdev) { - struct w83627ehf_data *data = i2c_get_clientdata(client); - int err; + struct w83627ehf_data *data = platform_get_drvdata(pdev); hwmon_device_unregister(data->class_dev); - w83627ehf_device_remove_files(&client->dev); - - if ((err = i2c_detach_client(client))) - return err; - release_region(client->addr + IOREGION_OFFSET, IOREGION_LENGTH); + w83627ehf_device_remove_files(&pdev->dev); + release_region(data->addr, IOREGION_LENGTH); + platform_set_drvdata(pdev, NULL); kfree(data); return 0; } -static struct i2c_driver w83627ehf_driver = { +static struct platform_driver w83627ehf_driver = { .driver = { .owner = THIS_MODULE, - .name = "w83627ehf", + .name = DRVNAME, }, - .attach_adapter = w83627ehf_detect, - .detach_client = w83627ehf_detach_client, + .probe = w83627ehf_probe, + .remove = __devexit_p(w83627ehf_remove), }; -static int __init w83627ehf_find(int sioaddr, unsigned short *addr) +/* w83627ehf_find() looks for a '627 in the Super-I/O config space */ +static int __init w83627ehf_find(int sioaddr, unsigned short *addr, + struct w83627ehf_sio_data *sio_data) { + static const char __initdata sio_name_W83627EHF[] = "W83627EHF"; + static const char __initdata sio_name_W83627EHG[] = "W83627EHG"; + static const char __initdata sio_name_W83627DHG[] = "W83627DHG"; + u16 val; + const char *sio_name; - REG = sioaddr; - VAL = sioaddr + 1; - superio_enter(); + superio_enter(sioaddr); - val = (superio_inb(SIO_REG_DEVID) << 8) - | superio_inb(SIO_REG_DEVID + 1); + val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) + | superio_inb(sioaddr, SIO_REG_DEVID + 1); switch (val & SIO_ID_MASK) { - case SIO_W83627DHG_ID: - w83627ehf_num_in = 9; - break; case SIO_W83627EHF_ID: + sio_data->kind = w83627ehf; + sio_name = sio_name_W83627EHF; + break; case SIO_W83627EHG_ID: - w83627ehf_num_in = 10; + sio_data->kind = w83627ehf; + sio_name = sio_name_W83627EHG; + break; + case SIO_W83627DHG_ID: + sio_data->kind = w83627dhg; + sio_name = sio_name_W83627DHG; break; default: - printk(KERN_WARNING "w83627ehf: unsupported chip ID: 0x%04x\n", - val); - superio_exit(); + if (val != 0xffff) + pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n", + val); + superio_exit(sioaddr); return -ENODEV; } - superio_select(W83627EHF_LD_HWM); - val = (superio_inb(SIO_REG_ADDR) << 8) - | superio_inb(SIO_REG_ADDR + 1); + /* We have a known chip, find the HWM I/O address */ + superio_select(sioaddr, W83627EHF_LD_HWM); + val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8) + | superio_inb(sioaddr, SIO_REG_ADDR + 1); *addr = val & IOREGION_ALIGNMENT; if (*addr == 0) { - superio_exit(); + printk(KERN_ERR DRVNAME ": Refusing to enable a Super-I/O " + "device with a base I/O port 0.\n"); + superio_exit(sioaddr); return -ENODEV; } /* Activate logical device if needed */ - val = superio_inb(SIO_REG_ENABLE); - if (!(val & 0x01)) - superio_outb(SIO_REG_ENABLE, val | 0x01); + val = superio_inb(sioaddr, SIO_REG_ENABLE); + if (!(val & 0x01)) { + printk(KERN_WARNING DRVNAME ": Forcibly enabling Super-I/O. " + "Sensor is probably unusable.\n"); + superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); + } + + superio_exit(sioaddr); + pr_info(DRVNAME ": Found %s chip at %#x\n", sio_name, *addr); + sio_data->sioreg = sioaddr; - superio_exit(); return 0; } +/* when Super-I/O functions move to a separate file, the Super-I/O + * bus will manage the lifetime of the device and this module will only keep + * track of the w83627ehf driver. But since we platform_device_alloc(), we + * must keep track of the device */ +static struct platform_device *pdev; + static int __init sensors_w83627ehf_init(void) { - if (w83627ehf_find(0x2e, &address) - && w83627ehf_find(0x4e, &address)) + int err; + unsigned short address; + struct resource res; + struct w83627ehf_sio_data sio_data; + + /* initialize sio_data->kind and sio_data->sioreg. + * + * when Super-I/O functions move to a separate file, the Super-I/O + * driver will probe 0x2e and 0x4e and auto-detect the presence of a + * w83627ehf hardware monitor, and call probe() */ + if (w83627ehf_find(0x2e, &address, &sio_data) && + w83627ehf_find(0x4e, &address, &sio_data)) return -ENODEV; - return i2c_isa_add_driver(&w83627ehf_driver); + err = platform_driver_register(&w83627ehf_driver); + if (err) + goto exit; + + if (!(pdev = platform_device_alloc(DRVNAME, address))) { + err = -ENOMEM; + printk(KERN_ERR DRVNAME ": Device allocation failed\n"); + goto exit_unregister; + } + + err = platform_device_add_data(pdev, &sio_data, + sizeof(struct w83627ehf_sio_data)); + if (err) { + printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); + goto exit_device_put; + } + + memset(&res, 0, sizeof(res)); + res.name = DRVNAME; + res.start = address + IOREGION_OFFSET; + res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; + res.flags = IORESOURCE_IO; + err = platform_device_add_resources(pdev, &res, 1); + if (err) { + printk(KERN_ERR DRVNAME ": Device resource addition failed " + "(%d)\n", err); + goto exit_device_put; + } + + /* platform_device_add calls probe() */ + err = platform_device_add(pdev); + if (err) { + printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", + err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); +exit_unregister: + platform_driver_unregister(&w83627ehf_driver); +exit: + return err; } static void __exit sensors_w83627ehf_exit(void) { - i2c_isa_del_driver(&w83627ehf_driver); + platform_device_unregister(pdev); + platform_driver_unregister(&w83627ehf_driver); } MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 12cb40a975de..7a4a15f4bf8b 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -220,6 +220,18 @@ static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, #define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \ regpwm_627hf[(nr) - 1] : regpwm[(nr) - 1]) +#define W83627HF_REG_PWM_FREQ 0x5C /* Only for the 627HF */ + +#define W83637HF_REG_PWM_FREQ1 0x00 /* 697HF/687THF too */ +#define W83637HF_REG_PWM_FREQ2 0x02 /* 697HF/687THF too */ +#define W83637HF_REG_PWM_FREQ3 0x10 /* 687THF too */ + +static const u8 W83637HF_REG_PWM_FREQ[] = { W83637HF_REG_PWM_FREQ1, + W83637HF_REG_PWM_FREQ2, + W83637HF_REG_PWM_FREQ3 }; + +#define W83627HF_BASE_PWM_FREQ 46870 + #define W83781D_REG_I2C_ADDR 0x48 #define W83781D_REG_I2C_SUBADDR 0x4A @@ -267,6 +279,49 @@ static int TEMP_FROM_REG(u8 reg) #define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) +static inline unsigned long pwm_freq_from_reg_627hf(u8 reg) +{ + unsigned long freq; + freq = W83627HF_BASE_PWM_FREQ >> reg; + return freq; +} +static inline u8 pwm_freq_to_reg_627hf(unsigned long val) +{ + u8 i; + /* Only 5 dividers (1 2 4 8 16) + Search for the nearest available frequency */ + for (i = 0; i < 4; i++) { + if (val > (((W83627HF_BASE_PWM_FREQ >> i) + + (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2)) + break; + } + return i; +} + +static inline unsigned long pwm_freq_from_reg(u8 reg) +{ + /* Clock bit 8 -> 180 kHz or 24 MHz */ + unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL; + + reg &= 0x7f; + /* This should not happen but anyway... */ + if (reg == 0) + reg++; + return (clock / (reg << 8)); +} +static inline u8 pwm_freq_to_reg(unsigned long val) +{ + /* Minimum divider value is 0x01 and maximum is 0x7F */ + if (val >= 93750) /* The highest we can do */ + return 0x01; + if (val >= 720) /* Use 24 MHz clock */ + return (24000000UL / (val << 8)); + if (val < 6) /* The lowest we can do */ + return 0xFF; + else /* Use 180 kHz clock */ + return (0x80 | (180000UL / (val << 8))); +} + #define BEEP_MASK_FROM_REG(val) (val) #define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) #define BEEP_ENABLE_TO_REG(val) ((val)?1:0) @@ -316,6 +371,7 @@ struct w83627hf_data { u32 beep_mask; /* Register encoding, combined */ u8 beep_enable; /* Boolean */ u8 pwm[3]; /* Register value */ + u8 pwm_freq[3]; /* Register value */ u16 sens[3]; /* 782D/783S only. 1 = pentium diode; 2 = 3904 diode; 3000-5000 = thermistor beta. @@ -331,7 +387,7 @@ struct w83627hf_sio_data { static int w83627hf_probe(struct platform_device *pdev); -static int w83627hf_remove(struct platform_device *pdev); +static int __devexit 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); @@ -852,6 +908,64 @@ sysfs_pwm(2); sysfs_pwm(3); static ssize_t +show_pwm_freq_reg(struct device *dev, char *buf, int nr) +{ + struct w83627hf_data *data = w83627hf_update_device(dev); + if (data->type == w83627hf) + return sprintf(buf, "%ld\n", + pwm_freq_from_reg_627hf(data->pwm_freq[nr - 1])); + else + return sprintf(buf, "%ld\n", + pwm_freq_from_reg(data->pwm_freq[nr - 1])); +} + +static ssize_t +store_pwm_freq_reg(struct device *dev, const char *buf, size_t count, int nr) +{ + struct w83627hf_data *data = dev_get_drvdata(dev); + static const u8 mask[]={0xF8, 0x8F}; + u32 val; + + val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + + if (data->type == w83627hf) { + data->pwm_freq[nr - 1] = pwm_freq_to_reg_627hf(val); + w83627hf_write_value(data, W83627HF_REG_PWM_FREQ, + (data->pwm_freq[nr - 1] << ((nr - 1)*4)) | + (w83627hf_read_value(data, + W83627HF_REG_PWM_FREQ) & mask[nr - 1])); + } else { + data->pwm_freq[nr - 1] = pwm_freq_to_reg(val); + w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr - 1], + data->pwm_freq[nr - 1]); + } + + mutex_unlock(&data->update_lock); + return count; +} + +#define sysfs_pwm_freq(offset) \ +static ssize_t show_regs_pwm_freq_##offset(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + return show_pwm_freq_reg(dev, buf, offset); \ +} \ +static ssize_t \ +store_regs_pwm_freq_##offset(struct device *dev, \ + struct device_attribute *attr, const char *buf, size_t count) \ +{ \ + return store_pwm_freq_reg(dev, buf, count, offset); \ +} \ +static DEVICE_ATTR(pwm##offset##_freq, S_IRUGO | S_IWUSR, \ + show_regs_pwm_freq_##offset, store_regs_pwm_freq_##offset); + +sysfs_pwm_freq(1); +sysfs_pwm_freq(2); +sysfs_pwm_freq(3); + +static ssize_t show_sensor_reg(struct device *dev, char *buf, int nr) { struct w83627hf_data *data = w83627hf_update_device(dev); @@ -1077,6 +1191,9 @@ static struct attribute *w83627hf_attributes_opt[] = { &dev_attr_pwm3.attr, + &dev_attr_pwm1_freq.attr, + &dev_attr_pwm2_freq.attr, + &dev_attr_pwm3_freq.attr, NULL }; @@ -1139,7 +1256,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) || (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))) + || (err = device_create_file(dev, &dev_attr_in6_max)) + || (err = device_create_file(dev, &dev_attr_pwm1_freq)) + || (err = device_create_file(dev, &dev_attr_pwm2_freq))) goto ERROR4; if (data->type != w83697hf) @@ -1169,6 +1288,12 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) if ((err = device_create_file(dev, &dev_attr_pwm3))) goto ERROR4; + if (data->type == w83637hf || data->type == w83687thf) + if ((err = device_create_file(dev, &dev_attr_pwm1_freq)) + || (err = device_create_file(dev, &dev_attr_pwm2_freq)) + || (err = device_create_file(dev, &dev_attr_pwm3_freq))) + goto ERROR4; + data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); @@ -1181,6 +1306,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) sysfs_remove_group(&dev->kobj, &w83627hf_group); sysfs_remove_group(&dev->kobj, &w83627hf_group_opt); ERROR3: + platform_set_drvdata(pdev, NULL); kfree(data); ERROR1: release_region(res->start, WINB_REGION_SIZE); @@ -1193,11 +1319,11 @@ static int __devexit w83627hf_remove(struct platform_device *pdev) 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(&pdev->dev.kobj, &w83627hf_group); sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt); + platform_set_drvdata(pdev, NULL); kfree(data); res = platform_get_resource(pdev, IORESOURCE_IO, 0); @@ -1472,6 +1598,20 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) (data->type == w83627hf || data->type == w83697hf)) break; } + if (data->type == w83627hf) { + u8 tmp = w83627hf_read_value(data, + W83627HF_REG_PWM_FREQ); + data->pwm_freq[0] = tmp & 0x07; + data->pwm_freq[1] = (tmp >> 4) & 0x07; + } else if (data->type != w83627thf) { + for (i = 1; i <= 3; i++) { + data->pwm_freq[i - 1] = + w83627hf_read_value(data, + W83637HF_REG_PWM_FREQ[i - 1]); + if (i == 2 && (data->type == w83697hf)) + break; + } + } data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1)); data->temp_max = @@ -1548,15 +1688,12 @@ static int __init w83627hf_device_add(unsigned short address, goto exit_device_put; } - pdev->dev.platform_data = kmalloc(sizeof(struct w83627hf_sio_data), - GFP_KERNEL); - if (!pdev->dev.platform_data) { - err = -ENOMEM; + err = platform_device_add_data(pdev, sio_data, + sizeof(struct w83627hf_sio_data)); + if (err) { printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); goto exit_device_put; } - memcpy(pdev->dev.platform_data, sio_data, - sizeof(struct w83627hf_sio_data)); err = platform_device_add(pdev); if (err) { diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index c95909cc1d21..dcc941a5aaff 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -1746,7 +1746,7 @@ w83781d_isa_device_add(unsigned short address) { struct resource res = { .start = address, - .end = address + W83781D_EXTENT, + .end = address + W83781D_EXTENT - 1, .name = "w83781d", .flags = IORESOURCE_IO, }; |