root/lm-sensors/trunk/kernel/chips/adm1025.c @ 2784

Revision 2784, 19.0 KB (checked in by khali, 8 years ago)

Restore controlling_mod argument to i2c_register_entry(). This
is needed to properly lock chip drivers in memory while anyone uses their
/proc entries. This also brings back compatibility with the 2.4 Linux
kernel.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    adm1025.c - Part of lm_sensors, Linux kernel modules for hardware
3               monitoring
4    Copyright (c) 2000 Chen-Yuan Wu <gwu@esoft.com>
5    Copyright (c) 2003-2004 Jean Delvare <khali@linux-fr.org>
6
7    Based on the adm9240 driver.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24/* Supports the Analog Devices ADM1025 and the Philips NE1619.
25   See doc/chips/adm1025 for details */
26
27#include <linux/module.h>
28#include <linux/slab.h>
29#include <linux/i2c.h>
30#include <linux/i2c-proc.h>
31#include <linux/init.h>
32#include "version.h"
33#include "sensors_vid.h"
34
35MODULE_LICENSE("GPL");
36
37/* Addresses to scan */
38static unsigned short normal_i2c[] = { SENSORS_I2C_END };
39static unsigned short normal_i2c_range[] = { 0x2c, 0x2e, SENSORS_I2C_END };
40static unsigned int normal_isa[] = { SENSORS_ISA_END };
41static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
42
43/* Insmod parameters */
44SENSORS_INSMOD_2(adm1025, ne1619);
45
46/* Many ADM1025 constants specified below */
47
48
49/* The ADM1025 registers */
50
51/* These are all read-only */
52#define ADM1025_REG_2_5V        0x20 /* not used directly, see   */
53#define ADM1025_REG_VCCP1       0x21 /* ADM1025_REG_IN(nr) below */
54#define ADM1025_REG_3_3V        0x22
55#define ADM1025_REG_5V          0x23
56#define ADM1025_REG_12V         0x24
57#define ADM1025_REG_VCC         0x25
58
59#define ADM1025_REG_RTEMP       0x26 /* not used directly, see     */
60#define ADM1025_REG_LTEMP       0x27 /* ADM1025_REG_TEMP(nr) below */
61
62#define ADM1025_REG_COMPANY_ID  0x3E /* 0x41 for Analog Devices,
63                                        0xA1 for Philips */
64#define ADM1025_REG_DIE_REV     0x3F /* 0x20-0x2F for ADM1025 and compatible */
65
66#define ADM1025_REG_STATUS1     0x41
67#define ADM1025_REG_STATUS2     0x42
68
69#define ADM1025_REG_VID         0x47
70#define ADM1025_REG_VID4        0x49 /* actually R/W
71                                        but we don't write to it */
72
73/* These are read/write */
74#define ADM1025_REG_2_5V_HIGH   0x2B /* not used directly, see       */
75#define ADM1025_REG_2_5V_LOW    0x2C /* ADM1025_REG_IN_MAX(nr) and   */
76#define ADM1025_REG_VCCP1_HIGH  0x2D /* ADM1025_REG_IN_MIN(nr) below */
77#define ADM1025_REG_VCCP1_LOW   0x2E
78#define ADM1025_REG_3_3V_HIGH   0x2F
79#define ADM1025_REG_3_3V_LOW    0x30
80#define ADM1025_REG_5V_HIGH     0x31
81#define ADM1025_REG_5V_LOW      0x32
82#define ADM1025_REG_12V_HIGH    0x33
83#define ADM1025_REG_12V_LOW     0x34
84#define ADM1025_REG_VCC_HIGH    0x35
85#define ADM1025_REG_VCC_LOW     0x36
86
87#define ADM1025_REG_RTEMP_HIGH  0x37 /* not used directly, see         */
88#define ADM1025_REG_RTEMP_LOW   0x38 /* ADM1025_REG_TEMP_MAX(nr) and   */
89#define ADM1025_REG_LTEMP_HIGH  0x39 /* ADM1025_REG_TEMP_MIN(nr) below */
90#define ADM1025_REG_LTEMP_LOW   0x3A
91
92#define ADM1025_REG_CONFIG      0x40
93
94/* Useful macros */
95#define ADM1025_REG_IN(nr)        (ADM1025_REG_2_5V + (nr))
96#define ADM1025_REG_IN_MAX(nr)    (ADM1025_REG_2_5V_HIGH + (nr) * 2)
97#define ADM1025_REG_IN_MIN(nr)    (ADM1025_REG_2_5V_LOW + (nr) * 2)
98#define ADM1025_REG_TEMP(nr)      (ADM1025_REG_RTEMP + (nr))
99#define ADM1025_REG_TEMP_HIGH(nr) (ADM1025_REG_RTEMP_HIGH + (nr) * 2)
100#define ADM1025_REG_TEMP_LOW(nr)  (ADM1025_REG_RTEMP_LOW + (nr) * 2)
101
102/* Conversions. Rounding and limit checking is only done on the TO_REG
103   variants. Note that you should be a bit careful with which arguments
104   these macros are called: arguments may be evaluated more than once.
105   Fixing this is just not worth it. */
106#define IN_TO_REG(val) SENSORS_LIMIT(val, 0, 255)
107#define IN_FROM_REG(val) (val)
108
109#define TEMP_FROM_REG(val) (((val)>=0x80?(val)-0x100:(val))*10)
110#define TEMP_TO_REG(val) SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
111                                                 ((val)+5)/10),-128,127)
112
113#define ALARMS_FROM_REG(val) (val)
114
115/* For each registered ADM1025, we need to keep some data in memory. That
116   data is pointed to by adm1025_list[NR]->data. The structure itself is
117   dynamically allocated, at the same time when a new adm1025 client is
118   allocated. */
119struct adm1025_data {
120        struct i2c_client client;
121        int sysctl_id;
122        enum chips type;
123
124        struct semaphore update_lock;
125        char valid;                   /* !=0 if following fields are valid */
126        unsigned long last_updated;   /* In jiffies */
127
128        u8 in[6];               /* Register value */
129        u8 in_max[6];           /* Register value */
130        u8 in_min[6];           /* Register value */
131        u8 temp[2];             /* Register value */
132        u8 temp_high[2];        /* Register value */
133        u8 temp_low[2];         /* Register value */
134        u16 alarms;             /* Register encoding, combined */
135        u8 vid;                 /* Register value combined */
136        u8 vrm;
137};
138
139
140static int adm1025_attach_adapter(struct i2c_adapter *adapter);
141static int adm1025_detect(struct i2c_adapter *adapter, int address,
142                          unsigned short flags, int kind);
143static int adm1025_detach_client(struct i2c_client *client);
144static void adm1025_update_client(struct i2c_client *client);
145static void adm1025_init_client(struct i2c_client *client);
146
147
148static void adm1025_in(struct i2c_client *client, int operation,
149                       int ctl_name, int *nrels_mag, long *results);
150static void adm1025_temp(struct i2c_client *client, int operation,
151                         int ctl_name, int *nrels_mag, long *results);
152static void adm1025_alarms(struct i2c_client *client, int operation,
153                           int ctl_name, int *nrels_mag, long *results);
154static void adm1025_vid(struct i2c_client *client, int operation,
155                        int ctl_name, int *nrels_mag, long *results);
156static void adm1025_vrm(struct i2c_client *client, int operation,
157                        int ctl_name, int *nrels_mag, long *results);
158
159static int adm1025_id = 0;
160
161static struct i2c_driver adm1025_driver = {
162        .name           = "ADM1025 sensor driver",
163        .id             = I2C_DRIVERID_ADM1025,
164        .flags          = I2C_DF_NOTIFY,
165        .attach_adapter = adm1025_attach_adapter,
166        .detach_client  = adm1025_detach_client,
167};
168
169/* The /proc/sys entries */
170/* -- SENSORS SYSCTL START -- */
171
172#define ADM1025_SYSCTL_IN0     1000 /* Volts * 100 */
173#define ADM1025_SYSCTL_IN1     1001
174#define ADM1025_SYSCTL_IN2     1002
175#define ADM1025_SYSCTL_IN3     1003
176#define ADM1025_SYSCTL_IN4     1004
177#define ADM1025_SYSCTL_IN5     1005
178
179#define ADM1025_SYSCTL_RTEMP   1250 /* Degrees Celcius * 10 */
180#define ADM1025_SYSCTL_TEMP    1251
181
182#define ADM1025_SYSCTL_ALARMS  2001 /* bitvector */
183#define ADM1025_SYSCTL_VID     2003 /* Volts * 1000 */
184#define ADM1025_SYSCTL_VRM     2004
185
186#define ADM1025_ALARM_IN0     0x0001
187#define ADM1025_ALARM_IN1     0x0002
188#define ADM1025_ALARM_IN2     0x0004
189#define ADM1025_ALARM_IN3     0x0008
190#define ADM1025_ALARM_IN4     0x0100
191#define ADM1025_ALARM_IN5     0x0200
192#define ADM1025_ALARM_RTEMP   0x0020
193#define ADM1025_ALARM_TEMP    0x0010
194#define ADM1025_ALARM_RFAULT  0x4000
195
196/* -- SENSORS SYSCTL END -- */
197
198/* These files are created for each detected ADM1025. This is just a template;
199   though at first sight, you might think we could use a statically
200   allocated list, we need some way to get back to the parent - which
201   is done through one of the 'extra' fields which are initialized
202   when a new copy is allocated. */
203static ctl_table adm1025_dir_table_template[] = {
204        {ADM1025_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
205         &i2c_sysctl_real, NULL, &adm1025_in},
206        {ADM1025_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
207         &i2c_sysctl_real, NULL, &adm1025_in},
208        {ADM1025_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
209         &i2c_sysctl_real, NULL, &adm1025_in},
210        {ADM1025_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
211         &i2c_sysctl_real, NULL, &adm1025_in},
212        {ADM1025_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
213         &i2c_sysctl_real, NULL, &adm1025_in},
214        {ADM1025_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
215         &i2c_sysctl_real, NULL, &adm1025_in},
216        {ADM1025_SYSCTL_RTEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
217         &i2c_sysctl_real, NULL, &adm1025_temp},
218        {ADM1025_SYSCTL_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
219         &i2c_sysctl_real, NULL, &adm1025_temp},
220        {ADM1025_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
221         &i2c_sysctl_real, NULL, &adm1025_alarms},
222        {ADM1025_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
223         &i2c_sysctl_real, NULL, &adm1025_vid},
224        {ADM1025_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
225         &i2c_sysctl_real, NULL, &adm1025_vrm},
226        {0}
227};
228
229static int adm1025_attach_adapter(struct i2c_adapter *adapter)
230{
231        return i2c_detect(adapter, &addr_data, adm1025_detect);
232}
233
234static int adm1025_detect(struct i2c_adapter *adapter, int address,
235                          unsigned short flags, int kind)
236{
237        int i;
238        struct i2c_client *new_client;
239        struct adm1025_data *data;
240        int err = 0;
241        const char *type_name = "";
242        const char *client_name = "";
243
244        /* Make sure we aren't probing the ISA bus!! This is just a safety check
245           at this moment; i2c_detect really won't call us. */
246#ifdef DEBUG
247        if (i2c_is_isa_adapter(adapter)) {
248                printk
249                    ("adm1025.o: adm1025_detect called for an ISA bus adapter?!?\n");
250                return 0;
251        }
252#endif
253
254        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
255                goto ERROR0;
256
257        /* OK. For now, we presume we have a valid client. We now create the
258           client structure, even though we cannot fill it completely yet.
259           But it allows us to access adm1025_{read,write}_value. */
260
261        if (!(data = kmalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
262                err = -ENOMEM;
263                goto ERROR0;
264        }
265
266        new_client = &data->client;
267        new_client->addr = address;
268        new_client->data = data;
269        new_client->adapter = adapter;
270        new_client->driver = &adm1025_driver;
271        new_client->flags = 0;
272
273        /* Now, we do the remaining detection. */
274
275        if (kind < 0) {
276                if ((i2c_smbus_read_byte_data(new_client,
277                     ADM1025_REG_CONFIG) & 0x80) != 0x00
278                 || (i2c_smbus_read_byte_data(new_client,
279                     ADM1025_REG_STATUS1) & 0xC0) != 0x00
280                 || (i2c_smbus_read_byte_data(new_client,
281                     ADM1025_REG_STATUS2) & 0xBC) != 0x00)
282                        goto ERROR1;
283        }
284
285        /* Determine the chip type. */
286        if (kind <= 0) {
287                u8 man_id, chip_id;
288               
289                man_id = i2c_smbus_read_byte_data(new_client,
290                         ADM1025_REG_COMPANY_ID);
291                chip_id = i2c_smbus_read_byte_data(new_client,
292                          ADM1025_REG_DIE_REV);
293               
294                if (man_id == 0x41) { /* Analog Devices */
295                        if ((chip_id & 0xF0) == 0x20) /* ADM1025 */
296                                kind = adm1025;
297                } else if (man_id == 0xA1) { /* Philips */
298                        if (address != 0x2E
299                         && (chip_id & 0xF0) == 0x20) /* NE1619 */
300                                kind = ne1619;
301                }
302        }
303
304        if (kind <= 0) { /* Identification failed */
305                printk("adm1025.o: Unsupported chip.\n");
306                goto ERROR1;
307        }
308
309        if (kind == adm1025) {
310                type_name = "adm1025";
311                client_name = "ADM1025 chip";
312        } else if (kind == ne1619) {
313                type_name = "ne1619";
314                client_name = "NE1619 chip";           
315        } else {
316#ifdef DEBUG
317                printk("adm1025.o: Internal error: unknown kind (%d)?!?",
318                       kind);
319#endif
320                goto ERROR1;
321        }
322
323        /* Fill in the remaining client fields and put it into the global list */
324        strcpy(new_client->name, client_name);
325        data->type = kind;
326
327        new_client->id = adm1025_id++;
328        data->valid = 0;
329        init_MUTEX(&data->update_lock);
330
331        /* Tell the I2C layer a new client has arrived */
332        if ((err = i2c_attach_client(new_client)))
333                goto ERROR3;
334
335        /* Register a new directory entry with module sensors */
336        if ((i = i2c_register_entry(new_client,
337                                        type_name,
338                                        adm1025_dir_table_template,
339                                        THIS_MODULE)) < 0) {
340                err = i;
341                goto ERROR4;
342        }
343        data->sysctl_id = i;
344
345        /* Initialize the ADM1025 chip */
346        adm1025_init_client(new_client);
347        return 0;
348
349/* OK, this is not exactly good programming practice, usually. But it is
350   very code-efficient in this case. */
351
352      ERROR4:
353        i2c_detach_client(new_client);
354      ERROR3:
355      ERROR1:
356        kfree(data);
357      ERROR0:
358        return err;
359}
360
361static int adm1025_detach_client(struct i2c_client *client)
362{
363        int err;
364
365        i2c_deregister_entry(((struct adm1025_data *) (client->data))->
366                                 sysctl_id);
367
368        if ((err = i2c_detach_client(client))) {
369                printk
370                    ("adm1025.o: Client deregistration failed, client not detached.\n");
371                return err;
372        }
373
374        kfree(client->data);
375
376        return 0;
377}
378
379/* Called when we have found a new ADM1025. */
380static void adm1025_init_client(struct i2c_client *client)
381{
382        struct adm1025_data *data = client->data;
383        u8 reg;
384        int i;
385
386        data->vrm = 82;
387
388        /* Set high limits
389           Usually we avoid setting limits on driver init, but it happens
390           that the ADM1025 comes with stupid default limits (all registers
391           set to 0). In case the chip has not gone through any limit
392           setting yet, we better set the high limits to the max so that
393           no alarm triggers. */
394        for (i=0; i<6; i++) {
395                reg = i2c_smbus_read_byte_data(client,
396                                               ADM1025_REG_IN_MAX(i));
397                if (reg == 0)
398                        i2c_smbus_write_byte_data(client,
399                                                  ADM1025_REG_IN_MAX(i),
400                                                  0xFF);
401        }
402        for (i=0; i<2; i++) {
403                reg = i2c_smbus_read_byte_data(client,
404                                               ADM1025_REG_TEMP_HIGH(i));
405                if (reg == 0)
406                        i2c_smbus_write_byte_data(client,
407                                                  ADM1025_REG_TEMP_HIGH(i),
408                                                  0x7F);
409        }
410
411        /* Start monitoring */
412        reg = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
413        i2c_smbus_write_byte_data(client, ADM1025_REG_CONFIG, (reg|0x01)&0x7F);
414}
415
416static void adm1025_update_client(struct i2c_client *client)
417{
418        struct adm1025_data *data = client->data;
419        u8 nr;
420
421        down(&data->update_lock);
422
423        if ((jiffies - data->last_updated > 2 * HZ)
424         || (jiffies < data->last_updated) || !data->valid) {
425#ifdef DEBUG
426                printk("Starting adm1025 update\n");
427#endif
428
429                /* Voltages */
430                for (nr = 0; nr < 6; nr++) {
431                        data->in[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN(nr));
432                        data->in_min[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN_MIN(nr));
433                        data->in_max[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN_MAX(nr));
434                }
435
436                /* Temperatures */
437                for (nr = 0; nr < 2; nr++) {
438                        data->temp[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP(nr));
439                        data->temp_high[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP_HIGH(nr));
440                        data->temp_low[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP_LOW(nr));
441                }
442
443                /* VID */
444                data->vid = (i2c_smbus_read_byte_data(client, ADM1025_REG_VID) & 0x0f)
445                         + ((i2c_smbus_read_byte_data(client, ADM1025_REG_VID4) & 0x01) << 4);
446
447                /* Alarms */
448                data->alarms = (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS1) & 0x3f)
449                            + ((i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS2) & 0x43) << 8);
450
451                data->last_updated = jiffies;
452                data->valid = 1;
453        }
454
455        up(&data->update_lock);
456}
457
458
459/* The next few functions are the call-back functions of the /proc/sys and
460   sysctl files. Which function is used is defined in the ctl_table in
461   the extra1 field.
462   Each function must return the magnitude (power of 10 to divide the data
463   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
464   put a maximum of *nrels elements in results reflecting the data of this
465   file, and set *nrels to the number it actually put in it, if operation==
466   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
467   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
468   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
469   large enough (by checking the incoming value of *nrels). This is not very
470   good practice, but as long as you put less than about 5 values in results,
471   you can assume it is large enough. */
472void adm1025_in(struct i2c_client *client, int operation, int ctl_name,
473                int *nrels_mag, long *results)
474{
475        int scales[6] = { 250, 225, 330, 500, 1200, 330 };
476
477        struct adm1025_data *data = client->data;
478        int nr = ctl_name - ADM1025_SYSCTL_IN0;
479
480        if (operation == SENSORS_PROC_REAL_INFO)
481                *nrels_mag = 2;
482        else if (operation == SENSORS_PROC_REAL_READ) {
483                adm1025_update_client(client);
484                results[0] = (IN_FROM_REG(data->in_min[nr]) * scales[nr] + 96) / 192;
485                results[1] = (IN_FROM_REG(data->in_max[nr]) * scales[nr] + 96) / 192;
486                results[2] = (IN_FROM_REG(data->in[nr]) * scales[nr] + 96) / 192;
487                *nrels_mag = 3;
488        } else if (operation == SENSORS_PROC_REAL_WRITE) {
489                if (*nrels_mag >= 1) {
490                        data->in_min[nr] = IN_TO_REG((results[0] * 192 + scales[nr] / 2)
491                                           / scales[nr]);
492                        i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(nr),
493                                            data->in_min[nr]);
494                }
495                if (*nrels_mag >= 2) {
496                        data->in_max[nr] = IN_TO_REG((results[1] * 192 + scales[nr] / 2)
497                                           / scales[nr]);
498                        i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(nr),
499                                            data->in_max[nr]);
500                }
501        }
502}
503
504void adm1025_temp(struct i2c_client *client, int operation, int ctl_name,
505                  int *nrels_mag, long *results)
506{
507        struct adm1025_data *data = client->data;
508        int nr = ctl_name - ADM1025_SYSCTL_RTEMP;
509
510        if (operation == SENSORS_PROC_REAL_INFO)
511                *nrels_mag = 1;
512        else if (operation == SENSORS_PROC_REAL_READ) {
513                adm1025_update_client(client);
514                results[0] = TEMP_FROM_REG(data->temp_high[nr]);
515                results[1] = TEMP_FROM_REG(data->temp_low[nr]);
516                results[2] = TEMP_FROM_REG(data->temp[nr]);
517                *nrels_mag = 3;
518        } else if (operation == SENSORS_PROC_REAL_WRITE) {
519                if (*nrels_mag >= 1) {
520                        data->temp_high[nr] = TEMP_TO_REG(results[0]);
521                        i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(nr),
522                                            data->temp_high[nr]);
523                }
524                if (*nrels_mag >= 2) {
525                        data->temp_low[nr] = TEMP_TO_REG(results[1]);
526                        i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(nr),
527                                            data->temp_low[nr]);
528                }
529        }
530}
531
532void adm1025_alarms(struct i2c_client *client, int operation, int ctl_name,
533                    int *nrels_mag, long *results)
534{
535        struct adm1025_data *data = client->data;
536
537        if (operation == SENSORS_PROC_REAL_INFO)
538                *nrels_mag = 0;
539        else if (operation == SENSORS_PROC_REAL_READ) {
540                adm1025_update_client(client);
541                results[0] = ALARMS_FROM_REG(data->alarms);
542                *nrels_mag = 1;
543        }
544}
545
546void adm1025_vid(struct i2c_client *client, int operation, int ctl_name,
547                 int *nrels_mag, long *results)
548{
549        struct adm1025_data *data = client->data;
550
551        if (operation == SENSORS_PROC_REAL_INFO)
552                *nrels_mag = 3;
553        else if (operation == SENSORS_PROC_REAL_READ) {
554                adm1025_update_client(client);
555                results[0] = vid_from_reg(data->vid, data->vrm);
556                *nrels_mag = 1;
557        }
558}
559
560void adm1025_vrm(struct i2c_client *client, int operation, int ctl_name,
561                 int *nrels_mag, long *results)
562{
563        struct adm1025_data *data = client->data;
564        if (operation == SENSORS_PROC_REAL_INFO)
565                *nrels_mag = 1;
566        else if (operation == SENSORS_PROC_REAL_READ) {
567                results[0] = data->vrm;
568                *nrels_mag = 1;
569        } else if (operation == SENSORS_PROC_REAL_WRITE) {
570                if (*nrels_mag >= 1)
571                        data->vrm = results[0];
572        }
573}
574
575static int __init sm_adm1025_init(void)
576{
577        printk("adm1025.o version %s (%s)\n", LM_VERSION, LM_DATE);
578        return i2c_add_driver(&adm1025_driver);
579}
580
581static void __exit sm_adm1025_exit(void)
582{
583        i2c_del_driver(&adm1025_driver);
584}
585
586
587
588MODULE_AUTHOR("Chen-Yuan Wu <gwu@esoft.com>"
589        " and Jean Delvare <khali@linux-fr.org>");
590MODULE_DESCRIPTION("ADM1025 driver");
591
592module_init(sm_adm1025_init);
593module_exit(sm_adm1025_exit);
Note: See TracBrowser for help on using the browser.