diff options
-rw-r--r-- | Documentation/hwmon/dme1737 | 33 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 4 | ||||
-rw-r--r-- | drivers/hwmon/dme1737.c | 375 |
3 files changed, 359 insertions, 53 deletions
diff --git a/Documentation/hwmon/dme1737 b/Documentation/hwmon/dme1737 index 1a0f3d64ab80..8f446070e64a 100644 --- a/Documentation/hwmon/dme1737 +++ b/Documentation/hwmon/dme1737 | |||
@@ -6,6 +6,10 @@ Supported chips: | |||
6 | Prefix: 'dme1737' | 6 | Prefix: 'dme1737' |
7 | Addresses scanned: I2C 0x2c, 0x2d, 0x2e | 7 | Addresses scanned: I2C 0x2c, 0x2d, 0x2e |
8 | Datasheet: Provided by SMSC upon request and under NDA | 8 | Datasheet: Provided by SMSC upon request and under NDA |
9 | * SMSC SCH3112, SCH3114, SCH3116 | ||
10 | Prefix: 'sch311x' | ||
11 | Addresses scanned: none, address read from Super-I/O config space | ||
12 | Datasheet: http://www.nuhorizons.com/FeaturedProducts/Volume1/SMSC/311x.pdf | ||
9 | 13 | ||
10 | Authors: | 14 | Authors: |
11 | Juerg Haefliger <juergh@gmail.com> | 15 | Juerg Haefliger <juergh@gmail.com> |
@@ -27,16 +31,25 @@ Description | |||
27 | ----------- | 31 | ----------- |
28 | 32 | ||
29 | This driver implements support for the hardware monitoring capabilities of the | 33 | This driver implements support for the hardware monitoring capabilities of the |
30 | SMSC DME1737 and Asus A8000 (which are the same) Super-I/O chips. This chip | 34 | SMSC DME1737 and Asus A8000 (which are the same) and SMSC SCH311x Super-I/O |
31 | features monitoring of 3 temp sensors temp[1-3] (2 remote diodes and 1 | 35 | chips. These chips feature monitoring of 3 temp sensors temp[1-3] (2 remote |
32 | internal), 7 voltages in[0-6] (6 external and 1 internal) and 6 fan speeds | 36 | diodes and 1 internal), 7 voltages in[0-6] (6 external and 1 internal) and up |
33 | fan[1-6]. Additionally, the chip implements 5 PWM outputs pwm[1-3,5-6] for | 37 | to 6 fan speeds fan[1-6]. Additionally, the chips implement up to 5 PWM |
34 | controlling fan speeds both manually and automatically. | 38 | outputs pwm[1-3,5-6] for controlling fan speeds both manually and |
35 | 39 | automatically. | |
36 | Fan[3-6] and pwm[3,5-6] are optional features and their availability is | 40 | |
37 | dependent on the configuration of the chip. The driver will detect which | 41 | For the DME1737 and A8000, fan[1-2] and pwm[1-2] are always present. Fan[3-6] |
38 | features are present during initialization and create the sysfs attributes | 42 | and pwm[3,5-6] are optional features and their availability depends on the |
39 | accordingly. | 43 | configuration of the chip. The driver will detect which features are present |
44 | during initialization and create the sysfs attributes accordingly. | ||
45 | |||
46 | For the SCH311x, fan[1-3] and pwm[1-3] are always present and fan[4-6] and | ||
47 | pwm[5-6] don't exist. | ||
48 | |||
49 | The hardware monitoring features of the DME1737 and A8000 are only accessible | ||
50 | via SMBus, while the SCH311x only provides access via the ISA bus. The driver | ||
51 | will therefore register itself as an I2C client driver if it detects a DME1737 | ||
52 | or A8000 and as a platform driver if it detects a SCH311x chip. | ||
40 | 53 | ||
41 | 54 | ||
42 | Voltage Monitoring | 55 | Voltage Monitoring |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index b8854b94807f..c69de6c56d97 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -509,13 +509,13 @@ config SENSORS_SIS5595 | |||
509 | will be called sis5595. | 509 | will be called sis5595. |
510 | 510 | ||
511 | config SENSORS_DME1737 | 511 | config SENSORS_DME1737 |
512 | tristate "SMSC DME1737 and compatibles" | 512 | tristate "SMSC DME1737, SCH311x and compatibles" |
513 | depends on I2C && EXPERIMENTAL | 513 | depends on I2C && EXPERIMENTAL |
514 | select HWMON_VID | 514 | select HWMON_VID |
515 | help | 515 | help |
516 | If you say yes here you get support for the hardware monitoring | 516 | If you say yes here you get support for the hardware monitoring |
517 | and fan control features of the SMSC DME1737 (and compatibles | 517 | and fan control features of the SMSC DME1737 (and compatibles |
518 | like the Asus A8000) Super-I/O chip. | 518 | like the Asus A8000) and SCH311x Super-I/O chips. |
519 | 519 | ||
520 | This driver can also be built as a module. If so, the module | 520 | This driver can also be built as a module. If so, the module |
521 | will be called dme1737. | 521 | will be called dme1737. |
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index ec8edd2a8cbd..a878c98e252e 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c | |||
@@ -1,12 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * dme1737.c - driver for the SMSC DME1737 and Asus A8000 Super-I/O chips | 2 | * dme1737.c - Driver for the SMSC DME1737, Asus A8000, and SMSC SCH311x |
3 | * integrated hardware monitoring features. | 3 | * Super-I/O chips integrated hardware monitoring features. |
4 | * Copyright (c) 2007 Juerg Haefliger <juergh@gmail.com> | 4 | * Copyright (c) 2007 Juerg Haefliger <juergh@gmail.com> |
5 | * | 5 | * |
6 | * This driver is based on the LM85 driver. The hardware monitoring | 6 | * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access |
7 | * capabilities of the DME1737 are very similar to the LM85 with some | 7 | * the chip registers if a DME1737 (or A8000) is found and the ISA bus if a |
8 | * additional features. Even though the DME1737 is a Super-I/O chip, the | 8 | * SCH311x chip is found. Both types of chips have very similar hardware |
9 | * hardware monitoring registers are only accessible via SMBus. | 9 | * monitoring capabilities but differ in the way they can be accessed. |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/jiffies.h> | 29 | #include <linux/jiffies.h> |
30 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
31 | #include <linux/platform_device.h> | ||
31 | #include <linux/hwmon.h> | 32 | #include <linux/hwmon.h> |
32 | #include <linux/hwmon-sysfs.h> | 33 | #include <linux/hwmon-sysfs.h> |
33 | #include <linux/hwmon-vid.h> | 34 | #include <linux/hwmon-vid.h> |
@@ -35,6 +36,9 @@ | |||
35 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
37 | 38 | ||
39 | /* ISA device, if found */ | ||
40 | static struct platform_device *pdev; | ||
41 | |||
38 | /* Module load parameters */ | 42 | /* Module load parameters */ |
39 | static int force_start; | 43 | static int force_start; |
40 | module_param(force_start, bool, 0); | 44 | module_param(force_start, bool, 0); |
@@ -133,6 +137,7 @@ static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6}; | |||
133 | static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; | 137 | static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; |
134 | 138 | ||
135 | /* Miscellaneous registers */ | 139 | /* Miscellaneous registers */ |
140 | #define DME1737_REG_DEVICE 0x3d | ||
136 | #define DME1737_REG_COMPANY 0x3e | 141 | #define DME1737_REG_COMPANY 0x3e |
137 | #define DME1737_REG_VERSTEP 0x3f | 142 | #define DME1737_REG_VERSTEP 0x3f |
138 | #define DME1737_REG_CONFIG 0x40 | 143 | #define DME1737_REG_CONFIG 0x40 |
@@ -148,11 +153,17 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; | |||
148 | #define DME1737_COMPANY_SMSC 0x5c | 153 | #define DME1737_COMPANY_SMSC 0x5c |
149 | #define DME1737_VERSTEP 0x88 | 154 | #define DME1737_VERSTEP 0x88 |
150 | #define DME1737_VERSTEP_MASK 0xf8 | 155 | #define DME1737_VERSTEP_MASK 0xf8 |
156 | #define SCH311X_DEVICE 0x8c | ||
157 | |||
158 | /* Length of ISA address segment */ | ||
159 | #define DME1737_EXTENT 2 | ||
151 | 160 | ||
152 | /* --------------------------------------------------------------------- | 161 | /* --------------------------------------------------------------------- |
153 | * Data structures and manipulation thereof | 162 | * Data structures and manipulation thereof |
154 | * --------------------------------------------------------------------- */ | 163 | * --------------------------------------------------------------------- */ |
155 | 164 | ||
165 | /* For ISA chips, we abuse the i2c_client addr and name fields. We also use | ||
166 | the driver field to differentiate between I2C and ISA chips. */ | ||
156 | struct dme1737_data { | 167 | struct dme1737_data { |
157 | struct i2c_client client; | 168 | struct i2c_client client; |
158 | struct device *hwmon_dev; | 169 | struct device *hwmon_dev; |
@@ -465,27 +476,48 @@ static inline int PWM_OFF_TO_REG(int val, int ix, int reg) | |||
465 | 476 | ||
466 | /* --------------------------------------------------------------------- | 477 | /* --------------------------------------------------------------------- |
467 | * Device I/O access | 478 | * Device I/O access |
479 | * | ||
480 | * ISA access is performed through an index/data register pair and needs to | ||
481 | * be protected by a mutex during runtime (not required for initialization). | ||
482 | * We use data->update_lock for this and need to ensure that we acquire it | ||
483 | * before calling dme1737_read or dme1737_write. | ||
468 | * --------------------------------------------------------------------- */ | 484 | * --------------------------------------------------------------------- */ |
469 | 485 | ||
470 | static u8 dme1737_read(struct i2c_client *client, u8 reg) | 486 | static u8 dme1737_read(struct i2c_client *client, u8 reg) |
471 | { | 487 | { |
472 | s32 val = i2c_smbus_read_byte_data(client, reg); | 488 | s32 val; |
473 | 489 | ||
474 | if (val < 0) { | 490 | if (client->driver) { /* I2C device */ |
475 | dev_warn(&client->dev, "Read from register 0x%02x failed! " | 491 | val = i2c_smbus_read_byte_data(client, reg); |
476 | "Please report to the driver maintainer.\n", reg); | 492 | |
493 | if (val < 0) { | ||
494 | dev_warn(&client->dev, "Read from register " | ||
495 | "0x%02x failed! Please report to the driver " | ||
496 | "maintainer.\n", reg); | ||
497 | } | ||
498 | } else { /* ISA device */ | ||
499 | outb(reg, client->addr); | ||
500 | val = inb(client->addr + 1); | ||
477 | } | 501 | } |
478 | 502 | ||
479 | return val; | 503 | return val; |
480 | } | 504 | } |
481 | 505 | ||
482 | static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 value) | 506 | static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val) |
483 | { | 507 | { |
484 | s32 res = i2c_smbus_write_byte_data(client, reg, value); | 508 | s32 res = 0; |
509 | |||
510 | if (client->driver) { /* I2C device */ | ||
511 | res = i2c_smbus_write_byte_data(client, reg, val); | ||
485 | 512 | ||
486 | if (res < 0) { | 513 | if (res < 0) { |
487 | dev_warn(&client->dev, "Write to register 0x%02x failed! " | 514 | dev_warn(&client->dev, "Write to register " |
488 | "Please report to the driver maintainer.\n", reg); | 515 | "0x%02x failed! Please report to the driver " |
516 | "maintainer.\n", reg); | ||
517 | } | ||
518 | } else { /* ISA device */ | ||
519 | outb(reg, client->addr); | ||
520 | outb(val, client->addr + 1); | ||
489 | } | 521 | } |
490 | 522 | ||
491 | return res; | 523 | return res; |
@@ -630,6 +662,24 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
630 | DME1737_REG_ALARM3) << 16; | 662 | DME1737_REG_ALARM3) << 16; |
631 | } | 663 | } |
632 | 664 | ||
665 | /* The ISA chips require explicit clearing of alarm bits. | ||
666 | * Don't worry, an alarm will come back if the condition | ||
667 | * that causes it still exists */ | ||
668 | if (!client->driver) { | ||
669 | if (data->alarms & 0xff0000) { | ||
670 | dme1737_write(client, DME1737_REG_ALARM3, | ||
671 | 0xff); | ||
672 | } | ||
673 | if (data->alarms & 0xff00) { | ||
674 | dme1737_write(client, DME1737_REG_ALARM2, | ||
675 | 0xff); | ||
676 | } | ||
677 | if (data->alarms & 0xff) { | ||
678 | dme1737_write(client, DME1737_REG_ALARM1, | ||
679 | 0xff); | ||
680 | } | ||
681 | } | ||
682 | |||
633 | data->last_update = jiffies; | 683 | data->last_update = jiffies; |
634 | data->valid = 1; | 684 | data->valid = 1; |
635 | } | 685 | } |
@@ -995,7 +1045,7 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr, | |||
995 | /* Only valid for fan[1-4] */ | 1045 | /* Only valid for fan[1-4] */ |
996 | if (!(val == 1 || val == 2 || val == 4)) { | 1046 | if (!(val == 1 || val == 2 || val == 4)) { |
997 | count = -EINVAL; | 1047 | count = -EINVAL; |
998 | dev_warn(&client->dev, "Fan type value %ld not " | 1048 | dev_warn(dev, "Fan type value %ld not " |
999 | "supported. Choose one of 1, 2, or 4.\n", | 1049 | "supported. Choose one of 1, 2, or 4.\n", |
1000 | val); | 1050 | val); |
1001 | goto exit; | 1051 | goto exit; |
@@ -1122,7 +1172,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
1122 | /* Only valid for pwm[1-3] */ | 1172 | /* Only valid for pwm[1-3] */ |
1123 | if (val < 0 || val > 2) { | 1173 | if (val < 0 || val > 2) { |
1124 | count = -EINVAL; | 1174 | count = -EINVAL; |
1125 | dev_warn(&client->dev, "PWM enable %ld not " | 1175 | dev_warn(dev, "PWM enable %ld not " |
1126 | "supported. Choose one of 0, 1, or 2.\n", | 1176 | "supported. Choose one of 0, 1, or 2.\n", |
1127 | val); | 1177 | val); |
1128 | goto exit; | 1178 | goto exit; |
@@ -1223,7 +1273,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
1223 | if (!(val == 1 || val == 2 || val == 4 || | 1273 | if (!(val == 1 || val == 2 || val == 4 || |
1224 | val == 6 || val == 7)) { | 1274 | val == 6 || val == 7)) { |
1225 | count = -EINVAL; | 1275 | count = -EINVAL; |
1226 | dev_warn(&client->dev, "PWM auto channels zone %ld " | 1276 | dev_warn(dev, "PWM auto channels zone %ld " |
1227 | "not supported. Choose one of 1, 2, 4, 6, " | 1277 | "not supported. Choose one of 1, 2, 4, 6, " |
1228 | "or 7.\n", val); | 1278 | "or 7.\n", val); |
1229 | goto exit; | 1279 | goto exit; |
@@ -1311,6 +1361,14 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, | |||
1311 | return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); | 1361 | return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); |
1312 | } | 1362 | } |
1313 | 1363 | ||
1364 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, | ||
1365 | char *buf) | ||
1366 | { | ||
1367 | struct dme1737_data *data = dev_get_drvdata(dev); | ||
1368 | |||
1369 | return sprintf(buf, "%s\n", data->client.name); | ||
1370 | } | ||
1371 | |||
1314 | /* --------------------------------------------------------------------- | 1372 | /* --------------------------------------------------------------------- |
1315 | * Sysfs device attribute defines and structs | 1373 | * Sysfs device attribute defines and structs |
1316 | * --------------------------------------------------------------------- */ | 1374 | * --------------------------------------------------------------------- */ |
@@ -1446,6 +1504,7 @@ SENSOR_DEVICE_ATTR_PWM_5TO6(6); | |||
1446 | 1504 | ||
1447 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); | 1505 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); |
1448 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | 1506 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); |
1507 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); /* for ISA devices */ | ||
1449 | 1508 | ||
1450 | #define SENSOR_DEV_ATTR_IN(ix) \ | 1509 | #define SENSOR_DEV_ATTR_IN(ix) \ |
1451 | &sensor_dev_attr_in##ix##_input.dev_attr.attr, \ | 1510 | &sensor_dev_attr_in##ix##_input.dev_attr.attr, \ |
@@ -1698,7 +1757,7 @@ static inline void dme1737_sio_outb(int sio_cip, int reg, int val) | |||
1698 | } | 1757 | } |
1699 | 1758 | ||
1700 | /* --------------------------------------------------------------------- | 1759 | /* --------------------------------------------------------------------- |
1701 | * Device detection, registration and initialization | 1760 | * Device initialization |
1702 | * --------------------------------------------------------------------- */ | 1761 | * --------------------------------------------------------------------- */ |
1703 | 1762 | ||
1704 | static int dme1737_i2c_get_features(int, struct dme1737_data*); | 1763 | static int dme1737_i2c_get_features(int, struct dme1737_data*); |
@@ -1743,6 +1802,10 @@ static void dme1737_remove_files(struct device *dev) | |||
1743 | } | 1802 | } |
1744 | 1803 | ||
1745 | sysfs_remove_group(&dev->kobj, &dme1737_group); | 1804 | sysfs_remove_group(&dev->kobj, &dme1737_group); |
1805 | |||
1806 | if (!data->client.driver) { | ||
1807 | sysfs_remove_file(&dev->kobj, &dev_attr_name.attr); | ||
1808 | } | ||
1746 | } | 1809 | } |
1747 | 1810 | ||
1748 | static int dme1737_create_files(struct device *dev) | 1811 | static int dme1737_create_files(struct device *dev) |
@@ -1750,9 +1813,15 @@ static int dme1737_create_files(struct device *dev) | |||
1750 | struct dme1737_data *data = dev_get_drvdata(dev); | 1813 | struct dme1737_data *data = dev_get_drvdata(dev); |
1751 | int err, ix; | 1814 | int err, ix; |
1752 | 1815 | ||
1816 | /* Create a name attribute for ISA devices */ | ||
1817 | if (!data->client.driver && | ||
1818 | (err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr))) { | ||
1819 | goto exit; | ||
1820 | } | ||
1821 | |||
1753 | /* Create standard sysfs attributes */ | 1822 | /* Create standard sysfs attributes */ |
1754 | if ((err = sysfs_create_group(&dev->kobj, &dme1737_group))) { | 1823 | if ((err = sysfs_create_group(&dev->kobj, &dme1737_group))) { |
1755 | goto exit; | 1824 | goto exit_remove; |
1756 | } | 1825 | } |
1757 | 1826 | ||
1758 | /* Create fan sysfs attributes */ | 1827 | /* Create fan sysfs attributes */ |
@@ -1840,27 +1909,36 @@ static int dme1737_init_device(struct device *dev) | |||
1840 | return -EFAULT; | 1909 | return -EFAULT; |
1841 | } | 1910 | } |
1842 | 1911 | ||
1843 | data->config2 = dme1737_read(client, DME1737_REG_CONFIG2); | 1912 | /* Determine which optional fan and pwm features are enabled/present */ |
1844 | /* Check if optional fan3 input is enabled */ | 1913 | if (client->driver) { /* I2C chip */ |
1845 | if (data->config2 & 0x04) { | 1914 | data->config2 = dme1737_read(client, DME1737_REG_CONFIG2); |
1846 | data->has_fan |= (1 << 2); | 1915 | /* Check if optional fan3 input is enabled */ |
1847 | } | 1916 | if (data->config2 & 0x04) { |
1917 | data->has_fan |= (1 << 2); | ||
1918 | } | ||
1848 | 1919 | ||
1849 | /* Fan4 and pwm3 are only available if the client's I2C address | 1920 | /* Fan4 and pwm3 are only available if the client's I2C address |
1850 | * is the default 0x2e. Otherwise the I/Os associated with these | 1921 | * is the default 0x2e. Otherwise the I/Os associated with |
1851 | * functions are used for addr enable/select. */ | 1922 | * these functions are used for addr enable/select. */ |
1852 | if (client->addr == 0x2e) { | 1923 | if (data->client.addr == 0x2e) { |
1853 | data->has_fan |= (1 << 3); | 1924 | data->has_fan |= (1 << 3); |
1854 | data->has_pwm |= (1 << 2); | 1925 | data->has_pwm |= (1 << 2); |
1855 | } | 1926 | } |
1856 | 1927 | ||
1857 | /* Determine if the optional fan[5-6] and/or pwm[5-6] are enabled. | 1928 | /* Determine which of the optional fan[5-6] and pwm[5-6] |
1858 | * For this, we need to query the runtime registers through the | 1929 | * features are enabled. For this, we need to query the runtime |
1859 | * Super-IO LPC interface. Try both config ports 0x2e and 0x4e. */ | 1930 | * registers through the Super-IO LPC interface. Try both |
1860 | if (dme1737_i2c_get_features(0x2e, data) && | 1931 | * config ports 0x2e and 0x4e. */ |
1861 | dme1737_i2c_get_features(0x4e, data)) { | 1932 | if (dme1737_i2c_get_features(0x2e, data) && |
1862 | dev_warn(dev, "Failed to query Super-IO for optional " | 1933 | dme1737_i2c_get_features(0x4e, data)) { |
1863 | "features.\n"); | 1934 | dev_warn(dev, "Failed to query Super-IO for optional " |
1935 | "features.\n"); | ||
1936 | } | ||
1937 | } else { /* ISA chip */ | ||
1938 | /* Fan3 and pwm3 are always available. Fan[4-5] and pwm[5-6] | ||
1939 | * don't exist in the ISA chip. */ | ||
1940 | data->has_fan |= (1 << 2); | ||
1941 | data->has_pwm |= (1 << 2); | ||
1864 | } | 1942 | } |
1865 | 1943 | ||
1866 | /* Fan1, fan2, pwm1, and pwm2 are always present */ | 1944 | /* Fan1, fan2, pwm1, and pwm2 are always present */ |
@@ -1879,13 +1957,19 @@ static int dme1737_init_device(struct device *dev) | |||
1879 | 1957 | ||
1880 | reg = dme1737_read(client, DME1737_REG_TACH_PWM); | 1958 | reg = dme1737_read(client, DME1737_REG_TACH_PWM); |
1881 | /* Inform if fan-to-pwm mapping differs from the default */ | 1959 | /* Inform if fan-to-pwm mapping differs from the default */ |
1882 | if (reg != 0xa4) { | 1960 | if (client->driver && reg != 0xa4) { /* I2C chip */ |
1883 | dev_warn(dev, "Non-standard fan to pwm mapping: " | 1961 | dev_warn(dev, "Non-standard fan to pwm mapping: " |
1884 | "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, " | 1962 | "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, " |
1885 | "fan4->pwm%d. Please report to the driver " | 1963 | "fan4->pwm%d. Please report to the driver " |
1886 | "maintainer.\n", | 1964 | "maintainer.\n", |
1887 | (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1, | 1965 | (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1, |
1888 | ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1); | 1966 | ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1); |
1967 | } else if (!client->driver && reg != 0x24) { /* ISA chip */ | ||
1968 | dev_warn(dev, "Non-standard fan to pwm mapping: " | ||
1969 | "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. " | ||
1970 | "Please report to the driver maintainer.\n", | ||
1971 | (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1, | ||
1972 | ((reg >> 4) & 0x03) + 1); | ||
1889 | } | 1973 | } |
1890 | 1974 | ||
1891 | /* Switch pwm[1-3] to manual mode if they are currently disabled and | 1975 | /* Switch pwm[1-3] to manual mode if they are currently disabled and |
@@ -2094,16 +2178,225 @@ static struct i2c_driver dme1737_i2c_driver = { | |||
2094 | }; | 2178 | }; |
2095 | 2179 | ||
2096 | /* --------------------------------------------------------------------- | 2180 | /* --------------------------------------------------------------------- |
2181 | * ISA device detection and registration | ||
2182 | * --------------------------------------------------------------------- */ | ||
2183 | |||
2184 | static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr) | ||
2185 | { | ||
2186 | int err = 0, reg; | ||
2187 | unsigned short base_addr; | ||
2188 | |||
2189 | dme1737_sio_enter(sio_cip); | ||
2190 | |||
2191 | /* Check device ID | ||
2192 | * We currently know about SCH3112 (0x7c), SCH3114 (0x7d), and | ||
2193 | * SCH3116 (0x7f). */ | ||
2194 | reg = dme1737_sio_inb(sio_cip, 0x20); | ||
2195 | if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) { | ||
2196 | err = -ENODEV; | ||
2197 | goto exit; | ||
2198 | } | ||
2199 | |||
2200 | /* Select logical device A (runtime registers) */ | ||
2201 | dme1737_sio_outb(sio_cip, 0x07, 0x0a); | ||
2202 | |||
2203 | /* Get the base address of the runtime registers */ | ||
2204 | if (!(base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | | ||
2205 | dme1737_sio_inb(sio_cip, 0x61))) { | ||
2206 | printk(KERN_ERR "dme1737: Base address not set.\n"); | ||
2207 | err = -ENODEV; | ||
2208 | goto exit; | ||
2209 | } | ||
2210 | |||
2211 | /* Access to the hwmon registers is through an index/data register | ||
2212 | * pair located at offset 0x70/0x71. */ | ||
2213 | *addr = base_addr + 0x70; | ||
2214 | |||
2215 | exit: | ||
2216 | dme1737_sio_exit(sio_cip); | ||
2217 | return err; | ||
2218 | } | ||
2219 | |||
2220 | static int __init dme1737_isa_device_add(unsigned short addr) | ||
2221 | { | ||
2222 | struct resource res = { | ||
2223 | .start = addr, | ||
2224 | .end = addr + DME1737_EXTENT - 1, | ||
2225 | .name = "dme1737", | ||
2226 | .flags = IORESOURCE_IO, | ||
2227 | }; | ||
2228 | int err; | ||
2229 | |||
2230 | if (!(pdev = platform_device_alloc("dme1737", addr))) { | ||
2231 | printk(KERN_ERR "dme1737: Failed to allocate device.\n"); | ||
2232 | err = -ENOMEM; | ||
2233 | goto exit; | ||
2234 | } | ||
2235 | |||
2236 | if ((err = platform_device_add_resources(pdev, &res, 1))) { | ||
2237 | printk(KERN_ERR "dme1737: Failed to add device resource " | ||
2238 | "(err = %d).\n", err); | ||
2239 | goto exit_device_put; | ||
2240 | } | ||
2241 | |||
2242 | if ((err = platform_device_add(pdev))) { | ||
2243 | printk(KERN_ERR "dme1737: Failed to add device (err = %d).\n", | ||
2244 | err); | ||
2245 | goto exit_device_put; | ||
2246 | } | ||
2247 | |||
2248 | return 0; | ||
2249 | |||
2250 | exit_device_put: | ||
2251 | platform_device_put(pdev); | ||
2252 | pdev = NULL; | ||
2253 | exit: | ||
2254 | return err; | ||
2255 | } | ||
2256 | |||
2257 | static int __devinit dme1737_isa_probe(struct platform_device *pdev) | ||
2258 | { | ||
2259 | u8 company, device; | ||
2260 | struct resource *res; | ||
2261 | struct i2c_client *client; | ||
2262 | struct dme1737_data *data; | ||
2263 | struct device *dev = &pdev->dev; | ||
2264 | int err; | ||
2265 | |||
2266 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
2267 | if (!request_region(res->start, DME1737_EXTENT, "dme1737")) { | ||
2268 | dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", | ||
2269 | (unsigned short)res->start, | ||
2270 | (unsigned short)res->start + DME1737_EXTENT - 1); | ||
2271 | err = -EBUSY; | ||
2272 | goto exit; | ||
2273 | } | ||
2274 | |||
2275 | if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) { | ||
2276 | err = -ENOMEM; | ||
2277 | goto exit_release_region; | ||
2278 | } | ||
2279 | |||
2280 | client = &data->client; | ||
2281 | i2c_set_clientdata(client, data); | ||
2282 | client->addr = res->start; | ||
2283 | platform_set_drvdata(pdev, data); | ||
2284 | |||
2285 | company = dme1737_read(client, DME1737_REG_COMPANY); | ||
2286 | device = dme1737_read(client, DME1737_REG_DEVICE); | ||
2287 | |||
2288 | if (!((company == DME1737_COMPANY_SMSC) && | ||
2289 | (device == SCH311X_DEVICE))) { | ||
2290 | err = -ENODEV; | ||
2291 | goto exit_kfree; | ||
2292 | } | ||
2293 | |||
2294 | /* Fill in the remaining client fields and initialize the mutex */ | ||
2295 | strlcpy(client->name, "sch311x", I2C_NAME_SIZE); | ||
2296 | mutex_init(&data->update_lock); | ||
2297 | |||
2298 | dev_info(dev, "Found a SCH311x chip at 0x%04x\n", client->addr); | ||
2299 | |||
2300 | /* Initialize the chip */ | ||
2301 | if ((err = dme1737_init_device(dev))) { | ||
2302 | dev_err(dev, "Failed to initialize device.\n"); | ||
2303 | goto exit_kfree; | ||
2304 | } | ||
2305 | |||
2306 | /* Create sysfs files */ | ||
2307 | if ((err = dme1737_create_files(dev))) { | ||
2308 | dev_err(dev, "Failed to create sysfs files.\n"); | ||
2309 | goto exit_kfree; | ||
2310 | } | ||
2311 | |||
2312 | /* Register device */ | ||
2313 | data->hwmon_dev = hwmon_device_register(dev); | ||
2314 | if (IS_ERR(data->hwmon_dev)) { | ||
2315 | dev_err(dev, "Failed to register device.\n"); | ||
2316 | err = PTR_ERR(data->hwmon_dev); | ||
2317 | goto exit_remove_files; | ||
2318 | } | ||
2319 | |||
2320 | return 0; | ||
2321 | |||
2322 | exit_remove_files: | ||
2323 | dme1737_remove_files(dev); | ||
2324 | exit_kfree: | ||
2325 | platform_set_drvdata(pdev, NULL); | ||
2326 | kfree(data); | ||
2327 | exit_release_region: | ||
2328 | release_region(res->start, DME1737_EXTENT); | ||
2329 | exit: | ||
2330 | return err; | ||
2331 | } | ||
2332 | |||
2333 | static int __devexit dme1737_isa_remove(struct platform_device *pdev) | ||
2334 | { | ||
2335 | struct dme1737_data *data = platform_get_drvdata(pdev); | ||
2336 | |||
2337 | hwmon_device_unregister(data->hwmon_dev); | ||
2338 | dme1737_remove_files(&pdev->dev); | ||
2339 | release_region(data->client.addr, DME1737_EXTENT); | ||
2340 | platform_set_drvdata(pdev, NULL); | ||
2341 | kfree(data); | ||
2342 | |||
2343 | return 0; | ||
2344 | } | ||
2345 | |||
2346 | static struct platform_driver dme1737_isa_driver = { | ||
2347 | .driver = { | ||
2348 | .owner = THIS_MODULE, | ||
2349 | .name = "dme1737", | ||
2350 | }, | ||
2351 | .probe = dme1737_isa_probe, | ||
2352 | .remove = __devexit_p(dme1737_isa_remove), | ||
2353 | }; | ||
2354 | |||
2355 | /* --------------------------------------------------------------------- | ||
2097 | * Module initialization and cleanup | 2356 | * Module initialization and cleanup |
2098 | * --------------------------------------------------------------------- */ | 2357 | * --------------------------------------------------------------------- */ |
2099 | 2358 | ||
2100 | static int __init dme1737_init(void) | 2359 | static int __init dme1737_init(void) |
2101 | { | 2360 | { |
2102 | return i2c_add_driver(&dme1737_i2c_driver); | 2361 | int err; |
2362 | unsigned short addr; | ||
2363 | |||
2364 | if ((err = i2c_add_driver(&dme1737_i2c_driver))) { | ||
2365 | goto exit; | ||
2366 | } | ||
2367 | |||
2368 | if (dme1737_isa_detect(0x2e, &addr) && | ||
2369 | dme1737_isa_detect(0x4e, &addr)) { | ||
2370 | /* Return 0 if we didn't find an ISA device */ | ||
2371 | return 0; | ||
2372 | } | ||
2373 | |||
2374 | if ((err = platform_driver_register(&dme1737_isa_driver))) { | ||
2375 | goto exit_del_i2c_driver; | ||
2376 | } | ||
2377 | |||
2378 | /* Sets global pdev as a side effect */ | ||
2379 | if ((err = dme1737_isa_device_add(addr))) { | ||
2380 | goto exit_del_isa_driver; | ||
2381 | } | ||
2382 | |||
2383 | return 0; | ||
2384 | |||
2385 | exit_del_isa_driver: | ||
2386 | platform_driver_unregister(&dme1737_isa_driver); | ||
2387 | exit_del_i2c_driver: | ||
2388 | i2c_del_driver(&dme1737_i2c_driver); | ||
2389 | exit: | ||
2390 | return err; | ||
2103 | } | 2391 | } |
2104 | 2392 | ||
2105 | static void __exit dme1737_exit(void) | 2393 | static void __exit dme1737_exit(void) |
2106 | { | 2394 | { |
2395 | if (pdev) { | ||
2396 | platform_device_unregister(pdev); | ||
2397 | platform_driver_unregister(&dme1737_isa_driver); | ||
2398 | } | ||
2399 | |||
2107 | i2c_del_driver(&dme1737_i2c_driver); | 2400 | i2c_del_driver(&dme1737_i2c_driver); |
2108 | } | 2401 | } |
2109 | 2402 | ||