OSDN Git Service

Merge branch 'release' of git://lm-sensors.org/kernel/mhoffman/hwmon-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 13 Nov 2007 17:09:36 +0000 (09:09 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 13 Nov 2007 17:09:36 +0000 (09:09 -0800)
* 'release' of git://lm-sensors.org/kernel/mhoffman/hwmon-2.6:
  hwmon: (i5k_amb) Convert macros to C functions
  hwmon: (w83781d) Add missing curly braces
  hwmon: (abituguru3) Identify ABit IP35 Pro as such
  hwmon: (f75375s) pwmX_mode sysfs files writable for f75375 variant
  hwmon: (f75375s) On n2100 systems, set fans to full speed on boot
  hwmon: (f75375s) Allow setting up fans with platform_data
  hwmon: (f75375s) Add new style bindings
  hwmon: (lm70) Convert semaphore to mutex
  hwmon: (applesmc) Add support for Mac Pro 2 x Quad-Core
  hwmon: (abituguru3) Add support for 2 new motherboards
  hwmon: (ibmpex) Change printk to dev_{info,err} macros
  hwmon: (i5k_amb) New memory temperature sensor driver
  hwmon: (f75375s) fix pwm mode setting
  hwmon: (ibmpex.c) fix NULL dereference
  hwmon: (sis5595) Split sis5595_attributes_opt
  hwmon: (sis5595) Add individual alarm files
  hwmon: (w83627hf) push nr+1 offset into *_REG_FAN macros and simplify
  hwmon: (w83627hf) hoist nr-1 offset out of show-store-temp-X
  hwmon: Add power meter spec to Documentation/hwmon/sysfs-interface

15 files changed:
Documentation/hwmon/sysfs-interface
arch/arm/mach-iop32x/n2100.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/abituguru3.c
drivers/hwmon/applesmc.c
drivers/hwmon/f75375s.c
drivers/hwmon/i5k_amb.c [new file with mode: 0644]
drivers/hwmon/ibmpex.c
drivers/hwmon/lm70.c
drivers/hwmon/sis5595.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
include/linux/f75375s.h [new file with mode: 0644]
include/linux/pci_ids.h

index a17b692..f4a8ebc 100644 (file)
@@ -328,6 +328,37 @@ curr[1-*]_input    Current input value
                Unit: milliampere
                RO
 
+*********
+* Power *
+*********
+
+power[1-*]_average             Average power use
+                               Unit: microWatt
+                               RO
+
+power[1-*]_average_highest     Historical average maximum power use
+                               Unit: microWatt
+                               RO
+
+power[1-*]_average_lowest      Historical average minimum power use
+                               Unit: microWatt
+                               RO
+
+power[1-*]_input               Instantaneous power use
+                               Unit: microWatt
+                               RO
+
+power[1-*]_input_highest       Historical maximum power use
+                               Unit: microWatt
+                               RO
+
+power[1-*]_input_lowest                Historical minimum power use
+                               Unit: microWatt
+                               RO
+
+power[1-*]_reset_history       Reset input_highest, input_lowest,
+                               average_highest and average_lowest.
+                               WO
 
 **********
 * Alarms *
index 1873bd8..bc91d6e 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/f75375s.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -200,11 +201,21 @@ static struct platform_device n2100_serial_device = {
        .resource       = &n2100_uart_resource,
 };
 
+static struct f75375s_platform_data n2100_f75375s = {
+       .pwm            = { 255, 255 },
+       .pwm_enable = { 0, 0 },
+};
+
 static struct i2c_board_info __initdata n2100_i2c_devices[] = {
        {
                I2C_BOARD_INFO("rtc-rs5c372", 0x32),
                .type = "rs5c372b",
        },
+       {
+               I2C_BOARD_INFO("f75375", 0x2e),
+               .type = "f75375",
+               .platform_data = &n2100_f75375s,
+       },
 };
 
 /*
index 700a165..a0445be 100644 (file)
@@ -216,6 +216,16 @@ config SENSORS_DS1621
          This driver can also be built as a module.  If so, the module
          will be called ds1621.
 
+config SENSORS_I5K_AMB
+       tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
+       depends on PCI && EXPERIMENTAL
+       help
+         If you say yes here you get support for FB-DIMM AMB temperature
+         monitoring chips on systems with the Intel 5000 series chipset.
+
+         This driver can also be built as a module. If so, the module
+         will be called i5k_amb.
+
 config SENSORS_F71805F
        tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
        depends on EXPERIMENTAL
index 6da3eef..55595f6 100644 (file)
@@ -38,6 +38,7 @@ obj-$(CONFIG_SENSORS_FSCPOS)  += fscpos.o
 obj-$(CONFIG_SENSORS_GL518SM)  += gl518sm.o
 obj-$(CONFIG_SENSORS_GL520SM)  += gl520sm.o
 obj-$(CONFIG_SENSORS_HDAPS)    += hdaps.o
+obj-$(CONFIG_SENSORS_I5K_AMB)  += i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMPEX)   += ibmpex.o
 obj-$(CONFIG_SENSORS_IT87)     += it87.o
 obj-$(CONFIG_SENSORS_K8TEMP)   += k8temp.o
index cb2331b..d9f04ce 100644 (file)
@@ -503,7 +503,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
                { "AUX3 FAN",           36, 2, 60, 1, 0 },
                { NULL, 0, 0, 0, 0, 0 } }
        },
-       { 0x001A, "unknown", {
+       { 0x001A, "Abit IP35 Pro", {
                { "CPU Core",            0, 0, 10, 1, 0 },
                { "DDR2",                1, 0, 20, 1, 0 },
                { "DDR2 VTT",            2, 0, 10, 1, 0 },
@@ -530,6 +530,60 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
                { "AUX3 Fan",           36, 2, 60, 1, 0 },
                { NULL, 0, 0, 0, 0, 0 } }
        },
+       { 0x001B, "unknown", {
+               { "CPU Core",            0, 0, 10, 1, 0 },
+               { "DDR3",                1, 0, 20, 1, 0 },
+               { "DDR3 VTT",            2, 0, 10, 1, 0 },
+               { "CPU VTT",             3, 0, 10, 1, 0 },
+               { "MCH 1.25V",           4, 0, 10, 1, 0 },
+               { "ICHIO 1.5V",          5, 0, 10, 1, 0 },
+               { "ICH 1.05V",           6, 0, 10, 1, 0 },
+               { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
+               { "ATX +12V (8-pin)",    8, 0, 60, 1, 0 },
+               { "ATX +5V",             9, 0, 30, 1, 0 },
+               { "+3.3V",              10, 0, 20, 1, 0 },
+               { "5VSB",               11, 0, 30, 1, 0 },
+               { "CPU",                24, 1, 1, 1, 0 },
+               { "System",             25, 1, 1, 1, 0 },
+               { "PWM Phase1",         26, 1, 1, 1, 0 },
+               { "PWM Phase2",         27, 1, 1, 1, 0 },
+               { "PWM Phase3",         28, 1, 1, 1, 0 },
+               { "PWM Phase4",         29, 1, 1, 1, 0 },
+               { "PWM Phase5",         30, 1, 1, 1, 0 },
+               { "CPU Fan",            32, 2, 60, 1, 0 },
+               { "SYS Fan",            34, 2, 60, 1, 0 },
+               { "AUX1 Fan",           33, 2, 60, 1, 0 },
+               { "AUX2 Fan",           35, 2, 60, 1, 0 },
+               { "AUX3 Fan",           36, 2, 60, 1, 0 },
+               { NULL, 0, 0, 0, 0, 0 } }
+       },
+       { 0x001C, "unknown", {
+               { "CPU Core",            0, 0, 10, 1, 0 },
+               { "DDR2",                1, 0, 20, 1, 0 },
+               { "DDR2 VTT",            2, 0, 10, 1, 0 },
+               { "CPU VTT",             3, 0, 10, 1, 0 },
+               { "MCH 1.25V",           4, 0, 10, 1, 0 },
+               { "ICHIO 1.5V",          5, 0, 10, 1, 0 },
+               { "ICH 1.05V",           6, 0, 10, 1, 0 },
+               { "ATX +12V (24-Pin)",   7, 0, 60, 1, 0 },
+               { "ATX +12V (8-pin)",    8, 0, 60, 1, 0 },
+               { "ATX +5V",             9, 0, 30, 1, 0 },
+               { "+3.3V",              10, 0, 20, 1, 0 },
+               { "5VSB",               11, 0, 30, 1, 0 },
+               { "CPU",                24, 1, 1, 1, 0 },
+               { "System",             25, 1, 1, 1, 0 },
+               { "PWM Phase1",         26, 1, 1, 1, 0 },
+               { "PWM Phase2",         27, 1, 1, 1, 0 },
+               { "PWM Phase3",         28, 1, 1, 1, 0 },
+               { "PWM Phase4",         29, 1, 1, 1, 0 },
+               { "PWM Phase5",         30, 1, 1, 1, 0 },
+               { "CPU Fan",            32, 2, 60, 1, 0 },
+               { "SYS Fan",            34, 2, 60, 1, 0 },
+               { "AUX1 Fan",           33, 2, 60, 1, 0 },
+               { "AUX2 Fan",           35, 2, 60, 1, 0 },
+               { "AUX3 Fan",           36, 2, 60, 1, 0 },
+               { NULL, 0, 0, 0, 0, 0 } }
+       },
        { 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
 };
 
index 1001d2e..86c66c3 100644 (file)
@@ -80,7 +80,7 @@
 /*
  * Temperature sensors keys (sp78 - 2 bytes).
  */
-static const char* temperature_sensors_sets[][13] = {
+static const char* temperature_sensors_sets[][36] = {
 /* Set 0: Macbook Pro */
        { "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
          "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
@@ -88,7 +88,13 @@ static const char* temperature_sensors_sets[][13] = {
        { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
          "Th1H", "Ts0P", NULL },
 /* Set 2: Macmini set */
-       { "TC0D", "TC0P", NULL }
+       { "TC0D", "TC0P", NULL },
+/* Set 3: Mac Pro (2 x Quad-Core) */
+       { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
+         "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "THTG", "TH0P",
+         "TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
+         "TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
+         "TM9S", "TN0H", "TS0C", NULL },
 };
 
 /* List of keys used to read/write fan speeds */
@@ -990,14 +996,18 @@ static struct attribute *fan##offset##_attributes[] = { \
 
 /*
  * Create the needed functions for each fan using the macro defined above
- * (2 fans are supported)
+ * (4 fans are supported)
  */
 sysfs_fan_speeds_offset(1);
 sysfs_fan_speeds_offset(2);
+sysfs_fan_speeds_offset(3);
+sysfs_fan_speeds_offset(4);
 
 static const struct attribute_group fan_attribute_groups[] = {
        { .attrs = fan1_attributes },
-       { .attrs = fan2_attributes }
+       { .attrs = fan2_attributes },
+       { .attrs = fan3_attributes },
+       { .attrs = fan4_attributes },
 };
 
 /*
@@ -1027,6 +1037,52 @@ static SENSOR_DEVICE_ATTR(temp11_input, S_IRUGO,
                                        applesmc_show_temperature, NULL, 10);
 static SENSOR_DEVICE_ATTR(temp12_input, S_IRUGO,
                                        applesmc_show_temperature, NULL, 11);
+static SENSOR_DEVICE_ATTR(temp13_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 12);
+static SENSOR_DEVICE_ATTR(temp14_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 13);
+static SENSOR_DEVICE_ATTR(temp15_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 14);
+static SENSOR_DEVICE_ATTR(temp16_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 15);
+static SENSOR_DEVICE_ATTR(temp17_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 16);
+static SENSOR_DEVICE_ATTR(temp18_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 17);
+static SENSOR_DEVICE_ATTR(temp19_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 18);
+static SENSOR_DEVICE_ATTR(temp20_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 19);
+static SENSOR_DEVICE_ATTR(temp21_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 20);
+static SENSOR_DEVICE_ATTR(temp22_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 21);
+static SENSOR_DEVICE_ATTR(temp23_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 22);
+static SENSOR_DEVICE_ATTR(temp24_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 23);
+static SENSOR_DEVICE_ATTR(temp25_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 24);
+static SENSOR_DEVICE_ATTR(temp26_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 25);
+static SENSOR_DEVICE_ATTR(temp27_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 26);
+static SENSOR_DEVICE_ATTR(temp28_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 27);
+static SENSOR_DEVICE_ATTR(temp29_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 28);
+static SENSOR_DEVICE_ATTR(temp30_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 29);
+static SENSOR_DEVICE_ATTR(temp31_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 30);
+static SENSOR_DEVICE_ATTR(temp32_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 31);
+static SENSOR_DEVICE_ATTR(temp33_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 32);
+static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 33);
+static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO,
+                                       applesmc_show_temperature, NULL, 34);
 
 static struct attribute *temperature_attributes[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -1041,6 +1097,29 @@ static struct attribute *temperature_attributes[] = {
        &sensor_dev_attr_temp10_input.dev_attr.attr,
        &sensor_dev_attr_temp11_input.dev_attr.attr,
        &sensor_dev_attr_temp12_input.dev_attr.attr,
+       &sensor_dev_attr_temp13_input.dev_attr.attr,
+       &sensor_dev_attr_temp14_input.dev_attr.attr,
+       &sensor_dev_attr_temp15_input.dev_attr.attr,
+       &sensor_dev_attr_temp16_input.dev_attr.attr,
+       &sensor_dev_attr_temp17_input.dev_attr.attr,
+       &sensor_dev_attr_temp18_input.dev_attr.attr,
+       &sensor_dev_attr_temp19_input.dev_attr.attr,
+       &sensor_dev_attr_temp20_input.dev_attr.attr,
+       &sensor_dev_attr_temp21_input.dev_attr.attr,
+       &sensor_dev_attr_temp22_input.dev_attr.attr,
+       &sensor_dev_attr_temp23_input.dev_attr.attr,
+       &sensor_dev_attr_temp24_input.dev_attr.attr,
+       &sensor_dev_attr_temp25_input.dev_attr.attr,
+       &sensor_dev_attr_temp26_input.dev_attr.attr,
+       &sensor_dev_attr_temp27_input.dev_attr.attr,
+       &sensor_dev_attr_temp28_input.dev_attr.attr,
+       &sensor_dev_attr_temp29_input.dev_attr.attr,
+       &sensor_dev_attr_temp30_input.dev_attr.attr,
+       &sensor_dev_attr_temp31_input.dev_attr.attr,
+       &sensor_dev_attr_temp32_input.dev_attr.attr,
+       &sensor_dev_attr_temp33_input.dev_attr.attr,
+       &sensor_dev_attr_temp34_input.dev_attr.attr,
+       &sensor_dev_attr_temp35_input.dev_attr.attr,
        NULL
 };
 
@@ -1137,6 +1216,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
        { .accelerometer = 1, .light = 0, .temperature_set = 1 },
 /* MacMini: temperature set 2 */
        { .accelerometer = 0, .light = 0, .temperature_set = 2 },
+/* MacPro: temperature set 3 */
+       { .accelerometer = 0, .light = 0, .temperature_set = 3 },
 };
 
 /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
@@ -1154,6 +1235,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
                (void*)&applesmc_dmi_data[2]},
+       { applesmc_dmi_match, "Apple MacPro2", {
+         DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
+               (void*)&applesmc_dmi_data[3]},
        { .ident = NULL }
 };
 
@@ -1204,9 +1289,19 @@ static int __init applesmc_init(void)
 
                switch (count) {
                default:
-                       printk(KERN_WARNING "applesmc: More than 2 fans found,"
-                                       " but at most 2 fans are supported"
+                       printk(KERN_WARNING "applesmc: More than 4 fans found,"
+                                       " but at most 4 fans are supported"
                                                " by the driver.\n");
+               case 4:
+                       ret = sysfs_create_group(&pdev->dev.kobj,
+                                                &fan_attribute_groups[3]);
+                       if (ret)
+                               goto out_key_enumeration;
+               case 3:
+                       ret = sysfs_create_group(&pdev->dev.kobj,
+                                                &fan_attribute_groups[2]);
+                       if (ret)
+                               goto out_key_enumeration;
                case 2:
                        ret = sysfs_create_group(&pdev->dev.kobj,
                                                 &fan_attribute_groups[1]);
index 13a0413..6892f76 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/i2c.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
+#include <linux/f75375s.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END };
@@ -86,7 +87,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375);
 
 struct f75375_data {
        unsigned short addr;
-       struct i2c_client client;
+       struct i2c_client *client;
        struct device *hwmon_dev;
 
        const char *name;
@@ -116,15 +117,25 @@ struct f75375_data {
 static int f75375_attach_adapter(struct i2c_adapter *adapter);
 static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
 static int f75375_detach_client(struct i2c_client *client);
+static int f75375_probe(struct i2c_client *client);
+static int f75375_remove(struct i2c_client *client);
 
-static struct i2c_driver f75375_driver = {
+static struct i2c_driver f75375_legacy_driver = {
        .driver = {
-               .name = "f75375",
+               .name = "f75375_legacy",
        },
        .attach_adapter = f75375_attach_adapter,
        .detach_client = f75375_detach_client,
 };
 
+static struct i2c_driver f75375_driver = {
+       .driver = {
+               .name = "f75375",
+       },
+       .probe = f75375_probe,
+       .remove = f75375_remove,
+};
+
 static inline int f75375_read8(struct i2c_client *client, u8 reg)
 {
        return i2c_smbus_read_byte_data(client, reg);
@@ -276,19 +287,14 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
        return sprintf(buf, "%d\n", data->pwm_enable[nr]);
 }
 
-static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
+static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
 {
-       int nr = to_sensor_dev_attr(attr)->index;
-       struct i2c_client *client = to_i2c_client(dev);
        struct f75375_data *data = i2c_get_clientdata(client);
-       int val = simple_strtoul(buf, NULL, 10);
        u8 fanmode;
 
        if (val < 0 || val > 4)
                return -EINVAL;
 
-       mutex_lock(&data->update_lock);
        fanmode = f75375_read8(client, F75375_REG_FAN_TIMER);
        fanmode = ~(3 << FAN_CTRL_MODE(nr));
 
@@ -310,8 +316,22 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
        }
        f75375_write8(client, F75375_REG_FAN_TIMER, fanmode);
        data->pwm_enable[nr] = val;
+       return 0;
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       int nr = to_sensor_dev_attr(attr)->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct f75375_data *data = i2c_get_clientdata(client);
+       int val = simple_strtoul(buf, NULL, 10);
+       int err = 0;
+
+       mutex_lock(&data->update_lock);
+       err = set_pwm_enable_direct(client, nr, val);
        mutex_unlock(&data->update_lock);
-       return count;
+       return err ? err : count;
 }
 
 static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr,
@@ -323,7 +343,7 @@ static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr,
        int val = simple_strtoul(buf, NULL, 10);
        u8 conf = 0;
 
-       if (val != 0 || val != 1 || data->kind == f75373)
+       if (!(val == 0 || val == 1))
                return -EINVAL;
 
        mutex_lock(&data->update_lock);
@@ -529,13 +549,13 @@ static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR,
        show_pwm, set_pwm, 0);
 static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR,
        show_pwm_enable, set_pwm_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO|S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO,
        show_pwm_mode, set_pwm_mode, 0);
 static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR,
        show_pwm, set_pwm, 1);
 static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR,
        show_pwm_enable, set_pwm_enable, 1);
-static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO|S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO,
        show_pwm_mode, set_pwm_mode, 1);
 
 static struct attribute *f75375_attributes[] = {
@@ -580,12 +600,9 @@ static const struct attribute_group f75375_group = {
 
 static int f75375_detach_client(struct i2c_client *client)
 {
-       struct f75375_data *data = i2c_get_clientdata(client);
        int err;
 
-       hwmon_device_unregister(data->hwmon_dev);
-       sysfs_remove_group(&client->dev.kobj, &f75375_group);
-
+       f75375_remove(client);
        err = i2c_detach_client(client);
        if (err) {
                dev_err(&client->dev,
@@ -593,7 +610,91 @@ static int f75375_detach_client(struct i2c_client *client)
                        "client not detached.\n");
                return err;
        }
+       kfree(client);
+       return 0;
+}
+
+static void f75375_init(struct i2c_client *client, struct f75375_data *data,
+               struct f75375s_platform_data *f75375s_pdata)
+{
+       int nr;
+       set_pwm_enable_direct(client, 0, f75375s_pdata->pwm_enable[0]);
+       set_pwm_enable_direct(client, 1, f75375s_pdata->pwm_enable[1]);
+       for (nr = 0; nr < 2; nr++) {
+               data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255);
+               f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr),
+                       data->pwm[nr]);
+       }
+
+}
+
+static int f75375_probe(struct i2c_client *client)
+{
+       struct f75375_data *data = i2c_get_clientdata(client);
+       struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
+       int err;
+
+       if (!i2c_check_functionality(client->adapter,
+                               I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EIO;
+       if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL)))
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, data);
+       data->client = client;
+       mutex_init(&data->update_lock);
+
+       if (strcmp(client->name, "f75375") == 0)
+               data->kind = f75375;
+       else if (strcmp(client->name, "f75373") == 0)
+               data->kind = f75373;
+       else {
+               dev_err(&client->dev, "Unsupported device: %s\n", client->name);
+               return -ENODEV;
+       }
+
+       if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
+               goto exit_free;
+
+       if (data->kind == f75375) {
+               err = sysfs_chmod_file(&client->dev.kobj,
+                       &sensor_dev_attr_pwm1_mode.dev_attr.attr,
+                       S_IRUGO | S_IWUSR);
+               if (err)
+                       goto exit_remove;
+               err = sysfs_chmod_file(&client->dev.kobj,
+                       &sensor_dev_attr_pwm2_mode.dev_attr.attr,
+                       S_IRUGO | S_IWUSR);
+               if (err)
+                       goto exit_remove;
+       }
+
+       data->hwmon_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
+               goto exit_remove;
+       }
+
+       if (f75375s_pdata != NULL)
+               f75375_init(client, data, f75375s_pdata);
+
+       return 0;
+
+exit_remove:
+       sysfs_remove_group(&client->dev.kobj, &f75375_group);
+exit_free:
        kfree(data);
+       i2c_set_clientdata(client, NULL);
+       return err;
+}
+
+static int f75375_remove(struct i2c_client *client)
+{
+       struct f75375_data *data = i2c_get_clientdata(client);
+       hwmon_device_unregister(data->hwmon_dev);
+       sysfs_remove_group(&client->dev.kobj, &f75375_group);
+       kfree(data);
+       i2c_set_clientdata(client, NULL);
        return 0;
 }
 
@@ -608,20 +709,17 @@ static int f75375_attach_adapter(struct i2c_adapter *adapter)
 static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        struct i2c_client *client;
-       struct f75375_data *data;
        u8 version = 0;
        int err = 0;
        const char *name = "";
 
-       if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) {
+       if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
                err = -ENOMEM;
                goto exit;
        }
-       client = &data->client;
-       i2c_set_clientdata(client, data);
        client->addr = address;
        client->adapter = adapter;
-       client->driver = &f75375_driver;
+       client->driver = &f75375_legacy_driver;
 
        if (kind < 0) {
                u16 vendid = f75375_read16(client, F75375_REG_VENDOR);
@@ -644,42 +742,42 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
        } else if (kind == f75373) {
                name = "f75373";
        }
-
        dev_info(&adapter->dev, "found %s version: %02X\n", name, version);
        strlcpy(client->name, name, I2C_NAME_SIZE);
-       data->kind = kind;
-       mutex_init(&data->update_lock);
+
        if ((err = i2c_attach_client(client)))
                goto exit_free;
 
-       if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
+       if ((err = f75375_probe(client)) < 0)
                goto exit_detach;
 
-       data->hwmon_dev = hwmon_device_register(&client->dev);
-       if (IS_ERR(data->hwmon_dev)) {
-               err = PTR_ERR(data->hwmon_dev);
-               goto exit_remove;
-       }
-
        return 0;
 
-exit_remove:
-       sysfs_remove_group(&client->dev.kobj, &f75375_group);
 exit_detach:
        i2c_detach_client(client);
 exit_free:
-       kfree(data);
+       kfree(client);
 exit:
        return err;
 }
 
 static int __init sensors_f75375_init(void)
 {
-       return i2c_add_driver(&f75375_driver);
+       int status;
+       status = i2c_add_driver(&f75375_driver);
+       if (status)
+               return status;
+
+       status = i2c_add_driver(&f75375_legacy_driver);
+       if (status)
+               i2c_del_driver(&f75375_driver);
+
+       return status;
 }
 
 static void __exit sensors_f75375_exit(void)
 {
+       i2c_del_driver(&f75375_legacy_driver);
        i2c_del_driver(&f75375_driver);
 }
 
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
new file mode 100644 (file)
index 0000000..6ac5c6f
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * A hwmon driver for the Intel 5000 series chipset FB-DIMM AMB
+ * temperature sensors
+ * Copyright (C) 2007 IBM
+ *
+ * Author: Darrick J. Wong <djwong@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#define DRVNAME "i5k_amb"
+
+#define I5K_REG_AMB_BASE_ADDR          0x48
+#define I5K_REG_AMB_LEN_ADDR           0x50
+#define I5K_REG_CHAN0_PRESENCE_ADDR    0x64
+#define I5K_REG_CHAN1_PRESENCE_ADDR    0x66
+
+#define AMB_REG_TEMP_MIN_ADDR          0x80
+#define AMB_REG_TEMP_MID_ADDR          0x81
+#define AMB_REG_TEMP_MAX_ADDR          0x82
+#define AMB_REG_TEMP_STATUS_ADDR       0x84
+#define AMB_REG_TEMP_ADDR              0x85
+
+#define AMB_CONFIG_SIZE                        2048
+#define AMB_FUNC_3_OFFSET              768
+
+static unsigned long amb_reg_temp_status(unsigned int amb)
+{
+       return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_STATUS_ADDR +
+              AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_min(unsigned int amb)
+{
+       return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MIN_ADDR +
+              AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_mid(unsigned int amb)
+{
+       return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MID_ADDR +
+              AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp_max(unsigned int amb)
+{
+       return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MAX_ADDR +
+              AMB_CONFIG_SIZE * amb;
+}
+
+static unsigned long amb_reg_temp(unsigned int amb)
+{
+       return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_ADDR +
+              AMB_CONFIG_SIZE * amb;
+}
+
+#define MAX_MEM_CHANNELS               4
+#define MAX_AMBS_PER_CHANNEL           16
+#define MAX_AMBS                       (MAX_MEM_CHANNELS * \
+                                        MAX_AMBS_PER_CHANNEL)
+/*
+ * Ugly hack: For some reason the highest bit is set if there
+ * are _any_ DIMMs in the channel.  Attempting to read from
+ * this "high-order" AMB results in a memory bus error, so
+ * for now we'll just ignore that top bit, even though that
+ * might prevent us from seeing the 16th DIMM in the channel.
+ */
+#define REAL_MAX_AMBS_PER_CHANNEL      15
+#define KNOBS_PER_AMB                  5
+
+static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit)
+{
+       return byte_num * MAX_AMBS_PER_CHANNEL + bit;
+}
+
+#define AMB_SYSFS_NAME_LEN             16
+struct i5k_device_attribute {
+       struct sensor_device_attribute s_attr;
+       char name[AMB_SYSFS_NAME_LEN];
+};
+
+struct i5k_amb_data {
+       struct device *hwmon_dev;
+
+       unsigned long amb_base;
+       unsigned long amb_len;
+       u16 amb_present[MAX_MEM_CHANNELS];
+       void __iomem *amb_mmio;
+       struct i5k_device_attribute *attrs;
+       unsigned int num_attrs;
+};
+
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+                        char *buf)
+{
+       return sprintf(buf, "%s\n", DRVNAME);
+}
+
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct platform_device *amb_pdev;
+
+static u8 amb_read_byte(struct i5k_amb_data *data, unsigned long offset)
+{
+       return ioread8(data->amb_mmio + offset);
+}
+
+static void amb_write_byte(struct i5k_amb_data *data, unsigned long offset,
+                          u8 val)
+{
+       iowrite8(val, data->amb_mmio + offset);
+}
+
+static ssize_t show_amb_alarm(struct device *dev,
+                            struct device_attribute *devattr,
+                            char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i5k_amb_data *data = dev_get_drvdata(dev);
+
+       if (!(amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x20) &&
+            (amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x8))
+               return sprintf(buf, "1\n");
+       else
+               return sprintf(buf, "0\n");
+}
+
+static ssize_t store_amb_min(struct device *dev,
+                            struct device_attribute *devattr,
+                            const char *buf,
+                            size_t count)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i5k_amb_data *data = dev_get_drvdata(dev);
+       unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+       if (temp > 255)
+               temp = 255;
+
+       amb_write_byte(data, amb_reg_temp_min(attr->index), temp);
+       return count;
+}
+
+static ssize_t store_amb_mid(struct device *dev,
+                            struct device_attribute *devattr,
+                            const char *buf,
+                            size_t count)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i5k_amb_data *data = dev_get_drvdata(dev);
+       unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+       if (temp > 255)
+               temp = 255;
+
+       amb_write_byte(data, amb_reg_temp_mid(attr->index), temp);
+       return count;
+}
+
+static ssize_t store_amb_max(struct device *dev,
+                            struct device_attribute *devattr,
+                            const char *buf,
+                            size_t count)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i5k_amb_data *data = dev_get_drvdata(dev);
+       unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+
+       if (temp > 255)
+               temp = 255;
+
+       amb_write_byte(data, amb_reg_temp_max(attr->index), temp);
+       return count;
+}
+
+static ssize_t show_amb_min(struct device *dev,
+                            struct device_attribute *devattr,
+                            char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i5k_amb_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n",
+               500 * amb_read_byte(data, amb_reg_temp_min(attr->index)));
+}
+
+static ssize_t show_amb_mid(struct device *dev,
+                            struct device_attribute *devattr,
+                            char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i5k_amb_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n",
+               500 * amb_read_byte(data, amb_reg_temp_mid(attr->index)));
+}
+
+static ssize_t show_amb_max(struct device *dev,
+                            struct device_attribute *devattr,
+                            char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i5k_amb_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n",
+               500 * amb_read_byte(data, amb_reg_temp_max(attr->index)));
+}
+
+static ssize_t show_amb_temp(struct device *dev,
+                            struct device_attribute *devattr,
+                            char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+       struct i5k_amb_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n",
+               500 * amb_read_byte(data, amb_reg_temp(attr->index)));
+}
+
+static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev)
+{
+       int i, j, k, d = 0;
+       u16 c;
+       int res = 0;
+       int num_ambs = 0;
+       struct i5k_amb_data *data = platform_get_drvdata(pdev);
+
+       /* Count the number of AMBs found */
+       /* ignore the high-order bit, see "Ugly hack" comment above */
+       for (i = 0; i < MAX_MEM_CHANNELS; i++)
+               num_ambs += hweight16(data->amb_present[i] & 0x7fff);
+
+       /* Set up sysfs stuff */
+       data->attrs = kzalloc(sizeof(*data->attrs) * num_ambs * KNOBS_PER_AMB,
+                               GFP_KERNEL);
+       if (!data->attrs)
+               return -ENOMEM;
+       data->num_attrs = 0;
+
+       for (i = 0; i < MAX_MEM_CHANNELS; i++) {
+               c = data->amb_present[i];
+               for (j = 0; j < REAL_MAX_AMBS_PER_CHANNEL; j++, c >>= 1) {
+                       struct i5k_device_attribute *iattr;
+
+                       k = amb_num_from_reg(i, j);
+                       if (!(c & 0x1))
+                               continue;
+                       d++;
+
+                       /* Temperature sysfs knob */
+                       iattr = data->attrs + data->num_attrs;
+                       snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+                                "temp%d_input", d);
+                       iattr->s_attr.dev_attr.attr.name = iattr->name;
+                       iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+                       iattr->s_attr.dev_attr.show = show_amb_temp;
+                       iattr->s_attr.index = k;
+                       res = device_create_file(&pdev->dev,
+                                                &iattr->s_attr.dev_attr);
+                       if (res)
+                               goto exit_remove;
+                       data->num_attrs++;
+
+                       /* Temperature min sysfs knob */
+                       iattr = data->attrs + data->num_attrs;
+                       snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+                                "temp%d_min", d);
+                       iattr->s_attr.dev_attr.attr.name = iattr->name;
+                       iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+                       iattr->s_attr.dev_attr.show = show_amb_min;
+                       iattr->s_attr.dev_attr.store = store_amb_min;
+                       iattr->s_attr.index = k;
+                       res = device_create_file(&pdev->dev,
+                                                &iattr->s_attr.dev_attr);
+                       if (res)
+                               goto exit_remove;
+                       data->num_attrs++;
+
+                       /* Temperature mid sysfs knob */
+                       iattr = data->attrs + data->num_attrs;
+                       snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+                                "temp%d_mid", d);
+                       iattr->s_attr.dev_attr.attr.name = iattr->name;
+                       iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+                       iattr->s_attr.dev_attr.show = show_amb_mid;
+                       iattr->s_attr.dev_attr.store = store_amb_mid;
+                       iattr->s_attr.index = k;
+                       res = device_create_file(&pdev->dev,
+                                                &iattr->s_attr.dev_attr);
+                       if (res)
+                               goto exit_remove;
+                       data->num_attrs++;
+
+                       /* Temperature max sysfs knob */
+                       iattr = data->attrs + data->num_attrs;
+                       snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+                                "temp%d_max", d);
+                       iattr->s_attr.dev_attr.attr.name = iattr->name;
+                       iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO;
+                       iattr->s_attr.dev_attr.show = show_amb_max;
+                       iattr->s_attr.dev_attr.store = store_amb_max;
+                       iattr->s_attr.index = k;
+                       res = device_create_file(&pdev->dev,
+                                                &iattr->s_attr.dev_attr);
+                       if (res)
+                               goto exit_remove;
+                       data->num_attrs++;
+
+                       /* Temperature alarm sysfs knob */
+                       iattr = data->attrs + data->num_attrs;
+                       snprintf(iattr->name, AMB_SYSFS_NAME_LEN,
+                                "temp%d_alarm", d);
+                       iattr->s_attr.dev_attr.attr.name = iattr->name;
+                       iattr->s_attr.dev_attr.attr.mode = S_IRUGO;
+                       iattr->s_attr.dev_attr.show = show_amb_alarm;
+                       iattr->s_attr.index = k;
+                       res = device_create_file(&pdev->dev,
+                                                &iattr->s_attr.dev_attr);
+                       if (res)
+                               goto exit_remove;
+                       data->num_attrs++;
+               }
+       }
+
+       res = device_create_file(&pdev->dev, &dev_attr_name);
+       if (res)
+               goto exit_remove;
+
+       data->hwmon_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               res = PTR_ERR(data->hwmon_dev);
+               goto exit_remove;
+       }
+
+       return res;
+
+exit_remove:
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       for (i = 0; i < data->num_attrs; i++)
+               device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr);
+       kfree(data->attrs);
+
+       return res;
+}
+
+static int __devinit i5k_amb_add(void)
+{
+       int res = -ENODEV;
+
+       /* only ever going to be one of these */
+       amb_pdev = platform_device_alloc(DRVNAME, 0);
+       if (!amb_pdev)
+               return -ENOMEM;
+
+       res = platform_device_add(amb_pdev);
+       if (res)
+               goto err;
+       return 0;
+
+err:
+       platform_device_put(amb_pdev);
+       return res;
+}
+
+static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
+{
+       struct pci_dev *pcidev;
+       u32 val32;
+       int res = -ENODEV;
+
+       /* Find AMB register memory space */
+       pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                               PCI_DEVICE_ID_INTEL_5000_ERR,
+                               NULL);
+       if (!pcidev)
+               return -ENODEV;
+
+       if (pci_read_config_dword(pcidev, I5K_REG_AMB_BASE_ADDR, &val32))
+               goto out;
+       data->amb_base = val32;
+
+       if (pci_read_config_dword(pcidev, I5K_REG_AMB_LEN_ADDR, &val32))
+               goto out;
+       data->amb_len = val32;
+
+       /* Is it big enough? */
+       if (data->amb_len < AMB_CONFIG_SIZE * MAX_AMBS) {
+               dev_err(&pcidev->dev, "AMB region too small!\n");
+               goto out;
+       }
+
+       res = 0;
+out:
+       pci_dev_put(pcidev);
+       return res;
+}
+
+static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id)
+{
+       struct pci_dev *pcidev;
+       u16 val16;
+       int res = -ENODEV;
+
+       /* Copy the DIMM presence map for these two channels */
+       pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL);
+       if (!pcidev)
+               return -ENODEV;
+
+       if (pci_read_config_word(pcidev, I5K_REG_CHAN0_PRESENCE_ADDR, &val16))
+               goto out;
+       amb_present[0] = val16;
+
+       if (pci_read_config_word(pcidev, I5K_REG_CHAN1_PRESENCE_ADDR, &val16))
+               goto out;
+       amb_present[1] = val16;
+
+       res = 0;
+
+out:
+       pci_dev_put(pcidev);
+       return res;
+}
+
+static int __devinit i5k_amb_probe(struct platform_device *pdev)
+{
+       struct i5k_amb_data *data;
+       struct resource *reso;
+       int res = -ENODEV;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       /* Figure out where the AMB registers live */
+       res = i5k_find_amb_registers(data);
+       if (res)
+               goto err;
+
+       /* Copy the DIMM presence map for the first two channels */
+       res = i5k_channel_probe(&data->amb_present[0],
+                               PCI_DEVICE_ID_INTEL_5000_FBD0);
+       if (res)
+               goto err;
+
+       /* Copy the DIMM presence map for the optional second two channels */
+       i5k_channel_probe(&data->amb_present[2],
+                         PCI_DEVICE_ID_INTEL_5000_FBD1);
+
+       /* Set up resource regions */
+       reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME);
+       if (!reso) {
+               res = -EBUSY;
+               goto err;
+       }
+
+       data->amb_mmio = ioremap_nocache(data->amb_base, data->amb_len);
+       if (!data->amb_mmio) {
+               res = -EBUSY;
+               goto err_map_failed;
+       }
+
+       platform_set_drvdata(pdev, data);
+
+       res = i5k_amb_hwmon_init(pdev);
+       if (res)
+               goto err_init_failed;
+
+       return res;
+
+err_init_failed:
+       iounmap(data->amb_mmio);
+       platform_set_drvdata(pdev, NULL);
+err_map_failed:
+       release_mem_region(data->amb_base, data->amb_len);
+err:
+       kfree(data);
+       return res;
+}
+
+static int __devexit i5k_amb_remove(struct platform_device *pdev)
+{
+       int i;
+       struct i5k_amb_data *data = platform_get_drvdata(pdev);
+
+       hwmon_device_unregister(data->hwmon_dev);
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       for (i = 0; i < data->num_attrs; i++)
+               device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr);
+       kfree(data->attrs);
+       iounmap(data->amb_mmio);
+       release_mem_region(data->amb_base, data->amb_len);
+       platform_set_drvdata(pdev, NULL);
+       kfree(data);
+       return 0;
+}
+
+static struct platform_driver i5k_amb_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = DRVNAME,
+       },
+       .probe = i5k_amb_probe,
+       .remove = __devexit_p(i5k_amb_remove),
+};
+
+static int __init i5k_amb_init(void)
+{
+       int res;
+
+       res = platform_driver_register(&i5k_amb_driver);
+       if (res)
+               return res;
+
+       res = i5k_amb_add();
+       if (res)
+               platform_driver_unregister(&i5k_amb_driver);
+
+       return res;
+}
+
+static void __exit i5k_amb_exit(void)
+{
+       platform_device_unregister(amb_pdev);
+       platform_driver_unregister(&i5k_amb_driver);
+}
+
+MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
+MODULE_DESCRIPTION("Intel 5000 chipset FB-DIMM AMB temperature sensor");
+MODULE_LICENSE("GPL");
+
+module_init(i5k_amb_init);
+module_exit(i5k_amb_exit);
index c462824..9c9cdb0 100644 (file)
@@ -140,10 +140,10 @@ static int ibmpex_send_message(struct ibmpex_bmc_data *data)
 
        return 0;
 out1:
-       printk(KERN_ERR "%s: request_settime=%x\n", __FUNCTION__, err);
+       dev_err(data->bmc_device, "request_settime=%x\n", err);
        return err;
 out:
-       printk(KERN_ERR "%s: validate_addr=%x\n", __FUNCTION__, err);
+       dev_err(data->bmc_device, "validate_addr=%x\n", err);
        return err;
 }
 
@@ -161,14 +161,14 @@ static int ibmpex_ver_check(struct ibmpex_bmc_data *data)
        data->sensor_major = data->rx_msg_data[0];
        data->sensor_minor = data->rx_msg_data[1];
 
-       printk(KERN_INFO DRVNAME ": Found BMC with sensor interface "
-              "v%d.%d %d-%02d-%02d on interface %d\n",
-              data->sensor_major,
-              data->sensor_minor,
-              extract_value(data->rx_msg_data, 2),
-              data->rx_msg_data[4],
-              data->rx_msg_data[5],
-              data->interface);
+       dev_info(data->bmc_device, "Found BMC with sensor interface "
+                "v%d.%d %d-%02d-%02d on interface %d\n",
+                data->sensor_major,
+                data->sensor_minor,
+                extract_value(data->rx_msg_data, 2),
+                data->rx_msg_data[4],
+                data->rx_msg_data[5],
+                data->interface);
 
        return 0;
 }
@@ -212,8 +212,8 @@ static int ibmpex_query_sensor_data(struct ibmpex_bmc_data *data, int sensor)
        wait_for_completion(&data->read_complete);
 
        if (data->rx_result || data->rx_msg_len < 26) {
-               printk(KERN_ERR "Error reading sensor %d, please check.\n",
-                      sensor);
+               dev_err(data->bmc_device, "Error reading sensor %d.\n",
+                       sensor);
                return -ENOENT;
        }
 
@@ -456,8 +456,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data) {
-               printk(KERN_ERR DRVNAME ": Insufficient memory for BMC "
-                      "interface %d.\n", data->interface);
+               dev_err(dev, "Insufficient memory for BMC interface.\n");
                return;
        }
 
@@ -471,9 +470,8 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
        err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
                               data, &data->user);
        if (err < 0) {
-               printk(KERN_ERR DRVNAME ": Error, unable to register user with "
-                      "ipmi interface %d\n",
-                      data->interface);
+               dev_err(dev, "Unable to register user with IPMI "
+                       "interface %d\n", data->interface);
                goto out;
        }
 
@@ -495,9 +493,9 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
        data->hwmon_dev = hwmon_device_register(data->bmc_device);
 
        if (IS_ERR(data->hwmon_dev)) {
-               printk(KERN_ERR DRVNAME ": Error, unable to register hwmon "
-                      "class device for interface %d\n",
-                      data->interface);
+               dev_err(data->bmc_device, "Unable to register hwmon "
+                       "device for IPMI interface %d\n",
+                       data->interface);
                goto out_user;
        }
 
@@ -508,7 +506,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
        /* Now go find all the sensors */
        err = ibmpex_find_sensors(data);
        if (err) {
-               printk(KERN_ERR "Error %d allocating memory\n", err);
+               dev_err(data->bmc_device, "Error %d finding sensors\n", err);
                goto out_register;
        }
 
@@ -561,10 +559,10 @@ static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
        struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data;
 
        if (msg->msgid != data->tx_msgid) {
-               printk(KERN_ERR "Received msgid (%02x) and transmitted "
-                      "msgid (%02x) mismatch!\n",
-                      (int)msg->msgid,
-                      (int)data->tx_msgid);
+               dev_err(data->bmc_device, "Mismatch between received msgid "
+                       "(%02x) and transmitted msgid (%02x)!\n",
+                       (int)msg->msgid,
+                       (int)data->tx_msgid);
                ipmi_free_recv_msg(msg);
                return;
        }
index dd36688..d435f00 100644 (file)
 #include <linux/err.h>
 #include <linux/sysfs.h>
 #include <linux/hwmon.h>
+#include <linux/mutex.h>
 #include <linux/spi/spi.h>
-#include <asm/semaphore.h>
+
 
 #define DRVNAME                "lm70"
 
 struct lm70 {
        struct device *hwmon_dev;
-       struct semaphore sem;
+       struct mutex lock;
 };
 
 /* sysfs hook function */
@@ -51,7 +52,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
        s16 raw=0;
        struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
 
-       if (down_interruptible(&p_lm70->sem))
+       if (mutex_lock_interruptible(&p_lm70->lock))
                return -ERESTARTSYS;
 
        /*
@@ -83,7 +84,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
        val = ((int)raw/32) * 250;
        status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */
 out:
-       up(&p_lm70->sem);
+       mutex_unlock(&p_lm70->lock);
        return status;
 }
 
@@ -112,7 +113,7 @@ static int __devinit lm70_probe(struct spi_device *spi)
        if (!p_lm70)
                return -ENOMEM;
 
-       init_MUTEX(&p_lm70->sem);
+       mutex_init(&p_lm70->lock);
 
        /* sysfs hook */
        p_lm70->hwmon_dev = hwmon_device_register(&spi->dev);
index 7e2d978..a276806 100644 (file)
@@ -435,6 +435,22 @@ 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_alarm(struct device *dev, struct device_attribute *da,
+                         char *buf)
+{
+       struct sis5595_data *data = sis5595_update_device(dev);
+       int nr = to_sensor_dev_attr(da)->index;
+       return sprintf(buf, "%u\n", (data->alarms >> nr) & 1);
+}
+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);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 15);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 15);
+
 static ssize_t show_name(struct device *dev, struct device_attribute *attr,
                         char *buf)
 {
@@ -447,22 +463,28 @@ static struct attribute *sis5595_attributes[] = {
        &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_in0_alarm.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_in1_alarm.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_in2_alarm.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_in3_alarm.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_fan1_alarm.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,
+       &sensor_dev_attr_fan2_alarm.dev_attr.attr,
 
        &dev_attr_alarms.attr,
        &dev_attr_name.attr,
@@ -473,19 +495,28 @@ static const struct attribute_group sis5595_group = {
        .attrs = sis5595_attributes,
 };
 
-static struct attribute *sis5595_attributes_opt[] = {
+static struct attribute *sis5595_attributes_in4[] = {
        &sensor_dev_attr_in4_input.dev_attr.attr,
        &sensor_dev_attr_in4_min.dev_attr.attr,
        &sensor_dev_attr_in4_max.dev_attr.attr,
+       &sensor_dev_attr_in4_alarm.dev_attr.attr,
+       NULL
+};
+
+static const struct attribute_group sis5595_group_in4 = {
+       .attrs = sis5595_attributes_in4,
+};
 
+static struct attribute *sis5595_attributes_temp1[] = {
        &dev_attr_temp1_input.attr,
        &dev_attr_temp1_max.attr,
        &dev_attr_temp1_max_hyst.attr,
+       &sensor_dev_attr_temp1_alarm.dev_attr.attr,
        NULL
 };
 
-static const struct attribute_group sis5595_group_opt = {
-       .attrs = sis5595_attributes_opt,
+static const struct attribute_group sis5595_group_temp1 = {
+       .attrs = sis5595_attributes_temp1,
 };
  
 /* This is called when the module is loaded */
@@ -540,20 +571,12 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
        if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group)))
                goto exit_free;
        if (data->maxins == 4) {
-               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)))
+               if ((err = sysfs_create_group(&pdev->dev.kobj,
+                                             &sis5595_group_in4)))
                        goto exit_remove_files;
        } else {
-               if ((err = device_create_file(&pdev->dev,
-                                             &dev_attr_temp1_input))
-                || (err = device_create_file(&pdev->dev,
-                                             &dev_attr_temp1_max))
-                || (err = device_create_file(&pdev->dev,
-                                             &dev_attr_temp1_max_hyst)))
+               if ((err = sysfs_create_group(&pdev->dev.kobj,
+                                             &sis5595_group_temp1)))
                        goto exit_remove_files;
        }
 
@@ -567,7 +590,8 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
 
 exit_remove_files:
        sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
-       sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
+       sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
+       sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
 exit_free:
        kfree(data);
 exit_release:
@@ -582,7 +606,8 @@ static int __devexit sis5595_remove(struct platform_device *pdev)
 
        hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
-       sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
+       sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
+       sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
 
        release_region(data->addr, SIS5595_EXTENT);
        platform_set_drvdata(pdev, NULL);
index 20ae425..879d0a6 100644 (file)
@@ -170,20 +170,16 @@ superio_exit(void)
 #define W83781D_REG_IN(nr)     ((nr < 7) ? (0x20 + (nr)) : \
                                           (0x550 + (nr) - 7))
 
-#define W83781D_REG_FAN_MIN(nr) (0x3a + (nr))
-#define W83781D_REG_FAN(nr) (0x27 + (nr))
-
-#define W83781D_REG_TEMP2_CONFIG 0x152
-#define W83781D_REG_TEMP3_CONFIG 0x252
-#define W83781D_REG_TEMP(nr)           ((nr == 3) ? (0x0250) : \
-                                       ((nr == 2) ? (0x0150) : \
-                                                    (0x27)))
-#define W83781D_REG_TEMP_HYST(nr)      ((nr == 3) ? (0x253) : \
-                                       ((nr == 2) ? (0x153) : \
-                                                    (0x3A)))
-#define W83781D_REG_TEMP_OVER(nr)      ((nr == 3) ? (0x255) : \
-                                       ((nr == 2) ? (0x155) : \
-                                                    (0x39)))
+/* nr:0-2 for fans:1-3 */
+#define W83627HF_REG_FAN_MIN(nr)       (0x3b + (nr))
+#define W83627HF_REG_FAN(nr)           (0x28 + (nr))
+
+#define W83627HF_REG_TEMP2_CONFIG 0x152
+#define W83627HF_REG_TEMP3_CONFIG 0x252
+/* these are zero-based, unlike config constants above */
+static const u16 w83627hf_reg_temp[]           = { 0x27, 0x150, 0x250 };
+static const u16 w83627hf_reg_temp_hyst[]      = { 0x3A, 0x153, 0x253 };
+static const u16 w83627hf_reg_temp_over[]      = { 0x39, 0x155, 0x255 };
 
 #define W83781D_REG_BANK 0x4E
 
@@ -360,12 +356,9 @@ struct w83627hf_data {
        u8 in_min[9];           /* Register value */
        u8 fan[3];              /* Register value */
        u8 fan_min[3];          /* Register value */
-       u8 temp;
-       u8 temp_max;            /* Register value */
-       u8 temp_max_hyst;       /* Register value */
-       u16 temp_add[2];        /* Register value */
-       u16 temp_max_add[2];    /* Register value */
-       u16 temp_max_hyst_add[2]; /* Register value */
+       u16 temp[3];            /* Register value */
+       u16 temp_max[3];        /* Register value */
+       u16 temp_max_hyst[3];   /* Register value */
        u8 fan_div[3];          /* Register encoding, shifted right */
        u8 vid;                 /* Register encoding, combined */
        u32 alarms;             /* Register encoding, combined */
@@ -590,7 +583,7 @@ store_fan_min(struct device *dev, struct device_attribute *devattr,
 
        mutex_lock(&data->update_lock);
        data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
-       w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1),
+       w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr),
                             data->fan_min[nr]);
 
        mutex_unlock(&data->update_lock);
@@ -611,12 +604,10 @@ show_temp(struct device *dev, struct device_attribute *devattr, char *buf)
 {
        int nr = to_sensor_dev_attr(devattr)->index;
        struct w83627hf_data *data = w83627hf_update_device(dev);
-       if (nr >= 2) {  /* TEMP2 and TEMP3 */
-               return sprintf(buf, "%ld\n",
-                       (long)LM75_TEMP_FROM_REG(data->temp_add[nr-2]));
-       } else {        /* TEMP1 */
-               return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->temp));
-       }
+
+       u16 tmp = data->temp[nr];
+       return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+                                         : (long) TEMP_FROM_REG(tmp));
 }
 
 static ssize_t
@@ -625,13 +616,10 @@ show_temp_max(struct device *dev, struct device_attribute *devattr,
 {
        int nr = to_sensor_dev_attr(devattr)->index;
        struct w83627hf_data *data = w83627hf_update_device(dev);
-       if (nr >= 2) {  /* TEMP2 and TEMP3 */
-               return sprintf(buf, "%ld\n",
-                       (long)LM75_TEMP_FROM_REG(data->temp_max_add[nr-2]));
-       } else {        /* TEMP1 */
-               return sprintf(buf, "%ld\n",
-                       (long)TEMP_FROM_REG(data->temp_max));
-       }
+
+       u16 tmp = data->temp_max[nr];
+       return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+                                         : (long) TEMP_FROM_REG(tmp));
 }
 
 static ssize_t
@@ -640,13 +628,10 @@ show_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
 {
        int nr = to_sensor_dev_attr(devattr)->index;
        struct w83627hf_data *data = w83627hf_update_device(dev);
-       if (nr >= 2) {  /* TEMP2 and TEMP3 */
-               return sprintf(buf, "%ld\n",
-                       (long)LM75_TEMP_FROM_REG(data->temp_max_hyst_add[nr-2]));
-       } else {        /* TEMP1 */
-               return sprintf(buf, "%ld\n",
-                       (long)TEMP_FROM_REG(data->temp_max_hyst));
-       }
+
+       u16 tmp = data->temp_max_hyst[nr];
+       return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp)
+                                         : (long) TEMP_FROM_REG(tmp));
 }
 
 static ssize_t
@@ -656,18 +641,11 @@ store_temp_max(struct device *dev, struct device_attribute *devattr,
        int nr = to_sensor_dev_attr(devattr)->index;
        struct w83627hf_data *data = dev_get_drvdata(dev);
        long val = simple_strtol(buf, NULL, 10);
+       u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
 
        mutex_lock(&data->update_lock);
-
-       if (nr >= 2) {  /* TEMP2 and TEMP3 */
-               data->temp_max_add[nr-2] = LM75_TEMP_TO_REG(val);
-               w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
-                               data->temp_max_add[nr-2]);
-       } else {        /* TEMP1 */
-               data->temp_max = TEMP_TO_REG(val);
-               w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr),
-                       data->temp_max);
-       }
+       data->temp_max[nr] = tmp;
+       w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
        mutex_unlock(&data->update_lock);
        return count;
 }
@@ -679,29 +657,22 @@ store_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
        int nr = to_sensor_dev_attr(devattr)->index;
        struct w83627hf_data *data = dev_get_drvdata(dev);
        long val = simple_strtol(buf, NULL, 10);
+       u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
 
        mutex_lock(&data->update_lock);
-
-       if (nr >= 2) {  /* TEMP2 and TEMP3 */
-               data->temp_max_hyst_add[nr-2] = LM75_TEMP_TO_REG(val);
-               w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
-                               data->temp_max_hyst_add[nr-2]);
-       } else {        /* TEMP1 */
-               data->temp_max_hyst = TEMP_TO_REG(val);
-               w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr),
-                       data->temp_max_hyst);
-       }
+       data->temp_max_hyst[nr] = tmp;
+       w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
        mutex_unlock(&data->update_lock);
        return count;
 }
 
 #define sysfs_temp_decl(offset) \
 static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,               \
-                         show_temp, NULL, offset);                     \
+                         show_temp, NULL, offset - 1);                 \
 static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR,         \
-                         show_temp_max, store_temp_max, offset);       \
+                         show_temp_max, store_temp_max, offset - 1);   \
 static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR,    \
-                         show_temp_max_hyst, store_temp_max_hyst, offset);
+                         show_temp_max_hyst, store_temp_max_hyst, offset - 1);
 
 sysfs_temp_decl(1);
 sysfs_temp_decl(2);
@@ -844,7 +815,7 @@ store_fan_div(struct device *dev, struct device_attribute *devattr,
 
        /* Restore fan_min */
        data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
-       w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
+       w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]);
 
        mutex_unlock(&data->update_lock);
        return count;
@@ -1170,7 +1141,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
        struct w83627hf_sio_data *sio_data = dev->platform_data;
        struct w83627hf_data *data;
        struct resource *res;
-       int err;
+       int err, i;
 
        static const char *names[] = {
                "w83627hf",
@@ -1204,9 +1175,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
        w83627hf_init_device(pdev);
 
        /* A few vars need to be filled upon startup */
-       data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1));
-       data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2));
-       data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3));
+       for (i = 0; i <= 2; i++)
+               data->fan_min[i] = w83627hf_read_value(
+                                       data, W83627HF_REG_FAN_MIN(i));
        w83627hf_update_fan_div(data);
 
        /* Register common device attributes */
@@ -1514,23 +1485,23 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev)
 
        if(init) {
                /* Enable temp2 */
-               tmp = w83627hf_read_value(data, W83781D_REG_TEMP2_CONFIG);
+               tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG);
                if (tmp & 0x01) {
                        dev_warn(&pdev->dev, "Enabling temp2, readings "
                                 "might not make sense\n");
-                       w83627hf_write_value(data, W83781D_REG_TEMP2_CONFIG,
+                       w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG,
                                tmp & 0xfe);
                }
 
                /* Enable temp3 */
                if (type != w83697hf) {
                        tmp = w83627hf_read_value(data,
-                               W83781D_REG_TEMP3_CONFIG);
+                               W83627HF_REG_TEMP3_CONFIG);
                        if (tmp & 0x01) {
                                dev_warn(&pdev->dev, "Enabling temp3, "
                                         "readings might not make sense\n");
                                w83627hf_write_value(data,
-                                       W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
+                                       W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe);
                        }
                }
        }
@@ -1563,7 +1534,7 @@ static void w83627hf_update_fan_div(struct w83627hf_data *data)
 static struct w83627hf_data *w83627hf_update_device(struct device *dev)
 {
        struct w83627hf_data *data = dev_get_drvdata(dev);
-       int i;
+       int i, num_temps = (data->type == w83697hf) ? 2 : 3;
 
        mutex_lock(&data->update_lock);
 
@@ -1584,12 +1555,12 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
                            w83627hf_read_value(data,
                                               W83781D_REG_IN_MAX(i));
                }
-               for (i = 1; i <= 3; i++) {
-                       data->fan[i - 1] =
-                           w83627hf_read_value(data, W83781D_REG_FAN(i));
-                       data->fan_min[i - 1] =
+               for (i = 0; i <= 2; i++) {
+                       data->fan[i] =
+                           w83627hf_read_value(data, W83627HF_REG_FAN(i));
+                       data->fan_min[i] =
                            w83627hf_read_value(data,
-                                              W83781D_REG_FAN_MIN(i));
+                                              W83627HF_REG_FAN_MIN(i));
                }
                for (i = 0; i <= 2; i++) {
                        u8 tmp = w83627hf_read_value(data,
@@ -1616,25 +1587,13 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
                                        break;
                        }
                }
-
-               data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1));
-               data->temp_max =
-                   w83627hf_read_value(data, W83781D_REG_TEMP_OVER(1));
-               data->temp_max_hyst =
-                   w83627hf_read_value(data, W83781D_REG_TEMP_HYST(1));
-               data->temp_add[0] =
-                   w83627hf_read_value(data, W83781D_REG_TEMP(2));
-               data->temp_max_add[0] =
-                   w83627hf_read_value(data, W83781D_REG_TEMP_OVER(2));
-               data->temp_max_hyst_add[0] =
-                   w83627hf_read_value(data, W83781D_REG_TEMP_HYST(2));
-               if (data->type != w83697hf) {
-                       data->temp_add[1] =
-                         w83627hf_read_value(data, W83781D_REG_TEMP(3));
-                       data->temp_max_add[1] =
-                         w83627hf_read_value(data, W83781D_REG_TEMP_OVER(3));
-                       data->temp_max_hyst_add[1] =
-                         w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3));
+               for (i = 0; i < num_temps; i++) {
+                       data->temp[i] = w83627hf_read_value(
+                                               data, w83627hf_reg_temp[i]);
+                       data->temp_max[i] = w83627hf_read_value(
+                                               data, w83627hf_reg_temp_over[i]);
+                       data->temp_max_hyst[i] = w83627hf_read_value(
+                                               data, w83627hf_reg_temp_hyst[i]);
                }
 
                w83627hf_update_fan_div(data);
index a6a1edf..e0fa752 100644 (file)
@@ -1122,12 +1122,13 @@ w83781d_create_files(struct device *dev, int kind, int is_isa)
                                &sensor_dev_attr_temp3_beep.dev_attr)))
                        return err;
 
-               if (kind != w83781d)
+               if (kind != w83781d) {
                        err = sysfs_chmod_file(&dev->kobj,
                                &sensor_dev_attr_temp3_alarm.dev_attr.attr,
                                S_IRUGO | S_IWUSR);
                        if (err)
                                return err;
+               }
        }
 
        if (kind != w83781d && kind != as99127f) {
diff --git a/include/linux/f75375s.h b/include/linux/f75375s.h
new file mode 100644 (file)
index 0000000..e99e225
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * f75375s.h - platform data structure for f75375s sensor
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007, Riku Voipio <riku.voipio@iki.fi>
+ */
+
+#ifndef __LINUX_F75375S_H
+#define __LINUX_F75375S_H
+
+/* We want to set fans spinning on systems where there is no
+ * BIOS to do that for us */
+struct f75375s_platform_data {
+       u8 pwm[2];
+       u8 pwm_enable[2];
+};
+
+#endif /* __LINUX_F75375S_H */
index fbe1964..cd6cdb3 100644 (file)
 #define PCI_DEVICE_ID_INTEL_82915G_IG  0x2582
 #define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590
 #define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592
+#define PCI_DEVICE_ID_INTEL_5000_ERR   0x25F0
+#define PCI_DEVICE_ID_INTEL_5000_FBD0  0x25F5
+#define PCI_DEVICE_ID_INTEL_5000_FBD1  0x25F6
 #define PCI_DEVICE_ID_INTEL_82945G_HB  0x2770
 #define PCI_DEVICE_ID_INTEL_82945G_IG  0x2772
 #define PCI_DEVICE_ID_INTEL_3000_HB    0x2778