2 smsc47m1.c - Part of lm_sensors, Linux kernel modules
3 for hardware monitoring
5 Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x and LPC47M14x
8 Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
9 Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
10 Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com>
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <linux/module.h>
29 #include <linux/slab.h>
30 #include <linux/ioport.h>
31 #include <linux/jiffies.h>
32 #include <linux/i2c.h>
33 #include <linux/i2c-sensor.h>
34 #include <linux/init.h>
37 static unsigned short normal_i2c[] = { I2C_CLIENT_END };
38 /* Address is autodetected, there is no default value */
39 static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
40 static struct i2c_force_data forces[] = {{NULL}};
42 enum chips { any_chip, smsc47m1 };
43 static struct i2c_address_data addr_data = {
44 .normal_i2c = normal_i2c,
45 .normal_isa = normal_isa,
49 /* Super-I/0 registers and commands */
51 #define REG 0x2e /* The register to read/write */
52 #define VAL 0x2f /* The value to read/write */
55 superio_outb(int reg, int val)
68 /* logical device for fans is 0x0A */
69 #define superio_select() superio_outb(0x07, 0x0A)
83 #define SUPERIO_REG_ACT 0x30
84 #define SUPERIO_REG_BASE 0x60
85 #define SUPERIO_REG_DEVID 0x20
87 /* Logical device registers */
89 #define SMSC_EXTENT 0x80
91 /* nr is 0 or 1 in the macros below */
92 #define SMSC47M1_REG_ALARM 0x04
93 #define SMSC47M1_REG_TPIN(nr) (0x34 - (nr))
94 #define SMSC47M1_REG_PPIN(nr) (0x36 - (nr))
95 #define SMSC47M1_REG_PWM(nr) (0x56 + (nr))
96 #define SMSC47M1_REG_FANDIV 0x58
97 #define SMSC47M1_REG_FAN(nr) (0x59 + (nr))
98 #define SMSC47M1_REG_FAN_PRELOAD(nr) (0x5B + (nr))
100 #define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \
101 983040/((192-(reg))*(div)))
102 #define FAN_FROM_REG(reg,div,preload) ((reg)<=(preload) || (reg)==255 ? 0 : \
103 983040/(((reg)-(preload))*(div)))
104 #define DIV_FROM_REG(reg) (1 << (reg))
105 #define PWM_FROM_REG(reg) (((reg) & 0x7E) << 1)
106 #define PWM_EN_FROM_REG(reg) ((~(reg)) & 0x01)
107 #define PWM_TO_REG(reg) (((reg) >> 1) & 0x7E)
109 struct smsc47m1_data {
110 struct i2c_client client;
111 struct semaphore lock;
113 struct semaphore update_lock;
114 unsigned long last_updated; /* In jiffies */
116 u8 fan[2]; /* Register value */
117 u8 fan_preload[2]; /* Register value */
118 u8 fan_div[2]; /* Register encoding, shifted right */
119 u8 alarms; /* Register encoding */
120 u8 pwm[2]; /* Register value (bit 7 is enable) */
124 static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
125 static int smsc47m1_find(int *address);
126 static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind);
127 static int smsc47m1_detach_client(struct i2c_client *client);
129 static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
130 static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value);
132 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
136 static struct i2c_driver smsc47m1_driver = {
137 .owner = THIS_MODULE,
139 .id = I2C_DRIVERID_SMSC47M1,
140 .flags = I2C_DF_NOTIFY,
141 .attach_adapter = smsc47m1_attach_adapter,
142 .detach_client = smsc47m1_detach_client,
145 /* nr is 0 or 1 in the callback functions below */
147 static ssize_t get_fan(struct device *dev, char *buf, int nr)
149 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
150 /* This chip (stupidly) stops monitoring fan speed if PWM is
151 enabled and duty cycle is 0%. This is fine if the monitoring
152 and control concern the same fan, but troublesome if they are
153 not (which could as well happen). */
154 int rpm = (data->pwm[nr] & 0x7F) == 0x00 ? 0 :
155 FAN_FROM_REG(data->fan[nr],
156 DIV_FROM_REG(data->fan_div[nr]),
157 data->fan_preload[nr]);
158 return sprintf(buf, "%d\n", rpm);
161 static ssize_t get_fan_min(struct device *dev, char *buf, int nr)
163 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
164 int rpm = MIN_FROM_REG(data->fan_preload[nr],
165 DIV_FROM_REG(data->fan_div[nr]));
166 return sprintf(buf, "%d\n", rpm);
169 static ssize_t get_fan_div(struct device *dev, char *buf, int nr)
171 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
172 return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
175 static ssize_t get_pwm(struct device *dev, char *buf, int nr)
177 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
178 return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
181 static ssize_t get_pwm_en(struct device *dev, char *buf, int nr)
183 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
184 return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr]));
187 static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, char *buf)
189 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
190 return sprintf(buf, "%d\n", data->alarms);
193 static ssize_t set_fan_min(struct device *dev, const char *buf,
194 size_t count, int nr)
196 struct i2c_client *client = to_i2c_client(dev);
197 struct smsc47m1_data *data = i2c_get_clientdata(client);
198 long rpmdiv, val = simple_strtol(buf, NULL, 10);
200 down(&data->update_lock);
201 rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]);
203 if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) {
204 up(&data->update_lock);
208 data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv);
209 smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
210 data->fan_preload[nr]);
211 up(&data->update_lock);
216 /* Note: we save and restore the fan minimum here, because its value is
217 determined in part by the fan clock divider. This follows the principle
218 of least suprise; the user doesn't expect the fan minimum to change just
219 because the divider changed. */
220 static ssize_t set_fan_div(struct device *dev, const char *buf,
221 size_t count, int nr)
223 struct i2c_client *client = to_i2c_client(dev);
224 struct smsc47m1_data *data = i2c_get_clientdata(client);
226 long new_div = simple_strtol(buf, NULL, 10), tmp;
227 u8 old_div = DIV_FROM_REG(data->fan_div[nr]);
229 if (new_div == old_div) /* No change */
232 down(&data->update_lock);
234 case 1: data->fan_div[nr] = 0; break;
235 case 2: data->fan_div[nr] = 1; break;
236 case 4: data->fan_div[nr] = 2; break;
237 case 8: data->fan_div[nr] = 3; break;
239 up(&data->update_lock);
243 tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV) & 0x0F;
244 tmp |= (data->fan_div[0] << 4) | (data->fan_div[1] << 6);
245 smsc47m1_write_value(client, SMSC47M1_REG_FANDIV, tmp);
247 /* Preserve fan min */
248 tmp = 192 - (old_div * (192 - data->fan_preload[nr])
249 + new_div / 2) / new_div;
250 data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
251 smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
252 data->fan_preload[nr]);
253 up(&data->update_lock);
258 static ssize_t set_pwm(struct device *dev, const char *buf,
259 size_t count, int nr)
261 struct i2c_client *client = to_i2c_client(dev);
262 struct smsc47m1_data *data = i2c_get_clientdata(client);
264 long val = simple_strtol(buf, NULL, 10);
266 if (val < 0 || val > 255)
269 down(&data->update_lock);
270 data->pwm[nr] &= 0x81; /* Preserve additional bits */
271 data->pwm[nr] |= PWM_TO_REG(val);
272 smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
274 up(&data->update_lock);
279 static ssize_t set_pwm_en(struct device *dev, const char *buf,
280 size_t count, int nr)
282 struct i2c_client *client = to_i2c_client(dev);
283 struct smsc47m1_data *data = i2c_get_clientdata(client);
285 long val = simple_strtol(buf, NULL, 10);
287 if (val != 0 && val != 1)
290 down(&data->update_lock);
291 data->pwm[nr] &= 0xFE; /* preserve the other bits */
292 data->pwm[nr] |= !val;
293 smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
295 up(&data->update_lock);
300 #define fan_present(offset) \
301 static ssize_t get_fan##offset (struct device *dev, struct device_attribute *attr, char *buf) \
303 return get_fan(dev, buf, offset - 1); \
305 static ssize_t get_fan##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
307 return get_fan_min(dev, buf, offset - 1); \
309 static ssize_t set_fan##offset##_min (struct device *dev, struct device_attribute *attr, \
310 const char *buf, size_t count) \
312 return set_fan_min(dev, buf, count, offset - 1); \
314 static ssize_t get_fan##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \
316 return get_fan_div(dev, buf, offset - 1); \
318 static ssize_t set_fan##offset##_div (struct device *dev, struct device_attribute *attr, \
319 const char *buf, size_t count) \
321 return set_fan_div(dev, buf, count, offset - 1); \
323 static ssize_t get_pwm##offset (struct device *dev, struct device_attribute *attr, char *buf) \
325 return get_pwm(dev, buf, offset - 1); \
327 static ssize_t set_pwm##offset (struct device *dev, struct device_attribute *attr, \
328 const char *buf, size_t count) \
330 return set_pwm(dev, buf, count, offset - 1); \
332 static ssize_t get_pwm##offset##_en (struct device *dev, struct device_attribute *attr, char *buf) \
334 return get_pwm_en(dev, buf, offset - 1); \
336 static ssize_t set_pwm##offset##_en (struct device *dev, struct device_attribute *attr, \
337 const char *buf, size_t count) \
339 return set_pwm_en(dev, buf, count, offset - 1); \
341 static DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan##offset, \
343 static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
344 get_fan##offset##_min, set_fan##offset##_min); \
345 static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
346 get_fan##offset##_div, set_fan##offset##_div); \
347 static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
348 get_pwm##offset, set_pwm##offset); \
349 static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
350 get_pwm##offset##_en, set_pwm##offset##_en);
355 static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
357 static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
359 if (!(adapter->class & I2C_CLASS_HWMON))
361 return i2c_detect(adapter, &addr_data, smsc47m1_detect);
364 static int smsc47m1_find(int *address)
369 val = superio_inb(SUPERIO_REG_DEVID);
372 * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
373 * 0x5F) and LPC47B27x (device id 0x51) have fan control.
374 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
375 * can do much more besides (device id 0x60, unsupported).
378 printk(KERN_INFO "smsc47m1: Found SMSC47B27x\n");
379 else if (val == 0x59)
380 printk(KERN_INFO "smsc47m1: Found SMSC47M10x/SMSC47M13x\n");
381 else if (val == 0x5F)
382 printk(KERN_INFO "smsc47m1: Found SMSC47M14x\n");
389 *address = (superio_inb(SUPERIO_REG_BASE) << 8)
390 | superio_inb(SUPERIO_REG_BASE + 1);
391 val = superio_inb(SUPERIO_REG_ACT);
392 if (*address == 0 || (val & 0x01) == 0) {
393 printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
402 static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
404 struct i2c_client *new_client;
405 struct smsc47m1_data *data;
407 int fan1, fan2, pwm1, pwm2;
409 if (!i2c_is_isa_adapter(adapter)) {
413 if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
414 dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
418 if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
422 memset(data, 0x00, sizeof(struct smsc47m1_data));
424 new_client = &data->client;
425 i2c_set_clientdata(new_client, data);
426 new_client->addr = address;
427 init_MUTEX(&data->lock);
428 new_client->adapter = adapter;
429 new_client->driver = &smsc47m1_driver;
430 new_client->flags = 0;
432 strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE);
433 init_MUTEX(&data->update_lock);
435 /* If no function is properly configured, there's no point in
436 actually registering the chip. */
437 fan1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05)
439 fan2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05)
441 pwm1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05)
443 pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05)
445 if (!(fan1 || fan2 || pwm1 || pwm2)) {
446 dev_warn(&new_client->dev, "Device is not configured, will not use\n");
451 if ((err = i2c_attach_client(new_client)))
454 /* Some values (fan min, clock dividers, pwm registers) may be
455 needed before any update is triggered, so we better read them
456 at least once here. We don't usually do it that way, but in
457 this particular case, manually reading 5 registers out of 8
458 doesn't make much sense and we're better using the existing
460 smsc47m1_update_device(&new_client->dev, 1);
463 device_create_file(&new_client->dev, &dev_attr_fan1_input);
464 device_create_file(&new_client->dev, &dev_attr_fan1_min);
465 device_create_file(&new_client->dev, &dev_attr_fan1_div);
467 dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, "
471 device_create_file(&new_client->dev, &dev_attr_fan2_input);
472 device_create_file(&new_client->dev, &dev_attr_fan2_min);
473 device_create_file(&new_client->dev, &dev_attr_fan2_div);
475 dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, "
479 device_create_file(&new_client->dev, &dev_attr_pwm1);
480 device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
482 dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, "
485 device_create_file(&new_client->dev, &dev_attr_pwm2);
486 device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
488 dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, "
491 device_create_file(&new_client->dev, &dev_attr_alarms);
498 release_region(address, SMSC_EXTENT);
502 static int smsc47m1_detach_client(struct i2c_client *client)
506 if ((err = i2c_detach_client(client))) {
507 dev_err(&client->dev, "Client deregistration failed, "
508 "client not detached.\n");
512 release_region(client->addr, SMSC_EXTENT);
513 kfree(i2c_get_clientdata(client));
518 static int smsc47m1_read_value(struct i2c_client *client, u8 reg)
522 down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
523 res = inb_p(client->addr + reg);
524 up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
528 static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value)
530 down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
531 outb_p(value, client->addr + reg);
532 up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
535 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
538 struct i2c_client *client = to_i2c_client(dev);
539 struct smsc47m1_data *data = i2c_get_clientdata(client);
541 down(&data->update_lock);
543 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
546 for (i = 0; i < 2; i++) {
547 data->fan[i] = smsc47m1_read_value(client,
548 SMSC47M1_REG_FAN(i));
549 data->fan_preload[i] = smsc47m1_read_value(client,
550 SMSC47M1_REG_FAN_PRELOAD(i));
551 data->pwm[i] = smsc47m1_read_value(client,
552 SMSC47M1_REG_PWM(i));
555 i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV);
556 data->fan_div[0] = (i >> 4) & 0x03;
557 data->fan_div[1] = i >> 6;
559 data->alarms = smsc47m1_read_value(client,
560 SMSC47M1_REG_ALARM) >> 6;
561 /* Clear alarms if needed */
563 smsc47m1_write_value(client, SMSC47M1_REG_ALARM, 0xC0);
565 data->last_updated = jiffies;
568 up(&data->update_lock);
572 static int __init sm_smsc47m1_init(void)
574 if (smsc47m1_find(normal_isa)) {
578 return i2c_add_driver(&smsc47m1_driver);
581 static void __exit sm_smsc47m1_exit(void)
583 i2c_del_driver(&smsc47m1_driver);
586 MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
587 MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver");
588 MODULE_LICENSE("GPL");
590 module_init(sm_smsc47m1_init);
591 module_exit(sm_smsc47m1_exit);