root/lm-sensors/trunk/kernel/chips/adm1021.c @ 1685

Revision 1685, 20.2 KB (checked in by mds, 10 years ago)

cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    adm1021.c - Part of lm_sensors, Linux kernel modules for hardware
3             monitoring
4    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
5    Philip Edelbrock <phil@netroedge.com>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include <linux/version.h>
23#include <linux/module.h>
24#include <linux/slab.h>
25#include <linux/i2c.h>
26#include "sensors.h"
27#include "version.h"
28#include <linux/init.h>
29
30#ifdef MODULE_LICENSE
31MODULE_LICENSE("GPL");
32#endif
33
34#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)) || \
35    (LINUX_VERSION_CODE == KERNEL_VERSION(2,3,0))
36#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
37#endif
38
39#ifndef THIS_MODULE
40#define THIS_MODULE NULL
41#endif
42
43/* Addresses to scan */
44static unsigned short normal_i2c[] = { SENSORS_I2C_END };
45static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b,
46        0x4c, 0x4e, SENSORS_I2C_END
47};
48static unsigned int normal_isa[] = { SENSORS_ISA_END };
49static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
50
51/* Insmod parameters */
52SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
53
54/* adm1021 constants specified below */
55
56/* The adm1021 registers */
57/* Read-only */
58#define ADM1021_REG_TEMP 0x00
59#define ADM1021_REG_REMOTE_TEMP 0x01
60#define ADM1021_REG_STATUS 0x02
61#define ADM1021_REG_MAN_ID 0x0FE        /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
62#define ADM1021_REG_DEV_ID 0x0FF        /* ADM1021 = 0x0X, ADM1023 = 0x3X */
63#define ADM1021_REG_DIE_CODE 0x0FF      /* MAX1617A */
64/* These use different addresses for reading/writing */
65#define ADM1021_REG_CONFIG_R 0x03
66#define ADM1021_REG_CONFIG_W 0x09
67#define ADM1021_REG_CONV_RATE_R 0x04
68#define ADM1021_REG_CONV_RATE_W 0x0A
69/* These are for the ADM1023's additional precision on the remote temp sensor */
70#define ADM1021_REG_REM_TEMP_PREC 0x010
71#define ADM1021_REG_REM_OFFSET 0x011
72#define ADM1021_REG_REM_OFFSET_PREC 0x012
73#define ADM1021_REG_REM_TOS_PREC 0x013
74#define ADM1021_REG_REM_THYST_PREC 0x014
75/* limits */
76#define ADM1021_REG_TOS_R 0x05
77#define ADM1021_REG_TOS_W 0x0B
78#define ADM1021_REG_REMOTE_TOS_R 0x07
79#define ADM1021_REG_REMOTE_TOS_W 0x0D
80#define ADM1021_REG_THYST_R 0x06
81#define ADM1021_REG_THYST_W 0x0C
82#define ADM1021_REG_REMOTE_THYST_R 0x08
83#define ADM1021_REG_REMOTE_THYST_W 0x0E
84/* write-only */
85#define ADM1021_REG_ONESHOT 0x0F
86
87
88/* Conversions. Rounding and limit checking is only done on the TO_REG
89   variants. Note that you should be a bit careful with which arguments
90   these macros are called: arguments may be evaluated more than once.
91   Fixing this is just not worth it. */
92/* Conversions  note: 1021 uses normal integer signed-byte format*/
93#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
94#define TEMP_TO_REG(val)   (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
95
96/* Initial values */
97
98/* Note: Eventhough I left the low and high limits named os and hyst,
99they don't quite work like a thermostat the way the LM75 does.  I.e.,
100a lower temp than THYST actuall triggers an alarm instead of
101clearing it.  Weird, ey?   --Phil  */
102#define adm1021_INIT_TOS 60
103#define adm1021_INIT_THYST 20
104#define adm1021_INIT_REMOTE_TOS 60
105#define adm1021_INIT_REMOTE_THYST 20
106
107/* Each client has this additional data */
108struct adm1021_data {
109        int sysctl_id;
110        enum chips type;
111
112        struct semaphore update_lock;
113        char valid;             /* !=0 if following fields are valid */
114        unsigned long last_updated;     /* In jiffies */
115
116        u8 temp, temp_os, temp_hyst;    /* Register values */
117        u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms, die_code;
118        /* Special values for ADM1023 only */
119        u8 remote_temp_prec, remote_temp_os_prec, remote_temp_hyst_prec, 
120           remote_temp_offset, remote_temp_offset_prec;
121};
122
123#ifdef MODULE
124extern int init_module(void);
125extern int cleanup_module(void);
126#endif                          /* MODULE */
127
128#ifdef MODULE
129static
130#else
131extern
132#endif
133int __init sensors_adm1021_init(void);
134static int __init adm1021_cleanup(void);
135static int adm1021_attach_adapter(struct i2c_adapter *adapter);
136static int adm1021_detect(struct i2c_adapter *adapter, int address,
137                          unsigned short flags, int kind);
138static void adm1021_init_client(struct i2c_client *client);
139static int adm1021_detach_client(struct i2c_client *client);
140static int adm1021_command(struct i2c_client *client, unsigned int cmd,
141                           void *arg);
142static void adm1021_inc_use(struct i2c_client *client);
143static void adm1021_dec_use(struct i2c_client *client);
144static int adm1021_read_value(struct i2c_client *client, u8 reg);
145static int adm1021_rd_good(u8 *val, struct i2c_client *client, u8 reg);
146static int adm1021_write_value(struct i2c_client *client, u8 reg,
147                               u16 value);
148static void adm1021_temp(struct i2c_client *client, int operation,
149                         int ctl_name, int *nrels_mag, long *results);
150static void adm1021_remote_temp(struct i2c_client *client, int operation,
151                                int ctl_name, int *nrels_mag,
152                                long *results);
153static void adm1021_alarms(struct i2c_client *client, int operation,
154                           int ctl_name, int *nrels_mag, long *results);
155static void adm1021_die_code(struct i2c_client *client, int operation,
156                             int ctl_name, int *nrels_mag, long *results);
157static void adm1021_update_client(struct i2c_client *client);
158
159/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
160static int read_only = 0;
161
162
163/* This is the driver that will be inserted */
164static struct i2c_driver adm1021_driver = {
165        /* name */ "ADM1021, MAX1617 sensor driver",
166        /* id */ I2C_DRIVERID_ADM1021,
167        /* flags */ I2C_DF_NOTIFY,
168        /* attach_adapter */ &adm1021_attach_adapter,
169        /* detach_client */ &adm1021_detach_client,
170        /* command */ &adm1021_command,
171        /* inc_use */ &adm1021_inc_use,
172        /* dec_use */ &adm1021_dec_use
173};
174
175/* These files are created for each detected adm1021. This is just a template;
176   though at first sight, you might think we could use a statically
177   allocated list, we need some way to get back to the parent - which
178   is done through one of the 'extra' fields which are initialized
179   when a new copy is allocated. */
180static ctl_table adm1021_dir_table_template[] = {
181        {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
182         &i2c_sysctl_real, NULL, &adm1021_temp},
183        {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
184         &i2c_sysctl_real, NULL, &adm1021_remote_temp},
185        {ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &i2c_proc_real,
186         &i2c_sysctl_real, NULL, &adm1021_die_code},
187        {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
188         &i2c_sysctl_real, NULL, &adm1021_alarms},
189        {0}
190};
191
192static ctl_table adm1021_max_dir_table_template[] = {
193        {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
194         &i2c_sysctl_real, NULL, &adm1021_temp},
195        {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
196         &i2c_sysctl_real, NULL, &adm1021_remote_temp},
197        {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
198         &i2c_sysctl_real, NULL, &adm1021_alarms},
199        {0}
200};
201
202/* Used by init/cleanup */
203static int __initdata adm1021_initialized = 0;
204
205/* I choose here for semi-static allocation. Complete dynamic
206   allocation could also be used; the code needed for this would probably
207   take more memory than the datastructure takes now. */
208static int adm1021_id = 0;
209
210int adm1021_attach_adapter(struct i2c_adapter *adapter)
211{
212        return i2c_detect(adapter, &addr_data, adm1021_detect);
213}
214
215static int adm1021_detect(struct i2c_adapter *adapter, int address,
216                          unsigned short flags, int kind)
217{
218        int i;
219        struct i2c_client *new_client;
220        struct adm1021_data *data;
221        int err = 0;
222        const char *type_name = "";
223        const char *client_name = "";
224
225        /* Make sure we aren't probing the ISA bus!! This is just a safety check
226           at this moment; i2c_detect really won't call us. */
227#ifdef DEBUG
228        if (i2c_is_isa_adapter(adapter)) {
229                printk
230                    ("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
231                return 0;
232        }
233#endif
234
235        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
236                goto ERROR0;
237
238        /* OK. For now, we presume we have a valid client. We now create the
239           client structure, even though we cannot fill it completely yet.
240           But it allows us to access adm1021_{read,write}_value. */
241
242        if (!(new_client = kmalloc(sizeof(struct i2c_client) +
243                                   sizeof(struct adm1021_data),
244                                   GFP_KERNEL))) {
245                err = -ENOMEM;
246                goto ERROR0;
247        }
248
249        data = (struct adm1021_data *) (new_client + 1);
250        new_client->addr = address;
251        new_client->data = data;
252        new_client->adapter = adapter;
253        new_client->driver = &adm1021_driver;
254        new_client->flags = 0;
255
256        /* Now, we do the remaining detection. */
257
258        if (kind < 0) {
259                if (
260                    (adm1021_read_value(new_client, ADM1021_REG_STATUS) &
261                     0x03) != 0x00)
262                        goto ERROR1;
263        }
264
265        /* Determine the chip type. */
266
267        if (kind <= 0) {
268                i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
269                if (i == 0x41)
270                  if ((adm1021_read_value (new_client, ADM1021_REG_DEV_ID) & 0x0F0) == 0x030)
271                        kind = adm1023;
272                  else
273                        kind = adm1021;
274                else if (i == 0x49)
275                        kind = thmc10;
276                else if (i == 0x23)
277                        kind = gl523sm;
278                else if ((i == 0x4d) &&
279                         (adm1021_read_value
280                          (new_client, ADM1021_REG_DEV_ID) == 0x01))
281                        kind = max1617a;
282                /* LM84 Mfr ID in a different place */
283                else
284                    if (adm1021_read_value
285                        (new_client, ADM1021_REG_CONV_RATE_R) == 0x00)
286                        kind = lm84;
287                else if (i == 0x54)
288                        kind = mc1066;
289                else
290                        kind = max1617;
291        }
292
293        if (kind == max1617) {
294                type_name = "max1617";
295                client_name = "MAX1617 chip";
296        } else if (kind == max1617a) {
297                type_name = "max1617a";
298                client_name = "MAX1617A chip";
299        } else if (kind == adm1021) {
300                type_name = "adm1021";
301                client_name = "ADM1021 chip";
302        } else if (kind == adm1023) {
303                type_name = "adm1023";
304                client_name = "ADM1023 chip";
305        } else if (kind == thmc10) {
306                type_name = "thmc10";
307                client_name = "THMC10 chip";
308        } else if (kind == lm84) {
309                type_name = "lm84";
310                client_name = "LM84 chip";
311        } else if (kind == gl523sm) {
312                type_name = "gl523sm";
313                client_name = "GL523SM chip";
314        } else if (kind == mc1066) {
315                type_name = "mc1066";
316                client_name = "MC1066 chip";
317        } else {
318#ifdef DEBUG
319                printk("adm1021.o: Internal error: unknown kind (%d)?!?",
320                       kind);
321#endif
322                goto ERROR1;
323        }
324
325        /* Fill in the remaining client fields and put it into the global list */
326        strcpy(new_client->name, client_name);
327        data->type = kind;
328
329        new_client->id = adm1021_id++;
330        data->valid = 0;
331        init_MUTEX(&data->update_lock);
332
333        /* Tell the I2C layer a new client has arrived */
334        if ((err = i2c_attach_client(new_client)))
335                goto ERROR3;
336
337        /* Register a new directory entry with module sensors */
338        if ((i = i2c_register_entry(new_client,
339                                        type_name,
340                                        data->type ==
341                                        adm1021 ?
342                                        adm1021_dir_table_template :
343                                        adm1021_max_dir_table_template,
344                                        THIS_MODULE)) < 0) {
345                err = i;
346                goto ERROR4;
347        }
348        data->sysctl_id = i;
349
350        /* Initialize the ADM1021 chip */
351        adm1021_init_client(new_client);
352        return 0;
353
354/* OK, this is not exactly good programming practice, usually. But it is
355   very code-efficient in this case. */
356
357      ERROR4:
358        i2c_detach_client(new_client);
359      ERROR3:
360      ERROR1:
361        kfree(new_client);
362      ERROR0:
363        return err;
364}
365
366void adm1021_init_client(struct i2c_client *client)
367{
368        /* Initialize the adm1021 chip */
369        adm1021_write_value(client, ADM1021_REG_TOS_W,
370                            TEMP_TO_REG(adm1021_INIT_TOS));
371        adm1021_write_value(client, ADM1021_REG_THYST_W,
372                            TEMP_TO_REG(adm1021_INIT_THYST));
373        adm1021_write_value(client, ADM1021_REG_REMOTE_TOS_W,
374                            TEMP_TO_REG(adm1021_INIT_REMOTE_TOS));
375        adm1021_write_value(client, ADM1021_REG_REMOTE_THYST_W,
376                            TEMP_TO_REG(adm1021_INIT_REMOTE_THYST));
377        /* Enable ADC and disable suspend mode */
378        adm1021_write_value(client, ADM1021_REG_CONFIG_W, 0);
379        /* Set Conversion rate to 1/sec (this can be tinkered with) */
380        adm1021_write_value(client, ADM1021_REG_CONV_RATE_W, 0x04);
381}
382
383int adm1021_detach_client(struct i2c_client *client)
384{
385
386        int err;
387
388        i2c_deregister_entry(((struct adm1021_data *) (client->data))->
389                                 sysctl_id);
390
391        if ((err = i2c_detach_client(client))) {
392                printk
393                    ("adm1021.o: Client deregistration failed, client not detached.\n");
394                return err;
395        }
396
397        kfree(client);
398
399        return 0;
400
401}
402
403
404/* No commands defined yet */
405int adm1021_command(struct i2c_client *client, unsigned int cmd, void *arg)
406{
407        return 0;
408}
409
410void adm1021_inc_use(struct i2c_client *client)
411{
412#ifdef MODULE
413        MOD_INC_USE_COUNT;
414#endif
415}
416
417void adm1021_dec_use(struct i2c_client *client)
418{
419#ifdef MODULE
420        MOD_DEC_USE_COUNT;
421#endif
422}
423
424/* All registers are byte-sized */
425int adm1021_read_value(struct i2c_client *client, u8 reg)
426{
427        return i2c_smbus_read_byte_data(client, reg);
428}
429
430/* only update value if read succeeded */
431int adm1021_rd_good(u8 *val, struct i2c_client *client, u8 reg)
432{
433        int i;
434        i = i2c_smbus_read_byte_data(client, reg);
435        if(i < 0)
436                return i;
437        *val = i;
438        return 0;
439}
440
441int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value)
442{
443        if (read_only > 0)
444                return 0;
445
446        return i2c_smbus_write_byte_data(client, reg, value);
447}
448
449void adm1021_update_client(struct i2c_client *client)
450{
451        struct adm1021_data *data = client->data;
452
453        down(&data->update_lock);
454
455        if ((jiffies - data->last_updated > HZ + HZ / 2) ||
456            (jiffies < data->last_updated) || !data->valid) {
457
458#ifdef DEBUG
459                printk("Starting adm1021 update\n");
460#endif
461
462                adm1021_rd_good(&(data->temp), client, ADM1021_REG_TEMP);
463                adm1021_rd_good(&(data->temp_os), client, ADM1021_REG_TOS_R);
464                adm1021_rd_good(&(data->temp_hyst), client,
465                                ADM1021_REG_THYST_R);
466                adm1021_rd_good(&(data->remote_temp), client,
467                                ADM1021_REG_REMOTE_TEMP);
468                adm1021_rd_good(&(data->remote_temp_os), client,
469                                ADM1021_REG_REMOTE_TOS_R);
470                adm1021_rd_good(&(data->remote_temp_hyst), client,
471                                   ADM1021_REG_REMOTE_THYST_R);
472                if(!adm1021_rd_good(&(data->alarms), client,
473                                       ADM1021_REG_STATUS))
474                        data->alarms &= 0xec;
475                if (data->type == adm1021)
476                        adm1021_rd_good(&(data->die_code), client,
477                                        ADM1021_REG_DIE_CODE);
478                if (data->type == adm1023) {
479                        adm1021_rd_good(&(data->remote_temp_prec), client,
480                                        ADM1021_REG_REM_TEMP_PREC);
481                        adm1021_rd_good(&(data->remote_temp_os_prec), client,
482                                        ADM1021_REG_REM_TOS_PREC);
483                        adm1021_rd_good(&(data->remote_temp_hyst_prec), client,
484                                        ADM1021_REG_REM_THYST_PREC);
485                        adm1021_rd_good(&(data->remote_temp_offset), client,
486                                           ADM1021_REG_REM_OFFSET);
487                        adm1021_rd_good(&(data->remote_temp_offset_prec),
488                                           client, ADM1021_REG_REM_OFFSET_PREC);
489                }
490                data->last_updated = jiffies;
491                data->valid = 1;
492        }
493
494        up(&data->update_lock);
495}
496
497
498void adm1021_temp(struct i2c_client *client, int operation, int ctl_name,
499                  int *nrels_mag, long *results)
500{
501        struct adm1021_data *data = client->data;
502        if (operation == SENSORS_PROC_REAL_INFO)
503                *nrels_mag = 0;
504        else if (operation == SENSORS_PROC_REAL_READ) {
505                adm1021_update_client(client);
506                results[0] = TEMP_FROM_REG(data->temp_os);
507                results[1] = TEMP_FROM_REG(data->temp_hyst);
508                results[2] = TEMP_FROM_REG(data->temp);
509                *nrels_mag = 3;
510        } else if (operation == SENSORS_PROC_REAL_WRITE) {
511                if (*nrels_mag >= 1) {
512                        data->temp_os = TEMP_TO_REG(results[0]);
513                        adm1021_write_value(client, ADM1021_REG_TOS_W,
514                                            data->temp_os);
515                }
516                if (*nrels_mag >= 2) {
517                        data->temp_hyst = TEMP_TO_REG(results[1]);
518                        adm1021_write_value(client, ADM1021_REG_THYST_W,
519                                            data->temp_hyst);
520                }
521        }
522}
523
524void adm1021_remote_temp(struct i2c_client *client, int operation,
525                         int ctl_name, int *nrels_mag, long *results)
526{
527int prec=0;
528        struct adm1021_data *data = client->data;
529        if (operation == SENSORS_PROC_REAL_INFO)
530                if (data->type == adm1023) { *nrels_mag = 3; }
531                 else { *nrels_mag = 0; }
532        else if (operation == SENSORS_PROC_REAL_READ) {
533                adm1021_update_client(client);
534                results[0] = TEMP_FROM_REG(data->remote_temp_os);
535                results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
536                results[2] = TEMP_FROM_REG(data->remote_temp);
537                if (data->type == adm1023) {
538                  results[0]=results[0]*1000 + 
539                   ((data->remote_temp_os_prec >> 5) * 125);
540                  results[1]=results[1]*1000 + 
541                   ((data->remote_temp_hyst_prec >> 5) * 125);
542                  results[2]=(TEMP_FROM_REG(data->remote_temp_offset)*1000) + 
543                   ((data->remote_temp_offset_prec >> 5) * 125);
544                  results[3]=TEMP_FROM_REG(data->remote_temp)*1000 + 
545                   ((data->remote_temp_prec >> 5) * 125);
546                  *nrels_mag = 4;
547                } else {
548                  *nrels_mag = 3;
549                }
550        } else if (operation == SENSORS_PROC_REAL_WRITE) {
551                if (*nrels_mag >= 1) {
552                        if (data->type == adm1023) {
553                          prec=((results[0]-((results[0]/1000)*1000))/125)<<5;
554                          adm1021_write_value(client,
555                                            ADM1021_REG_REM_TOS_PREC,
556                                            prec);
557                          results[0]=results[0]/1000;
558                          data->remote_temp_os_prec=prec;
559                        }
560                        data->remote_temp_os = TEMP_TO_REG(results[0]);
561                        adm1021_write_value(client,
562                                            ADM1021_REG_REMOTE_TOS_W,
563                                            data->remote_temp_os);
564                }
565                if (*nrels_mag >= 2) {
566                        if (data->type == adm1023) {
567                          prec=((results[1]-((results[1]/1000)*1000))/125)<<5;
568                          adm1021_write_value(client,
569                                            ADM1021_REG_REM_THYST_PREC,
570                                            prec);
571                          results[1]=results[1]/1000;
572                          data->remote_temp_hyst_prec=prec;
573                        }
574                        data->remote_temp_hyst = TEMP_TO_REG(results[1]);
575                        adm1021_write_value(client,
576                                            ADM1021_REG_REMOTE_THYST_W,
577                                            data->remote_temp_hyst);
578                }
579                if (*nrels_mag >= 3) {
580                        if (data->type == adm1023) {
581                          prec=((results[2]-((results[2]/1000)*1000))/125)<<5;
582                          adm1021_write_value(client,
583                                            ADM1021_REG_REM_OFFSET_PREC,
584                                            prec);
585                          results[2]=results[2]/1000;
586                          data->remote_temp_offset_prec=prec;
587                          data->remote_temp_offset=results[2];
588                          adm1021_write_value(client,
589                                            ADM1021_REG_REM_OFFSET,
590                                            data->remote_temp_offset);
591                        }
592                }
593        }
594}
595
596void adm1021_die_code(struct i2c_client *client, int operation,
597                      int ctl_name, int *nrels_mag, long *results)
598{
599        struct adm1021_data *data = client->data;
600        if (operation == SENSORS_PROC_REAL_INFO)
601                *nrels_mag = 0;
602        else if (operation == SENSORS_PROC_REAL_READ) {
603                adm1021_update_client(client);
604                results[0] = data->die_code;
605                *nrels_mag = 1;
606        } else if (operation == SENSORS_PROC_REAL_WRITE) {
607                /* Can't write to it */
608        }
609}
610
611void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name,
612                    int *nrels_mag, long *results)
613{
614        struct adm1021_data *data = client->data;
615        if (operation == SENSORS_PROC_REAL_INFO)
616                *nrels_mag = 0;
617        else if (operation == SENSORS_PROC_REAL_READ) {
618                adm1021_update_client(client);
619                results[0] = data->alarms;
620                *nrels_mag = 1;
621        } else if (operation == SENSORS_PROC_REAL_WRITE) {
622                /* Can't write to it */
623        }
624}
625
626int __init sensors_adm1021_init(void)
627{
628        int res;
629
630        printk("adm1021.o version %s (%s)\n", LM_VERSION, LM_DATE);
631        adm1021_initialized = 0;
632        if ((res = i2c_add_driver(&adm1021_driver))) {
633                printk
634                    ("adm1021.o: Driver registration failed, module not inserted.\n");
635                adm1021_cleanup();
636                return res;
637        }
638        adm1021_initialized++;
639        return 0;
640}
641
642int __init adm1021_cleanup(void)
643{
644        int res;
645
646        if (adm1021_initialized >= 1) {
647                if ((res = i2c_del_driver(&adm1021_driver))) {
648                        printk
649                            ("adm1021.o: Driver deregistration failed, module not removed.\n");
650                        return res;
651                }
652                adm1021_initialized--;
653        }
654
655        return 0;
656}
657
658EXPORT_NO_SYMBOLS;
659
660#ifdef MODULE
661
662MODULE_AUTHOR
663    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
664MODULE_DESCRIPTION("adm1021 driver");
665
666MODULE_PARM(read_only, "i");
667MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
668
669int init_module(void)
670{
671        return sensors_adm1021_init();
672}
673
674int cleanup_module(void)
675{
676        return adm1021_cleanup();
677}
678
679#endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.