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