1/*
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>
5 *
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.
9 *
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.
14 *
15 *  Supports the following chips:
16 *
17 *  Chip        #vin    #fan    #pwm    #temp   devid
18 *  PC87427     -       8       -       -       0xF2
19 *
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.
22 */
23
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>
34#include <linux/ioport.h>
35#include <asm/io.h>
36
37static struct platform_device *pdev;
38
39#define DRVNAME "pc87427"
40
41/* The lock mutex protects both the I/O accesses (needed because the
42   device is using banked registers) and the register cache (needed to keep
43   the data in the registers and the cache in sync at any time). */
44struct pc87427_data {
45	struct class_device *class_dev;
46	struct mutex lock;
47	int address[2];
48	const char *name;
49
50	unsigned long last_updated;	/* in jiffies */
51	u8 fan_enabled;			/* bit vector */
52	u16 fan[8];			/* register values */
53	u16 fan_min[8];			/* register values */
54	u8 fan_status[8];		/* register values */
55};
56
57/*
58 * Super-I/O registers and operations
59 */
60
61#define SIOREG_LDSEL	0x07	/* Logical device select */
62#define SIOREG_DEVID	0x20	/* Device ID */
63#define SIOREG_ACT	0x30	/* Device activation */
64#define SIOREG_MAP	0x50	/* I/O or memory mapping */
65#define SIOREG_IOBASE	0x60	/* I/O base address */
66
67static const u8 logdev[2] = { 0x09, 0x14 };
68static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" };
69#define LD_FAN		0
70#define LD_IN		1
71#define LD_TEMP		1
72
73static inline void superio_outb(int sioaddr, int reg, int val)
74{
75	outb(reg, sioaddr);
76	outb(val, sioaddr + 1);
77}
78
79static inline int superio_inb(int sioaddr, int reg)
80{
81	outb(reg, sioaddr);
82	return inb(sioaddr + 1);
83}
84
85static inline void superio_exit(int sioaddr)
86{
87	outb(0x02, sioaddr);
88	outb(0x02, sioaddr + 1);
89}
90
91/*
92 * Logical devices
93 */
94
95#define REGION_LENGTH		32
96#define PC87427_REG_BANK	0x0f
97#define BANK_FM(nr)		(nr)
98#define BANK_FT(nr)		(0x08 + (nr))
99#define BANK_FC(nr)		(0x10 + (nr) * 2)
100
101/*
102 * I/O access functions
103 */
104
105/* ldi is the logical device index */
106static inline int pc87427_read8(struct pc87427_data *data, u8 ldi, u8 reg)
107{
108	return inb(data->address[ldi] + reg);
109}
110
111/* Must be called with data->lock held, except during init */
112static inline int pc87427_read8_bank(struct pc87427_data *data, u8 ldi,
113				     u8 bank, u8 reg)
114{
115	outb(bank, data->address[ldi] + PC87427_REG_BANK);
116	return inb(data->address[ldi] + reg);
117}
118
119/* Must be called with data->lock held, except during init */
120static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
121				       u8 bank, u8 reg, u8 value)
122{
123	outb(bank, data->address[ldi] + PC87427_REG_BANK);
124	outb(value, data->address[ldi] + reg);
125}
126
127/*
128 * Fan registers and conversions
129 */
130
131/* fan data registers are 16-bit wide */
132#define PC87427_REG_FAN			0x12
133#define PC87427_REG_FAN_MIN		0x14
134#define PC87427_REG_FAN_STATUS		0x10
135
136#define FAN_STATUS_STALL		(1 << 3)
137#define FAN_STATUS_LOSPD		(1 << 1)
138#define FAN_STATUS_MONEN		(1 << 0)
139
140/* Dedicated function to read all registers related to a given fan input.
141   This saves us quite a few locks and bank selections.
142   Must be called with data->lock held.
143   nr is from 0 to 7 */
144static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
145{
146	int iobase = data->address[LD_FAN];
147
148	outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
149	data->fan[nr] = inw(iobase + PC87427_REG_FAN);
150	data->fan_min[nr] = inw(iobase + PC87427_REG_FAN_MIN);
151	data->fan_status[nr] = inb(iobase + PC87427_REG_FAN_STATUS);
152	/* Clear fan alarm bits */
153	outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS);
154}
155
156/* The 2 LSB of fan speed registers are used for something different.
157   The actual 2 LSB of the measurements are not available. */
158static inline unsigned long fan_from_reg(u16 reg)
159{
160	reg &= 0xfffc;
161	if (reg == 0x0000 || reg == 0xfffc)
162		return 0;
163	return 5400000UL / reg;
164}
165
166/* The 2 LSB of the fan speed limit registers are not significant. */
167static inline u16 fan_to_reg(unsigned long val)
168{
169	if (val < 83UL)
170		return 0xffff;
171	if (val >= 1350000UL)
172		return 0x0004;
173	return ((1350000UL + val / 2) / val) << 2;
174}
175
176/*
177 * Data interface
178 */
179
180static struct pc87427_data *pc87427_update_device(struct device *dev)
181{
182	struct pc87427_data *data = dev_get_drvdata(dev);
183	int i;
184
185	mutex_lock(&data->lock);
186	if (!time_after(jiffies, data->last_updated + HZ)
187	 && data->last_updated)
188		goto done;
189
190	/* Fans */
191	for (i = 0; i < 8; i++) {
192		if (!(data->fan_enabled & (1 << i)))
193			continue;
194		pc87427_readall_fan(data, i);
195	}
196	data->last_updated = jiffies;
197
198done:
199	mutex_unlock(&data->lock);
200	return data;
201}
202
203static ssize_t show_fan_input(struct device *dev, struct device_attribute
204			      *devattr, char *buf)
205{
206	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
207	struct pc87427_data *data = pc87427_update_device(dev);
208	int nr = attr->index;
209
210	return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
211}
212
213static ssize_t show_fan_min(struct device *dev, struct device_attribute
214			    *devattr, char *buf)
215{
216	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
217	struct pc87427_data *data = pc87427_update_device(dev);
218	int nr = attr->index;
219
220	return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
221}
222
223static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
224			      *devattr, char *buf)
225{
226	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
227	struct pc87427_data *data = pc87427_update_device(dev);
228	int nr = attr->index;
229
230	return sprintf(buf, "%d\n", !!(data->fan_status[nr]
231				       & FAN_STATUS_LOSPD));
232}
233
234static ssize_t show_fan_fault(struct device *dev, struct device_attribute
235			      *devattr, char *buf)
236{
237	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
238	struct pc87427_data *data = pc87427_update_device(dev);
239	int nr = attr->index;
240
241	return sprintf(buf, "%d\n", !!(data->fan_status[nr]
242				       & FAN_STATUS_STALL));
243}
244
245static ssize_t set_fan_min(struct device *dev, struct device_attribute
246			   *devattr, const char *buf, size_t count)
247{
248	struct pc87427_data *data = dev_get_drvdata(dev);
249	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
250	int nr = attr->index;
251	unsigned long val = simple_strtoul(buf, NULL, 10);
252	int iobase = data->address[LD_FAN];
253
254	mutex_lock(&data->lock);
255	outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
256	/* The low speed limit registers are read-only while monitoring
257	   is enabled, so we have to disable monitoring, then change the
258	   limit, and finally enable monitoring again. */
259	outb(0, iobase + PC87427_REG_FAN_STATUS);
260	data->fan_min[nr] = fan_to_reg(val);
261	outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
262	outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS);
263	mutex_unlock(&data->lock);
264
265	return count;
266}
267
268static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
269static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
270static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
271static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
272static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
273static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
274static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
275static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
276
277static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
278			  show_fan_min, set_fan_min, 0);
279static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
280			  show_fan_min, set_fan_min, 1);
281static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
282			  show_fan_min, set_fan_min, 2);
283static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
284			  show_fan_min, set_fan_min, 3);
285static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
286			  show_fan_min, set_fan_min, 4);
287static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
288			  show_fan_min, set_fan_min, 5);
289static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
290			  show_fan_min, set_fan_min, 6);
291static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
292			  show_fan_min, set_fan_min, 7);
293
294static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
295static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
296static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
297static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
298static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
299static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
300static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
301static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
302
303static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
304static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
305static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
306static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
307static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
308static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
309static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
310static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
311
312static struct attribute *pc87427_attributes_fan[8][5] = {
313	{
314		&sensor_dev_attr_fan1_input.dev_attr.attr,
315		&sensor_dev_attr_fan1_min.dev_attr.attr,
316		&sensor_dev_attr_fan1_alarm.dev_attr.attr,
317		&sensor_dev_attr_fan1_fault.dev_attr.attr,
318		NULL
319	}, {
320		&sensor_dev_attr_fan2_input.dev_attr.attr,
321		&sensor_dev_attr_fan2_min.dev_attr.attr,
322		&sensor_dev_attr_fan2_alarm.dev_attr.attr,
323		&sensor_dev_attr_fan2_fault.dev_attr.attr,
324		NULL
325	}, {
326		&sensor_dev_attr_fan3_input.dev_attr.attr,
327		&sensor_dev_attr_fan3_min.dev_attr.attr,
328		&sensor_dev_attr_fan3_alarm.dev_attr.attr,
329		&sensor_dev_attr_fan3_fault.dev_attr.attr,
330		NULL
331	}, {
332		&sensor_dev_attr_fan4_input.dev_attr.attr,
333		&sensor_dev_attr_fan4_min.dev_attr.attr,
334		&sensor_dev_attr_fan4_alarm.dev_attr.attr,
335		&sensor_dev_attr_fan4_fault.dev_attr.attr,
336		NULL
337	}, {
338		&sensor_dev_attr_fan5_input.dev_attr.attr,
339		&sensor_dev_attr_fan5_min.dev_attr.attr,
340		&sensor_dev_attr_fan5_alarm.dev_attr.attr,
341		&sensor_dev_attr_fan5_fault.dev_attr.attr,
342		NULL
343	}, {
344		&sensor_dev_attr_fan6_input.dev_attr.attr,
345		&sensor_dev_attr_fan6_min.dev_attr.attr,
346		&sensor_dev_attr_fan6_alarm.dev_attr.attr,
347		&sensor_dev_attr_fan6_fault.dev_attr.attr,
348		NULL
349	}, {
350		&sensor_dev_attr_fan7_input.dev_attr.attr,
351		&sensor_dev_attr_fan7_min.dev_attr.attr,
352		&sensor_dev_attr_fan7_alarm.dev_attr.attr,
353		&sensor_dev_attr_fan7_fault.dev_attr.attr,
354		NULL
355	}, {
356		&sensor_dev_attr_fan8_input.dev_attr.attr,
357		&sensor_dev_attr_fan8_min.dev_attr.attr,
358		&sensor_dev_attr_fan8_alarm.dev_attr.attr,
359		&sensor_dev_attr_fan8_fault.dev_attr.attr,
360		NULL
361	}
362};
363
364static const struct attribute_group pc87427_group_fan[8] = {
365	{ .attrs = pc87427_attributes_fan[0] },
366	{ .attrs = pc87427_attributes_fan[1] },
367	{ .attrs = pc87427_attributes_fan[2] },
368	{ .attrs = pc87427_attributes_fan[3] },
369	{ .attrs = pc87427_attributes_fan[4] },
370	{ .attrs = pc87427_attributes_fan[5] },
371	{ .attrs = pc87427_attributes_fan[6] },
372	{ .attrs = pc87427_attributes_fan[7] },
373};
374
375static ssize_t show_name(struct device *dev, struct device_attribute
376			 *devattr, char *buf)
377{
378	struct pc87427_data *data = dev_get_drvdata(dev);
379
380	return sprintf(buf, "%s\n", data->name);
381}
382static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
383
384
385/*
386 * Device detection, attach and detach
387 */
388
389static void __devinit pc87427_init_device(struct device *dev)
390{
391	struct pc87427_data *data = dev_get_drvdata(dev);
392	int i;
393	u8 reg;
394
395	/* The FMC module should be ready */
396	reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
397	if (!(reg & 0x80))
398		dev_warn(dev, "FMC module not ready!\n");
399
400	/* Check which fans are enabled */
401	for (i = 0; i < 8; i++) {
402		reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
403					 PC87427_REG_FAN_STATUS);
404		if (reg & FAN_STATUS_MONEN)
405			data->fan_enabled |= (1 << i);
406	}
407
408	if (!data->fan_enabled) {
409		dev_dbg(dev, "Enabling all fan inputs\n");
410		for (i = 0; i < 8; i++)
411			pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
412					    PC87427_REG_FAN_STATUS,
413					    FAN_STATUS_MONEN);
414		data->fan_enabled = 0xff;
415	}
416}
417
418static int __devinit pc87427_probe(struct platform_device *pdev)
419{
420	struct pc87427_data *data;
421	struct resource *res;
422	int i, err;
423
424	if (!(data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL))) {
425		err = -ENOMEM;
426		printk(KERN_ERR DRVNAME ": Out of memory\n");
427		goto exit;
428	}
429
430	/* This will need to be revisited when we add support for
431	   temperature and voltage monitoring. */
432	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
433	if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) {
434		err = -EBUSY;
435		dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
436			(unsigned long)res->start, (unsigned long)res->end);
437		goto exit_kfree;
438	}
439	data->address[0] = res->start;
440
441	mutex_init(&data->lock);
442	data->name = "pc87427";
443	platform_set_drvdata(pdev, data);
444	pc87427_init_device(&pdev->dev);
445
446	/* Register sysfs hooks */
447	if ((err = device_create_file(&pdev->dev, &dev_attr_name)))
448		goto exit_release_region;
449	for (i = 0; i < 8; i++) {
450		if (!(data->fan_enabled & (1 << i)))
451			continue;
452		if ((err = sysfs_create_group(&pdev->dev.kobj,
453					      &pc87427_group_fan[i])))
454			goto exit_remove_files;
455	}
456
457	data->class_dev = hwmon_device_register(&pdev->dev);
458	if (IS_ERR(data->class_dev)) {
459		err = PTR_ERR(data->class_dev);
460		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
461		goto exit_remove_files;
462	}
463
464	return 0;
465
466exit_remove_files:
467	for (i = 0; i < 8; i++) {
468		if (!(data->fan_enabled & (1 << i)))
469			continue;
470		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
471	}
472exit_release_region:
473	release_region(res->start, res->end - res->start + 1);
474exit_kfree:
475	platform_set_drvdata(pdev, NULL);
476	kfree(data);
477exit:
478	return err;
479}
480
481static int __devexit pc87427_remove(struct platform_device *pdev)
482{
483	struct pc87427_data *data = platform_get_drvdata(pdev);
484	struct resource *res;
485	int i;
486
487	platform_set_drvdata(pdev, NULL);
488	hwmon_device_unregister(data->class_dev);
489	device_remove_file(&pdev->dev, &dev_attr_name);
490	for (i = 0; i < 8; i++) {
491		if (!(data->fan_enabled & (1 << i)))
492			continue;
493		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
494	}
495	kfree(data);
496
497	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
498	release_region(res->start, res->end - res->start + 1);
499
500	return 0;
501}
502
503
504static struct platform_driver pc87427_driver = {
505	.driver = {
506		.owner	= THIS_MODULE,
507		.name	= DRVNAME,
508	},
509	.probe		= pc87427_probe,
510	.remove		= __devexit_p(pc87427_remove),
511};
512
513static int __init pc87427_device_add(unsigned short address)
514{
515	struct resource res = {
516		.start	= address,
517		.end	= address + REGION_LENGTH - 1,
518		.name	= logdev_str[0],
519		.flags	= IORESOURCE_IO,
520	};
521	int err;
522
523	pdev = platform_device_alloc(DRVNAME, address);
524	if (!pdev) {
525		err = -ENOMEM;
526		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
527		goto exit;
528	}
529
530	err = platform_device_add_resources(pdev, &res, 1);
531	if (err) {
532		printk(KERN_ERR DRVNAME ": Device resource addition failed "
533		       "(%d)\n", err);
534		goto exit_device_put;
535	}
536
537	err = platform_device_add(pdev);
538	if (err) {
539		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
540		       err);
541		goto exit_device_put;
542	}
543
544	return 0;
545
546exit_device_put:
547	platform_device_put(pdev);
548exit:
549	return err;
550}
551
552static int __init pc87427_find(int sioaddr, unsigned short *address)
553{
554	u16 val;
555	int i, err = 0;
556
557	/* Identify device */
558	val = superio_inb(sioaddr, SIOREG_DEVID);
559	if (val != 0xf2) {	/* PC87427 */
560		err = -ENODEV;
561		goto exit;
562	}
563
564	for (i = 0; i < 2; i++) {
565		address[i] = 0;
566		/* Select logical device */
567		superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
568
569		val = superio_inb(sioaddr, SIOREG_ACT);
570		if (!(val & 0x01)) {
571			printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
572			       "not activated\n", logdev[i]);
573			continue;
574		}
575
576		val = superio_inb(sioaddr, SIOREG_MAP);
577		if (val & 0x01) {
578			printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
579			       "is memory-mapped, can't use\n", logdev[i]);
580			continue;
581		}
582
583		val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
584		    | superio_inb(sioaddr, SIOREG_IOBASE + 1);
585		if (!val) {
586			printk(KERN_INFO DRVNAME ": I/O base address not set "
587			       "for logical device 0x%02x\n", logdev[i]);
588			continue;
589		}
590		address[i] = val;
591	}
592
593exit:
594	superio_exit(sioaddr);
595	return err;
596}
597
598static int __init pc87427_init(void)
599{
600	int err;
601	unsigned short address[2];
602
603	if (pc87427_find(0x2e, address)
604	 && pc87427_find(0x4e, address))
605		return -ENODEV;
606
607	/* For now the driver only handles fans so we only care about the
608	   first address. */
609	if (!address[0])
610		return -ENODEV;
611
612	err = platform_driver_register(&pc87427_driver);
613	if (err)
614		goto exit;
615
616	/* Sets global pdev as a side effect */
617	err = pc87427_device_add(address[0]);
618	if (err)
619		goto exit_driver;
620
621	return 0;
622
623exit_driver:
624	platform_driver_unregister(&pc87427_driver);
625exit:
626	return err;
627}
628
629static void __exit pc87427_exit(void)
630{
631	platform_device_unregister(pdev);
632	platform_driver_unregister(&pc87427_driver);
633}
634
635MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
636MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
637MODULE_LICENSE("GPL");
638
639module_init(pc87427_init);
640module_exit(pc87427_exit);
641