hwmon: (max1619) Add individual alarm and fault files
[linux-2.6-block.git] / drivers / hwmon / smsc47m1.c
CommitLineData
1da177e4
LT
1/*
2 smsc47m1.c - Part of lm_sensors, Linux kernel modules
3 for hardware monitoring
4
6091780e 5 Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x,
8eccbb6f
JD
6 LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997
7 Super-I/O chips.
1da177e4
LT
8
9 Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
8eccbb6f 10 Copyright (C) 2004-2007 Jean Delvare <khali@linux-fr.org>
1da177e4
LT
11 Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com>
12 and Jean Delvare
13
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27*/
28
29#include <linux/module.h>
30#include <linux/slab.h>
31#include <linux/ioport.h>
32#include <linux/jiffies.h>
51f2cca1 33#include <linux/platform_device.h>
943b0830 34#include <linux/hwmon.h>
e84cfbcb 35#include <linux/hwmon-sysfs.h>
943b0830 36#include <linux/err.h>
1da177e4 37#include <linux/init.h>
9a61bf63 38#include <linux/mutex.h>
ce8c6ce1 39#include <linux/sysfs.h>
1da177e4
LT
40#include <asm/io.h>
41
67b671bc
JD
42static unsigned short force_id;
43module_param(force_id, ushort, 0);
44MODULE_PARM_DESC(force_id, "Override the detected device ID");
45
51f2cca1
JD
46static struct platform_device *pdev;
47
48#define DRVNAME "smsc47m1"
8eccbb6f 49enum chips { smsc47m1, smsc47m2 };
1da177e4
LT
50
51/* Super-I/0 registers and commands */
52
53#define REG 0x2e /* The register to read/write */
54#define VAL 0x2f /* The value to read/write */
55
56static inline void
57superio_outb(int reg, int val)
58{
59 outb(reg, REG);
60 outb(val, VAL);
61}
62
63static inline int
64superio_inb(int reg)
65{
66 outb(reg, REG);
67 return inb(VAL);
68}
69
70/* logical device for fans is 0x0A */
71#define superio_select() superio_outb(0x07, 0x0A)
72
73static inline void
74superio_enter(void)
75{
76 outb(0x55, REG);
77}
78
79static inline void
80superio_exit(void)
81{
82 outb(0xAA, REG);
83}
84
85#define SUPERIO_REG_ACT 0x30
86#define SUPERIO_REG_BASE 0x60
87#define SUPERIO_REG_DEVID 0x20
88
89/* Logical device registers */
90
91#define SMSC_EXTENT 0x80
92
93/* nr is 0 or 1 in the macros below */
94#define SMSC47M1_REG_ALARM 0x04
95#define SMSC47M1_REG_TPIN(nr) (0x34 - (nr))
96#define SMSC47M1_REG_PPIN(nr) (0x36 - (nr))
1da177e4 97#define SMSC47M1_REG_FANDIV 0x58
8eccbb6f
JD
98
99static const u8 SMSC47M1_REG_FAN[3] = { 0x59, 0x5a, 0x6b };
100static const u8 SMSC47M1_REG_FAN_PRELOAD[3] = { 0x5b, 0x5c, 0x6c };
101static const u8 SMSC47M1_REG_PWM[3] = { 0x56, 0x57, 0x69 };
102
103#define SMSC47M2_REG_ALARM6 0x09
104#define SMSC47M2_REG_TPIN1 0x38
105#define SMSC47M2_REG_TPIN2 0x37
106#define SMSC47M2_REG_TPIN3 0x2d
107#define SMSC47M2_REG_PPIN3 0x2c
108#define SMSC47M2_REG_FANDIV3 0x6a
1da177e4
LT
109
110#define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \
111 983040/((192-(reg))*(div)))
112#define FAN_FROM_REG(reg,div,preload) ((reg)<=(preload) || (reg)==255 ? 0 : \
113 983040/(((reg)-(preload))*(div)))
114#define DIV_FROM_REG(reg) (1 << (reg))
115#define PWM_FROM_REG(reg) (((reg) & 0x7E) << 1)
116#define PWM_EN_FROM_REG(reg) ((~(reg)) & 0x01)
117#define PWM_TO_REG(reg) (((reg) >> 1) & 0x7E)
118
119struct smsc47m1_data {
51f2cca1
JD
120 unsigned short addr;
121 const char *name;
8eccbb6f 122 enum chips type;
1beeffe4 123 struct device *hwmon_dev;
1da177e4 124
9a61bf63 125 struct mutex update_lock;
1da177e4
LT
126 unsigned long last_updated; /* In jiffies */
127
8eccbb6f
JD
128 u8 fan[3]; /* Register value */
129 u8 fan_preload[3]; /* Register value */
130 u8 fan_div[3]; /* Register encoding, shifted right */
1da177e4 131 u8 alarms; /* Register encoding */
8eccbb6f 132 u8 pwm[3]; /* Register value (bit 0 is disable) */
1da177e4
LT
133};
134
51f2cca1
JD
135struct smsc47m1_sio_data {
136 enum chips type;
137};
1da177e4 138
51f2cca1
JD
139
140static int smsc47m1_probe(struct platform_device *pdev);
d0546128 141static int __devexit smsc47m1_remove(struct platform_device *pdev);
1da177e4
LT
142static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
143 int init);
144
51f2cca1 145static inline int smsc47m1_read_value(struct smsc47m1_data *data, u8 reg)
94e183fd 146{
51f2cca1 147 return inb_p(data->addr + reg);
94e183fd
JD
148}
149
51f2cca1 150static inline void smsc47m1_write_value(struct smsc47m1_data *data, u8 reg,
94e183fd
JD
151 u8 value)
152{
51f2cca1 153 outb_p(value, data->addr + reg);
94e183fd 154}
1da177e4 155
51f2cca1 156static struct platform_driver smsc47m1_driver = {
cdaf7934 157 .driver = {
87218842 158 .owner = THIS_MODULE,
51f2cca1 159 .name = DRVNAME,
cdaf7934 160 },
51f2cca1
JD
161 .probe = smsc47m1_probe,
162 .remove = __devexit_p(smsc47m1_remove),
1da177e4
LT
163};
164
e84cfbcb
JD
165static ssize_t get_fan(struct device *dev, struct device_attribute
166 *devattr, char *buf)
1da177e4 167{
e84cfbcb 168 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1da177e4 169 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
e84cfbcb 170 int nr = attr->index;
1da177e4
LT
171 /* This chip (stupidly) stops monitoring fan speed if PWM is
172 enabled and duty cycle is 0%. This is fine if the monitoring
173 and control concern the same fan, but troublesome if they are
174 not (which could as well happen). */
175 int rpm = (data->pwm[nr] & 0x7F) == 0x00 ? 0 :
176 FAN_FROM_REG(data->fan[nr],
177 DIV_FROM_REG(data->fan_div[nr]),
178 data->fan_preload[nr]);
179 return sprintf(buf, "%d\n", rpm);
180}
181
e84cfbcb
JD
182static ssize_t get_fan_min(struct device *dev, struct device_attribute
183 *devattr, char *buf)
1da177e4 184{
e84cfbcb 185 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1da177e4 186 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
e84cfbcb 187 int nr = attr->index;
1da177e4
LT
188 int rpm = MIN_FROM_REG(data->fan_preload[nr],
189 DIV_FROM_REG(data->fan_div[nr]));
190 return sprintf(buf, "%d\n", rpm);
191}
192
e84cfbcb
JD
193static ssize_t get_fan_div(struct device *dev, struct device_attribute
194 *devattr, char *buf)
1da177e4 195{
e84cfbcb 196 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1da177e4 197 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
e84cfbcb 198 return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index]));
1da177e4
LT
199}
200
e84cfbcb
JD
201static ssize_t get_pwm(struct device *dev, struct device_attribute
202 *devattr, char *buf)
1da177e4 203{
e84cfbcb 204 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1da177e4 205 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
e84cfbcb 206 return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[attr->index]));
1da177e4
LT
207}
208
e84cfbcb
JD
209static ssize_t get_pwm_en(struct device *dev, struct device_attribute
210 *devattr, char *buf)
1da177e4 211{
e84cfbcb 212 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1da177e4 213 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
e84cfbcb 214 return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[attr->index]));
1da177e4
LT
215}
216
e84cfbcb
JD
217static ssize_t get_alarms(struct device *dev, struct device_attribute
218 *devattr, char *buf)
1da177e4
LT
219{
220 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
221 return sprintf(buf, "%d\n", data->alarms);
222}
223
e84cfbcb
JD
224static ssize_t set_fan_min(struct device *dev, struct device_attribute
225 *devattr, const char *buf, size_t count)
1da177e4 226{
e84cfbcb 227 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
51f2cca1 228 struct smsc47m1_data *data = dev_get_drvdata(dev);
e84cfbcb 229 int nr = attr->index;
1da177e4
LT
230 long rpmdiv, val = simple_strtol(buf, NULL, 10);
231
9a61bf63 232 mutex_lock(&data->update_lock);
1da177e4
LT
233 rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]);
234
235 if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) {
9a61bf63 236 mutex_unlock(&data->update_lock);
1da177e4
LT
237 return -EINVAL;
238 }
239
240 data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv);
51f2cca1 241 smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr],
1da177e4 242 data->fan_preload[nr]);
9a61bf63 243 mutex_unlock(&data->update_lock);
1da177e4
LT
244
245 return count;
246}
247
248/* Note: we save and restore the fan minimum here, because its value is
249 determined in part by the fan clock divider. This follows the principle
d6e05edc 250 of least surprise; the user doesn't expect the fan minimum to change just
1da177e4 251 because the divider changed. */
e84cfbcb
JD
252static ssize_t set_fan_div(struct device *dev, struct device_attribute
253 *devattr, const char *buf, size_t count)
1da177e4 254{
e84cfbcb 255 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
51f2cca1 256 struct smsc47m1_data *data = dev_get_drvdata(dev);
e84cfbcb 257 int nr = attr->index;
1da177e4
LT
258 long new_div = simple_strtol(buf, NULL, 10), tmp;
259 u8 old_div = DIV_FROM_REG(data->fan_div[nr]);
260
261 if (new_div == old_div) /* No change */
262 return count;
263
9a61bf63 264 mutex_lock(&data->update_lock);
1da177e4
LT
265 switch (new_div) {
266 case 1: data->fan_div[nr] = 0; break;
267 case 2: data->fan_div[nr] = 1; break;
268 case 4: data->fan_div[nr] = 2; break;
269 case 8: data->fan_div[nr] = 3; break;
270 default:
9a61bf63 271 mutex_unlock(&data->update_lock);
1da177e4
LT
272 return -EINVAL;
273 }
274
8eccbb6f
JD
275 switch (nr) {
276 case 0:
277 case 1:
51f2cca1 278 tmp = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV)
8eccbb6f
JD
279 & ~(0x03 << (4 + 2 * nr));
280 tmp |= data->fan_div[nr] << (4 + 2 * nr);
51f2cca1 281 smsc47m1_write_value(data, SMSC47M1_REG_FANDIV, tmp);
8eccbb6f
JD
282 break;
283 case 2:
51f2cca1 284 tmp = smsc47m1_read_value(data, SMSC47M2_REG_FANDIV3) & 0xCF;
8eccbb6f 285 tmp |= data->fan_div[2] << 4;
51f2cca1 286 smsc47m1_write_value(data, SMSC47M2_REG_FANDIV3, tmp);
8eccbb6f
JD
287 break;
288 }
1da177e4
LT
289
290 /* Preserve fan min */
291 tmp = 192 - (old_div * (192 - data->fan_preload[nr])
292 + new_div / 2) / new_div;
293 data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
51f2cca1 294 smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr],
1da177e4 295 data->fan_preload[nr]);
9a61bf63 296 mutex_unlock(&data->update_lock);
1da177e4
LT
297
298 return count;
299}
300
e84cfbcb
JD
301static ssize_t set_pwm(struct device *dev, struct device_attribute
302 *devattr, const char *buf, size_t count)
1da177e4 303{
e84cfbcb 304 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
51f2cca1 305 struct smsc47m1_data *data = dev_get_drvdata(dev);
e84cfbcb 306 int nr = attr->index;
1da177e4
LT
307 long val = simple_strtol(buf, NULL, 10);
308
309 if (val < 0 || val > 255)
310 return -EINVAL;
311
9a61bf63 312 mutex_lock(&data->update_lock);
1da177e4
LT
313 data->pwm[nr] &= 0x81; /* Preserve additional bits */
314 data->pwm[nr] |= PWM_TO_REG(val);
51f2cca1 315 smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr],
1da177e4 316 data->pwm[nr]);
9a61bf63 317 mutex_unlock(&data->update_lock);
1da177e4
LT
318
319 return count;
320}
321
e84cfbcb
JD
322static ssize_t set_pwm_en(struct device *dev, struct device_attribute
323 *devattr, const char *buf, size_t count)
1da177e4 324{
e84cfbcb 325 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
51f2cca1 326 struct smsc47m1_data *data = dev_get_drvdata(dev);
e84cfbcb 327 int nr = attr->index;
1da177e4
LT
328 long val = simple_strtol(buf, NULL, 10);
329
330 if (val != 0 && val != 1)
331 return -EINVAL;
332
9a61bf63 333 mutex_lock(&data->update_lock);
1da177e4
LT
334 data->pwm[nr] &= 0xFE; /* preserve the other bits */
335 data->pwm[nr] |= !val;
51f2cca1 336 smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr],
1da177e4 337 data->pwm[nr]);
9a61bf63 338 mutex_unlock(&data->update_lock);
1da177e4
LT
339
340 return count;
341}
342
343#define fan_present(offset) \
e84cfbcb
JD
344static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan, \
345 NULL, offset - 1); \
346static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
347 get_fan_min, set_fan_min, offset - 1); \
348static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
349 get_fan_div, set_fan_div, offset - 1); \
350static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
351 get_pwm, set_pwm, offset - 1); \
352static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
353 get_pwm_en, set_pwm_en, offset - 1)
1da177e4
LT
354
355fan_present(1);
356fan_present(2);
8eccbb6f 357fan_present(3);
1da177e4
LT
358
359static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
360
51f2cca1
JD
361static ssize_t show_name(struct device *dev, struct device_attribute
362 *devattr, char *buf)
363{
364 struct smsc47m1_data *data = dev_get_drvdata(dev);
365
366 return sprintf(buf, "%s\n", data->name);
367}
368static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
369
ce8c6ce1
JD
370/* Almost all sysfs files may or may not be created depending on the chip
371 setup so we create them individually. It is still convenient to define a
372 group to remove them all at once. */
373static struct attribute *smsc47m1_attributes[] = {
e84cfbcb
JD
374 &sensor_dev_attr_fan1_input.dev_attr.attr,
375 &sensor_dev_attr_fan1_min.dev_attr.attr,
376 &sensor_dev_attr_fan1_div.dev_attr.attr,
377 &sensor_dev_attr_fan2_input.dev_attr.attr,
378 &sensor_dev_attr_fan2_min.dev_attr.attr,
379 &sensor_dev_attr_fan2_div.dev_attr.attr,
380 &sensor_dev_attr_fan3_input.dev_attr.attr,
381 &sensor_dev_attr_fan3_min.dev_attr.attr,
382 &sensor_dev_attr_fan3_div.dev_attr.attr,
383
384 &sensor_dev_attr_pwm1.dev_attr.attr,
385 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
386 &sensor_dev_attr_pwm2.dev_attr.attr,
387 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
388 &sensor_dev_attr_pwm3.dev_attr.attr,
389 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
ce8c6ce1
JD
390
391 &dev_attr_alarms.attr,
51f2cca1 392 &dev_attr_name.attr,
ce8c6ce1
JD
393 NULL
394};
395
396static const struct attribute_group smsc47m1_group = {
397 .attrs = smsc47m1_attributes,
398};
399
51f2cca1
JD
400static int __init smsc47m1_find(unsigned short *addr,
401 struct smsc47m1_sio_data *sio_data)
1da177e4
LT
402{
403 u8 val;
404
405 superio_enter();
67b671bc 406 val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
1da177e4
LT
407
408 /*
6091780e
JD
409 * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
410 * (device id 0x5F) and LPC47B27x (device id 0x51) have fan control.
1da177e4 411 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
ec5ce552 412 * can do much more besides (device id 0x60).
b890a07f
JD
413 * The LPC47M997 is undocumented, but seems to be compatible with
414 * the LPC47M192, and has the same device id.
8eccbb6f
JD
415 * The LPC47M292 (device id 0x6B) is somewhat compatible, but it
416 * supports a 3rd fan, and the pin configuration registers are
417 * unfortunately different.
1da177e4 418 */
51f2cca1 419 switch (val) {
8eccbb6f 420 case 0x51:
620100cf 421 pr_info(DRVNAME ": Found SMSC LPC47B27x\n");
51f2cca1 422 sio_data->type = smsc47m1;
8eccbb6f
JD
423 break;
424 case 0x59:
620100cf 425 pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
51f2cca1 426 sio_data->type = smsc47m1;
8eccbb6f
JD
427 break;
428 case 0x5F:
620100cf 429 pr_info(DRVNAME ": Found SMSC LPC47M14x\n");
51f2cca1 430 sio_data->type = smsc47m1;
8eccbb6f
JD
431 break;
432 case 0x60:
620100cf 433 pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
51f2cca1 434 sio_data->type = smsc47m1;
8eccbb6f
JD
435 break;
436 case 0x6B:
620100cf 437 pr_info(DRVNAME ": Found SMSC LPC47M292\n");
51f2cca1 438 sio_data->type = smsc47m2;
8eccbb6f
JD
439 break;
440 default:
1da177e4
LT
441 superio_exit();
442 return -ENODEV;
443 }
444
445 superio_select();
2d8672c5
JD
446 *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
447 | superio_inb(SUPERIO_REG_BASE + 1);
1da177e4 448 val = superio_inb(SUPERIO_REG_ACT);
2d8672c5 449 if (*addr == 0 || (val & 0x01) == 0) {
620100cf 450 pr_info(DRVNAME ": Device is disabled, will not use\n");
1da177e4
LT
451 superio_exit();
452 return -ENODEV;
453 }
454
455 superio_exit();
456 return 0;
457}
458
51f2cca1 459static int __devinit smsc47m1_probe(struct platform_device *pdev)
1da177e4 460{
51f2cca1
JD
461 struct device *dev = &pdev->dev;
462 struct smsc47m1_sio_data *sio_data = dev->platform_data;
1da177e4 463 struct smsc47m1_data *data;
51f2cca1 464 struct resource *res;
1da177e4 465 int err = 0;
8eccbb6f 466 int fan1, fan2, fan3, pwm1, pwm2, pwm3;
1da177e4 467
51f2cca1
JD
468 static const char *names[] = {
469 "smsc47m1",
470 "smsc47m2",
471 };
472
473 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
474 if (!request_region(res->start, SMSC_EXTENT, DRVNAME)) {
475 dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
476 (unsigned long)res->start,
477 (unsigned long)res->end);
1da177e4
LT
478 return -EBUSY;
479 }
480
ba9c2e8d 481 if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
1da177e4
LT
482 err = -ENOMEM;
483 goto error_release;
484 }
1da177e4 485
51f2cca1
JD
486 data->addr = res->start;
487 data->type = sio_data->type;
488 data->name = names[sio_data->type];
9a61bf63 489 mutex_init(&data->update_lock);
51f2cca1 490 platform_set_drvdata(pdev, data);
1da177e4
LT
491
492 /* If no function is properly configured, there's no point in
493 actually registering the chip. */
51f2cca1 494 pwm1 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(0)) & 0x05)
1da177e4 495 == 0x04;
51f2cca1 496 pwm2 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(1)) & 0x05)
1da177e4 497 == 0x04;
8eccbb6f 498 if (data->type == smsc47m2) {
51f2cca1 499 fan1 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN1)
8eccbb6f 500 & 0x0d) == 0x09;
51f2cca1 501 fan2 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN2)
8eccbb6f 502 & 0x0d) == 0x09;
51f2cca1 503 fan3 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN3)
8eccbb6f 504 & 0x0d) == 0x0d;
51f2cca1 505 pwm3 = (smsc47m1_read_value(data, SMSC47M2_REG_PPIN3)
8eccbb6f
JD
506 & 0x0d) == 0x08;
507 } else {
51f2cca1 508 fan1 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(0))
8eccbb6f 509 & 0x05) == 0x05;
51f2cca1 510 fan2 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(1))
8eccbb6f
JD
511 & 0x05) == 0x05;
512 fan3 = 0;
513 pwm3 = 0;
514 }
515 if (!(fan1 || fan2 || fan3 || pwm1 || pwm2 || pwm3)) {
51f2cca1 516 dev_warn(dev, "Device not configured, will not use\n");
1da177e4
LT
517 err = -ENODEV;
518 goto error_free;
519 }
520
1da177e4
LT
521 /* Some values (fan min, clock dividers, pwm registers) may be
522 needed before any update is triggered, so we better read them
523 at least once here. We don't usually do it that way, but in
524 this particular case, manually reading 5 registers out of 8
525 doesn't make much sense and we're better using the existing
526 function. */
51f2cca1 527 smsc47m1_update_device(dev, 1);
1da177e4 528
943b0830 529 /* Register sysfs hooks */
1da177e4 530 if (fan1) {
e84cfbcb
JD
531 if ((err = device_create_file(dev,
532 &sensor_dev_attr_fan1_input.dev_attr))
533 || (err = device_create_file(dev,
534 &sensor_dev_attr_fan1_min.dev_attr))
535 || (err = device_create_file(dev,
536 &sensor_dev_attr_fan1_div.dev_attr)))
ce8c6ce1 537 goto error_remove_files;
1da177e4 538 } else
51f2cca1 539 dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n");
1da177e4
LT
540
541 if (fan2) {
e84cfbcb
JD
542 if ((err = device_create_file(dev,
543 &sensor_dev_attr_fan2_input.dev_attr))
544 || (err = device_create_file(dev,
545 &sensor_dev_attr_fan2_min.dev_attr))
546 || (err = device_create_file(dev,
547 &sensor_dev_attr_fan2_div.dev_attr)))
ce8c6ce1 548 goto error_remove_files;
1da177e4 549 } else
51f2cca1 550 dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n");
1da177e4 551
8eccbb6f 552 if (fan3) {
e84cfbcb
JD
553 if ((err = device_create_file(dev,
554 &sensor_dev_attr_fan3_input.dev_attr))
555 || (err = device_create_file(dev,
556 &sensor_dev_attr_fan3_min.dev_attr))
557 || (err = device_create_file(dev,
558 &sensor_dev_attr_fan3_div.dev_attr)))
8eccbb6f 559 goto error_remove_files;
8477d026 560 } else if (data->type == smsc47m2)
51f2cca1 561 dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n");
8eccbb6f 562
1da177e4 563 if (pwm1) {
e84cfbcb
JD
564 if ((err = device_create_file(dev,
565 &sensor_dev_attr_pwm1.dev_attr))
566 || (err = device_create_file(dev,
567 &sensor_dev_attr_pwm1_enable.dev_attr)))
ce8c6ce1 568 goto error_remove_files;
1da177e4 569 } else
51f2cca1 570 dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n");
8eccbb6f 571
1da177e4 572 if (pwm2) {
e84cfbcb
JD
573 if ((err = device_create_file(dev,
574 &sensor_dev_attr_pwm2.dev_attr))
575 || (err = device_create_file(dev,
576 &sensor_dev_attr_pwm2_enable.dev_attr)))
ce8c6ce1 577 goto error_remove_files;
1da177e4 578 } else
51f2cca1 579 dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n");
1da177e4 580
8eccbb6f 581 if (pwm3) {
e84cfbcb
JD
582 if ((err = device_create_file(dev,
583 &sensor_dev_attr_pwm3.dev_attr))
584 || (err = device_create_file(dev,
585 &sensor_dev_attr_pwm3_enable.dev_attr)))
8eccbb6f 586 goto error_remove_files;
8477d026 587 } else if (data->type == smsc47m2)
51f2cca1 588 dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n");
8eccbb6f 589
51f2cca1 590 if ((err = device_create_file(dev, &dev_attr_alarms)))
ce8c6ce1 591 goto error_remove_files;
68a50b56
JD
592 if ((err = device_create_file(dev, &dev_attr_name)))
593 goto error_remove_files;
ce8c6ce1 594
1beeffe4
TJ
595 data->hwmon_dev = hwmon_device_register(dev);
596 if (IS_ERR(data->hwmon_dev)) {
597 err = PTR_ERR(data->hwmon_dev);
ce8c6ce1
JD
598 goto error_remove_files;
599 }
1da177e4
LT
600
601 return 0;
602
ce8c6ce1 603error_remove_files:
51f2cca1 604 sysfs_remove_group(&dev->kobj, &smsc47m1_group);
1da177e4 605error_free:
04a6217d 606 platform_set_drvdata(pdev, NULL);
1f57ff89 607 kfree(data);
1da177e4 608error_release:
51f2cca1 609 release_region(res->start, SMSC_EXTENT);
1da177e4
LT
610 return err;
611}
612
51f2cca1 613static int __devexit smsc47m1_remove(struct platform_device *pdev)
1da177e4 614{
51f2cca1
JD
615 struct smsc47m1_data *data = platform_get_drvdata(pdev);
616 struct resource *res;
1da177e4 617
1beeffe4 618 hwmon_device_unregister(data->hwmon_dev);
51f2cca1 619 sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group);
1da177e4 620
51f2cca1
JD
621 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
622 release_region(res->start, SMSC_EXTENT);
04a6217d 623 platform_set_drvdata(pdev, NULL);
943b0830 624 kfree(data);
1da177e4
LT
625
626 return 0;
627}
628
1da177e4
LT
629static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
630 int init)
631{
51f2cca1 632 struct smsc47m1_data *data = dev_get_drvdata(dev);
1da177e4 633
9a61bf63 634 mutex_lock(&data->update_lock);
1da177e4
LT
635
636 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
8eccbb6f
JD
637 int i, fan_nr;
638 fan_nr = data->type == smsc47m2 ? 3 : 2;
1da177e4 639
8eccbb6f 640 for (i = 0; i < fan_nr; i++) {
51f2cca1 641 data->fan[i] = smsc47m1_read_value(data,
8eccbb6f 642 SMSC47M1_REG_FAN[i]);
51f2cca1 643 data->fan_preload[i] = smsc47m1_read_value(data,
8eccbb6f 644 SMSC47M1_REG_FAN_PRELOAD[i]);
51f2cca1 645 data->pwm[i] = smsc47m1_read_value(data,
8eccbb6f 646 SMSC47M1_REG_PWM[i]);
1da177e4
LT
647 }
648
51f2cca1 649 i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV);
1da177e4
LT
650 data->fan_div[0] = (i >> 4) & 0x03;
651 data->fan_div[1] = i >> 6;
652
51f2cca1 653 data->alarms = smsc47m1_read_value(data,
1da177e4
LT
654 SMSC47M1_REG_ALARM) >> 6;
655 /* Clear alarms if needed */
656 if (data->alarms)
51f2cca1 657 smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0);
1da177e4 658
8eccbb6f 659 if (fan_nr >= 3) {
51f2cca1 660 data->fan_div[2] = (smsc47m1_read_value(data,
8eccbb6f 661 SMSC47M2_REG_FANDIV3) >> 4) & 0x03;
51f2cca1 662 data->alarms |= (smsc47m1_read_value(data,
8eccbb6f
JD
663 SMSC47M2_REG_ALARM6) & 0x40) >> 4;
664 /* Clear alarm if needed */
665 if (data->alarms & 0x04)
51f2cca1 666 smsc47m1_write_value(data,
8eccbb6f
JD
667 SMSC47M2_REG_ALARM6,
668 0x40);
669 }
670
1da177e4
LT
671 data->last_updated = jiffies;
672 }
673
9a61bf63 674 mutex_unlock(&data->update_lock);
1da177e4
LT
675 return data;
676}
677
51f2cca1
JD
678static int __init smsc47m1_device_add(unsigned short address,
679 const struct smsc47m1_sio_data *sio_data)
680{
681 struct resource res = {
682 .start = address,
683 .end = address + SMSC_EXTENT - 1,
684 .name = DRVNAME,
685 .flags = IORESOURCE_IO,
686 };
687 int err;
688
689 pdev = platform_device_alloc(DRVNAME, address);
690 if (!pdev) {
691 err = -ENOMEM;
692 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
693 goto exit;
694 }
695
696 err = platform_device_add_resources(pdev, &res, 1);
697 if (err) {
698 printk(KERN_ERR DRVNAME ": Device resource addition failed "
699 "(%d)\n", err);
700 goto exit_device_put;
701 }
702
2df6d811
JD
703 err = platform_device_add_data(pdev, sio_data,
704 sizeof(struct smsc47m1_sio_data));
705 if (err) {
51f2cca1
JD
706 printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
707 goto exit_device_put;
708 }
51f2cca1
JD
709
710 err = platform_device_add(pdev);
711 if (err) {
712 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
713 err);
714 goto exit_device_put;
715 }
716
717 return 0;
718
719exit_device_put:
720 platform_device_put(pdev);
721exit:
722 return err;
723}
724
1da177e4
LT
725static int __init sm_smsc47m1_init(void)
726{
51f2cca1
JD
727 int err;
728 unsigned short address;
729 struct smsc47m1_sio_data sio_data;
730
731 if (smsc47m1_find(&address, &sio_data))
1da177e4 732 return -ENODEV;
1da177e4 733
51f2cca1
JD
734 err = platform_driver_register(&smsc47m1_driver);
735 if (err)
736 goto exit;
737
738 /* Sets global pdev as a side effect */
739 err = smsc47m1_device_add(address, &sio_data);
740 if (err)
741 goto exit_driver;
742
743 return 0;
744
745exit_driver:
746 platform_driver_unregister(&smsc47m1_driver);
747exit:
748 return err;
1da177e4
LT
749}
750
751static void __exit sm_smsc47m1_exit(void)
752{
51f2cca1
JD
753 platform_device_unregister(pdev);
754 platform_driver_unregister(&smsc47m1_driver);
1da177e4
LT
755}
756
757MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
758MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver");
759MODULE_LICENSE("GPL");
760
761module_init(sm_smsc47m1_init);
762module_exit(sm_smsc47m1_exit);