Linux-2.6.12-rc2
[linux-2.6/kvm.git] / drivers / i2c / chips / fscpos.c
blob2cac79145c7596b12827b02bdfb8cfb7430ed2e8
1 /*
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
30 improvements.
33 #include <linux/module.h>
34 #include <linux/slab.h>
35 #include <linux/i2c.h>
36 #include <linux/i2c-sensor.h>
37 #include <linux/init.h>
40 * Addresses to scan
42 static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
43 static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
46 * Insmod parameters
48 SENSORS_INSMOD_1(fscpos);
51 * The FSCPOS registers
54 /* chip identification */
55 #define FSCPOS_REG_IDENT_0 0x00
56 #define FSCPOS_REG_IDENT_1 0x01
57 #define FSCPOS_REG_IDENT_2 0x02
58 #define FSCPOS_REG_REVISION 0x03
60 /* global control and status */
61 #define FSCPOS_REG_EVENT_STATE 0x04
62 #define FSCPOS_REG_CONTROL 0x05
64 /* watchdog */
65 #define FSCPOS_REG_WDOG_PRESET 0x28
66 #define FSCPOS_REG_WDOG_STATE 0x23
67 #define FSCPOS_REG_WDOG_CONTROL 0x21
69 /* voltages */
70 #define FSCPOS_REG_VOLT_12 0x45
71 #define FSCPOS_REG_VOLT_5 0x42
72 #define FSCPOS_REG_VOLT_BATT 0x48
74 /* fans - the chip does not support minimum speed for fan2 */
75 static u8 FSCPOS_REG_PWM[] = { 0x55, 0x65 };
76 static u8 FSCPOS_REG_FAN_ACT[] = { 0x0e, 0x6b, 0xab };
77 static u8 FSCPOS_REG_FAN_STATE[] = { 0x0d, 0x62, 0xa2 };
78 static u8 FSCPOS_REG_FAN_RIPPLE[] = { 0x0f, 0x6f, 0xaf };
80 /* temperatures */
81 static u8 FSCPOS_REG_TEMP_ACT[] = { 0x64, 0x32, 0x35 };
82 static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 };
85 * Functions declaration
87 static int fscpos_attach_adapter(struct i2c_adapter *adapter);
88 static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind);
89 static int fscpos_detach_client(struct i2c_client *client);
91 static int fscpos_read_value(struct i2c_client *client, u8 register);
92 static int fscpos_write_value(struct i2c_client *client, u8 register, u8 value);
93 static struct fscpos_data *fscpos_update_device(struct device *dev);
94 static void fscpos_init_client(struct i2c_client *client);
96 static void reset_fan_alarm(struct i2c_client *client, int nr);
99 * Driver data (common to all clients)
101 static struct i2c_driver fscpos_driver = {
102 .owner = THIS_MODULE,
103 .name = "fscpos",
104 .id = I2C_DRIVERID_FSCPOS,
105 .flags = I2C_DF_NOTIFY,
106 .attach_adapter = fscpos_attach_adapter,
107 .detach_client = fscpos_detach_client,
111 * Client data (each client gets its own)
113 struct fscpos_data {
114 struct i2c_client client;
115 struct semaphore update_lock;
116 char valid; /* 0 until following fields are valid */
117 unsigned long last_updated; /* In jiffies */
119 /* register values */
120 u8 revision; /* revision of chip */
121 u8 global_event; /* global event status */
122 u8 global_control; /* global control register */
123 u8 wdog_control; /* watchdog control */
124 u8 wdog_state; /* watchdog status */
125 u8 wdog_preset; /* watchdog preset */
126 u8 volt[3]; /* 12, 5, battery current */
127 u8 temp_act[3]; /* temperature */
128 u8 temp_status[3]; /* status of sensor */
129 u8 fan_act[3]; /* fans revolutions per second */
130 u8 fan_status[3]; /* fan status */
131 u8 pwm[2]; /* fan min value for rps */
132 u8 fan_ripple[3]; /* divider for rps */
135 /* Temperature */
136 #define TEMP_FROM_REG(val) (((val) - 128) * 1000)
138 static ssize_t show_temp_input(struct fscpos_data *data, char *buf, int nr)
140 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[nr - 1]));
143 static ssize_t show_temp_status(struct fscpos_data *data, char *buf, int nr)
145 /* bits 2..7 reserved => mask with 0x03 */
146 return sprintf(buf, "%u\n", data->temp_status[nr - 1] & 0x03);
149 static ssize_t show_temp_reset(struct fscpos_data *data, char *buf, int nr)
151 return sprintf(buf, "1\n");
154 static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data
155 *data, const char *buf, size_t count, int nr, int reg)
157 unsigned long v = simple_strtoul(buf, NULL, 10);
158 if (v != 1) {
159 dev_err(&client->dev, "temp_reset value %ld not supported. "
160 "Use 1 to reset the alarm!\n", v);
161 return -EINVAL;
164 dev_info(&client->dev, "You used the temp_reset feature which has not "
165 "been proplerly tested. Please report your "
166 "experience to the module author.\n");
168 /* Supported value: 2 (clears the status) */
169 fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr], 2);
170 return count;
173 /* Fans */
174 #define RPM_FROM_REG(val) ((val) * 60)
176 static ssize_t show_fan_status(struct fscpos_data *data, char *buf, int nr)
178 /* bits 0..1, 3..7 reserved => mask with 0x04 */
179 return sprintf(buf, "%u\n", data->fan_status[nr - 1] & 0x04);
182 static ssize_t show_fan_input(struct fscpos_data *data, char *buf, int nr)
184 return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[nr - 1]));
187 static ssize_t show_fan_ripple(struct fscpos_data *data, char *buf, int nr)
189 /* bits 2..7 reserved => mask with 0x03 */
190 return sprintf(buf, "%u\n", data->fan_ripple[nr - 1] & 0x03);
193 static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data
194 *data, const char *buf, size_t count, int nr, int reg)
196 /* supported values: 2, 4, 8 */
197 unsigned long v = simple_strtoul(buf, NULL, 10);
199 switch (v) {
200 case 2: v = 1; break;
201 case 4: v = 2; break;
202 case 8: v = 3; break;
203 default:
204 dev_err(&client->dev, "fan_ripple value %ld not supported. "
205 "Must be one of 2, 4 or 8!\n", v);
206 return -EINVAL;
209 down(&data->update_lock);
210 /* bits 2..7 reserved => mask with 0x03 */
211 data->fan_ripple[nr - 1] &= ~0x03;
212 data->fan_ripple[nr - 1] |= v;
214 fscpos_write_value(client, reg, data->fan_ripple[nr - 1]);
215 up(&data->update_lock);
216 return count;
219 static ssize_t show_pwm(struct fscpos_data *data, char *buf, int nr)
221 return sprintf(buf, "%u\n", data->pwm[nr - 1]);
224 static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data,
225 const char *buf, size_t count, int nr, int reg)
227 unsigned long v = simple_strtoul(buf, NULL, 10);
229 /* Range: 0..255 */
230 if (v < 0) v = 0;
231 if (v > 255) v = 255;
233 down(&data->update_lock);
234 data->pwm[nr - 1] = v;
235 fscpos_write_value(client, reg, data->pwm[nr - 1]);
236 up(&data->update_lock);
237 return count;
240 static void reset_fan_alarm(struct i2c_client *client, int nr)
242 fscpos_write_value(client, FSCPOS_REG_FAN_STATE[nr], 4);
245 /* Volts */
246 #define VOLT_FROM_REG(val, mult) ((val) * (mult) / 255)
248 static ssize_t show_volt_12(struct device *dev, char *buf)
250 struct fscpos_data *data = fscpos_update_device(dev);
251 return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[0], 14200));
254 static ssize_t show_volt_5(struct device *dev, char *buf)
256 struct fscpos_data *data = fscpos_update_device(dev);
257 return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[1], 6600));
260 static ssize_t show_volt_batt(struct device *dev, char *buf)
262 struct fscpos_data *data = fscpos_update_device(dev);
263 return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[2], 3300));
266 /* Watchdog */
267 static ssize_t show_wdog_control(struct fscpos_data *data, char *buf)
269 /* bits 0..3 reserved, bit 6 write only => mask with 0xb0 */
270 return sprintf(buf, "%u\n", data->wdog_control & 0xb0);
273 static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data
274 *data, const char *buf, size_t count, int reg)
276 /* bits 0..3 reserved => mask with 0xf0 */
277 unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;
279 down(&data->update_lock);
280 data->wdog_control &= ~0xf0;
281 data->wdog_control |= v;
282 fscpos_write_value(client, reg, data->wdog_control);
283 up(&data->update_lock);
284 return count;
287 static ssize_t show_wdog_state(struct fscpos_data *data, char *buf)
289 /* bits 0, 2..7 reserved => mask with 0x02 */
290 return sprintf(buf, "%u\n", data->wdog_state & 0x02);
293 static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data
294 *data, const char *buf, size_t count, int reg)
296 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
298 /* Valid values: 2 (clear) */
299 if (v != 2) {
300 dev_err(&client->dev, "wdog_state value %ld not supported. "
301 "Must be 2 to clear the state!\n", v);
302 return -EINVAL;
305 down(&data->update_lock);
306 data->wdog_state &= ~v;
307 fscpos_write_value(client, reg, v);
308 up(&data->update_lock);
309 return count;
312 static ssize_t show_wdog_preset(struct fscpos_data *data, char *buf)
314 return sprintf(buf, "%u\n", data->wdog_preset);
317 static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data
318 *data, const char *buf, size_t count, int reg)
320 unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff;
322 down(&data->update_lock);
323 data->wdog_preset = v;
324 fscpos_write_value(client, reg, data->wdog_preset);
325 up(&data->update_lock);
326 return count;
329 /* Event */
330 static ssize_t show_event(struct device *dev, char *buf)
332 /* bits 5..7 reserved => mask with 0x1f */
333 struct fscpos_data *data = fscpos_update_device(dev);
334 return sprintf(buf, "%u\n", data->global_event & 0x9b);
338 * Sysfs stuff
340 #define create_getter(kind, sub) \
341 static ssize_t sysfs_show_##kind##sub(struct device *dev, char *buf) \
343 struct fscpos_data *data = fscpos_update_device(dev); \
344 return show_##kind##sub(data, buf); \
347 #define create_getter_n(kind, offset, sub) \
348 static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, char\
349 *buf) \
351 struct fscpos_data *data = fscpos_update_device(dev); \
352 return show_##kind##sub(data, buf, offset); \
355 #define create_setter(kind, sub, reg) \
356 static ssize_t sysfs_set_##kind##sub (struct device *dev, const char \
357 *buf, size_t count) \
359 struct i2c_client *client = to_i2c_client(dev); \
360 struct fscpos_data *data = i2c_get_clientdata(client); \
361 return set_##kind##sub(client, data, buf, count, reg); \
364 #define create_setter_n(kind, offset, sub, reg) \
365 static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, \
366 const char *buf, size_t count) \
368 struct i2c_client *client = to_i2c_client(dev); \
369 struct fscpos_data *data = i2c_get_clientdata(client); \
370 return set_##kind##sub(client, data, buf, count, offset, reg);\
373 #define create_sysfs_device_ro(kind, sub, offset) \
374 static DEVICE_ATTR(kind##offset##sub, S_IRUGO, \
375 sysfs_show_##kind##offset##sub, NULL);
377 #define create_sysfs_device_rw(kind, sub, offset) \
378 static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, \
379 sysfs_show_##kind##offset##sub, sysfs_set_##kind##offset##sub);
381 #define sysfs_ro_n(kind, sub, offset) \
382 create_getter_n(kind, offset, sub); \
383 create_sysfs_device_ro(kind, sub, offset);
385 #define sysfs_rw_n(kind, sub, offset, reg) \
386 create_getter_n(kind, offset, sub); \
387 create_setter_n(kind, offset, sub, reg); \
388 create_sysfs_device_rw(kind, sub, offset);
390 #define sysfs_rw(kind, sub, reg) \
391 create_getter(kind, sub); \
392 create_setter(kind, sub, reg); \
393 create_sysfs_device_rw(kind, sub,);
395 #define sysfs_fan_with_min(offset, reg_status, reg_ripple, reg_min) \
396 sysfs_fan(offset, reg_status, reg_ripple); \
397 sysfs_rw_n(pwm,, offset, reg_min);
399 #define sysfs_fan(offset, reg_status, reg_ripple) \
400 sysfs_ro_n(fan, _input, offset); \
401 sysfs_ro_n(fan, _status, offset); \
402 sysfs_rw_n(fan, _ripple, offset, reg_ripple);
404 #define sysfs_temp(offset, reg_status) \
405 sysfs_ro_n(temp, _input, offset); \
406 sysfs_ro_n(temp, _status, offset); \
407 sysfs_rw_n(temp, _reset, offset, reg_status);
409 #define sysfs_watchdog(reg_wdog_preset, reg_wdog_state, reg_wdog_control) \
410 sysfs_rw(wdog, _control, reg_wdog_control); \
411 sysfs_rw(wdog, _preset, reg_wdog_preset); \
412 sysfs_rw(wdog, _state, reg_wdog_state);
414 sysfs_fan_with_min(1, FSCPOS_REG_FAN_STATE[0], FSCPOS_REG_FAN_RIPPLE[0],
415 FSCPOS_REG_PWM[0]);
416 sysfs_fan_with_min(2, FSCPOS_REG_FAN_STATE[1], FSCPOS_REG_FAN_RIPPLE[1],
417 FSCPOS_REG_PWM[1]);
418 sysfs_fan(3, FSCPOS_REG_FAN_STATE[2], FSCPOS_REG_FAN_RIPPLE[2]);
420 sysfs_temp(1, FSCPOS_REG_TEMP_STATE[0]);
421 sysfs_temp(2, FSCPOS_REG_TEMP_STATE[1]);
422 sysfs_temp(3, FSCPOS_REG_TEMP_STATE[2]);
424 sysfs_watchdog(FSCPOS_REG_WDOG_PRESET, FSCPOS_REG_WDOG_STATE,
425 FSCPOS_REG_WDOG_CONTROL);
427 static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
428 static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL);
429 static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL);
430 static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL);
432 static int fscpos_attach_adapter(struct i2c_adapter *adapter)
434 if (!(adapter->class & I2C_CLASS_HWMON))
435 return 0;
436 return i2c_detect(adapter, &addr_data, fscpos_detect);
439 int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
441 struct i2c_client *new_client;
442 struct fscpos_data *data;
443 int err = 0;
445 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
446 goto exit;
449 * OK. For now, we presume we have a valid client. We now create the
450 * client structure, even though we cannot fill it completely yet.
451 * But it allows us to access fscpos_{read,write}_value.
454 if (!(data = kmalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
455 err = -ENOMEM;
456 goto exit;
458 memset(data, 0, sizeof(struct fscpos_data));
460 new_client = &data->client;
461 i2c_set_clientdata(new_client, data);
462 new_client->addr = address;
463 new_client->adapter = adapter;
464 new_client->driver = &fscpos_driver;
465 new_client->flags = 0;
467 /* Do the remaining detection unless force or force_fscpos parameter */
468 if (kind < 0) {
469 if ((fscpos_read_value(new_client, FSCPOS_REG_IDENT_0)
470 != 0x50) /* 'P' */
471 || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_1)
472 != 0x45) /* 'E' */
473 || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2)
474 != 0x47))/* 'G' */
476 dev_dbg(&new_client->dev, "fscpos detection failed\n");
477 goto exit_free;
481 /* Fill in the remaining client fields and put it in the global list */
482 strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE);
484 data->valid = 0;
485 init_MUTEX(&data->update_lock);
487 /* Tell the I2C layer a new client has arrived */
488 if ((err = i2c_attach_client(new_client)))
489 goto exit_free;
491 /* Inizialize the fscpos chip */
492 fscpos_init_client(new_client);
494 /* Announce that the chip was found */
495 dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
497 /* Register sysfs hooks */
498 device_create_file(&new_client->dev, &dev_attr_event);
499 device_create_file(&new_client->dev, &dev_attr_in0_input);
500 device_create_file(&new_client->dev, &dev_attr_in1_input);
501 device_create_file(&new_client->dev, &dev_attr_in2_input);
502 device_create_file(&new_client->dev, &dev_attr_wdog_control);
503 device_create_file(&new_client->dev, &dev_attr_wdog_preset);
504 device_create_file(&new_client->dev, &dev_attr_wdog_state);
505 device_create_file(&new_client->dev, &dev_attr_temp1_input);
506 device_create_file(&new_client->dev, &dev_attr_temp1_status);
507 device_create_file(&new_client->dev, &dev_attr_temp1_reset);
508 device_create_file(&new_client->dev, &dev_attr_temp2_input);
509 device_create_file(&new_client->dev, &dev_attr_temp2_status);
510 device_create_file(&new_client->dev, &dev_attr_temp2_reset);
511 device_create_file(&new_client->dev, &dev_attr_temp3_input);
512 device_create_file(&new_client->dev, &dev_attr_temp3_status);
513 device_create_file(&new_client->dev, &dev_attr_temp3_reset);
514 device_create_file(&new_client->dev, &dev_attr_fan1_input);
515 device_create_file(&new_client->dev, &dev_attr_fan1_status);
516 device_create_file(&new_client->dev, &dev_attr_fan1_ripple);
517 device_create_file(&new_client->dev, &dev_attr_pwm1);
518 device_create_file(&new_client->dev, &dev_attr_fan2_input);
519 device_create_file(&new_client->dev, &dev_attr_fan2_status);
520 device_create_file(&new_client->dev, &dev_attr_fan2_ripple);
521 device_create_file(&new_client->dev, &dev_attr_pwm2);
522 device_create_file(&new_client->dev, &dev_attr_fan3_input);
523 device_create_file(&new_client->dev, &dev_attr_fan3_status);
524 device_create_file(&new_client->dev, &dev_attr_fan3_ripple);
526 return 0;
528 exit_free:
529 kfree(data);
530 exit:
531 return err;
534 static int fscpos_detach_client(struct i2c_client *client)
536 int err;
538 if ((err = i2c_detach_client(client))) {
539 dev_err(&client->dev, "Client deregistration failed, client"
540 " not detached.\n");
541 return err;
543 kfree(i2c_get_clientdata(client));
544 return 0;
547 static int fscpos_read_value(struct i2c_client *client, u8 reg)
549 dev_dbg(&client->dev, "Read reg 0x%02x\n", reg);
550 return i2c_smbus_read_byte_data(client, reg);
553 static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value)
555 dev_dbg(&client->dev, "Write reg 0x%02x, val 0x%02x\n", reg, value);
556 return i2c_smbus_write_byte_data(client, reg, value);
559 /* Called when we have found a new FSCPOS chip */
560 static void fscpos_init_client(struct i2c_client *client)
562 struct fscpos_data *data = i2c_get_clientdata(client);
564 /* read revision from chip */
565 data->revision = fscpos_read_value(client, FSCPOS_REG_REVISION);
568 static struct fscpos_data *fscpos_update_device(struct device *dev)
570 struct i2c_client *client = to_i2c_client(dev);
571 struct fscpos_data *data = i2c_get_clientdata(client);
573 down(&data->update_lock);
575 if ((jiffies - data->last_updated > 2 * HZ) ||
576 (jiffies < data->last_updated) || !data->valid) {
577 int i;
579 dev_dbg(&client->dev, "Starting fscpos update\n");
581 for (i = 0; i < 3; i++) {
582 data->temp_act[i] = fscpos_read_value(client,
583 FSCPOS_REG_TEMP_ACT[i]);
584 data->temp_status[i] = fscpos_read_value(client,
585 FSCPOS_REG_TEMP_STATE[i]);
586 data->fan_act[i] = fscpos_read_value(client,
587 FSCPOS_REG_FAN_ACT[i]);
588 data->fan_status[i] = fscpos_read_value(client,
589 FSCPOS_REG_FAN_STATE[i]);
590 data->fan_ripple[i] = fscpos_read_value(client,
591 FSCPOS_REG_FAN_RIPPLE[i]);
592 if (i < 2) {
593 /* fan2_min is not supported by the chip */
594 data->pwm[i] = fscpos_read_value(client,
595 FSCPOS_REG_PWM[i]);
597 /* reset fan status if speed is back to > 0 */
598 if (data->fan_status[i] != 0 && data->fan_act[i] > 0) {
599 reset_fan_alarm(client, i);
603 data->volt[0] = fscpos_read_value(client, FSCPOS_REG_VOLT_12);
604 data->volt[1] = fscpos_read_value(client, FSCPOS_REG_VOLT_5);
605 data->volt[2] = fscpos_read_value(client, FSCPOS_REG_VOLT_BATT);
607 data->wdog_preset = fscpos_read_value(client,
608 FSCPOS_REG_WDOG_PRESET);
609 data->wdog_state = fscpos_read_value(client,
610 FSCPOS_REG_WDOG_STATE);
611 data->wdog_control = fscpos_read_value(client,
612 FSCPOS_REG_WDOG_CONTROL);
614 data->global_event = fscpos_read_value(client,
615 FSCPOS_REG_EVENT_STATE);
617 data->last_updated = jiffies;
618 data->valid = 1;
620 up(&data->update_lock);
621 return data;
624 static int __init sm_fscpos_init(void)
626 return i2c_add_driver(&fscpos_driver);
629 static void __exit sm_fscpos_exit(void)
631 i2c_del_driver(&fscpos_driver);
634 MODULE_AUTHOR("Stefan Ott <stefan@desire.ch> based on work from Hermann Jung "
635 "<hej@odn.de>, Frodo Looijaard <frodol@dds.nl>"
636 " and Philip Edelbrock <phil@netroedge.com>");
637 MODULE_DESCRIPTION("fujitsu siemens poseidon chip driver");
638 MODULE_LICENSE("GPL");
640 module_init(sm_fscpos_init);
641 module_exit(sm_fscpos_exit);