2 fscpos.c - Kernel module for hardware monitoring with FSC Poseidon chips
3 Copyright (C) 2004, 2005 Stefan Ott <stefan@desire.ch>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
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 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 fujitsu siemens poseidon chip,
22 module based on the old fscpos module by Hermann Jung <hej@odn.de> and
23 the fscher module by Reinhard Nissl <rnissl@gmx.de>
25 original module based on lm80.c
26 Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
27 and Philip Edelbrock <phil@netroedge.com>
29 Thanks to Jean Delvare for reviewing my code and suggesting a lot of
33 #include <linux/module.h>
34 #include <linux/slab.h>
35 #include <linux/jiffies.h>
36 #include <linux/i2c.h>
37 #include <linux/init.h>
38 #include <linux/hwmon.h>
39 #include <linux/err.h>
40 #include <linux/mutex.h>
41 #include <linux/sysfs.h>
46 static const unsigned short normal_i2c
[] = { 0x73, I2C_CLIENT_END
};
51 I2C_CLIENT_INSMOD_1(fscpos
);
54 * The FSCPOS registers
57 /* chip identification */
58 #define FSCPOS_REG_IDENT_0 0x00
59 #define FSCPOS_REG_IDENT_1 0x01
60 #define FSCPOS_REG_IDENT_2 0x02
61 #define FSCPOS_REG_REVISION 0x03
63 /* global control and status */
64 #define FSCPOS_REG_EVENT_STATE 0x04
65 #define FSCPOS_REG_CONTROL 0x05
68 #define FSCPOS_REG_WDOG_PRESET 0x28
69 #define FSCPOS_REG_WDOG_STATE 0x23
70 #define FSCPOS_REG_WDOG_CONTROL 0x21
73 #define FSCPOS_REG_VOLT_12 0x45
74 #define FSCPOS_REG_VOLT_5 0x42
75 #define FSCPOS_REG_VOLT_BATT 0x48
77 /* fans - the chip does not support minimum speed for fan2 */
78 static u8 FSCPOS_REG_PWM
[] = { 0x55, 0x65 };
79 static u8 FSCPOS_REG_FAN_ACT
[] = { 0x0e, 0x6b, 0xab };
80 static u8 FSCPOS_REG_FAN_STATE
[] = { 0x0d, 0x62, 0xa2 };
81 static u8 FSCPOS_REG_FAN_RIPPLE
[] = { 0x0f, 0x6f, 0xaf };
84 static u8 FSCPOS_REG_TEMP_ACT
[] = { 0x64, 0x32, 0x35 };
85 static u8 FSCPOS_REG_TEMP_STATE
[] = { 0x71, 0x81, 0x91 };
88 * Functions declaration
90 static int fscpos_attach_adapter(struct i2c_adapter
*adapter
);
91 static int fscpos_detect(struct i2c_adapter
*adapter
, int address
, int kind
);
92 static int fscpos_detach_client(struct i2c_client
*client
);
94 static int fscpos_read_value(struct i2c_client
*client
, u8 reg
);
95 static int fscpos_write_value(struct i2c_client
*client
, u8 reg
, u8 value
);
96 static struct fscpos_data
*fscpos_update_device(struct device
*dev
);
97 static void fscpos_init_client(struct i2c_client
*client
);
99 static void reset_fan_alarm(struct i2c_client
*client
, int nr
);
102 * Driver data (common to all clients)
104 static struct i2c_driver fscpos_driver
= {
108 .attach_adapter
= fscpos_attach_adapter
,
109 .detach_client
= fscpos_detach_client
,
113 * Client data (each client gets its own)
116 struct i2c_client client
;
117 struct device
*hwmon_dev
;
118 struct mutex update_lock
;
119 char valid
; /* 0 until following fields are valid */
120 unsigned long last_updated
; /* In jiffies */
122 /* register values */
123 u8 revision
; /* revision of chip */
124 u8 global_event
; /* global event status */
125 u8 global_control
; /* global control register */
126 u8 wdog_control
; /* watchdog control */
127 u8 wdog_state
; /* watchdog status */
128 u8 wdog_preset
; /* watchdog preset */
129 u8 volt
[3]; /* 12, 5, battery current */
130 u8 temp_act
[3]; /* temperature */
131 u8 temp_status
[3]; /* status of sensor */
132 u8 fan_act
[3]; /* fans revolutions per second */
133 u8 fan_status
[3]; /* fan status */
134 u8 pwm
[2]; /* fan min value for rps */
135 u8 fan_ripple
[3]; /* divider for rps */
139 #define TEMP_FROM_REG(val) (((val) - 128) * 1000)
141 static ssize_t
show_temp_input(struct fscpos_data
*data
, char *buf
, int nr
)
143 return sprintf(buf
, "%d\n", TEMP_FROM_REG(data
->temp_act
[nr
- 1]));
146 static ssize_t
show_temp_status(struct fscpos_data
*data
, char *buf
, int nr
)
148 /* bits 2..7 reserved => mask with 0x03 */
149 return sprintf(buf
, "%u\n", data
->temp_status
[nr
- 1] & 0x03);
152 static ssize_t
show_temp_reset(struct fscpos_data
*data
, char *buf
, int nr
)
154 return sprintf(buf
, "1\n");
157 static ssize_t
set_temp_reset(struct i2c_client
*client
, struct fscpos_data
158 *data
, const char *buf
, size_t count
, int nr
, int reg
)
160 unsigned long v
= simple_strtoul(buf
, NULL
, 10);
162 dev_err(&client
->dev
, "temp_reset value %ld not supported. "
163 "Use 1 to reset the alarm!\n", v
);
167 dev_info(&client
->dev
, "You used the temp_reset feature which has not "
168 "been proplerly tested. Please report your "
169 "experience to the module author.\n");
171 /* Supported value: 2 (clears the status) */
172 fscpos_write_value(client
, FSCPOS_REG_TEMP_STATE
[nr
- 1], 2);
177 #define RPM_FROM_REG(val) ((val) * 60)
179 static ssize_t
show_fan_status(struct fscpos_data
*data
, char *buf
, int nr
)
181 /* bits 0..1, 3..7 reserved => mask with 0x04 */
182 return sprintf(buf
, "%u\n", data
->fan_status
[nr
- 1] & 0x04);
185 static ssize_t
show_fan_input(struct fscpos_data
*data
, char *buf
, int nr
)
187 return sprintf(buf
, "%u\n", RPM_FROM_REG(data
->fan_act
[nr
- 1]));
190 static ssize_t
show_fan_ripple(struct fscpos_data
*data
, char *buf
, int nr
)
192 /* bits 2..7 reserved => mask with 0x03 */
193 return sprintf(buf
, "%u\n", data
->fan_ripple
[nr
- 1] & 0x03);
196 static ssize_t
set_fan_ripple(struct i2c_client
*client
, struct fscpos_data
197 *data
, const char *buf
, size_t count
, int nr
, int reg
)
199 /* supported values: 2, 4, 8 */
200 unsigned long v
= simple_strtoul(buf
, NULL
, 10);
203 case 2: v
= 1; break;
204 case 4: v
= 2; break;
205 case 8: v
= 3; break;
207 dev_err(&client
->dev
, "fan_ripple value %ld not supported. "
208 "Must be one of 2, 4 or 8!\n", v
);
212 mutex_lock(&data
->update_lock
);
213 /* bits 2..7 reserved => mask with 0x03 */
214 data
->fan_ripple
[nr
- 1] &= ~0x03;
215 data
->fan_ripple
[nr
- 1] |= v
;
217 fscpos_write_value(client
, reg
, data
->fan_ripple
[nr
- 1]);
218 mutex_unlock(&data
->update_lock
);
222 static ssize_t
show_pwm(struct fscpos_data
*data
, char *buf
, int nr
)
224 return sprintf(buf
, "%u\n", data
->pwm
[nr
- 1]);
227 static ssize_t
set_pwm(struct i2c_client
*client
, struct fscpos_data
*data
,
228 const char *buf
, size_t count
, int nr
, int reg
)
230 unsigned long v
= simple_strtoul(buf
, NULL
, 10);
234 if (v
> 255) v
= 255;
236 mutex_lock(&data
->update_lock
);
237 data
->pwm
[nr
- 1] = v
;
238 fscpos_write_value(client
, reg
, data
->pwm
[nr
- 1]);
239 mutex_unlock(&data
->update_lock
);
243 static void reset_fan_alarm(struct i2c_client
*client
, int nr
)
245 fscpos_write_value(client
, FSCPOS_REG_FAN_STATE
[nr
], 4);
249 #define VOLT_FROM_REG(val, mult) ((val) * (mult) / 255)
251 static ssize_t
show_volt_12(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
253 struct fscpos_data
*data
= fscpos_update_device(dev
);
254 return sprintf(buf
, "%u\n", VOLT_FROM_REG(data
->volt
[0], 14200));
257 static ssize_t
show_volt_5(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
259 struct fscpos_data
*data
= fscpos_update_device(dev
);
260 return sprintf(buf
, "%u\n", VOLT_FROM_REG(data
->volt
[1], 6600));
263 static ssize_t
show_volt_batt(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
265 struct fscpos_data
*data
= fscpos_update_device(dev
);
266 return sprintf(buf
, "%u\n", VOLT_FROM_REG(data
->volt
[2], 3300));
270 static ssize_t
show_wdog_control(struct fscpos_data
*data
, char *buf
)
272 /* bits 0..3 reserved, bit 6 write only => mask with 0xb0 */
273 return sprintf(buf
, "%u\n", data
->wdog_control
& 0xb0);
276 static ssize_t
set_wdog_control(struct i2c_client
*client
, struct fscpos_data
277 *data
, const char *buf
, size_t count
, int reg
)
279 /* bits 0..3 reserved => mask with 0xf0 */
280 unsigned long v
= simple_strtoul(buf
, NULL
, 10) & 0xf0;
282 mutex_lock(&data
->update_lock
);
283 data
->wdog_control
&= ~0xf0;
284 data
->wdog_control
|= v
;
285 fscpos_write_value(client
, reg
, data
->wdog_control
);
286 mutex_unlock(&data
->update_lock
);
290 static ssize_t
show_wdog_state(struct fscpos_data
*data
, char *buf
)
292 /* bits 0, 2..7 reserved => mask with 0x02 */
293 return sprintf(buf
, "%u\n", data
->wdog_state
& 0x02);
296 static ssize_t
set_wdog_state(struct i2c_client
*client
, struct fscpos_data
297 *data
, const char *buf
, size_t count
, int reg
)
299 unsigned long v
= simple_strtoul(buf
, NULL
, 10) & 0x02;
301 /* Valid values: 2 (clear) */
303 dev_err(&client
->dev
, "wdog_state value %ld not supported. "
304 "Must be 2 to clear the state!\n", v
);
308 mutex_lock(&data
->update_lock
);
309 data
->wdog_state
&= ~v
;
310 fscpos_write_value(client
, reg
, v
);
311 mutex_unlock(&data
->update_lock
);
315 static ssize_t
show_wdog_preset(struct fscpos_data
*data
, char *buf
)
317 return sprintf(buf
, "%u\n", data
->wdog_preset
);
320 static ssize_t
set_wdog_preset(struct i2c_client
*client
, struct fscpos_data
321 *data
, const char *buf
, size_t count
, int reg
)
323 unsigned long v
= simple_strtoul(buf
, NULL
, 10) & 0xff;
325 mutex_lock(&data
->update_lock
);
326 data
->wdog_preset
= v
;
327 fscpos_write_value(client
, reg
, data
->wdog_preset
);
328 mutex_unlock(&data
->update_lock
);
333 static ssize_t
show_event(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
335 /* bits 5..7 reserved => mask with 0x1f */
336 struct fscpos_data
*data
= fscpos_update_device(dev
);
337 return sprintf(buf
, "%u\n", data
->global_event
& 0x9b);
343 #define create_getter(kind, sub) \
344 static ssize_t sysfs_show_##kind##sub(struct device *dev, struct device_attribute *attr, char *buf) \
346 struct fscpos_data *data = fscpos_update_device(dev); \
347 return show_##kind##sub(data, buf); \
350 #define create_getter_n(kind, offset, sub) \
351 static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, struct device_attribute *attr, char\
354 struct fscpos_data *data = fscpos_update_device(dev); \
355 return show_##kind##sub(data, buf, offset); \
358 #define create_setter(kind, sub, reg) \
359 static ssize_t sysfs_set_##kind##sub (struct device *dev, struct device_attribute *attr, const char \
360 *buf, size_t count) \
362 struct i2c_client *client = to_i2c_client(dev); \
363 struct fscpos_data *data = i2c_get_clientdata(client); \
364 return set_##kind##sub(client, data, buf, count, reg); \
367 #define create_setter_n(kind, offset, sub, reg) \
368 static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, \
369 const char *buf, size_t count) \
371 struct i2c_client *client = to_i2c_client(dev); \
372 struct fscpos_data *data = i2c_get_clientdata(client); \
373 return set_##kind##sub(client, data, buf, count, offset, reg);\
376 #define create_sysfs_device_ro(kind, sub, offset) \
377 static DEVICE_ATTR(kind##offset##sub, S_IRUGO, \
378 sysfs_show_##kind##offset##sub, NULL);
380 #define create_sysfs_device_rw(kind, sub, offset) \
381 static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, \
382 sysfs_show_##kind##offset##sub, sysfs_set_##kind##offset##sub);
384 #define sysfs_ro_n(kind, sub, offset) \
385 create_getter_n(kind, offset, sub); \
386 create_sysfs_device_ro(kind, sub, offset);
388 #define sysfs_rw_n(kind, sub, offset, reg) \
389 create_getter_n(kind, offset, sub); \
390 create_setter_n(kind, offset, sub, reg); \
391 create_sysfs_device_rw(kind, sub, offset);
393 #define sysfs_rw(kind, sub, reg) \
394 create_getter(kind, sub); \
395 create_setter(kind, sub, reg); \
396 create_sysfs_device_rw(kind, sub,);
398 #define sysfs_fan_with_min(offset, reg_status, reg_ripple, reg_min) \
399 sysfs_fan(offset, reg_status, reg_ripple); \
400 sysfs_rw_n(pwm,, offset, reg_min);
402 #define sysfs_fan(offset, reg_status, reg_ripple) \
403 sysfs_ro_n(fan, _input, offset); \
404 sysfs_ro_n(fan, _status, offset); \
405 sysfs_rw_n(fan, _ripple, offset, reg_ripple);
407 #define sysfs_temp(offset, reg_status) \
408 sysfs_ro_n(temp, _input, offset); \
409 sysfs_ro_n(temp, _status, offset); \
410 sysfs_rw_n(temp, _reset, offset, reg_status);
412 #define sysfs_watchdog(reg_wdog_preset, reg_wdog_state, reg_wdog_control) \
413 sysfs_rw(wdog, _control, reg_wdog_control); \
414 sysfs_rw(wdog, _preset, reg_wdog_preset); \
415 sysfs_rw(wdog, _state, reg_wdog_state);
417 sysfs_fan_with_min(1, FSCPOS_REG_FAN_STATE
[0], FSCPOS_REG_FAN_RIPPLE
[0],
419 sysfs_fan_with_min(2, FSCPOS_REG_FAN_STATE
[1], FSCPOS_REG_FAN_RIPPLE
[1],
421 sysfs_fan(3, FSCPOS_REG_FAN_STATE
[2], FSCPOS_REG_FAN_RIPPLE
[2]);
423 sysfs_temp(1, FSCPOS_REG_TEMP_STATE
[0]);
424 sysfs_temp(2, FSCPOS_REG_TEMP_STATE
[1]);
425 sysfs_temp(3, FSCPOS_REG_TEMP_STATE
[2]);
427 sysfs_watchdog(FSCPOS_REG_WDOG_PRESET
, FSCPOS_REG_WDOG_STATE
,
428 FSCPOS_REG_WDOG_CONTROL
);
430 static DEVICE_ATTR(event
, S_IRUGO
, show_event
, NULL
);
431 static DEVICE_ATTR(in0_input
, S_IRUGO
, show_volt_12
, NULL
);
432 static DEVICE_ATTR(in1_input
, S_IRUGO
, show_volt_5
, NULL
);
433 static DEVICE_ATTR(in2_input
, S_IRUGO
, show_volt_batt
, NULL
);
435 static struct attribute
*fscpos_attributes
[] = {
436 &dev_attr_event
.attr
,
437 &dev_attr_in0_input
.attr
,
438 &dev_attr_in1_input
.attr
,
439 &dev_attr_in2_input
.attr
,
441 &dev_attr_wdog_control
.attr
,
442 &dev_attr_wdog_preset
.attr
,
443 &dev_attr_wdog_state
.attr
,
445 &dev_attr_temp1_input
.attr
,
446 &dev_attr_temp1_status
.attr
,
447 &dev_attr_temp1_reset
.attr
,
448 &dev_attr_temp2_input
.attr
,
449 &dev_attr_temp2_status
.attr
,
450 &dev_attr_temp2_reset
.attr
,
451 &dev_attr_temp3_input
.attr
,
452 &dev_attr_temp3_status
.attr
,
453 &dev_attr_temp3_reset
.attr
,
455 &dev_attr_fan1_input
.attr
,
456 &dev_attr_fan1_status
.attr
,
457 &dev_attr_fan1_ripple
.attr
,
459 &dev_attr_fan2_input
.attr
,
460 &dev_attr_fan2_status
.attr
,
461 &dev_attr_fan2_ripple
.attr
,
463 &dev_attr_fan3_input
.attr
,
464 &dev_attr_fan3_status
.attr
,
465 &dev_attr_fan3_ripple
.attr
,
469 static const struct attribute_group fscpos_group
= {
470 .attrs
= fscpos_attributes
,
473 static int fscpos_attach_adapter(struct i2c_adapter
*adapter
)
475 if (!(adapter
->class & I2C_CLASS_HWMON
))
477 return i2c_probe(adapter
, &addr_data
, fscpos_detect
);
480 static int fscpos_detect(struct i2c_adapter
*adapter
, int address
, int kind
)
482 struct i2c_client
*new_client
;
483 struct fscpos_data
*data
;
486 if (!i2c_check_functionality(adapter
, I2C_FUNC_SMBUS_BYTE_DATA
))
490 * OK. For now, we presume we have a valid client. We now create the
491 * client structure, even though we cannot fill it completely yet.
492 * But it allows us to access fscpos_{read,write}_value.
495 if (!(data
= kzalloc(sizeof(struct fscpos_data
), GFP_KERNEL
))) {
500 new_client
= &data
->client
;
501 i2c_set_clientdata(new_client
, data
);
502 new_client
->addr
= address
;
503 new_client
->adapter
= adapter
;
504 new_client
->driver
= &fscpos_driver
;
505 new_client
->flags
= 0;
507 /* Do the remaining detection unless force or force_fscpos parameter */
509 if ((fscpos_read_value(new_client
, FSCPOS_REG_IDENT_0
)
511 || (fscpos_read_value(new_client
, FSCPOS_REG_IDENT_1
)
513 || (fscpos_read_value(new_client
, FSCPOS_REG_IDENT_2
)
516 dev_dbg(&new_client
->dev
, "fscpos detection failed\n");
521 /* Fill in the remaining client fields and put it in the global list */
522 strlcpy(new_client
->name
, "fscpos", I2C_NAME_SIZE
);
525 mutex_init(&data
->update_lock
);
527 /* Tell the I2C layer a new client has arrived */
528 if ((err
= i2c_attach_client(new_client
)))
531 /* Inizialize the fscpos chip */
532 fscpos_init_client(new_client
);
534 /* Announce that the chip was found */
535 dev_info(&new_client
->dev
, "Found fscpos chip, rev %u\n", data
->revision
);
537 /* Register sysfs hooks */
538 if ((err
= sysfs_create_group(&new_client
->dev
.kobj
, &fscpos_group
)))
541 data
->hwmon_dev
= hwmon_device_register(&new_client
->dev
);
542 if (IS_ERR(data
->hwmon_dev
)) {
543 err
= PTR_ERR(data
->hwmon_dev
);
544 goto exit_remove_files
;
550 sysfs_remove_group(&new_client
->dev
.kobj
, &fscpos_group
);
552 i2c_detach_client(new_client
);
559 static int fscpos_detach_client(struct i2c_client
*client
)
561 struct fscpos_data
*data
= i2c_get_clientdata(client
);
564 hwmon_device_unregister(data
->hwmon_dev
);
565 sysfs_remove_group(&client
->dev
.kobj
, &fscpos_group
);
567 if ((err
= i2c_detach_client(client
)))
573 static int fscpos_read_value(struct i2c_client
*client
, u8 reg
)
575 dev_dbg(&client
->dev
, "Read reg 0x%02x\n", reg
);
576 return i2c_smbus_read_byte_data(client
, reg
);
579 static int fscpos_write_value(struct i2c_client
*client
, u8 reg
, u8 value
)
581 dev_dbg(&client
->dev
, "Write reg 0x%02x, val 0x%02x\n", reg
, value
);
582 return i2c_smbus_write_byte_data(client
, reg
, value
);
585 /* Called when we have found a new FSCPOS chip */
586 static void fscpos_init_client(struct i2c_client
*client
)
588 struct fscpos_data
*data
= i2c_get_clientdata(client
);
590 /* read revision from chip */
591 data
->revision
= fscpos_read_value(client
, FSCPOS_REG_REVISION
);
594 static struct fscpos_data
*fscpos_update_device(struct device
*dev
)
596 struct i2c_client
*client
= to_i2c_client(dev
);
597 struct fscpos_data
*data
= i2c_get_clientdata(client
);
599 mutex_lock(&data
->update_lock
);
601 if (time_after(jiffies
, data
->last_updated
+ 2 * HZ
) || !data
->valid
) {
604 dev_dbg(&client
->dev
, "Starting fscpos update\n");
606 for (i
= 0; i
< 3; i
++) {
607 data
->temp_act
[i
] = fscpos_read_value(client
,
608 FSCPOS_REG_TEMP_ACT
[i
]);
609 data
->temp_status
[i
] = fscpos_read_value(client
,
610 FSCPOS_REG_TEMP_STATE
[i
]);
611 data
->fan_act
[i
] = fscpos_read_value(client
,
612 FSCPOS_REG_FAN_ACT
[i
]);
613 data
->fan_status
[i
] = fscpos_read_value(client
,
614 FSCPOS_REG_FAN_STATE
[i
]);
615 data
->fan_ripple
[i
] = fscpos_read_value(client
,
616 FSCPOS_REG_FAN_RIPPLE
[i
]);
618 /* fan2_min is not supported by the chip */
619 data
->pwm
[i
] = fscpos_read_value(client
,
622 /* reset fan status if speed is back to > 0 */
623 if (data
->fan_status
[i
] != 0 && data
->fan_act
[i
] > 0) {
624 reset_fan_alarm(client
, i
);
628 data
->volt
[0] = fscpos_read_value(client
, FSCPOS_REG_VOLT_12
);
629 data
->volt
[1] = fscpos_read_value(client
, FSCPOS_REG_VOLT_5
);
630 data
->volt
[2] = fscpos_read_value(client
, FSCPOS_REG_VOLT_BATT
);
632 data
->wdog_preset
= fscpos_read_value(client
,
633 FSCPOS_REG_WDOG_PRESET
);
634 data
->wdog_state
= fscpos_read_value(client
,
635 FSCPOS_REG_WDOG_STATE
);
636 data
->wdog_control
= fscpos_read_value(client
,
637 FSCPOS_REG_WDOG_CONTROL
);
639 data
->global_event
= fscpos_read_value(client
,
640 FSCPOS_REG_EVENT_STATE
);
642 data
->last_updated
= jiffies
;
645 mutex_unlock(&data
->update_lock
);
649 static int __init
sm_fscpos_init(void)
651 return i2c_add_driver(&fscpos_driver
);
654 static void __exit
sm_fscpos_exit(void)
656 i2c_del_driver(&fscpos_driver
);
659 MODULE_AUTHOR("Stefan Ott <stefan@desire.ch> based on work from Hermann Jung "
660 "<hej@odn.de>, Frodo Looijaard <frodol@dds.nl>"
661 " and Philip Edelbrock <phil@netroedge.com>");
662 MODULE_DESCRIPTION("fujitsu siemens poseidon chip driver");
663 MODULE_LICENSE("GPL");
665 module_init(sm_fscpos_init
);
666 module_exit(sm_fscpos_exit
);