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).
378 printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
379 else if (val == 0x59)
380 printk(KERN_INFO "smsc47m1: Found SMSC LPC47M10x/LPC47M13x\n");
381 else if (val == 0x5F)
382 printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
383 else if (val == 0x60)
384 printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
391 *address = (superio_inb(SUPERIO_REG_BASE) << 8)
392 | superio_inb(SUPERIO_REG_BASE + 1);
393 val = superio_inb(SUPERIO_REG_ACT);
394 if (*address == 0 || (val & 0x01) == 0) {
395 printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
404 static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
406 struct i2c_client *new_client;
407 struct smsc47m1_data *data;
409 int fan1, fan2, pwm1, pwm2;
411 if (!i2c_is_isa_adapter(adapter)) {
415 if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
416 dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
420 if (!(data = kmalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
424 memset(data, 0x00, sizeof(struct smsc47m1_data));
426 new_client = &data->client;
427 i2c_set_clientdata(new_client, data);
428 new_client->addr = address;
429 init_MUTEX(&data->lock);
430 new_client->adapter = adapter;
431 new_client->driver = &smsc47m1_driver;
432 new_client->flags = 0;
434 strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE);
435 init_MUTEX(&data->update_lock);
437 /* If no function is properly configured, there's no point in
438 actually registering the chip. */
439 fan1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(0)) & 0x05)
441 fan2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_TPIN(1)) & 0x05)
443 pwm1 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(0)) & 0x05)
445 pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05)
447 if (!(fan1 || fan2 || pwm1 || pwm2)) {
448 dev_warn(&new_client->dev, "Device is not configured, will not use\n");
453 if ((err = i2c_attach_client(new_client)))
456 /* Some values (fan min, clock dividers, pwm registers) may be
457 needed before any update is triggered, so we better read them
458 at least once here. We don't usually do it that way, but in
459 this particular case, manually reading 5 registers out of 8
460 doesn't make much sense and we're better using the existing
462 smsc47m1_update_device(&new_client->dev, 1);
465 device_create_file(&new_client->dev, &dev_attr_fan1_input);
466 device_create_file(&new_client->dev, &dev_attr_fan1_min);
467 device_create_file(&new_client->dev, &dev_attr_fan1_div);
469 dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, "
473 device_create_file(&new_client->dev, &dev_attr_fan2_input);
474 device_create_file(&new_client->dev, &dev_attr_fan2_min);
475 device_create_file(&new_client->dev, &dev_attr_fan2_div);
477 dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, "
481 device_create_file(&new_client->dev, &dev_attr_pwm1);
482 device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
484 dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, "
487 device_create_file(&new_client->dev, &dev_attr_pwm2);
488 device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
490 dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, "
493 device_create_file(&new_client->dev, &dev_attr_alarms);
500 release_region(address, SMSC_EXTENT);
504 static int smsc47m1_detach_client(struct i2c_client *client)
508 if ((err = i2c_detach_client(client))) {
509 dev_err(&client->dev, "Client deregistration failed, "
510 "client not detached.\n");
514 release_region(client->addr, SMSC_EXTENT);
515 kfree(i2c_get_clientdata(client));
520 static int smsc47m1_read_value(struct i2c_client *client, u8 reg)
524 down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
525 res = inb_p(client->addr + reg);
526 up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
530 static void smsc47m1_write_value(struct i2c_client *client, u8 reg, u8 value)
532 down(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
533 outb_p(value, client->addr + reg);
534 up(&((struct smsc47m1_data *) i2c_get_clientdata(client))->lock);
537 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
540 struct i2c_client *client = to_i2c_client(dev);
541 struct smsc47m1_data *data = i2c_get_clientdata(client);
543 down(&data->update_lock);
545 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
548 for (i = 0; i < 2; i++) {
549 data->fan[i] = smsc47m1_read_value(client,
550 SMSC47M1_REG_FAN(i));
551 data->fan_preload[i] = smsc47m1_read_value(client,
552 SMSC47M1_REG_FAN_PRELOAD(i));
553 data->pwm[i] = smsc47m1_read_value(client,
554 SMSC47M1_REG_PWM(i));
557 i = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV);
558 data->fan_div[0] = (i >> 4) & 0x03;
559 data->fan_div[1] = i >> 6;
561 data->alarms = smsc47m1_read_value(client,
562 SMSC47M1_REG_ALARM) >> 6;
563 /* Clear alarms if needed */
565 smsc47m1_write_value(client, SMSC47M1_REG_ALARM, 0xC0);
567 data->last_updated = jiffies;
570 up(&data->update_lock);
574 static int __init sm_smsc47m1_init(void)
576 if (smsc47m1_find(normal_isa)) {
580 return i2c_add_driver(&smsc47m1_driver);
583 static void __exit sm_smsc47m1_exit(void)
585 i2c_del_driver(&smsc47m1_driver);
588 MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
589 MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver");
590 MODULE_LICENSE("GPL");
592 module_init(sm_smsc47m1_init);
593 module_exit(sm_smsc47m1_exit);