root/lm-sensors/trunk/kernel/chips/mtp008.c @ 1032

Revision 1032, 34.0 KB (checked in by mds, 13 years ago)

Change mtp008 temperature reporting from max/min to limit/hyst.

Change initial values in driver from 70/5 to 70/50.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2   mtp008.c - Part of lm_sensors, Linux kernel modules for hardware
3   monitoring
4   Copyright (c) 2001  Kris Van Hees <aedil@alchar.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 as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <linux/version.h>
22#include <linux/module.h>
23#include <linux/malloc.h>
24#include <linux/proc_fs.h>
25#include <linux/ioport.h>
26#include <linux/sysctl.h>
27#include <asm/errno.h>
28#include <asm/io.h>
29#include <linux/types.h>
30#include <linux/i2c.h>
31#include "version.h"
32#include "sensors.h"
33#include <linux/init.h>
34
35#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) || \
36    (LINUX_VERSION_CODE == KERNEL_VERSION(2,3,0))
37#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
38#endif
39
40#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
41#define THIS_MODULE NULL
42#endif
43
44/* Addresses to scan */
45static unsigned short normal_i2c[] = {SENSORS_I2C_END};
46static unsigned short normal_i2c_range[] = {0x2c, 0x2e, SENSORS_I2C_END};
47static unsigned int normal_isa[] = {SENSORS_ISA_END};
48static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
49
50/* Insmod parameters */
51SENSORS_INSMOD_1(mtp008);
52
53/* The MTP008 registers */
54/*      in0 .. in6 */
55#define MTP008_REG_IN(nr)               (0x20 + (nr))
56#define MTP008_REG_IN_MAX(nr)           (0x2b + (nr) * 2)
57#define MTP008_REG_IN_MIN(nr)           (0x2c + (nr) * 2)
58
59/*      temp1 */
60#define MTP008_REG_TEMP                 0x27
61#define MTP008_REG_TEMP_MAX             0x39
62#define MTP008_REG_TEMP_MIN             0x3a
63
64/*      fan1 .. fan3 */
65#define MTP008_REG_FAN(nr)              (0x27 + (nr))
66#define MTP008_REG_FAN_MIN(nr)          (0x3a + (nr))
67
68#define MTP008_REG_CONFIG               0x40
69#define MTP008_REG_INT_STAT1            0x41
70#define MTP008_REG_INT_STAT2            0x42
71
72#define MTP008_REG_SMI_MASK1            0x43
73#define MTP008_REG_SMI_MASK2            0x44
74
75#define MTP008_REG_NMI_MASK1            0x45
76#define MTP008_REG_NMI_MASK2            0x46
77
78#define MTP008_REG_VID_FANDIV           0x47
79
80#define MTP008_REG_I2C_ADDR             0x48
81
82#define MTP008_REG_RESET_VID4           0x49
83
84#define MTP008_REG_OVT_PROP             0x50
85
86#define MTP008_REG_BEEP_CTRL1           0x51
87#define MTP008_REG_BEEP_CTRL2           0x52
88
89/*      pwm1 .. pwm3  nr range 1-3 */
90#define MTP008_REG_PWM_CTRL(nr)         (0x52 + (nr))
91
92#define MTP008_REG_PIN_CTRL1            0x56
93#define MTP008_REG_PIN_CTRL2            0x57
94
95#define MTP008_REG_CHIPID               0x58
96
97/*
98 * Pin control register configuration constants.
99 */
100#define MTP008_CFG_VT1_PII              0x08
101#define MTP008_CFG_VT2_AIN              0x00
102#define MTP008_CFG_VT2_VT               0x03
103#define MTP008_CFG_VT2_PII              0x04
104#define MTP008_CFG_VT2_MASK             0x06
105#define MTP008_CFG_VT3_VT               0x01
106
107/* sensor pin types */
108#define VOLTAGE         1
109#define THERMISTOR      2
110#define PIIDIODE        3
111
112/*
113 * Conversion routines and macros.  Rounding and limit checking is only done on
114 * the TO_REG variants.
115 *
116 * Note that IN values are expressed as 100 times the actual voltage to avoid
117 * having to use floating point values.  As such, IN values are between 0 and
118 * 409 (0V to 4.096V).
119 */
120#define IN_TO_REG(val)          (SENSORS_LIMIT((((val) * 10 + 8) / 16), 0, 255))
121#define IN_FROM_REG(val)        (((val) * 16) / 10)
122
123/*
124 * The fan cotation count (as stored in the register) is calculated using the
125 * following formula:
126 *      count = (22.5K * 60) / (rpm * div) = 1350000 / (rpm * div)
127 * and the rpm is therefore:
128 *      rpm = 1350000 / (count * div)
129 */
130extern inline u8 FAN_TO_REG(long rpm, int div)
131{
132        if (rpm == 0)
133                return 255;
134
135        rpm = SENSORS_LIMIT(rpm, 1, 1000000);
136
137        return SENSORS_LIMIT(
138                 (1350000 + rpm * div / 2) / (rpm * div),
139                 1, 254
140               );
141}
142
143#define FAN_FROM_REG(val, div)  ((val) == 0 ? -1                              \
144                                            : (val) == 255 ? 0                \
145                                                           : 1350000 /        \
146                                                             ((val) * (div))  \
147                                )
148
149/*
150 * Temperatures are stored as two's complement values of the Celsius value.  It
151 * actually uses 10 times the Celsius value to avoid using floating point
152 * values.
153 */
154#define TEMP_TO_REG(val)        (                                             \
155                                 (val) < 0                                    \
156                                    ? SENSORS_LIMIT(((val) - 5) / 10, 0, 255) \
157                                    : SENSORS_LIMIT(((val) + 5) / 10, 0, 255) \
158                                )
159#define TEMP_FROM_REG(val)      (                                             \
160                                 (                                            \
161                                  (val) > 0x80 ? (val) - 0x100                \
162                                               : (val)                        \
163                                 ) * 10                                       \
164                                )
165
166/*
167 * VCORE voltage:
168 *      0x00 to 0x0f    = 2.05 to 1.30 (0.05 per unit)
169 *      0x10 to 0x1e    = 3.50 to 2.10 (0.10 per unit)
170 *      0x1f            = No CPU
171 */
172#define VID_FROM_REG(val)       ((val) == 0x1f                                \
173                                         ? 0                                  \
174                                         : (val) < 0x10 ? 205 - (val) * 5     \
175                                                        : 510 - (val) * 10)
176
177/*
178 * Fan divider.
179 */
180#define DIV_FROM_REG(val)       (1 << (val))
181#define DIV_TO_REG(val)         ((val) == 8 ? 3                               \
182                                            : (val) == 4 ? 2                  \
183                                                         : (val) == 2 ? 1     \
184                                                                      : 0)
185
186/*
187 * Alarms (interrupt status).
188 */
189#define ALARMS_FROM_REG(val)    (val)
190
191/*
192 * Beep controls.
193 */
194#define BEEPS_FROM_REG(val)     (val)
195#define BEEPS_TO_REG(val)       (val)
196
197/*
198 * PWM control. nr range 1 to 3
199 */
200#define PWM_FROM_REG(val)       (val)
201#define PWM_TO_REG(val)         (val)
202#define PWMENABLE_FROM_REG(nr, val)     (((val) >> ((nr) + 3)) & 1)
203
204/* Initial limits */
205#define MTP008_INIT_IN_0        (vid)                           /* VCore 1 */
206#define MTP008_INIT_IN_1        330                             /* +3.3V */
207#define MTP008_INIT_IN_2        (1200 * 10 / 38)                /* +12V */
208#define MTP008_INIT_IN_3        (vid)                           /* VCore 2 */
209#define MTP008_INIT_IN_5        ((11861 + 7 * (-1200)) / 36)    /* -12V */
210#define MTP008_INIT_IN_6        150                             /* Vtt */
211
212#define MTP008_INIT_IN_PCT      10
213
214#define MTP008_INIT_IN_MIN_0    (MTP008_INIT_IN_0 -                           \
215                                 MTP008_INIT_IN_0 * MTP008_INIT_IN_PCT / 100)
216#define MTP008_INIT_IN_MAX_0    (MTP008_INIT_IN_0 +                           \
217                                 MTP008_INIT_IN_0 * MTP008_INIT_IN_PCT / 100)
218#define MTP008_INIT_IN_MIN_1    (MTP008_INIT_IN_1 -                           \
219                                 MTP008_INIT_IN_1 * MTP008_INIT_IN_PCT / 100)
220#define MTP008_INIT_IN_MAX_1    (MTP008_INIT_IN_1 +                           \
221                                 MTP008_INIT_IN_1 * MTP008_INIT_IN_PCT / 100)
222#define MTP008_INIT_IN_MIN_2    (MTP008_INIT_IN_2 -                           \
223                                 MTP008_INIT_IN_2 * MTP008_INIT_IN_PCT / 100)
224#define MTP008_INIT_IN_MAX_2    (MTP008_INIT_IN_2 +                           \
225                                 MTP008_INIT_IN_2 * MTP008_INIT_IN_PCT / 100)
226#define MTP008_INIT_IN_MIN_3    (MTP008_INIT_IN_3 -                           \
227                                 MTP008_INIT_IN_3 * MTP008_INIT_IN_PCT / 100)
228#define MTP008_INIT_IN_MAX_3    (MTP008_INIT_IN_3 +                           \
229                                 MTP008_INIT_IN_3 * MTP008_INIT_IN_PCT / 100)
230
231#define MTP008_INIT_IN_MIN_5    (MTP008_INIT_IN_5 -                           \
232                                 MTP008_INIT_IN_5 * MTP008_INIT_IN_PCT / 100)
233#define MTP008_INIT_IN_MAX_5    (MTP008_INIT_IN_5 +                           \
234                                 MTP008_INIT_IN_5 * MTP008_INIT_IN_PCT / 100)
235#define MTP008_INIT_IN_MIN_6    (MTP008_INIT_IN_6 -                           \
236                                 MTP008_INIT_IN_6 * MTP008_INIT_IN_PCT / 100)
237#define MTP008_INIT_IN_MAX_6    (MTP008_INIT_IN_6 +                           \
238                                 MTP008_INIT_IN_6 * MTP008_INIT_IN_PCT / 100)
239
240#define MTP008_INIT_FAN_MIN_1   3000
241#define MTP008_INIT_FAN_MIN_2   3000
242#define MTP008_INIT_FAN_MIN_3   3000
243
244#define MTP008_INIT_TEMP_OVER   700                     /* 70 Celsius */
245#define MTP008_INIT_TEMP_HYST   500                     /* 50 Celsius */
246#define MTP008_INIT_TEMP2_OVER  700                     /* 70 Celsius */
247#define MTP008_INIT_TEMP2_HYST  500                     /* 50 Celsius */
248
249#ifdef MODULE
250extern int init_module(void);
251extern int cleanup_module(void);
252#endif                          /* MODULE */
253
254/*
255 * For each registered MTP008, we need to keep some data in memory.  The
256 * structure itself is dynamically allocated, at the same time when a new
257 * mtp008 client is allocated.
258 */
259struct mtp008_data {
260        int sysctl_id;
261        enum chips type;
262
263        struct semaphore update_lock;
264        char valid;                             /* !=0 if fields are valid */
265        unsigned long last_updated;             /* In jiffies */
266
267        u8 in[7];                               /* Register value */
268        u8 in_max[7];                           /* Register value */
269        u8 in_min[7];                           /* Register value */
270        u8 temp;                                /* Register value */
271        u8 temp_max;                            /* Register value */
272        u8 temp_min;                            /* Register value */
273        u8 fan[3];                              /* Register value */
274        u8 fan_min[3];                          /* Register value */
275        u8 vid;                                 /* Register encoding */
276        u8 fan_div[3];                          /* Register encoding */
277        u16 alarms;                             /* Register encoding */
278        u16 beeps;                              /* Register encoding */
279        u8 pwm[4];                              /* Register value */
280        u8 sens[3];                             /* 1 = Analog input,
281                                                   2 = Thermistor,
282                                                   3 = PII/Celeron diode */
283        u8 pwmenable;                           /* Register 0x57 value */
284};
285
286#ifdef MODULE
287static int __init sensors_mtp008_init(void);
288#else
289extern int __init sensors_mtp008_init(void);
290#endif
291static int __init mtp008_cleanup(void);
292
293static int mtp008_attach_adapter(struct i2c_adapter *adapter);
294static int mtp008_detect(struct i2c_adapter *adapter, int address,
295                         unsigned short flags, int kind);
296static int mtp008_detach_client(struct i2c_client *client);
297static int mtp008_command(struct i2c_client *client, unsigned int cmd,
298                          void *arg);
299static void mtp008_inc_use(struct i2c_client *client);
300static void mtp008_dec_use(struct i2c_client *client);
301
302static int mtp008_read_value(struct i2c_client *client, u8 register);
303static int mtp008_write_value(struct i2c_client *client, u8 register, u8 value);
304static void mtp008_update_client(struct i2c_client *client);
305static void mtp008_init_client(struct i2c_client *client);
306
307static void mtp008_in(struct i2c_client *client, int operation,
308                      int ctl_name, int *nrels_mag, long *results);
309static void mtp008_fan(struct i2c_client *client, int operation,
310                       int ctl_name, int *nrels_mag, long *results);
311static void mtp008_temp(struct i2c_client *client, int operation,
312                        int ctl_name, int *nrels_mag, long *results);
313static void mtp008_temp_add(struct i2c_client *client, int operation,
314                            int ctl_name, int *nrels_mag, long *results);
315static void mtp008_vid(struct i2c_client *client, int operation,
316                       int ctl_name, int *nrels_mag, long *results);
317static void mtp008_fan_div(struct i2c_client *client, int operation,
318                           int ctl_name, int *nrels_mag, long *results);
319static void mtp008_alarms(struct i2c_client *client, int operation,
320                          int ctl_name, int *nrels_mag, long *results);
321static void mtp008_beep(struct i2c_client *client, int operation,
322                        int ctl_name, int *nrels_mag, long *results);
323static void mtp008_pwm(struct i2c_client *client, int operation,
324                       int ctl_name, int *nrels_mag, long *results);
325static void mtp008_sens(struct i2c_client *client, int operation,
326                        int ctl_name, int *nrels_mag, long *results);
327static void mtp008_getsensortype(struct mtp008_data *data, u8 inp);
328
329static int mtp008_id = 0;
330
331static struct i2c_driver mtp008_driver =
332{
333    /* name */                  "MTP008 sensor driver",
334    /* id */                    I2C_DRIVERID_MTP008,
335    /* flags */                 I2C_DF_NOTIFY,
336    /* attach_adapter */        &mtp008_attach_adapter,
337    /* detach_client */         &mtp008_detach_client,
338    /* command */               &mtp008_command,
339    /* inc_use */               &mtp008_inc_use,
340    /* dec_use */               &mtp008_dec_use
341};
342
343/* Used by mtp008_init/cleanup */
344static int __initdata mtp008_initialized = 0;
345
346/* The /proc/sys entries */
347/* These files are created for each detected chip. This is just a template;
348   though at first sight, you might think we could use a statically
349   allocated list, we need some way to get back to the parent - which
350   is done through one of the 'extra' fields which are initialized
351   when a new copy is allocated. */
352
353static ctl_table mtp008_dir_table_template[] =
354{
355        {MTP008_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL,
356         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_in},
357        {MTP008_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL,
358         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_in},
359        {MTP008_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL,
360         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_in},
361        {MTP008_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL,
362         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_in},
363        {MTP008_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL,
364         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_in},
365        {MTP008_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL,
366         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_in},
367        {MTP008_SYSCTL_IN6, "in6", NULL, 0, 0644, NULL,
368         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_in},
369        {MTP008_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL,
370         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_fan},
371        {MTP008_SYSCTL_FAN2, "fan2", NULL, 0, 0644, NULL,
372         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_fan},
373        {MTP008_SYSCTL_FAN3, "fan3", NULL, 0, 0644, NULL,
374         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_fan},
375        {MTP008_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL,
376         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_temp},
377        {MTP008_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
378       &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_temp_add},
379        {MTP008_SYSCTL_TEMP3, "temp3", NULL, 0, 0644, NULL,
380       &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_temp_add},
381        {MTP008_SYSCTL_VID, "vid", NULL, 0, 0444, NULL,
382         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_vid},
383        {MTP008_SYSCTL_FAN_DIV, "fan_div", NULL, 0, 0644, NULL,
384         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_fan_div},
385        {MTP008_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
386         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_alarms},
387        {MTP008_SYSCTL_BEEP, "beep", NULL, 0, 0644, NULL,
388         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_beep},
389        {MTP008_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL,
390         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_pwm},
391        {MTP008_SYSCTL_PWM2, "pwm2", NULL, 0, 0644, NULL,
392         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_pwm},
393        {MTP008_SYSCTL_PWM3, "pwm3", NULL, 0, 0644, NULL,
394         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_pwm},
395        {MTP008_SYSCTL_SENS1, "sensor1", NULL, 0, 0644, NULL,
396         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_sens},
397        {MTP008_SYSCTL_SENS2, "sensor2", NULL, 0, 0644, NULL,
398         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_sens},
399        {MTP008_SYSCTL_SENS3, "sensor3", NULL, 0, 0644, NULL,
400         &sensors_proc_real, &sensors_sysctl_real, NULL, &mtp008_sens},
401        {0}
402};
403
404/* This function is called when:
405 * mtp008_driver is inserted (when this module is loaded), for each available
406 * adapter when a new adapter is inserted (and mtp008_driver is still present)
407 */
408int mtp008_attach_adapter(struct i2c_adapter *adapter)
409{
410        struct i2c_client_address_data mtp008_addr_data;
411
412        mtp008_addr_data.normal_i2c = addr_data.normal_i2c;
413        mtp008_addr_data.normal_i2c_range = addr_data.normal_i2c_range;
414        mtp008_addr_data.probe = addr_data.probe;
415        mtp008_addr_data.probe_range = addr_data.probe_range;
416        mtp008_addr_data.ignore = addr_data.ignore;
417        mtp008_addr_data.ignore_range = addr_data.ignore_range;
418        mtp008_addr_data.force = addr_data.forces->force;
419
420        return i2c_probe(adapter, &mtp008_addr_data, mtp008_detect);
421}
422
423int mtp008_detect(struct i2c_adapter *adapter, int address,
424                  unsigned short flags, int kind)
425{
426        const char *type_name = "";
427        const char *client_name = "";
428        int is_isa, err, sysid;
429        struct i2c_client *new_client;
430        struct mtp008_data *data;
431
432        err = 0;
433
434        is_isa = i2c_is_isa_adapter(adapter);
435        if (is_isa ||
436            !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
437                goto ERROR0;
438
439        /*
440         * We presume we have a valid client.  We now create the client
441         * structure, even though we cannot fill it completely yet.  But it
442         * allows us to use mtp008_(read|write)_value().
443         */
444        if (!(new_client = kmalloc(sizeof(struct i2c_client) +
445                                   sizeof(struct mtp008_data),
446                                   GFP_KERNEL))) {
447                err = -ENOMEM;
448                goto ERROR0;
449        }
450        data = (struct mtp008_data *) (new_client + 1);
451        new_client->addr = address;
452        new_client->data = data;
453        new_client->adapter = adapter;
454        new_client->driver = &mtp008_driver;
455        new_client->flags = 0;
456
457        /*
458         * Remaining detection.
459         */
460        if (kind < 0) {
461                if (mtp008_read_value(new_client, MTP008_REG_CHIPID) != 0xac)
462                        goto ERROR1;
463        }
464        /*
465         * Fill in the remaining client fields and put it into the global list.
466         */
467        type_name = "mtp008";
468        client_name = "MTP008 chip";
469        strcpy(new_client->name, client_name);
470        data->type = kind;
471
472        new_client->id = mtp008_id++;
473        data->valid = 0;
474        init_MUTEX(&data->update_lock);
475
476        /*
477         * Tell the I2C layer that a new client has arrived.
478         */
479        if ((err = i2c_attach_client(new_client)))
480                goto ERROR1;
481
482        /*
483         * Register a new directory entry with the sensors module.
484         */
485        if ((sysid = sensors_register_entry(new_client, type_name,
486                                            mtp008_dir_table_template,
487                                            THIS_MODULE)) < 0) {
488                err = sysid;
489                goto ERROR2;
490        }
491        data->sysctl_id = sysid;
492
493        /*
494         * Initialize the MTP008 chip.
495         */
496        mtp008_init_client(new_client);
497
498        return 0;
499
500        /*
501         * Error handling.  Bad programming practise but very code efficient.
502         */
503      ERROR2:
504        i2c_detach_client(new_client);
505      ERROR1:
506        kfree(new_client);
507
508      ERROR0:
509        return err;
510}
511
512int mtp008_detach_client(struct i2c_client *client)
513{
514        int err;
515
516        sensors_deregister_entry(
517                ((struct mtp008_data *) (client->data))->sysctl_id);
518
519        if ((err = i2c_detach_client(client))) {
520                printk("mtp008.o: Deregistration failed, "
521                       "client not detached.\n");
522                return err;
523        }
524        kfree(client);
525
526        return 0;
527}
528
529/* No commands defined yet */
530int mtp008_command(struct i2c_client *client, unsigned int cmd, void *arg)
531{
532        return 0;
533}
534
535void mtp008_inc_use(struct i2c_client *client)
536{
537#ifdef MODULE
538        MOD_INC_USE_COUNT;
539#endif
540}
541
542void mtp008_dec_use(struct i2c_client *client)
543{
544#ifdef MODULE
545        MOD_DEC_USE_COUNT;
546#endif
547}
548
549int mtp008_read_value(struct i2c_client *client, u8 reg)
550{
551        return i2c_smbus_read_byte_data(client, reg) & 0xff;
552}
553
554int mtp008_write_value(struct i2c_client *client, u8 reg, u8 value)
555{
556        return i2c_smbus_write_byte_data(client, reg, value);
557}
558
559/* Called when we have found a new MTP008. It should set limits, etc. */
560void mtp008_init_client(struct i2c_client *client)
561{
562        int vid;
563        u8 save1, save2;
564        struct mtp008_data *data;
565
566        data = client->data;
567
568        /*
569         * Initialize the Myson MTP008 hardware monitoring chip.
570         * Save the pin settings that the BIOS hopefully set.
571         */
572        save1 = mtp008_read_value(client, MTP008_REG_PIN_CTRL1);
573        save2 = mtp008_read_value(client, MTP008_REG_PIN_CTRL2);
574        mtp008_write_value(client, MTP008_REG_CONFIG,
575             (mtp008_read_value(client, MTP008_REG_CONFIG) & 0x7f) | 0x80);
576        mtp008_write_value(client, MTP008_REG_PIN_CTRL1, save1);
577        mtp008_write_value(client, MTP008_REG_PIN_CTRL2, save2);
578
579        mtp008_getsensortype(data, save2);
580
581        /*
582         * Retrieve the VID setting (needed for the default limits).
583         */
584        vid = mtp008_read_value(client, MTP008_REG_VID_FANDIV) & 0x0f;
585        vid |= (mtp008_read_value(client, MTP008_REG_RESET_VID4) & 0x01) << 4;
586        vid = VID_FROM_REG(vid);
587
588        /*
589         * Set the default limits.
590         *
591         * Setting temp sensors is done as follows:
592         *
593         *          Register 0x57: 0 0 0 0 x x x x
594         *                                 | \ / +-- AIN5/VT3
595         *                                 |  +----- AIN4/VT2/PII
596         *                                 +-------- VT1/PII
597         */
598
599        mtp008_write_value(client, MTP008_REG_IN_MAX(0),
600                           IN_TO_REG(MTP008_INIT_IN_MAX_0));
601        mtp008_write_value(client, MTP008_REG_IN_MIN(0),
602                           IN_TO_REG(MTP008_INIT_IN_MIN_0));
603        mtp008_write_value(client, MTP008_REG_IN_MAX(1),
604                           IN_TO_REG(MTP008_INIT_IN_MAX_1));
605        mtp008_write_value(client, MTP008_REG_IN_MIN(1),
606                           IN_TO_REG(MTP008_INIT_IN_MIN_1));
607        mtp008_write_value(client, MTP008_REG_IN_MAX(2),
608                           IN_TO_REG(MTP008_INIT_IN_MAX_2));
609        mtp008_write_value(client, MTP008_REG_IN_MIN(2),
610                           IN_TO_REG(MTP008_INIT_IN_MIN_2));
611        mtp008_write_value(client, MTP008_REG_IN_MAX(3),
612                           IN_TO_REG(MTP008_INIT_IN_MAX_3));
613        mtp008_write_value(client, MTP008_REG_IN_MIN(3),
614                           IN_TO_REG(MTP008_INIT_IN_MIN_3));
615
616        mtp008_write_value(client, MTP008_REG_IN_MAX(5),
617                           IN_TO_REG(MTP008_INIT_IN_MAX_5));
618        mtp008_write_value(client, MTP008_REG_IN_MIN(5),
619                           IN_TO_REG(MTP008_INIT_IN_MIN_5));
620        mtp008_write_value(client, MTP008_REG_IN_MAX(6),
621                           IN_TO_REG(MTP008_INIT_IN_MAX_6));
622        mtp008_write_value(client, MTP008_REG_IN_MIN(6),
623                           IN_TO_REG(MTP008_INIT_IN_MIN_6));
624
625        mtp008_write_value(client, MTP008_REG_TEMP_MAX,
626                           TEMP_TO_REG(MTP008_INIT_TEMP_OVER));
627        mtp008_write_value(client, MTP008_REG_TEMP_MIN,
628                           TEMP_TO_REG(MTP008_INIT_TEMP_HYST));
629        mtp008_write_value(client, MTP008_REG_IN_MAX(4),
630                           TEMP_TO_REG(MTP008_INIT_TEMP2_OVER));
631        mtp008_write_value(client, MTP008_REG_IN_MIN(4),
632                           TEMP_TO_REG(MTP008_INIT_TEMP2_HYST));
633
634        mtp008_write_value(client, MTP008_REG_FAN_MIN(1),
635                           FAN_TO_REG(MTP008_INIT_FAN_MIN_1, 2));
636        mtp008_write_value(client, MTP008_REG_FAN_MIN(2),
637                           FAN_TO_REG(MTP008_INIT_FAN_MIN_2, 2));
638        mtp008_write_value(client, MTP008_REG_FAN_MIN(3),
639                           FAN_TO_REG(MTP008_INIT_FAN_MIN_3, 2));
640
641        /*
642         * Start monitoring.
643         */
644        mtp008_write_value(
645                client, MTP008_REG_CONFIG,
646                (mtp008_read_value(client, MTP008_REG_CONFIG) & 0xf7) | 0x01
647        );
648}
649
650void mtp008_update_client(struct i2c_client *client)
651{
652        int i;
653        u8 inp;
654        struct mtp008_data *data;
655
656        data = client->data;
657
658        down(&data->update_lock);
659
660        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
661            (jiffies < data->last_updated) || !data->valid) {
662#ifdef DEBUG
663                printk("Starting MTP008 update\n");
664#endif
665
666                /*
667                 * Read in the analog inputs.  We're reading AIN4 and AIN5 as
668                 * regular analog inputs, even though they may have been
669                 * configured as temperature readings instead.  Interpretation
670                 * of these values is done elsewhere.
671                 */
672                for (i = 0; i < 7; i++) {
673                        data->in[i] =
674                                mtp008_read_value(client, MTP008_REG_IN(i));
675                        data->in_max[i] =
676                                mtp008_read_value(client, MTP008_REG_IN_MAX(i));
677                        data->in_min[i] =
678                                mtp008_read_value(client, MTP008_REG_IN_MIN(i));
679                }
680
681                /*
682                 * Read the temperature sensor.
683                 */
684                data->temp = mtp008_read_value(client, MTP008_REG_TEMP);
685                data->temp_max = mtp008_read_value(client, MTP008_REG_TEMP_MAX);
686                data->temp_min = mtp008_read_value(client, MTP008_REG_TEMP_MIN);
687
688                /*
689                 * Read the first 2 fan dividers and the VID setting.  Read the
690                 * third fan divider from a different register.
691                 */
692                inp = mtp008_read_value(client, MTP008_REG_VID_FANDIV);
693                data->vid = inp & 0x0f;
694                data->vid |= (mtp008_read_value(client,
695                                     MTP008_REG_RESET_VID4) & 0x01) << 4;
696
697                data->fan_div[0] = (inp >> 4) & 0x03;
698                data->fan_div[1] = inp >> 6;
699                data->fan_div[2] =
700                        mtp008_read_value(client, MTP008_REG_PIN_CTRL1) >> 6;
701
702                /*
703                 * Read the interrupt status registers.
704                 */
705                data->alarms =
706                        (mtp008_read_value(client,
707                                           MTP008_REG_INT_STAT1) & 0xdf) |
708                        (mtp008_read_value(client,
709                                           MTP008_REG_INT_STAT2) & 0x0f) << 8;
710
711                /*
712                 * Read the beep control registers.
713                 */
714                data->beeps =
715                        (mtp008_read_value(client,
716                                           MTP008_REG_BEEP_CTRL1) & 0xdf) |
717                        (mtp008_read_value(client,
718                                           MTP008_REG_BEEP_CTRL2) & 0x8f) << 8;
719
720                /*
721                 * Read the sensor configuration.
722                 */
723                inp = mtp008_read_value(client, MTP008_REG_PIN_CTRL2);
724                mtp008_getsensortype(data, inp);
725
726                /*
727                 * Read the PWM registers if enabled.
728                 */
729                for (i = 1; i <= 3; i++)
730                {
731                        if(PWMENABLE_FROM_REG(i, inp))
732                                data->pwm[i-1] = mtp008_read_value(client,
733                                                  MTP008_REG_PWM_CTRL(i));
734                        else
735                                data->pwm[i-1] = 255;
736                }
737
738                /*
739                 * Read the fan sensors. Skip 3 if PWM3 enabled.
740                 */
741                for (i = 1; i <= 3; i++) {
742                        if(i == 3 && PWMENABLE_FROM_REG(3, inp)) {
743                                data->fan[2] = 0;
744                                data->fan_min[2] = 0;
745                        } else {
746                                data->fan[i-1] = mtp008_read_value(client,
747                                          MTP008_REG_FAN(i));
748                                data->fan_min[i-1] = mtp008_read_value(client,
749                                          MTP008_REG_FAN_MIN(i));
750                        }
751                }
752
753                data->last_updated = jiffies;
754                data->valid = 1;
755        }
756        up(&data->update_lock);
757}
758
759void mtp008_getsensortype(struct mtp008_data *data, u8 inp)
760{
761        inp &= 0x0f;
762        data->sens[0] = (inp >> 3) + 2;                 /* 2 or 3 */
763        data->sens[1] = ((inp >> 1) & 0x03) + 1;        /* 1, 2 or 3 */
764        data->sens[2] = (inp & 0x01) + 1;               /* 1 or 2 */
765}
766
767/* The next few functions are the call-back functions of the /proc/sys and
768   sysctl files. Which function is used is defined in the ctl_table in
769   the extra1 field.
770   Each function must return the magnitude (power of 10 to divide the date
771   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
772   put a maximum of *nrels elements in results reflecting the data of this
773   file, and set *nrels to the number it actually put in it, if operation==
774   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
775   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
776   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
777   large enough (by checking the incoming value of *nrels). This is not very
778   good practice, but as long as you put less than about 5 values in results,
779   you can assume it is large enough. */
780void mtp008_in(struct i2c_client *client, int operation, int ctl_name,
781               int *nrels_mag, long *results)
782{
783        int nr;
784        struct mtp008_data *data;
785
786        nr = ctl_name - MTP008_SYSCTL_IN0;
787        data = client->data;
788
789        switch (operation) {
790        case SENSORS_PROC_REAL_INFO:
791                *nrels_mag = 2;
792
793                break;
794        case SENSORS_PROC_REAL_READ:
795                mtp008_update_client(client);
796
797                if((nr != 4 && nr != 5) || data->sens[nr - 3] == VOLTAGE) {
798                        results[0] = IN_FROM_REG(data->in_min[nr]);
799                        results[1] = IN_FROM_REG(data->in_max[nr]);
800                        results[2] = IN_FROM_REG(data->in[nr]);
801                } else {
802                        results[0] = 0;
803                        results[1] = 0;
804                        results[2] = 0;
805                }
806
807                *nrels_mag = 3;
808
809                break;
810        case SENSORS_PROC_REAL_WRITE:
811                if((nr != 4 && nr != 5) || data->sens[nr - 3] == VOLTAGE) {
812                        if (*nrels_mag >= 1) {
813                                data->in_min[nr] = IN_TO_REG(results[0]);
814                                mtp008_write_value(client, MTP008_REG_IN_MIN(nr),
815                                                   data->in_min[nr]);
816                        }
817                        if (*nrels_mag >= 2) {
818                                data->in_max[nr] = IN_TO_REG(results[1]);
819                                mtp008_write_value(client, MTP008_REG_IN_MAX(nr),
820                                                   data->in_max[nr]);
821                        }
822                }
823        }
824}
825
826void mtp008_fan(struct i2c_client *client, int operation, int ctl_name,
827                int *nrels_mag, long *results)
828{
829        int nr;
830        struct mtp008_data *data;
831
832        nr = ctl_name - MTP008_SYSCTL_FAN1;
833        data = client->data;
834
835        switch (operation) {
836        case SENSORS_PROC_REAL_INFO:
837                *nrels_mag = 0;
838
839                break;
840        case SENSORS_PROC_REAL_READ:
841                mtp008_update_client(client);
842
843                results[0] = FAN_FROM_REG(data->fan_min[nr],
844                                        DIV_FROM_REG(data->fan_div[nr]));
845                results[1] = FAN_FROM_REG(data->fan[nr],
846                                        DIV_FROM_REG(data->fan_div[nr]));
847
848                *nrels_mag = 2;
849
850                break;
851        case SENSORS_PROC_REAL_WRITE:
852                if (*nrels_mag >= 1) {
853                        data->fan_min[nr] =
854                            FAN_TO_REG(results[0],
855                                       DIV_FROM_REG(data->fan_div[nr]));
856                        mtp008_write_value(client, MTP008_REG_FAN_MIN(nr),
857                                           data->fan_min[nr]);
858                }
859        }
860}
861
862void mtp008_temp(struct i2c_client *client, int operation, int ctl_name,
863                 int *nrels_mag, long *results)
864{
865        struct mtp008_data *data;
866
867        data = client->data;
868
869        switch (operation) {
870        case SENSORS_PROC_REAL_INFO:
871                *nrels_mag = 1;
872
873                break;
874        case SENSORS_PROC_REAL_READ:
875                mtp008_update_client(client);
876
877                results[0] = TEMP_FROM_REG(data->temp_max);
878                results[1] = TEMP_FROM_REG(data->temp_min);
879                results[2] = TEMP_FROM_REG(data->temp);
880                *nrels_mag = 3;
881
882                break;
883        case SENSORS_PROC_REAL_WRITE:
884                if (*nrels_mag >= 1) {
885                        data->temp_max = TEMP_TO_REG(results[0]);
886                        mtp008_write_value(client, MTP008_REG_TEMP_MAX,
887                                           data->temp_max);
888                }
889                if (*nrels_mag >= 2) {
890                        data->temp_min = TEMP_TO_REG(results[1]);
891                        mtp008_write_value(client, MTP008_REG_TEMP_MIN,
892                                           data->temp_min);
893                }
894        }
895}
896
897void mtp008_temp_add(struct i2c_client *client, int operation, int ctl_name,
898                     int *nrels_mag, long *results)
899{
900        int nr;
901        struct mtp008_data *data;
902
903        nr = 3 + ctl_name - MTP008_SYSCTL_TEMP1;        /* AIN4 or AIN5 */
904        data = client->data;
905
906        switch (operation) {
907        case SENSORS_PROC_REAL_INFO:
908                *nrels_mag = 1;
909
910                break;
911        case SENSORS_PROC_REAL_READ:
912                mtp008_update_client(client);
913
914                if(data->sens[nr - 3] != VOLTAGE) {
915                        results[0] = TEMP_FROM_REG(data->in_max[nr]);
916                        results[1] = TEMP_FROM_REG(data->in_min[nr]);
917                        results[2] = TEMP_FROM_REG(data->in[nr]);
918                } else {
919                        results[0] = 0;
920                        results[1] = 0;
921                        results[2] = 0;
922                }
923                *nrels_mag = 3;
924
925                break;
926        case SENSORS_PROC_REAL_WRITE:
927                if(data->sens[nr - 3] != VOLTAGE) {
928                        if (*nrels_mag >= 1) {
929                                data->in_max[nr] = TEMP_TO_REG(results[0]);
930                                mtp008_write_value(client, MTP008_REG_TEMP_MAX,
931                                                   data->in_max[nr]);
932                        }
933                        if (*nrels_mag >= 2) {
934                                data->in_min[nr] = TEMP_TO_REG(results[1]);
935                                mtp008_write_value(client, MTP008_REG_TEMP_MIN,
936                                                   data->in_min[nr]);
937                        }
938                }
939        }
940}
941
942void mtp008_vid(struct i2c_client *client, int operation, int ctl_name,
943                int *nrels_mag, long *results)
944{
945        struct mtp008_data *data;
946
947        data = client->data;
948
949        switch (operation) {
950        case SENSORS_PROC_REAL_INFO:
951                *nrels_mag = 2;
952
953                break;
954        case SENSORS_PROC_REAL_READ:
955                mtp008_update_client(client);
956
957                results[0] = VID_FROM_REG(data->vid);
958
959                *nrels_mag = 1;
960        }
961}
962
963void mtp008_fan_div(struct i2c_client *client, int operation,
964                    int ctl_name, int *nrels_mag, long *results)
965{
966        struct mtp008_data *data;
967        u8 val;
968
969        data = client->data;
970
971        switch (operation) {
972        case SENSORS_PROC_REAL_INFO:
973                *nrels_mag = 0;
974
975                break;
976        case SENSORS_PROC_REAL_READ:
977                mtp008_update_client(client);
978
979                results[0] = DIV_FROM_REG(data->fan_div[0]);
980                results[1] = DIV_FROM_REG(data->fan_div[1]);
981                results[2] = DIV_FROM_REG(data->fan_div[2]);
982
983                *nrels_mag = 3;
984
985                break;
986        case SENSORS_PROC_REAL_WRITE:
987                if (*nrels_mag >= 3) {
988                        data->fan_div[2] = DIV_TO_REG(results[2]);
989                        val = mtp008_read_value(client, MTP008_REG_PIN_CTRL1);
990                        val = (val & 0x3f) | (data->fan_div[2] & 0x03) << 6;
991                        mtp008_write_value(client, MTP008_REG_PIN_CTRL1, val);
992                }
993                if (*nrels_mag >= 1) {
994                        val = mtp008_read_value(client, MTP008_REG_VID_FANDIV);
995                        if (*nrels_mag >= 2) {
996                                data->fan_div[1] = DIV_TO_REG(results[1]);
997                                val = (val & 0x3f) |
998                                      (data->fan_div[1] & 0x03) << 6;
999                        }
1000                        data->fan_div[0] = DIV_TO_REG(results[0]);
1001                        val = (val & 0xcf) | (data->fan_div[0] & 0x03) << 4;
1002                        mtp008_write_value(client, MTP008_REG_VID_FANDIV, val);
1003                }
1004        }
1005}
1006
1007void mtp008_alarms(struct i2c_client *client, int operation, int ctl_name,
1008                   int *nrels_mag, long *results)
1009{
1010        struct mtp008_data *data;
1011
1012        data = client->data;
1013
1014        switch (operation) {
1015        case SENSORS_PROC_REAL_INFO:
1016                *nrels_mag = 0;
1017
1018                break;
1019        case SENSORS_PROC_REAL_READ:
1020                mtp008_update_client(client);
1021
1022                results[0] = ALARMS_FROM_REG(data->alarms);
1023
1024                *nrels_mag = 1;
1025        }
1026}
1027
1028void mtp008_beep(struct i2c_client *client, int operation, int ctl_name,
1029                 int *nrels_mag, long *results)
1030{
1031        struct mtp008_data *data;
1032
1033        data = client->data;
1034
1035        switch (operation) {
1036        case SENSORS_PROC_REAL_INFO:
1037                *nrels_mag = 0;
1038
1039                break;
1040        case SENSORS_PROC_REAL_READ:
1041                mtp008_update_client(client);
1042
1043                results[0] = BEEPS_FROM_REG(data->beeps);
1044
1045                *nrels_mag = 1;
1046
1047                break;
1048        case SENSORS_PROC_REAL_WRITE:
1049                if (*nrels_mag >= 1) {
1050                        data->beeps = BEEPS_TO_REG(results[0]) & 0xdf8f;
1051
1052                        mtp008_write_value(client, MTP008_REG_BEEP_CTRL1,
1053                                           data->beeps & 0xff);
1054                        mtp008_write_value(client, MTP008_REG_BEEP_CTRL2,
1055                                           data->beeps >> 8);
1056                }
1057        }
1058}
1059
1060void mtp008_pwm(struct i2c_client *client, int operation, int ctl_name,
1061                int *nrels_mag, long *results)
1062{
1063        int nr;
1064        struct mtp008_data *data;
1065
1066        nr = ctl_name - MTP008_SYSCTL_PWM1;
1067        data = client->data;
1068
1069        switch (operation) {
1070        case SENSORS_PROC_REAL_INFO:
1071                *nrels_mag = 0;
1072
1073                break;
1074        case SENSORS_PROC_REAL_READ:
1075                mtp008_update_client(client);
1076
1077                results[0] = PWM_FROM_REG(data->pwm[nr]);
1078
1079                *nrels_mag = 1;
1080
1081                break;
1082        case SENSORS_PROC_REAL_WRITE:
1083                if (*nrels_mag >= 1) {
1084                        data->pwm[nr] = PWM_TO_REG(results[0]);
1085                        mtp008_write_value(client, MTP008_REG_PWM_CTRL(nr),
1086                                           data->pwm[nr]);
1087                }
1088        }
1089}
1090
1091void mtp008_sens(struct i2c_client *client, int operation, int ctl_name,
1092                 int *nrels_mag, long *results)
1093{
1094        const char *opts = "";
1095        int nr;
1096        u8 tmp;
1097        struct mtp008_data *data;
1098
1099        nr = ctl_name - MTP008_SYSCTL_SENS1;
1100        data = client->data;
1101
1102        switch (operation) {
1103        case SENSORS_PROC_REAL_INFO:
1104                *nrels_mag = 0;
1105
1106                break;
1107        case SENSORS_PROC_REAL_READ:
1108                results[0] = data->sens[nr];
1109
1110                *nrels_mag = 1;
1111
1112                break;
1113        case SENSORS_PROC_REAL_WRITE:
1114                if (*nrels_mag >= 1) {
1115                        tmp = mtp008_read_value(client, MTP008_REG_PIN_CTRL2);
1116
1117                        switch (nr) {
1118                        case 1: /* VT or PII */
1119                                opts = "2 or 3";
1120
1121                                switch (results[0]) {
1122                                case THERMISTOR:
1123                                        mtp008_write_value(
1124                                                client, MTP008_REG_PIN_CTRL2,
1125                                                tmp & ~MTP008_CFG_VT1_PII
1126                                        );
1127                                        data->sens[nr] = 2;
1128                                        break;
1129                                case PIIDIODE:
1130                                        mtp008_write_value(
1131                                                client, MTP008_REG_PIN_CTRL2,
1132                                                tmp | MTP008_CFG_VT1_PII
1133                                        );
1134                                        data->sens[nr] = 3;
1135                                        break;
1136                                }
1137
1138                                break;
1139                        case 2: /* AIN, VT or PII */
1140                                tmp &= ~MTP008_CFG_VT2_MASK;
1141                                opts = "1, 2 or 3";
1142
1143                                switch (results[0]) {
1144                                case VOLTAGE:
1145                                        mtp008_write_value(
1146                                                client, MTP008_REG_PIN_CTRL2,
1147                                                tmp | MTP008_CFG_VT2_AIN
1148                                        );
1149                                        data->sens[nr] = 1;
1150                                        break;
1151                                case THERMISTOR:
1152                                        mtp008_write_value(
1153                                                client, MTP008_REG_PIN_CTRL2,
1154                                                tmp | MTP008_CFG_VT2_VT
1155                                        );
1156                                        data->sens[nr] = 2;
1157                                        break;
1158                                case PIIDIODE:
1159                                        mtp008_write_value(
1160                                                client, MTP008_REG_PIN_CTRL2,
1161                                                tmp | MTP008_CFG_VT2_PII
1162                                        );
1163                                        data->sens[nr] = 3;
1164                                        break;
1165                                }
1166
1167                                break;
1168                        case 3: /* AIN or VT */
1169                                opts = "1 or 2";
1170
1171                                switch (results[0]) {
1172                                case VOLTAGE:
1173                                        mtp008_write_value(
1174                                                client, MTP008_REG_PIN_CTRL2,
1175                                                tmp & ~MTP008_CFG_VT3_VT
1176                                        );
1177                                        data->sens[nr] = 1;
1178                                        break;
1179                                case THERMISTOR:
1180                                        mtp008_write_value(
1181                                                client, MTP008_REG_PIN_CTRL2,
1182                                                tmp | MTP008_CFG_VT3_VT
1183                                        );
1184                                        data->sens[nr] = 2;
1185                                        break;
1186                                }
1187
1188                                break;
1189                        }
1190
1191                        printk("mtp008.o: Invalid sensor type %ld "
1192                               "for sensor %d; must be %s.\n",
1193                               results[0], nr, opts);
1194                }
1195        }
1196}
1197
1198int __init sensors_mtp008_init(void)
1199{
1200        int res;
1201
1202        printk("mtp008.o version %s (%s)\n", LM_VERSION, LM_DATE);
1203        mtp008_initialized = 0;
1204
1205        if ((res = i2c_add_driver(&mtp008_driver))) {
1206                printk("mtp008.o: Driver registration failed, "
1207                       "module not inserted.\n");
1208                mtp008_cleanup();
1209                return res;
1210        }
1211        mtp008_initialized++;
1212
1213        return 0;
1214}
1215
1216int __init mtp008_cleanup(void)
1217{
1218        int res;
1219
1220        if (mtp008_initialized >= 1) {
1221                if ((res = i2c_del_driver(&mtp008_driver))) {
1222                        printk("mtp008.o: Driver deregistration failed, "
1223                               "module not removed.\n");
1224                        return res;
1225                }
1226                mtp008_initialized--;
1227        }
1228        return 0;
1229}
1230
1231EXPORT_NO_SYMBOLS;
1232
1233#ifdef MODULE
1234
1235MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
1236              "Philip Edelbrock <phil@netroedge.com>, "
1237              "and Kris Van Hees <aedil@alchar.org>");
1238MODULE_DESCRIPTION("MTP008 driver");
1239
1240int init_module(void)
1241{
1242        return sensors_mtp008_init();
1243}
1244
1245int cleanup_module(void)
1246{
1247        return mtp008_cleanup();
1248}
1249
1250#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.