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