hwmon: (smsc47m1) Fail module loading on error
[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>
b9acb64a 40#include <linux/acpi.h>
6055fae8 41#include <linux/io.h>
1da177e4 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 141
3ecf44b3 142static int __exit 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 },
3ecf44b3 162 .remove = __exit_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.
1b54ab45
JD
431 * The LPC47M233 has the same device id (0x6B) but is not compatible.
432 * We check the high bit of the device revision register to
433 * differentiate them.
1da177e4 434 */
51f2cca1 435 switch (val) {
8eccbb6f 436 case 0x51:
620100cf 437 pr_info(DRVNAME ": Found SMSC LPC47B27x\n");
51f2cca1 438 sio_data->type = smsc47m1;
8eccbb6f
JD
439 break;
440 case 0x59:
620100cf 441 pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
51f2cca1 442 sio_data->type = smsc47m1;
8eccbb6f
JD
443 break;
444 case 0x5F:
620100cf 445 pr_info(DRVNAME ": Found SMSC LPC47M14x\n");
51f2cca1 446 sio_data->type = smsc47m1;
8eccbb6f
JD
447 break;
448 case 0x60:
620100cf 449 pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
51f2cca1 450 sio_data->type = smsc47m1;
8eccbb6f
JD
451 break;
452 case 0x6B:
1b54ab45
JD
453 if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) {
454 pr_debug(DRVNAME ": "
455 "Found SMSC LPC47M233, unsupported\n");
456 superio_exit();
457 return -ENODEV;
458 }
459
620100cf 460 pr_info(DRVNAME ": Found SMSC LPC47M292\n");
51f2cca1 461 sio_data->type = smsc47m2;
8eccbb6f
JD
462 break;
463 default:
1da177e4
LT
464 superio_exit();
465 return -ENODEV;
466 }
467
468 superio_select();
2d8672c5
JD
469 *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
470 | superio_inb(SUPERIO_REG_BASE + 1);
1da177e4 471 val = superio_inb(SUPERIO_REG_ACT);
2d8672c5 472 if (*addr == 0 || (val & 0x01) == 0) {
620100cf 473 pr_info(DRVNAME ": Device is disabled, will not use\n");
1da177e4
LT
474 superio_exit();
475 return -ENODEV;
476 }
477
478 superio_exit();
479 return 0;
480}
481
a0e92d70
JD
482#define CHECK 1
483#define REQUEST 2
484#define RELEASE 3
485
486/*
487 * This function can be used to:
488 * - test for resource conflicts with ACPI
489 * - request the resources
490 * - release the resources
491 * We only allocate the I/O ports we really need, to minimize the risk of
492 * conflicts with ACPI or with other drivers.
493 */
494static int smsc47m1_handle_resources(unsigned short address, enum chips type,
495 int action, struct device *dev)
496{
497 static const u8 ports_m1[] = {
498 /* register, region length */
499 0x04, 1,
500 0x33, 4,
501 0x56, 7,
502 };
503
504 static const u8 ports_m2[] = {
505 /* register, region length */
506 0x04, 1,
507 0x09, 1,
508 0x2c, 2,
509 0x35, 4,
510 0x56, 7,
511 0x69, 4,
512 };
513
514 int i, ports_size, err;
515 const u8 *ports;
516
517 switch (type) {
518 case smsc47m1:
519 default:
520 ports = ports_m1;
521 ports_size = ARRAY_SIZE(ports_m1);
522 break;
523 case smsc47m2:
524 ports = ports_m2;
525 ports_size = ARRAY_SIZE(ports_m2);
526 break;
527 }
528
529 for (i = 0; i + 1 < ports_size; i += 2) {
530 unsigned short start = address + ports[i];
531 unsigned short len = ports[i + 1];
532
533 switch (action) {
534 case CHECK:
535 /* Only check for conflicts */
536 err = acpi_check_region(start, len, DRVNAME);
537 if (err)
538 return err;
539 break;
540 case REQUEST:
541 /* Request the resources */
542 if (!request_region(start, len, DRVNAME)) {
543 dev_err(dev, "Region 0x%hx-0x%hx already in "
544 "use!\n", start, start + len);
545
546 /* Undo all requests */
547 for (i -= 2; i >= 0; i -= 2)
548 release_region(address + ports[i],
549 ports[i + 1]);
550 return -EBUSY;
551 }
552 break;
553 case RELEASE:
554 /* Release the resources */
555 release_region(start, len);
556 break;
557 }
558 }
559
560 return 0;
561}
562
3ecf44b3 563static int __init smsc47m1_probe(struct platform_device *pdev)
1da177e4 564{
51f2cca1
JD
565 struct device *dev = &pdev->dev;
566 struct smsc47m1_sio_data *sio_data = dev->platform_data;
1da177e4 567 struct smsc47m1_data *data;
51f2cca1 568 struct resource *res;
a0e92d70 569 int err;
8eccbb6f 570 int fan1, fan2, fan3, pwm1, pwm2, pwm3;
1da177e4 571
51f2cca1
JD
572 static const char *names[] = {
573 "smsc47m1",
574 "smsc47m2",
575 };
576
577 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
a0e92d70
JD
578 err = smsc47m1_handle_resources(res->start, sio_data->type,
579 REQUEST, dev);
580 if (err < 0)
581 return err;
1da177e4 582
ba9c2e8d 583 if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
1da177e4
LT
584 err = -ENOMEM;
585 goto error_release;
586 }
1da177e4 587
51f2cca1
JD
588 data->addr = res->start;
589 data->type = sio_data->type;
590 data->name = names[sio_data->type];
9a61bf63 591 mutex_init(&data->update_lock);
51f2cca1 592 platform_set_drvdata(pdev, data);
1da177e4
LT
593
594 /* If no function is properly configured, there's no point in
595 actually registering the chip. */
51f2cca1 596 pwm1 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(0)) & 0x05)
1da177e4 597 == 0x04;
51f2cca1 598 pwm2 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(1)) & 0x05)
1da177e4 599 == 0x04;
8eccbb6f 600 if (data->type == smsc47m2) {
51f2cca1 601 fan1 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN1)
8eccbb6f 602 & 0x0d) == 0x09;
51f2cca1 603 fan2 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN2)
8eccbb6f 604 & 0x0d) == 0x09;
51f2cca1 605 fan3 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN3)
8eccbb6f 606 & 0x0d) == 0x0d;
51f2cca1 607 pwm3 = (smsc47m1_read_value(data, SMSC47M2_REG_PPIN3)
8eccbb6f
JD
608 & 0x0d) == 0x08;
609 } else {
51f2cca1 610 fan1 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(0))
8eccbb6f 611 & 0x05) == 0x05;
51f2cca1 612 fan2 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(1))
8eccbb6f
JD
613 & 0x05) == 0x05;
614 fan3 = 0;
615 pwm3 = 0;
616 }
617 if (!(fan1 || fan2 || fan3 || pwm1 || pwm2 || pwm3)) {
51f2cca1 618 dev_warn(dev, "Device not configured, will not use\n");
1da177e4
LT
619 err = -ENODEV;
620 goto error_free;
621 }
622
1da177e4
LT
623 /* Some values (fan min, clock dividers, pwm registers) may be
624 needed before any update is triggered, so we better read them
625 at least once here. We don't usually do it that way, but in
626 this particular case, manually reading 5 registers out of 8
627 doesn't make much sense and we're better using the existing
628 function. */
51f2cca1 629 smsc47m1_update_device(dev, 1);
1da177e4 630
943b0830 631 /* Register sysfs hooks */
1da177e4 632 if (fan1) {
e84cfbcb
JD
633 if ((err = device_create_file(dev,
634 &sensor_dev_attr_fan1_input.dev_attr))
635 || (err = device_create_file(dev,
636 &sensor_dev_attr_fan1_min.dev_attr))
637 || (err = device_create_file(dev,
1f08af7e
JD
638 &sensor_dev_attr_fan1_div.dev_attr))
639 || (err = device_create_file(dev,
640 &sensor_dev_attr_fan1_alarm.dev_attr)))
ce8c6ce1 641 goto error_remove_files;
1da177e4 642 } else
51f2cca1 643 dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n");
1da177e4
LT
644
645 if (fan2) {
e84cfbcb
JD
646 if ((err = device_create_file(dev,
647 &sensor_dev_attr_fan2_input.dev_attr))
648 || (err = device_create_file(dev,
649 &sensor_dev_attr_fan2_min.dev_attr))
650 || (err = device_create_file(dev,
1f08af7e
JD
651 &sensor_dev_attr_fan2_div.dev_attr))
652 || (err = device_create_file(dev,
653 &sensor_dev_attr_fan2_alarm.dev_attr)))
ce8c6ce1 654 goto error_remove_files;
1da177e4 655 } else
51f2cca1 656 dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n");
1da177e4 657
8eccbb6f 658 if (fan3) {
e84cfbcb
JD
659 if ((err = device_create_file(dev,
660 &sensor_dev_attr_fan3_input.dev_attr))
661 || (err = device_create_file(dev,
662 &sensor_dev_attr_fan3_min.dev_attr))
663 || (err = device_create_file(dev,
1f08af7e
JD
664 &sensor_dev_attr_fan3_div.dev_attr))
665 || (err = device_create_file(dev,
666 &sensor_dev_attr_fan3_alarm.dev_attr)))
8eccbb6f 667 goto error_remove_files;
8477d026 668 } else if (data->type == smsc47m2)
51f2cca1 669 dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n");
8eccbb6f 670
1da177e4 671 if (pwm1) {
e84cfbcb
JD
672 if ((err = device_create_file(dev,
673 &sensor_dev_attr_pwm1.dev_attr))
674 || (err = device_create_file(dev,
675 &sensor_dev_attr_pwm1_enable.dev_attr)))
ce8c6ce1 676 goto error_remove_files;
1da177e4 677 } else
51f2cca1 678 dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n");
8eccbb6f 679
1da177e4 680 if (pwm2) {
e84cfbcb
JD
681 if ((err = device_create_file(dev,
682 &sensor_dev_attr_pwm2.dev_attr))
683 || (err = device_create_file(dev,
684 &sensor_dev_attr_pwm2_enable.dev_attr)))
ce8c6ce1 685 goto error_remove_files;
1da177e4 686 } else
51f2cca1 687 dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n");
1da177e4 688
8eccbb6f 689 if (pwm3) {
e84cfbcb
JD
690 if ((err = device_create_file(dev,
691 &sensor_dev_attr_pwm3.dev_attr))
692 || (err = device_create_file(dev,
693 &sensor_dev_attr_pwm3_enable.dev_attr)))
8eccbb6f 694 goto error_remove_files;
8477d026 695 } else if (data->type == smsc47m2)
51f2cca1 696 dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n");
8eccbb6f 697
51f2cca1 698 if ((err = device_create_file(dev, &dev_attr_alarms)))
ce8c6ce1 699 goto error_remove_files;
68a50b56
JD
700 if ((err = device_create_file(dev, &dev_attr_name)))
701 goto error_remove_files;
ce8c6ce1 702
1beeffe4
TJ
703 data->hwmon_dev = hwmon_device_register(dev);
704 if (IS_ERR(data->hwmon_dev)) {
705 err = PTR_ERR(data->hwmon_dev);
ce8c6ce1
JD
706 goto error_remove_files;
707 }
1da177e4
LT
708
709 return 0;
710
ce8c6ce1 711error_remove_files:
51f2cca1 712 sysfs_remove_group(&dev->kobj, &smsc47m1_group);
1da177e4 713error_free:
04a6217d 714 platform_set_drvdata(pdev, NULL);
1f57ff89 715 kfree(data);
1da177e4 716error_release:
a0e92d70 717 smsc47m1_handle_resources(res->start, sio_data->type, RELEASE, dev);
1da177e4
LT
718 return err;
719}
720
3ecf44b3 721static int __exit smsc47m1_remove(struct platform_device *pdev)
1da177e4 722{
51f2cca1
JD
723 struct smsc47m1_data *data = platform_get_drvdata(pdev);
724 struct resource *res;
1da177e4 725
1beeffe4 726 hwmon_device_unregister(data->hwmon_dev);
51f2cca1 727 sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group);
1da177e4 728
51f2cca1 729 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
a0e92d70 730 smsc47m1_handle_resources(res->start, data->type, RELEASE, &pdev->dev);
04a6217d 731 platform_set_drvdata(pdev, NULL);
943b0830 732 kfree(data);
1da177e4
LT
733
734 return 0;
735}
736
1da177e4
LT
737static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
738 int init)
739{
51f2cca1 740 struct smsc47m1_data *data = dev_get_drvdata(dev);
1da177e4 741
9a61bf63 742 mutex_lock(&data->update_lock);
1da177e4
LT
743
744 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
8eccbb6f
JD
745 int i, fan_nr;
746 fan_nr = data->type == smsc47m2 ? 3 : 2;
1da177e4 747
8eccbb6f 748 for (i = 0; i < fan_nr; i++) {
51f2cca1 749 data->fan[i] = smsc47m1_read_value(data,
8eccbb6f 750 SMSC47M1_REG_FAN[i]);
51f2cca1 751 data->fan_preload[i] = smsc47m1_read_value(data,
8eccbb6f 752 SMSC47M1_REG_FAN_PRELOAD[i]);
51f2cca1 753 data->pwm[i] = smsc47m1_read_value(data,
8eccbb6f 754 SMSC47M1_REG_PWM[i]);
1da177e4
LT
755 }
756
51f2cca1 757 i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV);
1da177e4
LT
758 data->fan_div[0] = (i >> 4) & 0x03;
759 data->fan_div[1] = i >> 6;
760
51f2cca1 761 data->alarms = smsc47m1_read_value(data,
1da177e4
LT
762 SMSC47M1_REG_ALARM) >> 6;
763 /* Clear alarms if needed */
764 if (data->alarms)
51f2cca1 765 smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0);
1da177e4 766
8eccbb6f 767 if (fan_nr >= 3) {
51f2cca1 768 data->fan_div[2] = (smsc47m1_read_value(data,
8eccbb6f 769 SMSC47M2_REG_FANDIV3) >> 4) & 0x03;
51f2cca1 770 data->alarms |= (smsc47m1_read_value(data,
8eccbb6f
JD
771 SMSC47M2_REG_ALARM6) & 0x40) >> 4;
772 /* Clear alarm if needed */
773 if (data->alarms & 0x04)
51f2cca1 774 smsc47m1_write_value(data,
8eccbb6f
JD
775 SMSC47M2_REG_ALARM6,
776 0x40);
777 }
778
1da177e4
LT
779 data->last_updated = jiffies;
780 }
781
9a61bf63 782 mutex_unlock(&data->update_lock);
1da177e4
LT
783 return data;
784}
785
51f2cca1
JD
786static int __init smsc47m1_device_add(unsigned short address,
787 const struct smsc47m1_sio_data *sio_data)
788{
789 struct resource res = {
790 .start = address,
791 .end = address + SMSC_EXTENT - 1,
792 .name = DRVNAME,
793 .flags = IORESOURCE_IO,
794 };
795 int err;
796
a0e92d70 797 err = smsc47m1_handle_resources(address, sio_data->type, CHECK, NULL);
b9acb64a
JD
798 if (err)
799 goto exit;
800
51f2cca1
JD
801 pdev = platform_device_alloc(DRVNAME, address);
802 if (!pdev) {
803 err = -ENOMEM;
804 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
805 goto exit;
806 }
807
808 err = platform_device_add_resources(pdev, &res, 1);
809 if (err) {
810 printk(KERN_ERR DRVNAME ": Device resource addition failed "
811 "(%d)\n", err);
812 goto exit_device_put;
813 }
814
2df6d811
JD
815 err = platform_device_add_data(pdev, sio_data,
816 sizeof(struct smsc47m1_sio_data));
817 if (err) {
51f2cca1
JD
818 printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
819 goto exit_device_put;
820 }
51f2cca1
JD
821
822 err = platform_device_add(pdev);
823 if (err) {
824 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
825 err);
826 goto exit_device_put;
827 }
828
829 return 0;
830
831exit_device_put:
832 platform_device_put(pdev);
833exit:
834 return err;
835}
836
1da177e4
LT
837static int __init sm_smsc47m1_init(void)
838{
51f2cca1
JD
839 int err;
840 unsigned short address;
841 struct smsc47m1_sio_data sio_data;
842
843 if (smsc47m1_find(&address, &sio_data))
1da177e4 844 return -ENODEV;
1da177e4 845
3ecf44b3
JD
846 /* Sets global pdev as a side effect */
847 err = smsc47m1_device_add(address, &sio_data);
51f2cca1
JD
848 if (err)
849 goto exit;
850
3ecf44b3 851 err = platform_driver_probe(&smsc47m1_driver, smsc47m1_probe);
51f2cca1 852 if (err)
3ecf44b3 853 goto exit_device;
51f2cca1
JD
854
855 return 0;
856
3ecf44b3
JD
857exit_device:
858 platform_device_unregister(pdev);
51f2cca1
JD
859exit:
860 return err;
1da177e4
LT
861}
862
863static void __exit sm_smsc47m1_exit(void)
864{
51f2cca1 865 platform_driver_unregister(&smsc47m1_driver);
3ecf44b3 866 platform_device_unregister(pdev);
1da177e4
LT
867}
868
869MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
870MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver");
871MODULE_LICENSE("GPL");
872
873module_init(sm_smsc47m1_init);
874module_exit(sm_smsc47m1_exit);
This page took 0.509698 seconds and 5 git commands to generate.