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