2 * pc87427.c - hardware monitoring driver for the
3 * National Semiconductor PC87427 Super-I/O chip
4 * Copyright (C) 2006 Jean Delvare <khali@linux-fr.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * Supports the following chips:
17 * Chip #vin #fan #pwm #temp devid
18 * PC87427 - 8 - - 0xF2
20 * This driver assumes that no more than one chip is present.
21 * Only fan inputs are supported so far, although the chip can do much more.
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/slab.h>
27 #include <linux/jiffies.h>
28 #include <linux/platform_device.h>
29 #include <linux/hwmon.h>
30 #include <linux/hwmon-sysfs.h>
31 #include <linux/err.h>
32 #include <linux/mutex.h>
33 #include <linux/sysfs.h>
36 static struct platform_device *pdev;
38 #define DRVNAME "pc87427"
40 /* The lock mutex protects both the I/O accesses (needed because the
41 device is using banked registers) and the register cache (needed to keep
42 the data in the registers and the cache in sync at any time). */
44 struct class_device *class_dev;
49 unsigned long last_updated; /* in jiffies */
50 u8 fan_enabled; /* bit vector */
51 u16 fan[8]; /* register values */
52 u16 fan_min[8]; /* register values */
53 u8 fan_status[8]; /* register values */
57 * Super-I/O registers and operations
60 #define SIOREG_LDSEL 0x07 /* Logical device select */
61 #define SIOREG_DEVID 0x20 /* Device ID */
62 #define SIOREG_ACT 0x30 /* Device activation */
63 #define SIOREG_MAP 0x50 /* I/O or memory mapping */
64 #define SIOREG_IOBASE 0x60 /* I/O base address */
66 static const u8 logdev[2] = { 0x09, 0x14 };
67 static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" };
72 static inline void superio_outb(int sioaddr, int reg, int val)
75 outb(val, sioaddr + 1);
78 static inline int superio_inb(int sioaddr, int reg)
81 return inb(sioaddr + 1);
84 static inline void superio_exit(int sioaddr)
87 outb(0x02, sioaddr + 1);
94 #define REGION_LENGTH 32
95 #define PC87427_REG_BANK 0x0f
96 #define BANK_FM(nr) (nr)
97 #define BANK_FT(nr) (0x08 + (nr))
98 #define BANK_FC(nr) (0x10 + (nr) * 2)
101 * I/O access functions
104 /* ldi is the logical device index */
105 static inline int pc87427_read8(struct pc87427_data *data, u8 ldi, u8 reg)
107 return inb(data->address[ldi] + reg);
110 /* Must be called with data->lock held, except during init */
111 static inline int pc87427_read8_bank(struct pc87427_data *data, u8 ldi,
114 outb(bank, data->address[ldi] + PC87427_REG_BANK);
115 return inb(data->address[ldi] + reg);
118 /* Must be called with data->lock held, except during init */
119 static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
120 u8 bank, u8 reg, u8 value)
122 outb(bank, data->address[ldi] + PC87427_REG_BANK);
123 outb(value, data->address[ldi] + reg);
127 * Fan registers and conversions
130 /* fan data registers are 16-bit wide */
131 #define PC87427_REG_FAN 0x12
132 #define PC87427_REG_FAN_MIN 0x14
133 #define PC87427_REG_FAN_STATUS 0x10
135 #define FAN_STATUS_STALL (1 << 3)
136 #define FAN_STATUS_LOSPD (1 << 1)
137 #define FAN_STATUS_MONEN (1 << 0)
139 /* Dedicated function to read all registers related to a given fan input.
140 This saves us quite a few locks and bank selections.
141 Must be called with data->lock held.
143 static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
145 int iobase = data->address[LD_FAN];
147 outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
148 data->fan[nr] = inw(iobase + PC87427_REG_FAN);
149 data->fan_min[nr] = inw(iobase + PC87427_REG_FAN_MIN);
150 data->fan_status[nr] = inb(iobase + PC87427_REG_FAN_STATUS);
151 /* Clear fan alarm bits */
152 outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS);
155 /* The 2 LSB of fan speed registers are used for something different.
156 The actual 2 LSB of the measurements are not available. */
157 static inline unsigned long fan_from_reg(u16 reg)
160 if (reg == 0x0000 || reg == 0xfffc)
162 return 5400000UL / reg;
165 /* The 2 LSB of the fan speed limit registers are not significant. */
166 static inline u16 fan_to_reg(unsigned long val)
170 if (val >= 1350000UL)
172 return ((1350000UL + val / 2) / val) << 2;
179 static struct pc87427_data *pc87427_update_device(struct device *dev)
181 struct pc87427_data *data = dev_get_drvdata(dev);
184 mutex_lock(&data->lock);
185 if (!time_after(jiffies, data->last_updated + HZ)
186 && data->last_updated)
190 for (i = 0; i < 8; i++) {
191 if (!(data->fan_enabled & (1 << i)))
193 pc87427_readall_fan(data, i);
195 data->last_updated = jiffies;
198 mutex_unlock(&data->lock);
202 static ssize_t show_fan_input(struct device *dev, struct device_attribute
205 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
206 struct pc87427_data *data = pc87427_update_device(dev);
207 int nr = attr->index;
209 return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
212 static ssize_t show_fan_min(struct device *dev, struct device_attribute
215 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
216 struct pc87427_data *data = pc87427_update_device(dev);
217 int nr = attr->index;
219 return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
222 static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
225 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
226 struct pc87427_data *data = pc87427_update_device(dev);
227 int nr = attr->index;
229 return sprintf(buf, "%d\n", !!(data->fan_status[nr]
230 & FAN_STATUS_LOSPD));
233 static ssize_t show_fan_fault(struct device *dev, struct device_attribute
236 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
237 struct pc87427_data *data = pc87427_update_device(dev);
238 int nr = attr->index;
240 return sprintf(buf, "%d\n", !!(data->fan_status[nr]
241 & FAN_STATUS_STALL));
244 static ssize_t set_fan_min(struct device *dev, struct device_attribute
245 *devattr, const char *buf, size_t count)
247 struct pc87427_data *data = dev_get_drvdata(dev);
248 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
249 int nr = attr->index;
250 unsigned long val = simple_strtoul(buf, NULL, 10);
251 int iobase = data->address[LD_FAN];
253 mutex_lock(&data->lock);
254 outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
255 /* The low speed limit registers are read-only while monitoring
256 is enabled, so we have to disable monitoring, then change the
257 limit, and finally enable monitoring again. */
258 outb(0, iobase + PC87427_REG_FAN_STATUS);
259 data->fan_min[nr] = fan_to_reg(val);
260 outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
261 outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS);
262 mutex_unlock(&data->lock);
267 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
268 static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
269 static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
270 static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
271 static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
272 static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
273 static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
274 static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
276 static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
277 show_fan_min, set_fan_min, 0);
278 static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
279 show_fan_min, set_fan_min, 1);
280 static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
281 show_fan_min, set_fan_min, 2);
282 static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
283 show_fan_min, set_fan_min, 3);
284 static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
285 show_fan_min, set_fan_min, 4);
286 static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
287 show_fan_min, set_fan_min, 5);
288 static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
289 show_fan_min, set_fan_min, 6);
290 static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
291 show_fan_min, set_fan_min, 7);
293 static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
294 static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
295 static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
296 static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
297 static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
298 static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
299 static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
300 static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
302 static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
303 static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
304 static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
305 static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
306 static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
307 static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
308 static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
309 static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
311 static struct attribute *pc87427_attributes_fan[8][5] = {
313 &sensor_dev_attr_fan1_input.dev_attr.attr,
314 &sensor_dev_attr_fan1_min.dev_attr.attr,
315 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
316 &sensor_dev_attr_fan1_fault.dev_attr.attr,
319 &sensor_dev_attr_fan2_input.dev_attr.attr,
320 &sensor_dev_attr_fan2_min.dev_attr.attr,
321 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
322 &sensor_dev_attr_fan2_fault.dev_attr.attr,
325 &sensor_dev_attr_fan3_input.dev_attr.attr,
326 &sensor_dev_attr_fan3_min.dev_attr.attr,
327 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
328 &sensor_dev_attr_fan3_fault.dev_attr.attr,
331 &sensor_dev_attr_fan4_input.dev_attr.attr,
332 &sensor_dev_attr_fan4_min.dev_attr.attr,
333 &sensor_dev_attr_fan4_alarm.dev_attr.attr,
334 &sensor_dev_attr_fan4_fault.dev_attr.attr,
337 &sensor_dev_attr_fan5_input.dev_attr.attr,
338 &sensor_dev_attr_fan5_min.dev_attr.attr,
339 &sensor_dev_attr_fan5_alarm.dev_attr.attr,
340 &sensor_dev_attr_fan5_fault.dev_attr.attr,
343 &sensor_dev_attr_fan6_input.dev_attr.attr,
344 &sensor_dev_attr_fan6_min.dev_attr.attr,
345 &sensor_dev_attr_fan6_alarm.dev_attr.attr,
346 &sensor_dev_attr_fan6_fault.dev_attr.attr,
349 &sensor_dev_attr_fan7_input.dev_attr.attr,
350 &sensor_dev_attr_fan7_min.dev_attr.attr,
351 &sensor_dev_attr_fan7_alarm.dev_attr.attr,
352 &sensor_dev_attr_fan7_fault.dev_attr.attr,
355 &sensor_dev_attr_fan8_input.dev_attr.attr,
356 &sensor_dev_attr_fan8_min.dev_attr.attr,
357 &sensor_dev_attr_fan8_alarm.dev_attr.attr,
358 &sensor_dev_attr_fan8_fault.dev_attr.attr,
363 static const struct attribute_group pc87427_group_fan[8] = {
364 { .attrs = pc87427_attributes_fan[0] },
365 { .attrs = pc87427_attributes_fan[1] },
366 { .attrs = pc87427_attributes_fan[2] },
367 { .attrs = pc87427_attributes_fan[3] },
368 { .attrs = pc87427_attributes_fan[4] },
369 { .attrs = pc87427_attributes_fan[5] },
370 { .attrs = pc87427_attributes_fan[6] },
371 { .attrs = pc87427_attributes_fan[7] },
374 static ssize_t show_name(struct device *dev, struct device_attribute
377 struct pc87427_data *data = dev_get_drvdata(dev);
379 return sprintf(buf, "%s\n", data->name);
381 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
385 * Device detection, attach and detach
388 static void __devinit pc87427_init_device(struct device *dev)
390 struct pc87427_data *data = dev_get_drvdata(dev);
394 /* The FMC module should be ready */
395 reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
397 dev_warn(dev, "FMC module not ready!\n");
399 /* Check which fans are enabled */
400 for (i = 0; i < 8; i++) {
401 reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
402 PC87427_REG_FAN_STATUS);
403 if (reg & FAN_STATUS_MONEN)
404 data->fan_enabled |= (1 << i);
407 if (!data->fan_enabled) {
408 dev_dbg(dev, "Enabling all fan inputs\n");
409 for (i = 0; i < 8; i++)
410 pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
411 PC87427_REG_FAN_STATUS,
413 data->fan_enabled = 0xff;
417 static int __devinit pc87427_probe(struct platform_device *pdev)
419 struct pc87427_data *data;
420 struct resource *res;
423 if (!(data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL))) {
425 printk(KERN_ERR DRVNAME ": Out of memory\n");
429 /* This will need to be revisited when we add support for
430 temperature and voltage monitoring. */
431 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
432 data->address[0] = res->start;
434 mutex_init(&data->lock);
435 data->name = "pc87427";
436 platform_set_drvdata(pdev, data);
437 pc87427_init_device(&pdev->dev);
439 /* Register sysfs hooks */
440 if ((err = device_create_file(&pdev->dev, &dev_attr_name)))
442 for (i = 0; i < 8; i++) {
443 if (!(data->fan_enabled & (1 << i)))
445 if ((err = sysfs_create_group(&pdev->dev.kobj,
446 &pc87427_group_fan[i])))
447 goto exit_remove_files;
450 data->class_dev = hwmon_device_register(&pdev->dev);
451 if (IS_ERR(data->class_dev)) {
452 err = PTR_ERR(data->class_dev);
453 dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
454 goto exit_remove_files;
460 for (i = 0; i < 8; i++) {
461 if (!(data->fan_enabled & (1 << i)))
463 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
466 platform_set_drvdata(pdev, NULL);
472 static int __devexit pc87427_remove(struct platform_device *pdev)
474 struct pc87427_data *data = platform_get_drvdata(pdev);
477 platform_set_drvdata(pdev, NULL);
478 hwmon_device_unregister(data->class_dev);
479 device_remove_file(&pdev->dev, &dev_attr_name);
480 for (i = 0; i < 8; i++) {
481 if (!(data->fan_enabled & (1 << i)))
483 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
491 static struct platform_driver pc87427_driver = {
493 .owner = THIS_MODULE,
496 .probe = pc87427_probe,
497 .remove = __devexit_p(pc87427_remove),
500 static int __init pc87427_device_add(unsigned short address)
502 struct resource res = {
504 .end = address + REGION_LENGTH - 1,
505 .name = logdev_str[0],
506 .flags = IORESOURCE_IO,
510 pdev = platform_device_alloc(DRVNAME, address);
513 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
517 err = platform_device_add_resources(pdev, &res, 1);
519 printk(KERN_ERR DRVNAME ": Device resource addition failed "
521 goto exit_device_put;
524 err = platform_device_add(pdev);
526 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
528 goto exit_device_put;
534 platform_device_put(pdev);
539 static int __init pc87427_find(int sioaddr, unsigned short *address)
544 /* Identify device */
545 val = superio_inb(sioaddr, SIOREG_DEVID);
546 if (val != 0xf2) { /* PC87427 */
551 for (i = 0; i < 2; i++) {
553 /* Select logical device */
554 superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
556 val = superio_inb(sioaddr, SIOREG_ACT);
558 printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
559 "not activated\n", logdev[i]);
563 val = superio_inb(sioaddr, SIOREG_MAP);
565 printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
566 "is memory-mapped, can't use\n", logdev[i]);
570 val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
571 | superio_inb(sioaddr, SIOREG_IOBASE + 1);
573 printk(KERN_INFO DRVNAME ": I/O base address not set "
574 "for logical device 0x%02x\n", logdev[i]);
581 superio_exit(sioaddr);
585 static int __init pc87427_init(void)
588 unsigned short address[2];
590 if (pc87427_find(0x2e, address)
591 && pc87427_find(0x4e, address))
594 /* For now the driver only handles fans so we only care about the
599 err = platform_driver_register(&pc87427_driver);
603 /* Sets global pdev as a side effect */
604 err = pc87427_device_add(address[0]);
611 platform_driver_unregister(&pc87427_driver);
616 static void __exit pc87427_exit(void)
618 platform_device_unregister(pdev);
619 platform_driver_unregister(&pc87427_driver);
622 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
623 MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
624 MODULE_LICENSE("GPL");
626 module_init(pc87427_init);
627 module_exit(pc87427_exit);