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