aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/hwmon/sch562722
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/hwmon/Kconfig9
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/sch5627.c858
5 files changed, 897 insertions, 0 deletions
diff --git a/Documentation/hwmon/sch5627 b/Documentation/hwmon/sch5627
new file mode 100644
index 000000000000..446a054e4912
--- /dev/null
+++ b/Documentation/hwmon/sch5627
@@ -0,0 +1,22 @@
1Kernel driver sch5627
2=====================
3
4Supported chips:
5 * SMSC SCH5627
6 Prefix: 'sch5627'
7 Addresses scanned: none, address read from Super I/O config space
8 Datasheet: Application Note available upon request
9
10Author: Hans de Goede <hdegoede@redhat.com>
11
12
13Description
14-----------
15
16SMSC SCH5627 Super I/O chips include complete hardware monitoring
17capabilities. They can monitor up to 5 voltages, 4 fans and 8 temperatures.
18
19The hardware monitoring part of the SMSC SCH5627 is accessed by talking
20through an embedded microcontroller. An application note describing the
21protocol for communicating with the microcontroller is available upon
22request. Please mail me if you want a copy.
diff --git a/MAINTAINERS b/MAINTAINERS
index 666287a6f3da..b8a123f7e810 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5769,6 +5769,13 @@ S: Supported
5769F: Documentation/hwmon/emc2103 5769F: Documentation/hwmon/emc2103
5770F: drivers/hwmon/emc2103.c 5770F: drivers/hwmon/emc2103.c
5771 5771
5772SMSC SCH5627 HARDWARE MONITOR DRIVER
5773M: Hans de Goede <hdegoede@redhat.com>
5774L: lm-sensors@lm-sensors.org
5775S: Supported
5776F: Documentation/hwmon/sch5627
5777F: drivers/hwmon/sch5627.c
5778
5772SMSC47B397 HARDWARE MONITOR DRIVER 5779SMSC47B397 HARDWARE MONITOR DRIVER
5773M: "Mark M. Hoffman" <mhoffman@lightlink.com> 5780M: "Mark M. Hoffman" <mhoffman@lightlink.com>
5774L: lm-sensors@lm-sensors.org 5781L: lm-sensors@lm-sensors.org
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 19d72bcf966a..6fad9f082f67 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -959,6 +959,15 @@ config SENSORS_SMSC47B397
959 This driver can also be built as a module. If so, the module 959 This driver can also be built as a module. If so, the module
960 will be called smsc47b397. 960 will be called smsc47b397.
961 961
962config SENSORS_SCH5627
963 tristate "SMSC SCH5627"
964 help
965 If you say yes here you get support for the hardware monitoring
966 features of the SMSC SCH5627 Super-I/O chip.
967
968 This driver can also be built as a module. If so, the module
969 will be called sch5627.
970
962config SENSORS_ADS7828 971config SENSORS_ADS7828
963 tristate "Texas Instruments ADS7828" 972 tristate "Texas Instruments ADS7828"
964 depends on I2C 973 depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index c068f82082cd..4d0122c52219 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -90,6 +90,7 @@ obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
90obj-$(CONFIG_SENSORS_PC87427) += pc87427.o 90obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
91obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o 91obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
92obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o 92obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
93obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
93obj-$(CONFIG_SENSORS_SHT15) += sht15.o 94obj-$(CONFIG_SENSORS_SHT15) += sht15.o
94obj-$(CONFIG_SENSORS_SHT21) += sht21.o 95obj-$(CONFIG_SENSORS_SHT21) += sht21.o
95obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o 96obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
new file mode 100644
index 000000000000..9a51dcca9b0d
--- /dev/null
+++ b/drivers/hwmon/sch5627.c
@@ -0,0 +1,858 @@
1/***************************************************************************
2 * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21
22#include <linux/module.h>
23#include <linux/init.h>
24#include <linux/slab.h>
25#include <linux/jiffies.h>
26#include <linux/platform_device.h>
27#include <linux/hwmon.h>
28#include <linux/hwmon-sysfs.h>
29#include <linux/err.h>
30#include <linux/mutex.h>
31#include <linux/io.h>
32#include <linux/acpi.h>
33#include <linux/delay.h>
34
35#define DRVNAME "sch5627"
36#define DEVNAME DRVNAME /* We only support one model */
37
38#define SIO_SCH5627_EM_LD 0x0C /* Embedded Microcontroller LD */
39#define SIO_UNLOCK_KEY 0x55 /* Key to enable Super-I/O */
40#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
41
42#define SIO_REG_LDSEL 0x07 /* Logical device select */
43#define SIO_REG_DEVID 0x20 /* Device ID */
44#define SIO_REG_ENABLE 0x30 /* Logical device enable */
45#define SIO_REG_ADDR 0x66 /* Logical device address (2 bytes) */
46
47#define SIO_SCH5627_ID 0xC6 /* Chipset ID */
48
49#define REGION_LENGTH 9
50
51#define SCH5627_HWMON_ID 0xa5
52#define SCH5627_COMPANY_ID 0x5c
53#define SCH5627_PRIMARY_ID 0xa0
54
55#define SCH5627_REG_BUILD_CODE 0x39
56#define SCH5627_REG_BUILD_ID 0x3a
57#define SCH5627_REG_HWMON_ID 0x3c
58#define SCH5627_REG_HWMON_REV 0x3d
59#define SCH5627_REG_COMPANY_ID 0x3e
60#define SCH5627_REG_PRIMARY_ID 0x3f
61#define SCH5627_REG_CTRL 0x40
62
63#define SCH5627_NO_TEMPS 8
64#define SCH5627_NO_FANS 4
65#define SCH5627_NO_IN 5
66
67static const u16 SCH5627_REG_TEMP_MSB[SCH5627_NO_TEMPS] = {
68 0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181 };
69static const u16 SCH5627_REG_TEMP_LSN[SCH5627_NO_TEMPS] = {
70 0xE2, 0xE1, 0xE1, 0xE5, 0xE5, 0xE6, 0x182, 0x182 };
71static const u16 SCH5627_REG_TEMP_HIGH_NIBBLE[SCH5627_NO_TEMPS] = {
72 0, 0, 1, 1, 0, 0, 0, 1 };
73static const u16 SCH5627_REG_TEMP_HIGH[SCH5627_NO_TEMPS] = {
74 0x61, 0x57, 0x59, 0x5B, 0x5D, 0x5F, 0x184, 0x186 };
75static const u16 SCH5627_REG_TEMP_ABS[SCH5627_NO_TEMPS] = {
76 0x9B, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x1A8, 0x1A9 };
77
78static const u16 SCH5627_REG_FAN[SCH5627_NO_FANS] = {
79 0x2C, 0x2E, 0x30, 0x32 };
80static const u16 SCH5627_REG_FAN_MIN[SCH5627_NO_FANS] = {
81 0x62, 0x64, 0x66, 0x68 };
82
83static const u16 SCH5627_REG_IN_MSB[SCH5627_NO_IN] = {
84 0x22, 0x23, 0x24, 0x25, 0x189 };
85static const u16 SCH5627_REG_IN_LSN[SCH5627_NO_IN] = {
86 0xE4, 0xE4, 0xE3, 0xE3, 0x18A };
87static const u16 SCH5627_REG_IN_HIGH_NIBBLE[SCH5627_NO_IN] = {
88 1, 0, 1, 0, 1 };
89static const u16 SCH5627_REG_IN_FACTOR[SCH5627_NO_IN] = {
90 10745, 3660, 9765, 10745, 3660 };
91static const char * const SCH5627_IN_LABELS[SCH5627_NO_IN] = {
92 "VCC", "VTT", "VBAT", "VTR", "V_IN" };
93
94struct sch5627_data {
95 unsigned short addr;
96 struct device *hwmon_dev;
97 u8 temp_max[SCH5627_NO_TEMPS];
98 u8 temp_crit[SCH5627_NO_TEMPS];
99 u16 fan_min[SCH5627_NO_FANS];
100
101 struct mutex update_lock;
102 char valid; /* !=0 if following fields are valid */
103 unsigned long last_updated; /* In jiffies */
104 u16 temp[SCH5627_NO_TEMPS];
105 u16 fan[SCH5627_NO_FANS];
106 u16 in[SCH5627_NO_IN];
107};
108
109static struct platform_device *sch5627_pdev;
110
111/* Super I/O functions */
112static inline int superio_inb(int base, int reg)
113{
114 outb(reg, base);
115 return inb(base + 1);
116}
117
118static inline int superio_enter(int base)
119{
120 /* Don't step on other drivers' I/O space by accident */
121 if (!request_muxed_region(base, 2, DRVNAME)) {
122 pr_err("I/O address 0x%04x already in use\n", base);
123 return -EBUSY;
124 }
125
126 outb(SIO_UNLOCK_KEY, base);
127
128 return 0;
129}
130
131static inline void superio_select(int base, int ld)
132{
133 outb(SIO_REG_LDSEL, base);
134 outb(ld, base + 1);
135}
136
137static inline void superio_exit(int base)
138{
139 outb(SIO_LOCK_KEY, base);
140 release_region(base, 2);
141}
142
143static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg)
144{
145 u8 val;
146 int i;
147 /*
148 * According to SMSC for the commands we use the maximum time for
149 * the EM to respond is 15 ms, but testing shows in practice it
150 * responds within 15-32 reads, so we first busy poll, and if
151 * that fails sleep a bit and try again until we are way past
152 * the 15 ms maximum response time.
153 */
154 const int max_busy_polls = 64;
155 const int max_lazy_polls = 32;
156
157 /* (Optional) Write-Clear the EC to Host Mailbox Register */
158 val = inb(data->addr + 1);
159 outb(val, data->addr + 1);
160
161 /* Set Mailbox Address Pointer to first location in Region 1 */
162 outb(0x00, data->addr + 2);
163 outb(0x80, data->addr + 3);
164
165 /* Write Request Packet Header */
166 outb(0x02, data->addr + 4); /* Access Type: VREG read */
167 outb(0x01, data->addr + 5); /* # of Entries: 1 Byte (8-bit) */
168 outb(0x04, data->addr + 2); /* Mailbox AP to first data entry loc. */
169
170 /* Write Address field */
171 outb(reg & 0xff, data->addr + 6);
172 outb(reg >> 8, data->addr + 7);
173
174 /* Execute the Random Access Command */
175 outb(0x01, data->addr); /* Write 01h to the Host-to-EC register */
176
177 /* EM Interface Polling "Algorithm" */
178 for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
179 if (i >= max_busy_polls)
180 msleep(1);
181 /* Read Interrupt source Register */
182 val = inb(data->addr + 8);
183 /* Write Clear the interrupt source bits */
184 if (val)
185 outb(val, data->addr + 8);
186 /* Command Completed ? */
187 if (val & 0x01)
188 break;
189 }
190 if (i == max_busy_polls + max_lazy_polls) {
191 pr_err("Max retries exceeded reading virtual "
192 "register 0x%04hx (%d)\n", reg, 1);
193 return -EIO;
194 }
195
196 /*
197 * According to SMSC we may need to retry this, but sofar I've always
198 * seen this succeed in 1 try.
199 */
200 for (i = 0; i < max_busy_polls; i++) {
201 /* Read EC-to-Host Register */
202 val = inb(data->addr + 1);
203 /* Command Completed ? */
204 if (val == 0x01)
205 break;
206
207 if (i == 0)
208 pr_warn("EC reports: 0x%02x reading virtual register "
209 "0x%04hx\n", (unsigned int)val, reg);
210 }
211 if (i == max_busy_polls) {
212 pr_err("Max retries exceeded reading virtual "
213 "register 0x%04hx (%d)\n", reg, 2);
214 return -EIO;
215 }
216
217 /*
218 * According to the SMSC app note we should now do:
219 *
220 * Set Mailbox Address Pointer to first location in Region 1 *
221 * outb(0x00, data->addr + 2);
222 * outb(0x80, data->addr + 3);
223 *
224 * But if we do that things don't work, so let's not.
225 */
226
227 /* Read Data from Mailbox */
228 return inb(data->addr + 4);
229}
230
231static int sch5627_read_virtual_reg16(struct sch5627_data *data, u16 reg)
232{
233 int lsb, msb;
234
235 /* Read LSB first, this will cause the matching MSB to be latched */
236 lsb = sch5627_read_virtual_reg(data, reg);
237 if (lsb < 0)
238 return lsb;
239
240 msb = sch5627_read_virtual_reg(data, reg + 1);
241 if (msb < 0)
242 return msb;
243
244 return lsb | (msb << 8);
245}
246
247static int sch5627_read_virtual_reg12(struct sch5627_data *data, u16 msb_reg,
248 u16 lsn_reg, int high_nibble)
249{
250 int msb, lsn;
251
252 /* Read MSB first, this will cause the matching LSN to be latched */
253 msb = sch5627_read_virtual_reg(data, msb_reg);
254 if (msb < 0)
255 return msb;
256
257 lsn = sch5627_read_virtual_reg(data, lsn_reg);
258 if (lsn < 0)
259 return lsn;
260
261 if (high_nibble)
262 return (msb << 4) | (lsn >> 4);
263 else
264 return (msb << 4) | (lsn & 0x0f);
265}
266
267static struct sch5627_data *sch5627_update_device(struct device *dev)
268{
269 struct sch5627_data *data = dev_get_drvdata(dev);
270 struct sch5627_data *ret = data;
271 int i, val;
272
273 mutex_lock(&data->update_lock);
274
275 /* Cache the values for 1 second */
276 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
277 for (i = 0; i < SCH5627_NO_TEMPS; i++) {
278 val = sch5627_read_virtual_reg12(data,
279 SCH5627_REG_TEMP_MSB[i],
280 SCH5627_REG_TEMP_LSN[i],
281 SCH5627_REG_TEMP_HIGH_NIBBLE[i]);
282 if (unlikely(val < 0)) {
283 ret = ERR_PTR(val);
284 goto abort;
285 }
286 data->temp[i] = val;
287 }
288
289 for (i = 0; i < SCH5627_NO_FANS; i++) {
290 val = sch5627_read_virtual_reg16(data,
291 SCH5627_REG_FAN[i]);
292 if (unlikely(val < 0)) {
293 ret = ERR_PTR(val);
294 goto abort;
295 }
296 data->fan[i] = val;
297 }
298
299 for (i = 0; i < SCH5627_NO_IN; i++) {
300 val = sch5627_read_virtual_reg12(data,
301 SCH5627_REG_IN_MSB[i],
302 SCH5627_REG_IN_LSN[i],
303 SCH5627_REG_IN_HIGH_NIBBLE[i]);
304 if (unlikely(val < 0)) {
305 ret = ERR_PTR(val);
306 goto abort;
307 }
308 data->in[i] = val;
309 }
310
311 data->last_updated = jiffies;
312 data->valid = 1;
313 }
314abort:
315 mutex_unlock(&data->update_lock);
316 return ret;
317}
318
319static int __devinit sch5627_read_limits(struct sch5627_data *data)
320{
321 int i, val;
322
323 for (i = 0; i < SCH5627_NO_TEMPS; i++) {
324 /*
325 * Note what SMSC calls ABS, is what lm_sensors calls max
326 * (aka high), and HIGH is what lm_sensors calls crit.
327 */
328 val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_ABS[i]);
329 if (val < 0)
330 return val;
331 data->temp_max[i] = val;
332
333 val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_HIGH[i]);
334 if (val < 0)
335 return val;
336 data->temp_crit[i] = val;
337 }
338 for (i = 0; i < SCH5627_NO_FANS; i++) {
339 val = sch5627_read_virtual_reg16(data, SCH5627_REG_FAN_MIN[i]);
340 if (val < 0)
341 return val;
342 data->fan_min[i] = val;
343 }
344
345 return 0;
346}
347
348static int reg_to_temp(u16 reg)
349{
350 return (reg * 625) / 10 - 64000;
351}
352
353static int reg_to_temp_limit(u8 reg)
354{
355 return (reg - 64) * 1000;
356}
357
358static int reg_to_rpm(u16 reg)
359{
360 if (reg == 0)
361 return -EIO;
362 if (reg == 0xffff)
363 return 0;
364
365 return 5400540 / reg;
366}
367
368static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
369 char *buf)
370{
371 return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
372}
373
374static ssize_t show_temp(struct device *dev, struct device_attribute
375 *devattr, char *buf)
376{
377 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
378 struct sch5627_data *data = sch5627_update_device(dev);
379 int val;
380
381 if (IS_ERR(data))
382 return PTR_ERR(data);
383
384 val = reg_to_temp(data->temp[attr->index]);
385 return snprintf(buf, PAGE_SIZE, "%d\n", val);
386}
387
388static ssize_t show_temp_fault(struct device *dev, struct device_attribute
389 *devattr, char *buf)
390{
391 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
392 struct sch5627_data *data = sch5627_update_device(dev);
393
394 if (IS_ERR(data))
395 return PTR_ERR(data);
396
397 return snprintf(buf, PAGE_SIZE, "%d\n", data->temp[attr->index] == 0);
398}
399
400static ssize_t show_temp_max(struct device *dev, struct device_attribute
401 *devattr, char *buf)
402{
403 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
404 struct sch5627_data *data = dev_get_drvdata(dev);
405 int val;
406
407 val = reg_to_temp_limit(data->temp_max[attr->index]);
408 return snprintf(buf, PAGE_SIZE, "%d\n", val);
409}
410
411static ssize_t show_temp_crit(struct device *dev, struct device_attribute
412 *devattr, char *buf)
413{
414 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
415 struct sch5627_data *data = dev_get_drvdata(dev);
416 int val;
417
418 val = reg_to_temp_limit(data->temp_crit[attr->index]);
419 return snprintf(buf, PAGE_SIZE, "%d\n", val);
420}
421
422static ssize_t show_fan(struct device *dev, struct device_attribute
423 *devattr, char *buf)
424{
425 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
426 struct sch5627_data *data = sch5627_update_device(dev);
427 int val;
428
429 if (IS_ERR(data))
430 return PTR_ERR(data);
431
432 val = reg_to_rpm(data->fan[attr->index]);
433 if (val < 0)
434 return val;
435
436 return snprintf(buf, PAGE_SIZE, "%d\n", val);
437}
438
439static ssize_t show_fan_fault(struct device *dev, struct device_attribute
440 *devattr, char *buf)
441{
442 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
443 struct sch5627_data *data = sch5627_update_device(dev);
444
445 if (IS_ERR(data))
446 return PTR_ERR(data);
447
448 return snprintf(buf, PAGE_SIZE, "%d\n",
449 data->fan[attr->index] == 0xffff);
450}
451
452static ssize_t show_fan_min(struct device *dev, struct device_attribute
453 *devattr, char *buf)
454{
455 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
456 struct sch5627_data *data = dev_get_drvdata(dev);
457 int val = reg_to_rpm(data->fan_min[attr->index]);
458 if (val < 0)
459 return val;
460
461 return snprintf(buf, PAGE_SIZE, "%d\n", val);
462}
463
464static ssize_t show_in(struct device *dev, struct device_attribute
465 *devattr, char *buf)
466{
467 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
468 struct sch5627_data *data = sch5627_update_device(dev);
469 int val;
470
471 if (IS_ERR(data))
472 return PTR_ERR(data);
473
474 val = DIV_ROUND_CLOSEST(
475 data->in[attr->index] * SCH5627_REG_IN_FACTOR[attr->index],
476 10000);
477 return snprintf(buf, PAGE_SIZE, "%d\n", val);
478}
479
480static ssize_t show_in_label(struct device *dev, struct device_attribute
481 *devattr, char *buf)
482{
483 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
484
485 return snprintf(buf, PAGE_SIZE, "%s\n",
486 SCH5627_IN_LABELS[attr->index]);
487}
488
489static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
490static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
491static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
492static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
493static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
494static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
495static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5);
496static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6);
497static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7);
498static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
499static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
500static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
501static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
502static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4);
503static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5);
504static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6);
505static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7);
506static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0);
507static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1);
508static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2);
509static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3);
510static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4);
511static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5);
512static SENSOR_DEVICE_ATTR(temp7_max, S_IRUGO, show_temp_max, NULL, 6);
513static SENSOR_DEVICE_ATTR(temp8_max, S_IRUGO, show_temp_max, NULL, 7);
514static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
515static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1);
516static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2);
517static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3);
518static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4);
519static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5);
520static SENSOR_DEVICE_ATTR(temp7_crit, S_IRUGO, show_temp_crit, NULL, 6);
521static SENSOR_DEVICE_ATTR(temp8_crit, S_IRUGO, show_temp_crit, NULL, 7);
522
523static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
524static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
525static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
526static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
527static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
528static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
529static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
530static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
531static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan_min, NULL, 0);
532static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan_min, NULL, 1);
533static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO, show_fan_min, NULL, 2);
534static SENSOR_DEVICE_ATTR(fan4_min, S_IRUGO, show_fan_min, NULL, 3);
535
536static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
537static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
538static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
539static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
540static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
541static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_in_label, NULL, 0);
542static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_in_label, NULL, 1);
543static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_in_label, NULL, 2);
544static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_in_label, NULL, 3);
545
546static struct attribute *sch5627_attributes[] = {
547 &dev_attr_name.attr,
548
549 &sensor_dev_attr_temp1_input.dev_attr.attr,
550 &sensor_dev_attr_temp2_input.dev_attr.attr,
551 &sensor_dev_attr_temp3_input.dev_attr.attr,
552 &sensor_dev_attr_temp4_input.dev_attr.attr,
553 &sensor_dev_attr_temp5_input.dev_attr.attr,
554 &sensor_dev_attr_temp6_input.dev_attr.attr,
555 &sensor_dev_attr_temp7_input.dev_attr.attr,
556 &sensor_dev_attr_temp8_input.dev_attr.attr,
557 &sensor_dev_attr_temp1_fault.dev_attr.attr,
558 &sensor_dev_attr_temp2_fault.dev_attr.attr,
559 &sensor_dev_attr_temp3_fault.dev_attr.attr,
560 &sensor_dev_attr_temp4_fault.dev_attr.attr,
561 &sensor_dev_attr_temp5_fault.dev_attr.attr,
562 &sensor_dev_attr_temp6_fault.dev_attr.attr,
563 &sensor_dev_attr_temp7_fault.dev_attr.attr,
564 &sensor_dev_attr_temp8_fault.dev_attr.attr,
565 &sensor_dev_attr_temp1_max.dev_attr.attr,
566 &sensor_dev_attr_temp2_max.dev_attr.attr,
567 &sensor_dev_attr_temp3_max.dev_attr.attr,
568 &sensor_dev_attr_temp4_max.dev_attr.attr,
569 &sensor_dev_attr_temp5_max.dev_attr.attr,
570 &sensor_dev_attr_temp6_max.dev_attr.attr,
571 &sensor_dev_attr_temp7_max.dev_attr.attr,
572 &sensor_dev_attr_temp8_max.dev_attr.attr,
573 &sensor_dev_attr_temp1_crit.dev_attr.attr,
574 &sensor_dev_attr_temp2_crit.dev_attr.attr,
575 &sensor_dev_attr_temp3_crit.dev_attr.attr,
576 &sensor_dev_attr_temp4_crit.dev_attr.attr,
577 &sensor_dev_attr_temp5_crit.dev_attr.attr,
578 &sensor_dev_attr_temp6_crit.dev_attr.attr,
579 &sensor_dev_attr_temp7_crit.dev_attr.attr,
580 &sensor_dev_attr_temp8_crit.dev_attr.attr,
581
582 &sensor_dev_attr_fan1_input.dev_attr.attr,
583 &sensor_dev_attr_fan2_input.dev_attr.attr,
584 &sensor_dev_attr_fan3_input.dev_attr.attr,
585 &sensor_dev_attr_fan4_input.dev_attr.attr,
586 &sensor_dev_attr_fan1_fault.dev_attr.attr,
587 &sensor_dev_attr_fan2_fault.dev_attr.attr,
588 &sensor_dev_attr_fan3_fault.dev_attr.attr,
589 &sensor_dev_attr_fan4_fault.dev_attr.attr,
590 &sensor_dev_attr_fan1_min.dev_attr.attr,
591 &sensor_dev_attr_fan2_min.dev_attr.attr,
592 &sensor_dev_attr_fan3_min.dev_attr.attr,
593 &sensor_dev_attr_fan4_min.dev_attr.attr,
594
595 &sensor_dev_attr_in0_input.dev_attr.attr,
596 &sensor_dev_attr_in1_input.dev_attr.attr,
597 &sensor_dev_attr_in2_input.dev_attr.attr,
598 &sensor_dev_attr_in3_input.dev_attr.attr,
599 &sensor_dev_attr_in4_input.dev_attr.attr,
600 &sensor_dev_attr_in0_label.dev_attr.attr,
601 &sensor_dev_attr_in1_label.dev_attr.attr,
602 &sensor_dev_attr_in2_label.dev_attr.attr,
603 &sensor_dev_attr_in3_label.dev_attr.attr,
604 /* No in4_label as in4 is a generic input pin */
605
606 NULL
607};
608
609static const struct attribute_group sch5627_group = {
610 .attrs = sch5627_attributes,
611};
612
613static int sch5627_remove(struct platform_device *pdev)
614{
615 struct sch5627_data *data = platform_get_drvdata(pdev);
616
617 if (data->hwmon_dev)
618 hwmon_device_unregister(data->hwmon_dev);
619
620 sysfs_remove_group(&pdev->dev.kobj, &sch5627_group);
621 platform_set_drvdata(pdev, NULL);
622 kfree(data);
623
624 return 0;
625}
626
627static int __devinit sch5627_probe(struct platform_device *pdev)
628{
629 struct sch5627_data *data;
630 int err, build_code, build_id, hwmon_rev, val;
631
632 data = kzalloc(sizeof(struct sch5627_data), GFP_KERNEL);
633 if (!data)
634 return -ENOMEM;
635
636 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
637 mutex_init(&data->update_lock);
638 platform_set_drvdata(pdev, data);
639
640 val = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_ID);
641 if (val < 0) {
642 err = val;
643 goto error;
644 }
645 if (val != SCH5627_HWMON_ID) {
646 pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "hwmon",
647 val, SCH5627_HWMON_ID);
648 err = -ENODEV;
649 goto error;
650 }
651
652 val = sch5627_read_virtual_reg(data, SCH5627_REG_COMPANY_ID);
653 if (val < 0) {
654 err = val;
655 goto error;
656 }
657 if (val != SCH5627_COMPANY_ID) {
658 pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "company",
659 val, SCH5627_COMPANY_ID);
660 err = -ENODEV;
661 goto error;
662 }
663
664 val = sch5627_read_virtual_reg(data, SCH5627_REG_PRIMARY_ID);
665 if (val < 0) {
666 err = val;
667 goto error;
668 }
669 if (val != SCH5627_PRIMARY_ID) {
670 pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "primary",
671 val, SCH5627_PRIMARY_ID);
672 err = -ENODEV;
673 goto error;
674 }
675
676 build_code = sch5627_read_virtual_reg(data, SCH5627_REG_BUILD_CODE);
677 if (build_code < 0) {
678 err = build_code;
679 goto error;
680 }
681
682 build_id = sch5627_read_virtual_reg16(data, SCH5627_REG_BUILD_ID);
683 if (build_id < 0) {
684 err = build_id;
685 goto error;
686 }
687
688 hwmon_rev = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_REV);
689 if (hwmon_rev < 0) {
690 err = hwmon_rev;
691 goto error;
692 }
693
694 val = sch5627_read_virtual_reg(data, SCH5627_REG_CTRL);
695 if (val < 0) {
696 err = val;
697 goto error;
698 }
699 if (!(val & 0x01)) {
700 pr_err("hardware monitoring not enabled\n");
701 err = -ENODEV;
702 goto error;
703 }
704
705 /*
706 * Read limits, we do this only once as reading a register on
707 * the sch5627 is quite expensive (and they don't change).
708 */
709 err = sch5627_read_limits(data);
710 if (err)
711 goto error;
712
713 pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n",
714 build_code, build_id, hwmon_rev);
715
716 /* Register sysfs interface files */
717 err = sysfs_create_group(&pdev->dev.kobj, &sch5627_group);
718 if (err)
719 goto error;
720
721 data->hwmon_dev = hwmon_device_register(&pdev->dev);
722 if (IS_ERR(data->hwmon_dev)) {
723 err = PTR_ERR(data->hwmon_dev);
724 data->hwmon_dev = NULL;
725 goto error;
726 }
727
728 return 0;
729
730error:
731 sch5627_remove(pdev);
732 return err;
733}
734
735static int __init sch5627_find(int sioaddr, unsigned short *address)
736{
737 u8 devid;
738 int err = superio_enter(sioaddr);
739 if (err)
740 return err;
741
742 devid = superio_inb(sioaddr, SIO_REG_DEVID);
743 if (devid != SIO_SCH5627_ID) {
744 pr_debug("Unsupported device id: 0x%02x\n",
745 (unsigned int)devid);
746 err = -ENODEV;
747 goto exit;
748 }
749
750 superio_select(sioaddr, SIO_SCH5627_EM_LD);
751
752 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
753 pr_warn("Device not activated\n");
754 err = -ENODEV;
755 goto exit;
756 }
757
758 /*
759 * Warning the order of the low / high byte is the other way around
760 * as on most other superio devices!!
761 */
762 *address = superio_inb(sioaddr, SIO_REG_ADDR) |
763 superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
764 if (*address == 0) {
765 pr_warn("Base address not set\n");
766 err = -ENODEV;
767 goto exit;
768 }
769
770 pr_info("Found %s chip at %#hx\n", DEVNAME, *address);
771exit:
772 superio_exit(sioaddr);
773 return err;
774}
775
776static int __init sch5627_device_add(unsigned short address)
777{
778 struct resource res = {
779 .start = address,
780 .end = address + REGION_LENGTH - 1,
781 .flags = IORESOURCE_IO,
782 };
783 int err;
784
785 sch5627_pdev = platform_device_alloc(DRVNAME, address);
786 if (!sch5627_pdev)
787 return -ENOMEM;
788
789 res.name = sch5627_pdev->name;
790 err = acpi_check_resource_conflict(&res);
791 if (err)
792 goto exit_device_put;
793
794 err = platform_device_add_resources(sch5627_pdev, &res, 1);
795 if (err) {
796 pr_err("Device resource addition failed\n");
797 goto exit_device_put;
798 }
799
800 err = platform_device_add(sch5627_pdev);
801 if (err) {
802 pr_err("Device addition failed\n");
803 goto exit_device_put;
804 }
805
806 return 0;
807
808exit_device_put:
809 platform_device_put(sch5627_pdev);
810
811 return err;
812}
813
814static struct platform_driver sch5627_driver = {
815 .driver = {
816 .owner = THIS_MODULE,
817 .name = DRVNAME,
818 },
819 .probe = sch5627_probe,
820 .remove = sch5627_remove,
821};
822
823static int __init sch5627_init(void)
824{
825 int err = -ENODEV;
826 unsigned short address;
827
828 if (sch5627_find(0x4e, &address) && sch5627_find(0x2e, &address))
829 goto exit;
830
831 err = platform_driver_register(&sch5627_driver);
832 if (err)
833 goto exit;
834
835 err = sch5627_device_add(address);
836 if (err)
837 goto exit_driver;
838
839 return 0;
840
841exit_driver:
842 platform_driver_unregister(&sch5627_driver);
843exit:
844 return err;
845}
846
847static void __exit sch5627_exit(void)
848{
849 platform_device_unregister(sch5627_pdev);
850 platform_driver_unregister(&sch5627_driver);
851}
852
853MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver");
854MODULE_AUTHOR("Hans de Goede (hdegoede@redhat.com)");
855MODULE_LICENSE("GPL");
856
857module_init(sch5627_init);
858module_exit(sch5627_exit);