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

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

Drop unused client id.

  • 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 struct i2c_driver adm1025_driver = {
160        .name           = "ADM1025 sensor driver",
161        .id             = I2C_DRIVERID_ADM1025,
162        .flags          = I2C_DF_NOTIFY,
163        .attach_adapter = adm1025_attach_adapter,
164        .detach_client  = adm1025_detach_client,
165};
166
167/* The /proc/sys entries */
168/* -- SENSORS SYSCTL START -- */
169
170#define ADM1025_SYSCTL_IN0     1000 /* Volts * 100 */
171#define ADM1025_SYSCTL_IN1     1001
172#define ADM1025_SYSCTL_IN2     1002
173#define ADM1025_SYSCTL_IN3     1003
174#define ADM1025_SYSCTL_IN4     1004
175#define ADM1025_SYSCTL_IN5     1005
176
177#define ADM1025_SYSCTL_RTEMP   1250 /* Degrees Celcius * 10 */
178#define ADM1025_SYSCTL_TEMP    1251
179
180#define ADM1025_SYSCTL_ALARMS  2001 /* bitvector */
181#define ADM1025_SYSCTL_VID     2003 /* Volts * 1000 */
182#define ADM1025_SYSCTL_VRM     2004
183
184#define ADM1025_ALARM_IN0     0x0001
185#define ADM1025_ALARM_IN1     0x0002
186#define ADM1025_ALARM_IN2     0x0004
187#define ADM1025_ALARM_IN3     0x0008
188#define ADM1025_ALARM_IN4     0x0100
189#define ADM1025_ALARM_IN5     0x0200
190#define ADM1025_ALARM_RTEMP   0x0020
191#define ADM1025_ALARM_TEMP    0x0010
192#define ADM1025_ALARM_RFAULT  0x4000
193
194/* -- SENSORS SYSCTL END -- */
195
196/* These files are created for each detected ADM1025. This is just a template;
197   though at first sight, you might think we could use a statically
198   allocated list, we need some way to get back to the parent - which
199   is done through one of the 'extra' fields which are initialized
200   when a new copy is allocated. */
201static ctl_table adm1025_dir_table_template[] = {
202        {ADM1025_SYSCTL_IN0, "in0", NULL, 0, 0644, NULL, &i2c_proc_real,
203         &i2c_sysctl_real, NULL, &adm1025_in},
204        {ADM1025_SYSCTL_IN1, "in1", NULL, 0, 0644, NULL, &i2c_proc_real,
205         &i2c_sysctl_real, NULL, &adm1025_in},
206        {ADM1025_SYSCTL_IN2, "in2", NULL, 0, 0644, NULL, &i2c_proc_real,
207         &i2c_sysctl_real, NULL, &adm1025_in},
208        {ADM1025_SYSCTL_IN3, "in3", NULL, 0, 0644, NULL, &i2c_proc_real,
209         &i2c_sysctl_real, NULL, &adm1025_in},
210        {ADM1025_SYSCTL_IN4, "in4", NULL, 0, 0644, NULL, &i2c_proc_real,
211         &i2c_sysctl_real, NULL, &adm1025_in},
212        {ADM1025_SYSCTL_IN5, "in5", NULL, 0, 0644, NULL, &i2c_proc_real,
213         &i2c_sysctl_real, NULL, &adm1025_in},
214        {ADM1025_SYSCTL_RTEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
215         &i2c_sysctl_real, NULL, &adm1025_temp},
216        {ADM1025_SYSCTL_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
217         &i2c_sysctl_real, NULL, &adm1025_temp},
218        {ADM1025_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
219         &i2c_sysctl_real, NULL, &adm1025_alarms},
220        {ADM1025_SYSCTL_VID, "vid", NULL, 0, 0444, NULL, &i2c_proc_real,
221         &i2c_sysctl_real, NULL, &adm1025_vid},
222        {ADM1025_SYSCTL_VRM, "vrm", NULL, 0, 0644, NULL, &i2c_proc_real,
223         &i2c_sysctl_real, NULL, &adm1025_vrm},
224        {0}
225};
226
227static int adm1025_attach_adapter(struct i2c_adapter *adapter)
228{
229        return i2c_detect(adapter, &addr_data, adm1025_detect);
230}
231
232static int adm1025_detect(struct i2c_adapter *adapter, int address,
233                          unsigned short flags, int kind)
234{
235        int i;
236        struct i2c_client *new_client;
237        struct adm1025_data *data;
238        int err = 0;
239        const char *type_name = "";
240        const char *client_name = "";
241
242        /* Make sure we aren't probing the ISA bus!! This is just a safety check
243           at this moment; i2c_detect really won't call us. */
244#ifdef DEBUG
245        if (i2c_is_isa_adapter(adapter)) {
246                printk
247                    ("adm1025.o: adm1025_detect called for an ISA bus adapter?!?\n");
248                return 0;
249        }
250#endif
251
252        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
253                goto ERROR0;
254
255        /* OK. For now, we presume we have a valid client. We now create the
256           client structure, even though we cannot fill it completely yet.
257           But it allows us to access adm1025_{read,write}_value. */
258
259        if (!(data = kmalloc(sizeof(struct adm1025_data), GFP_KERNEL))) {
260                err = -ENOMEM;
261                goto ERROR0;
262        }
263
264        new_client = &data->client;
265        new_client->addr = address;
266        new_client->data = data;
267        new_client->adapter = adapter;
268        new_client->driver = &adm1025_driver;
269        new_client->flags = 0;
270
271        /* Now, we do the remaining detection. */
272
273        if (kind < 0) {
274                if ((i2c_smbus_read_byte_data(new_client,
275                     ADM1025_REG_CONFIG) & 0x80) != 0x00
276                 || (i2c_smbus_read_byte_data(new_client,
277                     ADM1025_REG_STATUS1) & 0xC0) != 0x00
278                 || (i2c_smbus_read_byte_data(new_client,
279                     ADM1025_REG_STATUS2) & 0xBC) != 0x00)
280                        goto ERROR1;
281        }
282
283        /* Determine the chip type. */
284        if (kind <= 0) {
285                u8 man_id, chip_id;
286               
287                man_id = i2c_smbus_read_byte_data(new_client,
288                         ADM1025_REG_COMPANY_ID);
289                chip_id = i2c_smbus_read_byte_data(new_client,
290                          ADM1025_REG_DIE_REV);
291               
292                if (man_id == 0x41) { /* Analog Devices */
293                        if ((chip_id & 0xF0) == 0x20) /* ADM1025 */
294                                kind = adm1025;
295                } else if (man_id == 0xA1) { /* Philips */
296                        if (address != 0x2E
297                         && (chip_id & 0xF0) == 0x20) /* NE1619 */
298                                kind = ne1619;
299                }
300        }
301
302        if (kind <= 0) { /* Identification failed */
303                printk("adm1025.o: Unsupported chip.\n");
304                goto ERROR1;
305        }
306
307        if (kind == adm1025) {
308                type_name = "adm1025";
309                client_name = "ADM1025 chip";
310        } else if (kind == ne1619) {
311                type_name = "ne1619";
312                client_name = "NE1619 chip";           
313        } else {
314#ifdef DEBUG
315                printk("adm1025.o: Internal error: unknown kind (%d)?!?",
316                       kind);
317#endif
318                goto ERROR1;
319        }
320
321        /* Fill in the remaining client fields and put it into the global list */
322        strcpy(new_client->name, client_name);
323        data->type = kind;
324        data->valid = 0;
325        init_MUTEX(&data->update_lock);
326
327        /* Tell the I2C layer a new client has arrived */
328        if ((err = i2c_attach_client(new_client)))
329                goto ERROR3;
330
331        /* Register a new directory entry with module sensors */
332        if ((i = i2c_register_entry(new_client,
333                                        type_name,
334                                        adm1025_dir_table_template,
335                                        THIS_MODULE)) < 0) {
336                err = i;
337                goto ERROR4;
338        }
339        data->sysctl_id = i;
340
341        /* Initialize the ADM1025 chip */
342        adm1025_init_client(new_client);
343        return 0;
344
345/* OK, this is not exactly good programming practice, usually. But it is
346   very code-efficient in this case. */
347
348      ERROR4:
349        i2c_detach_client(new_client);
350      ERROR3:
351      ERROR1:
352        kfree(data);
353      ERROR0:
354        return err;
355}
356
357static int adm1025_detach_client(struct i2c_client *client)
358{
359        int err;
360
361        i2c_deregister_entry(((struct adm1025_data *) (client->data))->
362                                 sysctl_id);
363
364        if ((err = i2c_detach_client(client))) {
365                printk
366                    ("adm1025.o: Client deregistration failed, client not detached.\n");
367                return err;
368        }
369
370        kfree(client->data);
371
372        return 0;
373}
374
375/* Called when we have found a new ADM1025. */
376static void adm1025_init_client(struct i2c_client *client)
377{
378        struct adm1025_data *data = client->data;
379        u8 reg;
380        int i;
381
382        data->vrm = 82;
383
384        /* Set high limits
385           Usually we avoid setting limits on driver init, but it happens
386           that the ADM1025 comes with stupid default limits (all registers
387           set to 0). In case the chip has not gone through any limit
388           setting yet, we better set the high limits to the max so that
389           no alarm triggers. */
390        for (i=0; i<6; i++) {
391                reg = i2c_smbus_read_byte_data(client,
392                                               ADM1025_REG_IN_MAX(i));
393                if (reg == 0)
394                        i2c_smbus_write_byte_data(client,
395                                                  ADM1025_REG_IN_MAX(i),
396                                                  0xFF);
397        }
398        for (i=0; i<2; i++) {
399                reg = i2c_smbus_read_byte_data(client,
400                                               ADM1025_REG_TEMP_HIGH(i));
401                if (reg == 0)
402                        i2c_smbus_write_byte_data(client,
403                                                  ADM1025_REG_TEMP_HIGH(i),
404                                                  0x7F);
405        }
406
407        /* Start monitoring */
408        reg = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
409        i2c_smbus_write_byte_data(client, ADM1025_REG_CONFIG, (reg|0x01)&0x7F);
410}
411
412static void adm1025_update_client(struct i2c_client *client)
413{
414        struct adm1025_data *data = client->data;
415        u8 nr;
416
417        down(&data->update_lock);
418
419        if ((jiffies - data->last_updated > 2 * HZ)
420         || (jiffies < data->last_updated) || !data->valid) {
421#ifdef DEBUG
422                printk("Starting adm1025 update\n");
423#endif
424
425                /* Voltages */
426                for (nr = 0; nr < 6; nr++) {
427                        data->in[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN(nr));
428                        data->in_min[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN_MIN(nr));
429                        data->in_max[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_IN_MAX(nr));
430                }
431
432                /* Temperatures */
433                for (nr = 0; nr < 2; nr++) {
434                        data->temp[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP(nr));
435                        data->temp_high[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP_HIGH(nr));
436                        data->temp_low[nr] = i2c_smbus_read_byte_data(client, ADM1025_REG_TEMP_LOW(nr));
437                }
438
439                /* VID */
440                data->vid = (i2c_smbus_read_byte_data(client, ADM1025_REG_VID) & 0x0f)
441                         + ((i2c_smbus_read_byte_data(client, ADM1025_REG_VID4) & 0x01) << 4);
442
443                /* Alarms */
444                data->alarms = (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS1) & 0x3f)
445                            + ((i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS2) & 0x43) << 8);
446
447                data->last_updated = jiffies;
448                data->valid = 1;
449        }
450
451        up(&data->update_lock);
452}
453
454
455/* The next few functions are the call-back functions of the /proc/sys and
456   sysctl files. Which function is used is defined in the ctl_table in
457   the extra1 field.
458   Each function must return the magnitude (power of 10 to divide the data
459   with) if it is called with operation==SENSORS_PROC_REAL_INFO. It must
460   put a maximum of *nrels elements in results reflecting the data of this
461   file, and set *nrels to the number it actually put in it, if operation==
462   SENSORS_PROC_REAL_READ. Finally, it must get upto *nrels elements from
463   results and write them to the chip, if operations==SENSORS_PROC_REAL_WRITE.
464   Note that on SENSORS_PROC_REAL_READ, I do not check whether results is
465   large enough (by checking the incoming value of *nrels). This is not very
466   good practice, but as long as you put less than about 5 values in results,
467   you can assume it is large enough. */
468void adm1025_in(struct i2c_client *client, int operation, int ctl_name,
469                int *nrels_mag, long *results)
470{
471        int scales[6] = { 250, 225, 330, 500, 1200, 330 };
472
473        struct adm1025_data *data = client->data;
474        int nr = ctl_name - ADM1025_SYSCTL_IN0;
475
476        if (operation == SENSORS_PROC_REAL_INFO)
477                *nrels_mag = 2;
478        else if (operation == SENSORS_PROC_REAL_READ) {
479                adm1025_update_client(client);
480                results[0] = (IN_FROM_REG(data->in_min[nr]) * scales[nr] + 96) / 192;
481                results[1] = (IN_FROM_REG(data->in_max[nr]) * scales[nr] + 96) / 192;
482                results[2] = (IN_FROM_REG(data->in[nr]) * scales[nr] + 96) / 192;
483                *nrels_mag = 3;
484        } else if (operation == SENSORS_PROC_REAL_WRITE) {
485                if (*nrels_mag >= 1) {
486                        data->in_min[nr] = IN_TO_REG((results[0] * 192 + scales[nr] / 2)
487                                           / scales[nr]);
488                        i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(nr),
489                                            data->in_min[nr]);
490                }
491                if (*nrels_mag >= 2) {
492                        data->in_max[nr] = IN_TO_REG((results[1] * 192 + scales[nr] / 2)
493                                           / scales[nr]);
494                        i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(nr),
495                                            data->in_max[nr]);
496                }
497        }
498}
499
500void adm1025_temp(struct i2c_client *client, int operation, int ctl_name,
501                  int *nrels_mag, long *results)
502{
503        struct adm1025_data *data = client->data;
504        int nr = ctl_name - ADM1025_SYSCTL_RTEMP;
505
506        if (operation == SENSORS_PROC_REAL_INFO)
507                *nrels_mag = 1;
508        else if (operation == SENSORS_PROC_REAL_READ) {
509                adm1025_update_client(client);
510                results[0] = TEMP_FROM_REG(data->temp_high[nr]);
511                results[1] = TEMP_FROM_REG(data->temp_low[nr]);
512                results[2] = TEMP_FROM_REG(data->temp[nr]);
513                *nrels_mag = 3;
514        } else if (operation == SENSORS_PROC_REAL_WRITE) {
515                if (*nrels_mag >= 1) {
516                        data->temp_high[nr] = TEMP_TO_REG(results[0]);
517                        i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(nr),
518                                            data->temp_high[nr]);
519                }
520                if (*nrels_mag >= 2) {
521                        data->temp_low[nr] = TEMP_TO_REG(results[1]);
522                        i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(nr),
523                                            data->temp_low[nr]);
524                }
525        }
526}
527
528void adm1025_alarms(struct i2c_client *client, int operation, int ctl_name,
529                    int *nrels_mag, long *results)
530{
531        struct adm1025_data *data = client->data;
532
533        if (operation == SENSORS_PROC_REAL_INFO)
534                *nrels_mag = 0;
535        else if (operation == SENSORS_PROC_REAL_READ) {
536                adm1025_update_client(client);
537                results[0] = ALARMS_FROM_REG(data->alarms);
538                *nrels_mag = 1;
539        }
540}
541
542void adm1025_vid(struct i2c_client *client, int operation, int ctl_name,
543                 int *nrels_mag, long *results)
544{
545        struct adm1025_data *data = client->data;
546
547        if (operation == SENSORS_PROC_REAL_INFO)
548                *nrels_mag = 3;
549        else if (operation == SENSORS_PROC_REAL_READ) {
550                adm1025_update_client(client);
551                results[0] = vid_from_reg(data->vid, data->vrm);
552                *nrels_mag = 1;
553        }
554}
555
556void adm1025_vrm(struct i2c_client *client, int operation, int ctl_name,
557                 int *nrels_mag, long *results)
558{
559        struct adm1025_data *data = client->data;
560        if (operation == SENSORS_PROC_REAL_INFO)
561                *nrels_mag = 1;
562        else if (operation == SENSORS_PROC_REAL_READ) {
563                results[0] = data->vrm;
564                *nrels_mag = 1;
565        } else if (operation == SENSORS_PROC_REAL_WRITE) {
566                if (*nrels_mag >= 1)
567                        data->vrm = results[0];
568        }
569}
570
571static int __init sm_adm1025_init(void)
572{
573        printk("adm1025.o version %s (%s)\n", LM_VERSION, LM_DATE);
574        return i2c_add_driver(&adm1025_driver);
575}
576
577static void __exit sm_adm1025_exit(void)
578{
579        i2c_del_driver(&adm1025_driver);
580}
581
582
583
584MODULE_AUTHOR("Chen-Yuan Wu <gwu@esoft.com>"
585        " and Jean Delvare <khali@linux-fr.org>");
586MODULE_DESCRIPTION("ADM1025 driver");
587
588module_init(sm_adm1025_init);
589module_exit(sm_adm1025_exit);
Note: See TracBrowser for help on using the browser.